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