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

📄 transports.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 5 页
字号:


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

OpalTransportUDP::OpalTransportUDP(OpalEndPoint & ep,
                                   PIPSocket::Address binding,
                                   WORD port,
                                   BOOL reuseAddr)
  : OpalTransportIP(ep, binding, port)
{
  promiscuousReads = AcceptFromRemoteOnly;
  socketOwnedByListener = FALSE;
  reuseAddressFlag = reuseAddr;

  PUDPSocket * udp = new PUDPSocket;
  udp->Listen(binding, 0, port,
              reuseAddr ? PSocket::CanReuseAddress : PSocket::AddressIsExclusive);

  localPort = udp->GetPort();

  Open(udp);

  PTRACE(3, "OpalUDP\tBinding to interface: " << localAddress << ':' << localPort);
}


OpalTransportUDP::OpalTransportUDP(OpalEndPoint & ep, PUDPSocket & udp)
  : OpalTransportIP(ep, PIPSocket::GetDefaultIpAny(), 0)
{
  promiscuousReads = AcceptFromAnyAutoSet;
  socketOwnedByListener = TRUE;
  reuseAddressFlag = FALSE;

  udp.GetLocalAddress(localAddress, localPort);

  Open(udp);


  PTRACE(3, "OpalUDP\tPre-bound to interface: " << localAddress << ':' << localPort);
}


OpalTransportUDP::OpalTransportUDP(OpalEndPoint & ep,
                                   PIPSocket::Address binding,
                                   const PBYTEArray & packet,
                                   PIPSocket::Address remAddr,
                                   WORD remPort)
  : OpalTransportIP(ep, binding, 0),
    preReadPacket(packet)
{
  promiscuousReads = AcceptFromAnyAutoSet;
  socketOwnedByListener = FALSE;

  remoteAddress = remAddr;
  remotePort = remPort;

  PUDPSocket * udp = new PUDPSocket;
  udp->Listen(binding);

  localPort = udp->GetPort();

  Open(udp);

  PTRACE(3, "OpalUDP\tBinding to interface: " << localAddress << ':' << localPort);
}


OpalTransportUDP::~OpalTransportUDP()
{
  CloseWait();
  PTRACE(4,"Opal\tDeleted transport " << *this);
}


BOOL OpalTransportUDP::Close()
{
  PTRACE(4, "OpalUDP\tClose");
  PReadWaitAndSignal mutex(channelPointerMutex);

  if (socketOwnedByListener) {
    channelPointerMutex.StartWrite();
    readChannel = writeChannel = NULL;
    // Thread also owned by listener as well, don't wait on or delete it!
    thread = NULL; 
    channelPointerMutex.EndWrite();
    return TRUE;
  }

  if (connectSockets.IsEmpty())
    return OpalTransport::Close();

  channelPointerMutex.StartWrite();
  readChannel = writeChannel = NULL;

  // Still in connection on multiple interface phase. Close all of the
  // sockets we have open.
  for (PINDEX i = 0; i < connectSockets.GetSize(); i++)
    connectSockets[i].Close();

  channelPointerMutex.EndWrite();

  return TRUE;
}


BOOL OpalTransportUDP::IsReliable() const
{
  return FALSE;
}


BOOL OpalTransportUDP::IsCompatibleTransport(const OpalTransportAddress & address) const
{
  return address.Left(strlen(UdpPrefix)).ToLower () == UdpPrefix ||
         address.Left(sizeof(IpPrefix)-1).ToLower () == IpPrefix;
}


