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