/// Internet Protocol sockets
namespace inet {
+
+/// Address to accept any incoming messages
+const uint32_t any = INADDR_ANY;
+
+/// Address to send to all hosts
+const uint32_t broadcast = INADDR_BROADCAST;
+
+
/// IP socket address
struct sockaddr: sockaddr_in
{
/**
* Create an IP socket address.
+ *
+ * @note The IP address is expected in network byte order but the
+ * port is expected in host byte order. This is because this
+ * constructor is expected to be used with predefined IP
+ * addresses, like any, none, loopback, etc.
+ *
+ * @param addr IP address in network byte order
+ * @param port IP port in host byte order
+ *
+ * @see any, none, etc. constants
*/
- sockaddr(u_int16_t port = 0, const std::string& ip = "0.0.0.0")
- throw ();
+ explicit sockaddr(uint32_t addr = any, uint16_t port = 0) throw ();
- /// Length of this IP socket address
- socklen_t length() const throw ();
+ /**
+ * Create an IP socket address.
+ *
+ * @param addr String representation of the IP address
+ * @param port IP port in host byte order
+ */
+ explicit sockaddr(const std::string& addr, uint16_t port) throw ();
- /// Compare two IP socket addresses
- bool operator == (const sockaddr& other) const throw ();
+ /**
+ * Set the IP address and port.
+ *
+ * @param addr IP address in network byte order
+ * @param port IP port in host byte order
+ *
+ * @see sockaddr(uint32_t, uint16_t)
+ */
+ void set(uint32_t addr, uint16_t port) throw();
+
+ /**
+ * Set the IP address and port.
+ *
+ * @param addr String representation of the IP address
+ * @param port IP port in host byte order
+ *
+ * @see sockaddr(const std::string&, uint16_t)
+ */
+ void set(const std::string& addr, uint16_t port) throw();
+
+ /// Get the IP address as a string
+ std::string addr() const throw ();
+
+ /// Set the IP address (in network byte order)
+ void addr(uint32_t addr) throw ();
+
+ /// Set the IP address from a string
+ void addr(const std::string& addr) throw ();
/// Get the port number
uint16_t port() const throw ();
- /// Get the IP address
- std::string addr() const throw ();
+ /// Set the port number (port is expected to be in host byte order)
+ void port(uint16_t port) throw ();
+
+ /// Length of this IP socket address
+ socklen_t length() const throw ();
+
+ /// Compare two IP socket addresses
+ bool operator == (const sockaddr& other) const throw ();
}; // struct sockaddr
inline
-posixx::socket::inet::sockaddr::sockaddr(u_int16_t port, const std::string& ip)
+posixx::socket::inet::sockaddr::sockaddr(uint32_t addr, uint16_t port)
throw ()
{
memset(this, 0, sizeof(struct sockaddr_in));
sin_family = AF_INET;
- if (ip == "0.0.0.0") {
- sin_addr.s_addr = htonl(INADDR_ANY);
- }
- else {
- sin_addr.s_addr = inet_addr(ip.c_str());
- }
- sin_port = htons(port);
+ set(addr, port);
}
inline
-socklen_t posixx::socket::inet::sockaddr::length() const throw ()
+posixx::socket::inet::sockaddr::sockaddr(const std::string& addr, uint16_t port)
+ throw ()
{
- return sizeof(sockaddr_in);
+ memset(this, 0, sizeof(struct sockaddr_in));
+ sin_family = AF_INET;
+ set(addr, port);
}
inline
-bool posixx::socket::inet::sockaddr::operator == (const sockaddr& other) const
+void posixx::socket::inet::sockaddr::set(uint32_t addr, uint16_t port)
throw ()
{
- return !memcmp(this, &other, sizeof(*this));
+ sin_addr.s_addr = addr;
+ this->port(port);
}
inline
-uint16_t posixx::socket::inet::sockaddr::port() const throw ()
+void posixx::socket::inet::sockaddr::set(const std::string& addr, uint16_t port)
+ throw ()
{
- return ntohs(sin_port);
+ this->addr(addr);
+ this->port(port);
}
inline
return inet_ntoa(sin_addr);
}
+inline
+void posixx::socket::inet::sockaddr::addr(uint32_t addr) throw ()
+{
+ sin_addr.s_addr = addr;
+}
+
+inline
+void posixx::socket::inet::sockaddr::addr(const std::string& addr) throw ()
+{
+ sin_addr.s_addr = inet_addr(addr.c_str());
+}
+
+inline
+uint16_t posixx::socket::inet::sockaddr::port() const throw ()
+{
+ return ntohs(sin_port);
+}
+
+inline
+void posixx::socket::inet::sockaddr::port(uint16_t port) throw ()
+{
+ sin_port = htons(port);
+}
+
+inline
+socklen_t posixx::socket::inet::sockaddr::length() const throw ()
+{
+ return sizeof(sockaddr_in);
+}
+
+inline
+bool posixx::socket::inet::sockaddr::operator == (const sockaddr& other) const
+ throw ()
+{
+ return !memcmp(this, &other, sizeof(*this));
+}
+
#endif // POSIXX_SOCKET_INET_HPP_
std::ostream& operator << (std::ostream& os,
const posixx::socket::inet::sockaddr& sa) throw()
{
- return os << "inet::sockaddr(port=" << ntohs(sa.sin_port)
- << ", addr=" << inet_ntoa(sa.sin_addr) << ")";
+ return os << "inet::sockaddr(addr=" << sa.addr()
+ << ", port=" << sa.port() << ")";
}
#endif // POSIXX_SOCKET_INET_PRINT_HPP_
socket.opt< posixx::socket::opt::REUSEADDR >(true);
}
-static posixx::socket::inet::sockaddr test_address1(PORT1, IP);
-static posixx::socket::inet::sockaddr test_address2(PORT2, IP);
+static posixx::socket::inet::sockaddr test_address1(IP, PORT1);
+static posixx::socket::inet::sockaddr test_address2(IP, PORT2);
#endif // TEST_SOCKET_IP_COMMON_HPP_
#include <posixx/socket/inet.hpp> // posixx::socket::inet
#include <boost/test/unit_test.hpp> // unit testing stuff
+namespace inet = posixx::socket::inet;
+
BOOST_AUTO_TEST_CASE( socket_inet_sockaddr_test )
{
+ BOOST_CHECK_EQUAL(test_address1.sin_family, AF_INET);
BOOST_CHECK_EQUAL(test_address1.addr(), IP);
BOOST_CHECK_EQUAL(test_address1.port(), PORT1);
}
+BOOST_AUTO_TEST_CASE( socket_inet_sockaddr_default )
+{
+ inet::sockaddr addr;
+ BOOST_CHECK_EQUAL(addr.sin_family, AF_INET);
+ BOOST_CHECK_EQUAL(addr.sin_addr.s_addr, inet::any);
+ BOOST_CHECK_EQUAL(addr.sin_port, 0);
+ BOOST_CHECK_EQUAL(addr.port(), 0);
+}
+
+BOOST_AUTO_TEST_CASE( socket_inet_sockaddr_broadcast )
+{
+ inet::sockaddr addr(inet::broadcast);
+ BOOST_CHECK_EQUAL(addr.sin_family, AF_INET);
+ BOOST_CHECK_EQUAL(addr.sin_addr.s_addr, inet::broadcast);
+ BOOST_CHECK_EQUAL(addr.sin_port, 0);
+ BOOST_CHECK_EQUAL(addr.port(), 0);
+}
+
+BOOST_AUTO_TEST_CASE( socket_inet_sockaddr_broadcast_port )
+{
+ inet::sockaddr addr(inet::broadcast, 12345);
+ BOOST_CHECK_EQUAL(addr.sin_family, AF_INET);
+ BOOST_CHECK_EQUAL(addr.sin_addr.s_addr, inet::broadcast);
+ BOOST_CHECK_EQUAL(addr.port(), 12345);
+}
+
+BOOST_AUTO_TEST_CASE( socket_inet_sockaddr_1_1_1_1_8080 )
+{
+ inet::sockaddr addr("1.1.1.1", 8080);
+ BOOST_CHECK_EQUAL(addr.sin_family, AF_INET);
+ BOOST_CHECK_EQUAL(addr.addr(), "1.1.1.1");
+ BOOST_CHECK_EQUAL(addr.sin_addr.s_addr, 0x01010101);
+ BOOST_CHECK_EQUAL(addr.port(), 8080);
+}
+
+BOOST_AUTO_TEST_CASE( socket_inet_sockaddr_16_16_16_16_12345 )
+{
+ inet::sockaddr addr("16.16.16.16", 12345);
+ BOOST_CHECK_EQUAL(addr.sin_family, AF_INET);
+ BOOST_CHECK_EQUAL(addr.addr(), "16.16.16.16");
+ BOOST_CHECK_EQUAL(addr.sin_addr.s_addr, 0x10101010);
+ BOOST_CHECK_EQUAL(addr.port(), 12345);
+}
+
+BOOST_AUTO_TEST_CASE( socket_inet_sockaddr_set_broadcast_port )
+{
+ inet::sockaddr addr;
+ addr.set(inet::broadcast, 12345);
+ BOOST_CHECK_EQUAL(addr.sin_family, AF_INET);
+ BOOST_CHECK_EQUAL(addr.sin_addr.s_addr, inet::broadcast);
+ BOOST_CHECK_EQUAL(addr.port(), 12345);
+}
+
+BOOST_AUTO_TEST_CASE( socket_inet_sockaddr_set_16_16_16_16_12345 )
+{
+ inet::sockaddr addr;
+ addr.set("16.16.16.16", 12345);
+ BOOST_CHECK_EQUAL(addr.sin_family, AF_INET);
+ BOOST_CHECK_EQUAL(addr.addr(), "16.16.16.16");
+ BOOST_CHECK_EQUAL(addr.sin_addr.s_addr, 0x10101010);
+ BOOST_CHECK_EQUAL(addr.port(), 12345);
+}
+
+BOOST_AUTO_TEST_CASE( socket_inet_sockaddr_set_port_broadcast )
+{
+ inet::sockaddr addr(inet::broadcast);
+ addr.port(12345);
+ BOOST_CHECK_EQUAL(addr.sin_family, AF_INET);
+ BOOST_CHECK_EQUAL(addr.sin_addr.s_addr, inet::broadcast);
+ BOOST_CHECK_EQUAL(addr.port(), 12345);
+}
+
+BOOST_AUTO_TEST_CASE( socket_inet_sockaddr_set_port_16_16_16_16_12345 )
+{
+ inet::sockaddr addr("16.16.16.16", 0);
+ addr.port(12345);
+ BOOST_CHECK_EQUAL(addr.sin_family, AF_INET);
+ BOOST_CHECK_EQUAL(addr.addr(), "16.16.16.16");
+ BOOST_CHECK_EQUAL(addr.sin_addr.s_addr, 0x10101010);
+ BOOST_CHECK_EQUAL(addr.port(), 12345);
+}
+
+BOOST_AUTO_TEST_CASE( socket_inet_sockaddr_set_addr_broadcast )
+{
+ inet::sockaddr addr;
+ addr.addr(inet::broadcast);
+ BOOST_CHECK_EQUAL(addr.sin_family, AF_INET);
+ BOOST_CHECK_EQUAL(addr.sin_addr.s_addr, inet::broadcast);
+ BOOST_CHECK_EQUAL(addr.port(), 0);
+}
+
+BOOST_AUTO_TEST_CASE( socket_inet_sockaddr_set_addr_16_16_16_16 )
+{
+ inet::sockaddr addr;
+ addr.addr("16.16.16.16");
+ BOOST_CHECK_EQUAL(addr.sin_family, AF_INET);
+ BOOST_CHECK_EQUAL(addr.addr(), "16.16.16.16");
+ BOOST_CHECK_EQUAL(addr.sin_addr.s_addr, 0x10101010);
+ BOOST_CHECK_EQUAL(addr.port(), 0);
+}
+