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

📄 sockets.cxx

📁 opal的ptlib c++源程序 可以从官方网站上下载
💻 CXX
📖 第 1 页 / 共 5 页
字号:
  return "tcp";
}


PBoolean PTCPSocket::Write(const void * buf, PINDEX len)
{
  flush();
  PINDEX writeCount = 0;

  while (len > 0) {
    if (!os_sendto(((char *)buf)+writeCount, len, 0, NULL, 0))
      return PFalse;
    writeCount += lastWriteCount;
    len -= lastWriteCount;
  }

  lastWriteCount = writeCount;
  return PTrue;
}


PBoolean PTCPSocket::Listen(unsigned queueSize, WORD newPort, Reusability reuse)
{
#if P_HAS_IPV6
  return Listen(GetDefaultIpAny(), queueSize, newPort, reuse);
#else
  return Listen(INADDR_ANY, queueSize, newPort, reuse);
#endif
}


PBoolean PTCPSocket::Listen(const Address & bindAddr,
                        unsigned queueSize,
                        WORD newPort,
                        Reusability reuse)
{
  if (PIPSocket::Listen(bindAddr, queueSize, newPort, reuse) &&
      ConvertOSError(::listen(os_handle, queueSize)))
    return PTrue;

  os_close();
  return PFalse;
}


PBoolean PTCPSocket::Accept(PSocket & socket)
{
  PAssert(PIsDescendant(&socket, PIPSocket), "Invalid listener socket");

#if P_HAS_IPV6

  Psockaddr sa;
  PINDEX size = sa.GetSize();
  if (!os_accept(socket, sa, &size))
    return PFalse;
    
#else

  sockaddr_in address;
  address.sin_family = AF_INET;
  PINDEX size = sizeof(address);
  if (!os_accept(socket, (struct sockaddr *)&address, &size))
    return PFalse;

#endif

  port = ((PIPSocket &)socket).GetPort();
  
  return PTrue;
}


PBoolean PTCPSocket::WriteOutOfBand(void const * buf, PINDEX len)
{
#ifdef __NUCLEUS_NET__
  PAssertAlways("WriteOutOfBand unavailable on Nucleus Plus");
  //int count = NU_Send(os_handle, (char *)buf, len, 0);
  int count = ::send(os_handle, (const char *)buf, len, 0);
#elif defined(P_VXWORKS)
  int count = ::send(os_handle, (char *)buf, len, MSG_OOB);
#else
  int count = ::send(os_handle, (const char *)buf, len, MSG_OOB);
#endif
  if (count < 0) {
    lastWriteCount = 0;
    return ConvertOSError(count, LastWriteError);
  }
  else {
    lastWriteCount = count;
    return PTrue;
  }
}


void PTCPSocket::OnOutOfBand(const void *, PINDEX)
{
}


//////////////////////////////////////////////////////////////////////////////
// PIPDatagramSocket

PIPDatagramSocket::PIPDatagramSocket()
{
}


PBoolean PIPDatagramSocket::ReadFrom(void * buf, PINDEX len,
                                 Address & addr, WORD & port)
{
  lastReadCount = 0;

#if P_HAS_IPV6

  Psockaddr sa;
  PINDEX size = sa.GetSize();
  if (os_recvfrom(buf, len, 0, sa, &size)) {
    addr = sa.GetIP();
    port = sa.GetPort();
  }

#else

  sockaddr_in sockAddr;
  PINDEX addrLen = sizeof(sockAddr);
  if (os_recvfrom(buf, len, 0, (struct sockaddr *)&sockAddr, &addrLen)) {
    addr = sockAddr.sin_addr;
    port = ntohs(sockAddr.sin_port);
  }

#endif

  return lastReadCount > 0;
}


PBoolean PIPDatagramSocket::WriteTo(const void * buf, PINDEX len,
                                const Address & addr, WORD port)
{
  lastWriteCount = 0;

  PBoolean broadcast = addr.IsAny() || addr.IsBroadcast();
  if (broadcast) {
#ifdef __BEOS__
    PAssertAlways("Broadcast option under BeOS is not implemented yet");
    return PFalse;
#else
    if (!SetOption(SO_BROADCAST, 1))
      return PFalse;
#endif
  }

#if P_HAS_IPV6

  Psockaddr sa(broadcast ? Address::GetBroadcast() : addr, port);
  PBoolean ok = os_sendto(buf, len, 0, sa, sa.GetSize()) != 0;

#else

  sockaddr_in sockAddr;
  sockAddr.sin_family = AF_INET;
  sockAddr.sin_addr = (broadcast ? Address::GetBroadcast() : addr);
  sockAddr.sin_port = htons(port);
  PBoolean ok = os_sendto(buf, len, 0, (struct sockaddr *)&sockAddr, sizeof(sockAddr)) != 0;

#endif

#ifndef __BEOS__
  if (broadcast)
    SetOption(SO_BROADCAST, 0);
#endif

  return ok && lastWriteCount >= len;
}


//////////////////////////////////////////////////////////////////////////////
// PUDPSocket

