1 /*
2  * h323.cxx
3  *
4  * H.323 protocol 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  * Contributor(s): ______________________________________.
25  *
26  * $Id$
27 
28  */
29 
30 #include <ptlib.h>
31 
32 
33 #ifdef __GNUC__
34 #pragma implementation "h323con.h"
35 #endif
36 
37 #include "h323con.h"
38 
39 #include "h323ep.h"
40 #include "h323neg.h"
41 #include "h323rtp.h"
42 
43 #ifdef H323_H450
44 #include "h450/h4501.h"
45 #include "h450/h4503.h"
46 #include "h450/h4504.h"
47 #include "h450/h45011.h"
48 #include "h450/h450pdu.h"
49 #endif
50 
51 #ifdef H323_H460
52 #include "h460/h460.h"
53 #include "h460/h4601.h"
54 
55 #ifdef H323_H46018
56 #include "h460/h460_std18.h"
57 #include "h460/h46018_h225.h"
58 #include "h460/h46019.h"
59 #endif
60 
61 #ifdef H323_H46024B
62 #include "h460/h46024b.h"
63 #endif
64 #endif
65 
66 #ifdef P_STUN
67 #include <ptclib/random.h>
68 #endif
69 
70 #include "gkclient.h"
71 #include "rfc2833.h"
72 
73 #ifdef H323_T120
74 #include "t120proto.h"
75 #endif
76 
77 #ifdef H323_T38
78 #include "t38proto.h"
79 #endif
80 
81 #ifdef H323_H224
82 #include "h323h224.h"
83 #endif
84 
85 #ifdef H323_FILE
86 #include "h323filetransfer.h"
87 #endif
88 
89 #ifdef H323_AEC
90 #include <etc/h323aec.h>
91 #endif
92 
93 #include "h235auth.h"
94 
95 const PTimeInterval MonitorCallStatusTime(0, 10); // Seconds
96 
97 #define new PNEW
98 
99 #ifdef H323_SIGNAL_AGGREGATE
100 
101 class AggregatedH225Handle : public H323AggregatedH2x5Handle
102 {
103 //  PCLASSINFO(AggregatedH225Handle, H323AggregatedH2x5Handle)
104   public:
AggregatedH225Handle(H323Transport & _transport,H323Connection & _connection)105     AggregatedH225Handle(H323Transport & _transport, H323Connection & _connection)
106       : H323AggregatedH2x5Handle(_transport, _connection)
107     {
108     }
109 
~AggregatedH225Handle()110     ~AggregatedH225Handle()
111     {
112     }
113 
OnRead()114     PBoolean OnRead()
115     {
116       PBoolean ret = H323AggregatedH2x5Handle::OnRead();
117       if (connection.controlChannel == NULL)
118         connection.MonitorCallStatus();
119       return ret;
120     }
121 
HandlePDU(PBoolean ok,PBYTEArray & dataPDU)122     PBoolean HandlePDU(PBoolean ok, PBYTEArray & dataPDU)
123     {
124       H323SignalPDU pdu;
125       if (ok && dataPDU.GetSize() > 0)
126         ok = pdu.ProcessReadData(transport, dataPDU);
127       return connection.HandleReceivedSignalPDU(ok, pdu);
128     }
129 
OnClose()130     void OnClose()
131     {  DeInit(); }
132 
DeInit()133     void DeInit()
134     {
135       if (connection.controlChannel == NULL) {
136         connection.endSessionReceived.Signal();
137       }
138     }
139 };
140 
141 class AggregatedH245Handle : public H323AggregatedH2x5Handle
142 {
143 //  PCLASSINFO(AggregatedH245Handle, H323AggregatedH2x5Handle)
144   public:
AggregatedH245Handle(H323Transport & _transport,H323Connection & _connection)145     AggregatedH245Handle(H323Transport & _transport, H323Connection & _connection)
146       : H323AggregatedH2x5Handle(_transport, _connection)
147     {
148     }
149 
~AggregatedH245Handle()150     ~AggregatedH245Handle()
151     {
152     }
153 
OnRead()154     PBoolean OnRead()
155     {
156       PBoolean ret = H323AggregatedH2x5Handle::OnRead();
157       connection.MonitorCallStatus();
158       return ret;
159     }
160 
HandlePDU(PBoolean ok,PBYTEArray & pdu)161     PBoolean HandlePDU(PBoolean ok, PBYTEArray & pdu)
162     {
163       PPER_Stream strm(pdu);
164       return connection.HandleReceivedControlPDU(ok, strm);
165     }
166 
OnClose()167     void OnClose()
168     {
169       PPER_Stream strm;
170       connection.HandleReceivedControlPDU(FALSE, strm);
171     }
172 
DeInit()173     void DeInit()
174     {
175       connection.EndHandleControlChannel();
176     }
177 };
178 
179 #endif
180 
181 /////////////////////////////////////////////////////////////////////////////
182 
183 #if PTRACING
operator <<(ostream & o,H323Connection::CallEndReason r)184 ostream & operator<<(ostream & o, H323Connection::CallEndReason r)
185 {
186   static const char * const CallEndReasonNames[H323Connection::NumCallEndReasons] = {
187     "EndedByLocalUser",         /// Local endpoint application cleared call
188     "EndedByNoAccept",          /// Local endpoint did not accept call OnIncomingCall()=FALSE
189     "EndedByAnswerDenied",      /// Local endpoint declined to answer call
190     "EndedByRemoteUser",        /// Remote endpoint application cleared call
191     "EndedByRefusal",           /// Remote endpoint refused call
192     "EndedByNoAnswer",          /// Remote endpoint did not answer in required time
193     "EndedByCallerAbort",       /// Remote endpoint stopped calling
194     "EndedByTransportFail",     /// Transport error cleared call
195     "EndedByConnectFail",       /// Transport connection failed to establish call
196     "EndedByGatekeeper",        /// Gatekeeper has cleared call
197     "EndedByNoUser",            /// Call failed as could not find user (in GK)
198     "EndedByNoBandwidth",       /// Call failed as could not get enough bandwidth
199     "EndedByCapabilityExchange",/// Could not find common capabilities
200     "EndedByCallForwarded",     /// Call was forwarded using FACILITY message
201     "EndedBySecurityDenial",    /// Call failed a security check and was ended
202     "EndedByLocalBusy",         /// Local endpoint busy
203     "EndedByLocalCongestion",   /// Local endpoint congested
204     "EndedByRemoteBusy",        /// Remote endpoint busy
205     "EndedByRemoteCongestion",  /// Remote endpoint congested
206     "EndedByUnreachable",       /// Could not reach the remote party
207     "EndedByNoEndPoint",        /// The remote party is not running an endpoint
208     "EndedByHostOffline",       /// The remote party host off line
209     "EndedByTemporaryFailure",  /// The remote failed temporarily app may retry
210     "EndedByQ931Cause",         /// The remote ended the call with unmapped Q.931 cause code
211     "EndedByDurationLimit",     /// Call cleared due to an enforced duration limit
212     "EndedByInvalidConferenceID", /// Call cleared due to invalid conference ID
213     "EndedByOSPRefusal"         // Call cleared as OSP server unable or unwilling to route
214   };
215 
216   if ((PINDEX)r >= PARRAYSIZE(CallEndReasonNames))
217     o << "InvalidCallEndReason<" << (unsigned)r << '>';
218   else if (CallEndReasonNames[r] == NULL)
219     o << "CallEndReason<" << (unsigned)r << '>';
220   else
221     o << CallEndReasonNames[r];
222   return o;
223 }
224 
225 
operator <<(ostream & o,H323Connection::AnswerCallResponse s)226 ostream & operator<<(ostream & o, H323Connection::AnswerCallResponse s)
227 {
228   static const char * const AnswerCallResponseNames[H323Connection::NumAnswerCallResponses] = {
229     "AnswerCallNow",
230     "AnswerCallDenied",
231     "AnswerCallPending",
232     "AnswerCallDeferred",
233     "AnswerCallAlertWithMedia",
234     "AnswerCallDeferredWithMedia",
235     "AnswerCallNowWithAlert"
236   };
237   if ((PINDEX)s >= PARRAYSIZE(AnswerCallResponseNames))
238     o << "InvalidAnswerCallResponse<" << (unsigned)s << '>';
239   else if (AnswerCallResponseNames[s] == NULL)
240     o << "AnswerCallResponse<" << (unsigned)s << '>';
241   else
242     o << AnswerCallResponseNames[s];
243   return o;
244 }
245 
246 
operator <<(ostream & o,H323Connection::SendUserInputModes m)247 ostream & operator<<(ostream & o, H323Connection::SendUserInputModes m)
248 {
249   static const char * const SendUserInputModeNames[H323Connection::NumSendUserInputModes] = {
250     "SendUserInputAsQ931",
251     "SendUserInputAsString",
252     "SendUserInputAsTone",
253     "SendUserInputAsRFC2833",
254     "SendUserInputAsSeparateRFC2833"
255 #ifdef H323_H249
256     ,"SendUserInputAsNavigation",
257     "SendUserInputAsSoftkey",
258     "SendUserInputAsPointDevice",
259     "SendUserInputAsModal"
260 #endif
261   };
262 
263   if ((PINDEX)m >= PARRAYSIZE(SendUserInputModeNames))
264     o << "InvalidSendUserInputMode<" << (unsigned)m << '>';
265   else if (SendUserInputModeNames[m] == NULL)
266     o << "SendUserInputMode<" << (unsigned)m << '>';
267   else
268     o << SendUserInputModeNames[m];
269   return o;
270 }
271 
272 
273 const char * const H323Connection::ConnectionStatesNames[NumConnectionStates] = {
274   "NoConnectionActive",
275   "AwaitingGatekeeperAdmission",
276   "AwaitingTransportConnect",
277   "AwaitingSignalConnect",
278   "AwaitingLocalAnswer",
279   "HasExecutedSignalConnect",
280   "EstablishedConnection",
281   "ShuttingDownConnection"
282 };
283 
284 const char * const H323Connection::FastStartStateNames[NumFastStartStates] = {
285   "FastStartDisabled",
286   "FastStartInitiate",
287   "FastStartResponse",
288   "FastStartAcknowledged"
289 };
290 #endif
291 #ifdef H323_H460
ReceiveSetupFeatureSet(const H323Connection * connection,const H225_Setup_UUIE & pdu,bool nonCall=false)292 static bool ReceiveSetupFeatureSet(const H323Connection * connection, const H225_Setup_UUIE & pdu, bool nonCall = false)
293 {
294     H225_FeatureSet fs;
295     PBoolean hasFeaturePDU = FALSE;
296 
297     if (pdu.HasOptionalField(H225_Setup_UUIE::e_neededFeatures)) {
298         fs.IncludeOptionalField(H225_FeatureSet::e_neededFeatures);
299         H225_ArrayOf_FeatureDescriptor & fsn = fs.m_neededFeatures;
300         fsn = pdu.m_neededFeatures;
301         hasFeaturePDU = TRUE;
302     }
303 
304     if (pdu.HasOptionalField(H225_Setup_UUIE::e_desiredFeatures)) {
305         fs.IncludeOptionalField(H225_FeatureSet::e_desiredFeatures);
306         H225_ArrayOf_FeatureDescriptor & fsn = fs.m_desiredFeatures;
307         fsn = pdu.m_desiredFeatures;
308         hasFeaturePDU = TRUE;
309     }
310 
311     if (pdu.HasOptionalField(H225_Setup_UUIE::e_supportedFeatures)) {
312         fs.IncludeOptionalField(H225_FeatureSet::e_supportedFeatures);
313         H225_ArrayOf_FeatureDescriptor & fsn = fs.m_supportedFeatures;
314         fsn = pdu.m_supportedFeatures;
315         hasFeaturePDU = TRUE;
316     }
317 
318     if (hasFeaturePDU && (!nonCall || connection->FeatureSetSupportNonCallService(fs))) {
319         connection->OnReceiveFeatureSet(H460_MessageType::e_setup, fs);
320         return true;
321 
322     } else if (!nonCall)
323         connection->DisableFeatureSet(H460_MessageType::e_setup);
324 
325     return false;
326 }
327 
328 template <typename PDUType>
ReceiveFeatureData(const H323Connection * connection,unsigned code,const PDUType & pdu)329 static void ReceiveFeatureData(const H323Connection * connection, unsigned code, const PDUType & pdu)
330 {
331     if (pdu.m_h323_uu_pdu.HasOptionalField(H225_H323_UU_PDU::e_genericData)) {
332         H225_FeatureSet fs;
333         fs.IncludeOptionalField(H225_FeatureSet::e_supportedFeatures);
334         H225_ArrayOf_FeatureDescriptor & fsn = fs.m_supportedFeatures;
335         const H225_ArrayOf_GenericData & data = pdu.m_h323_uu_pdu.m_genericData;
336         for (PINDEX i=0; i < data.GetSize(); i++) {
337              PINDEX lastPos = fsn.GetSize();
338              fsn.SetSize(lastPos+1);
339              fsn[lastPos] = (H225_FeatureDescriptor &)data[i];
340         }
341         connection->OnReceiveFeatureSet(code, fs, true);
342     }
343 }
344 #endif
345 
346 template <typename PDUType>
ReceiveFeatureSet(const H323Connection * connection,unsigned code,const PDUType & pdu)347 static void ReceiveFeatureSet(const H323Connection * connection, unsigned code, const PDUType & pdu)
348 {
349     if (pdu.HasOptionalField(PDUType::e_featureSet))
350       connection->OnReceiveFeatureSet(code, pdu.m_featureSet);
351 }
352 
353 template <typename PDUType>
ReceiveAuthenticatorPDU(const H323Connection * connection,const PDUType & pdu,unsigned code)354 static PBoolean ReceiveAuthenticatorPDU(const H323Connection * connection,
355                                    const PDUType & pdu, unsigned code)
356 {
357 
358 PBoolean AuthResult = FALSE;
359 H235Authenticators authenticators = connection->GetEPAuthenticators();
360 PBYTEArray strm;
361 
362   if (!pdu.HasOptionalField(PDUType::e_tokens) && !pdu.HasOptionalField(PDUType::e_cryptoTokens)) {
363         PTRACE(2, "H235EP\tReceived unsecured EPAuthentication message (no crypto tokens),"
364             " expected one of:\n" << setfill(',') << connection->GetEPAuthenticators() << setfill(' '));
365 #ifdef H323_H235
366         if (H235Authenticators::GetEncryptionPolicy() == 2) {
367            PTRACE(2, "H235EP\tCall rejected due to Media Encryption Policy!");
368            return false;
369         }
370 #endif
371        return connection->OnEPAuthenticationFailed(H235Authenticator::e_Absent);
372   } else {
373 
374     H235Authenticator::ValidationResult result = authenticators.ValidateSignalPDU(code,
375                                                     pdu.m_tokens, pdu.m_cryptoTokens,strm);
376       if (result == H235Authenticator::e_Failed) {
377           PTRACE(4, "H235EP\tSecurity Failure!");
378           return false;
379       }  else if (result == H235Authenticator::e_OK) {
380           PTRACE(4, "H235EP\tAuthentication succeeded");
381           AuthResult = TRUE;
382       }
383       return AuthResult ? TRUE : connection->OnEPAuthenticationFailed(result);
384   }
385 }
386 
387 #ifdef H323_H46018
388 const char * H46018OID = "0.0.8.460.18.0.1";
389 const char * H46019OID = "0.0.8.460.19.0.1";
390 const unsigned defH46019payload = 127;
391 #endif
392 
393 #ifdef H323_H46024A
394 const char * H46024AOID = "0.0.8.460.24.1";
395 #endif
396 #ifdef H323_H46024B
397 const char * H46024BOID = "0.0.8.460.24.2";
398 #endif
399 
H323Connection(H323EndPoint & ep,unsigned ref,unsigned options)400 H323Connection::H323Connection(H323EndPoint & ep,
401                                unsigned ref,
402                                unsigned options)
403   : endpoint(ep),
404     localAliasNames(ep.GetAliasNames()),
405     localPartyName(ep.GetLocalUserName()),
406 	localLanguages(ep.GetLocalLanguages()),
407     localCapabilities(ep.GetCapabilities()),
408     gkAccessTokenOID(ep.GetGkAccessTokenOID()),
409     alertingTime(0),
410     connectedTime(0),
411     callEndTime(0),
412     reverseMediaOpenTime(0),
413     noMediaTimeOut(ep.GetNoMediaTimeout().GetMilliSeconds()),
414     roundTripDelayRate(ep.GetRoundTripDelayRate().GetMilliSeconds()),
415     releaseSequence(ReleaseSequenceUnknown)
416     ,EPAuthenticators(ep.CreateEPAuthenticators())
417 #ifdef H323_H239
418     ,h239SessionID(0)
419 #endif
420 #ifdef H323_H460
421     ,features(ep.GetFeatureSet())
422 #endif
423 {
424   localAliasNames.MakeUnique();
425 
426   callAnswered = FALSE;
427   gatekeeperRouted = FALSE;
428   distinctiveRing = 0;
429   callReference = ref;
430   remoteCallWaiting = -1;
431 
432   h225version = H225_PROTOCOL_VERSION;
433   h245version = H245_PROTOCOL_VERSION;
434   h245versionSet = FALSE;
435 
436   signallingChannel = NULL;
437   controlChannel = NULL;
438 
439 #ifdef H323_H450
440   holdAudioMediaChannel = NULL;
441   holdVideoMediaChannel = NULL;
442   isConsultationTransfer = FALSE;
443   isCallIntrusion = FALSE;
444   callIntrusionProtectionLevel = endpoint.GetCallIntrusionProtectionLevel();
445 
446   mwiInformation.mwiCtrId = ep.GetMWIMessageCentre();
447   mwiInformation.mwiUser = ep.GetLocalUserName();
448 #endif
449 
450   switch (options&H245TunnelingOptionMask) {
451     case H245TunnelingOptionDisable :
452       h245Tunneling = FALSE;
453       break;
454 
455     case H245TunnelingOptionEnable :
456       h245Tunneling = TRUE;
457       break;
458 
459     default :
460       h245Tunneling = !ep.IsH245TunnelingDisabled();
461       break;
462   }
463 
464   h245TunnelTxPDU = NULL;
465   h245TunnelRxPDU = NULL;
466   alertingPDU = NULL;
467   connectPDU = NULL;
468 
469   connectionState = NoConnectionActive;
470   callEndReason = NumCallEndReasons;
471   q931Cause = Q931::ErrorInCauseIE;
472 
473   bandwidthAvailable = endpoint.GetInitialBandwidth();
474 
475   useQ931Display = endpoint.UseQ931Display();
476 
477   uuiesRequested = 0; // Empty set
478   addAccessTokenToSetup = TRUE; // Automatic inclusion of ACF access token in SETUP
479   sendUserInputMode = endpoint.GetSendUserInputMode();
480 
481   mediaWaitForConnect = FALSE;
482   transmitterSidePaused = FALSE;
483 
484   switch (options&FastStartOptionMask) {
485     case FastStartOptionDisable :
486       fastStartState = FastStartDisabled;
487       break;
488 
489     case FastStartOptionEnable :
490       fastStartState = FastStartInitiate;
491       break;
492 
493     default :
494       fastStartState = ep.IsFastStartDisabled() ? FastStartDisabled : FastStartInitiate;
495       break;
496   }
497 
498   mustSendDRQ = FALSE;
499   earlyStart = FALSE;
500   enableMERAHack = FALSE;
501 
502 #ifdef H323_T120
503   startT120 = TRUE;
504 #endif
505 
506 #ifdef H323_H224
507   startH224 = FALSE;
508 #endif
509 
510   lastPDUWasH245inSETUP = FALSE;
511   endSessionNeeded = FALSE;
512   endSessionSent = FALSE;
513 
514   switch (options&H245inSetupOptionMask) {
515     case H245inSetupOptionDisable :
516       doH245inSETUP = FALSE;
517       break;
518 
519     case H245inSetupOptionEnable :
520       doH245inSETUP = TRUE;
521       break;
522 
523     default :
524       doH245inSETUP = !ep.IsH245inSetupDisabled();
525       break;
526   }
527 
528   doH245QoS = !ep.IsH245QoSDisabled();
529 
530 #ifdef H323_AUDIO_CODECS
531   remoteMaxAudioDelayJitter = 0;
532   minAudioJitterDelay = endpoint.GetMinAudioJitterDelay();
533   maxAudioJitterDelay = endpoint.GetMaxAudioJitterDelay();
534 #endif
535 
536   switch (options&DetectInBandDTMFOptionMask) {
537     case DetectInBandDTMFOptionDisable :
538       detectInBandDTMF = FALSE;
539       break;
540 
541     case DetectInBandDTMFOptionEnable :
542       detectInBandDTMF = TRUE;
543       break;
544 
545     default :
546       detectInBandDTMF = !ep.DetectInBandDTMFDisabled();
547       break;
548   }
549 
550   masterSlaveDeterminationProcedure = new H245NegMasterSlaveDetermination(endpoint, *this);
551   capabilityExchangeProcedure = new H245NegTerminalCapabilitySet(endpoint, *this);
552   logicalChannels = new H245NegLogicalChannels(endpoint, *this);
553   requestModeProcedure = new H245NegRequestMode(endpoint, *this);
554   roundTripDelayProcedure = new H245NegRoundTripDelay(endpoint, *this);
555 
556 #ifdef H323_H450
557   h450dispatcher = new H450xDispatcher(*this);
558   h4502handler = new H4502Handler(*this, *h450dispatcher);
559   h4503handler = new H4503Handler(*this, *h450dispatcher);
560   h4504handler = new H4504Handler(*this, *h450dispatcher);
561   h4506handler = new H4506Handler(*this, *h450dispatcher);
562   h45011handler = new H45011Handler(*this, *h450dispatcher);
563 #endif
564 
565   rfc2833InBandDTMF = !ep.RFC2833InBandDTMFDisabled();
566   if (rfc2833InBandDTMF)
567     rfc2833handler = new OpalRFC2833(PCREATE_NOTIFIER(OnUserInputInlineRFC2833));
568   else
569     rfc2833handler = NULL;
570 
571   extendedUserInput = !ep.ExtendedUserInputDisabled();
572 
573 #ifdef H323_T120
574   t120handler = NULL;
575 #endif
576 
577 #ifdef H323_T38
578   t38handler = NULL;
579 #endif
580 
581   endSync = NULL;
582 #ifdef P_DTMF
583   dtmfTones = PString();
584 #endif
585   remoteIsNAT = false;
586   NATsupport =  true;
587   sameNAT = false;
588 
589   AuthenticationFailed = FALSE;
590   hasAuthentication = FALSE;
591 
592   // set aggregation options
593 #ifdef H323_RTP_AGGREGATE
594   useRTPAggregation        = (options & RTPAggregationMask)        != RTPAggregationDisable;
595 #endif
596 #ifdef H323_SIGNAL_AGGREGATE
597   signalAggregator = NULL;
598   controlAggregator = NULL;
599   useSignallingAggregation = (options & SignallingAggregationMask) != SignallingAggregationDisable;
600 #endif
601 
602 #ifdef H323_AEC
603     aec = NULL;
604 #endif
605 
606 #ifdef H323_H460
607   disableH460 = ep.FeatureSetDisabled();
608   features->LoadFeatureSet(H460_Feature::FeatureSignal,this);
609 
610 #ifdef H323_H460IM
611   m_IMsupport = false;
612   m_IMsession = false;
613   m_IMcall = false;
614   m_IMmsg = PString();
615 #endif
616 
617 #ifdef H323_H4609
618   m_h4609enabled = false;
619   m_h4609Final = false;
620 #endif
621 #ifdef H323_H46017
622   m_maintainConnection = ep.RegisteredWithH46017();
623 #else
624   m_maintainConnection = false;
625 #endif
626 
627 #ifdef H323_H46018
628   m_H46019CallReceiver = false;
629   m_H46019enabled = false;
630   m_H46019multiplex = false;
631   m_H46019offload = false;
632   m_h245Connect = false;
633 #endif
634 #ifdef H323_H46024A
635   m_H46024Aenabled = false;
636   m_H46024Ainitator = false;
637   m_H46024Astate = 0;
638 #endif
639 #ifdef H323_H46024B
640   m_H46024Benabled = false;
641   m_H46024Bstate = 0;
642 #endif
643 #ifdef H323_H46026
644   m_H46026enabled = false;
645 #endif
646 #ifdef H323_H461
647   m_H461Mode = e_h461EndpointCall;
648 #endif
649 #endif
650 
651   nonCallConnection = FALSE;
652 }
653 
654 
~H323Connection()655 H323Connection::~H323Connection()
656 {
657 
658   delete masterSlaveDeterminationProcedure;
659   delete capabilityExchangeProcedure;
660   delete logicalChannels;
661   delete requestModeProcedure;
662   delete roundTripDelayProcedure;
663 #ifdef H323_AEC
664   delete aec;
665 #endif
666 #ifdef H323_H450
667   delete h450dispatcher;
668 #endif
669   if (rfc2833handler)
670     delete rfc2833handler;
671 #ifdef H323_T120
672   delete t120handler;
673 #endif
674 #ifdef H323_T38
675   delete t38handler;
676 #endif
677   if (!m_maintainConnection)
678     delete signallingChannel;
679 
680   delete controlChannel;
681   delete alertingPDU;
682   delete connectPDU;
683 #ifdef H323_H450
684   delete holdAudioMediaChannel;
685   delete holdVideoMediaChannel;
686 #endif
687 #ifdef H323_H460
688   delete features;
689 #ifdef H323_H4609
690   if (m_h4609Stats.GetSize() > 0) {
691     H4609Statistics * stat = m_h4609Stats.Dequeue();
692     while (stat) {
693         delete stat;
694         stat = m_h4609Stats.Dequeue();
695     }
696   }
697 #endif
698 #endif
699 #ifdef P_STUN
700     m_NATSockets.clear();
701 #endif
702 
703   PTRACE(3, "H323\tConnection " << callToken << " deleted.");
704 
705   if (endSync != NULL)
706     endSync->Signal();
707 }
708 
709 
Lock()710 PBoolean H323Connection::Lock()
711 {
712   outerMutex.Wait();
713 
714   // If shutting down don't try and lock, just return failed. If not then lock
715   // it but do second test for shut down to avoid a possible race condition.
716 
717   if (connectionState == ShuttingDownConnection) {
718     outerMutex.Signal();
719     return FALSE;
720   }
721 
722   innerMutex.Wait();
723   return TRUE;
724 }
725 
726 
TryLock()727 int H323Connection::TryLock()
728 {
729   if (!outerMutex.Wait(0))
730     return -1;
731 
732   if (connectionState == ShuttingDownConnection) {
733     outerMutex.Signal();
734     return 0;
735   }
736 
737   innerMutex.Wait();
738   return 1;
739 }
740 
741 
Unlock()742 void H323Connection::Unlock()
743 {
744   innerMutex.Signal();
745   outerMutex.Signal();
746 }
747 
748 
SetCallEndReason(CallEndReason reason,PSyncPoint * sync)749 void H323Connection::SetCallEndReason(CallEndReason reason, PSyncPoint * sync)
750 {
751   // Only set reason if not already set to something
752   if (callEndReason == NumCallEndReasons) {
753     PTRACE(3, "H323\tCall end reason for " << callToken << " set to " << reason);
754     callEndReason = reason;
755   }
756 
757   // only set the sync point if it is NULL
758   if (endSync == NULL)
759     endSync = sync;
760   else
761     PAssert(sync == NULL, "SendCallEndReason called to overwrite syncpoint");
762 
763   if (!callEndTime.IsValid())
764     callEndTime = PTime();
765 
766   if (endSessionSent)
767     return;
768 
769   endSessionSent = TRUE;
770 
771   PTRACE(2, "H225\tSending release complete PDU: callRef=" << callReference);
772   H323SignalPDU rcPDU;
773   rcPDU.BuildReleaseComplete(*this);
774 
775 #ifdef H323_H450
776   h450dispatcher->AttachToReleaseComplete(rcPDU);
777 #endif
778 
779   PBoolean sendingReleaseComplete = OnSendReleaseComplete(rcPDU);
780 
781   if (endSessionNeeded) {
782     if (sendingReleaseComplete)
783       h245TunnelTxPDU = &rcPDU; // Piggy back H245 on this reply
784 
785     // Send an H.245 end session to the remote endpoint.
786     H323ControlPDU pdu;
787     pdu.BuildEndSessionCommand(H245_EndSessionCommand::e_disconnect);
788     WriteControlPDU(pdu);
789   }
790 
791   if (sendingReleaseComplete) {
792     h245TunnelTxPDU = NULL;
793     if (releaseSequence == ReleaseSequenceUnknown)
794       releaseSequence = ReleaseSequence_Local;
795     WriteSignalPDU(rcPDU);
796   }
797 }
798 
799 
ClearCall(H323Connection::CallEndReason reason)800 PBoolean H323Connection::ClearCall(H323Connection::CallEndReason reason)
801 {
802   return endpoint.ClearCall(callToken, reason);
803 }
804 
ClearCallSynchronous(PSyncPoint * sync,H323Connection::CallEndReason reason)805 PBoolean H323Connection::ClearCallSynchronous(PSyncPoint * sync, H323Connection::CallEndReason reason)
806 {
807   return endpoint.ClearCallSynchronous(callToken, reason, sync);
808 }
809 
810 
CleanUpOnCallEnd()811 void H323Connection::CleanUpOnCallEnd()
812 {
813   PTRACE(3, "H323\tConnection " << callToken << " closing: connectionState=" << connectionState);
814 
815   /* The following double mutex is designed to guarentee that there is no
816      deadlock or access of deleted object with a random thread that may have
817      just called Lock() at the instant we are trying to get rid of the
818      connection.
819    */
820 
821   outerMutex.Wait();
822   connectionState = ShuttingDownConnection;
823   outerMutex.Signal();
824   innerMutex.Wait();
825 
826   // Unblock sync points
827   digitsWaitFlag.Signal();
828 
829   // stop various timers
830   masterSlaveDeterminationProcedure->Stop();
831   capabilityExchangeProcedure->Stop();
832 
833   // Clean up any fast start "pending" channels we may have running.
834   PINDEX i;
835   for (i = 0; i < fastStartChannels.GetSize(); i++)
836     fastStartChannels[i].CleanUpOnTermination();
837   fastStartChannels.RemoveAll();
838 
839   // Dispose of all the logical channels
840   logicalChannels->RemoveAll();
841 
842   if (endSessionNeeded) {
843     // Calculate time since we sent the end session command so we do not actually
844     // wait for returned endSession if it has already been that long
845     PTimeInterval waitTime = endpoint.GetEndSessionTimeout();
846     if (callEndTime.IsValid()) {
847       PTime now;
848       if (now > callEndTime) { // Allow for backward motion in time (DST change)
849         waitTime -= now - callEndTime;
850         if (waitTime < 0)
851           waitTime = 0;
852       }
853     }
854 
855     // Wait a while for the remote to send an endSession
856     PTRACE(4, "H323\tAwaiting end session from remote for " << waitTime << " seconds");
857     if (!endSessionReceived.Wait(waitTime)) {
858       PTRACE(3, "H323\tDid not receive an end session from remote.");
859     }
860   }
861 
862   // Wait for control channel to be cleaned up (thread ended).
863   if (controlChannel != NULL)
864     controlChannel->CleanUpOnTermination();
865 
866 #ifdef H323_SIGNAL_AGGREGATE
867   if (controlAggregator != NULL)
868     endpoint.GetSignallingAggregator()->RemoveHandle(controlAggregator);
869 #endif
870 
871   // Wait for signalling channel to be cleaned up (thread ended).
872   if (signallingChannel != NULL)
873     signallingChannel->CleanUpOnTermination();
874 
875 #ifdef H323_SIGNAL_AGGREGATE
876   if (signalAggregator != NULL)
877     endpoint.GetSignallingAggregator()->RemoveHandle(signalAggregator);
878 #endif
879 
880   // Check for gatekeeper and do disengage if have one
881   if (mustSendDRQ) {
882     H323Gatekeeper * gatekeeper = endpoint.GetGatekeeper();
883     if (gatekeeper != NULL)
884       gatekeeper->DisengageRequest(*this, H225_DisengageReason::e_normalDrop);
885   }
886 
887   PTRACE(1, "H323\tConnection " << callToken << " terminated.");
888 }
889 
AttachSignalChannel(const PString & token,H323Transport * channel,PBoolean answeringCall)890 void H323Connection::AttachSignalChannel(const PString & token,
891                                          H323Transport * channel,
892                                          PBoolean answeringCall)
893 {
894   callAnswered = answeringCall;
895 
896   if (signallingChannel != NULL && signallingChannel->IsOpen()) {
897     PTRACE(1, "H323\tLogic error: signalling channel is open");
898     return;
899   }
900 
901   delete signallingChannel;
902   signallingChannel = channel;
903 
904   // Set our call token for identification in endpoint dictionary
905   callToken = token;
906 
907   SetAuthenticationConnection();
908 }
909 
ChangeSignalChannel(H323Transport * channel)910 void H323Connection::ChangeSignalChannel(H323Transport * channel)
911 {
912   if (signallingChannel == NULL || controlChannel == NULL || !h245Tunneling) {
913     PTRACE(1, "H323\tLogic error: no signaling and no control channel");
914     return;
915   }
916 
917   signallingMutex.Wait();
918     H323Transport * oldTransport = signallingChannel;
919     signallingChannel = channel;
920       controlMutex.Wait();
921         H323Transport * oldControl = controlChannel;
922         (void)StartControlChannel();
923       controlMutex.Signal();
924   signallingMutex.Signal();
925 
926   oldControl->CleanUpOnTermination();
927   delete oldControl;
928 
929   oldTransport->CleanUpOnTermination();
930   delete oldTransport;
931 
932 }
933 
934 
WriteSignalPDU(H323SignalPDU & pdu)935 PBoolean H323Connection::WriteSignalPDU(H323SignalPDU & pdu)
936 {
937   lastPDUWasH245inSETUP = FALSE;
938 
939   PBoolean success = false;
940   if (signallingChannel != NULL) {
941     pdu.m_h323_uu_pdu.m_h245Tunneling = h245Tunneling;
942 
943     H323Gatekeeper * gk = endpoint.GetGatekeeper();
944     if (gk)
945       gk->InfoRequestResponse(*this, pdu.m_h323_uu_pdu, TRUE);
946 
947     signallingMutex.Wait();
948 #ifdef H323_H46017
949     if (m_maintainConnection) {
950         if (!pdu.GetQ931().HasIE(Q931::UserUserIE) && pdu.m_h323_uu_pdu.m_h323_message_body.IsValid())
951               pdu.BuildQ931();
952 
953         if (!signallingChannel->WriteSignalPDU(pdu)) {
954             PTRACE(2,"H225\tERROR: Signalling Channel Failure: PDU was not sent!");
955             success = HandleSignalChannelFailure();
956         } else
957             success = true;
958     } else
959 #endif
960     {
961         // We don't have to take down the call if the signalling channel fails.
962         // We may want to wait until the media fails or the local hangs up.
963         if (!pdu.Write(*signallingChannel,this)) {
964             PTRACE(2,"H225\tERROR: Signalling Channel Failure: PDU was not sent!");
965             success = HandleSignalChannelFailure();
966         } else
967             success = true;
968     }
969     signallingMutex.Signal();
970   }
971 
972   if (!success)
973     ClearCall(EndedByTransportFail);
974 
975   return success;
976 }
977 
HandleSignallingChannel()978 void H323Connection::HandleSignallingChannel()
979 {
980 
981   PTRACE(2, "H225\tReading PDUs: callRef=" << callReference);
982 
983   while (signallingChannel && signallingChannel->IsOpen()) {
984     H323SignalPDU pdu;
985     PBoolean readStatus = pdu.Read(*signallingChannel);
986 	// skip keep-alives
987     if (readStatus && pdu.GetQ931().GetMessageType() == 0)
988       continue;
989     if (!HandleReceivedSignalPDU(readStatus, pdu))
990       break;
991   }
992 
993   // If we are the only link to the far end then indicate that we have
994   // received endSession even if we hadn't, because we are now never going
995   // to get one so there is no point in having CleanUpOnCallEnd wait.
996   if (controlChannel == NULL)
997     endSessionReceived.Signal();
998 
999   // if the signalling thread ends, make sure we end the call if it hasn't been done, yet
1000   // otherwise we have error conditions where the connection is never deleted
1001   if (!endSessionSent)
1002     ClearCall(EndedByTransportFail);
1003 
1004   PTRACE(2, "H225\tSignal channel closed.");
1005 }
1006 
HandleReceivedSignalPDU(PBoolean readStatus,H323SignalPDU & pdu)1007 PBoolean H323Connection::HandleReceivedSignalPDU(PBoolean readStatus, H323SignalPDU & pdu)
1008 {
1009   if (readStatus) {
1010     if (!HandleSignalPDU(pdu)) {
1011       if (AuthenticationFailed)
1012           ClearCall(EndedBySecurityDenial);
1013       else
1014         ClearCall(EndedByTransportFail);
1015       return FALSE;
1016     }
1017     switch (connectionState) {
1018       case EstablishedConnection :
1019         signallingChannel->SetReadTimeout(MonitorCallStatusTime);
1020         break;
1021       default:
1022         break;
1023     }
1024   }
1025   else if (signallingChannel->GetErrorCode() != PChannel::Timeout) {
1026     if (controlChannel == NULL || !controlChannel->IsOpen())
1027       ClearCall(EndedByTransportFail);
1028     signallingChannel->Close();
1029     return FALSE;
1030   }
1031   else {
1032     switch (connectionState) {
1033       case AwaitingSignalConnect :
1034         // Had time out waiting for remote to send a CONNECT
1035         ClearCall(EndedByNoAnswer);
1036         break;
1037       case HasExecutedSignalConnect :
1038         // Have had minimum MonitorCallStatusTime delay since CONNECT but
1039         // still no media to move it to EstablishedConnection state. Must
1040         // thus not have any common codecs to use!
1041         ClearCall(EndedByCapabilityExchange);
1042         break;
1043       default :
1044         break;
1045     }
1046   }
1047 
1048   if (controlChannel == NULL)
1049     MonitorCallStatus();
1050 
1051   return TRUE;
1052 }
1053 
CallEstablishmentMessage(const Q931 & q931)1054 PBoolean CallEstablishmentMessage(const Q931 & q931)
1055 {
1056   switch (q931.GetMessageType()) {
1057     case Q931::SetupMsg :
1058     case Q931::ProgressMsg :
1059     case Q931::AlertingMsg :
1060     case Q931::ConnectMsg :
1061       return true;
1062     default:
1063       return false;
1064   }
1065 }
1066 
1067 
HandleSignalPDU(H323SignalPDU & pdu)1068 PBoolean H323Connection::HandleSignalPDU(H323SignalPDU & pdu)
1069 {
1070   // Process the PDU.
1071   const Q931 & q931 = pdu.GetQ931();
1072 
1073   PTRACE(3, "H225\tHandling PDU: " << q931.GetMessageTypeName()
1074                     << " callRef=" << q931.GetCallReference());
1075 
1076   if (!Lock()) {
1077     // Continue to look for endSession/releaseComplete pdus
1078     if (pdu.m_h323_uu_pdu.m_h245Tunneling) {
1079       for (PINDEX i = 0; i < pdu.m_h323_uu_pdu.m_h245Control.GetSize(); i++) {
1080         PPER_Stream strm = pdu.m_h323_uu_pdu.m_h245Control[i].GetValue();
1081         if (!InternalEndSessionCheck(strm))
1082           break;
1083       }
1084     }
1085     if (q931.GetMessageType() == Q931::ReleaseCompleteMsg)
1086       endSessionReceived.Signal();
1087     return FALSE;
1088   }
1089 
1090   if (CallEstablishmentMessage(q931)) {
1091       // If remote does not do tunneling, so we don't either. Note that if it
1092       // gets turned off once, it stays off for good.
1093       if (h245Tunneling && !pdu.m_h323_uu_pdu.m_h245Tunneling.GetValue()) {
1094         masterSlaveDeterminationProcedure->Stop();
1095         capabilityExchangeProcedure->Stop();
1096         PTRACE(3, "H225\tFast Start DISABLED!");
1097         h245Tunneling = FALSE;
1098       }
1099   }
1100 
1101   h245TunnelRxPDU = &pdu;
1102 
1103 #ifdef H323_H450
1104   // Check for presence of supplementary services
1105   if (pdu.m_h323_uu_pdu.HasOptionalField(H225_H323_UU_PDU::e_h4501SupplementaryService)) {
1106     if (!h450dispatcher->HandlePDU(pdu)) { // Process H4501SupplementaryService APDU
1107       Unlock();
1108       return FALSE;
1109     }
1110   }
1111 #endif
1112 
1113 #ifdef H323_H460
1114     if (pdu.m_h323_uu_pdu.HasOptionalField(H225_H323_UU_PDU::e_genericData)) {
1115        if (q931.GetMessageType() == Q931::SetupMsg) {
1116           remotePartyName = pdu.GetQ931().GetDisplayName();
1117           remoteAliasNames = pdu.GetSourceAliasNames();
1118        }
1119        ReceiveFeatureData<H323SignalPDU>(this,q931.GetMessageType(),pdu);
1120     }
1121 #endif
1122 
1123   // Add special code to detect if call is from a Cisco and remoteApplication needs setting
1124   if (remoteApplication.IsEmpty() && pdu.m_h323_uu_pdu.HasOptionalField(H225_H323_UU_PDU::e_nonStandardControl)) {
1125     for (PINDEX i = 0; i < pdu.m_h323_uu_pdu.m_nonStandardControl.GetSize(); i++) {
1126       const H225_NonStandardIdentifier & id = pdu.m_h323_uu_pdu.m_nonStandardControl[i].m_nonStandardIdentifier;
1127       if (id.GetTag() == H225_NonStandardIdentifier::e_h221NonStandard) {
1128         const H225_H221NonStandard & h221 = id;
1129         if (h221.m_t35CountryCode == 181 && h221.m_t35Extension == 0 && h221.m_manufacturerCode == 18) {
1130           remoteApplication = "Cisco IOS\t12.x\t181/18";
1131           PTRACE(2, "H225\tSet remote application name: \"" << remoteApplication << '"');
1132           break;
1133         }
1134       }
1135     }
1136   }
1137 
1138   PBoolean ok;
1139   switch (q931.GetMessageType()) {
1140     case Q931::SetupMsg :
1141       setupTime = PTime();
1142       ok = OnReceivedSignalSetup(pdu);
1143       break;
1144 
1145     case Q931::CallProceedingMsg :
1146       ok = OnReceivedCallProceeding(pdu);
1147       break;
1148 
1149     case Q931::ProgressMsg :
1150       ok = OnReceivedProgress(pdu);
1151       break;
1152 
1153     case Q931::AlertingMsg :
1154       ok = OnReceivedAlerting(pdu);
1155       break;
1156 
1157     case Q931::ConnectMsg :
1158       connectedTime = PTime();
1159       ok = OnReceivedSignalConnect(pdu);
1160       break;
1161 
1162     case Q931::FacilityMsg :
1163       ok = OnReceivedFacility(pdu);
1164       break;
1165 
1166     case Q931::SetupAckMsg :
1167       ok = OnReceivedSignalSetupAck(pdu);
1168       break;
1169 
1170     case Q931::InformationMsg :
1171       ok = OnReceivedSignalInformation(pdu);
1172       break;
1173 
1174     case Q931::NotifyMsg :
1175       ok = OnReceivedSignalNotify(pdu);
1176       break;
1177 
1178     case Q931::StatusMsg :
1179       ok = OnReceivedSignalStatus(pdu);
1180       break;
1181 
1182     case Q931::StatusEnquiryMsg :
1183       ok = OnReceivedStatusEnquiry(pdu);
1184       break;
1185 
1186     case Q931::ReleaseCompleteMsg :
1187       if (releaseSequence == ReleaseSequenceUnknown)
1188         releaseSequence = ReleaseSequence_Remote;
1189       OnReceivedReleaseComplete(pdu);
1190       ok = FALSE;
1191       break;
1192 
1193     default :
1194       ok = OnUnknownSignalPDU(pdu);
1195   }
1196 
1197   if (ok) {
1198     // Process tunnelled H245 PDU, if present.
1199     HandleTunnelPDU(NULL);
1200 
1201     // Check for establishment criteria met
1202     InternalEstablishedConnectionCheck();
1203   }
1204 
1205   h245TunnelRxPDU = NULL;
1206 
1207   PString digits = pdu.GetQ931().GetKeypad();
1208   if (!digits)
1209     OnUserInputString(digits);
1210 
1211   H323Gatekeeper * gk = endpoint.GetGatekeeper();
1212   if (gk != NULL)
1213     gk->InfoRequestResponse(*this, pdu.m_h323_uu_pdu, FALSE);
1214 
1215   Unlock();
1216 
1217   return ok;
1218 }
1219 
1220 
HandleTunnelPDU(H323SignalPDU * txPDU)1221 void H323Connection::HandleTunnelPDU(H323SignalPDU * txPDU)
1222 {
1223   if (h245TunnelRxPDU == NULL || !h245TunnelRxPDU->m_h323_uu_pdu.m_h245Tunneling)
1224     return;
1225 
1226   if (!h245Tunneling && h245TunnelRxPDU->m_h323_uu_pdu.m_h323_message_body.GetTag() == H225_H323_UU_PDU_h323_message_body::e_setup)
1227     return;
1228 
1229   H323SignalPDU localTunnelPDU;
1230   if (txPDU != NULL)
1231     h245TunnelTxPDU = txPDU;
1232   else {
1233     /* Compensate for Cisco bug. IOS cannot seem to accept multiple tunnelled
1234        H.245 PDUs insode the same facility message */
1235     if (remoteApplication.Find("Cisco IOS") == P_MAX_INDEX) {
1236       // Not Cisco, so OK to tunnel multiple PDUs
1237       localTunnelPDU.BuildFacility(*this, TRUE);
1238       h245TunnelTxPDU = &localTunnelPDU;
1239     }
1240   }
1241 
1242   // if a response to a SETUP PDU containing TCS/MSD was ignored, then shutdown negotiations
1243   PINDEX i;
1244   if (lastPDUWasH245inSETUP &&
1245       (h245TunnelRxPDU->m_h323_uu_pdu.m_h245Control.GetSize() == 0) &&
1246       (h245TunnelRxPDU->GetQ931().GetMessageType() != Q931::CallProceedingMsg)) {
1247     PTRACE(4, "H225\tH.245 in SETUP ignored - resetting H.245 negotiations");
1248     masterSlaveDeterminationProcedure->Stop();
1249     lastPDUWasH245inSETUP = FALSE;
1250     capabilityExchangeProcedure->Stop();
1251   } else {
1252     for (i = 0; i < h245TunnelRxPDU->m_h323_uu_pdu.m_h245Control.GetSize(); i++) {
1253       PPER_Stream strm = h245TunnelRxPDU->m_h323_uu_pdu.m_h245Control[i].GetValue();
1254       HandleControlData(strm);
1255     }
1256   }
1257 
1258   // Make sure does not get repeated, clear tunnelled H.245 PDU's
1259   h245TunnelRxPDU->m_h323_uu_pdu.m_h245Control.SetSize(0);
1260 
1261   if (h245TunnelRxPDU->m_h323_uu_pdu.m_h323_message_body.GetTag() == H225_H323_UU_PDU_h323_message_body::e_setup) {
1262     H225_Setup_UUIE & setup = h245TunnelRxPDU->m_h323_uu_pdu.m_h323_message_body;
1263 
1264     if (setup.HasOptionalField(H225_Setup_UUIE::e_parallelH245Control)) {
1265       for (i = 0; i < setup.m_parallelH245Control.GetSize(); i++) {
1266         PPER_Stream strm = setup.m_parallelH245Control[i].GetValue();
1267         HandleControlData(strm);
1268       }
1269 
1270       // Make sure does not get repeated, clear tunnelled H.245 PDU's
1271       setup.m_parallelH245Control.SetSize(0);
1272     }
1273   }
1274 
1275   h245TunnelTxPDU = NULL;
1276 
1277   // If had replies, then send them off in their own packet
1278   if (txPDU == NULL && localTunnelPDU.m_h323_uu_pdu.m_h245Control.GetSize() > 0)
1279     WriteSignalPDU(localTunnelPDU);
1280 }
1281 
1282 
BuildFastStartList(const H323Channel & channel,H225_ArrayOf_PASN_OctetString & array,H323Channel::Directions reverseDirection)1283 static PBoolean BuildFastStartList(const H323Channel & channel,
1284                                H225_ArrayOf_PASN_OctetString & array,
1285                                H323Channel::Directions reverseDirection)
1286 {
1287   H245_OpenLogicalChannel open;
1288   const H323Capability & capability = channel.GetCapability();
1289 
1290   if (channel.GetDirection() != reverseDirection) {
1291     if (!capability.OnSendingPDU(open.m_forwardLogicalChannelParameters.m_dataType))
1292       return FALSE;
1293   }
1294   else {
1295     if (!capability.OnSendingPDU(open.m_reverseLogicalChannelParameters.m_dataType))
1296       return FALSE;
1297 
1298     open.m_forwardLogicalChannelParameters.m_multiplexParameters.SetTag(
1299                 H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters::e_none);
1300     open.m_forwardLogicalChannelParameters.m_dataType.SetTag(H245_DataType::e_nullData);
1301     open.IncludeOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters);
1302   }
1303 
1304   if (!channel.OnSendingPDU(open))
1305     return FALSE;
1306 
1307   PTRACE(4, "H225\tBuild fastStart:\n  " << setprecision(2) << open);
1308   PINDEX last = array.GetSize();
1309   array.SetSize(last+1);
1310   array[last].EncodeSubType(open);
1311 
1312   PTRACE(3, "H225\tBuilt fastStart for " << capability);
1313   return TRUE;
1314 }
1315 
OnEstablished()1316 void H323Connection::OnEstablished()
1317 {
1318   endpoint.OnConnectionEstablished(*this, callToken);
1319 }
1320 
OnCleared()1321 void H323Connection::OnCleared()
1322 {
1323   endpoint.OnConnectionCleared(*this, callToken);
1324 }
1325 
1326 
SetRemoteVersions(const H225_ProtocolIdentifier & protocolIdentifier)1327 void H323Connection::SetRemoteVersions(const H225_ProtocolIdentifier & protocolIdentifier)
1328 {
1329   if (protocolIdentifier.GetSize() < 6)
1330     return;
1331 
1332   h225version = protocolIdentifier[5];
1333 
1334   if (h245versionSet) {
1335     PTRACE(3, "H225\tSet protocol version to " << h225version);
1336     return;
1337   }
1338 
1339   // If has not been told explicitly what the H.245 version use, make an
1340   // assumption based on the H.225 version
1341   switch (h225version) {
1342     case 1 :
1343       h245version = 2;  // H.323 version 1
1344       break;
1345     case 2 :
1346       h245version = 3;  // H.323 version 2
1347       break;
1348     case 3 :
1349       h245version = 5;  // H.323 version 3
1350       break;
1351     case 4 :
1352       h245version = 7;  // H.323 version 4
1353       break;
1354     case 5 :
1355       h245version = 9;  // H.323 version 5
1356       break;
1357 	case 6 :
1358 	  h245version = 13; // H.323 version 6
1359 	  break;
1360     default:
1361       h245version = 15; // H.323 version 7
1362       break;
1363   }
1364   PTRACE(3, "H225\tSet protocol version to " << h225version
1365          << " and implying H.245 version " << h245version);
1366 }
1367 
DecodeFastStartCaps(const H225_ArrayOf_PASN_OctetString & fastStartCaps)1368 PBoolean H323Connection::DecodeFastStartCaps(const H225_ArrayOf_PASN_OctetString & fastStartCaps)
1369 {
1370   if (!capabilityExchangeProcedure->HasReceivedCapabilities())
1371     remoteCapabilities.RemoveAll();
1372 
1373   PTRACE(3, "H225\tFast start detected");
1374 
1375   // Extract capabilities from the fast start OpenLogicalChannel structures
1376   PINDEX i;
1377   for (i = 0; i < fastStartCaps.GetSize(); i++) {
1378     H245_OpenLogicalChannel open;
1379     if (fastStartCaps[i].DecodeSubType(open)) {
1380       PTRACE(4, "H225\tFast start open:\n  " << setprecision(2) << open);
1381       unsigned error;
1382       H323Channel * channel = CreateLogicalChannel(open, TRUE, error);
1383       if (channel != NULL) {
1384         if (channel->GetDirection() == H323Channel::IsTransmitter)
1385           channel->SetNumber(logicalChannels->GetNextChannelNumber());
1386         fastStartChannels.Append(channel);
1387       }
1388     }
1389     else {
1390       PTRACE(1, "H225\tInvalid fast start PDU decode:\n  " << open);
1391     }
1392   }
1393 
1394   PTRACE(3, "H225\tOpened " << fastStartChannels.GetSize() << " fast start channels");
1395 
1396   // If we are incapable of ANY of the fast start channels, don't do fast start
1397   if (!fastStartChannels.IsEmpty())
1398     fastStartState = FastStartResponse;
1399 
1400   return !fastStartChannels.IsEmpty();
1401 }
1402 
1403 
1404 
OnReceivedSignalSetup(const H323SignalPDU & setupPDU)1405 PBoolean H323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
1406 {
1407   if (setupPDU.m_h323_uu_pdu.m_h323_message_body.GetTag() != H225_H323_UU_PDU_h323_message_body::e_setup)
1408     return FALSE;
1409 
1410   const H225_Setup_UUIE & setup = setupPDU.m_h323_uu_pdu.m_h323_message_body;
1411 
1412   if (!CheckRemoteApplication(setup.m_sourceInfo)) {
1413         PTRACE(2,"SETUP\tRemote Application check FAILURE.");
1414         return false;
1415   }
1416 
1417   /// Do Authentication of Incoming Call before anything else
1418   if (!ReceiveAuthenticatorPDU<H225_Setup_UUIE>(this,setup,
1419                             H225_H323_UU_PDU_h323_message_body::e_setup)) {
1420      if (GetEndPoint().GetEPSecurityPolicy() == H323EndPoint::SecRequired) {
1421         PTRACE(4, "H235EP\tAuthentication Failed. Ending Call");
1422         AuthenticationFailed = TRUE;
1423         return FALSE;
1424      }
1425      PTRACE(6, "H235EP\tAuthentication Failed but allowed by policy");
1426   } else {
1427      hasAuthentication = TRUE;
1428   }
1429 
1430   switch (setup.m_conferenceGoal.GetTag()) {
1431     case H225_Setup_UUIE_conferenceGoal::e_create:
1432     case H225_Setup_UUIE_conferenceGoal::e_join:
1433       break;
1434 
1435     case H225_Setup_UUIE_conferenceGoal::e_invite:
1436       return endpoint.OnConferenceInvite(FALSE,this,setupPDU);
1437 
1438     case H225_Setup_UUIE_conferenceGoal::e_callIndependentSupplementaryService:
1439       nonCallConnection = OnReceiveCallIndependentSupplementaryService(setupPDU);
1440       if (!nonCallConnection) return FALSE;
1441        break;
1442 
1443     case H225_Setup_UUIE_conferenceGoal::e_capability_negotiation:
1444       return endpoint.OnNegotiateConferenceCapabilities(setupPDU);
1445   }
1446 
1447   // Check Language Support
1448   if (setup.HasOptionalField(H225_Setup_UUIE::e_language)) {
1449       PStringList remoteLang;
1450 	  if (!H323GetLanguages(remoteLang, setup.m_language) || !MergeLanguages(remoteLang, true)) {
1451 		  PTRACE(2,"SETUP\tMissing or no common language support");
1452 	  }
1453   }
1454 
1455   SetRemoteVersions(setup.m_protocolIdentifier);
1456 
1457   // Get the ring pattern
1458   distinctiveRing = setupPDU.GetDistinctiveRing();
1459 
1460   // Save the identifiers sent by caller
1461   if (setup.HasOptionalField(H225_Setup_UUIE::e_callIdentifier))
1462     callIdentifier = setup.m_callIdentifier.m_guid;
1463   conferenceIdentifier = setup.m_conferenceID;
1464   SetRemoteApplication(setup.m_sourceInfo);
1465 
1466   // Determine the remote parties name/number/address as best we can
1467   setupPDU.GetQ931().GetCallingPartyNumber(remoteQ931Number);
1468   remotePartyNumber = remoteQ931Number;
1469   remoteQ931Display = setupPDU.GetQ931().GetDisplayName();
1470   remoteAliasNames = setupPDU.GetSourceAliasNames();
1471   remotePartyAddress = signallingChannel->GetRemoteAddress();
1472 
1473   if (useQ931Display && !remotePartyNumber)
1474       remotePartyName = remotePartyNumber;
1475   else if (remoteAliasNames.GetSize() > 0)
1476       remotePartyName = remoteAliasNames[0];
1477   else
1478       remotePartyName = remotePartyAddress;
1479 
1480   if (setup.m_sourceAddress.GetSize() > 0) {
1481     if (!remotePartyAddress.IsEmpty())
1482         remotePartyAddress = H323GetAliasAddressString(setup.m_sourceAddress[0]) + '@' + remotePartyAddress;
1483     else
1484         remotePartyAddress = H323GetAliasAddressString(setup.m_sourceAddress[0]);
1485   }
1486 
1487 #ifdef H323_H460
1488      ReceiveSetupFeatureSet(this, setup);
1489 #endif
1490 
1491   // compare the source call signalling address
1492   if (setup.HasOptionalField(H225_Setup_UUIE::e_sourceCallSignalAddress)) {
1493 
1494     PIPSocket::Address srcAddr, sigAddr;
1495     H323TransportAddress sourceAddress(setup.m_sourceCallSignalAddress);
1496     sourceAddress.GetIpAddress(srcAddr);
1497     signallingChannel->GetRemoteAddress().GetIpAddress(sigAddr);
1498 
1499     NatDetection(srcAddr, sigAddr);
1500   }
1501 
1502   // Anything else we need from setup PDU
1503   mediaWaitForConnect = setup.m_mediaWaitForConnect;
1504 
1505   // Get the local capabilities before fast start or tunnelled TCS is handled
1506    if (!nonCallConnection)
1507       OnSetLocalCapabilities();
1508 
1509   // Send back a H323 Call Proceeding PDU in case OnIncomingCall() takes a while
1510   PTRACE(3, "H225\tSending call proceeding PDU");
1511   H323SignalPDU callProceedingPDU;
1512   H225_CallProceeding_UUIE & callProceeding = callProceedingPDU.BuildCallProceeding(*this);
1513 
1514 #ifdef H323_H450
1515   if (!isConsultationTransfer) {
1516 #endif
1517     if (OnSendCallProceeding(callProceedingPDU)) {
1518       if (fastStartState == FastStartDisabled)
1519         callProceeding.IncludeOptionalField(H225_CallProceeding_UUIE::e_fastConnectRefused);
1520 
1521       if (!WriteSignalPDU(callProceedingPDU))
1522         return FALSE;
1523     }
1524 
1525     /** Here is a spot where we should wait in case of Call Intrusion
1526     for CIPL from other endpoints
1527     if (isCallIntrusion) return TRUE;
1528     */
1529 
1530     // if the application indicates not to contine, then send a Q931 Release Complete PDU
1531     alertingPDU = new H323SignalPDU;
1532     alertingPDU->BuildAlerting(*this);
1533 
1534     /** If we have a case of incoming call intrusion we should not Clear the Call*/
1535     {
1536       CallEndReason incomingCallEndReason = EndedByNoAccept;
1537       if (!OnIncomingCall(setupPDU, *alertingPDU, incomingCallEndReason)
1538 #ifdef H323_H450
1539         && (!isCallIntrusion)
1540 #endif
1541       ) {
1542         ClearCall(incomingCallEndReason);
1543         PTRACE(1, "H225\tApplication not accepting calls");
1544         return FALSE;
1545       }
1546     }
1547 
1548     // send Q931 Alerting PDU
1549     PTRACE(3, "H225\tIncoming call accepted");
1550 
1551     // Check for gatekeeper and do admission check if have one
1552     H323Gatekeeper * gatekeeper = endpoint.GetGatekeeper();
1553     if (gatekeeper != NULL) {
1554       H225_ArrayOf_AliasAddress destExtraCallInfoArray;
1555       H323Gatekeeper::AdmissionResponse response;
1556       response.destExtraCallInfo = &destExtraCallInfoArray;
1557       response.languageSupport = &localLanguages;
1558       if (!gatekeeper->AdmissionRequest(*this, response)) {
1559         PTRACE(1, "H225\tGatekeeper refused admission: "
1560                << (response.rejectReason == UINT_MAX
1561                     ? PString("Transport error")
1562                     : H225_AdmissionRejectReason(response.rejectReason).GetTagName()));
1563         switch (response.rejectReason) {
1564           case H225_AdmissionRejectReason::e_calledPartyNotRegistered :
1565             ClearCall(EndedByNoUser);
1566             break;
1567           case H225_AdmissionRejectReason::e_requestDenied :
1568             ClearCall(EndedByNoBandwidth);
1569             break;
1570           case H225_AdmissionRejectReason::e_invalidPermission :
1571           case H225_AdmissionRejectReason::e_securityDenial :
1572             ClearCall(EndedBySecurityDenial);
1573             break;
1574           case H225_AdmissionRejectReason::e_resourceUnavailable :
1575             ClearCall(EndedByRemoteBusy);
1576             break;
1577           default :
1578             ClearCall(EndedByGatekeeper);
1579         }
1580         return FALSE;
1581       }
1582 
1583       if (destExtraCallInfoArray.GetSize() > 0)
1584         destExtraCallInfo = H323GetAliasAddressString(destExtraCallInfoArray[0]);
1585       mustSendDRQ = TRUE;
1586       gatekeeperRouted = response.gatekeeperRouted;
1587     }
1588 #ifdef H323_H450
1589   }
1590 #endif
1591 
1592   if (!nonCallConnection) {
1593       // See if remote endpoint wants to start fast
1594       if (fastStartState != FastStartDisabled &&
1595            setup.HasOptionalField(H225_Setup_UUIE::e_fastStart) &&
1596            localCapabilities.GetSize() > 0) {
1597 
1598         DecodeFastStartCaps(setup.m_fastStart);
1599       }
1600 
1601       // Check that if we are not doing Fast Connect that we have H.245 channel info
1602       if (fastStartState != FastStartResponse &&
1603           setup.HasOptionalField(H225_Setup_UUIE::e_h245Address)) {
1604              if (!StartControlChannel(setup.m_h245Address))
1605                        return FALSE;
1606       }
1607   }
1608 
1609   // Build the reply with the channels we are actually using
1610   connectPDU = new H323SignalPDU;
1611   connectPDU->BuildConnect(*this);
1612 
1613 #ifdef H323_H450
1614   /** If Call Intrusion is allowed we must answer the call*/
1615   if (IsCallIntrusion()) {
1616     AnsweringCall(AnswerCallDeferred);
1617   }
1618   else {
1619     if (!isConsultationTransfer) {
1620 #endif
1621       // call the application callback to determine if to answer the call or not
1622       connectionState = AwaitingLocalAnswer;
1623       AnsweringCall(OnAnswerCall(remotePartyName, setupPDU, *connectPDU));
1624 #ifdef H323_H450
1625     }
1626     else
1627       AnsweringCall(AnswerCallNow);
1628   }
1629 #endif
1630 
1631   return connectionState != ShuttingDownConnection;
1632 }
1633 
SetLocalPartyName(const PString & name)1634 void H323Connection::SetLocalPartyName(const PString & name)
1635 {
1636   localPartyName = name;
1637 
1638   if (!name.IsEmpty()) {
1639     localAliasNames.RemoveAll();
1640     localAliasNames.SetSize(0);
1641     localAliasNames.AppendString(name);
1642   }
1643 }
1644 
1645 
SetRemotePartyInfo(const H323SignalPDU & pdu)1646 void H323Connection::SetRemotePartyInfo(const H323SignalPDU & pdu)
1647 {
1648   PString number=PString();
1649   if (pdu.GetQ931().GetCalledPartyNumber(number) && !number.IsEmpty()) {
1650     remoteQ931Number = number;
1651     remotePartyNumber = remoteQ931Number;
1652   }
1653 
1654   PString newRemotePartyName = pdu.GetQ931().GetDisplayName();
1655   if (!newRemotePartyName.IsEmpty()) {
1656     remoteQ931Display = newRemotePartyName;
1657     remotePartyName = newRemotePartyName;
1658   } else if (!remotePartyNumber.IsEmpty())
1659     remotePartyName = remotePartyNumber;
1660   else
1661     remotePartyName = signallingChannel->GetRemoteAddress().GetHostName();
1662 
1663   PTRACE(2, "H225\tSet remote party name: \"" << remotePartyName << '"');
1664 }
1665 
1666 
SetRemotePartyName(const PString & name)1667 void H323Connection::SetRemotePartyName(const PString & name)
1668 {
1669     if (useQ931Display)
1670         remoteQ931Number = name;
1671 
1672     remotePartyName = name;
1673 }
1674 
1675 
SetRemoteApplication(const H225_EndpointType & pdu)1676 void H323Connection::SetRemoteApplication(const H225_EndpointType & pdu)
1677 {
1678   if (pdu.HasOptionalField(H225_EndpointType::e_vendor)) {
1679     remoteApplication = H323GetApplicationInfo(pdu.m_vendor);
1680     PTRACE(2, "H225\tSet remote application name: \"" << remoteApplication << '"');
1681   }
1682 }
1683 
CheckRemoteApplication(const H225_EndpointType & pdu)1684 PBoolean H323Connection::CheckRemoteApplication(const H225_EndpointType & pdu)
1685 {
1686 #ifdef H323_H461
1687     if (endpoint.GetEndPointASSETMode() == H323EndPoint::e_H461ASSET &&
1688         (!pdu.HasOptionalField(H225_EndpointType::e_set) || !pdu.m_set[3]))
1689         return false;
1690 #endif
1691     return true;
1692 }
1693 
OnSendCallIndependentSupplementaryService(H323SignalPDU & pdu) const1694 PBoolean H323Connection::OnSendCallIndependentSupplementaryService(H323SignalPDU & pdu) const
1695 {
1696     return endpoint.OnSendCallIndependentSupplementaryService(this,pdu);
1697 }
1698 
OnReceiveCallIndependentSupplementaryService(const H323SignalPDU & pdu)1699 PBoolean H323Connection::OnReceiveCallIndependentSupplementaryService(const H323SignalPDU & pdu)
1700 {
1701 
1702 #ifdef H323_H450
1703     if (pdu.m_h323_uu_pdu.HasOptionalField(H225_H323_UU_PDU::e_h4501SupplementaryService)) {
1704         PTRACE(2,"CON\tReceived H.450 Call Independent Supplementary Service");
1705         return h450dispatcher->HandlePDU(pdu);
1706     }
1707 #endif
1708 
1709 #ifdef H323_H460
1710     if (!disableH460) {
1711         const H225_Setup_UUIE & setup = pdu.m_h323_uu_pdu.m_h323_message_body;
1712         if (ReceiveSetupFeatureSet(this, setup, true)) {
1713             PTRACE(2,"CON\tProcessed H.460 Call Independent Supplementary Service");
1714             return true;
1715         }
1716 
1717 #ifdef H323_H461
1718         if (setup.m_sourceInfo.HasOptionalField(H225_EndpointType::e_set) && setup.m_sourceInfo.m_set[3]) {
1719             H323EndPoint::H461Mode mode = endpoint.GetEndPointASSETMode();
1720             if (mode == H323EndPoint::e_H461Disabled) {
1721                 PTRACE(2,"CON\tLogic error SET call to regular endpoint");
1722                 return false;
1723             }
1724 
1725             if (pdu.m_h323_uu_pdu.HasOptionalField(H225_H323_UU_PDU::e_genericData) && pdu.m_h323_uu_pdu.m_genericData.GetSize() > 0) {
1726                 const H225_GenericIdentifier & id = pdu.m_h323_uu_pdu.m_genericData[0].m_id;
1727                 if (id.GetTag() == H225_GenericIdentifier::e_oid) {
1728                     const PASN_ObjectId & val = id;
1729                     if (val.AsString() == "0.0.8.461.0") {
1730                         SetH461Mode(e_h461Associate);
1731                         return true;
1732                     }
1733                 }
1734             }
1735         }
1736 #endif
1737     }
1738 #endif
1739     return endpoint.OnReceiveCallIndependentSupplementaryService(this,pdu);
1740 }
1741 
1742 
OnReceivedSignalSetupAck(const H323SignalPDU &)1743 PBoolean H323Connection::OnReceivedSignalSetupAck(const H323SignalPDU & /*setupackPDU*/)
1744 {
1745   OnInsufficientDigits();
1746   return TRUE;
1747 }
1748 
1749 
OnReceivedSignalInformation(const H323SignalPDU &)1750 PBoolean H323Connection::OnReceivedSignalInformation(const H323SignalPDU & /*infoPDU*/)
1751 {
1752   return TRUE;
1753 }
1754 
1755 
OnReceivedCallProceeding(const H323SignalPDU & pdu)1756 PBoolean H323Connection::OnReceivedCallProceeding(const H323SignalPDU & pdu)
1757 {
1758   if (pdu.m_h323_uu_pdu.m_h323_message_body.GetTag() != H225_H323_UU_PDU_h323_message_body::e_callProceeding)
1759     return FALSE;
1760   const H225_CallProceeding_UUIE & call = pdu.m_h323_uu_pdu.m_h323_message_body;
1761 
1762   SetRemoteVersions(call.m_protocolIdentifier);
1763   //SetRemotePartyInfo(pdu);  - Call proceeding could be fake do not set call party info
1764   SetRemoteApplication(call.m_destinationInfo);
1765 
1766   if (!ReceiveAuthenticatorPDU<H225_CallProceeding_UUIE>(this,call,
1767                  H225_H323_UU_PDU_h323_message_body::e_callProceeding)) {
1768 //          don't do anything
1769   }
1770 
1771 #ifdef H323_H460
1772   ReceiveFeatureSet<H225_CallProceeding_UUIE>(this, H460_MessageType::e_callProceeding, call);
1773 #endif
1774 
1775   // Check for fastStart data and start fast
1776 /*  MERA gatekeepers send fast start in call proceeding then
1777     decide to send a different one in either Alert,Progress or Connect and has assumed
1778     you have ignored the one in the CallProceeding.. Very Frustrating - S.H.
1779 */
1780  if (!enableMERAHack && call.HasOptionalField(H225_CallProceeding_UUIE::e_fastStart))
1781     HandleFastStartAcknowledge(call.m_fastStart);
1782   if (fastStartState == FastStartAcknowledged) {
1783         lastPDUWasH245inSETUP = FALSE;
1784         masterSlaveDeterminationProcedure->Stop();
1785         capabilityExchangeProcedure->Stop();
1786   } else {
1787         if (call.HasOptionalField(H225_CallProceeding_UUIE::e_h245Address))
1788                return StartControlChannel(call.m_h245Address);
1789   }
1790 
1791   return TRUE;
1792 }
1793 
1794 
OnReceivedProgress(const H323SignalPDU & pdu)1795 PBoolean H323Connection::OnReceivedProgress(const H323SignalPDU & pdu)
1796 {
1797   if (pdu.m_h323_uu_pdu.m_h323_message_body.GetTag() != H225_H323_UU_PDU_h323_message_body::e_progress)
1798     return FALSE;
1799   const H225_Progress_UUIE & progress = pdu.m_h323_uu_pdu.m_h323_message_body;
1800 
1801   SetRemoteVersions(progress.m_protocolIdentifier);
1802   SetRemotePartyInfo(pdu);
1803   SetRemoteApplication(progress.m_destinationInfo);
1804 
1805   // Check for fastStart data and start fast
1806   if (progress.HasOptionalField(H225_Progress_UUIE::e_fastStart))
1807     HandleFastStartAcknowledge(progress.m_fastStart);
1808 
1809   // Check that it has the H.245 channel connection info
1810   if (progress.HasOptionalField(H225_Progress_UUIE::e_h245Address))
1811     return StartControlChannel(progress.m_h245Address);
1812 
1813   return TRUE;
1814 }
1815 
1816 
OnReceivedAlerting(const H323SignalPDU & pdu)1817 PBoolean H323Connection::OnReceivedAlerting(const H323SignalPDU & pdu)
1818 {
1819   if (pdu.m_h323_uu_pdu.m_h323_message_body.GetTag() != H225_H323_UU_PDU_h323_message_body::e_alerting)
1820     return FALSE;
1821   const H225_Alerting_UUIE & alert = pdu.m_h323_uu_pdu.m_h323_message_body;
1822 
1823   SetRemoteVersions(alert.m_protocolIdentifier);
1824   SetRemotePartyInfo(pdu);
1825   SetRemoteApplication(alert.m_destinationInfo);
1826 
1827   if (!ReceiveAuthenticatorPDU<H225_Alerting_UUIE>(this,alert,
1828                          H225_H323_UU_PDU_h323_message_body::e_alerting)){
1829 //          don't do anything
1830   }
1831 
1832 #ifdef H323_H248
1833    if (alert.HasOptionalField(H225_Alerting_UUIE::e_serviceControl))
1834           OnReceiveServiceControlSessions(alert.m_serviceControl);
1835 #endif
1836 
1837 #ifdef H323_H460
1838   ReceiveFeatureSet<H225_Alerting_UUIE>(this, H460_MessageType::e_alerting, alert);
1839 #endif
1840 
1841   // Check for fastStart data and start fast
1842   if (alert.HasOptionalField(H225_Alerting_UUIE::e_fastStart))
1843     HandleFastStartAcknowledge(alert.m_fastStart);
1844 
1845   // Check that it has the H.245 channel connection info
1846   if (alert.HasOptionalField(H225_Alerting_UUIE::e_h245Address))
1847     if (!StartControlChannel(alert.m_h245Address))
1848       return FALSE;
1849 
1850   alertingTime = PTime();
1851 
1852   if (nonCallConnection)
1853       return true;
1854   else
1855       return OnAlerting(pdu, remotePartyName);
1856 }
1857 
1858 
OnReceivedSignalConnect(const H323SignalPDU & pdu)1859 PBoolean H323Connection::OnReceivedSignalConnect(const H323SignalPDU & pdu)
1860 {
1861 
1862   if (nonCallConnection) {
1863     connectedTime = PTime();
1864     connectionState = EstablishedConnection;
1865     return TRUE;
1866   }
1867 
1868   if (connectionState == ShuttingDownConnection)
1869     return FALSE;
1870   connectionState = HasExecutedSignalConnect;
1871 
1872   if (pdu.m_h323_uu_pdu.m_h323_message_body.GetTag() != H225_H323_UU_PDU_h323_message_body::e_connect)
1873     return FALSE;
1874   const H225_Connect_UUIE & connect = pdu.m_h323_uu_pdu.m_h323_message_body;
1875 
1876   SetRemoteVersions(connect.m_protocolIdentifier);
1877   SetRemotePartyInfo(pdu);
1878   SetRemoteApplication(connect.m_destinationInfo);
1879 
1880   if (connect.HasOptionalField(H225_Connect_UUIE::e_language)) {
1881 	  PStringList remoteLang;
1882 	  if (!H323GetLanguages(remoteLang, connect.m_language) || !MergeLanguages(remoteLang, false)) {
1883 		  PTRACE(2,"SETUP\tMissing or no common language support");
1884 	  }
1885   }
1886 
1887    if (!ReceiveAuthenticatorPDU<H225_Connect_UUIE>(this,connect,
1888                          H225_H323_UU_PDU_h323_message_body::e_connect)) {
1889 //          don't do anything
1890    }
1891 
1892 #ifdef H323_H460
1893   ReceiveFeatureSet<H225_Connect_UUIE>(this, H460_MessageType::e_connect, connect);
1894 #endif
1895 
1896   if (!OnOutgoingCall(pdu)) {
1897     ClearCall(EndedByNoAccept);
1898     return FALSE;
1899   }
1900 
1901 #ifdef H323_H450
1902   // Are we involved in a transfer with a non H.450.2 compatible transferred-to endpoint?
1903   if (h4502handler->GetState() == H4502Handler::e_ctAwaitSetupResponse &&
1904       h4502handler->IsctTimerRunning())
1905   {
1906     PTRACE(4, "H4502\tRemote Endpoint does not support H.450.2.");
1907     h4502handler->OnReceivedSetupReturnResult();
1908   }
1909 #endif
1910 
1911   // have answer, so set timeout to interval for monitoring calls health
1912   signallingChannel->SetReadTimeout(MonitorCallStatusTime);
1913 
1914   // If we are already faststartacknowledged (early media)
1915   // there is no need to proceed any further
1916   if (fastStartState == FastStartAcknowledged) {
1917       PTRACE(4, "H225\tConnect Accepted: Early Media already negotiated.");
1918       return TRUE;
1919   }
1920 
1921   // Check for fastStart data and start fast
1922   if (connect.HasOptionalField(H225_Connect_UUIE::e_fastStart))
1923     HandleFastStartAcknowledge(connect.m_fastStart);
1924 
1925   // Check that it has the H.245 channel connection info
1926   // ignore if we already have a Fast Start connection
1927   if (connect.HasOptionalField(H225_Connect_UUIE::e_h245Address) &&
1928              fastStartState != FastStartAcknowledged) {
1929     if (!StartControlChannel(connect.m_h245Address))
1930         return FALSE;
1931   }
1932 
1933   // If didn't get fast start channels accepted by remote then clear our
1934   // proposed channels so we can renegotiate
1935   if (fastStartState != FastStartAcknowledged) {
1936     fastStartState = FastStartDisabled;
1937     fastStartChannels.RemoveAll();
1938 #ifdef P_STUN
1939     m_NATSockets.clear();
1940 #endif
1941   }
1942 
1943   PTRACE(4, "H225\tFast Start " << (h245Tunneling ? "TRUE" : "FALSE")
1944                                     << " fastStartState " << fastStartState);
1945 
1946   // If we have a H.245 channel available, bring it up. We either have media
1947   // and this is just so user indications work, or we don't have media and
1948   // desperately need it!
1949   if (h245Tunneling || controlChannel != NULL)
1950       return OnStartHandleControlChannel();
1951 
1952   // We have no tunnelling and not separate channel, but we really want one
1953   // so we will start one using a facility message
1954   PTRACE(2, "H225\tNo H245 address provided by remote, starting control channel");
1955 
1956   if (!StartControlChannel())
1957     return FALSE;
1958 
1959   H323SignalPDU want245PDU;
1960   H225_Facility_UUIE * fac = want245PDU.BuildFacility(*this, FALSE, H225_FacilityReason::e_startH245);
1961 
1962   fac->IncludeOptionalField(H225_Facility_UUIE::e_h245Address);
1963   controlChannel->SetUpTransportPDU(fac->m_h245Address, TRUE);
1964 
1965   return WriteSignalPDU(want245PDU);
1966 }
1967 
1968 
OnReceivedFacility(const H323SignalPDU & pdu)1969 PBoolean H323Connection::OnReceivedFacility(const H323SignalPDU & pdu)
1970 {
1971   if (pdu.m_h323_uu_pdu.m_h323_message_body.GetTag() == H225_H323_UU_PDU_h323_message_body::e_empty)
1972     return TRUE;
1973 
1974   if (pdu.m_h323_uu_pdu.m_h323_message_body.GetTag() != H225_H323_UU_PDU_h323_message_body::e_facility)
1975     return FALSE;
1976   const H225_Facility_UUIE & fac = pdu.m_h323_uu_pdu.m_h323_message_body;
1977 
1978   if (!ReceiveAuthenticatorPDU<H225_Facility_UUIE>(this,fac,
1979                             H225_H323_UU_PDU_h323_message_body::e_facility)) {
1980 //          don't do anything
1981   }
1982 
1983 #ifdef H323_H248
1984    if (fac.HasOptionalField(H225_Facility_UUIE::e_serviceControl))
1985           OnReceiveServiceControlSessions(fac.m_serviceControl);
1986 #endif
1987 
1988 #ifdef H323_H460
1989    // Do not process H.245 Control PDU's
1990    if (!pdu.m_h323_uu_pdu.HasOptionalField(H225_H323_UU_PDU::e_h245Control))
1991          ReceiveFeatureSet<H225_Facility_UUIE>(this, H460_MessageType::e_facility, fac);
1992 #endif
1993 
1994   SetRemoteVersions(fac.m_protocolIdentifier);
1995 
1996   // Check for fastStart data and start fast
1997   if (fac.HasOptionalField(H225_Facility_UUIE::e_fastStart))
1998     HandleFastStartAcknowledge(fac.m_fastStart);
1999 
2000   // Check that it has the H.245 channel connection info
2001   if (fac.HasOptionalField(H225_Facility_UUIE::e_h245Address)) {
2002     if (controlChannel != NULL && !controlChannel->IsOpen()) {
2003       // Fix race condition where both side want to open H.245 channel. we have
2004       // channel bit it is not open (ie we are listening) and the remote has
2005       // sent us an address to connect to. To resolve we compare the addresses.
2006 
2007       H225_TransportAddress myAddress;
2008       controlChannel->GetLocalAddress().SetPDU(myAddress);
2009       PPER_Stream myBuffer;
2010       myAddress.Encode(myBuffer);
2011 
2012       PPER_Stream otherBuffer;
2013       fac.m_h245Address.Encode(otherBuffer);
2014 
2015       if (myBuffer < otherBuffer || OnH245AddressConflict()) {
2016         PTRACE(2, "H225\tSimultaneous start of H.245 channel, connecting to remote.");
2017         controlChannel->CleanUpOnTermination();
2018         delete controlChannel;
2019         controlChannel = NULL;
2020       }
2021       else {
2022         PTRACE(2, "H225\tSimultaneous start of H.245 channel, using local listener.");
2023       }
2024     }
2025 
2026     if (!StartControlChannel(fac.m_h245Address))
2027       return FALSE;
2028   }
2029 
2030   if ((fac.m_reason.GetTag() != H225_FacilityReason::e_callForwarded)
2031       && (fac.m_reason.GetTag() != H225_FacilityReason::e_routeCallToGatekeeper)
2032       && (fac.m_reason.GetTag() != H225_FacilityReason::e_routeCallToMC))
2033     return TRUE;
2034 
2035   PString address;
2036   if (fac.m_reason.GetTag() == H225_FacilityReason::e_routeCallToGatekeeper) {
2037       PIPSocket::Address add;
2038       H323TransportAddress(remotePartyAddress).GetIpAddress(add);
2039       if (add.IsValid() && !add.IsAny() && !add.IsLoopback())
2040             address = add.AsString();
2041       else if (remotePartyAddress.Find('@') != P_MAX_INDEX)
2042             address = remotePartyAddress.Left(remotePartyAddress.Find('@'));
2043       else
2044             address = remotePartyAddress;
2045   }
2046 
2047   if (fac.HasOptionalField(H225_Facility_UUIE::e_alternativeAliasAddress) &&
2048       fac.m_alternativeAliasAddress.GetSize() > 0)
2049     address = H323GetAliasAddressString(fac.m_alternativeAliasAddress[0]);
2050 
2051   if (fac.HasOptionalField(H225_Facility_UUIE::e_alternativeAddress)) {
2052     if (!address)
2053       address += '@';
2054     address += H323TransportAddress(fac.m_alternativeAddress);
2055   }
2056 
2057   if (endpoint.OnConnectionForwarded(*this, address, pdu)) {
2058     ClearCall(EndedByCallForwarded);
2059     return FALSE;
2060   }
2061 
2062   if (!endpoint.CanAutoCallForward())
2063     return TRUE;
2064 
2065   if (!endpoint.ForwardConnection(*this, address, pdu))
2066     return TRUE;
2067 
2068   // This connection is on the way out and a new one has the same token now
2069   // so change our token to make sure no accidents can happen clearing the
2070   // wrong call
2071   callToken += "-forwarded";
2072   return FALSE;
2073 }
2074 
2075 
OnReceivedSignalNotify(const H323SignalPDU & pdu)2076 PBoolean H323Connection::OnReceivedSignalNotify(const H323SignalPDU & pdu)
2077 {
2078   if (pdu.m_h323_uu_pdu.m_h323_message_body.GetTag() == H225_H323_UU_PDU_h323_message_body::e_notify) {
2079     const H225_Notify_UUIE & notify = pdu.m_h323_uu_pdu.m_h323_message_body;
2080     SetRemoteVersions(notify.m_protocolIdentifier);
2081   }
2082   return TRUE;
2083 }
2084 
2085 
OnReceivedSignalStatus(const H323SignalPDU & pdu)2086 PBoolean H323Connection::OnReceivedSignalStatus(const H323SignalPDU & pdu)
2087 {
2088   if (pdu.m_h323_uu_pdu.m_h323_message_body.GetTag() == H225_H323_UU_PDU_h323_message_body::e_status) {
2089     const H225_Status_UUIE & status = pdu.m_h323_uu_pdu.m_h323_message_body;
2090     SetRemoteVersions(status.m_protocolIdentifier);
2091   }
2092   return TRUE;
2093 }
2094 
2095 
OnReceivedStatusEnquiry(const H323SignalPDU & pdu)2096 PBoolean H323Connection::OnReceivedStatusEnquiry(const H323SignalPDU & pdu)
2097 {
2098   if (pdu.m_h323_uu_pdu.m_h323_message_body.GetTag() == H225_H323_UU_PDU_h323_message_body::e_statusInquiry) {
2099     const H225_StatusInquiry_UUIE & status = pdu.m_h323_uu_pdu.m_h323_message_body;
2100     SetRemoteVersions(status.m_protocolIdentifier);
2101   }
2102 
2103   H323SignalPDU reply;
2104   reply.BuildStatus(*this);
2105   return reply.Write(*signallingChannel,this);
2106 }
2107 
2108 
OnReceivedReleaseComplete(const H323SignalPDU & pdu)2109 void H323Connection::OnReceivedReleaseComplete(const H323SignalPDU & pdu)
2110 {
2111   if (!callEndTime.IsValid())
2112     callEndTime = PTime();
2113 
2114   endSessionReceived.Signal();
2115 
2116   if (q931Cause == Q931::ErrorInCauseIE)
2117     q931Cause = pdu.GetQ931().GetCause();
2118 
2119   if (pdu.m_h323_uu_pdu.m_h323_message_body.GetTag() != H225_H323_UU_PDU_h323_message_body::e_releaseComplete)
2120     return;
2121   const H225_ReleaseComplete_UUIE & rc = pdu.m_h323_uu_pdu.m_h323_message_body;
2122 
2123   switch (connectionState) {
2124     case EstablishedConnection :
2125       if (rc.m_reason.GetTag() == H225_ReleaseCompleteReason::e_facilityCallDeflection)
2126         ClearCall(EndedByCallForwarded);
2127       else
2128         ClearCall(EndedByRemoteUser);
2129       break;
2130 
2131     case AwaitingLocalAnswer :
2132       if (rc.m_reason.GetTag() == H225_ReleaseCompleteReason::e_facilityCallDeflection)
2133         ClearCall(EndedByCallForwarded);
2134       else
2135         ClearCall(EndedByCallerAbort);
2136       break;
2137 
2138     default :
2139       if (callEndReason == EndedByRefusal)
2140         callEndReason = NumCallEndReasons;
2141 
2142 #ifdef H323_H450
2143       // Are we involved in a transfer with a non H.450.2 compatible transferred-to endpoint?
2144       if (h4502handler->GetState() == H4502Handler::e_ctAwaitSetupResponse &&
2145           h4502handler->IsctTimerRunning())
2146       {
2147         PTRACE(4, "H4502\tThe Remote Endpoint has rejected our transfer request and does not support H.450.2.");
2148         h4502handler->OnReceivedSetupReturnError(H4501_GeneralErrorList::e_notAvailable);
2149       }
2150 #endif
2151 
2152 #ifdef H323_H460
2153     ReceiveFeatureSet<H225_ReleaseComplete_UUIE>(this, H460_MessageType::e_releaseComplete, rc);
2154 #endif
2155 
2156       if (pdu.m_h323_uu_pdu.m_h323_message_body.GetTag() != H225_H323_UU_PDU_h323_message_body::e_releaseComplete)
2157         ClearCall(EndedByRefusal);
2158       else {
2159         SetRemoteVersions(rc.m_protocolIdentifier);
2160         ClearCall(H323TranslateToCallEndReason(pdu.GetQ931().GetCause(), rc.m_reason));
2161       }
2162   }
2163 }
2164 
OnIncomingCall(const H323SignalPDU & setupPDU,H323SignalPDU & alertingPDU,CallEndReason & reason)2165 PBoolean H323Connection::OnIncomingCall(const H323SignalPDU & setupPDU,
2166                                           H323SignalPDU & alertingPDU,
2167                                           CallEndReason & reason)
2168 {
2169   return endpoint.OnIncomingCall(*this, setupPDU, alertingPDU, reason);
2170 }
2171 
OnIncomingCall(const H323SignalPDU & setupPDU,H323SignalPDU & alertingPDU)2172 PBoolean H323Connection::OnIncomingCall(const H323SignalPDU & setupPDU,
2173                                           H323SignalPDU & alertingPDU)
2174 {
2175   return endpoint.OnIncomingCall(*this, setupPDU, alertingPDU);
2176 }
2177 
2178 
ForwardCall(const PString & forwardParty)2179 PBoolean H323Connection::ForwardCall(const PString & forwardParty)
2180 {
2181   if (forwardParty.IsEmpty())
2182     return FALSE;
2183 
2184   PString alias;
2185   H323TransportAddress address;
2186 
2187   PStringList Addresses;
2188   if (!endpoint.ResolveCallParty(forwardParty, Addresses))
2189       return FALSE;
2190 
2191   if (!endpoint.ParsePartyName(Addresses[0], alias, address)) {
2192       PTRACE(2, "H323\tCould not parse forward party \"" << forwardParty << '"');
2193       return FALSE;
2194   }
2195 
2196   H323SignalPDU redirectPDU;
2197   H225_Facility_UUIE * fac = redirectPDU.BuildFacility(*this, FALSE, H225_FacilityReason::e_callForwarded);
2198 
2199   if (!address) {
2200     fac->IncludeOptionalField(H225_Facility_UUIE::e_alternativeAddress);
2201     address.SetPDU(fac->m_alternativeAddress);
2202   }
2203 
2204   if (!alias) {
2205     fac->IncludeOptionalField(H225_Facility_UUIE::e_alternativeAliasAddress);
2206     fac->m_alternativeAliasAddress.SetSize(1);
2207     H323SetAliasAddress(alias, fac->m_alternativeAliasAddress[0]);
2208   }
2209 
2210   return WriteSignalPDU(redirectPDU);
2211 }
2212 
ForwardCall(const H225_ArrayOf_AliasAddress & alternativeAliasAddresses,const H323TransportAddress & alternativeAddress)2213 PBoolean H323Connection::ForwardCall(const H225_ArrayOf_AliasAddress & alternativeAliasAddresses, const H323TransportAddress & alternativeAddress)
2214 {
2215   H323SignalPDU redirectPDU;
2216   H225_Facility_UUIE * fac = redirectPDU.BuildFacility(*this, FALSE, H225_FacilityReason::e_callForwarded);
2217 
2218   if (!alternativeAddress) {
2219     fac->IncludeOptionalField(H225_Facility_UUIE::e_alternativeAddress);
2220     alternativeAddress.SetPDU(fac->m_alternativeAddress);
2221   }
2222 
2223   if (alternativeAliasAddresses.GetSize() > 0) {
2224     fac->IncludeOptionalField(H225_Facility_UUIE::e_alternativeAliasAddress);
2225     fac->m_alternativeAliasAddress = alternativeAliasAddresses;
2226   }
2227 
2228   return WriteSignalPDU(redirectPDU);
2229 }
2230 
2231 
RouteCallToMC(const PString & forwardParty,const H225_ConferenceIdentifier & confID)2232 PBoolean H323Connection::RouteCallToMC(const PString & forwardParty, const H225_ConferenceIdentifier & confID)
2233 {
2234   if (forwardParty.IsEmpty())
2235     return FALSE;
2236 
2237   PString alias;
2238   H323TransportAddress address;
2239 
2240   PStringList Addresses;
2241   if (!endpoint.ResolveCallParty(forwardParty, Addresses))
2242       return FALSE;
2243 
2244   if (!endpoint.ParsePartyName(Addresses[0], alias, address)) {
2245       PTRACE(2, "H323\tCould not parse forward party \"" << forwardParty << '"');
2246       return FALSE;
2247   }
2248 
2249   H323SignalPDU redirectPDU;
2250   H225_Facility_UUIE * fac = redirectPDU.BuildFacility(*this, FALSE, H225_FacilityReason::e_routeCallToMC);
2251 
2252   if (!address) {
2253     fac->IncludeOptionalField(H225_Facility_UUIE::e_alternativeAddress);
2254     address.SetPDU(fac->m_alternativeAddress);
2255   }
2256 
2257   if (!alias) {
2258     fac->IncludeOptionalField(H225_Facility_UUIE::e_alternativeAliasAddress);
2259     fac->m_alternativeAliasAddress.SetSize(1);
2260     H323SetAliasAddress(alias, fac->m_alternativeAliasAddress[0]);
2261   }
2262 
2263   fac->IncludeOptionalField(H225_Facility_UUIE::e_conferenceID);
2264   fac->m_conferenceID = confID;
2265 
2266   return WriteSignalPDU(redirectPDU);
2267 }
2268 
RouteCallToMC(const H225_ArrayOf_AliasAddress & alternativeAliasAddresses,const H323TransportAddress & alternativeAddress,const H225_ConferenceIdentifier & confID)2269 PBoolean H323Connection::RouteCallToMC(const H225_ArrayOf_AliasAddress & alternativeAliasAddresses, const H323TransportAddress & alternativeAddress, const H225_ConferenceIdentifier & confID)
2270 {
2271   H323SignalPDU redirectPDU;
2272   H225_Facility_UUIE * fac = redirectPDU.BuildFacility(*this, FALSE, H225_FacilityReason::e_routeCallToMC);
2273 
2274   if (!alternativeAddress) {
2275     fac->IncludeOptionalField(H225_Facility_UUIE::e_alternativeAddress);
2276     alternativeAddress.SetPDU(fac->m_alternativeAddress);
2277   }
2278 
2279   if (alternativeAliasAddresses.GetSize() > 0) {
2280     fac->IncludeOptionalField(H225_Facility_UUIE::e_alternativeAliasAddress);
2281     fac->m_alternativeAliasAddress = alternativeAliasAddresses;
2282   }
2283 
2284   fac->IncludeOptionalField(H225_Facility_UUIE::e_conferenceID);
2285   fac->m_conferenceID = confID;
2286 
2287   return WriteSignalPDU(redirectPDU);
2288 }
2289 
2290 
2291 H323Connection::AnswerCallResponse
OnAnswerCall(const PString & caller,const H323SignalPDU & setupPDU,H323SignalPDU & connectPDU)2292      H323Connection::OnAnswerCall(const PString & caller,
2293                                   const H323SignalPDU & setupPDU,
2294                                   H323SignalPDU & connectPDU)
2295 {
2296   return endpoint.OnAnswerCall(*this, caller, setupPDU, connectPDU);
2297 }
2298 
2299 
AnsweringCall(AnswerCallResponse response)2300 void H323Connection::AnsweringCall(AnswerCallResponse response)
2301 {
2302   PTRACE(2, "H323\tAnswering call: " << response);
2303 
2304   if (!Lock())
2305     return;
2306 
2307   switch (response) {
2308     default : // AnswerCallDeferred
2309       break;
2310 
2311     case AnswerCallDeferredWithMedia :
2312       if (!mediaWaitForConnect) {
2313         // create a new facility PDU if doing AnswerDeferredWithMedia
2314         H323SignalPDU want245PDU;
2315         H225_Progress_UUIE & prog = want245PDU.BuildProgress(*this);
2316 
2317         PBoolean sendPDU = TRUE;
2318 
2319         if (SendFastStartAcknowledge(prog.m_fastStart))
2320           prog.IncludeOptionalField(H225_Progress_UUIE::e_fastStart);
2321         else {
2322           // See if aborted call
2323           if (connectionState == ShuttingDownConnection)
2324             break;
2325 
2326           // Do early H.245 start
2327           H225_Facility_UUIE & fac = *want245PDU.BuildFacility(*this, FALSE, H225_FacilityReason::e_startH245);
2328           earlyStart = TRUE;
2329           if (!h245Tunneling && (controlChannel == NULL)) {
2330             if (!StartControlChannel())
2331               break;
2332 
2333             fac.IncludeOptionalField(H225_Facility_UUIE::e_h245Address);
2334             controlChannel->SetUpTransportPDU(fac.m_h245Address, TRUE);
2335           }
2336           else
2337             sendPDU = FALSE;
2338         }
2339 
2340         if (sendPDU) {
2341           HandleTunnelPDU(&want245PDU);
2342           WriteSignalPDU(want245PDU);
2343         }
2344       }
2345       break;
2346 
2347     case AnswerCallAlertWithMedia :
2348       if (alertingPDU != NULL && !mediaWaitForConnect) {
2349         H225_Alerting_UUIE & alerting = alertingPDU->m_h323_uu_pdu.m_h323_message_body;
2350 
2351         PBoolean sendPDU = TRUE;
2352         if (SendFastStartAcknowledge(alerting.m_fastStart))
2353           alerting.IncludeOptionalField(H225_Alerting_UUIE::e_fastStart);
2354         else {
2355           alerting.IncludeOptionalField(H225_Alerting_UUIE::e_fastConnectRefused);
2356 
2357           // See if aborted call
2358           if (connectionState == ShuttingDownConnection)
2359             break;
2360 
2361           // Do early H.245 start
2362           earlyStart = TRUE;
2363           if (!h245Tunneling && (controlChannel == NULL)) {
2364             if (!StartControlChannel())
2365               break;
2366             alerting.IncludeOptionalField(H225_Alerting_UUIE::e_h245Address);
2367             controlChannel->SetUpTransportPDU(alerting.m_h245Address, TRUE);
2368           }
2369           else
2370             sendPDU = FALSE;
2371         }
2372 
2373         if (sendPDU) {
2374           HandleTunnelPDU(alertingPDU);
2375 
2376 #ifdef H323_H450
2377           h450dispatcher->AttachToAlerting(*alertingPDU);
2378 #endif
2379 
2380           WriteSignalPDU(*alertingPDU);
2381           alertingTime = PTime();
2382         }
2383         break;
2384       }
2385       // else clause falls into AnswerCallPending case
2386 
2387     case AnswerCallPending :
2388       if (alertingPDU != NULL) {
2389         // send Q931 Alerting PDU
2390         PTRACE(3, "H225\tSending Alerting PDU");
2391 
2392         HandleTunnelPDU(alertingPDU);
2393 
2394 #ifdef H323_H450
2395         h450dispatcher->AttachToAlerting(*alertingPDU);
2396 #endif
2397 
2398         // commented out by CRS: no need to check for lack of fastStart channels
2399         // as this Alerting is not associated with media channel. And doing so
2400         // screws up deferred fastStart setup
2401         //
2402         //if (fastStartChannels.IsEmpty()) {
2403         //  H225_Alerting_UUIE & alerting = alertingPDU->m_h323_uu_pdu.m_h323_message_body;
2404         //  alerting.IncludeOptionalField(H225_Alerting_UUIE::e_fastConnectRefused);
2405         //}
2406 
2407         WriteSignalPDU(*alertingPDU);
2408         alertingTime = PTime();
2409       }
2410       break;
2411 
2412     case AnswerCallDenied :
2413       // If response is denied, abort the call
2414       PTRACE(1, "H225\tApplication has declined to answer incoming call");
2415       ClearCall(EndedByAnswerDenied);
2416       break;
2417 
2418     case AnswerCallDeniedByInvalidCID :
2419       // If response is denied, abort the call
2420       PTRACE(1, "H225\tApplication has refused to answer incoming call due to invalid conference ID");
2421       ClearCall(EndedByInvalidConferenceID);
2422       break;
2423 
2424     case AnswerCallNowWithAlert :
2425       if (alertingPDU != NULL) {
2426         // send Q931 Alerting PDU
2427         PTRACE(3, "H225\tSending Alerting PDU prior to AnswerCall Now");
2428 
2429         HandleTunnelPDU(alertingPDU);
2430 
2431 #ifdef H323_H450
2432         h450dispatcher->AttachToAlerting(*alertingPDU);
2433 #endif
2434         WriteSignalPDU(*alertingPDU);
2435         alertingTime = PTime();
2436       }
2437         // Now we progress with AnswerCallNow.
2438     case AnswerCallNow :
2439       if (connectPDU != NULL) {
2440         H225_Connect_UUIE & connect = connectPDU->m_h323_uu_pdu.m_h323_message_body;
2441 
2442         // If we have not already negotiated Fast Connect (early media)
2443         if (fastStartState != FastStartAcknowledged) {
2444           // Now ask the application to select which channels to start
2445           if (SendFastStartAcknowledge(connect.m_fastStart))
2446             connect.IncludeOptionalField(H225_Connect_UUIE::e_fastStart);
2447           else
2448             connect.IncludeOptionalField(H225_Connect_UUIE::e_fastConnectRefused);
2449         }
2450 
2451         // See if aborted call
2452         if (connectionState == ShuttingDownConnection)
2453           break;
2454 
2455         // Set flag that we are up to CONNECT stage
2456         connectionState = HasExecutedSignalConnect;
2457 
2458 #ifdef H323_H450
2459         h450dispatcher->AttachToConnect(*connectPDU);
2460 #endif
2461         if (!nonCallConnection) {
2462             if (h245Tunneling) {
2463               // If no channels selected (or never provided) do traditional H245 start
2464               if (fastStartState == FastStartDisabled) {
2465                 h245TunnelTxPDU = connectPDU; // Piggy back H245 on this reply
2466                 PBoolean ok = StartControlNegotiations();
2467                 h245TunnelTxPDU = NULL;
2468                 if (!ok)
2469                   break;
2470               }
2471 
2472               HandleTunnelPDU(connectPDU);
2473             }
2474             else { // Start separate H.245 channel if not tunneling.
2475               if (!StartControlChannel())
2476                 break;
2477               connect.IncludeOptionalField(H225_Connect_UUIE::e_h245Address);
2478               controlChannel->SetUpTransportPDU(connect.m_h245Address, TRUE);
2479             }
2480         }
2481 
2482         connectedTime = PTime();
2483         WriteSignalPDU(*connectPDU); // Send H323 Connect PDU
2484         delete connectPDU;
2485         connectPDU = NULL;
2486         delete alertingPDU;
2487         alertingPDU = NULL;
2488       }
2489   }
2490 
2491   InternalEstablishedConnectionCheck();
2492   Unlock();
2493 }
2494 
SendSignalSetup(const PString & alias,const H323TransportAddress & address)2495 H323Connection::CallEndReason H323Connection::SendSignalSetup(const PString & alias,
2496                                                               const H323TransportAddress & address)
2497 {
2498   CallEndReason reason = NumCallEndReasons;
2499 
2500   // Start the call, first state is asking gatekeeper
2501   connectionState = AwaitingGatekeeperAdmission;
2502 
2503   // Indicate the direction of call.
2504   if (alias.IsEmpty())
2505     remotePartyName = remotePartyAddress = address;
2506   else {
2507     remotePartyName = alias;
2508     remoteAliasNames.AppendString(alias);
2509     if (!address.IsEmpty())
2510        remotePartyAddress = alias + '@' + address;
2511     else
2512        remotePartyAddress = alias;
2513   }
2514 
2515   // Start building the setup PDU to get various ID's
2516   H323SignalPDU setupPDU;
2517   H225_Setup_UUIE & setup = setupPDU.BuildSetup(*this, address);
2518 
2519 #ifdef H323_H450
2520   h450dispatcher->AttachToSetup(setupPDU);
2521 #endif
2522 
2523   // Save the identifiers generated by BuildSetup
2524   setupPDU.GetQ931().GetCalledPartyNumber(remotePartyNumber);
2525 
2526   H323TransportAddress gatekeeperRoute = address;
2527 
2528   // Check for gatekeeper and do admission check if have one
2529   H323Gatekeeper * gatekeeper = endpoint.GetGatekeeper();
2530   H225_ArrayOf_AliasAddress newAliasAddresses;
2531   PStringList callLanguages;
2532   if (gatekeeper != NULL) {
2533     H323Gatekeeper::AdmissionResponse response;
2534     response.transportAddress = &gatekeeperRoute;
2535     response.aliasAddresses = &newAliasAddresses;
2536     response.languageSupport = &callLanguages;
2537     if (!gkAccessTokenOID)
2538       response.accessTokenData = &gkAccessTokenData;
2539     while (!gatekeeper->AdmissionRequest(*this, response, alias.IsEmpty())) {
2540       PTRACE(1, "H225\tGatekeeper refused admission: "
2541              << (response.rejectReason == UINT_MAX
2542                   ? PString("Transport error")
2543                   : H225_AdmissionRejectReason(response.rejectReason).GetTagName()));
2544 #ifdef H323_H450
2545       h4502handler->onReceivedAdmissionReject(H4501_GeneralErrorList::e_notAvailable);
2546 #endif
2547 
2548       switch (response.rejectReason) {
2549         case H225_AdmissionRejectReason::e_calledPartyNotRegistered :
2550           return EndedByNoUser;
2551         case H225_AdmissionRejectReason::e_requestDenied :
2552           return EndedByNoBandwidth;
2553         case H225_AdmissionRejectReason::e_invalidPermission :
2554         case H225_AdmissionRejectReason::e_securityDenial :
2555           return EndedBySecurityDenial;
2556         case H225_AdmissionRejectReason::e_resourceUnavailable :
2557           return EndedByRemoteBusy;
2558         case H225_AdmissionRejectReason::e_incompleteAddress :
2559           if (OnInsufficientDigits())
2560             break;
2561           // Then default case
2562         default :
2563           return EndedByGatekeeper;
2564       }
2565 
2566       PString lastRemotePartyName = remotePartyName;
2567       while (lastRemotePartyName == remotePartyName) {
2568         Unlock(); // Release the mutex as can deadlock trying to clear call during connect.
2569         digitsWaitFlag.Wait();
2570         if (!Lock()) // Lock while checking for shutting down.
2571           return EndedByCallerAbort;
2572       }
2573     }
2574     mustSendDRQ = TRUE;
2575     if (response.gatekeeperRouted) {
2576       setup.IncludeOptionalField(H225_Setup_UUIE::e_endpointIdentifier);
2577       setup.m_endpointIdentifier = gatekeeper->GetEndpointIdentifier();
2578       gatekeeperRouted = TRUE;
2579     }
2580   }
2581 
2582   // Update the field e_destinationAddress in the SETUP PDU to reflect the new
2583   // alias received in the ACF (m_destinationInfo).
2584   if (newAliasAddresses.GetSize() > 0) {
2585     setup.IncludeOptionalField(H225_Setup_UUIE::e_destinationAddress);
2586     setup.m_destinationAddress = newAliasAddresses;
2587 
2588     // Update the Q.931 Information Element (if is an E.164 address)
2589     PString e164 = H323GetAliasAddressE164(newAliasAddresses);
2590     if (!e164) {
2591       remotePartyNumber = e164;
2592       setupPDU.GetQ931().SetCalledPartyNumber(e164);
2593     }
2594   }
2595 
2596   if (addAccessTokenToSetup && !gkAccessTokenOID && !gkAccessTokenData.IsEmpty()) {
2597     PString oid1, oid2;
2598     PINDEX comma = gkAccessTokenOID.Find(',');
2599     if (comma == P_MAX_INDEX)
2600       oid1 = oid2 = gkAccessTokenOID;
2601     else {
2602       oid1 = gkAccessTokenOID.Left(comma);
2603       oid2 = gkAccessTokenOID.Mid(comma+1);
2604     }
2605     setup.IncludeOptionalField(H225_Setup_UUIE::e_tokens);
2606     PINDEX last = setup.m_tokens.GetSize();
2607     setup.m_tokens.SetSize(last+1);
2608     setup.m_tokens[last].m_tokenOID = oid1;
2609     setup.m_tokens[last].IncludeOptionalField(H235_ClearToken::e_nonStandard);
2610     setup.m_tokens[last].m_nonStandard.m_nonStandardIdentifier = oid2;
2611     setup.m_tokens[last].m_nonStandard.m_data = gkAccessTokenData;
2612   }
2613 
2614   if (H323SetLanguages(callLanguages.GetSize() > 0 ? callLanguages : localLanguages, setup.m_language))
2615      setup.IncludeOptionalField(H225_Setup_UUIE::e_language);
2616 
2617 #ifdef H323_H46017
2618   if (endpoint.RegisteredWithH46017()) {
2619        Unlock();
2620   } else
2621 #endif
2622   {
2623       if (gatekeeper != NULL) {
2624           if (signallingChannel->InitialiseSecurity(&m_transportSecurity) &&
2625               !m_transportSecurity.GetRemoteTLSAddress().IsEmpty()) {
2626               gatekeeperRoute = m_transportSecurity.GetRemoteTLSAddress();
2627               PTRACE(4, "H225\tChanged remote address to secure " << gatekeeperRoute);
2628           }
2629       }
2630 
2631       if (!signallingChannel->IsOpen() && !signallingChannel->SetRemoteAddress(gatekeeperRoute)) {
2632         PTRACE(1, "H225\tInvalid "
2633                << (gatekeeperRoute != address ? "gatekeeper" : "user")
2634                << " supplied address: \"" << gatekeeperRoute << '"');
2635         connectionState = AwaitingTransportConnect;
2636         return EndedByConnectFail;
2637       }
2638 
2639       // Do the transport connect
2640       connectionState = AwaitingTransportConnect;
2641 
2642 
2643       // Release the mutex as can deadlock trying to clear call during connect.
2644       Unlock();
2645 
2646       PBoolean connectFailed = false;
2647       if (!signallingChannel->IsOpen()) {
2648         signallingChannel->SetWriteTimeout(100);
2649         connectFailed = !signallingChannel->Connect();
2650       }
2651 
2652       // See if transport connect failed, abort if so.
2653       if (connectFailed) {
2654         connectionState = NoConnectionActive;
2655         switch (signallingChannel->GetErrorNumber()) {
2656           case ENETUNREACH :
2657             reason = EndedByUnreachable;
2658             break;
2659           case ECONNREFUSED :
2660             reason = EndedByNoEndPoint;
2661             break;
2662           case ETIMEDOUT :
2663             reason = EndedByHostOffline;
2664             break;
2665           default:
2666              reason = EndedByConnectFail;
2667         }
2668       }
2669   }
2670 
2671   // Lock while checking for shutting down.
2672   if (!Lock())
2673     return EndedByCallerAbort;
2674   else if (reason != NumCallEndReasons)
2675     return reason;
2676 
2677   PTRACE(3, "H225\tSending Setup PDU");
2678   connectionState = AwaitingSignalConnect;
2679 
2680  // Add CryptoTokens and H460 features if available (need to do this after the ARQ/ACF)
2681    setupPDU.InsertCryptoTokensSetup(*this,setup);
2682 
2683 #ifdef H323_H460
2684    if (!disableH460) {
2685      if (IsNonCallConnection())
2686          setupPDU.InsertH460Generic(*this);
2687 
2688      setupPDU.InsertH460Setup(*this,setup);
2689    }
2690 #endif
2691 
2692   // Put in all the signalling addresses for link
2693   setup.IncludeOptionalField(H225_Setup_UUIE::e_sourceCallSignalAddress);
2694   signallingChannel->SetUpTransportPDU(setup.m_sourceCallSignalAddress, TRUE, this);
2695   if (!setup.HasOptionalField(H225_Setup_UUIE::e_destCallSignalAddress)) {
2696     setup.IncludeOptionalField(H225_Setup_UUIE::e_destCallSignalAddress);
2697     signallingChannel->SetUpTransportPDU(setup.m_destCallSignalAddress, FALSE, this);
2698   }
2699 
2700   // If a standard call do Fast Start (if required)
2701 if (setup.m_conferenceGoal.GetTag() == H225_Setup_UUIE_conferenceGoal::e_create) {
2702 
2703   // Get the local capabilities before fast start is handled
2704   OnSetLocalCapabilities();
2705 
2706   // Adjust the local userInput capabilities.
2707   OnSetLocalUserInputCapabilities();
2708 
2709   // Ask the application what channels to open
2710   PTRACE(3, "H225\tCheck for Fast start by local endpoint");
2711   fastStartChannels.RemoveAll();
2712   OnSelectLogicalChannels();
2713 
2714   // If application called OpenLogicalChannel, put in the fastStart field
2715   if (!fastStartChannels.IsEmpty()) {
2716     PTRACE(3, "H225\tFast start begun by local endpoint");
2717     for (PINDEX i = 0; i < fastStartChannels.GetSize(); i++)
2718       BuildFastStartList(fastStartChannels[i], setup.m_fastStart, H323Channel::IsReceiver);
2719     if (setup.m_fastStart.GetSize() > 0)
2720       setup.IncludeOptionalField(H225_Setup_UUIE::e_fastStart);
2721   }
2722 
2723   // Search the capability set and see if we have video capability
2724   for (PINDEX i = 0; i < localCapabilities.GetSize(); i++) {
2725     switch (localCapabilities[i].GetMainType()) {
2726       case H323Capability::e_Audio :
2727       case H323Capability::e_UserInput :
2728       case H323Capability::e_GenericControl :
2729       case H323Capability::e_ConferenceControl :
2730       case H323Capability::e_Security :
2731         break;
2732 
2733       default : // Is video or other data (eg T.120)
2734         unsigned transferRate= 384000;  // default to 384 kb/s;
2735         OnBearerCapabilityTransferRate(transferRate);
2736         unsigned rate = setupPDU.GetQ931().SetBearerTransferRate(transferRate);
2737         setupPDU.GetQ931().SetBearerCapabilities(Q931::TransferUnrestrictedDigital, rate);
2738         i = localCapabilities.GetSize(); // Break out of the for loop
2739         break;
2740     }
2741   }
2742 }
2743 
2744   if (!OnSendSignalSetup(setupPDU))
2745     return EndedByNoAccept;
2746 
2747   setupPDU.GetQ931().GetCalledPartyNumber(remotePartyNumber);
2748 
2749   //fastStartState = FastStartDisabled;
2750   PBoolean set_lastPDUWasH245inSETUP = FALSE;
2751 
2752   if (h245Tunneling && doH245inSETUP) {
2753     h245TunnelTxPDU = &setupPDU;
2754 
2755     // Try and start the master/slave and capability exchange through the tunnel
2756     // Note: this used to be disallowed but is now allowed as of H323v4
2757     PBoolean ok = StartControlNegotiations();
2758 
2759     h245TunnelTxPDU = NULL;
2760 
2761     if (!ok)
2762       return EndedByTransportFail;
2763 
2764 
2765     if (setup.m_fastStart.GetSize() > 0) {
2766       // Now if fast start as well need to put this in setup specific field
2767       // and not the generic H.245 tunneling field
2768       setup.IncludeOptionalField(H225_Setup_UUIE::e_parallelH245Control);
2769       setup.m_parallelH245Control = setupPDU.m_h323_uu_pdu.m_h245Control;
2770       setupPDU.m_h323_uu_pdu.RemoveOptionalField(H225_H323_UU_PDU::e_h245Control);
2771       set_lastPDUWasH245inSETUP = TRUE;
2772     }
2773   }
2774 
2775   // Send the initial PDU
2776   setupTime = PTime();
2777   if (!WriteSignalPDU(setupPDU))
2778     return EndedByTransportFail;
2779 
2780   // WriteSignalPDU always resets lastPDUWasH245inSETUP.
2781   // So set it here if required
2782   if (set_lastPDUWasH245inSETUP)
2783     lastPDUWasH245inSETUP = TRUE;
2784 
2785   // Set timeout for remote party to answer the call
2786   if (!m_maintainConnection)
2787     signallingChannel->SetReadTimeout(endpoint.GetSignallingChannelCallTimeout());
2788 
2789   return reason;
2790 }
2791 
NatDetection(const PIPSocket::Address & srcAddress,const PIPSocket::Address & sigAddress)2792 void H323Connection::NatDetection(const PIPSocket::Address & srcAddress, const PIPSocket::Address & sigAddress)
2793 {
2794     // if the peer address is a public address, but the advertised source address is a private address
2795     // then there is a good chance the remote endpoint is behind a NAT but does not know it.
2796     // in this case, we active the NAT mode and wait for incoming RTP to provide the media address before
2797     // sending anything to the remote endpoint
2798     if ((!sigAddress.IsRFC1918() && srcAddress.IsRFC1918()) ||    // Internet Address
2799         ((sigAddress.IsRFC1918() && srcAddress.IsRFC1918()) && (sigAddress != srcAddress)))  // LAN on another LAN
2800     {
2801       PTRACE(3, "H225\tSource signal address " << srcAddress << " and TCP peer address " << sigAddress << " indicate remote endpoint is behind NAT");
2802       if (OnNatDetected())
2803           remoteIsNAT = true;
2804     }
2805 }
2806 
OnNatDetected()2807 PBoolean H323Connection::OnNatDetected()
2808 {
2809 #ifdef H323_H46018
2810     if (m_H46019enabled)
2811        return false;
2812 #endif
2813     return true;
2814 }
2815 
DisableNATSupport()2816 void H323Connection::DisableNATSupport() {
2817 #ifdef H323_H46018
2818     if (!IsH46019Multiplexed())
2819 #endif
2820         NATsupport = false;
2821 
2822     remoteIsNAT = false;
2823 }
2824 
2825 #ifdef P_STUN
2826 
GetPreferedNatMethod(const PIPSocket::Address & ip) const2827 PNatMethod * H323Connection::GetPreferedNatMethod(const PIPSocket::Address & ip) const
2828 {
2829     return endpoint.GetPreferedNatMethod(ip);
2830 }
2831 
GetNatSocket(unsigned session,PBoolean rtp)2832 PUDPSocket * H323Connection::GetNatSocket(unsigned session, PBoolean rtp)
2833 {
2834     std::map<unsigned,NAT_Sockets>::const_iterator sockets_iter = m_NATSockets.find(session);
2835     if (sockets_iter != m_NATSockets.end()) {
2836         NAT_Sockets sockets = sockets_iter->second;
2837         if (rtp)
2838             return sockets.rtp;
2839         else
2840             return sockets.rtcp;
2841     }
2842     return NULL;
2843 }
2844 
SetRTPNAT(unsigned sessionid,PUDPSocket * _rtp,PUDPSocket * _rtcp)2845 void H323Connection::SetRTPNAT(unsigned sessionid, PUDPSocket * _rtp, PUDPSocket * _rtcp)
2846 {
2847     PWaitAndSignal m(NATSocketMutex);
2848 
2849     PTRACE(4,"H323\tRTP NAT Connection Callback! Session: " << sessionid);
2850 
2851     NAT_Sockets sockets;
2852      sockets.rtp = _rtp;
2853      sockets.rtcp = _rtcp;
2854      sockets.isActive = false;
2855 
2856     m_NATSockets.insert(pair<unsigned, NAT_Sockets>(sessionid, sockets));
2857 }
2858 
SetNATChannelActive(unsigned sessionid)2859 void H323Connection::SetNATChannelActive(unsigned sessionid)
2860 {
2861     std::map<unsigned,NAT_Sockets>::iterator sockets_iter = m_NATSockets.find(sessionid);
2862     if (sockets_iter != m_NATSockets.end())
2863         sockets_iter->second.isActive = true;
2864 }
2865 
IsNATMethodActive(unsigned sessionid)2866 PBoolean H323Connection::IsNATMethodActive(unsigned sessionid)
2867 {
2868     std::map<unsigned,NAT_Sockets>::iterator sockets_iter = m_NATSockets.find(sessionid);
2869     if (sockets_iter != m_NATSockets.end())
2870         return sockets_iter->second.isActive;
2871 
2872     return false;
2873 }
2874 #endif
2875 
SetEndpointTypeInfo(H225_EndpointType & info) const2876 void H323Connection::SetEndpointTypeInfo(H225_EndpointType & info) const
2877 {
2878     return endpoint.SetEndpointTypeInfo(info);
2879 }
2880 
2881 
OnSendSignalSetup(H323SignalPDU &)2882 PBoolean H323Connection::OnSendSignalSetup(H323SignalPDU & /*setupPDU*/)
2883 {
2884   return TRUE;
2885 }
2886 
2887 
OnSendCallProceeding(H323SignalPDU &)2888 PBoolean H323Connection::OnSendCallProceeding(H323SignalPDU & /*callProceedingPDU*/)
2889 {
2890   return TRUE;
2891 }
2892 
2893 
OnSendReleaseComplete(H323SignalPDU &)2894 PBoolean H323Connection::OnSendReleaseComplete(H323SignalPDU & /*releaseCompletePDU*/)
2895 {
2896   return TRUE;
2897 }
2898 
2899 
OnAlerting(const H323SignalPDU & alertingPDU,const PString & username)2900 PBoolean H323Connection::OnAlerting(const H323SignalPDU & alertingPDU,
2901                                 const PString & username)
2902 {
2903   return endpoint.OnAlerting(*this, alertingPDU, username);
2904 }
2905 
2906 
OnInsufficientDigits()2907 PBoolean H323Connection::OnInsufficientDigits()
2908 {
2909   return FALSE;
2910 }
2911 
2912 
SendMoreDigits(const PString & digits)2913 void H323Connection::SendMoreDigits(const PString & digits)
2914 {
2915   remotePartyNumber += digits;
2916   remotePartyName = remotePartyNumber;
2917   if (connectionState == AwaitingGatekeeperAdmission)
2918     digitsWaitFlag.Signal();
2919   else {
2920     H323SignalPDU infoPDU;
2921     infoPDU.BuildInformation(*this);
2922     infoPDU.GetQ931().SetCalledPartyNumber(digits);
2923     WriteSignalPDU(infoPDU);
2924   }
2925 }
2926 
OnOutgoingCall(const H323SignalPDU & connectPDU)2927 PBoolean H323Connection::OnOutgoingCall(const H323SignalPDU & connectPDU)
2928 {
2929   return endpoint.OnOutgoingCall(*this, connectPDU);
2930 }
2931 
SendFastStartAcknowledge(H225_ArrayOf_PASN_OctetString & array)2932 PBoolean H323Connection::SendFastStartAcknowledge(H225_ArrayOf_PASN_OctetString & array)
2933 {
2934   PINDEX i;
2935 
2936   // See if we have already added the fast start OLC's
2937   if (array.GetSize() > 0)
2938     return TRUE;
2939 
2940   // See if we need to select our fast start channels
2941   if (fastStartState == FastStartResponse)
2942     OnSelectLogicalChannels();
2943 
2944   // Remove any channels that were not started by OnSelectLogicalChannels(),
2945   // those that were started are put into the logical channel dictionary
2946   for (i = 0; i < fastStartChannels.GetSize(); i++) {
2947     if (fastStartChannels[i].IsRunning())
2948       logicalChannels->Add(fastStartChannels[i]);
2949     else
2950       fastStartChannels.RemoveAt(i--);
2951   }
2952 
2953   // None left, so didn't open any channels fast
2954   if (fastStartChannels.IsEmpty()) {
2955     fastStartState = FastStartDisabled;
2956     return FALSE;
2957   }
2958 
2959   // The channels we just transferred to the logical channels dictionary
2960   // should not be deleted via this structure now.
2961   fastStartChannels.DisallowDeleteObjects();
2962 
2963   PTRACE(3, "H225\tAccepting fastStart for " << fastStartChannels.GetSize() << " channels");
2964 
2965   for (i = 0; i < fastStartChannels.GetSize(); i++)
2966     BuildFastStartList(fastStartChannels[i], array, H323Channel::IsTransmitter);
2967 
2968   // Have moved open channels to logicalChannels structure, remove all others.
2969   fastStartChannels.RemoveAll();
2970 
2971   // Last minute check to see that the remote has not decided
2972   // to send slow connect while we are doing fast!
2973   if (fastStartState == FastStartDisabled)
2974       return FALSE;
2975 
2976   // Set flag so internal establishment check does not require H.245
2977   fastStartState = FastStartAcknowledged;
2978 
2979   endSessionNeeded = FALSE;
2980 
2981   return TRUE;
2982 }
2983 
2984 
HandleFastStartAcknowledge(const H225_ArrayOf_PASN_OctetString & array)2985 PBoolean H323Connection::HandleFastStartAcknowledge(const H225_ArrayOf_PASN_OctetString & array)
2986 {
2987   if (fastStartChannels.IsEmpty()) {
2988     PTRACE(3, "H225\tFast start response with no channels to open");
2989     return FALSE;
2990   }
2991 
2992   // record the time at which media was opened
2993   reverseMediaOpenTime = PTime();
2994 
2995   PTRACE(3, "H225\tFast start accepted by remote endpoint");
2996 
2997   PINDEX i;
2998 
2999   // Go through provided list of structures, if can decode it and match it up
3000   // with a channel we requested AND it has all the information needed in the
3001   // m_multiplexParameters, then we can start the channel.
3002   for (i = 0; i < array.GetSize(); i++) {
3003     H245_OpenLogicalChannel open;
3004     if (array[i].DecodeSubType(open)) {
3005       PTRACE(4, "H225\tFast start open:\n  " << setprecision(2) << open);
3006       PBoolean reverse = open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters);
3007       const H245_DataType & dataType = reverse ? open.m_reverseLogicalChannelParameters.m_dataType
3008                                                : open.m_forwardLogicalChannelParameters.m_dataType;
3009       H323Capability * replyCapability = localCapabilities.FindCapability(dataType);
3010       if (replyCapability != NULL) {
3011         for (PINDEX ch = 0; ch < fastStartChannels.GetSize(); ch++) {
3012           H323Channel & channelToStart = fastStartChannels[ch];
3013           H323Channel::Directions dir = channelToStart.GetDirection();
3014           if ((dir == H323Channel::IsReceiver) == reverse &&
3015                channelToStart.GetCapability() == *replyCapability) {
3016             unsigned error = 1000;
3017             if (channelToStart.OnReceivedPDU(open, error)) {
3018               H323Capability * channelCapability;
3019               if (dir == H323Channel::IsReceiver)
3020                 channelCapability = replyCapability;
3021               else {
3022                 // For transmitter, need to fake a capability into the remote table
3023                 channelCapability = remoteCapabilities.FindCapability(channelToStart.GetCapability());
3024                 if (channelCapability == NULL) {
3025                   channelCapability = remoteCapabilities.Copy(channelToStart.GetCapability());
3026                   remoteCapabilities.SetCapability(0, channelCapability->GetDefaultSessionID()-1, channelCapability);
3027                 }
3028               }
3029               // Must use the actual capability instance from the
3030               // localCapability or remoteCapability structures.
3031               if (OnCreateLogicalChannel(*channelCapability, dir, error)) {
3032                 if (channelToStart.SetInitialBandwidth()) {
3033                     if (open.HasOptionalField(H245_OpenLogicalChannel::e_genericInformation))
3034                         OnReceiveOLCGenericInformation(channelToStart.GetSessionID(),open.m_genericInformation,true);
3035                   channelToStart.Start();
3036                   break;
3037                 }
3038                 else
3039                   PTRACE(2, "H225\tFast start channel open fail: insufficent bandwidth");
3040               }
3041               else
3042                 PTRACE(2, "H225\tFast start channel open error: " << error);
3043             }
3044             else
3045               PTRACE(2, "H225\tFast start capability error: " << error);
3046           }
3047         }
3048       }
3049     }
3050     else {
3051       PTRACE(1, "H225\tInvalid fast start PDU decode:\n  " << setprecision(2) << open);
3052     }
3053   }
3054 
3055   // Remove any channels that were not started by above, those that were
3056   // started are put into the logical channel dictionary
3057   for (i = 0; i < fastStartChannels.GetSize(); i++) {
3058     if (fastStartChannels[i].IsRunning())
3059       logicalChannels->Add(fastStartChannels[i]);
3060     else
3061       fastStartChannels.RemoveAt(i--);
3062   }
3063 
3064   // The channels we just transferred to the logical channels dictionary
3065   // should not be deleted via this structure now.
3066   fastStartChannels.DisallowDeleteObjects();
3067 
3068   PTRACE(2, "H225\tFast starting " << fastStartChannels.GetSize() << " channels");
3069   if (fastStartChannels.IsEmpty())
3070     return FALSE;
3071 
3072   // Have moved open channels to logicalChannels structure, remove them now.
3073   fastStartChannels.RemoveAll();
3074 
3075   fastStartState = FastStartAcknowledged;
3076 
3077   endSessionNeeded = FALSE;
3078 
3079   return TRUE;
3080 }
3081 
3082 
StartControlChannel()3083 PBoolean H323Connection::StartControlChannel()
3084 {
3085   // Already have the H245 channel up.
3086   if (controlChannel != NULL)
3087     return TRUE;
3088 
3089   controlChannel = signallingChannel->CreateControlChannel(*this);
3090   if (controlChannel == NULL) {
3091     ClearCall(EndedByTransportFail);
3092     return FALSE;
3093   }
3094 
3095   controlChannel->StartControlChannel(*this);
3096   return TRUE;
3097 }
3098 
3099 
StartControlChannel(const H225_TransportAddress & h245Address)3100 PBoolean H323Connection::StartControlChannel(const H225_TransportAddress & h245Address)
3101 {
3102   // Check that it is an IP address, all we support at the moment
3103   if (h245Address.GetTag() != H225_TransportAddress::e_ipAddress
3104 #ifdef H323_IPV6
3105         && h245Address.GetTag() != H225_TransportAddress::e_ip6Address
3106 #endif
3107       ) {
3108     PTRACE(1, "H225\tConnect of H245 failed: Unsupported transport");
3109     return FALSE;
3110   }
3111 
3112   // Already have the H245 channel up.
3113   if (controlChannel != NULL)
3114     return TRUE;
3115 
3116   unsigned m_version = 4;
3117   if (h245Address.GetTag() == H225_TransportAddress::e_ip6Address)
3118            m_version = 6;
3119 
3120   H323TransportSecurity m_h245Security;
3121   controlChannel = new H323TransportTCP(endpoint, PIPSocket::Address::GetAny(m_version));
3122   controlChannel->InitialiseSecurity(&m_h245Security);
3123   if (!controlChannel->SetRemoteAddress(h245Address)) {
3124     PTRACE(1, "H225\tCould not extract H245 address");
3125     delete controlChannel;
3126     controlChannel = NULL;
3127     return FALSE;
3128   }
3129 
3130   if (!controlChannel->Connect()) {
3131     PTRACE(1, "H225\tConnect of H245 failed: " << controlChannel->GetErrorText());
3132     delete controlChannel;
3133     controlChannel = NULL;
3134     return FALSE;
3135   }
3136 
3137   controlChannel->StartControlChannel(*this);
3138   return TRUE;
3139 }
3140 
3141 
OnUnknownSignalPDU(const H323SignalPDU & PTRACE_PARAM (pdu))3142 PBoolean H323Connection::OnUnknownSignalPDU(const H323SignalPDU & PTRACE_PARAM(pdu))
3143 {
3144   PTRACE(2, "H225\tUnknown signalling PDU: " << pdu);
3145   return TRUE;
3146 }
3147 
3148 
WriteControlPDU(const H323ControlPDU & pdu)3149 PBoolean H323Connection::WriteControlPDU(const H323ControlPDU & pdu)
3150 {
3151   PWaitAndSignal m(controlMutex);
3152 
3153   PPER_Stream strm;
3154   pdu.Encode(strm);
3155   strm.CompleteEncoding();
3156 
3157   H323TraceDumpPDU("H245", TRUE, strm, pdu, pdu, 0,
3158                    (controlChannel == NULL) ? H323TransportAddress("") : controlChannel->GetLocalAddress(),
3159                    (controlChannel == NULL) ? H323TransportAddress("") : controlChannel->GetRemoteAddress()
3160                   );
3161 
3162   if (!h245Tunneling) {
3163     if (controlChannel == NULL) {
3164       PTRACE(1, "H245\tWrite PDU fail: no control channel.");
3165       return FALSE;
3166     }
3167 
3168     if (controlChannel->IsOpen() && controlChannel->WritePDU(strm))
3169       return TRUE;
3170 
3171     PTRACE(1, "H245\tWrite PDU fail: " << controlChannel->GetErrorText(PChannel::LastWriteError));
3172     return HandleControlChannelFailure();
3173   }
3174 
3175   // If have a pending signalling PDU, use it rather than separate write
3176   H323SignalPDU localTunnelPDU;
3177   H323SignalPDU * tunnelPDU;
3178   if (h245TunnelTxPDU != NULL)
3179     tunnelPDU = h245TunnelTxPDU;
3180   else {
3181     localTunnelPDU.BuildFacility(*this, TRUE);
3182     tunnelPDU = &localTunnelPDU;
3183   }
3184 
3185   tunnelPDU->m_h323_uu_pdu.IncludeOptionalField(H225_H323_UU_PDU::e_h245Control);
3186   PINDEX last = tunnelPDU->m_h323_uu_pdu.m_h245Control.GetSize();
3187   tunnelPDU->m_h323_uu_pdu.m_h245Control.SetSize(last+1);
3188   tunnelPDU->m_h323_uu_pdu.m_h245Control[last] = strm;
3189 
3190   if (h245TunnelTxPDU != NULL)
3191     return TRUE;
3192 
3193   return WriteSignalPDU(localTunnelPDU);
3194 }
3195 
3196 
StartControlNegotiations(PBoolean renegotiate)3197 PBoolean H323Connection::StartControlNegotiations(PBoolean renegotiate)
3198 {
3199   PTRACE(2, "H245\tStart control negotiations");
3200 
3201   if(renegotiate)  // makes reopening of media channels possible
3202     connectionState = HasExecutedSignalConnect;
3203 
3204   // Begin the capability exchange procedure
3205   if (!capabilityExchangeProcedure->Start(renegotiate)) {
3206     PTRACE(1, "H245\tStart of Capability Exchange failed");
3207     return FALSE;
3208   }
3209 
3210   // Begin the Master/Slave determination procedure
3211   if (!masterSlaveDeterminationProcedure->Start(renegotiate)) {
3212     PTRACE(1, "H245\tStart of Master/Slave determination failed");
3213     return FALSE;
3214   }
3215 
3216   endSessionNeeded = TRUE;
3217   return TRUE;
3218 }
3219 
OnStartHandleControlChannel()3220 PBoolean H323Connection::OnStartHandleControlChannel()
3221 {
3222      if (fastStartState == FastStartAcknowledged)
3223          return true;
3224 
3225      if (controlChannel == NULL)
3226          return StartControlNegotiations();
3227 #ifndef H323_H46018
3228      else {
3229          PTRACE(2, "H245\tHandle control channel");
3230          return StartHandleControlChannel();
3231      }
3232 #else
3233     if (!m_H46019enabled) {
3234         PTRACE(2, "H245\tHandle control channel");
3235         return StartHandleControlChannel();
3236     }
3237 
3238     // according to H.460.18 cl.11 we have to send a generic Indication on the opening of a
3239     // H.245 control channel. Details are specified in H.460.18 cl.16
3240     // This must be the first PDU otherwise gatekeeper/proxy will close the channel.
3241 
3242     PTRACE(2, "H46018\tStarted control channel");
3243 
3244         if (endpoint.H46018IsEnabled() && !m_h245Connect) {
3245 
3246         H323ControlPDU pdu;
3247         H245_GenericMessage & cap = pdu.Build(H245_IndicationMessage::e_genericIndication);
3248 
3249             H245_CapabilityIdentifier & id = cap.m_messageIdentifier;
3250                 id.SetTag(H245_CapabilityIdentifier::e_standard);
3251                 PASN_ObjectId & gid = id;
3252                 gid.SetValue(H46018OID);
3253 
3254             cap.IncludeOptionalField(H245_GenericMessage::e_subMessageIdentifier);
3255                 PASN_Integer & sub = cap.m_subMessageIdentifier;
3256                 sub = 1;
3257 
3258             cap.IncludeOptionalField(H245_GenericMessage::e_messageContent);
3259               H245_ArrayOf_GenericParameter & msg = cap.m_messageContent;
3260 
3261               // callIdentifer
3262                 H245_GenericParameter call;
3263                    H245_ParameterIdentifier & idx = call.m_parameterIdentifier;
3264                      idx.SetTag(H245_ParameterIdentifier::e_standard);
3265                      PASN_Integer & m = idx;
3266                      m =1;
3267                    H245_ParameterValue & conx = call.m_parameterValue;
3268                      conx.SetTag(H245_ParameterValue::e_octetString);
3269                      PASN_OctetString & raw = conx;
3270                      raw.SetValue(callIdentifier);
3271                 msg.SetSize(1);
3272                 msg[0] = call;
3273 
3274               // Is receiver
3275                 if (m_H46019CallReceiver) {
3276                      H245_GenericParameter answer;
3277                     H245_ParameterIdentifier & an = answer.m_parameterIdentifier;
3278                         an.SetTag(H245_ParameterIdentifier::e_standard);
3279                         PASN_Integer & n = an;
3280                         n =2;
3281                     H245_ParameterValue & aw = answer.m_parameterValue;
3282                     aw.SetTag(H245_ParameterValue::e_logical);
3283                     msg.SetSize(2);
3284                     msg[1] = answer;
3285                 }
3286             PTRACE(4,"H46018\tSending H.245 Control PDU " << pdu);
3287 
3288             if (!WriteControlPDU(pdu))
3289                   return false;
3290 
3291               m_h245Connect = true;
3292         }
3293 
3294      return StartHandleControlChannel();
3295 
3296 #endif
3297 }
3298 
StartHandleControlChannel()3299 PBoolean H323Connection::StartHandleControlChannel()
3300 {
3301   // If have started separate H.245 channel then don't tunnel any more
3302   h245Tunneling = FALSE;
3303 
3304   // Start the TCS and MSD operations on new H.245 channel.
3305   if (!StartControlNegotiations())
3306     return FALSE;
3307 
3308   // Disable the signalling channels timeout for monitoring call status and
3309   // start up one in this thread instead. Then the Q.931 channel can be closed
3310   // without affecting the call.
3311   signallingChannel->SetReadTimeout(PMaxTimeInterval);
3312   controlChannel->SetReadTimeout(MonitorCallStatusTime);
3313 
3314   return TRUE;
3315 }
3316 
EndHandleControlChannel()3317 void H323Connection::EndHandleControlChannel()
3318 {
3319   // If we are the only link to the far end or if we have already sent our
3320   // endSession command then indicate that we have received endSession even
3321   // if we hadn't, because we are now never going to get one so there is no
3322   // point in having CleanUpOnCallEnd wait.
3323   if (signallingChannel == NULL || endSessionSent == TRUE)
3324     endSessionReceived.Signal();
3325 }
3326 
HandleControlChannel()3327 void H323Connection::HandleControlChannel()
3328 {
3329   if (!OnStartHandleControlChannel())
3330     return;
3331 
3332   PBoolean ok = TRUE;
3333   while (ok) {
3334     MonitorCallStatus();
3335     PPER_Stream strm;
3336     PBoolean readStatus = controlChannel->ReadPDU(strm);
3337     ok = HandleReceivedControlPDU(readStatus, strm);
3338   }
3339 
3340   EndHandleControlChannel();
3341 
3342   PTRACE(2, "H245\tControl channel closed.");
3343 }
3344 
3345 
HandleReceivedControlPDU(PBoolean readStatus,PPER_Stream & strm)3346 PBoolean H323Connection::HandleReceivedControlPDU(PBoolean readStatus, PPER_Stream & strm)
3347 {
3348   PBoolean ok = FALSE;
3349 
3350   if (readStatus) {
3351     // Lock while checking for shutting down.
3352     if (Lock()) {
3353       // Process the received PDU
3354       PTRACE(4, "H245\tReceived TPKT: " << strm);
3355       ok = HandleControlData(strm);
3356       Unlock(); // Unlock connection
3357     }
3358     else
3359       ok = InternalEndSessionCheck(strm);
3360   }
3361   else if (controlChannel->GetErrorCode() == PChannel::Timeout) {
3362     ok = true;
3363   }
3364   else {
3365       PTRACE(1, "H245\tRead error: " << controlChannel->GetErrorText(PChannel::LastReadError)
3366           << " endSessionSent=" << endSessionSent);
3367     // If the connection is already shutting down then don't overwrite the
3368     // call end reason.  This could happen if the remote end point misbehaves
3369     // and simply closes the H.245 TCP connection rather than sending an
3370     // endSession.
3371       if(endSessionSent == FALSE) {
3372          PTRACE(1, "H245\tTCP Socket closed Unexpectedly.");
3373          if (!HandleControlChannelFailure()) {
3374              PTRACE(1, "H245\tAborting call");
3375              ClearCall(EndedByTransportFail);
3376              return false;
3377          }
3378          PTRACE(1, "H245\tTCP Socket closed Unexpectedly. Attempting to reconnect.");
3379          if (!controlChannel->Connect()) {
3380              PTRACE(1, "H245\tTCP Socket could not reconnect. Proceed without control channel.");
3381              PThread::Sleep(500);
3382          }
3383         ok = true;
3384       } else {
3385          PTRACE(1, "H245\tendSession already sent assuming H245 connection closed by remote side");
3386          ok = false;
3387       }
3388   }
3389 
3390   return ok;
3391 }
3392 
3393 
InternalEndSessionCheck(PPER_Stream & strm)3394 PBoolean H323Connection::InternalEndSessionCheck(PPER_Stream & strm)
3395 {
3396   H323ControlPDU pdu;
3397 
3398   if (!pdu.Decode(strm)) {
3399     PTRACE(1, "H245\tInvalid PDU decode:\n  " << setprecision(2) << pdu);
3400     return FALSE;
3401   }
3402 
3403   PTRACE(3, "H245\tChecking for end session on PDU: " << pdu.GetTagName()
3404          << ' ' << ((PASN_Choice &)pdu.GetObject()).GetTagName());
3405 
3406   if (pdu.GetTag() != H245_MultimediaSystemControlMessage::e_command)
3407     return TRUE;
3408 
3409   H245_CommandMessage & command = pdu;
3410   if (command.GetTag() == H245_CommandMessage::e_endSessionCommand)
3411     endSessionReceived.Signal();
3412   return FALSE;
3413 }
3414 
3415 
HandleControlData(PPER_Stream & strm)3416 PBoolean H323Connection::HandleControlData(PPER_Stream & strm)
3417 {
3418   while (!strm.IsAtEnd()) {
3419     H323ControlPDU pdu;
3420     if (!pdu.Decode(strm)) {
3421       PTRACE(1, "H245\tInvalid PDU decode!"
3422                 "\nRaw PDU:\n" << hex << setfill('0')
3423                                << setprecision(2) << strm
3424                                << dec << setfill(' ') <<
3425                 "\nPartial PDU:\n  " << setprecision(2) << pdu);
3426       return TRUE;
3427     }
3428 
3429     H323TraceDumpPDU("H245", FALSE, strm, pdu, pdu, 0,
3430                      (controlChannel == NULL) ? H323TransportAddress("") : controlChannel->GetLocalAddress(),
3431                      (controlChannel == NULL) ? H323TransportAddress("") : controlChannel->GetRemoteAddress()
3432                     );
3433 
3434     if (!HandleControlPDU(pdu))
3435       return FALSE;
3436 
3437     InternalEstablishedConnectionCheck();
3438 
3439     strm.ByteAlign();
3440   }
3441 
3442   return TRUE;
3443 }
3444 
3445 
HandleControlPDU(const H323ControlPDU & pdu)3446 PBoolean H323Connection::HandleControlPDU(const H323ControlPDU & pdu)
3447 {
3448   switch (pdu.GetTag()) {
3449     case H245_MultimediaSystemControlMessage::e_request :
3450       return OnH245Request(pdu);
3451 
3452     case H245_MultimediaSystemControlMessage::e_response :
3453       return OnH245Response(pdu);
3454 
3455     case H245_MultimediaSystemControlMessage::e_command :
3456       return OnH245Command(pdu);
3457 
3458     case H245_MultimediaSystemControlMessage::e_indication :
3459       return OnH245Indication(pdu);
3460   }
3461 
3462   return OnUnknownControlPDU(pdu);
3463 }
3464 
3465 
OnUnknownControlPDU(const H323ControlPDU & pdu)3466 PBoolean H323Connection::OnUnknownControlPDU(const H323ControlPDU & pdu)
3467 {
3468   PTRACE(2, "H245\tUnknown Control PDU: " << pdu);
3469 
3470   H323ControlPDU reply;
3471   reply.BuildFunctionNotUnderstood(pdu);
3472   return WriteControlPDU(reply);
3473 }
3474 
3475 
OnH245Request(const H323ControlPDU & pdu)3476 PBoolean H323Connection::OnH245Request(const H323ControlPDU & pdu)
3477 {
3478   const H245_RequestMessage & request = pdu;
3479 
3480   switch (request.GetTag()) {
3481     case H245_RequestMessage::e_masterSlaveDetermination :
3482       if (fastStartState == FastStartResponse) {
3483          PTRACE(4,"H245\tIgnoring masterSlaveDetermination, already doing Fast Connect");
3484          return TRUE;
3485       }
3486       return masterSlaveDeterminationProcedure->HandleIncoming(request);
3487 
3488     case H245_RequestMessage::e_terminalCapabilitySet :
3489     {
3490       if (fastStartState == FastStartResponse) {
3491          PTRACE(4,"H245\tIgnoring TerminalCapabilitySet, already doing Fast Connect");
3492          return TRUE;
3493       }
3494       const H245_TerminalCapabilitySet & tcs = request;
3495       if (tcs.m_protocolIdentifier.GetSize() >= 6) {
3496         h245version = tcs.m_protocolIdentifier[5];
3497         h245versionSet = TRUE;
3498         PTRACE(3, "H245\tSet protocol version to " << h245version);
3499       }
3500       return capabilityExchangeProcedure->HandleIncoming(tcs);
3501     }
3502 
3503     case H245_RequestMessage::e_openLogicalChannel :
3504       return logicalChannels->HandleOpen(request);
3505 
3506     case H245_RequestMessage::e_closeLogicalChannel :
3507       return logicalChannels->HandleClose(request);
3508 
3509     case H245_RequestMessage::e_requestChannelClose :
3510       return logicalChannels->HandleRequestClose(request);
3511 
3512     case H245_RequestMessage::e_requestMode :
3513       return requestModeProcedure->HandleRequest(request);
3514 
3515     case H245_RequestMessage::e_roundTripDelayRequest :
3516       return roundTripDelayProcedure->HandleRequest(request);
3517 
3518     case H245_RequestMessage::e_conferenceRequest :
3519       if (OnHandleConferenceRequest(request))
3520         return TRUE;
3521       break;
3522 
3523     case H245_RequestMessage::e_genericRequest :
3524       if (OnHandleH245GenericMessage(h245request,request))
3525         return TRUE;
3526       break;
3527   }
3528 
3529   return OnUnknownControlPDU(pdu);
3530 }
3531 
3532 
OnH245Response(const H323ControlPDU & pdu)3533 PBoolean H323Connection::OnH245Response(const H323ControlPDU & pdu)
3534 {
3535   const H245_ResponseMessage & response = pdu;
3536 
3537   switch (response.GetTag()) {
3538     case H245_ResponseMessage::e_masterSlaveDeterminationAck :
3539       return masterSlaveDeterminationProcedure->HandleAck(response);
3540 
3541     case H245_ResponseMessage::e_masterSlaveDeterminationReject :
3542       return masterSlaveDeterminationProcedure->HandleReject(response);
3543 
3544     case H245_ResponseMessage::e_terminalCapabilitySetAck :
3545       return capabilityExchangeProcedure->HandleAck(response);
3546 
3547     case H245_ResponseMessage::e_terminalCapabilitySetReject :
3548       return capabilityExchangeProcedure->HandleReject(response);
3549 
3550     case H245_ResponseMessage::e_openLogicalChannelAck :
3551       return logicalChannels->HandleOpenAck(response);
3552 
3553     case H245_ResponseMessage::e_openLogicalChannelReject :
3554       return logicalChannels->HandleReject(response);
3555 
3556     case H245_ResponseMessage::e_closeLogicalChannelAck :
3557       return logicalChannels->HandleCloseAck(response);
3558 
3559     case H245_ResponseMessage::e_requestChannelCloseAck :
3560       return logicalChannels->HandleRequestCloseAck(response);
3561 
3562     case H245_ResponseMessage::e_requestChannelCloseReject :
3563       return logicalChannels->HandleRequestCloseReject(response);
3564 
3565     case H245_ResponseMessage::e_requestModeAck :
3566       return requestModeProcedure->HandleAck(response);
3567 
3568     case H245_ResponseMessage::e_requestModeReject :
3569       return requestModeProcedure->HandleReject(response);
3570 
3571     case H245_ResponseMessage::e_roundTripDelayResponse :
3572       return roundTripDelayProcedure->HandleResponse(response);
3573 
3574     case H245_ResponseMessage::e_conferenceResponse :
3575       if (OnHandleConferenceResponse(response))
3576         return TRUE;
3577       break;
3578 
3579     case H245_ResponseMessage::e_genericResponse :
3580       if (OnHandleH245GenericMessage(h245response,response))
3581         return TRUE;
3582       break;
3583   }
3584 
3585   return OnUnknownControlPDU(pdu);
3586 }
3587 
3588 
OnH245Command(const H323ControlPDU & pdu)3589 PBoolean H323Connection::OnH245Command(const H323ControlPDU & pdu)
3590 {
3591   const H245_CommandMessage & command = pdu;
3592 
3593   switch (command.GetTag()) {
3594     case H245_CommandMessage::e_sendTerminalCapabilitySet :
3595       return OnH245_SendTerminalCapabilitySet(command);
3596 
3597     case H245_CommandMessage::e_flowControlCommand :
3598       return OnH245_FlowControlCommand(command);
3599 
3600     case H245_CommandMessage::e_miscellaneousCommand :
3601       return OnH245_MiscellaneousCommand(command);
3602 
3603     case H245_CommandMessage::e_endSessionCommand :
3604       endSessionNeeded = TRUE;
3605       endSessionReceived.Signal();
3606       switch (connectionState) {
3607         case EstablishedConnection :
3608           ClearCall(EndedByRemoteUser);
3609           break;
3610         case AwaitingLocalAnswer :
3611           ClearCall(EndedByCallerAbort);
3612           break;
3613         default :
3614           ClearCall(EndedByRefusal);
3615       }
3616       return FALSE;
3617 
3618     case H245_CommandMessage::e_conferenceCommand:
3619       if (OnHandleConferenceCommand(command))
3620         return TRUE;
3621       break;
3622 
3623     case H245_CommandMessage::e_genericCommand :
3624       if (OnHandleH245GenericMessage(h245command,command))
3625         return TRUE;
3626       break;
3627   }
3628 
3629   return OnUnknownControlPDU(pdu);
3630 }
3631 
3632 
OnH245Indication(const H323ControlPDU & pdu)3633 PBoolean H323Connection::OnH245Indication(const H323ControlPDU & pdu)
3634 {
3635   const H245_IndicationMessage & indication = pdu;
3636 
3637   switch (indication.GetTag()) {
3638     case H245_IndicationMessage::e_masterSlaveDeterminationRelease :
3639       return masterSlaveDeterminationProcedure->HandleRelease(indication);
3640 
3641     case H245_IndicationMessage::e_terminalCapabilitySetRelease :
3642       return capabilityExchangeProcedure->HandleRelease(indication);
3643 
3644     case H245_IndicationMessage::e_openLogicalChannelConfirm :
3645       return logicalChannels->HandleOpenConfirm(indication);
3646 
3647     case H245_IndicationMessage::e_requestChannelCloseRelease :
3648       return logicalChannels->HandleRequestCloseRelease(indication);
3649 
3650     case H245_IndicationMessage::e_requestModeRelease :
3651       return requestModeProcedure->HandleRelease(indication);
3652 
3653     case H245_IndicationMessage::e_miscellaneousIndication :
3654       return OnH245_MiscellaneousIndication(indication);
3655 
3656     case H245_IndicationMessage::e_jitterIndication :
3657       return OnH245_JitterIndication(indication);
3658 
3659     case H245_IndicationMessage::e_userInput :
3660       OnUserInputIndication(indication);
3661       break;
3662 
3663     case H245_IndicationMessage::e_conferenceIndication :
3664       if (OnHandleConferenceIndication(indication))
3665         return TRUE;
3666       break;
3667 
3668     case H245_IndicationMessage::e_flowControlIndication :
3669         PTRACE(3,"H245\tFlow Indication received NOT HANDLED!");
3670         return TRUE;
3671       break;
3672 
3673     case H245_IndicationMessage::e_genericIndication :
3674       if (OnHandleH245GenericMessage(h245indication,indication))
3675         return TRUE;
3676       break;
3677   }
3678 
3679   return TRUE; // Do NOT call OnUnknownControlPDU for indications
3680 }
3681 
3682 
OnH245_SendTerminalCapabilitySet(const H245_SendTerminalCapabilitySet & pdu)3683 PBoolean H323Connection::OnH245_SendTerminalCapabilitySet(
3684                  const H245_SendTerminalCapabilitySet & pdu)
3685 {
3686   if (pdu.GetTag() == H245_SendTerminalCapabilitySet::e_genericRequest)
3687     return capabilityExchangeProcedure->Start(TRUE);
3688 
3689   PTRACE(2, "H245\tUnhandled SendTerminalCapabilitySet: " << pdu);
3690   return TRUE;
3691 }
3692 
3693 
OnH245_FlowControlCommand(const H245_FlowControlCommand & pdu)3694 PBoolean H323Connection::OnH245_FlowControlCommand(
3695                  const H245_FlowControlCommand & pdu)
3696 {
3697   PTRACE(3, "H245\tFlowControlCommand: scope=" << pdu.m_scope.GetTagName());
3698 
3699   long restriction;
3700   if (pdu.m_restriction.GetTag() == H245_FlowControlCommand_restriction::e_maximumBitRate)
3701     restriction = (const PASN_Integer &)pdu.m_restriction;
3702   else
3703     restriction = -1; // H245_FlowControlCommand_restriction::e_noRestriction
3704 
3705   switch (pdu.m_scope.GetTag()) {
3706     case H245_FlowControlCommand_scope::e_wholeMultiplex :
3707       OnLogicalChannelFlowControl(NULL, restriction);
3708       break;
3709 
3710     case H245_FlowControlCommand_scope::e_logicalChannelNumber :
3711     {
3712       H323Channel * chan = logicalChannels->FindChannel((unsigned)(const H245_LogicalChannelNumber &)pdu.m_scope, FALSE);
3713       if (chan != NULL)
3714         OnLogicalChannelFlowControl(chan, restriction);
3715     }
3716   }
3717 
3718   return TRUE;
3719 }
3720 
3721 
OnH245_MiscellaneousCommand(const H245_MiscellaneousCommand & pdu)3722 PBoolean H323Connection::OnH245_MiscellaneousCommand(
3723                  const H245_MiscellaneousCommand & pdu)
3724 {
3725   H323Channel * chan = logicalChannels->FindChannel((unsigned)pdu.m_logicalChannelNumber, FALSE);
3726   if (chan != NULL)
3727     chan->OnMiscellaneousCommand(pdu.m_type);
3728   else
3729     PTRACE(3, "H245\tMiscellaneousCommand: is ignored chan=" << pdu.m_logicalChannelNumber
3730            << ", type=" << pdu.m_type.GetTagName());
3731 
3732   return TRUE;
3733 }
3734 
3735 
OnH245_MiscellaneousIndication(const H245_MiscellaneousIndication & pdu)3736 PBoolean H323Connection::OnH245_MiscellaneousIndication(
3737                  const H245_MiscellaneousIndication & pdu)
3738 {
3739   H323Channel * chan = logicalChannels->FindChannel((unsigned)pdu.m_logicalChannelNumber, TRUE);
3740   if (chan != NULL)
3741     chan->OnMiscellaneousIndication(pdu.m_type);
3742   else
3743     PTRACE(3, "H245\tMiscellaneousIndication is ignored. chan=" << pdu.m_logicalChannelNumber
3744            << ", type=" << pdu.m_type.GetTagName());
3745 
3746   return TRUE;
3747 }
3748 
3749 
OnH245_JitterIndication(const H245_JitterIndication & pdu)3750 PBoolean H323Connection::OnH245_JitterIndication(
3751                  const H245_JitterIndication & pdu)
3752 {
3753   PTRACE(3, "H245\tJitterIndication: scope=" << pdu.m_scope.GetTagName());
3754 
3755   static const DWORD mantissas[8] = { 0, 1, 10, 100, 1000, 10000, 100000, 1000000 };
3756   static const DWORD exponents[8] = { 10, 25, 50, 75 };
3757   DWORD jitter = mantissas[pdu.m_estimatedReceivedJitterMantissa]*
3758                  exponents[pdu.m_estimatedReceivedJitterExponent]/10;
3759 
3760   int skippedFrameCount = -1;
3761   if (pdu.HasOptionalField(H245_JitterIndication::e_skippedFrameCount))
3762     skippedFrameCount = pdu.m_skippedFrameCount;
3763 
3764   int additionalBuffer = -1;
3765   if (pdu.HasOptionalField(H245_JitterIndication::e_additionalDecoderBuffer))
3766     additionalBuffer = pdu.m_additionalDecoderBuffer;
3767 
3768   switch (pdu.m_scope.GetTag()) {
3769     case H245_JitterIndication_scope::e_wholeMultiplex :
3770       OnLogicalChannelJitter(NULL, jitter, skippedFrameCount, additionalBuffer);
3771       break;
3772 
3773     case H245_JitterIndication_scope::e_logicalChannelNumber :
3774     {
3775       H323Channel * chan = logicalChannels->FindChannel((unsigned)(const H245_LogicalChannelNumber &)pdu.m_scope, FALSE);
3776       if (chan != NULL)
3777         OnLogicalChannelJitter(chan, jitter, skippedFrameCount, additionalBuffer);
3778     }
3779   }
3780 
3781   return TRUE;
3782 }
3783 
3784 
GetLogicalChannel(unsigned number,PBoolean fromRemote) const3785 H323Channel * H323Connection::GetLogicalChannel(unsigned number, PBoolean fromRemote) const
3786 {
3787   return logicalChannels->FindChannel(number, fromRemote);
3788 }
3789 
3790 
FindChannel(unsigned rtpSessionId,PBoolean fromRemote) const3791 H323Channel * H323Connection::FindChannel(unsigned rtpSessionId, PBoolean fromRemote) const
3792 {
3793   return logicalChannels->FindChannelBySession(rtpSessionId, fromRemote);
3794 }
3795 
3796 #ifdef H323_H450
3797 
TransferCall(const PString & remoteParty,const PString & callIdentity)3798 void H323Connection::TransferCall(const PString & remoteParty,
3799                                   const PString & callIdentity)
3800 {
3801   // According to H.450.4, if prior to consultation the primary call has been put on hold, the
3802   // transferring endpoint shall first retrieve the call before Call Transfer is invoked.
3803   if (!callIdentity.IsEmpty() && IsLocalHold())
3804     RetrieveCall();
3805   h4502handler->TransferCall(remoteParty, callIdentity);
3806 }
3807 
OnReceivedInitiateReturnError()3808 void H323Connection::OnReceivedInitiateReturnError()
3809 {
3810     endpoint.OnReceivedInitiateReturnError();
3811 }
3812 
ConsultationTransfer(const PString & primaryCallToken)3813 void H323Connection::ConsultationTransfer(const PString & primaryCallToken)
3814 {
3815   h4502handler->ConsultationTransfer(primaryCallToken);
3816 }
3817 
3818 
HandleConsultationTransfer(const PString & callIdentity,H323Connection & incoming)3819 void H323Connection::HandleConsultationTransfer(const PString & callIdentity,
3820                                                 H323Connection& incoming)
3821 {
3822   h4502handler->HandleConsultationTransfer(callIdentity, incoming);
3823 }
3824 
3825 
IsTransferringCall() const3826 PBoolean H323Connection::IsTransferringCall() const
3827 {
3828   switch (h4502handler->GetState()) {
3829     case H4502Handler::e_ctAwaitIdentifyResponse :
3830     case H4502Handler::e_ctAwaitInitiateResponse :
3831     case H4502Handler::e_ctAwaitSetupResponse :
3832       return TRUE;
3833 
3834     default :
3835       return FALSE;
3836   }
3837 }
3838 
3839 
IsTransferredCall() const3840 PBoolean H323Connection::IsTransferredCall() const
3841 {
3842    return (h4502handler->GetInvokeId() != 0 &&
3843            h4502handler->GetState() == H4502Handler::e_ctIdle) ||
3844            h4502handler->isConsultationTransferSuccess();
3845 }
3846 
3847 
HandleTransferCall(const PString & token,const PString & identity)3848 void H323Connection::HandleTransferCall(const PString & token,
3849                                         const PString & identity)
3850 {
3851   if (!token.IsEmpty() || !identity)
3852     h4502handler->AwaitSetupResponse(token, identity);
3853 }
3854 
3855 
GetCallTransferInvokeId()3856 int H323Connection::GetCallTransferInvokeId()
3857 {
3858   return h4502handler->GetInvokeId();
3859 }
3860 
3861 
HandleCallTransferFailure(const int returnError)3862 void H323Connection::HandleCallTransferFailure(const int returnError)
3863 {
3864   h4502handler->HandleCallTransferFailure(returnError);
3865 }
3866 
3867 
SetAssociatedCallToken(const PString & token)3868 void H323Connection::SetAssociatedCallToken(const PString& token)
3869 {
3870   h4502handler->SetAssociatedCallToken(token);
3871 }
3872 
3873 
OnConsultationTransferSuccess(H323Connection &)3874 void H323Connection::OnConsultationTransferSuccess(H323Connection& /*secondaryCall*/)
3875 {
3876    h4502handler->SetConsultationTransferSuccess();
3877 }
3878 
SetCallLinkage(H225_AdmissionRequest &)3879 void H323Connection::SetCallLinkage(H225_AdmissionRequest& /*arq*/ )
3880 {
3881 }
3882 
GetCallLinkage(const H225_AdmissionRequest &)3883 void H323Connection::GetCallLinkage(const H225_AdmissionRequest& /*arq*/)
3884 {
3885 }
3886 
HoldCall(PBoolean localHold)3887 void H323Connection::HoldCall(PBoolean localHold)
3888 {
3889   h4504handler->HoldCall(localHold);
3890   holdAudioMediaChannel = SwapHoldMediaChannels(holdAudioMediaChannel,RTP_Session::DefaultAudioSessionID);
3891   holdVideoMediaChannel = SwapHoldMediaChannels(holdVideoMediaChannel,RTP_Session::DefaultVideoSessionID);
3892 }
3893 
GetRedirectingNumber(PString & originalCalledNr,PString & lastDivertingNr,int & divCounter,int & originaldivReason,int & divReason)3894 PBoolean H323Connection::GetRedirectingNumber(
3895     PString &originalCalledNr,
3896     PString &lastDivertingNr,
3897     int &divCounter,
3898     int &originaldivReason,
3899     int &divReason)
3900 {
3901   return h4503handler->GetRedirectingNumber(originalCalledNr,lastDivertingNr,
3902                                          divCounter,originaldivReason,divReason);
3903 }
3904 
RetrieveCall()3905 void H323Connection::RetrieveCall()
3906 {
3907   // Is the current call on hold?
3908   if (IsLocalHold()) {
3909     h4504handler->RetrieveCall();
3910     holdAudioMediaChannel = SwapHoldMediaChannels(holdAudioMediaChannel,RTP_Session::DefaultAudioSessionID);
3911     holdVideoMediaChannel = SwapHoldMediaChannels(holdVideoMediaChannel,RTP_Session::DefaultVideoSessionID);
3912   }
3913   else if (IsRemoteHold()) {
3914     PTRACE(4, "H4504\tRemote-end Call Hold not implemented.");
3915   }
3916   else {
3917     PTRACE(4, "H4504\tCall is not on Hold.");
3918   }
3919 }
3920 
3921 
SetHoldMedia(PChannel * audioChannel)3922 void H323Connection::SetHoldMedia(PChannel * audioChannel)
3923 {
3924 
3925   holdAudioMediaChannel = audioChannel;
3926 }
3927 
SetVideoHoldMedia(PChannel * videoChannel)3928 void H323Connection::SetVideoHoldMedia(PChannel * videoChannel)
3929 {
3930   holdVideoMediaChannel = videoChannel;
3931 }
3932 
IsMediaOnHold() const3933 PBoolean H323Connection::IsMediaOnHold() const
3934 {
3935   return holdAudioMediaChannel != NULL;
3936 }
3937 
3938 
SwapHoldMediaChannels(PChannel * newChannel,unsigned sessionId)3939 PChannel * H323Connection::SwapHoldMediaChannels(PChannel * newChannel,unsigned sessionId)
3940 {
3941   if (IsMediaOnHold()) {
3942       if (newChannel == NULL) {
3943          PTRACE(4, "H4504\tCannot Retrieve session " << sessionId << " as hold media is NULL.");
3944          return NULL;
3945       }
3946   }
3947 
3948   PChannel * existingTransmitChannel = NULL;
3949 
3950   PINDEX count = logicalChannels->GetSize();
3951 
3952   for (PINDEX i = 0; i < count; ++i) {
3953     H323Channel* channel = logicalChannels->GetChannelAt(i);
3954 
3955     if (!channel) {
3956          PTRACE(4, "H4504\tLogical Channel " << i << " Empty or closed! Session ID: " << sessionId);
3957         // Fire off to ensure if channel is being Held that it is retrieved in derived application
3958          OnCallRetrieve(TRUE,sessionId,0,newChannel);
3959          return NULL;
3960     }
3961 
3962     unsigned int session_id = channel->GetSessionID();
3963     if (session_id == sessionId) {
3964       const H323ChannelNumber & channelNumber = channel->GetNumber();
3965 
3966       H323_RTPChannel * chan2 = reinterpret_cast<H323_RTPChannel*>(channel);
3967 
3968       H323Codec & codec = *channel->GetCodec();
3969       PChannel * rawChannel = codec.GetRawDataChannel();
3970       unsigned frameRate = codec.GetFrameRate()*2;
3971 
3972       if (!channelNumber.IsFromRemote()) { // Transmit channel
3973         if (IsMediaOnHold()) {
3974           if (IsCallOnHold()) {
3975              PTRACE(4, "H4504\tHold Media OnHold Transmit " << i);
3976           existingTransmitChannel = codec.SwapChannel(newChannel);
3977               existingTransmitChannel = OnCallHold(TRUE,session_id,frameRate,existingTransmitChannel);
3978           } else {
3979              PTRACE(4, "H4504\tRetrieve Media OnHold Transmit " << i);
3980          existingTransmitChannel = codec.SwapChannel(OnCallRetrieve(TRUE,session_id,frameRate,existingTransmitChannel));
3981           }
3982         }
3983         else {
3984           // Enable/mute the transmit channel depending on whether the remote end is held
3985        if (IsCallOnHold()) {
3986               PTRACE(4, "H4504\tHold Transmit " << i);
3987               chan2->SetPause(TRUE);
3988               if (codec.SetRawDataHeld(TRUE))
3989                 codec.SwapChannel(OnCallHold(TRUE,session_id,frameRate,rawChannel));
3990            } else {
3991               PTRACE(4, "H4504\tRetreive Transmit " << i);
3992               codec.SwapChannel(OnCallRetrieve(TRUE,session_id,frameRate,rawChannel));
3993               if (codec.SetRawDataHeld(FALSE))
3994                 chan2->SetPause(FALSE);
3995            }
3996         }
3997       }
3998       else {
3999         // Enable/mute the receive channel depending on whether the remote endis held
4000           if (IsCallOnHold()) {
4001             PTRACE(4, "H4504\tHold Receive " << i);
4002             chan2->SetPause(TRUE);
4003              if (codec.SetRawDataHeld(TRUE))
4004                  codec.SwapChannel(OnCallHold(FALSE,session_id,frameRate,rawChannel));
4005           } else {
4006              PTRACE(4, "H4504\tRetrieve Receive " << i);
4007              codec.SwapChannel(OnCallRetrieve(FALSE,session_id,frameRate,rawChannel));
4008              if (codec.SetRawDataHeld(FALSE))
4009                  chan2->SetPause(FALSE);
4010           }
4011       }
4012     }
4013   }
4014 
4015   return existingTransmitChannel;
4016 }
4017 
OnCallHold(PBoolean,unsigned,unsigned,PChannel * channel)4018 PChannel * H323Connection::OnCallHold(PBoolean /*IsEncoder*/,
4019                                   unsigned /*sessionId*/,
4020                                   unsigned /*bufferSize*/,
4021                                   PChannel * channel)
4022 {
4023          return channel;
4024 }
4025 
OnCallRetrieve(PBoolean,unsigned,unsigned bufferSize,PChannel * channel)4026 PChannel * H323Connection::OnCallRetrieve(PBoolean /*IsEncoder*/,
4027                                  unsigned /*sessionId*/,
4028                                  unsigned bufferSize,
4029                                  PChannel * channel)
4030 {
4031     if (bufferSize == 0)
4032         return NULL;
4033     else
4034         return channel;
4035 }
4036 
IsLocalHold() const4037 PBoolean H323Connection::IsLocalHold() const
4038 {
4039   return h4504handler->GetState() == H4504Handler::e_ch_NE_Held;
4040 }
4041 
4042 
IsRemoteHold() const4043 PBoolean H323Connection::IsRemoteHold() const
4044 {
4045   return h4504handler->GetState() == H4504Handler::e_ch_RE_Held;
4046 }
4047 
4048 
IsCallOnHold() const4049 PBoolean H323Connection::IsCallOnHold() const
4050 {
4051   return h4504handler->GetState() != H4504Handler::e_ch_Idle;
4052 }
4053 
4054 
IntrudeCall(unsigned capabilityLevel)4055 void H323Connection::IntrudeCall(unsigned capabilityLevel)
4056 {
4057   h45011handler->IntrudeCall(capabilityLevel);
4058 }
4059 
4060 
HandleIntrudeCall(const PString & token,const PString & identity)4061 void H323Connection::HandleIntrudeCall(const PString & token,
4062                                        const PString & identity)
4063 {
4064   if (!token.IsEmpty() || !identity)
4065     h45011handler->AwaitSetupResponse(token, identity);
4066 }
4067 
4068 
GetRemoteCallIntrusionProtectionLevel(const PString & intrusionCallToken,unsigned intrusionCICL)4069 PBoolean H323Connection::GetRemoteCallIntrusionProtectionLevel(const PString & intrusionCallToken,
4070                                                            unsigned intrusionCICL)
4071 {
4072   return h45011handler->GetRemoteCallIntrusionProtectionLevel(intrusionCallToken, intrusionCICL);
4073 }
4074 
4075 
SetIntrusionImpending()4076 void H323Connection::SetIntrusionImpending()
4077 {
4078   h45011handler->SetIntrusionImpending();
4079 }
4080 
4081 
SetForcedReleaseAccepted()4082 void H323Connection::SetForcedReleaseAccepted()
4083 {
4084   h45011handler->SetForcedReleaseAccepted();
4085 }
4086 
4087 
SetIntrusionNotAuthorized()4088 void H323Connection::SetIntrusionNotAuthorized()
4089 {
4090   h45011handler->SetIntrusionNotAuthorized();
4091 }
4092 
4093 
SendCallWaitingIndication(const unsigned nbOfAddWaitingCalls)4094 void H323Connection::SendCallWaitingIndication(const unsigned nbOfAddWaitingCalls)
4095 {
4096   h4506handler->AttachToAlerting(*alertingPDU, nbOfAddWaitingCalls);
4097 }
4098 
SetMWINonCallParameters(const H323Connection::MWIInformation & mwiInfo)4099 void H323Connection::SetMWINonCallParameters(const H323Connection::MWIInformation & mwiInfo)
4100 {
4101     SetNonCallConnection();
4102 
4103     // Replace the default information
4104     mwiInformation = mwiInfo;
4105 }
4106 
GetMWINonCallParameters()4107 const H323Connection::MWIInformation & H323Connection::GetMWINonCallParameters()
4108 {
4109     return mwiInformation;
4110 }
4111 
OnReceivedMWI(const MWIInformation & mwiInfo)4112 PBoolean H323Connection::OnReceivedMWI(const MWIInformation & mwiInfo)
4113 {
4114     return endpoint.OnReceivedMWI(mwiInfo);
4115 }
4116 
OnReceivedMWIClear(const PString & user)4117 PBoolean H323Connection::OnReceivedMWIClear(const PString & user)
4118 {
4119     return endpoint.OnReceivedMWIClear(user);
4120 }
4121 
OnReceivedMWIRequest(const PString & user)4122 PBoolean H323Connection::OnReceivedMWIRequest(const PString & user)
4123 {
4124     return endpoint.OnReceivedMWIRequest(this, user);
4125 }
4126 
4127 #endif // H323_H450
4128 
4129 
OnControlProtocolError(ControlProtocolErrors,const void *)4130 PBoolean H323Connection::OnControlProtocolError(ControlProtocolErrors /*errorSource*/,
4131                                             const void * /*errorData*/)
4132 {
4133   return TRUE;
4134 }
4135 
4136 
SetRFC2833PayloadType(H323Capabilities & capabilities,OpalRFC2833 & rfc2833handler)4137 static void SetRFC2833PayloadType(H323Capabilities & capabilities,
4138                                   OpalRFC2833 & rfc2833handler)
4139 {
4140   H323Capability * capability = capabilities.FindCapability(H323_UserInputCapability::SubTypeNames[H323_UserInputCapability::SignalToneRFC2833]);
4141   if (capability != NULL) {
4142     RTP_DataFrame::PayloadTypes pt = ((H323_UserInputCapability*)capability)->GetPayloadType();
4143     if (rfc2833handler.GetPayloadType() != pt) {
4144       PTRACE(2, "H323\tUser Input RFC2833 payload type set to " << pt);
4145       rfc2833handler.SetPayloadType(pt);
4146     }
4147   }
4148 }
4149 
4150 
OnSendCapabilitySet(H245_TerminalCapabilitySet &)4151 void H323Connection::OnSendCapabilitySet(H245_TerminalCapabilitySet & /*pdu*/)
4152 {
4153   // If we originated call, then check for RFC2833 capability and set payload type
4154   if (!callAnswered && rfc2833handler)
4155     SetRFC2833PayloadType(localCapabilities, *rfc2833handler);
4156 }
4157 
4158 
OnReceivedCapabilitySet(const H245_TerminalCapabilitySet &)4159 void H323Connection::OnReceivedCapabilitySet(const H245_TerminalCapabilitySet & /*pdu*/)
4160 {
4161     // do nothing
4162 }
4163 
OnReceivedCapabilitySet(const H323Capabilities & remoteCaps,const H245_MultiplexCapability * muxCap,H245_TerminalCapabilitySetReject &)4164 PBoolean H323Connection::OnReceivedCapabilitySet(const H323Capabilities & remoteCaps,
4165                                              const H245_MultiplexCapability * muxCap,
4166                                              H245_TerminalCapabilitySetReject & /*rejectPDU*/)
4167 {
4168   if (muxCap != NULL) {
4169     if (muxCap->GetTag() != H245_MultiplexCapability::e_h2250Capability) {
4170       PTRACE(1, "H323\tCapabilitySet contains unsupported multiplex.");
4171       return FALSE;
4172     }
4173 
4174     const H245_H2250Capability & h225_0 = *muxCap;
4175     remoteMaxAudioDelayJitter = h225_0.m_maximumAudioDelayJitter;
4176   }
4177 
4178   // save this time as being when the reverse media channel was opened
4179   if (!reverseMediaOpenTime.IsValid())
4180     reverseMediaOpenTime = PTime();
4181 
4182   if (remoteCaps.GetSize() == 0) {
4183     // Received empty TCS, so close all transmit channels
4184     for (PINDEX i = 0; i < logicalChannels->GetSize(); i++) {
4185       H245NegLogicalChannel & negChannel = logicalChannels->GetNegLogicalChannelAt(i);
4186       H323Channel * channel = negChannel.GetChannel();
4187       if (channel != NULL && !channel->GetNumber().IsFromRemote())
4188         negChannel.Close();
4189     }
4190     transmitterSidePaused = TRUE;
4191   }
4192   else { // Received non-empty TCS
4193 
4194     // If we had received a TCS=0 previously, or we have a remoteCapabilities which
4195     // was "faked" from the fast start data, overwrite it, don't merge it.
4196     if (transmitterSidePaused || !capabilityExchangeProcedure->HasReceivedCapabilities())
4197       remoteCapabilities.RemoveAll();
4198 
4199     if (!remoteCapabilities.Merge(remoteCaps))
4200       return FALSE;
4201 
4202     if (transmitterSidePaused) {
4203       transmitterSidePaused = FALSE;
4204       connectionState = HasExecutedSignalConnect;
4205       capabilityExchangeProcedure->Start(TRUE);
4206     }
4207     else {
4208       if (localCapabilities.GetSize() > 0)
4209         capabilityExchangeProcedure->Start(FALSE);
4210 
4211       // If we terminated call, then check for RFC2833 capability and set payload type
4212       if (callAnswered && rfc2833handler)
4213         SetRFC2833PayloadType(remoteCapabilities, *rfc2833handler);
4214     }
4215   }
4216 
4217   return OnCommonCapabilitySet(remoteCapabilities);
4218 }
4219 
OnCommonCapabilitySet(H323Capabilities & caps) const4220 PBoolean H323Connection::OnCommonCapabilitySet(H323Capabilities & caps) const
4221 {
4222     return TRUE;
4223 }
4224 
4225 
SendCapabilitySet(PBoolean empty)4226 void H323Connection::SendCapabilitySet(PBoolean empty)
4227 {
4228   capabilityExchangeProcedure->Start(TRUE, empty);
4229 }
4230 
OnBearerCapabilityTransferRate(unsigned & bitRate)4231 void H323Connection::OnBearerCapabilityTransferRate(unsigned & bitRate)
4232 {
4233     endpoint.OnBearerCapabilityTransferRate(bitRate);
4234 }
4235 
SetInitialBandwidth(H323Capability::MainTypes captype,int bitRate)4236 void H323Connection::SetInitialBandwidth(H323Capability::MainTypes captype, int bitRate)
4237 {
4238 #ifdef H323_VIDEO
4239   for (PINDEX i=0; i< localCapabilities.GetSize(); ++i) {
4240     if (localCapabilities[i].GetMainType() == captype) {
4241       OpalMediaFormat & fmt = localCapabilities[i].GetWritableMediaFormat();
4242       if (fmt.GetOptionInteger(OpalVideoFormat::MaxBitRateOption) > bitRate)
4243              fmt.SetOptionInteger(OpalVideoFormat::MaxBitRateOption,bitRate);
4244     }
4245   }
4246 #endif
4247 }
4248 
SetMaxPayloadSize(H323Capability::MainTypes captype,int size)4249 void H323Connection::SetMaxPayloadSize(H323Capability::MainTypes captype, int size)
4250 {
4251 #ifdef H323_VIDEO
4252   for (PINDEX i=0; i< localCapabilities.GetSize(); ++i) {
4253     if (localCapabilities[i].GetMainType() == captype) {
4254       OpalMediaFormat & fmt = localCapabilities[i].GetWritableMediaFormat();
4255       if (fmt.HasOption(OpalVideoFormat::MaxPayloadSizeOption)) {
4256              fmt.SetOptionInteger(OpalVideoFormat::MaxPayloadSizeOption,size);
4257   //           if (fmt.HasOption("Generic Parameter 9"))   // for H.264....
4258   //               fmt.SetOptionInteger("Generic Parameter 9",size);
4259       }
4260     }
4261   }
4262 #endif
4263 }
4264 
SetEmphasisSpeed(H323Capability::MainTypes captype,bool speed)4265 void H323Connection::SetEmphasisSpeed(H323Capability::MainTypes captype, bool speed)
4266 {
4267 #ifdef H323_VIDEO
4268   for (PINDEX i=0; i< localCapabilities.GetSize(); ++i) {
4269     if (localCapabilities[i].GetMainType() == captype) {
4270       OpalMediaFormat & fmt = localCapabilities[i].GetWritableMediaFormat();
4271       if (fmt.HasOption(OpalVideoFormat::EmphasisSpeedOption))
4272           fmt.SetOptionBoolean(OpalVideoFormat::EmphasisSpeedOption,speed);
4273     }
4274   }
4275 #endif
4276 }
4277 
4278 
OnSetLocalCapabilities()4279 void H323Connection::OnSetLocalCapabilities()
4280 {
4281 }
4282 
OnSetLocalUserInputCapabilities()4283 void H323Connection::OnSetLocalUserInputCapabilities()
4284 {
4285     if (!rfc2833InBandDTMF)
4286         localCapabilities.Remove("UserInput/RFC2833");
4287 
4288     if (!extendedUserInput)
4289         localCapabilities.Remove("UserInput/H249_*");
4290 }
4291 
IsH245Master() const4292 PBoolean H323Connection::IsH245Master() const
4293 {
4294   return masterSlaveDeterminationProcedure->IsMaster();
4295 }
4296 
4297 
StartRoundTripDelay()4298 void H323Connection::StartRoundTripDelay()
4299 {
4300   if (Lock()) {
4301     if (masterSlaveDeterminationProcedure->IsDetermined() &&
4302         capabilityExchangeProcedure->HasSentCapabilities()) {
4303       if (roundTripDelayProcedure->IsRemoteOffline()) {
4304         PTRACE(2, "H245\tRemote failed to respond to PDU.");
4305         if (endpoint.ShouldClearCallOnRoundTripFail())
4306           ClearCall(EndedByTransportFail);
4307       }
4308       else
4309         roundTripDelayProcedure->StartRequest();
4310     }
4311     Unlock();
4312   }
4313 }
4314 
4315 
GetRoundTripDelay() const4316 PTimeInterval H323Connection::GetRoundTripDelay() const
4317 {
4318   return roundTripDelayProcedure->GetRoundTripDelay();
4319 }
4320 
4321 
InternalEstablishedConnectionCheck()4322 void H323Connection::InternalEstablishedConnectionCheck()
4323 {
4324   PTRACE(3, "H323\tInternalEstablishedConnectionCheck: "
4325             "connectionState=" << connectionState << " "
4326             "fastStartState=" << fastStartState);
4327 
4328   PBoolean h245_available = masterSlaveDeterminationProcedure->IsDetermined() &&
4329                         capabilityExchangeProcedure->HasSentCapabilities() &&
4330                         capabilityExchangeProcedure->HasReceivedCapabilities();
4331 
4332   if (h245_available)
4333     endSessionNeeded = TRUE;
4334 
4335   // Check for if all the 245 conditions are met so can start up logical
4336   // channels and complete the connection establishment.
4337   if (fastStartState != FastStartAcknowledged) {
4338     if (!h245_available)
4339       return;
4340 
4341     // If we are early starting, start channels as soon as possible instead of
4342     // waiting for connect PDU
4343     if (earlyStart && FindChannel(RTP_Session::DefaultAudioSessionID, FALSE) == NULL)
4344       OnSelectLogicalChannels();
4345   }
4346 
4347 #ifdef H323_T120
4348   if (h245_available && startT120) {
4349     if (remoteCapabilities.FindCapability("T.120") != NULL) {
4350       H323Capability * capability = localCapabilities.FindCapability("T.120");
4351       if (capability != NULL)
4352         OpenLogicalChannel(*capability, 3, H323Channel::IsBidirectional);
4353     }
4354     startT120 = FALSE;
4355   }
4356 #endif
4357 
4358 #ifdef H323_H224
4359   if (h245_available && startH224) {
4360     if(remoteCapabilities.FindCapability("H.224") != NULL) {
4361       H323Capability * capability = localCapabilities.FindCapability("H.224");
4362       if(capability != NULL)
4363          OpenLogicalChannel(*capability,RTP_Session::DefaultH224SessionID, H323Channel::IsBidirectional);
4364     }
4365     startH224 = FALSE;
4366   }
4367 #endif
4368 
4369   // Special case for Cisco CCM, when it does "early start" and opens its audio
4370   // channel to us, we better open one back or it hangs up!
4371   if ( h245_available &&
4372       !mediaWaitForConnect &&
4373        connectionState == AwaitingSignalConnect &&
4374        FindChannel(RTP_Session::DefaultAudioSessionID, TRUE) != NULL &&
4375        FindChannel(RTP_Session::DefaultAudioSessionID, FALSE) == NULL)
4376     OnSelectLogicalChannels();
4377 
4378   if (connectionState != HasExecutedSignalConnect)
4379     return;
4380 
4381   // Check if we have already got a transmitter running, select one if not
4382   if (FindChannel(RTP_Session::DefaultAudioSessionID, FALSE) == NULL)
4383     OnSelectLogicalChannels();
4384 
4385   connectionState = EstablishedConnection;
4386 
4387   if (signallingChannel)
4388       signallingChannel->SetCallEstablished();
4389 
4390   OnEstablished();
4391 }
4392 
4393 #if defined(H323_AUDIO_CODECS) || defined(H323_VIDEO) || defined(H323_T38) || defined(H323_FILE)
4394 
StartFastStartChannel(H323LogicalChannelList & fastStartChannels,unsigned sessionID,H323Channel::Directions direction)4395 static void StartFastStartChannel(H323LogicalChannelList & fastStartChannels,
4396                                   unsigned sessionID, H323Channel::Directions direction)
4397 {
4398   for (PINDEX i = 0; i < fastStartChannels.GetSize(); i++) {
4399     H323Channel & channel = fastStartChannels[i];
4400     if (channel.GetSessionID() == sessionID && channel.GetDirection() == direction) {
4401       fastStartChannels[i].Start();
4402       break;
4403     }
4404   }
4405 }
4406 
4407 #endif
4408 
4409 
OnSelectLogicalChannels()4410 void H323Connection::OnSelectLogicalChannels()
4411 {
4412   PTRACE(2, "H245\tDefault OnSelectLogicalChannels, " << fastStartState);
4413 
4414   // Select the first codec that uses the "standard" audio session.
4415   switch (fastStartState) {
4416     default : //FastStartDisabled :
4417 #ifdef H323_AUDIO_CODECS
4418       if (endpoint.CanAutoStartTransmitAudio())
4419          SelectDefaultLogicalChannel(RTP_Session::DefaultAudioSessionID);
4420 #endif
4421 #ifdef H323_VIDEO
4422       if (endpoint.CanAutoStartTransmitVideo())
4423         SelectDefaultLogicalChannel(RTP_Session::DefaultVideoSessionID);
4424 #ifdef H323_H239
4425       if (endpoint.CanAutoStartTransmitExtVideo())
4426         SelectDefaultLogicalChannel(RTP_Session::DefaultExtVideoSessionID);
4427 #endif
4428 #endif // H323_VIDEO
4429 #ifdef H323_T38
4430       if (endpoint.CanAutoStartTransmitFax())
4431         SelectDefaultLogicalChannel(RTP_Session::DefaultFaxSessionID);
4432 #endif
4433       break;
4434 
4435     case FastStartInitiate :
4436 #ifdef H323_AUDIO_CODECS
4437       SelectFastStartChannels(RTP_Session::DefaultAudioSessionID,
4438                               endpoint.CanAutoStartTransmitAudio(),
4439                               endpoint.CanAutoStartReceiveAudio());
4440 #endif
4441 #ifdef H323_VIDEO
4442       SelectFastStartChannels(RTP_Session::DefaultVideoSessionID,
4443                               endpoint.CanAutoStartTransmitVideo(),
4444                               endpoint.CanAutoStartReceiveVideo());
4445 #ifdef H323_H239
4446       SelectFastStartChannels(RTP_Session::DefaultExtVideoSessionID,
4447                               endpoint.CanAutoStartTransmitExtVideo(),
4448                               endpoint.CanAutoStartReceiveExtVideo());
4449 #endif
4450 #endif // H323_VIDEO
4451 
4452 #if defined(H323_T38) || defined(H323_FILE)
4453       SelectFastStartChannels(RTP_Session::DefaultFaxSessionID,
4454                               endpoint.CanAutoStartTransmitFax(),
4455                               endpoint.CanAutoStartReceiveFax());
4456 #endif
4457       break;
4458 
4459     case FastStartResponse :
4460 #ifdef H323_AUDIO_CODECS
4461       if (endpoint.CanAutoStartTransmitAudio())
4462         StartFastStartChannel(fastStartChannels, RTP_Session::DefaultAudioSessionID, H323Channel::IsTransmitter);
4463       if (endpoint.CanAutoStartReceiveAudio())
4464         StartFastStartChannel(fastStartChannels, RTP_Session::DefaultAudioSessionID, H323Channel::IsReceiver);
4465 #endif
4466 #ifdef H323_VIDEO
4467       if (endpoint.CanAutoStartTransmitVideo())
4468         StartFastStartChannel(fastStartChannels, RTP_Session::DefaultVideoSessionID, H323Channel::IsTransmitter);
4469       if (endpoint.CanAutoStartReceiveVideo())
4470         StartFastStartChannel(fastStartChannels, RTP_Session::DefaultVideoSessionID, H323Channel::IsReceiver);
4471 
4472 #ifdef H323_H239
4473       if (endpoint.CanAutoStartTransmitExtVideo())
4474         StartFastStartChannel(fastStartChannels, RTP_Session::DefaultExtVideoSessionID, H323Channel::IsTransmitter);
4475       if (endpoint.CanAutoStartReceiveExtVideo())
4476         StartFastStartChannel(fastStartChannels, RTP_Session::DefaultExtVideoSessionID, H323Channel::IsReceiver);
4477 #endif
4478 #endif  // H323_VIDEO
4479 
4480 #ifdef H323_T38
4481       if (endpoint.CanAutoStartTransmitFax())
4482         StartFastStartChannel(fastStartChannels, RTP_Session::DefaultFaxSessionID, H323Channel::IsTransmitter);
4483       if (endpoint.CanAutoStartReceiveFax())
4484         StartFastStartChannel(fastStartChannels, RTP_Session::DefaultFaxSessionID, H323Channel::IsReceiver);
4485 #endif
4486       break;
4487   }
4488 }
4489 
4490 
SelectDefaultLogicalChannel(unsigned sessionID)4491 void H323Connection::SelectDefaultLogicalChannel(unsigned sessionID)
4492 {
4493   if (FindChannel (sessionID, FALSE))
4494     return;
4495 
4496   for (PINDEX i = 0; i < localCapabilities.GetSize(); i++) {
4497     H323Capability & localCapability = localCapabilities[i];
4498     if (localCapability.GetDefaultSessionID() == sessionID) {
4499       H323Capability * remoteCapability = remoteCapabilities.FindCapability(localCapability);
4500       if (remoteCapability != NULL) {
4501         PTRACE(3, "H323\tSelecting " << *remoteCapability);
4502 
4503         MergeCapabilities(sessionID, localCapability, remoteCapability);
4504 
4505         if (OpenLogicalChannel(*remoteCapability, sessionID, H323Channel::IsTransmitter))
4506           break;
4507         PTRACE(2, "H323\tOnSelectLogicalChannels, OpenLogicalChannel failed: "
4508                << *remoteCapability);
4509       }
4510     }
4511   }
4512 }
4513 
4514 
MergeCapabilities(unsigned sessionID,const H323Capability & local,H323Capability * remote)4515 PBoolean H323Connection::MergeCapabilities(unsigned sessionID, const H323Capability & local, H323Capability * remote)
4516 {
4517 
4518    OpalMediaFormat & remoteFormat = remote->GetWritableMediaFormat();
4519    const OpalMediaFormat & localFormat = local.GetMediaFormat();
4520 
4521    if (remoteFormat.Merge(localFormat)) {
4522 #ifdef H323_VIDEO
4523        unsigned maxBitRate = remoteFormat.GetOptionInteger(OpalVideoFormat::MaxBitRateOption);
4524        unsigned targetBitRate = remoteFormat.GetOptionInteger(OpalVideoFormat::TargetBitRateOption);
4525        if (targetBitRate > maxBitRate)
4526           remoteFormat.SetOptionInteger(OpalVideoFormat::TargetBitRateOption, maxBitRate);
4527 #endif
4528 #if PTRACING
4529       PTRACE(6, "H323\tCapability Merge: ");
4530       OpalMediaFormat::DebugOptionList(remoteFormat);
4531 #endif
4532       return TRUE;
4533    }
4534    return FALSE;
4535 }
4536 
MergeLanguages(const PStringList & remote,PBoolean)4537 PBoolean H323Connection::MergeLanguages(const PStringList & remote, PBoolean /*isCaller*/)
4538 {
4539     return MergeLanguages(remote);
4540 }
4541 
MergeLanguages(const PStringList & remote)4542 PBoolean H323Connection::MergeLanguages(const PStringList & remote)
4543 {
4544 	PStringList common;
4545 	common.SetSize(0);
4546 	for (PINDEX i=0; i < remote.GetSize(); ++i) {
4547 		for (PINDEX j=0; j < localLanguages.GetSize(); ++j) {
4548 			if (remote[i] == localLanguages[j])
4549 				common.AppendString(remote[i]);
4550 		}
4551 	}
4552 	localLanguages = common;
4553 	return OnCommonLanguages(localLanguages);
4554 }
4555 
OnCommonLanguages(const PStringList & lang)4556 PBoolean H323Connection::OnCommonLanguages(const PStringList & lang)
4557 {
4558 	return (lang.GetSize() > 0);
4559 }
4560 
DisableFastStart()4561 void H323Connection::DisableFastStart()
4562 {
4563     fastStartState = FastStartDisabled;
4564 }
4565 
4566 
SelectFastStartChannels(unsigned sessionID,PBoolean transmitter,PBoolean receiver)4567 void H323Connection::SelectFastStartChannels(unsigned sessionID,
4568                                              PBoolean transmitter,
4569                                              PBoolean receiver)
4570 {
4571   // Select all of the fast start channels to offer to the remote when initiating a call.
4572   for (PINDEX i = 0; i < localCapabilities.GetSize(); i++) {
4573     H323Capability & capability = localCapabilities[i];
4574     if (capability.GetDefaultSessionID() == sessionID) {
4575       if (receiver) {
4576         if (!OpenLogicalChannel(capability, sessionID, H323Channel::IsReceiver)) {
4577           PTRACE(2, "H323\tOnSelectLogicalChannels, OpenLogicalChannel rx failed: " << capability);
4578         }
4579       }
4580       if (transmitter) {
4581         if (!OpenLogicalChannel(capability, sessionID, H323Channel::IsTransmitter)) {
4582           PTRACE(2, "H323\tOnSelectLogicalChannels, OpenLogicalChannel tx failed: " << capability);
4583         }
4584       }
4585     }
4586   }
4587 }
4588 
4589 
OpenLogicalChannel(const H323Capability & capability,unsigned sessionID,H323Channel::Directions dir)4590 PBoolean H323Connection::OpenLogicalChannel(const H323Capability & capability,
4591                                         unsigned sessionID,
4592                                         H323Channel::Directions dir)
4593 {
4594   switch (fastStartState) {
4595     default : // FastStartDisabled
4596       if (dir == H323Channel::IsReceiver)
4597         return FALSE;
4598 
4599       // Traditional H245 handshake
4600       return logicalChannels->Open(capability, sessionID);
4601 
4602     case FastStartResponse :
4603       // Do not use OpenLogicalChannel for starting these.
4604       return FALSE;
4605 
4606     case FastStartInitiate :
4607       break;
4608   }
4609 
4610   /*If starting a receiver channel and are initiating the fast start call,
4611     indicated by the remoteCapabilities being empty, we do a "trial"
4612     listen on the channel. That is, for example, the UDP sockets are created
4613     to receive data in the RTP session, but no thread is started to read the
4614     packets and pass them to the codec. This is because at this point in time,
4615     we do not know which of the codecs is to be used, and more than one thread
4616     cannot read from the RTP ports at the same time.
4617   */
4618   H323Channel * channel = capability.CreateChannel(*this, dir, sessionID, NULL);
4619   if (channel == NULL)
4620     return FALSE;
4621 
4622   if (dir != H323Channel::IsReceiver)
4623     channel->SetNumber(logicalChannels->GetNextChannelNumber());
4624 
4625   fastStartChannels.Append(channel);
4626   return TRUE;
4627 }
4628 
4629 
OnOpenLogicalChannel(const H245_OpenLogicalChannel & openPDU,H245_OpenLogicalChannelAck & ackPDU,unsigned &,const unsigned & sessionID)4630 PBoolean H323Connection::OnOpenLogicalChannel(const H245_OpenLogicalChannel & openPDU,
4631                                           H245_OpenLogicalChannelAck & ackPDU,
4632                                           unsigned & /*errorCode*/,
4633                                           const unsigned & sessionID)
4634 
4635 {
4636   // If get a OLC via H.245 stop trying to do fast start
4637   fastStartState = FastStartDisabled;
4638   if (!fastStartChannels.IsEmpty()) {
4639     fastStartChannels.RemoveAll();
4640 #ifdef P_STUN
4641     m_NATSockets.clear();
4642 #endif
4643     PTRACE(1, "H245\tReceived early start OLC, aborting fast start");
4644   }
4645 
4646 #ifdef H323_H46018
4647   PTRACE(4,"H323\tOnOpenLogicalChannel");
4648   if (openPDU.HasOptionalField(H245_OpenLogicalChannel::e_genericInformation)) {
4649          OnReceiveOLCGenericInformation(sessionID,openPDU.m_genericInformation,false);
4650 
4651          if (OnSendingOLCGenericInformation(sessionID,ackPDU.m_genericInformation,true))
4652              ackPDU.IncludeOptionalField(H245_OpenLogicalChannelAck::e_genericInformation);
4653   }
4654 #endif
4655 
4656   //errorCode = H245_OpenLogicalChannelReject_cause::e_unspecified;
4657   return true;
4658 }
4659 
4660 
OnConflictingLogicalChannel(H323Channel & conflictingChannel)4661 PBoolean H323Connection::OnConflictingLogicalChannel(H323Channel & conflictingChannel)
4662 {
4663   unsigned session = conflictingChannel.GetSessionID();
4664   PTRACE(2, "H323\tLogical channel " << conflictingChannel
4665          << " conflict on session " << session
4666          << ", codec: " << conflictingChannel.GetCapability());
4667 
4668   /* Matrix of conflicts:
4669        Local EP is master and conflicting channel from remote (OLC)
4670           Reject remote transmitter (function is not called)
4671        Local EP is master and conflicting channel to remote (OLCAck)
4672           Should not happen (function is not called)
4673        Local EP is slave and conflicting channel from remote (OLC)
4674           Close sessions reverse channel from remote
4675           Start new reverse channel using codec in conflicting channel
4676           Accept the OLC for masters transmitter
4677        Local EP is slave and conflicting channel to remote (OLCRej)
4678           Start transmitter channel using codec in sessions reverse channel
4679 
4680       Upshot is this is only called if a slave and require a restart of
4681       some channel. Possibly closing channels as master has precedence.
4682    */
4683 
4684   PBoolean fromRemote = conflictingChannel.GetNumber().IsFromRemote();
4685   H323Channel * channel = FindChannel(session, !fromRemote);
4686   if (channel == NULL) {
4687     PTRACE(1, "H323\tCould not resolve conflict, no reverse channel.");
4688     return FALSE;
4689   }
4690 
4691   if (!fromRemote) {
4692     conflictingChannel.CleanUpOnTermination();
4693     H323Capability * capability = remoteCapabilities.FindCapability(channel->GetCapability());
4694     if (capability == NULL) {
4695       PTRACE(1, "H323\tCould not resolve conflict, capability not available on remote.");
4696       return FALSE;
4697     }
4698     OpenLogicalChannel(*capability, session, H323Channel::IsTransmitter);
4699     return TRUE;
4700   }
4701 
4702   // Shut down the conflicting channel that got in before our transmitter
4703   channel->CleanUpOnTermination();
4704 
4705   // Get the conflisting channel number to close
4706   H323ChannelNumber number = channel->GetNumber();
4707 
4708   // Must be slave and conflict from something we are sending, so try starting a
4709   // new channel using the master endpoints transmitter codec.
4710   logicalChannels->Open(conflictingChannel.GetCapability(), session, number);
4711 
4712   // Now close the conflicting channel
4713   CloseLogicalChannelNumber(number);
4714   return TRUE;
4715 }
4716 
4717 
CreateLogicalChannel(const H245_OpenLogicalChannel & open,PBoolean startingFast,unsigned & errorCode)4718 H323Channel * H323Connection::CreateLogicalChannel(const H245_OpenLogicalChannel & open,
4719                                                    PBoolean startingFast,
4720                                                    unsigned & errorCode)
4721 {
4722   const H245_H2250LogicalChannelParameters * param = NULL;
4723   const H245_DataType * dataType = NULL;
4724   H323Channel::Directions direction;
4725 
4726   if (startingFast && open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters)) {
4727     if (open.m_reverseLogicalChannelParameters.m_multiplexParameters.GetTag() !=
4728               H245_OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
4729                                                       ::e_h2250LogicalChannelParameters) {
4730       errorCode = H245_OpenLogicalChannelReject_cause::e_unsuitableReverseParameters;
4731       PTRACE(2, "H323\tCreateLogicalChannel - reverse channel, H225.0 only supported");
4732       return NULL;
4733     }
4734 
4735     PTRACE(3, "H323\tCreateLogicalChannel - reverse channel");
4736     dataType = &open.m_reverseLogicalChannelParameters.m_dataType;
4737     param = &(const H245_H2250LogicalChannelParameters &)
4738                       open.m_reverseLogicalChannelParameters.m_multiplexParameters;
4739     direction = H323Channel::IsTransmitter;
4740   }
4741   else {
4742     if (open.m_forwardLogicalChannelParameters.m_multiplexParameters.GetTag() !=
4743               H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters
4744                                                       ::e_h2250LogicalChannelParameters) {
4745       PTRACE(2, "H323\tCreateLogicalChannel - forward channel, H225.0 only supported");
4746       errorCode = H245_OpenLogicalChannelReject_cause::e_unspecified;
4747       return NULL;
4748     }
4749 
4750     PTRACE(3, "H323\tCreateLogicalChannel - forward channel");
4751     dataType = &open.m_forwardLogicalChannelParameters.m_dataType;
4752     param = &(const H245_H2250LogicalChannelParameters &)
4753                       open.m_forwardLogicalChannelParameters.m_multiplexParameters;
4754     direction = H323Channel::IsReceiver;
4755   }
4756 
4757   unsigned sessionID = param->m_sessionID;
4758 
4759 #ifdef H323_VIDEO
4760 #ifdef H323_H239
4761   if (sessionID == 0) {
4762     if (IsH245Master()) {
4763       // as master we assign the session ID
4764       sessionID = GetExtVideoRTPSessionID();
4765       const_cast<H245_H2250LogicalChannelParameters *>(param)->m_sessionID = sessionID; // TODO: make PDU (open) non-const all the way ?
4766       PTRACE(2, "H323\tAssigned RTP session ID " << sessionID);
4767     } else {
4768       PTRACE(2, "H323\tCreateLogicalChannel - received RTP session ID 0 as slave");
4769       return NULL;
4770     }
4771   }
4772 
4773   if (!startingFast &&
4774       open.HasOptionalField(H245_OpenLogicalChannel::e_genericInformation)) {  // check for extended Video OLC
4775 
4776     unsigned roleLabel = 0;
4777     H323ChannelNumber channelnum = H323ChannelNumber(open.m_forwardLogicalChannelNumber, TRUE);
4778 
4779     const H245_ArrayOf_GenericInformation & cape = open.m_genericInformation;
4780     for (PINDEX i = 0; i < cape.GetSize(); i++) {
4781        const H245_GenericMessage & gcap = cape[i];
4782        const PASN_ObjectId & object_id = gcap.m_messageIdentifier;
4783        if (object_id.AsString() == OpalPluginCodec_Identifer_H239_Video) {
4784            if (gcap.HasOptionalField(H245_GenericMessage::e_messageContent)) {
4785                const H245_ArrayOf_GenericParameter & params = gcap.m_messageContent;
4786                for (PINDEX j = 0; j < params.GetSize(); j++) {
4787                    const H245_GenericParameter & content = params[j];
4788                    const H245_ParameterValue & paramval = content.m_parameterValue;
4789                    if (paramval.GetTag() == H245_ParameterValue::e_booleanArray) {
4790                        const PASN_Integer & val = paramval;
4791                        roleLabel = val;
4792                    }
4793                }
4794            }
4795           OnReceivedExtendedVideoSession(roleLabel, channelnum);
4796        }
4797     }
4798   }
4799 #endif
4800 #endif // H323_VIDEO
4801 
4802   // See if datatype is supported
4803   H323Capability * capability = localCapabilities.FindCapability(*dataType);
4804   if (capability == NULL) {
4805     errorCode = H245_OpenLogicalChannelReject_cause::e_unknownDataType;
4806     PTRACE(2, "H323\tCreateLogicalChannel - unknown data type");
4807     return NULL; // If codec not supported, return error
4808   }
4809 
4810   if (!capability->OnReceivedPDU(*dataType, direction == H323Channel::IsReceiver)) {
4811     errorCode = H245_OpenLogicalChannelReject_cause::e_dataTypeNotSupported;
4812     PTRACE(2, "H323\tCreateLogicalChannel - data type not supported");
4813     return NULL; // If codec not supported, return error
4814   }
4815 
4816   if (startingFast && (direction == H323Channel::IsTransmitter)) {
4817     H323Capability * remoteCapability = remoteCapabilities.FindCapability(*capability);
4818     if (remoteCapability != NULL)
4819       capability = remoteCapability;
4820     else {
4821       capability = remoteCapabilities.Copy(*capability);
4822       remoteCapabilities.SetCapability(0, 0, capability);
4823     }
4824   }
4825 
4826   if (!OnCreateLogicalChannel(*capability, direction, errorCode))
4827     return NULL; // If codec combination not supported, return error
4828 
4829   H323Channel * channel = capability->CreateChannel(*this, direction, sessionID, param);
4830   if (channel == NULL) {
4831     errorCode = H245_OpenLogicalChannelReject_cause::e_dataTypeNotAvailable;
4832     PTRACE(2, "H323\tCreateLogicalChannel - data type not available");
4833     return NULL;
4834   }
4835 
4836 #ifdef H323_H239
4837   if ((channel->GetCapability().GetMainType() == H323Capability::e_Video)
4838       && (channel->GetCapability().GetSubType() == H245_VideoCapability::e_extendedVideoCapability)
4839       && !IsH245Master()) {
4840     // as slave remember the session ID for H.239 that the master has used
4841     SetExtVideoRTPSessionID(sessionID);
4842   }
4843 #endif // H323_H239
4844 
4845   if (startingFast &&
4846       open.HasOptionalField(H245_OpenLogicalChannel::e_genericInformation))
4847           OnReceiveOLCGenericInformation(sessionID, open.m_genericInformation, false);
4848 
4849   if (!channel->SetInitialBandwidth())
4850     errorCode = H245_OpenLogicalChannelReject_cause::e_insufficientBandwidth;
4851   else if (channel->OnReceivedPDU(open, errorCode))
4852     return channel;
4853 
4854   PTRACE(2, "H323\tOnReceivedPDU gave error " << errorCode);
4855   delete channel;
4856   return NULL;
4857 }
4858 
4859 
CreateRealTimeLogicalChannel(const H323Capability & capability,H323Channel::Directions dir,unsigned sessionID,const H245_H2250LogicalChannelParameters * param,RTP_QOS * rtpqos)4860 H323Channel * H323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability,
4861                                                            H323Channel::Directions dir,
4862                                                            unsigned sessionID,
4863                                const H245_H2250LogicalChannelParameters * param,
4864                                                            RTP_QOS * rtpqos)
4865 {
4866 #ifdef H323_H235
4867   if (PIsDescendant(&capability, H323SecureCapability) || PIsDescendant(&capability, H323SecureExtendedCapability)) {
4868         // Override this function to add Secure ExternalRTPChannel Support
4869         // H323Channel * extChannel = new H323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
4870         // return new H323SecureChannel(this, capability, extChannel);
4871 
4872         // call H323_ExternalRTPChannel::OnReadFrame(RTP_DataFrame & frame) and H323_ExternalRTPChannel::OnWriteFrame(RTP_DataFrame & frame)
4873         // to encrypt and decrypt media
4874       return NULL;
4875   }
4876 #endif
4877 
4878   RTP_Session * session = NULL;
4879 
4880   if (
4881 #ifdef H323_H46026
4882      H46026IsMediaTunneled() ||
4883 #endif
4884      !param || !param->HasOptionalField(H245_H2250LogicalChannelParameters::e_mediaControlChannel)) {
4885         // Make a fake transmprt address from the connection so gets initialised with
4886         // the transport type (IP, IPX, multicast etc).
4887         H245_TransportAddress addr;
4888         GetControlChannel().SetUpTransportPDU(addr, H323Transport::UseLocalTSAP);
4889         session = UseSession(sessionID, addr, dir, rtpqos);
4890   } else {
4891     session = UseSession(sessionID, param->m_mediaControlChannel, dir, rtpqos);
4892   }
4893 
4894   if (session == NULL)
4895     return NULL;
4896 
4897   return new H323_RTPChannel(*this, capability, dir, *session);
4898 }
4899 
4900 
OnCreateLogicalChannel(const H323Capability & capability,H323Channel::Directions dir,unsigned & errorCode)4901 PBoolean H323Connection::OnCreateLogicalChannel(const H323Capability & capability,
4902                                             H323Channel::Directions dir,
4903                                             unsigned & errorCode)
4904 {
4905   if (connectionState == ShuttingDownConnection) {
4906     errorCode = H245_OpenLogicalChannelReject_cause::e_unspecified;
4907     return FALSE;
4908   }
4909 
4910   // Default error if returns FALSE
4911   errorCode = H245_OpenLogicalChannelReject_cause::e_dataTypeALCombinationNotSupported;
4912 
4913   // Check if in set at all
4914   if (dir != H323Channel::IsReceiver) {
4915     if (!remoteCapabilities.IsAllowed(capability)) {
4916       PTRACE(2, "H323\tOnCreateLogicalChannel - transmit capability " << capability << " not allowed.");
4917       return FALSE;
4918     }
4919   }
4920   else {
4921     if (!localCapabilities.IsAllowed(capability)) {
4922       PTRACE(2, "H323\tOnCreateLogicalChannel - receive capability " << capability << " not allowed.");
4923       return FALSE;
4924     }
4925   }
4926 
4927   // Check all running channels, and if new one can't run with it return FALSE
4928   for (PINDEX i = 0; i < logicalChannels->GetSize(); i++) {
4929     H323Channel * channel = logicalChannels->GetChannelAt(i);
4930     if (channel != NULL && channel->GetDirection() == dir) {
4931       if (dir != H323Channel::IsReceiver) {
4932         if (!remoteCapabilities.IsAllowed(capability, channel->GetCapability())) {
4933           PTRACE(2, "H323\tOnCreateLogicalChannel - transmit capability " << capability
4934                  << " and " << channel->GetCapability() << " incompatible.");
4935           return FALSE;
4936         }
4937       }
4938       else {
4939         if (!localCapabilities.IsAllowed(capability, channel->GetCapability())) {
4940           PTRACE(2, "H323\tOnCreateLogicalChannel - receive capability " << capability
4941                  << " and " << channel->GetCapability() << " incompatible.");
4942           return FALSE;
4943         }
4944       }
4945     }
4946   }
4947 
4948   return TRUE;
4949 }
4950 
4951 
OnStartLogicalChannel(H323Channel & channel)4952 PBoolean H323Connection::OnStartLogicalChannel(H323Channel & channel)
4953 {
4954   if (channel.GetSessionID() == OpalMediaFormat::DefaultAudioSessionID &&
4955       PIsDescendant(&channel, H323_RTPChannel)) {
4956     H323_RTPChannel & rtp = (H323_RTPChannel &)channel;
4957     if (channel.GetNumber().IsFromRemote()) {
4958       if (rfc2833InBandDTMF && rfc2833handler)
4959         rtp.AddFilter(rfc2833handler->GetReceiveHandler());
4960 
4961       if (detectInBandDTMF) {
4962         H323Codec * codec = channel.GetCodec();
4963         if (codec != NULL)
4964           codec->AddFilter(PCREATE_NOTIFIER(OnUserInputInBandDTMF));
4965       }
4966     }
4967     else if (rfc2833InBandDTMF && rfc2833handler)
4968       rtp.AddFilter(rfc2833handler->GetTransmitHandler());
4969   }
4970 
4971 #ifdef H323_H239
4972   if ((channel.GetCapability().GetMainType() == H323Capability::e_Video) &&
4973       (channel.GetCapability().GetSubType() == H245_VideoCapability::e_extendedVideoCapability)) {
4974           OnH239SessionStarted(channel.GetNumber(),
4975                 channel.GetNumber().IsFromRemote() ? H323Capability::e_Receive : H323Capability::e_Transmit);
4976   }
4977 #endif
4978 
4979   return endpoint.OnStartLogicalChannel(*this, channel);
4980 }
4981 
OnInitialFlowRestriction(H323Channel & channel)4982 PBoolean H323Connection::OnInitialFlowRestriction(H323Channel & channel)
4983 {
4984 #if H323_VIDEO
4985     if (channel.GetSessionID() == OpalMediaFormat::DefaultAudioSessionID)
4986          return true;
4987 
4988     if (!channel.GetNumber().IsFromRemote())
4989          return true;
4990 
4991     H323Codec * codec = channel.GetCodec();
4992     if (codec == NULL) return true;
4993 
4994     const OpalMediaFormat & fmt = codec->GetMediaFormat();
4995     unsigned maxBitRate = fmt.GetOptionInteger(OpalVideoFormat::MaxBitRateOption);
4996     unsigned targetBitRate = fmt.GetOptionInteger(OpalVideoFormat::TargetBitRateOption);
4997 
4998     if (targetBitRate < maxBitRate) {
4999         return SendLogicalChannelFlowControl(channel,targetBitRate/100);
5000     }
5001 #endif
5002     return true;
5003 }
5004 
5005 #ifdef H323_AUDIO_CODECS
OpenAudioChannel(PBoolean isEncoding,unsigned bufferSize,H323AudioCodec & codec)5006 PBoolean H323Connection::OpenAudioChannel(PBoolean isEncoding, unsigned bufferSize, H323AudioCodec & codec)
5007 {
5008 #ifdef H323_AEC
5009   if (endpoint.AECEnabled() && (aec == NULL)) {
5010     PTRACE(2, "H323\tCreating AEC instance.");
5011     int rate = codec.GetMediaFormat().GetTimeUnits() * 1000;
5012     aec = new H323Aec(rate, codec.GetMediaFormat().GetFrameTime(), endpoint.GetSoundChannelBufferDepth());
5013   }
5014    codec.AttachAEC(aec);
5015 #endif
5016 
5017   return endpoint.OpenAudioChannel(*this, isEncoding, bufferSize, codec);
5018 }
5019 #endif
5020 
5021 #ifdef H323_VIDEO
OpenVideoChannel(PBoolean isEncoding,H323VideoCodec & codec)5022 PBoolean H323Connection::OpenVideoChannel(PBoolean isEncoding, H323VideoCodec & codec)
5023 {
5024   return endpoint.OpenVideoChannel(*this, isEncoding, codec);
5025 }
5026 #endif // NO_H323_VIDEO
5027 
5028 
CloseLogicalChannel(unsigned number,PBoolean fromRemote)5029 void H323Connection::CloseLogicalChannel(unsigned number, PBoolean fromRemote)
5030 {
5031   if (connectionState != ShuttingDownConnection)
5032     logicalChannels->Close(number, fromRemote);
5033 }
5034 
5035 
CloseLogicalChannelNumber(const H323ChannelNumber & number)5036 void H323Connection::CloseLogicalChannelNumber(const H323ChannelNumber & number)
5037 {
5038   CloseLogicalChannel(number, number.IsFromRemote());
5039 }
5040 
5041 
CloseAllLogicalChannels(PBoolean fromRemote)5042 void H323Connection::CloseAllLogicalChannels(PBoolean fromRemote)
5043 {
5044   for (PINDEX i = 0; i < logicalChannels->GetSize(); i++) {
5045     H245NegLogicalChannel & negChannel = logicalChannels->GetNegLogicalChannelAt(i);
5046     H323Channel * channel = negChannel.GetChannel();
5047     if (channel != NULL && channel->GetNumber().IsFromRemote() == fromRemote)
5048       negChannel.Close();
5049   }
5050 }
5051 
5052 
OnClosingLogicalChannel(H323Channel &)5053 PBoolean H323Connection::OnClosingLogicalChannel(H323Channel & /*channel*/)
5054 {
5055   return TRUE;
5056 }
5057 
5058 
OnClosedLogicalChannel(const H323Channel & channel)5059 void H323Connection::OnClosedLogicalChannel(const H323Channel & channel)
5060 {
5061 #ifdef H323_H239
5062   if ((channel.GetCapability().GetMainType() == H323Capability::e_Video) &&
5063       (channel.GetCapability().GetSubType() == H245_VideoCapability::e_extendedVideoCapability)) {
5064           OnH239SessionEnded(channel.GetNumber(),
5065                 channel.GetNumber().IsFromRemote() ? H323Capability::e_Receive : H323Capability::e_Transmit);
5066   }
5067 #endif
5068 
5069   endpoint.OnClosedLogicalChannel(*this, channel);
5070 }
5071 
5072 
OnLogicalChannelFlowControl(H323Channel * channel,long bitRateRestriction)5073 void H323Connection::OnLogicalChannelFlowControl(H323Channel * channel,
5074                                                  long bitRateRestriction)
5075 {
5076   if (channel != NULL)
5077     channel->OnFlowControl(bitRateRestriction);
5078 }
5079 
SendLogicalChannelFlowControl(const H323Channel & channel,long restriction)5080 PBoolean H323Connection::SendLogicalChannelFlowControl(const H323Channel & channel,
5081                                                        long restriction)
5082 {
5083     H323ControlPDU pdu;
5084     H245_CommandMessage & command = pdu.Build(H245_CommandMessage::e_flowControlCommand);
5085     H245_FlowControlCommand & flowCommand = command;
5086 
5087     H245_FlowControlCommand_scope & scope = flowCommand.m_scope;
5088     scope.SetTag(H245_FlowControlCommand_scope::e_logicalChannelNumber);
5089     H245_LogicalChannelNumber & lc = scope;
5090     lc = channel.GetNumber();
5091 
5092     H245_FlowControlCommand_restriction & restrict = flowCommand.m_restriction;
5093     restrict.SetTag(H245_FlowControlCommand_restriction::e_maximumBitRate);
5094     PASN_Integer & bitRate = restrict;
5095     bitRate = restriction;
5096 
5097     return WriteControlPDU(pdu);
5098 }
5099 
OnLogicalChannelJitter(H323Channel * channel,DWORD jitter,int skippedFrameCount,int additionalBuffer)5100 void H323Connection::OnLogicalChannelJitter(H323Channel * channel,
5101                                             DWORD jitter,
5102                                             int skippedFrameCount,
5103                                             int additionalBuffer)
5104 {
5105   if (channel != NULL)
5106     channel->OnJitterIndication(jitter, skippedFrameCount, additionalBuffer);
5107 }
5108 
5109 
5110 // TODO: the bandwidth value returned here is wrong, usually, 1280
GetBandwidthUsed() const5111 unsigned H323Connection::GetBandwidthUsed() const
5112 {
5113   unsigned used = 0;
5114 
5115   for (PINDEX i = 0; i < logicalChannels->GetSize(); i++) {
5116     H323Channel * channel = logicalChannels->GetChannelAt(i);
5117     if (channel != NULL)
5118       used += channel->GetBandwidthUsed();
5119   }
5120 
5121   PTRACE(3, "H323\tBandwidth used: " << used);
5122 
5123   return used;
5124 }
5125 
5126 #ifdef H323_VIDEO
OnSetInitialBandwidth(H323VideoCodec * codec)5127 void H323Connection::OnSetInitialBandwidth(H323VideoCodec * codec)
5128 {
5129     endpoint.OnSetInitialBandwidth(codec);
5130 }
5131 #endif
5132 
UseBandwidth(unsigned bandwidth,PBoolean removing)5133 PBoolean H323Connection::UseBandwidth(unsigned bandwidth, PBoolean removing)
5134 {
5135   PTRACE(3, "H323\tBandwidth request: "
5136          << (removing ? '-' : '+')
5137          << bandwidth/10 << '.' << bandwidth%10
5138          << "kb/s, available: "
5139          << bandwidthAvailable/10 << '.' << bandwidthAvailable%10
5140          << "kb/s");
5141 
5142   if (removing)
5143     bandwidthAvailable += bandwidth;
5144   else {
5145     if (bandwidth > bandwidthAvailable) {
5146       PTRACE(2, "H323\tAvailable bandwidth exceeded");
5147       return FALSE;
5148     }
5149 
5150     bandwidthAvailable -= bandwidth;
5151   }
5152 
5153   return TRUE;
5154 }
5155 
5156 
SetBandwidthAvailable(unsigned newBandwidth,PBoolean force)5157 PBoolean H323Connection::SetBandwidthAvailable(unsigned newBandwidth, PBoolean force)
5158 {
5159   unsigned used = GetBandwidthUsed();
5160 
5161   if (!OnSetBandwidthAvailable(newBandwidth*100,used*100))
5162       return false;
5163 
5164   if (used > newBandwidth) {
5165     if (!force)
5166       return FALSE;
5167 
5168     // Go through logical channels and close down some.
5169     PINDEX chanIdx = logicalChannels->GetSize();
5170     while (used > newBandwidth && chanIdx-- > 0) {
5171       H323Channel * channel = logicalChannels->GetChannelAt(chanIdx);
5172       if (channel != NULL) {
5173         used -= channel->GetBandwidthUsed();
5174         CloseLogicalChannelNumber(channel->GetNumber());
5175       }
5176     }
5177   }
5178 
5179   bandwidthAvailable = newBandwidth - used;
5180 
5181   return true;
5182 }
5183 
OnSetBandwidthAvailable(unsigned,unsigned)5184 PBoolean H323Connection::OnSetBandwidthAvailable(unsigned /*newBandwidth*/, unsigned /*available*/)
5185 {
5186   return true;
5187 }
5188 
5189 
SetSendUserInputMode(SendUserInputModes mode)5190 void H323Connection::SetSendUserInputMode(SendUserInputModes mode)
5191 {
5192   PAssert(mode != SendUserInputAsSeparateRFC2833, PUnimplementedFunction);
5193 
5194   PTRACE(2, "H323\tSetting default User Input send mode to " << mode);
5195   sendUserInputMode = mode;
5196 }
5197 
5198 
CheckSendUserInputMode(const H323Capabilities & caps,H323Connection::SendUserInputModes mode)5199 static PBoolean CheckSendUserInputMode(const H323Capabilities & caps,
5200                                    H323Connection::SendUserInputModes mode)
5201 {
5202   // If have remote capabilities, then verify we can send selected mode,
5203   // otherwise just return and accept it for future validation
5204   static const H323_UserInputCapability::SubTypes types[H323Connection::NumSendUserInputModes] = {
5205     H323_UserInputCapability::NumSubTypes,
5206     H323_UserInputCapability::BasicString,
5207     H323_UserInputCapability::SignalToneH245,
5208     H323_UserInputCapability::SignalToneRFC2833
5209 #ifdef H323_H249
5210 //    H323_UserInputCapability::SignalToneSeperateRFC2833,  // Not implemented
5211    ,H323_UserInputCapability::H249A_Navigation,
5212     H323_UserInputCapability::H249B_Softkey,
5213     H323_UserInputCapability::H249C_PointDevice,
5214     H323_UserInputCapability::H249D_Modal,
5215     H323_UserInputCapability::NumSubTypes
5216 #endif
5217   };
5218 
5219   if (types[mode] == H323_UserInputCapability::NumSubTypes)
5220     return mode == H323Connection::SendUserInputAsQ931;
5221 
5222   return caps.FindCapability(H323_UserInputCapability::SubTypeNames[types[mode]]) != NULL;
5223 }
5224 
5225 
GetRealSendUserInputMode() const5226 H323Connection::SendUserInputModes H323Connection::GetRealSendUserInputMode() const
5227 {
5228   // If have not yet exchanged capabilities (ie not finished setting up the
5229   // H.245 channel) then the only thing we can do is Q.931
5230   if (!capabilityExchangeProcedure->HasReceivedCapabilities())
5231     return SendUserInputAsQ931;
5232 
5233   // First try recommended mode
5234   if (CheckSendUserInputMode(remoteCapabilities, sendUserInputMode))
5235     return sendUserInputMode;
5236 
5237   // Then try H.245 tones
5238   if (CheckSendUserInputMode(remoteCapabilities, SendUserInputAsTone))
5239     return SendUserInputAsTone;
5240 
5241   // Finally if is H.245 alphanumeric or does not indicate it could do other
5242   // modes we use H.245 alphanumeric as per spec.
5243   return SendUserInputAsString;
5244 }
5245 
5246 
SendUserInput(const PString & value)5247 void H323Connection::SendUserInput(const PString & value)
5248 {
5249   SendUserInputModes mode = GetRealSendUserInputMode();
5250 
5251   PTRACE(2, "H323\tSendUserInput(\"" << value << "\"), using mode " << mode);
5252   PINDEX i;
5253 
5254   switch (mode) {
5255     case SendUserInputAsQ931 :
5256       SendUserInputIndicationQ931(value);
5257       break;
5258 
5259     case SendUserInputAsString :
5260       SendUserInputIndicationString(value);
5261       break;
5262 
5263     case SendUserInputAsTone :
5264       for (i = 0; i < value.GetLength(); i++)
5265         SendUserInputIndicationTone(value[i]);
5266       break;
5267 
5268     case SendUserInputAsInlineRFC2833 :
5269       for (i = 0; i < value.GetLength(); i++)
5270         if (rfc2833handler) rfc2833handler->SendTone(value[i], 180);
5271       break;
5272 
5273     default :
5274       ;
5275   }
5276 }
5277 
5278 
OnUserInputString(const PString & value)5279 void H323Connection::OnUserInputString(const PString & value)
5280 {
5281   endpoint.OnUserInputString(*this, value);
5282 }
5283 
5284 
SendUserInputTone(char tone,unsigned duration,unsigned logicalChannel,unsigned rtpTimestamp)5285 void H323Connection::SendUserInputTone(char tone,
5286                                        unsigned duration,
5287                                        unsigned logicalChannel,
5288                                        unsigned rtpTimestamp)
5289 {
5290   SendUserInputModes mode = GetRealSendUserInputMode();
5291 
5292   PTRACE(2, "H323\tSendUserInputTone("
5293          << tone << ','
5294          << duration << ','
5295          << logicalChannel << ','
5296          << rtpTimestamp << "), using mode " << mode);
5297 
5298   switch (mode) {
5299     case SendUserInputAsQ931 :
5300       SendUserInputIndicationQ931(PString(tone));
5301       break;
5302 
5303     case SendUserInputAsString :
5304       SendUserInputIndicationString(PString(tone));
5305       break;
5306 
5307     case SendUserInputAsTone :
5308       SendUserInputIndicationTone(tone, duration, logicalChannel, rtpTimestamp);
5309       break;
5310 
5311     case SendUserInputAsInlineRFC2833 :
5312       if (rfc2833handler) rfc2833handler->SendTone(tone, duration);
5313       break;
5314 
5315     default :
5316       ;
5317   }
5318 }
5319 
5320 
OnUserInputTone(char tone,unsigned duration,unsigned logicalChannel,unsigned rtpTimestamp)5321 void H323Connection::OnUserInputTone(char tone,
5322                                      unsigned duration,
5323                                      unsigned logicalChannel,
5324                                      unsigned rtpTimestamp)
5325 {
5326   endpoint.OnUserInputTone(*this, tone, duration, logicalChannel, rtpTimestamp);
5327 }
5328 
5329 
SendUserInputIndicationQ931(const PString & value)5330 void H323Connection::SendUserInputIndicationQ931(const PString & value)
5331 {
5332   PTRACE(2, "H323\tSendUserInputIndicationQ931(\"" << value << "\")");
5333 
5334   H323SignalPDU pdu;
5335   pdu.BuildInformation(*this);
5336   pdu.GetQ931().SetKeypad(value);
5337   WriteSignalPDU(pdu);
5338 }
5339 
5340 
SendUserInputIndicationString(const PString & value)5341 void H323Connection::SendUserInputIndicationString(const PString & value)
5342 {
5343   PTRACE(2, "H323\tSendUserInputIndicationString(\"" << value << "\")");
5344 
5345   H323ControlPDU pdu;
5346   PASN_GeneralString & str = pdu.BuildUserInputIndication(value);
5347   if (!str.GetValue())
5348     WriteControlPDU(pdu);
5349   else {
5350     PTRACE(1, "H323\tInvalid characters for UserInputIndication");
5351   }
5352 }
5353 
5354 
SendUserInputIndicationTone(char tone,unsigned duration,unsigned logicalChannel,unsigned rtpTimestamp)5355 void H323Connection::SendUserInputIndicationTone(char tone,
5356                                                  unsigned duration,
5357                                                  unsigned logicalChannel,
5358                                                  unsigned rtpTimestamp)
5359 {
5360   PTRACE(2, "H323\tSendUserInputIndicationTone("
5361          << tone << ','
5362          << duration << ','
5363          << logicalChannel << ','
5364          << rtpTimestamp << ')');
5365 
5366   H323ControlPDU pdu;
5367   pdu.BuildUserInputIndication(tone, duration, logicalChannel, rtpTimestamp);
5368   WriteControlPDU(pdu);
5369 }
5370 
5371 #ifdef H323_H249
5372 
SendUserInputIndicationNavigate(H323_UserInputCapability::NavigateKeyID keyID)5373 void H323Connection::SendUserInputIndicationNavigate(H323_UserInputCapability::NavigateKeyID keyID)
5374 {
5375  if (!CheckSendUserInputMode(remoteCapabilities,SendUserInputAsNavigation))
5376      return;
5377 
5378   PTRACE(2, "H323\tSendUserInputIndicationNavigate(" << keyID << ')');
5379 
5380   H323ControlPDU pdu;
5381   H245_UserInputIndication & ind = pdu.Build(H245_IndicationMessage::e_userInput);
5382   ind.SetTag(H245_UserInputIndication::e_genericInformation);
5383   H245_ArrayOf_GenericInformation & infolist = ind;
5384 
5385   H245_GenericInformation * info =
5386              H323_UserInputCapability::BuildGenericIndication(H323_UserInputCapability::SubTypeOID[0]);
5387 
5388    info->IncludeOptionalField(H245_GenericMessage::e_messageContent);
5389    H245_ArrayOf_GenericParameter & contents = info->m_messageContent;
5390 
5391    H245_GenericParameter * content =
5392         H323_UserInputCapability::BuildGenericParameter(1,H245_ParameterValue::e_unsignedMin,keyID);
5393 
5394    contents.Append(content);
5395    contents.SetSize(contents.GetSize()+1);
5396 
5397   infolist.Append(info);
5398   infolist.SetSize(infolist.GetSize()+1);
5399   WriteControlPDU(pdu);
5400 }
5401 
SendUserInputIndicationSoftkey(unsigned key,const PString & keyName)5402 void H323Connection::SendUserInputIndicationSoftkey(unsigned key, const PString & keyName)
5403 {
5404  if (!CheckSendUserInputMode(remoteCapabilities,SendUserInputAsSoftkey))
5405      return;
5406 
5407   PTRACE(2, "H323\tSendUserInputIndicationSoftkey(" << key << ')');
5408 
5409   H323ControlPDU pdu;
5410   H245_UserInputIndication & ind = pdu.Build(H245_IndicationMessage::e_userInput);
5411   ind.SetTag(H245_UserInputIndication::e_genericInformation);
5412   H245_ArrayOf_GenericInformation & infolist = ind;
5413 
5414   H245_GenericInformation * info =
5415              H323_UserInputCapability::BuildGenericIndication(H323_UserInputCapability::SubTypeOID[1]);
5416 
5417    info->IncludeOptionalField(H245_GenericMessage::e_messageContent);
5418    H245_ArrayOf_GenericParameter & contents = info->m_messageContent;
5419 
5420    H245_GenericParameter * content =
5421         H323_UserInputCapability::BuildGenericParameter(2,H245_ParameterValue::e_unsignedMin,key);
5422     contents.Append(content);
5423     contents.SetSize(contents.GetSize()+1);
5424 
5425     if (keyName.GetLength() > 0) {
5426       H245_GenericParameter * contentstr =
5427          H323_UserInputCapability::BuildGenericParameter(1,H245_ParameterValue::e_octetString,keyName);
5428       contents.Append(contentstr);
5429       contents.SetSize(contents.GetSize()+1);
5430     }
5431 
5432   infolist.Append(info);
5433   infolist.SetSize(infolist.GetSize()+1);
5434   WriteControlPDU(pdu);
5435 }
5436 
SendUserInputIndicationPointDevice(unsigned x,unsigned y,unsigned button,unsigned buttonstate,unsigned clickcount)5437 void H323Connection::SendUserInputIndicationPointDevice(unsigned x, unsigned y, unsigned button,
5438                                                            unsigned buttonstate, unsigned clickcount)
5439 {
5440  if (!CheckSendUserInputMode(remoteCapabilities,SendUserInputAsPointDevice))
5441      return;
5442 
5443   PTRACE(6, "H323\tSendUserInputIndicationPointDevice");
5444 
5445   H323ControlPDU pdu;
5446   H245_UserInputIndication & ind = pdu.Build(H245_IndicationMessage::e_userInput);
5447   ind.SetTag(H245_UserInputIndication::e_genericInformation);
5448   H245_ArrayOf_GenericInformation & infolist = ind;
5449 
5450   H245_GenericInformation * info =
5451              H323_UserInputCapability::BuildGenericIndication(H323_UserInputCapability::SubTypeOID[2]);
5452 
5453    info->IncludeOptionalField(H245_GenericMessage::e_messageContent);
5454    H245_ArrayOf_GenericParameter & contents = info->m_messageContent;
5455 
5456 /// Add X and Y co-ords
5457     H245_GenericParameter * X =
5458         H323_UserInputCapability::BuildGenericParameter(1,H245_ParameterValue::e_unsignedMin,x);
5459     contents.Append(X);
5460     contents.SetSize(contents.GetSize()+1);
5461 
5462     H245_GenericParameter * Y =
5463         H323_UserInputCapability::BuildGenericParameter(2,H245_ParameterValue::e_unsignedMin,y);
5464     contents.Append(Y);
5465     contents.SetSize(contents.GetSize()+1);
5466 
5467 /// Optional values
5468     if (button > 0) {
5469       H245_GenericParameter * but =
5470         H323_UserInputCapability::BuildGenericParameter(3,H245_ParameterValue::e_unsignedMin,button);
5471       contents.Append(but);
5472       contents.SetSize(contents.GetSize()+1);
5473     }
5474 
5475     if (buttonstate > 0) {
5476       H245_GenericParameter * butstate =
5477         H323_UserInputCapability::BuildGenericParameter(4,H245_ParameterValue::e_unsignedMin,buttonstate);
5478       contents.Append(butstate);
5479       contents.SetSize(contents.GetSize()+1);
5480     }
5481 
5482     if (clickcount > 0) {
5483       H245_GenericParameter * cc =
5484         H323_UserInputCapability::BuildGenericParameter(5,H245_ParameterValue::e_unsignedMin,clickcount);
5485       contents.Append(cc);
5486       contents.SetSize(contents.GetSize()+1);
5487     }
5488 
5489   infolist.Append(info);
5490   infolist.SetSize(infolist.GetSize()+1);
5491   WriteControlPDU(pdu);
5492 }
5493 
SendUserInputIndicationModal()5494 void H323Connection::SendUserInputIndicationModal()
5495 {
5496  if (!CheckSendUserInputMode(remoteCapabilities,SendUserInputAsModal))
5497      return;
5498 
5499 }
5500 #endif
5501 
SendUserInputIndication(const H245_UserInputIndication & indication)5502 void H323Connection::SendUserInputIndication(const H245_UserInputIndication & indication)
5503 {
5504   H323ControlPDU pdu;
5505   H245_UserInputIndication & ind = pdu.Build(H245_IndicationMessage::e_userInput);
5506   ind = indication;
5507   WriteControlPDU(pdu);
5508 }
5509 
5510 
OnUserInputIndication(const H245_UserInputIndication & ind)5511 void H323Connection::OnUserInputIndication(const H245_UserInputIndication & ind)
5512 {
5513   switch (ind.GetTag()) {
5514     case H245_UserInputIndication::e_alphanumeric :
5515       OnUserInputString((const PASN_GeneralString &)ind);
5516       break;
5517 
5518     case H245_UserInputIndication::e_signal :
5519     {
5520       const H245_UserInputIndication_signal & sig = ind;
5521       OnUserInputTone(sig.m_signalType[0],
5522                       sig.HasOptionalField(H245_UserInputIndication_signal::e_duration)
5523                                 ? (unsigned)sig.m_duration : 0,
5524                       sig.m_rtp.m_logicalChannelNumber,
5525                       sig.m_rtp.m_timestamp);
5526       break;
5527     }
5528     case H245_UserInputIndication::e_signalUpdate :
5529     {
5530       const H245_UserInputIndication_signalUpdate & sig = ind;
5531       OnUserInputTone(' ', sig.m_duration, sig.m_rtp.m_logicalChannelNumber, 0);
5532       break;
5533     }
5534 #ifdef H323_H249
5535     case H245_UserInputIndication::e_genericInformation :
5536     {
5537       const H245_ArrayOf_GenericInformation & sig = ind;
5538       if ((sig.GetSize() > 0) &&
5539          sig[0].HasOptionalField(H245_GenericMessage::e_subMessageIdentifier)) {
5540            const H245_CapabilityIdentifier & id = sig[0].m_messageIdentifier;
5541            if (id.GetTag() == H245_CapabilityIdentifier::e_standard) {
5542                const PASN_ObjectId & gid = id;
5543                PString sid = gid.AsString();
5544                if (sid == H323_UserInputCapability::SubTypeOID[0]) {          // Navigation
5545                     OnUserInputIndicationNavigate(sig[0].m_messageContent);
5546                } else if (sid == H323_UserInputCapability::SubTypeOID[1]) {   // Softkey
5547                     OnUserInputIndicationSoftkey(sig[0].m_messageContent);
5548                } else if (sid == H323_UserInputCapability::SubTypeOID[2]) {   // PointingDevice
5549                     OnUserInputIndicationPointDevice(sig[0].m_messageContent);
5550                } else if (sid == H323_UserInputCapability::SubTypeOID[3]) {   // Mode interface
5551                     OnUserInputIndicationModal(sig[0].m_messageContent);
5552                }
5553            }
5554       }
5555     }
5556 #endif
5557   }
5558 }
5559 
5560 
OnUserInputInlineRFC2833(OpalRFC2833Info & info,H323_INT)5561 void H323Connection::OnUserInputInlineRFC2833(OpalRFC2833Info & info, H323_INT)
5562 {
5563   if (!info.IsToneStart())
5564     OnUserInputTone(info.GetTone(), info.GetDuration(), 0, info.GetTimestamp());
5565 }
5566 
5567 
OnUserInputInBandDTMF(H323Codec::FilterInfo & info,H323_INT)5568 void H323Connection::OnUserInputInBandDTMF(H323Codec::FilterInfo & info, H323_INT)
5569 {
5570   // This function is set up as an 'audio filter'.
5571   // This allows us to access the 16 bit PCM audio (at 8Khz sample rate)
5572   // before the audio is passed on to the sound card (or other output device)
5573 
5574 #ifdef P_DTMF
5575   // Pass the 16 bit PCM audio through the DTMF decoder
5576   dtmfTones = dtmfDecoder.Decode((short *)info.buffer, info.bufferLength/sizeof(short));
5577   if (!dtmfTones.IsEmpty()) {
5578     PTRACE(1, "DTMF detected. " << dtmfTones);
5579     for (PINDEX i = 0; i < dtmfTones.GetLength(); i++) {
5580 #if PTLIB_VER < 270
5581       OnUserInputTone(dtmfTones[i], 0, 0, 0);
5582 #else
5583       OnUserInputTone(dtmfTones[i], 0, 0, PDTMFDecoder::DetectTime);
5584 #endif
5585     }
5586   }
5587 #endif
5588 }
5589 
5590 #ifdef H323_H249
OnUserInputIndicationNavigate(const H245_ArrayOf_GenericParameter & contents)5591 void H323Connection::OnUserInputIndicationNavigate(const H245_ArrayOf_GenericParameter & contents)
5592 {
5593 }
5594 
OnUserInputIndicationSoftkey(const H245_ArrayOf_GenericParameter & contents)5595 void H323Connection::OnUserInputIndicationSoftkey(const H245_ArrayOf_GenericParameter & contents)
5596 {
5597 }
5598 
OnUserInputIndicationPointDevice(const H245_ArrayOf_GenericParameter & contents)5599 void H323Connection::OnUserInputIndicationPointDevice(const H245_ArrayOf_GenericParameter & contents)
5600 {
5601 }
5602 
OnUserInputIndicationModal(const H245_ArrayOf_GenericParameter & contents)5603 void H323Connection::OnUserInputIndicationModal(const H245_ArrayOf_GenericParameter & contents)
5604 {
5605 }
5606 #endif
5607 
GetSession(unsigned sessionID) const5608 RTP_Session * H323Connection::GetSession(unsigned sessionID) const
5609 {
5610   return rtpSessions.GetSession(sessionID);
5611 }
5612 
5613 
GetSessionCallbacks(unsigned sessionID) const5614 H323_RTP_Session * H323Connection::GetSessionCallbacks(unsigned sessionID) const
5615 {
5616   RTP_Session * session = rtpSessions.GetSession(sessionID);
5617   if (session == NULL)
5618     return NULL;
5619 
5620   PTRACE(3, "RTP\tFound existing session " << sessionID);
5621   PObject * data = session->GetUserData();
5622   PAssert(PIsDescendant(data, H323_RTP_Session), PInvalidCast);
5623   return (H323_RTP_Session *)data;
5624 }
5625 
5626 
UseSession(unsigned sessionID,const H245_TransportAddress & taddr,H323Channel::Directions dir,RTP_QOS * rtpqos)5627 RTP_Session * H323Connection::UseSession(unsigned sessionID,
5628                                          const H245_TransportAddress & taddr,
5629                                                    H323Channel::Directions dir,
5630                                          RTP_QOS * rtpqos)
5631 {
5632   // We only support unicast IP at this time.
5633   if (taddr.GetTag() != H245_TransportAddress::e_unicastAddress) {
5634     return NULL;
5635   }
5636 
5637   // We must have a valid sessionID  H.239 sometimes negotiates 0
5638   if (sessionID > 255)
5639       return NULL;
5640 
5641   const H245_UnicastAddress & uaddr = taddr;
5642   if (uaddr.GetTag() != H245_UnicastAddress::e_iPAddress
5643 #ifdef H323_IPV6
5644         && uaddr.GetTag() != H245_UnicastAddress::e_iP6Address
5645 #endif
5646      ) {
5647     return NULL;
5648   }
5649 
5650   RTP_Session * session = rtpSessions.UseSession(sessionID);
5651   if (session != NULL) {
5652     ((RTP_UDP *) session)->Reopen(dir == H323Channel::IsReceiver);
5653     return session;
5654   }
5655 
5656   RTP_UDP * udp_session = new RTP_UDP(
5657 #ifdef H323_RTP_AGGREGATE
5658                   useRTPAggregation ? endpoint.GetRTPAggregator() : NULL,
5659 #endif
5660                   sessionID, remoteIsNAT
5661 #ifdef H323_H46026
5662                   , m_H46026enabled
5663 #endif
5664                   );
5665 
5666   udp_session->SetUserData(new H323_RTP_UDP(*this, *udp_session, rtpqos));
5667   rtpSessions.AddSession(udp_session);
5668   return udp_session;
5669 }
5670 
OnHandleH245GenericMessage(h245MessageType type,const H245_GenericMessage & pdu)5671 PBoolean H323Connection::OnHandleH245GenericMessage(h245MessageType type, const H245_GenericMessage & pdu)
5672 {
5673     //if (!pdu.HasOptionalField(H245_GenericMessage::e_subMessageIdentifier)) {
5674     //    PTRACE(2,"H323\tUnIdentified Generic Message Received!");
5675     //    return false;
5676     //}
5677 
5678     PString guid = PString();
5679     const H245_CapabilityIdentifier & id = pdu.m_messageIdentifier;
5680 
5681     if (id.GetTag() == H245_CapabilityIdentifier::e_standard) {
5682               const PASN_ObjectId & gid = id;
5683               guid = gid.AsString();
5684     }
5685     else if (id.GetTag() == H245_CapabilityIdentifier::e_h221NonStandard) {
5686         PTRACE(2,"H323\tUnknown NonStandard Generic Message Received!");
5687               return false;
5688     }
5689     else if (id.GetTag() == H245_CapabilityIdentifier::e_uuid) {
5690               const PASN_OctetString & gid = id;
5691               guid = gid.AsString();
5692     }
5693     else if (id.GetTag() == H245_CapabilityIdentifier::e_domainBased) {
5694               const PASN_IA5String & gid = id;
5695               guid = gid;
5696     }
5697 
5698     if (pdu.HasOptionalField(H245_GenericMessage::e_messageContent))
5699         return OnReceivedGenericMessage(type,guid,pdu.m_messageContent);
5700     else
5701         return OnReceivedGenericMessage(type,guid);
5702 }
5703 
5704 
5705 #ifdef H323_H46024A
5706 
ReceivedH46024AMessage(bool toStart)5707 PBoolean H323Connection::ReceivedH46024AMessage(bool toStart)
5708 {
5709     if (m_H46024Astate < 3) {
5710         if (m_H46024Ainitator && !toStart) {
5711             PTRACE(4,"H46024A\tCONFLICT: wait for Media initiate Indication");
5712             return true;
5713         }
5714 
5715         PTRACE(4,"H46024A\tReceived Indication to " << (toStart ? "initiate" : "wait for") << " direct connection");
5716 
5717             if (m_H46024Astate == 0)                // We are the receiver
5718                 m_H46024Astate = (toStart ? 2 : 1);
5719 
5720             for (std::map<unsigned,NAT_Sockets>::const_iterator r = m_NATSockets.begin(); r != m_NATSockets.end(); ++r) {
5721                 NAT_Sockets sockets = r->second;
5722                 ((H46019UDPSocket *)sockets.rtp)->H46024Adirect(toStart);
5723                 ((H46019UDPSocket *)sockets.rtcp)->H46024Adirect(toStart);
5724             }
5725     //    }
5726 
5727         if (!toStart) {
5728             PTRACE(4,"H46024A\tReply for remote to " << (!toStart ? "initiate" : "wait for") << " direct connection");
5729             SendH46024AMessage(!toStart);
5730         }
5731        m_H46024Astate = 3;
5732    }
5733     return true;
5734 }
5735 
GetUnsignedGenericMessage(unsigned id,const H245_ArrayOf_GenericParameter & params,unsigned & val)5736 bool GetUnsignedGenericMessage(unsigned id, const H245_ArrayOf_GenericParameter & params, unsigned & val)
5737 {
5738    for (PINDEX i=0; i < params.GetSize(); i++)
5739    {
5740       const H245_GenericParameter & param = params[i];
5741       const H245_ParameterIdentifier & idm = param.m_parameterIdentifier;
5742       if (idm.GetTag() == H245_ParameterIdentifier::e_standard) {
5743           const PASN_Integer & idx = idm;
5744           if (idx == id) {
5745              const H245_ParameterValue & genvalue = params[i].m_parameterValue;
5746              if ((genvalue.GetTag() == H245_ParameterValue::e_unsignedMin) ||
5747                 (genvalue.GetTag() == H245_ParameterValue::e_unsignedMax) ||
5748                 (genvalue.GetTag() == H245_ParameterValue::e_unsigned32Min) ||
5749                 (genvalue.GetTag() == H245_ParameterValue::e_unsigned32Max)) {
5750                     const PASN_Integer & xval = genvalue;
5751                     val = xval;
5752                     return true;
5753              }
5754           }
5755       }
5756    }
5757     PTRACE(4,"H46024A\tError finding Transport parameter " << id);
5758     return false;
5759 }
5760 
GetStringGenericOctetString(unsigned id,const H245_ArrayOf_GenericParameter & params,PString & str)5761 bool GetStringGenericOctetString(unsigned id, const H245_ArrayOf_GenericParameter & params, PString & str)
5762 {
5763     for (PINDEX i = 0; i < params.GetSize(); i++) {
5764         const H245_GenericParameter & param = params[i];
5765         const H245_ParameterIdentifier & idm = param.m_parameterIdentifier;
5766         if (idm.GetTag() == H245_ParameterIdentifier::e_standard) {
5767             const PASN_Integer & idx = idm;
5768             if (idx == id) {
5769                 const H245_ParameterValue & genvalue = params[i].m_parameterValue;
5770                 if (genvalue.GetTag() == H245_ParameterValue::e_octetString) {
5771                     const PASN_OctetString & valg = genvalue;
5772                     PASN_IA5String data;
5773                     if (valg.DecodeSubType(data)) {
5774                         str = data;
5775                         return true;
5776                     }
5777                 }
5778             }
5779         }
5780     }
5781     PTRACE(4,"H46024A\tError finding String parameter " << id);
5782     return false;
5783 }
5784 
GetUnsignedGeneric(unsigned id,const H245_ArrayOf_GenericParameter & params,unsigned & num)5785 bool GetUnsignedGeneric(unsigned id, const H245_ArrayOf_GenericParameter & params, unsigned & num)
5786 {
5787    for (PINDEX i=0; i < params.GetSize(); i++)
5788    {
5789       const H245_GenericParameter & param = params[i];
5790       const H245_ParameterIdentifier & idm = param.m_parameterIdentifier;
5791       if (idm.GetTag() == H245_ParameterIdentifier::e_standard) {
5792          const PASN_Integer & idx = idm;
5793           if (idx == id) {
5794              const H245_ParameterValue & genvalue = params[i].m_parameterValue;
5795              if (genvalue.GetTag() == H245_ParameterValue::e_unsigned32Min) {
5796                    const PASN_Integer & valg = genvalue;
5797                    num = valg;
5798                    return true;
5799              }
5800          }
5801       }
5802    }
5803     PTRACE(4,"H46024A\tError finding unsigned parameter " << id);
5804     return false;
5805 }
5806 
GetTransportGenericOctetString(unsigned id,const H245_ArrayOf_GenericParameter & params,H323TransportAddress & str)5807 bool GetTransportGenericOctetString(unsigned id, const H245_ArrayOf_GenericParameter & params, H323TransportAddress & str)
5808 {
5809     for (PINDEX i = 0; i < params.GetSize(); i++) {
5810         const H245_GenericParameter & param = params[i];
5811         const H245_ParameterIdentifier & idm = param.m_parameterIdentifier;
5812         if (idm.GetTag() == H245_ParameterIdentifier::e_standard) {
5813             const PASN_Integer & idx = idm;
5814             if (idx == id) {
5815                 const H245_ParameterValue & genvalue = params[i].m_parameterValue;
5816                 if (genvalue.GetTag() == H245_ParameterValue::e_octetString) {
5817                     const PASN_OctetString & valg = genvalue;
5818                     H245_TransportAddress addr;
5819                     if (valg.DecodeSubType(addr)) {
5820                         str = H323TransportAddress(addr);
5821                         return true;
5822                     }
5823                 }
5824             }
5825         }
5826     }
5827     return false;
5828 }
5829 
BuildGenericOctetString(H245_GenericParameter & param,unsigned id,const PASN_Object & data)5830 H245_GenericParameter & BuildGenericOctetString(H245_GenericParameter & param, unsigned id, const PASN_Object & data)
5831 {
5832      H245_ParameterIdentifier & idm = param.m_parameterIdentifier;
5833          idm.SetTag(H245_ParameterIdentifier::e_standard);
5834          PASN_Integer & idx = idm;
5835          idx = id;
5836          H245_ParameterValue & genvalue = param.m_parameterValue;
5837          genvalue.SetTag(H245_ParameterValue::e_octetString);
5838          PASN_OctetString & valg = genvalue;
5839          valg.EncodeSubType(data);
5840     return param;
5841 }
5842 
BuildGenericOctetString(H245_GenericParameter & param,unsigned id,const H323TransportAddress & transport)5843 H245_GenericParameter & BuildGenericOctetString(H245_GenericParameter & param, unsigned id, const H323TransportAddress & transport)
5844 {
5845     H245_TransportAddress data;
5846     transport.SetPDU(data);
5847     return BuildGenericOctetString(param, id, data);
5848 }
5849 
BuildGenericInteger(H245_GenericParameter & param,unsigned id,unsigned val)5850 H245_GenericParameter & BuildGenericInteger(H245_GenericParameter & param, unsigned id, unsigned val)
5851 {
5852      H245_ParameterIdentifier & idm = param.m_parameterIdentifier;
5853          idm.SetTag(H245_ParameterIdentifier::e_standard);
5854          PASN_Integer & idx = idm;
5855          idx = id;
5856          H245_ParameterValue & genvalue = param.m_parameterValue;
5857          genvalue.SetTag(H245_ParameterValue::e_unsignedMin);
5858          PASN_Integer & xval = genvalue;
5859          xval = val;
5860     return param;
5861 }
5862 
BuildGenericUnsigned(H245_GenericParameter & param,unsigned id,unsigned val)5863 H245_GenericParameter & BuildGenericUnsigned(H245_GenericParameter & param, unsigned id, unsigned val)
5864 {
5865      H245_ParameterIdentifier & idm = param.m_parameterIdentifier;
5866          idm.SetTag(H245_ParameterIdentifier::e_standard);
5867          PASN_Integer & idx = idm;
5868          idx = id;
5869          H245_ParameterValue & genvalue = param.m_parameterValue;
5870          genvalue.SetTag(H245_ParameterValue::e_unsigned32Min);
5871          PASN_Integer & xval = genvalue;
5872          xval = val;
5873     return param;
5874 }
5875 
BuildH46024AIndication(H323ControlPDU & pdu,const PString & oid,bool sender)5876 void BuildH46024AIndication(H323ControlPDU & pdu, const PString & oid, bool sender)
5877 {
5878       H245_GenericMessage & cap = pdu.Build(H245_IndicationMessage::e_genericIndication);
5879   //    cap.IncludeOptionalField(H245_GenericMessage::e_subMessageIdentifier);
5880       H245_CapabilityIdentifier & id = cap.m_messageIdentifier;
5881       id.SetTag(H245_CapabilityIdentifier::e_standard);
5882       PASN_ObjectId & gid = id;
5883       gid.SetValue(oid);
5884     // Indicate whether remote can start channel. // standard does specify who starts - SH
5885       //cap.IncludeOptionalField(H245_GenericMessage::e_messageContent);
5886       //H245_ArrayOf_GenericParameter & data = cap.m_messageContent;
5887       //data.SetSize(1);
5888       //BuildGenericInteger(data[0], 0, (sender ? 1 : 0));
5889 }
5890 #endif // H323_H46024A
5891 
5892 #ifdef H323_H46024B
DecodeH46024BRequest(unsigned id,const H245_ArrayOf_GenericParameter & params,H46024B_ArrayOf_AlternateAddress & val)5893 bool DecodeH46024BRequest(unsigned id, const H245_ArrayOf_GenericParameter & params, H46024B_ArrayOf_AlternateAddress & val)
5894 {
5895    for (PINDEX i=0; i < params.GetSize(); i++)
5896    {
5897       const H245_GenericParameter & param = params[i];
5898       const H245_ParameterIdentifier & idm = param.m_parameterIdentifier;
5899       if (idm.GetTag() == H245_ParameterIdentifier::e_standard) {
5900           const PASN_Integer & idx = idm;
5901           if (idx == id) {
5902              const H245_ParameterValue & genvalue = params[i].m_parameterValue;
5903              if (genvalue.GetTag() == H245_ParameterValue::e_octetString) {
5904                     const PASN_OctetString & xval = genvalue;
5905                     if (xval.DecodeSubType(val))
5906                       return true;
5907              }
5908           }
5909       }
5910    }
5911    PTRACE(4,"H46024B\tError finding H46024BRequest " << id);
5912    return false;
5913 }
5914 
BuildH46024BResponse(H323ControlPDU & pdu)5915 void BuildH46024BResponse(H323ControlPDU & pdu)
5916 {
5917     H245_GenericMessage & cap = pdu.Build(H245_ResponseMessage::e_genericResponse);
5918       H245_CapabilityIdentifier & id = cap.m_messageIdentifier;
5919       id.SetTag(H245_CapabilityIdentifier::e_standard);
5920       PASN_ObjectId & gid = id;
5921       gid.SetValue(H46024BOID);
5922 
5923       cap.IncludeOptionalField(H245_GenericMessage::e_subMessageIdentifier);
5924       PASN_Integer & num = cap.m_subMessageIdentifier;
5925       num = 1;
5926 
5927 }
5928 
BuildH46024BIndication(H323ControlPDU & pdu)5929 void BuildH46024BIndication(H323ControlPDU & pdu)
5930 {
5931     H245_GenericMessage & cap = pdu.Build(H245_IndicationMessage::e_genericIndication);
5932       H245_CapabilityIdentifier & id = cap.m_messageIdentifier;
5933       id.SetTag(H245_CapabilityIdentifier::e_standard);
5934       PASN_ObjectId & gid = id;
5935       gid.SetValue(H46024BOID);
5936 }
5937 
5938 #endif  // H323_H46024B
5939 
5940 #ifdef H323_H46024A
SendH46024AMessage(bool sender)5941 PBoolean H323Connection::SendH46024AMessage(bool sender)
5942 {
5943     if ((sender && m_H46024Astate == 2) ||  // Message already sent
5944         (!sender && m_H46024Astate == 1))    // Message already sent
5945                 return false;
5946 
5947     m_H46024Ainitator = sender;
5948     if (m_H46024Astate == 0)                // We are instigator
5949         m_H46024Astate = (sender ? 2 : 1);
5950 
5951     PTRACE(4,"H46024A\tSending Control DirectMedia " << (sender ? "Wait" : "Initiate"));
5952 
5953     H323ControlPDU pdu;
5954     BuildH46024AIndication(pdu,H46024AOID,sender);
5955     return WriteControlPDU(pdu);
5956 }
5957 
5958 #endif
5959 
OnReceivedGenericMessage(h245MessageType type,const PString & id)5960 PBoolean H323Connection::OnReceivedGenericMessage(h245MessageType type, const PString & id )
5961 {
5962 #ifdef H323_H46024A
5963     if (id == H46024AOID && type == h245indication) {
5964         PTRACE(4,"H46024A\tReceived Generic Message.");
5965         return ReceivedH46024AMessage(m_H46024Ainitator);
5966     }
5967 #endif
5968 #ifdef H323_H46024B
5969     if (id == H46024BOID && type == h245response) {
5970         PTRACE(4,"H46024B\tReceived Generic Response.");
5971         return true;
5972     }
5973 #endif
5974     return false;
5975 }
5976 
OnReceivedGenericMessage(h245MessageType type,const PString & id,const H245_ArrayOf_GenericParameter & content)5977 PBoolean H323Connection::OnReceivedGenericMessage(h245MessageType type, const PString & id, const H245_ArrayOf_GenericParameter & content)
5978 {
5979 #ifdef H323_H46024A
5980     if (id == H46024AOID && type == h245indication) {
5981         PTRACE(4,"H46024A\tReceived Generic Indication.");
5982           //  unsigned start=0;
5983           //  if (GetUnsignedGenericMessage(0,content,start))
5984                 return ReceivedH46024AMessage(m_H46024Ainitator);
5985     }
5986 #endif
5987 
5988 #ifdef H323_H46024B
5989     if (id == H46024BOID && type == h245request) {
5990         H46024B_ArrayOf_AlternateAddress address;
5991         if (DecodeH46024BRequest(1, content, address)) {
5992             PTRACE(4,"H46024B\tReceived\n" << address);
5993             for (PINDEX i=0; i < address.GetSize(); ++i) {
5994                 unsigned muxID = 0;
5995                 if (address[i].HasOptionalField(H46024B_AlternateAddress::e_multiplexID))
5996                       muxID = address[i].m_multiplexID;
5997                 std::map<unsigned,NAT_Sockets>::const_iterator sockets_iter = m_NATSockets.find(address[i].m_sessionID);
5998                     if (sockets_iter != m_NATSockets.end()) {
5999                         NAT_Sockets sockets = sockets_iter->second;
6000                         if (address[i].HasOptionalField(H46024B_AlternateAddress::e_rtpAddress)) {
6001                             H323TransportAddress add = H323TransportAddress(address[i].m_rtpAddress);
6002                             ((H46019UDPSocket *)sockets.rtp)->H46024Bdirect(add,muxID);
6003                         }
6004                     }
6005             }
6006             H323ControlPDU pdu;
6007             BuildH46024BResponse(pdu);
6008             return WriteControlPDU(pdu);
6009         }
6010     }
6011 #endif
6012 
6013 #ifdef H323_H239
6014    if (id == OpalPluginCodec_Identifer_H239_GenericMessage) {
6015      H239Control * ctrl = (H239Control *)remoteCapabilities.FindCapability("H.239 Control");
6016      if (!ctrl) return false;
6017 
6018      switch (type) {
6019         case h245request:
6020             return ctrl->HandleGenericMessage(H239Control::e_h245request,this, &content);
6021         case h245response:
6022             return ctrl->HandleGenericMessage(H239Control::e_h245response,this, &content);
6023         case h245command:
6024             return ctrl->HandleGenericMessage(H239Control::e_h245command,this, &content);
6025         case h245indication:
6026             return ctrl->HandleGenericMessage(H239Control::e_h245indication,this, &content);
6027      }
6028    }
6029 #endif
6030     return false;
6031 }
6032 
6033 #ifdef H323_H239
SendH239GenericResponse(PBoolean response)6034 PBoolean H323Connection::SendH239GenericResponse(PBoolean response)
6035 {
6036    H239Control * ctrl = (H239Control *)remoteCapabilities.FindCapability("H.239 Control");
6037    if (ctrl)
6038        return ctrl->SendGenericMessage(H239Control::e_h245response,this,response);
6039 
6040    return false;
6041 }
6042 
GetLogicalChannels()6043 H245NegLogicalChannels * H323Connection::GetLogicalChannels()
6044 {
6045     return logicalChannels;
6046 }
6047 #endif
6048 
OnReceiveOLCGenericInformation(unsigned sessionID,const H245_ArrayOf_GenericInformation & alternate,PBoolean isAck) const6049 PBoolean H323Connection::OnReceiveOLCGenericInformation(unsigned sessionID,
6050                         const H245_ArrayOf_GenericInformation & alternate,
6051                         PBoolean isAck
6052                         ) const
6053 {
6054     PBoolean success = false;
6055 
6056 #ifdef H323_H460
6057         PTRACE(4,"Handling Generic OLC Session " << sessionID );
6058         for (PINDEX i=0; i<alternate.GetSize(); i++) {
6059           const H245_GenericInformation & info = alternate[i];
6060           const H245_CapabilityIdentifier & id = info.m_messageIdentifier;
6061           if (id.GetTag() != H245_CapabilityIdentifier::e_standard)
6062               break;
6063 
6064 #ifdef H323_H46018
6065             const PASN_ObjectId & oid = id;
6066             const H245_ArrayOf_GenericParameter & msg = info.m_messageContent;
6067             if (m_H46019enabled && (oid.AsString() == H46019OID) && msg.GetSize() > 0) {
6068                 H245_GenericParameter & val = msg[0];
6069                  if (val.m_parameterValue.GetTag() != H245_ParameterValue::e_octetString)
6070                      break;
6071 
6072                     PASN_OctetString & raw = val.m_parameterValue;
6073                     PPER_Stream pdu(raw);
6074                     H46019_TraversalParameters params;
6075                     if (!params.Decode(pdu)) {
6076                         PTRACE(2,"H46019\tError decoding Traversal Parameters!");
6077                         break;
6078                     }
6079 
6080                   PTRACE(4,"H46019\tTraversal Parameters: Rec'd Session " << sessionID
6081                                << " " << (isAck ? "OLCack" : "OLC")  << "\n" << params);
6082 #ifdef H323_H46019M
6083                   H323TransportAddress multiRTPaddress;
6084                   H323TransportAddress multiRTCPaddress;
6085                   unsigned             multiID=0;
6086 
6087                     if (params.HasOptionalField(H46019_TraversalParameters::e_multiplexedMediaChannel)) {
6088                         H245_TransportAddress & mRTP = params.m_multiplexedMediaChannel;
6089                         multiRTPaddress = H323TransportAddress(mRTP);
6090                     }
6091 
6092                     if (params.HasOptionalField(H46019_TraversalParameters::e_multiplexedMediaControlChannel)) {
6093                         H245_TransportAddress & mRTCP = params.m_multiplexedMediaControlChannel;
6094                         multiRTCPaddress = H323TransportAddress(mRTCP);
6095                     }
6096 
6097                     if (params.HasOptionalField(H46019_TraversalParameters::e_multiplexID)) {
6098                         PASN_Integer & mID = params.m_multiplexID;
6099                         multiID = mID;
6100                     }
6101 
6102                     if (!m_H46019multiplex && multiID > 0) {
6103                         PTRACE(2,"H46019\tMultiplex remote detected. To send Multiplexed!");
6104                     }
6105 #endif
6106 
6107                     H323TransportAddress RTPaddress;
6108                     H323TransportAddress RTCPaddress;
6109                     bool keepAliveAddress = false;
6110                     if (params.HasOptionalField(H46019_TraversalParameters::e_keepAliveChannel)) {
6111                         H245_TransportAddress & k = params.m_keepAliveChannel;
6112                         RTPaddress = H323TransportAddress(k);
6113                         PIPSocket::Address add; WORD port = 0;
6114                         RTPaddress.GetIpAndPort(add,port);
6115                         RTCPaddress = H323TransportAddress(add,port+1);  // Compute the RTCP Address
6116                         keepAliveAddress = true;
6117                     }
6118 
6119                     unsigned payload = 0;
6120                     if (params.HasOptionalField(H46019_TraversalParameters::e_keepAlivePayloadType)) {
6121                         PASN_Integer & p = params.m_keepAlivePayloadType;
6122                         payload = p;
6123                     }
6124 
6125                     unsigned ttl = 0;
6126                     if (params.HasOptionalField(H46019_TraversalParameters::e_keepAliveInterval)) {
6127                         H225_TimeToLive & a = params.m_keepAliveInterval;
6128                         ttl = a;
6129                     }
6130 
6131                     std::map<unsigned,NAT_Sockets>::const_iterator sockets_iter = m_NATSockets.find(sessionID);
6132                         if (sockets_iter != m_NATSockets.end()) {
6133                             NAT_Sockets sockets = sockets_iter->second;
6134 #ifdef H323_H46019M
6135                             if (multiID > 0) {
6136                                ((H46019UDPSocket *)sockets.rtp)->SetMultiplexID(multiID, isAck);
6137                                ((H46019UDPSocket *)sockets.rtcp)->SetMultiplexID(multiID, isAck);
6138                                if (keepAliveAddress) {
6139                                    PIPSocket::Address multiAddr;
6140                                    multiRTPaddress.GetIpAddress(multiAddr);    // Sanity check....
6141                                    if (!multiAddr.IsValid() || multiAddr.IsAny()|| multiAddr.IsLoopback()) {
6142                                       PTRACE(2,"H46019M\tInvalid Multiplex Address! Use Keepalive Address");
6143                                       multiRTPaddress = RTPaddress;
6144                                       multiRTCPaddress = RTCPaddress;
6145                                    }
6146                                   ((H46019UDPSocket *)sockets.rtp)->Activate(multiRTPaddress,payload,ttl);
6147                                   ((H46019UDPSocket *)sockets.rtcp)->Activate(multiRTCPaddress,payload,ttl);
6148                                }
6149                             } else
6150 #endif
6151                             {
6152                               if (keepAliveAddress) {
6153                                 ((H46019UDPSocket *)sockets.rtp)->Activate(RTPaddress,payload,ttl);
6154                                 ((H46019UDPSocket *)sockets.rtcp)->Activate(RTCPaddress,payload,ttl);
6155                               }
6156                             }
6157                         }
6158                  success = true;
6159             }
6160 #ifdef H323_H46024A
6161             if (m_H46024Aenabled && (oid.AsString() == H46024AOID)) {
6162                 PTRACE(4,"H46024A\tAlt Port Info:\n" << msg);
6163                 PString m_CUI = PString();  H323TransportAddress m_altAddr1, m_altAddr2; unsigned m_altMuxID=0;
6164                 bool error = false;
6165                 if (!GetStringGenericOctetString(0,msg,m_CUI))  error = true;
6166                 if (!GetTransportGenericOctetString(1,msg,m_altAddr1))  error = true;
6167                 if (!GetTransportGenericOctetString(2,msg,m_altAddr2))  error = true;
6168                 GetUnsignedGeneric(3,msg,m_altMuxID);
6169 
6170                 if (!error) {
6171                     std::map<unsigned,NAT_Sockets>::const_iterator sockets_iter = m_NATSockets.find(sessionID);
6172                         if (sockets_iter != m_NATSockets.end()) {
6173                             NAT_Sockets sockets = sockets_iter->second;
6174                             ((H46019UDPSocket *)sockets.rtp)->SetAlternateAddresses(m_altAddr1,m_CUI,m_altMuxID);
6175                             ((H46019UDPSocket *)sockets.rtcp)->SetAlternateAddresses(m_altAddr2,m_CUI,m_altMuxID);
6176                             success = true;
6177                         }
6178                 }
6179             }
6180 #endif
6181 #endif  // H323_H46018
6182         }
6183 
6184 #endif  // H323_H460
6185     return success;
6186 }
6187 
OnSendingOLCGenericInformation(const unsigned & sessionID,H245_ArrayOf_GenericInformation & generic,PBoolean isAck) const6188 PBoolean H323Connection::OnSendingOLCGenericInformation(const unsigned & sessionID,
6189                 H245_ArrayOf_GenericInformation & generic, PBoolean isAck) const
6190 {
6191 #ifdef H323_H46018
6192     PTRACE(4,"Set Generic " << (isAck ? "OLCack" : "OLC") << " Session " << sessionID );
6193     if (m_H46019enabled) {
6194         unsigned payload=0; unsigned ttl=0; //H323TransportAddress m_keepAlive;
6195 #ifdef H323_H46019M
6196         H323TransportAddress m_multiRTPAddress, m_multiRTCPAddress;
6197         unsigned multiID=0;
6198 #endif
6199 #ifdef H323_H46024A
6200         PString m_cui = PString();
6201         H323TransportAddress m_altAddr1, m_altAddr2;
6202         unsigned m_altMuxID=0;
6203 #endif
6204         std::map<unsigned,NAT_Sockets>::const_iterator sockets_iter = m_NATSockets.find(sessionID);
6205             if (sockets_iter != m_NATSockets.end()) {
6206                 NAT_Sockets sockets = sockets_iter->second;
6207                 H46019UDPSocket * rtp = ((H46019UDPSocket *)sockets.rtp);
6208                 H46019UDPSocket * rtcp = ((H46019UDPSocket *)sockets.rtcp);
6209                 if (rtp->GetPingPayload() == 0)
6210                     rtp->SetPingPayLoad(defH46019payload);
6211                 payload = rtp->GetPingPayload();
6212 
6213                 if (rtp->GetTTL() == 0)
6214                     rtp->SetTTL(ttl);
6215                 ttl = rtp->GetTTL();
6216 
6217                 // Traversal Clients do not need to send a keepalive address
6218                 // ToDo Server implementation  - SH
6219                 //PIPSocket::Address addr;  WORD port=0;
6220                 //if (rtp->GetLocalAddress(addr,port)) {
6221                 //   m_keepAlive = H323TransportAddress(addr,port);
6222                 //}
6223 #ifdef H323_H46019M
6224                 if (/*!isAck &&*/ m_H46019multiplex) {
6225                    rtp->GetMultiplexAddress(m_multiRTPAddress,multiID, isAck);
6226                    rtcp->GetMultiplexAddress(m_multiRTCPAddress,multiID, isAck);
6227                 }
6228 #endif
6229                 if (isAck) {
6230                     rtp->Activate();  // Start the RTP Channel if not already started
6231                     rtcp->Activate();  // Start the RTCP Channel if not already started
6232                 }
6233 #ifdef H323_H46024A
6234               if (m_H46024Aenabled) {
6235                 rtp->GetAlternateAddresses(m_altAddr1,m_cui, m_altMuxID);
6236                 rtcp->GetAlternateAddresses(m_altAddr2,m_cui, m_altMuxID);
6237               }
6238 #endif
6239             } else {
6240                 PTRACE(4,"H46019\tERROR NAT Socket not found for " << sessionID << " ABORTING!" );
6241                 return false;
6242             }
6243 
6244           H245_GenericInformation info;
6245           H245_CapabilityIdentifier & id = info.m_messageIdentifier;
6246             id.SetTag(H245_CapabilityIdentifier::e_standard);
6247             PASN_ObjectId & oid = id;
6248             oid.SetValue(H46019OID);
6249 
6250               bool h46019msg = false;
6251               H46019_TraversalParameters params;
6252 #ifdef H323_H46019M
6253               if (m_H46019multiplex) {   // TODO: Change bool to direction multiplex to go
6254                     params.IncludeOptionalField(H46019_TraversalParameters::e_multiplexedMediaChannel);
6255                     H245_TransportAddress & mRTP = params.m_multiplexedMediaChannel;
6256                     m_multiRTPAddress.SetPDU(mRTP);
6257 
6258                     params.IncludeOptionalField(H46019_TraversalParameters::e_multiplexedMediaControlChannel);
6259                     H245_TransportAddress & mRTCP = params.m_multiplexedMediaControlChannel;
6260                     m_multiRTCPAddress.SetPDU(mRTCP);
6261 
6262                     params.IncludeOptionalField(H46019_TraversalParameters::e_multiplexID);
6263                     PASN_Integer & mID = params.m_multiplexID;
6264                     mID = multiID;
6265                     h46019msg = true;
6266               }
6267 #endif
6268                // Traversal Clients do not need to send a keepalive address only Servers - SH
6269               //if (!isAck) {
6270               //      params.IncludeOptionalField(H46019_TraversalParameters::e_keepAliveChannel);
6271               //      H245_TransportAddress & mKeep = params.m_keepAliveChannel;
6272               //      m_keepAlive.SetPDU(mKeep);
6273               //      h46019msg = true;
6274               //}
6275 
6276               if (!isAck && ttl > 0) {
6277                     params.IncludeOptionalField(H46019_TraversalParameters::e_keepAliveInterval);
6278                     H225_TimeToLive & a = params.m_keepAliveInterval;
6279                     a = ttl;
6280                     h46019msg = true;
6281               }
6282 
6283               if (isAck && payload > 0) {
6284                     params.IncludeOptionalField(H46019_TraversalParameters::e_keepAlivePayloadType);
6285                     PASN_Integer & p = params.m_keepAlivePayloadType;
6286                     p = payload;
6287                     h46019msg = true;
6288               }
6289 
6290               if (h46019msg) {
6291                 PTRACE(4,"H46019\tTraversal Parameters: Send Session " << sessionID
6292                                     << " " << (isAck ? "OLCack" : "OLC")  << "\n" << params);
6293                 info.IncludeOptionalField(H245_GenericMessage::e_messageContent);
6294                 H245_ArrayOf_GenericParameter & msg = info.m_messageContent;
6295                 H245_GenericParameter genericParameter;
6296                 H245_ParameterIdentifier & idm = genericParameter.m_parameterIdentifier;
6297                     idm.SetTag(H245_ParameterIdentifier::e_standard);
6298                     PASN_Integer & idx = idm;
6299                     idx = 1;
6300                 genericParameter.m_parameterValue.SetTag(H245_ParameterValue::e_octetString);
6301                 H245_ParameterValue & octetValue = genericParameter.m_parameterValue;
6302                 PASN_OctetString & raw = octetValue;
6303                 raw.EncodeSubType(params);
6304                 msg.SetSize(1);
6305                 msg[0] = genericParameter;
6306               }
6307           PINDEX sz = generic.GetSize();
6308           generic.SetSize(sz+1);
6309           generic[sz] = info;
6310 
6311 #ifdef H323_H46024A
6312           if (m_H46024Aenabled) {
6313               H245_GenericInformation alt;
6314               H245_CapabilityIdentifier & altid = alt.m_messageIdentifier;
6315                 id.SetTag(H245_CapabilityIdentifier::e_standard);
6316                 PASN_ObjectId & oid = altid;
6317                 oid.SetValue(H46024AOID);
6318                 alt.IncludeOptionalField(H245_GenericMessage::e_messageContent);
6319                 H245_ArrayOf_GenericParameter & msg = alt.m_messageContent;
6320                 msg.SetSize(3);
6321                   BuildGenericOctetString(msg[0],0,(PASN_IA5String)m_cui);
6322                   BuildGenericOctetString(msg[1],1,m_altAddr1);
6323                   BuildGenericOctetString(msg[2],2,m_altAddr2);
6324 
6325                   if (m_altMuxID) {
6326                       msg.SetSize(4);
6327                       BuildGenericUnsigned(msg[3],3,m_altMuxID);
6328                   }
6329                PTRACE(5,"H46024A\tAltInfo:\n" << alt);
6330               PINDEX sz = generic.GetSize();
6331               generic.SetSize(sz+1);
6332               generic[sz] = alt;
6333           }
6334 #endif
6335           if (generic.GetSize() > 0)
6336                 return true;
6337     }
6338 #endif
6339 
6340   return false;
6341 }
6342 
ReleaseSession(unsigned sessionID)6343 void H323Connection::ReleaseSession(unsigned sessionID)
6344 {
6345     // Clunge for H.239 which opens with a sessionID of 0
6346     if ((rtpSessions.GetSession(sessionID) == NULL) && (sessionID > 3))
6347                sessionID = 0;
6348 
6349 #ifdef H323_H46024A
6350    const RTP_Session * sess = GetSession(sessionID);
6351    if (sess && sess->GetReferenceCount() == 1) {  // last session reference
6352       std::map<unsigned,NAT_Sockets>::iterator sockets_iter = m_NATSockets.find(sessionID);
6353       if (sockets_iter != m_NATSockets.end())
6354          m_NATSockets.erase(sockets_iter);
6355       else {
6356          sockets_iter = m_NATSockets.find(0);
6357          if (sockets_iter != m_NATSockets.end())
6358               m_NATSockets.erase(sockets_iter);
6359       }
6360    }
6361 #endif
6362   rtpSessions.ReleaseSession(sessionID);
6363 }
6364 
UpdateSession(unsigned oldSessionID,unsigned newSessionID)6365 void H323Connection::UpdateSession(unsigned oldSessionID, unsigned newSessionID)
6366 {
6367     rtpSessions.MoveSession(oldSessionID,newSessionID);
6368 }
6369 
6370 
OnRTPStatistics(const RTP_Session & session) const6371 void H323Connection::OnRTPStatistics(const RTP_Session & session) const
6372 {
6373 #ifdef H323_H4609
6374        if (!m_h4609Final && session.GetPacketsReceived() > 0)
6375            (PRemoveConst(H323Connection,this))->H4609QueueStats(session);
6376 #endif
6377   endpoint.OnRTPStatistics(*this, session);
6378 }
6379 
OnRTPFinalStatistics(const RTP_Session & session) const6380 void H323Connection::OnRTPFinalStatistics(const RTP_Session & session) const
6381 {
6382 #ifdef H323_H4609
6383        if (session.GetPacketsReceived() > 0)
6384            (PRemoveConst(H323Connection,this))->H4609QueueStats(session);
6385 #endif
6386   endpoint.OnRTPFinalStatistics(*this, session);
6387 }
6388 
OnRxSenderReport(unsigned sessionID,const RTP_Session::SenderReport & send,const RTP_Session::ReceiverReportArray & recv) const6389 void H323Connection::OnRxSenderReport(unsigned sessionID, const RTP_Session::SenderReport & send,
6390         const RTP_Session::ReceiverReportArray & recv) const
6391 {
6392 }
6393 
6394 #ifdef H323_H460IM
6395 
IMSupport()6396 PBoolean H323Connection::IMSupport()
6397 {
6398     return m_IMsupport;
6399 }
6400 
SetIMSupport(PBoolean state)6401 void H323Connection::SetIMSupport(PBoolean state)
6402 {
6403     m_IMsupport = state;
6404 }
6405 
IMSession()6406 PBoolean H323Connection::IMSession()
6407 {
6408     return m_IMsession;
6409 }
6410 
SetIMSession(PBoolean state)6411 void H323Connection::SetIMSession(PBoolean state)
6412 {
6413     m_IMsession = state;
6414 }
6415 
IMCall()6416 PBoolean H323Connection::IMCall()
6417 {
6418     return m_IMcall;
6419 }
6420 
SetIMCall(PBoolean state)6421 void H323Connection::SetIMCall(PBoolean state)
6422 {
6423     m_IMcall = state;
6424 }
6425 
IMMsg()6426 const PString & H323Connection::IMMsg()
6427 {
6428     return m_IMmsg;
6429 }
6430 
SetIMMsg(const PString & msg)6431 void H323Connection::SetIMMsg(const PString & msg)
6432 {
6433     m_IMmsg = msg;
6434 }
6435 
6436 #endif
6437 
6438 #ifdef H323_H4609
6439 
H4609Statistics()6440 H323Connection::H4609Statistics::H4609Statistics()
6441 {
6442     meanEndToEndDelay = 0;
6443     worstEndToEndDelay = 0;
6444     packetsReceived = 0;
6445     accumPacketLost = 0;
6446     packetLossRate = 0;
6447     fractionLostRate = 0;
6448     meanJitter = 0;
6449     worstJitter = 0;
6450     bandwidth = 0;
6451     sessionid = 1;
6452 }
6453 
H4609QueueStats(const RTP_Session & session)6454 void H323Connection::H4609QueueStats(const RTP_Session & session)
6455 {
6456    if (!m_h4609enabled)
6457        return;
6458 
6459     H4609Statistics * stat = new H4609Statistics();
6460     stat->sendRTPaddr  = H323TransportAddress(session.GetLocalTransportAddress());
6461     stat->recvRTPaddr  = H323TransportAddress(session.GetRemoteTransportAddress());
6462 //     stat->sendRTCPaddr = H323TransportAddress();
6463 //   stat->recvRTCPaddr = H323TransportAddress();
6464     stat->sessionid = session.GetSessionID();
6465     stat->meanEndToEndDelay = session.GetAverageSendTime();
6466     stat->worstEndToEndDelay = session.GetMaximumSendTime();
6467     stat->packetsReceived = session.GetPacketsReceived();
6468     stat->accumPacketLost = session.GetPacketsLost();
6469     stat->packetLossRate = session.GetPacketsLost() / session.GetPacketsReceived();
6470     stat->fractionLostRate = stat->packetLossRate * 100;
6471     stat->meanJitter = session.GetAvgJitterTime();
6472     stat->worstJitter = session.GetMaxJitterTime();
6473     if (session.GetPacketsReceived() > 0 && session.GetAverageReceiveTime() > 0)
6474       stat->bandwidth  = (unsigned)((session.GetOctetsReceived()/session.GetPacketsReceived()/session.GetAverageReceiveTime())*1000);
6475 
6476     m_h4609Stats.Enqueue(stat);
6477 }
6478 
6479 
H4609DequeueStats()6480 H323Connection::H4609Statistics * H323Connection::H4609DequeueStats()
6481 {
6482     if (m_h4609Stats.GetSize() == 0)
6483         return NULL;
6484 
6485     return (m_h4609Stats.Dequeue());
6486 }
6487 
H4609EnableStats()6488 void H323Connection::H4609EnableStats()
6489 {
6490     m_h4609enabled = true;
6491 }
6492 
H4609StatsFinal(PBoolean final)6493 void H323Connection::H4609StatsFinal(PBoolean final)
6494 {
6495     m_h4609Final = final;
6496 }
6497 #endif
6498 
AddSessionCodecName(PStringStream & name,H323Channel * channel)6499 static void AddSessionCodecName(PStringStream & name, H323Channel * channel)
6500 {
6501   if (channel == NULL)
6502     return;
6503 
6504   H323Codec * codec = channel->GetCodec();
6505   if (codec == NULL)
6506     return;
6507 
6508   OpalMediaFormat mediaFormat = codec->GetMediaFormat();
6509   if (mediaFormat.IsEmpty())
6510     return;
6511 
6512   if (name.IsEmpty())
6513     name << mediaFormat;
6514   else if (name != mediaFormat)
6515     name << " / " << mediaFormat;
6516 }
6517 
6518 
GetSessionCodecNames(unsigned sessionID) const6519 PString H323Connection::GetSessionCodecNames(unsigned sessionID) const
6520 {
6521   PStringStream name;
6522 
6523   AddSessionCodecName(name, FindChannel(sessionID, FALSE));
6524   AddSessionCodecName(name, FindChannel(sessionID, TRUE));
6525 
6526   return name;
6527 }
6528 
6529 
RequestModeChange(const PString & newModes)6530 PBoolean H323Connection::RequestModeChange(const PString & newModes)
6531 {
6532   return requestModeProcedure->StartRequest(newModes);
6533 }
6534 
6535 
RequestModeChange(const H245_ArrayOf_ModeDescription & newModes)6536 PBoolean H323Connection::RequestModeChange(const H245_ArrayOf_ModeDescription & newModes)
6537 {
6538   return requestModeProcedure->StartRequest(newModes);
6539 }
6540 
6541 
OnRequestModeChange(const H245_RequestMode & pdu,H245_RequestModeAck &,H245_RequestModeReject &,PINDEX & selectedMode)6542 PBoolean H323Connection::OnRequestModeChange(const H245_RequestMode & pdu,
6543                                          H245_RequestModeAck & /*ack*/,
6544                                          H245_RequestModeReject & /*reject*/,
6545                                          PINDEX & selectedMode)
6546 {
6547   for (selectedMode = 0; selectedMode < pdu.m_requestedModes.GetSize(); selectedMode++) {
6548     PBoolean ok = TRUE;
6549     for (PINDEX i = 0; i < pdu.m_requestedModes[selectedMode].GetSize(); i++) {
6550       if (localCapabilities.FindCapability(pdu.m_requestedModes[selectedMode][i]) == NULL) {
6551         ok = FALSE;
6552         break;
6553       }
6554     }
6555     if (ok)
6556       return TRUE;
6557   }
6558 
6559   PTRACE(1, "H245\tMode change rejected as does not have capabilities");
6560   return FALSE;
6561 }
6562 
6563 
OnModeChanged(const H245_ModeDescription & newMode)6564 void H323Connection::OnModeChanged(const H245_ModeDescription & newMode)
6565 {
6566   CloseAllLogicalChannels(FALSE);
6567 
6568   // Start up the new ones
6569   for (PINDEX i = 0; i < newMode.GetSize(); i++) {
6570     H323Capability * capability = localCapabilities.FindCapability(newMode[i]);
6571     if (PAssertNULL(capability) != NULL)  {// Should not occur as OnRequestModeChange checks them
6572       if (!OpenLogicalChannel(*capability,
6573                               capability->GetDefaultSessionID(),
6574                               H323Channel::IsTransmitter)) {
6575         PTRACE(1, "H245\tCould not open channel after mode change: " << *capability);
6576       }
6577     }
6578   }
6579 }
6580 
6581 
OnAcceptModeChange(const H245_RequestModeAck & pdu)6582 void H323Connection::OnAcceptModeChange(const H245_RequestModeAck & pdu)
6583 {
6584 #if H323_T38
6585   if (t38ModeChangeCapabilities.IsEmpty())
6586     return;
6587 
6588   PTRACE(2, "H323\tT.38 mode change accepted.");
6589 
6590   // Now we have conviced the other side to send us T.38 data we should do the
6591   // same assuming the RequestModeChangeT38() function provided a list of \n
6592   // separaete capability names to start. Only one will be.
6593 
6594   CloseAllLogicalChannels(FALSE);
6595 
6596   PStringArray modes = t38ModeChangeCapabilities.Lines();
6597 
6598   PINDEX first, last;
6599   if (pdu.m_response.GetTag() == H245_RequestModeAck_response::e_willTransmitMostPreferredMode) {
6600     first = 0;
6601     last = 1;
6602   }
6603   else {
6604     first = 1;
6605     last = modes.GetSize();
6606   }
6607 
6608   for (PINDEX i = first; i < last; i++) {
6609     H323Capability * capability = localCapabilities.FindCapability(modes[i]);
6610     if (capability != NULL && OpenLogicalChannel(*capability,
6611                                                  capability->GetDefaultSessionID(),
6612                                                  H323Channel::IsTransmitter)) {
6613       PTRACE(1, "H245\tOpened " << *capability << " after T.38 mode change");
6614       break;
6615     }
6616 
6617     PTRACE(1, "H245\tCould not open channel after T.38 mode change");
6618   }
6619 
6620   t38ModeChangeCapabilities = PString::Empty();
6621 #endif
6622 }
6623 
6624 
OnRefusedModeChange(const H245_RequestModeReject *)6625 void H323Connection::OnRefusedModeChange(const H245_RequestModeReject * /*pdu*/)
6626 {
6627 #ifdef H323_T38
6628   if (!t38ModeChangeCapabilities) {
6629     PTRACE(2, "H323\tT.38 mode change rejected.");
6630     t38ModeChangeCapabilities = PString::Empty();
6631   }
6632 #endif
6633 }
6634 
OnSendARQ(H225_AdmissionRequest & arq)6635 void H323Connection::OnSendARQ(H225_AdmissionRequest & arq)
6636 {
6637 #ifdef H323_H460
6638     if (OnSendFeatureSet(H460_MessageType::e_admissionRequest, arq.m_featureSet, true))
6639         arq.IncludeOptionalField(H225_AdmissionRequest::e_featureSet);
6640 
6641     H225_FeatureSet fs;
6642     if (OnSendFeatureSet(H460_MessageType::e_admissionRequest, fs, false)) {
6643           if (fs.HasOptionalField(H225_FeatureSet::e_supportedFeatures)) {
6644             arq.IncludeOptionalField(H225_AdmissionRequest::e_genericData);
6645 
6646             H225_ArrayOf_FeatureDescriptor & fsn = fs.m_supportedFeatures;
6647             H225_ArrayOf_GenericData & data = arq.m_genericData;
6648 
6649             for (PINDEX i=0; i < fsn.GetSize(); i++) {
6650                  PINDEX lastPos = data.GetSize();
6651                  data.SetSize(lastPos+1);
6652                  data[lastPos] = fsn[i];
6653             }
6654           }
6655      }
6656 #endif
6657   endpoint.OnSendARQ(*this, arq);
6658 }
6659 
OnReceivedACF(const H225_AdmissionConfirm & acf)6660 void H323Connection::OnReceivedACF(const H225_AdmissionConfirm & acf)
6661 {
6662 #ifdef H323_H460
6663     if (acf.HasOptionalField(H225_AdmissionConfirm::e_featureSet))
6664         OnReceiveFeatureSet(H460_MessageType::e_admissionConfirm, acf.m_featureSet);
6665 
6666     if (acf.HasOptionalField(H225_AdmissionConfirm::e_genericData)) {
6667         const H225_ArrayOf_GenericData & data = acf.m_genericData;
6668 
6669       if (data.GetSize() > 0) {
6670          H225_FeatureSet fs;
6671          fs.IncludeOptionalField(H225_FeatureSet::e_supportedFeatures);
6672          H225_ArrayOf_FeatureDescriptor & fsn = fs.m_supportedFeatures;
6673          fsn.SetSize(data.GetSize());
6674             for (PINDEX i=0; i < data.GetSize(); i++)
6675                  fsn[i] = (H225_FeatureDescriptor &)data[i];
6676 
6677          OnReceiveFeatureSet(H460_MessageType::e_admissionConfirm, fs);
6678       }
6679     }
6680 #endif
6681   endpoint.OnReceivedACF(*this, acf);
6682 }
6683 
OnReceivedARJ(const H225_AdmissionReject & arj)6684 void H323Connection::OnReceivedARJ(const H225_AdmissionReject & arj)
6685 {
6686 
6687     if (arj.m_rejectReason.GetTag() == H225_AdmissionRejectReason::e_routeCallToGatekeeper) {
6688       H323SignalPDU facilityPDU;
6689       H225_Facility_UUIE * fac = facilityPDU.BuildFacility(*this,false, H225_FacilityReason::e_routeCallToGatekeeper);
6690 
6691       H323Gatekeeper * gatekeeper = endpoint.GetGatekeeper();
6692       if (gatekeeper) {
6693          H323TransportAddress add = gatekeeper->GetGatekeeperRouteAddress();
6694          fac->IncludeOptionalField(H225_Facility_UUIE::e_alternativeAddress);
6695          add.SetPDU(fac->m_alternativeAddress);
6696          WriteSignalPDU(facilityPDU);
6697       }
6698     }
6699 
6700 #ifdef H323_H460
6701     if (arj.HasOptionalField(H225_AdmissionReject::e_featureSet))
6702         OnReceiveFeatureSet(H460_MessageType::e_admissionConfirm, arj.m_featureSet);
6703 
6704     if (arj.HasOptionalField(H225_AdmissionReject::e_genericData)) {
6705         const H225_ArrayOf_GenericData & data = arj.m_genericData;
6706 
6707       if (data.GetSize() > 0) {
6708          H225_FeatureSet fs;
6709          fs.IncludeOptionalField(H225_FeatureSet::e_supportedFeatures);
6710          H225_ArrayOf_FeatureDescriptor & fsn = fs.m_supportedFeatures;
6711          fsn.SetSize(data.GetSize());
6712             for (PINDEX i=0; i < data.GetSize(); i++)
6713                  fsn[i] = (H225_FeatureDescriptor &)data[i];
6714 
6715          OnReceiveFeatureSet(H460_MessageType::e_admissionReject, fs);
6716       }
6717     }
6718 #endif
6719   endpoint.OnReceivedARJ(*this, arj);
6720 }
6721 
OnSendIRR(H225_InfoRequestResponse & irr) const6722 void H323Connection::OnSendIRR(H225_InfoRequestResponse & irr) const
6723 {
6724 #ifdef H323_H460
6725     H225_FeatureSet fs;
6726     if (OnSendFeatureSet(H460_MessageType::e_inforequestresponse, fs, false)) {
6727         if (fs.HasOptionalField(H225_FeatureSet::e_supportedFeatures)) {
6728             irr.IncludeOptionalField(H225_InfoRequestResponse::e_genericData);
6729 
6730             H225_ArrayOf_FeatureDescriptor & fsn = fs.m_supportedFeatures;
6731             H225_ArrayOf_GenericData & data = irr.m_genericData;
6732 
6733             for (PINDEX i=0; i < fsn.GetSize(); i++) {
6734                  PINDEX lastPos = data.GetSize();
6735                  data.SetSize(lastPos+1);
6736                  data[lastPos] = fsn[i];
6737             }
6738         }
6739      }
6740 #endif
6741 }
6742 
OnSendDRQ(H225_DisengageRequest & drq) const6743 void H323Connection::OnSendDRQ(H225_DisengageRequest & drq) const
6744 {
6745 #ifdef H323_H460
6746     H225_FeatureSet fs;
6747     if (OnSendFeatureSet(H460_MessageType::e_disengagerequest, fs, false)) {
6748           if (fs.HasOptionalField(H225_FeatureSet::e_supportedFeatures)) {
6749             drq.IncludeOptionalField(H225_DisengageRequest::e_genericData);
6750 
6751             H225_ArrayOf_FeatureDescriptor & fsn = fs.m_supportedFeatures;
6752             H225_ArrayOf_GenericData & data = drq.m_genericData;
6753 
6754             for (PINDEX i=0; i < fsn.GetSize(); i++) {
6755                  PINDEX lastPos = data.GetSize();
6756                  data.SetSize(lastPos+1);
6757                  data[lastPos] = fsn[i];
6758             }
6759           }
6760      }
6761 #endif
6762 }
6763 
6764 
6765 #ifdef H323_T120
6766 
CreateT120ProtocolHandler()6767 OpalT120Protocol * H323Connection::CreateT120ProtocolHandler()
6768 {
6769   if (t120handler == NULL)
6770     t120handler = endpoint.CreateT120ProtocolHandler(*this);
6771   return t120handler;
6772 }
6773 
6774 #endif
6775 
6776 #ifdef H323_T38
6777 
CreateT38ProtocolHandler()6778 OpalT38Protocol * H323Connection::CreateT38ProtocolHandler()
6779 {
6780   if (t38handler == NULL)
6781     t38handler = endpoint.CreateT38ProtocolHandler(*this);
6782   return t38handler;
6783 }
6784 
6785 
RequestModeChangeT38(const char * capabilityNames)6786 PBoolean H323Connection::RequestModeChangeT38(const char * capabilityNames)
6787 {
6788   t38ModeChangeCapabilities = capabilityNames;
6789   if (RequestModeChange(t38ModeChangeCapabilities))
6790     return TRUE;
6791 
6792   t38ModeChangeCapabilities = PString::Empty();
6793   return FALSE;
6794 }
6795 
6796 #endif // H323_T38
6797 
6798 #ifdef H323_H224
CreateH224ProtocolHandler(H323Channel::Directions dir,unsigned sessionID)6799 OpalH224Handler * H323Connection::CreateH224ProtocolHandler(H323Channel::Directions dir, unsigned sessionID)
6800 {
6801   return endpoint.CreateH224ProtocolHandler(dir, *this, sessionID);
6802 }
6803 
OnCreateH224Handler(H323Channel::Directions dir,const PString & id,H224_Handler * m_handler) const6804 PBoolean H323Connection::OnCreateH224Handler(H323Channel::Directions dir, const PString & id, H224_Handler * m_handler) const
6805 {
6806     return endpoint.OnCreateH224Handler(dir,*this,id,m_handler);
6807 }
6808 
CreateH224Handler(H323Channel::Directions dir,OpalH224Handler & h224Handler,const PString & id)6809 H224_Handler * H323Connection::CreateH224Handler(H323Channel::Directions dir, OpalH224Handler & h224Handler, const PString & id)
6810 {
6811     if (id == "H281")  // Backwards compatibility
6812         return CreateH281ProtocolHandler(h224Handler);
6813     else
6814         return NULL;
6815 }
6816 
6817 #ifdef H224_H281
CreateH281ProtocolHandler(OpalH224Handler & h224Handler)6818 H224_H281Handler * H323Connection::CreateH281ProtocolHandler(OpalH224Handler & h224Handler)
6819 {
6820     return endpoint.CreateH281ProtocolHandler(h224Handler);
6821 }
6822 #endif
6823 
6824 #endif  // H323_H224
6825 
6826 
6827 #ifdef H323_T140
CreateRFC4103ProtocolHandler(H323Channel::Directions dir,unsigned sessionID)6828 H323_RFC4103Handler * H323Connection::CreateRFC4103ProtocolHandler(H323Channel::Directions dir, unsigned sessionID)
6829 {
6830   return endpoint.CreateRFC4103ProtocolHandler(dir, *this, sessionID);
6831 }
6832 #endif  // H323_T140
6833 
6834 
6835 #ifdef H323_FILE
OpenFileTransferSession(const H323FileTransferList & list,H323ChannelNumber & num)6836 PBoolean H323Connection::OpenFileTransferSession(const H323FileTransferList & list, H323ChannelNumber & num)
6837 {
6838   PBoolean filetransferOpen = FALSE;
6839 
6840   for (PINDEX i = 0; i < localCapabilities.GetSize(); i++) {
6841     H323Capability & localCapability = localCapabilities[i];
6842     if ((localCapability.GetMainType() == H323Capability::e_Data) &&
6843         (localCapability.GetSubType() == H245_DataApplicationCapability_application::e_genericDataCapability)) {
6844       H323FileTransferCapability * remoteCapability = (H323FileTransferCapability *)remoteCapabilities.FindCapability(localCapability);
6845       if (remoteCapability != NULL) {
6846         PTRACE(3, "H323\tFile Transfer Available " << *remoteCapability);
6847         remoteCapability->SetFileTransferList(list);
6848         if (logicalChannels->Open(*remoteCapability, OpalMediaFormat::DefaultFileSessionID,num)) {
6849            filetransferOpen = TRUE;
6850            break;
6851         }
6852         PTRACE(2, "H323\tFileTranfer OpenLogicalChannel failed: " << *remoteCapability);
6853       }
6854       break;
6855     }
6856   }
6857 
6858   return filetransferOpen;
6859 }
6860 
CloseFileTransferSession(unsigned num)6861 PBoolean H323Connection::CloseFileTransferSession(unsigned num)
6862 {
6863     CloseLogicalChannel(num,false);
6864     return TRUE;
6865 }
6866 
CreateFileTransferHandler(unsigned sessionID,H323Channel::Directions dir,H323FileTransferList & filelist)6867 H323FileTransferHandler * H323Connection::CreateFileTransferHandler(unsigned sessionID,
6868                                                                     H323Channel::Directions dir,
6869                                                                     H323FileTransferList & filelist)
6870 {
6871 
6872   if (!filelist.IsMaster() && !OpenFileTransferChannel(dir == H323Channel::IsTransmitter, filelist))
6873         return NULL;
6874 
6875   return OnCreateFileTransferHandler(sessionID,dir,filelist);
6876 }
6877 
OnCreateFileTransferHandler(unsigned sessionID,H323Channel::Directions dir,H323FileTransferList & filelist)6878 H323FileTransferHandler * H323Connection::OnCreateFileTransferHandler(unsigned sessionID,
6879                                                                     H323Channel::Directions dir,
6880                                                                     H323FileTransferList & filelist)
6881 {
6882     return new H323FileTransferHandler(*this, sessionID, dir, filelist);
6883 }
6884 
6885 
OpenFileTransferChannel(PBoolean isEncoder,H323FileTransferList & filelist)6886 PBoolean H323Connection::OpenFileTransferChannel( PBoolean isEncoder,
6887                                               H323FileTransferList & filelist
6888                                              )
6889 {
6890    return endpoint.OpenFileTransferChannel(*this,isEncoder,filelist);
6891 }
6892 
6893 
6894 #endif
6895 
6896 
GetAdmissionRequestAuthentication(const H225_AdmissionRequest &,H235Authenticators &)6897 PBoolean H323Connection::GetAdmissionRequestAuthentication(const H225_AdmissionRequest & /*arq*/,
6898                                                        H235Authenticators & /*authenticators*/)
6899 {
6900   return FALSE;
6901 }
6902 
6903 
GetControlChannel() const6904 const H323Transport & H323Connection::GetControlChannel() const
6905 {
6906   return *(controlChannel != NULL ? controlChannel : signallingChannel);
6907 }
6908 
6909 
SetAudioJitterDelay(unsigned minDelay,unsigned maxDelay)6910 void H323Connection::SetAudioJitterDelay(unsigned minDelay, unsigned maxDelay)
6911 {
6912   PAssert(minDelay <= 1000 && maxDelay <= 1000, PInvalidParameter);
6913 
6914   if (minDelay < 10)
6915     minDelay = 10;
6916   minAudioJitterDelay = minDelay;
6917 
6918   if (maxDelay < minDelay)
6919     maxDelay = minDelay;
6920   maxAudioJitterDelay = maxDelay;
6921 }
6922 
6923 
SendLogicalChannelMiscCommand(H323Channel & channel,unsigned commandIdentifier)6924 void H323Connection::SendLogicalChannelMiscCommand(H323Channel & channel,
6925                                                    unsigned commandIdentifier)
6926 {
6927   if (channel.GetDirection() == H323Channel::IsReceiver) {
6928     H323ControlPDU pdu;
6929     H245_CommandMessage & command = pdu.Build(H245_CommandMessage::e_miscellaneousCommand);
6930     H245_MiscellaneousCommand & miscCommand = command;
6931     miscCommand.m_logicalChannelNumber = (unsigned)channel.GetNumber();
6932     miscCommand.m_type.SetTag(commandIdentifier);
6933     WriteControlPDU(pdu);
6934   }
6935 }
6936 
6937 
SetEnforcedDurationLimit(unsigned seconds)6938 void H323Connection::SetEnforcedDurationLimit(unsigned seconds)
6939 {
6940   enforcedDurationLimit.SetInterval(0, seconds);
6941 }
6942 
6943 
MonitorCallStatus()6944 void H323Connection::MonitorCallStatus()
6945 {
6946   if (!Lock())
6947     return;
6948 
6949   if (roundTripDelayTimer > 0 && !roundTripDelayTimer.IsRunning()) {
6950     roundTripDelayTimer.SetInterval(roundTripDelayRate);
6951     StartRoundTripDelay();
6952   }
6953 
6954   if (noMediaTimeOut > 0) {
6955     PBoolean oneRunning = FALSE;
6956     PBoolean allSilent = TRUE;
6957     for (PINDEX i = 0; i < logicalChannels->GetSize(); i++) {
6958         H323Channel * channel = logicalChannels->GetChannelAt(i);
6959         if (channel && channel->IsRunning()) {
6960             oneRunning = TRUE;
6961             if (channel->GetSilenceDuration() < noMediaTimeOut) {
6962                 allSilent = FALSE;
6963                 break;
6964             }
6965         }
6966     }
6967     if (oneRunning && allSilent)
6968       ClearCall(EndedByTransportFail);
6969   }
6970 
6971   if (enforcedDurationLimit.GetResetTime() > 0 && enforcedDurationLimit == 0)
6972     ClearCall(EndedByDurationLimit);
6973 
6974   Unlock();
6975 }
6976 
6977 #ifdef P_STUN
6978 
SessionInformation(const OpalGloballyUniqueID & id,unsigned crv,const PString & token,unsigned session,const H323Connection * conn)6979 H323Connection::SessionInformation::SessionInformation(const OpalGloballyUniqueID & id, unsigned crv, const PString & token, unsigned session, const H323Connection * conn)
6980 : m_callID(id), m_crv(crv), m_callToken(token), m_sessionID(session), m_recvMultiID(0), m_sendMultiID(0), m_connection(conn)
6981 {
6982 
6983 #ifdef H323_H46019M
6984     if (conn->IsH46019Multiplexed())
6985         m_recvMultiID = conn->GetEndPoint().GetMultiplexID();
6986 #endif
6987 
6988 #ifdef H323_H46024A
6989     // Some random number bases on the session id (for H.460.24A)
6990     int rand = PRandom::Number((session *100),((session+1)*100)-1);
6991     m_CUI = PString(rand);
6992     PTRACE(4,"H46024A\tGenerated CUI s: " << session << " value: " << m_CUI);
6993 #else
6994     m_CUI = PString();
6995 #endif
6996 }
6997 
GetCallReference()6998 unsigned H323Connection::SessionInformation::GetCallReference()
6999 {
7000     return m_crv;
7001 }
7002 
GetCallToken()7003 const PString & H323Connection::SessionInformation::GetCallToken()
7004 {
7005     return m_callToken;
7006 }
7007 
GetSessionID() const7008 unsigned H323Connection::SessionInformation::GetSessionID() const
7009 {
7010     return m_sessionID;
7011 }
7012 
SetSendMultiplexID(unsigned id)7013 void H323Connection::SessionInformation::SetSendMultiplexID(unsigned id)
7014 {
7015     m_sendMultiID = id;
7016 }
7017 
GetRecvMultiplexID() const7018 unsigned H323Connection::SessionInformation::GetRecvMultiplexID() const
7019 {
7020     return m_recvMultiID;
7021 }
7022 
BuildSessionInformation(unsigned sessionID) const7023 H323Connection::SessionInformation * H323Connection::BuildSessionInformation(unsigned sessionID) const
7024 {
7025     return new SessionInformation(GetCallIdentifier(),GetCallReference(),GetCallToken(),sessionID, this);
7026 }
7027 
GetCallIdentifer()7028 const OpalGloballyUniqueID & H323Connection::SessionInformation::GetCallIdentifer()
7029 {
7030     return m_callID;
7031 }
7032 
GetCUI()7033 const PString & H323Connection::SessionInformation::GetCUI()
7034 {
7035     return m_CUI;
7036 }
7037 
GetConnection()7038 const H323Connection * H323Connection::SessionInformation::GetConnection()
7039 {
7040     return m_connection;
7041 }
7042 
7043 #endif
7044 
7045 #ifdef H323_H460
DisableFeatures(PBoolean disable)7046 void H323Connection::DisableFeatures(PBoolean disable)
7047 {
7048      disableH460 = disable;
7049 }
7050 
7051 #ifdef H323_H46018
H46019SetCallReceiver()7052 void H323Connection::H46019SetCallReceiver()
7053 {
7054     PTRACE(4,"H46019\tCall is receiver.");
7055     m_H46019CallReceiver = true;
7056 }
7057 
H46019Enabled()7058 void H323Connection::H46019Enabled()
7059 {
7060     if (!m_H46019offload)
7061        m_H46019enabled = true;
7062 }
7063 
IsH46019Enabled() const7064 PBoolean H323Connection::IsH46019Enabled() const
7065 {
7066     return m_H46019enabled;
7067 }
7068 
H46019SetOffload()7069 void H323Connection::H46019SetOffload()
7070 {
7071     if (!m_H46019multiplex)
7072          m_H46019enabled = false;
7073 
7074     m_H46019offload = true;
7075 }
7076 
H46019MultiEnabled()7077 void H323Connection::H46019MultiEnabled()
7078 {
7079     m_H46019enabled = true;
7080     m_H46019multiplex = true;
7081     NATsupport = true;
7082 }
7083 
IsH46019Multiplexed() const7084 PBoolean H323Connection::IsH46019Multiplexed() const
7085 {
7086     return m_H46019multiplex;
7087 }
7088 #endif   // H323_H46018
7089 
7090 #ifdef H323_H46024A
H46024AEnabled()7091 void H323Connection::H46024AEnabled()
7092 {
7093     m_H46024Aenabled = true;
7094 }
7095 #endif   // H323_H46024A
7096 
7097 #ifdef H323_H46024B
H46024BEnabled()7098 void H323Connection::H46024BEnabled()
7099 {
7100     m_H46024Benabled = true;
7101 }
7102 #endif   // H323_H46024A
7103 
7104 
7105 #ifdef H323_H46026
H46026SetMediaTunneled()7106 void H323Connection::H46026SetMediaTunneled()
7107 {
7108     m_H46026enabled = true;
7109 #ifdef H323_H46018
7110     if (features->HasFeature(19)) {
7111         H460_Feature * feat = features->GetFeature(19);
7112         if (feat) {
7113             PTRACE(4,"H46026\tDisabling H.460.19 support for call");
7114             ((H460_FeatureStd19 *)feat)->SetAvailable(false);
7115         }
7116     }
7117     m_H46019enabled = false;
7118 #endif // H323_H46018
7119 }
7120 
H46026IsMediaTunneled()7121 PBoolean H323Connection::H46026IsMediaTunneled()
7122 {
7123     return m_H46026enabled;
7124 }
7125 #endif   // H323_H46026
7126 
7127 #ifdef H323_H460COM
OnRemoteVendorInformation(const PString & product,const PString & version)7128 void H323Connection::OnRemoteVendorInformation(const PString & product, const PString & version)
7129 {
7130 
7131 }
7132 #endif // H323_H460COM
7133 
7134 #ifdef H323_H461
7135 // Normally first message will be a listRequest. ie (4)
H461MessageInfo()7136 H323Connection::H461MessageInfo::H461MessageInfo()
7137 : m_message(4), m_assocToken(PString()), m_callToken(PString()),
7138   m_applicationID(-1), m_invokeToken(PString()), m_aliasAddress(PString()), m_approved(false)
7139 {
7140 
7141 }
7142 
SetH461Mode(ASSETCallType mode)7143 void H323Connection::SetH461Mode(ASSETCallType mode)
7144 {
7145     m_H461Mode = mode;
7146 }
7147 
GetH461Mode() const7148 H323Connection::ASSETCallType H323Connection::GetH461Mode() const
7149 {
7150     return m_H461Mode;
7151 }
7152 
SetH461MessageInfo(int type,const PString & assocCallToken,const PString & assocCallIdentifier,int applicationID,const PString & invokeToken,const PString & aliasAddress,bool approved)7153 void H323Connection::SetH461MessageInfo(int type, const PString & assocCallToken, const PString & assocCallIdentifier, int applicationID,
7154                                         const PString & invokeToken, const PString & aliasAddress, bool approved )
7155 {
7156     m_H461Info.m_message = type;
7157     m_H461Info.m_assocToken = assocCallToken;
7158     m_H461Info.m_callToken = assocCallIdentifier;
7159     m_H461Info.m_applicationID = applicationID;
7160     m_H461Info.m_invokeToken = invokeToken;
7161     m_H461Info.m_aliasAddress = aliasAddress;
7162     m_H461Info.m_approved = approved;
7163 }
7164 
GetH461MessageInfo()7165 H323Connection::H461MessageInfo & H323Connection::GetH461MessageInfo()
7166 {
7167     return m_H461Info;
7168 }
7169 #endif // H323_H461
7170 
7171 #endif   // H323_H461
7172 
OnH245AddressConflict()7173 PBoolean H323Connection::OnH245AddressConflict()
7174 {
7175     // if the other side requests us to start a H.245 channel, we always do that instead of insisting that we already opened a listener
7176     return true;
7177 }
7178 
7179 
OnSendFeatureSet(unsigned code,H225_FeatureSet & feats,PBoolean advertise) const7180 PBoolean H323Connection::OnSendFeatureSet(unsigned code, H225_FeatureSet & feats, PBoolean advertise) const
7181 {
7182 #ifdef H323_H460
7183    if (disableH460)
7184        return FALSE;
7185 
7186    return features->SendFeature(code, feats, advertise);
7187 #else
7188    return endpoint.OnSendFeatureSet(code, feats, advertise);
7189 #endif
7190 }
7191 
OnReceiveFeatureSet(unsigned code,const H225_FeatureSet & feats,PBoolean genericData) const7192 void H323Connection::OnReceiveFeatureSet(unsigned code, const H225_FeatureSet & feats, PBoolean genericData) const
7193 {
7194 #ifdef H323_H460
7195    if (disableH460)
7196        return;
7197 
7198    features->ReceiveFeature(code, feats, genericData);
7199 #else
7200    endpoint.OnReceiveFeatureSet(code, feats, genericData);
7201 #endif
7202 }
7203 
7204 #ifdef H323_H460
DisableFeatureSet(int msgtype) const7205 void H323Connection::DisableFeatureSet(int msgtype) const
7206 {
7207     features->DisableAllFeatures(msgtype);
7208 }
7209 #endif
7210 
SetAuthenticationConnection()7211 void H323Connection::SetAuthenticationConnection()
7212 {
7213      for (PINDEX i = 0; i < EPAuthenticators.GetSize(); i++) {
7214         EPAuthenticators[i].SetConnection(this);
7215      }
7216 }
7217 
GetEPAuthenticators() const7218 const H235Authenticators & H323Connection::GetEPAuthenticators() const
7219 {
7220       return EPAuthenticators;
7221 }
7222 
OnCallAuthentication(const PString & username,PString & password)7223 PBoolean H323Connection::OnCallAuthentication(const PString & username,
7224                                          PString & password)
7225 {
7226     return endpoint.OnCallAuthentication(username,password);
7227 }
7228 
OnEPAuthenticationFailed(H235Authenticator::ValidationResult result) const7229 PBoolean H323Connection::OnEPAuthenticationFailed(H235Authenticator::ValidationResult result) const
7230 {
7231     return FALSE;
7232 }
7233 
OnAuthenticationFinalise(unsigned pdu,PBYTEArray & rawData)7234 void H323Connection::OnAuthenticationFinalise(unsigned pdu,PBYTEArray & rawData)
7235 {
7236      for (PINDEX i = 0; i < EPAuthenticators.GetSize(); i++) {
7237        if (EPAuthenticators[i].IsSecuredSignalPDU(pdu,FALSE))
7238            EPAuthenticators[i].Finalise(rawData);
7239      }
7240 }
7241 
7242 #ifdef H323_H235
OnMediaEncryption(unsigned session,H323Channel::Directions dir,const PString & cipher)7243 void H323Connection::OnMediaEncryption(unsigned session, H323Channel::Directions dir, const PString & cipher)
7244 {
7245     endpoint.OnMediaEncryption(session, dir, cipher);
7246 }
7247 #endif
7248 
SetTransportSecurity(const H323TransportSecurity & m_callSecurity)7249 void H323Connection::SetTransportSecurity(const H323TransportSecurity & m_callSecurity)
7250 {
7251     m_transportSecurity = m_callSecurity;
7252 }
7253 
GetTransportSecurity() const7254 const H323TransportSecurity & H323Connection::GetTransportSecurity() const
7255 {
7256     return m_transportSecurity;
7257 }
7258 
7259 #ifdef H323_SIGNAL_AGGREGATE
7260 
AggregateSignalChannel(H323Transport * transport)7261 void H323Connection::AggregateSignalChannel(H323Transport * transport)
7262 {
7263   signalAggregator = new AggregatedH225Handle(*transport, *this);
7264   endpoint.GetSignallingAggregator()->AddHandle(signalAggregator);
7265 }
7266 
AggregateControlChannel(H323Transport * transport)7267 void H323Connection::AggregateControlChannel(H323Transport * transport)
7268 {
7269   if (!OnStartHandleControlChannel())
7270     return;
7271 
7272   controlAggregator = new AggregatedH245Handle(*transport, *this);
7273   endpoint.GetSignallingAggregator()->AddHandle(controlAggregator);
7274 }
7275 
H323AggregatedH2x5Handle(H323Transport & _transport,H323Connection & _connection)7276 H323AggregatedH2x5Handle::H323AggregatedH2x5Handle(H323Transport & _transport, H323Connection & _connection)
7277   : PAggregatedHandle(TRUE),
7278     fd(((PIPSocket *)_transport.GetBaseReadChannel())->GetHandle()),
7279     transport(_transport),
7280     connection(_connection)
7281 {
7282   pduDataLen = 0;
7283 }
7284 
~H323AggregatedH2x5Handle()7285 H323AggregatedH2x5Handle::~H323AggregatedH2x5Handle()
7286 {
7287 }
7288 
GetFDs()7289 PAggregatorFDList_t H323AggregatedH2x5Handle::GetFDs()
7290 {
7291   PAggregatorFDList_t list;
7292   list.push_back(&fd);
7293   return list;
7294 }
7295 
OnRead()7296 PBoolean H323AggregatedH2x5Handle::OnRead()
7297 {
7298   //
7299   // pduDataLen  : size of PDU data read so far, always less than pduBufferLen , always same as pduBuffer.GetSize()
7300   //
7301 
7302   // if the transport is not open, then there is no need process it further
7303   if (!transport.IsOpen())
7304     return FALSE;
7305 
7306   // make sure have a minimum headroom in the PDU buffer
7307   PINDEX pduSize = pduBuffer.GetSize();
7308   if ((pduSize - pduDataLen) < 100) {
7309     pduSize += 1000;
7310     pduBuffer.SetSize(pduSize);
7311   }
7312 
7313   // save the timeout
7314   PTimeInterval oldTimeout = transport.GetReadTimeout();
7315   transport.SetReadTimeout(0);
7316 
7317   // read PDU until no more data is available
7318   PINDEX numRead = 0;
7319   PBoolean ok = TRUE;
7320   {
7321     char * ptr = (char *)(pduBuffer.GetPointer() + pduDataLen);
7322     int lenLeftInBuffer = pduSize - pduDataLen;
7323     while (ok && (lenLeftInBuffer > numRead) && transport.Read(ptr + numRead, lenLeftInBuffer - numRead)) {
7324       ok = transport.GetLastReadCount() > 0;
7325       if (ok)
7326         numRead += transport.GetLastReadCount();
7327     }
7328     if (pduBuffer[0] != 0x03) {
7329       PTRACE(1, "Error");
7330       ok = FALSE;
7331     }
7332   }
7333 
7334   // reset timeout
7335   transport.SetReadTimeout(oldTimeout);
7336 
7337   // if data was actually received, then process it
7338   if (ok) {
7339 
7340     // if PDU length was zero, must be timeout
7341     if (numRead == 0) {
7342       PBYTEArray dataPDU;
7343       ok = HandlePDU(FALSE, dataPDU);
7344     }
7345 
7346     else {
7347 
7348       // update pdu size for new data that was read
7349       pduDataLen += numRead;
7350 
7351       while (pduDataLen > 0) {
7352 
7353         // convert data to PDU. If PDU is invalid, return error
7354         PINDEX pduLen = pduDataLen;
7355         if (!transport.ExtractPDU(pduBuffer, pduLen)) {
7356           ok = FALSE;
7357           break;
7358         }
7359 
7360         // if PDU is not yet complete, then no error but stop looping
7361         else if (pduLen <= 0) {
7362           ok = TRUE;
7363           break;
7364         }
7365 
7366         // otherwise process the data
7367         else {
7368           transport.SetErrorValues(PChannel::NoError, 0, PChannel::LastReadError);
7369           {
7370             // create the new PDU
7371             PBYTEArray dataPDU((const BYTE *)pduBuffer+4, pduLen-4, FALSE);
7372             ok = HandlePDU(ok, dataPDU);
7373           }
7374 
7375           // remove processed data
7376           if (pduLen == pduDataLen)
7377             pduDataLen = 0;
7378           else {
7379             pduDataLen -= pduLen;
7380             memcpy(pduBuffer.GetPointer(), pduBuffer.GetPointer() + pduLen, pduDataLen);
7381           }
7382         }
7383       }
7384     }
7385   }
7386 
7387 
7388   return ok;
7389 }
7390 
7391 #endif
7392 
7393 #ifdef H323_H248
7394 
OnSendServiceControlSessions(H225_ArrayOf_ServiceControlSession & serviceControl,H225_ServiceControlSession_reason reason) const7395 PBoolean H323Connection::OnSendServiceControlSessions(
7396                    H225_ArrayOf_ServiceControlSession & serviceControl,
7397                    H225_ServiceControlSession_reason reason) const
7398 {
7399 
7400     PString amount;
7401     PBoolean credit=TRUE;
7402     unsigned time=0;
7403     PString url;
7404 
7405     if (!OnSendServiceControl(amount, credit,time, url) &&
7406                         (serviceControlSessions.GetSize() == 0))
7407         return FALSE;
7408 
7409     H323Dictionary<POrdinalKey, H323ServiceControlSession> SCS = serviceControlSessions;
7410 
7411     if (!amount) {
7412         H323CallCreditServiceControl * csc =
7413                  new H323CallCreditServiceControl(amount,credit,time);
7414         SCS.SetAt(H323ServiceControlSession::e_CallCredit, csc);
7415     }
7416 
7417     if (!url) {
7418         H323HTTPServiceControl * scs = new H323HTTPServiceControl(url);
7419         SCS.SetAt(H323ServiceControlSession::e_URL, scs);
7420     }
7421 
7422     for (PINDEX j = 0; j < SCS.GetSize(); j++) {
7423 
7424       PINDEX last = serviceControl.GetSize();
7425       serviceControl.SetSize(last+1);
7426       H225_ServiceControlSession & pdu = serviceControl[last];
7427 
7428       unsigned type = ((H323ServiceControlSession *)SCS.GetAt(j))->GetType();
7429       pdu.m_sessionId = type;
7430       pdu.m_reason = reason;
7431 
7432       if (SCS[type].OnSendingPDU(pdu.m_contents))
7433         pdu.IncludeOptionalField(H225_ServiceControlSession::e_contents);
7434 
7435     }
7436 
7437    return TRUE;
7438 }
7439 
OnReceiveServiceControlSessions(const H225_ArrayOf_ServiceControlSession & serviceControl)7440 void H323Connection::OnReceiveServiceControlSessions(const H225_ArrayOf_ServiceControlSession & serviceControl)
7441 {
7442 
7443   PBoolean isContent=FALSE;
7444 
7445   for (PINDEX i = 0; i < serviceControl.GetSize(); i++) {
7446     H225_ServiceControlSession & pdu = serviceControl[i];
7447 
7448     H323ServiceControlSession * session = NULL;
7449     unsigned sessionId = pdu.m_sessionId;
7450 
7451     if (serviceControlSessions.Contains(sessionId)) {
7452       session = &serviceControlSessions[sessionId];
7453       if (pdu.HasOptionalField(H225_ServiceControlSession::e_contents)) {
7454           if (session->OnReceivedPDU(pdu.m_contents))
7455               isContent = TRUE;
7456       }
7457     }
7458 
7459     if (session == NULL && pdu.HasOptionalField(H225_ServiceControlSession::e_contents)) {
7460       session = endpoint.CreateServiceControlSession(pdu.m_contents);
7461       serviceControlSessions.SetAt(sessionId, session);
7462     }
7463   }
7464 
7465   if (isContent) {
7466     PString amount;
7467     PBoolean credit=TRUE;
7468     unsigned time;
7469     PString url;
7470     PString ldapURL;
7471     PString baseDN;
7472 
7473     for (PINDEX j = 0; j < serviceControlSessions.GetSize(); j++) {
7474       H323ServiceControlSession & sess = serviceControlSessions[j];
7475       switch (sess.GetType()) {
7476          case H323ServiceControlSession::e_CallCredit:
7477             ((H323CallCreditServiceControl &)sess).GetValue(amount,credit,time);
7478                  break;
7479          case H323ServiceControlSession::e_URL:
7480             ((H323HTTPServiceControl &)sess).GetValue(url);
7481                 break;
7482 #ifdef H323_H350
7483          case H323ServiceControlSession::e_NonStandard:
7484             ((H323H350ServiceControl &)sess).GetValue(ldapURL,baseDN);
7485                 break;
7486 #endif
7487          default:
7488                 break;
7489       }
7490     }
7491     OnReceiveServiceControl(amount,credit,time,url,ldapURL,baseDN);
7492   }
7493 }
7494 
OnReceiveServiceControl(const PString & amount,PBoolean credit,const unsigned & timelimit,const PString & url,const PString & ldapURL,const PString & baseDN)7495 void H323Connection::OnReceiveServiceControl(const PString & amount,
7496                                              PBoolean credit,
7497                                              const unsigned & timelimit,
7498                                              const PString & url,
7499                                              const PString & ldapURL,
7500                                              const PString & baseDN
7501                                             )
7502 {
7503     if (!amount)
7504         endpoint.OnCallCreditServiceControl(amount,credit,timelimit);
7505 
7506     if (!url)
7507         endpoint.OnHTTPServiceControl(0, 0, url);
7508 
7509 #ifdef H323_H350
7510     if (!ldapURL)
7511         endpoint.OnH350ServiceControl(ldapURL,baseDN);
7512 #endif
7513 }
7514 
OnSendServiceControl(PString &,PBoolean,unsigned &,PString &) const7515 PBoolean H323Connection::OnSendServiceControl(PString & /*amount*/,
7516                                           PBoolean /*credit*/,
7517                                           unsigned & /*timelimit*/,
7518                                           PString & /*url*/
7519                                          ) const
7520 {
7521     return FALSE;
7522 }
7523 
7524 #endif
7525 
DisableH245inSETUP()7526 void H323Connection::DisableH245inSETUP()
7527 {
7528     doH245inSETUP = FALSE;
7529 }
7530 
DisableH245QoS()7531 void H323Connection::DisableH245QoS()
7532 {
7533     doH245QoS = FALSE;
7534 }
7535 
H245QoSEnabled() const7536 PBoolean H323Connection::H245QoSEnabled() const
7537 {
7538     return doH245QoS;
7539 }
7540 
SetNonCallConnection()7541 void H323Connection::SetNonCallConnection()
7542 {
7543     nonCallConnection = TRUE;
7544 }
7545 
IsNonCallConnection() const7546 PBoolean H323Connection::IsNonCallConnection() const
7547 {
7548     return nonCallConnection;
7549 }
7550 
7551 #ifdef H323_H460
GetFeatureSet()7552 H460_FeatureSet * H323Connection::GetFeatureSet()
7553 {
7554     return features;
7555 }
7556 
FeatureSetSupportNonCallService(const H225_FeatureSet & fs) const7557 PBoolean H323Connection::FeatureSetSupportNonCallService(const H225_FeatureSet & fs) const
7558 {
7559     return (features && features->SupportNonCallService(fs));
7560 }
7561 #endif
7562 
7563 #ifdef H323_VIDEO
7564 #ifdef H323_H239
AcceptH239ControlRequest(PBoolean & delay)7565 PBoolean H323Connection::AcceptH239ControlRequest(PBoolean & delay)
7566 {
7567     delay = false;
7568     return true;
7569 }
7570 
OnH239ControlRequest(H239Control * ctrl)7571 PBoolean H323Connection::OnH239ControlRequest(H239Control * ctrl)
7572 {
7573     if (!ctrl)
7574         return false;
7575 
7576     PBoolean delay = false;
7577     if (AcceptH239ControlRequest(delay)) {
7578       if (delay) return true;
7579       return ctrl->SendGenericMessage(H239Control::e_h245response, this, true);
7580     }  else
7581       return ctrl->SendGenericMessage(H239Control::e_h245response, this, false);
7582 }
7583 
OnH239ControlCommand(H239Control * ctrl)7584 PBoolean H323Connection::OnH239ControlCommand(H239Control * ctrl)
7585 {
7586     return true;
7587 }
7588 
OpenH239Channel()7589 PBoolean H323Connection::OpenH239Channel()
7590 {
7591    if (callToken.IsEmpty()) {
7592       PTRACE(2,"H239\tERROR Open Channel. Not in a call");
7593       return false;
7594    }
7595 
7596    H239Control * ctrl = (H239Control *)remoteCapabilities.FindCapability("H.239 Control");
7597    if (ctrl)
7598       return ctrl->SendGenericMessage(H239Control::e_h245request, this);
7599 
7600    PTRACE(2,"H239\tERROR Open Channel. No Remote Support");
7601    return false;
7602 }
7603 
CloseH239Channel(H323Capability::CapabilityDirection dir)7604 PBoolean H323Connection::CloseH239Channel(H323Capability::CapabilityDirection dir)
7605 {
7606   H239Control * ctrl = (H239Control *)remoteCapabilities.FindCapability("H.239 Control");
7607   if (ctrl)
7608      return ctrl->CloseChannel(this, dir);
7609 
7610   return false;
7611 }
7612 
OnH239SessionStarted(int sessionNum,H323Capability::CapabilityDirection dir)7613 void H323Connection::OnH239SessionStarted(int sessionNum, H323Capability::CapabilityDirection dir)
7614 {
7615   if (!sessionNum)
7616       return;
7617 
7618   H239Control * ctrl = (H239Control *)remoteCapabilities.FindCapability("H.239 Control");
7619   if (ctrl)
7620      return ctrl->SetChannelNum(sessionNum,dir);
7621 }
7622 
OnH239SessionEnded(int sessionNum,H323Capability::CapabilityDirection dir)7623 void H323Connection::OnH239SessionEnded(int sessionNum, H323Capability::CapabilityDirection dir)
7624 {
7625   if (!sessionNum)
7626       return;
7627 
7628   H239Control * ctrl = (H239Control *)remoteCapabilities.FindCapability("H.239 Control");
7629   if (ctrl)
7630      return ctrl->SetChannelNum(0,dir);
7631 }
7632 
OpenExtendedVideoSessionDenied()7633 void H323Connection::OpenExtendedVideoSessionDenied()
7634 {
7635     PTRACE(2,"H239\tOpen Request denied from remote");
7636 }
7637 
OpenExtendedVideoSession(H323ChannelNumber & num,int defaultSession)7638 PBoolean H323Connection::OpenExtendedVideoSession(H323ChannelNumber & num, int defaultSession)
7639 {
7640   PBoolean applicationOpen = false;
7641   // First need to check if extended video channel is opened
7642   if (logicalChannels->FindChannelBySession(OpalMediaFormat::DefaultExtVideoSessionID, false) ||
7643       logicalChannels->FindChannelBySession(defaultSession, false)) {// is opened
7644     PTRACE(3, "Extended video channel is opened, no need open it");
7645     return true;
7646   }
7647 
7648   // extended video channel is not opened, try to open it
7649   for (PINDEX i = 0; i < localCapabilities.GetSize(); i++) {
7650     H323Capability & localCapability = localCapabilities[i];
7651     if ((localCapability.GetMainType() == H323Capability::e_Video) &&
7652         (localCapability.GetSubType() == H245_VideoCapability::e_extendedVideoCapability)) {
7653       H323ExtendedVideoCapability * remoteCapability = (H323ExtendedVideoCapability *)remoteCapabilities.FindCapability(localCapability);
7654       if (remoteCapability != NULL) {
7655         PTRACE(3, "H323\tApplication Available " << *remoteCapability);
7656 
7657 #ifdef H323_H235
7658         H323SecureExtendedCapability* secureCap = dynamic_cast<H323SecureExtendedCapability*>(remoteCapability);
7659         if (secureCap) { // this is case of H.235
7660           if (logicalChannels->Open(*secureCap, defaultSession, num)) {
7661              applicationOpen = TRUE;
7662              break;
7663           } else {
7664              PTRACE(2, "H323\tApplication OpenLogicalChannel failed: " << *secureCap);
7665           }
7666         } else
7667 #endif
7668         { // this is case of normal
7669           for (PINDEX j = 0; j < remoteCapability->GetSize(); j++) {
7670             if (logicalChannels->Open(remoteCapability[j], defaultSession, num)) {
7671                applicationOpen = TRUE;
7672                break;
7673             } else {
7674                PTRACE(2, "H323\tApplication OpenLogicalChannel failed: " << *remoteCapability);
7675             }
7676           }
7677         }
7678         if (applicationOpen)
7679             break;
7680       }
7681     }
7682   }
7683   return applicationOpen;
7684 }
7685 
CloseExtendedVideoSession(const H323ChannelNumber & num)7686 PBoolean H323Connection::CloseExtendedVideoSession(const H323ChannelNumber & num)
7687 {
7688     CloseLogicalChannel(num, num.IsFromRemote());
7689     return TRUE;
7690 }
7691 
OpenExtendedVideoChannel(PBoolean isEncoding,H323VideoCodec & codec)7692 PBoolean H323Connection::OpenExtendedVideoChannel(PBoolean isEncoding,H323VideoCodec & codec)
7693 {
7694    return endpoint.OpenExtendedVideoChannel(*this, isEncoding, codec);
7695 }
7696 
GetExtVideoRTPSessionID() const7697 unsigned H323Connection::GetExtVideoRTPSessionID() const
7698 {
7699   if (IsH245Master()) {
7700     return 32;  // TODO: make a constant ?
7701   } else {
7702     return h239SessionID;
7703   }
7704 }
7705 
7706 #endif  // H323_H239
7707 #endif  // NO_H323_VIDEO
7708 
7709 #ifdef H323_H230
OpenConferenceControlSession(PBoolean & chairControl,PBoolean & extControls)7710 PBoolean H323Connection::OpenConferenceControlSession(PBoolean & chairControl, PBoolean & extControls)
7711 {
7712   chairControl = FALSE;
7713   extControls = FALSE;
7714   for (PINDEX i = 0; i < localCapabilities.GetSize(); i++) {
7715     H323Capability & localCapability = localCapabilities[i];
7716     if (localCapability.GetMainType() == H323Capability::e_ConferenceControl) {
7717       H323_ConferenceControlCapability * remoteCapability = (H323_ConferenceControlCapability *)remoteCapabilities.FindCapability(localCapability);
7718       if (remoteCapability != NULL) {
7719           chairControl = remoteCapability->SupportChairControls();
7720           extControls = remoteCapability->SupportExtControls();
7721           PTRACE(3, "H323\tConference Controls Available for " << GetCallToken() << " Chair " << chairControl << " T124 " << extControls);
7722           return TRUE;
7723       }
7724     }
7725   }
7726   PTRACE(4, "H323\tConference Controls not available for " << GetCallToken());
7727   return FALSE;
7728 }
7729 
7730 #endif  // H323_H230
7731 
7732 #ifdef H323_FRAMEBUFFER
EnableVideoFrameBuffer(PBoolean enable)7733 void H323Connection::EnableVideoFrameBuffer(PBoolean enable)
7734 {
7735     endpoint.EnableVideoFrameBuffer(enable);
7736 }
7737 
HasVideoFrameBuffer()7738 PBoolean H323Connection::HasVideoFrameBuffer()
7739 {
7740     return endpoint.HasVideoFrameBuffer();
7741 }
7742 #endif
7743 
IsMaintainedConnection() const7744 PBoolean H323Connection::IsMaintainedConnection() const
7745 {
7746    return m_maintainConnection;
7747 }
7748 
7749 /////////////////////////////////////////////////////////////////////////////
7750 
7751