📄 socket.cxx
字号:
/*
* socket.cxx
*
* Berkley sockets classes implementation
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: socket.cxx,v $
* Revision 1.115.2.2 2006/02/22 00:04:39 csoutheren
* Backport interface table fix from HEAD
*
* Revision 1.115.2.1 2006/02/18 16:01:19 dsandras
* Backport from HEAD.
*
* Revision 1.117 2006/02/21 13:57:31 csoutheren
* Second attempt at fixing problem with interfaces having multiple addresses
*
* Revision 1.116 2006/02/18 15:57:45 dsandras
* Applied patch from Richard van der Hoff and Stephane Epardaud <stef lunatech
* com> to fix infinite loop with IPv6 interfaces. Thanks!
*
* Revision 1.115 2005/11/30 12:47:42 csoutheren
* Removed tabs, reformatted some code, and changed tags for Doxygen
*
* Revision 1.114 2005/11/23 11:47:03 shorne
* Changed EnableQoS to EnableGQoS
*
* Revision 1.113 2005/07/15 12:45:13 rogerhardiman
* Fix bug 1237508 (M Zygmuntowicz). Make IPV6 code use #if instead of #ifdef.
*
* Revision 1.112 2005/07/13 11:48:55 csoutheren
* Backported QOS changes from isvo branch
*
* Revision 1.111 2005/02/07 12:12:31 csoutheren
* Expanded interface list routines to include IPV6 addresses
* Added IPV6 to GetLocalAddress
*
* Revision 1.110 2004/08/24 07:08:11 csoutheren
* Added use of recvmsg to determine which interface UDP packets arrive on
*
* Revision 1.109 2004/07/11 07:56:36 csoutheren
* Applied jumbo VxWorks patch, thanks to Eize Slange
*
* Revision 1.108 2004/07/08 00:57:29 csoutheren
* Added check for EINTR on connect
* Thanks to Alex Vishnev
*
* Revision 1.107 2004/07/03 23:50:42 csoutheren
* Removed warnings under Solaris
*
* Revision 1.106 2004/05/06 11:28:30 rjongbloed
* Changed P_fd_set to use malloc/free isntead of new/delete due to pedantry about [].
*
* Revision 1.105 2004/05/05 06:52:37 ykiryanov
* Made BeOS changes
*
* Revision 1.104 2004/04/27 04:37:51 rjongbloed
* Fixed ability to break of a PSocket::Select call under linux when a socket
* is closed by another thread.
*
* Revision 1.103 2004/04/24 06:28:12 rjongbloed
* Fixed GCC 3.4.0 warnings about PAssertNULL and improved recoverability on
* NULL pointer usage in various bits of code.
*
* Revision 1.102 2004/04/18 07:46:32 rjongbloed
* Fixed other unix builds after Yuri's BeOS changes.
*
* Revision 1.101 2004/04/18 00:21:35 ykiryanov
* Cleaned up BeOS related code. Less ifdefs, more functionality
*
* Revision 1.100 2003/10/27 04:06:14 csoutheren
* Added code to allow compilation of new QoS code on Unix
*
* Revision 1.99 2003/01/24 10:21:06 robertj
* Fixed issues in RTEMS support, thanks Vladimir Nesic
*
* Revision 1.98 2002/11/22 10:14:07 robertj
* QNX port, thanks Xiaodan Tang
*
* Revision 1.97 2002/11/02 00:32:21 robertj
* Further fixes to VxWorks (Tornado) port, thanks Andreas Sikkema.
*
* Revision 1.96 2002/10/22 10:25:07 rogerh
* Fix process_rtentry() following Thomas's patch.
*
* Revision 1.95 2002/10/22 07:42:52 robertj
* Added extra debugging for file handle and thread leak detection.
*
* Revision 1.94 2002/10/22 06:53:38 craigs
* Fixed signed/unsigned problem in GetRoutTable thanks to Thomas Jalsovsky
*
* Revision 1.93 2002/10/19 06:12:20 robertj
* Moved P_fd_set::Zero() from platform independent to platform dependent
* code as Win32 implementation is completely different from Unix.
*
* Revision 1.92 2002/10/17 13:44:27 robertj
* Port to RTEMS, thanks Vladimir Nesic.
*
* Revision 1.91 2002/10/17 12:57:24 robertj
* Added ability to increase maximum file handles on a process.
*
* Revision 1.90 2002/10/10 04:43:44 robertj
* VxWorks port, thanks Martijn Roest
*
* Revision 1.89 2002/10/08 14:31:43 robertj
* Changed for IPv6 support, thanks S閎astien Josset.
*
* Revision 1.88 2002/06/05 12:29:16 craigs
* Changes for gcc 3.1
*
* Revision 1.87 2002/04/18 06:16:06 robertj
* Fixed Net BSD problem with RTF_CLONED flag, thanks Motoyuki OHMORI
* Fixed operator precedence problem with bit mask tests in RTF_CLONE code.
*
* Revision 1.86 2002/04/12 07:57:41 robertj
* Fixed bug introduced into Accept() by previous change.
*
* Revision 1.85 2002/04/12 01:42:41 robertj
* Changed return value on os_connect() and os_accept() to make sure
* get the correct error codes propagated up under unix.
*
* Revision 1.84 2002/02/13 02:19:47 robertj
* Fixed mistake in previous patch, is if not ifdef!
*
* Revision 1.83 2002/02/13 00:50:32 robertj
* Fixed use of symbol in older versionsof Solaris, thanks Markus Storm
*
* Revision 1.82 2002/01/31 22:52:18 robertj
* Added fix for buffer too small in Solaris GetRouteTable(), thanks Markus Storm.
*
* Revision 1.81 2001/12/17 23:33:50 robertj
* Solaris 8 porting changes, thanks James Dugal
*
* Revision 1.80 2001/12/10 07:07:27 rogerh
* Take out some #includes which were already in pachdep.h. Fixes openBSD 2.9
*
* Revision 1.79 2001/11/22 12:29:57 rogerh
* Take out the cloned flag on OpenBSD so it compiles
*
* Revision 1.78 2001/11/14 10:37:32 rogerh
* Define _SIZEOF_ADDR_IFREQ as OpenBSD does not have it
*
* Revision 1.77 2001/10/28 23:00:10 robertj
* Fixed Solaris and IRIX compatibility issue, thanks Andre Schulze
*
* Revision 1.76 2001/10/11 02:20:54 robertj
* Added IRIX support (no audio/video), thanks Andre Schulze.
*
* Revision 1.75 2001/10/03 19:31:56 rogerh
* Add MAC OS X support to GetInterfaceTable
*
* Revision 1.74 2001/10/03 10:18:15 rogerh
* Make Mac OS X (Darwin) use the new GetRouteTable() function.
*
* Revision 1.73 2001/09/24 15:37:35 rogerh
* Add GetRouteTable() for BSD Unix. Based on FreeBSD's own networking code,
* and from an implementation by Martin Nilsson <martin@gneto.com>
*
* Revision 1.72 2001/09/19 00:41:20 robertj
* Fixed GetInterfaceTable so does not add duplicate interfaces into list.
* Changed the loop condition to allow for BSD variable length records.
*
* Revision 1.71 2001/09/18 05:56:03 robertj
* Fixed numerous problems with thread suspend/resume and signals handling.
*
* Revision 1.70 2001/09/10 03:03:36 robertj
* Major change to fix problem with error codes being corrupted in a
* PChannel when have simultaneous reads and writes in threads.
*
* Revision 1.69 2001/08/16 11:58:22 rogerh
* Add more Mac OS X changes from John Woods <jfw@jfwhome.funhouse.com>
*
* Revision 1.68 2001/08/12 07:12:40 rogerh
* More Mac OS Carbon changes from John Woods <jfw@jfwhome.funhouse.com>
*
* Revision 1.67 2001/08/12 06:34:33 rogerh
* Add Mac OS Carbon changes from John Woods <jfw@jfwhome.funhouse.com>
*
* Revision 1.66 2001/08/07 02:27:22 robertj
* Fixed some incorrect error values returned in Read() and Write() functions.
*
* Revision 1.65 2001/07/03 04:41:25 yurik
* Corrections to Jac's submission from 6/28
*
* Revision 1.64 2001/06/30 06:59:07 yurik
* Jac Goudsmit from Be submit these changes 6/28. Implemented by Yuri Kiryanov
*
* Revision 1.63 2001/06/19 12:09:13 rogerh
* Mac OS X change
*
* Revision 1.62 2001/04/16 22:46:22 craigs
* Fixed problem with os_connect not correctly reporting errors
*
* Revision 1.61 2001/03/26 03:31:53 robertj
* Fixed Solaris compile error.
*
* Revision 1.60 2001/03/20 06:44:25 robertj
* Lots of changes to fix the problems with terminating threads that are I/O
* blocked, especially when doing orderly shutdown of service via SIGTERM.
*
* Revision 1.59 2001/03/07 23:37:59 robertj
* Fixed slow down in UDP packet send, thanks Dmitriy Reka
*
* Revision 1.58 2001/03/07 06:56:36 yurik
* Made adjustment for BONE platforms as requested by Jac Goudsmit
*
* Revision 1.57 2001/03/06 00:16:59 robertj
* Fixed BSD compatibility problem.
*
* Revision 1.56 2001/03/05 04:28:56 robertj
* Added net mask to interface info returned by GetInterfaceTable()
*
* Revision 1.55 2001/02/02 23:31:30 robertj
* Fixed enumeration of interfaces, thanks Bertrand Croq.
*
* Revision 1.54 2001/01/17 03:48:25 rogerh
* Fix GetInterfaceTable so it actually works through all interfaces rather
* than falling over after the first entry.
*
* Revision 1.53 2001/01/16 12:56:01 rogerh
* On BeOS sa_data is 'unsigned char *'. Linux and BSD defines sa_data as 'char *'
* Add typecast, submitted by Jac Goudsmit <jac_goudsmit@yahoo.com>
*
* Revision 1.52 2000/06/21 01:01:22 robertj
* AIX port, thanks Wolfgang Platzer (wolfgang.platzer@infonova.at).
*
* Revision 1.51 2000/04/19 00:13:53 robertj
* BeOS port changes.
*
* Revision 1.50 2000/04/07 05:43:48 rogerh
* Fix a compilation error in a non-pthreaded function. Found by Kevin Packard
*
* Revision 1.49 2000/03/17 03:45:40 craigs
* Fixed problem with connect call hanging
*
* Revision 1.48 2000/02/17 23:47:40 robertj
* Fixed error in check for SIOCGHWADDR define, thanks Markus Storm.
*
* Revision 1.47 2000/01/20 08:20:57 robertj
* FreeBSD v3 compatibility changes, thanks Roger Hardiman & Motonori Shindo
*
* Revision 1.46 1999/11/18 13:45:21 craigs
* Removed obsolete declaration of iostream semaphore
*
* Revision 1.45 1999/10/30 13:43:01 craigs
* Added correct method of aborting socket operations asynchronously
*
* Revision 1.44 1999/09/27 01:04:42 robertj
* BeOS support changes.
*
* Revision 1.43 1999/09/12 07:06:23 craigs
* Added support for getting Solaris interface info
*
* Revision 1.42 1999/09/10 02:31:19 craigs
* Added interface table routines
*
* Revision 1.41 1999/09/03 02:26:25 robertj
* Changes to aid in breaking I/O locks on thread termination. Still needs more work esp in BSD!
*
* Revision 1.40 1999/05/01 03:52:20 robertj
* Fixed various egcs warnings.
*
* Revision 1.39 1999/03/02 05:41:59 robertj
* More BeOS changes
*
* Revision 1.38 1999/02/26 04:10:39 robertj
* More BeOS port changes
*
* Revision 1.37 1999/02/22 13:26:54 robertj
* BeOS port changes.
*
* Revision 1.36 1998/11/30 21:51:58 robertj
* New directory structure.
*
* Revision 1.35 1998/11/24 09:39:22 robertj
* FreeBSD port.
*
* Revision 1.34 1998/11/22 08:11:37 craigs
* *** empty log message ***
*
* Revision 1.33 1998/11/14 10:37:38 robertj
* Changed semantics of os_sendto to return TRUE if ANY bytes are sent.
*
* Revision 1.32 1998/10/16 01:16:55 craigs
* Added Yield to help with cooperative multithreading.
*
* Revision 1.31 1998/10/11 02:23:16 craigs
* Fixed problem with socket writes not correctly detecting EOF
*
* Revision 1.30 1998/09/24 08:21:11 robertj
* Fixed warning on GNU 6 library.
*
* Revision 1.29 1998/09/24 07:55:51 robertj
* Fixed warning on solaris build.
*
* Revision 1.28 1998/09/24 04:13:49 robertj
* Added open software license.
*
* Revision 1.27 1998/09/18 05:46:00 robertj
* Fixed incorrectly returning success on a connect() error other than a timeout.
*
* Revision 1.26 1998/09/08 11:31:51 robertj
* Fixed ippp bug on very full packets.
*
* Revision 1.25 1998/09/08 09:54:31 robertj
* Fixed ppp and ippp compatibility.
*
* Revision 1.24 1998/09/08 05:15:14 robertj
* Fixed problem in Windows requiring snmpapi.dll for PEthSocket class.
*
* Revision 1.23 1998/08/27 01:13:20 robertj
* Changes to resolve signedness in GNU C library v6
* Remove Linux EthSocket stuff from Sun build, still needs implementing.
*
* Revision 1.22 1998/08/21 05:30:59 robertj
* Ethernet socket implementation.
*
*/
#pragma implementation "sockets.h"
#pragma implementation "socket.h"
#pragma implementation "ipsock.h"
#pragma implementation "udpsock.h"
#pragma implementation "tcpsock.h"
#pragma implementation "ipdsock.h"
#pragma implementation "ethsock.h"
#pragma implementation "qos.h"
#include <ptlib.h>
#include <ptlib/sockets.h>
#if defined(SIOCGENADDR)
#define SIO_Get_MAC_Address SIOCGENADDR
#define ifr_macaddr ifr_ifru.ifru_enaddr
#elif defined(SIOCGIFHWADDR)
#define SIO_Get_MAC_Address SIOCGIFHWADDR
#define ifr_macaddr ifr_hwaddr.sa_data
#endif
#if defined(P_FREEBSD) || defined(P_OPENBSD) || defined(P_NETBSD) || defined(P_SOLARIS) || defined(P_MACOSX) || defined(P_MACOS) || defined(P_IRIX) || defined(P_VXWORKS) || defined(P_RTEMS) || defined(P_QNX)
#define ifr_netmask ifr_addr
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#if !defined(P_QNX)
#include <netinet/if_ether.h>
#endif
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#endif
#if defined(P_FREEBSD) || defined(P_OPENBSD) || defined(P_NETBSD) || defined(P_MACOSX) || defined(P_MACOS) || defined(P_QNX)
#include <sys/sysctl.h>
#endif
#ifdef P_RTEMS
#include <bsp.h>
#endif
#ifdef __BEOS__
#include <posix/sys/ioctl.h> // for FIONBIO
#include <be/bone/net/if.h> // for ifconf
#include <be/bone/sys/sockio.h> // for SIOCGI*
#endif
int PX_NewHandle(const char *, int);
#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
//////////////////////////////////////////////////////////////////////////////
// P_fd_set
void P_fd_set::Construct()
{
max_fd = PProcess::Current().GetMaxHandles();
set = (fd_set *)malloc((max_fd+7)>>3);
}
void P_fd_set::Zero()
{
if (PAssertNULL(set) != NULL)
memset(set, 0, (max_fd+7)>>3);
}
//////////////////////////////////////////////////////////////////////////////
PSocket::~PSocket()
{
os_close();
}
int PSocket::os_close()
{
if (os_handle < 0)
return -1;
// send a shutdown to the other end
::shutdown(os_handle, 2);
return PXClose();
}
static int SetNonBlocking(int fd)
{
if (fd < 0)
return -1;
// Set non-blocking so we can use select calls to break I/O block on close
int cmd = 1;
#if defined(P_VXWORKS)
if (::ioctl(fd, FIONBIO, &cmd) == 0)
#else
if (::ioctl(fd, FIONBIO, &cmd) == 0 && ::fcntl(fd, F_SETFD, 1) == 0)
#endif
return fd;
::close(fd);
return -1;
}
int PSocket::os_socket(int af, int type, int protocol)
{
// attempt to create a socket
return SetNonBlocking(PX_NewHandle(GetClass(), ::socket(af, type, protocol)));
}
BOOL PSocket::os_connect(struct sockaddr * addr, PINDEX size)
{
int val;
do {
val = ::connect(os_handle, addr, size);
} while (val != 0 && errno == EINTR);
if (val == 0 || errno != EINPROGRESS)
return ConvertOSError(val);
if (!PXSetIOBlock(PXConnectBlock, readTimeout))
return FALSE;
// A successful select() call does not necessarily mean the socket connected OK.
int optval = -1;
socklen_t optlen = sizeof(optval);
getsockopt(os_handle, SOL_SOCKET, SO_ERROR, (char *)&optval, &optlen);
if (optval != 0) {
errno = optval;
return ConvertOSError(-1);
}
return TRUE;
}
BOOL PSocket::os_accept(PSocket & listener, struct sockaddr * addr, PINDEX * size)
{
if (!listener.PXSetIOBlock(PXAcceptBlock, listener.GetReadTimeout()))
return SetErrorValues(listener.GetErrorCode(), listener.GetErrorNumber());
#if defined(E_PROTO)
for (;;) {
int new_fd = ::accept(listener.GetHandle(), addr, (socklen_t *)size);
if (new_fd >= 0)
return ConvertOSError(os_handle = SetNonBlocking(new_fd));
if (errno != EPROTO)
return ConvertOSError(-1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -