D:/Storage/CVS_Head/h323plus/src/gkclient.cxx

00001 /*
00002  * gkclient.cxx
00003  *
00004  * Gatekeeper client protocol handler
00005  *
00006  * Open H323 Library
00007  *
00008  * Copyright (c) 1999-2000 Equivalence Pty. Ltd.
00009  *
00010  * The contents of this file are subject to the Mozilla Public License
00011  * Version 1.0 (the "License"); you may not use this file except in
00012  * compliance with the License. You may obtain a copy of the License at
00013  * http://www.mozilla.org/MPL/
00014  *
00015  * Software distributed under the License is distributed on an "AS IS"
00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00017  * the License for the specific language governing rights and limitations
00018  * under the License.
00019  *
00020  * The Original Code is Open H323 Library.
00021  *
00022  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
00023  *
00024  * Portions of this code were written with the assisance of funding from
00025  * iFace In, http://www.iface.com
00026  *
00027  * Contributor(s): ______________________________________.
00028  *
00029  * $Log: gkclient.cxx,v $
00030  * Revision 1.2  2007/10/16 17:02:47  shorne
00031  * Fix for H.235.1 on full reregistration
00032  *
00033  * Revision 1.1  2007/08/06 20:51:04  shorne
00034  * First commit of h323plus
00035  *
00036  * Revision 1.165.2.5  2007/07/23 21:47:11  shorne
00037  * Added QoS GK Reporting
00038  *
00039  * Revision 1.165.2.4  2007/07/19 20:05:56  shorne
00040  * Changed Terminal Aliases to be only sent on full registration
00041  *
00042  * Revision 1.165.2.3  2007/05/23 06:59:36  shorne
00043  * Added Assigned Alias/Gatekeeper
00044  *
00045  * Revision 1.165.2.2  2007/04/19 12:16:16  shorne
00046  * added ability to detect if no nat
00047  *
00048  * Revision 1.165.2.1  2006/12/23 19:08:02  shorne
00049  * Plugin video codecs & sundry
00050  *
00051  * Revision 1.165  2006/07/23 23:27:55  shorne
00052  * supportsAssignedGK made optional field in RRQ & GRQ for backwards interoperability
00053  *
00054  * Revision 1.164  2006/07/21 16:29:13  csoutheren
00055  * Initialise mandatory extension elements in GRQ and RRQ for H.225 V6
00056  *
00057  * Revision 1.163  2006/06/30 05:26:43  csoutheren
00058  * Applied 1509255 - Checking whether SetSize succeeds in GkClient
00059  * Thanks to Borko Jandras
00060  *
00061  * Revision 1.162  2006/06/09 06:30:12  csoutheren
00062  * Remove compile warning and errors with gcc
00063  *
00064  * Revision 1.161  2006/05/30 11:14:56  hfriederich
00065  * Switch from DISABLE_H460 to H323_H460
00066  *
00067  * Revision 1.160  2006/05/29 02:31:45  shorne
00068  * H460 functions now get called
00069  *
00070  * Revision 1.159  2006/05/18 17:15:54  shorne
00071  * Added H460 Support
00072  *
00073  * Revision 1.158  2006/05/16 11:39:39  shorne
00074  * call linkage support
00075  *
00076  * Revision 1.157  2006/03/07 10:37:46  csoutheren
00077  * Add ability to disable GRQ on GK registration
00078  *
00079  * Revision 1.156  2005/11/21 20:52:35  shorne
00080  * Added GnuGK Nat detection support
00081  *
00082  * Revision 1.155  2005/01/16 20:39:44  csoutheren
00083  * Fixed problem with IPv6 INADDR_ANY
00084  *
00085  * Revision 1.154  2005/01/03 06:25:54  csoutheren
00086  * Added extensive support for disabling code modules at compile time
00087  *
00088  * Revision 1.153  2004/11/20 22:00:10  csoutheren
00089  * Check address from RequestLocation due to stupid gatekeepers
00090  *
00091  * Revision 1.152  2004/09/07 23:51:46  rjongbloed
00092  * Fixed MSVC6 warning
00093  *
00094  * Revision 1.151  2004/09/03 01:06:09  csoutheren
00095  * Added initial hooks for H.460 GEF
00096  * Thanks to Simon Horne and ISVO (Asia) Pte Ltd. for this contribution
00097  *
00098  * Revision 1.150  2004/06/15 03:30:00  csoutheren
00099  * Added OnSendARQ to allow access to the ARQ message before sent by connection
00100  *
00101  * Revision 1.149  2004/04/03 08:28:06  csoutheren
00102  * Remove pseudo-RTTI and replaced with real RTTI
00103  *
00104  * Revision 1.148  2004/01/17 18:20:15  csoutheren
00105  * No longer force re-register on completion of LRQ
00106  *
00107  * Revision 1.147  2003/12/29 04:59:25  csoutheren
00108  * Added callbacks on H323EndPoint when gatekeeper discovery succeeds or fails
00109  *
00110  * Revision 1.146  2003/12/28 00:06:34  csoutheren
00111  * Added callbacks on H323EndPoint when gatekeeper registration succeeds or fails
00112  *
00113  * Revision 1.145  2003/05/01 05:04:00  robertj
00114  * Fixed inclusion of 127.0.0.1 into listener lists when no needed.
00115  *
00116  * Revision 1.144  2003/04/30 07:25:32  robertj
00117  * Fixed setting of remote ID in alternate credentials.
00118  *
00119  * Revision 1.143  2003/04/30 00:28:54  robertj
00120  * Redesigned the alternate credentials in ARQ system as old implementation
00121  *   was fraught with concurrency issues, most importantly it can cause false
00122  *   detection of replay attacks taking out an endpoint completely.
00123  *
00124  * Revision 1.142  2003/04/10 09:44:31  robertj
00125  * Added associated transport to new GetInterfaceAddresses() function so
00126  *   interfaces can be ordered according to active transport links. Improves
00127  *   interoperability.
00128  * Replaced old listener GetTransportPDU() with GetInterfaceAddresses()
00129  *   and H323SetTransportAddresses() functions.
00130  *
00131  * Revision 1.141  2003/04/09 03:08:10  robertj
00132  * Fixed race condition in shutting down transactor (pure virtual call)
00133  *
00134  * Revision 1.140  2003/03/26 00:46:28  robertj
00135  * Had another go at making H323Transactor being able to be created
00136  *   without having a listener running.
00137  *
00138  * Revision 1.139  2003/03/20 01:51:11  robertj
00139  * More abstraction of H.225 RAS and H.501 protocols transaction handling.
00140  *
00141  * Revision 1.138  2003/02/21 05:25:45  craigs
00142  * Abstracted out underlying transports for use with peerelements
00143  *
00144  * Revision 1.137  2003/02/12 23:59:25  robertj
00145  * Fixed adding missing endpoint identifer in SETUP packet when gatekeeper
00146  * routed, pointed out by Stefan Klein
00147  * Also fixed correct rutrn of gk routing in IRR packet.
00148  *
00149  * Revision 1.136  2003/02/11 04:46:37  robertj
00150  * Fixed keep alive RRQ being rejected with full registration required
00151  *   reason actually doing a full registration!
00152  *
00153  * Revision 1.135  2003/02/10 01:51:50  robertj
00154  * Fixed bad tokens causing an apparent "transport error", now correctly
00155  *   indicates a security error.
00156  *
00157  * Revision 1.134  2003/02/07 06:38:47  robertj
00158  * Changed registration state to an enum so can determine why the RRQ failed.
00159  *
00160  * Revision 1.133  2003/02/04 07:04:45  robertj
00161  * Prevent multiple calls to Connect() if did not change the gk.
00162  *
00163  * Revision 1.132  2003/02/01 13:31:21  robertj
00164  * Changes to support CAT authentication in RAS.
00165  *
00166  * Revision 1.131  2003/01/11 05:04:03  robertj
00167  * Added checks for valid URQ packet, thanks Chih-Wei Huang
00168  *
00169  * Revision 1.130  2003/01/09 04:45:04  robertj
00170  * Fixed problem where if gets GRJ which does not have an alternate gatekeeper
00171  *   the system gets into an infinite loop, pointed out by Vladimir Toncar
00172  *
00173  * Revision 1.129  2003/01/06 07:09:43  robertj
00174  * Further fixes for alternate gatekeeper, thanks Kevin Bouchard
00175  *
00176  * Revision 1.128  2002/12/23 22:47:53  robertj
00177  * Changed gatekeeper discovery so an GRJ does not indicate "discovered".
00178  * Added trace output of alternate gatekeepers list.
00179  * Fixed receiving GRJ with alternate gatekeepers to immediately  do discover
00180  *   and registration on the alternate.
00181  *
00182  * Revision 1.127  2002/12/19 23:52:53  robertj
00183  * Fixed probelm with registering with alternate gk, thanks Kevin Bouchard
00184  *
00185  * Revision 1.126  2002/12/10 23:39:03  robertj
00186  * Added some extra tracing.
00187  *
00188  * Revision 1.125  2002/11/28 04:41:48  robertj
00189  * Added support for RAS ServiceControlIndication command.
00190  *
00191  * Revision 1.124  2002/11/27 06:54:56  robertj
00192  * Added Service Control Session management as per Annex K/H.323 via RAS
00193  *   only at this stage.
00194  * Added H.248 ASN and very primitive infrastructure for linking into the
00195  *   Service Control Session management system.
00196  * Added basic infrastructure for Annex K/H.323 HTTP transport system.
00197  * Added Call Credit Service Control to display account balances.
00198  *
00199  * Revision 1.123  2002/11/22 07:16:14  robertj
00200  * Changed ARQ to include all local aliases for connection.
00201  *
00202  * Revision 1.122  2002/11/21 07:29:15  robertj
00203  * Fixed GNU warning
00204  *
00205  * Revision 1.121  2002/11/21 07:21:49  robertj
00206  * Improvements to alternate gatekeeper client code, thanks Kevin Bouchard
00207  *
00208  * Revision 1.120  2002/11/12 03:13:24  robertj
00209  * Removed redundent code.
00210  *
00211  * Revision 1.119  2002/11/10 08:10:43  robertj
00212  * Moved constants for "well known" ports to better place (OPAL change).
00213  *
00214  * Revision 1.118  2002/11/01 03:48:18  robertj
00215  * Fixed previous two hacks!! Neither of which would have worked.
00216  *
00217  * Revision 1.117  2002/10/31 23:31:41  dereks
00218  * Fix for previous quick hack. Thanks Damien Sandras.
00219  *
00220  * Revision 1.116  2002/10/31 21:40:28  dereks
00221  * Quick (and temporary) hack to enable compilation on redhat 8.0 boxes.
00222  *
00223  * Revision 1.115  2002/09/19 23:19:25  robertj
00224  * Fixed setting of info request rate, broken in a previous patch
00225  *
00226  * Revision 1.114  2002/09/18 06:58:32  robertj
00227  * Fixed setting of IRR frequency, an RCF could reset timer so it did not time
00228  *   out correctly and send IRR in time causing problems with gatekeeper.
00229  *
00230  * Revision 1.113  2002/09/09 23:59:59  robertj
00231  * Fixed incorrect inserting of UUIE pdu's into IRR, thanks Ravelli Rossano
00232  *
00233  * Revision 1.112  2002/08/29 07:02:19  robertj
00234  * Allowed network latency deadband in unsolicited IRR response time.
00235  *
00236  * Revision 1.111  2002/08/28 00:07:02  robertj
00237  * Added supportsAltGK capability flag in GRQ & RRQ.
00238  *
00239  * Revision 1.110  2002/08/15 09:38:55  robertj
00240  * Added more logging for when endpoint becomes unregistered.
00241  *
00242  * Revision 1.109  2002/08/15 04:12:54  robertj
00243  * Fixed correct status of isRegistered flag on various reject/errors.
00244  *
00245  * Revision 1.108  2002/08/12 05:38:24  robertj
00246  * Changes to the RAS subsystem to support ability to make requests to client
00247  *   from gkserver without causing bottlenecks and race conditions.
00248  *
00249  * Revision 1.107  2002/08/11 23:30:36  robertj
00250  * Fixed typo in previous patch.
00251  *
00252  * Revision 1.106  2002/08/11 23:24:24  robertj
00253  * Fixed problem with retrying ARQ after getting error saying are not
00254  *   registered and reregistering, needed new sequence number.
00255  * Fixed return of correct error in ARQ response when is a transport error
00256  *   rather than a reject reason from ARJ.
00257  *
00258  * Revision 1.105  2002/08/05 10:03:47  robertj
00259  * Cosmetic changes to normalise the usage of pragma interface/implementation.
00260  *
00261  * Revision 1.104  2002/08/05 05:17:41  robertj
00262  * Fairly major modifications to support different authentication credentials
00263  *   in ARQ to the logged in ones on RRQ. For both client and server.
00264  * Various other H.235 authentication bugs and anomalies fixed on the way.
00265  *
00266  * Revision 1.103  2002/07/19 10:20:03  robertj
00267  * Fixed bug of missing test for IRR frequency in RCF, thanks Thien Nguyen
00268  *
00269  * Revision 1.102  2002/07/18 03:03:19  robertj
00270  * Fixed bug with continually doing lightweight RRQ if no timeToLive present
00271  *   and it should not be doing it at all, ditto for unsolicited IRR.
00272  *
00273  * Revision 1.101  2002/07/17 00:04:10  robertj
00274  * Fixed missing initialisation of alternat gk pointer to NULL, thanks Kevin Bouchard
00275  *
00276  * Revision 1.100  2002/07/16 13:19:13  robertj
00277  * Minor optimisation of unsolicited IRR when no calls active.
00278  *
00279  * Revision 1.99  2002/07/16 11:06:27  robertj
00280  * Added more alternate gatekeeper implementation, thanks Kevin Bouchard
00281  *
00282  * Revision 1.98  2002/07/11 09:34:32  robertj
00283  * Fixed minor compliance to letter of specification.
00284  *
00285  * Revision 1.97  2002/07/11 01:34:37  robertj
00286  * Temporary fix for IRR frequency provided in ACF
00287  *
00288  * Revision 1.96  2002/07/07 02:08:53  robertj
00289  * Fixed missing originator field in IRR perCallInfo, thanks Ravelli Rossano
00290  *
00291  * Revision 1.95  2002/06/28 03:34:28  robertj
00292  * Fixed issues with address translation on gatekeeper RAS channel.
00293  *
00294  * Revision 1.94  2002/06/26 03:47:49  robertj
00295  * Added support for alternate gatekeepers.
00296  *
00297  * Revision 1.93  2002/06/26 00:50:12  robertj
00298  * Added other error code in ARJ that indicates we should reregister.
00299  *
00300  * Revision 1.92  2002/06/05 09:20:07  robertj
00301  * Added IRQ redirect of IRR to different address, thanks "thsuk".
00302  *
00303  * Revision 1.91  2002/05/29 00:03:19  robertj
00304  * Fixed unsolicited IRR support in gk client and server,
00305  *   including support for IACK and INAK.
00306  *
00307  * Revision 1.90  2002/05/17 04:01:53  robertj
00308  * Fixed problems with H.235 authentication on RAS for server and client.
00309  * Added support for unsolicited IRR transmission in background (heartbeat).
00310  *
00311  * Revision 1.89  2002/05/09 05:43:44  robertj
00312  * Added reattempt of full RRQ if get fullRegistrationRequired RRJ.
00313  *
00314  * Revision 1.88  2002/05/01 06:39:41  robertj
00315  * Fixed incorrect setting of srcCallSignalAddress in ARQ for outgoing call as
00316  *   putting in incorrect data is worse than not putting anything in at all! So
00317  *   unless the correct data is available it is now left out.
00318  *
00319  * Revision 1.87  2002/03/20 02:12:49  robertj
00320  * Added missing return value for number of endpoints returned in ACF
00321  *
00322  * Revision 1.86  2002/03/19 05:17:25  robertj
00323  * Normalised ACF destExtraCallIInfo to be same as other parameters.
00324  * Added ability to get multiple endpoint addresses and tokens from ACF.
00325  *
00326  * Revision 1.85  2002/03/01 04:06:44  robertj
00327  * Fixed autoreregister on ARQ failing due to unregistered endpoint.
00328  *
00329  * Revision 1.84  2002/02/11 04:25:57  robertj
00330  * Added ability to automatically reregister if do an ARQ and are told are not
00331  *   registered. Can occur if gk is restarted and is faster than waiting for TTL..
00332  *
00333  * Revision 1.83  2002/01/13 23:58:48  robertj
00334  * Added ability to set destination extra call info in ARQ
00335  * Filled in destinationInfo in ARQ when answering call.
00336  * Allowed application to override srcInfo in ARQ on outgoing call by
00337  *   changing localPartyName.
00338  * Added better end call codes for some ARJ reasons.
00339  * Thanks Ben Madsen of Norwood Systems.
00340  *
00341  * Revision 1.82  2001/12/15 10:10:48  robertj
00342  * GCC compatibility
00343  *
00344  * Revision 1.81  2001/12/15 08:36:49  robertj
00345  * Added previous call times to all the other PDU's it is supposed to be in!
00346  *
00347  * Revision 1.80  2001/12/15 08:09:21  robertj
00348  * Added alerting, connect and end of call times to be sent to RAS server.
00349  *
00350  * Revision 1.79  2001/12/14 06:41:36  robertj
00351  * Added call end reason codes in DisengageRequest for GK server use.
00352  *
00353  * Revision 1.78  2001/12/13 11:00:13  robertj
00354  * Changed search for access token in ACF to be able to look for two OID's.
00355  *
00356  * Revision 1.77  2001/12/06 06:44:42  robertj
00357  * Removed "Win32 SSL xxx" build configurations in favour of system
00358  *   environment variables to select optional libraries.
00359  *
00360  * Revision 1.76  2001/10/12 04:14:31  robertj
00361  * Changed gk unregister so only way it doe not actually unregister is if
00362  *   get URJ with reason code callInProgress, thanks Chris Purvis.
00363  *
00364  * Revision 1.75  2001/10/09 08:04:59  robertj
00365  * Fixed unregistration so still unregisters if gk goes offline, thanks Chris Purvis
00366  *
00367  * Revision 1.74  2001/10/08 01:37:42  robertj
00368  * Fixed uninitialised variable for ARQ authentication override.
00369  *
00370  * Revision 1.73  2001/09/26 07:03:08  robertj
00371  * Added needed mutex for SeparateAuthenticationInARQ mode, thanks Nick Hoath
00372  *
00373  * Revision 1.72  2001/09/18 10:36:57  robertj
00374  * Allowed multiple overlapping requests in RAS channel.
00375  *
00376  * Revision 1.71  2001/09/13 03:21:16  robertj
00377  * Added ability to override authentication credentials for ARQ, thanks Nick Hoath
00378  *
00379  * Revision 1.70  2001/09/13 01:15:20  robertj
00380  * Added flag to H235Authenticator to determine if gkid and epid is to be
00381  *   automatically set as the crypto token remote id and local id.
00382  *
00383  * Revision 1.69  2001/09/13 00:32:24  robertj
00384  * Added missing gkid in ARQ, thanks Nick Hoath
00385  *
00386  * Revision 1.68  2001/09/12 07:48:05  robertj
00387  * Fixed various problems with tracing.
00388  *
00389  * Revision 1.67  2001/09/12 06:58:00  robertj
00390  * Added support for iNow Access Token from gk, thanks Nick Hoath
00391  *
00392  * Revision 1.66  2001/09/12 06:04:38  robertj
00393  * Added support for sending UUIE's to gk on request, thanks Nick Hoath
00394  *
00395  * Revision 1.65  2001/09/05 01:16:32  robertj
00396  * Added overloaded AdmissionRequest for backward compatibility.
00397  *
00398  * Revision 1.64  2001/08/14 04:26:46  robertj
00399  * Completed the Cisco compatible MD5 authentications, thanks Wolfgang Platzer.
00400  *
00401  * Revision 1.63  2001/08/13 01:27:03  robertj
00402  * Changed GK admission so can return multiple aliases to be used in
00403  *   setup packet, thanks Nick Hoath.
00404  *
00405  * Revision 1.62  2001/08/13 00:22:14  robertj
00406  * Allowed for received DRQ not having call ID (eg v1 gk), uses conference ID
00407  *
00408  * Revision 1.61  2001/08/10 11:03:52  robertj
00409  * Major changes to H.235 support in RAS to support server.
00410  *
00411  * Revision 1.60  2001/08/06 07:44:55  robertj
00412  * Fixed problems with building without SSL
00413  *
00414  * Revision 1.59  2001/08/06 03:18:38  robertj
00415  * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
00416  * Improved access to H.235 secure RAS functionality.
00417  * Changes to H.323 secure RAS contexts to help use with gk server.
00418  *
00419  * Revision 1.58  2001/08/02 04:30:43  robertj
00420  * Added ability for AdmissionRequest to alter destination alias used in
00421  *   the outgoing call. Thanks Ben Madsen & Graeme Reid.
00422  *
00423  * Revision 1.57  2001/06/22 00:21:10  robertj
00424  * Fixed bug in H.225 RAS protocol with 16 versus 32 bit sequence numbers.
00425  *
00426  * Revision 1.56  2001/06/18 23:35:01  robertj
00427  * Removed condition that prevented aliases on non-terminal endpoints.
00428  *
00429  * Revision 1.55  2001/06/18 06:23:50  robertj
00430  * Split raw H.225 RAS protocol out of gatekeeper client class.
00431  *
00432  * Revision 1.54  2001/05/17 03:29:13  robertj
00433  * Fixed missing replyAddress in LRQ, thanks Alexander Smirnov.
00434  * Added some extra optional fields to LRQ.
00435  *
00436  * Revision 1.53  2001/04/19 08:03:21  robertj
00437  * Fixed scale on RIp delay, is milliseconds!
00438  *
00439  * Revision 1.52  2001/04/13 07:44:20  robertj
00440  * Fixed setting isRegistered flag to false when get RRJ
00441  *
00442  * Revision 1.51  2001/04/05 03:39:43  robertj
00443  * Fixed deadlock if tried to do discovery in time to live timeout.
00444  *
00445  * Revision 1.50  2001/03/28 07:13:06  robertj
00446  * Changed RAS thread interlock to allow for what should not happen, the
00447  *   syncpoint being signalled before receiving any packets.
00448  *
00449  * Revision 1.49  2001/03/27 02:19:22  robertj
00450  * Changed to send gk a GRQ if it gives a discoveryRequired error on RRQ.
00451  * Fixed BIG  condition in use of sequence numbers.
00452  *
00453  * Revision 1.48  2001/03/26 05:06:03  robertj
00454  * Added code to do full registration if RRJ indicates discovery to be redone.
00455  *
00456  * Revision 1.47  2001/03/24 00:51:41  robertj
00457  * Added retry every minute of time to live registration if fails.
00458  *
00459  * Revision 1.46  2001/03/23 01:47:49  robertj
00460  * Improved debug trace message on RAS packet retry.
00461  *
00462  * Revision 1.45  2001/03/23 01:19:25  robertj
00463  * Fixed usage of secure RAS in GRQ, should not do for that one PDU.
00464  *
00465  * Revision 1.44  2001/03/21 04:52:42  robertj
00466  * Added H.235 security to gatekeepers, thanks Fürbass Franz!
00467  *
00468  * Revision 1.43  2001/03/19 23:32:30  robertj
00469  * Fixed problem with auto-reregister doing so in the RAS receive thread.
00470  *
00471  * Revision 1.42  2001/03/19 05:50:52  robertj
00472  * Fixed trace display of timeout value.
00473  *
00474  * Revision 1.41  2001/03/18 22:21:29  robertj
00475  * Fixed GNU C++ problem.
00476  *
00477  * Revision 1.40  2001/03/17 00:05:52  robertj
00478  * Fixed problems with Gatekeeper RIP handling.
00479  *
00480  * Revision 1.39  2001/03/16 06:46:21  robertj
00481  * Added ability to set endpoints desired time to live on a gatekeeper.
00482  *
00483  * Revision 1.38  2001/03/15 00:25:58  robertj
00484  * Fixed bug in receiving RIP packet, did not restart timeout.
00485  *
00486  * Revision 1.37  2001/03/09 02:55:53  robertj
00487  * Fixed bug in RAS IRR, optional field not being included, thanks Erik Larsson.
00488  *
00489  * Revision 1.36  2001/03/02 06:59:59  robertj
00490  * Enhanced the globally unique identifier class.
00491  *
00492  * Revision 1.35  2001/02/28 00:20:16  robertj
00493  * Added DiscoverByNameAndAddress() function, thanks Chris Purvis.
00494  *
00495  * Revision 1.34  2001/02/18 22:33:47  robertj
00496  * Added better handling of URJ, thanks Chris Purvis.
00497  *
00498  * Revision 1.33  2001/02/09 05:13:55  craigs
00499  * Added pragma implementation to (hopefully) reduce the executable image size
00500  * under Linux
00501  *
00502  * Revision 1.32  2001/01/25 01:44:26  robertj
00503  * Reversed order of changing alias list to avoid assert if delete all aliases.
00504  *
00505  * Revision 1.31  2000/11/01 03:30:27  robertj
00506  * Changed gatekeeper registration time to live to update in slightly less than the
00507  *    time to live time. Allows for system/network latency. Thanks Laurent PELLETIER.
00508  *
00509  * Revision 1.30  2000/09/25 06:48:11  robertj
00510  * Removed use of alias if there is no alias present, ie only have transport address.
00511  *
00512  * Revision 1.29  2000/09/01 02:12:37  robertj
00513  * Fixed problem when multiple GK's on LAN, only discovered first one.
00514  * Added ability to select a gatekeeper on LAN via it's identifier name.
00515  *
00516  * Revision 1.28  2000/07/15 09:54:21  robertj
00517  * Fixed problem with having empty or unusable assigned aliases.
00518  *
00519  * Revision 1.27  2000/07/11 19:26:39  robertj
00520  * Fixed problem with endpoint identifiers from some gatekeepers not being a string, just binary info.
00521  *
00522  * Revision 1.26  2000/06/20 03:18:04  robertj
00523  * Added function to get name of gatekeeper, subtle difference from getting identifier.
00524  *
00525  * Revision 1.25  2000/05/09 12:14:32  robertj
00526  * Added adjustment of endpoints alias list as approved by gatekeeper.
00527  *
00528  * Revision 1.24  2000/05/09 08:52:50  robertj
00529  * Added support for preGrantedARQ fields on registration.
00530  *
00531  * Revision 1.23  2000/05/04 10:43:54  robertj
00532  * Fixed problem with still trying to RRQ if got a GRJ.
00533  *
00534  * Revision 1.22  2000/05/02 04:32:26  robertj
00535  * Fixed copyright notice comment.
00536  *
00537  * Revision 1.21  2000/04/27 02:52:58  robertj
00538  * Added keepAlive field to RRQ if already registered,
00539  *
00540  * Revision 1.20  2000/04/12 21:22:16  robertj
00541  * Fixed warning in No Trace mode.
00542  *
00543  * Revision 1.19  2000/04/11 04:00:55  robertj
00544  * Filled in destCallSignallingAddress if specified by caller, used for gateway permissions.
00545  *
00546  * Revision 1.18  2000/04/11 03:11:12  robertj
00547  * Added ability to reject reason on gatekeeper requests.
00548  *
00549  * Revision 1.17  2000/03/29 02:14:43  robertj
00550  * Changed TerminationReason to CallEndReason to use correct telephony nomenclature.
00551  * Added CallEndReason for capability exchange failure.
00552  *
00553  * Revision 1.16  2000/03/23 02:45:28  robertj
00554  * Changed ClearAllCalls() so will wait for calls to be closed (usefull in endpoint dtors).
00555  *
00556  * Revision 1.15  2000/03/21 23:17:55  robertj
00557  * Changed GK client so does not fill in destCallSignalAddress on outgoing call.
00558  *
00559  * Revision 1.14  2000/01/28 00:56:48  robertj
00560  * Changed ACF to return destination address irrespective of callModel, thanks Chris Gindel.
00561  *
00562  * Revision 1.13  1999/12/23 23:02:35  robertj
00563  * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
00564  *
00565  * Revision 1.12  1999/12/11 02:20:58  robertj
00566  * Added ability to have multiple aliases on local endpoint.
00567  *
00568  * Revision 1.11  1999/12/10 01:43:25  robertj
00569  * Fixed outgoing call Admissionrequestion addresses.
00570  *
00571  * Revision 1.10  1999/12/09 21:49:18  robertj
00572  * Added reregister on unregister and time to live reregistration
00573  *
00574  * Revision 1.9  1999/11/06 05:37:45  robertj
00575  * Complete rewrite of termination of connection to avoid numerous race conditions.
00576  *
00577  * Revision 1.8  1999/10/16 03:47:48  robertj
00578  * Fixed termination of gatekeeper RAS thread problem
00579  *
00580  * Revision 1.7  1999/10/15 05:55:50  robertj
00581  * Fixed crash in responding to InfoRequest
00582  *
00583  * Revision 1.6  1999/09/23 08:48:45  robertj
00584  * Changed register request so cannot do it of have no listeners.
00585  *
00586  * Revision 1.5  1999/09/21 14:09:19  robertj
00587  * Removed warnings when no tracing enabled.
00588  *
00589  * Revision 1.4  1999/09/14 08:19:37  robertj
00590  * Fixed timeout on retry of gatekeeper discover and added more tracing.
00591  *
00592  * Revision 1.3  1999/09/14 06:52:54  robertj
00593  * Added better support for multi-homed client hosts.
00594  *
00595  * Revision 1.2  1999/09/10 02:45:31  robertj
00596  * Added missing binding of address to transport when a specific gatway is used.
00597  *
00598  * Revision 1.1  1999/08/31 12:34:18  robertj
00599  * Added gatekeeper support.
00600  *
00601  */
00602 
00603 #include <ptlib.h>
00604 
00605 #ifdef __GNUC__
00606 #pragma implementation "gkclient.h"
00607 #endif
00608 
00609 #if defined(_WIN32) && (_MSC_VER > 1300)
00610   #pragma warning(disable:4244) // warning about possible loss of data
00611 #endif
00612 
00613 #include "gkclient.h"
00614 
00615 #include "h323ep.h"
00616 #include "h323rtp.h"
00617 #include "h323pdu.h"
00618 
00619 #ifdef H323_H460
00620 #include "h460/h4601.h"
00621 #endif
00622 
00623 #define new PNEW
00624 
00625 
00626 static PTimeInterval AdjustTimeout(unsigned seconds)
00627 {
00628   // Allow for an incredible amount of system/network latency
00629   static unsigned TimeoutDeadband = 5; // seconds
00630 
00631   return PTimeInterval(0, seconds > TimeoutDeadband
00632                               ? (seconds - TimeoutDeadband)
00633                               : TimeoutDeadband);
00634 }
00635 
00636 
00638 
00639 H323Gatekeeper::H323Gatekeeper(H323EndPoint & ep, H323Transport * trans)
00640   : H225_RAS(ep, trans),
00641     requestMutex(1, 1),
00642     authenticators(ep.CreateAuthenticators())
00643 #ifdef H323_H460
00644     ,features(ep.GetFeatureSet())
00645 #endif
00646 {
00647   alternatePermanent = FALSE;
00648   discoveryComplete = FALSE;
00649   registrationFailReason = UnregisteredLocally;
00650 
00651   pregrantMakeCall = pregrantAnswerCall = RequireARQ;
00652 
00653   autoReregister = TRUE;
00654   reregisterNow = FALSE;
00655   requiresDiscovery = FALSE;
00656 
00657   timeToLive.SetNotifier(PCREATE_NOTIFIER(TickleMonitor));
00658   infoRequestRate.SetNotifier(PCREATE_NOTIFIER(TickleMonitor));
00659 
00660   willRespondToIRR = FALSE;
00661   monitorStop = FALSE;
00662 
00663   monitor = PThread::Create(PCREATE_NOTIFIER(MonitorMain), 0,
00664                             PThread::NoAutoDeleteThread,
00665                             PThread::NormalPriority,
00666                             "GkMonitor:%x");
00667 #ifdef H323_H460
00668   features.LoadFeatureSet(H460_Feature::FeatureRas);
00669 #endif
00670 
00671   localId = PString();
00672   assignedGK = NULL;
00673 }
00674 
00675 
00676 H323Gatekeeper::~H323Gatekeeper()
00677 {
00678   if (monitor != NULL) {
00679     monitorStop = TRUE;
00680     monitorTickle.Signal();
00681     monitor->WaitForTermination();
00682     delete monitor;
00683   }
00684 
00685   StopChannel();
00686 }
00687 
00688 
00689 PString H323Gatekeeper::GetName() const
00690 {
00691   PStringStream s;
00692   s << *this;
00693   return s;
00694 }
00695 
00696 
00697 BOOL H323Gatekeeper::DiscoverAny()
00698 {
00699   gatekeeperIdentifier = PString();
00700   return StartDiscovery(H323TransportAddress());
00701 }
00702 
00703 
00704 BOOL H323Gatekeeper::DiscoverByName(const PString & identifier)
00705 {
00706   gatekeeperIdentifier = identifier;
00707   return StartDiscovery(H323TransportAddress());
00708 }
00709 
00710 
00711 BOOL H323Gatekeeper::DiscoverByAddress(const H323TransportAddress & address)
00712 {
00713   gatekeeperIdentifier = PString();
00714   return StartDiscovery(address);
00715 }
00716 
00717 
00718 BOOL H323Gatekeeper::DiscoverByNameAndAddress(const PString & identifier,
00719                                               const H323TransportAddress & address)
00720 {
00721   gatekeeperIdentifier = identifier;
00722   return StartDiscovery(address);
00723 }
00724 
00725 BOOL H323Gatekeeper::StartDiscovery(const H323TransportAddress & initialAddress)
00726 {
00727   if (PAssertNULL(transport) == NULL)
00728     return FALSE;
00729 
00731   if (!endpoint.GetSendGRQ() && !initialAddress.IsEmpty()) {
00732     transport->SetRemoteAddress(initialAddress);
00733     if (!transport->Connect()) {
00734       PTRACE(2, "RAS\tUnable to connect to gatekeeper at " << initialAddress);
00735       return FALSE;
00736     }
00737     transport->SetPromiscuous(H323Transport::AcceptFromRemoteOnly);
00738     StartChannel();
00739     PTRACE(2, "RAS\tSkipping gatekeeper discovery for " << initialAddress);
00740     return TRUE;
00741   }
00742 
00743   H323RasPDU pdu;
00744   Request request(SetupGatekeeperRequest(pdu), pdu);
00745 
00746   H323TransportAddress address = initialAddress;
00747   request.responseInfo = &address;
00748 
00749   requestsMutex.Wait();
00750   requests.SetAt(request.sequenceNumber, &request);
00751   requestsMutex.Signal();
00752 
00753   discoveryComplete = FALSE;
00754   unsigned retries = endpoint.GetGatekeeperRequestRetries();
00755   while (!discoveryComplete) {
00756     if (transport->DiscoverGatekeeper(*this, pdu, address)) {
00757       if (address == initialAddress)
00758         break;
00760     }
00761     else {
00762       // Transport failure, retry
00763       if (--retries == 0)
00764         break;
00765     }
00766   }
00767 
00768   requestsMutex.Wait();
00769   requests.SetAt(request.sequenceNumber, NULL);
00770   requestsMutex.Signal();
00771 
00772   if (discoveryComplete) {
00773     if (transport->Connect())
00774       StartChannel();
00775   }
00776 
00777   return discoveryComplete;
00778 }
00779 
00780 
00781 unsigned H323Gatekeeper::SetupGatekeeperRequest(H323RasPDU & request)
00782 {
00783   if (PAssertNULL(transport) == NULL)
00784     return 0;
00785 
00786   H225_GatekeeperRequest & grq = request.BuildGatekeeperRequest(GetNextSequenceNumber());
00787 
00788   endpoint.SetEndpointTypeInfo(grq.m_endpointType);
00789   transport->SetUpTransportPDU(grq.m_rasAddress, TRUE);
00790 
00791   grq.IncludeOptionalField(H225_GatekeeperRequest::e_endpointAlias);
00792   H323SetAliasAddresses(endpoint.GetAliasNames(), grq.m_endpointAlias);
00793 
00794   if (!gatekeeperIdentifier) {
00795     grq.IncludeOptionalField(H225_GatekeeperRequest::e_gatekeeperIdentifier);
00796     grq.m_gatekeeperIdentifier = gatekeeperIdentifier;
00797   }
00798 
00799   grq.IncludeOptionalField(H225_GatekeeperRequest::e_supportsAltGK);
00800 
00801   grq.IncludeOptionalField(H225_GatekeeperRequest::e_supportsAssignedGK);
00802   grq.m_supportsAssignedGK = TRUE;
00803 
00804   OnSendGatekeeperRequest(grq);
00805 
00806   discoveryComplete = FALSE;
00807 
00808   return grq.m_requestSeqNum;
00809 }
00810 
00811 
00812 void H323Gatekeeper::OnSendGatekeeperRequest(H225_GatekeeperRequest & grq)
00813 {
00814   H225_RAS::OnSendGatekeeperRequest(grq);
00815 
00816   for (PINDEX i = 0; i < authenticators.GetSize(); i++) {
00817     if (authenticators[i].SetCapability(grq.m_authenticationCapability, grq.m_algorithmOIDs)) {
00818       grq.IncludeOptionalField(H225_GatekeeperRequest::e_authenticationCapability);
00819       grq.IncludeOptionalField(H225_GatekeeperRequest::e_algorithmOIDs);
00820     }
00821   }
00822 }
00823 
00824 
00825 BOOL H323Gatekeeper::OnReceiveGatekeeperConfirm(const H225_GatekeeperConfirm & gcf)
00826 {
00827   if (!H225_RAS::OnReceiveGatekeeperConfirm(gcf))
00828     return FALSE;
00829 
00830   PINDEX i;
00831 
00832   for (i = 0; i < authenticators.GetSize(); i++) {
00833     H235Authenticator & authenticator = authenticators[i];
00834     if (authenticator.UseGkAndEpIdentifiers())
00835       authenticator.SetRemoteId(gatekeeperIdentifier);
00836   }
00837 
00838   if (gcf.HasOptionalField(H225_GatekeeperConfirm::e_authenticationMode) &&
00839       gcf.HasOptionalField(H225_GatekeeperConfirm::e_algorithmOID)) {
00840     for (i = 0; i < authenticators.GetSize(); i++) {
00841       H235Authenticator & authenticator = authenticators[i];
00842       authenticator.Enable(authenticator.IsCapability(gcf.m_authenticationMode,
00843                                                       gcf.m_algorithmOID));
00844           PTRACE(4,"RAS\tAuthenticator " << authenticator.GetName() 
00845                               << (authenticator.IsActive() ? " ACTIVATED" : " disabled"));
00846     }
00847   }
00848 
00849   H323TransportAddress locatedAddress = gcf.m_rasAddress;
00850   PTRACE(2, "RAS\tGatekeeper discovery found " << locatedAddress);
00851 
00852   if (!transport->SetRemoteAddress(locatedAddress)) {
00853     PTRACE(2, "RAS\tInvalid gatekeeper discovery address: \"" << locatedAddress << '"');
00854     return FALSE;
00855   }
00856 
00857   if (gcf.HasOptionalField(H225_GatekeeperConfirm::e_alternateGatekeeper))
00858     SetAlternates(gcf.m_alternateGatekeeper, FALSE);
00859 
00860   if (gcf.HasOptionalField(H225_GatekeeperConfirm::e_assignedGatekeeper)) {
00861     SetAssignedGatekeeper(gcf.m_assignedGatekeeper);
00862     PTRACE(2, "RAS\tAssigned Gatekeeper redirected " << assignedGK);
00863         // This will force the gatekeeper to register to the assigned Gatekeeper.
00864         if (lastRequest->responseInfo != NULL) {
00865       H323TransportAddress & gkAddress = *(H323TransportAddress *)lastRequest->responseInfo;
00866       gkAddress = assignedGK->rasAddress;
00867           gatekeeperIdentifier = PString();
00868         }
00869   } else {
00870     endpoint.OnGatekeeperConfirm();
00871     discoveryComplete = TRUE;
00872   }
00873   return TRUE;
00874 }
00875 
00876 
00877 BOOL H323Gatekeeper::OnReceiveGatekeeperReject(const H225_GatekeeperReject & grj)
00878 {
00879   if (!H225_RAS::OnReceiveGatekeeperReject(grj))
00880     return FALSE;
00881 
00882   if (grj.HasOptionalField(H225_GatekeeperReject::e_altGKInfo)) {
00883     SetAlternates(grj.m_altGKInfo.m_alternateGatekeeper,
00884                   grj.m_altGKInfo.m_altGKisPermanent);
00885   }
00886 
00887   if ((alternates.GetSize() > 0) && (lastRequest->responseInfo != NULL)) {
00888       H323TransportAddress & gkAddress = *(H323TransportAddress *)lastRequest->responseInfo;
00889       gkAddress = alternates[0].rasAddress;
00890   }
00891 
00892   endpoint.OnGatekeeperReject();
00893 
00894   return TRUE;
00895 }
00896 
00897 
00898 BOOL H323Gatekeeper::RegistrationRequest(BOOL autoReg)
00899 {
00900   if (PAssertNULL(transport) == NULL)
00901     return FALSE;
00902 
00903   autoReregister = autoReg;
00904 
00905   H323RasPDU pdu;
00906   H225_RegistrationRequest & rrq = pdu.BuildRegistrationRequest(GetNextSequenceNumber());
00907 
00908   // If discoveryComplete flag is FALSE then do lightweight reregister
00909   rrq.m_discoveryComplete = discoveryComplete;
00910 
00911   // Check if the IP address might of changed since last registration (for DDNS Type registrations)
00912   H323TransportAddress newaddress;
00913   if ((!discoveryComplete) && (endpoint.GatekeeperCheckIP(transport->GetRemoteAddress(),newaddress)))
00914           transport->SetRemoteAddress(newaddress);
00915 
00916   rrq.m_rasAddress.SetSize(1);
00917   transport->SetUpTransportPDU(rrq.m_rasAddress[0], TRUE);
00918 
00919   H323TransportAddressArray listeners = endpoint.GetInterfaceAddresses(TRUE, transport);
00920   if (listeners.IsEmpty()) {
00921     PTRACE(1, "RAS\tCannot register with Gatekeeper without a H323Listener!");
00922     return FALSE;
00923   }
00924 
00925   H323SetTransportAddresses(*transport, listeners, rrq.m_callSignalAddress);
00926 
00927   endpoint.SetEndpointTypeInfo(rrq.m_terminalType);
00928   endpoint.SetVendorIdentifierInfo(rrq.m_endpointVendor);
00929 
00930   if (!IsRegistered()) {  // only send terminal aliases on full registration reset localId
00931     rrq.IncludeOptionalField(H225_RegistrationRequest::e_terminalAlias);
00932     H323SetAliasAddresses(endpoint.GetAliasNames(), rrq.m_terminalAlias);
00933                 for (PINDEX i = 0; i < authenticators.GetSize(); i++) { 
00934                         H235Authenticator & authenticator = authenticators[i];
00935                         if (authenticator.UseGkAndEpIdentifiers())
00936                             authenticator.SetLocalId(localId);
00937                 }
00938   }
00939 
00940   rrq.m_willSupplyUUIEs = TRUE;
00941   rrq.IncludeOptionalField(H225_RegistrationRequest::e_usageReportingCapability);
00942   rrq.m_usageReportingCapability.IncludeOptionalField(H225_RasUsageInfoTypes::e_startTime);
00943   rrq.m_usageReportingCapability.IncludeOptionalField(H225_RasUsageInfoTypes::e_endTime);
00944   rrq.m_usageReportingCapability.IncludeOptionalField(H225_RasUsageInfoTypes::e_terminationCause);
00945   rrq.IncludeOptionalField(H225_RegistrationRequest::e_supportsAltGK);
00946 
00947   if (!gatekeeperIdentifier) {
00948     rrq.IncludeOptionalField(H225_RegistrationRequest::e_gatekeeperIdentifier);
00949     rrq.m_gatekeeperIdentifier = gatekeeperIdentifier;
00950   }
00951 
00952   if (!endpointIdentifier.IsEmpty()) {
00953     rrq.IncludeOptionalField(H225_RegistrationRequest::e_endpointIdentifier);
00954     rrq.m_endpointIdentifier = endpointIdentifier;
00955   }
00956 
00957   PTimeInterval ttl = endpoint.GetGatekeeperTimeToLive();
00958   if (ttl > 0) {
00959     rrq.IncludeOptionalField(H225_RegistrationRequest::e_timeToLive);
00960     rrq.m_timeToLive = (int)ttl.GetSeconds();
00961   }
00962 
00963   if (endpoint.CanDisplayAmountString()) {
00964     rrq.IncludeOptionalField(H225_RegistrationRequest::e_callCreditCapability);
00965     rrq.m_callCreditCapability.IncludeOptionalField(H225_CallCreditCapability::e_canDisplayAmountString);
00966     rrq.m_callCreditCapability.m_canDisplayAmountString = TRUE;
00967   }
00968 
00969   if (endpoint.CanEnforceDurationLimit()) {
00970     rrq.IncludeOptionalField(H225_RegistrationRequest::e_callCreditCapability);
00971     rrq.m_callCreditCapability.IncludeOptionalField(H225_CallCreditCapability::e_canEnforceDurationLimit);
00972     rrq.m_callCreditCapability.m_canEnforceDurationLimit = TRUE;
00973   }
00974 
00975   if (assignedGK != NULL) {
00976           rrq.IncludeOptionalField(H225_RegistrationRequest::e_assignedGatekeeper);
00977           rrq.m_assignedGatekeeper = assignedGK->GetAlternate();
00978   }
00979 
00980   if (IsRegistered()) {
00981     rrq.IncludeOptionalField(H225_RegistrationRequest::e_keepAlive);
00982     rrq.m_keepAlive = TRUE;
00983   }
00984 
00985   // After doing full register, do lightweight reregisters from now on
00986   discoveryComplete = FALSE;
00987 
00988   Request request(rrq.m_requestSeqNum, pdu);
00989   if (MakeRequest(request))
00990     return TRUE;
00991 
00992   PTRACE(3, "RAS\tFailed registration of " << endpointIdentifier << " with " << gatekeeperIdentifier);
00993   switch (request.responseResult) {
00994     case Request::RejectReceived :
00995       switch (request.rejectReason) {
00996         case H225_RegistrationRejectReason::e_discoveryRequired :
00997           // If have been told by GK that we need to discover it again, set flag
00998           // for next register done by timeToLive handler to do discovery
00999           requiresDiscovery = TRUE;
01000           // Do next case
01001 
01002         case H225_RegistrationRejectReason::e_fullRegistrationRequired :
01003           registrationFailReason = GatekeeperLostRegistration;
01004           // Set timer to retry registration
01005           reregisterNow = TRUE;
01006           monitorTickle.Signal();
01007           break;
01008 
01009         // Onse below here are permananent errors, so don't try again
01010         case H225_RegistrationRejectReason::e_invalidCallSignalAddress :
01011           registrationFailReason = InvalidListener;
01012           break;
01013 
01014         case H225_RegistrationRejectReason::e_duplicateAlias :
01015           registrationFailReason = DuplicateAlias;
01016           break;
01017 
01018         case H225_RegistrationRejectReason::e_securityDenial :
01019           registrationFailReason = SecurityDenied;
01020           break;
01021 
01022         default :
01023           registrationFailReason = (RegistrationFailReasons)(request.rejectReason|RegistrationRejectReasonMask);
01024           break;
01025       }
01026       break;
01027 
01028     case Request::BadCryptoTokens :
01029       registrationFailReason = SecurityDenied;
01030       break;
01031 
01032     default :
01033       registrationFailReason = TransportError;
01034       break;
01035   }
01036 
01037   return FALSE;
01038 }
01039 
01040 
01041 BOOL H323Gatekeeper::OnReceiveRegistrationConfirm(const H225_RegistrationConfirm & rcf)
01042 {
01043   if (!H225_RAS::OnReceiveRegistrationConfirm(rcf))
01044     return FALSE;
01045 
01046   registrationFailReason = RegistrationSuccessful;
01047 
01048   endpointIdentifier = rcf.m_endpointIdentifier;
01049   PTRACE(3, "RAS\tRegistered " << endpointIdentifier << " with " << gatekeeperIdentifier);
01050 
01051   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_assignedGatekeeper))
01052     SetAssignedGatekeeper(rcf.m_assignedGatekeeper);
01053 
01054   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_alternateGatekeeper))
01055     SetAlternates(rcf.m_alternateGatekeeper, FALSE);
01056 
01057   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_timeToLive))
01058     timeToLive = AdjustTimeout(rcf.m_timeToLive);
01059   else
01060     timeToLive = 0; // zero disables lightweight RRQ
01061 
01062   // At present only support first call signal address to GK
01063   if (rcf.m_callSignalAddress.GetSize() > 0)
01064     gkRouteAddress = rcf.m_callSignalAddress[0];
01065 
01066   willRespondToIRR = rcf.m_willRespondToIRR;
01067 
01068   pregrantMakeCall = pregrantAnswerCall = RequireARQ;
01069   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_preGrantedARQ)) {
01070     if (rcf.m_preGrantedARQ.m_makeCall)
01071       pregrantMakeCall = rcf.m_preGrantedARQ.m_useGKCallSignalAddressToMakeCall
01072                                                       ? PreGkRoutedARQ : PregrantARQ;
01073     if (rcf.m_preGrantedARQ.m_answerCall)
01074       pregrantAnswerCall = rcf.m_preGrantedARQ.m_useGKCallSignalAddressToAnswer
01075                                                       ? PreGkRoutedARQ : PregrantARQ;
01076     if (rcf.m_preGrantedARQ.HasOptionalField(H225_RegistrationConfirm_preGrantedARQ::e_irrFrequencyInCall))
01077       SetInfoRequestRate(AdjustTimeout(rcf.m_preGrantedARQ.m_irrFrequencyInCall));
01078     else
01079       ClearInfoRequestRate();
01080   }
01081   else
01082     ClearInfoRequestRate();
01083 
01084   // Remove the endpoint aliases that the gatekeeper did not like and add the
01085   // ones that it really wants us to be.
01086   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_terminalAlias) &&
01087                               !endpoint.OnGatekeeperAliases(rcf.m_terminalAlias)) {
01088     const PStringList & currentAliases = endpoint.GetAliasNames();
01089     PStringList aliasesToChange;
01090     PINDEX i, j;
01091 
01092     for (i = 0; i < rcf.m_terminalAlias.GetSize(); i++) {
01093       PString alias = H323GetAliasAddressString(rcf.m_terminalAlias[i]);
01094       if (!alias) {
01095         for (j = 0; j < currentAliases.GetSize(); j++) {
01096           if (alias *= currentAliases[j])
01097             break;
01098         }
01099         if (j >= currentAliases.GetSize())
01100           aliasesToChange.AppendString(alias);
01101       }
01102     }
01103     for (i = 0; i < aliasesToChange.GetSize(); i++) {
01104       PTRACE(2, "RAS\tGatekeeper add of alias \"" << aliasesToChange[i] << '"');
01105       endpoint.AddAliasName(aliasesToChange[i]);
01106     }
01107 
01108     aliasesToChange.RemoveAll();
01109 
01110     for (i = 0; i < currentAliases.GetSize(); i++) {
01111       for (j = 0; j < rcf.m_terminalAlias.GetSize(); j++) {
01112         if (currentAliases[i] *= H323GetAliasAddressString(rcf.m_terminalAlias[j]))
01113           break;
01114       }
01115       if (j >= rcf.m_terminalAlias.GetSize())
01116         aliasesToChange.AppendString(currentAliases[i]);
01117     }
01118     for (i = 0; i < aliasesToChange.GetSize(); i++) {
01119       PTRACE(2, "RAS\tGatekeeper removal of alias \"" << aliasesToChange[i] << '"');
01120       endpoint.RemoveAliasName(aliasesToChange[i]);
01121     }
01122   }
01123 
01124 #ifdef H323_H248
01125   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_serviceControl))
01126     OnServiceControlSessions(rcf.m_serviceControl, NULL);
01127 #endif
01128 
01129 // NAT Detection with GNUGK
01130   if (rcf.HasOptionalField(H225_RegistrationConfirm::e_nonStandardData))
01131   {
01132           PString NATaddr = rcf.m_nonStandardData.m_data.AsString();
01133        if (!NATaddr.IsEmpty())
01134                   if (NATaddr.Left(4) == "NAT=")
01135                       endpoint.OnGatekeeperNATDetect(NATaddr.Right(NATaddr.GetLength()-4),endpointIdentifier,gkRouteAddress);
01136                   else
01137               endpoint.OnGatekeeperOpenNATDetect(endpointIdentifier,gkRouteAddress);
01138   }
01139 
01140   endpoint.OnRegistrationConfirm(gkRouteAddress);
01141 
01142   return TRUE;
01143 }
01144 
01145 
01146 BOOL H323Gatekeeper::OnReceiveRegistrationReject(const H225_RegistrationReject & rrj)
01147 {
01148   if (!H225_RAS::OnReceiveRegistrationReject(rrj))
01149     return FALSE;
01150 
01151   if (rrj.HasOptionalField(H225_RegistrationReject::e_assignedGatekeeper))
01152      SetAssignedGatekeeper(rrj.m_assignedGatekeeper);
01153   else if (rrj.HasOptionalField(H225_RegistrationReject::e_altGKInfo))