📄 sockets.cxx
字号:
#else
sockaddr_in address;
socklen_t size = sizeof(address);
if (getpeername(os_handle, (struct sockaddr *)&address, &size) == 0)
return GetHostName(address.sin_addr) + psprintf(":%u", ntohs(address.sin_port));
#endif
return PString::Empty();
}
PString PIPSocket::GetHostName()
{
char name[100];
if (gethostname(name, sizeof(name)-1) != 0)
return "localhost";
name[sizeof(name)-1] = '\0';
return name;
}
PString PIPSocket::GetHostName(const PString & hostname)
{
// lookup the host address using inet_addr, assuming it is a "." address
Address temp = hostname;
if (temp != 0)
return GetHostName(temp);
PString canonicalname;
if (pHostByName().GetHostName(hostname, canonicalname))
return canonicalname;
return hostname;
}
PString PIPSocket::GetHostName(const Address & addr)
{
if (addr == 0)
return addr.AsString();
PString hostname;
if (pHostByAddr().GetHostName(addr, hostname))
return hostname;
return addr.AsString();
}
PBoolean PIPSocket::GetHostAddress(Address & addr)
{
return pHostByName().GetHostAddress(GetHostName(), addr);
}
PBoolean PIPSocket::GetHostAddress(const PString & hostname, Address & addr)
{
if (hostname.IsEmpty())
return PFalse;
// Check for special case of "[ipaddr]"
if (hostname[0] == '[') {
PINDEX end = hostname.Find(']');
if (end != P_MAX_INDEX) {
if (addr.FromString(hostname(1, end-1)))
return PTrue;
}
}
// Assuming it is a "." address and return if so
if (addr.FromString(hostname))
return PTrue;
// otherwise lookup the name as a host name
return pHostByName().GetHostAddress(hostname, addr);
}
PStringArray PIPSocket::GetHostAliases(const PString & hostname)
{
PStringArray aliases;
// lookup the host address using inet_addr, assuming it is a "." address
Address addr = hostname;
if (addr != 0)
pHostByAddr().GetHostAliases(addr, aliases);
else
pHostByName().GetHostAliases(hostname, aliases);
return aliases;
}
PStringArray PIPSocket::GetHostAliases(const Address & addr)
{
PStringArray aliases;
pHostByAddr().GetHostAliases(addr, aliases);
return aliases;
}
PString PIPSocket::GetLocalAddress()
{
PStringStream str;
Address addr;
WORD port;
if (GetLocalAddress(addr, port))
str << addr << ':' << port;
return str;
}
PBoolean PIPSocket::GetLocalAddress(Address & addr)
{
WORD dummy;
return GetLocalAddress(addr, dummy);
}
PBoolean PIPSocket::GetLocalAddress(Address & addr, WORD & portNum)
{
#if P_HAS_IPV6
Address addrv4;
Address peerv4;
Psockaddr sa;
socklen_t size = sa.GetSize();
if (!ConvertOSError(::getsockname(os_handle, sa, &size)))
return PFalse;
addr = sa.GetIP();
portNum = sa.GetPort();
// If the remote host is an IPv4 only host and our interface if an IPv4/IPv6 mapped
// Then return an IPv4 address instead of an IPv6
if (GetPeerAddress(peerv4)) {
if ((peerv4.GetVersion()==4)||(peerv4.IsV4Mapped())) {
if (addr.IsV4Mapped()) {
addr = Address(addr[12], addr[13], addr[14], addr[15]);
}
}
}
#else
sockaddr_in address;
socklen_t size = sizeof(address);
if (!ConvertOSError(::getsockname(os_handle,(struct sockaddr*)&address,&size)))
return PFalse;
addr = address.sin_addr;
portNum = ntohs(address.sin_port);
#endif
return PTrue;
}
PString PIPSocket::GetPeerAddress()
{
PStringStream str;
Address addr;
WORD port;
if (GetPeerAddress(addr, port))
str << addr << ':' << port;
return str;
}
PBoolean PIPSocket::GetPeerAddress(Address & addr)
{
WORD portNum;
return GetPeerAddress(addr, portNum);
}
PBoolean PIPSocket::GetPeerAddress(Address & addr, WORD & portNum)
{
#if P_HAS_IPV6
Psockaddr sa;
socklen_t size = sa.GetSize();
if (!ConvertOSError(::getpeername(os_handle, sa, &size)))
return PFalse;
addr = sa.GetIP();
portNum = sa.GetPort();
#else
sockaddr_in address;
socklen_t size = sizeof(address);
if (!ConvertOSError(::getpeername(os_handle,(struct sockaddr*)&address,&size)))
return PFalse;
addr = address.sin_addr;
portNum = ntohs(address.sin_port);
#endif
return PTrue;
}
PString PIPSocket::GetLocalHostName()
{
Address addr;
if (GetLocalAddress(addr))
return GetHostName(addr);
return PString::Empty();
}
PString PIPSocket::GetPeerHostName()
{
Address addr;
if (GetPeerAddress(addr))
return GetHostName(addr);
return PString::Empty();
}
PBoolean PIPSocket::Connect(const PString & host)
{
Address ipnum(host);
#if P_HAS_IPV6
if (ipnum.IsValid() || GetHostAddress(host, ipnum))
return Connect(GetDefaultIpAny(), 0, ipnum);
#else
if (ipnum.IsValid() || GetHostAddress(host, ipnum))
return Connect(INADDR_ANY, 0, ipnum);
#endif
return PFalse;
}
PBoolean PIPSocket::Connect(const Address & addr)
{
#if P_HAS_IPV6
return Connect(GetDefaultIpAny(), 0, addr);
#else
return Connect(INADDR_ANY, 0, addr);
#endif
}
PBoolean PIPSocket::Connect(WORD localPort, const Address & addr)
{
#if P_HAS_IPV6
return Connect(GetDefaultIpAny(), localPort, addr);
#else
return Connect(INADDR_ANY, localPort, addr);
#endif
}
PBoolean PIPSocket::Connect(const Address & iface, const Address & addr)
{
return Connect(iface, 0, addr);
}
PBoolean PIPSocket::Connect(const Address & iface, WORD localPort, const Address & addr)
{
// close the port if it is already open
if (IsOpen())
Close();
// make sure we have a port
PAssert(port != 0, "Cannot connect socket without setting port");
#if P_HAS_IPV6
Psockaddr sa(addr, port);
// attempt to create a socket with the right family
if (!OpenSocket(sa->sa_family))
return PFalse;
if (localPort != 0 || iface.IsValid()) {
Psockaddr bind_sa(iface, localPort);
if (!SetOption(SO_REUSEADDR, 0)) {
os_close();
return PFalse;
}
if (!ConvertOSError(::bind(os_handle, bind_sa, bind_sa.GetSize()))) {
os_close();
return PFalse;
}
}
// attempt to connect
if (os_connect(sa, sa.GetSize()))
return PTrue;
#else
// attempt to create a socket
if (!OpenSocket())
return PFalse;
// attempt to connect
sockaddr_in sin;
if (localPort != 0 || iface.IsValid()) {
if (!SetOption(SO_REUSEADDR, 0)) {
os_close();
return PFalse;
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = iface;
sin.sin_port = htons(localPort); // set the port
if (!ConvertOSError(::bind(os_handle, (struct sockaddr*)&sin, sizeof(sin)))) {
os_close();
return PFalse;
}
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port); // set the port
sin.sin_addr = addr;
if (os_connect((struct sockaddr *)&sin, sizeof(sin)))
return PTrue;
#endif
os_close();
return PFalse;
}
PBoolean PIPSocket::Listen(unsigned queueSize, WORD newPort, Reusability reuse)
{
#if P_HAS_IPV6
return Listen(GetDefaultIpAny(), queueSize, newPort, reuse);
#else
return Listen(INADDR_ANY, queueSize, newPort, reuse);
#endif
}
PBoolean PIPSocket::Listen(const Address & bindAddr,
unsigned,
WORD newPort,
Reusability reuse)
{
// make sure we have a port
if (newPort != 0)
port = newPort;
#if P_HAS_IPV6
Psockaddr bind_sa(bindAddr, port);
if (IsOpen()) {
int socketType;
if (!GetOption(SO_TYPE, socketType, SOL_SOCKET) || bind_sa->sa_family != socketType)
Close();
}
#endif
if (!IsOpen()) {
// attempt to create a socket
#if P_HAS_IPV6
if (!OpenSocket(bind_sa->sa_family))
return PFalse;
#else
if (!OpenSocket())
return PFalse;
#endif
}
#ifndef __BEOS__
// attempt to listen
if (!SetOption(SO_REUSEADDR, reuse == CanReuseAddress ? 1 : 0)) {
os_close();
return PFalse;
}
#else
// attempt to listen
int value = reuse == CanReuseAddress ? 1 : 0;
if (!SetOption(SO_REUSEADDR, &value, sizeof(int))) {
os_close();
return PFalse;
}
#endif // BEOS
#if P_HAS_IPV6
if (ConvertOSError(::bind(os_handle, bind_sa, bind_sa.GetSize()))) {
Psockaddr sa;
socklen_t size = sa.GetSize();
if (!ConvertOSError(::getsockname(os_handle, sa, &size)))
return PFalse;
port = sa.GetPort();
return PTrue;
}
#else
// attempt to listen
sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = bindAddr;
sin.sin_port = htons(port); // set the port
#ifdef __NUCLEUS_NET__
int bind_result;
if (port == 0)
bind_result = ::bindzero(os_handle, (struct sockaddr*)&sin, sizeof(sin));
else
bind_result = ::bind(os_handle, (struct sockaddr*)&sin, sizeof(sin));
if (ConvertOSError(bind_result))
#else
if (ConvertOSError(::bind(os_handle, (struct sockaddr*)&sin, sizeof(sin))))
#endif
{
socklen_t size = sizeof(sin);
if (ConvertOSError(::getsockname(os_handle, (struct sockaddr*)&sin, &size))) {
port = ntohs(sin.sin_port);
return PTrue;
}
}
#endif
os_close();
return PFalse;
}
const PIPSocket::Address & PIPSocket::Address::GetLoopback()
{
return loopback4;
}
#if P_HAS_IPV6
/// Check for v4 mapped i nv6 address ::ffff:a.b.c.d
PBoolean PIPSocket::Address::IsV4Mapped() const
{
if (version != 6)
return PFalse;
return IN6_IS_ADDR_V4MAPPED(&v.six) || IN6_IS_ADDR_V4COMPAT(&v.six);
}
const PIPSocket::Address & PIPSocket::Address::GetLoopback6()
{
return loopback6;
}
const PIPSocket::Address & PIPSocket::Address::GetAny6()
{
return any6;
}
#endif
PBoolean PIPSocket::Address::IsAny() const
{
return (!IsValid());
}
const PIPSocket::Address & PIPSocket::Address::GetBroadcast()
{
return broadcast4;
}
PIPSocket::Address::Address()
{
*this = loopback4;
}
PIPSocket::Address::Address(const PString & dotNotation)
{
operator=(dotNotation);
}
PIPSocket::Address::Address(PINDEX len, const BYTE * bytes)
{
switch (len) {
#if P_HAS_IPV6
case 16 :
version = 6;
memcpy(&v.six, bytes, len);
break;
#endif
case 4 :
version = 4;
memcpy(&v.four, bytes, len);
break;
default :
version = 0;
}
}
PIPSocket::Address::Address(const in_addr & addr)
{
version = 4;
v.four = addr;
}
#if P_HAS_IPV6
PIPSocket::Address::Address(const in6_addr & addr)
{
version = 6;
v.six = addr;
}
// Create an IP (v4 or v6) address from a sockaddr (sockaddr_in, sockaddr_in6 or sockaddr_in6_old) structure
PIPSocket::Address::Address(const int ai_family, const int ai_addrlen, struct sockaddr *ai_addr)
{
switch (ai_family) {
#if P_HAS_IPV6
case AF_INET6:
if (ai_addrlen < (int)sizeof(sockaddr_in6))
break;
version = 6;
v.six = ((struct sockaddr_in6 *)ai_addr)->sin6_addr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -