1 /*
2  * gkclient.h
3  *
4  * Gatekeeper client protocol handler
5  *
6  * Open H323 Library
7  *
8  * Copyright (c) 1998-2001 Equivalence Pty. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Open H323 Library.
21  *
22  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23  *
24  * Portions of this code were written with the assisance of funding from
25  * iFace, Inc. http://www.iface.com
26  *
27  * Contributor(s): ______________________________________.
28  *
29  * $Revision: 24178 $
30  * $Author: rjongbloed $
31  * $Date: 2010-04-05 19:10:56 -0500 (Mon, 05 Apr 2010) $
32  */
33 
34 #ifndef OPAL_H323_GKCLIENT_H
35 #define OPAL_H323_GKCLIENT_H
36 
37 #ifdef P_USE_PRAGMA
38 #pragma interface
39 #endif
40 
41 #include <opal/buildopts.h>
42 
43 #if OPAL_H323
44 
45 #include <h323/h225ras.h>
46 #include <h323/h235auth.h>
47 
48 #if OPAL_H460
49 class H460_FeatureSet;
50 #endif
51 
52 class H323Connection;
53 class H225_ArrayOf_AliasAddress;
54 class H225_H323_UU_PDU;
55 class H225_AlternateGK;
56 class H225_ArrayOf_AlternateGK;
57 class H225_ArrayOf_ServiceControlSession;
58 class H225_FeatureSet;
59 
60 
61 ///////////////////////////////////////////////////////////////////////////////
62 
63 /**This class embodies the H.225.0 RAS protocol to gatekeepers.
64   */
65 class H323Gatekeeper : public H225_RAS
66 {
67     PCLASSINFO(H323Gatekeeper, H225_RAS);
68   public:
69   /**@name Construction */
70   //@{
71     /**Create a new gatekeeper.
72      */
73     H323Gatekeeper(
74       H323EndPoint & endpoint,  ///<  Endpoint gatekeeper is associated with.
75       H323Transport * transport       ///<  Transport over which gatekeepers communicates.
76     );
77 
78     /**Destroy gatekeeper.
79      */
80     ~H323Gatekeeper();
81   //@}
82 
83   /**@name Overrides from H323Transactor */
84   //@{
85     virtual PBoolean WriteTo(
86       H323TransactionPDU & pdu,
87       const H323TransportAddressArray & addresses,
88       PBoolean callback = true
89     );
90   //@}
91 
92   /**@name Overrides from H225_RAS */
93   //@{
94     PBoolean OnReceiveGatekeeperConfirm(const H225_GatekeeperConfirm & gcf);
95     PBoolean OnReceiveGatekeeperReject(const H225_GatekeeperReject & grj);
96     PBoolean OnReceiveRegistrationConfirm(const H225_RegistrationConfirm & rcf);
97     PBoolean OnReceiveRegistrationReject(const H225_RegistrationReject & rrj);
98     PBoolean OnReceiveUnregistrationRequest(const H225_UnregistrationRequest & urq);
99     PBoolean OnReceiveUnregistrationConfirm(const H225_UnregistrationConfirm & ucf);
100     PBoolean OnReceiveUnregistrationReject(const H225_UnregistrationReject & urj);
101     PBoolean OnReceiveAdmissionConfirm(const H225_AdmissionConfirm & acf);
102     PBoolean OnReceiveAdmissionReject(const H225_AdmissionReject & arj);
103     PBoolean OnReceiveDisengageRequest(const H225_DisengageRequest & drq);
104     PBoolean OnReceiveBandwidthConfirm(const H225_BandwidthConfirm & bcf);
105     PBoolean OnReceiveBandwidthRequest(const H225_BandwidthRequest & brq);
106     PBoolean OnReceiveInfoRequest(const H225_InfoRequest & irq);
107     PBoolean OnReceiveServiceControlIndication(const H225_ServiceControlIndication &);
108     void OnSendGatekeeperRequest(H225_GatekeeperRequest & grq);
109     void OnSendAdmissionRequest(H225_AdmissionRequest & arq);
110     PBoolean OnSendFeatureSet(unsigned, H225_FeatureSet & features) const;
111     void OnReceiveFeatureSet(unsigned, const H225_FeatureSet & features) const;
112   //@}
113 
114   /**@name Protocol operations */
115   //@{
116     /**Discover a gatekeeper on the local network.
117      */
118     PBoolean DiscoverAny();
119 
120     /**Discover a gatekeeper on the local network.
121        If the identifier string is empty then the first gatekeeper to respond
122        to a broadcast is used.
123      */
124     PBoolean DiscoverByName(
125       const PString & identifier  ///<  Gatekeeper identifier to find
126     );
127 
128     /**Discover a gatekeeper on the local network.
129        If the address string is empty then the first gatekeeper to respond
130        to a broadcast is used.
131      */
132     PBoolean DiscoverByAddress(
133       const H323TransportAddress & address ///<  Address of gatekeeper.
134     );
135 
136     /**Discover a gatekeeper on the local network.
137        Combination of DiscoverByName() and DiscoverByAddress().
138      */
139     PBoolean DiscoverByNameAndAddress(
140       const PString & identifier,
141       const H323TransportAddress & address
142     );
143 
144     /**Register with gatekeeper.
145      */
146     PBoolean RegistrationRequest(
147       PBoolean autoReregister = true,  ///<  Automatic register on unregister
148       PBoolean didGkDiscovery = false  ///<  discovery procedure was done right before
149     );
150 
151     /**Unregister with gatekeeper.
152      */
153     PBoolean UnregistrationRequest(
154       int reason      ///<  Reason for unregistration
155     );
156 
157     /**Location request to gatekeeper.
158      */
159     PBoolean LocationRequest(
160       const PString & alias,          ///<  Alias name we wish to find.
161       H323TransportAddress & address  ///<  Resultant transport address.
162     );
163 
164     /**Location request to gatekeeper.
165      */
166     PBoolean LocationRequest(
167       const PStringList & aliases,    ///<  Alias names we wish to find.
168       H323TransportAddress & address  ///<  Resultant transport address.
169     );
170 
171     struct AdmissionResponse {
172       AdmissionResponse();
173 
174       unsigned rejectReason;                      /// Reject reason if returns false
175 
176       PBoolean gatekeeperRouted;                      /// Flag for call is through gk
177       PINDEX endpointCount;                       /// Number of endpoints that can be returned
178       H323TransportAddress * transportAddress;    /// Transport address or remote endpoint.
179       PBYTEArray * accessTokenData;               /// iNow Gatekeeper Access Token data
180 
181       H225_ArrayOf_AliasAddress * aliasAddresses; /// DestinationInfo to use in SETUP if not empty
182       H225_ArrayOf_AliasAddress * destExtraCallInfo; /// DestinationInfo to use in SETUP if not empty
183     };
184 
185     /**Admission request to gatekeeper.
186      */
187     PBoolean AdmissionRequest(
188       H323Connection & connection,      ///<  Connection we wish to change.
189       AdmissionResponse & response,     ///<  Response parameters to ARQ
190       PBoolean ignorePreGrantedARQ = false  ///<  Flag to force ARQ to be sent
191     );
192 
193     /**Disengage request to gatekeeper.
194      */
195     PBoolean DisengageRequest(
196       const H323Connection & connection,  ///<  Connection we wish admitted.
197       unsigned reason                     ///<  Reason code for disengage
198     );
199 
200     /**Bandwidth request to gatekeeper.
201      */
202     PBoolean BandwidthRequest(
203       H323Connection & connection,    ///<  Connection we wish to change.
204       unsigned requestedBandwidth     ///<  New bandwidth wanted in 0.1kbps
205     );
206 
207     /**Send an unsolicited info response to the gatekeeper.
208      */
209     void InfoRequestResponse();
210 
211     /**Send an unsolicited info response to the gatekeeper.
212      */
213     void InfoRequestResponse(
214       const H323Connection & connection  ///<  Connection to send info about
215     );
216 
217     /**Send an unsolicited info response to the gatekeeper.
218      */
219     void InfoRequestResponse(
220       const H323Connection & connection,  ///<  Connection to send info about
221       const H225_H323_UU_PDU & pdu,       ///<  PDU that was sent or received
222       PBoolean sent                           ///<  Flag for PDU was sent or received
223     );
224 
225     /**Handle incoming service control session information.
226      */
227     virtual void OnServiceControlSessions(
228       const H225_ArrayOf_ServiceControlSession & serviceControl,
229       H323Connection * connection
230     );
231 
232     /** Handle terminal alias changes
233       */
234     virtual void OnTerminalAliasChanged();
235   //@}
236 
237   /**@name Member variable access */
238   //@{
239     /**Determine if the endpoint has discovered the gatekeeper.
240       */
IsDiscoveryComplete()241     PBoolean IsDiscoveryComplete() const { return discoveryComplete; }
242 
243     /**Determine if the endpoint is registered with the gatekeeper.
244       */
IsRegistered()245     PBoolean IsRegistered() const { return registrationFailReason == RegistrationSuccessful; }
246 
247     enum RegistrationFailReasons {
248       RegistrationSuccessful,
249       UnregisteredLocally,
250       UnregisteredByGatekeeper,
251       GatekeeperLostRegistration,
252       InvalidListener,
253       DuplicateAlias,
254       SecurityDenied,
255       TransportError,
256       NumRegistrationFailReasons,
257       RegistrationRejectReasonMask = 0x8000
258     };
259     /**Get the registration fail reason.
260      */
GetRegistrationFailReason()261     RegistrationFailReasons GetRegistrationFailReason() const { return registrationFailReason; }
262 
263     /**Get the gatekeeper name.
264        The gets the name of the gatekeeper. It will be of the form id@address
265        where id is the gatekeeperIdentifier and address is the transport
266        address used. If the gatekeeperIdentifier is empty the '@' is not
267        included and only the transport is shown. The transport is minimised
268        also, with the type removed if IP is used and the :port removed if the
269        default port is used.
270       */
271     PString GetName() const;
272 
273     /** Get the endpoint identifier
274       */
GetEndpointIdentifier()275     const PString & GetEndpointIdentifier() const { return endpointIdentifier; }
276 
277     /**Set the H.235 password in the gatekeeper.
278        If no username is present then it will default to the endpoint local
279        user name (ie first alias).
280       */
281     void SetPassword(
282       const PString & password,            ///<  New password
283       const PString & username = PString() ///<  Username for password
284     );
285 
286     /*
287      * Return the call signalling address for the gatekeeper (if present)
288      */
GetGatekeeperRouteAddress()289     H323TransportAddress GetGatekeeperRouteAddress() const
290     { return gkRouteAddress; }
291   //@}
292 
293 
294   protected:
295     bool StartGatekeeper(const H323TransportAddress & address);
296     virtual bool DiscoverGatekeeper();
297     unsigned SetupGatekeeperRequest(H323RasPDU & request);
298 
299     void Connect(const H323TransportAddress & address, const PString & gatekeeperIdentifier);
300     PDECLARE_NOTIFIER(PThread, H323Gatekeeper, MonitorMain);
301     PDECLARE_NOTIFIER(PTimer, H323Gatekeeper, TickleMonitor);
302     void RegistrationTimeToLive();
303 
304     void SetInfoRequestRate(
305       const PTimeInterval & rate
306     );
307     void ClearInfoRequestRate();
308     H225_InfoRequestResponse & BuildInfoRequestResponse(
309       H323RasPDU & response,
310       unsigned seqNum
311     );
312     PBoolean SendUnsolicitedIRR(
313       H225_InfoRequestResponse & irr,
314       H323RasPDU & response
315     );
316 
317     void SetAlternates(
318       const H225_ArrayOf_AlternateGK & alts,
319       PBoolean permanent
320     );
321 
322     virtual PBoolean MakeRequest(
323       Request & request
324     );
325     PBoolean MakeRequestWithReregister(
326       Request & request,
327       unsigned unregisteredTag
328     );
329 
330     virtual H323Transport * CreateTransport(PIPSocket::Address bindng = PIPSocket::GetDefaultIpAny(), WORD port = 0, PBoolean reuseAddr = false);
331 
332     // Handling interface changes
333     void OnAddInterface(const PIPSocket::InterfaceEntry & entry, PINDEX priority);
334     void OnRemoveInterface(const PIPSocket::InterfaceEntry & entry, PINDEX priority);
335     void UpdateConnectionStatus();
336     bool SetListenerAddresses(H225_ArrayOf_TransportAddress & pdu);
337 
338     // Gatekeeper registration state variables
339     PBoolean     discoveryComplete;
340     PString  endpointIdentifier;
341     RegistrationFailReasons registrationFailReason;
342 
343     enum {
344       HighPriority = 80,
345       LowPriority  = 40,
346     };
347     class InterfaceMonitor : public PInterfaceMonitorClient
348     {
349       PCLASSINFO(InterfaceMonitor, PInterfaceMonitorClient);
350 
351       public:
352         InterfaceMonitor(H323Gatekeeper & gk, PINDEX priority);
353 
354       protected:
355         virtual void OnAddInterface(const PIPSocket::InterfaceEntry & entry);
356         virtual void OnRemoveInterface(const PIPSocket::InterfaceEntry & entry);
357 
358         H323Gatekeeper & gk;
359     };
360     InterfaceMonitor highPriorityMonitor;
361     InterfaceMonitor lowPriorityMonitor;
362 
363     class AlternateInfo : public PObject {
364       PCLASSINFO(AlternateInfo, PObject);
365       public:
366         AlternateInfo(H225_AlternateGK & alt);
367         ~AlternateInfo();
368         Comparison Compare(const PObject & obj);
369         void PrintOn(ostream & strm) const;
370 
371         H323TransportAddress rasAddress;
372         PString              gatekeeperIdentifier;
373         unsigned             priority;
374         enum {
375           NoRegistrationNeeded,
376           NeedToRegister,
377           Register,
378           IsRegistered,
379           RegistrationFailed
380         } registrationState;
381 
382       private:
383         // Disable copy constructor and assignment
AlternateInfo(const AlternateInfo & other)384         AlternateInfo(const AlternateInfo &other): PObject(other) { }
385         AlternateInfo & operator=(const AlternateInfo &) { return *this; }
386     };
387     PSortedList<AlternateInfo> alternates;
388     PBoolean               alternatePermanent;
389     PSemaphore         requestMutex;
390     H235Authenticators authenticators;
391 
392     enum {
393       RequireARQ,
394       PregrantARQ,
395       PreGkRoutedARQ
396     } pregrantMakeCall, pregrantAnswerCall;
397     H323TransportAddress gkRouteAddress;
398 
399     // Gatekeeper operation variables
400     PBoolean       autoReregister;
401     PBoolean       reregisterNow;
402     PTimer     timeToLive;
403     PBoolean       requiresDiscovery;
404     PTimer     infoRequestRate;
405     PBoolean       willRespondToIRR;
406     PThread  * monitor;
407     PBoolean       monitorStop;
408     PSyncPoint monitorTickle;
409 
410     PDictionary<POrdinalKey, H323ServiceControlSession> serviceControlSessions;
411 
412 #if OPAL_H460
413     H460_FeatureSet * features;
414 #endif
415 
416 };
417 
418 
419 PLIST(H323GatekeeperList, H323Gatekeeper);
420 
421 
422 #endif // OPAL_H323
423 
424 #endif // OPAL_H323_GKCLIENT_H
425 
426 
427 /////////////////////////////////////////////////////////////////////////////
428