OSDN Git Service

Fix no pic
[uclinux-h8/uClinux-dist.git] / user / gnugk / RasPDU.h
1 //////////////////////////////////////////////////////////////////
2 //
3 // RasPDU.h
4 //
5 // Define RAS PDU for GNU Gatekeeper
6 // Avoid including large h225.h in RasSrv.h
7 //
8 // Copyright (c) Citron Network Inc. 2001-2003
9 //
10 // This work is published under the GNU Public License (GPL)
11 // see file COPYING for details.
12 // We also explicitely grant the right to link this code
13 // with the OpenH323 library.
14 //
15 // initial author: Chih-Wei Huang <cwhuang@linux.org.tw>
16 // initial version: 05/02/2003
17 //
18 //////////////////////////////////////////////////////////////////
19
20 #ifndef RASPDU_H
21 #define RASPDU_H "@(#) $Id: RasPDU.h,v 1.10 2006/09/16 20:42:50 shorne Exp $"
22
23 #include <list>
24 #include "yasocket.h"
25 #include "factory.h"
26 #include "rasinfo.h"
27
28
29 class Toolkit;
30 class GkStatus;
31 class RegistrationTable;
32 class CallTable;
33 class RasListener;
34 class MulticastListener;
35 class CallSignalListener;
36 class StatusListener;
37 class RasServer;
38
39 const unsigned MaxRasTag = H225_RasMessage::e_serviceControlResponse;
40
41 struct GatekeeperMessage {
42         PPER_Stream m_rasPDU;
43         H225_RasMessage m_recvRAS;
44         H225_RasMessage m_replyRAS;
45         PIPSocket::Address m_peerAddr;
46         WORD m_peerPort;
47         PIPSocket::Address m_localAddr;
48         RasListener *m_socket;
49
50         unsigned GetTag() const { return m_recvRAS.GetTag(); }
51         const char *GetTagName() const;
52         bool Read(RasListener *);
53         bool Reply() const;
54 };
55
56 class RasListener : public UDPSocket {
57 public:
58         RasListener(const Address &, WORD);
59         ~RasListener();
60
61         GatekeeperMessage *ReadRas();
62         bool SendRas(const H225_RasMessage &, const Address &, WORD);
63
64         WORD GetSignalPort() const { return m_signalPort; }
65         void SetSignalPort(WORD pt) { m_signalPort = pt; }
66
67         Address GetLocalAddr(const Address &) const;
68         Address GetPhysicalAddr(const Address & addr) const;
69         H225_TransportAddress GetRasAddress(const Address &) const;
70         H225_TransportAddress GetCallSignalAddress(const Address &) const;
71
72         // new virtual function
73         // filter out unwanted message to the listener by returning false
74         virtual bool Filter(GatekeeperMessage *) const;
75
76 protected:
77         Address m_ip;
78         PMutex m_wmutex;
79         WORD m_signalPort;
80         bool m_virtualInterface;
81 };
82
83 class RasMsg : public Task {
84 public:
85         virtual ~RasMsg() { delete m_msg; } //PTRACE(1, "Delete " << m_msg->GetTagName()); }
86
87         // new virtual function
88         virtual bool Process() = 0;
89
90         virtual int GetSeqNum() const = 0;
91         virtual H225_NonStandardParameter *GetNonStandardParam() = 0;
92
93         // override from class Task
94         virtual void Exec();
95
96         bool IsFrom(const PIPSocket::Address &, WORD) const;
97         void GetRecvAddress(PIPSocket::Address &, WORD &) const;
98         unsigned GetTag() const { return m_msg->GetTag(); }
99         const char *GetTagName() const { return m_msg->GetTagName(); }
100
101         void GetRasAddress(H225_TransportAddress &) const;
102         void GetCallSignalAddress(H225_TransportAddress &) const;
103
104         bool EqualTo(const RasMsg *) const;
105         bool operator==(const RasMsg & other) const { return EqualTo(&other); }
106
107         bool Reply() const { return m_msg->Reply(); }
108
109         GatekeeperMessage *operator->() { return m_msg; }
110         const GatekeeperMessage *operator->() const { return m_msg; }
111         void Release();
112
113         static void Initialize();
114         static RegistrationTable *GetEndpointTbl()
115                 { return EndpointTbl; };
116         static CallTable *GetCallTbl()
117                 { return CallTbl; }; 
118 protected:
119         RasMsg(GatekeeperMessage *m) : m_msg(m) {}
120         RasMsg(const RasMsg &);
121
122         static bool PrintStatus(const PString &);
123         
124         GatekeeperMessage *m_msg;
125
126         // just pointers to global singleton objects
127         // cache for faster access
128         static Toolkit *Kit;
129         static GkStatus *StatusPort;
130         static RegistrationTable *EndpointTbl;
131         static CallTable *CallTbl; 
132         static RasServer *RasSrv;
133 };
134
135 template<class RAS>
136 class RasPDU : public RasMsg {
137 public:
138         typedef RAS RasClass;
139         
140         RasPDU(GatekeeperMessage *m) : RasMsg(m), request(m->m_recvRAS) {}
141
142         // override from class RasMsg
143         virtual bool Process() { return false; }
144         virtual int GetSeqNum() const { return request.m_requestSeqNum; }
145         virtual H225_NonStandardParameter *GetNonStandardParam();
146
147         operator RAS & () { return request; }
148         operator const RAS & () const { return request; }
149
150         H225_RasMessage & BuildConfirm();
151         H225_RasMessage & BuildReject(unsigned);
152
153         typedef Factory<RasMsg, unsigned>::Creator1<GatekeeperMessage *> RasCreator;
154         struct Creator : public RasCreator {
155                 Creator() : RasCreator(RasInfo<RAS>::tag) {}
156                 virtual RasMsg *operator()(GatekeeperMessage *m) const { return new RasPDU<RAS>(m); }
157         };
158
159 protected:
160         RAS & request;
161 };
162
163 // abstract factory for listeners
164 class GkInterface {
165 public:
166         typedef PIPSocket::Address Address;
167
168         GkInterface(const Address &);
169         virtual ~GkInterface();
170
171         // we can't call virtual functions in constructor
172         // so initialize here
173         virtual bool CreateListeners(RasServer *);
174
175         bool IsBoundTo(const Address *addr) const { return m_address == *addr; }
176         bool IsReachable(const Address *) const;
177
178         RasListener *GetRasListener() const { return m_rasListener; }
179         MulticastListener *GetMulticastListener() const { return m_multicastListener; }
180         CallSignalListener *GetCallSignalListener() const { return m_callSignalListener; }
181         StatusListener *GetStatusListener() const { return m_statusListener; }
182
183         WORD GetRasPort() const { return m_rasPort; }
184         WORD GetMulticastPort() const { return m_multicastPort; }
185         WORD GetSignalPort() const { return m_signalPort; }
186         WORD GetStatusPort() const { return m_statusPort; }
187
188 protected:
189         bool ValidateSocket(IPSocket *, WORD &);
190
191         template <class Listener> bool SetListener(WORD nport, WORD & oport, Listener *& listener, Listener *(GkInterface::*creator)())
192         {
193                 if (!listener || !oport || oport != nport) {
194                         oport = nport;
195                         if (listener)
196                                 listener->Close();
197                         listener = (this->*creator)();
198                         if (ValidateSocket(listener, oport))
199                                 return true;
200                         else
201                                 listener = 0;
202                 }
203                 return false;
204         }
205
206         Address m_address;
207         RasListener *m_rasListener;
208         MulticastListener *m_multicastListener;
209         CallSignalListener *m_callSignalListener;
210         StatusListener *m_statusListener;
211         WORD m_rasPort, m_multicastPort, m_signalPort, m_statusPort;
212         RasServer *m_rasSrv;
213
214 private:
215         virtual RasListener *CreateRasListener();
216         virtual MulticastListener *CreateMulticastListener();
217         virtual CallSignalListener *CreateCallSignalListener();
218         virtual StatusListener *CreateStatusListener();
219 };
220
221 class RasHandler {
222 public:
223         typedef PIPSocket::Address Address;
224
225         RasHandler();
226         virtual ~RasHandler() {}
227
228         // new virtual function
229
230         // check if the message is the expected one
231         // default behavior: check if the tag is in m_tagArray
232         virtual bool IsExpected(const RasMsg *) const;
233
234         // process the RasMsg object
235         // the object must be deleted after processed
236         virtual void Process(RasMsg *) = 0;
237
238         // give the derived class an opportunity to create customized PDU
239         // default behavior: return the original one
240         // Note: call RasMsg::Release() if new one is created
241         virtual RasMsg *CreatePDU(RasMsg *ras) { return ras; }
242
243         // stop the handler
244         virtual void Stop() {}
245
246 protected:
247         void AddFilter(unsigned);
248
249         RasServer *m_rasSrv;
250
251 private:
252         // delete the object after running RasMsg::Exec()
253         static void ProcessRAS(RasMsg *);
254
255         bool m_tagArray[MaxRasTag + 1];
256 };
257
258 // encapsulate a gatekeeper request and reply
259 class RasRequester : public RasHandler {
260 public:
261         RasRequester() { Init(); }
262         // note the H225_RasMessage object must have
263         // longer lifetime than this object
264         RasRequester(H225_RasMessage &);
265         RasRequester(H225_RasMessage &, const Address &);
266         ~RasRequester();
267
268         WORD GetSeqNum() const { return m_seqNum; }
269         bool WaitForResponse(int);
270         RasMsg *GetReply();
271
272         // override from class RasHandler
273         virtual bool IsExpected(const RasMsg *) const;
274         virtual void Process(RasMsg *);
275         virtual void Stop();
276
277         // new virtual function
278         virtual bool SendRequest(const Address &, WORD, int = 2);
279         virtual bool OnTimeout();
280
281 protected:
282         void AddReply(RasMsg *);
283
284         H225_RasMessage *m_request;
285         WORD m_seqNum;
286         Address m_txAddr, m_loAddr;
287         WORD m_txPort;
288         PTime m_sentTime;
289         int m_timeout, m_retry;
290         PSyncPoint m_sync;
291
292 private:
293         void Init();
294
295         PMutex m_qmutex;
296         std::list<RasMsg *> m_queue;
297         std::list<RasMsg *>::iterator m_iterator;
298 };
299
300 template<class RAS>
301 class Requester : public RasRequester {
302 public:
303         typedef typename RasInfo<RAS>::Tag Tag;
304         typedef typename RasInfo<RAS>::ConfirmTag ConfirmTag;
305         typedef typename RasInfo<RAS>::RejectTag RejectTag;
306         Requester(H225_RasMessage &, const Address &);
307         ~Requester() { this->m_rasSrv->UnregisterHandler(this); } // fix for GCC 3.4.2
308 };
309
310 template<class RAS>
311 Requester<RAS>::Requester(H225_RasMessage & obj_ras, const Address & ip) : RasRequester(obj_ras, ip)
312 {
313         obj_ras.SetTag(Tag());
314         RAS & ras = obj_ras;
315         ras.m_requestSeqNum = GetSeqNum();
316         AddFilter(ConfirmTag());
317         AddFilter(RejectTag());
318         this->m_rasSrv->RegisterHandler(this); // fix for GCC 3.4.2
319 }
320
321 /*****************************************************************
322
323 The template class let you to modify the default handler of a
324 given RAS message. Just explicitly specialize the Process method.
325 For example,
326
327 template<> bool HookedPDU<H225_RegistrationRequest>::Process()
328 {
329         do_something_before_process();
330         // call the default handler
331         bool result = m_opdu->Process();
332         do_something_after_process();
333         return result;
334 }
335
336 Then add a creator to hook the interested messages
337
338         HookedPDU<H225_RegistrationRequest>::Creator HookedRRQ;
339
340 Note the creator must be executed after RasServer::Run().
341
342 *****************************************************************/
343
344 template<class RAS>
345 class HookedPDU : public RasPDU<RAS> {
346 public:
347         HookedPDU(GatekeeperMessage *m, RasMsg *p) : RasPDU<RAS>(m), m_opdu(p) {}
348         ~HookedPDU() { m_opdu->Release(); }
349
350         virtual bool Process() { return m_opdu->Process(); }
351
352         typedef typename RasPDU<RAS>::RasCreator RasCreator;
353         struct Creator : public RasPDU<RAS>::Creator {
354                 Creator() { PAssert(this->m_old, "Error: Hook failed"); } // fix for GCC 3.4.2
355                 virtual RasMsg *operator()(GatekeeperMessage *m) const
356                 { return new HookedPDU<RAS>(m, dynamic_cast<RasCreator &>(*(this->m_old))(m)); } // fix for GCC 3.4.2
357         };
358
359 private:
360         RasMsg *m_opdu;
361 };
362
363 #endif // RASPDU_H