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))
01154     SetAlternates(rrj.m_altGKInfo.m_alternateGatekeeper,
01155                   rrj.m_altGKInfo.m_altGKisPermanent);
01156   else 
01157       endpoint.OnRegistrationReject();
01158 
01159   return TRUE;
01160 }
01161 
01162 void H323Gatekeeper::ReRegisterNow()
01163 {
01164   PTRACE(3, "RAS\tforcing reregistration");
01165   RegistrationTimeToLive();
01166 
01167 }
01168 
01169 void H323Gatekeeper::RegistrationTimeToLive()
01170 {
01171   PTRACE(3, "RAS\tTime To Live reregistration");
01172 
01173   if (requiresDiscovery) {
01174     PTRACE(2, "RAS\tRepeating discovery on gatekeepers request.");
01175 
01176     H323RasPDU pdu;
01177     Request request(SetupGatekeeperRequest(pdu), pdu);
01178     if (!MakeRequest(request) || !discoveryComplete) {
01179       PTRACE(2, "RAS\tRediscovery failed, retrying in 1 minute.");
01180       timeToLive = PTimeInterval(0, 0, 1);
01181       return;
01182     }
01183 
01184     requiresDiscovery = FALSE;
01185   }
01186 
01187   if (!RegistrationRequest(autoReregister)) {
01188     PTRACE_IF(2, !reregisterNow, "RAS\tTime To Live reregistration failed, retrying in 1 minute");
01189     timeToLive = PTimeInterval(0, 0, 1);
01190   }
01191 }
01192 
01193 
01194 BOOL H323Gatekeeper::UnregistrationRequest(int reason)
01195 {
01196   if (PAssertNULL(transport) == NULL)
01197     return FALSE;
01198 
01199   PINDEX i;
01200   H323RasPDU pdu;
01201   H225_UnregistrationRequest & urq = pdu.BuildUnregistrationRequest(GetNextSequenceNumber());
01202 
01203   H225_TransportAddress rasAddress;
01204   transport->SetUpTransportPDU(rasAddress, TRUE);
01205 
01206   H323SetTransportAddresses(*transport,
01207                             endpoint.GetInterfaceAddresses(TRUE, transport),
01208                             urq.m_callSignalAddress);
01209 
01210   urq.IncludeOptionalField(H225_UnregistrationRequest::e_endpointAlias);
01211   H323SetAliasAddresses(endpoint.GetAliasNames(), urq.m_endpointAlias);
01212 
01213   if (!gatekeeperIdentifier) {
01214     urq.IncludeOptionalField(H225_UnregistrationRequest::e_gatekeeperIdentifier);
01215     urq.m_gatekeeperIdentifier = gatekeeperIdentifier;
01216   }
01217 
01218   if (!endpointIdentifier.IsEmpty()) {
01219     urq.IncludeOptionalField(H225_UnregistrationRequest::e_endpointIdentifier);
01220     urq.m_endpointIdentifier = endpointIdentifier;
01221   }
01222 
01223   if (reason >= 0) {
01224     urq.IncludeOptionalField(H225_UnregistrationRequest::e_reason);
01225     urq.m_reason = reason;
01226   }
01227 
01228   Request request(urq.m_requestSeqNum, pdu);
01229 
01230   BOOL requestResult = MakeRequest(request);
01231 
01232   for (i = 0; i < alternates.GetSize(); i++) {
01233     AlternateInfo & altgk = alternates[i];
01234     if (altgk.registrationState == AlternateInfo::IsRegistered) {
01235       Connect(altgk.rasAddress,altgk.gatekeeperIdentifier);
01236       UnregistrationRequest(reason);
01237     }
01238   }
01239 
01240   if (requestResult)
01241     return TRUE;
01242 
01243   switch (request.responseResult) {
01244     case Request::NoResponseReceived :
01245       registrationFailReason = TransportError;
01246       timeToLive = 0; // zero disables lightweight RRQ
01247       break;
01248 
01249     case Request::BadCryptoTokens :
01250       registrationFailReason = SecurityDenied;
01251       timeToLive = 0; // zero disables lightweight RRQ
01252       break;
01253 
01254     default :
01255       break;
01256   }
01257 
01258   return !IsRegistered();
01259 }
01260 
01261 
01262 BOOL H323Gatekeeper::OnReceiveUnregistrationConfirm(const H225_UnregistrationConfirm & ucf)
01263 {
01264   if (!H225_RAS::OnReceiveUnregistrationConfirm(ucf))
01265     return FALSE;
01266 
01267   registrationFailReason = UnregisteredLocally;
01268   timeToLive = 0; // zero disables lightweight RRQ
01269 
01270   return TRUE;
01271 }
01272 
01273 
01274 BOOL H323Gatekeeper::OnReceiveUnregistrationRequest(const H225_UnregistrationRequest & urq)
01275 {
01276   if (!H225_RAS::OnReceiveUnregistrationRequest(urq))
01277     return FALSE;
01278 
01279   PTRACE(2, "RAS\tUnregistration received");
01280   if (!urq.HasOptionalField(H225_UnregistrationRequest::e_gatekeeperIdentifier) ||
01281        urq.m_gatekeeperIdentifier.GetValue() != gatekeeperIdentifier) {
01282     PTRACE(1, "RAS\tInconsistent gatekeeperIdentifier!");
01283     return FALSE;
01284   }
01285 
01286   if (!urq.HasOptionalField(H225_UnregistrationRequest::e_endpointIdentifier) ||
01287        urq.m_endpointIdentifier.GetValue() != endpointIdentifier) {
01288     PTRACE(1, "RAS\tInconsistent endpointIdentifier!");
01289     return FALSE;
01290   }
01291 
01292   endpoint.ClearAllCalls(H323Connection::EndedByGatekeeper, FALSE);
01293 
01294   PTRACE(3, "RAS\tUnregistered, calls cleared");
01295   registrationFailReason = UnregisteredByGatekeeper;
01296   timeToLive = 0; // zero disables lightweight RRQ
01297 
01298   if (urq.HasOptionalField(H225_UnregistrationRequest::e_alternateGatekeeper))
01299     SetAlternates(urq.m_alternateGatekeeper, FALSE);
01300 
01301   H323RasPDU response(authenticators);
01302   response.BuildUnregistrationConfirm(urq.m_requestSeqNum);
01303   BOOL ok = WritePDU(response);
01304 
01305   if (autoReregister) {
01306     PTRACE(3, "RAS\tReregistering by setting timeToLive");
01307     reregisterNow = TRUE;
01308     monitorTickle.Signal();
01309   }
01310 
01311   endpoint.OnUnRegisterRequest();
01312 
01313   return ok;
01314 }
01315 
01316 
01317 BOOL H323Gatekeeper::OnReceiveUnregistrationReject(const H225_UnregistrationReject & urj)
01318 {
01319   if (!H225_RAS::OnReceiveUnregistrationReject(urj))
01320     return FALSE;
01321 
01322   if (lastRequest->rejectReason != H225_UnregRejectReason::e_callInProgress) {
01323     registrationFailReason = UnregisteredLocally;
01324     timeToLive = 0; // zero disables lightweight RRQ
01325   }
01326 
01327   return TRUE;
01328 }
01329 
01330 
01331 BOOL H323Gatekeeper::LocationRequest(const PString & alias,
01332                                      H323TransportAddress & address)
01333 {
01334   PStringList aliases;
01335   aliases.AppendString(alias);
01336   return LocationRequest(aliases, address);
01337 }
01338 
01339 
01340 BOOL H323Gatekeeper::LocationRequest(const PStringList & aliases,
01341                                      H323TransportAddress & address)
01342 {
01343   if (PAssertNULL(transport) == NULL)
01344     return FALSE;
01345 
01346   H323RasPDU pdu;
01347   H225_LocationRequest & lrq = pdu.BuildLocationRequest(GetNextSequenceNumber());
01348 
01349   H323SetAliasAddresses(aliases, lrq.m_destinationInfo);
01350 
01351   if (!endpointIdentifier.IsEmpty()) {
01352     lrq.IncludeOptionalField(H225_LocationRequest::e_endpointIdentifier);
01353     lrq.m_endpointIdentifier = endpointIdentifier;
01354   }
01355 
01356   transport->SetUpTransportPDU(lrq.m_replyAddress, TRUE);
01357 
01358   lrq.IncludeOptionalField(H225_LocationRequest::e_sourceInfo);
01359   H323SetAliasAddresses(endpoint.GetAliasNames(), lrq.m_sourceInfo);
01360 
01361   if (!gatekeeperIdentifier) {
01362     lrq.IncludeOptionalField(H225_LocationRequest::e_gatekeeperIdentifier);
01363     lrq.m_gatekeeperIdentifier = gatekeeperIdentifier;
01364   }
01365 
01366   Request request(lrq.m_requestSeqNum, pdu);
01367   request.responseInfo = &address;
01368   if (!MakeRequest(request))
01369     return FALSE;
01370 
01371   // sanity check the address - some Gks return address 0.0.0.0 and port 0
01372   PIPSocket::Address ipAddr;
01373   WORD port;
01374   return address.GetIpAndPort(ipAddr, port) && (port != 0);
01375 }
01376 
01377 
01378 H323Gatekeeper::AdmissionResponse::AdmissionResponse()
01379 {
01380   rejectReason = UINT_MAX;
01381 
01382   gatekeeperRouted = FALSE;
01383   endpointCount = 1;
01384   transportAddress = NULL;
01385   accessTokenData = NULL;
01386 
01387   aliasAddresses = NULL;
01388   destExtraCallInfo = NULL;
01389 }
01390 
01391 
01392 struct AdmissionRequestResponseInfo {
01393   AdmissionRequestResponseInfo(
01394     H323Gatekeeper::AdmissionResponse & r,
01395     H323Connection & c
01396   ) : param(r), connection(c) { }
01397 
01398   H323Gatekeeper::AdmissionResponse & param;
01399   H323Connection & connection;
01400   unsigned allocatedBandwidth;
01401   unsigned uuiesRequested;
01402   PString      accessTokenOID1;
01403   PString      accessTokenOID2;
01404 };
01405 
01406 
01407 BOOL H323Gatekeeper::AdmissionRequest(H323Connection & connection,
01408                                       AdmissionResponse & response,
01409                                       BOOL ignorePreGrantedARQ)
01410 {
01411   BOOL answeringCall = connection.HadAnsweredCall();
01412 
01413   if (!ignorePreGrantedARQ) {
01414     switch (answeringCall ? pregrantAnswerCall : pregrantMakeCall) {
01415       case RequireARQ :
01416         break;
01417       case PregrantARQ :
01418         return TRUE;
01419       case PreGkRoutedARQ :
01420         if (gkRouteAddress.IsEmpty()) {
01421           response.rejectReason = UINT_MAX;
01422           return FALSE;
01423         }
01424         if (response.transportAddress != NULL)
01425           *response.transportAddress = gkRouteAddress;
01426         response.gatekeeperRouted = TRUE;
01427         return TRUE;
01428     }
01429   }
01430 
01431   H323RasPDU pdu;
01432   H225_AdmissionRequest & arq = pdu.BuildAdmissionRequest(GetNextSequenceNumber());
01433 
01434   arq.m_callType.SetTag(H225_CallType::e_pointToPoint);
01435   arq.m_endpointIdentifier = endpointIdentifier;
01436   arq.m_answerCall = answeringCall;
01437   arq.m_canMapAlias = TRUE; // Stack supports receiving a different number in the ACF 
01438                             // to the one sent in the ARQ
01439   arq.m_willSupplyUUIEs = TRUE;
01440 
01441   if (!gatekeeperIdentifier) {
01442     arq.IncludeOptionalField(H225_AdmissionRequest::e_gatekeeperIdentifier);
01443     arq.m_gatekeeperIdentifier = gatekeeperIdentifier;
01444   }
01445 
01446   PString destInfo = connection.GetRemotePartyName();
01447   arq.m_srcInfo.SetSize(1);
01448   if (answeringCall) {
01449     H323SetAliasAddress(destInfo, arq.m_srcInfo[0]);
01450     if (!connection.GetLocalPartyName()) {
01451       arq.IncludeOptionalField(H225_AdmissionRequest::e_destinationInfo);
01452       H323SetAliasAddresses(connection.GetLocalAliasNames(), arq.m_destinationInfo);
01453     }
01454   }
01455   else {
01456     H323SetAliasAddresses(connection.GetLocalAliasNames(), arq.m_srcInfo);
01457     if (response.transportAddress == NULL || destInfo != *response.transportAddress) {
01458       arq.IncludeOptionalField(H225_AdmissionRequest::e_destinationInfo);
01459       arq.m_destinationInfo.SetSize(1);
01460       H323SetAliasAddress(destInfo, arq.m_destinationInfo[0]);
01461     }
01462   }
01463 
01464   const H323Transport * signallingChannel = connection.GetSignallingChannel();
01465   if (answeringCall) {
01466     arq.IncludeOptionalField(H225_AdmissionRequest::e_srcCallSignalAddress);
01467     signallingChannel->SetUpTransportPDU(arq.m_srcCallSignalAddress, FALSE);
01468     arq.IncludeOptionalField(H225_AdmissionRequest::e_destCallSignalAddress);
01469     signallingChannel->SetUpTransportPDU(arq.m_destCallSignalAddress, TRUE);
01470   }
01471   else {
01472     if (signallingChannel != NULL && signallingChannel->IsOpen()) {
01473       arq.IncludeOptionalField(H225_AdmissionRequest::e_srcCallSignalAddress);
01474       signallingChannel->SetUpTransportPDU(arq.m_srcCallSignalAddress, TRUE);
01475     }
01476     if (response.transportAddress != NULL && !response.transportAddress->IsEmpty()) {
01477       arq.IncludeOptionalField(H225_AdmissionRequest::e_destCallSignalAddress);
01478       response.transportAddress->SetPDU(arq.m_destCallSignalAddress);
01479     }
01480   }
01481 
01482   arq.m_bandWidth = connection.GetBandwidthAvailable();
01483   arq.m_callReferenceValue = connection.GetCallReference();
01484   arq.m_conferenceID = connection.GetConferenceIdentifier();
01485   arq.m_callIdentifier.m_guid = connection.GetCallIdentifier();
01486 
01487   connection.SetCallLinkage(pdu);
01488 
01489   AdmissionRequestResponseInfo info(response, connection);
01490   info.accessTokenOID1 = connection.GetGkAccessTokenOID();
01491   PINDEX comma = info.accessTokenOID1.Find(',');
01492   if (comma == P_MAX_INDEX)
01493     info.accessTokenOID2 = info.accessTokenOID1;
01494   else {
01495     info.accessTokenOID2 = info.accessTokenOID1.Mid(comma+1);
01496     info.accessTokenOID1.Delete(comma, P_MAX_INDEX);
01497   }
01498 
01499   connection.OnSendARQ(arq);
01500 
01501   Request request(arq.m_requestSeqNum, pdu);
01502   request.responseInfo = &info;
01503 
01504   if (!authenticators.IsEmpty()) {
01505     pdu.Prepare(arq.m_tokens, H225_AdmissionRequest::e_tokens,
01506                 arq.m_cryptoTokens, H225_AdmissionRequest::e_cryptoTokens);
01507 
01508     H235Authenticators adjustedAuthenticators;
01509     if (connection.GetAdmissionRequestAuthentication(arq, adjustedAuthenticators)) {
01510       PTRACE(3, "RAS\tAuthenticators credentials replaced with \""
01511              << setfill(',') << adjustedAuthenticators << setfill(' ') << "\" during ARQ");
01512 
01513       for (PINDEX i = 0; i < adjustedAuthenticators.GetSize(); i++) {
01514         H235Authenticator & authenticator = adjustedAuthenticators[i];
01515         if (authenticator.UseGkAndEpIdentifiers())
01516           authenticator.SetRemoteId(gatekeeperIdentifier);
01517       }
01518 
01519       adjustedAuthenticators.PreparePDU(pdu,
01520                                         arq.m_tokens, H225_AdmissionRequest::e_tokens,
01521                                         arq.m_cryptoTokens, H225_AdmissionRequest::e_cryptoTokens);
01522       pdu.SetAuthenticators(adjustedAuthenticators);
01523     }
01524   }
01525 
01526   if (!MakeRequest(request)) {
01527     response.rejectReason = request.rejectReason;
01528 
01529     // See if we are registered.
01530     if (request.responseResult == Request::RejectReceived &&
01531         response.rejectReason != H225_AdmissionRejectReason::e_callerNotRegistered &&
01532         response.rejectReason != H225_AdmissionRejectReason::e_invalidEndpointIdentifier)
01533       return FALSE;
01534 
01535     PTRACE(2, "RAS\tEndpoint has become unregistered during ARQ from gatekeeper " << gatekeeperIdentifier);
01536 
01537     // Have been told we are not registered (or gk offline)
01538     switch (request.responseResult) {
01539       case Request::NoResponseReceived :
01540         registrationFailReason = TransportError;
01541         response.rejectReason = UINT_MAX;
01542         break;
01543 
01544       case Request::BadCryptoTokens :
01545         registrationFailReason = SecurityDenied;
01546         response.rejectReason = H225_AdmissionRejectReason::e_securityDenial;
01547         break;
01548 
01549       default :
01550         registrationFailReason = GatekeeperLostRegistration;
01551     }
01552 
01553     // If we are not registered and auto register is set ...
01554     if (!autoReregister)
01555       return FALSE;
01556 
01557     // Then immediately reregister.
01558     if (!RegistrationRequest(autoReregister))
01559       return FALSE;
01560 
01561     // Reset the gk info in ARQ
01562     arq.m_endpointIdentifier = endpointIdentifier;
01563     if (!gatekeeperIdentifier) {
01564       arq.IncludeOptionalField(H225_AdmissionRequest::e_gatekeeperIdentifier);
01565       arq.m_gatekeeperIdentifier = gatekeeperIdentifier;
01566     }
01567     else
01568       arq.RemoveOptionalField(H225_AdmissionRequest::e_gatekeeperIdentifier);
01569 
01570     // Is new request so need new sequence number as well.
01571     arq.m_requestSeqNum = GetNextSequenceNumber();
01572     request.sequenceNumber = arq.m_requestSeqNum;
01573 
01574     if (!MakeRequest(request)) {
01575       response.rejectReason = request.responseResult == Request::RejectReceived
01576                                                 ? request.rejectReason : UINT_MAX;
01577          
01578       return FALSE;
01579     }
01580   }
01581 
01582   connection.SetBandwidthAvailable(info.allocatedBandwidth);
01583   connection.SetUUIEsRequested(info.uuiesRequested);
01584 
01585   return TRUE;
01586 }
01587 
01588 
01589 void H323Gatekeeper::OnSendAdmissionRequest(H225_AdmissionRequest & /*arq*/)
01590 {
01591   // Override default function as it sets crypto tokens and this is really
01592   // done by the AdmissionRequest() function.
01593 }
01594 
01595 
01596 static unsigned GetUUIEsRequested(const H225_UUIEsRequested & pdu)
01597 {
01598   unsigned uuiesRequested = 0;
01599 
01600   if ((BOOL)pdu.m_setup)
01601     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_setup);
01602   if ((BOOL)pdu.m_callProceeding)
01603     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_callProceeding);
01604   if ((BOOL)pdu.m_connect)
01605     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_connect);
01606   if ((BOOL)pdu.m_alerting)
01607     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_alerting);
01608   if ((BOOL)pdu.m_information)
01609     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_information);
01610   if ((BOOL)pdu.m_releaseComplete)
01611     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_releaseComplete);
01612   if ((BOOL)pdu.m_facility)
01613     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_facility);
01614   if ((BOOL)pdu.m_progress)
01615     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_progress);
01616   if ((BOOL)pdu.m_empty)
01617     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_empty);
01618 
01619   if (pdu.HasOptionalField(H225_UUIEsRequested::e_status) && (BOOL)pdu.m_status)
01620     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_status);
01621   if (pdu.HasOptionalField(H225_UUIEsRequested::e_statusInquiry) && (BOOL)pdu.m_statusInquiry)
01622     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_statusInquiry);
01623   if (pdu.HasOptionalField(H225_UUIEsRequested::e_setupAcknowledge) && (BOOL)pdu.m_setupAcknowledge)
01624     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_setupAcknowledge);
01625   if (pdu.HasOptionalField(H225_UUIEsRequested::e_notify) && (BOOL)pdu.m_notify)
01626     uuiesRequested |= (1<<H225_H323_UU_PDU_h323_message_body::e_notify);
01627 
01628   return uuiesRequested;
01629 }
01630 
01631 
01632 static void ExtractToken(const AdmissionRequestResponseInfo & info,
01633                          const H225_ArrayOf_ClearToken & tokens,
01634                          PBYTEArray & accessTokenData)
01635 {
01636   if (!info.accessTokenOID1 && tokens.GetSize() > 0) {
01637     PTRACE(4, "Looking for OID " << info.accessTokenOID1 << " in ACF to copy.");
01638     for (PINDEX i = 0; i < tokens.GetSize(); i++) {
01639       if (tokens[i].m_tokenOID == info.accessTokenOID1) {
01640         PTRACE(4, "Looking for OID " << info.accessTokenOID2 << " in token to copy.");
01641         if (tokens[i].HasOptionalField(H235_ClearToken::e_nonStandard) &&
01642             tokens[i].m_nonStandard.m_nonStandardIdentifier == info.accessTokenOID2) {
01643           PTRACE(4, "Copying ACF nonStandard OctetString.");
01644           accessTokenData = tokens[i].m_nonStandard.m_data;
01645           break;
01646         }
01647       }
01648     }
01649   }
01650 }
01651 
01652 
01653 BOOL H323Gatekeeper::OnReceiveAdmissionConfirm(const H225_AdmissionConfirm & acf)
01654 {
01655   if (!H225_RAS::OnReceiveAdmissionConfirm(acf))
01656     return FALSE;
01657 
01658   AdmissionRequestResponseInfo & info = *(AdmissionRequestResponseInfo *)lastRequest->responseInfo;
01659   info.allocatedBandwidth = acf.m_bandWidth;
01660   if (info.param.transportAddress != NULL)
01661     *info.param.transportAddress = acf.m_destCallSignalAddress;
01662 
01663   info.param.gatekeeperRouted = acf.m_callModel.GetTag() == H225_CallModel::e_gatekeeperRouted;
01664 
01665   // Remove the endpoint aliases that the gatekeeper did not like and add the
01666   // ones that it really wants us to be.
01667   if (info.param.aliasAddresses != NULL &&
01668       acf.HasOptionalField(H225_AdmissionConfirm::e_destinationInfo)) {
01669     PTRACE(3, "RAS\tGatekeeper specified " << acf.m_destinationInfo.GetSize() << " aliases in ACF");
01670     *info.param.aliasAddresses = acf.m_destinationInfo;
01671   }
01672 
01673   if (acf.HasOptionalField(H225_AdmissionConfirm::e_uuiesRequested))
01674     info.uuiesRequested = GetUUIEsRequested(acf.m_uuiesRequested);
01675 
01676   if (info.param.destExtraCallInfo != NULL &&
01677       acf.HasOptionalField(H225_AdmissionConfirm::e_destExtraCallInfo))
01678     *info.param.destExtraCallInfo = acf.m_destExtraCallInfo;
01679 
01680   if (info.param.accessTokenData != NULL && acf.HasOptionalField(H225_AdmissionConfirm::e_tokens))
01681     ExtractToken(info, acf.m_tokens, *info.param.accessTokenData);
01682 
01683   if (info.param.transportAddress != NULL) {
01684     PINDEX count = 1;
01685     for (PINDEX i = 0; i < acf.m_alternateEndpoints.GetSize() && count < info.param.endpointCount; i++) {
01686       if (acf.m_alternateEndpoints[i].HasOptionalField(H225_Endpoint::e_callSignalAddress) &&
01687           acf.m_alternateEndpoints[i].m_callSignalAddress.GetSize() > 0) {
01688         info.param.transportAddress[count] = acf.m_alternateEndpoints[i].m_callSignalAddress[0];
01689         if (info.param.accessTokenData != NULL)
01690           ExtractToken(info, acf.m_alternateEndpoints[i].m_tokens, info.param.accessTokenData[count]);
01691         count++;
01692       }
01693     }
01694     info.param.endpointCount = count;
01695   }
01696 
01697   if (acf.HasOptionalField(H225_AdmissionConfirm::e_irrFrequency))
01698     SetInfoRequestRate(AdjustTimeout(acf.m_irrFrequency));
01699   willRespondToIRR = acf.m_willRespondToIRR;
01700 
01701   info.connection.OnReceivedACF(acf);
01702 
01703 #ifdef H323_H248
01704   if (acf.HasOptionalField(H225_AdmissionConfirm::e_serviceControl))
01705     OnServiceControlSessions(acf.m_serviceControl, &info.connection);
01706 #endif
01707 
01708   return TRUE;
01709 }
01710 
01711 
01712 BOOL H323Gatekeeper::OnReceiveAdmissionReject(const H225_AdmissionReject & arj)
01713 {
01714   if (!H225_RAS::OnReceiveAdmissionReject(arj))
01715     return FALSE;
01716 
01717   AdmissionRequestResponseInfo & info = *(AdmissionRequestResponseInfo *)lastRequest->responseInfo;
01718   info.connection.OnReceivedARJ(arj);
01719 
01720 #ifdef H323_H248
01721   if (arj.HasOptionalField(H225_AdmissionConfirm::e_serviceControl))
01722     OnServiceControlSessions(arj.m_serviceControl,&info.connection);
01723 #endif
01724 
01725   return TRUE;
01726 }
01727 
01728 
01729 static void SetRasUsageInformation(const H323Connection & connection, 
01730                                    H225_RasUsageInformation & usage)
01731 {
01732   unsigned time = connection.GetAlertingTime().GetTimeInSeconds();
01733   if (time != 0) {
01734     usage.IncludeOptionalField(H225_RasUsageInformation::e_alertingTime);
01735     usage.m_alertingTime = time;
01736   }
01737 
01738   time = connection.GetConnectionStartTime().GetTimeInSeconds();
01739   if (time != 0) {
01740     usage.IncludeOptionalField(H225_RasUsageInformation::e_connectTime);
01741     usage.m_connectTime = time;
01742   }
01743 
01744   time = connection.GetConnectionEndTime().GetTimeInSeconds();
01745   if (time != 0) {
01746     usage.IncludeOptionalField(H225_RasUsageInformation::e_endTime);
01747     usage.m_endTime = time;
01748   }
01749 }
01750 
01751 
01752 BOOL H323Gatekeeper::DisengageRequest(const H323Connection & connection, unsigned reason)
01753 {
01754   H323RasPDU pdu;
01755   H225_DisengageRequest & drq = pdu.BuildDisengageRequest(GetNextSequenceNumber());
01756 
01757   drq.m_endpointIdentifier = endpointIdentifier;
01758   drq.m_conferenceID = connection.GetConferenceIdentifier();
01759   drq.m_callReferenceValue = connection.GetCallReference();
01760   drq.m_callIdentifier.m_guid = connection.GetCallIdentifier();
01761   drq.m_disengageReason.SetTag(reason);
01762   drq.m_answeredCall = connection.HadAnsweredCall();
01763 
01764   drq.IncludeOptionalField(H225_DisengageRequest::e_usageInformation);
01765   SetRasUsageInformation(connection, drq.m_usageInformation);
01766 
01767   drq.IncludeOptionalField(H225_DisengageRequest::e_terminationCause);
01768   drq.m_terminationCause.SetTag(H225_CallTerminationCause::e_releaseCompleteReason);
01769   Q931::CauseValues cause = H323TranslateFromCallEndReason(connection, drq.m_terminationCause);
01770   if (cause != Q931::ErrorInCauseIE) {
01771     drq.m_terminationCause.SetTag(H225_CallTerminationCause::e_releaseCompleteCauseIE);
01772     PASN_OctetString & rcReason = drq.m_terminationCause;
01773     rcReason.SetSize(2);
01774     rcReason[0] = 0x80;
01775     rcReason[1] = (BYTE)(0x80|cause);
01776   }
01777 
01778   if (!gatekeeperIdentifier) {
01779     drq.IncludeOptionalField(H225_DisengageRequest::e_gatekeeperIdentifier);
01780     drq.m_gatekeeperIdentifier = gatekeeperIdentifier;
01781   }
01782 
01783   connection.OnSendDRQ(drq);
01784 
01785   Request request(drq.m_requestSeqNum, pdu);
01786   return MakeRequestWithReregister(request, H225_DisengageRejectReason::e_notRegistered);
01787 }
01788 
01789 
01790 BOOL H323Gatekeeper::OnReceiveDisengageRequest(const H225_DisengageRequest & drq)
01791 {
01792   if (!H225_RAS::OnReceiveDisengageRequest(drq))
01793     return FALSE;
01794 
01795   OpalGloballyUniqueID id = NULL;
01796   if (drq.HasOptionalField(H225_DisengageRequest::e_callIdentifier))
01797     id = drq.m_callIdentifier.m_guid;
01798   if (id == NULL)
01799     id = drq.m_conferenceID;
01800 
01801   H323RasPDU response(authenticators);
01802   H323Connection * connection = endpoint.FindConnectionWithLock(id.AsString());
01803   if (connection == NULL)
01804     response.BuildDisengageReject(drq.m_requestSeqNum,
01805                                   H225_DisengageRejectReason::e_requestToDropOther);
01806   else {
01807     H225_DisengageConfirm & dcf = response.BuildDisengageConfirm(drq.m_requestSeqNum);
01808 
01809     dcf.IncludeOptionalField(H225_DisengageConfirm::e_usageInformation);
01810     SetRasUsageInformation(*connection, dcf.m_usageInformation);
01811 
01812     connection->ClearCall(H323Connection::EndedByGatekeeper);
01813     connection->Unlock();
01814   }
01815 
01816 #ifdef H323_H248
01817   if (drq.HasOptionalField(H225_DisengageRequest::e_serviceControl))
01818     OnServiceControlSessions(drq.m_serviceControl, connection);
01819 #endif
01820 
01821   return WritePDU(response);
01822 }
01823 
01824 
01825 BOOL H323Gatekeeper::BandwidthRequest(H323Connection & connection,
01826                                       unsigned requestedBandwidth)
01827 {
01828   H323RasPDU pdu;
01829   H225_BandwidthRequest & brq = pdu.BuildBandwidthRequest(GetNextSequenceNumber());
01830 
01831   brq.m_endpointIdentifier = endpointIdentifier;
01832   brq.m_conferenceID = connection.GetConferenceIdentifier();
01833   brq.m_callReferenceValue = connection.GetCallReference();
01834   brq.m_callIdentifier.m_guid = connection.GetCallIdentifier();
01835   brq.m_bandWidth = requestedBandwidth;
01836   brq.IncludeOptionalField(H225_BandwidthRequest::e_usageInformation);
01837   SetRasUsageInformation(connection, brq.m_usageInformation);
01838 
01839   Request request(brq.m_requestSeqNum, pdu);
01840   
01841   unsigned allocatedBandwidth;
01842   request.responseInfo = &allocatedBandwidth;
01843 
01844   if (!MakeRequestWithReregister(request, H225_BandRejectReason::e_notBound))
01845     return FALSE;
01846 
01847   connection.SetBandwidthAvailable(allocatedBandwidth);
01848   return TRUE;
01849 }
01850 
01851 
01852 BOOL H323Gatekeeper::OnReceiveBandwidthConfirm(const H225_BandwidthConfirm & bcf)
01853 {
01854   if (!H225_RAS::OnReceiveBandwidthConfirm(bcf))
01855     return FALSE;
01856 
01857   if (lastRequest->responseInfo != NULL)
01858     *(unsigned *)lastRequest->responseInfo = bcf.m_bandWidth;
01859 
01860   return TRUE;
01861 }
01862 
01863 
01864 BOOL H323Gatekeeper::OnReceiveBandwidthRequest(const H225_BandwidthRequest & brq)
01865 {
01866   if (!H225_RAS::OnReceiveBandwidthRequest(brq))
01867     return FALSE;
01868 
01869   OpalGloballyUniqueID id = brq.m_callIdentifier.m_guid;
01870   H323Connection * connection = endpoint.FindConnectionWithLock(id.AsString());
01871 
01872   H323RasPDU response(authenticators);
01873   if (connection == NULL)
01874     response.BuildBandwidthReject(brq.m_requestSeqNum,
01875                                   H225_BandRejectReason::e_invalidConferenceID);
01876   else {
01877     if (connection->SetBandwidthAvailable(brq.m_bandWidth))
01878       response.BuildBandwidthConfirm(brq.m_requestSeqNum, brq.m_bandWidth);
01879     else
01880       response.BuildBandwidthReject(brq.m_requestSeqNum,
01881                                     H225_BandRejectReason::e_insufficientResources);
01882     connection->Unlock();
01883   }
01884 
01885   return WritePDU(response);
01886 }
01887 
01888 
01889 void H323Gatekeeper::SetInfoRequestRate(const PTimeInterval & rate)
01890 {
01891   if (rate < infoRequestRate.GetResetTime() || infoRequestRate.GetResetTime() == 0) {
01892     // Have to be sneaky here becuase we do not want to actually change the
01893     // amount of time to run on the timer.
01894     PTimeInterval timeToGo = infoRequestRate;
01895     infoRequestRate = rate;
01896     if (rate > timeToGo)
01897       infoRequestRate.PTimeInterval::operator=(timeToGo);
01898   }
01899 }
01900 
01901 
01902 void H323Gatekeeper::ClearInfoRequestRate()
01903 {
01904   // Only reset rate to zero (disabled) if no calls present
01905   if (endpoint.GetAllConnections().IsEmpty())
01906     infoRequestRate = 0;
01907 }
01908 
01909 
01910 H225_InfoRequestResponse & H323Gatekeeper::BuildInfoRequestResponse(H323RasPDU & response,
01911                                                                     unsigned seqNum)
01912 {
01913   H225_InfoRequestResponse & irr = response.BuildInfoRequestResponse(seqNum);
01914 
01915   endpoint.SetEndpointTypeInfo(irr.m_endpointType);
01916   irr.m_endpointIdentifier = endpointIdentifier;
01917   transport->SetUpTransportPDU(irr.m_rasAddress, TRUE);
01918   H323SetTransportAddresses(*transport,
01919                             endpoint.GetInterfaceAddresses(TRUE, transport),
01920                             irr.m_callSignalAddress);
01921 
01922   irr.IncludeOptionalField(H225_InfoRequestResponse::e_endpointAlias);
01923   H323SetAliasAddresses(endpoint.GetAliasNames(), irr.m_endpointAlias);
01924 
01925   return irr;
01926 }
01927 
01928 
01929 BOOL H323Gatekeeper::SendUnsolicitedIRR(H225_InfoRequestResponse & irr,
01930                                         H323RasPDU & response)
01931 {
01932   irr.m_unsolicited = TRUE;
01933 
01934   if (willRespondToIRR) {
01935     PTRACE(4, "RAS\tSending unsolicited IRR and awaiting acknowledgement");
01936     Request request(irr.m_requestSeqNum, response);
01937     return MakeRequest(request);
01938   }
01939 
01940   PTRACE(4, "RAS\tSending unsolicited IRR and without acknowledgement");
01941   response.SetAuthenticators(authenticators);
01942   return WritePDU(response);
01943 }
01944 
01945 
01946 static void AddInfoRequestResponseCall(H225_InfoRequestResponse & irr,
01947                                        const H323Connection & connection)
01948 {
01949   irr.IncludeOptionalField(H225_InfoRequestResponse::e_perCallInfo);
01950 
01951   PINDEX sz = irr.m_perCallInfo.GetSize();
01952   if (!irr.m_perCallInfo.SetSize(sz+1))
01953     return;
01954 
01955   H225_InfoRequestResponse_perCallInfo_subtype & info = irr.m_perCallInfo[sz];
01956 
01957   info.m_callReferenceValue = connection.GetCallReference();
01958   info.m_callIdentifier.m_guid = connection.GetCallIdentifier();
01959   info.m_conferenceID = connection.GetConferenceIdentifier();
01960   info.IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_originator);
01961   info.m_originator = !connection.HadAnsweredCall();
01962 
01963   H323_RTP_Session * session = connection.GetSessionCallbacks(RTP_Session::DefaultAudioSessionID);
01964   if (session != NULL) {
01965     info.IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_audio);
01966     info.m_audio.SetSize(1);
01967     session->OnSendRasInfo(info.m_audio[0]);
01968   }
01969 
01970   session = connection.GetSessionCallbacks(RTP_Session::DefaultVideoSessionID);
01971   if (session != NULL) {
01972     info.IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_video);
01973     info.m_video.SetSize(1);
01974     session->OnSendRasInfo(info.m_video[0]);
01975   }
01976 
01977   const H323Transport & controlChannel = connection.GetControlChannel();
01978   controlChannel.SetUpTransportPDU(info.m_h245.m_recvAddress, TRUE);
01979   controlChannel.SetUpTransportPDU(info.m_h245.m_sendAddress, FALSE);
01980 
01981   info.m_callType.SetTag(H225_CallType::e_pointToPoint);
01982   info.m_bandWidth = connection.GetBandwidthUsed();
01983   info.m_callModel.SetTag(connection.IsGatekeeperRouted() ? H225_CallModel::e_gatekeeperRouted
01984                                                           : H225_CallModel::e_direct);
01985 
01986   info.IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_usageInformation);
01987   SetRasUsageInformation(connection, info.m_usageInformation);
01988 }
01989 
01990 
01991 static BOOL AddAllInfoRequestResponseCall(H225_InfoRequestResponse & irr,
01992                                           H323EndPoint & endpoint,
01993                                           const PStringList & tokens)
01994 {
01995   BOOL addedOne = FALSE;
01996 
01997   for (PINDEX i = 0; i < tokens.GetSize(); i++) {
01998     H323Connection * connection = endpoint.FindConnectionWithLock(tokens[i]);
01999     if (connection != NULL) {
02000       AddInfoRequestResponseCall(irr, *connection);
02001           connection->OnSendIRR(irr);
02002       connection->Unlock();
02003       addedOne = TRUE;
02004     }
02005   }
02006 
02007   return addedOne;
02008 }
02009 
02010 
02011 void H323Gatekeeper::InfoRequestResponse()
02012 {
02013   PStringList tokens = endpoint.GetAllConnections();
02014   if (tokens.IsEmpty())
02015     return;
02016 
02017   H323RasPDU response;
02018   H225_InfoRequestResponse & irr = BuildInfoRequestResponse(response, GetNextSequenceNumber());
02019 
02020   if (AddAllInfoRequestResponseCall(irr, endpoint, tokens))
02021     SendUnsolicitedIRR(irr, response);
02022 }
02023 
02024 
02025 void H323Gatekeeper::InfoRequestResponse(const H323Connection & connection)
02026 {
02027   H323RasPDU response;
02028   H225_InfoRequestResponse & irr = BuildInfoRequestResponse(response, GetNextSequenceNumber());
02029 
02030   AddInfoRequestResponseCall(irr, connection);
02031 
02032   connection.OnSendIRR(irr);
02033 
02034   SendUnsolicitedIRR(irr, response);
02035 }
02036 
02037 
02038 void H323Gatekeeper::InfoRequestResponse(const H323Connection & connection,
02039                                          const H225_H323_UU_PDU & pdu,
02040                                          BOOL sent)
02041 {
02042   // Are unknown Q.931 PDU
02043   if (pdu.m_h323_message_body.GetTag() == P_MAX_INDEX)
02044     return;
02045 
02046   // Check mask of things to report on
02047   if ((connection.GetUUIEsRequested() & (1<<pdu.m_h323_message_body.GetTag())) == 0)
02048     return;
02049 
02050   PTRACE(3, "RAS\tSending unsolicited IRR for requested UUIE");
02051 
02052   // Report the PDU
02053   H323RasPDU response;
02054   H225_InfoRequestResponse & irr = BuildInfoRequestResponse(response, GetNextSequenceNumber());
02055 
02056   AddInfoRequestResponseCall(irr, connection);
02057 
02058   irr.m_perCallInfo[0].IncludeOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_pdu);
02059   irr.m_perCallInfo[0].m_pdu.SetSize(1);
02060   irr.m_perCallInfo[0].m_pdu[0].m_sent = sent;
02061   irr.m_perCallInfo[0].m_pdu[0].m_h323pdu = pdu;
02062 
02063   connection.OnSendIRR(irr);
02064   SendUnsolicitedIRR(irr, response);
02065 }
02066 
02067 
02068 BOOL H323Gatekeeper::OnReceiveInfoRequest(const H225_InfoRequest & irq)
02069 {
02070   if (!H225_RAS::OnReceiveInfoRequest(irq))
02071     return FALSE;
02072 
02073   H323RasPDU response(authenticators);
02074   H225_InfoRequestResponse & irr = BuildInfoRequestResponse(response, irq.m_requestSeqNum);
02075 
02076   if (irq.m_callReferenceValue == 0) {
02077     if (!AddAllInfoRequestResponseCall(irr, endpoint, endpoint.GetAllConnections())) {
02078       irr.IncludeOptionalField(H225_InfoRequestResponse::e_irrStatus);
02079       irr.m_irrStatus.SetTag(H225_InfoRequestResponseStatus::e_invalidCall);
02080     }
02081   }
02082   else {
02083     OpalGloballyUniqueID id = irq.m_callIdentifier.m_guid;
02084     H323Connection * connection = endpoint.FindConnectionWithLock(id.AsString());
02085     if (connection == NULL) {
02086       irr.IncludeOptionalField(H225_InfoRequestResponse::e_irrStatus);
02087       irr.m_irrStatus.SetTag(H225_InfoRequestResponseStatus::e_invalidCall);
02088     }
02089     else {
02090       if (irq.HasOptionalField(H225_InfoRequest::e_uuiesRequested))
02091         connection->SetUUIEsRequested(::GetUUIEsRequested(irq.m_uuiesRequested));
02092 
02093       AddInfoRequestResponseCall(irr, *connection);
02094 
02095       connection->Unlock();
02096     }
02097   }
02098 
02099   if (!irq.HasOptionalField(H225_InfoRequest::e_replyAddress))
02100     return WritePDU(response);
02101 
02102   H323TransportAddress replyAddress = irq.m_replyAddress;
02103   if (replyAddress.IsEmpty())
02104     return FALSE;
02105 
02106   H323TransportAddress oldAddress = transport->GetRemoteAddress();
02107 
02108   BOOL ok = transport->ConnectTo(replyAddress) && WritePDU(response);
02109 
02110   transport->ConnectTo(oldAddress);
02111 
02112   return ok;
02113 }
02114 
02115 #ifdef H323_H248
02116 
02117 BOOL H323Gatekeeper::OnReceiveServiceControlIndication(const H225_ServiceControlIndication & sci)
02118 {
02119   if (!H225_RAS::OnReceiveServiceControlIndication(sci))
02120     return FALSE;
02121 
02122   H323Connection * connection = NULL;
02123 
02124   if (sci.HasOptionalField(H225_ServiceControlIndication::e_callSpecific)) {
02125     OpalGloballyUniqueID id = sci.m_callSpecific.m_callIdentifier.m_guid;
02126     if (id.IsNULL())
02127       id = sci.m_callSpecific.m_conferenceID;
02128     connection = endpoint.FindConnectionWithLock(id.AsString());
02129   }
02130 
02131   OnServiceControlSessions(sci.m_serviceControl, connection);
02132 
02133 
02134   H323RasPDU response(authenticators);
02135   response.BuildServiceControlResponse(sci.m_requestSeqNum);
02136   return WritePDU(response);
02137 }
02138 
02139 
02140 void H323Gatekeeper::OnServiceControlSessions(const H225_ArrayOf_ServiceControlSession & serviceControl,
02141                                               H323Connection * connection)
02142 {
02143   for (PINDEX i = 0; i < serviceControl.GetSize(); i++) {
02144     H225_ServiceControlSession & pdu = serviceControl[i];
02145 
02146     H323ServiceControlSession * session = NULL;
02147     unsigned sessionId = pdu.m_sessionId;
02148 
02149     if (serviceControlSessions.Contains(sessionId)) {
02150       session = &serviceControlSessions[sessionId];
02151       if (pdu.HasOptionalField(H225_ServiceControlSession::e_contents)) {
02152         if (!session->OnReceivedPDU(pdu.m_contents)) {
02153           PTRACE(2, "SvcCtrl\tService control for session has changed!");
02154           session = NULL;
02155         }
02156       }
02157     }
02158 
02159     if (session == NULL && pdu.HasOptionalField(H225_ServiceControlSession::e_contents)) {
02160       session = endpoint.CreateServiceControlSession(pdu.m_contents);
02161       serviceControlSessions.SetAt(sessionId, session);
02162     }
02163 
02164     if (session != NULL)
02165       endpoint.OnServiceControlSession(pdu.m_reason.GetTag(),sessionId, *session, connection);
02166   }
02167 }
02168 
02169 #endif // H323_H248
02170 
02171 
02172 void H323Gatekeeper::SetPassword(const PString & password, 
02173                                  const PString & username)
02174 {
02175   localId = username;
02176   if (localId.IsEmpty())
02177     localId = endpoint.GetLocalUserName();
02178 
02179   for (PINDEX i = 0; i < authenticators.GetSize(); i++) {
02180     authenticators[i].SetLocalId(localId);
02181     authenticators[i].SetPassword(password);
02182   }
02183 }
02184 
02185 
02186 void H323Gatekeeper::MonitorMain(PThread &, INT)
02187 {
02188   PTRACE(3, "RAS\tBackground thread started");
02189 
02190   for (;;) {
02191     monitorTickle.Wait();
02192     if (monitorStop)
02193       break;
02194 
02195     if (reregisterNow || 
02196                 (!timeToLive.IsRunning() && timeToLive.GetResetTime() > 0)) {
02197       RegistrationTimeToLive();
02198       timeToLive.Reset();
02199     }
02200 
02201     if (!infoRequestRate.IsRunning() && infoRequestRate.GetResetTime() > 0) {
02202       InfoRequestResponse();
02203       infoRequestRate.Reset();
02204     }
02205   }
02206 
02207   PTRACE(3, "RAS\tBackground thread ended");
02208 }
02209 
02210 
02211 void H323Gatekeeper::TickleMonitor(PTimer &, INT)
02212 {
02213   monitorTickle.Signal();
02214 }
02215 
02216 
02217 void H323Gatekeeper::SetAlternates(const H225_ArrayOf_AlternateGK & alts, BOOL permanent)
02218 {
02219   PINDEX i;
02220 
02221   if (!alternatePermanent)  {
02222     // don't want to replace alternates gatekeepers if this is an alternate and it's not permanent
02223     for (i = 0; i < alternates.GetSize(); i++) {
02224       if (transport->GetRemoteAddress().IsEquivalent(alternates[i].rasAddress) &&
02225           gatekeeperIdentifier == alternates[i].gatekeeperIdentifier)
02226         return;
02227     }
02228   }
02229 
02230   alternates.RemoveAll();
02231 
02232   if (assignedGK != NULL)
02233           alternates.Append(assignedGK);
02234 
02235   for (i = 0; i < alts.GetSize(); i++) {
02236     AlternateInfo * alt = new AlternateInfo(alts[i]);
02237     if (alt->rasAddress.IsEmpty())
02238       delete alt;
02239     else
02240       alternates.Append(alt);
02241   }
02242   
02243   alternatePermanent = permanent;
02244 
02245   PTRACE(3, "RAS\tSet alternate gatekeepers:\n"
02246          << setfill('\n') << alternates << setfill(' '));
02247 }
02248 
02249 void H323Gatekeeper::SetAssignedGatekeeper(const H225_AlternateGK & gk)
02250 {
02251    assignedGK = new AlternateInfo(gk);
02252 }
02253 
02254 BOOL H323Gatekeeper::GetAssignedGatekeeper(H225_AlternateGK & gk)
02255 {
02256         if (assignedGK == NULL)
02257                 return FALSE;
02258 
02259         gk = assignedGK->GetAlternate();
02260         return TRUE;
02261 }
02262 
02263 
02264 BOOL H323Gatekeeper::MakeRequestWithReregister(Request & request, unsigned unregisteredTag)
02265 {
02266   if (MakeRequest(request))
02267     return TRUE;
02268 
02269   if (request.responseResult == Request::RejectReceived &&
02270       request.rejectReason != unregisteredTag)
02271     return FALSE;
02272 
02273   PTRACE(2, "RAS\tEndpoint has become unregistered from gatekeeper " << gatekeeperIdentifier);
02274 
02275   // Have been told we are not registered (or gk offline)
02276   switch (request.responseResult) {
02277     case Request::NoResponseReceived :
02278       registrationFailReason = TransportError;
02279       break;
02280 
02281     case Request::BadCryptoTokens :
02282       registrationFailReason = SecurityDenied;
02283       break;
02284 
02285     default :
02286       registrationFailReason = GatekeeperLostRegistration;
02287   }
02288 
02289   // If we are not registered and auto register is set ...
02290   if (!autoReregister)
02291     return FALSE;
02292 
02293   reregisterNow = TRUE;
02294   monitorTickle.Signal();
02295   return FALSE;
02296 }
02297 
02298 
02299 void H323Gatekeeper::Connect(const H323TransportAddress & address,
02300                              const PString & gkid)
02301 {
02302   if (transport == NULL)
02303     transport = new H323TransportUDP(endpoint, PIPSocket::GetDefaultIpAny());
02304 
02305   transport->SetRemoteAddress(address);
02306   transport->Connect();
02307   gatekeeperIdentifier = gkid;
02308 }
02309 
02310 
02311 BOOL H323Gatekeeper::MakeRequest(Request & request)
02312 {
02313   if (PAssertNULL(transport) == NULL)
02314     return FALSE;
02315 
02316   // Set authenticators if not already set by caller
02317   requestMutex.Wait();
02318 
02319   if (request.requestPDU.GetAuthenticators().IsEmpty())
02320     request.requestPDU.SetAuthenticators(authenticators);
02321 
02322   /* To be sure that the H323 Cleaner, H225 Caller or Monitor don't set the
02323      transport address of the alternate while the other is in timeout. We
02324      have to block the function */
02325 
02326   H323TransportAddress tempAddr = transport->GetRemoteAddress();
02327   PString tempIdentifier = gatekeeperIdentifier;
02328 
02329   PINDEX alt = 0;
02330   for (;;) {
02331     if (H225_RAS::MakeRequest(request)) {
02332       if (!alternatePermanent &&
02333             (transport->GetRemoteAddress() != tempAddr ||
02334              gatekeeperIdentifier != tempIdentifier))
02335         Connect(tempAddr, tempIdentifier);
02336       requestMutex.Signal();
02337       return TRUE;
02338     }
02339     
02340     if (request.responseResult != Request::NoResponseReceived &&
02341         request.responseResult != Request::TryAlternate) {
02342       // try alternate in those cases and see if it's successful
02343       requestMutex.Signal();
02344       return FALSE;
02345     }
02346     
02347     AlternateInfo * altInfo;
02348     PIPSocket::Address localAddress;
02349     WORD localPort;
02350     do {
02351       if (alt >= alternates.GetSize()) {
02352         if (!alternatePermanent) 
02353           Connect(tempAddr,tempIdentifier);
02354         requestMutex.Signal();
02355         return FALSE;
02356       }
02357       
02358       altInfo = &alternates[alt++];
02359       transport->GetLocalAddress().GetIpAndPort(localAddress,localPort);
02360       transport->CleanUpOnTermination();
02361       delete transport;
02362 
02363       transport = new H323TransportUDP(endpoint,localAddress,localPort);
02364       transport->SetRemoteAddress (altInfo->rasAddress);
02365       transport->Connect();
02366       gatekeeperIdentifier = altInfo->gatekeeperIdentifier;
02367       StartChannel();
02368     } while (altInfo->registrationState == AlternateInfo::RegistrationFailed);
02369     
02370     if (altInfo->registrationState == AlternateInfo::NeedToRegister) {
02371       altInfo->registrationState = AlternateInfo::RegistrationFailed;
02372       registrationFailReason = TransportError;
02373       discoveryComplete = FALSE;
02374       H323RasPDU pdu;
02375       Request req(SetupGatekeeperRequest(pdu), pdu);
02376       
02377       if (H225_RAS::MakeRequest(req)) {
02378         requestMutex.Signal(); // avoid deadlock...
02379         if (RegistrationRequest(autoReregister)) {
02380           altInfo->registrationState = AlternateInfo::IsRegistered;
02381           // The wanted registration is done, we can return
02382           if (request.requestPDU.GetChoice().GetTag() == H225_RasMessage::e_registrationRequest) {
02383             if (!alternatePermanent)
02384               Connect(tempAddr,tempIdentifier);
02385             return TRUE;
02386           }
02387         }
02388         requestMutex.Wait();
02389       }
02390     }
02391   }
02392 }
02393         
02394 
02395 H323Gatekeeper::AlternateInfo::AlternateInfo(const H225_AlternateGK & alt)
02396   : rasAddress(alt.m_rasAddress),
02397     gatekeeperIdentifier(alt.m_gatekeeperIdentifier.GetValue()),
02398     priority(alt.m_priority)
02399 {
02400   registrationState = alt.m_needToRegister ? NeedToRegister : NoRegistrationNeeded;
02401 }
02402 
02403 
02404 H323Gatekeeper::AlternateInfo::~AlternateInfo ()
02405 {
02406 
02407 }
02408 
02409 
02410 PObject::Comparison H323Gatekeeper::AlternateInfo::Compare(const PObject & obj)
02411 {
02412   PAssert(PIsDescendant(&obj, H323Gatekeeper), PInvalidCast);
02413   unsigned otherPriority = ((const AlternateInfo & )obj).priority;
02414   if (priority < otherPriority)
02415     return LessThan;
02416   if (priority > otherPriority)
02417     return GreaterThan;
02418   return EqualTo;
02419 }
02420 
02421 H225_AlternateGK H323Gatekeeper::AlternateInfo::GetAlternate()
02422 {
02423         H225_AlternateGK gk;
02424     rasAddress.SetPDU(gk.m_rasAddress);
02425     gk.m_gatekeeperIdentifier = gatekeeperIdentifier;
02426     gk.m_priority = priority;
02427         gk.m_needToRegister = registrationState;
02428 
02429         return gk;
02430 }
02431 
02432 
02433 void H323Gatekeeper::AlternateInfo::PrintOn(ostream & strm) const
02434 {
02435   if (!gatekeeperIdentifier)
02436     strm << gatekeeperIdentifier << '@';
02437 
02438   strm << rasAddress;
02439 
02440   if (priority > 0)
02441     strm << ";priority=" << priority;
02442 }
02443 
02444 BOOL H323Gatekeeper::OnSendFeatureSet(unsigned pduType, H225_FeatureSet & feats) const
02445 {
02446 #ifdef H323_H460
02447     return features.SendFeature(pduType, feats);
02448 #else
02449     return endpoint.OnSendFeatureSet(pduType, feats);
02450 #endif
02451 }
02452 
02453 void H323Gatekeeper::OnReceiveFeatureSet(unsigned pduType, const H225_FeatureSet & feats) const
02454 {
02455 #ifdef H323_H460
02456     features.ReceiveFeature(pduType, feats);
02457 #else
02458     endpoint.OnReceiveFeatureSet(pduType, feats);
02459 #endif
02460 }
02461 

Generated on Thu Oct 25 13:42:43 2007 for h323plus by  doxygen 1.5.2