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

📄 sockets.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 5 页
字号:
 *
 * Revision 1.66  1998/01/26 00:49:28  robertj
 * Fixed bug in detecting local host on NT, 95 bug kludge was interfering with it.
 *
 * Revision 1.65  1998/01/06 12:43:23  craigs
 * Added definition of REENTRANT_BUFFER_LEN
 *
 * Revision 1.64  1998/01/04 07:25:09  robertj
 * Added pthreads compatible calls for gethostbyx functions.
 *
 * Revision 1.63  1997/12/18 05:06:13  robertj
 * Moved IsLocalHost() to platform dependent code.
 *
 * Revision 1.62  1997/12/11 10:30:35  robertj
 * Added operators for IP address to DWORD conversions.
 *
 * Revision 1.61  1997/10/03 13:33:22  robertj
 * Added workaround for NT winsock bug with RAS and DNS lookups.
 *
 * Revision 1.60  1997/09/27 00:58:39  robertj
 * Fixed race condition on socket close in Select() function.
 *
 * Revision 1.59  1997/06/06 10:56:36  craigs
 * Added new functions for connectionless UDP writes
 *
 * Revision 1.58  1997/01/04 07:42:18  robertj
 * Fixed GCC Warnings.
 *
 * Revision 1.57  1997/01/04 06:54:38  robertj
 * Added missing canonical name to alias list.
 *
 * Revision 1.56  1996/12/17 11:07:05  robertj
 * Added clear of name cache.
 *
 * Revision 1.55  1996/12/12 09:23:27  robertj
 * Fixed name cache to cache missing names as well.
 * Fixed new connect with specific local port so can be re-used (simultaneous FTP session bug)
 *
 * Revision 1.54  1996/12/05 11:46:39  craigs
 * Fixed problem with Win95 recvfrom not having timeouts
 *
 * Revision 1.53  1996/11/30 12:08:17  robertj
 * Added Connect() variant so can set the local port number on link.
 *
 * Revision 1.52  1996/11/16 10:49:03  robertj
 * Fixed missing const in PIPSocket::Address stream output operator..
 *
 * Revision 1.51  1996/11/16 01:43:49  craigs
 * Fixed problem with ambiguous DNS cache keys
 *
 * Revision 1.50  1996/11/10 21:08:31  robertj
 * Added host name caching.
 *
 * Revision 1.49  1996/11/04 03:40:22  robertj
 * Moved address printer from inline to source.
 *
 * Revision 1.48  1996/10/26 01:41:09  robertj
 * Compensated for Win'95 gethostbyaddr bug.
 *
 * Revision 1.47  1996/09/14 13:09:40  robertj
 * Major upgrade:
 *   rearranged sockets to help support IPX.
 *   added indirect channel class and moved all protocols to descend from it,
 *   separating the protocol from the low level byte transport.
 *
 * Revision 1.46  1996/08/25 09:33:32  robertj
 * Added function to detect "local" host name.
 *
 * Revision 1.45  1996/07/30 12:24:53  robertj
 * Fixed incorrect conditional stopping Select() from working.
 *
 * Revision 1.44  1996/07/27 04:10:35  robertj
 * Changed Select() calls to return error codes.
 *
 * Revision 1.43  1996/06/10 09:58:21  robertj
 * Fixed win95 compatibility with looking up zero address (got a response and shouldn't).
 *
 * Revision 1.42  1996/05/26 03:47:03  robertj
 * Compatibility to GNU 2.7.x
 *
 * Revision 1.39  1996/04/29 12:20:01  robertj
 * Fixed GetHostAliases() so doesn't overwrite names with IP numbers.
 *
 * Revision 1.38  1996/04/15 10:59:41  robertj
 * Opened socket on UDP sockets so ReadFrom/WriteTo work when no Connect/Listen.
 *
 * Revision 1.37  1996/03/31 09:06:41  robertj
 * Added socket shutdown function.
 *
 * Revision 1.35  1996/03/18 13:33:18  robertj
 * Fixed incompatibilities to GNU compiler where PINDEX != int.
 *
 * Revision 1.34  1996/03/17 05:51:18  robertj
 * Fixed strange bug in accept cant have NULL address.
 *
 * Revision 1.33  1996/03/16 04:52:20  robertj
 * Changed all the get host name and get host address functions to be more consistent.
 *
 * Revision 1.32  1996/03/04 12:21:00  robertj
 * Split file into telnet.cxx
 *
 * Revision 1.31  1996/03/03 07:38:45  robertj
 * Added Reusability clause to the Listen() function on sockets.
 *
 * Revision 1.30  1996/03/02 03:25:13  robertj
 * Added Capability to get and set Berkeley socket options.
 *
 * Revision 1.29  1996/02/25 11:30:08  robertj
 * Changed Listen so can do a listen on a socket that is connected.
 *
 * Revision 1.28  1996/02/25 03:10:55  robertj
 * Moved some socket functions to platform dependent code.
 *
 * Revision 1.27  1996/02/19 13:30:15  robertj
 * Fixed bug in getting port by service name when specifying service by string number.
 * Added SO_LINGER option to socket to stop data loss on close.
 *
 * Revision 1.26  1996/02/15 14:46:44  robertj
 * Added Select() function to PSocket.
 *
 * Revision 1.25  1996/02/13 13:08:09  robertj
 * Fixed usage of sock_addr structure, not being cleared correctly.
 *
 * Revision 1.24  1996/02/08 12:27:22  robertj
 * Added function to get peer port as well as IP number..
 *
 * Revision 1.23  1996/02/03 11:07:37  robertj
 * Fixed buf in assuring error when converting string to IP number and string is empty.
 *
 * Revision 1.22  1996/01/28 14:08:13  robertj
 * Changed service parameter to PString for ease of use in GetPortByService function
 * Fixed up comments.
 * Added default value in string for service name.
 *
 * Revision 1.21  1996/01/23 13:19:13  robertj
 * Moved Accept() function to platform dependent code.
 *
 * Revision 1.20  1995/12/23 03:42:53  robertj
 * Unix portability issues.
 *
 * Revision 1.19  1995/12/10 11:42:23  robertj
 * Numerous fixes for sockets.
 *
 * Revision 1.18  1995/10/14 15:11:31  robertj
 * Added internet address to string conversion functionality.
 *
 * Revision 1.17  1995/07/02 01:21:23  robertj
 * Added static functions to get the current host name/address.
 *
 * Revision 1.16  1995/06/17 00:47:01  robertj
 * Changed overloaded Open() calls to 3 separate function names.
 * More logical design of port numbers and service names.
 *
 * Revision 1.15  1995/06/04 12:45:33  robertj
 * Added application layer protocol sockets.
 * Slight redesign of port numbers on sockets.
 *
 * Revision 1.14  1995/04/25 11:12:44  robertj
 * Fixed functions hiding ancestor virtuals.
 *
 * Revision 1.13  1995/04/01 08:31:54  robertj
 * Finally got a working TELNET.
 *
 * Revision 1.12  1995/03/18 06:27:49  robertj
 * Rewrite of telnet socket protocol according to RFC1143.
 *
 * Revision 1.11  1995/03/12  04:46:29  robertj
 * Added more functionality.
 *
 * Revision 1.10  1995/02/21  11:25:29  robertj
 * Further implementation of telnet socket, feature complete now.
 *
 * Revision 1.9  1995/01/27  11:16:16  robertj
 * Fixed missing cast in function, required by some platforms.
 *
 * Revision 1.8  1995/01/15  04:55:47  robertj
 * Moved all Berkley socket functions inside #ifdef.
 *
 * Revision 1.7  1995/01/04  10:57:08  robertj
 * Changed for HPUX and GNU2.6.x
 *
 * Revision 1.6  1995/01/03  09:37:52  robertj
 * Added constructor to open TCP socket.
 *
 * Revision 1.5  1995/01/02  12:28:25  robertj
 * Documentation.
 * Added more socket functions.
 *
 * Revision 1.4  1995/01/01  01:06:58  robertj
 * More implementation.
 *
 * Revision 1.3  1994/11/28  12:38:49  robertj
 * Added DONT and WONT states.
 *
 * Revision 1.2  1994/08/21  23:43:02  robertj
 * Some implementation.
 *
 * Revision 1.1  1994/08/01  03:39:05  robertj
 * Initial revision
 *
 */

#ifdef __NUCLEUS_PLUS__
#include <ConfigurationClass.h>
#endif


#include <ptlib.h>

#include <ptlib/sockets.h>

#include <ctype.h>

#ifdef P_VXWORKS
// VxWorks variant of inet_ntoa() allocates INET_ADDR_LEN bytes via malloc
// BUT DOES NOT FREE IT !!!  Use inet_ntoa_b() instead.
#define INET_ADDR_LEN      18
extern "C" void inet_ntoa_b(struct in_addr inetAddress, char *pString);
#endif // P_VXWORKS

#if P_HAS_QOS

#ifdef _WIN32
#include <winbase.h>
#include <winreg.h>

#ifndef _WIN32_WCE

void CALLBACK CompletionRoutine(DWORD dwError,
                                DWORD cbTransferred,
                                LPWSAOVERLAPPED lpOverlapped,
                                DWORD dwFlags);
                                

#endif  // _WIN32_WCE
#endif  // _WIN32
#endif // P_HAS_QOS

///////////////////////////////////////////////////////////////////////////////
// PIPSocket::Address

static int defaultIpAddressFamily = PF_INET;  // PF_UNSPEC;   // default to IPV4

static PIPSocket::Address loopback4(127,0,0,1);
static PIPSocket::Address broadcast4(INADDR_BROADCAST);
static PIPSocket::Address any4(INADDR_ANY);
static in_addr inaddr_empty;
#if P_HAS_IPV6
static PIPSocket::Address loopback6(16,(const BYTE *)"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\001");
static PIPSocket::Address any6(16,(const BYTE *)"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); 
#endif


int PIPSocket::GetDefaultIpAddressFamily()
{
  return defaultIpAddressFamily;
}


void PIPSocket::SetDefaultIpAddressFamily(int ipAdressFamily)
{
  defaultIpAddressFamily = ipAdressFamily;
}


void PIPSocket::SetDefaultIpAddressFamilyV4()
{
  SetDefaultIpAddressFamily(PF_INET);
}


#if P_HAS_IPV6

void PIPSocket::SetDefaultIpAddressFamilyV6()
{
  SetDefaultIpAddressFamily(PF_INET6);
}


BOOL PIPSocket::IsIpAddressFamilyV6Supported()
{
  int s = ::socket(PF_INET6, SOCK_DGRAM, 0);
  if (s < 0)
    return FALSE;

  _close(s);
  return TRUE;
}

#endif


PIPSocket::Address PIPSocket::GetDefaultIpAny()
{
#if P_HAS_IPV6
  if (defaultIpAddressFamily != PF_INET)
    return any6;
#endif

  return any4;
}


#if P_HAS_IPV6

class Psockaddr
{
  public:
    Psockaddr() { memset(&storage, 0, sizeof(storage)); }
    Psockaddr(const PIPSocket::Address & ip, WORD port);
    sockaddr* operator->() const { return (sockaddr *)&storage; }
    operator sockaddr*()   const { return (sockaddr *)&storage; }
    socklen_t GetSize() const;
    PIPSocket::Address GetIP() const;
    WORD GetPort() const;
  private:
    sockaddr_storage storage;
};


Psockaddr::Psockaddr(const PIPSocket::Address & ip, WORD port)
{
  memset(&storage, 0, sizeof(storage));

  if (ip.GetVersion() == 6) {
    sockaddr_in6 * addr6 = (sockaddr_in6 *)&storage;
    addr6->sin6_family = AF_INET6;
    addr6->sin6_addr = ip;
    addr6->sin6_port = htons(port);
    addr6->sin6_flowinfo = 0;
    addr6->sin6_scope_id = 0; // Should be set to the right interface....
  }
  else {
    sockaddr_in * addr4 = (sockaddr_in *)&storage;
    addr4->sin_family = AF_INET;
    addr4->sin_addr = ip;
    addr4->sin_port = htons(port);
  }
}


socklen_t Psockaddr::GetSize() const
{
  switch (((sockaddr *)&storage)->sa_family) {
    case AF_INET :
      return sizeof(sockaddr_in);
    case AF_INET6 :
      // RFC 2133 (Old IPv6 spec) size is 24
      // RFC 2553 (New IPv6 spec) size is 28
      return sizeof(sockaddr_in6);
    default :
      return sizeof(storage);
  }
}


PIPSocket::Address Psockaddr::GetIP() const
{
  switch (((sockaddr *)&storage)->sa_family) {
    case AF_INET :
      return ((sockaddr_in *)&storage)->sin_addr;
    case AF_INET6 :
      return ((sockaddr_in6 *)&storage)->sin6_addr;
    default :
      return 0;
  }
}


WORD Psockaddr::GetPort() const
{
  switch (((sockaddr *)&storage)->sa_family) {
    case AF_INET :
      return ntohs(((sockaddr_in *)&storage)->sin_port);
    case AF_INET6 :
      return ntohs(((sockaddr_in6 *)&storage)->sin6_port);
    default :
      return 0;
  }
}

#endif


#if (defined(_WIN32) || defined(WINDOWS)) && !defined(__NUCLEUS_MNT__)
static PWinSock dummyForWinSock; // Assure winsock is initialised
#endif

#if (defined(P_PTHREADS) && !defined(P_THREAD_SAFE_CLIB)) || defined(__NUCLEUS_PLUS__)
#define REENTRANT_BUFFER_LEN 1024
#endif


class PIPCacheData : public PObject
{
  PCLASSINFO(PIPCacheData, PObject)
  public:
    PIPCacheData(struct hostent * ent, const char * original);
#if P_HAS_IPV6
    PIPCacheData(struct addrinfo  * addr_info, const char * original);
    void AddEntry(struct addrinfo  * addr_info);
#endif
    const PString & GetHostName() const { return hostname; }
    const PIPSocket::Address & GetHostAddress() const { return address; }
    const PStringList & GetHostAliases() const { return aliases; }
    BOOL HasAged() const;
  private:
    PString            hostname;
    PIPSocket::Address address;
    PStringList        aliases;
    PTime              birthDate;
};



PDICTIONARY(PHostByName_private, PCaselessString, PIPCacheData);

class PHostByName : PHostByName_private
{
  public:
    BOOL GetHostName(const PString & name, PString & hostname);
    BOOL GetHostAddress(const PString & name, PIPSocket::Address & address);
    BOOL GetHostAliases(const PString & name, PStringArray & aliases);
  private:
    PIPCacheData * GetHost(const PString & name);
    PMutex mutex;
  friend void PIPSocket::ClearNameCache();
};


static PHostByName & pHostByName()
{
  static PHostByName t;
  return t;
}

class PIPCacheKey : public PObject
{
  PCLASSINFO(PIPCacheKey, PObject)
  public:
    PIPCacheKey(const PIPSocket::Address & a)
      { addr = a; }

    PObject * Clone() const
      { return new PIPCacheKey(*this); }

    PINDEX HashFunction() const
      { return (addr[1] + addr[2] + addr[3])%41; }

  private:
    PIPSocket::Address addr;
};

PDICTIONARY(PHostByAddr_private, PIPCacheKey, PIPCacheData);

class PHostByAddr : PHostByAddr_private
{
  public:
    BOOL GetHostName(const PIPSocket::Address & addr, PString & hostname);
    BOOL GetHostAddress(const PIPSocket::Address & addr, PIPSocket::Address & address);
    BOOL GetHostAliases(const PIPSocket::Address & addr, PStringArray & aliases);
  private:
    PIPCacheData * GetHost(const PIPSocket::Address & addr);
    PMutex mutex;
  friend void PIPSocket::ClearNameCache();
};

static PHostByAddr & pHostByAddr()
{
  static PHostByAddr t;
  return t;
}

#define new PNEW


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

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

⌨️ 快捷键说明

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