mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-29 12:18:01 +01:00
merge Unix Domain Sockets support and other changes from develop
This commit is contained in:
@@ -18,19 +18,24 @@
|
||||
#include "Poco/Net/DNS.h"
|
||||
#include "Poco/RefCountedObject.h"
|
||||
#include "Poco/NumberParser.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/BinaryReader.h"
|
||||
#include "Poco/BinaryWriter.h"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
using Poco::RefCountedObject;
|
||||
using Poco::NumberParser;
|
||||
using Poco::NumberFormatter;
|
||||
using Poco::UInt16;
|
||||
using Poco::InvalidArgumentException;
|
||||
using Poco::Net::Impl::SocketAddressImpl;
|
||||
using Poco::Net::Impl::IPv4SocketAddressImpl;
|
||||
#ifdef POCO_HAVE_IPv6
|
||||
using Poco::Net::Impl::IPv6SocketAddressImpl;
|
||||
#endif
|
||||
#ifdef POCO_OS_FAMILY_UNIX
|
||||
using Poco::Net::Impl::LocalSocketAddressImpl;
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -51,12 +56,31 @@ struct AFLT
|
||||
//
|
||||
|
||||
|
||||
#if !defined(_MSC_VER) || defined(__STDC__)
|
||||
// Go home MSVC, you're drunk...
|
||||
// See http://stackoverflow.com/questions/5899857/multiple-definition-error-for-static-const-class-members
|
||||
const SocketAddress::Family SocketAddress::IPv4;
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
const SocketAddress::Family SocketAddress::IPv6;
|
||||
#endif
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
const SocketAddress::Family SocketAddress::UNIX_LOCAL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
SocketAddress::SocketAddress()
|
||||
{
|
||||
newIPv4();
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(Family fam)
|
||||
{
|
||||
init(IPAddress(fam), 0);
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(const IPAddress& hostAddress, Poco::UInt16 portNumber)
|
||||
{
|
||||
init(hostAddress, portNumber);
|
||||
@@ -69,65 +93,76 @@ SocketAddress::SocketAddress(Poco::UInt16 portNumber)
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(Family fam, Poco::UInt16 portNumber)
|
||||
{
|
||||
init(IPAddress(fam), portNumber);
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(const std::string& hostAddress, Poco::UInt16 portNumber)
|
||||
{
|
||||
init(hostAddress, portNumber);
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(Family fam, const std::string& hostAddress, Poco::UInt16 portNumber)
|
||||
{
|
||||
init(fam, hostAddress, portNumber);
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(const std::string& hostAddress, const std::string& portNumber)
|
||||
{
|
||||
init(hostAddress, resolveService(portNumber));
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(Family fam, const std::string& hostAddress, const std::string& portNumber)
|
||||
{
|
||||
init(fam, hostAddress, resolveService(portNumber));
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(Family fam, const std::string& addr)
|
||||
{
|
||||
init(fam, addr);
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(const std::string& hostAndPort)
|
||||
{
|
||||
poco_assert (!hostAndPort.empty());
|
||||
|
||||
std::string host;
|
||||
std::string port;
|
||||
std::string::const_iterator it = hostAndPort.begin();
|
||||
std::string::const_iterator end = hostAndPort.end();
|
||||
if (*it == '[')
|
||||
{
|
||||
++it;
|
||||
while (it != end && *it != ']') host += *it++;
|
||||
if (it == end) throw InvalidArgumentException("Malformed IPv6 address");
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (it != end && *it != ':') host += *it++;
|
||||
}
|
||||
if (it != end && *it == ':')
|
||||
{
|
||||
++it;
|
||||
while (it != end) port += *it++;
|
||||
}
|
||||
else throw InvalidArgumentException("Missing port number");
|
||||
init(host, resolveService(port));
|
||||
init(hostAndPort);
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(const SocketAddress& socketAddress)
|
||||
{
|
||||
if (socketAddress.family() == IPAddress::IPv4)
|
||||
if (socketAddress.family() == IPv4)
|
||||
newIPv4(reinterpret_cast<const sockaddr_in*>(socketAddress.addr()));
|
||||
else
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
else if (socketAddress.family() == IPv6)
|
||||
newIPv6(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr()));
|
||||
#endif
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
else if (socketAddress.family() == UNIX_LOCAL)
|
||||
newLocal(reinterpret_cast<const sockaddr_un*>(socketAddress.addr()));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(const struct sockaddr* sockAddr, poco_socklen_t length)
|
||||
{
|
||||
if (length == sizeof(struct sockaddr_in))
|
||||
if (length == sizeof(struct sockaddr_in) && sockAddr->sa_family == AF_INET)
|
||||
newIPv4(reinterpret_cast<const struct sockaddr_in*>(sockAddr));
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
else if (length == sizeof(struct sockaddr_in6))
|
||||
else if (length == sizeof(struct sockaddr_in6) && sockAddr->sa_family == AF_INET6)
|
||||
newIPv6(reinterpret_cast<const struct sockaddr_in6*>(sockAddr));
|
||||
#endif
|
||||
else throw Poco::InvalidArgumentException("Invalid address length passed to SocketAddress()");
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
else if (length > 0 && length <= sizeof(struct sockaddr_un) && sockAddr->sa_family == AF_UNIX)
|
||||
newLocal(reinterpret_cast<const sockaddr_un*>(sockAddr));
|
||||
#endif
|
||||
else throw Poco::InvalidArgumentException("Invalid address length or family passed to SocketAddress()");
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +176,9 @@ bool SocketAddress::operator < (const SocketAddress& socketAddress) const
|
||||
{
|
||||
if (family() < socketAddress.family()) return true;
|
||||
if (family() > socketAddress.family()) return false;
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
if (family() == UNIX_LOCAL) return toString() < socketAddress.toString();
|
||||
#endif
|
||||
if (host() < socketAddress.host()) return true;
|
||||
if (host() > socketAddress.host()) return false;
|
||||
return (port() < socketAddress.port());
|
||||
@@ -152,10 +190,16 @@ SocketAddress& SocketAddress::operator = (const SocketAddress& socketAddress)
|
||||
if (&socketAddress != this)
|
||||
{
|
||||
destruct();
|
||||
if (socketAddress.family() == IPAddress::IPv4)
|
||||
if (socketAddress.family() == IPv4)
|
||||
newIPv4(reinterpret_cast<const sockaddr_in*>(socketAddress.addr()));
|
||||
else
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
else if (socketAddress.family() == IPv6)
|
||||
newIPv6(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr()));
|
||||
#endif
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
else if (socketAddress.family() == UNIX_LOCAL)
|
||||
newLocal(reinterpret_cast<const sockaddr_un*>(socketAddress.addr()));
|
||||
#endif
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -191,19 +235,15 @@ int SocketAddress::af() const
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::Family SocketAddress::family() const
|
||||
{
|
||||
return static_cast<Family>(pImpl()->family());
|
||||
}
|
||||
|
||||
|
||||
std::string SocketAddress::toString() const
|
||||
{
|
||||
std::string result;
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
if (host().family() == IPAddress::IPv6)
|
||||
result.append("[");
|
||||
result.append(host().toString());
|
||||
if (host().family() == IPAddress::IPv6)
|
||||
result.append("]");
|
||||
#endif
|
||||
result.append(":");
|
||||
NumberFormatter::append(result, port());
|
||||
return result;
|
||||
return pImpl()->toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -232,7 +272,7 @@ void SocketAddress::init(const std::string& hostAddress, Poco::UInt16 portNumber
|
||||
HostEntry::AddressList addresses = he.addresses();
|
||||
if (addresses.size() > 0)
|
||||
{
|
||||
#if defined(POCO_HAVE_IPv6) && !defined(POCO_SOCKETADDRESS_DONT_PREFER_IPV4)
|
||||
#if defined(POCO_HAVE_IPv6) && defined(POCO_SOCKETADDRESS_PREFER_IPv4)
|
||||
// if we get both IPv4 and IPv6 addresses, prefer IPv4
|
||||
std::stable_sort(addresses.begin(), addresses.end(), AFLT());
|
||||
#endif
|
||||
@@ -243,6 +283,109 @@ void SocketAddress::init(const std::string& hostAddress, Poco::UInt16 portNumber
|
||||
}
|
||||
|
||||
|
||||
void SocketAddress::init(Family fam, const std::string& hostAddress, Poco::UInt16 portNumber)
|
||||
{
|
||||
IPAddress ip;
|
||||
if (IPAddress::tryParse(hostAddress, ip))
|
||||
{
|
||||
if (ip.family() != fam) throw AddressFamilyMismatchException(hostAddress);
|
||||
init(ip, portNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
HostEntry he = DNS::hostByName(hostAddress);
|
||||
HostEntry::AddressList addresses = he.addresses();
|
||||
if (addresses.size() > 0)
|
||||
{
|
||||
for (HostEntry::AddressList::const_iterator it = addresses.begin(); it != addresses.end(); ++it)
|
||||
{
|
||||
if (it->family() == fam)
|
||||
{
|
||||
init(*it, portNumber);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw AddressFamilyMismatchException(hostAddress);
|
||||
}
|
||||
else throw HostNotFoundException("No address found for host", hostAddress);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SocketAddress::init(Family fam, const std::string& address)
|
||||
{
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
if (fam == UNIX_LOCAL)
|
||||
{
|
||||
newLocal(address);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
std::string host;
|
||||
std::string port;
|
||||
std::string::const_iterator it = address.begin();
|
||||
std::string::const_iterator end = address.end();
|
||||
|
||||
if (*it == '[')
|
||||
{
|
||||
++it;
|
||||
while (it != end && *it != ']') host += *it++;
|
||||
if (it == end) throw InvalidArgumentException("Malformed IPv6 address");
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (it != end && *it != ':') host += *it++;
|
||||
}
|
||||
if (it != end && *it == ':')
|
||||
{
|
||||
++it;
|
||||
while (it != end) port += *it++;
|
||||
}
|
||||
else throw InvalidArgumentException("Missing port number");
|
||||
init(fam, host, resolveService(port));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SocketAddress::init(const std::string& hostAndPort)
|
||||
{
|
||||
poco_assert (!hostAndPort.empty());
|
||||
|
||||
std::string host;
|
||||
std::string port;
|
||||
std::string::const_iterator it = hostAndPort.begin();
|
||||
std::string::const_iterator end = hostAndPort.end();
|
||||
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
if (*it == '/')
|
||||
{
|
||||
newLocal(hostAndPort);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (*it == '[')
|
||||
{
|
||||
++it;
|
||||
while (it != end && *it != ']') host += *it++;
|
||||
if (it == end) throw InvalidArgumentException("Malformed IPv6 address");
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (it != end && *it != ':') host += *it++;
|
||||
}
|
||||
if (it != end && *it == ':')
|
||||
{
|
||||
++it;
|
||||
while (it != end) port += *it++;
|
||||
}
|
||||
else throw InvalidArgumentException("Missing port number");
|
||||
init(host, resolveService(port));
|
||||
}
|
||||
|
||||
|
||||
Poco::UInt16 SocketAddress::resolveService(const std::string& service)
|
||||
{
|
||||
unsigned port;
|
||||
@@ -266,3 +409,29 @@ Poco::UInt16 SocketAddress::resolveService(const std::string& service)
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
||||
|
||||
Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::SocketAddress& value)
|
||||
{
|
||||
writer << value.host();
|
||||
writer << value.port();
|
||||
return writer;
|
||||
}
|
||||
|
||||
|
||||
Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::SocketAddress& value)
|
||||
{
|
||||
Poco::Net::IPAddress host;
|
||||
reader >> host;
|
||||
Poco::UInt16 port;
|
||||
reader >> port;
|
||||
value = Poco::Net::SocketAddress(host, port);
|
||||
return reader;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator << (std::ostream& ostr, const Poco::Net::SocketAddress& address)
|
||||
{
|
||||
ostr << address.toString();
|
||||
return ostr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user