PUDPSocket::PUDPSocket(WORD newPort)
{
  sendPort = 0;
  SetPort(newPort);
  OpenSocket();
}

PUDPSocket::PUDPSocket(PQoS * qos, WORD newPort)
{
  if (qos != NULL)
      qosSpec = *qos;
  sendPort = 0;
  SetPort(newPort);
  OpenSocket();
}


PUDPSocket::PUDPSocket(const PString & service, PQoS * qos)
{
  if (qos != NULL)
      qosSpec = *qos;
  sendPort = 0;
  SetPort(service);
  OpenSocket();
}


PUDPSocket::PUDPSocket(const PString & address, WORD newPort)
{
  sendPort = 0;
  SetPort(newPort);
  Connect(address);
}


PUDPSocket::PUDPSocket(const PString & address, const PString & service)
{
  sendPort = 0;
  SetPort(service);
  Connect(address);
}


PBoolean PUDPSocket::ModifyQoSSpec(PQoS * qos)
{
  if (qos==NULL)
    return PFalse;

  qosSpec = *qos;
  return PTrue;
}

#if P_HAS_QOS
PQoS & PUDPSocket::GetQoSSpec()
{
  return qosSpec;
}
#endif

PBoolean PUDPSocket::ApplyQoS()
{
#ifdef _WIN32_WCE
  return PFalse;   //QoS not supported
#endif

  char DSCPval = 0;
  if (qosSpec.GetDSCP() < 0 ||
      qosSpec.GetDSCP() > 63) {
    if (qosSpec.GetServiceType() == SERVICETYPE_PNOTDEFINED)
      return PTrue;
    else {
      switch (qosSpec.GetServiceType()) {
        case SERVICETYPE_GUARANTEED:
          DSCPval = PQoS::guaranteedDSCP;
          break;
        case SERVICETYPE_CONTROLLEDLOAD:
          DSCPval = PQoS::controlledLoadDSCP;
          break;
        case SERVICETYPE_BESTEFFORT:
        default:
          DSCPval = PQoS::bestEffortDSCP;
          break;
      }
    }
  }
  else
    DSCPval = (char)qosSpec.GetDSCP();

#ifdef _WIN32
#if P_HAS_QOS
  if (disableGQoS)
    return PFalse;

  PBoolean usesetsockopt = PFalse;

  OSVERSIONINFO versInfo;
  ZeroMemory(&versInfo,sizeof(OSVERSIONINFO));
  versInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  if (!(GetVersionEx(&versInfo)))
    usesetsockopt = PTrue;
  else {
    if (versInfo.dwMajorVersion < 5)
      usesetsockopt = PTrue;

    if (disableGQoS)
          return PFalse;

    PBoolean usesetsockopt = PFalse;

    if (versInfo.dwMajorVersion == 5 &&
        versInfo.dwMinorVersion == 0)
      usesetsockopt = PTrue;         //Windows 2000 does not always support QOS_DESTADDR
  }

  PBoolean retval = PFalse;
  if (!usesetsockopt && sendAddress.IsValid() && sendPort != 0) {
    sockaddr_in sa;
    sa.sin_family = AF_INET;
    sa.sin_port = htons(sendPort);
    sa.sin_addr = sendAddress;
    memset(sa.sin_zero,0,8);

    char * inBuf = new char[2048];
    memset(inBuf,0,2048);
    DWORD bufLen = 0;
    PWinQoS wqos(qosSpec, (struct sockaddr *)(&sa), inBuf, bufLen);

    DWORD dummy = 0;
    int irval = WSAIoctl(os_handle, SIO_SET_QOS, inBuf, bufLen, NULL, 0, &dummy, NULL, NULL);

    delete[] inBuf;

    return irval == 0;
  }

  if (!usesetsockopt)
    return retval;

#endif  // P_HAS_QOS
#endif  // _WIN32

  unsigned int setDSCP = DSCPval<<2;

  int rv = 0;
  unsigned int curval = 0;
  socklen_t cursize = sizeof(curval);
  rv = ::getsockopt(os_handle,IPPROTO_IP, IP_TOS, (char *)(&curval), &cursize);
  if (curval == setDSCP)
    return PTrue;    //Required DSCP already set


  rv = ::setsockopt(os_handle, IPPROTO_IP, IP_TOS, (char *)&setDSCP, sizeof(setDSCP));

  if (rv != 0) {
    int err;
#ifdef _WIN32
    err = WSAGetLastError();
#else
    err = errno;
#endif
    PTRACE(1,"QOS\tsetsockopt failed with code " << err);
    return PFalse;
  }
    
  return PTrue;
}

