OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / user / gnugk / Routing.h
1 //////////////////////////////////////////////////////////////////
2 //
3 // Routing.h
4 //
5 // Routing Mechanism for GNU Gatekeeper
6 //
7 // Copyright (c) Citron Network Inc. 2003
8 //
9 // This work is published under the GNU Public License (GPL)
10 // see file COPYING for details.
11 // We also explicitely grant the right to link this code
12 // with the OpenH323 library.
13 //
14 // initial author: Chih-Wei Huang <cwhuang@linux.org.tw>
15 // initial version: 06/18/2003
16 //
17 //////////////////////////////////////////////////////////////////
18
19 #ifndef ROUTING_H
20 #define ROUTING_H "@(#) $Id: Routing.h,v 1.26 2007/03/10 12:16:09 shorne Exp $"
21
22 #include <map>
23 #include <list>
24 #include "slist.h"
25 #include "singleton.h"
26 #include "RasTbl.h"
27
28 // forward references to avoid includes
29 class H225_AdmissionRequest;
30 class H225_LocationRequest;
31 class H225_Setup_UUIE;
32 class H225_Facility_UUIE;
33 class H225_TransportAddress;
34 class H225_ArrayOf_AliasAddress;
35 class Q931;
36 class SignalingMsg;
37 template <class> class H225SignalingMsg;
38 typedef H225SignalingMsg<H225_Setup_UUIE> SetupMsg;
39 typedef H225SignalingMsg<H225_Facility_UUIE> FacilityMsg;
40
41 class RasMsg;
42
43 namespace Routing {
44
45 /// An entry for a single call destination route
46 struct Route {
47         // a policy can set flags to indicate extra status of a processed request
48         enum Flags {
49                 e_toParent = 1,
50                 e_toNeighbor = 2
51         };
52         
53         Route();
54         Route(
55                 const endptr &destEndpoint
56                 );
57         Route(
58                 const PString &policyName,
59                 const H225_TransportAddress &destAddr
60                 );
61         Route(
62                 const PString &policyName,
63                 const PIPSocket::Address &destIpAddr,
64                 WORD destPort
65                 );
66                 
67         PString AsString() const;
68
69         bool IsFailoverActive(
70                 unsigned cause
71                 ) const;
72
73         H225_TransportAddress m_destAddr; /// destination address for signaling
74         endptr m_destEndpoint; /// destination endpoint record (if available)
75         H225_AliasAddress m_srcAddr; /// source alias that matched the route
76         PString m_policy; /// name of the policy that found the route
77         PString m_routeId; /// optional policy-specific route identifier
78         int m_proxyMode; /// per-route proxy mode flag
79         unsigned m_flags; /// additional route specific flags
80         unsigned char m_rerouteCauses[16]; /// bit flags to trigger rerouting on particular Q931 causes
81 };
82
83 class RoutingRequest {
84 public:
85         enum Flags {
86                 e_aliasesChanged = 1,
87                 e_fromInternal = 2,
88                 e_fromParent = 4,
89                 e_fromNeighbor = 8
90         };
91         
92         // note this is not a polymorphic class
93         RoutingRequest();
94         RoutingRequest(
95                 const std::list<Route> &failedRoutes
96                 );
97         ~RoutingRequest();
98
99         bool AddRoute(
100                 const Route &route
101                 );
102         bool GetFirstRoute(
103                 Route &route
104                 );
105         void RemoveAllRoutes();
106         std::list<Route> &GetRoutes() { return m_routes; }
107         
108         void SetRejectReason(unsigned reason) { m_reason = reason; }
109         void SetFlag(unsigned f) { m_flags |= f; }
110         unsigned GetRejectReason() const { return m_reason; }
111         unsigned GetFlags() const { return m_flags; }
112
113 private:
114         RoutingRequest(const RoutingRequest&);
115         RoutingRequest& operator=(const RoutingRequest&);
116
117 private:
118         int m_reason; /// reject reason, if no routes are found
119         unsigned m_flags; /// request specific flags
120         std::list<Route> m_routes;
121         std::list<Route> m_failedRoutes;
122 };
123
124 template<class R, class W>
125 class Request : public RoutingRequest {
126 public:
127         typedef R ReqObj;
128         typedef W Wrapper;
129
130         Request(ReqObj & r, Wrapper *w) : m_request(r), m_wrapper(w) {}
131         Request(ReqObj & r, Wrapper *w, const std::list<Route> &failedRoutes)
132                 : RoutingRequest(failedRoutes), m_request(r), m_wrapper(w) {}
133
134         bool Process();
135
136         ReqObj & GetRequest() { return m_request; }
137         Wrapper *GetWrapper() { return m_wrapper; }
138         H225_ArrayOf_AliasAddress *GetAliases();
139         void SetAliases(H225_ArrayOf_AliasAddress & aliases);
140         const ReqObj & GetRequest() const { return m_request; }
141         const Wrapper *GetWrapper() const { return m_wrapper; }
142         const H225_ArrayOf_AliasAddress *GetAliases() const
143         { return const_cast<Request<R, W> *>(this)->GetAliases(); }
144
145 private:
146         ReqObj & m_request;
147         Wrapper *m_wrapper;
148 };
149
150 typedef Request<H225_AdmissionRequest, RasMsg> AdmissionRequest;
151 typedef Request<H225_LocationRequest, RasMsg> LocationRequest;
152 typedef Request<H225_Setup_UUIE, SetupMsg> SetupRequest;
153 typedef Request<H225_Facility_UUIE, FacilityMsg> FacilityRequest;
154
155
156 class Policy : public SList<Policy> {
157 public:
158         Policy() : m_name("Undefined") {}
159
160         template <class R> bool HandleRas(Request<R,RasMsg> & request)
161         {
162                 if( IsActive() ) {
163 #if PTRACING
164                         const char* tagname = request.GetWrapper()
165                                 ? request.GetWrapper()->GetTagName() : "unknown";
166                         const unsigned seqnum = request.GetRequest().m_requestSeqNum.GetValue();
167                         PTRACE(5,"ROUTING\tChecking policy "<<m_name
168                                 <<" for the request "<<tagname<<' '<<seqnum
169                                 );
170 #endif
171                         if( OnRequest(request) ) {
172 #if PTRACING
173                                 PTRACE(5,"ROUTING\tPolicy "<<m_name
174                                         <<" applied to the request "<<tagname<<' '<<seqnum
175                                         );
176 #endif
177                                 return true;
178                         }
179                 }
180                 return m_next && m_next->HandleRas(request);
181         }
182
183         bool Handle(SetupRequest &request);
184         bool Handle(FacilityRequest &request);
185
186 protected:
187         // new virtual function
188         // if return false, the policy is disable
189         virtual bool IsActive() { return true; }
190
191         // methods to handle the request
192         // return true:  fate of the request is determined (confirm or reject)
193         // return false: undetermined, try next
194         virtual bool OnRequest(AdmissionRequest &) { return false; }
195         virtual bool OnRequest(LocationRequest &)  { return false; }
196         virtual bool OnRequest(SetupRequest &)     { return false; }
197         virtual bool OnRequest(FacilityRequest &)  { return false; }
198
199 protected:
200         /// human readable name for the policy - it should be set inside constructors
201         /// of derived policies, default value is "undefined"
202         const char* m_name;
203 };
204
205 class AliasesPolicy : public Policy {
206 public:
207         AliasesPolicy() { m_name = "Aliases"; }
208
209 protected:
210         // override from class Policy
211         virtual bool OnRequest(AdmissionRequest &);
212         virtual bool OnRequest(LocationRequest &);
213         virtual bool OnRequest(SetupRequest &);
214         virtual bool OnRequest(FacilityRequest &);
215
216         // new virtual function
217         virtual bool FindByAliases(RoutingRequest&, H225_ArrayOf_AliasAddress &) = 0;
218         virtual bool FindByAliases(LocationRequest&, H225_ArrayOf_AliasAddress&) = 0;
219 };
220
221 class Analyzer : public Singleton<Analyzer> {
222 public:
223         Analyzer();
224         ~Analyzer();
225
226         void OnReload();
227
228         bool Parse(AdmissionRequest &);
229         bool Parse(LocationRequest &);
230         bool Parse(SetupRequest &);
231         bool Parse(FacilityRequest &);
232
233 private:
234         typedef std::map<PString, Policy *, pstr_prefix_lesser> Rules;
235
236         Policy *Create(const PString & policy);
237         Policy *ChoosePolicy(const H225_ArrayOf_AliasAddress *, Rules &);
238
239         Rules m_rules[4];
240         PReadWriteMutex m_reloadMutex;
241 };
242
243
244 template<class R, class W>
245 inline bool Request<R, W>::Process()
246 {
247         return Analyzer::Instance()->Parse(*this);
248 }
249
250 /** A class that supports ACD (Automatic Call Distribution). A call
251     made to specified alias(-es) (called virtual queue) is signalled
252         via the GK status line to an external application (an ACD application)
253         that decides where the call should be routed (e.g. what agent should
254         answe the call). Basically, it rewrites virtual queue alias
255         into the alias of the specified agent.
256
257         The route request is uniquelly identified by (EndpointIdentifier,CRV)
258         values pair.
259 */
260 class VirtualQueue
261 {
262 public:
263         VirtualQueue();
264         ~VirtualQueue();
265
266         /// reload settings from the config file
267         void OnReload();
268
269         /** @return
270                 True if there is at least one virtual queue configured.
271         */
272         bool IsActive() const { return m_active; }
273
274         /** Send RouteRequest to the GK status line     and wait
275                 for a routing decision to be made by some external application
276                 (ACD application).
277
278                 @return
279                 True if the external application routed the call (either by specifying
280                 an alias or by rejecting the call), false if timed out waiting
281                 for the routing decision.
282                 If the request was rejected, destinationInfo is set to an epmty array
283                 (0 elements).
284         */
285         bool SendRouteRequest(
286                 /// source IP of the request (endpoint for ARQ, gatekeeper for LRQ)
287                 const PString& source,
288                 /// calling endpoint
289                 const PString& epid,
290                 /// CRV (Call Reference Value) of the call associated with this request
291                 unsigned crv,
292                 /// destination (virtual queue) aliases as specified
293                 /// by the calling endpoint (modified by this function on successful return)
294                 H225_ArrayOf_AliasAddress* destinationInfo,
295                 /// destinationCallSignalAddr (optionally set by this function on successful return)
296                 PString* callSigAdr,
297                 /// an actual virtual queue name (should be present in destinationInfo too)
298                 const PString& vqueue,
299                 /// a sequence of aliases for the calling endpoint
300                 /// (in the "alias:type[=alias:type]..." format)
301                 const PString& sourceInfo,
302                 /// the callID as string
303                 const PString& callID
304                 );
305
306         /** Make a routing decision for a pending route request (inserted
307                 by SendRequest).
308
309                 @return
310                 True if the matching pending request has been found, false otherwise.
311         */
312         bool RouteToAlias(
313                 /// aliases for the routing target (an agent that the call will be routed to)
314                 /// that will replace the original destination info
315                 const H225_ArrayOf_AliasAddress& agent,
316                 /// ip that will replace the destionationCallSignalAddress (RouteToGateway)
317                 /// used only if set (port != 0)
318                 const PString& destinationip,
319                 /// identifier of the endpoint associated with the route request
320                 const PString& callingEpId,
321                 /// CRV of the call associated with the route request
322                 unsigned crv,
323                 /// callID of the call associated with the route request
324                 const PString& callID
325                 );
326
327         /** Make a routing decision for a pending route request (inserted
328                 by SendRequest).
329
330                 @return
331                 True if the matching pending request has been found, false otherwise.
332         */
333         bool RouteToAlias(
334                 /// alias for the routing target that
335                 /// will replace the original destination info
336                 const PString& agent,
337                 /// will replace the original destinationCallSignallAddress
338                 const PString& destinationip,           
339                 /// identifier of the endpoint associated with the route request
340                 const PString& callingEpId,
341                 /// CRV of the call associated with the route request
342                 unsigned crv,
343                 /// callID of the call associated with the route request
344                 const PString& callID
345                 );
346
347         /** Reject a pending route request (inserted by SendRequest).
348
349                 @return
350                 True if the matching pending request has been found, false otherwise.
351         */
352         bool RouteReject(
353                 /// identifier of the endpoint associated with the route request
354                 const PString& callingEpId,
355                 /// CRV of the call associated with the route request
356                 unsigned crv,
357                 /// callID of the call associated with the route request
358                 const PString& callID
359                 );
360
361         /** @return
362                 True if the specified alias matches a name of an existing virtual queue.
363         */
364         bool IsDestinationVirtualQueue(
365                 const PString& destinationAlias /// alias to be matched
366                 ) const;
367
368 private:
369         /// a holder for a pending route request
370         struct RouteRequest
371         {
372                 RouteRequest(
373                         const PString& callingEpId,
374                         unsigned crv,
375                         const PString& callID,
376                         H225_ArrayOf_AliasAddress* agent,
377                         PString* callsignaladdr
378                         )
379                         :
380                         m_callingEpId((const char*)callingEpId), m_crv(crv), m_callID(callID),
381                         m_agent(agent), m_callsignaladdr(callsignaladdr) {}
382
383                 /// identifier for the endpoint associated with this request
384                 PString m_callingEpId;
385                 /// CRV for the call associated with this request
386                 unsigned m_crv;
387                 /// callID for the call associated with this request
388                 PString m_callID;
389                 /// aliases for the virtual queue matched (on input)
390                 /// aliases for the target agent - target route (on output)
391                 H225_ArrayOf_AliasAddress* m_agent;
392                 /// destinationCallSignallAddress for the target agent - target route IF NOT NULL
393                 PString* m_callsignaladdr;
394                 /// a synchronization point for signalling that routing decision
395                 /// has been made by the external application
396                 PSyncPoint m_sync;
397         };
398
399         typedef std::list<RouteRequest *> RouteRequests;
400
401         RouteRequest *InsertRequest(
402                 /// identifier for the endpoint associated with this request
403                 const PString& callingEpId,
404                 /// CRV for the call associated with this request
405                 unsigned crv,
406                 /// callID for the call associated with this request
407                 const PString& callID,
408                 /// a pointer to an array to be filled with agent aliases
409                 /// when the routing decision has been made
410                 H225_ArrayOf_AliasAddress* agent,
411                 /// a pointer to a string to be filled with a callSignalAddress
412                 /// when the routing decision has been made (optional)
413                 PString* callSigAdr,
414                 /// set by the function to true if another route request for the same
415                 /// call is pending
416                 bool& duplicate
417                 );
418
419         /// an array of names (aliases) for the virtual queues
420         PStringArray m_virtualQueueAliases;
421         /// an array of prefixes for the virtual queues
422         PStringArray m_virtualQueuePrefixes;
423         /// a regular expression for the virtual queues
424         PString m_virtualQueueRegex;
425         /// virtual queues enabled/disabled
426         bool m_active;
427         /// time (in milliseconds) to wait for a routing decision to be made
428         long m_requestTimeout;
429         /// a list of active (pending) route requests
430         RouteRequests m_pendingRequests;
431         /// a mutex protecting pending requests and virtual queues lists
432         PMutex m_listMutex;
433 };
434
435
436 } // end of namespace Routing
437
438 #endif // ROUTING_H