📄 transports.cxx
字号:
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 + -