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