Added optional argument on which address to bind (socket).
This commit is contained in:
parent
6b9781475d
commit
3a12fc6505
@ -99,7 +99,7 @@ public:
|
|||||||
/// This constructor uses the internal representation of
|
/// This constructor uses the internal representation of
|
||||||
/// the address directly. It should be used for optimization
|
/// the address directly. It should be used for optimization
|
||||||
/// purposes, and only if you got that representation from
|
/// purposes, and only if you got that representation from
|
||||||
/// IpAddress::ToInteger().
|
/// IpAddress::toInteger().
|
||||||
///
|
///
|
||||||
/// \param address 4 bytes of the address packed into a 32-bits integer
|
/// \param address 4 bytes of the address packed into a 32-bits integer
|
||||||
///
|
///
|
||||||
@ -182,15 +182,27 @@ public:
|
|||||||
// Static member data
|
// Static member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static const IpAddress None; ///< Value representing an empty/invalid address
|
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 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)
|
static const IpAddress Broadcast; ///< The "broadcast" address (for sending UDP messages to everyone on a local network)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
friend SFML_NETWORK_API bool operator <(const IpAddress& left, const IpAddress& right);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Resolve the given address string
|
||||||
|
///
|
||||||
|
/// \param address Address string
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void resolve(const std::string& address);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Uint32 m_address; ///< Address stored as an unsigned 32 bits integer
|
Uint32 m_address; ///< Address stored as an unsigned 32 bits integer
|
||||||
|
bool m_valid; ///< Is the address valid?
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/Export.hpp>
|
#include <SFML/Network/Export.hpp>
|
||||||
#include <SFML/Network/Socket.hpp>
|
#include <SFML/Network/Socket.hpp>
|
||||||
|
#include <SFML/Network/IpAddress.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -71,14 +72,15 @@ public:
|
|||||||
/// If the socket was previously listening to another port,
|
/// If the socket was previously listening to another port,
|
||||||
/// it will be stopped first and bound to the new port.
|
/// it will be stopped first and bound to the new port.
|
||||||
///
|
///
|
||||||
/// \param port Port to listen for new connections
|
/// \param port Port to listen for new connections
|
||||||
|
/// \param address Address of the interface to listen on
|
||||||
///
|
///
|
||||||
/// \return Status code
|
/// \return Status code
|
||||||
///
|
///
|
||||||
/// \see accept, close
|
/// \see accept, close
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Status listen(unsigned short port);
|
Status listen(unsigned short port, const IpAddress& address = IpAddress::Any);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Stop listening and close the socket
|
/// \brief Stop listening and close the socket
|
||||||
|
@ -30,12 +30,12 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/Export.hpp>
|
#include <SFML/Network/Export.hpp>
|
||||||
#include <SFML/Network/Socket.hpp>
|
#include <SFML/Network/Socket.hpp>
|
||||||
|
#include <SFML/Network/IpAddress.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
class IpAddress;
|
|
||||||
class Packet;
|
class Packet;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -82,14 +82,15 @@ public:
|
|||||||
/// system to automatically pick an available port, and then
|
/// system to automatically pick an available port, and then
|
||||||
/// call getLocalPort to retrieve the chosen port.
|
/// call getLocalPort to retrieve the chosen port.
|
||||||
///
|
///
|
||||||
/// \param port Port to bind the socket to
|
/// \param port Port to bind the socket to
|
||||||
|
/// \param address Address of the interface to bind to
|
||||||
///
|
///
|
||||||
/// \return Status code
|
/// \return Status code
|
||||||
///
|
///
|
||||||
/// \see unbind, getLocalPort
|
/// \see unbind, getLocalPort
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Status bind(unsigned short port);
|
Status bind(unsigned short port, const IpAddress& address = IpAddress::Any);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Unbind the socket from the local port to which it is bound
|
/// \brief Unbind the socket from the local port to which it is bound
|
||||||
|
@ -29,89 +29,56 @@
|
|||||||
#include <SFML/Network/Http.hpp>
|
#include <SFML/Network/Http.hpp>
|
||||||
#include <SFML/Network/SocketImpl.hpp>
|
#include <SFML/Network/SocketImpl.hpp>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
sf::Uint32 resolve(const std::string& address)
|
|
||||||
{
|
|
||||||
if (address == "255.255.255.255")
|
|
||||||
{
|
|
||||||
// The broadcast address needs to be handled explicitly,
|
|
||||||
// because it is also the value returned by inet_addr on error
|
|
||||||
return INADDR_BROADCAST;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 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)
|
|
||||||
return ip;
|
|
||||||
|
|
||||||
// Not a valid address, try to convert it as a host name
|
|
||||||
addrinfo hints;
|
|
||||||
std::memset(&hints, 0, sizeof(hints));
|
|
||||||
hints.ai_family = AF_INET;
|
|
||||||
addrinfo* result = NULL;
|
|
||||||
if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0)
|
|
||||||
{
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
ip = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr;
|
|
||||||
freeaddrinfo(result);
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not a valid address nor a host name
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const IpAddress IpAddress::None;
|
const IpAddress IpAddress::None;
|
||||||
|
const IpAddress IpAddress::Any(0, 0, 0, 0);
|
||||||
const IpAddress IpAddress::LocalHost(127, 0, 0, 1);
|
const IpAddress IpAddress::LocalHost(127, 0, 0, 1);
|
||||||
const IpAddress IpAddress::Broadcast(255, 255, 255, 255);
|
const IpAddress IpAddress::Broadcast(255, 255, 255, 255);
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
IpAddress::IpAddress() :
|
IpAddress::IpAddress() :
|
||||||
m_address(0)
|
m_address(0),
|
||||||
|
m_valid (false)
|
||||||
{
|
{
|
||||||
// We're using 0 (INADDR_ANY) instead of INADDR_NONE to represent the invalid address,
|
|
||||||
// because the latter is also the broadcast address (255.255.255.255); it's ok because
|
|
||||||
// SFML doesn't publicly use INADDR_ANY (it is always used implicitly)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
IpAddress::IpAddress(const std::string& address) :
|
IpAddress::IpAddress(const std::string& address) :
|
||||||
m_address(resolve(address))
|
m_address(0),
|
||||||
|
m_valid (false)
|
||||||
{
|
{
|
||||||
|
resolve(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
IpAddress::IpAddress(const char* address) :
|
IpAddress::IpAddress(const char* address) :
|
||||||
m_address(resolve(address))
|
m_address(0),
|
||||||
|
m_valid (false)
|
||||||
{
|
{
|
||||||
|
resolve(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
IpAddress::IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3) :
|
IpAddress::IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3) :
|
||||||
m_address(htonl((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3))
|
m_address(htonl((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3)),
|
||||||
|
m_valid (true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
IpAddress::IpAddress(Uint32 address) :
|
IpAddress::IpAddress(Uint32 address) :
|
||||||
m_address(htonl(address))
|
m_address(htonl(address)),
|
||||||
|
m_valid (true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,10 +160,59 @@ IpAddress IpAddress::getPublicAddress(Time timeout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void IpAddress::resolve(const std::string& address)
|
||||||
|
{
|
||||||
|
m_address = 0;
|
||||||
|
m_valid = false;
|
||||||
|
|
||||||
|
if (address == "255.255.255.255")
|
||||||
|
{
|
||||||
|
// The broadcast address needs to be handled explicitly,
|
||||||
|
// because it is also the value returned by inet_addr on error
|
||||||
|
m_address = INADDR_BROADCAST;
|
||||||
|
m_valid = true;
|
||||||
|
}
|
||||||
|
else if (address == "0.0.0.0")
|
||||||
|
{
|
||||||
|
m_address = INADDR_ANY;
|
||||||
|
m_valid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx")
|
||||||
|
Uint32 ip = inet_addr(address.c_str());
|
||||||
|
if (ip != INADDR_NONE)
|
||||||
|
{
|
||||||
|
m_address = ip;
|
||||||
|
m_valid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Not a valid address, try to convert it as a host name
|
||||||
|
addrinfo hints;
|
||||||
|
std::memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
addrinfo* result = NULL;
|
||||||
|
if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0)
|
||||||
|
{
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
ip = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr;
|
||||||
|
freeaddrinfo(result);
|
||||||
|
m_address = ip;
|
||||||
|
m_valid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool operator ==(const IpAddress& left, const IpAddress& right)
|
bool operator ==(const IpAddress& left, const IpAddress& right)
|
||||||
{
|
{
|
||||||
return left.toInteger() == right.toInteger();
|
return !(left < right) && !(right < left);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -210,7 +226,7 @@ bool operator !=(const IpAddress& left, const IpAddress& right)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool operator <(const IpAddress& left, const IpAddress& right)
|
bool operator <(const IpAddress& left, const IpAddress& right)
|
||||||
{
|
{
|
||||||
return left.toInteger() < right.toInteger();
|
return std::make_pair(left.m_valid, left.m_address) < std::make_pair(right.m_valid, right.m_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,14 +61,18 @@ unsigned short TcpListener::getLocalPort() const
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Socket::Status TcpListener::listen(unsigned short port)
|
Socket::Status TcpListener::listen(unsigned short port, const IpAddress& address)
|
||||||
{
|
{
|
||||||
// Create the internal socket if it doesn't exist
|
// Create the internal socket if it doesn't exist
|
||||||
create();
|
create();
|
||||||
|
|
||||||
|
// Check if the address is valid
|
||||||
|
if ((address == IpAddress::None) || (address == IpAddress::Broadcast))
|
||||||
|
return Error;
|
||||||
|
|
||||||
// Bind the socket to the specified port
|
// Bind the socket to the specified port
|
||||||
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port);
|
sockaddr_in addr = priv::SocketImpl::createAddress(address.toInteger(), port);
|
||||||
if (bind(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
if (bind(getHandle(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1)
|
||||||
{
|
{
|
||||||
// Not likely to happen, but...
|
// Not likely to happen, but...
|
||||||
err() << "Failed to bind listener socket to port " << port << std::endl;
|
err() << "Failed to bind listener socket to port " << port << std::endl;
|
||||||
|
@ -64,14 +64,18 @@ unsigned short UdpSocket::getLocalPort() const
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Socket::Status UdpSocket::bind(unsigned short port)
|
Socket::Status UdpSocket::bind(unsigned short port, const IpAddress& address)
|
||||||
{
|
{
|
||||||
// Create the internal socket if it doesn't exist
|
// Create the internal socket if it doesn't exist
|
||||||
create();
|
create();
|
||||||
|
|
||||||
|
// Check if the address is valid
|
||||||
|
if ((address == IpAddress::None) || (address == IpAddress::Broadcast))
|
||||||
|
return Error;
|
||||||
|
|
||||||
// Bind the socket
|
// Bind the socket
|
||||||
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port);
|
sockaddr_in addr = priv::SocketImpl::createAddress(address.toInteger(), port);
|
||||||
if (::bind(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
if (::bind(getHandle(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1)
|
||||||
{
|
{
|
||||||
err() << "Failed to bind socket to port " << port << std::endl;
|
err() << "Failed to bind socket to port " << port << std::endl;
|
||||||
return Error;
|
return Error;
|
||||||
|
Loading…
Reference in New Issue
Block a user