📄 sockets.cxx
字号:
PIPCacheData * host = GetHost(addr);
if (host != NULL)
address = host->GetHostAddress();
mutex.Signal();
return host != NULL;
}
BOOL PHostByAddr::GetHostAliases(const PIPSocket::Address & addr, PStringArray & aliases)
{
PIPCacheData * host = GetHost(addr);
if (host != NULL) {
const PStringList & a = host->GetHostAliases();
aliases.SetSize(a.GetSize());
for (PINDEX i = 0; i < a.GetSize(); i++)
aliases[i] = a[i];
}
mutex.Signal();
return host != NULL;
}
PIPCacheData * PHostByAddr::GetHost(const PIPSocket::Address & addr)
{
mutex.Wait();
PIPCacheKey key = addr;
PIPCacheData * host = GetAt(key);
if (host != NULL && host->HasAged()) {
SetAt(key, NULL);
host = NULL;
}
if (host == NULL) {
mutex.Signal();
struct hostent * host_info;
int retry = 3;
do {
#if defined(P_PTHREADS) && !defined(P_THREAD_SAFE_CLIB)
// this function should really be a static on PIPSocket, but this would
// require allocating thread-local storage for the data and that's too much
// of a pain!
struct hostent hostEnt;
int localErrNo;
char buffer[REENTRANT_BUFFER_LEN];
#ifdef P_LINUX
::gethostbyaddr_r((const char *)&addr, sizeof(addr),
PF_INET,
&hostEnt,
buffer, REENTRANT_BUFFER_LEN,
&host_info,
&localErrNo);
#else
host_info = ::gethostbyaddr_r((const char *)&addr, sizeof(addr), PF_INET,
&hostEnt, buffer, REENTRANT_BUFFER_LEN, &localErrNo);
#endif
#elif defined (P_VXWORKS)
char buffer[1024];
// added by Jurjan
host_info = ::resolvGetHostByAddr((const char *)&addr, buffer, 1024);
#else
host_info = ::gethostbyaddr((const char *)&addr, sizeof(addr), PF_INET);
#if defined(_WIN32) || defined(WINDOWS) // Kludge to avoid strange 95 bug
extern P_IsOldWin95();
if (P_IsOldWin95() && host_info != NULL && host_info->h_addr_list[0] != NULL)
host_info->h_addr_list[1] = NULL;
#endif
#endif // added by Jurjan
} while (errno == S_resolvLib_TRY_AGAIN && --retry > 0); //(h_errno == TRY_AGAIN && --retry > 0);
mutex.Wait();
if (retry == 0)
return FALSE;
host = new PIPCacheData(host_info, inet_ntoa(addr.s_addr));
SetAt(key, host);
}
if (host->GetHostAddress() == 0)
return NULL;
return host;
}
//////////////////////////////////////////////////////////////////////////////
// PSocket
PSocket::PSocket()
{
port = 0;
}
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)
{
return ConvertOSError(::setsockopt(os_handle,
SOL_SOCKET, option, (char *)&value, sizeof(value)));
}
BOOL PSocket::SetOption(int option, const void * valuePtr, PINDEX valueSize)
{
return ConvertOSError(::setsockopt(os_handle,
SOL_SOCKET, option, (char *)valuePtr, valueSize));
}
BOOL PSocket::GetOption(int option, int & value)
{
#ifdef __BEOS__
return FALSE;
#else
socklen_t valSize = sizeof(value);
return ConvertOSError(::getsockopt(os_handle,
SOL_SOCKET, option, (char *)&value, (int *)(unsigned int *)&valSize)); // casted by Jurjan
#endif
}
BOOL PSocket::GetOption(int option, void * valuePtr, PINDEX valueSize)
{
#ifdef __BEOS__
return FALSE;
#else
return ConvertOSError(::getsockopt(os_handle,
SOL_SOCKET, option, (char *)valuePtr, (int *)(unsigned int *)(socklen_t *)&valueSize)); // casted by Jurjan
#endif
}
BOOL PSocket::Shutdown(ShutdownValue value)
{
return ConvertOSError(::shutdown(os_handle, value));
}
WORD PSocket::GetProtocolByName(const PString & name)
{
#if !defined(__BEOS__) && !defined(P_VXWORKS) // added by Jurjan todo
struct protoent * ent = getprotobyname(name);
if (ent != NULL)
return ent->p_proto;
#endif
PAssertAlways(PUnimplementedFunction);
return 0;
}
PString PSocket::GetNameByProtocol(WORD proto)
{
#if !defined(__BEOS__) && !defined(P_VXWORKS) // added by Jurjan todo
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)
{
PINDEX space = service.FindOneOf(" \t\r\n");
#ifndef P_VXWORKS // added by Jurjan.. todo.. getservbyname not implemented in VxWorks
struct servent * serv = ::getservbyname(service(0, space-1), protocol);
if (serv != NULL)
return ntohs(serv->s_port);
// add here
#endif // !VXWORKS
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;
}
PString PSocket::GetServiceByPort(WORD port) const
{
return GetServiceByPort(GetProtocolName(), port);
}
PString PSocket::GetServiceByPort(const char * protocol, WORD port)
{
#if !defined(__BEOS__) && !defined(P_VXWORKS) // added by Jurjan todo
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)
{
if (!sock1.IsOpen() || !sock2.IsOpen())
return NotOpen;
int h1 = sock1.GetHandle();
int h2 = sock2.GetHandle();
#ifdef _MSC_VER
#pragma warning(disable:4127)
#endif
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(h1, &readfds);
FD_SET(h2, &readfds);
fd_set writefds;
FD_ZERO(&writefds);
fd_set exceptfds;
FD_ZERO(&exceptfds);
#ifdef _MSC_VER
#pragma warning(default:4127)
#endif
PIntArray allfds(4);
allfds[0] = h1;
allfds[1] = 1;
allfds[2] = h2;
allfds[3] = 1;
int rval = os_select(PMAX(h1, h2)+1,
readfds, writefds, exceptfds, allfds, timeout);
Errors lastError;
int osError;
if (!ConvertOSError(rval, lastError, osError))
return lastError;
rval = 0;
if (FD_ISSET(h1, &readfds))
rval -= 1;
if (FD_ISSET(h2, &readfds))
rval -= 2;
return rval;
}
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);
}
PChannel::Errors PSocket::Select(SelectList & read,
SelectList & write,
SelectList & except,
const PTimeInterval & timeout)
{
int maxfds = 0;
PINDEX nextfd = 0;
PIntArray allfds(2*(read.GetSize()+write.GetSize()+except.GetSize()));
#ifdef _MSC_VER
#pragma warning(disable:4127)
#endif
fd_set readfds;
FD_ZERO(&readfds);
PINDEX i;
for (i = 0; i < read.GetSize(); i++) {
if (!read[i].IsOpen())
return NotOpen;
int h = read[i].GetHandle();
FD_SET(h, &readfds);
if (h > maxfds)
maxfds = h;
allfds[nextfd++] = h;
allfds[nextfd++] = 1;
}
fd_set writefds;
FD_ZERO(&writefds);
for (i = 0; i < write.GetSize(); i++) {
if (!write[i].IsOpen())
return NotOpen;
int h = write[i].GetHandle();
FD_SET(h, &writefds);
if (h > maxfds)
maxfds = h;
allfds[nextfd++] = h;
allfds[nextfd++] = 2;
}
fd_set exceptfds;
FD_ZERO(&exceptfds);
for (i = 0; i < except.GetSize(); i++) {
if (!except[i].IsOpen())
return NotOpen;
int h = except[i].GetHandle();
FD_SET(h, &exceptfds);
if (h > maxfds)
maxfds = h;
allfds[nextfd++] = h;
allfds[nextfd++] = 4;
}
#ifdef _MSC_VER
#pragma warning(default:4127)
#endif
int retval = os_select(maxfds+1,readfds,writefds,exceptfds,allfds,timeout);
Errors lastError;
int osError;
if (!ConvertOSError(retval, lastError, osError))
return lastError;
if (retval > 0) {
for (i = 0; i < read.GetSize(); i++) {
int h = read[i].GetHandle();
if (h < 0)
return Interrupted;
if (!FD_ISSET(h, &readfds))
read.RemoveAt(i--);
}
for (i = 0; i < write.GetSize(); i++) {
int h = write[i].GetHandle();
if (h < 0)
return Interrupted;
if (!FD_ISSET(h, &writefds))
write.RemoveAt(i--);
}
for (i = 0; i < except.GetSize(); i++) {
int h = except[i].GetHandle();
if (h < 0)
return Interrupted;
if (!FD_ISSET(h, &exceptfds))
except.RemoveAt(i--);
}
}
else {
read.RemoveAll();
write.RemoveAll();
except.RemoveAll();
}
return NoError;
}
//////////////////////////////////////////////////////////////////////////////
// PIPSocket
PIPSocket::PIPSocket()
{
}
void PIPSocket::ClearNameCache()
{
pHostByName.mutex.Wait();
pHostByAddr.mutex.Wait();
pHostByName.RemoveAll();
pHostByAddr.RemoveAll();
#if defined(_WIN32) || defined(WINDOWS) // 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
{
PString name;
sockaddr_in address;
socklen_t size = sizeof(address);
if (getpeername(os_handle, (struct sockaddr *)&address, (int *)(unsigned int *)&size) == 0)
name = GetHostName(address.sin_addr) + psprintf(":%u", ntohs(address.sin_port));
return name;
}
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;
PString hostname;
if (pHostByAddr.GetHostName(addr, hostname)) {
return hostname;
}
return addr;
}
BOOL PIPSocket::GetHostAddress(Address & addr)
{
return pHostByName.GetHostAddress(GetHostName(), addr);
}
BOOL PIPSocket::GetHostAddress(const PString & hostname, Address & addr)
{
if (hostname.IsEmpty())
return FALSE;
// lookup the host address using inet_addr, assuming it is a "." address
addr = hostname;
if (addr != 0)
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)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -