📄 sockets.cxx
字号:
*
* 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 + -