📄 sockets.cxx
字号:
* 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 18extern "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_WCEvoid CALLBACK CompletionRoutine(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags); #endif // _WIN32_WCE#endif // _WIN32#endif // P_HAS_QOS///////////////////////////////////////////////////////////////////////////////// PIPSocket::Addressstatic int defaultIpAddressFamily=PF_INET; //PF_INET for IPv4 (default) or PF_INET6 for IPv6static 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_IPV6static 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"); #endifint PIPSocket::GetDefaultIpAddressFamily(){ return defaultIpAddressFamily;}void PIPSocket::SetDefaultIpAddressFamily(int ipAdressFamily){ defaultIpAddressFamily = ipAdressFamily;}void PIPSocket::SetDefaultIpAddressFamilyV4(){ SetDefaultIpAddressFamily(PF_INET);}#if P_HAS_IPV6void 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;}#endifPIPSocket::Address PIPSocket::GetDefaultIpAny(){#if P_HAS_IPV6 if (defaultIpAddressFamily == PF_INET6) return any6;#endif return any4;}#if P_HAS_IPV6class 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#endifclass 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 CachingPIPCacheData::PIPCacheData(struct hostent * host_info, const char * original){ if (host_info == NULL) { address = 0; return; } hostname = host_info->h_name; if (host_info->h_addr != NULL)#ifndef _WIN32_WCE address = *(DWORD *)host_info->h_addr;#else address = PIPSocket::Address(host_info->h_length, (const BYTE *)host_info->h_addr);#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++) {#ifndef _WIN32_WCE PIPSocket::Address ip(*(DWORD *)host_info->h_addr_list[i]);#else PIPSocket::Address ip(host_info->h_length, (const BYTE *)host_info->h_addr_list[i]);#endif aliases.AppendString(ip.AsString()); } for (i = 0; i < aliases.GetSize(); i++) if (aliases[i] *= original) return; aliases.AppendString(original);}#if P_HAS_IPV6PIPCacheData::PIPCacheData(struct addrinfo * addr_info, const char * original){ PINDEX i; if (addr_info == NULL) { address = 0; return; } // Fill Host primary informations hostname = addr_info->ai_canonname; // Fully Qualified Domain Name (FQDN) if (addr_info->ai_addr != NULL) address = PIPSocket::Address(addr_info->ai_family, addr_info->ai_addrlen, addr_info->ai_addr); // Next entries while (addr_info != NULL) { AddEntry(addr_info); addr_info = addr_info->ai_next; } // Add original as alias or allready added ? for (i = 0; i < aliases.GetSize(); i++) { if (aliases[i] *= original) return; } aliases.AppendString(original);}void PIPCacheData::AddEntry(struct addrinfo * addr_info){ PINDEX i; if (addr_info == NULL) return; // Add canonical name BOOL add_it = TRUE; for (i = 0; i < aliases.GetSize(); i++) { if (addr_info->ai_canonname != NULL && (aliases[i] *= addr_info->ai_canonname)) { add_it = FALSE; break; } } if (add_it && addr_info->ai_canonname != NULL) aliases.AppendString(addr_info->ai_canonname); // Add IP address PIPSocket::Address ip(addr_info->ai_family, addr_info->ai_addrlen, addr_info->ai_addr); add_it = TRUE; for (i = 0; i < aliases.GetSize(); i++) { if (aliases[i] *= ip.AsString()) { add_it = FALSE; break; } } if (add_it) aliases.AppendString(ip.AsString());}#endifstatic PTimeInterval GetConfigTime(const char * /*key*/, DWORD dflt){ //PConfig cfg("DNS Cache"); //return cfg.GetInteger(key, dflt); return dflt;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -