⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sockets.cxx

📁 windows mobile phone source code
💻 CXX
📖 第 1 页 / 共 4 页
字号:

//////////////////////////////////////////////////////////////////////////////
// IP Caching

PIPCacheData::PIPCacheData(struct hostent * host_info, const char * original)
{
  if (host_info == NULL) {
    address.s_addr = 0;
    return;
  }

  hostname = host_info->h_name;
#ifndef _WIN32_WCE
  address = *(DWORD *)host_info->h_addr;
#else
  if( host_info->h_addr )
	  address = PIPSocket::Address(
		  (BYTE) host_info->h_addr[0],
		  (BYTE) host_info->h_addr[1],
		  (BYTE) host_info->h_addr[2],
		  (BYTE) host_info->h_addr[3]);

#endif
  aliases.AppendString(host_info->h_name);

  PINDEX i;
  for (i = 0; host_info->h_aliases[i] != NULL; i++)
    aliases.AppendString(host_info->h_aliases[i]);

  for (i = 0; host_info->h_addr_list[i] != NULL; i++)
    aliases.AppendString(inet_ntoa(*(struct in_addr *)host_info->h_addr_list[i]));

  for (i = 0; i < aliases.GetSize(); i++)
    if (aliases[i] *= original)
      return;

  aliases.AppendString(original);
}


static PTimeInterval GetConfigTime(const char * key, DWORD dflt)
{
  PConfig cfg("DNS Cache");
  return cfg.GetInteger(key, dflt);
}

BOOL PIPCacheData::HasAged() const
{
  static PTimeInterval retirement = GetConfigTime("Age Limit", 300000); // 5 minutes
  PTime now;
  PTimeInterval age = now - birthDate;
  return age > retirement;
}


BOOL PHostByName::GetHostName(const PString & name, PString & hostname)
{
  PIPCacheData * host = GetHost(name);

  if (host != NULL) {
    hostname = host->GetHostName();
    hostname.MakeUnique();
  }

  mutex.Signal();

  return host != NULL;
}


BOOL PHostByName::GetHostAddress(const PString & name, PIPSocket::Address & address)
{
  PIPCacheData * host = GetHost(name);

  if (host != NULL)
    address = host->GetHostAddress();

  mutex.Signal();

  return host != NULL;
}