PBoolean PUDPSocket::OpenSocketGQOS(int af, int type, int proto)
{
#ifdef _WIN32_WCE   //QOS not supported
  return ConvertOSError(os_handle = os_socket(af, type, proto));
#endif

#if defined(_WIN32) && defined(P_HAS_QOS)
    
  DWORD bufferSize = 0;
  DWORD numProtocols, i;
  LPWSAPROTOCOL_INFO installedProtocols, qosProtocol;

  //Try to find a QOS-enabled protocol
 
  PBoolean retval = ConvertOSError(numProtocols = WSAEnumProtocols(((proto==0) ? NULL : &proto),
                                                            NULL,
                                                            &bufferSize));
    
  if (numProtocols == SOCKET_ERROR && WSAGetLastError()!=WSAENOBUFS) 
    return retval;

  installedProtocols = (LPWSAPROTOCOL_INFO)(new BYTE[bufferSize]);
  retval = ConvertOSError(numProtocols = WSAEnumProtocols(((proto==0) ? NULL : &proto),
                                                            installedProtocols,
                                                            &bufferSize));
  if (numProtocols == SOCKET_ERROR) {
    delete[] installedProtocols;
    return retval;
  }

  qosProtocol = installedProtocols;
  PBoolean haveQoSproto = PFalse;

  for (i=0; i<numProtocols; qosProtocol++, i++) {
    if ((qosProtocol->dwServiceFlags1 & XP1_QOS_SUPPORTED) &&
        (qosProtocol->iSocketType == type) &&
        (qosProtocol->iAddressFamily == af)) {
      haveQoSproto = PTrue;
      break;
    }
  }

  if (haveQoSproto) {
    retval =  ConvertOSError(os_handle = WSASocket(af,
                                                   type,
                                                   proto,
                                                   qosProtocol,
                                                   0,
                                                   WSA_FLAG_OVERLAPPED));
  }
  else
  {    
    retval = ConvertOSError(os_handle = WSASocket (af,
                                                   type,
                                                   proto,
                                                   NULL,
                                                   0,
                                                   WSA_FLAG_OVERLAPPED));
  }

  delete[] installedProtocols;

  if (os_handle == INVALID_SOCKET)
    return retval;
#else
  PBoolean retval = ConvertOSError(os_handle = os_socket(af, type, proto));
#endif

  return retval;
}

#ifdef _WIN32
#ifndef _WIN32_WCE
#ifdef P_HAS_QOS

#define COULD_HAVE_QOS

static PBoolean CheckOSVersion()
{
    OSVERSIONINFO versInfo;
    ZeroMemory(&versInfo,sizeof(OSVERSIONINFO));
    versInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if (GetVersionEx(&versInfo))
    {
        if (versInfo.dwMajorVersion > 5 ||
           (versInfo.dwMajorVersion == 5 &&
            versInfo.dwMinorVersion > 0))
          return PTrue;
    }
  return PFalse;
}

#endif
#endif
#endif

PBoolean PUDPSocket::OpenSocket()
{
#ifdef COULD_HAVE_QOS
  if (CheckOSVersion()) 
    return OpenSocketGQOS(AF_INET, SOCK_DGRAM, 0);
#endif

  return ConvertOSError(os_handle = os_socket(AF_INET,SOCK_DGRAM, 0));
}

PBoolean PUDPSocket::OpenSocket(int ipAdressFamily)
{
#ifdef COULD_HAVE_QOS
  if (CheckOSVersion()) 
    return OpenSocketGQOS(ipAdressFamily, SOCK_DGRAM, 0);
#endif

  return ConvertOSError(os_handle = os_socket(ipAdressFamily,SOCK_DGRAM, 0));
}

const char * PUDPSocket::GetProtocolName() const
{
  return "udp";
}


PBoolean PUDPSocket::Connect(const PString & address)
{
  sendPort = 0;
  return PIPDatagramSocket::Connect(address);
}


PBoolean PUDPSocket::Read(void * buf, PINDEX len)
{
  return PIPDatagramSocket::ReadFrom(buf, len, lastReceiveAddress, lastReceivePort);
}


PBoolean PUDPSocket::Write(const void * buf, PINDEX len)
{
  if (sendPort == 0)
    return PIPDatagramSocket::Write(buf, len);
  else
    return PIPDatagramSocket::WriteTo(buf, len, sendAddress, sendPort);
}


void PUDPSocket::SetSendAddress(const Address & newAddress, WORD newPort)
{
  sendAddress = newAddress;
  sendPort    = newPort;
  ApplyQoS();
}


void PUDPSocket::GetSendAddress(Address & address, WORD & port)
{
  address = sendAddress;
  port    = sendPort;
}


void PUDPSocket::GetLastReceiveAddress(Address & address, WORD & port)
{
  address = lastReceiveAddress;
  port    = lastReceivePort;
}

//////////////////////////////////////////////////////////////////////////////

PBoolean PICMPSocket::OpenSocket(int)
{
  return PFalse;
}

//////////////////////////////////////////////////////////////////////////////

PBoolean PIPSocketAddressAndPort::Parse(const PString & str, WORD _port, char _sep)
{
  sep  = _sep;
  port = _port;

  PINDEX pos = str.Find(sep);
  if (pos != P_MAX_INDEX) {
    port    = (WORD)str.Mid(pos+1).AsInteger();
    if (!PIPSocket::GetHostAddress(str.Left(pos), address))
      return PFalse;
  }
  else if (port == 0) 
    return PFalse;
  else if (!PIPSocket::GetHostAddress(str, address))
    return PFalse;

  return PTrue;
}


// End Of File ///////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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