1 /*
2  * gkclient.cxx
3  *
4  * Gatekeeper client protocol handler
5  *
6  * Open H323 Library
7  *
8  * Copyright (c) 1999-2000 Equivalence Pty. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Open H323 Library.
21  *
22  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23  *
24  * Portions of this code were written with the assisance of funding from
25  * iFace In, http://www.iface.com
26  *
27  * Contributor(s): ______________________________________.
28  *
29  * $Id$
30  *
31  */
32 
33 #include <ptlib.h>
34 
35 #ifdef __GNUC__
36 #pragma implementation "gkclient.h"
37 #endif
38 
39 #if defined(_WIN32) && (_MSC_VER > 1300)
40   #pragma warning(disable:4244) // warning about possible loss of data
41 #endif
42 
43 #include "gkclient.h"
44 
45 #include "h323ep.h"
46 #include "h323rtp.h"
47 #include "h323pdu.h"
48 
49 #ifdef H323_H460
50 #include "h460/h4601.h"
51 #endif
52 
53 #ifdef H323_H46017
54 #include "h460/h460_std17.h"
55 #endif
56 
57 #define new PNEW
58 
59 
AdjustTimeout(unsigned seconds)60 static PTimeInterval AdjustTimeout(unsigned seconds)
61 {
62   // Allow for an incredible amount of system/network latency
63   static unsigned TimeoutDeadband = 5; // seconds
64 
65   return PTimeInterval(0, seconds > TimeoutDeadband
66                               ? (seconds - TimeoutDeadband)
67                               : TimeoutDeadband);
68 }
69 
70 
71 /////////////////////////////////////////////////////////////////////////////
72 
H323Gatekeeper(H323EndPoint & ep,H323Transport * trans)73 H323Gatekeeper::H323Gatekeeper(H323EndPoint & ep, H323Transport * trans)
74   : H225_RAS(ep, trans),
75     requestMutex(1, 1),
76     authenticators(ep.CreateAuthenticators())
77 #ifdef H323_H460
78     ,features(ep.GetFeatureSet())
79 #endif
80 {
81   alternatePermanent = FALSE;
82   discoveryComplete = FALSE;
83   moveAlternate = FALSE;
84   registrationFailReason = UnregisteredLocally;
85 
86   pregrantMakeCall = pregrantAnswerCall = RequireARQ;
87 
88   autoReregister = TRUE;
89   reregisterNow = FALSE;
90   requiresDiscovery = FALSE;
91 
92   timeToLive.SetNotifier(PCREATE_NOTIFIER(TickleMonitor));
93   infoRequestRate.SetNotifier(PCREATE_NOTIFIER(TickleMonitor));
94 
95   willRespondToIRR = FALSE;
96   monitorStop = FALSE;
97 
98   monitor = PThread::Create(PCREATE_NOTIFIER(MonitorMain), 0,
99                             PThread::NoAutoDeleteThread,
100                             PThread::NormalPriority,
101                             "GkMonitor:%x");
102 #ifdef H323_H460
103   features->AttachEndPoint(&ep);
104   features->LoadFeatureSet(H460_Feature::FeatureRas);
105 #endif
106 
107   localId = PString();
108 }
109 
110 
~H323Gatekeeper()111 H323Gatekeeper::~H323Gatekeeper()
112 {
113   if (monitor != NULL) {
114     monitorStop = TRUE;
115     monitorTickle.Signal();
116     monitor->WaitForTermination();
117     delete monitor;
118   }
119 #ifdef H323_H460
120   delete features;
121 #endif
122 
123   StopChannel();
124 }
125 
126 
GetName() const127 PString H323Gatekeeper::GetName() const
128 {
129   PStringStream s;
130   s << *this;
131   return s;
132 }
133 
134 
DiscoverAny()135 PBoolean H323Gatekeeper::DiscoverAny()
136 {
137   gatekeeperIdentifier = PString();
138   return StartDiscovery(H323TransportAddress());
139 }
140 
141 
DiscoverByName(const PString & identifier)142 PBoolean H323Gatekeeper::DiscoverByName(const PString & identifier)
143 {
144   gatekeeperIdentifier = identifier;
145   return StartDiscovery(H323TransportAddress());
146 }
147 
148 
DiscoverByAddress(const H323TransportAddress & address)149 PBoolean H323Gatekeeper::DiscoverByAddress(const H323TransportAddress & address)
150 {
151   gatekeeperIdentifier = PString();
152   return StartDiscovery(address);
153 }
154 
155 
DiscoverByNameAndAddress(const PString & identifier,const H323TransportAddress & address)156 PBoolean H323Gatekeeper::DiscoverByNameAndAddress(const PString & identifier,
157                                               const H323TransportAddress & address)
158 {
159   gatekeeperIdentifier = identifier;
160   return StartDiscovery(address);
161 }
162 
StartDiscovery(const H323TransportAddress & initialAddress)163 PBoolean H323Gatekeeper::StartDiscovery(const H323TransportAddress & initialAddress)
164 {
165   if (PAssertNULL(transport) == NULL)
166     return FALSE;
167 
168   /// don't send GRQ if not requested
169   if (!endpoint.GetSendGRQ() && !initialAddress.IsEmpty()) {
170     transport->SetRemoteAddress(initialAddress);
171     if (!transport->Connect()) {
172       PTRACE(2, "RAS\tUnable to connect to gatekeeper at " << initialAddress);
173       return FALSE;
174     }
175     transport->SetPromiscuous(H323Transport::AcceptFromRemoteOnly);
176     StartChannel();
177     PTRACE(2, "RAS\tSkipping gatekeeper discovery for " << initialAddress);
178     return TRUE;
179   }
180 
181   H323RasPDU pdu;
182   Request request(SetupGatekeeperRequest(pdu), pdu);
183 
184   H323TransportAddress address = initialAddress;
185   request.responseInfo = &address;
186 
187   requestsMutex.Wait();
188   requests.SetAt(request.sequenceNumber, &request);
189   requestsMutex.Signal();
190 
191   discoveryComplete = FALSE;
192   unsigned retries = endpoint.GetGatekeeperRequestRetries();
193   while (!discoveryComplete) {
194     if (transport->DiscoverGatekeeper(*this, pdu, address)) {
195       if (address == initialAddress)
196         break;
197       /// If get here must have been GRJ with an alternate gk, start again
198     }
199     else {
200       // Transport failure, retry
201       if (--retries == 0)
202         break;
203     }
204   }
205 
206   requestsMutex.Wait();
207   requests.SetAt(request.sequenceNumber, NULL);
208   requestsMutex.Signal();
209 
210   if (discoveryComplete) {
211     if (transport->Connect())
212       StartChannel();
213   }
214 
215   return discoveryComplete;
216 }
217 
218 
SetupGatekeeperRequest(H323RasPDU & request)219 unsigned H323Gatekeeper::SetupGatekeeperRequest(H323RasPDU & request)
220 {
221   if (PAssertNULL(transport) == NULL)
222     return 0;
223 
224   H225_GatekeeperRequest & grq = request.BuildGatekeeperRequest(GetNextSequenceNumber());
225 
226   endpoint.SetEndpointTypeInfo(grq.m_endpointType);
227   transport->SetUpTransportPDU(grq.m_rasAddress, TRUE);
228 
229   grq.IncludeOptionalField(H225_GatekeeperRequest::e_endpointAlias);
230   H323SetAliasAddresses(endpoint.GetAliasNames(), grq.m_endpointAlias);
231 
232   if (!gatekeeperIdentifier) {
233     grq.IncludeOptionalField(H225_GatekeeperRequest::e_gatekeeperIdentifier);
234     grq.m_gatekeeperIdentifier = gatekeeperIdentifier;
235   }
236 
237   grq.IncludeOptionalField(H225_GatekeeperRequest::e_supportsAltGK);
238 
239   grq.IncludeOptionalField(H225_GatekeeperRequest::e_supportsAssignedGK);
240   grq.m_supportsAssignedGK = TRUE;
241 
242   OnSendGatekeeperRequest(grq);
243 
244   discoveryComplete = FALSE;
245 
246   return grq.m_requestSeqNum;
247 }
248 
249 
OnSendGatekeeperRequest(H225_GatekeeperRequest & grq)250 void H323Gatekeeper::OnSendGatekeeperRequest(H225_GatekeeperRequest & grq)
251 {
252   H225_RAS::OnSendGatekeeperRequest(grq);
253 
254   for (PINDEX i = 0; i < authenticators.GetSize(); i++) {
255     if (authenticators[i].SetCapability(grq.m_authenticationCapability, grq.m_algorithmOIDs)) {
256       grq.IncludeOptionalField(H225_GatekeeperRequest::e_authenticationCapability);
257       grq.IncludeOptionalField(H225_GatekeeperRequest::e_algorithmOIDs);
258     }
259   }
260 }
261 
262 
OnReceiveGatekeeperConfirm(const H225_GatekeeperConfirm & gcf)263 PBoolean H323Gatekeeper::OnReceiveGatekeeperConfirm(const H225_GatekeeperConfirm & gcf)
264 {
265   if (!H225_RAS::OnReceiveGatekeeperConfirm(gcf))
266     return FALSE;
267 
268   PINDEX i;
269 
270   for (i = 0; i < authenticators.GetSize(); i++) {
271     H235Authenticator & authenticator = authenticators[i];
272     if (authenticator.UseGkAndEpIdentifiers())
273       authenticator.SetRemoteId(gatekeeperIdentifier);
274   }
275 
276   if (gcf.HasOptionalField(H225_GatekeeperConfirm::e_authenticationMode) &&
277       gcf.HasOptionalField(H225_GatekeeperConfirm::e_algorithmOID)) {
278     for (i = 0; i < authenticators.GetSize(); i++) {
279       H235Authenticator & authenticator = authenticators[i];
280       authenticator.Enable(authenticator.IsCapability(gcf.m_authenticationMode,
281                                                       gcf.m_algorithmOID));
282       PTRACE(4,"RAS\tAuthenticator " << authenticator.GetName()
283                       << (authenticator.IsActive() ? " ACTIVATED" : " disabled"));
284     }
285   }
286 
287   H323TransportAddress locatedAddress = gcf.m_rasAddress;
288   PTRACE(2, "RAS\tGatekeeper discovery found " << locatedAddress);
289 
290   if (!transport->SetRemoteAddress(locatedAddress)) {
291     PTRACE(2, "RAS\tInvalid gatekeeper discovery address: \"" << locatedAddress << '"');
292     return FALSE;
293   }
294 
295   if (gcf.HasOptionalField(H225_GatekeeperConfirm::e_alternateGatekeeper))
296     SetAlternates(gcf.m_alternateGatekeeper, FALSE);
297 
298   if (gcf.HasOptionalField(H225_GatekeeperConfirm::e_assignedGatekeeper)) {
299     SetAssignedGatekeeper(gcf.m_assignedGatekeeper);
300   }
301   // switch if we are assigned to another gatekeeper, stay if its already the right one
302   H323TransportAddress assignedGKIP(assignedGK.rasAddress); // convert H225_TransportAddress into H323TransportAddress
303   if (gcf.HasOptionalField(H225_GatekeeperConfirm::e_assignedGatekeeper) && assignedGKIP != locatedAddress) {
304     // TODO: we still might have to register with this gatekeeper, because the assigned gatekeeper might be down
305     // TODO: start a background thread to check assigned gatekeeper availability, unless re-homing model is server-based
306     PTRACE(2, "RAS\tAssigned Gatekeeper redirected " << assignedGK);
307     // This will force the gatekeeper to register to the assigned Gatekeeper.
308     if (lastRequest->responseInfo != NULL) {
309       H323TransportAddress & gkAddress = *(H323TransportAddress *)lastRequest->responseInfo;
310       gkAddress = assignedGK.rasAddress;
311       gatekeeperIdentifier = PString();
312     }
313   } else {
314     endpoint.OnGatekeeperConfirm();
315     discoveryComplete = TRUE;
316   }
317   return TRUE;
318 }
319 
320 
OnReceiveGatekeeperReject(const H225_GatekeeperReject & grj)321 PBoolean H323Gatekeeper::OnReceiveGatekeeperReject(const H225_GatekeeperReject & grj)
322 {
323   if (!H225_RAS::OnReceiveGatekeeperReject(grj))
324     return FALSE;
325 
326   if (grj.HasOptionalField(H225_GatekeeperReject::e_altGKInfo)) {
327     SetAlternates(grj.m_altGKInfo.m_alternateGatekeeper,
328                   grj.m_altGKInfo.m_altGKisPermanent);
329   }
330 
331   if ((alternates.GetSize() > 0) && (lastRequest->responseInfo != NULL)) {
332       H323TransportAddress & gkAddress = *(H323TransportAddress *)lastRequest->responseInfo;
333       gkAddress = alternates[0].rasAddress;
334   }
335 
336   endpoint.OnGatekeeperReject();
337 
338   return TRUE;
339 }
340 
341 
RegistrationRequest(PBoolean autoReg)342 PBoolean H323Gatekeeper::RegistrationRequest(PBoolean autoReg)
343 {
344   PWaitAndSignal m(RegisterMutex);
345 
346   if (PAssertNULL(transport) == NULL)
347     return FALSE;
348 
349   autoReregister = autoReg;
350 
351   H323RasPDU pdu;
352   H225_RegistrationRequest & rrq = pdu.BuildRegistrationRequest(GetNextSequenceNumber());
353 
354   // If discoveryComplete flag is FALSE then do lightweight reregister
355   rrq.m_discoveryComplete = discoveryComplete;
356 
357   // Check if the IP address might of changed since last registration (for DDNS Type registrations)
358   H323TransportAddress newaddress;
359   if ((!discoveryComplete) && (endpoint.GatekeeperCheckIP(transport->GetRemoteAddress(),newaddress)))
360       transport->SetRemoteAddress(newaddress);
361 
362   if (transport->IsRASTunnelled()) {
363       rrq.IncludeOptionalField(H225_RegistrationRequest::e_maintainConnection);
364       rrq.m_maintainConnection = true;
365   } else {
366       rrq.m_rasAddress.SetSize(1);
367       transport->SetUpTransportPDU(rrq.m_rasAddress[0], TRUE);
368 
369       H323TransportAddressArray listeners = endpoint.GetInterfaceAddresses(TRUE, transport);
370       if (listeners.IsEmpty()) {
371         PTRACE(1, "RAS\tCannot register with Gatekeeper without a H323Listener!");
372         return FALSE;
373       }
374 
375       H323SetTransportAddresses(*transport, listeners, rrq.m_callSignalAddress);
376   }
377 
378   endpoint.SetEndpointTypeInfo(rrq.m_terminalType);
379   endpoint.SetVendorIdentifierInfo(rrq.m_endpointVendor);
380 
381   if (!IsRegistered()) {  // only send terminal aliases on full registration reset localId
382     rrq.IncludeOptionalField(H225_RegistrationRequest::e_terminalAlias);
383     H323SetAliasAddresses(endpoint.GetAliasNames(), rrq.m_terminalAlias);
384         for (PINDEX i = 0; i < authenticators.GetSize(); i++) {
385             H235Authenticator & authenticator = authenticators[i];
386             if (authenticator.UseGkAndEpIdentifiers())
387                 authenticator.SetLocalId(localId);
388         }
389   }
390 
391   rrq.m_willSupplyUUIEs = TRUE;
392   rrq.IncludeOptionalField(H225_RegistrationRequest::e_usageReportingCapability);
393   rrq.m_usageReportingCapability.IncludeOptionalField(H225_RasUsageInfoTypes::e_startTime);
394   rrq.m_usageReportingCapability.IncludeOptionalField(H225_RasUsageInfoTypes::e_endTime);
395   rrq.m_usageReportingCapability.IncludeOptionalField(H225_RasUsageInfoTypes::e_terminationCause);
396   rrq.IncludeOptionalField(H225_RegistrationRequest::e_supportsAltGK);
397 
398   if (!gatekeeperIdentifier) {
399     rrq.IncludeOptionalField(H225_RegistrationRequest::e_gatekeeperIdentifier);
400     rrq.m_gatekeeperIdentifier = gatekeeperIdentifier;
401   }
402 
403   if (!endpointIdentifier.GetValue().IsEmpty()) {
404     rrq.IncludeOptionalField(H225_RegistrationRequest::e_endpointIdentifier);
405     rrq.m_endpointIdentifier = endpointIdentifier;
406   }
407 
408   PTimeInterval ttl = endpoint.GetGatekeeperTimeToLive();
409   if (ttl > 0) {
410     rrq.IncludeOptionalField(H225_RegistrationRequest::e_timeToLive);
411     rrq.m_timeToLive = (int)ttl.GetSeconds();
412   }
413 
414   if (endpoint.CanDisplayAmountString()) {
415     rrq.IncludeOptionalField(H225_RegistrationRequest::e_callCreditCapability);
416     rrq.m_callCreditCapability.IncludeOptionalField(H225_CallCreditCapability::e_canDisplayAmountString);
417     rrq.m_callCreditCapability.m_canDisplayAmountString = TRUE;
418   }
419 
420   if (endpoint.CanEnforceDurationLimit()) {
421     rrq.IncludeOptionalField(H225_RegistrationRequest::e_callCreditCapability);
422     rrq.m_callCreditCapability.IncludeOptionalField(H225_CallCreditCapability::e_canEnforceDurationLimit);
423     rrq.m_callCreditCapability.m_canEnforceDurationLimit = TRUE;
424   }
425 
426   if (assignedGK.IsValid()) {
427       rrq.IncludeOptionalField(H225_RegistrationRequest::e_assignedGatekeeper);
428       rrq.m_assignedGatekeeper = assignedGK.GetAlternate();
429   }
430 
431   PStringList lang;
432   if (endpoint.GetDefaultLanguages(lang)) {
433       H323SetLanguages(lang,rrq.m_language);
434       rrq.IncludeOptionalField(H225_RegistrationRequest::e_language);
435   }
436 
437   if (IsRegistered()) {
438     rrq.IncludeOptionalField(H225_RegistrationRequest::e_keepAlive);
439     rrq.m_keepAlive = TRUE;
440   }
441 
442   // After doing full register, do lightweight reregisters from now on
443   discoveryComplete = FALSE;
444 
445   Request request(rrq.m_requestSeqNum, pdu);
446   if (MakeRequest(request))
447     return TRUE;
448 
449   PTRACE(3, "RAS\tFailed registration of " << endpointIdentifier << " with " << gatekeeperIdentifier);
450   switch (request.responseResult) {
451     case Request::RejectReceived :
452       switch (request.rejectReason) {
453         case H225_RegistrationRejectReason::e_discoveryRequired :
454           // If have been told by GK that we need to discover it again, set flag
455           // for next register done by timeToLive handler to do discovery
456           requiresDiscovery = TRUE;
457           // Do next case
458 
459         case H225_RegistrationRejectReason::e_fullRegistrationRequired :
460           registrationFailReason = GatekeeperLostRegistration;
461           endpointIdentifier = PString();  // Reset the endpoint Identifier
462           reregisterNow = TRUE;            // Set timer to retry registration
463           monitorTickle.Signal();
464           break;
465 
466         // Onse below here are permananent errors, so don't try again
467         case H225_RegistrationRejectReason::e_invalidCallSignalAddress :
468           registrationFailReason = InvalidListener;
469           break;
470 
471         case H225_RegistrationRejectReason::e_duplicateAlias :
472           registrationFailReason = DuplicateAlias;
473           break;
474 
475         case H225_RegistrationRejectReason::e_securityDenial :
476           registrationFailReason = SecurityDenied;
477           break;
478 
479         case H225_RegistrationRejectReason::e_neededFeatureNotSupported :
480           registrationFailReason = NeededFeatureNotSupported;
481           break;
482 
483         default :
484           registrationFailReason = (RegistrationFailReasons)(request.rejectReason|RegistrationRejectReasonMask);
485           break;
486       }
487       break;
488 
489     case Request::BadCryptoTokens :
490       registrationFailReason = SecurityDenied;
491       break;
492 
493     default :
494       registrationFailReason = TransportError;
495       break;
496   }
497 
498   return FALSE;
499 }
500 
501 
OnReceiveRegistrationConfirm(const H225_RegistrationConfirm & rcf)502 PBoolean H323Gatekeeper::OnReceiveRegistrationConfirm(const H225_RegistrationConfirm & rcf)
503 {
504   if (!H225_RAS::OnReceiveRegistrationConfirm(rcf))
505     return FALSE;
506 
507   registrationFailReason = RegistrationSuccessful;
508 
509   if (gatekeeperIdentifier.IsEmpty())
510         gatekeeperIdentifier = rcf.m_gatekeeperIdentifier.GetValue();
511 
512   if (endpointIdentifier.GetValue().IsEmpty())
513         endpointIdentifier = rcf.m_endpointIdentifier;
514 
515   PTRACE(3, "RAS\tRegistered " << endpointIdentifier.GetValue() << " with " << gatekeeperIdentifier);
516 
517   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_assignedGatekeeper))
518     SetAssignedGatekeeper(rcf.m_assignedGatekeeper);
519 
520   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_alternateGatekeeper))
521     SetAlternates(rcf.m_alternateGatekeeper, FALSE);
522 
523   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_timeToLive))
524     timeToLive = AdjustTimeout(rcf.m_timeToLive);
525   else
526     timeToLive = 0; // zero disables lightweight RRQ
527 
528   // At present only support first call signal address to GK
529   if (rcf.m_callSignalAddress.GetSize() > 0)
530     gkRouteAddress = rcf.m_callSignalAddress[0];
531 
532 #ifdef H323_IPV6
533   // Set to only resolve DNS addresses of the type supported by the signalling address of the gatekeeper.
534   if (PIPSocket::GetDefaultIpAddressFamily() == AF_INET6 && gkRouteAddress.GetIpVersion() != 6)
535        PIPSocket::SetDefaultIpAddressFamilyV4();
536 #endif
537 
538   willRespondToIRR = rcf.m_willRespondToIRR;
539 
540   pregrantMakeCall = pregrantAnswerCall = RequireARQ;
541   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_preGrantedARQ)) {
542     if (rcf.m_preGrantedARQ.m_makeCall)
543       pregrantMakeCall = rcf.m_preGrantedARQ.m_useGKCallSignalAddressToMakeCall
544                                                       ? PreGkRoutedARQ : PregrantARQ;
545     if (rcf.m_preGrantedARQ.m_answerCall)
546       pregrantAnswerCall = rcf.m_preGrantedARQ.m_useGKCallSignalAddressToAnswer
547                                                       ? PreGkRoutedARQ : PregrantARQ;
548     if (rcf.m_preGrantedARQ.HasOptionalField(H225_RegistrationConfirm_preGrantedARQ::e_irrFrequencyInCall))
549       SetInfoRequestRate(AdjustTimeout(rcf.m_preGrantedARQ.m_irrFrequencyInCall));
550     else
551       ClearInfoRequestRate();
552   }
553   else
554     ClearInfoRequestRate();
555 
556   // Remove the endpoint aliases that the gatekeeper did not like and add the
557   // ones that it really wants us to be.
558   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_terminalAlias) &&
559                           !endpoint.OnGatekeeperAliases(rcf.m_terminalAlias)) {
560     const PStringList & currentAliases = endpoint.GetAliasNames();
561     PStringList aliasesToChange;
562     PINDEX i, j;
563 
564     for (i = 0; i < rcf.m_terminalAlias.GetSize(); i++) {
565       PString alias = H323GetAliasAddressString(rcf.m_terminalAlias[i]);
566       if (!alias) {
567         for (j = 0; j < currentAliases.GetSize(); j++) {
568           if (alias *= currentAliases[j])
569             break;
570         }
571         if (j >= currentAliases.GetSize())
572           aliasesToChange.AppendString(alias);
573       }
574     }
575     for (i = 0; i < aliasesToChange.GetSize(); i++) {
576       PTRACE(2, "RAS\tGatekeeper add of alias \"" << aliasesToChange[i] << '"');
577       endpoint.AddAliasName(aliasesToChange[i]);
578     }
579 
580     aliasesToChange.RemoveAll();
581 
582     for (i = 0; i < currentAliases.GetSize(); i++) {
583       for (j = 0; j < rcf.m_terminalAlias.GetSize(); j++) {
584         if (currentAliases[i] *= H323GetAliasAddressString(rcf.m_terminalAlias[j]))
585           break;
586       }
587       if (j >= rcf.m_terminalAlias.GetSize())
588         aliasesToChange.AppendString(currentAliases[i]);
589     }
590     for (i = 0; i < aliasesToChange.GetSize(); i++) {
591       PTRACE(2, "RAS\tGatekeeper removal of alias \"" << aliasesToChange[i] << '"');
592       endpoint.RemoveAliasName(aliasesToChange[i]);
593     }
594   }
595 
596   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_language)) {
597       PStringList lang;
598       H323GetLanguages(lang,rcf.m_language);
599       endpoint.OnReceiveLanguages(lang);
600   }
601 
602 #ifdef H323_H248
603   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_serviceControl))
604     OnServiceControlSessions(rcf.m_serviceControl, NULL);
605 #endif
606 
607 // NAT Detection with GNUGK
608 #ifdef H323_GNUGK
609   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_nonStandardData))
610   {
611     PString NATaddr = rcf.m_nonStandardData.m_data.AsString();
612     if (!NATaddr.IsEmpty()) {
613       if (NATaddr.Left(4) == "NAT=") {
614         endpoint.OnGatekeeperNATDetect(PIPSocket::Address(NATaddr.Right(NATaddr.GetLength()-4)),endpointIdentifier.GetValue(),gkRouteAddress);
615       } else {
616         endpoint.OnGatekeeperOpenNATDetect(endpointIdentifier.GetValue(),gkRouteAddress);
617       }
618     }
619   }
620 #endif
621 
622   endpoint.OnRegistrationConfirm(gkRouteAddress);
623 
624   return TRUE;
625 }
626 
627 
OnReceiveRegistrationReject(const H225_RegistrationReject & rrj)628 PBoolean H323Gatekeeper::OnReceiveRegistrationReject(const H225_RegistrationReject & rrj)
629 {
630   if (!H225_RAS::OnReceiveRegistrationReject(rrj))
631     return FALSE;
632 
633   if (rrj.HasOptionalField(H225_RegistrationReject::e_assignedGatekeeper))
634      SetAssignedGatekeeper(rrj.m_assignedGatekeeper);
635   else if (rrj.HasOptionalField(H225_RegistrationReject::e_altGKInfo))
636     SetAlternates(rrj.m_altGKInfo.m_alternateGatekeeper,
637                   rrj.m_altGKInfo.m_altGKisPermanent);
638   else
639       endpoint.OnRegistrationReject();
640 
641   return TRUE;
642 }
643 
ReRegisterNow()644 void H323Gatekeeper::ReRegisterNow()
645 {
646   PTRACE(3, "RAS\tforcing reregistration");
647   RegistrationTimeToLive();
648 
649 }
650 
RegistrationTimeToLive()651 void H323Gatekeeper::RegistrationTimeToLive()
652 {
653   PTRACE(3, "RAS\tTime To Live reregistration");
654 
655   if (requiresDiscovery || moveAlternate) {
656     PTRACE(2, "RAS\tRepeating discovery on gatekeepers request.");
657 
658     H323RasPDU pdu;
659     Request request(SetupGatekeeperRequest(pdu), pdu);
660     request.SetUseAlternate(moveAlternate);
661     if (!MakeRequest(request) || (!discoveryComplete && !moveAlternate)) {
662       PTRACE(2, "RAS\tRediscovery failed, retrying in 1 minute.");
663       timeToLive = PTimeInterval(0, 0, 1);
664       return;
665     }
666     requiresDiscovery = FALSE;
667     moveAlternate = FALSE;
668     return;
669   }
670 
671   reregisterNow = FALSE;
672   if (!RegistrationRequest(autoReregister) && (!reregisterNow || !requiresDiscovery)) {
673     PTRACE(2,"RAS\tTime To Live reregistration failed, continue retrying.");
674     endpoint.OnRegisterTTLFail();
675 	if (timeToLive == 0) {
676       timeToLive = PTimeInterval(0, 0, 1);	// set a TTL oftherwise there won't be retries
677     }
678   }
679   reregisterNow = TRUE;
680 }
681 
682 
UnregistrationRequest(int reason)683 PBoolean H323Gatekeeper::UnregistrationRequest(int reason)
684 {
685   if (PAssertNULL(transport) == NULL)
686     return FALSE;
687 
688   H323RasPDU pdu;
689   H225_UnregistrationRequest & urq = pdu.BuildUnregistrationRequest(GetNextSequenceNumber());
690 
691   H225_TransportAddress rasAddress;
692   transport->SetUpTransportPDU(rasAddress, TRUE);
693 
694   H323SetTransportAddresses(*transport,
695                             endpoint.GetInterfaceAddresses(TRUE, transport),
696                             urq.m_callSignalAddress);
697 
698   urq.IncludeOptionalField(H225_UnregistrationRequest::e_endpointAlias);
699   H323SetAliasAddresses(endpoint.GetAliasNames(), urq.m_endpointAlias);
700 
701   if (!gatekeeperIdentifier) {
702     urq.IncludeOptionalField(H225_UnregistrationRequest::e_gatekeeperIdentifier);
703     urq.m_gatekeeperIdentifier = gatekeeperIdentifier;
704   }
705 
706   if (!endpointIdentifier.GetValue().IsEmpty()) {
707     urq.IncludeOptionalField(H225_UnregistrationRequest::e_endpointIdentifier);
708     urq.m_endpointIdentifier = endpointIdentifier;
709   }
710 
711   if (reason >= 0) {
712     urq.IncludeOptionalField(H225_UnregistrationRequest::e_reason);
713     urq.m_reason = reason;
714   }
715 
716   Request request(urq.m_requestSeqNum, pdu);
717   if (MakeRequest(request))
718     return TRUE;
719 
720   switch (request.responseResult) {
721     case Request::NoResponseReceived :
722       registrationFailReason = TransportError;
723       timeToLive = 0; // zero disables lightweight RRQ
724       break;
725 
726     case Request::BadCryptoTokens :
727       registrationFailReason = SecurityDenied;
728       timeToLive = 0; // zero disables lightweight RRQ
729       break;
730 
731     default :
732       break;
733   }
734 
735   return !IsRegistered();
736 }
737 
738 
OnReceiveUnregistrationConfirm(const H225_UnregistrationConfirm & ucf)739 PBoolean H323Gatekeeper::OnReceiveUnregistrationConfirm(const H225_UnregistrationConfirm & ucf)
740 {
741   if (!H225_RAS::OnReceiveUnregistrationConfirm(ucf))
742     return FALSE;
743 
744   registrationFailReason = UnregisteredLocally;
745   timeToLive = 0; // zero disables lightweight RRQ
746 
747   endpoint.OnUnRegisterConfirm();
748   return TRUE;
749 }
750 
751 
OnReceiveUnregistrationRequest(const H225_UnregistrationRequest & urq)752 PBoolean H323Gatekeeper::OnReceiveUnregistrationRequest(const H225_UnregistrationRequest & urq)
753 {
754   if (!H225_RAS::OnReceiveUnregistrationRequest(urq))
755     return FALSE;
756 
757   PTRACE(2, "RAS\tUnregistration received");
758   if (!urq.HasOptionalField(H225_UnregistrationRequest::e_gatekeeperIdentifier) ||
759        urq.m_gatekeeperIdentifier.GetValue() != gatekeeperIdentifier) {
760     PTRACE(1, "RAS\tInconsistent gatekeeperIdentifier!");
761     return FALSE;
762   }
763 
764   if (!urq.HasOptionalField(H225_UnregistrationRequest::e_endpointIdentifier) ||
765        urq.m_endpointIdentifier != endpointIdentifier) {
766     PTRACE(1, "RAS\tInconsistent endpointIdentifier!");
767     return FALSE;
768   }
769 
770   endpoint.ClearAllCalls(H323Connection::EndedByGatekeeper, FALSE);
771 
772   PTRACE(3, "RAS\tUnregistered, calls cleared");
773   registrationFailReason = UnregisteredByGatekeeper;
774 //  timeToLive = 0; // zero disables lightweight RRQ
775 
776   PBoolean retryRegister = true;
777 #ifdef H323_H460PRE
778   if (endpoint.IsPreempted())
779       retryRegister = false;
780 #endif
781 
782   if (retryRegister && urq.HasOptionalField(H225_UnregistrationRequest::e_alternateGatekeeper)) {
783     SetAlternates(urq.m_alternateGatekeeper, FALSE);
784     if (alternates.GetSize() > 0) {
785         PTRACE(2, "RAS\tTry Alternate Gatekeepers");
786         moveAlternate = true;
787     }
788   }
789 
790   H323RasPDU response(authenticators);
791   response.BuildUnregistrationConfirm(urq.m_requestSeqNum);
792   PBoolean ok = WritePDU(response);
793 
794   if (retryRegister && autoReregister) {
795     PTRACE(3, "RAS\tReregistering by setting timeToLive");
796     reregisterNow = TRUE;
797     monitorTickle.Signal();
798   } else
799     timeToLive = 0; // zero disables lightweight RRQ
800 
801   endpoint.OnUnRegisterRequest();
802 
803   return ok;
804 }
805 
806 
OnReceiveUnregistrationReject(const H225_UnregistrationReject & urj)807 PBoolean H323Gatekeeper::OnReceiveUnregistrationReject(const H225_UnregistrationReject & urj)
808 {
809   if (!H225_RAS::OnReceiveUnregistrationReject(urj))
810     return FALSE;
811 
812   if (lastRequest->rejectReason != H225_UnregRejectReason::e_callInProgress) {
813     registrationFailReason = UnregisteredLocally;
814     timeToLive = 0; // zero disables lightweight RRQ
815   }
816 
817   return TRUE;
818 }
819 
820 
LocationRequest(const PString & alias,H323TransportAddress & address)821 PBoolean H323Gatekeeper::LocationRequest(const PString & alias,
822                                      H323TransportAddress & address)
823 {
824   PStringList aliases;
825   aliases.AppendString(alias);
826   return LocationRequest(aliases, address);
827 }
828 
829 
LocationRequest(const PStringList & aliases,H323TransportAddress & address)830 PBoolean H323Gatekeeper::LocationRequest(const PStringList & aliases,
831                                      H323TransportAddress & address)
832 {
833   if (PAssertNULL(transport) == NULL)
834     return FALSE;
835 
836   H323RasPDU pdu;
837   H225_LocationRequest & lrq = pdu.BuildLocationRequest(GetNextSequenceNumber());
838 
839   H323SetAliasAddresses(aliases, lrq.m_destinationInfo);
840 
841   if (!endpointIdentifier.GetValue().IsEmpty()) {
842     lrq.IncludeOptionalField(H225_LocationRequest::e_endpointIdentifier);
843     lrq.m_endpointIdentifier = endpointIdentifier;
844   }
845 
846   transport->SetUpTransportPDU(lrq.m_replyAddress, TRUE);
847 
848   lrq.IncludeOptionalField(H225_LocationRequest::e_sourceInfo);
849   H323SetAliasAddresses(endpoint.GetAliasNames(), lrq.m_sourceInfo);
850 
851   if (!gatekeeperIdentifier) {
852     lrq.IncludeOptionalField(H225_LocationRequest::e_gatekeeperIdentifier);
853     lrq.m_gatekeeperIdentifier = gatekeeperIdentifier;
854   }
855 
856   Request request(lrq.m_requestSeqNum, pdu);
857   request.responseInfo = &address;
858   if (!MakeRequest(request))
859     return FALSE;
860 
861   // sanity check the address - some Gks return address 0.0.0.0 and port 0
862   PIPSocket::Address ipAddr;
863   WORD port = 0;
864   return address.GetIpAndPort(ipAddr, port) && (port != 0);
865 }
866 
867 
AdmissionResponse()868 H323Gatekeeper::AdmissionResponse::AdmissionResponse()
869 {
870   rejectReason = UINT_MAX;
871 
872   gatekeeperRouted = FALSE;
873   endpointCount = 1;
874   transportAddress = NULL;
875   accessTokenData = NULL;
876 
877   aliasAddresses = NULL;
878   destExtraCallInfo = NULL;
879 
880   languageSupport = NULL;
881 }
882 
883 
884 struct AdmissionRequestResponseInfo {
AdmissionRequestResponseInfoAdmissionRequestResponseInfo885   AdmissionRequestResponseInfo(
886     H323Gatekeeper::AdmissionResponse & r,
887     H323Connection & c
888   ) : param(r), connection(c), allocatedBandwidth(0), uuiesRequested(0) { }
889 
890   H323Gatekeeper::AdmissionResponse & param;
891   H323Connection & connection;
892   unsigned allocatedBandwidth;
893   unsigned uuiesRequested;
894   PString      accessTokenOID1;
895   PString      accessTokenOID2;
896 };
897 
898 
AdmissionRequest(H323Connection & connection,AdmissionResponse & response,PBoolean ignorePreGrantedARQ)899 PBoolean H323Gatekeeper::AdmissionRequest(H323Connection & connection,
900                                       AdmissionResponse & response,
901                                       PBoolean ignorePreGrantedARQ)
902 {
903   PBoolean answeringCall = connection.HadAnsweredCall();
904 
905   if (!ignorePreGrantedARQ) {
906     switch (answeringCall ? pregrantAnswerCall : pregrantMakeCall) {
907       case RequireARQ :
908         break;
909       case PregrantARQ :
910         return TRUE;
911       case PreGkRoutedARQ :
912         if (gkRouteAddress.IsEmpty()) {
913           response.rejectReason = UINT_MAX;
914           return FALSE;
915         }
916         if (response.transportAddress != NULL)
917           *response.transportAddress = gkRouteAddress;
918         response.gatekeeperRouted = TRUE;
919         return TRUE;
920     }
921   }
922 
923   H323RasPDU pdu;
924   H225_AdmissionRequest & arq = pdu.BuildAdmissionRequest(GetNextSequenceNumber());
925 
926   arq.m_callType.SetTag(H225_CallType::e_pointToPoint);
927   arq.m_endpointIdentifier = endpointIdentifier;
928   arq.m_answerCall = answeringCall;
929   arq.m_canMapAlias = TRUE; // Stack supports receiving a different number in the ACF
930                             // to the one sent in the ARQ
931   arq.m_willSupplyUUIEs = TRUE;
932 
933   if (!gatekeeperIdentifier) {
934     arq.IncludeOptionalField(H225_AdmissionRequest::e_gatekeeperIdentifier);
935     arq.m_gatekeeperIdentifier = gatekeeperIdentifier;
936   }
937 
938   PString destInfo = connection.GetRemotePartyName();
939   arq.m_srcInfo.SetSize(1);
940   if (answeringCall) {
941     H323SetAliasAddress(destInfo, arq.m_srcInfo[0]);
942     if (!connection.GetLocalPartyName()) {
943       arq.IncludeOptionalField(H225_AdmissionRequest::e_destinationInfo);
944       H323SetAliasAddresses(endpoint.GetAliasNames(), arq.m_destinationInfo);
945     }
946   }
947   else {
948     H323SetAliasAddresses(endpoint.GetAliasNames(), arq.m_srcInfo);
949     if (response.transportAddress == NULL || destInfo != *response.transportAddress) {
950       arq.IncludeOptionalField(H225_AdmissionRequest::e_destinationInfo);
951       arq.m_destinationInfo.SetSize(1);
952       H323SetAliasAddress(destInfo, arq.m_destinationInfo[0], -2);
953     }
954   }
955 
956   const H323Transport * signallingChannel = connection.GetSignallingChannel();
957   if (answeringCall) {
958     arq.IncludeOptionalField(H225_AdmissionRequest::e_srcCallSignalAddress);
959     signallingChannel->SetUpTransportPDU(arq.m_srcCallSignalAddress, FALSE);
960     arq.IncludeOptionalField(H225_AdmissionRequest::e_destCallSignalAddress);
961     signallingChannel->SetUpTransportPDU(arq.m_destCallSignalAddress, TRUE);
962   }
963   else {
964     if (signallingChannel != NULL && signallingChannel->IsOpen()) {
965       arq.IncludeOptionalField(H225_AdmissionRequest::e_srcCallSignalAddress);
966       signallingChannel->SetUpTransportPDU(arq.m_srcCallSignalAddress, TRUE);
967     }
968     if (response.transportAddress != NULL && !response.transportAddress->IsEmpty()) {
969       arq.IncludeOptionalField(H225_AdmissionRequest::e_destCallSignalAddress);
970       response.transportAddress->SetPDU(arq.m_destCallSignalAddress);
971     }
972   }
973 
974   arq.m_bandWidth = connection.GetBandwidthRequired();
975   arq.m_callReferenceValue = connection.GetCallReference();
976   arq.m_conferenceID = connection.GetConferenceIdentifier();
977   arq.m_callIdentifier.m_guid = connection.GetCallIdentifier();
978 
979 #ifdef H323_H450
980   connection.SetCallLinkage(pdu);
981 #endif
982 
983   AdmissionRequestResponseInfo info(response, connection);
984   info.accessTokenOID1 = connection.GetGkAccessTokenOID();
985   PINDEX comma = info.accessTokenOID1.Find(',');
986   if (comma == P_MAX_INDEX)
987     info.accessTokenOID2 = info.accessTokenOID1;
988   else {
989     info.accessTokenOID2 = info.accessTokenOID1.Mid(comma+1);
990     info.accessTokenOID1.Delete(comma, P_MAX_INDEX);
991   }
992 
993   connection.OnSendARQ(arq);
994 
995   Request request(arq.m_requestSeqNum, pdu);
996   request.responseInfo = &info;
997 
998   if (!authenticators.IsEmpty()) {
999     pdu.Prepare(arq.m_tokens, H225_AdmissionRequest::e_tokens,
1000                 arq.m_cryptoTokens, H225_AdmissionRequest::e_cryptoTokens);
1001 
1002     H235Authenticators adjustedAuthenticators;
1003     if (connection.GetAdmissionRequestAuthentication(arq, adjustedAuthenticators)) {
1004       PTRACE(3, "RAS\tAuthenticators credentials replaced with \""
1005              << setfill(',') << adjustedAuthenticators << setfill(' ') << "\" during ARQ");
1006 
1007       for (PINDEX i = 0; i < adjustedAuthenticators.GetSize(); i++) {
1008         H235Authenticator & authenticator = adjustedAuthenticators[i];
1009         if (authenticator.UseGkAndEpIdentifiers())
1010           authenticator.SetRemoteId(gatekeeperIdentifier);
1011       }
1012 
1013       adjustedAuthenticators.PreparePDU(pdu,
1014                                         arq.m_tokens, H225_AdmissionRequest::e_tokens,
1015                                         arq.m_cryptoTokens, H225_AdmissionRequest::e_cryptoTokens);
1016       pdu.SetAuthenticators(adjustedAuthenticators);
1017     }
1018   }
1019 
1020   if (!MakeRequest(request)) {
1021     response.rejectReason = request.rejectReason;
1022 
1023     // See if we are registered.
1024     if (request.responseResult == Request::RejectReceived &&
1025         response.rejectReason != H225_AdmissionRejectReason::e_callerNotRegistered &&
1026         response.rejectReason != H225_AdmissionRejectReason::e_invalidEndpointIdentifier)
1027       return FALSE;
1028 
1029     PTRACE(2, "RAS\tEndpoint has become unregistered during ARQ from gatekeeper " << gatekeeperIdentifier);
1030 
1031     // Have been told we are not registered (or gk offline)
1032     switch (request.responseResult) {
1033       case Request::NoResponseReceived :
1034         registrationFailReason = TransportError;
1035         response.rejectReason = UINT_MAX;
1036         break;
1037 
1038       case Request::BadCryptoTokens :
1039         registrationFailReason = SecurityDenied;
1040         response.rejectReason = H225_AdmissionRejectReason::e_securityDenial;
1041         break;
1042 
1043       default :
1044         registrationFailReason = GatekeeperLostRegistration;
1045     }
1046 
1047     // If we are not registered and auto register is set ...
1048     if (!autoReregister)
1049       return FALSE;
1050 
1051     // Then immediately reregister.
1052     if (!RegistrationRequest(autoReregister))
1053       return FALSE;
1054 
1055     // Reset the gk info in ARQ
1056     arq.m_endpointIdentifier = endpointIdentifier;
1057     if (!gatekeeperIdentifier) {
1058       arq.IncludeOptionalField(H225_AdmissionRequest::e_gatekeeperIdentifier);
1059       arq.m_gatekeeperIdentifier = gatekeeperIdentifier;
1060     }
1061     else
1062       arq.RemoveOptionalField(H225_AdmissionRequest::e_gatekeeperIdentifier);
1063 
1064     // Is new request so need new sequence number as well.
1065     arq.m_requestSeqNum = GetNextSequenceNumber();
1066     request.sequenceNumber = arq.m_requestSeqNum;
1067 
1068     if (!MakeRequest(request)) {
1069       response.rejectReason = request.responseResult == Request::RejectReceived
1070                                                 ? request.rejectReason : UINT_MAX;
1071 
1072       return FALSE;
1073     }
1074   }
1075 
1076   connection.SetBandwidthAvailable(info.allocatedBandwidth);
1077   connection.SetUUIEsRequested(info.uuiesRequested);
1078 
1079   return TRUE;
1080 }
1081 
1082 
OnSendAdmissionRequest(H225_AdmissionRequest &)1083 void H323Gatekeeper::OnSendAdmissionRequest(H225_AdmissionRequest & /*arq*/)
1084 {
1085   // Override default function as it sets crypto tokens and this is really
1086   // done by the AdmissionRequest() function.
1087 }
1088 
1089 
GetUUIEsRequested(const H225_UUIEsRequested & pdu)1090 static unsigned GetUUIEsRequested(const H225_UUIEsRequested & pdu)
1091 {
1092   unsigned uuiesRequested = 0;
1093 
1094   if ((PBoolean)pdu.m_setup)
1095     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_setup);
1096   if ((PBoolean)pdu.m_callProceeding)
1097     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_callProceeding);
1098   if ((PBoolean)pdu.m_connect)
1099     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_connect);
1100   if ((PBoolean)pdu.m_alerting)
1101     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_alerting);
1102   if ((PBoolean)pdu.m_information)
1103     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_information);
1104   if ((PBoolean)pdu.m_releaseComplete)
1105     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_releaseComplete);
1106   if ((PBoolean)pdu.m_facility)
1107     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_facility);
1108   if ((PBoolean)pdu.m_progress)
1109     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_progress);
1110   if ((PBoolean)pdu.m_empty)
1111     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_empty);
1112 
1113   if (pdu.HasOptionalField(H225_UUIEsRequested::e_status) && (PBoolean)pdu.m_status)
1114     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_status);
1115   if (pdu.HasOptionalField(H225_UUIEsRequested::e_statusInquiry) && (PBoolean)pdu.m_statusInquiry)
1116     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_statusInquiry);
1117   if (pdu.HasOptionalField(H225_UUIEsRequested::e_setupAcknowledge) && (PBoolean)pdu.m_setupAcknowledge)
1118     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_setupAcknowledge);
1119   if (pdu.HasOptionalField(H225_UUIEsRequested::e_notify) && (PBoolean)pdu.m_notify)
1120     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_notify);
1121 
1122   return uuiesRequested;
1123 }
1124 
1125 
ExtractToken(const AdmissionRequestResponseInfo & info,const H225_ArrayOf_ClearToken & tokens,PBYTEArray & accessTokenData)1126 static void ExtractToken(const AdmissionRequestResponseInfo & info,
1127                          const H225_ArrayOf_ClearToken & tokens,
1128                          PBYTEArray & accessTokenData)
1129 {
1130   if (!info.accessTokenOID1 && tokens.GetSize() > 0) {
1131     PTRACE(4, "Looking for OID " << info.accessTokenOID1 << " in ACF to copy.");
1132     for (PINDEX i = 0; i < tokens.GetSize(); i++) {
1133       if (tokens[i].m_tokenOID == info.accessTokenOID1) {
1134         PTRACE(4, "Looking for OID " << info.accessTokenOID2 << " in token to copy.");
1135         if (tokens[i].HasOptionalField(H235_ClearToken::e_nonStandard) &&
1136             tokens[i].m_nonStandard.m_nonStandardIdentifier == info.accessTokenOID2) {
1137           PTRACE(4, "Copying ACF nonStandard OctetString.");
1138           accessTokenData = tokens[i].m_nonStandard.m_data;
1139           break;
1140         }
1141       }
1142     }
1143   }
1144 }
1145 
1146 
OnReceiveAdmissionConfirm(const H225_AdmissionConfirm & acf)1147 PBoolean H323Gatekeeper::OnReceiveAdmissionConfirm(const H225_AdmissionConfirm & acf)
1148 {
1149   if (!H225_RAS::OnReceiveAdmissionConfirm(acf))
1150     return FALSE;
1151 
1152   AdmissionRequestResponseInfo & info = *(AdmissionRequestResponseInfo *)lastRequest->responseInfo;
1153   info.allocatedBandwidth = acf.m_bandWidth;
1154   if (info.param.transportAddress != NULL)
1155     *info.param.transportAddress = acf.m_destCallSignalAddress;
1156 
1157   info.param.gatekeeperRouted = acf.m_callModel.GetTag() == H225_CallModel::e_gatekeeperRouted;
1158 
1159   // Remove the endpoint aliases that the gatekeeper did not like and add the
1160   // ones that it really wants us to be.
1161   if (info.param.aliasAddresses != NULL &&
1162       acf.HasOptionalField(H225_AdmissionConfirm::e_destinationInfo)) {
1163     PTRACE(3, "RAS\tGatekeeper specified " << acf.m_destinationInfo.GetSize() << " aliases in ACF");
1164     *info.param.aliasAddresses = acf.m_destinationInfo;
1165   }
1166 
1167   if (acf.HasOptionalField(H225_AdmissionConfirm::e_uuiesRequested))
1168     info.uuiesRequested = GetUUIEsRequested(acf.m_uuiesRequested);
1169 
1170   if (info.param.destExtraCallInfo != NULL &&
1171       acf.HasOptionalField(H225_AdmissionConfirm::e_destExtraCallInfo))
1172     *info.param.destExtraCallInfo = acf.m_destExtraCallInfo;
1173 
1174   if (info.param.accessTokenData != NULL && acf.HasOptionalField(H225_AdmissionConfirm::e_tokens))
1175     ExtractToken(info, acf.m_tokens, *info.param.accessTokenData);
1176 
1177   if (info.param.transportAddress != NULL) {
1178     PINDEX count = 1;
1179     for (PINDEX i = 0; i < acf.m_alternateEndpoints.GetSize() && count < info.param.endpointCount; i++) {
1180       if (acf.m_alternateEndpoints[i].HasOptionalField(H225_Endpoint::e_callSignalAddress) &&
1181           acf.m_alternateEndpoints[i].m_callSignalAddress.GetSize() > 0) {
1182         info.param.transportAddress[count] = acf.m_alternateEndpoints[i].m_callSignalAddress[0];
1183         if (info.param.accessTokenData != NULL)
1184           ExtractToken(info, acf.m_alternateEndpoints[i].m_tokens, info.param.accessTokenData[count]);
1185         count++;
1186       }
1187     }
1188     info.param.endpointCount = count;
1189   }
1190 
1191   if (acf.HasOptionalField(H225_AdmissionConfirm::e_irrFrequency))
1192     SetInfoRequestRate(AdjustTimeout(acf.m_irrFrequency));
1193   willRespondToIRR = acf.m_willRespondToIRR;
1194 
1195   info.connection.OnReceivedACF(acf);
1196 
1197 #ifdef H323_H248
1198   if (acf.HasOptionalField(H225_AdmissionConfirm::e_serviceControl))
1199     OnServiceControlSessions(acf.m_serviceControl, &info.connection);
1200 #endif
1201 
1202   if (acf.HasOptionalField(H225_AdmissionConfirm::e_language))
1203       H323GetLanguages(*info.param.languageSupport, acf.m_language);
1204 
1205   return TRUE;
1206 }
1207 
1208 
OnReceiveAdmissionReject(const H225_AdmissionReject & arj)1209 PBoolean H323Gatekeeper::OnReceiveAdmissionReject(const H225_AdmissionReject & arj)
1210 {
1211   if (!H225_RAS::OnReceiveAdmissionReject(arj))
1212     return FALSE;
1213 
1214   AdmissionRequestResponseInfo & info = *(AdmissionRequestResponseInfo *)lastRequest->responseInfo;
1215   info.connection.OnReceivedARJ(arj);
1216 
1217 #ifdef H323_H248
1218   if (arj.HasOptionalField(H225_AdmissionConfirm::e_serviceControl))
1219     OnServiceControlSessions(arj.m_serviceControl,&info.connection);
1220 #endif
1221 
1222   return TRUE;
1223 }
1224 
1225 
SetRasUsageInformation(const H323Connection & connection,H225_RasUsageInformation & usage)1226 static void SetRasUsageInformation(const H323Connection & connection,
1227                                    H225_RasUsageInformation & usage)
1228 {
1229   unsigned time = connection.GetAlertingTime().GetTimeInSeconds();
1230   if (time != 0) {
1231     usage.IncludeOptionalField(H225_RasUsageInformation::e_alertingTime);
1232     usage.m_alertingTime = time;
1233   }
1234 
1235   time = connection.GetConnectionStartTime().GetTimeInSeconds();
1236   if (time != 0) {
1237     usage.IncludeOptionalField(H225_RasUsageInformation::e_connectTime);
1238     usage.m_connectTime = time;
1239   }
1240 
1241   time = connection.GetConnectionEndTime().GetTimeInSeconds();
1242   if (time != 0) {
1243     usage.IncludeOptionalField(H225_RasUsageInformation::e_endTime);
1244     usage.m_endTime = time;
1245   }
1246 }
1247 
1248 
DisengageRequest(const H323Connection & connection,unsigned reason)1249 PBoolean H323Gatekeeper::DisengageRequest(const H323Connection & connection, unsigned reason)
1250 {
1251   H323RasPDU pdu;
1252   H225_DisengageRequest & drq = pdu.BuildDisengageRequest(GetNextSequenceNumber());
1253 
1254   drq.m_endpointIdentifier = endpointIdentifier;
1255   drq.m_conferenceID = connection.GetConferenceIdentifier();
1256   drq.m_callReferenceValue = connection.GetCallReference();
1257   drq.m_callIdentifier.m_guid = connection.GetCallIdentifier();
1258   drq.m_disengageReason.SetTag(reason);
1259   drq.m_answeredCall = connection.HadAnsweredCall();
1260 
1261   drq.IncludeOptionalField(H225_DisengageRequest::e_usageInformation);
1262   SetRasUsageInformation(connection, drq.m_usageInformation);
1263 
1264   drq.IncludeOptionalField(H225_DisengageRequest::e_terminationCause);
1265   drq.m_terminationCause.SetTag(H225_CallTerminationCause::e_releaseCompleteReason);
1266   Q931::CauseValues cause = H323TranslateFromCallEndReason(connection, drq.m_terminationCause);
1267   if (cause != Q931::ErrorInCauseIE) {
1268     drq.m_terminationCause.SetTag(H225_CallTerminationCause::e_releaseCompleteCauseIE);
1269     PASN_OctetString & rcReason = drq.m_terminationCause;
1270     rcReason.SetSize(2);
1271     rcReason[0] = 0x80;
1272     rcReason[1] = (BYTE)(0x80|cause);
1273   }
1274 
1275   if (!gatekeeperIdentifier) {
1276     drq.IncludeOptionalField(H225_DisengageRequest::e_gatekeeperIdentifier);
1277     drq.m_gatekeeperIdentifier = gatekeeperIdentifier;
1278   }
1279 
1280   connection.OnSendDRQ(drq);
1281 
1282   Request request(drq.m_requestSeqNum, pdu);
1283   return MakeRequestWithReregister(request, H225_DisengageRejectReason::e_notRegistered);
1284 }
1285 
1286 
OnReceiveDisengageRequest(const H225_DisengageRequest & drq)1287 PBoolean H323Gatekeeper::OnReceiveDisengageRequest(const H225_DisengageRequest & drq)
1288 {
1289   if (!H225_RAS::OnReceiveDisengageRequest(drq))
1290     return FALSE;
1291 
1292   OpalGloballyUniqueID id = NULL;
1293   if (drq.HasOptionalField(H225_DisengageRequest::e_callIdentifier))
1294     id = drq.m_callIdentifier.m_guid;
1295   if (id == NULL)
1296     id = drq.m_conferenceID;
1297 
1298   H323RasPDU response(authenticators);
1299   H323Connection * connection = endpoint.FindConnectionWithLock(id.AsString());
1300   if (connection == NULL)
1301     response.BuildDisengageReject(drq.m_requestSeqNum,
1302                                   H225_DisengageRejectReason::e_requestToDropOther);
1303   else {
1304     H225_DisengageConfirm & dcf = response.BuildDisengageConfirm(drq.m_requestSeqNum);
1305 
1306     dcf.IncludeOptionalField(H225_DisengageConfirm::e_usageInformation);
1307     SetRasUsageInformation(*connection, dcf.m_usageInformation);
1308 
1309     connection->ClearCall(H323Connection::EndedByGatekeeper);
1310     connection->Unlock();
1311   }
1312 
1313 #ifdef H323_H248
1314   if (drq.HasOptionalField(H225_DisengageRequest::e_serviceControl))
1315     OnServiceControlSessions(drq.m_serviceControl, connection);
1316 #endif
1317 
1318   return WritePDU(response);
1319 }
1320 
1321 
BandwidthRequest(H323Connection & connection,unsigned requestedBandwidth)1322 PBoolean H323Gatekeeper::BandwidthRequest(H323Connection & connection,
1323                                       unsigned requestedBandwidth)
1324 {
1325   H323RasPDU pdu;
1326   H225_BandwidthRequest & brq = pdu.BuildBandwidthRequest(GetNextSequenceNumber());
1327 
1328   brq.m_endpointIdentifier = endpointIdentifier;
1329   brq.m_conferenceID = connection.GetConferenceIdentifier();
1330   brq.m_callReferenceValue = connection.GetCallReference();
1331   brq.m_callIdentifier.m_guid = connection.GetCallIdentifier();
1332   brq.m_bandWidth = requestedBandwidth;
1333   brq.IncludeOptionalField(H225_BandwidthRequest::e_usageInformation);
1334   SetRasUsageInformation(connection, brq.m_usageInformation);
1335 
1336   Request request(brq.m_requestSeqNum, pdu);
1337 
1338   unsigned allocatedBandwidth;
1339   request.responseInfo = &allocatedBandwidth;
1340 
1341   if (!MakeRequestWithReregister(request, H225_BandRejectReason::e_notBound))
1342     return FALSE;
1343 
1344   connection.SetBandwidthAvailable(allocatedBandwidth);
1345   return TRUE;
1346 }
1347 
1348 
OnReceiveBandwidthConfirm(const H225_BandwidthConfirm & bcf)1349 PBoolean H323Gatekeeper::OnReceiveBandwidthConfirm(const H225_BandwidthConfirm & bcf)
1350 {
1351   if (!H225_RAS::OnReceiveBandwidthConfirm(bcf))
1352     return FALSE;
1353 
1354   if (lastRequest->responseInfo != NULL)
1355     *(unsigned *)lastRequest->responseInfo = bcf.m_bandWidth;
1356 
1357   return TRUE;
1358 }
1359 
1360 
OnReceiveBandwidthRequest(const H225_BandwidthRequest & brq)1361 PBoolean H323Gatekeeper::OnReceiveBandwidthRequest(const H225_BandwidthRequest & brq)
1362 {
1363   if (!H225_RAS::OnReceiveBandwidthRequest(brq))
1364     return FALSE;
1365 
1366   OpalGloballyUniqueID id = brq.m_callIdentifier.m_guid;
1367   H323Connection * connection = endpoint.FindConnectionWithLock(id.AsString());
1368 
1369   H323RasPDU response(authenticators);
1370   if (connection == NULL)
1371     response.BuildBandwidthReject(brq.m_requestSeqNum,
1372                                   H225_BandRejectReason::e_invalidConferenceID);
1373   else {
1374     if (connection->SetBandwidthAvailable(brq.m_bandWidth))
1375       response.BuildBandwidthConfirm(brq.m_requestSeqNum, brq.m_bandWidth);
1376     else
1377       response.BuildBandwidthReject(brq.m_requestSeqNum,
1378                                     H225_BandRejectReason::e_insufficientResources);
1379     connection->Unlock();
1380   }
1381 
1382   return WritePDU(response);
1383 }
1384 
1385 
SetInfoRequestRate(const PTimeInterval & rate)1386 void H323Gatekeeper::SetInfoRequestRate(const PTimeInterval & rate)
1387 {
1388   if (rate < infoRequestRate.GetResetTime() || infoRequestRate.GetResetTime() == 0) {
1389     // Have to be sneaky here becuase we do not want to actually change the
1390     // amount of time to run on the timer.
1391     PTimeInterval timeToGo = infoRequestRate;
1392     infoRequestRate = rate;
1393     if (rate > timeToGo)
1394       infoRequestRate.PTimeInterval::operator=(timeToGo);
1395   }
1396 }
1397 
1398 
ClearInfoRequestRate()1399 void H323Gatekeeper::ClearInfoRequestRate()
1400 {
1401   // Only reset rate to zero (disabled) if no calls present
1402   if (endpoint.GetAllConnections().IsEmpty())
1403     infoRequestRate = 0;
1404 }
1405 
1406 
BuildInfoRequestResponse(H323RasPDU & response,unsigned seqNum)1407 H225_InfoRequestResponse & H323Gatekeeper::BuildInfoRequestResponse(H323RasPDU & response,
1408                                                                     unsigned seqNum)
1409 {
1410   H225_InfoRequestResponse & irr = response.BuildInfoRequestResponse(seqNum);
1411 
1412   endpoint.SetEndpointTypeInfo(irr.m_endpointType);
1413   irr.m_endpointIdentifier = endpointIdentifier;
1414   transport->SetUpTransportPDU(irr.m_rasAddress, TRUE);
1415   H323SetTransportAddresses(*transport,
1416                             endpoint.GetInterfaceAddresses(TRUE, transport),
1417                             irr.m_callSignalAddress);
1418 
1419   irr.IncludeOptionalField(H225_InfoRequestResponse::e_endpointAlias);
1420   H323SetAliasAddresses(endpoint.GetAliasNames(), irr.m_endpointAlias);
1421 
1422   return irr;
1423 }
1424 
1425 
SendUnsolicitedIRR(H225_InfoRequestResponse & irr,H323RasPDU & response)1426 PBoolean H323Gatekeeper::SendUnsolicitedIRR(H225_InfoRequestResponse & irr,
1427                                         H323RasPDU & response)
1428 {
1429   irr.m_unsolicited = TRUE;
1430 
1431   if (willRespondToIRR) {
1432     PTRACE(4, "RAS\tSending unsolicited IRR and awaiting acknowledgement");
1433     Request request(irr.m_requestSeqNum, response);
1434     return MakeRequest(request);
1435   }
1436 
1437   PTRACE(4, "RAS\tSending unsolicited IRR and without acknowledgement");
1438   response.SetAuthenticators(authenticators);
1439   return WritePDU(response);
1440 }
1441 
1442 
AddInfoRequestResponseCall(H225_InfoRequestResponse & irr,const H323Connection & connection)1443 static void AddInfoRequestResponseCall(H225_InfoRequestResponse & irr,
1444                                        const H323Connection & connection)
1445 {
1446   irr.IncludeOptionalField(H225_InfoRequestResponse::e_perCallInfo);
1447 
1448   PINDEX sz = irr.m_perCallInfo.GetSize();
1449   if (sz > 100) // don't include more than 100 calls in IRR to keep message size reasonable
1450     return;
1451   if (!irr.m_perCallInfo.SetSize(sz+1))
1452     return;
1453 
1454   H225_InfoRequestResponse_perCallInfo_subtype & info = irr.m_perCallInfo[sz];
1455 
1456   info.m_callReferenceValue = connection.GetCallReference();
1457   info.m_callIdentifier.m_guid = connection.GetCallIdentifier();
1458   info.m_conferenceID = connection.GetConferenceIdentifier();
1459   info.IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_originator);
1460   info.m_originator = !connection.HadAnsweredCall();
1461 
1462   // include details RTP info only for the first 10 calls to keep message size reasonable
1463   if (sz <= 10) {
1464     H323_RTP_Session * session = connection.GetSessionCallbacks(RTP_Session::DefaultAudioSessionID);
1465     if (session != NULL) {
1466       info.IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_audio);
1467       info.m_audio.SetSize(1);
1468       session->OnSendRasInfo(info.m_audio[0]);
1469     }
1470 
1471     session = connection.GetSessionCallbacks(RTP_Session::DefaultVideoSessionID);
1472     if (session != NULL) {
1473       info.IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_video);
1474       info.m_video.SetSize(1);
1475       session->OnSendRasInfo(info.m_video[0]);
1476     }
1477   }
1478 
1479   info.m_h245.IncludeOptionalField(H225_TransportChannelInfo::e_recvAddress);
1480   info.m_h245.IncludeOptionalField(H225_TransportChannelInfo::e_sendAddress);
1481   const H323Transport & controlChannel = connection.GetControlChannel();
1482   controlChannel.SetUpTransportPDU(info.m_h245.m_recvAddress, false);
1483   controlChannel.SetUpTransportPDU(info.m_h245.m_sendAddress, true);
1484 
1485   const H323Transport * sig = connection.GetSignallingChannel();
1486   if (sig) {
1487     info.m_callSignaling.IncludeOptionalField(H225_TransportChannelInfo::e_recvAddress);
1488     info.m_callSignaling.IncludeOptionalField(H225_TransportChannelInfo::e_sendAddress);
1489     sig->GetRemoteAddress().SetPDU(info.m_callSignaling.m_recvAddress);
1490     sig->GetLocalAddress().SetPDU(info.m_callSignaling.m_sendAddress);
1491   }
1492 
1493   info.m_callType.SetTag(H225_CallType::e_pointToPoint);
1494   info.m_bandWidth = connection.GetBandwidthUsed();
1495   info.m_callModel.SetTag(connection.IsGatekeeperRouted() ? H225_CallModel::e_gatekeeperRouted
1496                                                           : H225_CallModel::e_direct);
1497 
1498   info.IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_usageInformation);
1499   SetRasUsageInformation(connection, info.m_usageInformation);
1500 }
1501 
1502 
AddAllInfoRequestResponseCall(H225_InfoRequestResponse & irr,H323EndPoint & endpoint,const PStringList & tokens)1503 static PBoolean AddAllInfoRequestResponseCall(H225_InfoRequestResponse & irr,
1504                                           H323EndPoint & endpoint,
1505                                           const PStringList & tokens)
1506 {
1507   PBoolean addedOne = FALSE;
1508 
1509   for (PINDEX i = 0; i < tokens.GetSize(); i++) {
1510     H323Connection * connection = endpoint.FindConnectionWithLock(tokens[i]);
1511     if (connection != NULL) {
1512       AddInfoRequestResponseCall(irr, *connection);
1513       connection->OnSendIRR(irr);
1514       connection->Unlock();
1515       addedOne = TRUE;
1516     }
1517   }
1518 
1519   return addedOne;
1520 }
1521 
1522 
InfoRequestResponse()1523 void H323Gatekeeper::InfoRequestResponse()
1524 {
1525   PStringList tokens = endpoint.GetAllConnections();
1526   if (tokens.IsEmpty())
1527     return;
1528 
1529   H323RasPDU response;
1530   H225_InfoRequestResponse & irr = BuildInfoRequestResponse(response, GetNextSequenceNumber());
1531 
1532   if (AddAllInfoRequestResponseCall(irr, endpoint, tokens))
1533     SendUnsolicitedIRR(irr, response);
1534 }
1535 
1536 
InfoRequestResponse(const H323Connection & connection)1537 void H323Gatekeeper::InfoRequestResponse(const H323Connection & connection)
1538 {
1539   H323RasPDU response;
1540   H225_InfoRequestResponse & irr = BuildInfoRequestResponse(response, GetNextSequenceNumber());
1541 
1542   AddInfoRequestResponseCall(irr, connection);
1543 
1544   connection.OnSendIRR(irr);
1545 
1546   SendUnsolicitedIRR(irr, response);
1547 }
1548 
1549 
InfoRequestResponse(const H323Connection & connection,const H225_H323_UU_PDU & pdu,PBoolean sent)1550 void H323Gatekeeper::InfoRequestResponse(const H323Connection & connection,
1551                                          const H225_H323_UU_PDU & pdu,
1552                                          PBoolean sent)
1553 {
1554   // Are unknown Q.931 PDU
1555   if (pdu.m_h323_message_body.GetTag() == P_MAX_INDEX)
1556     return;
1557 
1558   // Check mask of things to report on
1559   if ((connection.GetUUIEsRequested() & (1<<pdu.m_h323_message_body.GetTag())) == 0)
1560     return;
1561 
1562   PTRACE(3, "RAS\tSending unsolicited IRR for requested UUIE");
1563 
1564   // Report the PDU
1565   H323RasPDU response;
1566   H225_InfoRequestResponse & irr = BuildInfoRequestResponse(response, GetNextSequenceNumber());
1567 
1568   AddInfoRequestResponseCall(irr, connection);
1569 
1570   irr.m_perCallInfo[0].IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_pdu);
1571   irr.m_perCallInfo[0].m_pdu.SetSize(1);
1572   irr.m_perCallInfo[0].m_pdu[0].m_sent = sent;
1573   irr.m_perCallInfo[0].m_pdu[0].m_h323pdu = pdu;
1574 
1575   connection.OnSendIRR(irr);
1576   SendUnsolicitedIRR(irr, response);
1577 }
1578 
1579 
OnReceiveInfoRequest(const H225_InfoRequest & irq)1580 PBoolean H323Gatekeeper::OnReceiveInfoRequest(const H225_InfoRequest & irq)
1581 {
1582   if (!H225_RAS::OnReceiveInfoRequest(irq))
1583     return FALSE;
1584 
1585   H323RasPDU response(authenticators);
1586   H225_InfoRequestResponse & irr = BuildInfoRequestResponse(response, irq.m_requestSeqNum);
1587 
1588   if (irq.m_callReferenceValue == 0) {
1589     if (!AddAllInfoRequestResponseCall(irr, endpoint, endpoint.GetAllConnections())) {
1590       irr.IncludeOptionalField(H225_InfoRequestResponse::e_irrStatus);
1591       irr.m_irrStatus.SetTag(H225_InfoRequestResponseStatus::e_invalidCall);
1592     }
1593   }
1594   else {
1595     OpalGloballyUniqueID id = irq.m_callIdentifier.m_guid;
1596     H323Connection * connection = endpoint.FindConnectionWithLock(id.AsString());
1597     if (connection == NULL) {
1598       irr.IncludeOptionalField(H225_InfoRequestResponse::e_irrStatus);
1599       irr.m_irrStatus.SetTag(H225_InfoRequestResponseStatus::e_invalidCall);
1600     }
1601     else {
1602       if (irq.HasOptionalField(H225_InfoRequest::e_uuiesRequested))
1603         connection->SetUUIEsRequested(::GetUUIEsRequested(irq.m_uuiesRequested));
1604 
1605       AddInfoRequestResponseCall(irr, *connection);
1606 
1607       connection->Unlock();
1608     }
1609   }
1610 
1611   if (!irq.HasOptionalField(H225_InfoRequest::e_replyAddress))
1612     return WritePDU(response);
1613 
1614   H323TransportAddress replyAddress = irq.m_replyAddress;
1615   if (replyAddress.IsEmpty())
1616     return FALSE;
1617 
1618   H323TransportAddress oldAddress = transport->GetRemoteAddress();
1619 
1620   PBoolean ok = transport->ConnectTo(replyAddress) && WritePDU(response);
1621 
1622   transport->ConnectTo(oldAddress);
1623 
1624   return ok;
1625 }
1626 
1627 
SendServiceControlIndication()1628 PBoolean H323Gatekeeper::SendServiceControlIndication()
1629 {
1630 
1631   H323RasPDU pdu;
1632   H225_ServiceControlIndication & sci = pdu.BuildServiceControlIndication(GetNextSequenceNumber());
1633 
1634   sci.m_serviceControl.SetSize(0);
1635 
1636   Request request(sci.m_requestSeqNum, pdu);
1637   return MakeRequest(request);
1638 }
1639 
OnReceiveServiceControlIndication(const H225_ServiceControlIndication & sci)1640 PBoolean H323Gatekeeper::OnReceiveServiceControlIndication(const H225_ServiceControlIndication & sci)
1641 {
1642   if (!H225_RAS::OnReceiveServiceControlIndication(sci))
1643     return FALSE;
1644 
1645   H323Connection * connection = NULL;
1646 
1647   if (sci.HasOptionalField(H225_ServiceControlIndication::e_callSpecific)) {
1648     OpalGloballyUniqueID id = sci.m_callSpecific.m_callIdentifier.m_guid;
1649     if (id.IsNULL())
1650       id = sci.m_callSpecific.m_conferenceID;
1651     connection = endpoint.FindConnectionWithLock(id.AsString());
1652   }
1653 
1654 #ifdef H323_H248
1655   OnServiceControlSessions(sci.m_serviceControl, connection);
1656 #endif
1657 
1658 
1659   H323RasPDU response(authenticators);
1660   response.BuildServiceControlResponse(sci.m_requestSeqNum);
1661   return WritePDU(response);
1662 }
1663 
1664 #ifdef H323_H248
1665 
OnServiceControlSessions(const H225_ArrayOf_ServiceControlSession & serviceControl,H323Connection * connection)1666 void H323Gatekeeper::OnServiceControlSessions(const H225_ArrayOf_ServiceControlSession & serviceControl,
1667                                               H323Connection * connection)
1668 {
1669   for (PINDEX i = 0; i < serviceControl.GetSize(); i++) {
1670     H225_ServiceControlSession & pdu = serviceControl[i];
1671 
1672     H323ServiceControlSession * session = NULL;
1673     unsigned sessionId = pdu.m_sessionId;
1674 
1675     if (serviceControlSessions.Contains(sessionId)) {
1676       session = &serviceControlSessions[sessionId];
1677       if (pdu.HasOptionalField(H225_ServiceControlSession::e_contents)) {
1678         if (!session->OnReceivedPDU(pdu.m_contents)) {
1679           PTRACE(2, "SvcCtrl\tService control for session has changed!");
1680           session = NULL;
1681         }
1682       }
1683     }
1684 
1685     if (session == NULL && pdu.HasOptionalField(H225_ServiceControlSession::e_contents)) {
1686       session = endpoint.CreateServiceControlSession(pdu.m_contents);
1687       serviceControlSessions.SetAt(sessionId, session);
1688     }
1689 
1690     if (session != NULL)
1691       endpoint.OnServiceControlSession(pdu.m_reason.GetTag(),sessionId, *session, connection);
1692   }
1693 }
1694 
1695 #endif // H323_H248
1696 
1697 
SetPassword(const PString & password,const PString & username)1698 void H323Gatekeeper::SetPassword(const PString & password,
1699                                  const PString & username)
1700 {
1701   localId = username;
1702   if (localId.IsEmpty())
1703     localId = endpoint.GetLocalUserName();
1704 
1705   for (PINDEX i = 0; i < authenticators.GetSize(); i++) {
1706     authenticators[i].SetLocalId(localId);
1707     authenticators[i].SetPassword(password);
1708   }
1709 }
1710 
1711 
MonitorMain(PThread &,H323_INT)1712 void H323Gatekeeper::MonitorMain(PThread &, H323_INT)
1713 {
1714   PTRACE(3, "RAS\tBackground thread started");
1715 
1716   for (;;) {
1717     monitorTickle.Wait();
1718     if (monitorStop)
1719       break;
1720     if (reregisterNow ||
1721                 (!timeToLive.IsRunning() && timeToLive.GetResetTime() > 0)) {
1722       RegistrationTimeToLive();
1723       timeToLive.Reset();
1724     }
1725 
1726     if (!infoRequestRate.IsRunning() && infoRequestRate.GetResetTime() > 0) {
1727       InfoRequestResponse();
1728       infoRequestRate.Reset();
1729     }
1730   }
1731 
1732   PTRACE(3, "RAS\tBackground thread ended");
1733 }
1734 
1735 
TickleMonitor(PTimer &,H323_INT)1736 void H323Gatekeeper::TickleMonitor(PTimer &, H323_INT)
1737 {
1738   monitorTickle.Signal();
1739 }
1740 
1741 
SetAlternates(const H225_ArrayOf_AlternateGK & alts,PBoolean permanent)1742 void H323Gatekeeper::SetAlternates(const H225_ArrayOf_AlternateGK & alts, PBoolean permanent)
1743 {
1744   PINDEX i;
1745 
1746   if (!alternatePermanent)  {
1747     // don't want to replace alternates gatekeepers if this is an alternate and it's not permanent
1748     for (i = 0; i < alternates.GetSize(); i++) {
1749       if (transport->GetRemoteAddress().IsEquivalent(alternates[i].rasAddress) &&
1750           gatekeeperIdentifier == alternates[i].gatekeeperIdentifier)
1751         return;
1752     }
1753   }
1754 
1755   alternates.SetSize(0);
1756   for (i = 0; i < alts.GetSize(); i++) {
1757 	  if (AlternateInfo::IsValid(alts[i])) {
1758 		PTRACE(3, "RAS\tAdded alternate gatekeeper:" << H323TransportAddress(alts[i].m_rasAddress));
1759 		alternates.Append(new AlternateInfo(alts[i]));
1760 	  }
1761   }
1762 
1763   if (alternates.GetSize() > 0)
1764       alternatePermanent = permanent;
1765 }
1766 
SetAssignedGatekeeper(const H225_AlternateGK & gk)1767 void H323Gatekeeper::SetAssignedGatekeeper(const H225_AlternateGK & gk)
1768 {
1769    assignedGK.SetAlternate(gk);
1770 }
1771 
GetAssignedGatekeeper(H225_AlternateGK & gk)1772 PBoolean H323Gatekeeper::GetAssignedGatekeeper(H225_AlternateGK & gk)
1773 {
1774     if (!assignedGK.IsValid())
1775         return FALSE;
1776 
1777     gk = assignedGK.GetAlternate();
1778     return TRUE;
1779 }
1780 
1781 
MakeRequestWithReregister(Request & request,unsigned unregisteredTag)1782 PBoolean H323Gatekeeper::MakeRequestWithReregister(Request & request, unsigned unregisteredTag)
1783 {
1784   if (MakeRequest(request))
1785     return TRUE;
1786 
1787   if (request.responseResult == Request::RejectReceived &&
1788       request.rejectReason != unregisteredTag)
1789     return FALSE;
1790 
1791   PTRACE(2, "RAS\tEndpoint has become unregistered from gatekeeper " << gatekeeperIdentifier);
1792 
1793   // Have been told we are not registered (or gk offline)
1794   switch (request.responseResult) {
1795     case Request::NoResponseReceived :
1796       registrationFailReason = TransportError;
1797       break;
1798 
1799     case Request::BadCryptoTokens :
1800       registrationFailReason = SecurityDenied;
1801       break;
1802 
1803     default :
1804       registrationFailReason = GatekeeperLostRegistration;
1805   }
1806 
1807   // If we are not registered and auto register is set ...
1808   if (!autoReregister)
1809     return FALSE;
1810 
1811   reregisterNow = TRUE;
1812   monitorTickle.Signal();
1813   return FALSE;
1814 }
1815 
1816 
Connect(const H323TransportAddress & address,const PString & gkid)1817 void H323Gatekeeper::Connect(const H323TransportAddress & address,
1818                              const PString & gkid)
1819 {
1820   if (transport == NULL)
1821       transport = new H323TransportUDP(endpoint, PIPSocket::Address::GetAny(4));
1822 
1823   transport->SetRemoteAddress(address);
1824   transport->Connect();
1825   if (!gkid.IsEmpty())
1826     gatekeeperIdentifier = gkid;
1827 }
1828 
1829 
MakeRequest(Request & request)1830 PBoolean H323Gatekeeper::MakeRequest(Request & request)
1831 {
1832   if (transport == NULL)
1833     return FALSE;
1834 
1835   // Set authenticators if not already set by caller
1836   requestMutex.Wait();
1837 
1838   if (request.requestPDU.GetAuthenticators().IsEmpty())
1839     request.requestPDU.SetAuthenticators(authenticators);
1840 
1841   /* To be sure that the H323 Cleaner, H225 Caller or Monitor don't set the
1842      transport address of the alternate while the other is in timeout. We
1843      have to block the function */
1844 
1845   H323TransportAddress tempAddr = transport->GetRemoteAddress();
1846   PString tempIdentifier = gatekeeperIdentifier;
1847 
1848   PINDEX alt = 0;
1849   for (;;) {
1850     if (!request.useAlternate && H225_RAS::MakeRequest(request)) {
1851       if (!alternatePermanent &&
1852             (transport->GetRemoteAddress() != tempAddr ||
1853              gatekeeperIdentifier != tempIdentifier))
1854         Connect(tempAddr, tempIdentifier);
1855       requestMutex.Signal();
1856       return TRUE;
1857     }
1858 
1859     if (request.responseResult != Request::NoResponseReceived &&
1860         request.responseResult != Request::TryAlternate) {
1861       // try alternate in those cases and see if it's successful
1862       requestMutex.Signal();
1863       return FALSE;
1864     }
1865 
1866     if (request.responseResult == Request::NoResponseReceived) {
1867 #ifdef H323_H46017
1868         if (transport && PIsDescendant(transport,H46017RasTransport)) {
1869             PTRACE(2,"GK\tRegistration no response. H46017 Channel shutdown?");
1870             requestMutex.Signal();
1871             return FALSE;
1872         }
1873 #endif
1874         if (endpoint.GetConnections().GetSize() > 0) {
1875             PTRACE(2,"GK\tRegistration no response. Unregister deferred as on call.");
1876             requestMutex.Signal();
1877             return TRUE;
1878         }
1879     }
1880 
1881     AlternateInfo * altInfo;
1882     PIPSocket::Address localAddress;
1883     WORD localPort = 0;
1884     do {
1885       if (alt >= alternates.GetSize()) {
1886         if (!alternatePermanent)
1887           Connect(tempAddr,tempIdentifier);
1888         requestMutex.Signal();
1889         return FALSE;
1890       }
1891 
1892       altInfo = &alternates[alt++];
1893       if (transport) {
1894         transport->GetLocalAddress().GetIpAndPort(localAddress,localPort);
1895         transport->CleanUpOnTermination();
1896         delete transport;
1897       }
1898 
1899       transport = new H323TransportUDP(endpoint,localAddress,localPort);
1900       transport->SetRemoteAddress (altInfo->rasAddress);
1901       transport->Connect();
1902       gatekeeperIdentifier = altInfo->gatekeeperIdentifier;
1903       StartChannel();
1904     } while (altInfo->registrationState == AlternateInfo::RegistrationFailed);
1905 
1906     if (altInfo->registrationState == AlternateInfo::NeedToRegister) {
1907       altInfo->registrationState = AlternateInfo::RegistrationFailed;
1908       registrationFailReason = TransportError;
1909       discoveryComplete = FALSE;
1910       H323RasPDU pdu;
1911       Request req(SetupGatekeeperRequest(pdu), pdu);
1912 
1913       if (H225_RAS::MakeRequest(req)) {
1914         requestMutex.Signal(); // avoid deadlock...
1915         if (RegistrationRequest(autoReregister)) {
1916           altInfo->registrationState = AlternateInfo::IsRegistered;
1917           // The wanted registration is done, we can return
1918           if (request.requestPDU.GetChoice().GetTag() == H225_RasMessage::e_registrationRequest) {
1919             if (!alternatePermanent)
1920               Connect(tempAddr,tempIdentifier);
1921           }
1922           return TRUE;
1923         }
1924         requestMutex.Wait();
1925       }
1926     }
1927   }
1928 }
1929 
AlternateInfo()1930 H323Gatekeeper::AlternateInfo::AlternateInfo()
1931 :  priority(0), registrationState(NoRegistrationNeeded)
1932 {
1933     H323TransportAddress(PIPSocket::Address::GetAny(4),1719).SetPDU(rasAddress);
1934 }
1935 
AlternateInfo(const H225_AlternateGK & alt)1936 H323Gatekeeper::AlternateInfo::AlternateInfo(const H225_AlternateGK & alt)
1937 {
1938     SetAlternate(alt);
1939 }
1940 
1941 
~AlternateInfo()1942 H323Gatekeeper::AlternateInfo::~AlternateInfo ()
1943 {
1944 
1945 }
1946 
1947 
Compare(const PObject & obj) const1948 PObject::Comparison H323Gatekeeper::AlternateInfo::Compare(const PObject & obj) const
1949 {
1950   PAssert(PIsDescendant(&obj, H323Gatekeeper), PInvalidCast);
1951   unsigned otherPriority = ((const AlternateInfo & )obj).priority;
1952   if (priority < otherPriority)
1953     return LessThan;
1954   if (priority > otherPriority)
1955     return GreaterThan;
1956   return EqualTo;
1957 }
1958 
GetAlternate()1959 H225_AlternateGK H323Gatekeeper::AlternateInfo::GetAlternate()
1960 {
1961     H225_AlternateGK gk;
1962     gk.m_rasAddress = rasAddress;
1963     gk.m_gatekeeperIdentifier = gatekeeperIdentifier;
1964     gk.m_priority = priority;
1965     gk.m_needToRegister = registrationState;
1966 
1967     return gk;
1968 }
1969 
GetAlternate(AlternateInfo & alt)1970 void H323Gatekeeper::AlternateInfo::GetAlternate(AlternateInfo & alt)
1971 {
1972 	alt.rasAddress = rasAddress;
1973     alt.gatekeeperIdentifier = gatekeeperIdentifier;
1974     alt.priority = priority;
1975 	alt.registrationState = registrationState;
1976 }
1977 
SetAlternate(const H225_AlternateGK & alt)1978 void H323Gatekeeper::AlternateInfo::SetAlternate(const H225_AlternateGK & alt)
1979 {
1980 	rasAddress = alt.m_rasAddress;
1981     gatekeeperIdentifier = alt.m_gatekeeperIdentifier.GetValue();
1982     priority = alt.m_priority;
1983 	registrationState = alt.m_needToRegister ? NeedToRegister : NoRegistrationNeeded;
1984 }
1985 
PrintOn(ostream & strm) const1986 void H323Gatekeeper::AlternateInfo::PrintOn(ostream & strm) const
1987 {
1988   if (!gatekeeperIdentifier)
1989     strm << gatekeeperIdentifier << '@';
1990 
1991   strm << rasAddress;
1992 
1993   if (priority > 0)
1994     strm << ";priority=" << priority;
1995 }
1996 
IsValid() const1997 PBoolean H323Gatekeeper::AlternateInfo::IsValid() const
1998 {
1999     PIPSocket::Address addr;
2000     H323TransportAddress(rasAddress).GetIpAddress(addr);
2001 
2002     if (addr.IsValid()) {
2003         if (!addr.IsAny() && !addr.IsLoopback())
2004             return true;
2005         else
2006             return false;
2007     }
2008 
2009     PTRACE(2,"GKALT\tAlternate Address " << addr << " is not valid. Ignoring...");
2010     return false;
2011 }
2012 
IsValid(const H225_AlternateGK & alt)2013 PBoolean H323Gatekeeper::AlternateInfo::IsValid(const H225_AlternateGK & alt)
2014 {
2015 	H323TransportAddress taddr = alt.m_rasAddress;
2016     PIPSocket::Address addr;
2017     taddr.GetIpAddress(addr);
2018 
2019     if (addr.IsValid() && !addr.IsAny() && !addr.IsLoopback())
2020         return true;
2021 
2022     return false;
2023 }
2024 
OnSendFeatureSet(unsigned pduType,H225_FeatureSet & feats,PBoolean advertise) const2025 PBoolean H323Gatekeeper::OnSendFeatureSet(unsigned pduType, H225_FeatureSet & feats, PBoolean advertise) const
2026 {
2027 #ifdef H323_H460
2028     return features->SendFeature(pduType, feats, advertise);
2029 #else
2030     return endpoint.OnSendFeatureSet(pduType, feats, advertise);
2031 #endif
2032 }
2033 
OnReceiveFeatureSet(unsigned pduType,const H225_FeatureSet & feats) const2034 void H323Gatekeeper::OnReceiveFeatureSet(unsigned pduType, const H225_FeatureSet & feats) const
2035 {
2036 #ifdef H323_H460
2037     features->ReceiveFeature(pduType, feats);
2038 #else
2039     endpoint.OnReceiveFeatureSet(pduType, feats);
2040 #endif
2041 }
2042 
2043 #ifdef H323_H460
DisableFeatureSet(int msgtype) const2044 void H323Gatekeeper::DisableFeatureSet(int msgtype) const
2045 {
2046     features->DisableAllFeatures(msgtype);
2047 }
2048 
GetFeatures()2049 H460_FeatureSet & H323Gatekeeper::GetFeatures()
2050 {
2051     return *features;
2052 }
2053 #endif
2054 
2055 /////////////////////////////////////////////////////////////////////////////
2056