1 /*
2 * H46017.cxx
3 *
4 * H46017 NAT Traversal class.
5 *
6 * h323plus library
7 *
8 * Copyright (c) 2011 ISVO (Asia) Pte. Ltd.
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.1 (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 * Alternatively, the contents of this file may be used under the terms
16 * of the General Public License (the "GNU License"), in which case the
17 * provisions of GNU License are applicable instead of those
18 * above. If you wish to allow use of your version of this file only
19 * under the terms of the GNU License and not to allow others to use
20 * your version of this file under the MPL, indicate your decision by
21 * deleting the provisions above and replace them with the notice and
22 * other provisions required by the GNU License. If you do not delete
23 * the provisions above, a recipient may use your version of this file
24 * under either the MPL or the GNU License."
25 *
26 * Software distributed under the License is distributed on an "AS IS"
27 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
28 * the License for the specific language governing rights and limitations
29 * under the License.
30 *
31 *
32 * The Initial Developer of the Original Code is ISVO (Asia) Pte. Ltd.
33 *
34 * Contributor(s): ______________________________________.
35 *
36 * $Id$
37 *
38 */
39
40 #include <ptlib.h>
41 #include "openh323buildopts.h"
42
43 #ifdef H323_H46017
44
45 #include <h323ep.h>
46 #include <h323pdu.h>
47 #include <h460/h460_std17.h>
48 #ifdef H323_H46026
49 #include <h460/h460_std26.h>
50 #endif
51
52 #include <ptclib/pdns.h>
53 #include <ptclib/delaychan.h>
54
55
56 struct LookupRecord {
57 PIPSocket::Address addr;
58 WORD port;
59 };
60
FindSRVRecords(std::vector<LookupRecord> & recs,const PString & domain,const PString & srv)61 static PBoolean FindSRVRecords(std::vector<LookupRecord> & recs,
62 const PString & domain,
63 const PString & srv)
64 {
65 #if P_DNS
66 PDNS::SRVRecordList srvRecords;
67 PString srvLookupStr = srv + domain;
68 PBoolean found = PDNS::GetRecords(srvLookupStr, srvRecords);
69 if (found) {
70 PDNS::SRVRecord * recPtr = srvRecords.GetFirst();
71 while (recPtr != NULL) {
72 LookupRecord rec;
73 rec.addr = recPtr->hostAddress;
74 rec.port = recPtr->port;
75 recs.push_back(rec);
76 recPtr = srvRecords.GetNext();
77 PTRACE(4, "H323\tFound " << rec.addr << ":" << rec.port << " with SRV " << srv << " for domain " << domain);
78 }
79 }
80 return found;
81 #else
82 return false;
83 #endif
84 }
85
FindRoutes(const PString & domain,std::vector<std::pair<LookupRecord,H323TransportSecurity>> & routes,H323TransportSecurity * sec)86 static PBoolean FindRoutes(const PString & domain, std::vector<std::pair<LookupRecord, H323TransportSecurity> > & routes, H323TransportSecurity * sec)
87 {
88 std::vector<LookupRecord> secureRoute;
89 std::vector<LookupRecord>::iterator r;
90 if (sec && sec->IsTLSEnabled()) {
91 H323TransportSecurity tls;
92 tls.EnableTLS(true);
93 FindSRVRecords(secureRoute, domain, "_h323rs-sec._tcp.");
94 for (r = secureRoute.begin(); r != secureRoute.end(); ++r)
95 routes.push_back(std::make_pair(*r, tls));
96
97 if (!routes.empty())
98 return true;
99 }
100
101 std::vector<LookupRecord> route;
102 H323TransportSecurity unsecure;
103 FindSRVRecords(route, domain, "_h323rs._tcp.");
104 for (r = route.begin(); r != route.end(); ++r)
105 routes.push_back(std::make_pair(*r,unsecure));
106
107 return !routes.empty();
108 }
109
110 ///////////////////////////////////////////////////////////////////////////////////
111 // Must Declare for Factory Loader.
112 H460_FEATURE(Std17);
113
114 PBoolean H460_FeatureStd17::isEnabled = false;
H460_FeatureStd17()115 H460_FeatureStd17::H460_FeatureStd17()
116 : H460_FeatureStd(17), EP(NULL), CON(NULL), m_handler(NULL)
117 {
118
119 }
120
~H460_FeatureStd17()121 H460_FeatureStd17::~H460_FeatureStd17()
122 {
123 isEnabled = false;
124 delete m_handler;
125 }
126
AttachEndPoint(H323EndPoint * _ep)127 void H460_FeatureStd17::AttachEndPoint(H323EndPoint * _ep)
128 {
129 if (!EP)
130 EP = _ep;
131 }
132
AttachConnection(H323Connection * _con)133 void H460_FeatureStd17::AttachConnection(H323Connection * _con)
134 {
135 CON = _con;
136 if (!EP)
137 EP = &CON->GetEndPoint();
138
139 }
140
GetPurpose()141 int H460_FeatureStd17::GetPurpose()
142 {
143 if (isEnabled)
144 return FeatureRas;
145 else
146 return FeatureBase;
147 }
148
Initialise(const PString & remoteAddr,PBoolean srv)149 PBoolean H460_FeatureStd17::Initialise(const PString & remoteAddr, PBoolean srv)
150 {
151 return Initialise(NULL, remoteAddr, srv);
152 }
153
Initialise(H323TransportSecurity * sec,const PString & remoteAddr,PBoolean srv)154 PBoolean H460_FeatureStd17::Initialise(H323TransportSecurity * sec, const PString & remoteAddr, PBoolean srv)
155 {
156 if (!srv) { // We are not doing SRV lookup
157 H323TransportAddress rem(remoteAddr);
158 if (!sec || !InitialiseTunnel(rem, *sec)) {
159 PTRACE(2,"H46017\tTunnel to " << rem << " Failed!");
160 return false;
161 }
162 if (!m_handler)
163 return false;
164 #ifdef H323_H46018
165 EP->H46018Enable(false);
166 #endif
167 isEnabled = true;
168 return (m_handler->RegisterGatekeeper());
169
170 } else {
171 typedef std::vector<std::pair<LookupRecord,H323TransportSecurity> > type_routes;
172 type_routes routes;
173
174 if (!FindRoutes(remoteAddr, routes, sec)) {
175 PTRACE(2,"H46017\tNo Gatekeeper registration SRV Records found!");
176 return false;
177 }
178
179 type_routes::const_iterator r;
180 for (r = routes.begin(); r != routes.end(); ++r) {
181 const LookupRecord & rec = r->first;
182 H323TransportAddress rem(rec.addr ,rec.port);
183 const H323TransportSecurity & sec = r->second;
184
185 if (!InitialiseTunnel(rem, sec)) {
186 PTRACE(2,"H46017\t" << (sec.IsTLSEnabled() ? "TLS " : "") << "Tunnel to " << rem << " Failed!");
187 continue;
188 }
189 #ifdef H323_H46018
190 EP->H46018Enable(false);
191 #endif
192 isEnabled = true;
193 if (!m_handler->RegisterGatekeeper())
194 continue;
195
196 return true;
197 }
198 return false;
199 }
200 }
201
202
InitialiseTunnel(const H323TransportAddress & remoteAddr,const H323TransportSecurity & sec)203 PBoolean H460_FeatureStd17::InitialiseTunnel(const H323TransportAddress & remoteAddr, const H323TransportSecurity & sec)
204 {
205 if (!m_handler)
206 m_handler = new H46017Handler(*EP, remoteAddr);
207
208 return m_handler->CreateNewTransport(sec);
209 }
210
UnInitialise()211 void H460_FeatureStd17::UnInitialise()
212 {
213 if (m_handler) {
214 delete m_handler;
215 m_handler = NULL;
216 }
217 }
218
219
220 ///////////////////////////////////////////////////////////////////////////////////
221 // Listening/Keep Alive Thread
222
223 class H46017TransportThread : public PThread
224 {
225 PCLASSINFO(H46017TransportThread, PThread)
226
227 public:
228 H46017TransportThread(H323EndPoint & endpoint, H46017Transport * transport);
229
230 protected:
231 void Main();
232
233 H46017Transport * transport;
234
235 };
236
237 /////////////////////////////////////////////////////////////////////////////
238
H46017TransportThread(H323EndPoint & ep,H46017Transport * t)239 H46017TransportThread::H46017TransportThread(H323EndPoint & ep, H46017Transport * t)
240 : PThread(ep.GetSignallingThreadStackSize(), AutoDeleteThread, NormalPriority, "H46017:%0x"),
241 transport(t)
242 {
243
244 transport->AttachThread(this);
245
246 // Start the Thread
247 Resume();
248 }
249
Main()250 void H46017TransportThread::Main()
251 {
252 PTRACE(3, "H46017\tStarted Listening Thread");
253
254 PBoolean ret = TRUE;
255 while ((transport->IsOpen()) && (!transport->CloseTransport())) {
256
257 ret = transport->HandleH46017Socket();
258
259 if (!ret && transport->CloseTransport()) { // Closing down Instruction
260 PTRACE(3, "H46017\tShutting down H46017 Thread");
261 transport->ConnectionLost(TRUE);
262
263 } else if (!ret) { // We have a socket failure wait 1 sec and try again.
264 PTRACE(3, "H46017\tConnection Lost! Retrying Connection..");
265 transport->ConnectionLost(TRUE);
266
267 if (transport->CloseTransport()) {
268 PTRACE(3, "H46017\tConnection Lost");
269 break;
270 } else {
271 PTRACE(3, "H46017\tConnection ReEstablished");
272 transport->ConnectionLost(FALSE);
273 }
274 }
275 }
276
277 PTRACE(3, "H46017\tTransport Closed");
278 }
279
280 ///////////////////////////////////////////////////////////////////////////////////////
281
282
283
H46017Transport(H323EndPoint & endpoint,PIPSocket::Address binding,H46017Handler * feat)284 H46017Transport::H46017Transport(H323EndPoint & endpoint,
285 PIPSocket::Address binding,
286 H46017Handler * feat
287 )
288 : H323TransportTCP(endpoint, binding),
289 ReadTimeOut(PMaxTimeInterval),
290 Feature(feat), remoteShutDown(false), closeTransport(false), m_signalProcess(NULL)
291 #ifdef H323_H46026
292 ,m_h46026tunnel(false), m_socketMgr(NULL), m_socketWrite(NULL)
293 #endif
294 {
295
296 }
297
~H46017Transport()298 H46017Transport::~H46017Transport()
299 {
300 Close();
301 }
302
FindH46017RAS(const H225_H323_UU_PDU & pdu,std::list<PBYTEArray> & ras)303 PBoolean FindH46017RAS(const H225_H323_UU_PDU & pdu, std::list<PBYTEArray> & ras)
304 {
305 if (pdu.HasOptionalField(H225_H323_UU_PDU::e_genericData)) {
306 const H225_ArrayOf_GenericData & data = pdu.m_genericData;
307 for (PINDEX i = 0; i < data.GetSize(); i++) {
308 if (data[i].m_id == H460_FeatureID(17)) {
309 H460_Feature feat((const H225_FeatureDescriptor &)data[i]);
310 for (PINDEX i = 0; i< feat.GetParameterCount(); ++i) {
311 H460_FeatureParameter & param = feat.GetFeatureParameter(i);
312 if (param.ID() == 1 && param.hasContent()) {
313 PASN_OctetString raw = param;
314 ras.push_back(raw.GetValue());
315 }
316 }
317 }
318 }
319 }
320 return (!ras.empty());
321 }
322
WriteRasPDU(const PBYTEArray & pdu)323 PBoolean H46017Transport::WriteRasPDU(const PBYTEArray & pdu)
324 {
325 if (remoteShutDown)
326 return false;
327
328 H323SignalPDU rasPDU;
329 rasPDU.BuildRasFacility();
330
331 rasPDU.m_h323_uu_pdu.IncludeOptionalField(H225_H323_UU_PDU::e_genericData);
332
333 H225_ArrayOf_GenericData & gdata = rasPDU.m_h323_uu_pdu.m_genericData;
334 int sz = gdata.GetSize();
335 gdata.SetSize(sz+1);
336 H225_GenericData & data = gdata[sz];
337
338 H460_FeatureStd feat = H460_FeatureStd(17);
339 PASN_OctetString encFrame;
340 encFrame.SetValue(pdu);
341 feat.Add(1,H460_FeatureContent(encFrame));
342 data = feat;
343
344 rasPDU.BuildQ931();
345
346 PTRACE(6, "H46017\tSend " << rasPDU);
347 return WriteTunnel(rasPDU);
348 }
349
350
HandleH46017Socket()351 PBoolean H46017Transport::HandleH46017Socket()
352 {
353 for (;;) {
354
355 if (!IsOpen())
356 return false;
357
358 H323SignalPDU rpdu;
359 if (!rpdu.Read(*this)) {
360 PTRACE(3, "H46017\tSocket Read Failure");
361 if (GetErrorNumber(PChannel::LastReadError) == 0) {
362 PTRACE(3, "H46017\tRemote SHUT DOWN or Intermediary Shutdown!");
363 closeTransport = true;
364 remoteShutDown = TRUE;
365 }
366 return false;
367 } else if (closeTransport) {
368 PTRACE(3, "H46017\tClosing Transport!");
369 return false;
370 } else {
371 // Keep alive Message
372 if (rpdu.GetQ931().GetMessageType() == Q931::NationalEscapeMsg) {
373 PTRACE(6,"H46017\tEscape received. Ignoring...");
374 continue;
375 }
376 #ifdef H323_H46026
377 if (m_h46026tunnel) {
378 m_socketMgr->SocketIn(rpdu.GetQ931());
379 continue;
380 } else
381 #endif
382 {
383 if (HandleH46017PDU(rpdu.GetQ931()))
384 continue;
385 }
386
387 PTRACE(5,"H46017\tMessage not Handled!");
388 }
389 }
390 }
391
HandleH46017PDU(const Q931 & q931)392 PBoolean H46017Transport::HandleH46017PDU(const Q931 & q931)
393 {
394 H323SignalPDU pdu;
395 pdu.LoadTunneledQ931(q931);
396 return HandleH46017PDU(pdu);
397 }
398
HandleH46017PDU(H323SignalPDU & pdu)399 PBoolean H46017Transport::HandleH46017PDU(H323SignalPDU & pdu)
400 {
401 // Inspect the signalling message to see if RAS
402 if (HandleH46017RAS(pdu))
403 return true;
404 else if (HandleH46017SignalPDU(pdu))
405 return true;
406 else
407 return false;
408 }
409
HandleH46017RAS(const H323SignalPDU & pdu)410 PBoolean H46017Transport::HandleH46017RAS(const H323SignalPDU & pdu)
411 {
412 std::list<PBYTEArray> ras;
413 if ((pdu.GetQ931().GetMessageType() == Q931::FacilityMsg) && FindH46017RAS(pdu.m_h323_uu_pdu, ras)) {
414 H46017RasTransport * rasTransport = Feature->GetRasTransport();
415 for (std::list<PBYTEArray>::iterator r = ras.begin(); r != ras.end(); ++r) {
416 if (!rasTransport->ReceivedPDU(*r))
417 return false;
418 }
419 ras.clear();
420 return true;
421 }
422 return false;
423 }
424
425 // Unfortunately we have to put the signaling messages onto a separate thread
426 // as the messages may block for several seconds.
HandleH46017SignalPDU(H323SignalPDU & pdu)427 PBoolean H46017Transport::HandleH46017SignalPDU(H323SignalPDU & pdu)
428 {
429 if (!m_signalProcess) {
430 m_signalProcess = PThread::Create(PCREATE_NOTIFIER(SignalProcess), 0,
431 PThread::AutoDeleteThread,
432 PThread::NormalPriority,
433 "h46017signal:%x");
434 }
435 signalMutex.Wait();
436 recdpdu.push(pdu);
437 signalMutex.Signal();
438 msgRecd.Signal();
439 return true;
440 }
441
SignalProcess(PThread &,H323_INT)442 void H46017Transport::SignalProcess(PThread &, H323_INT)
443 {
444 H323SignalPDU pdu;
445 PBoolean dataToProcess = false;
446 while (!closeTransport) {
447 msgRecd.Wait();
448 while (!closeTransport && !recdpdu.empty()) {
449 signalMutex.Wait();
450 if (!recdpdu.empty()) {
451 pdu = recdpdu.front();
452 dataToProcess = true;
453 recdpdu.pop();
454 }
455 signalMutex.Signal();
456 if (dataToProcess) {
457 HandleH46017SignallingPDU(pdu.GetQ931().GetCallReference(), pdu);
458 dataToProcess = false;
459 }
460 }
461 }
462 }
463
HandleH46017SignallingPDU(unsigned crv,H323SignalPDU & pdu)464 PBoolean H46017Transport::HandleH46017SignallingPDU(unsigned crv, H323SignalPDU & pdu)
465 {
466 H323Connection * connection = NULL;
467 if ((pdu.GetQ931().GetMessageType() == Q931::SetupMsg))
468 connection = HandleH46017SetupPDU(pdu);
469 else {
470 connectionsMutex.Wait();
471 for (PINDEX i = 0; i < endpoint.GetConnections().GetSize(); i++) {
472 H323Connection & conn = endpoint.GetConnections().GetDataAt(i);
473 if (conn.GetCallReference() == crv)
474 connection = &conn;
475 }
476 connectionsMutex.Signal();
477 }
478 if (!connection) {
479 PTRACE(2, "H46017\tConnection " << crv << " not found or could not process. Q931 not processed.");
480 return true;
481 }
482 if (!connection->HandleReceivedSignalPDU(true, pdu)) {
483 PTRACE(2, "H46017\tMessage not processed dropping call.");
484 }
485 return true;
486 }
487
HandleH46017SetupPDU(H323SignalPDU & pdu)488 H323Connection * H46017Transport::HandleH46017SetupPDU(H323SignalPDU & pdu)
489 {
490
491 unsigned callReference = pdu.GetQ931().GetCallReference();
492 PString callToken = endpoint.BuildConnectionToken(*this, callReference, TRUE);
493
494 H323Connection * connection = endpoint.CreateConnection(callReference, NULL, this, &pdu);
495 if (!connection) {
496 PTRACE(1, "H46017\tEndpoint could not create connection, " <<
497 "sending release complete PDU: callRef=" << callReference);
498 Q931 pdu;
499 pdu.BuildReleaseComplete(callReference, TRUE);
500 PBYTEArray rawData;
501 pdu.Encode(rawData);
502 WritePDU(rawData);
503 return NULL;
504 }
505
506 PTRACE(3, "H46017\tCreated new connection: " << callToken);
507 connectionsMutex.Wait();
508 endpoint.GetConnections().SetAt(callToken, connection);
509 connectionsMutex.Signal();
510
511 connection->AttachSignalChannel(callToken, this, TRUE);
512
513 return connection;
514 }
515
WritePDU(const PBYTEArray & pdu)516 PBoolean H46017Transport::WritePDU(const PBYTEArray & pdu)
517 {
518 PWaitAndSignal m(WriteMutex);
519 return H323TransportTCP::WritePDU(pdu);
520 }
521
WriteSignalPDU(const H323SignalPDU & pdu)522 PBoolean H46017Transport::WriteSignalPDU( const H323SignalPDU & pdu )
523 {
524 PTRACE(4, "H46017\tSending Tunnel\t" << pdu);
525
526 PPER_Stream strm;
527 const Q931 & q931 = pdu.GetQ931();
528 q931.Encode(strm);
529
530 if (WritePDU(strm))
531 return true;
532
533 PTRACE(1, "H46017\tTunnel write failed ("
534 << GetErrorNumber(PChannel::LastWriteError)
535 << "): " << GetErrorText(PChannel::LastWriteError));
536
537 return false;
538 }
539
ReadPDU(PBYTEArray & pdu)540 PBoolean H46017Transport::ReadPDU(PBYTEArray & pdu)
541 {
542 return H323TransportTCP::ReadPDU(pdu);
543 }
544
Connect()545 PBoolean H46017Transport::Connect()
546 {
547 if (closeTransport)
548 return true;
549
550 PTRACE(4, "H46017\tConnecting to remote");
551 if (!H323TransportTCP::Connect())
552 return false;
553
554 return true;
555 }
556
ConnectionLost(PBoolean established)557 void H46017Transport::ConnectionLost(PBoolean established)
558 {
559 PWaitAndSignal m(shutdownMutex);
560
561 if (closeTransport) {
562 // TODO Handle TCP socket reconnect
563 if (Feature)
564 Feature->TransportClosed();
565 return;
566 }
567 PBoolean lost = IsConnectionLost();
568 PTRACE(4,"H46017\tConnection lost " << established << " have " << lost);
569 }
570
IsConnectionLost() const571 PBoolean H46017Transport::IsConnectionLost() const
572 {
573 return Feature->IsConnectionLost();
574 }
575
Close()576 PBoolean H46017Transport::Close()
577 {
578 PWaitAndSignal m(shutdownMutex);
579
580 closeTransport = TRUE;
581
582 signalMutex.Wait();
583 while (!recdpdu.empty()) {
584 recdpdu.pop();
585 }
586 signalMutex.Signal();
587 msgRecd.Signal();
588
589 PTRACE(4, "H46017\tClosing H46017 NAT channel.");
590 return H323TransportTCP::Close();
591 }
592
CleanUpOnTermination()593 void H46017Transport::CleanUpOnTermination()
594 {
595 // Do nothing at the end of a call. This is a permanent connection
596 PTRACE(4, "H46017\tIgnore cleanup of H46017 NAT channel.");
597 }
598
IsOpen() const599 PBoolean H46017Transport::IsOpen () const
600 {
601 return H323Transport::IsOpen();
602 }
603
IsListening() const604 PBoolean H46017Transport::IsListening() const
605 {
606 if (h245listener == NULL)
607 return FALSE;
608
609 if (IsConnectionLost())
610 return FALSE;
611
612 return h245listener->IsOpen();
613 }
614
WriteTunnel(H323SignalPDU & msg)615 PBoolean H46017Transport::WriteTunnel(H323SignalPDU & msg)
616 {
617 if (!IsOpen()) return false;
618
619 #ifdef H323_H46026
620 if (m_h46026tunnel) {
621 m_socketMgr->SignalToSend(msg.GetQ931());
622 return true;
623 } else
624 #endif
625 return msg.Write(*this,NULL);
626 }
627
628 #ifdef H323_H46026
SetTunnel(H46026Tunnel * mgr)629 void H46017Transport::SetTunnel(H46026Tunnel * mgr)
630 {
631 m_socketMgr = mgr;
632 m_socketMgr->AttachTransport(this);
633
634 if (!m_socketWrite)
635 m_socketWrite = PThread::Create(PCREATE_NOTIFIER(SocketWrite), 0, PThread::AutoDeleteThread, PThread::NormalPriority, "H.460.26 Writer");
636
637 m_h46026tunnel = true;
638 }
639
SocketWrite(PThread &,H323_INT)640 void H46017Transport::SocketWrite(PThread &, H323_INT)
641 {
642 PBYTEArray tpkt(10004); // 10K buffer with RFC1006 Header
643 tpkt[0] = 3;
644 tpkt[1] = 0;
645
646 PINDEX sz = 0;
647 int packetLength = 0;
648 while (!closeTransport) {
649 if (m_socketMgr->SocketOut(tpkt.GetPointer()+4,sz)) {
650 packetLength = sz + 4;
651 tpkt[2] = (BYTE)(packetLength >> 8);
652 tpkt[3] = (BYTE)packetLength;
653 Write((const BYTE *)tpkt, packetLength);
654 } else {
655 PThread::Sleep(2);
656 }
657 }
658 tpkt.SetSize(0);
659 PTRACE(2,"H46017\tTunnel Write Thread ended");
660 }
661 #endif
662
663 /////////////////////////////////////////////////////////////////////////////
664
H46017Handler(H323EndPoint & _ep,const H323TransportAddress & _remoteAddress)665 H46017Handler::H46017Handler(H323EndPoint & _ep, const H323TransportAddress & _remoteAddress)
666 : ep(_ep), curtransport(NULL), ras(NULL), remoteAddress(_remoteAddress),
667 connectionlost(false), openTransport(false)
668 #ifdef H323_H46026
669 , m_h46026tunnel(false)
670 #endif
671 {
672 PTRACE(4, "H46017\tCreating H46017 Feature.");
673
674 PIPSocket::Address remAddr;
675 remoteAddress.GetIpAddress(remAddr);
676 localBindAddress = PIPSocket::GetRouteInterfaceAddress(remAddr);
677 }
678
~H46017Handler()679 H46017Handler::~H46017Handler()
680 {
681 if (curtransport != NULL) {
682 curtransport->Close();
683 curtransport = NULL;
684 }
685
686 if (ras != NULL) {
687 delete ras;
688 ras = NULL;
689 }
690 }
691
692
CreateNewTransport(const H323TransportSecurity & security)693 PBoolean H46017Handler::CreateNewTransport(const H323TransportSecurity & security)
694 {
695 PTRACE(5, "H46017\tCreating Transport.");
696
697 curtransport = new H46017Transport(ep, PIPSocket::Address::GetAny(remoteAddress.GetIpVersion()), this);
698
699 curtransport->InitialiseSecurity(&security);
700 curtransport->SetRemoteAddress(remoteAddress);
701
702 if (curtransport->Connect()) {
703 PTRACE(3, "H46017\tConnected to " << curtransport->GetRemoteAddress());
704 new H46017TransportThread(curtransport->GetEndPoint(), curtransport);
705 openTransport = true;
706 return TRUE;
707 }
708
709 PTRACE(3, "H46017\tTransport Failure " << curtransport->GetRemoteAddress());
710 delete curtransport;
711 curtransport = NULL;
712 return FALSE;
713 }
714
GetEndPoint()715 H323EndPoint * H46017Handler::GetEndPoint()
716 {
717 return &ep;
718 }
719
GetTunnelBindAddress() const720 H323TransportAddress H46017Handler::GetTunnelBindAddress() const
721 {
722 return curtransport->GetLocalAddress();
723 }
724
GetTransport()725 H46017Transport * H46017Handler::GetTransport()
726 {
727 return curtransport;
728 }
729
AttachRasTransport(H46017RasTransport * _ras)730 void H46017Handler::AttachRasTransport(H46017RasTransport * _ras)
731 {
732 ras = _ras;
733 if (!ras)
734 curtransport->Close();
735 }
736
GetRasTransport()737 H46017RasTransport * H46017Handler::GetRasTransport()
738 {
739 return ras;
740 }
741
RegisterGatekeeper()742 PBoolean H46017Handler::RegisterGatekeeper()
743 {
744 if (!curtransport->IsOpen())
745 return false;
746
747 if (ras) delete ras;
748
749 PString dummyAddress("0.0.0.0:0");
750 if (!ep.SetGatekeeper(dummyAddress, new H46017RasTransport(ep, this)))
751 return false;
752
753 return true;
754 }
755
TransportClosed()756 void H46017Handler::TransportClosed()
757 {
758 if (ras)
759 ras->Close();
760 }
761
762 #ifdef H323_H46026
SetH46026Tunnel(PBoolean tunnel)763 void H46017Handler::SetH46026Tunnel(PBoolean tunnel)
764 {
765 m_h46026tunnel = tunnel;
766 }
767
IsH46026Tunnel()768 PBoolean H46017Handler::IsH46026Tunnel()
769 {
770 return m_h46026tunnel;
771 }
772 #endif
773
774 /////////////////////////////////////////////////////////////////////////
775
H46017RasTransport(H323EndPoint & endpoint,H46017Handler * handler)776 H46017RasTransport::H46017RasTransport(H323EndPoint & endpoint, H46017Handler * handler)
777 : H323TransportUDP(endpoint), m_handler(handler), shutdown(false)
778 {
779 endpoint.SetSendGRQ(false);
780 m_handler->AttachRasTransport(this);
781 }
782
~H46017RasTransport()783 H46017RasTransport::~H46017RasTransport()
784 {
785
786 }
787
SetRemoteAddress(const H323TransportAddress &)788 PBoolean H46017RasTransport::SetRemoteAddress(const H323TransportAddress & /*address*/)
789 {
790 return true;
791 }
792
GetLocalAddress() const793 H323TransportAddress H46017RasTransport::GetLocalAddress() const
794 {
795 return H323TransportAddress("0.0.0.0:0");
796 }
797
GetRemoteAddress() const798 H323TransportAddress H46017RasTransport::GetRemoteAddress() const
799 {
800 return H323TransportAddress("0.0.0.0:0");
801 }
802
SetUpTransportPDU(H225_TransportAddress & pdu,PBoolean,H323Connection *) const803 void H46017RasTransport::SetUpTransportPDU(H225_TransportAddress & pdu, PBoolean /*localTsap*/, H323Connection * /*connection*/) const
804 {
805 H323TransportAddress transAddr = GetLocalAddress();
806 transAddr.SetPDU(pdu);
807 }
808
Connect()809 PBoolean H46017RasTransport::Connect()
810 {
811 return true;
812 }
813
Close()814 PBoolean H46017RasTransport::Close()
815 {
816 if (!shutdown) {
817 shutdown = true;
818 msgRecd.Signal();
819 }
820 return true;
821 }
822
823
ReceivedPDU(const PBYTEArray & pdu)824 PBoolean H46017RasTransport::ReceivedPDU(const PBYTEArray & pdu)
825 {
826 recdpdu = pdu;
827 msgRecd.Signal();
828 return true;
829 }
830
ReadPDU(PBYTEArray & pdu)831 PBoolean H46017RasTransport::ReadPDU(PBYTEArray & pdu)
832 {
833 msgRecd.Wait();
834 if (shutdown)
835 return false;
836
837 pdu = recdpdu;
838 return true;
839 }
840
WritePDU(const PBYTEArray & pdu)841 PBoolean H46017RasTransport::WritePDU(const PBYTEArray & pdu)
842 {
843 return m_handler->GetTransport()->WriteRasPDU(pdu);
844 }
845
DiscoverGatekeeper(H323Gatekeeper &,H323RasPDU &,const H323TransportAddress &)846 PBoolean H46017RasTransport::DiscoverGatekeeper(H323Gatekeeper & /*gk*/, H323RasPDU & /*pdu*/, const H323TransportAddress & /*address*/)
847 {
848 return true;
849 }
850
IsRASTunnelled()851 PBoolean H46017RasTransport::IsRASTunnelled()
852 {
853 return true;
854 }
855
GetErrorCode(ErrorGroup) const856 PChannel::Errors H46017RasTransport::GetErrorCode(ErrorGroup /*group*/) const
857 {
858 if (shutdown)
859 return PChannel::NotOpen;
860
861 return PChannel::Interrupted;
862 }
863
CleanUpOnTermination()864 void H46017RasTransport::CleanUpOnTermination()
865 {
866 PTRACE(4,"H46017\tRAS transport cleanup");
867 m_handler->AttachRasTransport(NULL);
868 H323Transport::CleanUpOnTermination();
869 }
870
871 #endif // H323_H46017
872