IpAddress is always valid
This commit is contained in:
parent
fd3526f742
commit
8c8d97c6c9
@ -5,6 +5,7 @@
|
||||
#include <SFML/Network.hpp>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -26,17 +27,17 @@ std::ostream& operator <<(std::ostream& stream, const sf::Ftp::Response& respons
|
||||
int main()
|
||||
{
|
||||
// Choose the server address
|
||||
sf::IpAddress address;
|
||||
std::optional<sf::IpAddress> address;
|
||||
do
|
||||
{
|
||||
std::cout << "Enter the FTP server address: ";
|
||||
std::cin >> address;
|
||||
}
|
||||
while (address == sf::IpAddress::None);
|
||||
while (!address.has_value());
|
||||
|
||||
// Connect to the server
|
||||
sf::Ftp server;
|
||||
sf::Ftp::Response connectResponse = server.connect(address);
|
||||
sf::Ftp::Response connectResponse = server.connect(address.value());
|
||||
std::cout << connectResponse << std::endl;
|
||||
if (!connectResponse.isOk())
|
||||
return EXIT_FAILURE;
|
||||
|
@ -26,7 +26,7 @@ void runTcpServer(unsigned short port)
|
||||
sf::TcpSocket socket;
|
||||
if (listener.accept(socket) != sf::Socket::Done)
|
||||
return;
|
||||
std::cout << "Client connected: " << socket.getRemoteAddress() << std::endl;
|
||||
std::cout << "Client connected: " << socket.getRemoteAddress().value() << std::endl;
|
||||
|
||||
// Send a message to the connected client
|
||||
const char out[] = "Hi, I'm the server";
|
||||
@ -51,21 +51,21 @@ void runTcpServer(unsigned short port)
|
||||
void runTcpClient(unsigned short port)
|
||||
{
|
||||
// Ask for the server address
|
||||
sf::IpAddress server;
|
||||
std::optional<sf::IpAddress> server;
|
||||
do
|
||||
{
|
||||
std::cout << "Type the address or name of the server to connect to: ";
|
||||
std::cin >> server;
|
||||
}
|
||||
while (server == sf::IpAddress::None);
|
||||
while (!server.has_value());
|
||||
|
||||
// Create a socket for communicating with the server
|
||||
sf::TcpSocket socket;
|
||||
|
||||
// Connect to the server
|
||||
if (socket.connect(server, port) != sf::Socket::Done)
|
||||
if (socket.connect(server.value(), port) != sf::Socket::Done)
|
||||
return;
|
||||
std::cout << "Connected to server " << server << std::endl;
|
||||
std::cout << "Connected to server " << server.value() << std::endl;
|
||||
|
||||
// Receive a message from the server
|
||||
char in[128];
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <SFML/Network.hpp>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -24,15 +25,15 @@ void runUdpServer(unsigned short port)
|
||||
// Wait for a message
|
||||
char in[128];
|
||||
std::size_t received;
|
||||
sf::IpAddress sender;
|
||||
std::optional<sf::IpAddress> sender;
|
||||
unsigned short senderPort;
|
||||
if (socket.receive(in, sizeof(in), received, sender, senderPort) != sf::Socket::Done)
|
||||
return;
|
||||
std::cout << "Message received from client " << sender << ": " << std::quoted(in) << std::endl;
|
||||
std::cout << "Message received from client " << sender.value() << ": " << std::quoted(in) << std::endl;
|
||||
|
||||
// Send an answer to the client
|
||||
const char out[] = "Hi, I'm the server";
|
||||
if (socket.send(out, sizeof(out), sender, senderPort) != sf::Socket::Done)
|
||||
if (socket.send(out, sizeof(out), sender.value(), senderPort) != sf::Socket::Done)
|
||||
return;
|
||||
std::cout << "Message sent to the client: " << std::quoted(out) << std::endl;
|
||||
}
|
||||
@ -45,29 +46,29 @@ void runUdpServer(unsigned short port)
|
||||
void runUdpClient(unsigned short port)
|
||||
{
|
||||
// Ask for the server address
|
||||
sf::IpAddress server;
|
||||
std::optional<sf::IpAddress> server;
|
||||
do
|
||||
{
|
||||
std::cout << "Type the address or name of the server to connect to: ";
|
||||
std::cin >> server;
|
||||
}
|
||||
while (server == sf::IpAddress::None);
|
||||
while (!server.has_value());
|
||||
|
||||
// Create a socket for communicating with the server
|
||||
sf::UdpSocket socket;
|
||||
|
||||
// Send a message to the server
|
||||
const char out[] = "Hi, I'm a client";
|
||||
if (socket.send(out, sizeof(out), server, port) != sf::Socket::Done)
|
||||
if (socket.send(out, sizeof(out), server.value(), port) != sf::Socket::Done)
|
||||
return;
|
||||
std::cout << "Message sent to the server: " << std::quoted(out) << std::endl;
|
||||
|
||||
// Receive an answer from anyone (but most likely from the server)
|
||||
char in[128];
|
||||
std::size_t received;
|
||||
sf::IpAddress sender;
|
||||
std::optional<sf::IpAddress> sender;
|
||||
unsigned short senderPort;
|
||||
if (socket.receive(in, sizeof(in), received, sender, senderPort) != sf::Socket::Done)
|
||||
return;
|
||||
std::cout << "Message received from " << sender << ": " << std::quoted(in) << std::endl;
|
||||
std::cout << "Message received from " << sender.value() << ": " << std::quoted(in) << std::endl;
|
||||
}
|
||||
|
@ -121,16 +121,16 @@ void doClient(unsigned short port)
|
||||
}
|
||||
|
||||
// Ask for server address
|
||||
sf::IpAddress server;
|
||||
std::optional<sf::IpAddress> server;
|
||||
do
|
||||
{
|
||||
std::cout << "Type address or name of the server to connect to: ";
|
||||
std::cin >> server;
|
||||
}
|
||||
while (server == sf::IpAddress::None);
|
||||
while (!server.has_value());
|
||||
|
||||
// Create an instance of our custom recorder
|
||||
NetworkRecorder recorder(server, port);
|
||||
NetworkRecorder recorder(server.value(), port);
|
||||
|
||||
// Wait for user input...
|
||||
std::cin.ignore(10000, '\n');
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
// Wait for a connection
|
||||
if (m_listener.accept(m_client) != sf::Socket::Done)
|
||||
return;
|
||||
std::cout << "Client connected: " << m_client.getRemoteAddress() << std::endl;
|
||||
std::cout << "Client connected: " << m_client.getRemoteAddress().value() << std::endl;
|
||||
|
||||
// Start playback
|
||||
play();
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <SFML/Network/TcpSocket.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
|
||||
@ -420,10 +421,10 @@ private:
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpSocket m_connection; //!< Connection to the host
|
||||
IpAddress m_host; //!< Web host address
|
||||
std::string m_hostName; //!< Web host name
|
||||
unsigned short m_port; //!< Port used for connection with host
|
||||
TcpSocket m_connection; //!< Connection to the host
|
||||
std::optional<IpAddress> m_host; //!< Web host address
|
||||
std::string m_hostName; //!< Web host name
|
||||
unsigned short m_port; //!< Port used for connection with host
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include <iosfwd>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
|
||||
|
||||
@ -44,17 +45,8 @@ namespace sf
|
||||
class SFML_NETWORK_API IpAddress
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// This constructor creates an empty (invalid) address
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the address from a string
|
||||
/// \brief Construct the address from a null-terminated string view
|
||||
///
|
||||
/// Here \a address can be either a decimal address
|
||||
/// (ex: "192.168.1.56") or a network name (ex: "localhost").
|
||||
@ -62,28 +54,14 @@ public:
|
||||
/// \param address IP address or network name
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress(const std::string& address);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the address from a string
|
||||
///
|
||||
/// Here \a address can be either a decimal address
|
||||
/// (ex: "192.168.1.56") or a network name (ex: "localhost").
|
||||
/// This is equivalent to the constructor taking a std::string
|
||||
/// parameter, it is defined for convenience so that the
|
||||
/// implicit conversions from literal strings to IpAddress work.
|
||||
///
|
||||
/// \param address IP address or network name
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress(const char* address);
|
||||
static std::optional<IpAddress> resolve(std::string_view address);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the address from 4 bytes
|
||||
///
|
||||
/// Calling IpAddress(a, b, c, d) is equivalent to calling
|
||||
/// IpAddress("a.b.c.d"), but safer as it doesn't have to
|
||||
/// parse a string to get the address components.
|
||||
/// IpAddress::resolve("a.b.c.d"), but safer as it doesn't
|
||||
/// have to parse a string to get the address components.
|
||||
///
|
||||
/// \param byte0 First byte of the address
|
||||
/// \param byte1 Second byte of the address
|
||||
@ -152,7 +130,7 @@ public:
|
||||
/// \see getPublicAddress
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static IpAddress getLocalAddress();
|
||||
static std::optional<IpAddress> getLocalAddress();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the computer's public address
|
||||
@ -176,12 +154,11 @@ public:
|
||||
/// \see getLocalAddress
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static IpAddress getPublicAddress(Time timeout = Time::Zero);
|
||||
static std::optional<IpAddress> getPublicAddress(Time timeout = Time::Zero);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Static member data
|
||||
////////////////////////////////////////////////////////////
|
||||
static const IpAddress None; //!< Value representing an empty/invalid address
|
||||
static const IpAddress Any; //!< Value representing any address (0.0.0.0)
|
||||
static const IpAddress LocalHost; //!< The "localhost" address (for connecting a computer to itself locally)
|
||||
static const IpAddress Broadcast; //!< The "broadcast" address (for sending UDP messages to everyone on a local network)
|
||||
@ -193,7 +170,7 @@ private:
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
std::optional<Uint32> m_address; //!< Address stored as an unsigned 32 bits integer
|
||||
Uint32 m_address; //!< Address stored as an unsigned 32 bits integer
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -271,7 +248,7 @@ SFML_NETWORK_API bool operator >=(const IpAddress& left, const IpAddress& right)
|
||||
/// \return Reference to the input stream
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_NETWORK_API std::istream& operator >>(std::istream& stream, IpAddress& address);
|
||||
SFML_NETWORK_API std::istream& operator >>(std::istream& stream, std::optional<IpAddress>& address);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of << operator to print an IP address to an output stream
|
||||
@ -301,16 +278,14 @@ SFML_NETWORK_API std::ostream& operator <<(std::ostream& stream, const IpAddress
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// sf::IpAddress a0; // an invalid address
|
||||
/// sf::IpAddress a1 = sf::IpAddress::None; // an invalid address (same as a0)
|
||||
/// sf::IpAddress a2("127.0.0.1"); // the local host address
|
||||
/// sf::IpAddress a3 = sf::IpAddress::Broadcast; // the broadcast address
|
||||
/// sf::IpAddress a4(192, 168, 1, 56); // a local address
|
||||
/// sf::IpAddress a5("my_computer"); // a local address created from a network name
|
||||
/// sf::IpAddress a6("89.54.1.169"); // a distant address
|
||||
/// sf::IpAddress a7("www.google.com"); // a distant address created from a network name
|
||||
/// sf::IpAddress a8 = sf::IpAddress::getLocalAddress(); // my address on the local network
|
||||
/// sf::IpAddress a9 = sf::IpAddress::getPublicAddress(); // my address on the internet
|
||||
/// auto a2 = sf::IpAddress::resolve("127.0.0.1"); // the local host address
|
||||
/// auto a3 = sf::IpAddress::Broadcast; // the broadcast address
|
||||
/// sf::IpAddress a4(192, 168, 1, 56); // a local address
|
||||
/// auto a5 = sf::IpAddress::resolve("my_computer"); // a local address created from a network name
|
||||
/// auto a6 = sf::IpAddress::resolve("89.54.1.169"); // a distant address
|
||||
/// auto a7 = sf::IpAddress::resolve("www.google.com"); // a distant address created from a network name
|
||||
/// auto a8 = sf::IpAddress::getLocalAddress(); // my address on the local network
|
||||
/// auto a9 = sf::IpAddress::getPublicAddress(); // my address on the internet
|
||||
/// \endcode
|
||||
///
|
||||
/// Note that sf::IpAddress currently doesn't support IPv6
|
||||
|
@ -159,7 +159,7 @@ public:
|
||||
/// if (listener.accept(client) == sf::Socket::Done)
|
||||
/// {
|
||||
/// // A new client just connected!
|
||||
/// std::cout << "New connection received from " << client.getRemoteAddress() << std::endl;
|
||||
/// std::cout << "New connection received from " << client.getRemoteAddress().value() << std::endl;
|
||||
/// doSomethingWith(client);
|
||||
/// }
|
||||
/// }
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <SFML/Network/Export.hpp>
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include <optional>
|
||||
|
||||
|
||||
namespace sf
|
||||
@ -69,14 +70,14 @@ public:
|
||||
/// \brief Get the address of the connected peer
|
||||
///
|
||||
/// If the socket is not connected, this function returns
|
||||
/// sf::IpAddress::None.
|
||||
/// an unset optional.
|
||||
///
|
||||
/// \return Address of the remote peer
|
||||
///
|
||||
/// \see getRemotePort
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress getRemoteAddress() const;
|
||||
std::optional<IpAddress> getRemoteAddress() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the port of the connected peer to which
|
||||
@ -299,7 +300,7 @@ private:
|
||||
/// // Wait for a connection
|
||||
/// sf::TcpSocket socket;
|
||||
/// listener.accept(socket);
|
||||
/// std::cout << "New client connected: " << socket.getRemoteAddress() << std::endl;
|
||||
/// std::cout << "New client connected: " << socket.getRemoteAddress().value() << std::endl;
|
||||
///
|
||||
/// // Receive a message from the client
|
||||
/// char buffer[1024];
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <SFML/Network/Export.hpp>
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <SFML/Network/IpAddress.hpp>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
|
||||
@ -152,7 +153,7 @@ public:
|
||||
/// \see send
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] Status receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort);
|
||||
[[nodiscard]] Status receive(void* data, std::size_t size, std::size_t& received, std::optional<IpAddress>& remoteAddress, unsigned short& remotePort);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Send a formatted packet of data to a remote peer
|
||||
@ -187,7 +188,7 @@ public:
|
||||
/// \see send
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] Status receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort);
|
||||
[[nodiscard]] Status receive(Packet& packet, std::optional<IpAddress>& remoteAddress, unsigned short& remotePort);
|
||||
|
||||
private:
|
||||
|
||||
@ -263,10 +264,10 @@ private:
|
||||
/// // Receive an answer (most likely from 192.168.1.50, but could be anyone else)
|
||||
/// char buffer[1024];
|
||||
/// std::size_t received = 0;
|
||||
/// sf::IpAddress sender;
|
||||
/// std::optional<sf::IpAddress> sender;
|
||||
/// unsigned short port;
|
||||
/// socket.receive(buffer, sizeof(buffer), received, sender, port);
|
||||
/// std::cout << sender.ToString() << " said: " << buffer << std::endl;
|
||||
/// if (socket.receive(buffer, sizeof(buffer), received, sender, port) == sf::Socket::Done)
|
||||
/// std::cout << sender->toString() << " said: " << buffer << std::endl;
|
||||
///
|
||||
/// // ----- The server -----
|
||||
///
|
||||
@ -277,10 +278,10 @@ private:
|
||||
/// // Receive a message from anyone
|
||||
/// char buffer[1024];
|
||||
/// std::size_t received = 0;
|
||||
/// sf::IpAddress sender;
|
||||
/// std::optional<sf::IpAddress> sender;
|
||||
/// unsigned short port;
|
||||
/// socket.receive(buffer, sizeof(buffer), received, sender, port);
|
||||
/// std::cout << sender.ToString() << " said: " << buffer << std::endl;
|
||||
/// if (socket.receive(buffer, sizeof(buffer), received, sender, port) == sf::Socket::Done)
|
||||
/// std::cout << sender->toString() << " said: " << buffer << std::endl;
|
||||
///
|
||||
/// // Send an answer
|
||||
/// std::string message = "Welcome " + sender.toString();
|
||||
|
@ -329,7 +329,7 @@ void Http::setHost(const std::string& host, unsigned short port)
|
||||
if (!m_hostName.empty() && (*m_hostName.rbegin() == '/'))
|
||||
m_hostName.erase(m_hostName.size() - 1);
|
||||
|
||||
m_host = IpAddress(m_hostName);
|
||||
m_host = IpAddress::resolve(m_hostName);
|
||||
}
|
||||
|
||||
|
||||
@ -369,7 +369,7 @@ Http::Response Http::sendRequest(const Http::Request& request, Time timeout)
|
||||
Response received;
|
||||
|
||||
// Connect the socket to the host
|
||||
if (m_connection.connect(m_host, m_port, timeout) == Socket::Done)
|
||||
if (m_connection.connect(m_host.value(), m_port, timeout) == Socket::Done)
|
||||
{
|
||||
// Convert the request to string and send it through the connected socket
|
||||
std::string requestStr = toSend.prepare();
|
||||
|
@ -37,68 +37,56 @@
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
const IpAddress IpAddress::None;
|
||||
const IpAddress IpAddress::Any(0, 0, 0, 0);
|
||||
const IpAddress IpAddress::LocalHost(127, 0, 0, 1);
|
||||
const IpAddress IpAddress::Broadcast(255, 255, 255, 255);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress() = default;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(const std::string& address)
|
||||
std::optional<IpAddress> IpAddress::resolve(std::string_view address)
|
||||
{
|
||||
if (address == "255.255.255.255")
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
if (address.empty())
|
||||
return std::nullopt;
|
||||
|
||||
if (address == "255.255.255.255"sv)
|
||||
{
|
||||
// The broadcast address needs to be handled explicitly,
|
||||
// because it is also the value returned by inet_addr on error
|
||||
m_address = INADDR_BROADCAST;
|
||||
return;
|
||||
return Broadcast;
|
||||
}
|
||||
|
||||
if (address == "0.0.0.0")
|
||||
{
|
||||
m_address = INADDR_ANY;
|
||||
return;
|
||||
}
|
||||
if (address == "0.0.0.0"sv)
|
||||
return Any;
|
||||
|
||||
// Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx")
|
||||
sf::Uint32 ip = inet_addr(address.c_str());
|
||||
if (ip != INADDR_NONE)
|
||||
{
|
||||
m_address = ip;
|
||||
return;
|
||||
}
|
||||
if (const Uint32 ip = inet_addr(address.data()); ip != INADDR_NONE)
|
||||
return IpAddress(ntohl(ip));
|
||||
|
||||
// Not a valid address, try to convert it as a host name
|
||||
addrinfo hints;
|
||||
std::memset(&hints, 0, sizeof(hints));
|
||||
addrinfo hints{}; // Zero-initialize
|
||||
hints.ai_family = AF_INET;
|
||||
|
||||
addrinfo* result = nullptr;
|
||||
if (getaddrinfo(address.c_str(), nullptr, &hints, &result) == 0 && result)
|
||||
if (getaddrinfo(address.data(), nullptr, &hints, &result) == 0 && result != nullptr)
|
||||
{
|
||||
sockaddr_in sin;
|
||||
std::memcpy(&sin, result->ai_addr, sizeof(*result->ai_addr));
|
||||
ip = sin.sin_addr.s_addr;
|
||||
|
||||
const Uint32 ip = sin.sin_addr.s_addr;
|
||||
freeaddrinfo(result);
|
||||
m_address = ip;
|
||||
return;
|
||||
|
||||
return IpAddress(ntohl(ip));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(const char* address) :
|
||||
IpAddress(std::string(address))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3) :
|
||||
m_address(htonl(static_cast<uint32_t>((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3)))
|
||||
m_address(htonl(static_cast<std::uint32_t>((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3)))
|
||||
{
|
||||
}
|
||||
|
||||
@ -114,7 +102,7 @@ m_address(htonl(address))
|
||||
std::string IpAddress::toString() const
|
||||
{
|
||||
in_addr address;
|
||||
address.s_addr = m_address.value_or(0);
|
||||
address.s_addr = m_address;
|
||||
|
||||
return inet_ntoa(address);
|
||||
}
|
||||
@ -123,30 +111,28 @@ std::string IpAddress::toString() const
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 IpAddress::toInteger() const
|
||||
{
|
||||
return ntohl(m_address.value_or(0));
|
||||
return ntohl(m_address);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress IpAddress::getLocalAddress()
|
||||
std::optional<IpAddress> IpAddress::getLocalAddress()
|
||||
{
|
||||
// The method here is to connect a UDP socket to anyone (here to localhost),
|
||||
// and get the local socket address with the getsockname function.
|
||||
// UDP connection will not send anything to the network, so this function won't cause any overhead.
|
||||
|
||||
IpAddress localAddress;
|
||||
|
||||
// Create the socket
|
||||
SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == priv::SocketImpl::invalidSocket())
|
||||
return localAddress;
|
||||
return std::nullopt;
|
||||
|
||||
// Connect the socket to localhost on any port
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(ntohl(INADDR_LOOPBACK), 9);
|
||||
if (connect(sock, reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||
{
|
||||
priv::SocketImpl::close(sock);
|
||||
return localAddress;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Get the local address of the socket connection
|
||||
@ -154,21 +140,19 @@ IpAddress IpAddress::getLocalAddress()
|
||||
if (getsockname(sock, reinterpret_cast<sockaddr*>(&address), &size) == -1)
|
||||
{
|
||||
priv::SocketImpl::close(sock);
|
||||
return localAddress;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Close the socket
|
||||
priv::SocketImpl::close(sock);
|
||||
|
||||
// Finally build the IP address
|
||||
localAddress = IpAddress(ntohl(address.sin_addr.s_addr));
|
||||
|
||||
return localAddress;
|
||||
return IpAddress(ntohl(address.sin_addr.s_addr));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress IpAddress::getPublicAddress(Time timeout)
|
||||
std::optional<IpAddress> IpAddress::getPublicAddress(Time timeout)
|
||||
{
|
||||
// The trick here is more complicated, because the only way
|
||||
// to get our public IP address is to get it from a distant computer.
|
||||
@ -180,10 +164,10 @@ IpAddress IpAddress::getPublicAddress(Time timeout)
|
||||
Http::Request request("/ip-provider.php", Http::Request::Get);
|
||||
Http::Response page = server.sendRequest(request, timeout);
|
||||
if (page.getStatus() == Http::Response::Ok)
|
||||
return IpAddress(page.getBody());
|
||||
return IpAddress::resolve(page.getBody());
|
||||
|
||||
// Something failed: return an invalid address
|
||||
return IpAddress();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
@ -230,11 +214,11 @@ bool operator >=(const IpAddress& left, const IpAddress& right)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::istream& operator >>(std::istream& stream, IpAddress& address)
|
||||
std::istream& operator >>(std::istream& stream, std::optional<IpAddress>& address)
|
||||
{
|
||||
std::string str;
|
||||
stream >> str;
|
||||
address = IpAddress(str);
|
||||
address = IpAddress::resolve(str);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ Socket::Status TcpListener::listen(unsigned short port, const IpAddress& address
|
||||
create();
|
||||
|
||||
// Check if the address is valid
|
||||
if ((address == IpAddress::None) || (address == IpAddress::Broadcast))
|
||||
if (address == IpAddress::Broadcast)
|
||||
return Error;
|
||||
|
||||
// Bind the socket to the specified port
|
||||
|
@ -79,7 +79,7 @@ unsigned short TcpSocket::getLocalPort() const
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress TcpSocket::getRemoteAddress() const
|
||||
std::optional<IpAddress> TcpSocket::getRemoteAddress() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
@ -93,7 +93,7 @@ IpAddress TcpSocket::getRemoteAddress() const
|
||||
}
|
||||
|
||||
// We failed to retrieve the address
|
||||
return IpAddress::None;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
@ -183,7 +183,7 @@ Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short
|
||||
{
|
||||
// At this point the connection may have been either accepted or refused.
|
||||
// To know whether it's a success or a failure, we must check the address of the connected peer
|
||||
if (getRemoteAddress() != IpAddress::None)
|
||||
if (getRemoteAddress().has_value())
|
||||
{
|
||||
// Connection accepted
|
||||
status = Done;
|
||||
|
@ -74,7 +74,7 @@ Socket::Status UdpSocket::bind(unsigned short port, const IpAddress& address)
|
||||
create();
|
||||
|
||||
// Check if the address is valid
|
||||
if ((address == IpAddress::None) || (address == IpAddress::Broadcast))
|
||||
if (address == IpAddress::Broadcast)
|
||||
return Error;
|
||||
|
||||
// Bind the socket
|
||||
@ -129,11 +129,11 @@ Socket::Status UdpSocket::send(const void* data, std::size_t size, const IpAddre
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort)
|
||||
Socket::Status UdpSocket::receive(void* data, std::size_t size, std::size_t& received, std::optional<IpAddress>& remoteAddress, unsigned short& remotePort)
|
||||
{
|
||||
// First clear the variables to fill
|
||||
received = 0;
|
||||
remoteAddress = IpAddress();
|
||||
remoteAddress = std::nullopt;
|
||||
remotePort = 0;
|
||||
|
||||
// Check the destination buffer
|
||||
@ -187,7 +187,7 @@ Socket::Status UdpSocket::send(Packet& packet, const IpAddress& remoteAddress, u
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort)
|
||||
Socket::Status UdpSocket::receive(Packet& packet, std::optional<IpAddress>& remoteAddress, unsigned short& remotePort)
|
||||
{
|
||||
// See the detailed comment in send(Packet) above.
|
||||
|
||||
|
@ -3,78 +3,45 @@
|
||||
#include <doctest.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
|
||||
using namespace std::string_literals;
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
TEST_CASE("sf::IpAddress class - [network]")
|
||||
{
|
||||
SUBCASE("Construction")
|
||||
{
|
||||
SUBCASE("Default constructor")
|
||||
SUBCASE("static 'create' function")
|
||||
{
|
||||
const sf::IpAddress ipAddress;
|
||||
CHECK(ipAddress.toString() == "0.0.0.0"s);
|
||||
CHECK(ipAddress.toInteger() == 0);
|
||||
CHECK(ipAddress == sf::IpAddress::None);
|
||||
}
|
||||
const auto ipAddress = sf::IpAddress::resolve("192.168.0.1"sv);
|
||||
REQUIRE(ipAddress.has_value());
|
||||
CHECK(ipAddress->toString() == "192.168.0.1"s);
|
||||
CHECK(ipAddress->toInteger() == 0xC0A80001);
|
||||
CHECK(*ipAddress != sf::IpAddress::Any);
|
||||
CHECK(*ipAddress != sf::IpAddress::Broadcast);
|
||||
CHECK(*ipAddress != sf::IpAddress::LocalHost);
|
||||
|
||||
SUBCASE("std::string constructor")
|
||||
{
|
||||
const sf::IpAddress ipAddress = "192.168.0.1"s;
|
||||
CHECK(ipAddress.toString() == "192.168.0.1"s);
|
||||
CHECK(ipAddress.toInteger() == 0xC0A80001);
|
||||
CHECK(ipAddress != sf::IpAddress::None);
|
||||
CHECK(ipAddress != sf::IpAddress::Any);
|
||||
CHECK(ipAddress != sf::IpAddress::Broadcast);
|
||||
CHECK(ipAddress != sf::IpAddress::LocalHost);
|
||||
const auto broadcast = sf::IpAddress::resolve("255.255.255.255"sv);
|
||||
REQUIRE(broadcast.has_value());
|
||||
CHECK(broadcast->toString() == "255.255.255.255"s);
|
||||
CHECK(broadcast->toInteger() == 0xFFFFFFFF);
|
||||
CHECK(*broadcast == sf::IpAddress::Broadcast);
|
||||
|
||||
const sf::IpAddress broadcast("255.255.255.255"s);
|
||||
CHECK(broadcast.toString() == "255.255.255.255"s);
|
||||
CHECK(broadcast.toInteger() == 0xFFFFFFFF);
|
||||
CHECK(broadcast == sf::IpAddress::Broadcast);
|
||||
const auto any = sf::IpAddress::resolve("0.0.0.0"sv);
|
||||
REQUIRE(any.has_value());
|
||||
CHECK(any->toString() == "0.0.0.0"s);
|
||||
CHECK(any->toInteger() == 0x00000000);
|
||||
CHECK(*any == sf::IpAddress::Any);
|
||||
|
||||
const sf::IpAddress any("0.0.0.0"s);
|
||||
CHECK(any.toString() == "0.0.0.0"s);
|
||||
CHECK(any.toInteger() == 0x00000000);
|
||||
CHECK(any == sf::IpAddress::Any);
|
||||
const auto localHost = sf::IpAddress::resolve("localhost"s);
|
||||
REQUIRE(localHost.has_value());
|
||||
CHECK(localHost->toString() == "127.0.0.1"s);
|
||||
CHECK(localHost->toInteger() == 0x7F000001);
|
||||
CHECK(*localHost == sf::IpAddress::LocalHost);
|
||||
|
||||
const sf::IpAddress localHost("localhost"s);
|
||||
CHECK(localHost.toString() == "127.0.0.1"s);
|
||||
CHECK(localHost.toInteger() == 0x7F000001);
|
||||
CHECK(localHost == sf::IpAddress::LocalHost);
|
||||
|
||||
const sf::IpAddress invalidIpAddress("255.255.255.256"s);
|
||||
CHECK(invalidIpAddress.toString() == "0.0.0.0"s);
|
||||
CHECK(invalidIpAddress.toInteger() == 0);
|
||||
CHECK(invalidIpAddress == sf::IpAddress::None);
|
||||
}
|
||||
|
||||
SUBCASE("const char* constructor")
|
||||
{
|
||||
const sf::IpAddress ipAddress = "192.168.0.1";
|
||||
CHECK(ipAddress.toString() == "192.168.0.1"s);
|
||||
CHECK(ipAddress.toInteger() == 0xC0A80001);
|
||||
CHECK(ipAddress != sf::IpAddress::None);
|
||||
|
||||
const sf::IpAddress broadcast("255.255.255.255");
|
||||
CHECK(broadcast.toString() == "255.255.255.255"s);
|
||||
CHECK(broadcast.toInteger() == 0xFFFFFFFF);
|
||||
CHECK(broadcast == sf::IpAddress::Broadcast);
|
||||
|
||||
const sf::IpAddress any("0.0.0.0");
|
||||
CHECK(any.toString() == "0.0.0.0"s);
|
||||
CHECK(any.toInteger() == 0x00000000);
|
||||
CHECK(any == sf::IpAddress::Any);
|
||||
|
||||
const sf::IpAddress localHost("localhost");
|
||||
CHECK(localHost.toString() == "127.0.0.1"s);
|
||||
CHECK(localHost.toInteger() == 0x7F000001);
|
||||
CHECK(localHost == sf::IpAddress::LocalHost);
|
||||
|
||||
const sf::IpAddress invalidIpAddress("255.255.255.256");
|
||||
CHECK(invalidIpAddress.toString() == "0.0.0.0"s);
|
||||
CHECK(invalidIpAddress.toInteger() == 0);
|
||||
CHECK(invalidIpAddress == sf::IpAddress::None);
|
||||
CHECK(!sf::IpAddress::resolve("255.255.255.256"s).has_value());
|
||||
CHECK(!sf::IpAddress::resolve("").has_value());
|
||||
}
|
||||
|
||||
SUBCASE("Byte constructor")
|
||||
@ -82,7 +49,6 @@ TEST_CASE("sf::IpAddress class - [network]")
|
||||
const sf::IpAddress ipAddress(142, 250, 69, 238);
|
||||
CHECK(ipAddress.toString() == "142.250.69.238"s);
|
||||
CHECK(ipAddress.toInteger() == 0x8EFA45EE);
|
||||
CHECK(ipAddress != sf::IpAddress::None);
|
||||
}
|
||||
|
||||
SUBCASE("Uint32 constructor")
|
||||
@ -90,7 +56,6 @@ TEST_CASE("sf::IpAddress class - [network]")
|
||||
const sf::IpAddress ipAddress(0xDEADBEEF);
|
||||
CHECK(ipAddress.toString() == "222.173.190.239"s);
|
||||
CHECK(ipAddress.toInteger() == 0xDEADBEEF);
|
||||
CHECK(ipAddress != sf::IpAddress::None);
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,26 +63,23 @@ TEST_CASE("sf::IpAddress class - [network]")
|
||||
{
|
||||
SUBCASE("getLocalAddress")
|
||||
{
|
||||
const sf::IpAddress ipAddress = sf::IpAddress::getLocalAddress();
|
||||
CHECK(ipAddress.toString() != "0.0.0.0");
|
||||
CHECK(ipAddress.toInteger() != 0);
|
||||
CHECK(ipAddress != sf::IpAddress::None);
|
||||
const std::optional<sf::IpAddress> ipAddress = sf::IpAddress::getLocalAddress();
|
||||
REQUIRE(ipAddress.has_value());
|
||||
CHECK(ipAddress->toString() != "0.0.0.0");
|
||||
CHECK(ipAddress->toInteger() != 0);
|
||||
}
|
||||
|
||||
SUBCASE("getPublicAddress")
|
||||
{
|
||||
const sf::IpAddress ipAddress = sf::IpAddress::getPublicAddress();
|
||||
CHECK(ipAddress.toString() != "0.0.0.0");
|
||||
CHECK(ipAddress.toInteger() != 0);
|
||||
CHECK(ipAddress != sf::IpAddress::None);
|
||||
const std::optional<sf::IpAddress> ipAddress = sf::IpAddress::getPublicAddress();
|
||||
REQUIRE(ipAddress.has_value());
|
||||
CHECK(ipAddress->toString() != "0.0.0.0");
|
||||
CHECK(ipAddress->toInteger() != 0);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("Static constants")
|
||||
{
|
||||
CHECK(sf::IpAddress::None.toString() == "0.0.0.0"s);
|
||||
CHECK(sf::IpAddress::None.toInteger() == 0);
|
||||
|
||||
CHECK(sf::IpAddress::Any.toString() == "0.0.0.0"s);
|
||||
CHECK(sf::IpAddress::Any.toInteger() == 0);
|
||||
|
||||
@ -132,24 +94,19 @@ TEST_CASE("sf::IpAddress class - [network]")
|
||||
{
|
||||
SUBCASE("operator==")
|
||||
{
|
||||
CHECK(sf::IpAddress() == sf::IpAddress());
|
||||
CHECK(sf::IpAddress("") == sf::IpAddress(""s));
|
||||
CHECK(sf::IpAddress("8.8.8.8") == sf::IpAddress(8, 8, 8, 8));
|
||||
CHECK(sf::IpAddress(0x42, 0x69, 0x96, 0x24) == sf::IpAddress(0x42699624));
|
||||
CHECK(sf::IpAddress(0xABCDEF01) == sf::IpAddress("171.205.239.1"));
|
||||
CHECK(sf::IpAddress(0xABCDEF01) == sf::IpAddress(171, 205, 239, 1));
|
||||
}
|
||||
|
||||
SUBCASE("operator!=")
|
||||
{
|
||||
CHECK(sf::IpAddress() != sf::IpAddress("1.1.1.1"));
|
||||
CHECK(sf::IpAddress(0x12344321) != sf::IpAddress(""));
|
||||
CHECK(sf::IpAddress(0x12344321) != sf::IpAddress(1234));
|
||||
CHECK(sf::IpAddress(192, 168, 1, 10) != sf::IpAddress(192, 168, 1, 11));
|
||||
}
|
||||
|
||||
SUBCASE("operator<")
|
||||
{
|
||||
CHECK(sf::IpAddress(1) < sf::IpAddress(2));
|
||||
CHECK(sf::IpAddress() < sf::IpAddress(0, 0, 0, 0));
|
||||
CHECK(sf::IpAddress(0, 0, 0, 0) < sf::IpAddress(1, 0, 0, 0));
|
||||
CHECK(sf::IpAddress(1, 0, 0, 0) < sf::IpAddress(0, 1, 0, 0));
|
||||
CHECK(sf::IpAddress(0, 1, 0, 0) < sf::IpAddress(0, 0, 1, 0));
|
||||
@ -160,7 +117,6 @@ TEST_CASE("sf::IpAddress class - [network]")
|
||||
SUBCASE("operator>")
|
||||
{
|
||||
CHECK(sf::IpAddress(2) > sf::IpAddress(1));
|
||||
CHECK(sf::IpAddress(0, 0, 0, 0) > sf::IpAddress());
|
||||
CHECK(sf::IpAddress(1, 0, 0, 0) > sf::IpAddress(0, 0, 0, 0));
|
||||
CHECK(sf::IpAddress(0, 1, 0, 0) > sf::IpAddress(1, 0, 0, 0));
|
||||
CHECK(sf::IpAddress(0, 0, 1, 0) > sf::IpAddress(0, 1, 0, 0));
|
||||
@ -171,49 +127,44 @@ TEST_CASE("sf::IpAddress class - [network]")
|
||||
SUBCASE("operator<=")
|
||||
{
|
||||
CHECK(sf::IpAddress(1) <= sf::IpAddress(2));
|
||||
CHECK(sf::IpAddress() <= sf::IpAddress(0, 0, 0, 0));
|
||||
CHECK(sf::IpAddress(0, 0, 0, 0) <= sf::IpAddress(1, 0, 0, 0));
|
||||
CHECK(sf::IpAddress(1, 0, 0, 0) <= sf::IpAddress(0, 1, 0, 0));
|
||||
CHECK(sf::IpAddress(0, 1, 0, 0) <= sf::IpAddress(0, 0, 1, 0));
|
||||
CHECK(sf::IpAddress(0, 0, 1, 0) <= sf::IpAddress(0, 0, 0, 1));
|
||||
CHECK(sf::IpAddress(0, 0, 0, 1) <= sf::IpAddress(1, 0, 0, 1));
|
||||
|
||||
CHECK(sf::IpAddress() <= sf::IpAddress());
|
||||
CHECK(sf::IpAddress("") <= sf::IpAddress(""s));
|
||||
CHECK(sf::IpAddress("8.8.8.8") <= sf::IpAddress(8, 8, 8, 8));
|
||||
CHECK(sf::IpAddress(0x42, 0x69, 0x96, 0x24) <= sf::IpAddress(0x42699624));
|
||||
CHECK(sf::IpAddress(0xABCDEF01) <= sf::IpAddress("171.205.239.1"));
|
||||
CHECK(sf::IpAddress(0xABCDEF01) <= sf::IpAddress(171, 205, 239, 1));
|
||||
}
|
||||
|
||||
SUBCASE("operator>=")
|
||||
{
|
||||
CHECK(sf::IpAddress(2) >= sf::IpAddress(1));
|
||||
CHECK(sf::IpAddress(0, 0, 0, 0) >= sf::IpAddress());
|
||||
CHECK(sf::IpAddress(1, 0, 0, 0) >= sf::IpAddress(0, 0, 0, 0));
|
||||
CHECK(sf::IpAddress(0, 1, 0, 0) >= sf::IpAddress(1, 0, 0, 0));
|
||||
CHECK(sf::IpAddress(0, 0, 1, 0) >= sf::IpAddress(0, 1, 0, 0));
|
||||
CHECK(sf::IpAddress(0, 0, 0, 1) >= sf::IpAddress(0, 0, 1, 0));
|
||||
CHECK(sf::IpAddress(1, 0, 0, 1) >= sf::IpAddress(0, 0, 0, 1));
|
||||
|
||||
CHECK(sf::IpAddress() >= sf::IpAddress());
|
||||
CHECK(sf::IpAddress("") >= sf::IpAddress(""s));
|
||||
CHECK(sf::IpAddress("8.8.8.8") >= sf::IpAddress(8, 8, 8, 8));
|
||||
CHECK(sf::IpAddress(0x42, 0x69, 0x96, 0x24) >= sf::IpAddress(0x42699624));
|
||||
CHECK(sf::IpAddress(0xABCDEF01) >= sf::IpAddress("171.205.239.1"));
|
||||
CHECK(sf::IpAddress(0xABCDEF01) >= sf::IpAddress(171, 205, 239, 1));
|
||||
}
|
||||
|
||||
SUBCASE("operator>>")
|
||||
{
|
||||
sf::IpAddress ipAddress;
|
||||
std::optional<sf::IpAddress> ipAddress;
|
||||
std::istringstream("4.4.4.4") >> ipAddress;
|
||||
CHECK(ipAddress.toString() == "4.4.4.4"s);
|
||||
CHECK(ipAddress.toInteger() == 0x04040404);
|
||||
CHECK(ipAddress != sf::IpAddress::None);
|
||||
REQUIRE(ipAddress.has_value());
|
||||
CHECK(ipAddress->toString() == "4.4.4.4"s);
|
||||
CHECK(ipAddress->toInteger() == 0x04040404);
|
||||
|
||||
std::istringstream("92.100.0.72") >> ipAddress;
|
||||
CHECK(ipAddress.toString() == "92.100.0.72"s);
|
||||
CHECK(ipAddress.toInteger() == 0x5C640048);
|
||||
CHECK(ipAddress != sf::IpAddress::None);
|
||||
REQUIRE(ipAddress.has_value());
|
||||
CHECK(ipAddress->toString() == "92.100.0.72"s);
|
||||
CHECK(ipAddress->toInteger() == 0x5C640048);
|
||||
|
||||
std::istringstream("") >> ipAddress;
|
||||
CHECK(!ipAddress.has_value());
|
||||
}
|
||||
|
||||
SUBCASE("operator<<")
|
||||
|
Loading…
Reference in New Issue
Block a user