Tidied some trace logs to assure all have a category (bit before a tab character...
[opal/cbnco.git] / src / h323 / gkclient.cxx
bloba04d8c29803783399510f052a19662aa8c04264a
1 /*
2 * gkclient.cxx
4 * Gatekeeper client protocol handler
6 * Open H323 Library
8 * Copyright (c) 1999-2000 Equivalence Pty. Ltd.
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/
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.
20 * The Original Code is Open H323 Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions of this code were written with the assisance of funding from
25 * iFace In, http://www.iface.com
27 * Contributor(s): ______________________________________.
29 * $Log$
30 * Revision 2.36 2007/04/02 05:51:33 rjongbloed
31 * Tidied some trace logs to assure all have a category (bit before a tab character) set.
33 * Revision 2.35 2006/07/28 10:41:50 rjongbloed
34 * Fixed DevStudio 2005 warnings on time_t conversions.
36 * Revision 2.34 2006/06/30 05:26:13 csoutheren
37 * Applied 1509255 - Checking whether SetSize succeeds in GkClient
38 * Borko Jandras
40 * Revision 2.33 2006/06/22 22:44:24 csoutheren
41 * Fix compile problem when H.460 is disabled
43 * Revision 2.32 2006/06/07 23:41:57 csoutheren
44 * Fixed compile warning on gcc
46 * Revision 2.31 2006/05/30 11:33:02 hfriederich
47 * Porting support for H.460 from OpenH323
49 * Revision 2.30 2006/03/07 11:23:46 csoutheren
50 * Add ability to disable GRQ on GK registration
52 * Revision 2.29 2006/02/22 10:52:30 csoutheren
53 * Applied patch #1375161 from Frederic Heem
54 * Add srcInfo to ARQ
56 * Revision 2.28 2006/02/13 11:31:20 csoutheren
57 * Removed debug
59 * Revision 2.27 2006/02/13 11:09:56 csoutheren
60 * Multiple fixes for H235 authenticators
62 * Revision 2.26 2006/01/02 15:51:44 dsandras
63 * Merged changes from OpenH323 Atlas_devel_2.
65 * Revision 2.25 2005/10/12 21:14:32 dsandras
66 * Applied patch from Hannes Friederich to only call ConnectTo when required. Thanks!
68 * Revision 2.24 2005/08/11 22:47:17 rjongbloed
69 * Fixed correct default gatekeeper address when doing auto-discovery
71 * Revision 2.23 2005/04/20 06:18:35 csoutheren
72 * Patch 1182998. Fix for using GK through NAT, and fixed Connect to be idempotent
73 * Thanks to Hannes Friederich
75 * Revision 2.22 2005/02/21 19:24:18 dsandras
76 * Fixed problem with GRQ timeout not being set.
78 * Revision 2.21 2005/01/16 23:07:33 csoutheren
79 * Fixed problem with IPv6 INADDR_ANY
81 * Revision 2.20 2004/08/14 07:56:30 rjongbloed
82 * Major revision to utilise the PSafeCollection classes for the connections and calls.
84 * Revision 2.19 2004/04/07 08:21:02 rjongbloed
85 * Changes for new RTTI system.
87 * Revision 2.18 2004/03/13 06:30:03 rjongbloed
88 * Changed parameter in UDP write function to void * from PObject *.
90 * Revision 2.17 2004/02/19 10:47:03 rjongbloed
91 * Merged OpenH323 version 1.13.1 changes.
93 * Revision 2.16 2003/01/07 04:39:53 robertj
94 * Updated to OpenH323 v1.11.2
96 * Revision 2.15 2002/11/12 08:53:01 robertj
97 * Fixed GNU comaptibility
99 * Revision 2.14 2002/11/10 11:33:18 robertj
100 * Updated to OpenH323 v1.10.3
102 * Revision 2.13 2002/09/13 05:16:33 robertj
103 * Fixed missing address defaults in DiscoverByNameAndAddress()
105 * Revision 2.12 2002/09/12 06:58:33 robertj
106 * Removed protocol prefix strings as static members as has problems with
107 * use in DLL environment.
109 * Revision 2.11 2002/09/04 06:01:48 robertj
110 * Updated to OpenH323 v1.9.6
112 * Revision 2.10 2002/07/01 04:56:31 robertj
113 * Updated to OpenH323 v1.9.1
115 * Revision 2.9 2002/03/22 06:57:49 robertj
116 * Updated to OpenH323 version 1.8.2
118 * Revision 2.8 2002/02/11 09:32:12 robertj
119 * Updated to openH323 v1.8.0
121 * Revision 2.7 2002/01/14 06:35:57 robertj
122 * Updated to OpenH323 v1.7.9
124 * Revision 2.6 2001/11/18 23:10:42 craigs
125 * Added cast to allow compilation under Linux
127 * Revision 2.5 2001/11/09 05:49:47 robertj
128 * Abstracted UDP connection algorithm
130 * Revision 2.4 2001/10/05 00:22:13 robertj
131 * Updated to PWLib 1.2.0 and OpenH323 1.7.0
133 * Revision 2.3 2001/08/17 08:30:21 robertj
134 * Update from OpenH323
135 * Moved call end reasons enum from OpalConnection to global.
137 * Revision 2.2 2001/08/13 05:10:39 robertj
138 * Updates from OpenH323 v1.6.0 release.
140 * Revision 2.1 2001/08/01 05:16:18 robertj
141 * Moved default session ID's to OpalMediaFormat class.
143 * Revision 2.0 2001/07/27 15:48:25 robertj
144 * Conversion of OpenH323 to Open Phone Abstraction Library (OPAL)
146 * Revision 1.148 2004/01/17 18:20:15 csoutheren
147 * No longer force re-register on completion of LRQ
149 * Revision 1.147 2003/12/29 04:59:25 csoutheren
150 * Added callbacks on H323EndPoint when gatekeeper discovery succeeds or fails
152 * Revision 1.146 2003/12/28 00:06:34 csoutheren
153 * Added callbacks on H323EndPoint when gatekeeper registration succeeds or fails
155 * Revision 1.145 2003/05/01 05:04:00 robertj
156 * Fixed inclusion of 127.0.0.1 into listener lists when no needed.
158 * Revision 1.144 2003/04/30 07:25:32 robertj
159 * Fixed setting of remote ID in alternate credentials.
161 * Revision 1.143 2003/04/30 00:28:54 robertj
162 * Redesigned the alternate credentials in ARQ system as old implementation
163 * was fraught with concurrency issues, most importantly it can cause false
164 * detection of replay attacks taking out an endpoint completely.
166 * Revision 1.142 2003/04/10 09:44:31 robertj
167 * Added associated transport to new GetInterfaceAddresses() function so
168 * interfaces can be ordered according to active transport links. Improves
169 * interoperability.
170 * Replaced old listener GetTransportPDU() with GetInterfaceAddresses()
171 * and H323SetTransportAddresses() functions.
173 * Revision 1.141 2003/04/09 03:08:10 robertj
174 * Fixed race condition in shutting down transactor (pure virtual call)
176 * Revision 1.140 2003/03/26 00:46:28 robertj
177 * Had another go at making H323Transactor being able to be created
178 * without having a listener running.
180 * Revision 1.139 2003/03/20 01:51:11 robertj
181 * More abstraction of H.225 RAS and H.501 protocols transaction handling.
183 * Revision 1.138 2003/02/21 05:25:45 craigs
184 * Abstracted out underlying transports for use with peerelements
186 * Revision 1.137 2003/02/12 23:59:25 robertj
187 * Fixed adding missing endpoint identifer in SETUP packet when gatekeeper
188 * routed, pointed out by Stefan Klein
189 * Also fixed correct rutrn of gk routing in IRR packet.
191 * Revision 1.136 2003/02/11 04:46:37 robertj
192 * Fixed keep alive RRQ being rejected with full registration required
193 * reason actually doing a full registration!
195 * Revision 1.135 2003/02/10 01:51:50 robertj
196 * Fixed bad tokens causing an apparent "transport error", now correctly
197 * indicates a security error.
199 * Revision 1.134 2003/02/07 06:38:47 robertj
200 * Changed registration state to an enum so can determine why the RRQ failed.
202 * Revision 1.133 2003/02/04 07:04:45 robertj
203 * Prevent multiple calls to Connect() if did not change the gk.
205 * Revision 1.132 2003/02/01 13:31:21 robertj
206 * Changes to support CAT authentication in RAS.
208 * Revision 1.131 2003/01/11 05:04:03 robertj
209 * Added checks for valid URQ packet, thanks Chih-Wei Huang
211 * Revision 1.130 2003/01/09 04:45:04 robertj
212 * Fixed problem where if gets GRJ which does not have an alternate gatekeeper
213 * the system gets into an infinite loop, pointed out by Vladimir Toncar
215 * Revision 1.129 2003/01/06 07:09:43 robertj
216 * Further fixes for alternate gatekeeper, thanks Kevin Bouchard
218 * Revision 1.128 2002/12/23 22:47:53 robertj
219 * Changed gatekeeper discovery so an GRJ does not indicate "discovered".
220 * Added trace output of alternate gatekeepers list.
221 * Fixed receiving GRJ with alternate gatekeepers to immediately do discover
222 * and registration on the alternate.
224 * Revision 1.127 2002/12/19 23:52:53 robertj
225 * Fixed probelm with registering with alternate gk, thanks Kevin Bouchard
227 * Revision 1.126 2002/12/10 23:39:03 robertj
228 * Added some extra tracing.
230 * Revision 1.125 2002/11/28 04:41:48 robertj
231 * Added support for RAS ServiceControlIndication command.
233 * Revision 1.124 2002/11/27 06:54:56 robertj
234 * Added Service Control Session management as per Annex K/H.323 via RAS
235 * only at this stage.
236 * Added H.248 ASN and very primitive infrastructure for linking into the
237 * Service Control Session management system.
238 * Added basic infrastructure for Annex K/H.323 HTTP transport system.
239 * Added Call Credit Service Control to display account balances.
241 * Revision 1.123 2002/11/22 07:16:14 robertj
242 * Changed ARQ to include all local aliases for connection.
244 * Revision 1.122 2002/11/21 07:29:15 robertj
245 * Fixed GNU warning
247 * Revision 1.121 2002/11/21 07:21:49 robertj
248 * Improvements to alternate gatekeeper client code, thanks Kevin Bouchard
250 * Revision 1.120 2002/11/12 03:13:24 robertj
251 * Removed redundent code.
253 * Revision 1.119 2002/11/10 08:10:43 robertj
254 * Moved constants for "well known" ports to better place (OPAL change).
256 * Revision 1.118 2002/11/01 03:48:18 robertj
257 * Fixed previous two hacks!! Neither of which would have worked.
259 * Revision 1.117 2002/10/31 23:31:41 dereks
260 * Fix for previous quick hack. Thanks Damien Sandras.
262 * Revision 1.116 2002/10/31 21:40:28 dereks
263 * Quick (and temporary) hack to enable compilation on redhat 8.0 boxes.
265 * Revision 1.115 2002/09/19 23:19:25 robertj
266 * Fixed setting of info request rate, broken in a previous patch
268 * Revision 1.114 2002/09/18 06:58:32 robertj
269 * Fixed setting of IRR frequency, an RCF could reset timer so it did not time
270 * out correctly and send IRR in time causing problems with gatekeeper.
272 * Revision 1.113 2002/09/09 23:59:59 robertj
273 * Fixed incorrect inserting of UUIE pdu's into IRR, thanks Ravelli Rossano
275 * Revision 1.112 2002/08/29 07:02:19 robertj
276 * Allowed network latency deadband in unsolicited IRR response time.
278 * Revision 1.111 2002/08/28 00:07:02 robertj
279 * Added supportsAltGK capability flag in GRQ & RRQ.
281 * Revision 1.110 2002/08/15 09:38:55 robertj
282 * Added more logging for when endpoint becomes unregistered.
284 * Revision 1.109 2002/08/15 04:12:54 robertj
285 * Fixed correct status of isRegistered flag on various reject/errors.
287 * Revision 1.108 2002/08/12 05:38:24 robertj
288 * Changes to the RAS subsystem to support ability to make requests to client
289 * from gkserver without causing bottlenecks and race conditions.
291 * Revision 1.107 2002/08/11 23:30:36 robertj
292 * Fixed typo in previous patch.
294 * Revision 1.106 2002/08/11 23:24:24 robertj
295 * Fixed problem with retrying ARQ after getting error saying are not
296 * registered and reregistering, needed new sequence number.
297 * Fixed return of correct error in ARQ response when is a transport error
298 * rather than a reject reason from ARJ.
300 * Revision 1.105 2002/08/05 10:03:47 robertj
301 * Cosmetic changes to normalise the usage of pragma interface/implementation.
303 * Revision 1.104 2002/08/05 05:17:41 robertj
304 * Fairly major modifications to support different authentication credentials
305 * in ARQ to the logged in ones on RRQ. For both client and server.
306 * Various other H.235 authentication bugs and anomalies fixed on the way.
308 * Revision 1.103 2002/07/19 10:20:03 robertj
309 * Fixed bug of missing test for IRR frequency in RCF, thanks Thien Nguyen
311 * Revision 1.102 2002/07/18 03:03:19 robertj
312 * Fixed bug with continually doing lightweight RRQ if no timeToLive present
313 * and it should not be doing it at all, ditto for unsolicited IRR.
315 * Revision 1.101 2002/07/17 00:04:10 robertj
316 * Fixed missing initialisation of alternat gk pointer to NULL, thanks Kevin Bouchard
318 * Revision 1.100 2002/07/16 13:19:13 robertj
319 * Minor optimisation of unsolicited IRR when no calls active.
321 * Revision 1.99 2002/07/16 11:06:27 robertj
322 * Added more alternate gatekeeper implementation, thanks Kevin Bouchard
324 * Revision 1.98 2002/07/11 09:34:32 robertj
325 * Fixed minor compliance to letter of specification.
327 * Revision 1.97 2002/07/11 01:34:37 robertj
328 * Temporary fix for IRR frequency provided in ACF
330 * Revision 1.96 2002/07/07 02:08:53 robertj
331 * Fixed missing originator field in IRR perCallInfo, thanks Ravelli Rossano
333 * Revision 1.95 2002/06/28 03:34:28 robertj
334 * Fixed issues with address translation on gatekeeper RAS channel.
336 * Revision 1.94 2002/06/26 03:47:49 robertj
337 * Added support for alternate gatekeepers.
339 * Revision 1.93 2002/06/26 00:50:12 robertj
340 * Added other error code in ARJ that indicates we should reregister.
342 * Revision 1.92 2002/06/05 09:20:07 robertj
343 * Added IRQ redirect of IRR to different address, thanks "thsuk".
345 * Revision 1.91 2002/05/29 00:03:19 robertj
346 * Fixed unsolicited IRR support in gk client and server,
347 * including support for IACK and INAK.
349 * Revision 1.90 2002/05/17 04:01:53 robertj
350 * Fixed problems with H.235 authentication on RAS for server and client.
351 * Added support for unsolicited IRR transmission in background (heartbeat).
353 * Revision 1.89 2002/05/09 05:43:44 robertj
354 * Added reattempt of full RRQ if get fullRegistrationRequired RRJ.
356 * Revision 1.88 2002/05/01 06:39:41 robertj
357 * Fixed incorrect setting of srcCallSignalAddress in ARQ for outgoing call as
358 * putting in incorrect data is worse than not putting anything in at all! So
359 * unless the correct data is available it is now left out.
361 * Revision 1.87 2002/03/20 02:12:49 robertj
362 * Added missing return value for number of endpoints returned in ACF
364 * Revision 1.86 2002/03/19 05:17:25 robertj
365 * Normalised ACF destExtraCallIInfo to be same as other parameters.
366 * Added ability to get multiple endpoint addresses and tokens from ACF.
368 * Revision 1.85 2002/03/01 04:06:44 robertj
369 * Fixed autoreregister on ARQ failing due to unregistered endpoint.
371 * Revision 1.84 2002/02/11 04:25:57 robertj
372 * Added ability to automatically reregister if do an ARQ and are told are not
373 * registered. Can occur if gk is restarted and is faster than waiting for TTL..
375 * Revision 1.83 2002/01/13 23:58:48 robertj
376 * Added ability to set destination extra call info in ARQ
377 * Filled in destinationInfo in ARQ when answering call.
378 * Allowed application to override srcInfo in ARQ on outgoing call by
379 * changing localPartyName.
380 * Added better end call codes for some ARJ reasons.
381 * Thanks Ben Madsen of Norwood Systems.
383 * Revision 1.82 2001/12/15 10:10:48 robertj
384 * GCC compatibility
386 * Revision 1.81 2001/12/15 08:36:49 robertj
387 * Added previous call times to all the other PDU's it is supposed to be in!
389 * Revision 1.80 2001/12/15 08:09:21 robertj
390 * Added alerting, connect and end of call times to be sent to RAS server.
392 * Revision 1.79 2001/12/14 06:41:36 robertj
393 * Added call end reason codes in DisengageRequest for GK server use.
395 * Revision 1.78 2001/12/13 11:00:13 robertj
396 * Changed search for access token in ACF to be able to look for two OID's.
398 * Revision 1.77 2001/12/06 06:44:42 robertj
399 * Removed "Win32 SSL xxx" build configurations in favour of system
400 * environment variables to select optional libraries.
402 * Revision 1.76 2001/10/12 04:14:31 robertj
403 * Changed gk unregister so only way it doe not actually unregister is if
404 * get URJ with reason code callInProgress, thanks Chris Purvis.
406 * Revision 1.75 2001/10/09 08:04:59 robertj
407 * Fixed unregistration so still unregisters if gk goes offline, thanks Chris Purvis
409 * Revision 1.74 2001/10/08 01:37:42 robertj
410 * Fixed uninitialised variable for ARQ authentication override.
412 * Revision 1.73 2001/09/26 07:03:08 robertj
413 * Added needed mutex for SeparateAuthenticationInARQ mode, thanks Nick Hoath
415 * Revision 1.72 2001/09/18 10:36:57 robertj
416 * Allowed multiple overlapping requests in RAS channel.
418 * Revision 1.71 2001/09/13 03:21:16 robertj
419 * Added ability to override authentication credentials for ARQ, thanks Nick Hoath
421 * Revision 1.70 2001/09/13 01:15:20 robertj
422 * Added flag to H235Authenticator to determine if gkid and epid is to be
423 * automatically set as the crypto token remote id and local id.
425 * Revision 1.69 2001/09/13 00:32:24 robertj
426 * Added missing gkid in ARQ, thanks Nick Hoath
428 * Revision 1.68 2001/09/12 07:48:05 robertj
429 * Fixed various problems with tracing.
431 * Revision 1.67 2001/09/12 06:58:00 robertj
432 * Added support for iNow Access Token from gk, thanks Nick Hoath
434 * Revision 1.66 2001/09/12 06:04:38 robertj
435 * Added support for sending UUIE's to gk on request, thanks Nick Hoath
437 * Revision 1.65 2001/09/05 01:16:32 robertj
438 * Added overloaded AdmissionRequest for backward compatibility.
440 * Revision 1.64 2001/08/14 04:26:46 robertj
441 * Completed the Cisco compatible MD5 authentications, thanks Wolfgang Platzer.
443 * Revision 1.63 2001/08/13 01:27:03 robertj
444 * Changed GK admission so can return multiple aliases to be used in
445 * setup packet, thanks Nick Hoath.
447 * Revision 1.62 2001/08/13 00:22:14 robertj
448 * Allowed for received DRQ not having call ID (eg v1 gk), uses conference ID
450 * Revision 1.61 2001/08/10 11:03:52 robertj
451 * Major changes to H.235 support in RAS to support server.
453 * Revision 1.60 2001/08/06 07:44:55 robertj
454 * Fixed problems with building without SSL
456 * Revision 1.59 2001/08/06 03:18:38 robertj
457 * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
458 * Improved access to H.235 secure RAS functionality.
459 * Changes to H.323 secure RAS contexts to help use with gk server.
461 * Revision 1.58 2001/08/02 04:30:43 robertj
462 * Added ability for AdmissionRequest to alter destination alias used in
463 * the outgoing call. Thanks Ben Madsen & Graeme Reid.
465 * Revision 1.57 2001/06/22 00:21:10 robertj
466 * Fixed bug in H.225 RAS protocol with 16 versus 32 bit sequence numbers.
468 * Revision 1.56 2001/06/18 23:35:01 robertj
469 * Removed condition that prevented aliases on non-terminal endpoints.
471 * Revision 1.55 2001/06/18 06:23:50 robertj
472 * Split raw H.225 RAS protocol out of gatekeeper client class.
474 * Revision 1.54 2001/05/17 03:29:13 robertj
475 * Fixed missing replyAddress in LRQ, thanks Alexander Smirnov.
476 * Added some extra optional fields to LRQ.
478 * Revision 1.53 2001/04/19 08:03:21 robertj
479 * Fixed scale on RIp delay, is milliseconds!
481 * Revision 1.52 2001/04/13 07:44:20 robertj
482 * Fixed setting isRegistered flag to false when get RRJ
484 * Revision 1.51 2001/04/05 03:39:43 robertj
485 * Fixed deadlock if tried to do discovery in time to live timeout.
487 * Revision 1.50 2001/03/28 07:13:06 robertj
488 * Changed RAS thread interlock to allow for what should not happen, the
489 * syncpoint being signalled before receiving any packets.
491 * Revision 1.49 2001/03/27 02:19:22 robertj
492 * Changed to send gk a GRQ if it gives a discoveryRequired error on RRQ.
493 * Fixed BIG condition in use of sequence numbers.
495 * Revision 1.48 2001/03/26 05:06:03 robertj
496 * Added code to do full registration if RRJ indicates discovery to be redone.
498 * Revision 1.47 2001/03/24 00:51:41 robertj
499 * Added retry every minute of time to live registration if fails.
501 * Revision 1.46 2001/03/23 01:47:49 robertj
502 * Improved debug trace message on RAS packet retry.
504 * Revision 1.45 2001/03/23 01:19:25 robertj
505 * Fixed usage of secure RAS in GRQ, should not do for that one PDU.
507 * Revision 1.44 2001/03/21 04:52:42 robertj
508 * Added H.235 security to gatekeepers, thanks Fürbass Franz!
510 * Revision 1.43 2001/03/19 23:32:30 robertj
511 * Fixed problem with auto-reregister doing so in the RAS receive thread.
513 * Revision 1.42 2001/03/19 05:50:52 robertj
514 * Fixed trace display of timeout value.
516 * Revision 1.41 2001/03/18 22:21:29 robertj
517 * Fixed GNU C++ problem.
519 * Revision 1.40 2001/03/17 00:05:52 robertj
520 * Fixed problems with Gatekeeper RIP handling.
522 * Revision 1.39 2001/03/16 06:46:21 robertj
523 * Added ability to set endpoints desired time to live on a gatekeeper.
525 * Revision 1.38 2001/03/15 00:25:58 robertj
526 * Fixed bug in receiving RIP packet, did not restart timeout.
528 * Revision 1.37 2001/03/09 02:55:53 robertj
529 * Fixed bug in RAS IRR, optional field not being included, thanks Erik Larsson.
531 * Revision 1.36 2001/03/02 06:59:59 robertj
532 * Enhanced the globally unique identifier class.
534 * Revision 1.35 2001/02/28 00:20:16 robertj
535 * Added DiscoverByNameAndAddress() function, thanks Chris Purvis.
537 * Revision 1.34 2001/02/18 22:33:47 robertj
538 * Added better handling of URJ, thanks Chris Purvis.
540 * Revision 1.33 2001/02/09 05:13:55 craigs
541 * Added pragma implementation to (hopefully) reduce the executable image size
542 * under Linux
544 * Revision 1.32 2001/01/25 01:44:26 robertj
545 * Reversed order of changing alias list to avoid assert if delete all aliases.
547 * Revision 1.31 2000/11/01 03:30:27 robertj
548 * Changed gatekeeper registration time to live to update in slightly less than the
549 * time to live time. Allows for system/network latency. Thanks Laurent PELLETIER.
551 * Revision 1.30 2000/09/25 06:48:11 robertj
552 * Removed use of alias if there is no alias present, ie only have transport address.
554 * Revision 1.29 2000/09/01 02:12:37 robertj
555 * Fixed problem when multiple GK's on LAN, only discovered first one.
556 * Added ability to select a gatekeeper on LAN via it's identifier name.
558 * Revision 1.28 2000/07/15 09:54:21 robertj
559 * Fixed problem with having empty or unusable assigned aliases.
561 * Revision 1.27 2000/07/11 19:26:39 robertj
562 * Fixed problem with endpoint identifiers from some gatekeepers not being a string, just binary info.
564 * Revision 1.26 2000/06/20 03:18:04 robertj
565 * Added function to get name of gatekeeper, subtle difference from getting identifier.
567 * Revision 1.25 2000/05/09 12:14:32 robertj
568 * Added adjustment of endpoints alias list as approved by gatekeeper.
570 * Revision 1.24 2000/05/09 08:52:50 robertj
571 * Added support for preGrantedARQ fields on registration.
573 * Revision 1.23 2000/05/04 10:43:54 robertj
574 * Fixed problem with still trying to RRQ if got a GRJ.
576 * Revision 1.22 2000/05/02 04:32:26 robertj
577 * Fixed copyright notice comment.
579 * Revision 1.21 2000/04/27 02:52:58 robertj
580 * Added keepAlive field to RRQ if already registered,
582 * Revision 1.20 2000/04/12 21:22:16 robertj
583 * Fixed warning in No Trace mode.
585 * Revision 1.19 2000/04/11 04:00:55 robertj
586 * Filled in destCallSignallingAddress if specified by caller, used for gateway permissions.
588 * Revision 1.18 2000/04/11 03:11:12 robertj
589 * Added ability to reject reason on gatekeeper requests.
591 * Revision 1.17 2000/03/29 02:14:43 robertj
592 * Changed TerminationReason to CallEndReason to use correct telephony nomenclature.
593 * Added CallEndReason for capability exchange failure.
595 * Revision 1.16 2000/03/23 02:45:28 robertj
596 * Changed ClearAllCalls() so will wait for calls to be closed (usefull in endpoint dtors).
598 * Revision 1.15 2000/03/21 23:17:55 robertj
599 * Changed GK client so does not fill in destCallSignalAddress on outgoing call.
601 * Revision 1.14 2000/01/28 00:56:48 robertj
602 * Changed ACF to return destination address irrespective of callModel, thanks Chris Gindel.
604 * Revision 1.13 1999/12/23 23:02:35 robertj
605 * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
607 * Revision 1.12 1999/12/11 02:20:58 robertj
608 * Added ability to have multiple aliases on local endpoint.
610 * Revision 1.11 1999/12/10 01:43:25 robertj
611 * Fixed outgoing call Admissionrequestion addresses.
613 * Revision 1.10 1999/12/09 21:49:18 robertj
614 * Added reregister on unregister and time to live reregistration
616 * Revision 1.9 1999/11/06 05:37:45 robertj
617 * Complete rewrite of termination of connection to avoid numerous race conditions.
619 * Revision 1.8 1999/10/16 03:47:48 robertj
620 * Fixed termination of gatekeeper RAS thread problem
622 * Revision 1.7 1999/10/15 05:55:50 robertj
623 * Fixed crash in responding to InfoRequest
625 * Revision 1.6 1999/09/23 08:48:45 robertj
626 * Changed register request so cannot do it of have no listeners.
628 * Revision 1.5 1999/09/21 14:09:19 robertj
629 * Removed warnings when no tracing enabled.
631 * Revision 1.4 1999/09/14 08:19:37 robertj
632 * Fixed timeout on retry of gatekeeper discover and added more tracing.
634 * Revision 1.3 1999/09/14 06:52:54 robertj
635 * Added better support for multi-homed client hosts.
637 * Revision 1.2 1999/09/10 02:45:31 robertj
638 * Added missing binding of address to transport when a specific gatway is used.
640 * Revision 1.1 1999/08/31 12:34:18 robertj
641 * Added gatekeeper support.
645 #include <ptlib.h>
647 #ifdef __GNUC__
648 #pragma implementation "gkclient.h"
649 #endif
651 #include <h323/gkclient.h>
653 #include <h323/h323ep.h>
654 #include <h323/h323con.h>
655 #include <h323/h323pdu.h>
656 #include <h323/h323rtp.h>
658 #ifdef H323_H460
659 #include <h323/h4601.h>
660 #endif
662 #define new PNEW
664 static class PAuthInitialiseInstantiateMe
666 public:
667 PAuthInitialiseInstantiateMe()
669 PWLibStupidLinkerHacks::h235AuthLoader = 1;
670 #if P_SSL
671 PWLibStupidLinkerHacks::h235AuthProcedure1Loader = 1;
672 #endif
674 } instance;
676 static PTimeInterval AdjustTimeout(unsigned seconds)
678 // Allow for an incredible amount of system/network latency
679 static unsigned TimeoutDeadband = 5; // seconds
681 return PTimeInterval(0, seconds > TimeoutDeadband
682 ? (seconds - TimeoutDeadband)
683 : TimeoutDeadband);
687 /////////////////////////////////////////////////////////////////////////////
689 H323Gatekeeper::H323Gatekeeper(H323EndPoint & ep, H323Transport * trans)
690 : H225_RAS(ep, trans),
691 requestMutex(1, 1),
692 authenticators(ep.CreateAuthenticators())
693 #ifdef H323_H460
694 ,features(ep.GetFeatureSet())
695 #endif
697 alternatePermanent = FALSE;
698 discoveryComplete = FALSE;
699 registrationFailReason = UnregisteredLocally;
701 pregrantMakeCall = pregrantAnswerCall = RequireARQ;
703 autoReregister = TRUE;
704 reregisterNow = FALSE;
705 requiresDiscovery = FALSE;
707 timeToLive.SetNotifier(PCREATE_NOTIFIER(TickleMonitor));
708 infoRequestRate.SetNotifier(PCREATE_NOTIFIER(TickleMonitor));
710 willRespondToIRR = FALSE;
711 monitorStop = FALSE;
713 monitor = PThread::Create(PCREATE_NOTIFIER(MonitorMain), 0,
714 PThread::NoAutoDeleteThread,
715 PThread::NormalPriority,
716 "GkMonitor:%x");
718 #ifdef H323_H460
719 features.LoadFeatureSet(H460_Feature::FeatureRas);
720 #endif
724 H323Gatekeeper::~H323Gatekeeper()
726 if (monitor != NULL) {
727 monitorStop = TRUE;
728 monitorTickle.Signal();
729 monitor->WaitForTermination();
730 delete monitor;
733 StopChannel();
737 PString H323Gatekeeper::GetName() const
739 PStringStream s;
740 s << *this;
741 return s;
745 BOOL H323Gatekeeper::DiscoverAny()
747 gatekeeperIdentifier = PString();
748 return StartDiscovery(H323TransportAddress());
752 BOOL H323Gatekeeper::DiscoverByName(const PString & identifier)
754 gatekeeperIdentifier = identifier;
755 return StartDiscovery(H323TransportAddress());
759 BOOL H323Gatekeeper::DiscoverByAddress(const H323TransportAddress & address)
761 gatekeeperIdentifier = PString();
762 return StartDiscovery(address);
766 BOOL H323Gatekeeper::DiscoverByNameAndAddress(const PString & identifier,
767 const H323TransportAddress & address)
769 gatekeeperIdentifier = identifier;
770 return StartDiscovery(address);
774 static BOOL WriteGRQ(H323Transport & transport, void * param)
776 H323RasPDU & pdu = *(H323RasPDU *)param;
777 H225_GatekeeperRequest & grq = pdu;
778 H323TransportAddress address = transport.GetLocalAddress();
780 // We do have to use the translated address if one is specified
781 PIPSocket::Address localAddress, remoteAddress;
782 WORD localPort;
784 if (address.GetIpAndPort(localAddress, localPort) &&
785 transport.GetRemoteAddress().GetIpAddress(remoteAddress))
787 if (transport.GetEndPoint().GetManager().TranslateIPAddress(localAddress, remoteAddress))
788 address = H323TransportAddress(localAddress, localPort);
791 address.SetPDU(grq.m_rasAddress);
792 return pdu.Write(transport);
796 BOOL H323Gatekeeper::StartDiscovery(const H323TransportAddress & initialAddress)
798 if (PAssertNULL(transport) == NULL)
799 return FALSE;
801 PAssert(!transport->IsRunning(), "Cannot do discovery on running RAS channel");
803 H323TransportAddress address = initialAddress;
804 if (address.IsEmpty())
805 address = "udp$*:1719";
807 if (!transport->ConnectTo(address))
808 return FALSE;
810 /// don't send GRQ if not requested
811 if (!endpoint.GetSendGRQ() && !initialAddress.IsEmpty()) {
812 StartChannel();
813 PTRACE(2, "RAS\tSkipping gatekeeper discovery for " << initialAddress);
814 return TRUE;
817 discoveryComplete = FALSE;
819 H323RasPDU pdu;
820 Request request(SetupGatekeeperRequest(pdu), pdu);
822 request.responseInfo = &address;
824 requestsMutex.Wait();
825 requests.SetAt(request.sequenceNumber, &request);
826 requestsMutex.Signal();
828 for (unsigned retry = 0; retry < endpoint.GetGatekeeperRequestRetries(); retry++) {
829 if (!transport->WriteConnect(WriteGRQ, &pdu)) {
830 PTRACE(1, "RAS\tError writing discovery PDU: " << transport->GetErrorText());
831 break;
834 H323RasPDU response;
835 transport->SetReadTimeout(endpoint.GetGatekeeperRequestTimeout ());
836 if (response.Read(*transport) && HandleTransaction(response) && discoveryComplete)
837 break;
840 transport->EndConnect(transport->GetLocalAddress());
842 if (discoveryComplete) {
843 PTRACE(2, "RAS\tGatekeeper discovered at: "
844 << transport->GetRemoteAddress()
845 << " (if=" << transport->GetLocalAddress() << ')');
846 StartChannel();
849 requestsMutex.Wait();
850 requests.SetAt(request.sequenceNumber, NULL);
851 requestsMutex.Signal();
853 return discoveryComplete;
857 unsigned H323Gatekeeper::SetupGatekeeperRequest(H323RasPDU & request)
859 if (PAssertNULL(transport) == NULL)
860 return 0;
862 H225_GatekeeperRequest & grq = request.BuildGatekeeperRequest(GetNextSequenceNumber());
864 H323TransportAddress rasAddress = transport->GetLocalAddress();
865 rasAddress.SetPDU(grq.m_rasAddress);
867 endpoint.SetEndpointTypeInfo(grq.m_endpointType);
869 grq.IncludeOptionalField(H225_GatekeeperRequest::e_endpointAlias);
870 H323SetAliasAddresses(endpoint.GetAliasNames(), grq.m_endpointAlias);
872 if (!gatekeeperIdentifier) {
873 grq.IncludeOptionalField(H225_GatekeeperRequest::e_gatekeeperIdentifier);
874 grq.m_gatekeeperIdentifier = gatekeeperIdentifier;
877 grq.IncludeOptionalField(H225_GatekeeperRequest::e_supportsAltGK);
879 H225_RAS::OnSendGatekeeperRequest(request, grq);
881 discoveryComplete = FALSE;
883 return grq.m_requestSeqNum;
887 void H323Gatekeeper::OnSendGatekeeperRequest(H225_GatekeeperRequest & grq)
889 H225_RAS::OnSendGatekeeperRequest(grq);
891 for (PINDEX i = 0; i < authenticators.GetSize(); i++) {
892 if (authenticators[i].SetCapability(grq.m_authenticationCapability, grq.m_algorithmOIDs)) {
893 grq.IncludeOptionalField(H225_GatekeeperRequest::e_authenticationCapability);
894 grq.IncludeOptionalField(H225_GatekeeperRequest::e_algorithmOIDs);
900 BOOL H323Gatekeeper::OnReceiveGatekeeperConfirm(const H225_GatekeeperConfirm & gcf)
902 if (!H225_RAS::OnReceiveGatekeeperConfirm(gcf))
903 return FALSE;
905 PINDEX i;
907 for (i = 0; i < authenticators.GetSize(); i++) {
908 H235Authenticator & authenticator = authenticators[i];
909 if (authenticator.UseGkAndEpIdentifiers())
910 authenticator.SetRemoteId(gatekeeperIdentifier);
913 if (gcf.HasOptionalField(H225_GatekeeperConfirm::e_authenticationMode) &&
914 gcf.HasOptionalField(H225_GatekeeperConfirm::e_algorithmOID)) {
915 for (i = 0; i < authenticators.GetSize(); i++) {
916 H235Authenticator & authenticator = authenticators[i];
917 authenticator.Enable(authenticator.IsCapability(gcf.m_authenticationMode,
918 gcf.m_algorithmOID));
922 H323TransportAddress locatedAddress(gcf.m_rasAddress, "udp");
923 PTRACE(2, "RAS\tGatekeeper discovery found " << locatedAddress);
925 if (!transport->SetRemoteAddress(locatedAddress)) {
926 PTRACE(2, "RAS\tInvalid gatekeeper discovery address: \"" << locatedAddress << '"');
927 return FALSE;
930 if (gcf.HasOptionalField(H225_GatekeeperConfirm::e_alternateGatekeeper))
931 SetAlternates(gcf.m_alternateGatekeeper, FALSE);
933 endpoint.OnGatekeeperConfirm();
935 discoveryComplete = TRUE;
936 return TRUE;
940 BOOL H323Gatekeeper::OnReceiveGatekeeperReject(const H225_GatekeeperReject & grj)
942 if (!H225_RAS::OnReceiveGatekeeperReject(grj))
943 return FALSE;
945 if (grj.HasOptionalField(H225_GatekeeperReject::e_altGKInfo)) {
946 SetAlternates(grj.m_altGKInfo.m_alternateGatekeeper,
947 grj.m_altGKInfo.m_altGKisPermanent);
949 if (lastRequest->responseInfo != NULL) {
950 H323TransportAddress & gkAddress = *(H323TransportAddress *)lastRequest->responseInfo;
951 gkAddress = alternates[0].rasAddress;
955 endpoint.OnGatekeeperReject();
957 return TRUE;
961 BOOL H323Gatekeeper::RegistrationRequest(BOOL autoReg)
963 if (PAssertNULL(transport) == NULL)
964 return FALSE;
966 autoReregister = autoReg;
968 H323RasPDU pdu;
969 H225_RegistrationRequest & rrq = pdu.BuildRegistrationRequest(GetNextSequenceNumber());
971 // If discoveryComplete flag is FALSE then do lightweight reregister
972 rrq.m_discoveryComplete = discoveryComplete;
974 rrq.m_rasAddress.SetSize(1);
975 H323TransportAddress rasAddress = transport->GetLocalAddress();
977 // We do have to use the translated address if specified
978 PIPSocket::Address localAddress, remoteAddress;
979 WORD localPort;
981 if(rasAddress.GetIpAndPort(localAddress, localPort) &&
982 transport->GetRemoteAddress().GetIpAddress(remoteAddress))
984 OpalManager & manager = transport->GetEndPoint().GetManager();
986 if(manager.TranslateIPAddress(localAddress, remoteAddress))
988 rasAddress = H323TransportAddress(localAddress, localPort);
992 rasAddress.SetPDU(rrq.m_rasAddress[0]);
994 H323TransportAddressArray listeners = endpoint.GetInterfaceAddresses(TRUE, transport);
995 if (listeners.IsEmpty()) {
996 PTRACE(1, "RAS\tCannot register with Gatekeeper without a H323Listener!");
997 return FALSE;
1000 for (PINDEX i = 0; i < listeners.GetSize(); i++)
1001 listeners[i].SetPDU(rrq.m_callSignalAddress, *transport);
1003 endpoint.SetEndpointTypeInfo(rrq.m_terminalType);
1004 endpoint.SetVendorIdentifierInfo(rrq.m_endpointVendor);
1006 rrq.IncludeOptionalField(H225_RegistrationRequest::e_terminalAlias);
1007 H323SetAliasAddresses(endpoint.GetAliasNames(), rrq.m_terminalAlias);
1009 rrq.m_willSupplyUUIEs = TRUE;
1010 rrq.IncludeOptionalField(H225_RegistrationRequest::e_usageReportingCapability);
1011 rrq.m_usageReportingCapability.IncludeOptionalField(H225_RasUsageInfoTypes::e_startTime);
1012 rrq.m_usageReportingCapability.IncludeOptionalField(H225_RasUsageInfoTypes::e_endTime);
1013 rrq.m_usageReportingCapability.IncludeOptionalField(H225_RasUsageInfoTypes::e_terminationCause);
1014 rrq.IncludeOptionalField(H225_RegistrationRequest::e_supportsAltGK);
1016 if (!gatekeeperIdentifier) {
1017 rrq.IncludeOptionalField(H225_RegistrationRequest::e_gatekeeperIdentifier);
1018 rrq.m_gatekeeperIdentifier = gatekeeperIdentifier;
1021 if (!endpointIdentifier.IsEmpty()) {
1022 rrq.IncludeOptionalField(H225_RegistrationRequest::e_endpointIdentifier);
1023 rrq.m_endpointIdentifier = endpointIdentifier;
1026 PTimeInterval ttl = endpoint.GetGatekeeperTimeToLive();
1027 if (ttl > 0) {
1028 rrq.IncludeOptionalField(H225_RegistrationRequest::e_timeToLive);
1029 rrq.m_timeToLive = (int)ttl.GetSeconds();
1032 if (endpoint.CanDisplayAmountString()) {
1033 rrq.IncludeOptionalField(H225_RegistrationRequest::e_callCreditCapability);
1034 rrq.m_callCreditCapability.IncludeOptionalField(H225_CallCreditCapability::e_canDisplayAmountString);
1035 rrq.m_callCreditCapability.m_canDisplayAmountString = TRUE;
1038 if (endpoint.CanEnforceDurationLimit()) {
1039 rrq.IncludeOptionalField(H225_RegistrationRequest::e_callCreditCapability);
1040 rrq.m_callCreditCapability.IncludeOptionalField(H225_CallCreditCapability::e_canEnforceDurationLimit);
1041 rrq.m_callCreditCapability.m_canEnforceDurationLimit = TRUE;
1044 if (IsRegistered()) {
1045 rrq.IncludeOptionalField(H225_RegistrationRequest::e_keepAlive);
1046 rrq.m_keepAlive = TRUE;
1049 // After doing full register, do lightweight reregisters from now on
1050 discoveryComplete = FALSE;
1052 Request request(rrq.m_requestSeqNum, pdu);
1053 if (MakeRequest(request))
1054 return TRUE;
1056 PTRACE(3, "RAS\tFailed registration of " << endpointIdentifier << " with " << gatekeeperIdentifier);
1057 switch (request.responseResult) {
1058 case Request::RejectReceived :
1059 switch (request.rejectReason) {
1060 case H225_RegistrationRejectReason::e_discoveryRequired :
1061 // If have been told by GK that we need to discover it again, set flag
1062 // for next register done by timeToLive handler to do discovery
1063 requiresDiscovery = TRUE;
1064 // Do next case
1066 case H225_RegistrationRejectReason::e_fullRegistrationRequired :
1067 registrationFailReason = GatekeeperLostRegistration;
1068 // Set timer to retry registration
1069 reregisterNow = TRUE;
1070 monitorTickle.Signal();
1071 break;
1073 // Onse below here are permananent errors, so don't try again
1074 case H225_RegistrationRejectReason::e_invalidCallSignalAddress :
1075 registrationFailReason = InvalidListener;
1076 break;
1078 case H225_RegistrationRejectReason::e_duplicateAlias :
1079 registrationFailReason = DuplicateAlias;
1080 break;
1082 case H225_RegistrationRejectReason::e_securityDenial :
1083 registrationFailReason = SecurityDenied;
1084 break;
1086 default :
1087 registrationFailReason = (RegistrationFailReasons)(request.rejectReason|RegistrationRejectReasonMask);
1088 break;
1090 break;
1092 case Request::BadCryptoTokens :
1093 registrationFailReason = SecurityDenied;
1094 break;
1096 default :
1097 registrationFailReason = TransportError;
1098 break;
1101 return FALSE;
1105 BOOL H323Gatekeeper::OnReceiveRegistrationConfirm(const H225_RegistrationConfirm & rcf)
1107 if (!H225_RAS::OnReceiveRegistrationConfirm(rcf))
1108 return FALSE;
1110 registrationFailReason = RegistrationSuccessful;
1112 endpointIdentifier = rcf.m_endpointIdentifier;
1113 PTRACE(3, "RAS\tRegistered " << endpointIdentifier << " with " << gatekeeperIdentifier);
1116 if (rcf.HasOptionalField(H225_RegistrationConfirm::e_alternateGatekeeper))
1117 SetAlternates(rcf.m_alternateGatekeeper, FALSE);
1119 if (rcf.HasOptionalField(H225_RegistrationConfirm::e_timeToLive))
1120 timeToLive = AdjustTimeout(rcf.m_timeToLive);
1121 else
1122 timeToLive = 0; // zero disables lightweight RRQ
1124 // At present only support first call signal address to GK
1125 if (rcf.m_callSignalAddress.GetSize() > 0)
1126 gkRouteAddress = rcf.m_callSignalAddress[0];
1128 willRespondToIRR = rcf.m_willRespondToIRR;
1130 pregrantMakeCall = pregrantAnswerCall = RequireARQ;
1131 if (rcf.HasOptionalField(H225_RegistrationConfirm::e_preGrantedARQ)) {
1132 if (rcf.m_preGrantedARQ.m_makeCall)
1133 pregrantMakeCall = rcf.m_preGrantedARQ.m_useGKCallSignalAddressToMakeCall
1134 ? PreGkRoutedARQ : PregrantARQ;
1135 if (rcf.m_preGrantedARQ.m_answerCall)
1136 pregrantAnswerCall = rcf.m_preGrantedARQ.m_useGKCallSignalAddressToAnswer
1137 ? PreGkRoutedARQ : PregrantARQ;
1138 if (rcf.m_preGrantedARQ.HasOptionalField(H225_RegistrationConfirm_preGrantedARQ::e_irrFrequencyInCall))
1139 SetInfoRequestRate(AdjustTimeout(rcf.m_preGrantedARQ.m_irrFrequencyInCall));
1140 else
1141 ClearInfoRequestRate();
1143 else
1144 ClearInfoRequestRate();
1146 // Remove the endpoint aliases that the gatekeeper did not like and add the
1147 // ones that it really wants us to be.
1148 if (rcf.HasOptionalField(H225_RegistrationConfirm::e_terminalAlias)) {
1149 const PStringList & currentAliases = endpoint.GetAliasNames();
1150 PStringList aliasesToChange;
1151 PINDEX i, j;
1153 for (i = 0; i < rcf.m_terminalAlias.GetSize(); i++) {
1154 PString alias = H323GetAliasAddressString(rcf.m_terminalAlias[i]);
1155 if (!alias) {
1156 for (j = 0; j < currentAliases.GetSize(); j++) {
1157 if (alias *= currentAliases[j])
1158 break;
1160 if (j >= currentAliases.GetSize())
1161 aliasesToChange.AppendString(alias);
1164 for (i = 0; i < aliasesToChange.GetSize(); i++) {
1165 PTRACE(2, "RAS\tGatekeeper add of alias \"" << aliasesToChange[i] << '"');
1166 endpoint.AddAliasName(aliasesToChange[i]);
1169 aliasesToChange.RemoveAll();
1171 for (i = 0; i < currentAliases.GetSize(); i++) {
1172 for (j = 0; j < rcf.m_terminalAlias.GetSize(); j++) {
1173 if (currentAliases[i] *= H323GetAliasAddressString(rcf.m_terminalAlias[j]))
1174 break;
1176 if (j >= rcf.m_terminalAlias.GetSize())
1177 aliasesToChange.AppendString(currentAliases[i]);
1179 for (i = 0; i < aliasesToChange.GetSize(); i++) {
1180 PTRACE(2, "RAS\tGatekeeper removal of alias \"" << aliasesToChange[i] << '"');
1181 endpoint.RemoveAliasName(aliasesToChange[i]);
1185 if (rcf.HasOptionalField(H225_RegistrationConfirm::e_serviceControl))
1186 OnServiceControlSessions(rcf.m_serviceControl, NULL);
1188 // NAT Detection with GNUGK
1189 if (rcf.HasOptionalField(H225_RegistrationConfirm::e_nonStandardData)) {
1190 PString NATaddr = rcf.m_nonStandardData.m_data.AsString();
1191 if ((!NATaddr.IsEmpty()) && (NATaddr.Left(4) == "NAT="))
1192 endpoint.OnGatekeeperNATDetect(NATaddr.Right(NATaddr.GetLength()-4),endpointIdentifier,gkRouteAddress);
1195 endpoint.OnRegistrationConfirm();
1197 return TRUE;
1201 BOOL H323Gatekeeper::OnReceiveRegistrationReject(const H225_RegistrationReject & rrj)
1203 if (!H225_RAS::OnReceiveRegistrationReject(rrj))
1204 return FALSE;
1206 if (rrj.HasOptionalField(H225_RegistrationReject::e_altGKInfo))
1207 SetAlternates(rrj.m_altGKInfo.m_alternateGatekeeper,
1208 rrj.m_altGKInfo.m_altGKisPermanent);
1210 endpoint.OnRegistrationReject();
1212 return TRUE;
1216 void H323Gatekeeper::RegistrationTimeToLive()
1218 PTRACE(3, "RAS\tTime To Live reregistration");
1220 if (requiresDiscovery) {
1221 PTRACE(2, "RAS\tRepeating discovery on gatekeepers request.");
1223 H323RasPDU pdu;
1224 Request request(SetupGatekeeperRequest(pdu), pdu);
1225 if (!MakeRequest(request) || !discoveryComplete) {
1226 PTRACE(2, "RAS\tRediscovery failed, retrying in 1 minute.");
1227 timeToLive = PTimeInterval(0, 0, 1);
1228 return;
1231 requiresDiscovery = FALSE;
1234 if (!RegistrationRequest(autoReregister)) {
1235 PTRACE_IF(2, !reregisterNow, "RAS\tTime To Live reregistration failed, retrying in 1 minute");
1236 timeToLive = PTimeInterval(0, 0, 1);
1241 BOOL H323Gatekeeper::UnregistrationRequest(int reason)
1243 if (PAssertNULL(transport) == NULL)
1244 return FALSE;
1246 PINDEX i;
1247 H323RasPDU pdu;
1248 H225_UnregistrationRequest & urq = pdu.BuildUnregistrationRequest(GetNextSequenceNumber());
1250 H323TransportAddress rasAddress = transport->GetLocalAddress();
1252 const H323ListenerList & listeners = endpoint.GetListeners();
1253 for (i = 0; i < listeners.GetSize(); i++) {
1254 H323TransportAddress signalAddress = listeners[i].GetLocalAddress(rasAddress);
1255 signalAddress.SetPDU(urq.m_callSignalAddress, *transport);
1258 urq.IncludeOptionalField(H225_UnregistrationRequest::e_endpointAlias);
1259 H323SetAliasAddresses(endpoint.GetAliasNames(), urq.m_endpointAlias);
1261 if (!gatekeeperIdentifier) {
1262 urq.IncludeOptionalField(H225_UnregistrationRequest::e_gatekeeperIdentifier);
1263 urq.m_gatekeeperIdentifier = gatekeeperIdentifier;
1266 if (!endpointIdentifier.IsEmpty()) {
1267 urq.IncludeOptionalField(H225_UnregistrationRequest::e_endpointIdentifier);
1268 urq.m_endpointIdentifier = endpointIdentifier;
1271 if (reason >= 0) {
1272 urq.IncludeOptionalField(H225_UnregistrationRequest::e_reason);
1273 urq.m_reason = reason;
1276 Request request(urq.m_requestSeqNum, pdu);
1278 BOOL requestResult = MakeRequest(request);
1280 for (i = 0; i < alternates.GetSize(); i++) {
1281 AlternateInfo & altgk = alternates[i];
1282 if (altgk.registrationState == AlternateInfo::IsRegistered) {
1283 Connect(altgk.rasAddress,altgk.gatekeeperIdentifier);
1284 UnregistrationRequest(reason);
1288 if (requestResult)
1289 return TRUE;
1291 switch (request.responseResult) {
1292 case Request::NoResponseReceived :
1293 registrationFailReason = TransportError;
1294 timeToLive = 0; // zero disables lightweight RRQ
1295 break;
1297 case Request::BadCryptoTokens :
1298 registrationFailReason = SecurityDenied;
1299 timeToLive = 0; // zero disables lightweight RRQ
1300 break;
1302 default :
1303 break;
1306 return !IsRegistered();
1310 BOOL H323Gatekeeper::OnReceiveUnregistrationConfirm(const H225_UnregistrationConfirm & ucf)
1312 if (!H225_RAS::OnReceiveUnregistrationConfirm(ucf))
1313 return FALSE;
1315 registrationFailReason = UnregisteredLocally;
1316 timeToLive = 0; // zero disables lightweight RRQ
1318 return TRUE;
1322 BOOL H323Gatekeeper::OnReceiveUnregistrationRequest(const H225_UnregistrationRequest & urq)
1324 if (!H225_RAS::OnReceiveUnregistrationRequest(urq))
1325 return FALSE;
1327 PTRACE(2, "RAS\tUnregistration received");
1328 if (!urq.HasOptionalField(H225_UnregistrationRequest::e_gatekeeperIdentifier) ||
1329 urq.m_gatekeeperIdentifier.GetValue() != gatekeeperIdentifier) {
1330 PTRACE(1, "RAS\tInconsistent gatekeeperIdentifier!");
1331 return FALSE;
1334 if (!urq.HasOptionalField(H225_UnregistrationRequest::e_endpointIdentifier) ||
1335 urq.m_endpointIdentifier.GetValue() != endpointIdentifier) {
1336 PTRACE(1, "RAS\tInconsistent endpointIdentifier!");
1337 return FALSE;
1340 endpoint.ClearAllCalls(H323Connection::EndedByGatekeeper, FALSE);
1342 PTRACE(3, "RAS\tUnregistered, calls cleared");
1343 registrationFailReason = UnregisteredByGatekeeper;
1344 timeToLive = 0; // zero disables lightweight RRQ
1346 if (urq.HasOptionalField(H225_UnregistrationRequest::e_alternateGatekeeper))
1347 SetAlternates(urq.m_alternateGatekeeper, FALSE);
1349 H323RasPDU response(authenticators);
1350 response.BuildUnregistrationConfirm(urq.m_requestSeqNum);
1351 BOOL ok = WritePDU(response);
1353 if (autoReregister) {
1354 PTRACE(3, "RAS\tReregistering by setting timeToLive");
1355 reregisterNow = TRUE;
1356 monitorTickle.Signal();
1359 return ok;
1363 BOOL H323Gatekeeper::OnReceiveUnregistrationReject(const H225_UnregistrationReject & urj)
1365 if (!H225_RAS::OnReceiveUnregistrationReject(urj))
1366 return FALSE;
1368 if (lastRequest->rejectReason != H225_UnregRejectReason::e_callInProgress) {
1369 registrationFailReason = UnregisteredLocally;
1370 timeToLive = 0; // zero disables lightweight RRQ
1373 return TRUE;
1377 BOOL H323Gatekeeper::LocationRequest(const PString & alias,
1378 H323TransportAddress & address)
1380 PStringList aliases;
1381 aliases.AppendString(alias);
1382 return LocationRequest(aliases, address);
1386 BOOL H323Gatekeeper::LocationRequest(const PStringList & aliases,
1387 H323TransportAddress & address)
1389 if (PAssertNULL(transport) == NULL)
1390 return FALSE;
1392 H323RasPDU pdu;
1393 H225_LocationRequest & lrq = pdu.BuildLocationRequest(GetNextSequenceNumber());
1395 H323SetAliasAddresses(aliases, lrq.m_destinationInfo);
1397 if (!endpointIdentifier.IsEmpty()) {
1398 lrq.IncludeOptionalField(H225_LocationRequest::e_endpointIdentifier);
1399 lrq.m_endpointIdentifier = endpointIdentifier;
1402 H323TransportAddress replyAddress = transport->GetLocalAddress();
1403 replyAddress.SetPDU(lrq.m_replyAddress);
1405 lrq.IncludeOptionalField(H225_LocationRequest::e_sourceInfo);
1406 H323SetAliasAddresses(endpoint.GetAliasNames(), lrq.m_sourceInfo);
1408 if (!gatekeeperIdentifier) {
1409 lrq.IncludeOptionalField(H225_LocationRequest::e_gatekeeperIdentifier);
1410 lrq.m_gatekeeperIdentifier = gatekeeperIdentifier;
1413 Request request(lrq.m_requestSeqNum, pdu);
1414 request.responseInfo = &address;
1415 if (!MakeRequest(request))
1416 return FALSE;
1418 // sanity check the address - some Gks return address 0.0.0.0 and port 0
1419 PIPSocket::Address ipAddr;
1420 WORD port;
1421 return address.GetIpAndPort(ipAddr, port) && (port != 0);
1425 H323Gatekeeper::AdmissionResponse::AdmissionResponse()
1427 rejectReason = UINT_MAX;
1429 gatekeeperRouted = FALSE;
1430 endpointCount = 1;
1431 transportAddress = NULL;
1432 accessTokenData = NULL;
1434 aliasAddresses = NULL;
1435 destExtraCallInfo = NULL;
1439 struct AdmissionRequestResponseInfo {
1440 AdmissionRequestResponseInfo(
1441 H323Gatekeeper::AdmissionResponse & r,
1442 H323Connection & c
1443 ) : param(r), connection(c) { }
1445 H323Gatekeeper::AdmissionResponse & param;
1446 H323Connection & connection;
1447 unsigned allocatedBandwidth;
1448 unsigned uuiesRequested;
1449 PString accessTokenOID1;
1450 PString accessTokenOID2;
1454 BOOL H323Gatekeeper::AdmissionRequest(H323Connection & connection,
1455 AdmissionResponse & response,
1456 BOOL ignorePreGrantedARQ)
1458 BOOL answeringCall = connection.HadAnsweredCall();
1460 if (!ignorePreGrantedARQ) {
1461 switch (answeringCall ? pregrantAnswerCall : pregrantMakeCall) {
1462 case RequireARQ :
1463 break;
1464 case PregrantARQ :
1465 return TRUE;
1466 case PreGkRoutedARQ :
1467 if (gkRouteAddress.IsEmpty()) {
1468 response.rejectReason = UINT_MAX;
1469 return FALSE;
1471 if (response.transportAddress != NULL)
1472 *response.transportAddress = gkRouteAddress;
1473 response.gatekeeperRouted = TRUE;
1474 return TRUE;
1478 H323RasPDU pdu;
1479 H225_AdmissionRequest & arq = pdu.BuildAdmissionRequest(GetNextSequenceNumber());
1481 arq.m_callType.SetTag(H225_CallType::e_pointToPoint);
1482 arq.m_endpointIdentifier = endpointIdentifier;
1483 arq.m_answerCall = answeringCall;
1484 arq.m_canMapAlias = TRUE; // Stack supports receiving a different number in the ACF
1485 // to the one sent in the ARQ
1486 arq.m_willSupplyUUIEs = TRUE;
1488 if (!gatekeeperIdentifier) {
1489 arq.IncludeOptionalField(H225_AdmissionRequest::e_gatekeeperIdentifier);
1490 arq.m_gatekeeperIdentifier = gatekeeperIdentifier;
1493 PString destInfo = connection.GetRemotePartyName();
1494 arq.m_srcInfo.SetSize(1);
1495 if (answeringCall) {
1496 H323SetAliasAddress(destInfo, arq.m_srcInfo[0]);
1498 if (!connection.GetLocalPartyName()) {
1499 arq.IncludeOptionalField(H225_AdmissionRequest::e_destinationInfo);
1500 H323SetAliasAddresses(connection.GetLocalAliasNames(), arq.m_destinationInfo);
1503 else {
1504 H323SetAliasAddresses(connection.GetLocalAliasNames(), arq.m_srcInfo);
1505 if (response.transportAddress == NULL || destInfo != *response.transportAddress) {
1506 arq.IncludeOptionalField(H225_AdmissionRequest::e_destinationInfo);
1507 arq.m_destinationInfo.SetSize(1);
1508 H323SetAliasAddress(destInfo, arq.m_destinationInfo[0]);
1512 PTRACE(3, "RAS\tAdmissionRequest answering = " << answeringCall << " local alias name " << connection.GetLocalAliasNames());
1514 const H323Transport * signallingChannel = connection.GetSignallingChannel();
1515 if (answeringCall) {
1516 arq.IncludeOptionalField(H225_AdmissionRequest::e_srcCallSignalAddress);
1517 H323TransportAddress signalAddress = signallingChannel->GetRemoteAddress();
1518 signalAddress.SetPDU(arq.m_srcCallSignalAddress);
1519 signalAddress = signallingChannel->GetLocalAddress();
1520 arq.IncludeOptionalField(H225_AdmissionRequest::e_destCallSignalAddress);
1521 signalAddress.SetPDU(arq.m_destCallSignalAddress);
1523 else {
1524 if (signallingChannel != NULL && signallingChannel->IsOpen()) {
1525 arq.IncludeOptionalField(H225_AdmissionRequest::e_srcCallSignalAddress);
1526 H323TransportAddress signalAddress = signallingChannel->GetLocalAddress();
1527 signalAddress.SetPDU(arq.m_srcCallSignalAddress);
1529 if (response.transportAddress != NULL && !response.transportAddress->IsEmpty()) {
1530 arq.IncludeOptionalField(H225_AdmissionRequest::e_destCallSignalAddress);
1531 response.transportAddress->SetPDU(arq.m_destCallSignalAddress);
1535 arq.m_bandWidth = connection.GetBandwidthAvailable();
1536 arq.m_callReferenceValue = connection.GetCallReference();
1537 arq.m_conferenceID = connection.GetConferenceIdentifier();
1538 arq.m_callIdentifier.m_guid = connection.GetCallIdentifier();
1540 AdmissionRequestResponseInfo info(response, connection);
1541 info.accessTokenOID1 = connection.GetGkAccessTokenOID();
1542 PINDEX comma = info.accessTokenOID1.Find(',');
1543 if (comma == P_MAX_INDEX)
1544 info.accessTokenOID2 = info.accessTokenOID1;
1545 else {
1546 info.accessTokenOID2 = info.accessTokenOID1.Mid(comma+1);
1547 info.accessTokenOID1.Delete(comma, P_MAX_INDEX);
1550 connection.OnSendARQ(arq);
1552 Request request(arq.m_requestSeqNum, pdu);
1553 request.responseInfo = &info;
1555 if (!authenticators.IsEmpty()) {
1556 pdu.Prepare(arq.m_tokens, H225_AdmissionRequest::e_tokens,
1557 arq.m_cryptoTokens, H225_AdmissionRequest::e_cryptoTokens);
1559 H235Authenticators adjustedAuthenticators;
1560 if (connection.GetAdmissionRequestAuthentication(arq, adjustedAuthenticators)) {
1561 PTRACE(3, "RAS\tAuthenticators credentials replaced with \""
1562 << setfill(',') << adjustedAuthenticators << setfill(' ') << "\" during ARQ");
1564 for (PINDEX i = 0; i < adjustedAuthenticators.GetSize(); i++) {
1565 H235Authenticator & authenticator = adjustedAuthenticators[i];
1566 if (authenticator.UseGkAndEpIdentifiers())
1567 authenticator.SetRemoteId(gatekeeperIdentifier);
1570 adjustedAuthenticators.PreparePDU(pdu,
1571 arq.m_tokens, H225_AdmissionRequest::e_tokens,
1572 arq.m_cryptoTokens, H225_AdmissionRequest::e_cryptoTokens);
1573 pdu.SetAuthenticators(adjustedAuthenticators);
1577 if (!MakeRequest(request)) {
1578 response.rejectReason = request.rejectReason;
1580 // See if we are registered.
1581 if (request.responseResult == Request::RejectReceived &&
1582 response.rejectReason != H225_AdmissionRejectReason::e_callerNotRegistered &&
1583 response.rejectReason != H225_AdmissionRejectReason::e_invalidEndpointIdentifier)
1584 return FALSE;
1586 PTRACE(2, "RAS\tEndpoint has become unregistered during ARQ from gatekeeper " << gatekeeperIdentifier);
1588 // Have been told we are not registered (or gk offline)
1589 switch (request.responseResult) {
1590 case Request::NoResponseReceived :
1591 registrationFailReason = TransportError;
1592 response.rejectReason = UINT_MAX;
1593 break;
1595 case Request::BadCryptoTokens :
1596 registrationFailReason = SecurityDenied;
1597 response.rejectReason = H225_AdmissionRejectReason::e_securityDenial;
1598 break;
1600 default :
1601 registrationFailReason = GatekeeperLostRegistration;
1604 // If we are not registered and auto register is set ...
1605 if (!autoReregister)
1606 return FALSE;
1608 // Then immediately reregister.
1609 if (!RegistrationRequest(autoReregister))
1610 return FALSE;
1612 // Reset the gk info in ARQ
1613 arq.m_endpointIdentifier = endpointIdentifier;
1614 if (!gatekeeperIdentifier) {
1615 arq.IncludeOptionalField(H225_AdmissionRequest::e_gatekeeperIdentifier);
1616 arq.m_gatekeeperIdentifier = gatekeeperIdentifier;
1618 else
1619 arq.RemoveOptionalField(H225_AdmissionRequest::e_gatekeeperIdentifier);
1621 // Is new request so need new sequence number as well.
1622 arq.m_requestSeqNum = GetNextSequenceNumber();
1623 request.sequenceNumber = arq.m_requestSeqNum;
1625 if (!MakeRequest(request)) {
1626 response.rejectReason = request.responseResult == Request::RejectReceived
1627 ? request.rejectReason : UINT_MAX;
1629 return FALSE;
1633 connection.SetBandwidthAvailable(info.allocatedBandwidth);
1634 connection.SetUUIEsRequested(info.uuiesRequested);
1636 return TRUE;
1640 void H323Gatekeeper::OnSendAdmissionRequest(H225_AdmissionRequest & /*arq*/)
1642 // Override default function as it sets crypto tokens and this is really
1643 // done by the AdmissionRequest() function.
1647 static unsigned GetUUIEsRequested(const H225_UUIEsRequested & pdu)
1649 unsigned uuiesRequested = 0;
1651 if ((BOOL)pdu.m_setup)
1652 uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_setup);
1653 if ((BOOL)pdu.m_callProceeding)
1654 uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_callProceeding);
1655 if ((BOOL)pdu.m_connect)
1656 uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_connect);
1657 if ((BOOL)pdu.m_alerting)
1658 uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_alerting);
1659 if ((BOOL)pdu.m_information)
1660 uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_information);
1661 if ((BOOL)pdu.m_releaseComplete)
1662 uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_releaseComplete);
1663 if ((BOOL)pdu.m_facility)
1664 uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_facility);
1665 if ((BOOL)pdu.m_progress)
1666 uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_progress);
1667 if ((BOOL)pdu.m_empty)
1668 uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_empty);
1670 if (pdu.HasOptionalField(H225_UUIEsRequested::e_status) && (BOOL)pdu.m_status)
1671 uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_status);
1672 if (pdu.HasOptionalField(H225_UUIEsRequested::e_statusInquiry) && (BOOL)pdu.m_statusInquiry)
1673 uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_statusInquiry);
1674 if (pdu.HasOptionalField(H225_UUIEsRequested::e_setupAcknowledge) && (BOOL)pdu.m_setupAcknowledge)
1675 uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_setupAcknowledge);
1676 if (pdu.HasOptionalField(H225_UUIEsRequested::e_notify) && (BOOL)pdu.m_notify)
1677 uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_notify);
1679 return uuiesRequested;
1683 static void ExtractToken(const AdmissionRequestResponseInfo & info,
1684 const H225_ArrayOf_ClearToken & tokens,
1685 PBYTEArray & accessTokenData)
1687 if (!info.accessTokenOID1 && tokens.GetSize() > 0) {
1688 PTRACE(4, "RAS\tLooking for OID " << info.accessTokenOID1 << " in ACF to copy.");
1689 for (PINDEX i = 0; i < tokens.GetSize(); i++) {
1690 if (tokens[i].m_tokenOID == info.accessTokenOID1) {
1691 PTRACE(4, "RAS\tLooking for OID " << info.accessTokenOID2 << " in token to copy.");
1692 if (tokens[i].HasOptionalField(H235_ClearToken::e_nonStandard) &&
1693 tokens[i].m_nonStandard.m_nonStandardIdentifier == info.accessTokenOID2) {
1694 PTRACE(4, "RAS\tCopying ACF nonStandard OctetString.");
1695 accessTokenData = tokens[i].m_nonStandard.m_data;
1696 break;
1704 BOOL H323Gatekeeper::OnReceiveAdmissionConfirm(const H225_AdmissionConfirm & acf)
1706 if (!H225_RAS::OnReceiveAdmissionConfirm(acf))
1707 return FALSE;
1709 AdmissionRequestResponseInfo & info = *(AdmissionRequestResponseInfo *)lastRequest->responseInfo;
1710 info.allocatedBandwidth = acf.m_bandWidth;
1711 if (info.param.transportAddress != NULL)
1712 *info.param.transportAddress = acf.m_destCallSignalAddress;
1714 info.param.gatekeeperRouted = acf.m_callModel.GetTag() == H225_CallModel::e_gatekeeperRouted;
1716 // Remove the endpoint aliases that the gatekeeper did not like and add the
1717 // ones that it really wants us to be.
1718 if (info.param.aliasAddresses != NULL &&
1719 acf.HasOptionalField(H225_AdmissionConfirm::e_destinationInfo)) {
1720 PTRACE(3, "RAS\tGatekeeper specified " << acf.m_destinationInfo.GetSize() << " aliases in ACF");
1721 *info.param.aliasAddresses = acf.m_destinationInfo;
1724 if (acf.HasOptionalField(H225_AdmissionConfirm::e_uuiesRequested))
1725 info.uuiesRequested = GetUUIEsRequested(acf.m_uuiesRequested);
1727 if (info.param.destExtraCallInfo != NULL &&
1728 acf.HasOptionalField(H225_AdmissionConfirm::e_destExtraCallInfo))
1729 *info.param.destExtraCallInfo = acf.m_destExtraCallInfo;
1731 if (info.param.accessTokenData != NULL && acf.HasOptionalField(H225_AdmissionConfirm::e_tokens))
1732 ExtractToken(info, acf.m_tokens, *info.param.accessTokenData);
1734 if (info.param.transportAddress != NULL) {
1735 PINDEX count = 1;
1736 for (PINDEX i = 0; i < acf.m_alternateEndpoints.GetSize() && count < info.param.endpointCount; i++) {
1737 if (acf.m_alternateEndpoints[i].HasOptionalField(H225_Endpoint::e_callSignalAddress) &&
1738 acf.m_alternateEndpoints[i].m_callSignalAddress.GetSize() > 0) {
1739 info.param.transportAddress[count] = acf.m_alternateEndpoints[i].m_callSignalAddress[0];
1740 if (info.param.accessTokenData != NULL)
1741 ExtractToken(info, acf.m_alternateEndpoints[i].m_tokens, info.param.accessTokenData[count]);
1742 count++;
1745 info.param.endpointCount = count;
1748 if (acf.HasOptionalField(H225_AdmissionConfirm::e_irrFrequency))
1749 SetInfoRequestRate(AdjustTimeout(acf.m_irrFrequency));
1750 willRespondToIRR = acf.m_willRespondToIRR;
1752 if (acf.HasOptionalField(H225_AdmissionConfirm::e_serviceControl))
1753 OnServiceControlSessions(acf.m_serviceControl, &info.connection);
1755 return TRUE;
1759 BOOL H323Gatekeeper::OnReceiveAdmissionReject(const H225_AdmissionReject & arj)
1761 if (!H225_RAS::OnReceiveAdmissionReject(arj))
1762 return FALSE;
1764 if (arj.HasOptionalField(H225_AdmissionConfirm::e_serviceControl))
1765 OnServiceControlSessions(arj.m_serviceControl,
1766 &((AdmissionRequestResponseInfo *)lastRequest->responseInfo)->connection);
1768 return TRUE;
1772 static void SetRasUsageInformation(const H323Connection & connection,
1773 H225_RasUsageInformation & usage)
1775 time_t time = connection.GetAlertingTime().GetTimeInSeconds();
1776 if (time != 0) {
1777 usage.IncludeOptionalField(H225_RasUsageInformation::e_alertingTime);
1778 usage.m_alertingTime = (unsigned)time;
1781 time = connection.GetConnectionStartTime().GetTimeInSeconds();
1782 if (time != 0) {
1783 usage.IncludeOptionalField(H225_RasUsageInformation::e_connectTime);
1784 usage.m_connectTime = (unsigned)time;
1787 time = connection.GetConnectionEndTime().GetTimeInSeconds();
1788 if (time != 0) {
1789 usage.IncludeOptionalField(H225_RasUsageInformation::e_endTime);
1790 usage.m_endTime = (unsigned)time;
1795 BOOL H323Gatekeeper::DisengageRequest(const H323Connection & connection, unsigned reason)
1797 H323RasPDU pdu;
1798 H225_DisengageRequest & drq = pdu.BuildDisengageRequest(GetNextSequenceNumber());
1800 drq.m_endpointIdentifier = endpointIdentifier;
1801 drq.m_conferenceID = connection.GetConferenceIdentifier();
1802 drq.m_callReferenceValue = connection.GetCallReference();
1803 drq.m_callIdentifier.m_guid = connection.GetCallIdentifier();
1804 drq.m_disengageReason.SetTag(reason);
1805 drq.m_answeredCall = connection.HadAnsweredCall();
1807 drq.IncludeOptionalField(H225_DisengageRequest::e_usageInformation);
1808 SetRasUsageInformation(connection, drq.m_usageInformation);
1810 drq.IncludeOptionalField(H225_DisengageRequest::e_terminationCause);
1811 drq.m_terminationCause.SetTag(H225_CallTerminationCause::e_releaseCompleteReason);
1812 Q931::CauseValues cause = H323TranslateFromCallEndReason(connection, drq.m_terminationCause);
1813 if (cause != Q931::ErrorInCauseIE) {
1814 drq.m_terminationCause.SetTag(H225_CallTerminationCause::e_releaseCompleteCauseIE);
1815 PASN_OctetString & rcReason = drq.m_terminationCause;
1816 rcReason.SetSize(2);
1817 rcReason[0] = 0x80;
1818 rcReason[1] = (BYTE)(0x80|cause);
1821 if (!gatekeeperIdentifier) {
1822 drq.IncludeOptionalField(H225_DisengageRequest::e_gatekeeperIdentifier);
1823 drq.m_gatekeeperIdentifier = gatekeeperIdentifier;
1826 Request request(drq.m_requestSeqNum, pdu);
1827 return MakeRequestWithReregister(request, H225_DisengageRejectReason::e_notRegistered);
1831 BOOL H323Gatekeeper::OnReceiveDisengageRequest(const H225_DisengageRequest & drq)
1833 if (!H225_RAS::OnReceiveDisengageRequest(drq))
1834 return FALSE;
1836 OpalGloballyUniqueID id = NULL;
1837 if (drq.HasOptionalField(H225_DisengageRequest::e_callIdentifier))
1838 id = drq.m_callIdentifier.m_guid;
1839 if (id == NULL)
1840 id = drq.m_conferenceID;
1842 H323RasPDU response(authenticators);
1843 PSafePtr<H323Connection> connection = endpoint.FindConnectionWithLock(id.AsString());
1844 if (connection == NULL)
1845 response.BuildDisengageReject(drq.m_requestSeqNum,
1846 H225_DisengageRejectReason::e_requestToDropOther);
1847 else {
1848 H225_DisengageConfirm & dcf = response.BuildDisengageConfirm(drq.m_requestSeqNum);
1850 dcf.IncludeOptionalField(H225_DisengageConfirm::e_usageInformation);
1851 SetRasUsageInformation(*connection, dcf.m_usageInformation);
1853 connection->Release(H323Connection::EndedByGatekeeper);
1856 if (drq.HasOptionalField(H225_DisengageRequest::e_serviceControl))
1857 OnServiceControlSessions(drq.m_serviceControl, connection);
1859 return WritePDU(response);
1863 BOOL H323Gatekeeper::BandwidthRequest(H323Connection & connection,
1864 unsigned requestedBandwidth)
1866 H323RasPDU pdu;
1867 H225_BandwidthRequest & brq = pdu.BuildBandwidthRequest(GetNextSequenceNumber());
1869 brq.m_endpointIdentifier = endpointIdentifier;
1870 brq.m_conferenceID = connection.GetConferenceIdentifier();
1871 brq.m_callReferenceValue = connection.GetCallReference();
1872 brq.m_callIdentifier.m_guid = connection.GetCallIdentifier();
1873 brq.m_bandWidth = requestedBandwidth;
1874 brq.IncludeOptionalField(H225_BandwidthRequest::e_usageInformation);
1875 SetRasUsageInformation(connection, brq.m_usageInformation);
1877 Request request(brq.m_requestSeqNum, pdu);
1879 unsigned allocatedBandwidth;
1880 request.responseInfo = &allocatedBandwidth;
1882 if (!MakeRequestWithReregister(request, H225_BandRejectReason::e_notBound))
1883 return FALSE;
1885 connection.SetBandwidthAvailable(allocatedBandwidth);
1886 return TRUE;
1890 BOOL H323Gatekeeper::OnReceiveBandwidthConfirm(const H225_BandwidthConfirm & bcf)
1892 if (!H225_RAS::OnReceiveBandwidthConfirm(bcf))
1893 return FALSE;
1895 if (lastRequest->responseInfo != NULL)
1896 *(unsigned *)lastRequest->responseInfo = bcf.m_bandWidth;
1898 return TRUE;
1902 BOOL H323Gatekeeper::OnReceiveBandwidthRequest(const H225_BandwidthRequest & brq)
1904 if (!H225_RAS::OnReceiveBandwidthRequest(brq))
1905 return FALSE;
1907 OpalGloballyUniqueID id = brq.m_callIdentifier.m_guid;
1908 PSafePtr<H323Connection> connection = endpoint.FindConnectionWithLock(id.AsString());
1910 H323RasPDU response(authenticators);
1911 if (connection == NULL)
1912 response.BuildBandwidthReject(brq.m_requestSeqNum,
1913 H225_BandRejectReason::e_invalidConferenceID);
1914 else {
1915 if (connection->SetBandwidthAvailable(brq.m_bandWidth))
1916 response.BuildBandwidthConfirm(brq.m_requestSeqNum, brq.m_bandWidth);
1917 else
1918 response.BuildBandwidthReject(brq.m_requestSeqNum,
1919 H225_BandRejectReason::e_insufficientResources);
1922 return WritePDU(response);
1926 void H323Gatekeeper::SetInfoRequestRate(const PTimeInterval & rate)
1928 if (rate < infoRequestRate.GetResetTime() || infoRequestRate.GetResetTime() == 0) {
1929 // Have to be sneaky here becuase we do not want to actually change the
1930 // amount of time to run on the timer.
1931 PTimeInterval timeToGo = infoRequestRate;
1932 infoRequestRate = rate;
1933 if (rate > timeToGo)
1934 infoRequestRate.PTimeInterval::operator=(timeToGo);
1939 void H323Gatekeeper::ClearInfoRequestRate()
1941 // Only reset rate to zero (disabled) if no calls present
1942 if (endpoint.GetAllConnections().IsEmpty())
1943 infoRequestRate = 0;
1947 H225_InfoRequestResponse & H323Gatekeeper::BuildInfoRequestResponse(H323RasPDU & response,
1948 unsigned seqNum)
1950 H225_InfoRequestResponse & irr = response.BuildInfoRequestResponse(seqNum);
1952 endpoint.SetEndpointTypeInfo(irr.m_endpointType);
1953 irr.m_endpointIdentifier = endpointIdentifier;
1955 H323TransportAddress address = transport->GetLocalAddress();
1957 // We do have to use the translated address if specified
1958 PIPSocket::Address localAddress, remoteAddress;
1959 WORD localPort;
1961 if(address.GetIpAndPort(localAddress, localPort) &&
1962 transport->GetRemoteAddress().GetIpAddress(remoteAddress)) {
1964 OpalManager & manager = transport->GetEndPoint().GetManager();
1966 if(manager.TranslateIPAddress(localAddress, remoteAddress))
1968 address = H323TransportAddress(localAddress, localPort);
1971 address.SetPDU(irr.m_rasAddress);
1973 const H323ListenerList & listeners = endpoint.GetListeners();
1974 for (PINDEX i = 0; i < listeners.GetSize(); i++) {
1975 address = listeners[i].GetLocalAddress();
1976 address.SetPDU(irr.m_callSignalAddress, *transport);
1979 irr.IncludeOptionalField(H225_InfoRequestResponse::e_endpointAlias);
1980 H323SetAliasAddresses(endpoint.GetAliasNames(), irr.m_endpointAlias);
1982 return irr;
1986 BOOL H323Gatekeeper::SendUnsolicitedIRR(H225_InfoRequestResponse & irr,
1987 H323RasPDU & response)
1989 irr.m_unsolicited = TRUE;
1991 if (willRespondToIRR) {
1992 PTRACE(4, "RAS\tSending unsolicited IRR and awaiting acknowledgement");
1993 Request request(irr.m_requestSeqNum, response);
1994 return MakeRequest(request);
1997 PTRACE(4, "RAS\tSending unsolicited IRR and without acknowledgement");
1998 response.SetAuthenticators(authenticators);
1999 return WritePDU(response);
2003 static void AddInfoRequestResponseCall(H225_InfoRequestResponse & irr,
2004 const H323Connection & connection)
2006 irr.IncludeOptionalField(H225_InfoRequestResponse::e_perCallInfo);
2008 PINDEX sz = irr.m_perCallInfo.GetSize();
2009 if (!irr.m_perCallInfo.SetSize(sz+1))
2010 return;
2012 H225_InfoRequestResponse_perCallInfo_subtype & info = irr.m_perCallInfo[sz];
2014 info.m_callReferenceValue = connection.GetCallReference();
2015 info.m_callIdentifier.m_guid = connection.GetCallIdentifier();
2016 info.m_conferenceID = connection.GetConferenceIdentifier();
2017 info.IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_originator);
2018 info.m_originator = !connection.HadAnsweredCall();
2020 H323_RTP_Session * session = connection.GetSessionCallbacks(OpalMediaFormat::DefaultAudioSessionID);
2021 if (session != NULL) {
2022 info.IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_audio);
2023 info.m_audio.SetSize(1);
2024 session->OnSendRasInfo(info.m_audio[0]);
2027 session = connection.GetSessionCallbacks(OpalMediaFormat::DefaultVideoSessionID);
2028 if (session != NULL) {
2029 info.IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_video);
2030 info.m_video.SetSize(1);
2031 session->OnSendRasInfo(info.m_video[0]);
2034 H323TransportAddress address = connection.GetControlChannel().GetLocalAddress();
2035 address.SetPDU(info.m_h245.m_sendAddress);
2036 address = connection.GetControlChannel().GetRemoteAddress();
2037 address.SetPDU(info.m_h245.m_recvAddress);
2039 info.m_callType.SetTag(H225_CallType::e_pointToPoint);
2040 info.m_bandWidth = connection.GetBandwidthUsed();
2041 info.m_callModel.SetTag(connection.IsGatekeeperRouted() ? H225_CallModel::e_gatekeeperRouted
2042 : H225_CallModel::e_direct);
2044 info.IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_usageInformation);
2045 SetRasUsageInformation(connection, info.m_usageInformation);
2049 static BOOL AddAllInfoRequestResponseCall(H225_InfoRequestResponse & irr,
2050 H323EndPoint & endpoint,
2051 const PStringList & tokens)
2053 BOOL addedOne = FALSE;
2055 for (PINDEX i = 0; i < tokens.GetSize(); i++) {
2056 PSafePtr<H323Connection> connection = endpoint.FindConnectionWithLock(tokens[i]);
2057 if (connection != NULL) {
2058 AddInfoRequestResponseCall(irr, *connection);
2059 addedOne = TRUE;
2063 return addedOne;
2067 void H323Gatekeeper::InfoRequestResponse()
2069 PStringList tokens = endpoint.GetAllConnections();
2070 if (tokens.IsEmpty())
2071 return;
2073 H323RasPDU response;
2074 H225_InfoRequestResponse & irr = BuildInfoRequestResponse(response, GetNextSequenceNumber());
2076 if (AddAllInfoRequestResponseCall(irr, endpoint, tokens))
2077 SendUnsolicitedIRR(irr, response);
2081 void H323Gatekeeper::InfoRequestResponse(const H323Connection & connection)
2083 H323RasPDU response;
2084 H225_InfoRequestResponse & irr = BuildInfoRequestResponse(response, GetNextSequenceNumber());
2086 AddInfoRequestResponseCall(irr, connection);
2088 SendUnsolicitedIRR(irr, response);
2092 void H323Gatekeeper::InfoRequestResponse(const H323Connection & connection,
2093 const H225_H323_UU_PDU & pdu,
2094 BOOL sent)
2096 // Are unknown Q.931 PDU
2097 if (pdu.m_h323_message_body.GetTag() == P_MAX_INDEX)
2098 return;
2100 // Check mask of things to report on
2101 if ((connection.GetUUIEsRequested() & (1<<pdu.m_h323_message_body.GetTag())) == 0)
2102 return;
2104 PTRACE(3, "RAS\tSending unsolicited IRR for requested UUIE");
2106 // Report the PDU
2107 H323RasPDU response;
2108 H225_InfoRequestResponse & irr = BuildInfoRequestResponse(response, GetNextSequenceNumber());
2110 AddInfoRequestResponseCall(irr, connection);
2112 irr.m_perCallInfo[0].IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_pdu);
2113 irr.m_perCallInfo[0].m_pdu.SetSize(1);
2114 irr.m_perCallInfo[0].m_pdu[0].m_sent = sent;
2115 irr.m_perCallInfo[0].m_pdu[0].m_h323pdu = pdu;
2117 SendUnsolicitedIRR(irr, response);
2121 BOOL H323Gatekeeper::OnReceiveInfoRequest(const H225_InfoRequest & irq)
2123 if (!H225_RAS::OnReceiveInfoRequest(irq))
2124 return FALSE;
2126 H323RasPDU response(authenticators);
2127 H225_InfoRequestResponse & irr = BuildInfoRequestResponse(response, irq.m_requestSeqNum);
2129 if (irq.m_callReferenceValue == 0) {
2130 if (!AddAllInfoRequestResponseCall(irr, endpoint, endpoint.GetAllConnections())) {
2131 irr.IncludeOptionalField(H225_InfoRequestResponse::e_irrStatus);
2132 irr.m_irrStatus.SetTag(H225_InfoRequestResponseStatus::e_invalidCall);
2135 else {
2136 OpalGloballyUniqueID id = irq.m_callIdentifier.m_guid;
2137 PSafePtr<H323Connection> connection = endpoint.FindConnectionWithLock(id.AsString());
2138 if (connection == NULL) {
2139 irr.IncludeOptionalField(H225_InfoRequestResponse::e_irrStatus);
2140 irr.m_irrStatus.SetTag(H225_InfoRequestResponseStatus::e_invalidCall);
2142 else {
2143 if (irq.HasOptionalField(H225_InfoRequest::e_uuiesRequested))
2144 connection->SetUUIEsRequested(::GetUUIEsRequested(irq.m_uuiesRequested));
2146 AddInfoRequestResponseCall(irr, *connection);
2150 if (!irq.HasOptionalField(H225_InfoRequest::e_replyAddress))
2151 return WritePDU(response);
2153 H323TransportAddress replyAddress = irq.m_replyAddress;
2154 if (replyAddress.IsEmpty())
2155 return FALSE;
2157 H323TransportAddress oldAddress = transport->GetRemoteAddress();
2158 if (!oldAddress.IsEquivalent(replyAddress)) {
2160 BOOL ok = transport->ConnectTo(replyAddress) && WritePDU(response);
2161 transport->ConnectTo(oldAddress);
2163 return ok;
2165 else
2166 return WritePDU(response);
2170 BOOL H323Gatekeeper::OnReceiveServiceControlIndication(const H225_ServiceControlIndication & sci)
2172 if (!H225_RAS::OnReceiveServiceControlIndication(sci))
2173 return FALSE;
2175 H323Connection * connection = NULL;
2177 if (sci.HasOptionalField(H225_ServiceControlIndication::e_callSpecific)) {
2178 OpalGloballyUniqueID id = sci.m_callSpecific.m_callIdentifier.m_guid;
2179 if (id.IsNULL())
2180 id = sci.m_callSpecific.m_conferenceID;
2181 connection = endpoint.FindConnectionWithLock(id.AsString());
2184 OnServiceControlSessions(sci.m_serviceControl, connection);
2186 H323RasPDU response(authenticators);
2187 response.BuildServiceControlResponse(sci.m_requestSeqNum);
2188 return WritePDU(response);
2192 void H323Gatekeeper::OnServiceControlSessions(const H225_ArrayOf_ServiceControlSession & serviceControl,
2193 H323Connection * connection)
2195 for (PINDEX i = 0; i < serviceControl.GetSize(); i++) {
2196 H225_ServiceControlSession & pdu = serviceControl[i];
2198 H323ServiceControlSession * session = NULL;
2199 unsigned sessionId = pdu.m_sessionId;
2201 if (serviceControlSessions.Contains(sessionId)) {
2202 session = &serviceControlSessions[sessionId];
2203 if (pdu.HasOptionalField(H225_ServiceControlSession::e_contents)) {
2204 if (!session->OnReceivedPDU(pdu.m_contents)) {
2205 PTRACE(2, "SvcCtrl\tService control for session has changed!");
2206 session = NULL;
2211 if (session == NULL && pdu.HasOptionalField(H225_ServiceControlSession::e_contents)) {
2212 session = endpoint.CreateServiceControlSession(pdu.m_contents);
2213 serviceControlSessions.SetAt(sessionId, session);
2216 if (session != NULL)
2217 endpoint.OnServiceControlSession(sessionId, pdu.m_reason.GetTag(), *session, connection);
2222 void H323Gatekeeper::SetPassword(const PString & password,
2223 const PString & username)
2225 PString localId = username;
2226 if (localId.IsEmpty())
2227 localId = endpoint.GetLocalUserName();
2229 for (PINDEX i = 0; i < authenticators.GetSize(); i++) {
2230 authenticators[i].SetLocalId(localId);
2231 authenticators[i].SetPassword(password);
2236 void H323Gatekeeper::MonitorMain(PThread &, INT)
2238 PTRACE(3, "RAS\tBackground thread started");
2240 for (;;) {
2241 monitorTickle.Wait();
2242 if (monitorStop)
2243 break;
2245 if (reregisterNow ||
2246 (!timeToLive.IsRunning() && timeToLive.GetResetTime() > 0)) {
2247 RegistrationTimeToLive();
2248 timeToLive.Reset();
2251 if (!infoRequestRate.IsRunning() && infoRequestRate.GetResetTime() > 0) {
2252 InfoRequestResponse();
2253 infoRequestRate.Reset();
2257 PTRACE(3, "RAS\tBackground thread ended");
2261 void H323Gatekeeper::TickleMonitor(PTimer &, INT)
2263 monitorTickle.Signal();
2267 void H323Gatekeeper::SetAlternates(const H225_ArrayOf_AlternateGK & alts, BOOL permanent)
2269 PINDEX i;
2271 if (!alternatePermanent) {
2272 // don't want to replace alternates gatekeepers if this is an alternate and it's not permanent
2273 for (i = 0; i < alternates.GetSize(); i++) {
2274 if (transport->GetRemoteAddress().IsEquivalent(alternates[i].rasAddress) &&
2275 gatekeeperIdentifier == alternates[i].gatekeeperIdentifier)
2276 return;
2280 alternates.RemoveAll();
2281 for (i = 0; i < alts.GetSize(); i++) {
2282 AlternateInfo * alt = new AlternateInfo(alts[i]);
2283 if (alt->rasAddress.IsEmpty())
2284 delete alt;
2285 else
2286 alternates.Append(alt);
2289 alternatePermanent = permanent;
2291 PTRACE(3, "RAS\tSet alternate gatekeepers:\n"
2292 << setfill('\n') << alternates << setfill(' '));
2296 BOOL H323Gatekeeper::MakeRequestWithReregister(Request & request, unsigned unregisteredTag)
2298 if (MakeRequest(request))
2299 return TRUE;
2301 if (request.responseResult == Request::RejectReceived &&
2302 request.rejectReason != unregisteredTag)
2303 return FALSE;
2305 PTRACE(2, "RAS\tEndpoint has become unregistered from gatekeeper " << gatekeeperIdentifier);
2307 // Have been told we are not registered (or gk offline)
2308 switch (request.responseResult) {
2309 case Request::NoResponseReceived :
2310 registrationFailReason = TransportError;
2311 break;
2313 case Request::BadCryptoTokens :
2314 registrationFailReason = SecurityDenied;
2315 break;
2317 default :
2318 registrationFailReason = GatekeeperLostRegistration;
2321 // If we are not registered and auto register is set ...
2322 if (!autoReregister)
2323 return FALSE;
2325 reregisterNow = TRUE;
2326 monitorTickle.Signal();
2327 return FALSE;
2331 void H323Gatekeeper::Connect(const H323TransportAddress & address,
2332 const PString & gkid)
2334 if (transport == NULL)
2335 transport = new H323TransportUDP(endpoint, PIPSocket::GetDefaultIpAny());
2337 transport->SetRemoteAddress(address);
2338 transport->Connect();
2340 gatekeeperIdentifier = gkid;
2344 BOOL H323Gatekeeper::MakeRequest(Request & request)
2346 if (PAssertNULL(transport) == NULL)
2347 return FALSE;
2349 // Set authenticators if not already set by caller
2350 requestMutex.Wait();
2352 if (request.requestPDU.GetAuthenticators().IsEmpty())
2353 request.requestPDU.SetAuthenticators(authenticators);
2355 /* To be sure that the H323 Cleaner, H225 Caller or Monitor don't set the
2356 transport address of the alternate while the other is in timeout. We
2357 have to block the function */
2359 H323TransportAddress tempAddr = transport->GetRemoteAddress();
2360 PString tempIdentifier = gatekeeperIdentifier;
2362 PINDEX alt = 0;
2363 for (;;) {
2364 if (H225_RAS::MakeRequest(request)) {
2365 if (!alternatePermanent &&
2366 (transport->GetRemoteAddress() != tempAddr ||
2367 gatekeeperIdentifier != tempIdentifier))
2368 Connect(tempAddr, tempIdentifier);
2369 requestMutex.Signal();
2370 return TRUE;
2373 if (request.responseResult != Request::NoResponseReceived &&
2374 request.responseResult != Request::TryAlternate) {
2375 // try alternate in those cases and see if it's successful
2376 requestMutex.Signal();
2377 return FALSE;
2380 AlternateInfo * altInfo;
2381 PIPSocket::Address localAddress;
2382 WORD localPort;
2383 do {
2384 if (alt >= alternates.GetSize()) {
2385 if (!alternatePermanent)
2386 Connect(tempAddr,tempIdentifier);
2387 requestMutex.Signal();
2388 return FALSE;
2391 altInfo = &alternates[alt++];
2392 transport->GetLocalAddress().GetIpAndPort(localAddress,localPort);
2393 transport->CleanUpOnTermination();
2394 delete transport;
2396 transport = new H323TransportUDP(endpoint,localAddress,localPort);
2397 transport->SetRemoteAddress (altInfo->rasAddress);
2398 transport->Connect();
2399 gatekeeperIdentifier = altInfo->gatekeeperIdentifier;
2400 StartChannel();
2401 } while (altInfo->registrationState == AlternateInfo::RegistrationFailed);
2403 if (altInfo->registrationState == AlternateInfo::NeedToRegister) {
2404 altInfo->registrationState = AlternateInfo::RegistrationFailed;
2405 registrationFailReason = TransportError;
2406 discoveryComplete = FALSE;
2407 H323RasPDU pdu;
2408 Request req(SetupGatekeeperRequest(pdu), pdu);
2410 if (H225_RAS::MakeRequest(req)) {
2411 requestMutex.Signal(); // avoid deadlock...
2412 if (RegistrationRequest(autoReregister)) {
2413 altInfo->registrationState = AlternateInfo::IsRegistered;
2414 // The wanted registration is done, we can return
2415 if (request.requestPDU.GetChoice().GetTag() == H225_RasMessage::e_registrationRequest) {
2416 if (!alternatePermanent)
2417 Connect(tempAddr,tempIdentifier);
2418 return TRUE;
2421 requestMutex.Wait();
2428 /////////////////////////////////////////////////////////////////////////////
2430 H323Gatekeeper::AlternateInfo::AlternateInfo(H225_AlternateGK & alt)
2431 : rasAddress(alt.m_rasAddress),
2432 gatekeeperIdentifier(alt.m_gatekeeperIdentifier.GetValue()),
2433 priority(alt.m_priority)
2435 registrationState = alt.m_needToRegister ? NeedToRegister : NoRegistrationNeeded;
2439 H323Gatekeeper::AlternateInfo::~AlternateInfo ()
2445 PObject::Comparison H323Gatekeeper::AlternateInfo::Compare(const PObject & obj)
2447 PAssert(PIsDescendant(&obj, H323Gatekeeper), PInvalidCast);
2448 unsigned otherPriority = ((const AlternateInfo & )obj).priority;
2449 if (priority < otherPriority)
2450 return LessThan;
2451 if (priority > otherPriority)
2452 return GreaterThan;
2453 return EqualTo;
2457 void H323Gatekeeper::AlternateInfo::PrintOn(ostream & strm) const
2459 if (!gatekeeperIdentifier)
2460 strm << gatekeeperIdentifier << '@';
2462 strm << rasAddress;
2464 if (priority > 0)
2465 strm << ";priority=" << priority;
2468 BOOL H323Gatekeeper::OnSendFeatureSet(unsigned pduType, H225_FeatureSet & message) const
2470 #ifdef H323_H460
2471 return features.SendFeature(pduType, message);
2472 #else
2473 return endpoint.OnSendFeatureSet(pduType, message);
2474 #endif
2477 void H323Gatekeeper::OnReceiveFeatureSet(unsigned pduType, const H225_FeatureSet & message) const
2479 #ifdef H323_H460
2480 features.ReceiveFeature(pduType, message);
2481 #else
2482 endpoint.OnReceiveFeatureSet(pduType, message);
2483 #endif
2487 /////////////////////////////////////////////////////////////////////////////