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

00001 /*
00002  * gkserver.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  * This code was based on original code from OpenGate of Egoboo Ltd. thanks
00025  * to Ashley Unitt for his efforts.
00026  *
00027  * Contributor(s): ______________________________________.
00028  *
00029  * $Log: gkserver.cxx,v $
00030  * Revision 1.1  2007/08/06 20:51:05  shorne
00031  * First commit of h323plus
00032  *
00033  * Revision 1.171  2006/01/26 03:33:19  shorne
00034  * Added TranslateTCPPort
00035  *
00036  * Revision 1.170  2005/01/03 06:25:54  csoutheren
00037  * Added extensive support for disabling code modules at compile time
00038  *
00039  * Revision 1.169  2004/12/14 06:22:21  csoutheren
00040  * More OSP implementation
00041  *
00042  * Revision 1.168  2004/12/08 02:21:26  csoutheren
00043  * Fix spelling mistake
00044  *
00045  * Revision 1.167  2004/11/25 07:38:58  csoutheren
00046  * Ensured that external TCP address translation is performed when using STUN to handle UDP
00047  *
00048  * Revision 1.166  2004/09/03 01:06:10  csoutheren
00049  * Added initial hooks for H.460 GEF
00050  * Thanks to Simon Horne and ISVO (Asia) Pte Ltd. for this contribution
00051  *
00052  * Revision 1.165  2004/08/03 07:00:13  csoutheren
00053  * Added isGKRouted hint to TranslateAliasAddress as this is needed for the reply ACF
00054  *
00055  * Revision 1.164  2004/05/05 14:11:17  csoutheren
00056  * Fixed problems with AccessRequest returning wildcards
00057  *
00058  * Revision 1.163  2004/04/24 23:58:04  rjongbloed
00059  * Fixed GCC 3.4 warning about PAssertNULL
00060  *
00061  * Revision 1.162  2004/04/21 04:52:12  csoutheren
00062  * Fixed problem wil using the incorrect call for AddCall
00063  *
00064  * Revision 1.161  2004/04/21 01:39:05  csoutheren
00065  * Added new overrides to GatekeeperServer to provide virtuals when calls and endpoints are created and destroyed
00066  *
00067  * Revision 1.160  2004/04/15 07:43:37  csoutheren
00068  * Allow gatekeeper to make a decision on multiple alias registrations for each registration
00069  *
00070  * Revision 1.159  2004/04/14 01:41:59  csoutheren
00071  * Added access to endpoint information for GetUserPassword
00072  *
00073  * Revision 1.157  2004/04/03 08:28:06  csoutheren
00074  * Remove pseudo-RTTI and replaced with real RTTI
00075  *
00076  * Revision 1.156  2004/04/01 04:44:15  csoutheren
00077  * Corrected sense of the check for descriptor translation
00078  *
00079  * Revision 1.155  2004/03/31 07:16:22  csoutheren
00080  * Added virtual to provide access to H.501 descriptor sent by GK
00081  *
00082  * Revision 1.154  2004/02/15 03:36:31  rjongbloed
00083  * Fixed bug in removing prefixes, plus added ability to have multiple endpoints
00084  *   with the same profix, thanks Rossano Ravelli
00085  *
00086  * Revision 1.153  2004/02/07 11:44:03  rjongbloed
00087  * Fixed deadlocks caused under high load by failure to check locking
00088  *   success. Also added functions to find destination endpoint.
00089  *   Thanks Federico Pinna and the gang at Reitek S.p.A.
00090  *
00091  * Revision 1.152  2004/02/04 09:40:13  rjongbloed
00092  * Fixed innovaphone gatekeeper compatibility, thanks Rossano Ravelli
00093  *
00094  * Revision 1.151  2003/12/24 06:35:25  csoutheren
00095  * Fixed problem with NAT endpoints and GRQs
00096  * Added TranslateAliasAddress on H323GatekeeperCall
00097  *
00098  * Revision 1.150  2003/12/11 05:41:00  csoutheren
00099  * Added storage of H.225 version in endpoint structure
00100  * Disabled sending RIPs to endpoints that cannot handle them
00101  *
00102  * Revision 1.149  2003/12/11 02:18:52  csoutheren
00103  * More fixes for NM deregister problems. Seems to be fixed now :)
00104  *
00105  * Revision 1.148  2003/12/09 06:56:53  csoutheren
00106  * Fixed unbalanced record lock
00107  *
00108  * Revision 1.147  2003/12/09 00:59:19  csoutheren
00109  * Fixed problem with endpoints deregistering
00110  *
00111  * Revision 1.146  2003/05/05 08:28:25  craigs
00112  * Fixed lastUpdate time in descriptors
00113  *
00114  * Revision 1.145  2003/05/01 01:44:36  robertj
00115  * Fixed missing authentication check on lightweight RRQs.
00116  *
00117  * Revision 1.144  2003/04/30 07:51:57  robertj
00118  * Fixed correct setting of reply authenticators, mus use ancestor writePDU.
00119  *
00120  * Revision 1.143  2003/04/30 07:27:19  robertj
00121  * Fixed setting of alternate security ID only if have one.
00122  *
00123  * Revision 1.142  2003/04/30 00:28:54  robertj
00124  * Redesigned the alternate credentials in ARQ system as old implementation
00125  *   was fraught with concurrency issues, most importantly it can cause false
00126  *   detection of replay attacks taking out an endpoint completely.
00127  *
00128  * Revision 1.141  2003/04/10 09:42:48  robertj
00129  * Added some more functions for converting to alias addresses.
00130  *
00131  * Revision 1.140  2003/04/10 07:47:57  robertj
00132  * Added endpoint type to peer element add descriptor.
00133  *
00134  * Revision 1.139  2003/04/09 10:46:39  craigs
00135  * Updated for changed to peer element
00136  *
00137  * Revision 1.138  2003/04/09 03:08:10  robertj
00138  * Fixed race condition in shutting down transactor (pure virtual call)
00139  *
00140  * Revision 1.137  2003/04/08 02:31:02  robertj
00141  * Fixed setting of call member variable (dstHost) outside of mutex.
00142  *
00143  * Revision 1.136  2003/04/03 05:21:11  robertj
00144  * Fixed updating aliases for look up of locally registered ep.
00145  *
00146  * Revision 1.135  2003/04/02 06:58:14  robertj
00147  * Added support for (optional) duplicate aliases in gatekeeper server, necessitating
00148  *   the removal of AddAlias and RemoveAlias functions.
00149  *
00150  * Revision 1.134  2003/04/02 06:08:00  robertj
00151  * Added H.323 Annex G Peer Element support to gatekeeper server.
00152  *
00153  * Revision 1.133  2003/04/01 07:31:45  robertj
00154  * Added function to translate alias into alias list and transport to make
00155  *   use of full information returned by peer element.
00156  *
00157  * Revision 1.132  2003/04/01 05:59:33  robertj
00158  * Fixed H.501 transaction code setting members for m_common PDU part.
00159  *
00160  * Revision 1.131  2003/04/01 04:47:54  robertj
00161  * Abstracted H.225 RAS transaction processing (RIP and secondary thread) in
00162  *   server environment for use by H.501 peer elements.
00163  *
00164  * Revision 1.130  2003/03/25 02:30:09  robertj
00165  * Additional tracing
00166  *
00167  * Revision 1.129  2003/03/17 22:51:10  craigs
00168  * Improvided useability of AddAlias and RemoveAlias
00169  *
00170  * Revision 1.128  2003/03/04 05:28:20  robertj
00171  * Added statistics for rejected registrations and call admissions.
00172  *
00173  * Revision 1.127  2003/03/04 01:29:03  robertj
00174  * Fixed rare bandwidth leak in call processing.
00175  *
00176  * Revision 1.126  2003/03/03 06:59:53  robertj
00177  * Fixed call SetBandwidth function so adjusts global bandwidth as well.
00178  *
00179  * Revision 1.125  2003/03/03 06:53:15  robertj
00180  * Fixed incorrect adjustment of bandwidth on BRQ if not enough for request.
00181  *
00182  * Revision 1.124  2003/02/28 05:09:19  robertj
00183  * Added trace of bandwidth allocation.
00184  *
00185  * Revision 1.123  2003/02/21 05:25:45  craigs
00186  * Abstracted out underlying transports for use with peerelements
00187  *
00188  * Revision 1.122  2003/02/11 04:50:01  robertj
00189  * Added missing gatekeeper identifiers in URQ and DRQ.
00190  *
00191  * Revision 1.121  2003/02/06 06:46:25  robertj
00192  * Changed to ignore srcCallSignalAddress if ep is flagegd as behind NAT.
00193  *
00194  * Revision 1.120  2003/02/06 04:47:25  robertj
00195  * Changes to help with endpoints behind NAT.
00196  *
00197  * Revision 1.119  2003/02/04 23:08:34  robertj
00198  * Fixed partial search for endpoint by alias so must match the partial at the
00199  *   begining of the endpoints alias name, preventing return of incorrect ep.
00200  *
00201  * Revision 1.118  2003/02/03 03:58:10  robertj
00202  * Fixed use of local password database with ep's that have multiple aliases.
00203  *
00204  * Revision 1.117  2003/02/03 00:47:12  robertj
00205  * Changed setting of alerting and connect times so if clock on client is early
00206  *   the gk server uses its own current time.
00207  *
00208  * Revision 1.116  2003/02/03 00:13:20  robertj
00209  * Fixed problem with Cisco non standard connect time, thanks Francisco Olarte Sanz
00210  *
00211  * Revision 1.115  2003/02/01 13:31:21  robertj
00212  * Changes to support CAT authentication in RAS.
00213  *
00214  * Revision 1.114  2003/01/27 23:17:28  robertj
00215  * Fixed use of alternate credentials in ARQ
00216  *
00217  * Revision 1.113  2003/01/26 04:48:58  robertj
00218  * Fixed LRQ so returns registered ep first and fills in rasAddress in LCF as
00219  *   best it can under various scenarios.
00220  * Fixed translate alias so a DN is not thought to be an IP address.
00221  *
00222  * Revision 1.112  2003/01/25 05:41:45  robertj
00223  * Changed LRQ handling to use translate alias to address function.
00224  *
00225  * Revision 1.111  2003/01/16 00:55:32  robertj
00226  * Fixed crash if reject ARQ early in processing.
00227  *
00228  * Revision 1.110  2003/01/08 04:40:34  robertj
00229  * Added more debug tracing for H.235 authenticators.
00230  *
00231  * Revision 1.109  2002/12/19 06:20:56  robertj
00232  * Rearranged crypto check to be at the end of the H323RegisteredEndPoint
00233  *   version of OnAdmission() to make it easier for overrides to do something
00234  *   with teh endpoint if it fails the security,
00235  *
00236  * Revision 1.108  2002/12/19 01:01:24  robertj
00237  * Fixed missing read/write lock when doing IRR update on call state.
00238  *
00239  * Revision 1.107  2002/12/17 01:25:26  robertj
00240  * Added call backs on gk server when ep indicates alerting or connect.
00241  *
00242  * Revision 1.106  2002/12/13 03:59:32  robertj
00243  * Fixed incorrect field identifier used in including optional field for
00244  *   balance in ARJ
00245  *
00246  * Revision 1.105  2002/12/12 03:50:42  robertj
00247  * Fixed incorrect condition for detecting suportset RRQ
00248  *
00249  * Revision 1.104  2002/12/02 07:42:35  robertj
00250  * Fixed GNU warning
00251  *
00252  * Revision 1.103  2002/12/02 06:44:21  robertj
00253  * Changed to allow for an already registered endpoint to send a full RRQ to add
00254  *   but not subtract aliases or signalling addresses. If tries to subtract then
00255  *   will reject the RRQ and de-register the endpoint.
00256  *
00257  * Revision 1.102  2002/11/28 05:46:20  robertj
00258  * Fixed bug so can set total bandwidth while calls are in progress.
00259  *
00260  * Revision 1.101  2002/11/28 04:41:48  robertj
00261  * Added support for RAS ServiceControlIndication command.
00262  *
00263  * Revision 1.100  2002/11/27 06:54:56  robertj
00264  * Added Service Control Session management as per Annex K/H.323 via RAS
00265  *   only at this stage.
00266  * Added H.248 ASN and very primitive infrastructure for linking into the
00267  *   Service Control Session management system.
00268  * Added basic infrastructure for Annex K/H.323 HTTP transport system.
00269  * Added Call Credit Service Control to display account balances.
00270  *
00271  * Revision 1.99  2002/11/25 03:27:28  robertj
00272  * Added sanity checking to the alerting, connected and end call times may
00273  *   receive from endpoint, don't accept if in future or before call started!
00274  *
00275  * Revision 1.98  2002/11/21 06:40:00  robertj
00276  * Changed promiscuous mode to be three way. Fixes race condition in gkserver
00277  *   which can cause crashes or more PDUs to be sent to the wrong place.
00278  *
00279  * Revision 1.97  2002/11/19 01:50:35  robertj
00280  * Added expiditing of alerting and connect time statistics if ep can do UUIEs
00281  *
00282  * Revision 1.96  2002/11/18 23:41:25  robertj
00283  * Changed to use the H323EndPoint::CreateAuthenticators() function, we
00284  *   should use only one.
00285  *
00286  * Revision 1.95  2002/11/15 03:26:40  robertj
00287  * Fixed crash when removing alias in URQ and it isn't registered with it.
00288  *
00289  * Revision 1.94  2002/11/12 11:36:07  robertj
00290  * Added function to find endpoint by partial alias.
00291  * Optimised endpoint "indexes" to use sorted lists instead of dictionaries.
00292  *
00293  * Revision 1.93  2002/11/11 07:20:12  robertj
00294  * Minor clean up of API for doing RAS requests suing authentication.
00295  *
00296  * Revision 1.92  2002/11/10 08:10:43  robertj
00297  * Moved constants for "well known" ports to better place (OPAL change).
00298  *
00299  * Revision 1.91  2002/11/05 05:56:09  robertj
00300  * Super slight optimisation!
00301  *
00302  * Revision 1.90  2002/11/04 23:48:48  robertj
00303  * Fixed memory leak on ep unregistration, pointed out by Ravelli Rossano.
00304  *
00305  * Revision 1.89  2002/10/29 00:14:08  robertj
00306  * Improved setting of usage info, included getting it from BRQ etc.
00307  *
00308  * Revision 1.88  2002/10/24 07:04:41  robertj
00309  * Changed use of translate address so can see previous dstHost value before
00310  *   it might change it.
00311  *
00312  * Revision 1.87  2002/10/24 05:54:18  robertj
00313  * Improved looking up alias as DNS host and port.
00314  *
00315  * Revision 1.86  2002/10/21 01:20:36  robertj
00316  * Moved setting of aliases in RCF to after OnFullRegistration() returns so an
00317  *   application can alter the aliases an endpoint registers as.
00318  *
00319  * Revision 1.85  2002/10/21 00:55:46  robertj
00320  * Added function to unregister an endpoint via user interface.
00321  * Added reason code to call disengage.
00322  * Added ability to find call by a description string.
00323  * Fixed LCF having RAS address in it.
00324  *
00325  * Revision 1.84  2002/10/17 05:28:11  robertj
00326  * Supported some dumb old version endpoints that could not ignore fields
00327  *   that they don't understand.
00328  *
00329  * Revision 1.83  2002/10/17 02:20:56  robertj
00330  * Fixed problem with older clients sending unsolicited IRR's using the
00331  *   seqnum==1 technique instead of explicit flag.
00332  *
00333  * Revision 1.82  2002/10/16 07:29:41  robertj
00334  * Added support for endpoints that do not support RRQ timeToLive parameter,
00335  *   will actively go see if ep is there using IRQ before expiring the ep.
00336  *
00337  * Revision 1.81  2002/10/16 01:53:09  robertj
00338  * Removed trace on starting slow PDU handler thread, cannot use pointer
00339  *   returned if is auto-delete thread as it can go out of scope any time.
00340  *
00341  * Revision 1.80  2002/10/16 01:00:02  robertj
00342  * Fixed gk server so can listen on localhost if listening on INADDR_ANY.
00343  *
00344  * Revision 1.79  2002/10/10 05:32:36  robertj
00345  * Minor changes for Tornado 2 compiler compatibility, thanks Martijn Roest
00346  *
00347  * Revision 1.78  2002/10/09 08:01:01  robertj
00348  * Changed registration so get URJ if calls are in progress.
00349  * Fixed call of registered eps OnRegistration() to before ep is removed.
00350  *
00351  * Revision 1.77  2002/10/02 09:33:24  robertj
00352  * Previous fix had to be done in two places.
00353  *
00354  * Revision 1.76  2002/10/01 08:27:52  robertj
00355  * Fixed (benign) race condition between client and server both wanting to do
00356  *   a DRQ of a call at the same time. Caused an Assert, but no crash.
00357  *
00358  * Revision 1.75  2002/10/01 06:40:52  robertj
00359  * Removed GNU compiler warning
00360  *
00361  * Revision 1.74  2002/10/01 02:44:58  robertj
00362  * Fixed problem where a non lightweight RRQ with endpointIdentifer does not
00363  *   overwrite old H323RegisteredEndpoint instance, but just updates it
00364  *   preventing loss of calls if ep is just changing things like aliases etc.
00365  *
00366  * Revision 1.73  2002/09/29 23:39:30  craigs
00367  * Rearranged expression to avoid MSVC compiler compiler internal error
00368  *
00369  * Revision 1.72  2002/09/25 14:33:05  robertj
00370  * Added special code for innovaphone's broken behaviour with unsolicited IRR's
00371  *   having no perCallInfo. For them this apparently means "all calls ok".
00372  *
00373  * Revision 1.71  2002/09/24 08:03:00  robertj
00374  * Added H.225 RAS protocol version number to registered endpoint structure.
00375  *
00376  * Revision 1.70  2002/09/20 05:39:22  robertj
00377  * Added Cisco non-standard version of connect time indication in IRR.
00378  *
00379  * Revision 1.69  2002/09/20 02:40:08  robertj
00380  * Fixed compatibility with buggy Cisco's that do not indicate the direction
00381  *   of the call in the IRR perCallInfo structure.
00382  *
00383  * Revision 1.68  2002/09/19 09:13:27  robertj
00384  * Fixed problem with making (and assuring with multi-threading) IRQ and DRQ
00385  *   requests are sent to the correct endpoint address, thanks Martijn Roest.
00386  *
00387  * Revision 1.67  2002/08/29 07:57:09  robertj
00388  * Added some statistics to gatekeeper server.
00389  *
00390  * Revision 1.66  2002/08/29 06:57:26  robertj
00391  * Removed redundent thread member variable from request info.
00392  * Added optimisation in does not need to look up endpoint on slow response
00393  *   sub-thread if already have looked it up duing the first pass.
00394  * Added optimisation and possible thread mutex issue in setting authenticator
00395  *   remote and local user names in RRQ, only do on full reg not keepAlive.
00396  *
00397  * Revision 1.65  2002/08/16 02:43:18  robertj
00398  * Fixed bug where call can exist in database even though was rejected.
00399  *
00400  * Revision 1.64  2002/08/16 02:32:58  robertj
00401  * Fixed possible deadlock in heartbeat
00402  *
00403  * Revision 1.63  2002/08/16 02:30:25  robertj
00404  * Fixed call heartbeat so if IRQ succeeds but indicates it does not know the
00405  *   call then the call in the gk is removed.
00406  *
00407  * Revision 1.62  2002/08/14 02:04:00  robertj
00408  * Added trace log for heartbeat timeout on call.
00409  *
00410  * Revision 1.61  2002/08/12 08:12:45  robertj
00411  * Added extra hint to help with ARQ using separate credentials from RRQ.
00412  *
00413  * Revision 1.60  2002/08/12 05:38:24  robertj
00414  * Changes to the RAS subsystem to support ability to make requests to client
00415  *   from gkserver without causing bottlenecks and race conditions.
00416  *
00417  * Revision 1.59  2002/08/11 23:20:42  robertj
00418  * Fixed GNU compatibility error
00419  *
00420  * Revision 1.58  2002/08/05 10:03:47  robertj
00421  * Cosmetic changes to normalise the usage of pragma interface/implementation.
00422  *
00423  * Revision 1.57  2002/08/05 05:17:41  robertj
00424  * Fairly major modifications to support different authentication credentials
00425  *   in ARQ to the logged in ones on RRQ. For both client and server.
00426  * Various other H.235 authentication bugs and anomalies fixed on the way.
00427  *
00428  * Revision 1.56  2002/07/25 05:22:22  robertj
00429  * Fixed possible race condition where call is removed between first ARQ
00430  *   processing and slow PDU handler thread starting!
00431  *
00432  * Revision 1.55  2002/07/24 02:57:44  robertj
00433  * Assured all calls for an ep are removed if ep is removed due to timeout
00434  *   rather than via an unregister.
00435  * Added tolerance to lightweight RRQ timer.
00436  * Added several missing mutex calls.
00437  *
00438  * Revision 1.54  2002/07/19 00:31:13  robertj
00439  * Allowed a zero IRR rate time to disable IRR hearbeat checks.
00440  *
00441  * Revision 1.53  2002/07/17 04:42:14  robertj
00442  * Fixed filling in callSignallingAddress in RCF
00443  *
00444  * Revision 1.52  2002/07/17 04:01:00  robertj
00445  * Fixed RRJ reason of duplicateAlias having correct choice field in PDU.
00446  *
00447  * Revision 1.51  2002/07/16 13:47:56  robertj
00448  * Added missing lock when removing call from endpoint.
00449  * Fixed setting of credentials when sending Disengage.
00450  * improved some logging messages.
00451  *
00452  * Revision 1.50  2002/07/16 09:20:56  robertj
00453  * Fixed bug where call was not removed from gk when Disengage called.
00454  * Fixed correct setting of unsolicited flag if get IRR from old v2 ep.
00455  *
00456  * Revision 1.49  2002/07/11 09:37:00  robertj
00457  * Added support for early versions of unsolicited IRR.
00458  * Fixed fail safe IRQ if does not receive unsolicited IRR in time.
00459  * Fixed removal of call if IRR failure indicates call is no longer valid.
00460  *
00461  * Revision 1.48  2002/07/11 07:01:41  robertj
00462  * Added Disengage() function to force call drop from gk server.
00463  * Added InfoRequest() function to force client to send an IRR.
00464  * Added ability to automatically clear calls if do not get IRR for it.
00465  *
00466  * Revision 1.47  2002/07/10 01:09:21  robertj
00467  * Fixed bug where did not use URQ endpoint id for look up.
00468  *
00469  * Revision 1.46  2002/07/10 00:05:47  robertj
00470  * Fixed bug where doing a URQ does not actually remove the endpoint.
00471  *
00472  * Revision 1.45  2002/07/09 00:16:26  robertj
00473  * Fixed incorrect allocation of bandwidth in ARQ, thanks Dave Giffin
00474  *
00475  * Revision 1.44  2002/06/24 07:01:05  robertj
00476  * Fixed correct adding of call to endpoint structure, only if call confirmed.
00477  *
00478  * Revision 1.43  2002/06/21 02:52:47  robertj
00479  * Fixed problem with double checking H.235 hashing, this causes failure as
00480  *   the authenticator thinks it is a replay attack.
00481  *
00482  * Revision 1.42  2002/06/19 05:03:11  robertj
00483  * Changed gk code to allow for H.235 security on an endpoint by endpoint basis.
00484  *
00485  * Revision 1.41  2002/06/12 03:55:21  robertj
00486  * Added function to add/remove multiple listeners in one go comparing against
00487  *   what is already running so does not interrupt unchanged listeners.
00488  *
00489  * Revision 1.40  2002/06/07 08:12:38  robertj
00490  * Added check to reject ARQ if does not contain a call identifier.
00491  *
00492  * Revision 1.39  2002/06/07 06:19:21  robertj
00493  * Fixed GNU warning
00494  *
00495  * Revision 1.38  2002/05/29 00:03:19  robertj
00496  * Fixed unsolicited IRR support in gk client and server,
00497  *   including support for IACK and INAK.
00498  *
00499  * Revision 1.37  2002/05/17 03:41:46  robertj
00500  * Fixed problems with H.235 authentication on RAS for server and client.
00501  *
00502  * Revision 1.36  2002/05/09 02:53:20  robertj
00503  * Fixed some problems with setting host/alias field in call on ARQ
00504  *
00505  * Revision 1.35  2002/05/08 02:06:07  robertj
00506  * Fixed failure to remove call if is rejected on slow reply.
00507  * Fixed overwriting of application infor on lightweight RRQ.
00508  * Fixed inclusion of adjusted aliases in RCF.
00509  *
00510  * Revision 1.34  2002/05/07 06:25:20  robertj
00511  * Fixed GNU compiler compatibility.
00512  *
00513  * Revision 1.33  2002/05/07 06:15:54  robertj
00514  * Changed ARQ processing so rejects multiple ARQ with same call id, not this
00515  *   does NOT include the transport level retries (based on sequence number).
00516  *
00517  * Revision 1.32  2002/05/07 03:18:15  robertj
00518  * Added application info (name/version etc) into registered endpoint data.
00519  *
00520  * Revision 1.31  2002/05/06 09:05:01  craigs
00521  * Fixed compile problem on Linux
00522  *
00523  * Revision 1.30  2002/05/06 00:56:41  robertj
00524  * Sizeable rewrite of gatekeeper server code to make more bulletproof against
00525  *   multithreaded operation. Especially when using slow response/RIP feature.
00526  * Also changed the call indexing to use call id and direction as key.
00527  *
00528  * Revision 1.29  2002/04/09 02:34:14  robertj
00529  * Fixed problem with duplicate entries in endpoint list if ARQ gets retried,
00530  *   thanks Horacio J. Peņa
00531  *
00532  * Revision 1.28  2002/03/06 02:51:31  robertj
00533  * Fixed race condition when starting slow server response thread.
00534  *
00535  * Revision 1.27  2002/03/06 02:01:26  craigs
00536  * Add log message when SlowHandler thread started
00537  *
00538  * Revision 1.26  2002/03/05 03:42:40  robertj
00539  * Fixed calling of endpoints OnUnregister() function, thanks Francisco Olarte Sanz
00540  *
00541  * Revision 1.25  2002/03/04 07:57:57  craigs
00542  * Changed log level of ageing message
00543  * Fixed assert caused by accessing byIdentifier with integer
00544  *
00545  * Revision 1.24  2002/03/03 21:34:54  robertj
00546  * Added gatekeeper monitor thread.
00547  *
00548  * Revision 1.23  2002/03/02 05:59:01  robertj
00549  * Fixed possible bandwidth leak (thanks Francisco Olarte Sanz) and in
00550  *   the process added OnBandwidth function to H323GatekeeperCall class.
00551  *
00552  * Revision 1.22  2002/03/01 04:09:35  robertj
00553  * Fixed problems with keeping track of calls. Calls are now indexed by call-id
00554  *   alone and maintain both endpoints of call in its structure. Fixes problem
00555  *   with calls form an endpoint to itself, and having two objects being tracked
00556  *   where there is really only one call.
00557  *
00558  * Revision 1.21  2002/02/25 10:26:39  robertj
00559  * Added ARQ with zero bandwidth as a request for a default, thanks Federico Pinna
00560  *
00561  * Revision 1.20  2002/02/25 10:16:21  robertj
00562  * Fixed bad mistake in getting new aliases from ARQ, thanks HoraPe
00563  *
00564  * Revision 1.19  2002/02/25 09:49:02  robertj
00565  * Fixed possible "bandwidth leak" on ARQ, thanks Francisco Olarte Sanz
00566  *
00567  * Revision 1.18  2002/02/11 05:19:21  robertj
00568  * Allowed for multiple ARQ requests for same call ID. Reuses existing call
00569  *   object and sends another ACF.
00570  *
00571  * Revision 1.17  2002/02/04 05:21:27  robertj
00572  * Lots of changes to fix multithreaded slow response code (RIP).
00573  * Fixed problem with having two entries for same call in call list.
00574  *
00575  * Revision 1.16  2002/01/31 06:45:44  robertj
00576  * Added more checking for invalid list processing in calls database.
00577  *
00578  * Revision 1.15  2002/01/30 05:07:54  robertj
00579  * Some robustness changes, temporarily removed threads in RIP.
00580  *
00581  * Revision 1.14  2001/12/15 10:10:48  robertj
00582  * GCC compatibility
00583  *
00584  * Revision 1.13  2001/12/15 08:09:08  robertj
00585  * Added alerting, connect and end of call times to be sent to RAS server.
00586  *
00587  * Revision 1.12  2001/12/14 06:41:17  robertj
00588  * Added call end reason codes in DisengageRequest for GK server use.
00589  *
00590  * Revision 1.11  2001/12/13 11:08:45  robertj
00591  * Significant changes to support slow request handling, automatically sending
00592  *   RIP and spawning thread to handle time consuming operation.
00593  *
00594  * Revision 1.10  2001/12/06 06:44:42  robertj
00595  * Removed "Win32 SSL xxx" build configurations in favour of system
00596  *   environment variables to select optional libraries.
00597  *
00598  * Revision 1.9  2001/11/21 13:35:23  craigs
00599  * Removed deadlock with empty registered endpoint list
00600  *
00601  * Revision 1.8  2001/11/19 06:56:44  robertj
00602  * Added prefix strings for gateways registered with this gk, thanks Mikael Stolt
00603  *
00604  * Revision 1.7  2001/09/18 10:06:54  robertj
00605  * Added trace for if RRJ on security because user has no password.
00606  *
00607  * Revision 1.6  2001/09/13 01:15:20  robertj
00608  * Added flag to H235Authenticator to determine if gkid and epid is to be
00609  *   automatically set as the crypto token remote id and local id.
00610  *
00611  * Revision 1.5  2001/08/10 11:03:52  robertj
00612  * Major changes to H.235 support in RAS to support server.
00613  *
00614  * Revision 1.4  2001/08/06 07:44:55  robertj
00615  * Fixed problems with building without SSL
00616  *
00617  * Revision 1.3  2001/08/06 03:18:38  robertj
00618  * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
00619  * Improved access to H.235 secure RAS functionality.
00620  * Changes to H.323 secure RAS contexts to help use with gk server.
00621  *
00622  * Revision 1.2  2001/07/24 10:12:33  craigs
00623  * Fixed problem with admission requests not having src signalling addresses
00624  *
00625  * Revision 1.1  2001/07/24 02:31:07  robertj
00626  * Added gatekeeper RAS protocol server classes.
00627  *
00628  */
00629 
00630 #include <ptlib.h>
00631 
00632 #ifdef __GNUC__
00633 #pragma implementation "gkserver.h"
00634 #endif
00635 
00636 #include "gkserver.h"
00637 
00638 #ifdef H323_H501
00639 #include "peclient.h"
00640 #endif
00641 
00642 const char AnswerCallStr[] = "-Answer";
00643 const char OriginateCallStr[] = "-Originate";
00644 
00645 
00646 #define new PNEW
00647 
00648 
00650 
00651 H323GatekeeperRequest::H323GatekeeperRequest(H323GatekeeperListener & ras,
00652                                              const H323RasPDU & pdu)
00653   : H323Transaction(ras, pdu, new H323RasPDU, new H323RasPDU),
00654     rasChannel(ras)
00655 {
00656 }
00657 
00658 
00659 H323TransactionPDU * H323GatekeeperRequest::CreateRIP(unsigned sequenceNumber,
00660                                                       unsigned delay) const
00661 {
00662   H323RasPDU * pdu = new H323RasPDU;
00663   pdu->BuildRequestInProgress(sequenceNumber, delay);
00664   return pdu;
00665 }
00666 
00667 
00668 BOOL H323GatekeeperRequest::WritePDU(H323TransactionPDU & pdu)
00669 {
00670   PTRACE_BLOCK("H323GatekeeperRequest::WritePDU");
00671 
00672   if (endpoint != NULL)
00673     replyAddresses = endpoint->GetRASAddresses();
00674 
00675   return H323Transaction::WritePDU(pdu);
00676 }
00677 
00678 
00679 BOOL H323GatekeeperRequest::CheckGatekeeperIdentifier()
00680 {
00681   PString pduGkid = GetGatekeeperIdentifier();
00682   if (pduGkid.IsEmpty()) // Not present in PDU
00683     return TRUE;
00684 
00685   PString rasGkid = rasChannel.GetIdentifier();
00686 
00687   // If it is present it has to be correct!
00688   if (pduGkid == rasGkid)
00689     return TRUE;
00690 
00691   SetRejectReason(GetGatekeeperRejectTag());
00692   PTRACE(2, "RAS\t" << GetName() << " rejected, has different identifier,"
00693             " got \"" << pduGkid << "\", should be \"" << rasGkid << '"');
00694   return FALSE;
00695 }
00696 
00697 
00698 BOOL H323GatekeeperRequest::GetRegisteredEndPoint()
00699 {
00700   if (endpoint != NULL) {
00701     PTRACE(4, "RAS\tAlready located endpoint: " << *endpoint);
00702     return TRUE;
00703   }
00704 
00705   PString id = GetEndpointIdentifier();
00706   endpoint = rasChannel.GetGatekeeper().FindEndPointByIdentifier(id);
00707   if (endpoint != NULL) {
00708     PTRACE(4, "RAS\tLocated endpoint: " << *endpoint);
00709     canSendRIP = endpoint->CanReceiveRIP();
00710     return TRUE;
00711   }
00712 
00713   SetRejectReason(GetRegisteredEndPointRejectTag());
00714   PTRACE(2, "RAS\t" << GetName() << " rejected,"
00715             " \"" << id << "\" not registered");
00716   return FALSE;
00717 }
00718 
00719 
00720 BOOL H323GatekeeperRequest::CheckCryptoTokens()
00721 {
00722   if (authenticatorResult == H235Authenticator::e_Disabled)
00723     return H323Transaction::CheckCryptoTokens(endpoint->GetAuthenticators());
00724 
00725   return authenticatorResult == H235Authenticator::e_OK;
00726 }
00727 
00728 
00730 
00731 H323GatekeeperGRQ::H323GatekeeperGRQ(H323GatekeeperListener & rasChannel,
00732                                      const H323RasPDU & pdu)
00733   : H323GatekeeperRequest(rasChannel, pdu),
00734     grq((H225_GatekeeperRequest &)request->GetChoice().GetObject()),
00735     gcf(((H323RasPDU &)confirm->GetPDU()).BuildGatekeeperConfirm(grq.m_requestSeqNum)),
00736     grj(((H323RasPDU &)reject->GetPDU()).BuildGatekeeperReject(grq.m_requestSeqNum,
00737                                           H225_GatekeeperRejectReason::e_terminalExcluded))
00738 {
00739   // Check the return address, if not the same side of a NAT firewall, then
00740   // just use the physical reply address already set by ancestor.
00741   H323TransportAddress rasAddress = grq.m_rasAddress;
00742   H323EndPoint & ep = rasChannel.GetEndPoint();
00743   PIPSocket::Address senderIP, rasIP;
00744 
00745   if (rasChannel.GetTransport().IsCompatibleTransport(grq.m_rasAddress) &&
00746        (!replyAddresses[0].GetIpAddress(senderIP) ||
00747         !rasAddress.GetIpAddress(rasIP) ||
00748         ep.IsLocalAddress(senderIP) == ep.IsLocalAddress(rasIP))) {
00749     PTRACE(4, "RAS\tFound suitable RAS address in GRQ: " << rasAddress);
00750     replyAddresses[0] = rasAddress;
00751   }
00752   else {
00753     isBehindNAT = TRUE;
00754     PTRACE(3, "RAS\tUnsuitable RAS address in GRQ, using " << replyAddresses[0]);
00755   }
00756 }
00757 
00758 
00759 #if PTRACING
00760 const char * H323GatekeeperGRQ::GetName() const
00761 {
00762   return "GRQ";
00763 }
00764 #endif
00765 
00766 
00767 PString H323GatekeeperGRQ::GetGatekeeperIdentifier() const
00768 {
00769   if (grq.HasOptionalField(H225_GatekeeperRequest::e_gatekeeperIdentifier))
00770     return grq.m_gatekeeperIdentifier;
00771 
00772   return PString::Empty();
00773 }
00774 
00775 
00776 unsigned H323GatekeeperGRQ::GetGatekeeperRejectTag() const
00777 {
00778   return H225_GatekeeperRejectReason::e_terminalExcluded;
00779 }
00780 
00781 
00782 PString H323GatekeeperGRQ::GetEndpointIdentifier() const
00783 {
00784   return PString::Empty(); // Dummy, should never be used
00785 }
00786 
00787 
00788 unsigned H323GatekeeperGRQ::GetRegisteredEndPointRejectTag() const
00789 {
00790   return H225_GatekeeperRejectReason::e_terminalExcluded;
00791 }
00792 
00793 
00794 H235Authenticator::ValidationResult H323GatekeeperGRQ::ValidatePDU() const
00795 {
00796   return request->Validate(grq.m_tokens, H225_GatekeeperRequest::e_tokens,
00797                            grq.m_cryptoTokens, H225_GatekeeperRequest::e_cryptoTokens);
00798 }
00799 
00800 
00801 unsigned H323GatekeeperGRQ::GetSecurityRejectTag() const
00802 {
00803   return H225_GatekeeperRejectReason::e_securityDenial;
00804 }
00805 
00806 
00807 void H323GatekeeperGRQ::SetRejectReason(unsigned reasonCode)
00808 {
00809   grj.m_rejectReason.SetTag(reasonCode);
00810 }
00811 
00812 
00813 H323GatekeeperRequest::Response H323GatekeeperGRQ::OnHandlePDU()
00814 {
00815   return rasChannel.OnDiscovery(*this);
00816 }
00817 
00818 
00819 H323GatekeeperRRQ::H323GatekeeperRRQ(H323GatekeeperListener & rasChannel,
00820                                      const H323RasPDU & pdu)
00821   : H323GatekeeperRequest(rasChannel, pdu),
00822     rrq((H225_RegistrationRequest &)request->GetChoice().GetObject()),
00823     rcf(((H323RasPDU &)confirm->GetPDU()).BuildRegistrationConfirm(rrq.m_requestSeqNum)),
00824     rrj(((H323RasPDU &)reject->GetPDU()).BuildRegistrationReject(rrq.m_requestSeqNum))
00825 {
00826   H323EndPoint & ep = rasChannel.GetEndPoint();
00827   PIPSocket::Address senderIP;
00828   BOOL senderIsIP = replyAddresses[0].GetIpAddress(senderIP);
00829   BOOL senderIsLocal = senderIsIP && ep.IsLocalAddress(senderIP);
00830 
00831   H323TransportAddressArray unsuitable;
00832 
00833   BOOL first = TRUE;
00834   PINDEX i;
00835   for (i = 0; i < rrq.m_rasAddress.GetSize(); i++) {
00836     if (rasChannel.GetTransport().IsCompatibleTransport(rrq.m_rasAddress[i])) {
00837       // Check the return address, if not the same side of a NAT firewall, then
00838       // just use the physical reply address already set by ancestor.
00839       H323TransportAddress rasAddress = rrq.m_rasAddress[i];
00840       PIPSocket::Address rasIP;
00841       if (!senderIsIP |
00842           !rasAddress.GetIpAddress(rasIP) ||
00843           senderIsLocal == ep.IsLocalAddress(rasIP)) {
00844         PTRACE(4, "RAS\tFound suitable RAS address in RRQ: " << rasAddress);
00845         if (first)
00846           replyAddresses[0] = rasAddress;
00847         else
00848           replyAddresses.AppendAddress(rasAddress);
00849         first = FALSE;
00850       }
00851       else
00852         unsuitable.AppendAddress(rasAddress);
00853     }
00854   }
00855 
00856   isBehindNAT = first;
00857   PTRACE_IF(3, isBehindNAT,
00858             "RAS\tCould not find suitable RAS address in RRQ, using " << replyAddresses[0]);
00859 
00860   for (i = 0; i < unsuitable.GetSize(); i++)
00861     replyAddresses.AppendAddress(unsuitable[i]);
00862 }
00863 
00864 
00865 #if PTRACING
00866 const char * H323GatekeeperRRQ::GetName() const
00867 {
00868   return "RRQ";
00869 }
00870 #endif
00871 
00872 
00873 PString H323GatekeeperRRQ::GetGatekeeperIdentifier() const
00874 {
00875   if (rrq.HasOptionalField(H225_RegistrationRequest::e_gatekeeperIdentifier))
00876     return rrq.m_gatekeeperIdentifier;
00877 
00878   return PString::Empty();
00879 }
00880 
00881 
00882 unsigned H323GatekeeperRRQ::GetGatekeeperRejectTag() const
00883 {
00884   return H225_RegistrationRejectReason::e_undefinedReason;
00885 }
00886 
00887 
00888 PString H323GatekeeperRRQ::GetEndpointIdentifier() const
00889 {
00890   return rrq.m_endpointIdentifier;
00891 }
00892 
00893 
00894 unsigned H323GatekeeperRRQ::GetRegisteredEndPointRejectTag() const
00895 {
00896   return H225_RegistrationRejectReason::e_fullRegistrationRequired;
00897 }
00898 
00899 
00900 H235Authenticator::ValidationResult H323GatekeeperRRQ::ValidatePDU() const
00901 {
00902   return request->Validate(rrq.m_tokens, H225_RegistrationRequest::e_tokens,
00903                            rrq.m_cryptoTokens, H225_RegistrationRequest::e_cryptoTokens);
00904 }
00905 
00906 
00907 unsigned H323GatekeeperRRQ::GetSecurityRejectTag() const
00908 {
00909   return H225_RegistrationRejectReason::e_securityDenial;
00910 }
00911 
00912 
00913 void H323GatekeeperRRQ::SetRejectReason(unsigned reasonCode)
00914 {
00915   rrj.m_rejectReason.SetTag(reasonCode);
00916 }
00917 
00918 
00919 H323GatekeeperRequest::Response H323GatekeeperRRQ::OnHandlePDU()
00920 {
00921   H323GatekeeperRequest::Response response = rasChannel.OnRegistration(*this);
00922   if (response != Reject)
00923     return response;
00924 
00925   H323GatekeeperServer & server = rasChannel.GetGatekeeper();
00926   server.mutex.Wait();
00927   server.rejectedRegistrations++;
00928   server.mutex.Signal();
00929 
00930   return Reject;
00931 }
00932 
00933 
00934 H323GatekeeperURQ::H323GatekeeperURQ(H323GatekeeperListener & rasChannel,
00935                                      const H323RasPDU & pdu)
00936   : H323GatekeeperRequest(rasChannel, pdu),
00937     urq((H225_UnregistrationRequest &)request->GetChoice().GetObject()),
00938     ucf(((H323RasPDU &)confirm->GetPDU()).BuildUnregistrationConfirm(urq.m_requestSeqNum)),
00939     urj(((H323RasPDU &)reject->GetPDU()).BuildUnregistrationReject(urq.m_requestSeqNum))
00940 {
00941 }
00942 
00943 
00944 #if PTRACING
00945 const char * H323GatekeeperURQ::GetName() const
00946 {
00947   return "URQ";
00948 }
00949 #endif
00950 
00951 
00952 PString H323GatekeeperURQ::GetGatekeeperIdentifier() const
00953 {
00954   if (urq.HasOptionalField(H225_UnregistrationRequest::e_gatekeeperIdentifier))
00955     return urq.m_gatekeeperIdentifier;
00956 
00957   return PString::Empty();
00958 }
00959 
00960 
00961 unsigned H323GatekeeperURQ::GetGatekeeperRejectTag() const
00962 {
00963   return H225_GatekeeperRejectReason::e_terminalExcluded;
00964 }
00965 
00966 
00967 PString H323GatekeeperURQ::GetEndpointIdentifier() const
00968 {
00969   return urq.m_endpointIdentifier;
00970 }
00971 
00972 
00973 unsigned H323GatekeeperURQ::GetRegisteredEndPointRejectTag() const
00974 {
00975   return H225_UnregRejectReason::e_notCurrentlyRegistered;
00976 }
00977 
00978 
00979 H235Authenticator::ValidationResult H323GatekeeperURQ::ValidatePDU() const
00980 {
00981   return request->Validate(urq.m_tokens, H225_UnregistrationRequest::e_tokens,
00982                            urq.m_cryptoTokens, H225_UnregistrationRequest::e_cryptoTokens);
00983 }
00984 
00985 
00986 unsigned H323GatekeeperURQ::GetSecurityRejectTag() const
00987 {
00988   return H225_UnregRejectReason::e_securityDenial;
00989 }
00990 
00991 
00992 void H323GatekeeperURQ::SetRejectReason(unsigned reasonCode)
00993 {
00994   urj.m_rejectReason.SetTag(reasonCode);
00995 }
00996 
00997 
00998 H323GatekeeperRequest::Response H323GatekeeperURQ::OnHandlePDU()
00999 {
01000   return rasChannel.OnUnregistration(*this);
01001 }
01002 
01003 
01004 H323GatekeeperARQ::H323GatekeeperARQ(H323GatekeeperListener & rasChannel,
01005                                      const H323RasPDU & pdu)
01006   : H323GatekeeperRequest(rasChannel, pdu),
01007     arq((H225_AdmissionRequest &)request->GetChoice().GetObject()),
01008     acf(((H323RasPDU &)confirm->GetPDU()).BuildAdmissionConfirm(arq.m_requestSeqNum)),
01009     arj(((H323RasPDU &)reject->GetPDU()).BuildAdmissionReject(arq.m_requestSeqNum))
01010 {
01011 }
01012 
01013 
01014 #if PTRACING
01015 const char * H323GatekeeperARQ::GetName() const
01016 {
01017   return "ARQ";
01018 }
01019 #endif
01020 
01021 
01022 PString H323GatekeeperARQ::GetGatekeeperIdentifier() const
01023 {
01024   if (arq.HasOptionalField(H225_AdmissionRequest::e_gatekeeperIdentifier))
01025     return arq.m_gatekeeperIdentifier;
01026 
01027   return PString::Empty();
01028 }
01029 
01030 
01031 unsigned H323GatekeeperARQ::GetGatekeeperRejectTag() const
01032 {
01033   return H225_AdmissionRejectReason::e_undefinedReason;
01034 }
01035 
01036 
01037 PString H323GatekeeperARQ::GetEndpointIdentifier() const
01038 {
01039   return arq.m_endpointIdentifier;
01040 }
01041 
01042 
01043 unsigned H323GatekeeperARQ::GetRegisteredEndPointRejectTag() const
01044 {
01045   return H225_AdmissionRejectReason::e_callerNotRegistered;
01046 }
01047 
01048 
01049 H235Authenticator::ValidationResult H323GatekeeperARQ::ValidatePDU() const
01050 {
01051   return request->Validate(arq.m_tokens, H225_AdmissionRequest::e_tokens,
01052                            arq.m_cryptoTokens, H225_AdmissionRequest::e_cryptoTokens);
01053 }
01054 
01055 
01056 unsigned H323GatekeeperARQ::GetSecurityRejectTag() const
01057 {
01058   return H225_AdmissionRejectReason::e_securityDenial;
01059 }
01060 
01061 
01062 void H323GatekeeperARQ::SetRejectReason(unsigned reasonCode)
01063 {
01064   arj.m_rejectReason.SetTag(reasonCode);
01065 }
01066 
01067 
01068 H323GatekeeperRequest::Response H323GatekeeperARQ::OnHandlePDU()
01069 {
01070   H323GatekeeperRequest::Response response = rasChannel.OnAdmission(*this);
01071   if (response != Reject)
01072     return response;
01073 
01074   H323GatekeeperServer & server = rasChannel.GetGatekeeper();
01075   PSafePtr<H323GatekeeperCall> call = server.FindCall(arq.m_callIdentifier.m_guid, arq.m_answerCall);
01076   if (call != NULL)
01077     server.RemoveCall(call);
01078 
01079   server.mutex.Wait();
01080   server.rejectedCalls++;
01081   server.mutex.Signal();
01082 
01083   return Reject;
01084 }
01085 
01086 
01087 H323GatekeeperDRQ::H323GatekeeperDRQ(H323GatekeeperListener & rasChannel,
01088                                      const H323RasPDU & pdu)
01089   : H323GatekeeperRequest(rasChannel, pdu),
01090     drq((H225_DisengageRequest &)request->GetChoice().GetObject()),
01091     dcf(((H323RasPDU &)confirm->GetPDU()).BuildDisengageConfirm(drq.m_requestSeqNum)),
01092     drj(((H323RasPDU &)reject->GetPDU()).BuildDisengageReject(drq.m_requestSeqNum))
01093 {
01094 }
01095 
01096 
01097 #if PTRACING
01098 const char * H323GatekeeperDRQ::GetName() const
01099 {
01100   return "DRQ";
01101 }
01102 #endif
01103 
01104 
01105 PString H323GatekeeperDRQ::GetGatekeeperIdentifier() const
01106 {
01107   if (drq.HasOptionalField(H225_DisengageRequest::e_gatekeeperIdentifier))
01108     return drq.m_gatekeeperIdentifier;
01109 
01110   return PString::Empty();
01111 }
01112 
01113 
01114 unsigned H323GatekeeperDRQ::GetGatekeeperRejectTag() const
01115 {
01116   return H225_DisengageRejectReason::e_notRegistered;
01117 }
01118 
01119 
01120 PString H323GatekeeperDRQ::GetEndpointIdentifier() const
01121 {
01122   return drq.m_endpointIdentifier;
01123 }
01124 
01125 
01126 unsigned H323GatekeeperDRQ::GetRegisteredEndPointRejectTag() const
01127 {
01128   return H225_DisengageRejectReason::e_notRegistered;
01129 }
01130 
01131 
01132 H235Authenticator::ValidationResult H323GatekeeperDRQ::ValidatePDU() const
01133 {
01134   return request->Validate(drq.m_tokens, H225_DisengageRequest::e_tokens,
01135                            drq.m_cryptoTokens, H225_DisengageRequest::e_cryptoTokens);
01136 }
01137 
01138 
01139 unsigned H323GatekeeperDRQ::GetSecurityRejectTag() const
01140 {
01141   return H225_DisengageRejectReason::e_securityDenial;
01142 }
01143 
01144 
01145 void H323GatekeeperDRQ::SetRejectReason(unsigned reasonCode)
01146 {
01147   drj.m_rejectReason.SetTag(reasonCode);
01148 }
01149 
01150 
01151 H323GatekeeperRequest::Response H323GatekeeperDRQ::OnHandlePDU()
01152 {
01153   return rasChannel.OnDisengage(*this);
01154 }
01155 
01156 
01157 H323GatekeeperBRQ::H323GatekeeperBRQ(H323GatekeeperListener & rasChannel,
01158                                      const H323RasPDU & pdu)
01159   : H323GatekeeperRequest(rasChannel, pdu),
01160     brq((H225_BandwidthRequest &)request->GetChoice().GetObject()),
01161     bcf(((H323RasPDU &)confirm->GetPDU()).BuildBandwidthConfirm(brq.m_requestSeqNum)),
01162     brj(((H323RasPDU &)reject->GetPDU()).BuildBandwidthReject(brq.m_requestSeqNum))
01163 {
01164 }
01165 
01166 
01167 #if PTRACING
01168 const char * H323GatekeeperBRQ::GetName() const
01169 {
01170   return "BRQ";
01171 }
01172 #endif
01173 
01174 
01175 PString H323GatekeeperBRQ::GetGatekeeperIdentifier() const
01176 {
01177   if (brq.HasOptionalField(H225_BandwidthRequest::e_gatekeeperIdentifier))
01178     return brq.m_gatekeeperIdentifier;
01179 
01180   return PString::Empty();
01181 }
01182 
01183 
01184 unsigned H323GatekeeperBRQ::GetGatekeeperRejectTag() const
01185 {
01186   return H225_BandRejectReason::e_undefinedReason;
01187 }
01188 
01189 
01190 PString H323GatekeeperBRQ::GetEndpointIdentifier() const
01191 {
01192   return brq.m_endpointIdentifier;
01193 }
01194 
01195 
01196 unsigned H323GatekeeperBRQ::GetRegisteredEndPointRejectTag() const
01197 {
01198   return H225_BandRejectReason::e_notBound;
01199 }
01200 
01201 
01202 H235Authenticator::ValidationResult H323GatekeeperBRQ::ValidatePDU() const
01203 {
01204   return request->Validate(brq.m_tokens, H225_BandwidthRequest::e_tokens,
01205                            brq.m_cryptoTokens, H225_BandwidthRequest::e_cryptoTokens);
01206 }
01207 
01208 
01209 unsigned H323GatekeeperBRQ::GetSecurityRejectTag() const
01210 {
01211   return H225_BandRejectReason::e_securityDenial;
01212 }
01213 
01214 
01215 void H323GatekeeperBRQ::SetRejectReason(unsigned reasonCode)
01216 {
01217   brj.m_rejectReason.SetTag(reasonCode);
01218 }
01219 
01220 
01221 H323GatekeeperRequest::Response H323GatekeeperBRQ::OnHandlePDU()
01222 {
01223   return rasChannel.OnBandwidth(*this);
01224 }
01225 
01226 
01227 H323GatekeeperLRQ::H323GatekeeperLRQ(H323GatekeeperListener & rasChannel,
01228                                      const H323RasPDU & pdu)
01229   : H323GatekeeperRequest(rasChannel, pdu),
01230     lrq((H225_LocationRequest &)request->GetChoice().GetObject()),
01231     lcf(((H323RasPDU &)confirm->GetPDU()).BuildLocationConfirm(lrq.m_requestSeqNum)),
01232     lrj(((H323RasPDU &)reject->GetPDU()).BuildLocationReject(lrq.m_requestSeqNum))
01233 {
01234   if (rasChannel.GetTransport().IsCompatibleTransport(lrq.m_replyAddress))
01235     replyAddresses[0] = lrq.m_replyAddress;
01236 }
01237 
01238 
01239 #if PTRACING
01240 const char * H323GatekeeperLRQ::GetName() const
01241 {
01242   return "LRQ";
01243 }
01244 #endif
01245 
01246 
01247 PString H323GatekeeperLRQ::GetGatekeeperIdentifier() const
01248 {
01249   if (lrq.HasOptionalField(H225_LocationRequest::e_gatekeeperIdentifier))
01250     return lrq.m_gatekeeperIdentifier;
01251 
01252   return PString::Empty();
01253 }
01254 
01255 
01256 unsigned H323GatekeeperLRQ::GetGatekeeperRejectTag() const
01257 {
01258   return H225_LocationRejectReason::e_undefinedReason;
01259 }
01260 
01261 
01262 PString H323GatekeeperLRQ::GetEndpointIdentifier() const
01263 {
01264   return lrq.m_endpointIdentifier;
01265 }
01266 
01267 
01268 unsigned H323GatekeeperLRQ::GetRegisteredEndPointRejectTag() const
01269 {
01270   return H225_LocationRejectReason::e_notRegistered;
01271 }
01272 
01273 
01274 H235Authenticator::ValidationResult H323GatekeeperLRQ::ValidatePDU() const
01275 {
01276   return request->Validate(lrq.m_tokens, H225_LocationRequest::e_tokens,
01277                            lrq.m_cryptoTokens, H225_LocationRequest::e_cryptoTokens);
01278 }
01279 
01280 
01281 unsigned H323GatekeeperLRQ::GetSecurityRejectTag() const
01282 {
01283   return H225_LocationRejectReason::e_securityDenial;
01284 }
01285 
01286 
01287 void H323GatekeeperLRQ::SetRejectReason(unsigned reasonCode)
01288 {
01289   lrj.m_rejectReason.SetTag(reasonCode);
01290 }
01291 
01292 
01293 H323GatekeeperRequest::Response H323GatekeeperLRQ::OnHandlePDU()
01294 {
01295   return rasChannel.OnLocation(*this);
01296 }
01297 
01298 
01299 H323GatekeeperIRR::H323GatekeeperIRR(H323GatekeeperListener & rasChannel,
01300                                      const H323RasPDU & pdu)
01301   : H323GatekeeperRequest(rasChannel, pdu),
01302     irr((H225_InfoRequestResponse &)request->GetChoice().GetObject()),
01303     iack(((H323RasPDU &)confirm->GetPDU()).BuildInfoRequestAck(irr.m_requestSeqNum)),
01304     inak(((H323RasPDU &)reject->GetPDU()).BuildInfoRequestNak(irr.m_requestSeqNum))
01305 {
01306 }
01307 
01308 
01309 #if PTRACING
01310 const char * H323GatekeeperIRR::GetName() const
01311 {
01312   return "IRR";
01313 }
01314 #endif
01315 
01316 
01317 PString H323GatekeeperIRR::GetGatekeeperIdentifier() const
01318 {
01319   return PString::Empty();
01320 }
01321 
01322 
01323 unsigned H323GatekeeperIRR::GetGatekeeperRejectTag() const
01324 {
01325   return H225_GatekeeperRejectReason::e_terminalExcluded;
01326 }
01327 
01328 
01329 PString H323GatekeeperIRR::GetEndpointIdentifier() const
01330 {
01331   return irr.m_endpointIdentifier;
01332 }
01333 
01334 
01335 unsigned H323GatekeeperIRR::GetRegisteredEndPointRejectTag() const
01336 {
01337   return H225_InfoRequestNakReason::e_notRegistered;
01338 }
01339 
01340 
01341 H235Authenticator::ValidationResult H323GatekeeperIRR::ValidatePDU() const
01342 {
01343   return request->Validate(irr.m_tokens, H225_InfoRequestResponse::e_tokens,
01344                            irr.m_cryptoTokens, H225_InfoRequestResponse::e_cryptoTokens);
01345 }
01346 
01347 
01348 unsigned H323GatekeeperIRR::GetSecurityRejectTag() const
01349 {
01350   return H225_InfoRequestNakReason::e_securityDenial;
01351 }
01352 
01353 
01354 void H323GatekeeperIRR::SetRejectReason(unsigned reasonCode)
01355 {
01356   inak.m_nakReason.SetTag(reasonCode);
01357 }
01358 
01359 
01360 H323GatekeeperRequest::Response H323GatekeeperIRR::OnHandlePDU()
01361 {
01362   return rasChannel.OnInfoResponse(*this);
01363 }
01364 
01365 
01367 
01368 H323GatekeeperCall::H323GatekeeperCall(H323GatekeeperServer& gk,
01369                                        const OpalGloballyUniqueID & id,
01370                                        Direction dir)
01371   : gatekeeper(gk),
01372     callIdentifier(id),
01373     conferenceIdentifier(NULL),
01374     alertingTime(0),
01375     connectedTime(0),
01376     callEndTime(0)
01377 {
01378   endpoint = NULL;
01379   rasChannel = NULL;
01380   direction = dir;
01381   callReference = 0;
01382 
01383   drqReceived = FALSE;
01384   callEndReason = H323Connection::NumCallEndReasons;
01385 
01386   bandwidthUsed = 0;
01387   infoResponseRate = gatekeeper.GetInfoResponseRate();
01388 }
01389 
01390 
01391 H323GatekeeperCall::~H323GatekeeperCall()
01392 {
01393   SetBandwidthUsed(0);
01394 }
01395 
01396 
01397 PObject::Comparison H323GatekeeperCall::Compare(const PObject & obj) const
01398 {
01399   // Do not have to lock the object as these fields should never change for
01400   // life of the object
01401 
01402   PAssert(PIsDescendant(&obj, H323GatekeeperCall), PInvalidCast);
01403   const H323GatekeeperCall & other = (const H323GatekeeperCall &)obj;
01404   Comparison result = callIdentifier.Compare(other.callIdentifier);
01405   if (result != EqualTo)
01406     return result;
01407 
01408   if (direction == UnknownDirection || other.direction == UnknownDirection)
01409     return EqualTo;
01410 
01411   if (direction > other.direction)
01412     return GreaterThan;
01413   if (direction < other.direction)
01414     return LessThan;
01415   return EqualTo;
01416 }
01417 
01418 
01419 void H323GatekeeperCall::PrintOn(ostream & strm) const
01420 {
01421   // Do not have to lock the object as these fields should never change for
01422   // life of the object
01423 
01424   strm << callIdentifier;
01425 
01426   switch (direction) {
01427     case AnsweringCall :
01428       strm << AnswerCallStr;
01429       break;
01430     case OriginatingCall :
01431       strm << OriginateCallStr;
01432       break;
01433     default :
01434       break;
01435   }
01436 }
01437 
01438 
01439 H323GatekeeperRequest::Response H323GatekeeperCall::OnAdmission(H323GatekeeperARQ & info)
01440 {
01441   PTRACE_BLOCK("H323GatekeeperCall::OnAdmission");
01442 
01443   if (endpoint != NULL) {
01444     info.SetRejectReason(H225_AdmissionRejectReason::e_resourceUnavailable);
01445     PTRACE(2, "RAS\tARQ rejected, multiple use of same call id.");
01446     return H323GatekeeperRequest::Reject;
01447   }
01448 
01449   PINDEX i;
01450 
01451   if (!LockReadWrite()) {
01452     PTRACE(1, "RAS\tARQ rejected, lock failed on call " << *this);
01453     return H323GatekeeperRequest::Reject;
01454   }
01455 
01456   PTRACE(3, "RAS\tProcessing OnAdmission for " << *this);
01457 
01458   endpoint = info.endpoint;
01459   rasChannel = &info.GetRasChannel();
01460 
01461   callReference = info.arq.m_callReferenceValue;
01462   conferenceIdentifier = info.arq.m_conferenceID;
01463 
01464   for (i = 0; i < info.arq.m_srcInfo.GetSize(); i++) {
01465     PString alias = H323GetAliasAddressString(info.arq.m_srcInfo[i]);
01466     if (srcAliases.GetValuesIndex(alias) == P_MAX_INDEX)
01467       srcAliases += alias;
01468   }
01469 
01470   srcNumber = H323GetAliasAddressE164(info.arq.m_srcInfo);
01471 
01472   if (!endpoint->IsBehindNAT() &&
01473           info.arq.HasOptionalField(H225_AdmissionRequest::e_srcCallSignalAddress))
01474     srcHost = info.arq.m_srcCallSignalAddress;
01475   else
01476     srcHost = info.GetReplyAddress();
01477 
01478   if (info.arq.HasOptionalField(H225_AdmissionRequest::e_destinationInfo)) {
01479     for (i = 0; i < info.arq.m_destinationInfo.GetSize(); i++) {
01480       PString alias = H323GetAliasAddressString(info.arq.m_destinationInfo[i]);
01481       if (dstAliases.GetValuesIndex(alias) == P_MAX_INDEX)
01482         dstAliases += alias;
01483     }
01484 
01485     dstNumber = H323GetAliasAddressE164(info.arq.m_destinationInfo);
01486   }
01487 
01488   if (info.arq.HasOptionalField(H225_AdmissionRequest::e_destCallSignalAddress))
01489     dstHost = info.arq.m_destCallSignalAddress;
01490 
01491   UnlockReadWrite();
01492 
01493   BOOL isGKRouted = gatekeeper.IsGatekeeperRouted();
01494 
01495   if (direction == AnsweringCall) {
01496 
01497     // See if our policies allow the call
01498     BOOL denied = TRUE;
01499     for (i = 0; i < info.arq.m_srcInfo.GetSize(); i++) {
01500       if (gatekeeper.CheckAliasAddressPolicy(*endpoint, info.arq, info.arq.m_srcInfo[i])) {
01501         denied = FALSE;
01502         break;
01503       }
01504     }
01505 
01506     if (info.arq.HasOptionalField(H225_AdmissionRequest::e_srcCallSignalAddress)) {
01507       if (gatekeeper.CheckSignalAddressPolicy(*endpoint, info.arq, info.arq.m_srcCallSignalAddress))
01508         denied = FALSE;
01509     }
01510 
01511     if (denied) {
01512       info.SetRejectReason(H225_AdmissionRejectReason::e_securityDenial);
01513       PTRACE(2, "RAS\tARQ rejected, not allowed to answer call");
01514       return H323GatekeeperRequest::Reject;
01515     }
01516   }
01517 
01518   else {
01519     PSafePtr<H323RegisteredEndPoint> destEP;
01520 
01521     BOOL denied = TRUE;
01522     BOOL noAddress = TRUE;
01523 
01524     // if no alias, convert signalling address to an alias
01525     if (!info.arq.HasOptionalField(H225_AdmissionRequest::e_destinationInfo) && info.arq.HasOptionalField(H225_AdmissionRequest::e_destCallSignalAddress)) {
01526 
01527       H323TransportAddress origTransAddr(info.arq.m_destCallSignalAddress);
01528       H225_AliasAddress transportAlias;
01529       H323SetAliasAddress(origTransAddr, transportAlias);
01530 
01531       if (gatekeeper.CheckAliasAddressPolicy(*endpoint, info.arq, transportAlias)) {
01532         denied = FALSE;
01533         H323TransportAddress destAddr;
01534         if (TranslateAliasAddress(transportAlias,
01535                                   info.acf.m_destinationInfo,
01536                                   destAddr,
01537                                   isGKRouted)) {
01538           if (info.acf.m_destinationInfo.GetSize())
01539             info.acf.IncludeOptionalField(H225_AdmissionConfirm::e_destinationInfo);
01540 
01541           destEP = gatekeeper.FindEndPointByAliasAddress(transportAlias);
01542           if (!LockReadWrite()) {
01543             PTRACE(1, "RAS\tARQ rejected, lock failed on call " << *this);
01544             return H323GatekeeperRequest::Reject;
01545           }
01546           dstHost = destAddr;
01547           UnlockReadWrite();
01548           noAddress = FALSE;
01549         }
01550       }
01551     }
01552 
01553     // if alias(es) specified, check them
01554     else {
01555 
01556       for (i = 0; i < info.arq.m_destinationInfo.GetSize(); i++) {
01557         if (gatekeeper.CheckAliasAddressPolicy(*endpoint, info.arq, info.arq.m_destinationInfo[i])) {
01558           denied = FALSE;
01559           H323TransportAddress destAddr;
01560           if (TranslateAliasAddress(info.arq.m_destinationInfo[i],
01561                                     info.acf.m_destinationInfo,
01562                                     destAddr,
01563                                     isGKRouted)) {
01564             if (info.acf.m_destinationInfo.GetSize())
01565               info.acf.IncludeOptionalField(H225_AdmissionConfirm::e_destinationInfo);
01566 
01567             destEP = gatekeeper.FindEndPointByAliasAddress(info.arq.m_destinationInfo[i]);
01568             if (!LockReadWrite()) {
01569               PTRACE(1, "RAS\tARQ rejected, lock failed on call " << *this);
01570               return H323GatekeeperRequest::Reject;
01571             }
01572             dstHost = destAddr;
01573             UnlockReadWrite();
01574             noAddress = FALSE;
01575             break;
01576           }
01577         }
01578       }
01579 
01580       if (denied) {
01581         info.SetRejectReason(H225_AdmissionRejectReason::e_securityDenial);
01582         PTRACE(2, "RAS\tARQ rejected, not allowed to make call");
01583         return H323GatekeeperRequest::Reject;
01584       }
01585 
01586       if (noAddress) {
01587         info.SetRejectReason(H225_AdmissionRejectReason::e_calledPartyNotRegistered);
01588         PTRACE(2, "RAS\tARQ rejected, destination alias not registered");
01589         return H323GatekeeperRequest::Reject;
01590       }
01591 
01592       if (destEP != NULL) {
01593         destEP.SetSafetyMode(PSafeReadOnly);
01594         if (!LockReadWrite()) {
01595           PTRACE(1, "RAS\tARQ rejected, lock failed on call " << *this);
01596           return H323GatekeeperRequest::Reject;
01597         }
01598         dstAliases.RemoveAll();
01599         dstNumber = PString::Empty();
01600         for (i = 0; i < destEP->GetAliasCount(); i++) {
01601           PString alias = destEP->GetAlias(i);
01602           dstAliases += alias;
01603           if (strspn(alias, "0123456789*#") == strlen(alias))
01604             dstNumber = alias;
01605         }
01606         UnlockReadWrite();
01607         destEP.SetSafetyMode(PSafeReference);
01608       }
01609 
01610       // Has provided an alias and signal address, see if agree
01611       if (destEP != NULL && info.arq.HasOptionalField(H225_AdmissionRequest::e_destCallSignalAddress)) {
01612         // Note nested if's used because some compilers (Tornado 2) cannot handle it
01613         if (gatekeeper.FindEndPointBySignalAddress(info.arq.m_destCallSignalAddress) != destEP) {
01614           info.SetRejectReason(H225_AdmissionRejectReason::e_aliasesInconsistent);
01615           PTRACE(2, "RAS\tARQ rejected, destination address not for specified alias");
01616           return H323GatekeeperRequest::Reject;
01617         }
01618       }
01619     }
01620 
01621     // Have no address from anywhere
01622     if (dstHost.IsEmpty()) {
01623       info.SetRejectReason(H225_AdmissionRejectReason::e_incompleteAddress);
01624       PTRACE(2, "RAS\tARQ rejected, must have destination address or alias");
01625       return H323GatekeeperRequest::Reject;
01626     }
01627 
01628     // Now see if security policy allows connection to that address
01629     if (!gatekeeper.CheckSignalAddressPolicy(*endpoint, info.arq, dstHost)) {
01630       info.SetRejectReason(H225_AdmissionRejectReason::e_securityDenial);
01631       PTRACE(2, "RAS\tARQ rejected, not allowed to make call");
01632       return H323GatekeeperRequest::Reject;
01633     }
01634   }
01635 
01636   // See if have bandwidth
01637   unsigned requestedBandwidth = info.arq.m_bandWidth;
01638   if (requestedBandwidth == 0)
01639     requestedBandwidth = gatekeeper.GetDefaultBandwidth();
01640 
01641   unsigned bandwidthAllocated = gatekeeper.AllocateBandwidth(requestedBandwidth);
01642   if (bandwidthAllocated == 0) {
01643     info.SetRejectReason(H225_AdmissionRejectReason::e_requestDenied);
01644     PTRACE(2, "RAS\tARQ rejected, not enough bandwidth");
01645     return H323GatekeeperRequest::Reject;
01646   }
01647 
01648   bandwidthUsed = bandwidthAllocated;  // Do we need to lock for atomic assignment?
01649   info.acf.m_bandWidth = bandwidthUsed;
01650 
01651   // Set the rate for getting unsolicited IRR's
01652   if (infoResponseRate > 0 && endpoint->GetProtocolVersion() > 2) {
01653     info.acf.IncludeOptionalField(H225_AdmissionConfirm::e_irrFrequency);
01654     info.acf.m_irrFrequency = infoResponseRate;
01655   }
01656   info.acf.m_willRespondToIRR = TRUE;
01657 
01658   // Set the destination to fixed value of gk routed
01659   if (isGKRouted)
01660     info.acf.m_callModel.SetTag(H225_CallModel::e_gatekeeperRouted);
01661 
01662   dstHost.SetPDU(info.acf.m_destCallSignalAddress);
01663 
01664   // If ep can do UUIE's then use that to expidite getting some statistics
01665   if (info.arq.m_willSupplyUUIEs) {
01666     info.acf.m_uuiesRequested.m_alerting = TRUE;
01667     info.acf.m_uuiesRequested.m_connect = TRUE;
01668   }
01669 
01670   return H323GatekeeperRequest::Confirm;
01671 }
01672 
01673 
01674 BOOL H323GatekeeperCall::Disengage(int reason)
01675 {
01676   if (!LockReadWrite()) {
01677     PTRACE(1, "RAS\tDRQ not sent, lock failed on call " << *this);
01678     return FALSE;
01679   }
01680 
01681   if (drqReceived) {
01682     UnlockReadWrite();
01683     PTRACE(1, "RAS\tAlready disengaged call " << *this);
01684     return FALSE;
01685   }
01686 
01687   drqReceived = TRUE;
01688 
01689   PTRACE(2, "RAS\tDisengage of call " << *this);
01690 
01691   UnlockReadWrite();
01692 
01693   if (reason == -1)
01694     reason = H225_DisengageReason::e_forcedDrop;
01695 
01696   BOOL ok;
01697   // Send DRQ to endpoint(s)
01698   if (rasChannel != NULL)
01699     ok = rasChannel->DisengageRequest(*this, reason);
01700   else {
01701     // Can't do DRQ as have no RAS channel to use (probably logic error)
01702     PAssertAlways("Tried to disengage call we did not receive ARQ for!");
01703     ok = FALSE;
01704   }
01705 
01706   gatekeeper.RemoveCall(this);
01707 
01708   return ok;
01709 }
01710 
01711 
01712 H323GatekeeperRequest::Response H323GatekeeperCall::OnDisengage(H323GatekeeperDRQ & info)
01713 {
01714   PTRACE_BLOCK("H323GatekeeperCall::OnDisengage");
01715 
01716   if (!LockReadWrite()) {
01717     PTRACE(1, "RAS\tDRQ rejected, lock failed on call " << *this);
01718     return H323GatekeeperRequest::Reject;
01719   }
01720 
01721   if (drqReceived) {
01722     UnlockReadWrite();
01723     info.SetRejectReason(H225_DisengageRejectReason::e_requestToDropOther);
01724     PTRACE(2, "RAS\tDRQ rejected, already disengaged call " << *this);
01725     return H323GatekeeperRequest::Reject;
01726   }
01727 
01728   drqReceived = TRUE;
01729 
01730   if (info.drq.HasOptionalField(H225_DisengageRequest::e_usageInformation))
01731     SetUsageInfo(info.drq.m_usageInformation);
01732 
01733   if (info.drq.HasOptionalField(H225_DisengageRequest::e_terminationCause)) {
01734     if (info.drq.m_terminationCause.GetTag() == H225_CallTerminationCause::e_releaseCompleteReason) {
01735       H225_ReleaseCompleteReason & reason = info.drq.m_terminationCause;
01736       callEndReason = H323TranslateToCallEndReason(Q931::ErrorInCauseIE, reason);
01737     }
01738     else {
01739       PASN_OctetString & cause = info.drq.m_terminationCause;
01740       H225_ReleaseCompleteReason dummy;
01741       callEndReason = H323TranslateToCallEndReason((Q931::CauseValues)(cause[1]&0x7f), dummy);
01742     }
01743   }
01744 
01745   UnlockReadWrite();
01746 
01747   return H323GatekeeperRequest::Confirm;
01748 }
01749 
01750 
01751 H323GatekeeperRequest::Response H323GatekeeperCall::OnBandwidth(H323GatekeeperBRQ & info)
01752 {
01753   PTRACE_BLOCK("H323GatekeeperCall::OnBandwidth");
01754 
01755   if (endpoint != info.endpoint) {
01756     info.SetRejectReason(H225_BandRejectReason::e_invalidPermission);
01757     PTRACE(2, "RAS\tBRQ rejected, call is not owned by endpoint");
01758     return H323GatekeeperRequest::Reject;
01759   }
01760 
01761   bandwidthUsed = gatekeeper.AllocateBandwidth(info.brq.m_bandWidth, bandwidthUsed);
01762   if (bandwidthUsed < info.brq.m_bandWidth) {
01763     info.SetRejectReason(H225_BandRejectReason::e_insufficientResources);
01764     info.brj.m_allowedBandWidth = bandwidthUsed;
01765     PTRACE(2, "RAS\tBRQ rejected, no bandwidth");
01766     return H323GatekeeperRequest::Reject;
01767   }
01768 
01769   info.bcf.m_bandWidth = bandwidthUsed;
01770 
01771   if (info.brq.HasOptionalField(H225_BandwidthRequest::e_usageInformation))
01772     SetUsageInfo(info.brq.m_usageInformation);
01773 
01774   return H323GatekeeperRequest::Confirm;
01775 }
01776 
01777 
01778 H323GatekeeperRequest::Response H323GatekeeperCall::OnInfoResponse(H323GatekeeperIRR &,
01779                                                                    H225_InfoRequestResponse_perCallInfo_subtype & info)
01780 {
01781   PTRACE_BLOCK("H323GatekeeperCall::OnInfoResponse");
01782 
01783   PTRACE(2, "RAS\tIRR received for call " << *this);
01784 
01785   if (!LockReadWrite()) {
01786     PTRACE(1, "RAS\tIRR rejected, lock failed on call " << *this);
01787     return H323GatekeeperRequest::Reject;
01788   }
01789 
01790   PTime now;
01791   lastInfoResponse = now;
01792 
01793   // Detect if have Cisco non-standard version of connect time indication.
01794   if (!connectedTime.IsValid() &&
01795       info.HasOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_nonStandardData) &&
01796       info.m_nonStandardData.m_nonStandardIdentifier.GetTag() == H225_NonStandardIdentifier::e_h221NonStandard) {
01797     H225_H221NonStandard & id = info.m_nonStandardData.m_nonStandardIdentifier;
01798     if (id.m_t35CountryCode == 181 && id.m_t35Extension == 0 && id.m_manufacturerCode == 18 && // Cisco
01799         info.m_nonStandardData.m_data.GetSize() == 5 && info.m_nonStandardData.m_data[0] == 0x70) {
01800       PTime theConnectedTime((info.m_nonStandardData.m_data[1] << 24)|
01801                             (info.m_nonStandardData.m_data[2] << 16)|
01802                             (info.m_nonStandardData.m_data[3] << 8 )|
01803                              info.m_nonStandardData.m_data[4]        );
01804       if (theConnectedTime > now || theConnectedTime < callStartTime) {
01805         connectedTime = now;
01806         OnConnected();
01807       }
01808       else {
01809         connectedTime = theConnectedTime;
01810         OnConnected();
01811       }
01812     }
01813   }
01814 
01815   SetUsageInfo(info.m_usageInformation);
01816 
01817   UnlockReadWrite();
01818 
01819   return H323GatekeeperRequest::Confirm;
01820 }
01821 
01822 
01823 void H323GatekeeperCall::OnAlerting()
01824 {
01825 }
01826 
01827 
01828 void H323GatekeeperCall::OnConnected()
01829 {
01830 }
01831 
01832 
01833 static BOOL CheckTimeSince(PTime & lastTime, unsigned threshold)
01834 {
01835   if (threshold == 0)
01836     return TRUE;
01837 
01838   PTime now;
01839   PTimeInterval delta = now - lastTime;
01840   return delta.GetSeconds() < (int)(threshold+10);
01841 }
01842 
01843 
01844 BOOL H323GatekeeperCall::OnHeartbeat()
01845 {
01846   if (!LockReadOnly()) {
01847     PTRACE(1, "RAS\tOnHeartbeat lock failed on call " << *this);
01848     return TRUE;
01849   }
01850 
01851   if (CheckTimeSince(lastInfoResponse, infoResponseRate)) {
01852     UnlockReadOnly();
01853     return TRUE;
01854   }
01855 
01856   // Can't do IRQ as have no RAS channel to use (probably logic error)
01857   if (rasChannel == NULL) {
01858     UnlockReadOnly();
01859     PAssertAlways("Timeout on heartbeat for call we did not receive ARQ for!");
01860     return FALSE;
01861   }
01862 
01863   UnlockReadOnly();
01864 
01865   // Do IRQ and wait for IRR on call
01866   PTRACE(2, "RAS\tTimeout on heartbeat, doing IRQ for call "<< *this);
01867   if (!rasChannel->InfoRequest(*endpoint, this))
01868     return FALSE;
01869 
01870   if (!LockReadOnly()) {
01871     PTRACE(1, "RAS\tOnHeartbeat lock failed on call " << *this);
01872     return TRUE;
01873   }
01874 
01875   // Return TRUE if got a resonse, ie client does not do unsolicited IRR's
01876   // otherwise did not get a response from client so return FALSE and
01877   // (probably) disengage the call.
01878   BOOL response = CheckTimeSince(lastInfoResponse, infoResponseRate); 
01879   
01880   UnlockReadOnly();
01881 
01882   return response;
01883 }
01884 
01885 #ifdef H323_H248
01886 
01887 PString H323GatekeeperCall::GetCallCreditAmount() const
01888 {
01889   if (endpoint != NULL)
01890     return endpoint->GetCallCreditAmount();
01891   
01892   return PString::Empty();
01893 }
01894 
01895 
01896 BOOL H323GatekeeperCall::GetCallCreditMode() const
01897 {
01898   return endpoint != NULL ? endpoint->GetCallCreditMode() : FALSE;
01899 }
01900 
01901 
01902 unsigned H323GatekeeperCall::GetDurationLimit() const
01903 {
01904   return 0;
01905 }
01906 
01907 BOOL H323GatekeeperCall::SendCallCreditServiceControl()
01908 {
01909   PString amount;
01910   if (endpoint->CanDisplayAmountString())
01911     amount = GetCallCreditAmount();
01912 
01913   unsigned durationLimit = 0;
01914   if (endpoint->CanEnforceDurationLimit())
01915     durationLimit = GetDurationLimit();
01916 
01917   if (amount.IsEmpty() && durationLimit == 0)
01918     return FALSE;
01919 
01920   H323CallCreditServiceControl credit(amount, GetCallCreditMode(), durationLimit);
01921   return SendServiceControlSession(credit);
01922 }
01923 
01924 
01925 BOOL H323GatekeeperCall::AddCallCreditServiceControl(H225_ArrayOf_ServiceControlSession & serviceControl) const
01926 {
01927   PString amount;
01928   if (endpoint->CanDisplayAmountString())
01929     amount = GetCallCreditAmount();
01930 
01931   unsigned durationLimit = 0;
01932   if (endpoint->CanEnforceDurationLimit())
01933     durationLimit = GetDurationLimit();
01934 
01935   if (amount.IsEmpty() && durationLimit == 0)
01936     return FALSE;
01937 
01938   H323CallCreditServiceControl credit(amount, GetCallCreditMode(), durationLimit);
01939   return endpoint->AddServiceControlSession(credit, serviceControl);
01940 }
01941 
01942 
01943 BOOL H323GatekeeperCall::SendServiceControlSession(const H323ServiceControlSession & session)
01944 {
01945   // Send SCI to endpoint(s)
01946   if (rasChannel == NULL || endpoint == NULL) {
01947     // Can't do SCI as have no RAS channel to use (probably logic error)
01948     PAssertAlways("Tried to do SCI to call we did not receive ARQ for!");
01949     return FALSE;
01950   }
01951 
01952   return rasChannel->ServiceControlIndication(*endpoint, session, this);
01953 }
01954 
01955 #endif // H323_H248
01956 
01957 
01958 BOOL H323GatekeeperCall::SetBandwidthUsed(unsigned newBandwidth)
01959 {
01960   if (newBandwidth == bandwidthUsed)
01961     return TRUE;
01962 
01963   bandwidthUsed = gatekeeper.AllocateBandwidth(newBandwidth, bandwidthUsed);
01964   return bandwidthUsed == newBandwidth;
01965 }
01966 
01967 
01968 static PString MakeAddress(const PString & number,
01969                            const PStringArray aliases,
01970                            const H323TransportAddress & host)
01971 {
01972   PStringStream addr;
01973 
01974   if (!number)
01975     addr << number;
01976   else if (!aliases.IsEmpty())
01977     addr << aliases[0];
01978 
01979   if (!host) {
01980     if (!addr.IsEmpty())
01981       addr << '@';
01982     addr << host;
01983   }
01984 
01985   return addr;
01986 }
01987 
01988 
01989 PString H323GatekeeperCall::GetSourceAddress() const
01990 {
01991   if (!LockReadOnly()) {
01992     PTRACE(1, "RAS\tGetSourceAddress lock failed on call " << *this);
01993     return PString::Empty();
01994   }
01995   PString addr = MakeAddress(srcNumber, srcAliases, srcHost);
01996   UnlockReadOnly();
01997   return addr;
01998 }
01999 
02000 
02001 PString H323GatekeeperCall::GetDestinationAddress() const
02002 {
02003   if (!LockReadOnly()) {
02004     PTRACE(1, "RAS\tGetDestinationAddress lock failed on call " << *this);
02005     return PString::Empty();
02006   }
02007   PString addr = MakeAddress(dstNumber, dstAliases, dstHost);
02008   UnlockReadOnly();
02009   return addr;
02010 }
02011 
02012 
02013 void H323GatekeeperCall::SetUsageInfo(const H225_RasUsageInformation & usage)
02014 {
02015   PTime now;
02016 
02017   if (!alertingTime.IsValid() &&
02018        usage.HasOptionalField(H225_RasUsageInformation::e_alertingTime)) {
02019     PTime theAlertingTime((unsigned)usage.m_alertingTime);
02020     if (theAlertingTime > now || theAlertingTime < callStartTime) {
02021       alertingTime = now;
02022       OnAlerting();
02023     }
02024     else if (theAlertingTime > callStartTime) {
02025       alertingTime = theAlertingTime;
02026       OnAlerting();
02027     }
02028   }
02029 
02030   if (!connectedTime.IsValid() &&
02031        usage.HasOptionalField(H225_RasUsageInformation::e_connectTime)) {
02032     PTime theConnectedTime((unsigned)usage.m_connectTime);
02033     if (theConnectedTime > now || theConnectedTime < callStartTime) {
02034       connectedTime = now;
02035       OnConnected();
02036     }
02037     else {
02038       connectedTime = theConnectedTime;
02039       OnConnected();
02040     }
02041   }
02042 
02043   if (!callEndTime.IsValid() &&
02044        usage.HasOptionalField(H225_RasUsageInformation::e_endTime)) {
02045     PTime theCallEndTime = PTime((unsigned)usage.m_endTime);
02046     if (theCallEndTime > now ||
02047        (alertingTime.IsValid() && theCallEndTime < alertingTime) ||
02048        (connectedTime.IsValid() && theCallEndTime < connectedTime) ||
02049         theCallEndTime < callStartTime)
02050       callEndTime = now;
02051     else
02052       callEndTime = theCallEndTime;
02053   }
02054 }
02055 
02056 BOOL H323GatekeeperCall::TranslateAliasAddress(
02057       const H225_AliasAddress & alias,
02058       H225_ArrayOf_AliasAddress & aliases,
02059       H323TransportAddress & address,
02060       BOOL & gkRouted
02061     )
02062 {
02063   return gatekeeper.TranslateAliasAddress(alias, aliases, address, gkRouted, this);
02064 }
02065 
02067 
02068 H323RegisteredEndPoint::H323RegisteredEndPoint(H323GatekeeperServer & gk,
02069                                                const PString & id)
02070   : gatekeeper(gk),
02071     rasChannel(NULL),
02072     identifier(id),
02073     protocolVersion(0),
02074     isBehindNAT(FALSE),
02075     canDisplayAmountString(FALSE),
02076     canEnforceDurationLimit(FALSE),
02077     timeToLive(0),
02078     authenticators(gk.GetOwnerEndPoint().CreateAuthenticators())
02079 {
02080   activeCalls.DisallowDeleteObjects();
02081 
02082   PTRACE(3, "RAS\tCreated registered endpoint: " << id);
02083 }
02084 
02085 
02086 PObject::Comparison H323RegisteredEndPoint::Compare(const PObject & obj) const
02087 {
02088   // Do not have to lock the object as these fields should never change for
02089   // life of the object
02090 
02091   PAssert(PIsDescendant(&obj, H323RegisteredEndPoint), PInvalidCast);
02092   return identifier.Compare(((const H323RegisteredEndPoint &)obj).identifier);
02093 }
02094 
02095 
02096 void H323RegisteredEndPoint::PrintOn(ostream & strm) const
02097 {
02098   // Do not have to lock the object as these fields should never change for
02099   // life of the object
02100 
02101   strm << identifier;
02102 }
02103 
02104 
02105 void H323RegisteredEndPoint::AddCall(H323GatekeeperCall * call)
02106 {
02107   if (call == NULL) {
02108     PTRACE(1, "RAS\tCould not add NULL call to endpoint " << *this);
02109     return; 
02110   }
02111 
02112   if (!LockReadWrite()) {
02113     PTRACE(1, "RAS\tCould not add call " << *call << ", lock failed on endpoint " << *this);
02114     return; 
02115   }
02116 
02117   if (activeCalls.GetObjectsIndex(call) == P_MAX_INDEX)
02118     activeCalls.Append(call);
02119 
02120   UnlockReadWrite();
02121 }
02122 
02123 
02124 BOOL H323RegisteredEndPoint::RemoveCall(H323GatekeeperCall * call)
02125 {
02126   if (call == NULL) {
02127     PTRACE(1, "RAS\tCould not remove NULL call to endpoint " << *this);
02128     return FALSE;
02129   }
02130 
02131   if (!LockReadWrite()) {
02132     PTRACE(1, "RAS\tCould not remove call " << *call << ", lock failed on endpoint " << *this);
02133     return FALSE; 
02134   }
02135 
02136   BOOL ok = activeCalls.Remove(call);
02137 
02138   UnlockReadWrite();
02139 
02140   return ok;
02141 }
02142 
02143 void H323RegisteredEndPoint::RemoveAlias(const PString & alias)
02144 { 
02145   if (!LockReadWrite()) {
02146     PTRACE(1, "RAS\tCould not remove alias \"" << alias << "\", lock failed on endpoint " << *this);
02147     return;
02148   }
02149 
02150   // remove the aliases from the list inside the endpoint
02151   PINDEX idx;
02152   while ((idx = aliases.GetValuesIndex(alias)) != P_MAX_INDEX)
02153     aliases.RemoveAt(idx); 
02154 
02155   // remove the aliases from the list in the gatekeeper
02156   gatekeeper.RemoveAlias(*this, alias);
02157 
02158   UnlockReadWrite();
02159 }
02160 
02161 static BOOL IsTransportAddressSuperset(const H225_ArrayOf_TransportAddress & pdu,
02162                                        const H323TransportAddressArray & oldAddresses)
02163 {
02164   H323TransportAddressArray newAddresses(pdu);
02165 
02166   for (PINDEX i = 0; i < oldAddresses.GetSize(); i++) {
02167     if (newAddresses.GetValuesIndex(oldAddresses[i]) == P_MAX_INDEX)
02168       return FALSE;
02169   }
02170 
02171   return TRUE;
02172 }
02173 
02174 
02175 static PStringArray GetAliasAddressArray(const H225_ArrayOf_AliasAddress & pdu)
02176 {
02177   PStringArray aliases;
02178 
02179   for (PINDEX i = 0; i < pdu.GetSize(); i++) {
02180     PString alias = H323GetAliasAddressString(pdu[i]);
02181     if (!alias)
02182       aliases.AppendString(alias);
02183   }
02184 
02185   return aliases;
02186 }
02187 
02188 
02189 static BOOL IsAliasAddressSuperset(const H225_ArrayOf_AliasAddress & pdu,
02190                                    const PStringArray & oldAliases)
02191 {
02192   PStringArray newAliases = GetAliasAddressArray(pdu);
02193 
02194   for (PINDEX i = 0; i < oldAliases.GetSize(); i++) {
02195     if (newAliases.GetValuesIndex(oldAliases[i]) == P_MAX_INDEX)
02196       return FALSE;
02197   }
02198 
02199   return TRUE;
02200 }
02201 
02202 
02203 H323GatekeeperRequest::Response H323RegisteredEndPoint::OnRegistration(H323GatekeeperRRQ & info)
02204 {
02205   PTRACE_BLOCK("H323RegisteredEndPoint::OnRegistration");
02206 
02207   if (!LockReadWrite()) {
02208     PTRACE(1, "RAS\tRRQ rejected, lock failed on endpoint " << *this);
02209     return H323GatekeeperRequest::Reject; 
02210   }
02211 
02212   rasChannel = &info.GetRasChannel();
02213   lastRegistration = PTime();
02214   protocolVersion = info.rrq.m_protocolIdentifier[5];
02215 
02216   timeToLive = gatekeeper.GetTimeToLive();
02217   if (info.rrq.HasOptionalField(H225_RegistrationRequest::e_timeToLive) &&
02218       timeToLive > info.rrq.m_timeToLive)
02219     timeToLive = info.rrq.m_timeToLive;
02220 
02221   if (timeToLive > 0) {
02222     info.rcf.IncludeOptionalField(H225_RegistrationRequest::e_timeToLive);
02223     info.rcf.m_timeToLive = timeToLive;
02224   }
02225 
02226   info.rcf.m_endpointIdentifier = identifier;
02227 
02228   UnlockReadWrite();
02229 
02230   if (info.rrq.m_keepAlive)
02231     return info.CheckCryptoTokens() ? H323GatekeeperRequest::Confirm
02232                                     : H323GatekeeperRequest::Reject;
02233 
02234   if (info.rrq.HasOptionalField(H225_RegistrationRequest::e_endpointIdentifier)) {
02235     // Make sure addresses are a superset of previous registration
02236     if (!IsTransportAddressSuperset(info.rrq.m_rasAddress, rasAddresses) ||
02237         !IsTransportAddressSuperset(info.rrq.m_callSignalAddress, signalAddresses) ||
02238         (info.rrq.HasOptionalField(H225_RegistrationRequest::e_terminalAlias) &&
02239          !IsAliasAddressSuperset(info.rrq.m_terminalAlias, aliases))) {
02240       info.SetRejectReason(H225_RegistrationRejectReason::e_discoveryRequired);
02241       PTRACE(2, "RAS\tRRQ rejected, not superset of existing registration.");
02242       return H323GatekeeperRequest::Reject;
02243     }
02244     PTRACE(3, "RAS\tFull RRQ received for already registered endpoint");
02245   }
02246 
02247   H323GatekeeperRequest::Response response = OnFullRegistration(info);
02248   if (response != H323GatekeeperRequest::Confirm)
02249     return response;
02250 
02251   // Final check, the H.235 security
02252   if (!info.CheckCryptoTokens())
02253     return H323GatekeeperRequest::Reject;
02254 
02255   PINDEX i;
02256 
02257   info.rcf.m_callSignalAddress.SetSize(signalAddresses.GetSize());
02258   for (i = 0; i < signalAddresses.GetSize(); i++)
02259     signalAddresses[i].SetPDU(info.rcf.m_callSignalAddress[i]);
02260 
02261   if (aliases.GetSize() > 0) {
02262     info.rcf.IncludeOptionalField(H225_RegistrationConfirm::e_terminalAlias);
02263     info.rcf.m_terminalAlias.SetSize(aliases.GetSize());
02264     for (i = 0; i < aliases.GetSize(); i++)
02265       H323SetAliasAddress(aliases[i], info.rcf.m_terminalAlias[i]);
02266   }
02267 
02268 #ifdef H323_H248
02269   if (canDisplayAmountString) {
02270     H323CallCreditServiceControl credit(GetCallCreditAmount(), GetCallCreditMode());
02271     if (AddServiceControlSession(credit, info.rcf.m_serviceControl))
02272       info.rcf.IncludeOptionalField(H225_RegistrationConfirm::e_serviceControl);
02273   }
02274 #endif
02275 
02276 #ifdef H323_H501
02277 
02278   // If have peer element, so add/update a descriptor for ep.
02279   H323PeerElement * peerElement = gatekeeper.GetPeerElement();
02280   if (peerElement != NULL) {
02281 
02282     H225_ArrayOf_AliasAddress transportAddresses;
02283     H323SetAliasAddresses(signalAddresses, transportAddresses);
02284     H225_EndpointType terminalType    = info.rrq.m_terminalType;
02285     H225_ArrayOf_AliasAddress aliases = info.rcf.m_terminalAlias;
02286 
02287     if (OnSendDescriptorForEndpoint(aliases, terminalType, transportAddresses)) {
02288       H501_ArrayOf_AddressTemplate addressTemplates;
02289       addressTemplates.SetSize(1);
02290       H323PeerElementDescriptor::CopyToAddressTemplate(addressTemplates[0],
02291                                                        terminalType,        // info.rrq.m_terminalType,
02292                                                        aliases,             // info.rcf.m_terminalAlias,
02293                                                        transportAddresses);
02294       peerElement->AddDescriptor(descriptorID,
02295                                  H323PeerElement::LocalServiceRelationshipOrdinal,
02296                                  addressTemplates,
02297                                  PTime());
02298     }
02299   }
02300 
02301 #endif
02302 
02303   return H323GatekeeperRequest::Confirm;
02304 }
02305 
02306 
02307 H323GatekeeperRequest::Response H323RegisteredEndPoint::OnFullRegistration(H323GatekeeperRRQ & info)
02308 {
02309   if (!LockReadWrite()) {
02310     PTRACE(1, "RAS\tRRQ rejected, lock failed on endpoint " << *this);
02311     return H323GatekeeperRequest::Reject;
02312   }
02313 
02314   isBehindNAT = info.IsBehindNAT();
02315   rasAddresses = info.GetReplyAddresses();
02316 
02317   signalAddresses = H323TransportAddressArray(info.rrq.m_callSignalAddress);
02318   if (signalAddresses.IsEmpty()) {
02319     UnlockReadWrite();
02320     info.SetRejectReason(H225_RegistrationRejectReason::e_invalidCallSignalAddress);
02321     return H323GatekeeperRequest::Reject;
02322   }
02323 
02324   if (isBehindNAT) {
02325     // Need to (maybe) massage the signalling addresses
02326     H323EndPoint & ep = rasChannel->GetEndPoint();
02327     WORD listenerPort = 0;
02328 
02329     PINDEX i;
02330     for (i = 0; i < signalAddresses.GetSize(); i++) {
02331       PIPSocket::Address ip;
02332       WORD port;
02333       if (signalAddresses[i].GetIpAndPort(ip, port)) {
02334         if (!ep.IsLocalAddress(ip))
02335           break;
02336         if (listenerPort == 0)
02337           listenerPort = port; // Have a private address, save the port
02338       }
02339     }
02340 
02341     if (i < signalAddresses.GetSize()) {
02342       // Found a public address in the list, make sure it is the first entry
02343       if (i > 0) {
02344         H323TransportAddress addr = signalAddresses[0];
02345         signalAddresses[0] = signalAddresses[i];
02346         signalAddresses[i] = addr;
02347       }
02348     }
02349     else if (listenerPort != 0) {
02350       // If did not have a public signalling address, but did have a private
02351       // one, then we insert at the begining an entry on the same port but
02352       // using the public address from the RAS. This will not work for all
02353       // NAT types, but will for some, eg symmetric with port forwarding which
02354       // is a common configuration for Linux based routers.
02355       i = signalAddresses.GetSize()-1;
02356       signalAddresses.AppendAddress(signalAddresses[i]);
02357       while (--i > 0)
02358         signalAddresses[i] = signalAddresses[i-1];
02359       PIPSocket::Address natAddress;
02360       rasAddresses[0].GetIpAddress(natAddress);
02361       signalAddresses[0] = H323TransportAddress(natAddress, listenerPort);
02362     }
02363   }
02364 
02365   if (info.rrq.HasOptionalField(H225_RegistrationRequest::e_terminalAlias))
02366     aliases = GetAliasAddressArray(info.rrq.m_terminalAlias);
02367 
02368   const H225_EndpointType & terminalType = info.rrq.m_terminalType;
02369   if (terminalType.HasOptionalField(H225_EndpointType::e_gateway) &&
02370       terminalType.m_gateway.HasOptionalField(H225_GatewayInfo::e_protocol)) {
02371     const H225_ArrayOf_SupportedProtocols & protocols = terminalType.m_gateway.m_protocol;
02372     for (PINDEX i = 0; i < protocols.GetSize(); i++) {
02373 
02374       // Only voice prefixes are supported
02375       if (protocols[i].GetTag() == H225_SupportedProtocols::e_voice) {
02376               H225_VoiceCaps & voiceCaps = protocols[i];
02377               if (voiceCaps.HasOptionalField(H225_VoiceCaps::e_supportedPrefixes)) {
02378                 H225_ArrayOf_SupportedPrefix & prefixes = voiceCaps.m_supportedPrefixes;
02379                 voicePrefixes.SetSize(prefixes.GetSize());
02380                 for (PINDEX j = 0; j < prefixes.GetSize(); j++) {
02381                   PString prefix = H323GetAliasAddressString(prefixes[j].m_prefix);
02382                   voicePrefixes[j] = prefix;
02383                 }
02384               }
02385               break;  // If voice protocol is found, don't look any further
02386       }
02387     }
02388   }
02389 
02390   applicationInfo = H323GetApplicationInfo(info.rrq.m_endpointVendor);
02391 
02392   canDisplayAmountString = FALSE;
02393   canEnforceDurationLimit = FALSE;
02394   if (info.rrq.HasOptionalField(H225_RegistrationRequest::e_callCreditCapability)) {
02395     if (info.rrq.m_callCreditCapability.HasOptionalField(H225_CallCreditCapability::e_canDisplayAmountString))
02396       canDisplayAmountString = info.rrq.m_callCreditCapability.m_canDisplayAmountString;
02397     if (info.rrq.m_callCreditCapability.HasOptionalField(H225_CallCreditCapability::e_canEnforceDurationLimit))
02398       canEnforceDurationLimit = info.rrq.m_callCreditCapability.m_canEnforceDurationLimit;
02399   }
02400 
02401   h225Version = 0;
02402   PUnsignedArray protocolVer = info.rrq.m_protocolIdentifier.GetValue();
02403   if (protocolVer.GetSize() >= 6)
02404     h225Version = protocolVer[5];
02405 
02406   H323GatekeeperRequest::Response respone = OnSecureRegistration(info);
02407 
02408   UnlockReadWrite();
02409 
02410   return respone;
02411 }
02412 
02413 
02414 H323GatekeeperRequest::Response H323RegisteredEndPoint::OnSecureRegistration(H323GatekeeperRRQ & info)
02415 {
02416   for (PINDEX i = 0; i < aliases.GetSize(); i++) {
02417     PString password;
02418     if (gatekeeper.GetUsersPassword(aliases[i], password, *this)) {
02419       PTRACE(3, "RAS\tFound user " << aliases[i] << " for H.235 security.");
02420       if (!password)
02421         SetPassword(password, aliases[i]);
02422       return H323GatekeeperRequest::Confirm;
02423     }
02424   }
02425 
02426   if (gatekeeper.IsRequiredH235()) {
02427     PTRACE(2, "RAS\tRejecting RRQ, no aliases have a password.");
02428     info.SetRejectReason(H225_RegistrationRejectReason::e_securityDenial);
02429     return H323GatekeeperRequest::Reject;
02430   }
02431 
02432   return H323GatekeeperRequest::Confirm;
02433 }
02434 
02435 
02436 BOOL H323RegisteredEndPoint::SetPassword(const PString & password,
02437                                          const PString & username)
02438 {
02439   if (authenticators.IsEmpty() || password.IsEmpty())
02440     return FALSE;
02441 
02442   PTRACE(3, "RAS\tSetting password and enabling H.235 security for " << *this);
02443   for (PINDEX i = 0; i < authenticators.GetSize(); i++) {
02444     H235Authenticator & authenticator = authenticators[i];
02445     authenticator.SetPassword(password);
02446     if (!username && !authenticator.UseGkAndEpIdentifiers())
02447       authenticator.SetRemoteId(username);
02448     authenticator.Enable();
02449   }
02450 
02451   return TRUE;
02452 }
02453 
02454 
02455 H323GatekeeperRequest::Response H323RegisteredEndPoint::OnUnregistration(H323GatekeeperURQ & info)
02456 {
02457   PTRACE_BLOCK("H323RegisteredEndPoint::OnUnregistration");
02458 
02459   if (activeCalls.GetSize() > 0) {
02460     info.SetRejectReason(H225_UnregRejectReason::e_callInProgress);
02461     return H323GatekeeperRequest::Reject;
02462   }
02463 
02464   return H323GatekeeperRequest::Confirm;
02465 }
02466 
02467 
02468 BOOL H323RegisteredEndPoint::Unregister(int reason)
02469 {
02470   if (reason == -1)
02471     reason = H225_UnregRequestReason::e_maintenance;
02472 
02473   BOOL ok;
02474 
02475   // Send DRQ to endpoint(s)
02476   if (rasChannel != NULL)
02477     ok = rasChannel->UnregistrationRequest(*this, reason);
02478   else {
02479     // Can't do DRQ as have no RAS channel to use (probably logic error)
02480     PAssertAlways("Tried to unregister endpoint we did not receive RRQ for!");
02481     ok = FALSE;
02482   }
02483 
02484   gatekeeper.RemoveEndPoint(this);
02485 
02486   return ok;
02487 }
02488 
02489 
02490 H323GatekeeperRequest::Response H323RegisteredEndPoint::OnInfoResponse(H323GatekeeperIRR & info)
02491 {
02492   PTRACE_BLOCK("H323RegisteredEndPoint::OnInfoResponse");
02493 
02494   if (!LockReadWrite()) {
02495     PTRACE(1, "RAS\tIRR rejected, lock failed on endpoint " << *this);
02496     return H323GatekeeperRequest::Reject; 
02497   }
02498 
02499   lastInfoResponse = PTime();
02500   UnlockReadWrite();
02501 
02502   if (info.irr.HasOptionalField(H225_InfoRequestResponse::e_irrStatus) &&
02503       info.irr.m_irrStatus.GetTag() == H225_InfoRequestResponseStatus::e_invalidCall) {
02504     PTRACE(2, "RAS\tIRR for call-id endpoint does not know about");
02505     return H323GatekeeperRequest::Confirm;
02506   }
02507     
02508 
02509   if (!info.irr.HasOptionalField(H225_InfoRequestResponse::e_perCallInfo)) {
02510     // Special case for Innovaphone clients that do not contain a perCallInfo
02511     // field and expects that to mean "all calls a normal".
02512     if (protocolVersion < 5 && applicationInfo.Find("innovaphone") != P_MAX_INDEX) {
02513       H225_InfoRequestResponse_perCallInfo_subtype fakeCallInfo;
02514       if (!LockReadOnly()) {
02515         PTRACE(1, "RAS\tIRR rejected, lock failed on endpoint " << *this);
02516         return H323GatekeeperRequest::Reject; 
02517       }
02518       for (PINDEX i = 0; i < activeCalls.GetSize(); i++)
02519         activeCalls[i].OnInfoResponse(info, fakeCallInfo);
02520       UnlockReadOnly();
02521     }
02522 
02523     PTRACE(2, "RAS\tIRR for call-id endpoint does not know about");
02524     return H323GatekeeperRequest::Confirm;
02525   }
02526 
02527   if (!LockReadOnly()) {
02528     PTRACE(1, "RAS\tIRR rejected, lock failed on endpoint " << *this);
02529     return H323GatekeeperRequest::Reject; 
02530   }
02531 
02532   for (PINDEX i = 0; i < info.irr.m_perCallInfo.GetSize(); i++) {
02533     H225_InfoRequestResponse_perCallInfo_subtype & perCallInfo = info.irr.m_perCallInfo[i];
02534 
02535     // Some systems don't say what direction the call is so find it in the
02536     // list regardless of the direction
02537     H323GatekeeperCall::Direction callDirection;
02538     if (!perCallInfo.HasOptionalField(H225_InfoRequestResponse_perCallInfo_subtype::e_originator))
02539       callDirection = H323GatekeeperCall::UnknownDirection;
02540     else if (perCallInfo.m_originator)
02541       callDirection = H323GatekeeperCall::OriginatingCall;
02542     else
02543       callDirection = H323GatekeeperCall::AnsweringCall;
02544 
02545     H323GatekeeperCall search(gatekeeper, perCallInfo.m_callIdentifier.m_guid, callDirection);
02546 
02547     PINDEX idx = activeCalls.GetValuesIndex(search);
02548     if (idx != P_MAX_INDEX) {
02549       activeCalls[idx].OnInfoResponse(info, perCallInfo);
02550 
02551       if (callDirection == H323GatekeeperCall::UnknownDirection) {
02552         // There could be two call entries (originator or destination) and the
02553         // ep did not say which. GetValuesIndex() always give the first one so
02554         // see if the next one is also a match
02555         if (idx < activeCalls.GetSize()-1 && activeCalls[idx+1] == search)
02556           activeCalls[idx+1].OnInfoResponse(info, perCallInfo);
02557       }
02558     }
02559     else {
02560       PTRACE(2, "RAS\tEndpoint has call-id gatekeeper does not know about: " << search);
02561     }
02562   }
02563 
02564   UnlockReadOnly();
02565 
02566   return H323GatekeeperRequest::Confirm;
02567 }
02568 
02569 
02570 BOOL H323RegisteredEndPoint::OnTimeToLive()
02571 {
02572   if (!LockReadOnly()) {
02573     PTRACE(1, "RAS\tOnTimeToLive lock failed on endpoint " << *this);
02574     return FALSE;
02575   }
02576 
02577   if (CheckTimeSince(lastRegistration, timeToLive) ||
02578       CheckTimeSince(lastInfoResponse, timeToLive)) {
02579     UnlockReadOnly();
02580     return TRUE;
02581   }
02582 
02583   // Can't do IRQ as have no RAS channel to use (probably logic error)
02584   if (rasChannel == NULL) {
02585     UnlockReadOnly();
02586     PAssertAlways("Timeout on time to live for endpoint we did not receive RRQ for!");
02587     return FALSE;
02588   }
02589 
02590   UnlockReadOnly();
02591 
02592   // Do IRQ and wait for IRR on call
02593   PTRACE(2, "RAS\tTime to live, doing IRQ for endpoint "<< *this);
02594   if (!rasChannel->InfoRequest(*this))
02595     return FALSE;
02596 
02597   if (!LockReadOnly()) {
02598     PTRACE(1, "RAS\tOnTimeToLive lock failed on endpoint " << *this);
02599     return FALSE;
02600   }
02601 
02602   // Return TRUE if got a resonse, ie client does not do unsolicited IRR's
02603   // otherwise did not get a response from client so return FALSE and
02604   // (probably) disengage the call.
02605   BOOL response = CheckTimeSince(lastInfoResponse, timeToLive);
02606 
02607   UnlockReadOnly();
02608 
02609   return response;
02610 }
02611 
02612 #ifdef H323_H248
02613 
02614 PString H323RegisteredEndPoint::GetCallCreditAmount() const
02615 {
02616   return PString::Empty();
02617 }
02618 
02619 
02620 BOOL H323RegisteredEndPoint::GetCallCreditMode() const
02621 {
02622   return TRUE;
02623 }
02624 
02625 
02626 BOOL H323RegisteredEndPoint::SendServiceControlSession(const H323ServiceControlSession & session)
02627 {
02628   // Send SCI to endpoint(s)
02629   if (rasChannel == NULL) {
02630     // Can't do SCI as have no RAS channel to use (probably logic error)
02631     PAssertAlways("Tried to do SCI to endpoint we did not receive RRQ for!");
02632     return FALSE;
02633   }
02634 
02635   return rasChannel->ServiceControlIndication(*this, session);
02636 }
02637 
02638 
02639 BOOL H323RegisteredEndPoint::AddServiceControlSession(const H323ServiceControlSession & session,
02640                                                       H225_ArrayOf_ServiceControlSession & serviceControl)
02641 {
02642   if (!session.IsValid())
02643     return FALSE;
02644 
02645   PString type = session.GetServiceControlType();
02646 
02647   H225_ServiceControlSession_reason::Choices reason = H225_ServiceControlSession_reason::e_refresh;
02648   if (!serviceControlSessions.Contains(type)) {
02649     PINDEX id = 0;
02650     PINDEX i = 0;
02651     while (i < serviceControlSessions.GetSize()) {
02652       if (id != serviceControlSessions.GetDataAt(i))
02653         i++;
02654       else {
02655         if (++id >= 256)
02656           return FALSE;
02657         i = 0;
02658       }
02659     }
02660     serviceControlSessions.SetAt(type, id);
02661     reason = H225_ServiceControlSession_reason::e_open;
02662   }
02663 
02664   PINDEX last = serviceControl.GetSize();
02665   serviceControl.SetSize(last+1);
02666   H225_ServiceControlSession & pdu = serviceControl[last];
02667 
02668   pdu.m_sessionId = serviceControlSessions[type];
02669   pdu.m_reason = reason;
02670 
02671   if (session.OnSendingPDU(pdu.m_contents))
02672     pdu.IncludeOptionalField(H225_ServiceControlSession::e_contents);
02673 
02674   return TRUE;
02675 }
02676 
02677 #endif // H323_H248
02678 
02679 
02680 BOOL H323RegisteredEndPoint::CanReceiveRIP() const
02681 { 
02682   // H225v1 does not support RIP
02683   // neither does NetMeeting, even though it says it is H225v2. 
02684   return (h225Version > 1) && (applicationInfo.Find("netmeeting") == P_MAX_INDEX);
02685 }
02686 
02687 #ifdef H323_H501
02688 
02689 BOOL H323RegisteredEndPoint::OnSendDescriptorForEndpoint(
02690         H225_ArrayOf_AliasAddress & aliases,          // aliases for the enndpoint
02691         H225_EndpointType & terminalType,             // terminal type
02692         H225_ArrayOf_AliasAddress & transportAddresses  // transport addresses
02693       )
02694 { 
02695   return gatekeeper.OnSendDescriptorForEndpoint(*this, aliases, terminalType, transportAddresses); 
02696 }
02697 
02698 #endif
02699 
02701 
02702 H323GatekeeperListener::H323GatekeeperListener(H323EndPoint & ep,
02703                                                H323GatekeeperServer & gk,
02704                                                const PString & id,
02705                                                H323Transport * trans)
02706   : H225_RAS(ep, trans),
02707     gatekeeper(gk)
02708 {
02709   gatekeeperIdentifier = id;
02710 
02711   transport->SetPromiscuous(H323Transport::AcceptFromAny);
02712 
02713   PTRACE(2, "H323gk\tGatekeeper server created.");
02714 }
02715 
02716 
02717 H323GatekeeperListener::~H323GatekeeperListener()
02718 {
02719   StopChannel();
02720   PTRACE(2, "H323gk\tGatekeeper server destroyed.");
02721 }
02722 
02723 
02724 H323GatekeeperRequest::Response H323GatekeeperListener::OnDiscovery(H323GatekeeperGRQ & info)
02725 {
02726   PTRACE_BLOCK("H323GatekeeperListener::OnDiscovery");
02727 
02728   if (info.grq.m_protocolIdentifier.GetSize() != 6 || info.grq.m_protocolIdentifier[5] < 2) {
02729     info.SetRejectReason(H225_GatekeeperRejectReason::e_invalidRevision);
02730     PTRACE(2, "RAS\tGRQ rejected, version 1 not supported");
02731     return H323GatekeeperRequest::Reject;
02732   }
02733 
02734   if (!info.CheckGatekeeperIdentifier())
02735     return H323GatekeeperRequest::Reject;
02736 
02737   // cannot use commented code because transport->remoteAddr is
02738   // not set on broadcast PDUs
02739   //      transport->SetUpTransportPDU(info.gcf.m_rasAddress, TRUE);
02740   {
02741     PIPSocket::Address localAddr, remoteAddr;
02742     WORD localPort;
02743     transport->GetLocalAddress().GetIpAndPort(localAddr, localPort);
02744     H323TransportAddress(info.grq.m_rasAddress).GetIpAddress(remoteAddr);
02745     endpoint.InternalTranslateTCPAddress(localAddr, remoteAddr);
02746     endpoint.TranslateTCPPort(localPort,remoteAddr);
02747     H323TransportAddress newAddr = H323TransportAddress(localAddr, localPort);
02748 
02749     H225_TransportAddress & pdu = info.gcf.m_rasAddress;
02750     newAddr.SetPDU(pdu);
02751   }
02752 
02753   return gatekeeper.OnDiscovery(info);
02754 }
02755 
02756 
02757 BOOL H323GatekeeperListener::OnReceiveGatekeeperRequest(const H323RasPDU & pdu,
02758                                                         const H225_GatekeeperRequest & /*grq*/)
02759 {
02760   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveGatekeeperRequest");
02761 
02762   H323GatekeeperGRQ * info = new H323GatekeeperGRQ(*this, pdu);
02763   if (!info->HandlePDU())
02764     delete info;
02765 
02766   return FALSE;
02767 }
02768 
02769 
02770 H323GatekeeperRequest::Response H323GatekeeperListener::OnRegistration(H323GatekeeperRRQ & info)
02771 {
02772   PTRACE_BLOCK("H323GatekeeperListener::OnRegistration");
02773 
02774   if (info.rrq.HasOptionalField(H225_RegistrationRequest::e_endpointIdentifier))
02775     info.endpoint = gatekeeper.FindEndPointByIdentifier(info.rrq.m_endpointIdentifier);
02776 
02777   if (!info.CheckGatekeeperIdentifier())
02778     return H323GatekeeperRequest::Reject;
02779 
02780   if (info.rrq.m_protocolIdentifier.GetSize() != 6 || info.rrq.m_protocolIdentifier[5] < 2) {
02781     info.SetRejectReason(H225_RegistrationRejectReason::e_invalidRevision);
02782     PTRACE(2, "RAS\tRRQ rejected, version 1 not supported");
02783     return H323GatekeeperRequest::Reject;
02784   }
02785 
02786   H323GatekeeperRequest::Response response = gatekeeper.OnRegistration(info);
02787   if (response != H323GatekeeperRequest::Confirm)
02788     return response;
02789 
02790   // Adjust the authenticator remote ID to endpoint ID
02791   if (!info.rrq.m_keepAlive) {
02792     PSafePtr<H323RegisteredEndPoint> lock(info.endpoint, PSafeReadWrite);
02793     H235Authenticators authenticators = info.endpoint->GetAuthenticators();
02794     for (PINDEX i = 0; i < authenticators.GetSize(); i++) {
02795       H235Authenticator & authenticator = authenticators[i];
02796       if (authenticator.UseGkAndEpIdentifiers()) {
02797         authenticator.SetRemoteId(info.endpoint->GetIdentifier());
02798         authenticator.SetLocalId(gatekeeperIdentifier);
02799       }
02800     }
02801   }
02802 
02803   return H323GatekeeperRequest::Confirm;
02804 }
02805 
02806 
02807 BOOL H323GatekeeperListener::OnReceiveRegistrationRequest(const H323RasPDU & pdu,
02808                                                           const H225_RegistrationRequest & /*rrq*/)
02809 {
02810   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveRegistrationRequest");
02811 
02812   H323GatekeeperRRQ * info = new H323GatekeeperRRQ(*this, pdu);
02813   if (!info->HandlePDU())
02814     delete info;
02815 
02816   return FALSE;
02817 }
02818 
02819 
02820 H323GatekeeperRequest::Response H323GatekeeperListener::OnUnregistration(H323GatekeeperURQ & info)
02821 {
02822   PTRACE_BLOCK("H323GatekeeperListener::OnUnregistration");
02823 
02824   if (info.urq.HasOptionalField(H225_UnregistrationRequest::e_endpointIdentifier))
02825     info.endpoint = gatekeeper.FindEndPointByIdentifier(info.urq.m_endpointIdentifier);
02826   else
02827     info.endpoint = gatekeeper.FindEndPointBySignalAddresses(info.urq.m_callSignalAddress);
02828 
02829   if (info.endpoint == NULL) {
02830     info.SetRejectReason(H225_UnregRejectReason::e_notCurrentlyRegistered);
02831     PTRACE(2, "RAS\tURQ rejected, not registered");
02832     return H323GatekeeperRequest::Reject;
02833   }
02834 
02835   return gatekeeper.OnUnregistration(info);
02836 }
02837 
02838 
02839 BOOL H323GatekeeperListener::OnReceiveUnregistrationRequest(const H323RasPDU & pdu,
02840                                                             const H225_UnregistrationRequest & /*urq*/)
02841 {
02842   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveUnregistrationRequest");
02843 
02844   H323GatekeeperURQ * info = new H323GatekeeperURQ(*this, pdu);
02845   if (!info->HandlePDU())
02846     delete info;
02847 
02848   return FALSE;
02849 }
02850 
02851 
02852 BOOL H323GatekeeperListener::OnReceiveUnregistrationConfirm(const H225_UnregistrationConfirm & pdu)
02853 {
02854   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveUnregistrationConfirm");
02855 
02856   if (!H225_RAS::OnReceiveUnregistrationConfirm(pdu))
02857     return FALSE;
02858 
02859   return TRUE;
02860 }
02861 
02862 
02863 BOOL H323GatekeeperListener::OnReceiveUnregistrationReject(const H225_UnregistrationReject & pdu)
02864 {
02865   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveUnregistrationReject");
02866 
02867   if (!H225_RAS::OnReceiveUnregistrationReject(pdu))
02868     return FALSE;
02869 
02870   return TRUE;
02871 }
02872 
02873 
02874 H323GatekeeperRequest::Response H323GatekeeperListener::OnAdmission(H323GatekeeperARQ & info)
02875 {
02876   PTRACE_BLOCK("H323GatekeeperListener::OnAdmission");
02877 
02878   if (!info.CheckGatekeeperIdentifier())
02879     return H323GatekeeperRequest::Reject;
02880 
02881   if (!info.GetRegisteredEndPoint())
02882     return H323GatekeeperRequest::Reject;
02883 
02884   if (!info.CheckCryptoTokens()) {
02885     H235Authenticators adjustedAuthenticators;
02886     if (!gatekeeper.GetAdmissionRequestAuthentication(info, adjustedAuthenticators))
02887       return H323GatekeeperRequest::Reject;
02888 
02889     PTRACE(3, "RAS\tARQ received with separate credentials: "
02890            << setfill(',') << adjustedAuthenticators << setfill(' '));
02891     if (!info.H323Transaction::CheckCryptoTokens(adjustedAuthenticators)) {
02892       PTRACE(2, "RAS\tARQ rejected, alternate security tokens invalid.");
02893 
02894       return H323GatekeeperRequest::Reject;
02895     }
02896 
02897     if (info.alternateSecurityID.IsEmpty() && !adjustedAuthenticators.IsEmpty())
02898       info.alternateSecurityID = adjustedAuthenticators[0].GetRemoteId();
02899   }
02900 
02901   H323GatekeeperRequest::Response response = gatekeeper.OnAdmission(info);
02902   if (response != H323GatekeeperRequest::Confirm)
02903     return response;
02904 
02905   if (info.acf.m_callModel.GetTag() == H225_CallModel::e_gatekeeperRouted) {
02906     H225_ArrayOf_TransportAddress addresses;
02907     if (SetUpCallSignalAddresses(addresses))
02908       info.acf.m_destCallSignalAddress = addresses[0];
02909   }
02910 
02911   return H323GatekeeperRequest::Confirm;
02912 }
02913 
02914 
02915 BOOL H323GatekeeperListener::OnReceiveAdmissionRequest(const H323RasPDU & pdu,
02916                                                        const H225_AdmissionRequest & /*arq*/)
02917 {
02918   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveAdmissionRequest");
02919 
02920   H323GatekeeperARQ * info = new H323GatekeeperARQ(*this, pdu);
02921   if (!info->HandlePDU())
02922     delete info;
02923 
02924   return FALSE;
02925 }
02926 
02927 
02928 BOOL H323GatekeeperListener::UnregistrationRequest(const H323RegisteredEndPoint & ep,
02929                                                    unsigned reason)
02930 {
02931   PTRACE(3, "RAS\tUnregistration request to endpoint " << ep);
02932 
02933   H323RasPDU pdu(ep.GetAuthenticators());
02934   H225_UnregistrationRequest & urq = pdu.BuildUnregistrationRequest(GetNextSequenceNumber());
02935 
02936   urq.IncludeOptionalField(H225_UnregistrationRequest::e_gatekeeperIdentifier);
02937   urq.m_gatekeeperIdentifier = gatekeeperIdentifier;
02938 
02939   urq.m_callSignalAddress.SetSize(ep.GetSignalAddressCount());
02940   for (PINDEX i = 0; i < ep.GetSignalAddressCount(); i++)
02941     ep.GetSignalAddress(i).SetPDU(urq.m_callSignalAddress[i]);
02942 
02943   urq.IncludeOptionalField(H225_UnregistrationRequest::e_endpointIdentifier);
02944   urq.m_endpointIdentifier = ep.GetIdentifier();
02945   urq.m_reason.SetTag(reason);
02946 
02947   Request request(urq.m_requestSeqNum, pdu, ep.GetRASAddresses());
02948   return MakeRequest(request);
02949 }
02950 
02951 
02952 BOOL H323GatekeeperListener::DisengageRequest(const H323GatekeeperCall & call,
02953                                               unsigned reason)
02954 {
02955   H323RegisteredEndPoint & ep = call.GetEndPoint();
02956 
02957   PTRACE(3, "RAS\tDisengage request to endpoint " << ep << " call " << call);
02958 
02959   H323RasPDU pdu(ep.GetAuthenticators());
02960   H225_DisengageRequest & drq = pdu.BuildDisengageRequest(GetNextSequenceNumber());
02961 
02962   drq.IncludeOptionalField(H225_DisengageRequest::e_gatekeeperIdentifier);
02963   drq.m_gatekeeperIdentifier = gatekeeperIdentifier;
02964 
02965   drq.m_endpointIdentifier = ep.GetIdentifier();
02966   drq.m_conferenceID = call.GetConferenceIdentifier();
02967   drq.m_callReferenceValue = call.GetCallReference();
02968   drq.m_callIdentifier.m_guid = call.GetCallIdentifier();
02969   drq.m_disengageReason.SetTag(reason);
02970   drq.m_answeredCall = call.IsAnsweringCall();
02971 
02972 #ifdef H323_H248
02973   if (call.AddCallCreditServiceControl(drq.m_serviceControl))
02974     drq.IncludeOptionalField(H225_DisengageRequest::e_serviceControl);
02975 #endif
02976 
02977   Request request(drq.m_requestSeqNum, pdu, ep.GetRASAddresses());
02978   return MakeRequest(request);
02979 }
02980 
02981 
02982 H323GatekeeperRequest::Response H323GatekeeperListener::OnDisengage(H323GatekeeperDRQ & info)
02983 {
02984   PTRACE_BLOCK("H323GatekeeperListener::OnDisengage");
02985 
02986   if (!info.CheckGatekeeperIdentifier())
02987     return H323GatekeeperRequest::Reject;
02988 
02989   if (!info.GetRegisteredEndPoint())
02990     return H323GatekeeperRequest::Reject;
02991 
02992   if (!info.CheckCryptoTokens())
02993     return H323GatekeeperRequest::Reject;
02994 
02995   return gatekeeper.OnDisengage(info);
02996 }
02997 
02998 
02999 BOOL H323GatekeeperListener::OnReceiveDisengageRequest(const H323RasPDU & pdu,
03000                                                        const H225_DisengageRequest & /*drq*/)
03001 {
03002   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveDisengageRequest");
03003 
03004   H323GatekeeperDRQ * info = new H323GatekeeperDRQ(*this, pdu);
03005   if (!info->HandlePDU())
03006     delete info;
03007 
03008   return FALSE;
03009 }
03010 
03011 
03012 BOOL H323GatekeeperListener::OnReceiveDisengageConfirm(const H225_DisengageConfirm & pdu)
03013 {
03014   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveDisengageConfirm");
03015 
03016   if (!H225_RAS::OnReceiveDisengageConfirm(pdu))
03017     return FALSE;
03018 
03019   return TRUE;
03020 }
03021 
03022 
03023 BOOL H323GatekeeperListener::OnReceiveDisengageReject(const H225_DisengageReject & drj)
03024 {
03025   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveDisengageReject");
03026 
03027   if (!H225_RAS::OnReceiveDisengageReject(drj))
03028     return FALSE;
03029 
03030   return TRUE;
03031 }
03032 
03033 
03034 H323GatekeeperRequest::Response H323GatekeeperListener::OnBandwidth(H323GatekeeperBRQ & info)
03035 {
03036   PTRACE_BLOCK("H323GatekeeperListener::OnBandwidth");
03037 
03038   if (!info.CheckGatekeeperIdentifier())
03039     return H323GatekeeperRequest::Reject;
03040 
03041   if (!info.GetRegisteredEndPoint())
03042     return H323GatekeeperRequest::Reject;
03043 
03044   if (!info.CheckCryptoTokens())
03045     return H323GatekeeperRequest::Reject;
03046 
03047   return gatekeeper.OnBandwidth(info);
03048 }
03049 
03050 
03051 BOOL H323GatekeeperListener::OnReceiveBandwidthRequest(const H323RasPDU & pdu,
03052                                                        const H225_BandwidthRequest & /*brq*/)
03053 {
03054   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveBandwidthRequest");
03055 
03056   H323GatekeeperBRQ * info = new H323GatekeeperBRQ(*this, pdu);
03057   if (!info->HandlePDU())
03058     delete info;
03059 
03060   return FALSE;
03061 }
03062 
03063 
03064 BOOL H323GatekeeperListener::OnReceiveBandwidthConfirm(const H225_BandwidthConfirm & pdu)
03065 {
03066   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveBandwidthConfirm");
03067 
03068   if (!H225_RAS::OnReceiveBandwidthConfirm(pdu))
03069     return FALSE;
03070 
03071   return TRUE;
03072 }
03073 
03074 
03075 BOOL H323GatekeeperListener::OnReceiveBandwidthReject(const H225_BandwidthReject & pdu)
03076 {
03077   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveBandwidthReject");
03078 
03079   if (!H225_RAS::OnReceiveBandwidthReject(pdu))
03080     return FALSE;
03081 
03082   return TRUE;
03083 }
03084 
03085 
03086 H323GatekeeperRequest::Response H323GatekeeperListener::OnLocation(H323GatekeeperLRQ & info)
03087 {
03088   PTRACE_BLOCK("H323GatekeeperListener::OnLocation");
03089 
03090   if (!info.CheckGatekeeperIdentifier())
03091     return H323GatekeeperRequest::Reject;
03092 
03093   if (info.lrq.HasOptionalField(H225_LocationRequest::e_endpointIdentifier)) {
03094     if (!info.GetRegisteredEndPoint())
03095       return H323GatekeeperRequest::Reject;
03096     if (!info.CheckCryptoTokens())
03097       return H323GatekeeperRequest::Reject;
03098   }
03099 
03100   transport->SetUpTransportPDU(info.lcf.m_rasAddress, TRUE);
03101 
03102   return gatekeeper.OnLocation(info);
03103 }
03104 
03105 
03106 BOOL H323GatekeeperListener::OnReceiveLocationRequest(const H323RasPDU & pdu,
03107                                                       const H225_LocationRequest & /*lrq*/)
03108 {
03109   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveLocationRequest");
03110 
03111   H323GatekeeperLRQ * info = new H323GatekeeperLRQ(*this, pdu);
03112   if (!info->HandlePDU())
03113     delete info;
03114 
03115   return FALSE;
03116 }
03117 
03118 
03119 BOOL H323GatekeeperListener::InfoRequest(H323RegisteredEndPoint & ep,
03120                                          H323GatekeeperCall * call)
03121 {
03122   PTRACE(3, "RAS\tInfo request to endpoint " << ep);
03123 
03124   unsigned callReference = 0;
03125   const OpalGloballyUniqueID * callIdentifier = NULL;
03126   if (call != NULL) {
03127     callReference = call->GetCallReference();
03128     callIdentifier = &call->GetCallIdentifier();
03129   }
03130 
03131   // As sequence number 1 is used for backward compatibility on unsolicited
03132   // IRR's we make sure we never makea  solicited IRQ using that number.
03133   unsigned seqnum = GetNextSequenceNumber();
03134   if (seqnum == 1)
03135     seqnum = GetNextSequenceNumber();
03136 
03137   H323RasPDU pdu(ep.GetAuthenticators());
03138   H225_InfoRequest & irq = pdu.BuildInfoRequest(seqnum, callReference, callIdentifier);
03139 
03140   H225_RAS::Request request(irq.m_requestSeqNum, pdu, ep.GetRASAddresses());
03141   return MakeRequest(request);
03142 }
03143 
03144 #ifdef H323_H248
03145 
03146 BOOL H323GatekeeperListener::ServiceControlIndication(H323RegisteredEndPoint & ep,
03147                                                       const H323ServiceControlSession & session,
03148                                                       H323GatekeeperCall * call)
03149 {
03150   PTRACE(3, "RAS\tService control request to endpoint " << ep);
03151 
03152   OpalGloballyUniqueID id = NULL;
03153   if (call != NULL)
03154     id = call->GetCallIdentifier();
03155 
03156   H323RasPDU pdu(ep.GetAuthenticators());
03157 
03158   H225_ServiceControlIndication & sci = pdu.BuildServiceControlIndication(GetNextSequenceNumber(), &id);
03159   ep.AddServiceControlSession(session, sci.m_serviceControl);
03160   H225_RAS::Request request(sci.m_requestSeqNum, pdu, ep.GetRASAddresses());
03161   return MakeRequest(request);
03162 }
03163 
03164 #endif
03165 
03166 H323GatekeeperRequest::Response H323GatekeeperListener::OnInfoResponse(H323GatekeeperIRR & info)
03167 {
03168   PTRACE_BLOCK("H323GatekeeperListener::OnInfoResponse");
03169 
03170   H323GatekeeperRequest::Response response;
03171   if (info.GetRegisteredEndPoint() && info.CheckCryptoTokens())
03172     response = gatekeeper.OnInfoResponse(info);
03173   else
03174     response = H323GatekeeperRequest::Reject;
03175 
03176   if (info.irr.m_unsolicited)
03177     return response;
03178 
03179   return H323GatekeeperRequest::Ignore;
03180 }
03181 
03182 
03183 BOOL H323GatekeeperListener::OnReceiveInfoRequestResponse(const H323RasPDU & pdu,
03184                                                           const H225_InfoRequestResponse & irr)
03185 {
03186   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveInfoRequestResponse");
03187 
03188   BOOL unsolicited = irr.m_unsolicited;
03189 
03190   if (!unsolicited) {
03191     // Got an IRR that is not marked as unsolicited but has sequence number of
03192     // one, thus according to 7.15.2/H.225.0 it actually IS unsolicited.
03193     if (irr.m_requestSeqNum == 1)
03194       unsolicited = TRUE;
03195     else {
03196       if (!H225_RAS::OnReceiveInfoRequestResponse(pdu, irr))
03197         return FALSE;
03198     }
03199   }
03200   else {
03201     if (SendCachedResponse(pdu))
03202       return FALSE;
03203   }
03204 
03205   H323GatekeeperIRR * info = new H323GatekeeperIRR(*this, pdu);
03206 
03207   info->irr.m_unsolicited = unsolicited;
03208 
03209   if (!info->HandlePDU())
03210     delete info;
03211 
03212   return !unsolicited;
03213 }
03214 
03215 
03216 BOOL H323GatekeeperListener::OnReceiveResourcesAvailableConfirm(const H225_ResourcesAvailableConfirm & pdu)
03217 {
03218   PTRACE_BLOCK("H323GatekeeperListener::OnReceiveResourcesAvailableConfirm");
03219 
03220   if (!H225_RAS::OnReceiveResourcesAvailableConfirm(pdu))
03221     return FALSE;
03222 
03223   return TRUE;
03224 }
03225 
03226 BOOL H323GatekeeperListener::OnSendFeatureSet(unsigned pduType, H225_FeatureSet & set) const
03227 {
03228   return gatekeeper.OnSendFeatureSet(pduType, set);
03229 }
03230 
03231 void H323GatekeeperListener::OnReceiveFeatureSet(unsigned pduType, const H225_FeatureSet & set) const
03232 {
03233   gatekeeper.OnReceiveFeatureSet(pduType, set);
03234 }
03235 
03237 
03238 H323GatekeeperServer::H323GatekeeperServer(H323EndPoint & ep)
03239   : H323TransactionServer(ep)
03240 {
03241   totalBandwidth = UINT_MAX;      // Unlimited total bandwidth
03242   usedBandwidth = 0;              // None used so far
03243   defaultBandwidth = 2560;        // Enough for bidirectional G.711 and 64k H.261
03244   maximumBandwidth = 200000;      // 10baseX LAN bandwidth
03245   defaultTimeToLive = 3600;       // One hour, zero disables
03246   defaultInfoResponseRate = 60;   // One minute, zero disables
03247   overwriteOnSameSignalAddress = TRUE;
03248   canHaveDuplicateAlias = FALSE;
03249   canHaveDuplicatePrefix = FALSE;
03250   canOnlyCallRegisteredEP = FALSE;
03251   canOnlyAnswerRegisteredEP = FALSE;
03252   answerCallPreGrantedARQ = FALSE;
03253   makeCallPreGrantedARQ = FALSE;
03254   isGatekeeperRouted = FALSE;
03255   aliasCanBeHostName = TRUE;
03256   requireH235 = FALSE;
03257   disengageOnHearbeatFail = TRUE;
03258 
03259   identifierBase = time(NULL);
03260   nextIdentifier = 1;
03261 
03262   peakRegistrations = 0;
03263   totalRegistrations = 0;
03264   rejectedRegistrations = 0;
03265   peakCalls = 0;
03266   totalCalls = 0;
03267   rejectedCalls = 0;
03268 
03269   monitorThread = PThread::Create(PCREATE_NOTIFIER(MonitorMain), 0,
03270                                   PThread::NoAutoDeleteThread,
03271                                   PThread::NormalPriority,
03272                                   "GkSrv Monitor");
03273 
03274 #ifdef H323_H501
03275   peerElement = NULL;
03276 #endif
03277 }
03278 
03279 
03280 H323GatekeeperServer::~H323GatekeeperServer()
03281 {
03282   monitorExit.Signal();
03283   PAssert(monitorThread->WaitForTermination(10000), "Gatekeeper monitor thread did not terminate!");
03284   delete monitorThread;
03285 
03286 #ifdef H323_H501
03287   delete peerElement;
03288 #endif
03289 }
03290 
03291 
03292 H323Transactor * H323GatekeeperServer::CreateListener(H323Transport * transport)
03293 {
03294   return new H323GatekeeperListener(ownerEndPoint, *this, gatekeeperIdentifier, transport);
03295 }
03296 
03297 
03298 H323GatekeeperRequest::Response H323GatekeeperServer::OnDiscovery(H323GatekeeperGRQ & info)
03299 {
03300   PTRACE_BLOCK("H323GatekeeperServer::OnDiscovery");
03301 
03302   H235Authenticators authenticators = ownerEndPoint.CreateAuthenticators();
03303   for (PINDEX auth = 0; auth < authenticators.GetSize(); auth++) {
03304     for (PINDEX cap = 0; cap < info.grq.m_authenticationCapability.GetSize(); cap++) {
03305       for (PINDEX alg = 0; alg < info.grq.m_algorithmOIDs.GetSize(); alg++) {
03306         if (authenticators[auth].IsCapability(info.grq.m_authenticationCapability[cap],
03307                                               info.grq.m_algorithmOIDs[alg])) {
03308           PTRACE(3, "RAS\tGRQ accepted on " << H323TransportAddress(info.gcf.m_rasAddress)
03309                  << " using authenticator " << authenticators[auth]);
03310           info.gcf.IncludeOptionalField(H225_GatekeeperConfirm::e_authenticationMode);
03311           info.gcf.m_authenticationMode = info.grq.m_authenticationCapability[cap];
03312           info.gcf.IncludeOptionalField(H225_GatekeeperConfirm::e_algorithmOID);
03313           info.gcf.m_algorithmOID = info.grq.m_algorithmOIDs[alg];
03314           return H323GatekeeperRequest::Confirm;
03315         }
03316       }
03317     }
03318   }
03319 
03320   PTRACE(3, "RAS\tGRQ accepted on " << H323TransportAddress(info.gcf.m_rasAddress));
03321   return H323GatekeeperRequest::Confirm;
03322 }
03323 
03324 
03325 H323GatekeeperRequest::Response H323GatekeeperServer::OnRegistration(H323GatekeeperRRQ & info)
03326 {
03327   PTRACE_BLOCK("H323GatekeeperServer::OnRegistration");
03328 
03329   PINDEX i;
03330 
03331   // Initialise reply with default stuff
03332   info.rcf.IncludeOptionalField(H225_RegistrationConfirm::e_preGrantedARQ);
03333   info.rcf.m_preGrantedARQ.m_answerCall = answerCallPreGrantedARQ;
03334   info.rcf.m_preGrantedARQ.m_useGKCallSignalAddressToAnswer = answerCallPreGrantedARQ && isGatekeeperRouted;
03335   info.rcf.m_preGrantedARQ.m_makeCall = makeCallPreGrantedARQ;
03336   info.rcf.m_preGrantedARQ.m_useGKCallSignalAddressToMakeCall = makeCallPreGrantedARQ && isGatekeeperRouted;
03337   info.rcf.m_willRespondToIRR = TRUE;
03338 
03339   if (defaultInfoResponseRate > 0 && info.rrq.m_protocolIdentifier[5] > 2) {
03340     info.rcf.m_preGrantedARQ.IncludeOptionalField(H225_RegistrationConfirm_preGrantedARQ::e_irrFrequencyInCall);
03341     info.rcf.m_preGrantedARQ.m_irrFrequencyInCall = defaultInfoResponseRate;
03342   }
03343 
03344   if (info.rrq.m_keepAlive) {
03345     if (info.endpoint != NULL)
03346       return info.endpoint->OnRegistration(info);
03347 
03348     info.SetRejectReason(H225_RegistrationRejectReason::e_fullRegistrationRequired);
03349     PTRACE(2, "RAS\tRRQ keep alive rejected, not registered");
03350     return H323GatekeeperRequest::Reject;
03351   }
03352 
03353   for (i = 0; i < info.rrq.m_callSignalAddress.GetSize(); i++) {
03354     PSafePtr<H323RegisteredEndPoint> ep2 = FindEndPointBySignalAddress(info.rrq.m_callSignalAddress[i]);
03355     if (ep2 != NULL && ep2 != info.endpoint) {
03356       if (overwriteOnSameSignalAddress) {
03357         PTRACE(2, "RAS\tOverwriting existing endpoint " << *ep2);
03358         RemoveEndPoint(ep2);
03359       }
03360       else {
03361         info.SetRejectReason(H225_RegistrationRejectReason::e_invalidCallSignalAddress);
03362         PTRACE(2, "RAS\tRRQ rejected, duplicate callSignalAddress");
03363         return H323GatekeeperRequest::Reject;
03364       }
03365     }
03366   }
03367 
03368   if (info.rrq.HasOptionalField(H225_RegistrationRequest::e_terminalAlias) && !AllowDuplicateAlias(info.rrq.m_terminalAlias)) {
03369     H225_ArrayOf_AliasAddress duplicateAliases;
03370     for (i = 0; i < info.rrq.m_terminalAlias.GetSize(); i++) {
03371       PSafePtr<H323RegisteredEndPoint> ep2 = FindEndPointByAliasAddress(info.rrq.m_terminalAlias[i]);
03372       if (ep2 != NULL && ep2 != info.endpoint) {
03373         PINDEX sz = duplicateAliases.GetSize();
03374         duplicateAliases.SetSize(sz+1);
03375               duplicateAliases[sz] = info.rrq.m_terminalAlias[i];
03376       }
03377     }
03378     if (duplicateAliases.GetSize() > 0) {
03379       info.SetRejectReason(H225_RegistrationRejectReason::e_duplicateAlias);
03380       H225_ArrayOf_AliasAddress & reasonAliases = info.rrj.m_rejectReason;
03381       reasonAliases = duplicateAliases;
03382       PTRACE(2, "RAS\tRRQ rejected, duplicate alias");
03383       return H323GatekeeperRequest::Reject;
03384     }
03385   }
03386 
03387   // Check if the endpoint is trying to register a prefix that can be resolved to another endpoint
03388   const H225_EndpointType & terminalType = info.rrq.m_terminalType;
03389   if (terminalType.HasOptionalField(H225_EndpointType::e_gateway) &&
03390       terminalType.m_gateway.HasOptionalField(H225_GatewayInfo::e_protocol)) {
03391     const H225_ArrayOf_SupportedProtocols & protocols = terminalType.m_gateway.m_protocol;
03392 
03393     for (i = 0; i < protocols.GetSize(); i++) {
03394 
03395       // Only voice prefixes are supported
03396       if (protocols[i].GetTag() == H225_SupportedProtocols::e_voice) {
03397             H225_VoiceCaps & voiceCaps = protocols[i];
03398               if (voiceCaps.HasOptionalField(H225_VoiceCaps::e_supportedPrefixes)) {
03399                 H225_ArrayOf_SupportedPrefix & prefixes = voiceCaps.m_supportedPrefixes;
03400                 for (PINDEX j = 0; j < prefixes.GetSize(); j++) {
03401 
03402                   // Reject if the prefix be matched to a registered alias or prefix
03403                   PSafePtr<H323RegisteredEndPoint> ep2 = FindEndPointByAliasAddress(prefixes[j].m_prefix);
03404                   if (ep2 != NULL && ep2 != info.endpoint && !canHaveDuplicatePrefix) {
03405                     info.SetRejectReason(H225_RegistrationRejectReason::e_duplicateAlias);
03406               H225_ArrayOf_AliasAddress & aliases = info.rrj.m_rejectReason;
03407               aliases.SetSize(1);
03408                     aliases[0] = prefixes[j].m_prefix;
03409                     PTRACE(2, "RAS\tRRQ rejected, duplicate prefix");
03410                     return H323GatekeeperRequest::Reject;
03411             }
03412           }
03413               }
03414               break;  // If voice protocol is found, don't look any further
03415       }
03416     }
03417   }
03418 
03419   // Are already registered and have just sent another heavy RRQ
03420   if (info.endpoint != NULL) {
03421     H323GatekeeperRequest::Response response = info.endpoint->OnRegistration(info);
03422     switch (response) {
03423       case H323GatekeeperRequest::Confirm :
03424         AddEndPoint(info.endpoint);
03425         break;
03426       case H323GatekeeperRequest::Reject :
03427         RemoveEndPoint(info.endpoint);
03428         break;
03429       default :
03430         break;
03431     }
03432     return response;
03433   }
03434 
03435   // Need to create a new endpoint object
03436   info.endpoint = CreateRegisteredEndPoint(info);
03437   if (info.endpoint == (H323RegisteredEndPoint *)NULL) {
03438     PTRACE(1, "RAS\tRRQ rejected, CreateRegisteredEndPoint() returned NULL");
03439     return H323GatekeeperRequest::Reject;
03440   }
03441 
03442   H323GatekeeperRequest::Response response = info.endpoint->OnRegistration(info);
03443   if (response != H323GatekeeperRequest::Confirm) {
03444     info.endpoint = (H323RegisteredEndPoint *)NULL;
03445     delete info.endpoint;
03446     return response;
03447   }
03448 
03449   // Have successfully registered, save it
03450   AddEndPoint(info.endpoint);
03451 
03452   PTRACE(2, "RAS\tRRQ accepted: \"" << *info.endpoint << '"');
03453   return H323GatekeeperRequest::Confirm;
03454 }
03455 
03456 
03457 H323GatekeeperRequest::Response H323GatekeeperServer::OnUnregistration(H323GatekeeperURQ & info)
03458 {
03459   PTRACE_BLOCK("H323GatekeeperServer::OnUnregistration");
03460 
03461   H323GatekeeperRequest::Response response = info.endpoint->OnUnregistration(info);
03462   if (response != H323GatekeeperRequest::Confirm)
03463     return response;
03464 
03465   if (info.urq.HasOptionalField(H225_UnregistrationRequest::e_endpointAlias)) {
03466     PINDEX i;
03467     // See if all aliases to be removed are on the same endpoint
03468     for (i = 0; i < info.urq.m_endpointAlias.GetSize(); i++) {
03469       if (FindEndPointByAliasAddress(info.urq.m_endpointAlias[i]) != info.endpoint) {
03470         info.SetRejectReason(H225_UnregRejectReason::e_permissionDenied);
03471         PTRACE(2, "RAS\tURQ rejected, alias " << info.urq.m_endpointAlias[i]
03472                << " not owned by registration");
03473         return H323GatekeeperRequest::Reject;
03474       }
03475     }
03476 
03477     // Remove all the aliases specified in PDU
03478     for (i = 0; i < info.urq.m_endpointAlias.GetSize(); i++)
03479       info.endpoint->RemoveAlias(H323GetAliasAddressString(info.urq.m_endpointAlias[i]));
03480 
03481     // if no aliases left, then remove the endpoint
03482     if (info.endpoint->GetAliasCount() > 0) {
03483 #ifdef H323_H501
03484       if (peerElement != NULL)
03485         peerElement->AddDescriptor(info.endpoint->GetDescriptorID(),
03486                                    info.endpoint->GetAliases(),
03487                                    info.endpoint->GetSignalAddresses());
03488 #endif
03489     } else {
03490       PTRACE(2, "RAS\tRemoving endpoint " << *info.endpoint << " with no aliases");
03491       RemoveEndPoint(info.endpoint);  // will also remove descriptor if required
03492     }
03493   }
03494   else
03495     RemoveEndPoint(info.endpoint);
03496 
03497   return H323GatekeeperRequest::Confirm;
03498 }
03499 
03500 
03501 H323GatekeeperRequest::Response H323GatekeeperServer::OnInfoResponse(H323GatekeeperIRR & info)
03502 {
03503   PTRACE_BLOCK("H323GatekeeperServer::OnInfoResponse");
03504 
03505   return info.endpoint->OnInfoResponse(info);
03506 }
03507 
03508 
03509 void H323GatekeeperServer::AddEndPoint(H323RegisteredEndPoint * ep)
03510 {
03511   PTRACE(3, "RAS\tAdding registered endpoint: " << *ep);
03512 
03513   PINDEX i;
03514 
03515   mutex.Wait();
03516 
03517   if (byIdentifier.FindWithLock(ep->GetIdentifier(), PSafeReference) != ep) {
03518     byIdentifier.SetAt(ep->GetIdentifier(), ep);
03519 
03520     if (byIdentifier.GetSize() > peakRegistrations)
03521       peakRegistrations = byIdentifier.GetSize();
03522     totalRegistrations++;
03523   }
03524 
03525   for (i = 0; i < ep->GetSignalAddressCount(); i++)
03526     byAddress.Append(new StringMap(ep->GetSignalAddress(i), ep->GetIdentifier()));
03527 
03528   for (i = 0; i < ep->GetAliasCount(); i++) {
03529     PString alias = ep->GetAlias(i);
03530     byAlias.Append(new StringMap(ep->GetAlias(i), ep->GetIdentifier()));
03531   }
03532 
03533   for (i = 0; i < ep->GetPrefixCount(); i++)
03534     byVoicePrefix.Append(new StringMap(ep->GetPrefix(i), ep->GetIdentifier()));
03535 
03536   mutex.Signal();
03537 }
03538 
03539 
03540 BOOL H323GatekeeperServer::RemoveEndPoint(H323RegisteredEndPoint * ep)
03541 {
03542   PTRACE(3, "RAS\tRemoving registered endpoint: " << *ep);
03543 
03544   // clear all calls in the endpoint
03545   while (ep->GetCallCount() > 0)
03546     RemoveCall(&ep->GetCall(0));
03547 
03548   // remove any aliases from the endpoint
03549   while (ep->GetAliasCount() > 0)
03550     ep->RemoveAlias(ep->GetAlias(0));
03551 
03552   PWaitAndSignal wait(mutex);
03553 
03554   PINDEX i;
03555 
03556   // remove prefixes belonging to this endpoint
03557   for (i = 0; i < byVoicePrefix.GetSize(); i++) {
03558     StringMap & prefixMap = (StringMap &)*byVoicePrefix.GetAt(i);
03559     if (prefixMap.identifier == ep->GetIdentifier())
03560       byVoicePrefix.RemoveAt(i);
03561   }
03562 
03563   // remove aliases belonging to this endpoint
03564   for (i = 0; i < byAlias.GetSize(); i++) {
03565     StringMap & aliasMap = (StringMap &)*byAlias.GetAt(i);
03566     if (aliasMap.identifier == ep->GetIdentifier())
03567       byAlias.RemoveAt(i);
03568   }
03569 
03570   // remove call signalling addresses
03571   for (i = 0; i < byAddress.GetSize(); i++) {
03572     StringMap & aliasMap = (StringMap &)*byAddress.GetAt(i);
03573     if (aliasMap.identifier == ep->GetIdentifier())
03574       byAddress.RemoveAt(i);
03575   }
03576 
03577   // remove the descriptor
03578 #ifdef H323_H501
03579   if (peerElement != NULL)
03580     peerElement->DeleteDescriptor(ep->GetDescriptorID());
03581 #endif
03582 
03583   // remove the endpoint from the list of active endpoints
03584   // ep is deleted by this
03585   return byIdentifier.RemoveAt(ep->GetIdentifier());
03586 }
03587 
03588 
03589 void H323GatekeeperServer::RemoveAlias(H323RegisteredEndPoint & ep,
03590                                                 const PString & alias)
03591 {
03592   PTRACE(3, "RAS\tRemoving registered endpoint alias: " << alias);
03593 
03594   mutex.Wait();
03595 
03596   PINDEX pos = byAlias.GetValuesIndex(alias);
03597   if (pos != P_MAX_INDEX) {
03598     // Allow for possible multiple aliases
03599     while (pos < byAlias.GetSize()) {
03600       StringMap & aliasMap = (StringMap &)byAlias[pos];
03601       if (aliasMap != alias)
03602         break;
03603 
03604       if (aliasMap.identifier == ep.GetIdentifier())
03605         byAlias.RemoveAt(pos);
03606       else
03607         pos++;
03608     }
03609   }
03610 
03611   if (ep.ContainsAlias(alias))
03612     ep.RemoveAlias(alias);
03613 
03614   mutex.Signal();
03615 }
03616 
03617 
03618 H323RegisteredEndPoint * H323GatekeeperServer::CreateRegisteredEndPoint(H323GatekeeperRRQ &)
03619 {
03620   return new H323RegisteredEndPoint(*this, CreateEndPointIdentifier());
03621 }
03622 
03623 
03624 PString H323GatekeeperServer::CreateEndPointIdentifier()
03625 {
03626   PWaitAndSignal wait(mutex);
03627   return psprintf("%x:%u", identifierBase, nextIdentifier++);
03628 }
03629 
03630 
03631 PSafePtr<H323RegisteredEndPoint> H323GatekeeperServer::FindEndPointByIdentifier(
03632                                             const PString & identifier, PSafetyMode mode)
03633 {
03634   return byIdentifier.FindWithLock(identifier, mode);
03635 }
03636 
03637 
03638 PSafePtr<H323RegisteredEndPoint> H323GatekeeperServer::FindEndPointBySignalAddresses(
03639                             const H225_ArrayOf_TransportAddress & addresses, PSafetyMode mode)
03640 {
03641   PWaitAndSignal wait(mutex);
03642 
03643   for (PINDEX i = 0; i < addresses.GetSize(); i++) {
03644     PINDEX pos = byAddress.GetValuesIndex(H323TransportAddress(addresses[i]));
03645     if (pos != P_MAX_INDEX)
03646       return FindEndPointByIdentifier(((StringMap &)byAddress[pos]).identifier, mode);
03647   }
03648 
03649   return (H323RegisteredEndPoint *)NULL;
03650 }
03651 
03652 
03653 PSafePtr<H323RegisteredEndPoint> H323GatekeeperServer::FindEndPointBySignalAddress(
03654                                      const H323TransportAddress & address, PSafetyMode mode)
03655 {
03656   PWaitAndSignal wait(mutex);
03657 
03658   PINDEX pos = byAddress.GetValuesIndex(address);
03659   if (pos != P_MAX_INDEX)
03660     return FindEndPointByIdentifier(((StringMap &)byAddress[pos]).identifier, mode);
03661 
03662   return (H323RegisteredEndPoint *)NULL;
03663 }
03664 
03665 
03666 PSafePtr<H323RegisteredEndPoint> H323GatekeeperServer::FindEndPointByAliasAddress(
03667                                          const H225_AliasAddress & alias, PSafetyMode mode)
03668 {
03669   return FindEndPointByAliasString(H323GetAliasAddressString(alias), mode);
03670 }
03671 
03672 
03673 PSafePtr<H323RegisteredEndPoint> H323GatekeeperServer::FindEndPointByAliasString(
03674                                                   const PString & alias, PSafetyMode mode)
03675 {
03676   {
03677     PWaitAndSignal wait(mutex);
03678     PINDEX pos = byAlias.GetValuesIndex(alias);
03679 
03680     if (pos != P_MAX_INDEX)
03681       return FindEndPointByIdentifier(((StringMap &)byAlias[pos]).identifier, mode);
03682   }
03683 
03684   return FindEndPointByPrefixString(alias, mode);
03685 }
03686 
03687 
03688 PSafePtr<H323RegisteredEndPoint> H323GatekeeperServer::FindEndPointByPartialAlias(
03689                                                   const PString & alias, PSafetyMode mode)
03690 {
03691   PWaitAndSignal wait(mutex);
03692   PINDEX pos = byAlias.GetNextStringsIndex(alias);
03693 
03694   if (pos != P_MAX_INDEX) {
03695     StringMap & possible = (StringMap &)byAlias[pos];
03696     if (possible.NumCompare(alias) == EqualTo) {
03697       PTRACE(4, "RAS\tPartial endpoint search for "
03698                 "\"" << alias << "\" found \"" << possible << '"');
03699       return FindEndPointByIdentifier(possible.identifier, mode);
03700     }
03701   }
03702 
03703   PTRACE(4, "RAS\tPartial endpoint search for \"" << alias << "\" failed");
03704   return (H323RegisteredEndPoint *)NULL;
03705 }
03706 
03707 
03708 PSafePtr<H323RegisteredEndPoint> H323GatekeeperServer::FindEndPointByPrefixString(
03709                                                   const PString & prefix, PSafetyMode mode)
03710 {
03711   PWaitAndSignal wait(mutex);
03712 
03713   if (byVoicePrefix.IsEmpty())
03714     return (H323RegisteredEndPoint *)NULL;
03715 
03716   for (PINDEX len = prefix.GetLength(); len > 0; len--) {
03717     PINDEX pos = byVoicePrefix.GetValuesIndex(prefix.Left(len));
03718     if (pos != P_MAX_INDEX)
03719       return FindEndPointByIdentifier(((StringMap &)byVoicePrefix[pos]).identifier, mode);
03720   }
03721 
03722   return (H323RegisteredEndPoint *)NULL;
03723 }
03724 
03725 
03726 PSafePtr<H323RegisteredEndPoint> H323GatekeeperServer::FindDestinationEndPoint(
03727                                          const OpalGloballyUniqueID & id,
03728                                          H323GatekeeperCall::Direction direction)
03729 {
03730   if ( !id ) {
03731     PSafePtr<H323GatekeeperCall> call = FindCall(id, direction);
03732     if (call == NULL)
03733       return NULL;
03734 
03735     for (PINDEX i = 0; i < call->GetDestinationAliases().GetSize(); i++) {
03736       const PString alias = call->GetDestinationAliases()[i];
03737       PSafePtr<H323RegisteredEndPoint> ep = FindEndPointByAliasString(alias);
03738       if (ep != NULL)
03739         return ep;
03740     }
03741   }
03742 
03743   return NULL;
03744 }
03745 
03746 
03747 H323GatekeeperRequest::Response H323GatekeeperServer::OnAdmission(H323GatekeeperARQ & info)
03748 {
03749   PTRACE_BLOCK("H323GatekeeperServer::OnAdmission");
03750 
03751   OpalGloballyUniqueID id = info.arq.m_callIdentifier.m_guid;
03752   if (id == NULL) {
03753     PTRACE(2, "RAS\tNo call identifier provided in ARQ!");
03754     info.SetRejectReason(H225_AdmissionRejectReason::e_undefinedReason);
03755     return H323GatekeeperRequest::Reject;
03756   }
03757 
03758   H323GatekeeperRequest::Response response;
03759 
03760   PSafePtr<H323GatekeeperCall> oldCall = FindCall(id, info.arq.m_answerCall);
03761   if (oldCall != NULL)
03762     response = oldCall->OnAdmission(info);
03763   else {
03764     // If on restarted in thread, then don't create new call, should already
03765     // have had one created on the last pass through.
03766     if (!info.IsFastResponseRequired() && info.CanSendRIP()) {
03767       PTRACE(2, "RAS\tCall object disappeared after starting slow PDU handler thread!");
03768       info.SetRejectReason(H225_AdmissionRejectReason::e_undefinedReason);
03769       return H323GatekeeperRequest::Reject;
03770     }
03771 
03772     H323GatekeeperCall * newCall = CreateCall(id,
03773                             info.arq.m_answerCall ? H323GatekeeperCall::AnsweringCall
03774                                                   : H323GatekeeperCall::OriginatingCall);
03775     PTRACE(3, "RAS\tCall created: " << *newCall);
03776 
03777     response = newCall->OnAdmission(info);
03778 
03779     if (response != H323GatekeeperRequest::Reject) {
03780       mutex.Wait();
03781 
03782       info.endpoint->AddCall(newCall);
03783       oldCall = activeCalls.Append(newCall);
03784 
03785       if (activeCalls.GetSize() > peakCalls)
03786         peakCalls = activeCalls.GetSize();
03787       totalCalls++;
03788 
03789       PTRACE(2, "RAS\tAdded new call (total=" << activeCalls.GetSize() << ") " << *newCall);
03790       mutex.Signal();
03791 
03792       AddCall(oldCall);
03793     }
03794   }
03795 
03796 #ifdef H323_H248
03797   switch (response) {
03798     case H323GatekeeperRequest::Confirm :
03799       if (oldCall->AddCallCreditServiceControl(info.acf.m_serviceControl))
03800         info.acf.IncludeOptionalField(H225_AdmissionConfirm::e_serviceControl);
03801       break;
03802 
03803     case H323GatekeeperRequest::Reject :
03804       if (oldCall != NULL && oldCall->AddCallCreditServiceControl(info.arj.m_serviceControl))
03805         info.arj.IncludeOptionalField(H225_AdmissionReject::e_serviceControl);
03806       break;
03807 
03808     default :
03809       break;
03810   }
03811 #endif
03812 
03813   return response;
03814 }
03815 
03816 
03817 H323GatekeeperRequest::Response H323GatekeeperServer::OnDisengage(H323GatekeeperDRQ & info)
03818 {
03819   PTRACE_BLOCK("H323GatekeeperServer::OnDisengage");
03820 
03821   OpalGloballyUniqueID callIdentifier = info.drq.m_callIdentifier.m_guid;
03822   PSafePtr<H323GatekeeperCall> call = FindCall(callIdentifier, info.drq.m_answeredCall);
03823   if (call == NULL) {
03824     info.SetRejectReason(H225_DisengageRejectReason::e_requestToDropOther);
03825     PTRACE(2, "RAS\tDRQ rejected, no call with ID " << callIdentifier);
03826     return H323GatekeeperRequest::Reject;
03827   }
03828 
03829   H323GatekeeperRequest::Response response = call->OnDisengage(info);
03830   if (response != H323GatekeeperRequest::Confirm)
03831     return response;
03832 
03833   RemoveCall(call);
03834 
03835   return H323GatekeeperRequest::Confirm;
03836 }
03837 
03838 
03839 H323GatekeeperRequest::Response H323GatekeeperServer::OnBandwidth(H323GatekeeperBRQ & info)
03840 {
03841   PTRACE_BLOCK("H323GatekeeperServer::OnBandwidth");
03842 
03843   PSafePtr<H323GatekeeperCall> call = FindCall(info.brq.m_callIdentifier.m_guid, info.brq.m_answeredCall);
03844   if (call == NULL) {
03845     info.SetRejectReason(H225_BandRejectReason::e_invalidConferenceID);
03846     PTRACE(2, "RAS\tBRQ rejected, no call with ID");
03847     return H323GatekeeperRequest::Reject;
03848   }
03849 
03850   H323GatekeeperRequest::Response response = call->OnBandwidth(info);
03851   return response;
03852 }
03853 
03854 
03855 BOOL H323GatekeeperServer::GetAdmissionRequestAuthentication(H323GatekeeperARQ & /*info*/,
03856                                                              H235Authenticators & /*authenticators*/)
03857 {
03858   return FALSE;
03859 }
03860 
03861 BOOL H323GatekeeperServer::GetUsersPassword(const PString & alias,
03862                                                   PString & password,
03863                                    H323RegisteredEndPoint & /*registerdEndpoint*/) const
03864 {
03865   return GetUsersPassword(alias, password);
03866 }
03867 
03868 BOOL H323GatekeeperServer::GetUsersPassword(const PString & alias, PString & password) const
03869 {
03870   if (!passwords.Contains(alias))
03871     return FALSE;
03872 
03873   password = passwords(alias);
03874   return TRUE;
03875 }
03876 
03877 
03878 unsigned H323GatekeeperServer::AllocateBandwidth(unsigned newBandwidth,
03879                                                  unsigned oldBandwidth)
03880 {
03881   PWaitAndSignal wait(mutex);
03882 
03883   // If first request for bandwidth, then only give them a maximum of the
03884   // configured default bandwidth
03885   if (oldBandwidth == 0 && newBandwidth > defaultBandwidth)
03886     newBandwidth = defaultBandwidth;
03887 
03888   // If then are asking for more than we have in total, drop it down to whatevers left
03889   if (newBandwidth > oldBandwidth && (newBandwidth - oldBandwidth) > (totalBandwidth - usedBandwidth))
03890     newBandwidth = totalBandwidth - usedBandwidth - oldBandwidth;
03891 
03892   // If greater than the absolute maximum configured for any endpoint, clamp it
03893   if (newBandwidth > maximumBandwidth)
03894     newBandwidth = maximumBandwidth;
03895 
03896   // Finally have adjusted new bandwidth, allocate it!
03897   usedBandwidth += (newBandwidth - oldBandwidth);
03898 
03899   PTRACE(3, "RAS\tBandwidth allocation: +" << newBandwidth << " -" << oldBandwidth
03900          << " used=" << usedBandwidth << " left=" << (totalBandwidth - usedBandwidth));
03901   return newBandwidth;
03902 }
03903 
03904 
03905 void H323GatekeeperServer::RemoveCall(H323GatekeeperCall * call)
03906 {
03907   if (PAssertNULL(call) == NULL)
03908     return;
03909 
03910   call->SetBandwidthUsed(0);
03911   PAssert(call->GetEndPoint().RemoveCall(call), PLogicError);
03912 
03913   PTRACE(2, "RAS\tRemoved call (total=" << (activeCalls.GetSize()-1) << ") id=" << *call);
03914   PAssert(activeCalls.Remove(call), PLogicError);
03915 }
03916 
03917 
03918 H323GatekeeperCall * H323GatekeeperServer::CreateCall(const OpalGloballyUniqueID & id,
03919                                                       H323GatekeeperCall::Direction dir)
03920 {
03921   return new H323GatekeeperCall(*this, id, dir);
03922 }
03923 
03924 
03925 PSafePtr<H323GatekeeperCall> H323GatekeeperServer::FindCall(const PString & desc,
03926                                                             PSafetyMode mode)
03927 {
03928   PINDEX pos = desc.Find(AnswerCallStr);
03929   if (pos == P_MAX_INDEX)
03930     pos = desc.Find(OriginateCallStr);
03931 
03932   OpalGloballyUniqueID id = desc.Left(pos);
03933 
03934   H323GatekeeperCall::Direction dir = H323GatekeeperCall::UnknownDirection;
03935 
03936   PString dirStr = desc.Mid(pos);
03937   if (dirStr == AnswerCallStr)
03938     dir = H323GatekeeperCall::AnsweringCall;
03939   else if (dirStr == OriginateCallStr)
03940     dir = H323GatekeeperCall::OriginatingCall;
03941 
03942   return FindCall(id, dir, mode);
03943 }
03944 
03945 
03946 PSafePtr<H323GatekeeperCall> H323GatekeeperServer::FindCall(const OpalGloballyUniqueID & id,
03947                                                             BOOL answer,
03948                                                             PSafetyMode mode)
03949 {
03950   return FindCall(id, answer ? H323GatekeeperCall::AnsweringCall
03951                              : H323GatekeeperCall::OriginatingCall, mode);
03952 }
03953 
03954 
03955 PSafePtr<H323GatekeeperCall> H323GatekeeperServer::FindCall(const OpalGloballyUniqueID & id,
03956                                                             H323GatekeeperCall::Direction dir,
03957                                                             PSafetyMode mode)
03958 {
03959   return activeCalls.FindWithLock(H323GatekeeperCall(*this, id, dir), mode);
03960 }
03961 
03962 
03963 H323GatekeeperRequest::Response H323GatekeeperServer::OnLocation(H323GatekeeperLRQ & info)
03964 {
03965   PINDEX i;
03966   for (i = 0; i < info.lrq.m_destinationInfo.GetSize(); i++) {
03967     PSafePtr<H323RegisteredEndPoint> ep =
03968                        FindEndPointByAliasAddress(info.lrq.m_destinationInfo[i], PSafeReadOnly);
03969     if (ep != NULL) {
03970       ep->GetSignalAddress(0).SetPDU(info.lcf.m_callSignalAddress);
03971       ep->GetRASAddress(0).SetPDU(info.lcf.m_rasAddress);
03972       PTRACE(2, "RAS\tLocation of " << H323GetAliasAddressString(info.lrq.m_destinationInfo[i])
03973              << " is endpoint " << *ep);
03974       return H323GatekeeperRequest::Confirm;
03975     }
03976   }
03977 
03978   BOOL isGKRouted = IsGatekeeperRouted();
03979 
03980   for (i = 0; i < info.lrq.m_destinationInfo.GetSize(); i++) {
03981     H323TransportAddress address;
03982     if (TranslateAliasAddress(info.lrq.m_destinationInfo[i],
03983                               info.lcf.m_destinationInfo,
03984                               address,
03985                               isGKRouted,
03986                               NULL)) {
03987       address.SetPDU(info.lcf.m_callSignalAddress);
03988       if (info.lcf.m_destinationInfo.GetSize() > 0)
03989         info.lcf.IncludeOptionalField(H225_LocationConfirm::e_destinationInfo);
03990 
03991       PTRACE(2, "RAS\tLocation of " << H323GetAliasAddressString(info.lrq.m_destinationInfo[i])
03992              << " is " << address);
03993       return H323GatekeeperRequest::Confirm;
03994     }
03995   }
03996 
03997   info.SetRejectReason(H225_LocationRejectReason::e_requestDenied);
03998   PTRACE(2, "RAS\tLRQ rejected, location not found");
03999   return H323GatekeeperRequest::Reject;
04000 }
04001 
04002 
04003 BOOL H323GatekeeperServer::TranslateAliasAddress(const H225_AliasAddress & alias,
04004                                                  H225_ArrayOf_AliasAddress & aliases,
04005                                                  H323TransportAddress & address,
04006                                                  BOOL & /*isGKRouted*/,
04007                                                  H323GatekeeperCall * /*call*/)
04008 {
04009   if (!TranslateAliasAddressToSignalAddress(alias, address)) {
04010 #ifdef H323_H501
04011     H225_AliasAddress transportAlias;
04012     if ((peerElement != NULL) && (peerElement->AccessRequest(alias, aliases, transportAlias))) {
04013       // if AccessRequest returns OK, but no aliases, then all of the aliases
04014       // must have been wildcards. In this case, add the original aliase back into the list
04015       if (aliases.GetSize() == 0) {
04016         PTRACE(1, "RAS\tAdding original alias to the top of the alias list");
04017         aliases.SetSize(1);
04018         aliases[0] = alias;
04019       }
04020       address = H323GetAliasAddressString(transportAlias);
04021       return TRUE;
04022     }
04023 #endif
04024     return FALSE;
04025   }
04026 
04027   PSafePtr<H323RegisteredEndPoint> ep = FindEndPointBySignalAddress(address, PSafeReadOnly);
04028   if (ep != NULL)
04029     H323SetAliasAddresses(ep->GetAliases(), aliases);
04030 
04031   return TRUE;
04032 }
04033 
04034 BOOL H323GatekeeperServer::TranslateAliasAddressToSignalAddress(const H225_AliasAddress & alias,
04035                                                                 H323TransportAddress & address)
04036 {
04037   PWaitAndSignal wait(mutex);
04038 
04039   PString aliasString = H323GetAliasAddressString(alias);
04040 
04041   if (isGatekeeperRouted) {
04042     const H323ListenerList & listeners = ownerEndPoint.GetListeners();
04043     address = listeners[0].GetTransportAddress();
04044     PTRACE(2, "RAS\tTranslating alias " << aliasString << " to " << address << ", gatekeeper routed");
04045     return TRUE;
04046   }
04047 
04048   PSafePtr<H323RegisteredEndPoint> ep = FindEndPointByAliasAddress(alias, PSafeReadOnly);
04049   if (ep != NULL) {
04050     address = ep->GetSignalAddress(0);
04051     PTRACE(2, "RAS\tTranslating alias " << aliasString << " to " << address <<