BOOL OpalTransportUDP::Connect()
{	
  if (remotePort == 0)
    return FALSE;

  if (remoteAddress == 0) {
    remoteAddress = INADDR_BROADCAST;
    PTRACE(2, "OpalUDP\tBroadcast connect to port " << remotePort);
  }
  else {
	PTRACE(2, "OpalUDP\tStarted connect to " << remoteAddress << ':' << remotePort);
  }

  OpalManager & manager = endpoint.GetManager();

  PSTUNClient * stun = manager.GetSTUN(remoteAddress);
  if (stun != NULL) {
    PUDPSocket * socket;
    if (stun->CreateSocket(socket)) {
      PIndirectChannel::Close();	//closing the channel and opening it with the new socket
      readAutoDelete = writeAutoDelete = FALSE;
      Open(socket);
      socket->GetLocalAddress(localAddress, localPort);
      socket->SetSendAddress(remoteAddress, remotePort);
      PTRACE(4, "OpalUDP\tSTUN created socket: " << localAddress << ':' << localPort);
      connectSockets.Append(socket);
      return true;
    }
    PTRACE(4, "OpalUDP\tSTUN could not create socket!");
  }
  

  // See if prebound to interface, only use that if so
  PIPSocket::InterfaceTable interfaces;
  if (localAddress != INADDR_ANY) {
    PTRACE(3, "OpalUDP\tConnect on pre-bound interface: " << localAddress);
    interfaces.Append(new PIPSocket::InterfaceEntry("", localAddress, PIPSocket::Address(0xffffffff), ""));
  }
  else if (!PIPSocket::GetInterfaceTable(interfaces)) {
    PTRACE(1, "OpalUDP\tNo interfaces on system!");
    interfaces.Append(new PIPSocket::InterfaceEntry("", localAddress, PIPSocket::Address(0xffffffff), ""));
  }
  else {
    PTRACE(4, "OpalUDP\tConnecting to interfaces:\n" << setfill('\n') << interfaces << setfill(' '));
  }

  PIndirectChannel::Close();	//closing the channel and opening it with the new socket
  PINDEX i;
  for (i = 0; i < interfaces.GetSize(); i++) {
    PIPSocket::Address interfaceAddress = interfaces[i].GetAddress();
    if (interfaceAddress == 0 || interfaceAddress == PIPSocket::Address())
      continue;

    // Check for already have had that IP address.
    PINDEX j;
    for (j = 0; j < i; j++) {
      if (interfaceAddress == interfaces[j].GetAddress())
        break;
    }
    if (j < i)
      continue;

    // Not explicitly multicast
    PUDPSocket * socket = new PUDPSocket;
    localPort = manager.GetNextUDPPort();
    WORD firstPort = localPort;
    while (!socket->Listen(interfaceAddress, 0, localPort, reuseAddressFlag?PIPSocket::CanReuseAddress:PIPSocket::AddressIsExclusive)) {
      localPort = manager.GetNextUDPPort();
      if (localPort == firstPort) {
        PTRACE(1, "OpalUDP\tCould not bind to any port in range " <<
	       manager.GetUDPPortBase() << " to " << manager.GetUDPPortMax());
        return FALSE;
      }
    }
    readAutoDelete = writeAutoDelete = FALSE;
    if (!PIndirectChannel::IsOpen())
      Open(socket);

#ifndef __BEOS__
    if (remoteAddress == INADDR_BROADCAST) {
      if (!socket->SetOption(SO_BROADCAST, 1)) {
        PTRACE(2, "OpalUDP\tError allowing broadcast: " << socket->GetErrorText());
        return FALSE;
      }
    }
#else
    PTRACE(3, "RAS\tBroadcast option under BeOS is not implemented yet");
#endif

    socket->GetLocalAddress(localAddress, localPort);
    socket->SetSendAddress(remoteAddress, remotePort);
    connectSockets.Append(socket);
  }
  
  readAutoDelete = writeAutoDelete = FALSE;

  if (connectSockets.IsEmpty())
    return FALSE;

  promiscuousReads = AcceptFromAnyAutoSet;

  return TRUE;
}


void OpalTransportUDP::EndConnect(const OpalTransportAddress & theLocalAddress)
{
  PAssert(theLocalAddress.GetIpAndPort(localAddress, localPort), PInvalidParameter);

  for (PINDEX i = 0; i < connectSockets.GetSize(); i++) {
    PUDPSocket * socket = (PUDPSocket *)connectSockets.GetAt(i);
    PIPSocket::Address addr;
    WORD port;
    if (socket->GetLocalAddress(addr, port) && addr == localAddress && port == localPort) {
      PTRACE(3, "OpalUDP\tEnded connect, selecting " << localAddress << ':' << localPort);
      connectSockets.DisallowDeleteObjects();
      connectSockets.RemoveAt(i);
      connectSockets.AllowDeleteObjects();
      readChannel = NULL;
      writeChannel = NULL;
      socket->SetOption(SO_BROADCAST, 0);
      PAssert(Open(socket), PLogicError);
      break;
    }
  }

  connectSockets.RemoveAll();

  OpalTransport::EndConnect(theLocalAddress);
}


