3 * Inter Asterisk Exchange 2
5 * Open Phone Abstraction Library (OPAL)
7 * Describes the IAX2 extension of the OpalEndpoint class.
9 * Copyright (c) 2005 Indranet Technologies Ltd.
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/
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
21 * The Original Code is Open Phone Abstraction Library.
23 * The Initial Developer of the Original Code is Indranet Technologies Ltd.
25 * The author of this code is Derek J Smithies
28 * Revision 1.13 2007/04/19 06:17:21 csoutheren
29 * Fixes for precompiled headers with gcc
31 * Revision 1.12 2007/03/13 00:32:16 csoutheren
32 * Simple but messy changes to allow compile time removal of protocol
33 * options such as H.450 and H.460
34 * Fix MakeConnection overrides
36 * Revision 1.11 2007/03/01 05:51:03 rjongbloed
37 * Fixed backward compatibility of OnIncomingConnection() virtual
38 * functions on various classes. If an old override returned FALSE
39 * then it will now abort the call as it used to.
41 * Revision 1.10 2007/01/24 04:00:55 csoutheren
42 * Arrrghh. Changing OnIncomingConnection turned out to have a lot of side-effects
43 * Added some pure viritual functions to prevent old code from breaking silently
44 * New OpalEndpoint and OpalConnection descendants will need to re-implement
45 * OnIncomingConnection. Sorry :)
47 * Revision 1.9 2007/01/12 02:39:00 dereksmithies
48 * Remove the notion of srcProcessors and dstProcessor lists from the ep.
49 * Ensure that the connection looks after the callProcessor.
51 * Revision 1.8 2007/01/09 03:32:23 dereksmithies
52 * Tidy up and improve the close down process - make it more robust.
53 * Alter level of several PTRACE statements. Add Terminate() method to transmitter and receiver.
55 * Revision 1.7 2006/12/18 03:18:41 csoutheren
56 * Messy but simple fixes
57 * - Add access to SIP REGISTER timeout
58 * - Ensure OpalConnection options are correctly progagated
60 * Revision 1.6 2006/09/11 03:08:51 dereksmithies
61 * Add fixes from Stephen Cook (sitiveni@gmail.com) for new patches to
62 * improve call handling. Notably, IAX2 call transfer. Many thanks.
63 * Thanks also to the Google summer of code for sponsoring this work.
65 * Revision 1.5 2006/08/09 03:46:39 dereksmithies
66 * Add ability to register to a remote Asterisk box. The iaxProcessor class is split
67 * into a callProcessor and a regProcessor class.
68 * Big thanks to Stephen Cook, (sitiveni@gmail.com) for this work.
70 * Revision 1.4 2005/08/26 03:07:38 dereksmithies
71 * Change naming convention, so all class names contain the string "IAX2"
73 * Revision 1.3 2005/08/24 01:38:38 dereksmithies
74 * Add encryption, iax2 style. Numerous tidy ups. Use the label iax2, not iax
76 * Revision 1.2 2005/08/04 08:14:17 rjongbloed
77 * Fixed Windows build under DevStudio 2003 of IAX2 code
79 * Revision 1.1 2005/07/30 07:01:32 csoutheren
80 * Added implementation of IAX2 (Inter Asterisk Exchange 2) protocol
81 * Thanks to Derek Smithies of Indranet Technologies Ltd. for
82 * writing and contributing this code
90 #ifndef IAX_ENDPOINT_H
91 #define IAX_ENDPOINT_H
101 #include <opal/endpoint.h>
102 #include <iax2/iax2con.h>
103 #include <iax2/processor.h>
104 #include <iax2/regprocessor.h>
105 #include <iax2/specialprocessor.h>
111 /** A class to take frames from the transmitter, and disperse them to
112 the appropriate IAX2Connection class. This class calls a method in
113 the IAX2EndPoint to do the dispersal. */
114 class IAX2IncomingEthernetFrames
: public PThread
116 PCLASSINFO(IAX2IncomingEthernetFrames
, PThread
);
119 /**@name Constructors/destructors*/
121 /**Construct a distributor, to send packets on to the relevant connection */
122 IAX2IncomingEthernetFrames();
124 /**Destroy the distributor */
125 ~IAX2IncomingEthernetFrames() { }
127 /**@name general worker methods*/
129 /*The method which gets everythig to happen */
132 /**Set the endpoint variable */
133 void Assign(IAX2EndPoint
*ep
);
135 /**Activate this thread to process all frames in the lists
139 /**Cause this thread to die immediately */
144 /**Global variable which holds the application specific data */
145 IAX2EndPoint
*endpoint
;
147 /**Flag to activate this thread*/
150 /**Flag to indicate if this receiver thread should keep listening for network data */
155 /** A class to manage global variables. There is one Endpoint per application. */
156 class IAX2EndPoint
: public OpalEndPoint
158 PCLASSINFO(IAX2EndPoint
, OpalEndPoint
);
160 /**@name Construction */
163 /**Create the endpoint, and define local variables */
165 OpalManager
& manager
168 /**Destroy the endpoint, and all associated connections*/
172 /**@name connection Connection handling */
174 /**Handle new incoming connection from listener.
176 The default behaviour does nothing.
178 virtual BOOL
NewIncomingConnection(
179 OpalTransport
* transport
/// Transport connection came in on
182 /**Set up a connection to a remote party.
183 This is called from the OpalManager::MakeConnection() function once
184 it has determined that this is the endpoint for the protocol.
186 The general form for this party parameter is:
188 [iax2:]{username@][transport$]address[/extension][+context]
190 where the various fields will have meanings specific to the endpoint
191 type. For example, with H.323 it could be "h323:Fred@site.com" which
192 indicates a user Fred at gatekeeper size.com. Whereas for the PSTN
193 endpoint it could be "pstn:5551234" which is to call 5551234 on the
194 first available PSTN line.
196 The proto field is optional when passed to a specific endpoint. If it
197 is present, however, it must agree with the endpoints protocol name or
200 This function usually returns almost immediately with the connection
201 continuing to occur in a new background thread.
203 If FALSE is returned then the connection could not be established. For
204 example if a PSTN endpoint is used and the assiciated line is engaged
205 then it may return immediately. Returning a non-NULL value does not
206 mean that the connection will succeed, only that an attempt is being
209 The default behaviour is pure.
211 virtual BOOL
MakeConnection(
212 OpalCall
& call
, /// Owner of connection
213 const PString
& party
, /// Remote party to call
214 void * userData
= NULL
, /// Arbitrary data to pass to connection
215 unsigned int options
= 0, ///< options to pass to connection
216 OpalConnection::StringOptions
* stringOptions
= NULL
219 /**Create a connection for the IAX endpoint.
220 The default implementation is to create a IAX2Connection.
222 virtual IAX2Connection
* CreateConnection(
223 OpalCall
& call
, /// Owner of connection
224 const PString
& token
, /// token used to identify connection
225 void * userData
, /// User data for connection
226 const PString
& remoteParty
, /// Url to call or is calling.
227 const PString
& remotePartyName
= PString::Empty() /// Name to call or is calling.
231 /**@name worker Methods*/
233 /**Setup the Endpoint internval variables, which is called at program
237 /**Handle a received IAX frame. This may be a mini frame or full frame */
238 virtual void IncomingEthernetFrame (IAX2Frame
*frame
);
240 /**A simple test to report if the connection associated with this
241 frame is still alive. This test is used when transmitting the
242 frame. If the connection is gone, don't bother transmitting the
243 frame. There are exceptins to this rule, such as when a hangup
244 packet is sent (which is after the connections has died. */
245 BOOL
ConectionForFrameIsAlive(IAX2Frame
*f
);
247 /**Request a new source call number, one that is different to
248 all other source call numbers for this program.
250 @return P_MAX_INDEX if there is no available call number,
251 or return a unique valid call number.
253 PINDEX
NextSrcCallNumber(IAX2Processor
* processor
);
255 /**Write the token of all connections in the connectionsActive
256 structure to the trace file */
257 void ReportStoredConnections();
259 /**Report the port in use for IAX calls */
260 WORD
ListenPortNumber() { return 4569; }
262 /**Pointer to the transmitter class, which is always valid*/
263 IAX2Transmit
*transmitter
;
265 /**Pointer to the receiver class, which is always valid*/
266 IAX2Receiver
*receiver
;
268 /**Report the local username*/
269 PString
GetLocalUserName() { return localUserName
; }
271 /**Report the number used by the computer running this program*/
272 PString
GetLocalNumber() { return localNumber
; }
274 /**Set the username to some value */
275 void SetLocalUserName(PString newValue
);
277 /**Set the local (on this host) number to some value */
278 void SetLocalNumber(PString newValue
);
280 /**Report the password*/
281 PString
& GetPassword() { return password
; }
283 /**Set the password to some value */
284 void SetPassword(PString newValue
);
286 /**It is possible that a retransmitted frame has been in the transmit queue,
287 and while sitting there that frames sending connection has died. Thus,
288 prior to transmission, call tis method.
290 @return True if a connection (which matches this Frame ) can be
292 BOOL
ConnectionForFrameIsAlive(IAX2Frame
*f
);
294 /**Get out sequence number to use on status query frames*/
295 PINDEX
GetOutSequenceNumberForStatusQuery();
297 /**We have an incoming call. Do we accept ? */
298 void StartRinging(PString remoteCaller
);
300 /**Call back for when a connection has closed */
301 void OnConnectionClose(IAX2Connection
& con
);
303 /**Handle new incoming connection from listener.
305 A return value of TRUE indicates that the transport object should be
306 deleted by the caller. FALSE indicates that something else (eg the
307 connection) has taken over responsibility for deleting the transport.
309 Well, that is true of Opal. In iax2, we do all the work of creating a new
310 connection etc. The transport arguement is ignore. In Iax2, this method
311 is void, as no value is returned. Further, in iax2, we process the
314 void NewIncomingConnection(IAX2Frame
*f
/// Frame carrying the new request.
318 /**Call back for when a connections is established (we have received
319 the first media packet) */
320 void OnEstablished(OpalConnection
& con
);
322 /**Get the data formats this endpoint is capable of operating. This
323 provides a list of media data format names that may be used by an
324 OpalMediaStream may be created by a connection from this endpoint.
326 Note that a specific connection may not actually support all of the
327 media formats returned here, but should return no more.
329 The default behaviour is pure.
331 virtual OpalMediaFormatList
GetMediaFormats() const;
333 /**Return the bitmask which specifies the possible codecs we support */
334 PINDEX
GetSupportedCodecs(OpalMediaFormatList
& list
);
336 /**Return the bitmask which specifies the preferred codec */
337 PINDEX
GetPreferredCodec(OpalMediaFormatList
& list
);
339 /**Get the frame size (bytes) and frame duration (ms) for compressed
340 data from this codec */
341 void GetCodecLengths(PINDEX src
, PINDEX
&compressedBytes
, PINDEX
&duration
);
343 /**enum of the components from a remote party address string
344 These fields are from the address,
346 [iax2:]{username@][transport$]address[/extension][+context]
348 enum IAX2RemoteAddressFields
{
349 protoIndex
= 0, /*!< the protocol, or iax2: field */
350 userIndex
= 1, /*!< the username, or alias field */
351 transportIndex
= 2, /*!< the transport, or transport field */
352 addressIndex
= 3, /*!< the address, or 192.168.1.1 field */
353 extensionIndex
= 4, /*!< the extension, or "extension"" field */
354 contextIndex
= 5, /*!< the context, or "+context" field */
355 maximumIndex
= 6 /*!< the number of possible fields */
358 /**Given a remote party name of the format:
360 [proto:][alias@][transport$]address[/extension]
362 pull the string apart and get the components. The compoents are stored
363 in a PStringList, indexed by the enum RemoteAddressFields */
364 static PStringList
DissectRemoteParty(const PString
& other
);
366 /**Pull frames off the incoming list, and pass on to the relevant
367 connection. If no matching connection found, delete the frame.
368 Repeat the process until no frames are left. */
369 void ProcessReceivedEthernetFrames();
372 /**Report on the frames in the current transmitter class, which are
373 pending transmission*/
374 void ReportTransmitterLists();
376 /**Copy to the supplied OpalMediaList the media formats we support*/
377 void CopyLocalMediaFormats(OpalMediaFormatList
& list
);
379 /**Register with a remote iax2 server. The host can either be a
380 hostname or ip address. The password is optional as some servers
381 may not require it to register. The requested refresh time is the
382 time that the registration should be refreshed in seconds. The time
383 must be more than 10 seconds.*/
385 const PString
& host
,
386 const PString
& username
,
387 const PString
& password
= PString::Empty(),
388 PINDEX requestedRefreshTime
= 60
391 enum RegisteredError
{
392 RegisteredFailureUnknown
395 /**This is a call back if an event related to registration occurs.
396 This callback should return as soon as possible.*/
397 virtual void OnRegistered(
398 const PString
& host
,
399 const PString
& userName
,
401 RegisteredError reason
= RegisteredFailureUnknown
);
403 /**Unregister from a registrar. This function is synchronous so it
406 const PString
& host
,
407 const PString
& username
);
409 enum UnregisteredError
{
410 UnregisteredFailureUnknown
413 /**This is a call back if an event related to unregistration occurs.
414 This callback should return as soon as possible. Generally even if
415 a failure occurs when unregistering it should be ignored because it
416 does not matter to much that it couldn't unregister.*/
417 virtual void OnUnregistered(
418 const PString
& host
,
419 const PString
& userName
,
421 UnregisteredError reason
= UnregisteredFailureUnknown
);
424 /**Check if an account is registered or being registered*/
425 BOOL
IsRegistered(const PString
& host
, const PString
& username
);
427 /**Get the number of accounts that are being registered*/
428 PINDEX
GetRegistrationsCount();
432 const PString
& host
,
433 const PString
& userName
= PString::Empty(),
434 const PString
& extension
= PString::Empty(),
435 const PString
& context
= PString::Empty(),
436 const PString
& transport
= PString::Empty()
442 /**Thread which transfers frames from the Receiver to the
443 appropriate connection. It momentarily locks the connection
444 list, searches through, and then completes the trasnsfer. If need
445 be, this thread will create a new conneciton (to cope with a new
446 incoming call) and add the new connections to the internal
448 IAX2IncomingEthernetFrames incomingFrameHandler
;
450 /**List of iax packets which has been read from the ethernet, and
451 is to be sent to the matching IAX2Connection */
452 IAX2FrameList packetsReadFromEthernet
;
454 /**The socket on which all data is sent/received.*/
457 /**Number of active calls */
460 /** lock on access to call numbers variable */
463 /**Time when a call was started */
466 /**Name of this user, which is used as the IeCallingNumber */
467 PString localUserName
;
469 /**Number, as used by the computer on the host running this program*/
472 /**Password for this user, which is used when processing an authentication request */
475 /**Counter to use for sending on status query frames */
476 PINDEX statusQueryCounter
;
478 /**Mutex for the statusQueryCounter */
479 PMutex statusQueryMutex
;
481 /**Pointer to the Processor class which handles special packets (eg lagrq) that have no
482 destination call to handle them. */
483 IAX2SpecialProcessor
* specialPacketHandler
;
485 /**For the supplied IAX2Frame, pass it to a connection in the
486 connectionsActive structure. If no matching connection is found, return
489 If a matching connections is found, give the frame to the
490 connection (for the connection to process) and return TRUE;
492 BOOL
ProcessInMatchingConnection(IAX2Frame
*f
);
494 /**The TokenTranslationDict may need a new entry. Examine
495 the list of active connections, to see if any match this frame.
496 If any do, then we add a new translation entry in tokenTable;
498 If a matching connection is found in connectionsActive, create a
499 new translation entry and return TRUE. The connection, after
500 processing the frame, will then delete the frame. */
501 BOOL
AddNewTranslationEntry(IAX2Frame
*f
);
503 /**tokenTable is a hack to allow IAX2 to fit in with one of the
504 demands of the opal library.
506 Opal demands that at connection setup, we know the unique ID which
509 Since the unique ID is remote ip adress + remote's Source Call
510 number, this is unknown if we are initiating the
511 call. Consequently, this table is needed, as it provides a
512 translation between the initial (or psuedo) token and the
513 token that is later adopted */
515 PStringToString tokenTable
;
517 /**Threading mutex on the variable tokenTable */
518 PMutex mutexTokenTable
;
520 /**Thread safe counter which keeps track of the calls created by this endpoint.
521 This value is used when giving outgoing calls a unique ID */
522 PAtomicInteger callsEstablished
;
524 /**Local copy of the media types we can handle*/
525 OpalMediaFormatList localMediaFormats
;
527 /**A mutex to protect the registerProcessors collection*/
528 PMutex regProcessorsMutex
;
530 /**An array of register processors. These are created when
531 another class calls register and deleted when another class
532 calls unregister or class destructor is called. This collection
533 must be protected by the regProcessorsMutex*/
534 PArrayObjects regProcessors
;
538 #endif // IAX_ENDPOINT_H
539 /* The comment below is magic for those who use emacs to edit this file. */
540 /* With the comment below, the tab key does auto indent to 4 spaces. */