📄 transports.cxx
字号:
* Updated to OpenH323 v1.9.1
*
* Revision 2.16 2002/06/16 23:07:19 robertj
* Fixed several memory leaks, thanks Ted Szoczei
* Fixed error opening UDP listener for broadcast packets under Win32.
* Is not needed as it is under windows, thanks Ted Szoczei
*
* Revision 2.15 2002/04/16 07:52:51 robertj
* Change to allow SetRemoteAddress before UDP is connected.
*
* Revision 2.14 2002/04/10 03:12:35 robertj
* Fixed SetLocalAddress to return FALSE if did not set the address to a
* different address to the current one. Altered UDP version to cope.
*
* Revision 2.13 2002/04/09 04:44:36 robertj
* Fixed bug where crahses if close channel while in UDP connect mode.
*
* Revision 2.12 2002/04/09 00:22:16 robertj
* Added ability to set the local address on a transport, under some circumstances.
*
* Revision 2.11 2002/03/27 05:37:39 robertj
* Fixed removal of writeChannel after wrinting to UDP transport in connect mode.
*
* Revision 2.10 2002/03/15 00:20:54 robertj
* Fixed bug when closing UDP transport when in "connect" mode.
*
* Revision 2.9 2002/02/06 06:07:10 robertj
* Fixed shutting down UDP listener thread
*
* Revision 2.8 2002/01/14 00:19:33 craigs
* Fixed problems with remote address used instead of local address
*
* Revision 2.7 2001/12/07 08:55:32 robertj
* Used UDP port base when creating UDP transport.
*
* Revision 2.6 2001/11/14 06:28:20 robertj
* Added missing break when ending UDP connect phase.
*
* Revision 2.5 2001/11/13 04:29:48 robertj
* Changed OpalTransportAddress CreateTransport and CreateListsner functions
* to have extra parameter to control local binding of sockets.
*
* Revision 2.4 2001/11/12 05:31:36 robertj
* Changed CreateTransport() on an OpalTransportAddress to bind to local address.
* Added OpalTransportAddress::GetIpAddress when don't need port number.
*
* Revision 2.3 2001/11/09 05:49:47 robertj
* Abstracted UDP connection algorithm
*
* Revision 2.2 2001/11/06 05:40:13 robertj
* Added OpalListenerUDP class to do listener semantics on a UDP socket.
*
* Revision 2.1 2001/10/03 05:53:25 robertj
* Update to new PTLib channel error system.
*
* Revision 2.0 2001/07/27 15:48:25 robertj
* Conversion of OpenH323 to Open Phone Abstraction Library (OPAL)
*
*/
#include <ptlib.h>
#ifdef __GNUC__
#pragma implementation "transports.h"
#endif
#include <opal/transports.h>
#include <opal/manager.h>
#include <opal/endpoint.h>
#include <opal/call.h>
#include <ptclib/pstun.h>
static const char IpPrefix[] = "ip$"; // For backward compatibility with OpenH323
static const char TcpPrefix[] = "tcp$";
static const char UdpPrefix[] = "udp$";
#include <ptclib/pstun.h>
////////////////////////////////////////////////////////////////
class OpalInternalTransport : public PObject
{
PCLASSINFO(OpalInternalTransport, PObject);
public:
virtual PString GetHostName(
const OpalTransportAddress & address
) const;
virtual BOOL GetIpAndPort(
const OpalTransportAddress & address,
PIPSocket::Address & ip,
WORD & port
) const;
virtual OpalListener * CreateListener(
const OpalTransportAddress & address,
OpalEndPoint & endpoint,
OpalTransportAddress::BindOptions options
) const = 0;
virtual OpalTransport * CreateTransport(
const OpalTransportAddress & address,
OpalEndPoint & endpoint,
OpalTransportAddress::BindOptions options
) const = 0;
};
////////////////////////////////////////////////////////////////
class OpalInternalIPTransport : public OpalInternalTransport
{
PCLASSINFO(OpalInternalIPTransport, OpalInternalTransport);
public:
virtual PString GetHostName(
const OpalTransportAddress & address
) const;
virtual BOOL GetIpAndPort(
const OpalTransportAddress & address,
PIPSocket::Address & ip,
WORD & port
) const;
};
////////////////////////////////////////////////////////////////
static class OpalInternalTCPTransport : public OpalInternalIPTransport
{
PCLASSINFO(OpalInternalTCPTransport, OpalInternalIPTransport);
public:
virtual OpalListener * CreateListener(
const OpalTransportAddress & address,
OpalEndPoint & endpoint,
OpalTransportAddress::BindOptions options
) const;
virtual OpalTransport * CreateTransport(
const OpalTransportAddress & address,
OpalEndPoint & endpoint,
OpalTransportAddress::BindOptions options
) const;
} internalTCPTransport;
////////////////////////////////////////////////////////////////
static class OpalInternalUDPTransport : public OpalInternalIPTransport
{
PCLASSINFO(OpalInternalUDPTransport, OpalInternalIPTransport);
public:
virtual OpalListener * CreateListener(
const OpalTransportAddress & address,
OpalEndPoint & endpoint,
OpalTransportAddress::BindOptions options
) const;
virtual OpalTransport * CreateTransport(
const OpalTransportAddress & address,
OpalEndPoint & endpoint,
OpalTransportAddress::BindOptions options
) const;
} internalUDPTransport;
/////////////////////////////////////////////////////////////////
#define new PNEW
/////////////////////////////////////////////////////////////////
OpalTransportAddress::OpalTransportAddress()
{
transport = NULL;
}
OpalTransportAddress::OpalTransportAddress(const char * cstr,
WORD port,
const char * proto)
: PString(cstr)
{
SetInternalTransport(port, proto);
}
OpalTransportAddress::OpalTransportAddress(const PString & str,
WORD port,
const char * proto)
: PString(str)
{
SetInternalTransport(port, proto);
}
OpalTransportAddress::OpalTransportAddress(const PIPSocket::Address & addr, WORD port, const char * proto)
: PString(addr.AsString())
{
SetInternalTransport(port, proto);
}
PString OpalTransportAddress::GetHostName() const
{
if (transport == NULL)
return PString();
return transport->GetHostName(*this);
}
BOOL OpalTransportAddress::IsEquivalent(const OpalTransportAddress & address)
{
if (*this == address)
return TRUE;
if (IsEmpty() || address.IsEmpty())
return FALSE;
PIPSocket::Address ip1, ip2;
WORD port1 = 65535, port2 = 65535;
return GetIpAndPort(ip1, port1) &&
address.GetIpAndPort(ip2, port2) &&
(ip1.IsAny() || ip2.IsAny() || (ip1 *= ip2)) &&
(port1 == 65535 || port2 == 65535 || port1 == port2);
}
BOOL OpalTransportAddress::GetIpAddress(PIPSocket::Address & ip) const
{
if (transport == NULL)
return FALSE;
WORD dummy = 65535;
return transport->GetIpAndPort(*this, ip, dummy);
}
BOOL OpalTransportAddress::GetIpAndPort(PIPSocket::Address & ip, WORD & port) const
{
if (transport == NULL)
return FALSE;
return transport->GetIpAndPort(*this, ip, port);
}
OpalListener * OpalTransportAddress::CreateListener(OpalEndPoint & endpoint,
BindOptions option) const
{
if (transport == NULL)
return NULL;
return transport->CreateListener(*this, endpoint, option);
}
OpalTransport * OpalTransportAddress::CreateTransport(OpalEndPoint & endpoint,
BindOptions option) const
{
if (transport == NULL)
return NULL;
return transport->CreateTransport(*this, endpoint, option);
}
void OpalTransportAddress::SetInternalTransport(WORD port, const char * proto)
{
transport = NULL;
if (IsEmpty())
return;
PINDEX dollar = Find('$');
if (dollar == P_MAX_INDEX) {
PString prefix(proto == NULL ? TcpPrefix : proto);
if (prefix.Find('$') == P_MAX_INDEX)
prefix += '$';
Splice(prefix, 0);
dollar = prefix.GetLength()-1;
}
PCaselessString type = Left(dollar+1);
// look for known transport types, note that "ip$" == "tcp$"
if ((type == IpPrefix) || (type == TcpPrefix))
transport = &internalTCPTransport;
else if (type == UdpPrefix)
transport = &internalUDPTransport;
else
return;
if (port != 0 && Find(':', dollar) == P_MAX_INDEX)
sprintf(":%u", port);
}
/////////////////////////////////////////////////////////////////
void OpalTransportAddressArray::AppendString(const char * str)
{
AppendAddress(OpalTransportAddress(str));
}
void OpalTransportAddressArray::AppendString(const PString & str)
{
AppendAddress(OpalTransportAddress(str));
}
void OpalTransportAddressArray::AppendAddress(const OpalTransportAddress & addr)
{
if (!addr)
Append(new OpalTransportAddress(addr));
}
void OpalTransportAddressArray::AppendStringCollection(const PCollection & coll)
{
for (PINDEX i = 0; i < coll.GetSize(); i++) {
PObject * obj = coll.GetAt(i);
if (obj != NULL && PIsDescendant(obj, PString))
AppendAddress(OpalTransportAddress(*(PString *)obj));
}
}
/////////////////////////////////////////////////////////////////
PString OpalInternalTransport::GetHostName(const OpalTransportAddress & address) const
{
// skip transport identifier
PINDEX pos = address.Find('$');
if (pos == P_MAX_INDEX)
return PString();
return address.Mid(pos+1);
}
BOOL OpalInternalTransport::GetIpAndPort(const OpalTransportAddress &,
PIPSocket::Address &,
WORD &) const
{
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
static BOOL SplitAddress(const PString & addr, PString & host, PString & service)
{
// skip transport identifier
PINDEX dollar = addr.Find('$');
if (dollar == P_MAX_INDEX)
return FALSE;
PINDEX lastChar = addr.GetLength()-1;
if (addr[lastChar] == '+')
lastChar--;
PINDEX bracket = addr.FindLast(']');
if (bracket == P_MAX_INDEX)
bracket = 0;
PINDEX colon = addr.Find(':', bracket);
if (colon == P_MAX_INDEX)
host = addr(dollar+1, lastChar);
else {
host = addr(dollar+1, colon-1);
service = addr(colon+1, lastChar);
}
return TRUE;
}
PString OpalInternalIPTransport::GetHostName(const OpalTransportAddress & address) const
{
PString host, service;
if (!SplitAddress(address, host, service))
return address;
PIPSocket::Address ip;
if (PIPSocket::GetHostAddress(host, ip))
return ip.AsString();
return host;
}
BOOL OpalInternalIPTransport::GetIpAndPort(const OpalTransportAddress & address,
PIPSocket::Address & ip,
WORD & port) const
{
PString host, service;
if (!SplitAddress(address, host, service))
return FALSE;
if (host.IsEmpty()) {
PTRACE(2, "Opal\tIllegal IP transport address: \"" << address << '"');
return FALSE;
}
if (service == "*")
port = 0;
else {
if (!service) {
PString proto = address.Left(address.Find('$'));
if (proto *= "ip")
proto = "tcp";
port = PIPSocket::GetPortByService(proto, service);
}
if (port == 0) {
PTRACE(2, "Opal\tIllegal IP transport port/service: \"" << address << '"');
return FALSE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -