📄 sockets.cxx
字号:
BOOL PSocket::Connect(const PString &)
{
PAssertAlways("Illegal operation.");
return FALSE;
}
BOOL PSocket::Listen(unsigned, WORD, Reusability)
{
PAssertAlways("Illegal operation.");
return FALSE;
}
BOOL PSocket::Accept(PSocket &)
{
PAssertAlways("Illegal operation.");
return FALSE;
}
BOOL PSocket::SetOption(int option, int value, int level)
{
#ifdef _WIN32_WCE
if(option == SO_RCVBUF || option == SO_SNDBUF || option == IP_TOS)
return TRUE;
#endif
return ConvertOSError(::setsockopt(os_handle, level, option,
(char *)&value, sizeof(value)));
}
BOOL PSocket::SetOption(int option, const void * valuePtr, PINDEX valueSize, int level)
{
return ConvertOSError(::setsockopt(os_handle, level, option,
(char *)valuePtr, valueSize));
}
BOOL PSocket::GetOption(int option, int & value, int level)
{
socklen_t valSize = sizeof(value);
return ConvertOSError(::getsockopt(os_handle, level, option,
(char *)&value, &valSize));
}
BOOL PSocket::GetOption(int option, void * valuePtr, PINDEX valueSize, int level)
{
return ConvertOSError(::getsockopt(os_handle, level, option,
(char *)valuePtr, (socklen_t *)&valueSize));
}
BOOL PSocket::Shutdown(ShutdownValue value)
{
return ConvertOSError(::shutdown(os_handle, value));
}
WORD PSocket::GetProtocolByName(const PString & name)
{
#if !defined(__NUCLEUS_PLUS__) && !defined(_WIN32_WCE) && !defined(P_VXWORKS)
struct protoent * ent = getprotobyname(name);
if (ent != NULL)
return ent->p_proto;
#endif
return 0;
}
PString PSocket::GetNameByProtocol(WORD proto)
{
#if !defined(__NUCLEUS_PLUS__) && !defined(_WIN32_WCE) && !defined(P_VXWORKS)
struct protoent * ent = getprotobynumber(proto);
if (ent != NULL)
return ent->p_name;
#endif
return psprintf("%u", proto);
}
WORD PSocket::GetPortByService(const PString & serviceName) const
{
return GetPortByService(GetProtocolName(), serviceName);
}
WORD PSocket::GetPortByService(const char * protocol, const PString & service)
{
// if the string is a valid integer, then use integer value
// this avoids stupid problems like operating systems that match service
// names to substrings (like "2000" to "taskmaster2000")
if (strspn(service, "0123456789") == strlen(service))
return (WORD)service.AsUnsigned();
#if defined( __NUCLEUS_PLUS__ )
PAssertAlways("PSocket::GetPortByService: problem as no ::getservbyname in Nucleus NET");
return 0;
#elif defined(_WIN32_WCE)
PAssertAlways("PSocket::GetPortByService: problem for WindowsCE as no port given.");
return 0;
#elif defined(P_VXWORKS)
PAssertAlways("PSocket::GetPortByService: problem as no ::getservbyname in VxWorks");
return 0;
#else
PINDEX space = service.FindOneOf(" \t\r\n");
struct servent * serv = ::getservbyname(service(0, space-1), protocol);
if (serv != NULL)
return ntohs(serv->s_port);
long portNum;
if (space != P_MAX_INDEX)
portNum = atol(service(space+1, P_MAX_INDEX));
else if (isdigit(service[0]))
portNum = atoi(service);
else
portNum = -1;
if (portNum < 0 || portNum > 65535)
return 0;
return (WORD)portNum;
#endif
}
PString PSocket::GetServiceByPort(WORD port) const
{
return GetServiceByPort(GetProtocolName(), port);
}
PString PSocket::GetServiceByPort(const char * protocol, WORD port)
{
#if !defined(__NUCLEUS_PLUS__) && !defined(_WIN32_WCE) && !defined(P_VXWORKS)
struct servent * serv = ::getservbyport(htons(port), protocol);
if (serv != NULL)
return PString(serv->s_name);
else
#endif
return PString(PString::Unsigned, port);
}
void PSocket::SetPort(WORD newPort)
{
PAssert(!IsOpen(), "Cannot change port number of opened socket");
port = newPort;
}
void PSocket::SetPort(const PString & service)
{
PAssert(!IsOpen(), "Cannot change port number of opened socket");
port = GetPortByService(service);
}
WORD PSocket::GetPort() const
{
return port;
}
PString PSocket::GetService() const
{
return GetServiceByPort(port);
}
int PSocket::Select(PSocket & sock1, PSocket & sock2)
{
return Select(sock1, sock2, PMaxTimeInterval);
}
int PSocket::Select(PSocket & sock1,
PSocket & sock2,
const PTimeInterval & timeout)
{
SelectList read, dummy1, dummy2;
read += sock1;
read += sock2;
Errors lastError;
int osError;
if (!ConvertOSError(Select(read, dummy1, dummy2, timeout), lastError, osError))
return lastError;
switch (read.GetSize()) {
case 0 :
return 0;
case 2 :
return -3;
default :
return &read[0] == &sock1 ? -1 : -2;
}
}
PChannel::Errors PSocket::Select(SelectList & read)
{
SelectList dummy1, dummy2;
return Select(read, dummy1, dummy2, PMaxTimeInterval);
}
PChannel::Errors PSocket::Select(SelectList & read, const PTimeInterval & timeout)
{
SelectList dummy1, dummy2;
return Select(read, dummy1, dummy2, timeout);
}
PChannel::Errors PSocket::Select(SelectList & read, SelectList & write)
{
SelectList dummy1;
return Select(read, write, dummy1, PMaxTimeInterval);
}
PChannel::Errors PSocket::Select(SelectList & read,
SelectList & write,
const PTimeInterval & timeout)
{
SelectList dummy1;
return Select(read, write, dummy1, timeout);
}
PChannel::Errors PSocket::Select(SelectList & read,
SelectList & write,
SelectList & except)
{
return Select(read, write, except, PMaxTimeInterval);
}
//////////////////////////////////////////////////////////////////////////////
// PIPSocket
PIPSocket::PIPSocket()
{
}
void PIPSocket::ClearNameCache()
{
pHostByName().mutex.Wait();
pHostByAddr().mutex.Wait();
pHostByName().RemoveAll();
pHostByAddr().RemoveAll();
#if (defined(_WIN32) || defined(WINDOWS)) && !defined(__NUCLEUS_MNT__) // Kludge to avoid strange NT bug
static PTimeInterval delay = GetConfigTime("NT Bug Delay", 0);
if (delay != 0) {
::Sleep(delay.GetInterval());
::gethostbyname("www.microsoft.com");
}
#endif
pHostByName().mutex.Signal();
pHostByAddr().mutex.Signal();
}
PString PIPSocket::GetName() const
{
#if P_HAS_IPV6
Psockaddr sa;
socklen_t size = sa.GetSize();
if (getpeername(os_handle, sa, &size) == 0)
return GetHostName(sa.GetIP()) + psprintf(":%u", sa.GetPort());
#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();
}
BOOL PIPSocket::GetHostAddress(Address & addr)
{
return pHostByName().GetHostAddress(GetHostName(), addr);
}
BOOL PIPSocket::GetHostAddress(const PString & hostname, Address & addr)
{
if (hostname.IsEmpty())
return FALSE;
// 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 TRUE;
}
}
// Assuming it is a "." address and return if so
if (addr.FromString(hostname))
return TRUE;
// 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;
}
BOOL PIPSocket::GetLocalAddress(Address & addr)
{
WORD dummy;
return GetLocalAddress(addr, dummy);
}
BOOL 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 FALSE;
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 FALSE;
addr = address.sin_addr;
portNum = ntohs(address.sin_port);
#endif
return TRUE;
}
BOOL PIPSocket::GetPeerAddress(Address & addr)
{
WORD portNum;
return GetPeerAddress(addr, portNum);
}
BOOL 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 FALSE;
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 FALSE;
addr = address.sin_addr;
portNum = ntohs(address.sin_port);
#endif
return TRUE;
}
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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -