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