BOOL PHostByName::GetHostAliases(const PString & name, PStringArray & aliases)
{
  PIPCacheData * host = GetHost(name);

  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 * PHostByName::GetHost(const PString & name)
{
  mutex.Wait();

  PCaselessString key = name;
  PIPCacheData * host = GetAt(key);

  if (host != NULL && host->HasAged()) {
    SetAt(key, NULL);
    host = NULL;
  }

  if (host == NULL) {
    mutex.Signal();

#ifdef P_AIX
    struct hostent_data ht_data;
    memset(&ht_data, 0, sizeof(ht_data)); 
    struct hostent host_info;
#else
    struct hostent * host_info;
#endif

    int retry = 3;
    do {
#if ( ( defined(P_PTHREADS) && !defined(P_THREAD_SAFE_CLIB) ) || (defined(__NUCLEUS_PLUS__) ) )
      // 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!


#ifndef P_AIX	// that I get no warnings
      int localErrNo;
      char buffer[REENTRANT_BUFFER_LEN];
      struct hostent hostEnt;
#endif

#ifdef P_LINUX
      ::gethostbyname_r(name,
                        &hostEnt,
                        buffer, REENTRANT_BUFFER_LEN,
                        &host_info,
      		        &localErrNo);
      		      		        
      		        
#elif defined P_AIX
      ::gethostbyname_r(name,
                        &host_info,
                        &ht_data);		    
#else
      host_info = ::gethostbyname_r(name,
			 &hostEnt, buffer, REENTRANT_BUFFER_LEN,
			 &localErrNo);
#endif

#else
      host_info = ::gethostbyname(name);
#endif
    } while (h_errno == TRY_AGAIN && --retry > 0);

    mutex.Wait();

    if (retry == 0)
      return NULL;

#ifdef P_AIX
    host = new PIPCacheData (&host_info, (const char*) name);
#else
    host = new PIPCacheData(host_info, name);
#endif

    SetAt(key, host);
  }

  if (host->GetHostAddress() == 0)
    return NULL;

  return host;
}


BOOL PHostByAddr::GetHostName(const PIPSocket::Address & addr, PString & hostname)
{
  PIPCacheData * host = GetHost(addr);

  if (host != NULL) {
    hostname = host->GetHostName();
    hostname.MakeUnique();
  }

  mutex.Signal();
  return host != NULL;
}


BOOL PHostByAddr::GetHostAddress(const PIPSocket::Address & addr, PIPSocket::Address & address)
{
  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();

#ifdef P_AIX
    struct hostent_data ht_data;
    struct hostent host_info;
#else    
    struct hostent * host_info;
#endif

    int retry = 3;
    do {
#if ( ( defined(P_PTHREADS) && !defined(P_THREAD_SAFE_CLIB) ) || ( defined(__NUCLEUS_PLUS__) ) )
      // 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!
      
#ifndef P_AIX	// that I get no warnings
      int localErrNo;
      char buffer[REENTRANT_BUFFER_LEN];
      struct hostent hostEnt;
#endif

#ifdef P_LINUX
      ::gethostbyaddr_r((const char *)&addr, sizeof(addr),
                        PF_INET, 
                        &hostEnt,
                        buffer, REENTRANT_BUFFER_LEN,
                        &host_info,
                        &localErrNo);
#elif P_AIX
      ::gethostbyaddr_r((char *)&addr, sizeof(addr),
                        PF_INET, 
                        &host_info,
                        &ht_data );
#else
      host_info = ::gethostbyaddr_r((const char *)&addr, sizeof(addr), PF_INET, 
                                    &hostEnt, buffer, REENTRANT_BUFFER_LEN, &localErrNo);
#endif

#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
    } while (h_errno == TRY_AGAIN && --retry > 0);

    mutex.Wait();

    if (retry == 0)
      return FALSE;

#ifdef P_AIX
    host = new PIPCacheData(&host_info, inet_ntoa(addr));
#else
    host = new PIPCacheData(host_info, inet_ntoa(addr));
#endif

    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, 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)
{
#ifdef BE_BONELESS
  return FALSE;
#else
  socklen_t valSize = sizeof(value);
  return ConvertOSError(::getsockopt(os_handle, level, option,
                                     (char *)&value, &valSize));
#endif
}


BOOL PSocket::GetOption(int option, void * valuePtr, PINDEX valueSize, int level)
{
#ifdef BE_BONELESS
  return FALSE;
#else
  return ConvertOSError(::getsockopt(os_handle, level, option,
                                     (char *)valuePtr, (socklen_t *)&valueSize));
#endif
}


BOOL PSocket::Shutdown(ShutdownValue value)
{
  return ConvertOSError(::shutdown(os_handle, value));
}


WORD PSocket::GetProtocolByName(const PString & name)
{
#if !defined(BE_BONELESS) && !defined(__NUCLEUS_PLUS__) && !defined(_WIN32_WCE)
  struct protoent * ent = getprotobyname(name);
  if (ent != NULL)
    return ent->p_proto;
#endif

  return 0;
}


PString PSocket::GetNameByProtocol(WORD proto)
{
#if !defined(BE_BONELESS) && !defined(__NUCLEUS_PLUS__) && !defined(_WIN32_WCE)
  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 defined( __NUCLEUS_PLUS__ )
  if(!strcmp(protocol,"tcp") && service.AsInteger()>0) return service.AsInteger();
  PAssertAlways
  ("PSocket::GetPortByService: problem as no ::getservbyname in Nucleus NET");
  return 0;
#elif defined(_WIN32_WCE)
  if( service.AsInteger() > 0 ) 
    return (WORD) service.AsInteger();
 
  PAssertAlways("PSocket::GetPortByService: problem for WindowsCE as no port given.");
  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(BE_BONELESS) && !defined(__NUCLEUS_PLUS__) && !defined(_WIN32_WCE)
  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;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -