1 /*
2  *
3  * Inter Asterisk Exchange 2
4  *
5  * Open Phone Abstraction Library (OPAL)
6  *
7  * Describes the IAX2 extension of the OpalEndpoint class.
8  *
9  * Copyright (c) 2005 Indranet Technologies Ltd.
10  *
11  * The contents of this file are subject to the Mozilla Public License
12  * Version 1.0 (the "License"); you may not use this file except in
13  * compliance with the License. You may obtain a copy of the License at
14  * http://www.mozilla.org/MPL/
15  *
16  * Software distributed under the License is distributed on an "AS IS"
17  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
18  * the License for the specific language governing rights and limitations
19  * under the License.
20  *
21  * The Original Code is Open Phone Abstraction Library.
22  *
23  * The Initial Developer of the Original Code is Indranet Technologies Ltd.
24  *
25  * The author of this code is Derek J Smithies
26  *
27  * $Revision: 24719 $
28  * $Author: rjongbloed $
29  * $Date: 2010-09-23 18:55:55 -0500 (Thu, 23 Sep 2010) $
30  */
31 
32 #ifndef OPAL_IAX2_IAX2EP_H
33 #define OPAL_IAX2_IAX2EP_H
34 
35 #ifndef _PTLIB_H
36 #include <ptlib.h>
37 #endif
38 
39 #ifdef P_USE_PRAGMA
40 #pragma interface
41 #endif
42 
43 #include <opal/buildopts.h>
44 
45 #if OPAL_IAX2
46 
47 #include <opal/endpoint.h>
48 #include <iax2/iax2con.h>
49 #include <iax2/processor.h>
50 #include <iax2/regprocessor.h>
51 #include <iax2/specialprocessor.h>
52 
53 class IAX2Receiver;
54 class IAX2Transmit;
55 class IAX2Processor;
56 
57 /** A class to take frames from the transmitter, and disperse them to
58     the appropriate IAX2Connection class.  This class calls a method in
59     the IAX2EndPoint to do the dispersal. */
60 class IAX2IncomingEthernetFrames : public PThread
61 {
62   PCLASSINFO(IAX2IncomingEthernetFrames, PThread);
63 public:
64 
65   /**@name Constructors/destructors*/
66   //@{
67   /**Construct a distributor, to send packets on to the relevant connection */
68   IAX2IncomingEthernetFrames();
69 
70   /**Destroy the distributor */
~IAX2IncomingEthernetFrames()71   ~IAX2IncomingEthernetFrames() { }
72 
73   /**@name general worker methods*/
74   //@{
75   /*The method which gets everythig to happen */
76   virtual void Main();
77 
78   /**Set the endpoint variable */
79   void Assign(IAX2EndPoint *ep);
80 
81   /**Activate this thread to process all frames in the lists
82    */
ProcessList()83   void ProcessList() { activate.Signal(); }
84 
85   /**Cause this thread to die immediately */
86   void Terminate();
87 
88   //@}
89  protected:
90   /**Global variable which holds the application specific data */
91   IAX2EndPoint *endpoint;
92 
93   /**Flag to activate this thread*/
94   PSyncPoint activate;
95 
96   /**Flag to indicate if this receiver thread should keep listening for network data */
97   PBoolean           keepGoing;
98 };
99 
100 
101 
102 
103 /** A class to manage global variables. There is one Endpoint per application. */
104 class IAX2EndPoint : public OpalEndPoint
105 {
106   PCLASSINFO(IAX2EndPoint, OpalEndPoint);
107  public:
108   /**@name Construction */
109 
110   //@{
111   /**Create the endpoint, and define local variables */
112   IAX2EndPoint(
113     OpalManager & manager,
114     unsigned short port	= 4569
115   );
116 
117   /**Destroy the endpoint, and all associated connections*/
118   ~IAX2EndPoint();
119   //@}
120 
121   /**@name connection Connection handling */
122   //@{
123   /**Handle new incoming connection from listener.
124 
125   The default behaviour does nothing.
126   */
127   virtual PBoolean NewIncomingConnection(
128     OpalTransport * transport  /// Transport connection came in on
129   );
130 
131   /**Set up a connection to a remote party.
132      This is called from the OpalManager::MakeConnection() function once
133      it has determined that this is the endpoint for the protocol.
134 
135      The general form for this party parameter is:
136 
137        [iax2:]{username@][transport$]address[/extension][+context]
138 
139      where the various fields will have meanings specific to the endpoint
140      type. For example, with H.323 it could be "h323:Fred@site.com" which
141      indicates a user Fred at gatekeeper size.com. Whereas for the PSTN
142      endpoint it could be "pstn:5551234" which is to call 5551234 on the
143      first available PSTN line.
144 
145      The proto field is optional when passed to a specific endpoint. If it
146      is present, however, it must agree with the endpoints protocol name or
147      false is returned.
148 
149      This function usually returns almost immediately with the connection
150      continuing to occur in a new background thread.
151 
152      If false is returned then the connection could not be established. For
153      example if a PSTN endpoint is used and the assiciated line is engaged
154      then it may return immediately. Returning a non-NULL value does not
155      mean that the connection will succeed, only that an attempt is being
156      made.
157 
158      The default behaviour is pure.
159   */
160   virtual PSafePtr<OpalConnection> MakeConnection(
161 			      OpalCall & call,          ///<  Owner of connection
162 			      const PString & party,    ///<  Remote party to call
163 			      void * userData = NULL,   ///<  Arbitrary data to pass to connection
164 			      unsigned int options = 0, ///<  options to pass to connection
165 			      OpalConnection::StringOptions * stringOptions = NULL
166 			      );
167 
168   /**Create a connection for the IAX endpoint.
169      The default implementation is to create a IAX2Connection.
170   */
171   virtual IAX2Connection * CreateConnection(
172 					   OpalCall & call,            /// Owner of connection
173 					   const PString & token,      /// token used to identify connection
174 					   void * userData,             /// User data for connection
175 					   const PString & remoteParty, /// Url to call or is calling.
176              const PString & remotePartyName = PString::Empty() /// Name to call or is calling.
177 					   );
178   //@}
179 
180   /**@name worker Methods*/
181   //@{
182   /**Setup the Endpoint internval variables, which is called at program
183      startup.*/
184   PBoolean Initialise();
185 
186   /**Handle a received IAX frame. This may be a mini frame or full frame */
187   virtual void IncomingEthernetFrame (IAX2Frame *frame);
188 
189   /**A simple test to report if the connection associated with this
190      frame is still alive. This test is used when transmitting the
191      frame. If the connection is gone, don't bother transmitting the
192      frame. There are exceptins to this rule, such as when a hangup
193      packet is sent (which is after the connections has died. */
194   PBoolean ConectionForFrameIsAlive(IAX2Frame *f);
195 
196   /**Request a new source call number, one that is different to
197      all other source call numbers for this program.
198 
199      @return P_MAX_INDEX  if there is no available call number,
200      or return a unique valid call number.
201      */
202   PINDEX NextSrcCallNumber(IAX2Processor * processor);
203 
204   /**Write the token of all connections in the connectionsActive
205      structure to the trace file */
206   void ReportStoredConnections();
207 
208   /**Report the port in use for IAX calls */
ListenPortNumber()209   WORD ListenPortNumber()  { return 4569; }
210 
211   /**Pointer to the transmitter class, which is always valid*/
212   IAX2Transmit *transmitter;
213 
214   /**Pointer to the receiver class, which is always valid*/
215   IAX2Receiver    *receiver;
216 
217   /**Report the local username*/
GetLocalUserName()218   PString GetLocalUserName() { return localUserName; }
219 
220   /**Report the number used by the computer running this program*/
GetLocalNumber()221   PString GetLocalNumber() { return localNumber; }
222 
223   /**Set the username to some value */
224   void SetLocalUserName(PString newValue);
225 
226   /**Set the local (on this host) number to some value */
227   void SetLocalNumber(PString newValue);
228 
229   /**Report the password*/
GetPassword()230   PString & GetPassword() { return password; }
231 
232   /**Set the password to some value */
233   void SetPassword(PString newValue);
234 
235   /**It is possible that a retransmitted frame has been in the transmit queue,
236      and while sitting there that frames sending connection has died.  Thus,
237      prior to transmission, call tis method.
238 
239      @return True if a connection (which matches this Frame ) can be
240      found. */
241   PBoolean ConnectionForFrameIsAlive(IAX2Frame *f);
242 
243   /**Get out sequence number to use on status query frames*/
244   PINDEX GetOutSequenceNumberForStatusQuery();
245 
246   /**We have an incoming call. Do we accept ? */
247   void StartRinging(PString remoteCaller);
248 
249     /**Handle new incoming connection from listener.
250 
251     A return value of true indicates that the transport object should be
252     deleted by the caller. false indicates that something else (eg the
253     connection) has taken over responsibility for deleting the transport.
254 
255     Well, that is true of Opal. In iax2, we do all the work of creating a new
256     connection etc.  The transport arguement is ignore. In Iax2, this method
257     is void, as no value is returned.  Further, in iax2, we process the
258     incoming frame.
259     */
260     void NewIncomingConnection(
261       IAX2Frame *f  /// Frame carrying the new request.
262 		);
263 
264     /**A call back function whenever a connection is established.
265        This indicates that a connection to an endpoint was established. This
266        usually occurs after OnConnected() and indicates that the connection
267        is both connected and has media flowing.
268       */
269     void OnEstablished(
270        OpalConnection & con
271     );
272 
273     /**Called whenever a connection instance is finished being used to
274        manage a call. We trap this callback to remove the connection
275        from this endpoints token table. Once we are done the token
276        table, we then call the generic OpalEndpoint::OnReleased
277        method. */
278     virtual void OnReleased(
279       OpalConnection & connection   ///<  Connection that was established
280     );
281 
282    /**Get the data formats this endpoint is capable of operating.  This
283        provides a list of media data format names that may be used by an
284        OpalMediaStream may be created by a connection from this endpoint.
285 
286        Note that a specific connection may not actually support all of the
287        media formats returned here, but should return no more.
288 
289        The default behaviour is pure.
290       */
291   virtual OpalMediaFormatList GetMediaFormats() const;
292 
293   /**Return the bitmask which specifies the possible codecs we support */
294   PINDEX GetSupportedCodecs(OpalMediaFormatList & list);
295 
296   /**Return the bitmask which specifies the preferred codec */
297   PINDEX GetPreferredCodec(OpalMediaFormatList & list);
298 
299   /**Get the frame size (bytes) and frame duration (ms) for compressed
300      data from this codec */
301   void GetCodecLengths(PINDEX src, PINDEX &compressedBytes, PINDEX &duration);
302 
303   /**enum of the components from a remote party address string
304      These fields are from the address,
305 
306       [iax2:]{username@][transport$]address[/extension][+context]
307   */
308   enum IAX2RemoteAddressFields {
309     protoIndex     = 0,     /*!< the protocol, or iax2: field            */
310     userIndex      = 1,     /*!< the username, or alias field            */
311     transportIndex = 2,     /*!< the transport, or transport field       */
312     addressIndex   = 3,     /*!< the address, or 192.168.1.1 field       */
313     portIndex      = 4,     /*!< the port number                         */
314     extensionIndex = 5,     /*!< the extension, or "extension"" field    */
315     contextIndex   = 6,     /*!< the context,   or "+context" field      */
316     maximumIndex   = 7      /*!< the number of possible fields           */
317   };
318 
319   /**Given a remote party name of the format:
320 
321      [proto:][alias@][transport$]address[/extension]
322 
323      pull the string apart and get the components. The compoents are stored
324      in a PStringList, indexed by the enum RemoteAddressFields */
325   static PStringArray DissectRemoteParty(const PString & other);
326 
327   /**Pull frames off the incoming list, and pass on to the relevant
328      connection. If no matching connection found, delete the frame.
329      Repeat the process until no frames are left. */
330   void ProcessReceivedEthernetFrames();
331 
332   /**Report on the frames in the current transmitter class, which are
333      pending transmission*/
334   void ReportTransmitterLists(PString & answer, bool getFullReport = false);
335 
336   /**Copy to the supplied OpalMediaList the media formats we support*/
337   void CopyLocalMediaFormats(OpalMediaFormatList & list);
338 
339   /**Register with a remote iax2 server.  The host can either be a
340      hostname or ip address.  The password is optional as some servers
341      may not require it to register.  The requested refresh time is the
342      time that the registration should be refreshed in seconds.  The time
343      must be more than 10 seconds.*/
344   void Register(
345       const PString & host,
346       const PString & username,
347       const PString & password = PString::Empty(),
348       PINDEX requestedRefreshTime = 60
349     );
350 
351   enum RegisteredError {
352     RegisteredFailureUnknown
353   };
354 
355   /**This is a call back if an event related to registration occurs.
356      This callback should return as soon as possible.*/
357   virtual void OnRegistered(
358       const PString & host,
359       const PString & userName,
360       PBoolean isFailure,
361       RegisteredError reason = RegisteredFailureUnknown);
362 
363    /**Unregister from a registrar. This function is synchronous so it
364       will block.*/
365   void Unregister(
366       const PString & host,
367       const PString & username);
368 
369   enum UnregisteredError {
370     UnregisteredFailureUnknown
371   };
372 
373   /**This is a call back if an event related to unregistration occurs.
374      This callback should return as soon as possible.  Generally even if
375      a failure occurs when unregistering it should be ignored because it
376      does not matter to much that it couldn't unregister.*/
377   virtual void OnUnregistered(
378       const PString & host,
379       const PString & userName,
380       PBoolean isFailure,
381       UnregisteredError reason = UnregisteredFailureUnknown);
382 
383 
384   /**Check if an account is registered or being registered*/
385   PBoolean IsRegistered(const PString & host, const PString & username);
386 
387   /**Get the number of accounts that are being registered*/
388   PINDEX GetRegistrationsCount();
389 
390   /**Builds a url*/
391   PString BuildUrl(
392     const PString & host,
393     const PString & userName = PString::Empty(),
394     const PString & extension = PString::Empty(),
395     const PString & context = PString::Empty(),
396     const PString & transport = PString::Empty()
397   );
398 
399   /**Report if this iax2 endpoint class is correctly initialised */
InitialisedOK()400   PBoolean InitialisedOK() { return (transmitter != NULL) && (receiver != NULL); }
401 
402   /**Report if there are frames (from the ethernet) waiting to be
403      processed */
EthernetFramesToBeProcessed()404   PBoolean EthernetFramesToBeProcessed()
405   { return packetsReadFromEthernet.GetSize() > 0; }
406   //@}
407 
408  protected:
409   /**Thread which transfers frames from the Receiver to the
410      appropriate connection.  It momentarily locks the connection
411      list, searches through, and then completes the trasnsfer. If need
412      be, this thread will create a new conneciton (to cope with a new
413      incoming call) and add the new connections to the internal
414      list. */
415   IAX2IncomingEthernetFrames incomingFrameHandler;
416 
417   /**List of iax2 packets which has been read from the ethernet, and
418      is to be sent to the matching IAX2Connection */
419   IAX2FrameList   packetsReadFromEthernet;
420 
421   /**The socket on which all data is sent/received.*/
422   PUDPSocket  *sock;
423 
424   /** The local port */
425   unsigned short localPort;
426 
427   /**Number of active calls */
428   int callnumbs;
429 
430   /** lock on access to call numbers variable */
431   PMutex callNumbLock;
432 
433   /**Time when a call was started */
434   PTime callStartTime;
435 
436   /**Name of this user, which is used as the IeCallingNumber */
437   PString localUserName;
438 
439   /**Number, as used by the computer on the host running this program*/
440   PString localNumber;
441 
442   /**Password for this user, which is used when processing an authentication request */
443   PString password;
444 
445   /**Counter to use for sending on status query frames */
446   PINDEX statusQueryCounter;
447 
448   /**Mutex for the statusQueryCounter */
449   PMutex statusQueryMutex;
450 
451   /**Pointer to the Processor class which handles special packets (eg lagrq) that have no
452      destination call to handle them. */
453   IAX2SpecialProcessor * specialPacketHandler;
454 
455   /**For the supplied IAX2Frame, pass it to a connection in the
456      connectionsActive structure.  If no matching connection is found, return
457      false;
458 
459      If a matching connections is found, give the frame to the
460      connection (for the connection to process) and return true;
461   */
462   PBoolean ProcessInMatchingConnection(IAX2Frame *f);
463 
464   /**For the supplied IAX2Frame, pass it to a connection in the
465      connectionsActive structure.  We are told the token of the connection
466      that matches this particular frame.
467 
468 
469      @return true - this is the normal and expected outcome.
470      @return false - connection not found - say it died immediately
471      before this method was called */
472     PBoolean ProcessFrameInConnection(IAX2Frame *f, const PString & token);
473 
474   /**Take the supplied frame, and compare it with all the existing
475      connections.  If any of the existing connections has a matching
476      dest call number, then put this frame to that connection.
477 
478      Update the token translation dictionary if the supplied frame has
479      a valid connection token. */
480   PBoolean ProcessInConnectionTestAll(IAX2Frame *f);
481 
482   /**tokenTable is a hack to allow IAX2 to fit in with one of the
483      demands of the opal library.
484 
485      Opal demands that at connection setup, we know the unique ID which
486      this call will use.
487 
488      Since the unique ID is remote ip adress + remote's Source Call
489      number, this is unknown if we are initiating the
490      call. Consequently, this table is needed, as it provides a
491      translation between the initial (or psuedo) token and the
492      token that is later adopted */
493 
494   PStringToString    tokenTable;
495 
496   /**Threading mutex on the variable tokenTable. We can now safely
497      read/write to this table, with the minimum of interference between
498      threads.  */
499   PReadWriteMutex    mutexTokenTable;
500 
501   /**Thread safe counter which keeps track of the calls created by this endpoint.
502      This value is used when giving outgoing calls a unique ID */
503   PAtomicInteger callsEstablished;
504 
505   /**Local copy of the media types we can handle*/
506   OpalMediaFormatList localMediaFormats;
507 
508    /**A mutex to protect the registerProcessors collection*/
509   PMutex regProcessorsMutex;
510 
511   /**An array of register processors.  These are created when
512      another class calls register and deleted when another class
513      calls unregister or class destructor is called.  This collection
514      must be protected by the regProcessorsMutex*/
515   PArrayObjects regProcessors;
516 
517 };
518 
519 
520 #endif // OPAL_IAX2
521 
522 #endif // OPAL_IAX2_IAX2EP_H
523 
524 /* The comment below is magic for those who use emacs to edit this file.
525  * With the comment below, the tab key does auto indent to 2 spaces.
526  *
527  * Local Variables:
528  * mode:c
529  * c-basic-offset:2
530  * End:
531  */
532 
533