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

📄 socket.cxx

📁 基于VXWORKS H323通信技术源代码
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/*
 * 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.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"


#include <ptlib.h>
#include <ptlib/sockets.h>


#ifdef SIOCGENADDR
#define SIO_Get_MAC_Address SIOCGENADDR
#define	ifr_macaddr         ifr_ifru.ifru_enaddr
#else
#define SIO_Get_MAC_Address SIOCGIFHWADDR
#define	ifr_macaddr         ifr_hwaddr.sa_data
#endif

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);

#ifdef __BEOS__
#ifndef BE_THREADS
  // abort any I/O block using this os_handle
  PProcess::Current().PXAbortIOBlock(os_handle);
#endif

  int retval = ::closesocket(os_handle);
  os_handle = -1;
  return retval;
#else
  return PXClose();
#endif
}

int PSocket::os_socket(int af, int type, int protocol)
{
  // attempt to create a socket
  int handle;

  if ((handle = ::socket(af, type, protocol)) >= 0) {
		  return handle;
	}

	else 
			return -1;
}


int PSocket::os_connect(struct sockaddr * addr, PINDEX size)
{
 
	int val = ::connect(os_handle, addr, size);

  if (val == 0)
    return 0;

  if (errno != EINPROGRESS)
    return -1;

  // wait for the connect to occur, or not

  val = PThread::Current()->PXBlockOnIO(os_handle, PXConnectBlock, readTimeout);
  // check the response
  if (val < 0)
    return -1;

  if (val == 0) {
    errno = ECONNREFUSED;
    return -1;
  }

#ifndef __BEOS__
  // 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, (int *)(unsigned int *)&optlen);	// casted by Jurjan
  if (optval == 0)
    return 0;

  errno = optval;
#endif //!__BEOS__
  return -1;
}


int PSocket::os_accept(int sock, struct sockaddr * addr, PINDEX * size,
                       const PTimeInterval & timeout)
{

  if (!PXSetIOBlock(PXAcceptBlock, sock, timeout)) {
    errno = EINTR;
    return -1;
  }

#if defined(E_PROTO)
  while (1) {
    int new_fd = ::accept(sock, addr, (socklen_t *)size);
    if ((new_fd >= 0) || (errno != EPROTO))
      return new_fd;
    //PError << "accept on " << sock << " failed with EPROTO - retrying" << endl;
  }
#else
  return ::accept(sock, addr, (int *)(unsigned int *)(socklen_t *)size);	// casted by Jurjan
#endif
}

#ifndef P_PTHREADS		// VxWorks

int PSocket::os_select(int maxHandle,
                   fd_set & readBits,
                   fd_set & writeBits,
                   fd_set & exceptionBits,
          const PIntArray & osHandles,
      const PTimeInterval & timeout)
{
  struct timeval * tptr = NULL;

  int stat = PThread::Current()->PXBlockOnIO(maxHandle,
                                         readBits,
                                         writeBits,
                                         exceptionBits,
                                         timeout,
																				 osHandles);



  if (stat <= 0){
    return stat;
	}

  struct timeval tout = {0, 0};
  tptr = &tout;

  return ::select(maxHandle, &readBits, &writeBits, &exceptionBits, tptr);
}
                     
#else

int PSocket::os_select(int width,
                   fd_set & readBits,
                   fd_set & writeBits,
                   fd_set & exceptionBits,
          const PIntArray & ,
      const PTimeInterval & timeout)
{

  struct timeval * tptr = NULL;
  struct timeval   timeout_val;
  if (timeout != PMaxTimeInterval) {
    if (timeout.GetMilliSeconds() < 1000L*60L*60L*24L) {
      timeout_val.tv_usec = (timeout.GetMilliSeconds() % 1000) * 1000;
      timeout_val.tv_sec  = timeout.GetSeconds();
      tptr                = &timeout_val;
    }
  }

  int termPipe = PThread::Current()->termPipe[0];
  FD_SET(termPipe, &readBits);
  width = PMAX(width, termPipe+1);

  do {
    int result = ::select(width, &readBits, &writeBits, &exceptionBits, tptr);
    if (result >= 0) {
      if (FD_ISSET(termPipe, &readBits)) {
        FD_CLR(termPipe, &readBits);
        if (result == 1) {
          BYTE ch;
          ::read(termPipe, &ch, 1);
          FD_CLR(termPipe, &readBits);
          errno = EINTR;
          return -1;
        }
      }
      return result;
    }
  } while (errno == EINTR);
  return -1;
}

#endif


PIPSocket::Address::Address(DWORD dw)
{
  s_addr = dw;
}


PIPSocket::Address & PIPSocket::Address::operator=(DWORD dw)
{
  s_addr = dw;
  return *this;
}


PIPSocket::Address::operator DWORD() const
{
  return (DWORD)s_addr;
}

BYTE PIPSocket::Address::Byte1() const
{
  return *(((BYTE *)&s_addr)+0);
}

BYTE PIPSocket::Address::Byte2() const
{
  return *(((BYTE *)&s_addr)+1);
}

BYTE PIPSocket::Address::Byte3() const
{
  return *(((BYTE *)&s_addr)+2);
}

BYTE PIPSocket::Address::Byte4() const
{
  return *(((BYTE *)&s_addr)+3);
}

PIPSocket::Address::Address(BYTE b1, BYTE b2, BYTE b3, BYTE b4)
{
  BYTE * p = (BYTE *)&s_addr;
  p[0] = b1;
  p[1] = b2;
  p[2] = b3;
  p[3] = b4;
}

BOOL PIPSocket::IsLocalHost(const PString & hostname)
{
  if (hostname.IsEmpty())
    return TRUE;

  if (hostname *= "localhost")
    return TRUE;

  // lookup the host address using inet_addr, assuming it is a "." address
  Address addr = hostname;
  if (addr == 16777343)  // Is 127.0.0.1
    return TRUE;
  if (addr == (DWORD)-1)
    return FALSE;

  if (!GetHostAddress(hostname, addr))
    return FALSE;

  PUDPSocket sock;

//#ifndef __BEOS__	// changed by Jurjan
#if !defined(__BEOS__) && !defined(P_VXWORKS)
  // get number of interfaces
  int ifNum;
#ifdef SIOCGIFNUM
  PAssert(::ioctl(sock.GetHandle(), SIOCGIFNUM, &ifNum) >= 0, "could not do ioctl for ifNum");
#else
  ifNum = 100;
#endif

  PBYTEArray buffer;
  struct ifconf ifConf;
  ifConf.ifc_len  = ifNum * sizeof(ifreq);
  ifConf.ifc_req = (struct ifreq *)buffer.GetPointer(ifConf.ifc_len);
  
  if (ioctl(sock.GetHandle(), SIOCGIFCONF, &ifConf) >= 0) {
#ifndef SIOCGIFNUM
    ifNum = ifConf.ifc_len / sizeof(ifreq);
#endif

    int num = 0;
    for (num = 0; num < ifNum; num++) {

      ifreq * ifName = ifConf.ifc_req + num;
      struct ifreq ifReq;
      strcpy(ifReq.ifr_name, ifName->ifr_name);

      if (ioctl(sock.GetHandle(), SIOCGIFFLAGS, &ifReq) >= 0) {
        int flags = ifReq.ifr_flags;
        if (ioctl(sock.GetHandle(), SIOCGIFADDR, &ifReq) >= 0) {
          if ((flags & IFF_UP) && (addr == Address(((sockaddr_in *)&ifReq.ifr_addr)->sin_addr)))
            return TRUE;
        }
      }
    }
  }
#endif //!__BEOS__

  return FALSE;
}


////////////////////////////////////////////////////////////////
//
//  PTCPSocket
//
BOOL PTCPSocket::Read(void * buf, PINDEX maxLen)
{

  lastReadCount = 0;

  // wait until select indicates there is data to read, or until
  // a timeout occurs
  if (!PXSetIOBlock(PXReadBlock, readTimeout)) {
    lastError     = Timeout;
    return FALSE;
  }

#ifndef __BEOS__
  // attempt to read out of band data
  char buffer[32];
  int ooblen;
  while ((ooblen = ::recv(os_handle, buffer, sizeof(buffer), MSG_OOB)) > 0) 
    OnOutOfBand(buffer, ooblen);
#endif // !__BEOS__

    // attempt to read non-out of band data
  if (ConvertOSError(lastReadCount = ::recv(os_handle, (char *)buf, maxLen, 0)))
    return lastReadCount > 0;

  lastReadCount = 0;
  return FALSE;
}


BOOL PSocket::os_recvfrom(
      void * buf,     // Data to be written as URGENT TCP data.
      PINDEX len,     // Number of bytes pointed to by <CODE>buf</CODE>.
      int    flags,
      sockaddr * addr, // Address from which the datagram was received.
      PINDEX * addrlen)
{

  if (!PXSetIOBlock(PXReadBlock, readTimeout)) {
    lastError     = Timeout;
    lastReadCount = 0;
    return FALSE;
  }

  // attempt to read non-out of band data
  if (ConvertOSError(lastReadCount =
        ::recvfrom(os_handle, (char *)buf, len, flags, (sockaddr *)addr, (int *)(unsigned int *)(socklen_t *)addrlen)))	// casted by Jurjan
    return lastReadCount > 0;

  lastReadCount = 0;
  return FALSE;
}


BOOL PSocket::os_sendto(
      const void * buf,   // Data to be written as URGENT TCP data.
      PINDEX len,         // Number of bytes pointed to by <CODE>buf</CODE>.
      int flags,
      sockaddr * addr, // Address to which the datagram is sent.
      PINDEX addrlen)  
{

  lastWriteCount = 0;

  if (!IsOpen()) {
    lastError     = NotOpen;
    return FALSE;
  }

  // attempt to read data
  int writeResult;
  if (addr != NULL) {
      writeResult = ::sendto(os_handle, (char *)buf, len, flags, (sockaddr *)addr, addrlen);
	}
  else
    writeResult = ::send(os_handle, (char *)buf, len, flags);
  if (writeResult > 0) {
   PThread::Yield();	// gaat niet verder
    lastWriteCount = writeResult;
    return TRUE;
  }


  if (errno != EWOULDBLOCK)
    return ConvertOSError(-1);

  if (!PXSetIOBlock(PXWriteBlock, writeTimeout)) {
    lastError     = Timeout;
    return FALSE;
  }

⌨️ 快捷键说明

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