BOOL OpalTransportUDP::SetLocalAddress(const OpalTransportAddress & newLocalAddress)
{
  if (connectSockets.IsEmpty())
    return OpalTransportIP::SetLocalAddress(newLocalAddress);

  if (!IsCompatibleTransport(newLocalAddress))
    return FALSE;

  if (!newLocalAddress.GetIpAndPort(localAddress, localPort))
    return FALSE;

  for (PINDEX i = 0; i < connectSockets.GetSize(); i++) {
    PUDPSocket * socket = (PUDPSocket *)connectSockets.GetAt(i);
    PIPSocket::Address ip;
    WORD port = 0;
    if (socket->GetLocalAddress(ip, port) && ip == localAddress && port == localPort) {
      writeChannel = &connectSockets[i];
      return TRUE;
    }
  }

  return FALSE;
}


BOOL OpalTransportUDP::SetRemoteAddress(const OpalTransportAddress & address)
{
  if (!OpalTransportIP::SetRemoteAddress(address))
    return FALSE;

  PUDPSocket * socket = (PUDPSocket *)GetReadChannel();
  if (socket != NULL)
    socket->SetSendAddress(remoteAddress, remotePort);
  return TRUE;
}


void OpalTransportUDP::SetPromiscuous(PromisciousModes promiscuous)
{
  promiscuousReads = promiscuous;
}


OpalTransportAddress OpalTransportUDP::GetLastReceivedAddress() const
{
  if (!lastReceivedAddress)
    return lastReceivedAddress;

  return OpalTransport::GetLastReceivedAddress();
}


BOOL OpalTransportUDP::Read(void * buffer, PINDEX length)
{
  if (!connectSockets.IsEmpty()) {
    PSocket::SelectList selection;

    PINDEX i;
    for (i = 0; i < connectSockets.GetSize(); i++)
      selection += connectSockets[i];

    if (PSocket::Select(selection, GetReadTimeout()) != PChannel::NoError) {
      PTRACE(1, "OpalUDP\tError on connection read select.");
      return FALSE;
    }

    if (selection.IsEmpty()) {
      PTRACE(2, "OpalUDP\tTimeout on connection read select.");
      return FALSE;
    }

    PUDPSocket & socket = (PUDPSocket &)selection[0];
    channelPointerMutex.StartWrite();
    if (!socket.IsOpen()) {
      channelPointerMutex.EndWrite();
      PTRACE(2, "OpalUDP\tSocket closed in connection read select.");
      return FALSE;
    }
    socket.GetLocalAddress(localAddress, localPort);
    readChannel = &socket;
    channelPointerMutex.EndWrite();
  }

  for (;;) {
    if (!OpalTransportIP::Read(buffer, length))
      return FALSE;

    PUDPSocket * socket = (PUDPSocket *)GetReadChannel();

    PIPSocket::Address address;
    WORD port;

    socket->GetLastReceiveAddress(address, port);
    lastReceivedAddress = OpalTransportAddress(address, port);

    switch (promiscuousReads) {
      case AcceptFromRemoteOnly :
        if (remoteAddress == address)
          return TRUE;
        break;

      case AcceptFromAnyAutoSet :
        remoteAddress = address;
        remotePort = port;
        socket->SetSendAddress(remoteAddress, remotePort);
        // fall into next case

      default : //AcceptFromAny
        return TRUE;
    }

    if (remoteAddress *= address)
      return TRUE;

    PTRACE(1, "UDP\tReceived PDU from incorrect host: " << address << ':' << port);
  }
}


BOOL OpalTransportUDP::ReadPDU(PBYTEArray & packet)
{
  if (preReadPacket.GetSize() > 0) {
    packet = preReadPacket;
    preReadPacket.SetSize(0);
    return TRUE;
  }

  if (!Read(packet.GetPointer(10000), 10000)) {
    packet.SetSize(0);
    return FALSE;
  }

  packet.SetSize(GetLastReadCount());
  return TRUE;
}


BOOL OpalTransportUDP::WritePDU(const PBYTEArray & packet)
{
  return Write((const BYTE *)packet, packet.GetSize());
}


BOOL OpalTransportUDP::WriteConnect(WriteConnectCallback function, void * userData)
{
  if (connectSockets.IsEmpty())
    return OpalTransport::WriteConnect(function, userData);

  BOOL ok = FALSE;

  PINDEX i;
  for (i = 0; i < connectSockets.GetSize(); i++) {
    PUDPSocket & socket = (PUDPSocket &)connectSockets[i];
    socket.GetLocalAddress(localAddress, localPort);
    writeChannel = &socket;
    if (function(*this, userData))
      ok = TRUE;
  }

  return ok;
}


const char * OpalTransportUDP::GetProtoPrefix() const
{
  return UdpPrefix;
}


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

⌨️ 快捷键说明

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