📄 sockets.cxx
字号:
}
BOOL PIPSocket::Connect(const PString & host)
{
Address ipnum;
#if P_HAS_IPV6
if (GetHostAddress(host, ipnum))
return Connect(GetDefaultIpAny(), 0, ipnum);
#else
if (GetHostAddress(host, ipnum))
return Connect(INADDR_ANY, 0, ipnum);
#endif
return FALSE;
}
BOOL PIPSocket::Connect(const Address & addr)
{
#if P_HAS_IPV6
return Connect(GetDefaultIpAny(), 0, addr);
#else
return Connect(INADDR_ANY, 0, addr);
#endif
}
BOOL PIPSocket::Connect(WORD localPort, const Address & addr)
{
#if P_HAS_IPV6
return Connect(GetDefaultIpAny(), localPort, addr);
#else
return Connect(INADDR_ANY, localPort, addr);
#endif
}
BOOL PIPSocket::Connect(const Address & iface, const Address & addr)
{
return Connect(iface, 0, addr);
}
BOOL 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 FALSE;
if (localPort != 0 || iface.IsValid()) {
Psockaddr bind_sa(iface, localPort);
if (!SetOption(SO_REUSEADDR, 0)) {
os_close();
return FALSE;
}
if (!ConvertOSError(::bind(os_handle, bind_sa, bind_sa.GetSize()))) {
os_close();
return FALSE;
}
}
// attempt to connect
if (os_connect(sa, sa.GetSize()))
return TRUE;
#else
// attempt to create a socket
if (!OpenSocket())
return FALSE;
// attempt to connect
sockaddr_in sin;
if (localPort != 0 || iface.IsValid()) {
if (!SetOption(SO_REUSEADDR, 0)) {
os_close();
return FALSE;
}
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 FALSE;
}
}
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 TRUE;
#endif
os_close();
return FALSE;
}
BOOL 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
}
BOOL 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 FALSE;
#else
if (!OpenSocket())
return FALSE;
#endif
}
#ifndef __BEOS__
// attempt to listen
if (!SetOption(SO_REUSEADDR, reuse == CanReuseAddress ? 1 : 0)) {
os_close();
return FALSE;
}
#else
// attempt to listen
int value = reuse == CanReuseAddress ? 1 : 0;
if (!SetOption(SO_REUSEADDR, &value, sizeof(int))) {
os_close();
return FALSE;
}
#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 FALSE;
port = sa.GetPort();
return TRUE;
}
#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 TRUE;
}
}
#endif
os_close();
return FALSE;
}
const PIPSocket::Address & PIPSocket::Address::GetLoopback()
{
return loopback4;
}
#if P_HAS_IPV6
/// Check for v4 mapped i nv6 address ::ffff:a.b.c.d
BOOL PIPSocket::Address::IsV4Mapped() const
{
if (version != 6)
return FALSE;
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
BOOL 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;
//sin6_scope_id, should be taken into account for link local addresses
return;
#endif
case AF_INET:
if (ai_addrlen < (int)sizeof(sockaddr_in))
break;
version = 4;
v.four = ((struct sockaddr_in *)ai_addr)->sin_addr;
return;
}
version = 0;
}
#endif
#ifdef __NUCLEUS_NET__
PIPSocket::Address::Address(const struct id_struct & addr)
{
operator=(addr);
}
PIPSocket::Address & PIPSocket::Address::operator=(const struct id_struct & addr)
{
s_addr = (((unsigned long)addr.is_ip_addrs[0])<<24) +
(((unsigned long)addr.is_ip_addrs[1])<<16) +
(((unsigned long)addr.is_ip_addrs[2])<<8) +
(((unsigned long)addr.is_ip_addrs[3]));
return *this;
}
#endif
PIPSocket::Address & PIPSocket::Address::operator=(const in_addr & addr)
{
version = 4;
v.four = addr;
return *this;
}
#if P_HAS_IPV6
PIPSocket::Address & PIPSocket::Address::operator=(const in6_addr & addr)
{
version = 6;
v.six = addr;
return *this;
}
#endif
PObject::Comparison PIPSocket::Address::Compare(const PObject & obj) const
{
const PIPSocket::Address & other = (const PIPSocket::Address &)obj;
if (version < other.version)
return LessThan;
if (version > other.version)
return GreaterThan;
#if P_HAS_IPV6
if (version == 6) {
int result = memcmp(&v.six, &other.v.six, sizeof(v.six));
if (result < 0)
return LessThan;
if (result > 0)
return GreaterThan;
return EqualTo;
}
#endif
if ((DWORD)*this < other)
return LessThan;
if ((DWORD)*this > other)
return GreaterThan;
return EqualTo;
}
#if P_HAS_IPV6
bool PIPSocket::Address::operator*=(const PIPSocket::Address & addr) const
{
if (version == addr.version)
return operator==(addr);
if (this->GetVersion() == 6 && this->IsV4Mapped())
return PIPSocket::Address((*this)[12], (*this)[13], (*this)[14], (*this)[15]) == addr;
else if (addr.GetVersion() == 6 && addr.IsV4Mapped())
return *this == PIPSocket::Address(addr[12], addr[13], addr[14], addr[15]);
return FALSE;
}
bool PIPSocket::Address::operator==(in6_addr & addr) const
{
PIPSocket::Address a(addr);
return Compare(a) == EqualTo;
}
#endif
bool PIPSocket::Address::operator==(in_addr & addr) const
{
PIPSocket::Address a(addr);
return Compare(a) == EqualTo;
}
bool PIPSocket::Address::operator==(DWORD dw) const
{
if (dw != 0)
return (DWORD)*this == dw;
return !IsValid();
}
PIPSocket::Address & PIPSocket::Address::operator=(const PString & dotNotation)
{
#if P_HAS_IPV6
struct addrinfo *res;
struct addrinfo hints = { AI_NUMERICHOST, PF_UNSPEC }; // Could be IPv4: x.x.x.x or IPv6: x:x:x:x::x
version = 0;
memset(&v, 0, sizeof(v));
if (getaddrinfo((const char *)dotNotation, NULL , &hints, &res) == 0) {
if (res->ai_family == PF_INET6) {
// IPv6 addr
version = 6;
struct sockaddr_in6 * addr_in6 = (struct sockaddr_in6 *)res->ai_addr;
v.six = addr_in6->sin6_addr;
} else {
// IPv4 addr
version = 4;
struct sockaddr_in * addr_in = (struct sockaddr_in *)res->ai_addr;
v.four = addr_in->sin_addr;
}
freeaddrinfo(res);
}
#else //P_HAS_IPV6
if (::strspn(dotNotation, "0123456789.") < ::strlen(dotNotation))
*this = 0;
else {
version = 4;
v.four.s_addr = inet_addr((const char *)dotNotation);
if (v.four.s_addr == (DWORD)INADDR_NONE)
v.four.s_addr = 0;
}
#endif
return *this;
}
PString PIPSocket::Address::AsString() const
{
#if P_HAS_IPV6
if (version == 6) {
PString str;
Psockaddr sa(*this, 0);
PAssertOS(getnameinfo(sa, sa.GetSize(), str.GetPointer(1024), 1024, NULL, 0, NI_NUMERICHOST) == 0);
PINDEX percent = str.Find('%'); // used for scoped address e.g. fe80::1%ne0, (ne0=network interface 0)
if (percen
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -