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

📄 transports.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 5 页
字号:
  if (host == "*") {
    ip = PIPSocket::GetDefaultIpAny();
    return TRUE;
  }

  if (PIPSocket::GetHostAddress(host, ip))
    return TRUE;

  PTRACE(1, "Opal\tCould not find host : \"" << host << '"');
  return FALSE;
}


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

static BOOL GetAdjustedIpAndPort(const OpalTransportAddress & address,
                                 OpalEndPoint & endpoint,
                                 OpalTransportAddress::BindOptions option,
                                 PIPSocket::Address & ip,
                                 WORD & port,
                                 BOOL & reuseAddr)
{
  reuseAddr = address[address.GetLength()-1] == '+';

  switch (option) {
    case OpalTransportAddress::NoBinding :
      ip = PIPSocket::GetDefaultIpAny();
      port = 0;
      return TRUE;

    case OpalTransportAddress::HostOnly :
      port = 0;
      return address.GetIpAddress(ip);

    default :
      port = endpoint.GetDefaultSignalPort();
      return address.GetIpAndPort(ip, port);
  }
}


OpalListener * OpalInternalTCPTransport::CreateListener(const OpalTransportAddress & address,
                                                        OpalEndPoint & endpoint,
                                                        OpalTransportAddress::BindOptions option) const
{
  PIPSocket::Address ip;
  WORD port;
  BOOL reuseAddr;
  if (GetAdjustedIpAndPort(address, endpoint, option, ip, port, reuseAddr))
    return new OpalListenerTCP(endpoint, ip, port, reuseAddr);

  return NULL;
}


OpalTransport * OpalInternalTCPTransport::CreateTransport(const OpalTransportAddress & address,
                                                          OpalEndPoint & endpoint,
                                                          OpalTransportAddress::BindOptions option) const
{
  PIPSocket::Address ip;
  WORD port;
  BOOL reuseAddr;
  if (GetAdjustedIpAndPort(address, endpoint, option, ip, port, reuseAddr)) {
    if (option == OpalTransportAddress::Datagram)
      return new OpalTransportUDP(endpoint, ip, 0, reuseAddr);
    return new OpalTransportTCP(endpoint, ip, port, reuseAddr);
  }

  return NULL;
}


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

OpalListener * OpalInternalUDPTransport::CreateListener(const OpalTransportAddress & address,
                                                        OpalEndPoint & endpoint,
                                                        OpalTransportAddress::BindOptions option) const
{
  PIPSocket::Address ip;
  WORD port;
  BOOL reuseAddr;
  if (GetAdjustedIpAndPort(address, endpoint, option, ip, port, reuseAddr))
    return new OpalListenerUDP(endpoint, ip, port, reuseAddr);

  return NULL;
}


OpalTransport * OpalInternalUDPTransport::CreateTransport(const OpalTransportAddress & address,
                                                          OpalEndPoint & endpoint,
                                                          OpalTransportAddress::BindOptions option) const
{
  PIPSocket::Address ip;
  WORD port;
  BOOL reuseAddr;
  if (GetAdjustedIpAndPort(address, endpoint, option, ip, port, reuseAddr)) {
    if (option == OpalTransportAddress::Streamed)
      return new OpalTransportTCP(endpoint, ip, 0, reuseAddr);
    return new OpalTransportUDP(endpoint, ip, port, reuseAddr);
  }

  return NULL;
}


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

OpalListener::OpalListener(OpalEndPoint & ep)
  : endpoint(ep)
{
  thread = NULL;
  singleThread = FALSE;
}


void OpalListener::PrintOn(ostream & strm) const
{
  strm << GetLocalAddress();
}


void OpalListener::CloseWait()
{
  PTRACE(3, "Listen\tStopping listening thread on " << GetLocalAddress());
  Close();

  PAssert(PThread::Current() != thread, PLogicError);
  if (thread != NULL) {
    PAssert(thread->WaitForTermination(10000), "Listener thread did not terminate");
    delete thread;
    thread = NULL;
  }
}


void OpalListener::ListenForConnections(PThread & thread, INT)
{
  PTRACE(3, "Listen\tStarted listening thread on " << GetLocalAddress());
  PAssert(!acceptHandler.IsNULL(), PLogicError);

  while (IsOpen()) {
    OpalTransport * transport = Accept(PMaxTimeInterval);
    if (transport == NULL)
      acceptHandler(*this, 0);
    else {
      if (singleThread) {
        transport->AttachThread(&thread);
        acceptHandler(*this, (INT)transport);
      }
      else {
        transport->AttachThread(PThread::Create(acceptHandler,
                                                (INT)transport,
                                                PThread::NoAutoDeleteThread,
                                                PThread::NormalPriority,
                                                "Opal Answer:%x"));
      }
      // Note: acceptHandler is responsible for deletion of the transport
    }
  }
}


BOOL OpalListener::StartThread(const PNotifier & theAcceptHandler, BOOL isSingleThread)
{
  acceptHandler = theAcceptHandler;
  singleThread = isSingleThread;

  thread = PThread::Create(PCREATE_NOTIFIER(ListenForConnections), 0,
                           PThread::NoAutoDeleteThread,
                           PThread::NormalPriority,
                           "Opal Listener:%x");

  return thread != NULL;
}


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

OpalTransportAddressArray OpalGetInterfaceAddresses(const OpalListenerList & listeners,
                                                    BOOL excludeLocalHost,
                                                    OpalTransport * associatedTransport)
{
  OpalTransportAddressArray interfaceAddresses;

  PINDEX i;
  for (i = 0; i < listeners.GetSize(); i++) {
    OpalTransportAddressArray newAddrs = OpalGetInterfaceAddresses(listeners[i].GetTransportAddress(), excludeLocalHost, associatedTransport);
    PINDEX size  = interfaceAddresses.GetSize();
    PINDEX nsize = newAddrs.GetSize();
    interfaceAddresses.SetSize(size + nsize);
    PINDEX j;
    for (j = 0; j < nsize; j++)
      interfaceAddresses.SetAt(size + j, new OpalTransportAddress(newAddrs[j]));
  }

  return interfaceAddresses;
}


OpalTransportAddressArray OpalGetInterfaceAddresses(const OpalTransportAddress & addr,
                                                    BOOL excludeLocalHost,
                                                    OpalTransport * associatedTransport)
{
  PIPSocket::Address ip;
  WORD port = 0;
  if (!addr.GetIpAndPort(ip, port) || !ip.IsAny())
    return addr;

  PIPSocket::InterfaceTable interfaces;
  if (!PIPSocket::GetInterfaceTable(interfaces))
    return addr;

  if (interfaces.GetSize() == 1)
    return OpalTransportAddress(interfaces[0].GetAddress(), port);

  PINDEX i;
  OpalTransportAddressArray interfaceAddresses;
  PIPSocket::Address firstAddress(0);

  if (associatedTransport != NULL) {
    if (associatedTransport->GetLocalAddress().GetIpAddress(firstAddress)) {
      for (i = 0; i < interfaces.GetSize(); i++) {
        PIPSocket::Address ip = interfaces[i].GetAddress();
        if (ip == firstAddress)
          interfaceAddresses.Append(new OpalTransportAddress(ip, port));
      }
    }
  }

  for (i = 0; i < interfaces.GetSize(); i++) {
    PIPSocket::Address ip = interfaces[i].GetAddress();
    if (ip != firstAddress && !(excludeLocalHost && ip.IsLoopback()))
      interfaceAddresses.Append(new OpalTransportAddress(ip, port));
  }

  return interfaceAddresses;
}


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

OpalListenerIP::OpalListenerIP(OpalEndPoint & ep,
                               PIPSocket::Address binding,
                               WORD port,
                               BOOL exclusive)
  : OpalListener(ep),
    localAddress(binding)
{
  listenerPort = port;
  exclusiveListener = exclusive;
}


OpalTransportAddress OpalListenerIP::GetLocalAddress(const OpalTransportAddress & preferredAddress) const
{
  PString addr;

  // If specifically bound to interface use that
  if (!localAddress.IsAny())
    addr = localAddress.AsString();
  else {
    // If bound to all, then use '*' unless a preferred address is specified
    addr = "*";

    PIPSocket::Address ip;
    if (preferredAddress.GetIpAddress(ip)) {
      // Verify preferred address is actually an interface in this machine!
      PIPSocket::InterfaceTable interfaces;
      if (PIPSocket::GetInterfaceTable(interfaces)) {
        for (PINDEX i = 0; i < interfaces.GetSize(); i++) {
          if (interfaces[i].GetAddress() == ip) {
            addr = ip.AsString();
            break;
          }
        }
      }
    }
  }

  addr.sprintf(":%u", listenerPort);

  return GetProtoPrefix() + addr;
}


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

OpalListenerTCP::OpalListenerTCP(OpalEndPoint & ep,
                                 PIPSocket::Address binding,
                                 WORD port,
                                 BOOL exclusive)
  : OpalListenerIP(ep, binding, port, exclusive)
{
  listenerPort = port;
}


OpalListenerTCP::~OpalListenerTCP()
{
  CloseWait();
}


BOOL OpalListenerTCP::Open(const PNotifier & theAcceptHandler, BOOL isSingleThread)
{
  if (listenerPort == 0) {
    OpalManager & manager = endpoint.GetManager();
    listenerPort = manager.GetNextTCPPort();
    WORD firstPort = listenerPort;
    while (!listener.Listen(localAddress, 1, listenerPort)) {
      listenerPort = manager.GetNextTCPPort();
      if (listenerPort == firstPort) {
        PTRACE(1, "Listen\tOpen on " << localAddress << " failed: " << listener.GetErrorText());
        break;
      }
    }
    listenerPort = listener.GetPort();
    return StartThread(theAcceptHandler, isSingleThread);
  }

  if (listener.Listen(localAddress, 1, listenerPort))
    return StartThread(theAcceptHandler, isSingleThread);

  if (exclusiveListener) {
    PTRACE(1, "Listen\tOpen on " << localAddress << ':' << listener.GetPort()
           << " failed: " << listener.GetErrorText());
    return FALSE;
  }

  if (listener.GetErrorNumber() != EADDRINUSE)
    return FALSE;

  PTRACE(1, "Listen\tSocket for " << localAddress << ':' << listener.GetPort()
         << " already in use, incoming connections may not all be serviced!");

  if (listener.Listen(localAddress, 100, 0, PSocket::CanReuseAddress))
    return StartThread(theAcceptHandler, isSingleThread);

  PTRACE(1, "Listen\tOpen (REUSEADDR) on " << localAddress << ':' << listener.GetPort()
         << " failed: " << listener.GetErrorText());
  return FALSE;
}


BOOL OpalListenerTCP::IsOpen()
{
  return listener.IsOpen();
}


void OpalListenerTCP::Close()
{
  listener.Close();
}


OpalTransport * OpalListenerTCP::Accept(const PTimeInterval & timeout)
{
  if (!listener.IsOpen())
    return NULL;

  listener.SetReadTimeout(timeout); // Wait for remote connect

  PTRACE(4, "Listen\tWaiting on socket accept on " << GetLocalAddress());
  PTCPSocket * socket = new PTCPSocket;
  if (socket->Accept(listener)) {
    OpalTransportTCP * transport = new OpalTransportTCP(endpoint);
    if (transport->Open(socket))
      return transport;

    PTRACE(1, "Listen\tFailed to open transport, connection not started.");
    delete transport;
    return NULL;
  }
  else if (socket->GetErrorCode() != PChannel::Interrupted) {
    PTRACE(1, "Listen\tAccept error:" << socket->GetErrorText());
    listener.Close();
  }

  delete socket;
  return NULL;
}


const char * OpalListenerTCP::GetProtoPrefix() const
{
  return TcpPrefix;
}


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

OpalListenerUDP::OpalListenerUDP(OpalEndPoint & endpoint,
                                 PIPSocket::Address binding,
                                 WORD port,
                                 BOOL exclusive)
  : OpalListenerIP(endpoint, binding, port, exclusive)
{
}


OpalListenerUDP::~OpalListenerUDP()
{
  CloseWait();
}


BOOL OpalListenerUDP::OpenOneSocket(const PIPSocket::Address & address)
{
  PUDPSocket * socket = new PUDPSocket(listenerPort);
  if (socket->Listen(address)) {
    listeners.Append(socket);
    if (listenerPort == 0)
      listenerPort = socket->GetPort();
    return TRUE;
  }

  PTRACE(1, "Listen\tError in UDP listen: " << socket->GetErrorText());
  delete socket;
  return FALSE;
}


BOOL OpalListenerUDP::Open(const PNotifier & theAcceptHandler, BOOL /*isSingleThread*/)
{

⌨️ 快捷键说明

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