diff --git a/Net/include/Poco/Net/SocketAddress.h b/Net/include/Poco/Net/SocketAddress.h index 17190e84d..ba4d3a9f1 100644 --- a/Net/include/Poco/Net/SocketAddress.h +++ b/Net/include/Poco/Net/SocketAddress.h @@ -18,14 +18,14 @@ // execute, and transmit the Software, and to prepare derivative works of the // Software, and to permit third-parties to whom the Software is furnished to // do so, all subject to the following: -// +// // The copyright notices in the Software and this entire statement, including // the above license grant, this restriction and the following disclaimer, // must be included in all copies of the Software, in whole or in part, and // all derivative works of the Software, unless such copies or derivative // works are solely in the form of machine-executable object code generated by // a source language processor. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT @@ -62,10 +62,10 @@ class Net_API SocketAddress public: SocketAddress(); /// Creates a wildcard (all zero) IPv4 SocketAddress. - + SocketAddress(const IPAddress& host, Poco::UInt16 port); /// Creates a SocketAddress from an IP address and a port number. - + SocketAddress(const std::string& host, Poco::UInt16 port); /// Creates a SocketAddress from an IP address and a port number. /// @@ -73,15 +73,15 @@ public: /// be in dotted decimal (IPv4) or hex string (IPv6) format. SocketAddress(const std::string& host, const std::string& port); - /// Creates a SocketAddress from an IP address and a + /// Creates a SocketAddress from an IP address and a /// service name or port number. /// /// The IP address must either be a domain name, or it must /// be in dotted decimal (IPv4) or hex string (IPv6) format. /// - /// The given port must either be a decimal port number, or + /// The given port must either be a decimal port number, or /// a service name. - + explicit SocketAddress(const std::string& hostAndPort); /// Creates a SocketAddress from an IP address or host name and a /// port number/service name. Host name/address and port number must @@ -89,49 +89,50 @@ public: /// the address part must be enclosed in brackets. /// /// Examples: - /// 192.168.1.10:80 - /// [::FFFF:192.168.1.120]:2040 + /// 192.168.1.10:80 + /// [::ffff:192.168.1.120]:2040 /// www.appinf.com:8080 SocketAddress(const SocketAddress& addr); /// Creates a SocketAddress by copying another one. - + SocketAddress(const struct sockaddr* addr, poco_socklen_t length); /// Creates a SocketAddress from a native socket address. - + ~SocketAddress(); /// Destroys the SocketAddress. - + SocketAddress& operator = (const SocketAddress& addr); /// Assigns another SocketAddress. - + void swap(SocketAddress& addr); - /// Swaps the SocketAddress with another one. - + /// Swaps the SocketAddress with another one. + IPAddress host() const; /// Returns the host IP address. - + Poco::UInt16 port() const; /// Returns the port number. - + poco_socklen_t length() const; - /// Returns the length of the internal native socket address. - + /// Returns the length of the internal native socket address. + const struct sockaddr* addr() const; /// Returns a pointer to the internal native socket address. int af() const; /// Returns the address family (AF_INET or AF_INET6) of the address. - + std::string toString() const; /// Returns a string representation of the address. - + IPAddress::Family family() const; /// Returns the address family of the host's address. - + + bool operator < (const SocketAddress& addr) const; bool operator == (const SocketAddress& addr) const; bool operator != (const SocketAddress& addr) const; - + enum { MAX_ADDRESS_LENGTH = diff --git a/Net/src/SocketAddress.cpp b/Net/src/SocketAddress.cpp index e780114e1..1cd74a355 100644 --- a/Net/src/SocketAddress.cpp +++ b/Net/src/SocketAddress.cpp @@ -16,14 +16,14 @@ // execute, and transmit the Software, and to prepare derivative works of the // Software, and to permit third-parties to whom the Software is furnished to // do so, all subject to the following: -// +// // The copyright notices in the Software and this entire statement, including // the above license grant, this restriction and the following disclaimer, // must be included in all copies of the Software, in whole or in part, and // all derivative works of the Software, unless such copies or derivative // works are solely in the form of machine-executable object code generated by // a source language processor. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT @@ -78,7 +78,7 @@ public: virtual poco_socklen_t length() const = 0; virtual const struct sockaddr* addr() const = 0; virtual int af() const = 0; - + protected: SocketAddressImpl() { @@ -86,14 +86,14 @@ protected: Poco::Net::initializeNetwork(); #endif } - + virtual ~SocketAddressImpl() { #if defined(_WIN32) Poco::Net::uninitializeNetwork(); #endif } - + private: SocketAddressImpl(const SocketAddressImpl&); SocketAddressImpl& operator = (const SocketAddressImpl&); @@ -109,12 +109,12 @@ public: _addr.sin_family = AF_INET; poco_set_sin_len(&_addr); } - + IPv4SocketAddressImpl(const struct sockaddr_in* addr) { std::memcpy(&_addr, addr, sizeof(_addr)); } - + IPv4SocketAddressImpl(const void* addr, UInt16 port) { std::memset(&_addr, 0, sizeof(_addr)); @@ -127,7 +127,7 @@ public: { return IPAddress(&_addr.sin_addr, sizeof(_addr.sin_addr)); } - + UInt16 port() const { return _addr.sin_port; @@ -137,12 +137,12 @@ public: { return sizeof(_addr); } - + const struct sockaddr* addr() const { return reinterpret_cast(&_addr); } - + int af() const { return _addr.sin_family; @@ -163,7 +163,7 @@ public: { std::memcpy(&_addr, addr, sizeof(_addr)); } - + IPv6SocketAddressImpl(const void* addr, UInt16 port) { std::memset(&_addr, 0, sizeof(_addr)); @@ -187,7 +187,7 @@ public: { return IPAddress(&_addr.sin6_addr, sizeof(_addr.sin6_addr), _addr.sin6_scope_id); } - + UInt16 port() const { return _addr.sin6_port; @@ -197,7 +197,7 @@ public: { return sizeof(_addr); } - + const struct sockaddr* addr() const { return reinterpret_cast(&_addr); @@ -226,13 +226,13 @@ SocketAddress::SocketAddress() _pImpl = new IPv4SocketAddressImpl; } - + SocketAddress::SocketAddress(const IPAddress& addr, Poco::UInt16 port) { - init(addr, port); + init(addr, port); } - + SocketAddress::SocketAddress(const std::string& addr, Poco::UInt16 port) { init(addr, port); @@ -248,7 +248,7 @@ SocketAddress::SocketAddress(const std::string& addr, const std::string& port) SocketAddress::SocketAddress(const std::string& hostAndPort) { poco_assert (!hostAndPort.empty()); - + std::string host; std::string port; std::string::const_iterator it = hostAndPort.begin(); @@ -298,7 +298,15 @@ SocketAddress::~SocketAddress() _pImpl->release(); } - + +bool SocketAddress::operator < (const SocketAddress& addr) const +{ + if (family() < addr.family()) return true; + if (host() < addr.host()) return true; + return (port() < addr.port()); +} + + SocketAddress& SocketAddress::operator = (const SocketAddress& addr) { if (&addr != this) @@ -316,25 +324,25 @@ void SocketAddress::swap(SocketAddress& addr) std::swap(_pImpl, addr._pImpl); } - + IPAddress SocketAddress::host() const { return _pImpl->host(); } - + Poco::UInt16 SocketAddress::port() const { return ntohs(_pImpl->port()); } - + poco_socklen_t SocketAddress::length() const { return _pImpl->length(); } - + const struct sockaddr* SocketAddress::addr() const { return _pImpl->addr(); diff --git a/Net/testsuite/src/SocketAddressTest.cpp b/Net/testsuite/src/SocketAddressTest.cpp index eaaa1e28f..16bdf1db1 100644 --- a/Net/testsuite/src/SocketAddressTest.cpp +++ b/Net/testsuite/src/SocketAddressTest.cpp @@ -12,14 +12,14 @@ // execute, and transmit the Software, and to prepare derivative works of the // Software, and to permit third-parties to whom the Software is furnished to // do so, all subject to the following: -// +// // The copyright notices in the Software and this entire statement, including // the above license grant, this restriction and the following disclaimer, // must be included in all copies of the Software, in whole or in part, and // all derivative works of the Software, unless such copies or derivative // works are solely in the form of machine-executable object code generated by // a source language processor. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT @@ -61,11 +61,11 @@ void SocketAddressTest::testSocketAddress() SocketAddress wild; assert (wild.host().isWildcard()); assert (wild.port() == 0); - + SocketAddress sa1("192.168.1.100", 100); assert (sa1.host().toString() == "192.168.1.100"); assert (sa1.port() == 100); - + SocketAddress sa2("192.168.1.100", "100"); assert (sa2.host().toString() == "192.168.1.100"); assert (sa2.port() == 100); @@ -84,11 +84,11 @@ void SocketAddressTest::testSocketAddress() catch (ServiceNotFoundException&) { } - + SocketAddress sa4("www.appinf.com", 80); assert (sa4.host().toString() == "50.57.108.29"); assert (sa4.port() == 80); - + try { SocketAddress sa5("192.168.2.260", 80); @@ -109,7 +109,7 @@ void SocketAddressTest::testSocketAddress() catch (ServiceNotFoundException&) { } - + SocketAddress sa7("192.168.2.120:88"); assert (sa7.host().toString() == "192.168.2.120"); assert (sa7.port() == 88); @@ -117,7 +117,7 @@ void SocketAddressTest::testSocketAddress() SocketAddress sa8("[192.168.2.120]:88"); assert (sa8.host().toString() == "192.168.2.120"); assert (sa8.port() == 88); - + try { SocketAddress sa9("[192.168.2.260]"); @@ -138,6 +138,20 @@ void SocketAddressTest::testSocketAddress() } +void SocketAddressTest::testSocketRelationals() +{ + SocketAddress sa1("192.168.1.100", 100); + SocketAddress sa2("192.168.1.100:100"); + assert (sa1 == sa2); + + SocketAddress sa3("192.168.1.101", "99"); + assert (sa2 < sa3); + + SocketAddress sa4("192.168.1.100", "102"); + assert (sa3 < sa4); +} + + void SocketAddressTest::testSocketAddress6() { #ifdef POCO_HAVE_IPv6 @@ -160,6 +174,7 @@ CppUnit::Test* SocketAddressTest::suite() CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SocketAddressTest"); CppUnit_addTest(pSuite, SocketAddressTest, testSocketAddress); + CppUnit_addTest(pSuite, SocketAddressTest, testSocketRelationals); CppUnit_addTest(pSuite, SocketAddressTest, testSocketAddress6); return pSuite; diff --git a/Net/testsuite/src/SocketAddressTest.h b/Net/testsuite/src/SocketAddressTest.h index 9f48a18a7..ab7f56415 100644 --- a/Net/testsuite/src/SocketAddressTest.h +++ b/Net/testsuite/src/SocketAddressTest.h @@ -14,14 +14,14 @@ // execute, and transmit the Software, and to prepare derivative works of the // Software, and to permit third-parties to whom the Software is furnished to // do so, all subject to the following: -// +// // The copyright notices in the Software and this entire statement, including // the above license grant, this restriction and the following disclaimer, // must be included in all copies of the Software, in whole or in part, and // all derivative works of the Software, unless such copies or derivative // works are solely in the form of machine-executable object code generated by // a source language processor. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT @@ -47,6 +47,7 @@ public: ~SocketAddressTest(); void testSocketAddress(); + void testSocketRelationals(); void testSocketAddress6(); void setUp();