1 /*
2  * transports.cxx
3  *
4  * H.323 transports handler
5  *
6  * H323Plus Library
7  *
8  * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Open H323 Library.
21  *
22  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23  *
24  * Portions of this code were written with the assisance of funding from
25  * Vovida Networks, Inc. http://www.vovida.com.
26  *
27  * Contributor(s): ______________________________________.
28  *
29  * $Id$
30  *
31  */
32 
33 #include <ptlib.h>
34 
35 #ifdef __GNUC__
36 #pragma implementation "transports.h"
37 #endif
38 
39 #include "transports.h"
40 
41 #include "h323pdu.h"
42 #include "h323ep.h"
43 #include "gkclient.h"
44 
45 #ifdef P_STUN
46 #include <ptclib/pstun.h>
47  #ifdef _MSC_VER
48   #pragma warning(disable : 4701)  // initialisation warning
49  #endif
50 #endif
51 
52 #ifdef H323_TLS
53 #include <openssl/opensslv.h>
54 #include <openssl/ssl.h>
55 #include <openssl/err.h>
56 #endif
57 
58 // TCP KeepAlive
59 static int KeepAliveInterval = 19;
60 
61 class H225TransportThread : public PThread
62 {
63   PCLASSINFO(H225TransportThread, PThread)
64 
65   public:
66     H225TransportThread(H323EndPoint & endpoint, H323Transport * transport);
67 
68     ~H225TransportThread();
69 
70     void ConnectionEstablished(PBoolean keepAlive);
71 
72     void EnableKeepAlive();
73 
74   protected:
75     void Main();
76 
77     H323Transport * transport;
78 
79     PDECLARE_NOTIFIER(PTimer, H225TransportThread, KeepAlive);
80     PTimer    m_keepAlive;
81     PBoolean useKeepAlive;
82 };
83 
84 
85 class H245TransportThread : public PThread
86 {
87   PCLASSINFO(H245TransportThread, PThread)
88 
89   public:
90     H245TransportThread(H323EndPoint & endpoint,
91                         H323Connection & connection,
92                         H323Transport & transport);
93 
94     ~H245TransportThread();
95 
96   protected:
97     void Main();
98 
99     H323Connection & connection;
100     H323Transport  & transport;
101 #ifdef H323_SIGNAL_AGGREGATE
102     PBoolean useAggregator;
103 #endif
104 
105     PDECLARE_NOTIFIER(PTimer, H245TransportThread, KeepAlive);
106     PTimer    m_keepAlive;
107 };
108 
109 
110 #define new PNEW
111 
112 
113 /////////////////////////////////////////////////////////////////////////////
114 
H225TransportThread(H323EndPoint & ep,H323Transport * t)115 H225TransportThread::H225TransportThread(H323EndPoint & ep, H323Transport * t)
116   : PThread(ep.GetSignallingThreadStackSize(),
117             AutoDeleteThread,
118             NormalPriority,
119             "H225 Answer:%0x"),
120     transport(t)
121 {
122   useKeepAlive = ep.EnableH225KeepAlive();
123   Resume();
124 }
125 
126 
~H225TransportThread()127 H225TransportThread::~H225TransportThread()
128 {
129     if (useKeepAlive)
130        m_keepAlive.Stop();
131 }
132 
ConnectionEstablished(PBoolean keepAlive)133 void H225TransportThread::ConnectionEstablished(PBoolean keepAlive)
134 {
135     if (useKeepAlive || keepAlive)
136         EnableKeepAlive();
137 }
138 
EnableKeepAlive()139 void H225TransportThread::EnableKeepAlive()
140 {
141     if (!m_keepAlive.IsRunning()) {
142         PTRACE(3, "H225\tStarted KeepAlive");
143         m_keepAlive.SetNotifier(PCREATE_NOTIFIER(KeepAlive));
144         m_keepAlive.RunContinuous(KeepAliveInterval * 1000);
145     }
146 }
147 
Main()148 void H225TransportThread::Main()
149 {
150   PTRACE(3, "H225\tStarted incoming call thread");
151 
152   if (!transport->HandleFirstSignallingChannelPDU(this))
153     delete transport;
154 }
155 
156 
KeepAlive(PTimer &,H323_INT)157 void H225TransportThread::KeepAlive(PTimer &,  H323_INT)
158 {
159   // Send empty RFC1006 TPKT
160   BYTE tpkt[4];
161   tpkt[0] = 3;  // Version 3
162   tpkt[1] = 0;
163 
164   PINDEX len = sizeof(tpkt);
165   tpkt[2] = (BYTE)(len >> 8);
166   tpkt[3] = (BYTE)len;
167 
168   PTRACE(5, "H225\tSending KeepAlive TPKT packet");
169 
170   if (transport)
171      transport->Write(tpkt, len);
172 }
173 
174 /////////////////////////////////////////////////////////////////////////////
175 
H245TransportThread(H323EndPoint & endpoint,H323Connection & c,H323Transport & t)176 H245TransportThread::H245TransportThread(H323EndPoint & endpoint,
177                                          H323Connection & c,
178                                          H323Transport & t)
179   : PThread(endpoint.GetSignallingThreadStackSize(),
180             NoAutoDeleteThread,
181             NormalPriority,
182             "H245:%0x"),
183     connection(c),
184     transport(t)
185 {
186 #ifdef H323_SIGNAL_AGGREGATE
187   useAggregator = endpoint.GetSignallingAggregator() != NULL;
188   if (!useAggregator)
189 #endif
190   {
191     transport.AttachThread(this);
192     if (endpoint.EnableH245KeepAlive()) {
193       m_keepAlive.SetNotifier(PCREATE_NOTIFIER(KeepAlive));
194       m_keepAlive.RunContinuous(KeepAliveInterval * 1000);
195     }
196   }
197   Resume();
198 }
199 
200 
~H245TransportThread()201 H245TransportThread::~H245TransportThread()
202 {
203   m_keepAlive.Stop();
204 }
205 
206 
Main()207 void H245TransportThread::Main()
208 {
209   PTRACE(3, "H245\tStarted thread");
210 
211   if (transport.AcceptControlChannel(connection)) {
212 #ifdef H323_SIGNAL_AGGREGATE
213     // if the endpoint is using signalling aggregation, we need to add this connection
214     // to the signalling aggregator.
215     if (useAggregator) {
216       connection.AggregateControlChannel(&transport);
217       SetAutoDelete(AutoDeleteThread);
218       return;
219     }
220 #endif
221 
222     connection.HandleControlChannel();
223   }
224 }
225 
226 
KeepAlive(PTimer &,H323_INT)227 void H245TransportThread::KeepAlive(PTimer &,  H323_INT)
228 {
229   // Send empty RFC1006 TPKT
230   BYTE tpkt[4];
231   tpkt[0] = 3;  // Version 3
232   tpkt[1] = 0;
233 
234   PINDEX len = sizeof(tpkt);
235   tpkt[2] = (BYTE)(len >> 8);
236   tpkt[3] = (BYTE)len;
237 
238   PTRACE(5, "H245\tSending KeepAlive TPKT packet");
239 
240   // TODO: check for error and consult connection.HandleControlChannelFailure() and disconnect or continue
241   // Write() seems to always return TRUE
242   transport.Write(tpkt, len);
243 }
244 
245 
246 /////////////////////////////////////////////////////////////////////////////
247 
248 static const char IpPrefix[] = "ip$";
249 
H323TransportAddress(const char * cstr)250 H323TransportAddress::H323TransportAddress(const char * cstr)
251   : PString(cstr), m_version(4), m_tls(false)
252 {
253   Validate();
254 }
255 
256 
H323TransportAddress(const PString & str)257 H323TransportAddress::H323TransportAddress(const PString & str)
258   : PString(str), m_version(4), m_tls(false)
259 {
260   Validate();
261 }
262 
263 
BuildIP(const PIPSocket::Address & ip,unsigned port)264 static PString BuildIP(const PIPSocket::Address & ip, unsigned port)
265 {
266   PStringStream str;
267 
268   str << IpPrefix;
269 
270   if (ip.IsAny() || !ip.IsValid())
271     str << '*';
272   else
273 #ifdef H323_IPV6
274   if (ip.GetVersion() == 6)
275     str << '[' << ip << ']';
276   else
277 #endif
278     str << ip;
279 
280   if (port != 0)
281     str << ':' << port;
282 
283   return str;
284 }
285 
286 
H323TransportAddress(const H225_TransportAddress & transport)287 H323TransportAddress::H323TransportAddress(const H225_TransportAddress & transport)
288 : m_version(4)
289 {
290   m_tls = false;
291   switch (transport.GetTag()) {
292     case H225_TransportAddress::e_ipAddress :
293     {
294       const H225_TransportAddress_ipAddress & ip = transport;
295       *this = BuildIP(PIPSocket::Address(ip.m_ip.GetSize(), ip.m_ip.GetValue()), ip.m_port);
296       m_version = 4;
297       break;
298     }
299 #ifdef H323_IPV6
300     case H225_TransportAddress::e_ip6Address :
301     {
302       const H225_TransportAddress_ip6Address & ip = transport;
303       *this = BuildIP(PIPSocket::Address(ip.m_ip.GetSize(), ip.m_ip.GetValue()), ip.m_port);
304       m_version = 6;
305       break;
306     }
307 #endif
308   }
309 }
310 
311 
H323TransportAddress(const H245_TransportAddress & transport)312 H323TransportAddress::H323TransportAddress(const H245_TransportAddress & transport)
313 : m_version(4)
314 {
315   m_tls = false;
316   switch (transport.GetTag()) {
317     case H245_TransportAddress::e_unicastAddress :
318     {
319       const H245_UnicastAddress & unicast = transport;
320       switch (unicast.GetTag()) {
321         case H245_UnicastAddress::e_iPAddress :
322         {
323           const H245_UnicastAddress_iPAddress & ip = unicast;
324           *this = BuildIP(PIPSocket::Address(ip.m_network.GetSize(), ip.m_network.GetValue()), ip.m_tsapIdentifier);
325           m_version = 4;
326           break;
327         }
328 #ifdef H323_IPV6
329         case H245_UnicastAddress::e_iP6Address :
330         {
331           const H245_UnicastAddress_iP6Address & ip = unicast;
332           *this = BuildIP(PIPSocket::Address(ip.m_network.GetSize(), ip.m_network.GetValue()), ip.m_tsapIdentifier);
333           m_version = 6;
334           break;
335         }
336 #endif
337         default:
338             break;
339       }
340     }
341     default:
342         break;
343   }
344 }
345 
346 
H323TransportAddress(const PIPSocket::Address & ip,WORD port)347 H323TransportAddress::H323TransportAddress(const PIPSocket::Address & ip, WORD port)
348 {
349    m_tls = false;
350 #ifdef H323_IPV6
351    m_version = ip.GetVersion();
352 #else
353    m_version = 4;
354 #endif
355   *this = BuildIP(ip, port);
356 }
357 
358 
Validate()359 void H323TransportAddress::Validate()
360 {
361   if (IsEmpty())
362     return;
363 
364   if (Find(']') != P_MAX_INDEX)
365      m_version = 6;
366   else
367      m_version = 4;
368 
369   if (Find('$') == P_MAX_INDEX) {
370     Splice(IpPrefix, 0, 0);
371 #ifdef H323_IPV6
372     if (PIPSocket::GetDefaultIpAddressFamily() == AF_INET6) {
373       // If a DNS record then detect the version of the DNS record.
374       PIPSocket::Address ip;
375       WORD port = H323EndPoint::DefaultTcpPort;
376       if (GetIpAndPort(ip, port))
377          m_version = ip.GetVersion();
378     }
379 #endif
380     return;
381   }
382 
383   if (strncmp(theArray, IpPrefix, 3) == 0) {
384     return;
385   }
386 
387   *this = PString();
388 }
389 
390 
SetPDU(H225_TransportAddress & pdu) const391 PBoolean H323TransportAddress::SetPDU(H225_TransportAddress & pdu) const
392 {
393   PIPSocket::Address ip;
394   WORD port = H323EndPoint::DefaultTcpPort;
395   if (GetIpAndPort(ip, port)) {
396 #ifdef H323_IPV6
397     if (ip.GetVersion() == 6) {
398       pdu.SetTag(H225_TransportAddress::e_ip6Address);
399       H225_TransportAddress_ip6Address & addr = pdu;
400       for (PINDEX i = 0; i < ip.GetSize(); i++)
401         addr.m_ip[i] = ip[i];
402       addr.m_port = port;
403       return TRUE;
404     }
405 #endif
406 
407     pdu.SetTag(H225_TransportAddress::e_ipAddress);
408     H225_TransportAddress_ipAddress & addr = pdu;
409     for (PINDEX i = 0; i < 4; i++)
410       addr.m_ip[i] = ip[i];
411     addr.m_port = port;
412     return TRUE;
413   }
414 
415   return FALSE;
416 }
417 
418 
SetPDU(H245_TransportAddress & pdu) const419 PBoolean H323TransportAddress::SetPDU(H245_TransportAddress & pdu) const
420 {
421   PIPSocket::Address ip;
422   WORD port = 0;
423   if (GetIpAndPort(ip, port)) {
424     pdu.SetTag(H245_TransportAddress::e_unicastAddress);
425 
426     H245_UnicastAddress & unicast = pdu;
427 
428 #ifdef H323_IPV6
429     if (ip.GetVersion() == 6) {
430       unicast.SetTag(H245_UnicastAddress::e_iP6Address);
431       H245_UnicastAddress_iP6Address & addr = unicast;
432       for (PINDEX i = 0; i < ip.GetSize(); i++)
433         addr.m_network[i] = ip[i];
434       addr.m_tsapIdentifier = port;
435       return TRUE;
436     }
437 #endif
438 
439     unicast.SetTag(H245_UnicastAddress::e_iPAddress);
440     H245_UnicastAddress_iPAddress & addr = unicast;
441     for (PINDEX i = 0; i < 4; i++)
442       addr.m_network[i] = ip[i];
443     addr.m_tsapIdentifier = port;
444     return TRUE;
445   }
446 
447   return FALSE;
448 }
449 
450 
IsEquivalent(const H323TransportAddress & address)451 PBoolean H323TransportAddress::IsEquivalent(const H323TransportAddress & address)
452 {
453   if (*this == address)
454     return TRUE;
455 
456   if (IsEmpty() || address.IsEmpty())
457     return FALSE;
458 
459   PIPSocket::Address ip1, ip2;
460   WORD port1 = 65535, port2 = 65535;
461   return GetIpAndPort(ip1, port1) &&
462          address.GetIpAndPort(ip2, port2) &&
463          (ip1.IsAny() || ip2.IsAny() || ip1 == ip2) &&
464          (port1 == 65535 || port2 == 65535 || port1 == port2);
465 }
466 
467 
GetIpAddress(PIPSocket::Address & ip) const468 PBoolean H323TransportAddress::GetIpAddress(PIPSocket::Address & ip) const
469 {
470   WORD dummy = 65535;
471   return GetIpAndPort(ip, dummy);
472 }
473 
GetPort() const474 WORD H323TransportAddress::GetPort() const
475 {
476   WORD port = 65535;
477   PIPSocket::Address ip;
478   GetIpAndPort(ip, port);
479   return port;
480 }
481 
SplitAddress(const PString & addr,PString & host,PString & service)482 static PBoolean SplitAddress(const PString & addr, PString & host, PString & service)
483 {
484   if (strncmp(addr, IpPrefix, 3) != 0) {
485     PTRACE(2, "H323\tUse of non IP transport address: \"" << addr << '"');
486     return FALSE;
487   }
488 
489   PINDEX lastChar = addr.GetLength()-1;
490   if (addr[lastChar] == '+')
491     lastChar--;
492 
493   PINDEX bracket = addr.FindLast(']');
494   if (bracket == P_MAX_INDEX)
495     bracket = 0;
496 
497   PINDEX colon = addr.Find(':', bracket);
498   if (colon == P_MAX_INDEX)
499     host = addr(3, lastChar);
500   else {
501     host = addr.Mid(3, colon-3);
502     service = addr.Mid(colon+1, lastChar);
503   }
504 
505   return TRUE;
506 }
507 
508 
GetIpAndPort(PIPSocket::Address & ip,WORD & port,const char * proto) const509 PBoolean H323TransportAddress::GetIpAndPort(PIPSocket::Address & ip,
510                                         WORD & port,
511                                         const char * proto) const
512 {
513   PString host, service;
514   if (!SplitAddress(*this, host, service))
515     return FALSE;
516 
517   if (host.IsEmpty()) {
518     PTRACE(2, "H323\tIllegal IP transport address: \"" << *this << '"');
519     return FALSE;
520   }
521 
522   if (service == "*")
523     port = 0;
524   else {
525     if (!service)
526       port = PIPSocket::GetPortByService(proto, service);
527     if (port == 0) {
528       PTRACE(2, "H323\tIllegal IP transport port/service: \"" << *this << '"');
529       return FALSE;
530     }
531   }
532 
533   if (host == "*") {
534     ip = PIPSocket::GetDefaultIpAny();
535     return TRUE;
536   }
537 
538   if (PIPSocket::GetHostAddress(host, ip))
539      return TRUE;
540 
541 #ifdef H323_IPV6
542   // This is really horrible
543   // You first attempt to get an IPv6 (default) record then if the fails
544   // Set the defaultIPAddress family to v4, Clear the cache then resolve the address via IPv4.
545   // This really needs to be cleaned up in PTLIB  - SH
546   if (PIPSocket::GetDefaultIpAddressFamily() == AF_INET6) {
547       PTRACE(3, "H323\tCould not resolve IPv6 Address for : \"" << host << '"' << " Trying IPv4:");
548       PIPSocket::SetDefaultIpAddressFamilyV4();
549       PIPSocket::ClearNameCache();  // clear the IPv6 record
550       bool success = PIPSocket::GetHostAddress(host, ip);
551       PIPSocket::SetDefaultIpAddressFamilyV6();
552       if (success)
553           return TRUE;
554   }
555 #endif
556 
557   PTRACE(1, "H323\tCould not find host : \"" << host << '"');
558   return FALSE;
559 }
560 
GetIpVersion() const561 unsigned H323TransportAddress::GetIpVersion() const
562 {
563     return m_version;
564 }
565 
566 
GetHostName() const567 PString H323TransportAddress::GetHostName() const
568 {
569   PString host, service;
570   if (!SplitAddress(*this, host, service))
571     return *this;
572 
573   PIPSocket::Address ip;
574   if (PIPSocket::GetHostAddress(host, ip))
575     return ip.AsString();
576 
577   return host;
578 }
579 
580 
CreateListener(H323EndPoint & endpoint) const581 H323Listener * H323TransportAddress::CreateListener(H323EndPoint & endpoint) const
582 {
583   /*Have transport type name, create the transport object. Hard coded at the
584     moment but would like to add some sort of "registration" of transport
585     classes so new transports can be added without changing this source file
586     every time. As we have one transport type at the moment and may never
587     actually have another, we hard code it for now.
588    */
589 
590 #ifdef H323_TLS
591   PBoolean useTLS = (endpoint.GetTransportSecurity()->IsTLSEnabled() &&
592                     (m_tls || GetPort() == H323EndPoint::DefaultTLSPort));
593 #endif
594 
595   PIPSocket::Address ip;
596   WORD port = H323EndPoint::DefaultTcpPort;
597   if (GetIpAndPort(ip, port)) {
598 #ifdef H323_TLS
599       if (useTLS)
600         return new H323ListenerTLS(endpoint, ip, port, theArray[GetLength()-1] != '+');
601       else
602 #endif
603         return new H323ListenerTCP(endpoint, ip, port, theArray[GetLength()-1] != '+');
604   }
605 
606   return NULL;
607 }
608 
609 
CreateCompatibleListener(H323EndPoint & endpoint) const610 H323Listener * H323TransportAddress::CreateCompatibleListener(H323EndPoint & endpoint) const
611 {
612   /*Have transport type name, create the transport object. Hard coded at the
613     moment but would like to add some sort of "registration" of transport
614     classes so new transports can be added without changing this source file
615     every time. As we have one transport type at the moment and may never
616     actually have another, we hard code it for now.
617    */
618 
619 #ifdef H323_TLS
620   PBoolean useTLS = (endpoint.GetTransportSecurity()->IsTLSEnabled() &&
621                     (m_tls || GetPort() == H323EndPoint::DefaultTLSPort));
622 #endif
623 
624   PIPSocket::Address ip;
625   WORD port = H323EndPoint::DefaultTcpPort;
626   if (GetIpAndPort(ip, port)) {
627 #ifdef H323_TLS
628      if (useTLS)
629         return new H323ListenerTLS(endpoint, ip, 0);
630      else
631 #endif
632         return new H323ListenerTCP(endpoint, ip, 0);
633   }
634 
635   return NULL;
636 }
637 
SetTLS(PBoolean tls)638 void H323TransportAddress::SetTLS(PBoolean tls)
639 {
640     m_tls = tls;
641 }
642 
CreateTransport(H323EndPoint & endpoint) const643 H323Transport * H323TransportAddress::CreateTransport(H323EndPoint & endpoint) const
644 {
645   /*Have transport type name, create the transport object. Hard coded at the
646     moment but would like to add some sort of "registration" of transport
647     classes so new transports can be added without changing this source file
648     every time. As we have one transport type at the moment and may never
649     actually have another, we hard code it for now.
650    */
651 
652     if (strncmp(theArray, IpPrefix, 3) == 0) {
653         H323TransportSecurity security;
654         PBoolean useTLS = (endpoint.GetTransportSecurity()->IsTLSEnabled() &&
655                           (m_tls || GetPort() == H323EndPoint::DefaultTLSPort));
656         security.EnableTLS(useTLS);
657         H323TransportTCP * transport = new H323TransportTCP(endpoint, PIPSocket::Address::GetAny(m_version));
658         transport->InitialiseSecurity(&security);
659         return transport;
660     }
661     return NULL;
662 }
663 
664 
H323GetInterfaceAddresses(const H323ListenerList & listeners,PBoolean excludeLocalHost,H323Transport * associatedTransport)665 H323TransportAddressArray H323GetInterfaceAddresses(const H323ListenerList & listeners,
666                                                     PBoolean excludeLocalHost,
667                                                     H323Transport * associatedTransport)
668 {
669   H323TransportAddressArray interfaceAddresses;
670   H323TransportAddress rasaddr(associatedTransport->GetRemoteAddress());
671 
672   PINDEX i;
673   for (i = 0; i < listeners.GetSize(); i++) {
674       H323TransportAddress sigaddr(listeners[i].GetTransportAddress());
675       if (sigaddr.GetIpVersion() == rasaddr.GetIpVersion()) {
676         H323TransportAddressArray newAddrs = H323GetInterfaceAddresses(sigaddr, excludeLocalHost, associatedTransport);
677         if (listeners[i].GetSecurity() == H323TransportSecurity::e_unsecure) {
678             PINDEX size  = interfaceAddresses.GetSize();
679             PINDEX nsize = newAddrs.GetSize();
680             interfaceAddresses.SetSize(size + nsize);
681             PINDEX j;
682             for (j = 0; j < nsize; j++)
683               interfaceAddresses.SetAt(size + j, new H323TransportAddress(newAddrs[j]));
684         } else if (newAddrs.GetSize() > 0) {
685             listeners[i].SetTransportAddress(newAddrs[0]);  // Set the local address for TLS/IPSEC
686         }
687       }
688   }
689   return interfaceAddresses;
690 }
691 
692 
H323GetInterfaceAddresses(const H323TransportAddress & addr,PBoolean excludeLocalHost,H323Transport * associatedTransport)693 H323TransportAddressArray H323GetInterfaceAddresses(const H323TransportAddress & addr,
694                                                     PBoolean excludeLocalHost,
695                                                     H323Transport * associatedTransport)
696 {
697   PIPSocket::Address ip;
698   WORD port = 0;
699   if (!addr.GetIpAndPort(ip, port) || !ip.IsAny())
700     return addr;
701 
702   PIPSocket::InterfaceTable interfaces;
703   if (!PIPSocket::GetInterfaceTable(interfaces))
704     return addr;
705 
706   if (interfaces.GetSize() == 1)
707     return H323TransportAddress(interfaces[0].GetAddress(), port);
708 
709   PINDEX i;
710   H323TransportAddressArray interfaceAddresses;
711   PIPSocket::Address firstAddress(0);
712 
713   if (associatedTransport != NULL) {
714     if (associatedTransport->GetLocalAddress().GetIpAddress(firstAddress)) {
715       for (i = 0; i < interfaces.GetSize(); i++) {
716         PIPSocket::Address ip = interfaces[i].GetAddress();
717         if (ip == firstAddress)
718           interfaceAddresses.Append(new H323TransportAddress(ip, port));
719       }
720     }
721   }
722 
723   for (i = 0; i < interfaces.GetSize(); i++) {
724     PIPSocket::Address ip = interfaces[i].GetAddress();
725     if (ip != firstAddress && !(excludeLocalHost && ip.IsLoopback()))
726       interfaceAddresses.Append(new H323TransportAddress(ip, port));
727   }
728 
729   return interfaceAddresses;
730 }
731 
732 
H323SetTransportAddresses(const H323Transport & associatedTransport,const H323TransportAddressArray & addresses,H225_ArrayOf_TransportAddress & pdu)733 void H323SetTransportAddresses(const H323Transport & associatedTransport,
734                                const H323TransportAddressArray & addresses,
735                                H225_ArrayOf_TransportAddress & pdu)
736 {
737   for (PINDEX i = 0; i < addresses.GetSize(); i++) {
738     H323TransportAddress addr = addresses[i];
739 
740     PIPSocket::Address ip;
741     WORD port = 0;
742     if (addr.GetIpAndPort(ip, port)) {
743       PIPSocket::Address remoteIP;
744       if (associatedTransport.GetRemoteAddress().GetIpAddress(remoteIP)) {
745         associatedTransport.GetEndPoint().InternalTranslateTCPAddress(ip, remoteIP);
746         associatedTransport.GetEndPoint().TranslateTCPPort(port,remoteIP);
747         addr = H323TransportAddress(ip, port);
748       }
749     }
750 
751     if (addresses.GetSize() > 1 && ip.IsLoopback())
752       continue;
753 
754     PTRACE(4, "TCP\tAppending H.225 transport " << addr
755            << " using associated transport " << associatedTransport);
756 
757     H225_TransportAddress pduAddr;
758     addr.SetPDU(pduAddr);
759 
760     PINDEX lastPos = pdu.GetSize();
761 
762     // Check for already have had that address.
763     PINDEX j;
764     for (j = 0; j < lastPos; j++) {
765       if (pdu[j] == pduAddr)
766         break;
767     }
768 
769     if (j >= lastPos) {
770       // Put new listener into array
771       pdu.SetSize(lastPos+1);
772       pdu[lastPos] = pduAddr;
773     }
774   }
775 }
776 
777 
778 /////////////////////////////////////////////////////////////////////////////
779 
H323TransportAddressArray(const H225_ArrayOf_TransportAddress & addresses)780 H323TransportAddressArray::H323TransportAddressArray(const H225_ArrayOf_TransportAddress & addresses)
781 {
782   for (PINDEX i = 0; i < addresses.GetSize(); i++)
783     AppendAddress(H323TransportAddress(addresses[i]));
784 }
785 
786 
AppendString(const char * str)787 void H323TransportAddressArray::AppendString(const char * str)
788 {
789   AppendAddress(H323TransportAddress(str));
790 }
791 
792 
AppendString(const PString & str)793 void H323TransportAddressArray::AppendString(const PString & str)
794 {
795   AppendAddress(H323TransportAddress(str));
796 }
797 
798 
AppendAddress(const H323TransportAddress & addr)799 void H323TransportAddressArray::AppendAddress(const H323TransportAddress & addr)
800 {
801   if (!addr)
802     Append(new H323TransportAddress(addr));
803 }
804 
805 
AppendStringCollection(const PCollection & coll)806 void H323TransportAddressArray::AppendStringCollection(const PCollection & coll)
807 {
808   for (PINDEX i = 0; i < coll.GetSize(); i++) {
809     PObject * obj = coll.GetAt(i);
810     if (obj != NULL && PIsDescendant(obj, PString))
811       AppendAddress(H323TransportAddress(*(PString *)obj));
812   }
813 }
814 
815 /////////////////////////////////////////////////////////////////////////////
816 
817 #define CHECKBIT(var,pos) (var & (1<<pos))
818 #define SETBIT(var,pos)  var |= 1<<pos;
819 #define CLEARBIT(var,pos) var &= ~(1 << pos);
820 
H323TransportSecurity(H323EndPoint * ep)821 H323TransportSecurity::H323TransportSecurity(H323EndPoint * ep)
822 :  m_securityMask(0), m_policyMask(0)
823 {
824     if (ep)
825         m_policyMask = ep->GetTransportSecurity()->GetMediaPolicy();
826 }
827 
MethodAsString(Method meth)828 PString H323TransportSecurity::MethodAsString(Method meth)
829 {
830     switch (meth) {
831         case H323TransportSecurity::e_unsecure: return "TCP";
832         case H323TransportSecurity::e_tls: return "TLS";
833         case H323TransportSecurity::e_ipsec: return "IPSec";
834     };
835     return "?";
836 }
837 
PolicyAsString(Policy policy)838 PString H323TransportSecurity::PolicyAsString(Policy policy)
839 {
840     switch (policy) {
841         case H323TransportSecurity::e_nopolicy: return "No Transport required for Media Encryption";
842         case H323TransportSecurity::e_reqTLSMediaEncHigh: return "Signal security required for High Media Encryption";
843         case H323TransportSecurity::e_reqTLSMediaEncAll: return "Signal security required for ALL Media Encryption";
844     };
845     return "?";
846 }
847 
HasSecurity()848 PBoolean H323TransportSecurity::HasSecurity()
849 {
850     return (m_securityMask != 0);
851 }
852 
EnableTLS(PBoolean enable)853 void H323TransportSecurity::EnableTLS(PBoolean enable)
854 {
855     if (enable)
856         SETBIT(m_securityMask,e_tls)
857     else
858         CLEARBIT(m_securityMask,e_tls)
859 }
860 
IsTLSEnabled() const861 PBoolean H323TransportSecurity::IsTLSEnabled() const
862 {
863     return CHECKBIT(m_securityMask,e_tls);
864 }
865 
SetRemoteTLSAddress(const H323TransportAddress & address)866 void H323TransportSecurity::SetRemoteTLSAddress(const H323TransportAddress & address)
867 {
868     m_remoteTLSAddress = address;
869 }
870 
GetRemoteTLSAddress()871 H323TransportAddress H323TransportSecurity::GetRemoteTLSAddress()
872 {
873     return m_remoteTLSAddress;
874 }
875 
EnableIPSec(PBoolean enable)876 void H323TransportSecurity::EnableIPSec(PBoolean enable)
877 {
878 #if 0 // Not supported yet - SH
879     if (enable)
880         SETBIT(m_securityMask,e_ipsec)
881     else
882         CLEARBIT(m_securityMask,e_ipsec)
883 #endif
884 }
885 
IsIPSecEnabled()886 PBoolean H323TransportSecurity::IsIPSecEnabled()
887 {
888     return CHECKBIT(m_securityMask,e_ipsec);
889 }
890 
SetMediaPolicy(H323TransportSecurity::Policy policy)891 void H323TransportSecurity::SetMediaPolicy(H323TransportSecurity::Policy policy)
892 {
893     m_policyMask = policy;
894 }
895 
GetMediaPolicy() const896 H323TransportSecurity::Policy H323TransportSecurity::GetMediaPolicy() const
897 {
898     return (Policy)m_policyMask;
899 }
900 
Reset()901 void H323TransportSecurity::Reset()
902 {
903     m_securityMask = 0;
904     m_policyMask = 0;
905     m_remoteTLSAddress = H323TransportAddress();
906 }
907 
908 /////////////////////////////////////////////////////////////////////////////
909 
H323Listener(H323EndPoint & end,H323TransportSecurity::Method security)910 H323Listener::H323Listener(H323EndPoint & end, H323TransportSecurity::Method security)
911   : PThread(end.GetListenerThreadStackSize(),
912             NoAutoDeleteThread,
913             NormalPriority,
914             "H323" + ((security == H323TransportSecurity::e_tls) ? PString("TLS") : PString("")) + "Listener:%0x"),
915      endpoint(end), m_security(security)
916 {
917 }
918 
919 
PrintOn(ostream & strm) const920 void H323Listener::PrintOn(ostream & strm) const
921 {
922   strm << "Listener " << TypeAsString() << '[' << GetTransportAddress() << ']';
923 }
924 
GetSecurity()925 H323TransportSecurity::Method H323Listener::GetSecurity()
926 {
927     return m_security;
928 }
929 
TypeAsString() const930 PString H323Listener::TypeAsString() const
931 {
932     return H323TransportSecurity::MethodAsString(m_security);
933 }
934 
935 
936 /////////////////////////////////////////////////////////////////////////////
937 
GetListener() const938 H323Listener * H323ListenerList::GetListener() const
939 {
940     for (PINDEX i = 0; i < this->GetSize(); i++) {
941         if ((*this)[i].GetSecurity() == H323TransportSecurity::e_unsecure)
942             return &((*this)[i]);
943     }
944     return NULL;
945 }
946 
947 #ifdef H323_TLS
GetTLSListener() const948 H323Listener * H323ListenerList::GetTLSListener() const
949 {
950     for (PINDEX i = 0; i < this->GetSize(); i++) {
951         if ((*this)[i].GetSecurity() == H323TransportSecurity::e_tls)
952             return &((*this)[i]);
953     }
954     return NULL;
955 }
956 #endif
957 
958 /////////////////////////////////////////////////////////////////////////////
959 
960 #ifdef H323_TLS
H323Transport(H323EndPoint & end,PSSLContext * _context,PBoolean autoDeleteContext)961 H323Transport::H323Transport(H323EndPoint & end, PSSLContext * _context, PBoolean autoDeleteContext)
962   : PSSLChannel(_context, autoDeleteContext), endpoint(end), m_secured(false), m_established(false)
963 {
964 #else
965 H323Transport::H323Transport(H323EndPoint & end)
966   : endpoint(end), m_secured(false), m_established(false)
967 {
968 #endif
969   thread = NULL;
970   canGetInterface = false;
971 }
972 
973 
974 H323Transport::~H323Transport()
975 {
976   PAssert(thread == NULL, PLogicError);
977 }
978 
979 
980 void H323Transport::PrintOn(ostream & strm) const
981 {
982   strm << "Transport[";
983   H323TransportAddress addr = GetRemoteAddress();
984   if (!addr)
985     strm << "remote=" << addr << ' ';
986   strm << "if=" << GetLocalAddress() << ']';
987 }
988 
989 PBoolean H323Transport::Read(void * buf, PINDEX len)
990 {
991 #ifdef H323_TLS
992     if (m_secured) {
993 #if PTLIB_VER < 2120
994         ssl_st * m_ssl = ssl;
995 #endif
996         PBoolean ret = false;
997         do {
998             ret = PSSLChannel::Read(buf,len);
999             if (!ret) {
1000                 int err = SSL_get_error(m_ssl, ret);
1001                 switch (err) {
1002                     case SSL_ERROR_WANT_READ:
1003                         break;
1004                     default:
1005                         return false;
1006                 }
1007             }
1008         } while (!ret);
1009        return true;
1010     }
1011     else
1012 #endif
1013         return PIndirectChannel::Read(buf,len);
1014 }
1015 
1016 PBoolean H323Transport::Write(const void * buf, PINDEX len)
1017 {
1018 #ifdef H323_TLS
1019     if (m_secured) {
1020 #if PTLIB_VER < 2120
1021         ssl_st * m_ssl = ssl;
1022 #endif
1023         PBoolean ret = false;
1024         do {
1025             ret =  PSSLChannel::Write(buf,len);
1026             if (!ret) {
1027                 int err = SSL_get_error(m_ssl, ret);
1028                 switch (err) {
1029                 case SSL_ERROR_WANT_WRITE:
1030                         break;
1031                     default:
1032                         return false;
1033                 }
1034             }
1035         } while (!ret);
1036        return true;
1037     }
1038     else
1039 #endif
1040         return PIndirectChannel::Write(buf,len);
1041 }
1042 
1043 PBoolean H323Transport::OnSocketOpen()
1044 {
1045     return true;
1046 }
1047 
1048 PBoolean H323Transport::IsOpen() const
1049 {
1050     return PIndirectChannel::IsOpen();
1051 }
1052 
1053 PBoolean H323Transport::IsTransportSecure()
1054 {
1055     return m_secured;
1056 }
1057 
1058 PBoolean H323Transport::OnOpen()
1059 {
1060     return OnSocketOpen();
1061 }
1062 
1063 PBoolean H323Transport::Close()
1064 {
1065   PTRACE(3, "H323\tH323Transport::Close");
1066 
1067   /* Do not use PIndirectChannel::Close() as this deletes the sub-channel
1068      member field crashing the background thread. Just close the base
1069      sub-channel so breaks the threads I/O block.
1070    */
1071   if (IsOpen()) {
1072     channelPointerMutex.StartRead();
1073     GetBaseReadChannel()->Close();
1074     channelPointerMutex.EndRead();
1075   }
1076 
1077   return TRUE;
1078 }
1079 
1080 PBoolean H323Transport::HandleSignallingSocket(H323SignalPDU & pdu)
1081 {
1082   for (;;) {
1083       H323SignalPDU rpdu;
1084       if (!rpdu.Read(*this)) {
1085             return FALSE;
1086       }
1087       else if ((rpdu.GetQ931().GetMessageType() == Q931::InformationMsg) &&
1088               endpoint.OnUnsolicitedInformation(rpdu)) {
1089            // Handle unsolicited Information Message
1090                 ;
1091       }
1092     else {
1093           pdu = rpdu;
1094           return TRUE;
1095       }
1096   }
1097 }
1098 
1099 PBoolean H323Transport::HandleFirstSignallingChannelPDU(PThread * thread)
1100 {
1101   PTRACE(3, "H225\tAwaiting first PDU");
1102   SetReadTimeout(15000); // Await 15 seconds after connect for first byte
1103   H323SignalPDU pdu;
1104 //  if (!pdu.Read(*this)) {
1105   if (!HandleSignallingSocket(pdu)) {
1106     PTRACE(1, "H225\tFailed to get initial Q.931 PDU, connection not started.");
1107     return FALSE;
1108   }
1109 
1110   const Q931 &firstQ931PDU = pdu.GetQ931();
1111   if (firstQ931PDU.GetMessageType() != Q931::SetupMsg) {
1112     PTRACE(1, "H225\tFirst PDU is not a Setup, connection not started.");
1113     return FALSE;
1114   }
1115 
1116   unsigned callReference = firstQ931PDU.GetCallReference();
1117   PTRACE(3, "H225\tIncoming call, first PDU: callReference=" << callReference);
1118 
1119   // Get a new (or old) connection from the endpoint
1120   H323Connection * connection = endpoint.OnIncomingConnection(this, pdu);
1121   if (connection == NULL) {
1122     PTRACE(1, "H225\tEndpoint could not create connection, "
1123               "sending release complete PDU: callRef=" << callReference);
1124 
1125     H323SignalPDU releaseComplete;
1126     Q931 &q931PDU = releaseComplete.GetQ931();
1127     q931PDU.BuildReleaseComplete(callReference, TRUE);
1128     releaseComplete.m_h323_uu_pdu.m_h323_message_body.SetTag(H225_H323_UU_PDU_h323_message_body::e_releaseComplete);
1129 
1130     H225_ReleaseComplete_UUIE &release = releaseComplete.m_h323_uu_pdu.m_h323_message_body;
1131     release.m_protocolIdentifier.SetValue(psprintf("0.0.8.2250.0.%u", H225_PROTOCOL_VERSION));
1132 
1133     H225_Setup_UUIE &setup = pdu.m_h323_uu_pdu.m_h323_message_body;
1134     if (setup.HasOptionalField(H225_Setup_UUIE::e_callIdentifier)) {
1135        release.IncludeOptionalField(H225_Setup_UUIE::e_callIdentifier);
1136        release.m_callIdentifier = setup.m_callIdentifier;
1137     }
1138 
1139     // Set the cause value
1140     q931PDU.SetCause(Q931::TemporaryFailure);
1141 
1142     // Send the PDU
1143     releaseComplete.Write(*this);
1144     return FALSE;
1145   }
1146 
1147   (void)connection->Lock();
1148 
1149   // handle the first PDU
1150   if (connection->HandleSignalPDU(pdu)) {
1151 
1152 #ifdef H323_SIGNAL_AGGREGATE
1153     // if the endpoint is using signalling aggregation, we need to add this connection
1154     // to the signalling aggregator.
1155     if (connection != NULL && endpoint.GetSignallingAggregator() != NULL) {
1156       connection->AggregateSignalChannel(this);
1157       connection->Unlock();
1158       return TRUE;
1159     }
1160 #endif
1161 
1162     // If aggregation is not being used, then this thread is attached to the transport,
1163     // which is in turn attached to the connection so everything from gets cleaned up by the
1164     // H323 cleaner thread from now on. So thread must not auto delete and the "transport"
1165     // variable is not deleted either
1166     PAssert(PIsDescendant(thread, H225TransportThread), PInvalidCast);
1167     PBoolean keepAlive = false;
1168 #ifdef H323_H46018
1169     keepAlive = connection->IsH46019Enabled();
1170 #endif
1171     ((H225TransportThread *)thread)->ConnectionEstablished(keepAlive);
1172     AttachThread(thread);
1173     thread->SetNoAutoDelete();
1174 
1175     connection->Unlock();
1176 
1177     // All subsequent PDU's should wait forever
1178     SetReadTimeout(PMaxTimeInterval);
1179     connection->HandleSignallingChannel();
1180   }
1181   else {
1182     connection->ClearCall(H323Connection::EndedByTransportFail);
1183     connection->Unlock();
1184     PTRACE(1, "H225\tSignal channel stopped on first PDU.");
1185   }
1186 
1187 
1188   return TRUE;
1189 }
1190 
1191 
1192 void H323Transport::StartControlChannel(H323Connection & connection)
1193 {
1194   new H245TransportThread(endpoint, connection, *this);
1195 }
1196 
1197 
1198 void H323Transport::AttachThread(PThread * thrd)
1199 {
1200   PAssert(thread == NULL, PLogicError);
1201   thread = thrd;
1202 }
1203 
1204 
1205 void H323Transport::CleanUpOnTermination()
1206 {
1207   Close();
1208 
1209   if (thread != NULL) {
1210     PTRACE(3, "H323\tH323Transport::CleanUpOnTermination for " << thread->GetThreadName());
1211     PAssert(thread->WaitForTermination(10000), "Transport thread did not terminate");
1212     delete thread;
1213     thread = NULL;
1214   }
1215 }
1216 
1217 PChannel::Errors H323Transport::GetErrorCode(ErrorGroup group) const
1218 {
1219     return PChannel::GetErrorCode(group);
1220 }
1221 
1222 
1223 PBoolean H323Transport::IsCompatibleTransport(const H225_TransportAddress & /*pdu*/) const
1224 {
1225   PAssertAlways(PUnimplementedFunction);
1226   return FALSE;
1227 }
1228 
1229 
1230 void H323Transport::SetUpTransportPDU(H225_TransportAddress & /*pdu*/,
1231                                       PBoolean /*localTsap*/,
1232                                       H323Connection * /*connection*/
1233                                       ) const
1234 {
1235   PAssertAlways(PUnimplementedFunction);
1236 }
1237 
1238 
1239 void H323Transport::SetUpTransportPDU(H245_TransportAddress & /*pdu*/,
1240                                       unsigned /*port*/) const
1241 {
1242   PAssertAlways(PUnimplementedFunction);
1243 }
1244 
1245 
1246 void H323Transport::SetPromiscuous(PromisciousModes /*promiscuous*/)
1247 {
1248 }
1249 
1250 
1251 H323TransportAddress H323Transport::GetLastReceivedAddress() const
1252 {
1253   return GetRemoteAddress();
1254 }
1255 
1256 
1257 H323Transport * H323Transport::CreateControlChannel(H323Connection & /*connection*/)
1258 {
1259   PAssertAlways(PUnimplementedFunction);
1260   return NULL;
1261 }
1262 
1263 
1264 PBoolean H323Transport::AcceptControlChannel(H323Connection & /*connection*/)
1265 {
1266   PAssertAlways(PUnimplementedFunction);
1267   return FALSE;
1268 }
1269 
1270 
1271 PBoolean H323Transport::DiscoverGatekeeper(H323Gatekeeper & /*gk*/,
1272                                        H323RasPDU & /*pdu*/,
1273                                        const H323TransportAddress & /*address*/)
1274 {
1275   PAssertAlways(PUnimplementedFunction);
1276   return FALSE;
1277 }
1278 
1279 
1280 /////////////////////////////////////////////////////////////////////////////
1281 
1282 H323ListenerTCP::H323ListenerTCP(H323EndPoint & end,
1283                                  PIPSocket::Address binding,
1284                                  WORD port,
1285                                  PBoolean exclusive,
1286                                  H323TransportSecurity::Method security)
1287   : H323Listener(end,security),
1288       listener((port == 0) ? (WORD)H323EndPoint::DefaultTcpPort : port),
1289     localAddress(binding)
1290 {
1291   exclusiveListener = exclusive;
1292 }
1293 
1294 
1295 H323ListenerTCP::~H323ListenerTCP()
1296 {
1297   Close();
1298 }
1299 
1300 
1301 PBoolean H323ListenerTCP::Open()
1302 {
1303   if (listener.Listen(localAddress, 100, 0,
1304                       exclusiveListener ? PSocket::AddressIsExclusive
1305                                         : PSocket::CanReuseAddress))
1306     return TRUE;
1307 
1308   PTRACE(1, TypeAsString() << "\tListen on " << localAddress << ':' << listener.GetPort()
1309          << " failed: " << listener.GetErrorText());
1310   return FALSE;
1311 }
1312 
1313 
1314 PBoolean H323ListenerTCP::Close()
1315 {
1316   PBoolean ok = listener.Close();
1317 
1318   PAssert(PThread::Current() != this, PLogicError);
1319 
1320   if (!IsTerminated() && !IsSuspended())
1321     PAssert(WaitForTermination(10000), "Listener thread did not terminate");
1322 
1323   return ok;
1324 }
1325 
1326 H323Transport * H323ListenerTCP::CreateTransport(const PIPSocket::Address & address)
1327 {
1328     H323TransportSecurity m_callSecurity;
1329     H323TransportTCP * transport = new H323TransportTCP(endpoint, address);
1330     transport->InitialiseSecurity(&m_callSecurity);
1331     return transport;
1332 }
1333 
1334 H323Transport * H323ListenerTCP::Accept(const PTimeInterval & timeout)
1335 {
1336   if (!listener.IsOpen())
1337     return NULL;
1338 
1339   listener.SetReadTimeout(timeout); // Wait for remote connect
1340 
1341   PTRACE(4, TypeAsString() << "\tWaiting on socket accept on " << GetTransportAddress());
1342   PTCPSocket * socket = new PTCPSocket;
1343   if (socket->Accept(listener)) {
1344     unsigned m_version = GetTransportAddress().GetIpVersion();
1345     H323Transport * transport = CreateTransport(PIPSocket::Address::GetAny(m_version));
1346     transport->FinaliseSecurity(socket);
1347     if (transport->Open(socket) && transport->SecureAccept()) {
1348         return transport;
1349     }
1350 
1351     PTRACE(1, TypeAsString() << "\tFailed to open transport, connection not started.");
1352     delete transport;
1353     return NULL;
1354   }
1355 
1356   if (socket->GetErrorCode() != PChannel::Interrupted) {
1357     PTRACE(1, TypeAsString() << "\tAccept error:" << socket->GetErrorText());
1358     listener.Close();
1359   }
1360 
1361   delete socket;
1362   return NULL;
1363 }
1364 
1365 
1366 H323TransportAddress H323ListenerTCP::GetTransportAddress() const
1367 {
1368     return H323TransportAddress(localAddress, listener.GetPort());
1369 }
1370 
1371 void H323ListenerTCP::SetTransportAddress(const H323TransportAddress & /*address*/)
1372 {
1373     // Does nothing
1374 }
1375 
1376 PBoolean H323ListenerTCP::SetUpTransportPDU(H245_TransportAddress & pdu,
1377                                         const H323Transport & associatedTransport)
1378 {
1379   if (!localAddress.IsAny())
1380     return GetTransportAddress().SetPDU(pdu);
1381 
1382   PIPSocket::Address addressOfExistingInterface;
1383   if (!associatedTransport.GetLocalAddress().GetIpAddress(addressOfExistingInterface))
1384     return FALSE;
1385 
1386   H323TransportAddress transAddr(addressOfExistingInterface, listener.GetPort());
1387   transAddr.SetPDU(pdu);
1388   return TRUE;
1389 }
1390 
1391 
1392 void H323ListenerTCP::Main()
1393 {
1394   PTRACE(2, TypeAsString() << "\tAwaiting " << TypeAsString() << " connections on port " << listener.GetPort());
1395 
1396   while (listener.IsOpen()) {
1397     H323Transport * transport = Accept(PMaxTimeInterval);
1398     if (transport != NULL)
1399       new H225TransportThread(endpoint, transport);
1400   }
1401 #ifdef P_SSL
1402 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
1403   ERR_remove_thread_state(NULL);
1404 #endif
1405 #endif
1406 }
1407 
1408 /////////////////////////////////////////////////////////////////////////////
1409 
1410 #ifdef H323_TLS
1411 H323ListenerTLS::H323ListenerTLS(H323EndPoint & endpoint, PIPSocket::Address binding, WORD port, PBoolean exclusive)
1412 : H323ListenerTCP(endpoint, binding, port, exclusive, H323TransportSecurity::e_tls)
1413 {
1414 
1415 }
1416 
1417 H323ListenerTLS::~H323ListenerTLS()
1418 {
1419    Close();
1420 }
1421 
1422 H323Transport * H323ListenerTLS::CreateTransport(const PIPSocket::Address & address)
1423 {
1424     H323TransportSecurity m_callSecurity;
1425     m_callSecurity.EnableTLS(true);
1426     H323TransportTCP * transport = new H323TransportTCP(endpoint, address);
1427     transport->InitialiseSecurity(&m_callSecurity);
1428     return transport;
1429 }
1430 
1431 PBoolean H323ListenerTLS::SetUpTransportPDU(H245_TransportAddress & /*pdu*/,
1432                                         const H323Transport & /*associatedTransport*/)
1433 {
1434     return false;
1435 }
1436 
1437 void H323ListenerTLS::SetTransportAddress(const H323TransportAddress & address)
1438 {
1439     address.GetIpAddress(localAddress);
1440 }
1441 #endif
1442 
1443 /////////////////////////////////////////////////////////////////////////////
1444 
1445 #ifdef H323_TLS
1446 H323TransportIP::H323TransportIP(H323EndPoint & end, PIPSocket::Address binding, WORD remPort, PSSLContext * context, PBoolean autoDeleteContext)
1447   : H323Transport(end, context, autoDeleteContext),
1448 #else
1449 H323TransportIP::H323TransportIP(H323EndPoint & end, PIPSocket::Address binding, WORD remPort)
1450   : H323Transport(end),
1451 #endif
1452     localAddress(binding),
1453     remoteAddress(0)
1454 {
1455   localPort = 0;
1456   remotePort = remPort;
1457 }
1458 
1459 
1460 H323TransportAddress H323TransportIP::GetLocalAddress() const
1461 {
1462   return H323TransportAddress(localAddress, localPort);
1463 }
1464 
1465 
1466 H323TransportAddress H323TransportIP::GetRemoteAddress() const
1467 {
1468   return H323TransportAddress(remoteAddress, remotePort);
1469 }
1470 
1471 
1472 PBoolean H323TransportIP::IsCompatibleTransport(const H225_TransportAddress & pdu) const
1473 {
1474   return pdu.GetTag() == H225_TransportAddress::e_ipAddress
1475 #ifdef H323_IPV6
1476             || pdu.GetTag() == H225_TransportAddress::e_ip6Address
1477 #endif
1478          ;
1479 }
1480 
1481 
1482 void H323TransportIP::SetUpTransportPDU(H225_TransportAddress & pdu, PBoolean localTsap,H323Connection * connection) const
1483 {
1484   H323TransportAddress transAddr;
1485   if (!localTsap)
1486     transAddr = H323TransportAddress(remoteAddress, remotePort);
1487   else {
1488     H323TransportAddress tAddr = GetLocalAddress();
1489     PIPSocket::Address ipAddr;
1490     tAddr.GetIpAddress(ipAddr);
1491     endpoint.InternalTranslateTCPAddress(ipAddr, remoteAddress,connection);
1492     WORD tPort = localPort;
1493     endpoint.TranslateTCPPort(tPort,remoteAddress);
1494     transAddr = H323TransportAddress(ipAddr, tPort);
1495   }
1496 
1497   transAddr.SetPDU(pdu);
1498 }
1499 
1500 
1501 void H323TransportIP::SetUpTransportPDU(H245_TransportAddress & pdu, unsigned port) const
1502 {
1503   PIPSocket::Address ipAddr = localAddress;
1504   endpoint.InternalTranslateTCPAddress(ipAddr, remoteAddress);
1505 
1506   switch (port) {
1507     case UseLocalTSAP :
1508       port = localPort;
1509       break;
1510     case UseRemoteTSAP :
1511       port = remotePort;
1512       break;
1513   }
1514 
1515   H323TransportAddress transAddr(ipAddr, (WORD)port);
1516   transAddr.SetPDU(pdu);
1517 }
1518 
1519 
1520 /////////////////////////////////////////////////////////////////////////////
1521 
1522 #ifdef H323_TLS
1523 H323TransportTCP::H323TransportTCP(H323EndPoint & end,
1524                                    PIPSocket::Address binding,
1525                                    PBoolean listen,
1526                                    PSSLContext * context,
1527                                    PBoolean autoDeleteContext
1528                                    )
1529                                    : H323TransportIP(end, binding, end.IsTLSEnabled() ? H323EndPoint::DefaultTLSPort : H323EndPoint::DefaultTcpPort,
1530                                      context ? context : end.GetTransportContext(), autoDeleteContext)
1531 #else
1532 H323TransportTCP::H323TransportTCP(H323EndPoint & end,
1533                                    PIPSocket::Address binding,
1534                                    PBoolean listen)
1535   : H323TransportIP(end, binding, H323EndPoint::DefaultTcpPort)
1536 #endif
1537 {
1538   h245listener = NULL;
1539 
1540   // construct listener socket if required
1541   if (listen) {
1542     h245listener = new PTCPSocket;
1543 
1544     localPort = end.GetNextTCPPort();
1545     WORD firstPort = localPort;
1546     while (!h245listener->Listen(binding, 5, localPort)) {
1547       localPort = end.GetNextTCPPort();
1548       if (localPort == firstPort)
1549         break;
1550     }
1551 
1552     if (h245listener->IsOpen()) {
1553       localPort = h245listener->GetPort();
1554       PTRACE(3, "H225\tTCP Listen for H245 on " << binding << ':' << localPort);
1555     }
1556     else {
1557       PTRACE(1, "H225\tTCP Listen for H245 failed: " << h245listener->GetErrorText());
1558       delete h245listener;
1559       h245listener = NULL;
1560     }
1561   }
1562 }
1563 
1564 
1565 H323TransportTCP::~H323TransportTCP()
1566 {
1567   delete h245listener;  // Delete any H245 listener that may be present
1568 }
1569 
1570 
1571 PBoolean H323TransportTCP::OnOpen()
1572 {
1573 #if H323_TLS
1574 #if PTLIB_VER < 2120
1575     ssl_st * m_ssl = ssl;
1576 #endif
1577     if (m_ssl) {
1578         if (!PSSLChannel::OnOpen())
1579             return false;
1580 
1581         m_secured = true;
1582     }
1583 #endif
1584     return OnSocketOpen();
1585 }
1586 
1587 PBoolean H323TransportTCP::OnSocketOpen()
1588 {
1589   PIPSocket * socket = (PIPSocket *)GetReadChannel();
1590 
1591   // Get name of the remote computer for information purposes
1592   if (!socket->GetPeerAddress(remoteAddress, remotePort)) {
1593     PTRACE(1, "H323TCP\tGetPeerAddress() failed: " << socket->GetErrorText());
1594     return FALSE;
1595   }
1596 
1597   // get local address of incoming socket to ensure that multi-homed machines
1598   // use a NIC address that is guaranteed to be addressable to destination
1599   if (!socket->GetLocalAddress(localAddress, localPort)) {
1600     PTRACE(1, "H323TCP\tGetLocalAddress() failed: " << socket->GetErrorText());
1601     return FALSE;
1602   }
1603 
1604   if (!socket->SetOption(TCP_NODELAY, 1, IPPROTO_TCP)) {
1605     PTRACE(1, "H323TCP\tSetOption(TCP_NODELAY) failed: " << socket->GetErrorText());
1606   }
1607 
1608   //if (!socket->SetOption(IP_TOS, endpoint.GetTcpIpTypeofService(), IPPROTO_IP)) {
1609   //  PTRACE(1, "H323TCP\tSetOption(IP_TOS) failed: " << socket->GetErrorText());
1610   //}
1611 
1612 
1613 #ifndef P_VXWORKS // VxWorks has alternative behaviour, so skip it
1614   // make sure do not lose outgoing packets on close
1615   const linger ling = { 1, 3 };
1616   if (!socket->SetOption(SO_LINGER, &ling, sizeof(ling))) {
1617     PTRACE(1, "H323TCP\tSetOption(SO_LINGER) failed: " << socket->GetErrorText());
1618     return FALSE;
1619   }
1620 #endif //P_VXWORKS
1621 
1622 #ifdef H323_TLS
1623   endpoint.OnSecureSignallingChannel(m_secured);
1624 #endif
1625 
1626   PTRACE(2, "H323TCP\tStarted connection: "
1627             " secured=" << (m_secured ? "true" : "false") << ","
1628             " host=" << remoteAddress << ':' << remotePort << ","
1629             " if=" << localAddress << ':' << localPort << ","
1630             " handle=" << socket->GetHandle());
1631 
1632   return TRUE;
1633 }
1634 
1635 
1636 PBoolean H323TransportTCP::Close()
1637 {
1638   // Close listening socket to break waiting accept
1639   if (IsListening())
1640     h245listener->Close();
1641 
1642 #if H323_TLS
1643 #if PTLIB_VER < 2120
1644     ssl_st * m_ssl = ssl;
1645 #endif
1646     if (m_ssl) {
1647         SSL_shutdown(m_ssl);
1648         m_ssl = NULL;
1649     }
1650 #endif
1651 
1652   return H323Transport::Close();
1653 }
1654 
1655 
1656 PBoolean H323TransportTCP::SetRemoteAddress(const H323TransportAddress & address)
1657 {
1658   return address.GetIpAndPort(remoteAddress, remotePort, "tcp");
1659 }
1660 
1661 PBoolean H323TransportTCP::InitialiseSecurity(const H323TransportSecurity * security)
1662 {
1663 #ifdef H323_TLS
1664     // Delete any context that was autoCreated in PSSLChannel. - Very Annoying - SH
1665 #if PTLIB_VER < 2120
1666     ssl_st * m_ssl = ssl;
1667 #endif
1668     if (m_ssl && !security->IsTLSEnabled()) {
1669         SSL_shutdown(m_ssl);
1670         SSL_free(m_ssl);
1671         m_ssl = NULL;
1672 #if PTLIB_VER < 2120
1673         ssl = NULL;
1674 #endif
1675     } else if (!m_ssl && security->IsTLSEnabled()) {
1676 #if PTLIB_VER < 2120
1677         ssl = SSL_new(*context);
1678         if (!ssl) {
1679 #else
1680         m_ssl = SSL_new(*m_context);
1681         if (!m_ssl) {
1682 #endif
1683             PTRACE(1, "TLS\tError creating SSL object");
1684             return false;
1685         }
1686     }
1687 #endif // H323_TLS
1688     return true;
1689 }
1690 
1691 PBoolean H323TransportTCP::ExtractPDU(const PBYTEArray & pdu, PINDEX & pduLen)
1692 {
1693   //
1694   // TPKT format is :
1695   //   byte 0   = type identifier - always 0x03
1696   //   byte 1   = ignored
1697   //   byte 2   = msb of data length
1698   //   byte 3   = lsb of data length
1699   //   byte xx  = data of length
1700   //
1701   // this gives minimum length of 4 bytes
1702 
1703   // ensure length is at least one byte
1704   if (pduLen < 1) {
1705     pduLen = 0;
1706     return TRUE;
1707   }
1708 
1709   // only accept TPKT of type 3
1710   if (pdu[0] != 3)
1711     return SetErrorValues(Miscellaneous, 0x41000000);
1712 
1713   // check for minimum header length
1714   if (pduLen < 4) {
1715     pduLen = 0;
1716     return TRUE;
1717   }
1718 
1719   // see if complete PDU received yet
1720   PINDEX dataLen = (pdu[2] << 8)|pdu[3];
1721 
1722   // dwarf PDUs are errors
1723   if (dataLen < 4) {
1724     PTRACE(1, "H323TCP\tDwarf PDU received (length " << dataLen << ")");
1725     return FALSE;
1726   }
1727 
1728   // wait for data to arrive
1729   if (pduLen < dataLen) {
1730     pduLen = 0;
1731     return TRUE;
1732   }
1733 
1734   // set the length of the complete PDU
1735   pduLen = dataLen;
1736 
1737   return TRUE;
1738 }
1739 
1740 #if PTLIB_VER >= 2130
1741 int H323TransportTCP::ReadChar()
1742 {
1743   BYTE c;
1744   PBoolean retVal = Read(&c, 1);
1745   return (retVal && lastReadCount == 1) ? c : -1;
1746 }
1747 
1748 PBoolean H323TransportTCP::ReadBlock(void * buf, PINDEX len)
1749 {
1750   char * ptr = (char *)buf;
1751   PINDEX numRead = 0;
1752 
1753   while (numRead < len && Read(ptr+numRead, len - numRead))
1754     numRead += lastReadCount;
1755 
1756   lastReadCount = numRead;
1757 
1758   return lastReadCount == len;
1759 }
1760 #endif
1761 
1762 PBoolean H323TransportTCP::ReadPDU(PBYTEArray & pdu)
1763 {
1764   // Make sure is a RFC1006 TPKT
1765   switch (ReadChar()) {
1766     case -1 :
1767       return FALSE;
1768 
1769     case 3 :  // Only support version 3
1770       break;
1771 
1772     default :  // Unknown version number
1773       return SetErrorValues(Miscellaneous, 0x41000000);
1774   }
1775 
1776   // Save timeout
1777   PTimeInterval oldTimeout = GetReadTimeout();
1778 
1779   // Should get all of PDU in 5 seconds or something is seriously wrong,
1780   SetReadTimeout(5000);
1781 
1782   // Get TPKT length
1783   BYTE header[3];
1784   PBoolean ok = ReadBlock(header, sizeof(header));
1785   if (ok) {
1786     PINDEX packetLength = ((header[1] << 8)|header[2]);
1787     if (packetLength < 4) {
1788       PTRACE(1, "H323TCP\tDwarf PDU received (length " << packetLength << ")");
1789       ok = FALSE;
1790     } else {
1791       packetLength -= 4;
1792       ok = ReadBlock(pdu.GetPointer(packetLength), packetLength);
1793     }
1794   }
1795 
1796   SetReadTimeout(oldTimeout);
1797 
1798   return ok;
1799 }
1800 
1801 
1802 PBoolean H323TransportTCP::WritePDU(const PBYTEArray & pdu)
1803 {
1804   // We copy the data into a new buffer so we can do a single write call. This
1805   // is necessary as we have disabled the Nagle TCP delay algorithm to improve
1806   // network performance.
1807 
1808   int packetLength = pdu.GetSize() + 4;
1809 
1810   // Send RFC1006 TPKT length
1811   PBYTEArray tpkt(packetLength);
1812   tpkt[0] = 3;
1813   tpkt[1] = 0;
1814   tpkt[2] = (BYTE)(packetLength >> 8);
1815   tpkt[3] = (BYTE)packetLength;
1816   memcpy(tpkt.GetPointer()+4, (const BYTE *)pdu, pdu.GetSize());
1817 
1818   return Write((const BYTE *)tpkt, packetLength);
1819 }
1820 
1821 PBoolean H323TransportTCP::FinaliseSecurity(PSocket * socket)
1822 {
1823 #ifdef H323_TLS
1824 #if PTLIB_VER < 2120
1825     ssl_st * m_ssl = ssl;
1826 #endif
1827     if (m_ssl && socket) {
1828         SSL_set_fd(m_ssl, socket->GetHandle());
1829         return true;
1830     }
1831 #endif
1832     return false;
1833 }
1834 
1835 PBoolean H323TransportTCP::SecureConnect()
1836 {
1837 #ifdef H323_TLS
1838 #if PTLIB_VER < 2120
1839     ssl_st * m_ssl = ssl;
1840 #endif
1841     int ret = 0;
1842     do {
1843         ret = SSL_connect(m_ssl);
1844         if (ret <= 0) {
1845             char msg[256];
1846             int err = SSL_get_error(m_ssl, ret);
1847             switch (err) {
1848                 case SSL_ERROR_NONE:
1849                     break;
1850                 case SSL_ERROR_SSL:
1851                     ERR_error_string(ERR_get_error(), msg);
1852                     PTRACE(1, "TLS\tTLS protocol error in SSL_connect(): " << err << " / " << msg);
1853                     SSL_shutdown(m_ssl);
1854                     return false;
1855                     break;
1856                 case SSL_ERROR_SYSCALL:
1857                     PTRACE(1, "TLS\tSyscall error in SSL_connect() errno=" << errno);
1858                     switch (errno) {
1859                         case 0:
1860                             ret = 1;	// done
1861                             break;
1862                         case EAGAIN:
1863                             break;
1864                         default:
1865                             ERR_error_string(ERR_get_error(), msg);
1866                             PTRACE(1, "TLS\tTerminating connection: " << msg);
1867                             SSL_shutdown(m_ssl);
1868                             return false;
1869                     };
1870                     break;
1871                 case SSL_ERROR_WANT_READ:
1872                     // just retry
1873                     break;
1874                 case SSL_ERROR_WANT_WRITE:
1875                     // just retry
1876                     break;
1877                 default:
1878                     ERR_error_string(ERR_get_error(), msg);
1879                     PTRACE(1, "TLS\tUnknown error in SSL_connect(): " << err << " / " << msg);
1880                     SSL_shutdown(m_ssl);
1881                     return false;
1882             }
1883         }
1884     } while (ret <= 0);
1885 #endif
1886     return true;
1887 }
1888 
1889 PBoolean H323TransportTCP::SecureAccept()
1890 {
1891 #ifdef H323_TLS
1892 #if PTLIB_VER < 2120
1893     ssl_st * m_ssl = ssl;
1894 #endif
1895     if (m_ssl)
1896         return PSSLChannel::Accept();
1897 #endif
1898     return true;
1899 }
1900 
1901 
1902 PBoolean H323TransportTCP::Connect()
1903 {
1904   if (IsListening())
1905     return TRUE;
1906 
1907   PTCPSocket * socket = new PTCPSocket(remotePort);
1908   Open(socket);
1909 
1910   channelPointerMutex.StartRead();
1911 
1912   socket->SetReadTimeout(endpoint.GetSignallingChannelConnectTimeout());
1913 
1914   localPort = endpoint.GetNextTCPPort();
1915   WORD firstPort = localPort;
1916   for (;;) {
1917     PTRACE(4, "H323TCP\tConnecting to "
1918            << remoteAddress << ':' << remotePort
1919            << " (local port=" << localPort << ')');
1920     if (socket->Connect(localAddress, localPort, remoteAddress))
1921       break;
1922 
1923     int errnum = socket->GetErrorNumber();
1924     if (localPort == 0 || (errnum != EADDRINUSE && errnum != EADDRNOTAVAIL)) {
1925       PTRACE(1, "H323TCP\tCould not connect to "
1926                 << remoteAddress << ':' << remotePort
1927                 << " (local port=" << localPort << ") - "
1928                 << socket->GetErrorText() << '(' << errnum << ')');
1929       channelPointerMutex.EndRead();
1930       return SetErrorValues(socket->GetErrorCode(), errnum);
1931     }
1932 
1933     localPort = endpoint.GetNextTCPPort();
1934     if (localPort == firstPort) {
1935       PTRACE(1, "H323TCP\tCould not bind to any port in range " <<
1936                 endpoint.GetTCPPortBase() << " to " << endpoint.GetTCPPortMax());
1937       channelPointerMutex.EndRead();
1938       return SetErrorValues(socket->GetErrorCode(), errnum);
1939     }
1940   }
1941 
1942   socket->SetReadTimeout(PMaxTimeInterval);
1943 
1944   if (FinaliseSecurity(socket) && !SecureConnect())
1945       return false;
1946 
1947   channelPointerMutex.EndRead();
1948 
1949   return OnOpen();
1950 }
1951 
1952 H323Transport * H323TransportTCP::CreateControlChannel(H323Connection & connection)
1953 {
1954   H323TransportSecurity m_callSecurity;
1955   H323TransportTCP * tcpTransport = new H323TransportTCP(endpoint, localAddress, true);
1956   tcpTransport->InitialiseSecurity(&m_callSecurity);
1957   tcpTransport->SetRemoteAddress(GetRemoteAddress());
1958   if (tcpTransport->IsListening()) // Listen() failed
1959     return tcpTransport;
1960 
1961   delete tcpTransport;
1962   connection.ClearCall(H323Connection::EndedByTransportFail);
1963   return FALSE;
1964 }
1965 
1966 
1967 PBoolean H323TransportTCP::AcceptControlChannel(H323Connection & connection)
1968 {
1969   if (IsOpen())
1970     return TRUE;
1971 
1972   if (h245listener == NULL) {
1973     PTRACE(1, "H225\tLogic error, no H.245 listener");
1974     return FALSE;
1975   }
1976 
1977   PTRACE(3, "H245\tTCP Accept wait");
1978 
1979   PTCPSocket * h245Socket = new PTCPSocket;
1980 
1981   h245listener->SetReadTimeout(endpoint.GetControlChannelStartTimeout());
1982   if (h245Socket->Accept(*h245listener)) {
1983       FinaliseSecurity(h245Socket);
1984       if (Open(h245Socket) && SecureAccept())
1985             return true;
1986   }
1987 
1988   PTRACE(1, "H225\tAccept for H245 failed: " << h245Socket->GetErrorText());
1989   delete h245Socket;
1990 
1991   if (h245listener->IsOpen() &&
1992       connection.IsConnected() &&
1993       connection.FindChannel(RTP_Session::DefaultAudioSessionID, TRUE) == NULL &&
1994       connection.FindChannel(RTP_Session::DefaultAudioSessionID, FALSE) == NULL)
1995     connection.ClearCall(H323Connection::EndedByTransportFail);
1996 
1997   return FALSE;
1998 }
1999 
2000 
2001 PBoolean H323TransportTCP::IsListening() const
2002 {
2003   if (IsOpen())
2004     return FALSE;
2005 
2006   if (h245listener == NULL)
2007     return FALSE;
2008 
2009   return h245listener->IsOpen();
2010 }
2011 
2012 
2013 /////////////////////////////////////////////////////////////////////////////
2014 
2015 static PBoolean ListenUDP(PUDPSocket & socket,
2016                       H323EndPoint & endpoint,
2017                       PIPSocket::Address binding,
2018                       WORD localPort)
2019 {
2020   if (localPort > 0) {
2021     if (socket.Listen(binding, 0, localPort))
2022       return TRUE;
2023   }
2024   else {
2025     localPort = endpoint.GetNextUDPPort();
2026     WORD firstPort = localPort;
2027 
2028     for (;;) {
2029       if (socket.Listen(binding, 0, localPort))
2030         return TRUE;
2031 
2032       int errnum = socket.GetErrorNumber();
2033       if (errnum != EADDRINUSE && errnum != EADDRNOTAVAIL)
2034         break;
2035 
2036       localPort = endpoint.GetNextUDPPort();
2037       if (localPort == firstPort) {
2038         PTRACE(1, "H323UDP\tCould not bind to any port in range " <<
2039                   endpoint.GetUDPPortBase() << " to " << endpoint.GetUDPPortMax());
2040         return FALSE;
2041       }
2042     }
2043   }
2044 
2045   PTRACE(1, "H323UDP\tCould not bind to "
2046             << binding << ':' << localPort << " - "
2047             << socket.GetErrorText() << '(' << socket.GetErrorNumber() << ')');
2048   return FALSE;
2049 }
2050 
2051 
2052 H323TransportUDP::H323TransportUDP(H323EndPoint & ep,
2053                                    PIPSocket::Address binding,
2054                                    WORD local_port,
2055                                    WORD remote_port)
2056 #ifdef H323_TLS
2057   : H323TransportIP(ep, binding, remote_port, ep.GetTransportContext())
2058 #else
2059   : H323TransportIP(ep, binding, remote_port)
2060 #endif
2061 {
2062   if (remotePort == 0)
2063     remotePort = H225_RAS::DefaultRasUdpPort; // For backward compatibility
2064 
2065   promiscuousReads = AcceptFromRemoteOnly;
2066 
2067   PUDPSocket * udp = new PUDPSocket;
2068   ListenUDP(*udp, ep, binding, local_port);
2069 
2070   interfacePort = localPort = udp->GetPort();
2071 
2072   Open(udp);
2073 
2074   PTRACE(3, "H323UDP\tBinding to interface: " << binding << ':' << localPort);
2075 
2076 #if PTLIB_VER >= 2110
2077   canGetInterface = false;
2078 #else
2079   canGetInterface = (binding.IsAny()) && udp->SetCaptureReceiveToAddress();
2080 #endif
2081 }
2082 
2083 
2084 H323TransportUDP::~H323TransportUDP()
2085 {
2086   Close();
2087 }
2088 
2089 
2090 PBoolean H323TransportUDP::SetRemoteAddress(const H323TransportAddress & address)
2091 {
2092   return address.GetIpAndPort(remoteAddress, remotePort, "udp");
2093 }
2094 
2095 
2096 PBoolean H323TransportUDP::Connect()
2097 {
2098   if (remoteAddress == 0 || remotePort == 0)
2099     return FALSE;
2100 
2101   PUDPSocket * socket;
2102 
2103 #ifdef P_STUN
2104   PSTUNClient * stun = endpoint.GetSTUN(remoteAddress);
2105   if (stun != NULL) {
2106 #if (PTLIB_VER >= 2110) && (PTLIB_VER < 2130)
2107     if (stun->CreateSocket(PNatMethod::eComponent_Unknown,socket)) {
2108 #else
2109     if (stun->CreateSocket(socket)) {
2110 #endif
2111       Open(socket);
2112       socket->GetLocalAddress(localAddress, localPort);
2113       PTRACE(4, "H323UDP\tSTUN created socket: " << localAddress << ':' << localPort);
2114     }
2115     else
2116       PTRACE(4, "H323UDP\tSTUN could not create socket!");
2117   }
2118 #endif
2119 
2120   socket = (PUDPSocket *)GetReadChannel();
2121   socket->SetSendAddress(remoteAddress, remotePort);
2122 
2123   return TRUE;
2124 }
2125 
2126 
2127 void H323TransportUDP::SetPromiscuous(PromisciousModes promiscuous)
2128 {
2129   promiscuousReads = promiscuous;
2130 }
2131 
2132 
2133 H323TransportAddress H323TransportUDP::GetLastReceivedAddress() const
2134 {
2135   if (!lastReceivedAddress)
2136     return lastReceivedAddress;
2137 
2138   return H323Transport::GetLastReceivedAddress();
2139 }
2140 
2141 PBoolean H323TransportUDP::ExtractPDU(const PBYTEArray & /*pdu*/, PINDEX & /*len*/)
2142 {
2143   return TRUE;
2144 }
2145 
2146 PBoolean H323TransportUDP::ReadPDU(PBYTEArray & pdu)
2147 {
2148   for (;;) {
2149     if (!Read(pdu.GetPointer(10000), 10000)) {
2150       pdu.SetSize(0);
2151       return FALSE;
2152     }
2153 
2154     pdu.SetSize(GetLastReadCount());
2155 
2156     PUDPSocket * socket = (PUDPSocket *)GetReadChannel();
2157 
2158 #if PTLIB_VER < 2110
2159     if (canGetInterface)
2160       lastReceivedInterface = socket->GetLastReceiveToAddress();
2161 #endif
2162 
2163     PIPSocket::Address address;
2164     WORD port;
2165 
2166     socket->GetLastReceiveAddress(address, port);
2167 
2168     switch (promiscuousReads) {
2169       case AcceptFromRemoteOnly :
2170         if (remoteAddress *= address)
2171           goto accept;
2172         break;
2173 
2174       case AcceptFromAnyAutoSet :
2175         remoteAddress = address;
2176         remotePort = port;
2177         socket->SetSendAddress(remoteAddress, remotePort);
2178         goto accept;
2179 
2180       case AcceptFromLastReceivedOnly :
2181         if (!lastReceivedAddress.IsEmpty()) {
2182           PIPSocket::Address lastAddr;
2183           WORD lastPort = 0;
2184 
2185           if (lastReceivedAddress.GetIpAndPort(lastAddr, lastPort, "udp") &&
2186              (lastAddr *= address) && lastPort == port)
2187             goto accept;
2188         }
2189         break;
2190 
2191       default : //AcceptFromAny
2192       accept:
2193         lastReceivedAddress = H323TransportAddress(address, port);
2194         return TRUE;
2195     }
2196 
2197     PTRACE(1, "UDP\tReceived PDU from incorrect host: " << address << ':' << port);
2198   }
2199 }
2200 
2201 
2202 PBoolean H323TransportUDP::WritePDU(const PBYTEArray & pdu)
2203 {
2204   return Write((const BYTE *)pdu, pdu.GetSize());
2205 }
2206 
2207 
2208 PBoolean H323TransportUDP::DiscoverGatekeeper(H323Gatekeeper & gk,
2209                                           H323RasPDU & request,
2210                                           const H323TransportAddress & address)
2211 {
2212   PINDEX i;
2213 
2214   PTRACE(3, "H225\tStarted gatekeeper discovery of \"" << address << '"');
2215 
2216   PIPSocket::Address destAddr;
2217 #ifdef H323_IPV6
2218   if (address.GetIpVersion() == 6)
2219       destAddr = PIPSocket::Address::GetBroadcast(6);
2220   else
2221 #endif
2222       destAddr = INADDR_BROADCAST;
2223 
2224     // Skip over the H323Transport::Close to make sure PUDPSocket is deleted.
2225   PIndirectChannel::Close();
2226 
2227   WORD destPort = H225_RAS::DefaultRasUdpPort;
2228   if (!address) {
2229     if (!address.GetIpAndPort(destAddr, destPort, "udp")) {
2230       PTRACE(2, "RAS\tError decoding address");
2231       return FALSE;
2232     }
2233     remoteAddress = destAddr;
2234     remotePort = destPort;
2235   } else {
2236     remoteAddress = 0;
2237     remotePort = 0;
2238   }
2239 
2240 
2241   // Remember the original info for pre-bound socket
2242   PIPSocket::Address originalLocalAddress = localAddress;
2243   WORD originalLocalPort = 0;
2244 
2245 #ifdef H323_IPV6
2246   // Again horrible code should be able to get interface listing for a given protocol - SH
2247   PBoolean ipv6IPv4Discover = false;
2248   if (address.GetIpVersion() == 4 && PIPSocket::GetDefaultIpAddressFamily() == AF_INET6) {
2249       PIPSocket::SetDefaultIpAddressFamilyV4();
2250       ipv6IPv4Discover = true;
2251   }
2252 #endif
2253 
2254   // Get the interfaces to try
2255   PIPSocket::InterfaceTable interfaces;
2256   PIPSocket::InterfaceTable InterfaceList;
2257 
2258   // See if prebound to interface, only use that if so
2259   if (destAddr.IsLoopback()) {
2260     PTRACE(3, "RAS\tGatekeeper discovery on loopback interface");
2261     localAddress = destAddr;
2262   }
2263   else if (!PIPSocket::GetInterfaceTable(InterfaceList)) {
2264     PTRACE(1, "RAS\tNo interfaces on system!");
2265   }
2266   else if (!localAddress.IsAny() && !localAddress.IsLoopback()) {
2267     PTRACE(3, "RAS\tGatekeeper discovery on pre-bound interface: "
2268               << localAddress.AsString(true) << ':' << localPort);
2269     originalLocalPort = localPort;
2270     for (i = 0; i < InterfaceList.GetSize(); i++) {
2271       if (InterfaceList[i].GetAddress() == localAddress) {
2272         PTRACE(3, "RAS\tGatekeeper local interface set: " << localAddress.AsString(true));
2273         interfaces.Append(new PIPSocket::InterfaceEntry(InterfaceList[i].GetName(),
2274                                                         InterfaceList[i].GetAddress(),
2275                                                         InterfaceList[i].GetNetMask(),
2276                                                         InterfaceList[i].GetMACAddress()));
2277       }
2278     }
2279     InterfaceList.RemoveAll();
2280   } else {
2281     for (i = 0; i < InterfaceList.GetSize(); i++) {
2282       if (!InterfaceList[i].GetAddress().IsLoopback() &&
2283            InterfaceList[i].GetAddress().GetVersion() == destAddr.GetVersion()) {
2284             interfaces.Append(new PIPSocket::InterfaceEntry(InterfaceList[i].GetName(),
2285                                                             InterfaceList[i].GetAddress(),
2286                                                             InterfaceList[i].GetNetMask(),
2287                                                             InterfaceList[i].GetMACAddress()));
2288       }
2289     }
2290     InterfaceList.RemoveAll();
2291   }
2292 
2293 #ifdef H323_IPV6
2294   if (ipv6IPv4Discover)
2295       PIPSocket::SetDefaultIpAddressFamilyV6();
2296 #endif
2297 
2298   if (interfaces.IsEmpty())
2299     interfaces.Append(new PIPSocket::InterfaceEntry("", localAddress, PIPSocket::Address(0xffffffff), ""));
2300 
2301 
2302 
2303 #ifdef P_STUN
2304   PSTUNClient * stun = endpoint.GetSTUN(remoteAddress);
2305 #endif
2306 
2307   PSocketList sockets;
2308   PSocket::SelectList selection;
2309   H225_GatekeeperRequest & grq = request;
2310 
2311   for (i = 0; i < interfaces.GetSize(); i++) {
2312     localAddress = interfaces[i].GetAddress();
2313 
2314     // don't try to use IPv4 interface to reach IPv6 gatekeeper or IPv6 interface to reach IPv4 gatekeeper
2315     if (localAddress.GetVersion() != destAddr.GetVersion())
2316       continue;
2317 
2318     if (localAddress == 0 || (destAddr != localAddress && localAddress.IsLoopback()))
2319       continue;
2320 
2321     // Check for already have had that IP address.
2322     PINDEX j;
2323     for (j = 0; j < i; j++) {
2324       if (localAddress == interfaces[j].GetAddress())
2325         break;
2326     }
2327     if (j < i)
2328       continue;
2329 
2330     PUDPSocket * socket = NULL;
2331 
2332     static PIPSocket::Address MulticastRasAddress(224, 0, 1, 41);
2333     if (destAddr != MulticastRasAddress) {
2334 
2335 #ifdef P_STUN
2336       // Not explicitly multicast
2337 #if (PTLIB_VER >= 2110) && (PTLIB_VER < 2130)
2338       if (stun != NULL && stun->CreateSocket(PNatMethod::eComponent_Unknown,socket)) {
2339 #else
2340       if (stun != NULL && stun->CreateSocket(socket)) {
2341 #endif
2342         socket->GetLocalAddress(localAddress, localPort);
2343         PTRACE(4, "H323UDP\tSTUN created socket: " << localAddress << ':' << localPort);
2344       }
2345       else
2346 #endif
2347       {
2348         socket = new PUDPSocket;
2349         if (!ListenUDP(*socket, endpoint, localAddress, originalLocalPort)) {
2350           delete socket;
2351           return FALSE;
2352         }
2353         localPort = socket->GetPort();
2354       }
2355 
2356       sockets.Append(socket);
2357 
2358       if (destAddr == INADDR_BROADCAST) {
2359         if (!socket->SetOption(SO_BROADCAST, 1)) {
2360           PTRACE(2, "RAS\tError allowing broadcast: " << socket->GetErrorText());
2361           return FALSE;
2362         }
2363       }
2364 
2365       // Adjust the PDU to reflect the interface we are writing to.
2366       PIPSocket::Address ipAddr = localAddress;
2367       endpoint.InternalTranslateTCPAddress(ipAddr, destAddr);
2368       endpoint.TranslateTCPPort(localPort, destAddr);
2369       H323TransportAddress(ipAddr, localPort).SetPDU(grq.m_rasAddress);
2370 
2371       PTRACE(3, "RAS\tGatekeeper discovery on interface: " << localAddress << ':' << localPort);
2372 
2373       socket->SetSendAddress(destAddr, destPort);
2374       writeChannel = socket;
2375       if (request.Write(*this))
2376         selection.Append(socket);
2377       else
2378         PTRACE(2, "RAS\tError writing discovery PDU: " << socket->GetErrorText());
2379 
2380       if (destAddr == INADDR_BROADCAST)
2381         socket->SetOption(SO_BROADCAST, 0);
2382     }
2383 
2384 
2385 #ifdef IP_ADD_MEMBERSHIP
2386     // Now do it again for Multicast
2387     if (destAddr == INADDR_BROADCAST || destAddr == MulticastRasAddress) {
2388       socket = new PUDPSocket;
2389       sockets.Append(socket);
2390 
2391       if (!ListenUDP(*socket, endpoint, localAddress, 0)) {
2392         writeChannel = NULL;
2393         return FALSE;
2394       }
2395 
2396       localPort = socket->GetPort();
2397 
2398       struct ip_mreq mreq;
2399       mreq.imr_multiaddr = MulticastRasAddress;
2400       mreq.imr_interface = localAddress;    // ip address of host
2401       if (socket->SetOption(IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq), IPPROTO_IP)) {
2402         // Adjust the PDU to reflect the interface we are writing to.
2403         SetUpTransportPDU(grq.m_rasAddress, TRUE);
2404 
2405         socket->SetOption(SO_BROADCAST, 1);
2406 
2407         socket->SetSendAddress(INADDR_BROADCAST, H225_RAS::DefaultRasMulticastPort);
2408         writeChannel = socket;
2409         if (request.Write(*this))
2410           selection.Append(socket);
2411         else
2412           PTRACE(2, "RAS\tError writing discovery PDU: " << socket->GetErrorText());
2413 
2414         socket->SetOption(SO_BROADCAST, 0);
2415       }
2416       else
2417         PTRACE(2, "RAS\tError allowing multicast: " << socket->GetErrorText());
2418     }
2419 #endif
2420 
2421     writeChannel = NULL;
2422   }
2423 
2424   if (sockets.IsEmpty()) {
2425     PTRACE(1, "RAS\tNo suitable interfaces for discovery!");
2426     return FALSE;
2427   }
2428 
2429   if (PSocket::Select(selection, endpoint.GetGatekeeperRequestTimeout()) != NoError) {
2430     PTRACE(3, "RAS\tError on discover request select");
2431     return FALSE;
2432   }
2433 
2434   SetReadTimeout(0);
2435 
2436   for (i = 0; i < selection.GetSize(); i++) {
2437     readChannel = &selection[i];
2438     promiscuousReads = AcceptFromAnyAutoSet;
2439 
2440     H323RasPDU response;
2441     if (!response.Read(*this)) {
2442       PTRACE(3, "RAS\tError on discover request read: " << readChannel->GetErrorText());
2443       break;
2444     }
2445 
2446     do {
2447       if (gk.HandleTransaction(response)) {
2448         if (!gk.IsDiscoveryComplete()) {
2449           localAddress = originalLocalAddress;
2450           localPort = originalLocalPort;
2451           promiscuousReads = AcceptFromRemoteOnly;
2452           readChannel = NULL;
2453           return TRUE;
2454         }
2455 
2456         PUDPSocket * socket = (PUDPSocket *)readChannel;
2457         socket->GetLocalAddress(localAddress, localPort);
2458         readChannel = NULL;
2459         if (Open(socket) && Connect()) {
2460           sockets.DisallowDeleteObjects();
2461           sockets.Remove(socket);
2462           sockets.AllowDeleteObjects();
2463 
2464           promiscuousReads = AcceptFromRemoteOnly;
2465 
2466           PTRACE(2, "RAS\tGatekeeper discovered at: "
2467                  << remoteAddress << ':' << remotePort
2468                  << " (if="
2469                  << localAddress << ':' << localPort << ')');
2470           return TRUE;
2471         }
2472       }
2473     } while (response.Read(*this));
2474   }
2475 
2476   PTRACE(2, "RAS\tGatekeeper discovery failed");
2477   localAddress = originalLocalAddress;
2478   localPort = originalLocalPort;
2479   promiscuousReads = AcceptFromRemoteOnly;
2480   readChannel = NULL;
2481   return FALSE;
2482 }
2483 
2484 H323TransportAddress H323TransportUDP::GetLocalAddress() const
2485 {
2486   if (canGetInterface && !lastReceivedInterface.IsLoopback())
2487     return H323TransportAddress(lastReceivedInterface, interfacePort);
2488 
2489   // check for special case of local interface, which means the PDU came from the same machine
2490   H323TransportAddress taddr = H323TransportIP::GetLocalAddress();
2491   if (!lastReceivedAddress.IsEmpty()) {
2492     PIPSocket::Address tipAddr;
2493     WORD tipPort = 0;
2494     taddr.GetIpAndPort(tipAddr, tipPort);
2495     if (tipAddr == PIPSocket::Address(0)) {
2496       PIPSocket::Address lastRxIPAddr;
2497       lastReceivedAddress.GetIpAddress(lastRxIPAddr);
2498       if (lastRxIPAddr != PIPSocket::Address())
2499         taddr = H323TransportAddress(lastRxIPAddr, tipPort);
2500     }
2501   }
2502 
2503   return taddr;
2504 }
2505 
2506 /////////////////////////////////////////////////////////////////////////////
2507 
2508 #ifdef _MSC_VER
2509   #pragma warning(default : 4244)
2510 #endif
2511