1 /**
2  * yateiax.h
3  * Yet Another IAX2 Stack
4  * This file is part of the YATE Project http://YATE.null.ro
5  *
6  * Yet Another Telephony Engine - a fully featured software PBX and IVR
7  * Copyright (C) 2004-2014 Null Team
8  *
9  * This software is distributed under multiple licenses;
10  * see the COPYING file in the main directory for licensing
11  * information for this specific distribution.
12  *
13  * This use of this software may be subject to additional restrictions.
14  * See the LEGAL file in the main directory for details.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  */
20 
21 #ifndef __YATEIAX_H
22 #define __YATEIAX_H
23 
24 #include <yateclass.h>
25 
26 #ifdef _WINDOWS
27 
28 #ifdef LIBYIAX_EXPORTS
29 #define YIAX_API __declspec(dllexport)
30 #else
31 #ifndef LIBYIAX_STATIC
32 #define YIAX_API __declspec(dllimport)
33 #endif
34 #endif
35 
36 #endif /* _WINDOWS */
37 
38 #ifndef YIAX_API
39 #define YIAX_API
40 #endif
41 
42 /**
43  * Holds all Telephony Engine related classes.
44  */
45 namespace TelEngine {
46 
47 class IAXInfoElement;                    // A single IAX2 Information Element
48 class IAXInfoElementString;              // A single IAX2 text Information Element
49 class IAXInfoElementNumeric;             // A single IAX2 numeric Information Element
50 class IAXInfoElementBinary;              // A single IAX2 numeric Information Element
51 class IAXIEList;                         // Information Element container
52 class IAXAuthMethod;                     // Wrapper class for authentication methods values
53 class IAXFormatDesc;                     // IAX format description
54 class IAXFormat;                         // Wrapper class for formats
55 class IAXControl;                        // Wrapper class for subclasses of frames of type IAX
56 class IAXFrame;                          // This class holds an IAX frame
57 class IAXFullFrame;                      // This class holds an IAX full frame
58 class IAXFrameOut;                       // This class holds an outgoing IAX full frame
59 class IAXTrunkInfo;                      // Trunk info
60 class IAXMetaTrunkFrame;                 // Meta trunk frame
61 class IAXMediaData;                      // IAX2 transaction media data
62 class IAXTransaction;                    // An IAX2 transaction
63 class IAXEvent;                          // Event class
64 class IAXEngine;                         // IAX engine
65 
66 #define IAX_PROTOCOL_VERSION         0x0002           // Protocol version
67 #define IAX2_MAX_CALLNO              32767            // Max call number value
68 #define IAX2_MAX_TRANSINFRAMELIST    127              // Max transaction incoming frame list
69 
70 // Trunk frame header length
71 #define IAX2_TRUNKFRAME_HEADERLENGTH 8
72 // Trunk frame length
73 #define IAX2_TRUNKFRAME_LEN_MIN 20                    // 16 bytes: meta header + miniframe with timestamps header
74 #define IAX2_TRUNKFRAME_LEN_DEF 1400
75 // Trunk frame send interval in milliseconds
76 #define IAX2_TRUNKFRAME_SEND_MIN 5
77 #define IAX2_TRUNKFRAME_SEND_DEF 20
78 
79 // Frame retransmission
80 #define IAX2_RETRANS_COUNT_MIN 1
81 #define IAX2_RETRANS_COUNT_MAX 10
82 #define IAX2_RETRANS_COUNT_DEF 4
83 #define IAX2_RETRANS_INTERVAL_MIN 200
84 #define IAX2_RETRANS_INTERVAL_MAX 5000
85 #define IAX2_RETRANS_INTERVAL_DEF 500
86 
87 // Ping
88 #define IAX2_PING_INTERVAL_MIN 10000
89 #define IAX2_PING_INTERVAL_DEF 20000
90 
91 // Sent challenge timeout
92 #define IAX2_CHALLENGETOUT_MIN 5000
93 #define IAX2_CHALLENGETOUT_DEF 30000
94 
95 /**
96  * This class holds a single Information Element with no data
97  * @short A single IAX2 Information Element
98  */
99 class YIAX_API IAXInfoElement : public RefObject
100 {
101 public:
102     /**
103      * Information Element enumeration types
104      */
105     enum Type {
106 	textframe = 0x00,	 // Text	Used internally only to generate an event of type Text
107         CALLED_NUMBER = 0x01,    // Text
108         CALLING_NUMBER = 0x02,   // Text
109         CALLING_ANI = 0x03,      // Text
110         CALLING_NAME = 0x04,     // Text
111         CALLED_CONTEXT = 0x05,   // Text
112         USERNAME = 0x06,         // Text
113         PASSWORD = 0x07,         // Text
114         CAPABILITY = 0x08,       // DW
115         FORMAT = 0x09,           // DW
116         LANGUAGE = 0x0a,         // Text
117         VERSION = 0x0b,          // W		Value: IAX_PROTOCOL_VERSION
118         ADSICPE = 0x0c,          // W
119         DNID = 0x0d,             // Text
120         AUTHMETHODS = 0x0e,      // W
121         CHALLENGE = 0x0f,        // Text
122         MD5_RESULT = 0x10,       // Text
123         RSA_RESULT = 0x11,       // Text
124         APPARENT_ADDR = 0x12,    // BIN
125         REFRESH = 0x13,          // W
126         DPSTATUS = 0x14,         // W
127         CALLNO = 0x15,           // W		Max value: IAX2_MAX_CALLNO
128         CAUSE = 0x16,            // Text
129         IAX_UNKNOWN = 0x17,      // B
130         MSGCOUNT = 0x18,         // W
131         AUTOANSWER = 0x19,       // Null
132         MUSICONHOLD = 0x1a,      // Text
133         TRANSFERID = 0x1b,       // DW
134         RDNIS = 0x1c,            // Text
135         PROVISIONING = 0x1d,     // BIN
136         AESPROVISIONING = 0x1e,  // BIN
137         DATETIME = 0x1f,         // DW
138         DEVICETYPE = 0x20,       // Text
139         SERVICEIDENT = 0x21,     // BIN
140         FIRMWAREVER = 0x22,      // W
141         FWBLOCKDESC = 0x23,      // DW
142         FWBLOCKDATA = 0x24,      // BIN
143         PROVVER = 0x25,          // DW
144         CALLINGPRES = 0x26,      // B
145         CALLINGTON = 0x27,       // B
146         CALLINGTNS = 0x28,       // W
147         SAMPLINGRATE = 0x29,     // DW
148         CAUSECODE = 0x2a,        // B
149         ENCRYPTION = 0x2b,       // B
150         ENKEY = 0x2c,            // BIN
151         CODEC_PREFS = 0x2d,      // Text
152         RR_JITTER = 0x2e,        // DW
153         RR_LOSS = 0x2f,          // DW
154         RR_PKTS = 0x30,          // DW
155         RR_DELAY = 0x31,         // W
156         RR_DROPPED = 0x32,       // DW
157         RR_OOO = 0x33,           // DW
158         CALLTOKEN = 0x36,        // BIN
159         CAPABILITY2 = 0x37,      // BIN		1 byte version + array
160         FORMAT2 = 0x38,          // BIN		1 byte version + array
161     };
162 
163     /**
164      * Constructor
165      * @param type Type of this IE
166      */
IAXInfoElement(Type type)167     inline IAXInfoElement(Type type) : m_type(type) {}
168 
169     /**
170      * Destructor
171      */
~IAXInfoElement()172     virtual ~IAXInfoElement() {}
173 
174     /**
175      * Get the type of this IE
176      * @return Type of this IE
177      */
type()178     inline Type type() const
179         { return m_type; }
180 
181     /**
182      * Constructs a buffer containing this Information Element
183      * @param buf Destination buffer
184      */
185     virtual void toBuffer(DataBlock& buf);
186 
187     /**
188      * Add this element to a string
189      * @param buf Destination string
190      */
191     virtual void toString(String& buf);
192 
193     /**
194      * Get the text associated with an IE type value
195      * @param ieCode Numeric code of the IE
196      * @return Pointer to the IE text or 0 if it doesn't exist
197      */
ieText(u_int8_t ieCode)198     static inline const char* ieText(u_int8_t ieCode)
199 	{ return lookup(ieCode,s_ieData); }
200 
201     /**
202      * Retrieve the cause name associated with a given code
203      * @param code Cause code
204      * @return Cause name, 0 if not found
205      */
causeName(int code)206     static inline const char* causeName(int code)
207 	{ return lookup(code,s_causeName); }
208 
209     /**
210      * Retrieve the cause code associated with a given name
211      * @param name Cause name
212      * @param defVal Default value to return if not found
213      * @return Cause code
214      */
215     static inline int causeCode(const char* name, int defVal = 0)
216 	{ return lookup(name,s_causeName,defVal); }
217 
218     /**
219      * Cause code dictionary
220      */
221     static const TokenDict s_causeName[];
222 
223     /**
224      * Number type dictionary
225      */
226     static const TokenDict s_typeOfNumber[];
227 
228     /**
229      * Number presentation dictionary
230      */
231     static const TokenDict s_presentation[];
232 
233     /**
234      * Number screening dictionary
235      */
236     static const TokenDict s_screening[];
237 
238 private:
239     static const TokenDict s_ieData[];// Association between IE type and text
240     Type m_type;		// Type of this IE
241 };
242 
243 /**
244  * This class holds a single Information Element with text data
245  * @short A single IAX2 text Information Element
246  */
247 class YIAX_API IAXInfoElementString : public IAXInfoElement
248 {
249 public:
250     /**
251      * Constructor
252      * @param type Type of this IE
253      * @param buf Source buffer to construct this IE
254      * @param len Buffer length
255      */
IAXInfoElementString(Type type,const char * buf,unsigned len)256     inline IAXInfoElementString(Type type, const char* buf, unsigned len) : IAXInfoElement(type), m_strData(buf,(int)len)
257         {}
258 
259     /**
260      * Destructor
261      */
~IAXInfoElementString()262     virtual ~IAXInfoElementString() {}
263 
264     /**
265      * Get the data length
266      * @return The data length
267      */
length()268     inline int length() const
269         { return m_strData.length(); }
270 
271     /**
272      * Get the data
273      * @return The data
274      */
data()275     inline String& data()
276         { return m_strData; }
277 
278     /**
279      * Constructs a buffer containing this Information Element
280      * @param buf Destination buffer
281      */
282     virtual void toBuffer(DataBlock& buf);
283 
284     /**
285      * Add this element to a string
286      * @param buf Destination string
287      */
toString(String & buf)288     virtual void toString(String& buf)
289 	{ buf << m_strData; }
290 
291 private:
292     String m_strData;		// IE text data
293 };
294 
295 /**
296  * This class holds a single Information Element with 1, 2 or 4 byte(s) length data
297  * @short A single IAX2 numeric Information Element
298  */
299 class YIAX_API IAXInfoElementNumeric : public IAXInfoElement
300 {
301 public:
302     /**
303      * Constructor
304      * @param type Type of this IE
305      * @param val Source value to construct this IE
306      * @param len Value length
307      */
308     IAXInfoElementNumeric(Type type, u_int32_t val, u_int8_t len);
309 
310     /**
311      * Destructor
312      */
~IAXInfoElementNumeric()313     virtual ~IAXInfoElementNumeric() {}
314 
315     /**
316      * Get the data length
317      * @return The data length
318      */
length()319     inline int length() const
320         { return m_length; }
321 
322     /**
323      * Get the data
324      * @return The data
325      */
data()326     inline u_int32_t data() const
327 	{ return m_numericData; }
328 
329     /**
330      * Constructs a buffer containing this Information Element
331      * @param buf Destination buffer
332      */
333     virtual void toBuffer(DataBlock& buf);
334 
335     /**
336      * Add this element to a string
337      * @param buf Destination string
338      */
339     virtual void toString(String& buf);
340 
341 private:
342     u_int8_t m_length;		// IE data length
343     u_int32_t m_numericData;	// IE numeric data
344 };
345 
346 /**
347  * This class holds a single Information Element with binary data
348  * @short A single IAX2 numeric Information Element
349  */
350 class YIAX_API IAXInfoElementBinary : public IAXInfoElement
351 {
352 public:
353     /**
354      * Constructor
355      * @param type Type of this IE
356      * @param buf Source buffer to construct this IE
357      * @param len Buffer length
358      */
IAXInfoElementBinary(Type type,unsigned char * buf,unsigned len)359     IAXInfoElementBinary(Type type, unsigned char* buf, unsigned len) : IAXInfoElement(type), m_data(buf,len)
360         {}
361 
362     /**
363      * Destructor
364      */
~IAXInfoElementBinary()365     virtual ~IAXInfoElementBinary() {}
366 
367     /**
368      * Get the data length
369      * @return The data length
370      */
length()371     inline int length() const
372         { return m_data.length(); }
373 
374     /**
375      * Get the data
376      * @return The data
377      */
data()378     inline DataBlock& data()
379         { return m_data; }
380 
381     /**
382      * Set the data
383      * @param buf Source buffer to construct this IE
384      * @param len Buffer length
385      */
setData(void * buf,unsigned len)386     inline void setData(void* buf, unsigned len)
387         { m_data.assign(buf,len); }
388 
389     /**
390      * Constructs a buffer containing this Information Element
391      * @param buf Destination buffer
392      */
393     virtual void toBuffer(DataBlock& buf);
394 
395     /**
396      * Constructs an APPARENT_ADDR information element from a SocketAddr object
397      * @param addr Source object
398      * @return A valid IAXInfoElementBinary pointer
399      */
400     static IAXInfoElementBinary* packIP(const SocketAddr& addr);
401 
402     /**
403      * Decode an APPARENT_ADDR information element and copy it to a SocketAddr object
404      * @param addr Destination object
405      * @param ie Source IE
406      * @return False if ie is 0
407      */
408     static bool unpackIP(SocketAddr& addr, IAXInfoElementBinary* ie);
409 
410     /**
411      * Add this element to a string
412      * @param buf Destination string
413      */
414     virtual void toString(String& buf);
415 
416 private:
417     DataBlock m_data;		// IE binary data
418 };
419 
420 /**
421  * Management class for a list of Information Elements
422  * @short Information Element container
423  */
424 class YIAX_API IAXIEList
425 {
426 public:
427     /**
428      * Constructor
429      */
430     IAXIEList();
431 
432     /**
433      * Constructor. Construct the list from an IAXFullFrame object
434      * @param frame Source object
435      * @param incoming True if it is an incoming frame
436      */
437     IAXIEList(const IAXFullFrame* frame, bool incoming = true);
438 
439     /**
440      * Destructor
441      */
442     ~IAXIEList();
443 
444     /**
445      * Get the invalid IE list flag
446      * @return False if the last frame parse was unsuccessful
447      */
invalidIEList()448     inline bool invalidIEList() const
449 	{ return m_invalidIEList; }
450 
451     /**
452      * Clear the list
453      */
clear()454     inline void clear()
455 	{ m_list.clear(); }
456 
457     /**
458      * Check if the list is empty
459      * @return True if the list is empty
460      */
empty()461     inline bool empty()
462 	{ return 0 == m_list.skipNull(); }
463 
464     /**
465      * Insert a VERSION Information Element in the list if not already done
466      */
467     void insertVersion();
468 
469     /**
470      * Get the validity of the VERSION Information Element of the list if any
471      * @return False if version is not IAX_PROTOCOL_VERSION or the list doesn't contain a VERSION Information Element
472      */
validVersion()473     inline bool validVersion() {
474 	    u_int32_t ver = 0xFFFF;
475 	    getNumeric(IAXInfoElement::VERSION,ver);
476 	    return ver == IAX_PROTOCOL_VERSION;
477 	}
478 
479     /**
480      * Append an Information Element to the list
481      * @param ie IAXInfoElement pointer to append
482      */
appendIE(IAXInfoElement * ie)483     inline void appendIE(IAXInfoElement* ie)
484 	{ m_list.append(ie); }
485 
486     /**
487      * Append an Information Element taken from another list
488      * @param src Source IE list
489      * @param type IE to move
490      * @return True if found and added
491      */
appendIE(IAXIEList & src,IAXInfoElement::Type type)492     inline bool appendIE(IAXIEList& src, IAXInfoElement::Type type) {
493 	    IAXInfoElement* ie = src.getIE(type,true);
494 	    if (ie)
495 		appendIE(ie);
496 	    return ie != 0;
497 	}
498 
499     /**
500      * Append an Information Element to the list
501      * @param type The type of the IAXInfoElement to append
502      */
appendNull(IAXInfoElement::Type type)503     inline void appendNull(IAXInfoElement::Type type)
504 	{ m_list.append(new IAXInfoElement(type)); }
505 
506     /**
507      * Append a text Information Element to the list from a String
508      * @param type The type of the IAXInfoElementString to append
509      * @param src The source
510      */
appendString(IAXInfoElement::Type type,const String & src)511     inline void appendString(IAXInfoElement::Type type, const String& src)
512 	{ m_list.append(new IAXInfoElementString(type,src.c_str(),src.length())); }
513 
514     /**
515      * Append a text Information Element to the list from a buffer
516      * @param type The type of the IAXInfoElementString to append
517      * @param src The source
518      * @param len Source length
519      */
appendString(IAXInfoElement::Type type,unsigned char * src,unsigned len)520     inline void appendString(IAXInfoElement::Type type, unsigned char* src, unsigned len)
521 	{ m_list.append(new IAXInfoElementString(type,(char*)src,len)); }
522 
523     /**
524      * Append a numeric Information Element to the list
525      * @param type The type of the IAXInfoElementNumeric to append
526      * @param value The source
527      * @param len Source length
528      */
appendNumeric(IAXInfoElement::Type type,u_int32_t value,u_int8_t len)529     inline void appendNumeric(IAXInfoElement::Type type, u_int32_t value, u_int8_t len)
530 	{ m_list.append(new IAXInfoElementNumeric(type,value,len)); }
531 
532     /**
533      * Append a binary Information Element to the list
534      * @param type The type of the IAXInfoElementBinary to append
535      * @param data The source data to append
536      * @param len Source length
537      */
appendBinary(IAXInfoElement::Type type,unsigned char * data,unsigned len)538     inline void appendBinary(IAXInfoElement::Type type, unsigned char* data, unsigned len)
539 	{ m_list.append(new IAXInfoElementBinary(type,data,len)); }
540 
541     /**
542      * Construct the list from an IAXFullFrame object.
543      *  On exit m_invalidIEList will contain the opposite of the returned value
544      * @param frame Source object
545      * @param incoming True if it is an incoming frame
546      * @return False if the frame contains invalid IEs
547      */
548     bool createFromFrame(const IAXFullFrame* frame, bool incoming = true);
549 
550     /**
551      * Construct a buffer from this list
552      * @param buf Destination buffer
553      */
554     void toBuffer(DataBlock& buf);
555 
556     /**
557      * Add this list to a string
558      * @param dest Destination string
559      * @param indent Optional indent for each element
560      */
561     void toString(String& dest, const char* indent = 0);
562 
563     /**
564      * Retrieve an IAXInfoElement from the list
565      * @param type The desired type
566      * @param remove True to remove from list. The caller will own the object
567      * @return An IAXInfoElement pointer or 0 if the list doesn't contain an IE of this type
568      */
569     IAXInfoElement* getIE(IAXInfoElement::Type type, bool remove = false);
570 
571     /**
572      * Get the data of a list item into a String. Before any operation dest is cleared
573      * @param type The desired type
574      * @param dest The destination String
575      * @return False if the list doesn't contain an IE of this type
576      */
577     bool getString(IAXInfoElement::Type type, String& dest);
578 
579     /**
580      * Get the data of a list item into a numeric destination
581      * @param type The desired type
582      * @param dest The destination
583      * @return False if the list doesn't contain an IE of this type
584      */
585     bool getNumeric(IAXInfoElement::Type type, u_int32_t& dest);
586 
587     /**
588      * Get the data of a list item into a DataBlock. Before any operation dest is cleared
589      * @param type The desired type
590      * @param dest The destination buffer
591      * @return False if the list doesn't contain an IE of this type
592      */
593     bool getBinary(IAXInfoElement::Type type, DataBlock& dest);
594 
595 private:
596     bool m_invalidIEList;	// Invalid IE flag
597     ObjList m_list;		// The IE list
598 };
599 
600 /**
601  * This class holds the enumeration values for authentication methods
602  * @short Wrapper class for authentication methods values
603  */
604 class YIAX_API IAXAuthMethod
605 {
606 public:
607     /**
608      * Authentication method enumeration types
609      */
610     enum Type {
611         Text = 1,
612         MD5  = 2,
613         RSA  = 4,
614     };
615 
616     /**
617      * Create a string list from authentication methods
618      * @param dest The destination
619      * @param auth The authentication methods as ORed bits
620      * @param sep The separator to use
621     */
622     static void authList(String& dest, u_int16_t auth, char sep);
623 
624     static TokenDict s_texts[];
625 };
626 
627 
628 /**
629  * This class holds IAX format description
630  * @short IAX format description
631  */
632 class YIAX_API IAXFormatDesc
633 {
634 public:
635     /**
636      * Constructor
637      */
IAXFormatDesc()638     inline IAXFormatDesc()
639 	: m_format(0), m_multiplier(1)
640 	{}
641 
642     /**
643      * Get the format
644      * @return The format
645      */
format()646     inline u_int32_t format() const
647 	{ return m_format; }
648 
649     /**
650      * Get the format multiplier used to translate timestamps
651      * @return The format multiplier (always greater then 0)
652      */
multiplier()653     inline unsigned int multiplier() const
654 	{ return m_multiplier; }
655 
656     /**
657      * Set the format
658      * @param fmt The format
659      * @param type Format type as IAXFormat::Media enumeration
660      */
661     void setFormat(u_int32_t fmt, int type);
662 
663 protected:
664     u_int32_t m_format;                  // The format
665     unsigned int m_multiplier;           // Format multiplier derived from sampling rate
666 };
667 
668 /**
669  * This class holds the enumeration values for audio and video formats
670  * @short Wrapper class for audio and video formats
671  */
672 class YIAX_API IAXFormat
673 {
674 public:
675     /**
676      * Format enumeration types
677      */
678     enum Formats {
679         G723_1 = (1 <<  0),
680         GSM    = (1 <<  1),
681         ULAW   = (1 <<  2),
682         ALAW   = (1 <<  3),
683         G726   = (1 <<  4),
684         ADPCM  = (1 <<  5),
685         SLIN   = (1 <<  6),
686         LPC10  = (1 <<  7),
687         G729   = (1 <<  8),
688         SPEEX  = (1 <<  9),
689         ILBC   = (1 << 10),
690         G726AAL2 = (1 << 11),
691         G722   = (1 << 12),
692         AMR    = (1 << 13),
693         // NOTE: GSM Half Rate is not defined in RFC5456
694         GSM_HR    = (1 << 31),
695         AudioMask = G723_1 | GSM | ULAW | ALAW | G726 | ADPCM | SLIN | LPC10 | G729 | SPEEX |
696             ILBC | G726AAL2 | G722 | AMR | GSM_HR,
697         JPEG   = (1 << 16),
698         PNG    = (1 << 17),
699         ImageMask = JPEG | PNG,
700         H261   = (1 << 18),
701         H263   = (1 << 19),
702         H263p  = (1 << 20),
703         H264   = (1 << 21),
704         VideoMask = H261 | H263 | H263p | H264,
705     };
706 
707     /**
708      * Media type enumeration
709      */
710     enum Media {
711         Audio = 0,
712         Video,
713         Image,
714         TypeCount
715     };
716 
717     /**
718      * Constructor. Build an audio format
719      * @param type Media type
720     */
721     inline IAXFormat(int type = Audio)
m_type(type)722 	: m_type(type)
723 	{}
724 
725     /**
726      * Get the media type
727      * @return Media type
728     */
type()729     inline int type() const
730 	{ return m_type; }
731 
732     /**
733      * Get the format
734      * @return The format
735     */
format()736     inline u_int32_t format() const
737 	{ return m_format.format(); }
738 
739     /**
740      * Get the incoming format
741      * @return The incoming format
742     */
in()743     inline u_int32_t in() const
744 	{ return m_formatIn.format(); }
745 
746     /**
747      * Get the outgoing format
748      * @return The outgoing format
749     */
out()750     inline u_int32_t out() const
751 	{ return m_formatOut.format(); }
752 
753     /**
754      * Get the incoming or outgoing format description
755      * @param in True to retrieve the incoming format, false to retrieve the outgoing one
756      * @return Requested format desc
757     */
formatDesc(bool in)758     inline const IAXFormatDesc& formatDesc(bool in) const
759 	{ return in ? m_formatIn : m_formatOut; }
760 
761      /**
762      * Get the text associated with the format
763      * @return Format name
764     */
formatName()765     inline const char* formatName() const
766 	{ return formatName(format()); }
767 
768     /**
769      * Get the text associated with the media type
770      * @return Media name
771     */
typeName()772     inline const char* typeName() const
773 	{ return typeName(m_type); }
774 
775     /**
776      * Set format
777      * @param fmt Optional pointer to format to set
778      * @param fmtIn Optional pointer to incoming format to set
779      * @param fmtOut Optional pointer to outgoing format to set
780     */
781     void set(u_int32_t* fmt, u_int32_t* fmtIn, u_int32_t* fmtOut);
782 
783     /**
784      * Create a string list from formats
785      * @param dest The destination
786      * @param formats The formats
787      * @param dict Optional dictionary to use, 0 to use s_formats
788      * @param sep The separator to use
789     */
790     static void formatList(String& dest, u_int32_t formats, const TokenDict* dict = 0,
791 	const char* sep = ",");
792 
793     /**
794      * Pick a format from a list of capabilities
795      * @param formats Capabilities list
796      * @param format Optional format to pick
797      * @return IAX format, 0 if not found
798     */
799     static u_int32_t pickFormat(u_int32_t formats, u_int32_t format = 0);
800 
801     /**
802      * Encode a formats list
803      * @param formats Formats list
804      * @param dict Dictionary to use
805      * @param sep Formats list separator
806      * @return Encoded formats
807     */
808     static u_int32_t encode(const String& formats, const TokenDict* dict, char sep = ',');
809 
810     /**
811      * Mask formats by type
812      * @param value Input format(s)
813      * @param type Media type to retrieve
814      * @return Media format(s) from input
815     */
mask(u_int32_t value,int type)816     static inline u_int32_t mask(u_int32_t value, int type) {
817 	    if (type == Audio)
818 		return value & AudioMask;
819 	    if (type == Video)
820 		return value & VideoMask;
821 	    if (type == Image)
822 		return value & ImageMask;
823 	    return 0;
824 	}
825 
826     /**
827      * Clear formats by type
828      * @param value Input format(s)
829      * @param type Media type to clear
830      * @return Cleared format(s) from input
831     */
clear(u_int32_t value,int type)832     static inline u_int32_t clear(u_int32_t value, int type) {
833 	    if (type == Audio)
834 		return value & ~AudioMask;
835 	    if (type == Video)
836 		return value & ~VideoMask;
837 	    if (type == Image)
838 		return value & ~ImageMask;
839 	    return value;
840 	}
841 
842     /**
843      * Get the text associated with a format
844      * @param fmt The desired format
845      * @return A pointer to the text associated with the format or 0 if the format doesn't exist
846     */
formatName(u_int32_t fmt)847     static inline const char* formatName(u_int32_t fmt)
848 	{ return lookup(fmt,s_formats); }
849 
850     /**
851      * Get the text associated with a media type
852      * @param type The media type
853      * @return A pointer to the text associated with the media type
854     */
typeName(int type)855     static inline const char* typeName(int type)
856 	{ return lookup(type,s_types); }
857 
858     /**
859      * Get the text associated with a media type
860      * @param type The media type
861      * @return A string associated with the media type
862     */
typeNameStr(int type)863     static inline const String& typeNameStr(int type)
864 	{ return s_typesList[type]; }
865 
866     /**
867      * Keep the texts associated with the formats
868     */
869     static const TokenDict s_formats[];
870 
871     /**
872      * Keep the texts associated with type
873      */
874     static const TokenDict s_types[];
875 
876     /**
877      * Keep the texts associated with a type also as String
878      */
879     static const String s_typesList[TypeCount];
880 
881 protected:
882     int m_type;
883     IAXFormatDesc m_format;
884     IAXFormatDesc m_formatIn;
885     IAXFormatDesc m_formatOut;
886 };
887 
888 /**
889  * This class holds the enumeration values for IAX control (subclass)
890  * @short Wrapper class for subclasses of frames of type IAX
891  */
892 class YIAX_API IAXControl
893 {
894 public:
895     /**
896      * IAX control (subclass) enumeration types
897      */
898     enum Type {
899         New       = 0x01,
900         Ping      = 0x02,
901         Pong      = 0x03,
902         Ack       = 0x04,
903         Hangup    = 0x05,
904         Reject    = 0x06,
905         Accept    = 0x07,
906         AuthReq   = 0x08,
907         AuthRep   = 0x09,
908         Inval     = 0x0a,
909         LagRq     = 0x0b,
910         LagRp     = 0x0c,
911         RegReq    = 0x0d,
912         RegAuth   = 0x0e,
913         RegAck    = 0x0f,
914         RegRej    = 0x10,
915         RegRel    = 0x11,
916         VNAK      = 0x12,
917         DpReq     = 0x13,
918         DpRep     = 0x14,
919         Dial      = 0x15,
920         TxReq     = 0x16,
921         TxCnt     = 0x17,
922         TxAcc     = 0x18,
923         TxReady   = 0x19,
924         TxRel     = 0x1a,
925         TxRej     = 0x1b,
926         Quelch    = 0x1c,
927         Unquelch  = 0x1d,
928         Poke      = 0x1e,
929 	//Reserved  = 0x1f,
930         MWI       = 0x20,
931         Unsupport = 0x21,
932         Transfer  = 0x22,
933         Provision = 0x23,
934         FwDownl   = 0x24,
935         FwData    = 0x25,
936         CallToken = 0x28,
937     };
938 
939     /**
940      * Get the string associated with the given IAX control type
941      * @param type The requested type
942      * @return The text if type is valid or 0
943      */
typeText(int type)944     static inline const char* typeText(int type)
945 	{ return lookup(type,s_types,0); }
946 
947 private:
948     static TokenDict s_types[]; // Keep the association between IAX control codes and their name
949 };
950 
951 /**
952  * This class holds all data needded to manage an IAX frame
953  * @short This class holds an IAX frame
954  */
955 class YIAX_API IAXFrame : public RefObject
956 {
957 public:
958     /**
959      * IAX frame type enumeration
960      */
961     enum Type {
962         DTMF    = 0x01,
963         Voice   = 0x02,
964         Video   = 0x03,
965         Control = 0x04,
966         Null    = 0x05,
967         IAX     = 0x06,
968         Text    = 0x07,
969         Image   = 0x08,
970         HTML    = 0x09,
971         Noise   = 0x0a,
972     };
973 
974     /**
975      * Constructor. Constructs an incoming frame
976      * @param type Frame type
977      * @param sCallNo Source call number
978      * @param tStamp Frame timestamp
979      * @param retrans Retransmission flag
980      * @param buf IE buffer
981      * @param len IE buffer length
982      * @param mark Mark flag
983      */
984     IAXFrame(Type type, u_int16_t sCallNo, u_int32_t tStamp, bool retrans,
985 	     const unsigned char* buf, unsigned int len, bool mark = false);
986 
987     /**
988      * Destructor
989      */
990     virtual ~IAXFrame();
991 
992     /**
993      * Get the type of this frame as enumeration
994      * @return The type of this frame as enumeration
995      */
type()996     inline Type type() const
997 	{ return m_type; }
998 
999     /**
1000      * Get the data buffer of the frame
1001      * @return The data buffer of the frame
1002      */
data()1003     inline DataBlock& data()
1004         { return m_data; }
1005 
1006     /**
1007      * Get the retransmission flag of this frame
1008      * @return The retransmission flag of this frame
1009      */
retrans()1010     inline bool retrans() const
1011 	{ return m_retrans; }
1012 
1013     /**
1014      * Get the source call number of this frame
1015      * @return The source call number of this frame
1016      */
sourceCallNo()1017     inline u_int16_t sourceCallNo() const
1018 	{ return m_sCallNo; }
1019 
1020     /**
1021      * Get the timestamp of this frame
1022      * @return The timestamp of this frame
1023      */
timeStamp()1024     inline u_int32_t timeStamp() const
1025 	{ return m_tStamp; }
1026 
1027     /**
1028      * Get the mark flag
1029      * @return The mark flag
1030      */
mark()1031     inline bool mark() const
1032 	{ return m_mark; }
1033 
1034     /**
1035      * Get a pointer to this frame if it is a full frame
1036      * @return A pointer to this frame if it is a full frame or 0
1037      */
1038     virtual IAXFullFrame* fullFrame();
1039 
1040     /**
1041      * Parse a received buffer and returns a IAXFrame pointer if valid
1042      * @param buf Received buffer
1043      * @param len Buffer length
1044      * @param engine The IAXEngine who requested the operation
1045      * @param addr The source address
1046      * @return A frame pointer on success or 0
1047      */
1048     static IAXFrame* parse(const unsigned char* buf, unsigned int len, IAXEngine* engine = 0, const SocketAddr* addr = 0);
1049 
1050     /**
1051      * Build a miniframe buffer
1052      * @param dest Destination buffer
1053      * @param sCallNo Source call number
1054      * @param ts Frame timestamp
1055      * @param data Data
1056      * @param len Data length
1057      */
buildMiniFrame(DataBlock & dest,u_int16_t sCallNo,u_int32_t ts,void * data,unsigned int len)1058     static inline void buildMiniFrame(DataBlock& dest, u_int16_t sCallNo, u_int32_t ts,
1059 	void* data, unsigned int len) {
1060 	    unsigned char header[4] = {(unsigned char)(sCallNo >> 8),
1061 		(unsigned char)sCallNo,(unsigned char)(ts >> 8),(unsigned char)ts};
1062 	    dest.assign(header,4);
1063 	    dest.append(data,len);
1064 	}
1065 
1066     /**
1067      * Build a video meta frame buffer
1068      * @param dest Destination buffer
1069      * @param sCallNo Source call number
1070      * @param tStamp Frame timestamp
1071      * @param mark Frame mark
1072      * @param data Data
1073      * @param len Data length
1074      */
1075     static void buildVideoMetaFrame(DataBlock& dest, u_int16_t sCallNo, u_int32_t tStamp,
1076 	bool mark, void* data, unsigned int len);
1077 
1078     /**
1079      * Pack a subclass value according to IAX protocol
1080      * @param value Value to pack
1081      * @return The packed subclass value or 0 if invalid (>255 and not a power of 2)
1082      */
1083     static u_int8_t packSubclass(u_int32_t value);
1084 
1085     /**
1086      * Unpack a subclass value according to IAX protocol
1087      * @param value Value to unpack
1088      * @return The unpacked subclass value
1089      */
1090     static u_int32_t unpackSubclass(u_int8_t value);
1091 
1092     /**
1093      * Get the string associated with the given IAX frame type
1094      * @param type The requested type
1095      * @return The text if type is valid or 0
1096      */
typeText(int type)1097     static inline const char* typeText(int type)
1098 	{ return lookup(type,s_types,0); }
1099 
1100 protected:
1101     /**
1102      * Contains the frame's IE list for an incoming frame or the whole frame for an outgoing one
1103      */
1104     DataBlock m_data;
1105 
1106     /**
1107      * Retransmission flag
1108      */
1109     bool m_retrans;
1110 
1111 private:
1112     static TokenDict s_types[]; // Keep the association between IAX frame types and their names
1113     Type m_type;		// Frame type
1114     u_int16_t m_sCallNo;	// Source call number
1115     u_int32_t m_tStamp;		// Frame timestamp
1116     bool m_mark;		// Mark flag
1117 };
1118 
1119 /**
1120  * This class holds all data needded to manage an IAX full frame
1121  * @short This class holds an IAX full frame
1122  */
1123 class YIAX_API IAXFullFrame : public IAXFrame
1124 {
1125 public:
1126     /**
1127      * IAX frame subclass enumeration types for frames of type Control
1128      */
1129     enum ControlType {
1130         Hangup = 0x01,
1131         //Ring = 0x02,
1132         Ringing = 0x03,
1133         Answer = 0x04,
1134         Busy = 0x05,
1135         Congestion = 0x08,
1136         FlashHook = 0x09,
1137         Option = 0x0b,
1138         KeyRadio = 0x0c,
1139         UnkeyRadio = 0x0d,
1140         Progressing = 0x0e,
1141         Proceeding = 0x0f,
1142         Hold = 0x10,
1143         Unhold = 0x11,
1144         VidUpdate = 0x12,
1145         SrcUpdate = 0x14,
1146         StopSounds = 0xff,
1147     };
1148 
1149     /**
1150      * Constructor. Constructs an incoming full frame
1151      * @param type Frame type
1152      * @param subclass Frame subclass
1153      * @param sCallNo Source (remote) call number
1154      * @param dCallNo Destination (local) call number
1155      * @param oSeqNo Outgoing sequence number
1156      * @param iSeqNo Incoming (expected) sequence number
1157      * @param tStamp Frame timestamp
1158      * @param retrans Retransmission flag
1159      * @param buf IE buffer
1160      * @param len IE buffer length
1161      * @param mark Mark flag
1162      */
1163     IAXFullFrame(Type type, u_int32_t subclass, u_int16_t sCallNo, u_int16_t dCallNo,
1164 		 unsigned char oSeqNo, unsigned char iSeqNo,
1165 		 u_int32_t tStamp, bool retrans,
1166 		 const unsigned char* buf, unsigned int len, bool mark = false);
1167 
1168     /**
1169      * Constructor. Constructs an outgoing full frame
1170      * @param type Frame type
1171      * @param subclass Frame subclass
1172      * @param sCallNo Source (remote) call number
1173      * @param dCallNo Destination (local) call number
1174      * @param oSeqNo Outgoing sequence number
1175      * @param iSeqNo Incoming (expected) sequence number
1176      * @param tStamp Frame timestamp
1177      * @param buf IE buffer
1178      * @param len IE buffer length
1179      * @param mark Mark flag
1180      */
1181     IAXFullFrame(Type type, u_int32_t subclass, u_int16_t sCallNo, u_int16_t dCallNo,
1182 		 unsigned char oSeqNo, unsigned char iSeqNo,
1183 		 u_int32_t tStamp,
1184 		 const unsigned char* buf = 0, unsigned int len = 0, bool mark = false);
1185 
1186     /**
1187      * Constructor. Constructs an outgoing full frame
1188      * @param type Frame type
1189      * @param subclass Frame subclass
1190      * @param sCallNo Source (remote) call number
1191      * @param dCallNo Destination (local) call number
1192      * @param oSeqNo Outgoing sequence number
1193      * @param iSeqNo Incoming (expected) sequence number
1194      * @param tStamp Frame timestamp
1195      * @param ieList List of frame IEs
1196      * @param maxlen Max frame data length
1197      * @param mark Mark flag
1198      */
1199     IAXFullFrame(Type type, u_int32_t subclass, u_int16_t sCallNo, u_int16_t dCallNo,
1200 		 unsigned char oSeqNo, unsigned char iSeqNo,
1201 		 u_int32_t tStamp, IAXIEList* ieList, u_int16_t maxlen, bool mark = false);
1202 
1203     /**
1204      * Destructor
1205      */
1206     virtual ~IAXFullFrame();
1207 
1208     /**
1209      * Get the destination call number
1210      * @return The destination call number
1211      */
destCallNo()1212     inline u_int16_t destCallNo() const
1213         { return m_dCallNo; }
1214 
1215     /**
1216      * Get the outgoing sequence number
1217      * @return The outgoing sequence number
1218      */
oSeqNo()1219     inline unsigned char oSeqNo() const
1220         { return m_oSeqNo; }
1221 
1222     /**
1223      * Get the incoming sequence number
1224      * @return The incoming sequence number
1225      */
iSeqNo()1226     inline unsigned char iSeqNo() const
1227         { return m_iSeqNo; }
1228 
1229     /**
1230      * Get the subclass of this frame
1231      * @return The subclass of this frame
1232      */
subclass()1233     inline u_int32_t subclass() const
1234 	{ return m_subclass; }
1235 
1236     /**
1237      * Check if this frame is used to request authentication
1238      * @return True if this frame is used to request authentication (like RegReq or RegAuth)
1239      */
isAuthReq()1240     inline bool isAuthReq() const {
1241 	    return type() == IAXFrame::IAX &&
1242 		(subclass() == IAXControl::AuthReq || subclass() == IAXControl::RegAuth);
1243 	}
1244 
1245     /**
1246      * Check if this frame is an INVAL one
1247      * @return True if this frame is INVAL
1248      */
isInval()1249     inline bool isInval() const
1250 	{ return type() == IAXFrame::IAX && subclass() == IAXControl::Inval; }
1251 
1252     /**
1253      * Get a pointer to this frame if it is a full frame
1254      * @return A pointer to this frame
1255      */
1256     virtual IAXFullFrame* fullFrame();
1257 
1258     /**
1259      * Rebuild frame buffer from the list of IEs
1260      * @param maxlen Max frame data length
1261      */
1262     void updateBuffer(u_int16_t maxlen);
1263 
1264     /**
1265      * Retrieve the IE list
1266      * @return IAXIEList pointer or NULL
1267      */
ieList()1268     inline IAXIEList* ieList()
1269 	{ return m_ieList; }
1270 
1271     /**
1272      * Update IE list from buffer if not already done
1273      * @param incoming True if this is an incoming frame
1274      * @return True if the list is valid
1275      */
1276     bool updateIEList(bool incoming);
1277 
1278     /**
1279      * Remove the IE list
1280      * @param delObj True to delete it
1281      * @return IAXIEList pointer or NULL if requested to delete it or already NULL
1282      */
1283     IAXIEList* removeIEList(bool delObj = true);
1284 
1285     /**
1286      * Fill a string with this frame
1287      * @param dest The string to fill
1288      * @param local The local address
1289      * @param remote The remote address
1290      * @param incoming True if it is an incoming frame
1291      */
1292     void toString(String& dest, const SocketAddr& local, const SocketAddr& remote,
1293 	bool incoming);
1294 
1295     /**
1296      * Get the string associated with the given IAX control type
1297      * @param type The requested control type
1298      * @return The text if type is valid or 0
1299      */
controlTypeText(int type)1300     static inline const char* controlTypeText(int type)
1301 	{ return lookup(type,s_controlTypes,0); }
1302 
1303 protected:
1304     /**
1305      * Destroyed notification. Clear data
1306      */
1307     virtual void destroyed();
1308 
1309 private:
1310     // Build frame buffer header
1311     void setDataHeader();
1312     static TokenDict s_controlTypes[]; // Keep the association between control types and their names
1313     u_int16_t m_dCallNo;	// Destination call number
1314     unsigned char m_oSeqNo;	// Out sequence number
1315     unsigned char m_iSeqNo;	// In sequence number
1316     u_int32_t m_subclass;	// Subclass
1317     IAXIEList* m_ieList;        // List of IEs
1318 };
1319 
1320 /**
1321  * This class holds all data needded to manage an outgoing IAX full frame
1322  * @short This class holds an outgoing IAX full frame
1323  */
1324 class YIAX_API IAXFrameOut : public IAXFullFrame
1325 {
1326 public:
1327     /**
1328      * Constructor. Constructs an outgoing full frame
1329      * @param type Frame type
1330      * @param subclass Frame subclass
1331      * @param sCallNo Source (remote) call number
1332      * @param dCallNo Destination (local) call number
1333      * @param oSeqNo Outgoing sequence number
1334      * @param iSeqNo Incoming (expected) sequence number
1335      * @param tStamp Frame timestamp
1336      * @param buf IE buffer
1337      * @param len IE buffer length
1338      * @param retransCount Retransmission counter
1339      * @param retransIntervalMs Time interval to the next retransmission
1340      * @param ackOnly Acknoledge only flag. If true, the frame only expects an ACK
1341      * @param mark Mark flag
1342      */
1343     inline IAXFrameOut(Type type, u_int32_t subclass, u_int16_t sCallNo, u_int16_t dCallNo,
1344                        unsigned char oSeqNo, unsigned char iSeqNo, u_int32_t tStamp,
1345 		       const unsigned char* buf, unsigned int len,
1346                        u_int16_t retransCount, u_int32_t retransIntervalMs,
1347 		       bool ackOnly, bool mark = false)
IAXFullFrame(type,subclass,sCallNo,dCallNo,oSeqNo,iSeqNo,tStamp,buf,len,mark)1348         : IAXFullFrame(type,subclass,sCallNo,dCallNo,oSeqNo,iSeqNo,tStamp,buf,len,mark),
1349           m_ack(false), m_ackOnly(ackOnly), m_retransCount(retransCount),
1350           m_retransTimeInterval(retransIntervalMs * 1000),
1351 	  m_nextTransTime(Time::now() + m_retransTimeInterval)
1352 	{}
1353 
1354     /**
1355      * Constructor. Constructs an outgoing full frame
1356      * @param type Frame type
1357      * @param subclass Frame subclass
1358      * @param sCallNo Source (remote) call number
1359      * @param dCallNo Destination (local) call number
1360      * @param oSeqNo Outgoing sequence number
1361      * @param iSeqNo Incoming (expected) sequence number
1362      * @param tStamp Frame timestamp
1363      * @param ieList List of frame IEs
1364      * @param maxlen Max frame data length
1365      * @param retransCount Retransmission counter
1366      * @param retransIntervalMs Time interval to the next retransmission
1367      * @param ackOnly Acknoledge only flag. If true, the frame only expects an ACK
1368      * @param mark Mark flag
1369      */
1370     inline IAXFrameOut(Type type, u_int32_t subclass, u_int16_t sCallNo, u_int16_t dCallNo,
1371                        unsigned char oSeqNo, unsigned char iSeqNo, u_int32_t tStamp,
1372 		       IAXIEList* ieList, u_int16_t maxlen,
1373                        u_int16_t retransCount, u_int32_t retransIntervalMs, bool ackOnly,
1374 		       bool mark = false)
IAXFullFrame(type,subclass,sCallNo,dCallNo,oSeqNo,iSeqNo,tStamp,ieList,maxlen,mark)1375         : IAXFullFrame(type,subclass,sCallNo,dCallNo,oSeqNo,iSeqNo,tStamp,ieList,maxlen,mark),
1376           m_ack(false), m_ackOnly(ackOnly), m_retransCount(retransCount),
1377           m_retransTimeInterval(retransIntervalMs * 1000),
1378 	  m_nextTransTime(Time::now() + m_retransTimeInterval)
1379 	{}
1380 
1381     /**
1382      * Destructor
1383      */
~IAXFrameOut()1384     virtual ~IAXFrameOut()
1385 	{}
1386 
1387     /**
1388      * Get the retransmission counter of this frame
1389      * @return The retransmission counter is 0
1390      */
retransCount()1391     inline unsigned int retransCount() const
1392         { return m_retransCount; }
1393 
1394     /**
1395      * Ask the frame if it's time for retransmit
1396      * @param time Current time
1397      * @return True if it's time to retransmit
1398      */
timeForRetrans(u_int64_t time)1399     inline bool timeForRetrans(u_int64_t time) const
1400         { return time >= m_nextTransTime; }
1401 
1402     /**
1403      * Set the retransmission flag of this frame
1404      */
setRetrans()1405     inline void setRetrans() {
1406 	    if (m_retrans)
1407 		return;
1408 	    m_retrans = true;
1409 	    ((unsigned char*)m_data.data())[2] |= 0x80;
1410 	}
1411 
1412     /**
1413      * Update the retransmission counter and the time to next retransmission
1414      */
transmitted()1415     inline void transmitted() {
1416 	    if (!m_retransCount)
1417 		return;
1418 	    m_retransCount--;
1419 	    m_retransTimeInterval *= 2;
1420 	    m_nextTransTime += m_retransTimeInterval;
1421 	}
1422 
1423     /**
1424      * Get the acknoledged flag of this frame
1425      * @return The acknoledged flag of this frame
1426      */
ack()1427     inline bool ack() const
1428 	{ return m_ack; }
1429 
1430     /**
1431      * Set the acknoledged flag of this frame
1432      */
setAck()1433     inline void setAck()
1434 	{ m_ack = true; }
1435 
1436     /**
1437      * Get the acknoledge only flag of this frame
1438      * @return The acknoledge only flag of this frame
1439      */
ackOnly()1440     inline bool ackOnly() const
1441 	{ return m_ackOnly; }
1442 
1443     /**
1444      * Check if absolute timeout can be set
1445      * @return True if absolute timeout can be set
1446      */
canSetTimeout()1447     inline bool canSetTimeout()
1448 	{ return m_retransTimeInterval != 0; }
1449 
1450     /**
1451      * Set absolute timeout. Reset retransmission counter
1452      * @param tout Timeout time
1453      */
setTimeout(u_int64_t tout)1454     inline void setTimeout(u_int64_t tout) {
1455 	    if (!m_retransTimeInterval)
1456 		return;
1457 	    m_retransTimeInterval = 0;
1458 	    m_retransCount = 0;
1459 	    m_nextTransTime = tout;
1460 	}
1461 
1462 private:
1463     bool m_ack;				// Acknoledge flag
1464     bool m_ackOnly;			// Frame need only ACK as a response
1465     u_int16_t m_retransCount;		// Retransmission counter
1466     u_int32_t m_retransTimeInterval;	// Retransmission interval
1467     u_int64_t m_nextTransTime;		// Next transmission time
1468 };
1469 
1470 /**
1471  * This class holds trunk description
1472  * @short Trunk info
1473  */
1474 class YIAX_API IAXTrunkInfo : public RefObject
1475 {
1476 public:
1477     /**
1478      * Constructor
1479      */
IAXTrunkInfo()1480     inline IAXTrunkInfo()
1481 	: m_timestamps(true), m_sendInterval(IAX2_TRUNKFRAME_SEND_DEF),
1482 	m_maxLen(IAX2_TRUNKFRAME_LEN_DEF),
1483 	m_efficientUse(false), m_trunkInSyncUsingTs(true),
1484 	m_trunkInTsDiffRestart(5000),
1485 	m_retransCount(IAX2_RETRANS_COUNT_DEF),
1486 	m_retransInterval(IAX2_RETRANS_INTERVAL_DEF),
1487 	m_pingInterval(IAX2_PING_INTERVAL_DEF)
1488 	{}
1489 
1490     /**
1491      * Init non trunking related data
1492      * @param params Parameter list
1493      * @param prefix Parameter prefix
1494      * @param def Optional defaults
1495      */
1496     void init(const NamedList& params, const String& prefix = String::empty(),
1497 	const IAXTrunkInfo* def = 0);
1498 
1499     /**
1500      * Init trunking from parameters
1501      * @param params Parameter list
1502      * @param prefix Parameter prefix
1503      * @param def Optional defaults
1504      * @param out True to init outgoing trunk data
1505      * @param in True to init incoming trunk data
1506      */
1507     void initTrunking(const NamedList& params, const String& prefix = String::empty(),
1508 	const IAXTrunkInfo* def = 0, bool out = true, bool in = true);
1509 
1510     /**
1511      * Update trunking from parameters. Don't change values not present in list
1512      * @param params Parameter list
1513      * @param prefix Parameter prefix
1514      * @param out True to update outgoing trunk data
1515      * @param in True to update incoming trunk data
1516      */
1517     void updateTrunking(const NamedList& params, const String& prefix = String::empty(),
1518 	bool out = true, bool in = true);
1519 
1520     /**
1521      * Dump info
1522      * @param buf Destination buffer
1523      * @param sep Parameters separator
1524      * @param out True to dump outgoing trunking info
1525      * @param in True to dump incoming trunking info
1526      * @param other True to dump non trunking info
1527      */
1528     void dump(String& buf, const char* sep = " ", bool out = true, bool in = true,
1529 	bool other = true);
1530 
1531     bool m_timestamps;                   // Trunk type: with(out) timestamps
1532     unsigned int m_sendInterval;         // Send interval
1533     unsigned int m_maxLen;               // Max frame length
1534     bool m_efficientUse;                 // Outgoing trunking: use or not the trunk based on calls using it
1535     bool m_trunkInSyncUsingTs;           // Incoming trunk without timestamps: use trunk
1536                                          //  time or trunk timestamp to re-build frame ts
1537     u_int32_t m_trunkInTsDiffRestart;    // Incoming trunk without timestamp: diff between
1538                                          //  timestamps at which we restart
1539     unsigned int m_retransCount;         // Frame retransmission counter
1540     unsigned int m_retransInterval;      // Frame retransmission interval in milliseconds
1541     unsigned int m_pingInterval;         // Ping interval in milliseconds
1542 };
1543 
1544 /**
1545  * Handle meta trunk frame with timestamps
1546  * @short Meta trunk frame
1547  */
1548 class YIAX_API IAXMetaTrunkFrame : public RefObject, public Mutex
1549 {
1550 public:
1551     /**
1552      * Constructor. Constructs an outgoing meta trunk frame
1553      * @param engine The engine that owns this frame
1554      * @param addr Remote peer address
1555      * @param timestamps True if miniframes have timestamps, false if not
1556      * @param maxLen Maximum frame length
1557      * @param sendInterval Trunk send interval in milliseconds
1558      */
1559     IAXMetaTrunkFrame(IAXEngine* engine, const SocketAddr& addr, bool timestamps,
1560 	unsigned int maxLen, unsigned int sendInterval);
1561 
1562     /**
1563      * Destructor
1564      */
1565     virtual ~IAXMetaTrunkFrame();
1566 
1567     /**
1568      * Get the remote peer address
1569      * @return The remote peer address
1570      */
addr()1571     inline const SocketAddr& addr() const
1572 	{ return m_addr; }
1573 
1574     /**
1575      * Retrieve the number of calls using this trunk
1576      * @return The number of calls using this trunk
1577      */
calls()1578     inline unsigned int calls() const
1579 	{ return m_calls; }
1580 
1581     /**
1582      * Change the number of calls using this trunk
1583      * @param add True to add a call, false to remove it
1584      */
changeCalls(bool add)1585     inline void changeCalls(bool add) {
1586 	    Lock lck(this);
1587 	    if (add)
1588 		m_calls++;
1589 	    else if (m_calls)
1590 		m_calls--;
1591 	}
1592 
1593     /**
1594      * Check if the frame is adding mini frames timestamps
1595      * @return True if the frame is adding mini frames timestamps
1596      */
trunkTimestamps()1597     inline bool trunkTimestamps() const
1598 	{ return m_trunkTimestamps; }
1599 
1600     /**
1601      * Retrieve the send interval
1602      * @return Send interval in milliseconds
1603      */
sendInterval()1604     inline unsigned int sendInterval() const
1605 	{ return m_sendInterval; }
1606 
1607     /**
1608      * Retrieve the frame maximum length
1609      * @return Frame maximum length
1610      */
maxLen()1611     inline unsigned int maxLen() const
1612 	{ return m_maxLen; }
1613 
1614     /**
1615      * Add a mini frame. If no room, send before adding
1616      * @param sCallNo Sorce call number
1617      * @param data Mini frame data
1618      * @param tStamp Mini frame timestamp
1619      * @return The number of data bytes added to trunk, 0 on failure
1620      */
1621     unsigned int add(u_int16_t sCallNo, const DataBlock& data, u_int32_t tStamp);
1622 
1623     /**
1624      * Send this frame to remote peer if the time arrived
1625      * @param now Current time
1626      * @return The result of the write operation
1627      */
1628     inline bool timerTick(const Time& now = Time()) {
1629 	    if (m_dataAddIdx == IAX2_TRUNKFRAME_HEADERLENGTH || !m_send)
1630 		return false;
1631 	    Lock lck(this);
1632 	    return (now > m_send) && doSend(now,true);
1633 	}
1634 
1635     /**
1636      * Send this frame to remote peer if there is any data in buffer
1637      * @return The result of the write operation
1638      */
send()1639     inline bool send() {
1640 	    if (m_dataAddIdx == IAX2_TRUNKFRAME_HEADERLENGTH)
1641 		return false;
1642 	    Lock lck(this);
1643 	    return m_dataAddIdx != IAX2_TRUNKFRAME_HEADERLENGTH && doSend();
1644 	}
1645 
1646 private:
IAXMetaTrunkFrame()1647     IAXMetaTrunkFrame() {}      // No default constructor
1648     // Send this frame to remote peer
1649     bool doSend(const Time& now = Time(), bool onTime = false);
1650     // Set timestamp and next time to send
setTimestamp(u_int64_t now)1651     inline void setTimestamp(u_int64_t now) {
1652 	    m_timeStamp = now;
1653 	    m_send = now + (u_int64_t)m_sendInterval * 1000;
1654 	}
1655     // Set next time to send
setSendTime(u_int64_t now)1656     inline void setSendTime(u_int64_t now)
1657 	{ m_send = now + (u_int64_t)m_sendInterval * 1000; }
1658 
1659     // Set the timestamp of this frame
setTimestamp(u_int32_t tStamp)1660     inline void setTimestamp(u_int32_t tStamp) {
1661             m_data[4] = (u_int8_t)(tStamp >> 24);
1662 	    m_data[5] = (u_int8_t)(tStamp >> 16);
1663 	    m_data[6] = (u_int8_t)(tStamp >> 8);
1664 	    m_data[7] = (u_int8_t)tStamp;
1665 	}
1666 
1667     unsigned int m_calls;       // The number of calls using it
1668     u_int8_t* m_data;		// Data buffer
1669     u_int16_t m_dataAddIdx;	// Current add index
1670     u_int64_t m_timeStamp;      // First time data was added
1671     u_int64_t m_send;           // Time to send
1672     u_int32_t m_lastSentTs;     // Last sent timestamp
1673     unsigned int m_sendInterval;// Send interval in milliseconds
1674     IAXEngine* m_engine;	// The engine that owns this frame
1675     SocketAddr m_addr;		// Remote peer address
1676     bool m_trunkTimestamps;     // Trunk type: with(out) timestamps
1677     unsigned int m_maxLen;      // Max frame length
1678     unsigned int m_maxDataLen;  // Max frame data length
1679     unsigned char m_miniHdrLen; // Miniframe header length
1680 };
1681 
1682 /**
1683  * This class holds data used by transaction to sync media.
1684  * The mutexes are not reentrant
1685  * @short IAX2 transaction media data
1686  */
1687 class YIAX_API IAXMediaData
1688 {
1689     friend class IAXTransaction;
1690 public:
1691     /**
1692      * Constructor
1693      */
IAXMediaData()1694     inline IAXMediaData()
1695 	: m_inMutex(false,"IAXTransaction::InMedia"),
1696 	m_outMutex(false,"IAXTransaction::OutMedia"),
1697 	m_startedIn(false), m_startedOut(false),
1698 	m_outStartTransTs(0), m_outFirstSrcTs(0),
1699 	m_lastOut(0), m_lastIn(0), m_sent(0), m_sentBytes(0),
1700 	m_recv(0), m_recvBytes(0), m_ooPackets(0), m_ooBytes(0),
1701 	m_showInNoFmt(true), m_showOutOldTs(true),
1702 	m_dropOut(0), m_dropOutBytes(0)
1703 	{}
1704 
1705     /**
1706      * Increase drop out data
1707      * @param len The number of dropped bytes
1708      */
dropOut(unsigned int len)1709     inline void dropOut(unsigned int len) {
1710 	    if (len) {
1711 		m_dropOut++;
1712 		m_dropOutBytes += len;
1713 	    }
1714 	}
1715 
1716     /**
1717      * Print statistics
1718      * @param buf Destination buffer
1719      */
1720     void print(String& buf);
1721 
1722 protected:
1723     Mutex m_inMutex;
1724     Mutex m_outMutex;
1725     bool m_startedIn;                    // Incoming media started
1726     bool m_startedOut;                   // Outgoing media started
1727     int m_outStartTransTs;               // Transaction timestamp where media send started
1728     unsigned int m_outFirstSrcTs;        // First outgoing source packet timestamp as received from source
1729     u_int32_t m_lastOut;                 // Last transmitted mini timestamp
1730     u_int32_t m_lastIn;                  // Last received timestamp
1731     unsigned int m_sent;                 // Packets sent
1732     unsigned int m_sentBytes;            // Bytes sent
1733     unsigned int m_recv;                 // Packets received
1734     unsigned int m_recvBytes;            // Bytes received
1735     unsigned int m_ooPackets;            // Dropped received out of order packets
1736     unsigned int m_ooBytes;              // Dropped received out of order bytes
1737     bool m_showInNoFmt;                  // Show incoming media arrival without format debug
1738     bool m_showOutOldTs;                 // Show dropped media out debug message
1739     unsigned int m_dropOut;              // The number of dropped outgoing packets
1740     unsigned int m_dropOutBytes;         // The number of dropped outgoing bytes
1741 };
1742 
1743 /**
1744  * This class holds all the data needded for the management of an IAX2 transaction
1745  *  which might be a call leg, a register/unregister or a poke one
1746  * @short An IAX2 transaction
1747  */
1748 class YIAX_API IAXTransaction : public RefObject, public Mutex
1749 {
1750     friend class IAXEvent;
1751     friend class IAXEngine;
1752 public:
1753     /**
1754      * The transaction type as enumeration
1755      */
1756     enum Type {
1757 	Incorrect,			// Unsupported/unknown type
1758 	New,				// Media exchange call
1759 	RegReq,				// Registration
1760 	RegRel,				// Registration release
1761 	Poke,				// Ping
1762 	//FwDownl,
1763     };
1764 
1765     /**
1766      * The transaction state as enumeration
1767      */
1768     enum State {
1769         Connected,		     	// Call leg established (Accepted) for transactions of type New
1770 	NewLocalInvite,		     	// New outgoing transaction: Poke/New/RegReq/RegRel
1771 	NewLocalInvite_AuthRecv,     	// Auth request received for an outgoing transaction
1772 	NewLocalInvite_RepSent,	     	// Auth reply sent for an outgoing transaction
1773 	NewRemoteInvite,             	// New incoming transaction: Poke/New/RegReq/RegRel
1774 	NewRemoteInvite_AuthSent,    	// Auth sent for an incoming transaction
1775 	NewRemoteInvite_RepRecv,     	// Auth reply received for an incoming transaction
1776 	Unknown,                     	// Initial state
1777 	Terminated,                  	// Terminated. No more frames accepted
1778         Terminating,                 	// Terminating. Wait for ACK or timeout to terminate
1779     };
1780 
1781     /**
1782      * Constructs an incoming transaction from a received full frame with an IAX
1783      *  control message that needs a new transaction
1784      * @param engine The engine that owns this transaction
1785      * @param frame A valid full frame
1786      * @param lcallno Local call number
1787      * @param addr Address from where the frame was received
1788      * @param data Pointer to arbitrary user data
1789      */
1790     static IAXTransaction* factoryIn(IAXEngine* engine, IAXFullFrame* frame, u_int16_t lcallno, const SocketAddr& addr,
1791 		void* data = 0);
1792 
1793     /**
1794      * Constructs an outgoing transaction with an IAX control message that needs a new transaction
1795      * @param engine The engine that owns this transaction
1796      * @param type Transaction type
1797      * @param lcallno Local call number
1798      * @param addr Address to use
1799      * @param ieList Starting IE list
1800      * @param data Pointer to arbitrary user data
1801      */
1802     static IAXTransaction* factoryOut(IAXEngine* engine, Type type, u_int16_t lcallno, const SocketAddr& addr,
1803 		IAXIEList& ieList, void* data = 0);
1804 
1805     /**
1806      * Destructor
1807      */
1808     virtual ~IAXTransaction();
1809 
1810     /**
1811      * The IAX engine this transaction belongs to
1812      * @return Pointer to the IAXEngine of this transaction
1813      */
getEngine()1814     inline IAXEngine* getEngine() const
1815         { return m_engine; }
1816 
1817     /**
1818      * Get the type of this transaction
1819      * @return The type of the transaction as enumeration
1820      */
type()1821     inline Type type() const
1822         { return m_type; }
1823 
1824     /**
1825      * Retrieve transaction type name
1826      * @return Transaction type name
1827      */
typeName()1828     inline const char* typeName()
1829 	{ return typeName(type()); }
1830 
1831     /**
1832      * Get the state of this transaction
1833      * @return The state of the transaction as enumeration
1834      */
state()1835     inline State state() const
1836         { return m_state; }
1837 
1838     /**
1839      * Retrieve the transaction state name
1840      * @return Transaction state name
1841      */
stateName()1842     inline const char* stateName()
1843 	{ return stateName(state()); }
1844 
1845     /**
1846      * Get the timestamp of this transaction
1847      * @return The timestamp of this transaction
1848      */
timeStamp()1849     inline u_int64_t timeStamp() const
1850         { return Time::msecNow() - m_timeStamp; }
1851 
1852     /**
1853      * Get the direction of this transaction
1854      * @return True if it is an outgoing transaction
1855      */
outgoing()1856     inline bool outgoing() const
1857         { return m_localInitTrans; }
1858 
1859     /**
1860      * Store a pointer to arbitrary user data
1861      * @param data User provided pointer
1862      */
setUserData(void * data)1863     inline void setUserData(void* data)
1864         { m_userdata = data; }
1865 
1866     /**
1867      * Return the opaque user data stored in the transaction
1868      * @return Pointer set by user
1869      */
getUserData()1870     inline void* getUserData() const
1871         { return m_userdata; }
1872 
1873     /**
1874      * Retrieve the local call number
1875      * @return 15-bit local call number
1876      */
localCallNo()1877     inline u_int16_t localCallNo() const
1878         { return m_lCallNo; }
1879 
1880     /**
1881      * Retrieve the remote call number
1882      * @return 15-bit remote call number
1883      */
remoteCallNo()1884     inline u_int16_t remoteCallNo() const
1885         { return m_rCallNo; }
1886 
1887     /**
1888      * Retrieve the remote host+port address
1889      * @return A reference to the remote address
1890      */
remoteAddr()1891     inline const SocketAddr& remoteAddr() const
1892         { return m_addr; }
1893 
1894     /**
1895      * Retrieve the username
1896      * @return A reference to the username
1897      */
username()1898     inline const String& username()
1899 	{ return m_username; }
1900 
1901     /**
1902      * Retrieve the calling number
1903      * @return A reference to the calling number
1904      */
callingNo()1905     inline const String& callingNo()
1906 	{ return m_callingNo; }
1907 
1908     /**
1909      * Retrieve the calling name
1910      * @return A reference to the calling name
1911      */
callingName()1912     inline const String& callingName()
1913 	{ return m_callingName; }
1914 
1915     /**
1916      * Retrieve the called number
1917      * @return A reference to the called number
1918      */
calledNo()1919     inline const String& calledNo()
1920 	{ return m_calledNo; }
1921 
1922     /**
1923      * Retrieve the called context
1924      * @return A reference to the called context
1925      */
calledContext()1926     inline const String& calledContext()
1927 	{ return m_calledContext; }
1928 
1929     /**
1930      * Retrieve the challenge sent/received during authentication
1931      * @return A reference to the challenge
1932      */
challenge()1933     inline const String& challenge()
1934 	{ return m_challenge; }
1935 
1936     /**
1937      * Retrieve the media of a given type
1938      * @param type Media type to retrieve
1939      * @return IAXFormat pointer or 0 for invalid type
1940      */
getFormat(int type)1941     inline IAXFormat* getFormat(int type) {
1942 	    if (type == IAXFormat::Audio)
1943 		return &m_format;
1944 	    if (type == IAXFormat::Video)
1945 		return &m_formatVideo;
1946 	    return 0;
1947 	}
1948 
1949     /**
1950      * Retrieve the media data for a given type
1951      * @param type Media type to retrieve
1952      * @return IAXMediaData pointer or 0 for invalid type
1953      */
getData(int type)1954     inline IAXMediaData* getData(int type) {
1955 	    if (type == IAXFormat::Audio)
1956 		return &m_dataAudio;
1957 	    if (type == IAXFormat::Video)
1958 		return &m_dataVideo;
1959 	    return 0;
1960 	}
1961 
1962     /**
1963      * Retrieve the media format used during initialization
1964      * @param type Media type to retrieve
1965      * @return The initial media format for the given type
1966      */
format(int type)1967     inline u_int32_t format(int type) {
1968 	    IAXFormat* fmt = getFormat(type);
1969 	    return fmt ? fmt->format() : 0;
1970 	}
1971 
1972     /**
1973      * Retrieve the incoming media format
1974      * @param type Media type to retrieve
1975      * @return The incoming media format for the given type
1976      */
formatIn(int type)1977     inline u_int32_t formatIn(int type) {
1978 	    IAXFormat* fmt = getFormat(type);
1979 	    return fmt ? fmt->in() : 0;
1980 	}
1981 
1982     /**
1983      * Retrieve the outgoing media format
1984      * @param type Media type to retrieve
1985      * @return The outgoing media format for the given type
1986      */
formatOut(int type)1987     inline u_int32_t formatOut(int type) {
1988 	    IAXFormat* fmt = getFormat(type);
1989 	    return fmt ? fmt->out() : 0;
1990 	}
1991 
1992     /**
1993      * Retrieve the media capability of this transaction
1994      * @return The media capability of this transaction
1995      */
capability()1996     inline u_int32_t capability() const
1997 	{ return m_capability; }
1998 
1999     /**
2000      * Retrieve the expiring time for a register/unregister transaction
2001      * @return The expiring time for a register/unregister transaction
2002      */
expire()2003     inline u_int32_t expire() const
2004 	{ return m_expire; }
2005 
2006     /**
2007      * Retrieve the authentication data sent/received during authentication
2008      * @return A reference to the authentication data
2009      */
authdata()2010     inline const String& authdata()
2011 	{ return m_authdata; }
2012 
2013     /**
2014      * Set the destroy flag
2015      */
setDestroy()2016     inline void setDestroy()
2017 	{ m_destroy = true; }
2018 
2019     /**
2020      * Start an outgoing transaction.
2021      * This method is thread safe
2022      */
2023     void start();
2024 
2025     /**
2026      * Process a frame from remote peer.
2027      * This method is thread safe
2028      * @param frame IAX frame belonging to this transaction to process
2029      * @return 'this' if successful or NULL if the frame is invalid
2030      */
2031     IAXTransaction* processFrame(IAXFrame* frame);
2032 
2033     /**
2034      * Process received media data
2035      * @param data Received data
2036      * @param tStamp Mini frame timestamp multiplied by format multiplier
2037      * @param type Media type
2038      * @param full True if received in a full frame
2039      * @param mark Mark flag
2040      * @return 0
2041      */
2042     IAXTransaction* processMedia(DataBlock& data, u_int32_t tStamp,
2043 	int type = IAXFormat::Audio, bool full = false, bool mark = false);
2044 
2045     /**
2046      * Send media data to remote peer. Update the outgoing media format if changed
2047      * @param data Data to send
2048      * @param tStamp Data timestamp
2049      * @param format Data format
2050      * @param type Media type
2051      * @param mark Mark flag
2052      * @return The number of bytes sent
2053      */
2054     unsigned int sendMedia(const DataBlock& data, unsigned int tStamp, u_int32_t format,
2055 	int type = IAXFormat::Audio, bool mark = false);
2056 
2057     /**
2058      * Get an IAX event from the queue
2059      * This method is thread safe.
2060      * @param now Current time
2061      * @return Pointer to an IAXEvent or 0 if none available
2062      */
2063     IAXEvent* getEvent(const Time& now = Time());
2064 
2065     /**
2066      * Get the maximum allowed number of full frames in the incoming frame list
2067      * @return The maximum allowed number of full frames in the incoming frame list
2068      */
2069     static unsigned char getMaxFrameList();
2070 
2071     /**
2072      * Set the maximum allowed number of full frames in the incoming frame list
2073      * @param value The new value of m_maxInFrames
2074      * @return False if value is greater then IAX2_MAX_TRANSINFRAMELIST
2075      */
2076     static bool setMaxFrameList(unsigned char value);
2077 
2078     /**
2079      * Send an ANSWER frame to remote peer
2080      * This method is thread safe
2081      * @return False if the current transaction state is not Connected
2082      */
sendAnswer()2083     inline bool sendAnswer()
2084 	{ return sendConnected(IAXFullFrame::Answer); }
2085 
2086     /**
2087      * Send a RINGING frame to remote peer
2088      * This method is thread safe
2089      * @return False if the current transaction state is not Connected
2090      */
sendRinging()2091     inline bool sendRinging()
2092 	{ return sendConnected(IAXFullFrame::Ringing); }
2093 
2094     /**
2095      * Send a PROCEEDING frame to remote peer
2096      * This method is thread safe
2097      * @return False if the current transaction state is not Connected
2098      */
sendProgress()2099     inline bool sendProgress()
2100 	{ return sendConnected(IAXFullFrame::Proceeding); }
2101 
2102     /**
2103      * Send an ACCEPT/REGACK frame to remote peer
2104      * This method is thread safe
2105      * @param expires Optional pointer to expiring time for register transactions
2106      * @return False if the transaction type is not New and state is NewRemoteInvite or NewRemoteInvite_AuthRep or
2107      *  if the transaction type is not RegReq and state is NewRemoteInvite or
2108      *  type is not RegReq/RegRel and state is NewRemoteInvite_AuthRep
2109      */
2110     bool sendAccept(unsigned int* expires = 0);
2111 
2112     /**
2113      * Send a HANGUP frame to remote peer
2114      * This method is thread safe
2115      * @param cause Optional reason for hangup
2116      * @param code Optional code of reason
2117      * @return False if the transaction type is not New or state is Terminated/Terminating
2118      */
2119     bool sendHangup(const char* cause = 0, u_int8_t code = 0);
2120 
2121     /**
2122      * Send a REJECT/REGREJ frame to remote peer
2123      * This method is thread safe
2124      * @param cause Optional reason for reject
2125      * @param code Optional code of reason
2126      * @return False if the transaction type is not New/RegReq/RegRel or state is Terminated/Terminating
2127      */
2128     bool sendReject(const char* cause = 0, u_int8_t code = 0);
2129 
2130     /**
2131      * Send an AUTHREQ/REGAUTH frame to remote peer
2132      * This method is thread safe
2133      * @return False if the current transaction state is not NewRemoteInvite
2134      */
2135     bool sendAuth();
2136 
2137     /**
2138      * Send an AUTHREP/REGREQ/REGREL frame to remote peer as a response to AUTHREQ/REGREQ/REGREL
2139      * This method is thread safe
2140      * @param response Response to send
2141      * @return False if the current transaction state is not NewLocalInvite_AuthRecv
2142      */
2143     bool sendAuthReply(const String& response);
2144 
2145     /**
2146      * Send a DTMF frame to remote peer
2147      * This method is thread safe
2148      * @param dtmf DTMF char to send
2149      * @return False if the current transaction state is not Connected or dtmf is grater then 127
2150      */
sendDtmf(u_int8_t dtmf)2151     inline bool sendDtmf(u_int8_t dtmf)
2152 	{ return dtmf <= 127 ? sendConnected((IAXFullFrame::ControlType)dtmf,IAXFrame::DTMF) : false; }
2153 
2154     /**
2155      * Send a TEXT frame to remote peer
2156      * This method is thread safe
2157      * @param text Text to send
2158      * @return False if the current transaction state is not Connected
2159      */
2160     bool sendText(const char* text);
2161 
2162     /**
2163      * Send a NOISE frame to remote peer
2164      * This method is thread safe
2165      * @param noise Noise value to send
2166      * @return False if the current transaction state is not Connected or noise is grater then 127
2167      */
sendNoise(u_int8_t noise)2168     inline bool sendNoise(u_int8_t noise)
2169 	{ return noise <= 127 ? sendConnected((IAXFullFrame::ControlType)noise,IAXFrame::Noise) : false; }
2170 
2171     /**
2172      * Abort a registration transaction
2173      * This method is thread safe
2174      * @return False transaction is not a registration one or is already terminating
2175      */
2176     bool abortReg();
2177 
2178     /**
2179      * Enable trunking for this transaction
2180      * @param trunkFrame Pointer to IAXMetaTrunkFrame used to send trunked media
2181      * @param efficientUse Use or not the trunk based on calls using it
2182      * @return False trunking is already enabled for this transactio or trunkFrame is 0
2183      */
2184     bool enableTrunking(IAXMetaTrunkFrame* trunkFrame, bool efficientUse);
2185 
2186     /**
2187      * Process a received call token
2188      * This method is thread safe
2189      * @param callToken Received call token
2190      */
2191     void processCallToken(const DataBlock& callToken);
2192 
2193     /**
2194      * Process incoming audio miniframes from trunk without timestamps
2195      * @param ts Trunk frame timestamp
2196      * @param blocks Received blocks
2197      * @param now Current time
2198      */
2199     void processMiniNoTs(u_int32_t ts, ObjList& blocks, const Time& now = Time());
2200 
2201     /**
2202      * Print transaction data on stdin
2203      * @param printStats True to print media statistics
2204      * @param printFrames True to print in/out pending frames
2205      * @param location Additional location info to be shown in debug
2206      */
2207     void print(bool printStats = false, bool printFrames = false, const char* location = "status");
2208 
2209     /**
2210      * Retrieve transaction type name from transaction type
2211      * @param type Transaction type
2212      * @return Requested type name
2213      */
typeName(int type)2214     static inline const char* typeName(int type)
2215 	{ return lookup(type,s_typeName); }
2216 
2217     /**
2218      * Retrieve transaction state name
2219      * @param state Transaction state
2220      * @return Requested state name
2221      */
stateName(int state)2222     static inline const char* stateName(int state)
2223 	{ return lookup(state,s_stateName); }
2224 
2225     /**
2226      * Transaction type name
2227      */
2228     static const TokenDict s_typeName[];
2229 
2230     /**
2231      * Transaction state name
2232      */
2233     static const TokenDict s_stateName[];
2234 
2235     /**
2236      * Standard message sent if unsupported/unknown/none authentication methosd was received
2237      */
2238     static String s_iax_modNoAuthMethod;
2239 
2240     /**
2241      * Standard message sent if unsupported/unknown/none media format was received
2242      */
2243     static String s_iax_modNoMediaFormat;
2244 
2245     /**
2246      * Standard message sent if the received authentication data is incorrect
2247      */
2248     static String s_iax_modInvalidAuth;
2249 
2250     /**
2251      * Standard message sent if a received frame doesn't have an username information element
2252      */
2253     static String s_iax_modNoUsername;
2254 
2255 protected:
2256     /**
2257      * Constructor: constructs an incoming transaction from a received full frame with an IAX
2258      *  control message that needs a new transaction
2259      * @param engine The engine that owns this transaction
2260      * @param frame A valid full frame
2261      * @param lcallno Local call number
2262      * @param addr Address from where the frame was received
2263      * @param data Pointer to arbitrary user data
2264      */
2265     IAXTransaction(IAXEngine* engine, IAXFullFrame* frame, u_int16_t lcallno, const SocketAddr& addr,
2266 	void* data = 0);
2267 
2268     /**
2269      * Constructor: constructs an outgoing transaction with an IAX control message that needs a new transaction
2270      * @param engine The engine that owns this transaction
2271      * @param type Transaction type: see Type enumeration
2272      * @param lcallno Local call number
2273      * @param addr Address to use
2274      * @param ieList Starting IE list
2275      * @param data Pointer to arbitrary user data
2276      */
2277     IAXTransaction(IAXEngine* engine, Type type, u_int16_t lcallno, const SocketAddr& addr, IAXIEList& ieList,
2278 	void* data = 0);
2279 
2280     /**
2281      * Cleanup
2282      */
2283     virtual void destroyed();
2284 
2285     /**
2286      * Init data members from an IE list
2287      * @param ieList IE list to init from
2288      */
2289     void init(IAXIEList& ieList);
2290 
2291     /**
2292      * Increment sequence numbers (inbound or outbound) for the frames that need it
2293      * @param frame Received frame if inbound is true, otherwise a transmitted one
2294      * @param inbound True for inbound frames
2295      * @return True if incremented.
2296      */
2297     bool incrementSeqNo(const IAXFullFrame* frame, bool inbound);
2298 
2299     /**
2300      * Test if frame is acceptable (not an out of order or a late one)
2301      * @param frame Frame to test
2302      * @return True if frame can be added to incoming frame list
2303      */
2304     bool isFrameAcceptable(const IAXFullFrame* frame);
2305 
2306     /**
2307      * Change the transaction state
2308      * @param newState the new transaction state
2309      * @return False if trying to change a termination state into a non termination one
2310      */
2311     bool changeState(State newState);
2312 
2313     /**
2314      * Terminate the transaction.
2315      * @param evType IAXEvent type to generate
2316      * @param local If true it is a locally generated event
2317      * @param frame Frame to build event from
2318      * @param createIEList If true create IE list in the generated event
2319      * @return Pointer to a valid IAXEvent
2320      */
2321     IAXEvent* terminate(u_int8_t evType, bool local, IAXFullFrame* frame = 0, bool createIEList = true);
2322 
2323     /**
2324      * Wait for ACK to terminate the transaction. No more events will be generated
2325      * @param evType IAXEvent type to generate
2326      * @param local If true it is a locally generated event
2327      * @param frame Frame to build event from
2328      * @return Pointer to a valid IAXEvent if evType if non 0, 0 otherwise
2329      */
2330     IAXEvent* waitForTerminate(u_int8_t evType = 0, bool local = true, IAXFullFrame* frame = 0);
2331 
2332     /**
2333      * Constructs an IAXFrameOut frame, send it to remote peer and put it in the transmission list
2334      * This method is thread safe
2335      * @param type Frame type
2336      * @param subclass Frame subclass
2337      * @param data Frame IE list
2338      * @param len Frame IE list length
2339      * @param tStamp Frame timestamp. If 0 the transaction timestamp will be used
2340      * @param ackOnly Frame's acknoledge only flag
2341      * @param mark Frame mark flag
2342      */
2343     void postFrame(IAXFrame::Type type, u_int32_t subclass, void* data = 0, u_int16_t len = 0, u_int32_t tStamp = 0,
2344 	bool ackOnly = false, bool mark = false);
2345 
2346     /**
2347      * Constructs an IAXFrameOut frame, send it to remote peer and put it in the transmission list
2348      * This method is thread safe
2349      * @param type Frame type
2350      * @param subclass Frame subclass
2351      * @param ies Frame IE list
2352      * @param tStamp Frame timestamp. If 0 the transaction timestamp will be used
2353      * @param ackOnly Frame's acknoledge only flag
2354      */
2355     void postFrameIes(IAXFrame::Type type, u_int32_t subclass, IAXIEList* ies, u_int32_t tStamp = 0,
2356 		bool ackOnly = false);
2357 
2358     /**
2359      * Send a full frame to remote peer
2360      * @param frame Frame to send
2361      * @param vnak If true the transmission is a response to a VNAK frame
2362      * @return True on success
2363      */
2364     bool sendFrame(IAXFrameOut* frame, bool vnak = false);
2365 
2366     /**
2367      * Create an event
2368      * @param evType Event type
2369      * @param local If true it is a locally generated event.
2370      * @param frame Frame to create from
2371      * @param newState The transaction new state
2372      * @return Pointer to an IAXEvent or 0 (invalid IE list)
2373      */
2374     IAXEvent* createEvent(u_int8_t evType, bool local, IAXFullFrame* frame, State newState);
2375 
2376     /**
2377      * Create an event from a received frame that is a response to a sent frame and
2378      *  change the transaction state to newState. Remove the response from incoming list.
2379      * @param frame Frame to create response for
2380      * @param findType Frame type to find
2381      * @param findSubclass Frame subclass to find
2382      * @param evType Event type to generate
2383      * @param local Local flag for the generated event.
2384      * @param newState New transaction state if an event was generated
2385      * @return Pointer to an IAXEvent or 0 (invalid IE list)
2386      */
2387     IAXEvent* createResponse(IAXFrameOut* frame, u_int8_t findType, u_int8_t findSubclass, u_int8_t evType, bool local, State newState);
2388 
2389     /**
2390      * Find a response for a previously sent frame
2391      * @param frame Frame to find response for
2392      * @param delFrame Delete frame flag. If true on exit, a response was found
2393      * @return Pointer to an IAXEvent or 0
2394      */
2395     IAXEvent* getEventResponse(IAXFrameOut* frame, bool& delFrame);
2396 
2397     /**
2398      * Find a response for a previously sent frame if the transaction type is New
2399      * @param frame Frame to find response for
2400      * @param delFrame Delete frame flag. If true on exit, a response was found
2401      * @return Pointer to an IAXEvent or 0
2402      */
2403     IAXEvent* getEventResponse_New(IAXFrameOut* frame, bool& delFrame);
2404 
2405     /**
2406      * Process an authentication request. If valid, send an authentication reply
2407      * @param event Already generated event
2408      * @return Pointer to a valid IAXEvent
2409      */
2410     IAXEvent* processAuthReq(IAXEvent* event);
2411 
2412     /**
2413      * Process an accept. If not valid (call m_engine->acceptFormatAndCapability) send a reject.
2414      *  Otherwise return the event
2415      * @param event Already generated event
2416      * @return Pointer to a valid IAXEvent
2417      */
2418     IAXEvent* processAccept(IAXEvent* event);
2419 
2420     /**
2421      * Process an authentication reply
2422      * @param event Already generated event
2423      * @return Pointer to a valid IAXEvent
2424      */
2425     IAXEvent* processAuthRep(IAXEvent* event);
2426 
2427     /**
2428      * Find a response for a previously sent frame if the transaction type is RegReq/RegRel
2429      * @param frame Frame to find response for
2430      * @param delFrame Delete frame flag. If true on exit, a response was found
2431      * @return Pointer to an IAXEvent or 0
2432      */
2433     IAXEvent* getEventResponse_Reg(IAXFrameOut* frame, bool& delFrame);
2434 
2435     /**
2436      * Update transaction data from the event
2437      * @param event Already generated event
2438      * @return The received event
2439      */
2440     IAXEvent* processRegAck(IAXEvent* event);
2441 
2442     /**
2443      * Find out if an incoming frame would start a transaction
2444      * @param frame Frame to process
2445      * @param delFrame Delete frame flag. If true on exit, frame is valid
2446      * @return Pointer to an IAXEvent or 0
2447      */
2448     IAXEvent* getEventStartTrans(IAXFullFrame* frame, bool& delFrame);
2449 
2450     /**
2451      * Find out if a frame is a remote request
2452      * @param frame Frame to process
2453      * @param delFrame Delete rame flag. If true on exit, a request was found
2454      * @return Pointer to an IAXEvent or 0
2455      */
2456     IAXEvent* getEventRequest(IAXFullFrame* frame, bool& delFrame);
2457 
2458     /**
2459      * Find out if a frame is a remote request if transaction type is New
2460      * @param frame Frame to process
2461      * @param delFrame Delete rame flag. If true on exit, a request was found
2462      * @return Pointer to an IAXEvent or 0
2463      */
2464     IAXEvent* getEventRequest_New(IAXFullFrame* frame, bool& delFrame);
2465 
2466     /**
2467      * Search for a frame in m_inFrames having the given type and subclass
2468      * @param type Frame type to find.
2469      * @param subclass Frame subclass to find.
2470      * @return Pointer to frame if found or 0.
2471      */
2472     IAXFullFrame* findInFrame(IAXFrame::Type type, u_int32_t subclass);
2473 
2474     /**
2475      * Search in m_inFrames for a frame with the same timestamp as frameOut and deletes it.
2476      * @param frameOut Frame to find response for
2477      * @param type Frame type to find
2478      * @param subclass Frame subclass to find
2479      * @return True if found.
2480      */
2481     bool findInFrameTimestamp(const IAXFullFrame* frameOut, IAXFrame::Type type, u_int32_t subclass);
2482 
2483     /**
2484      * Search in m_inFrames for an ACK frame which confirm the received frame and deletes it
2485      * @param frameOut Frame to find response for
2486      * @return True if found.
2487      */
2488     bool findInFrameAck(const IAXFullFrame* frameOut);
2489 
2490     /**
2491      * Acknoledge the last received full frame
2492      */
2493     void ackInFrames();
2494 
2495     /**
2496      * Send a frame to remote peer in state Connected
2497      * This method is thread safe
2498      * @param subclass Frame subclass to send
2499      * @param frametype Frame type to send
2500      * @return False if the current transaction state is not Connected
2501      */
2502     bool sendConnected(IAXFullFrame::ControlType subclass, IAXFrame::Type frametype = IAXFrame::Control);
2503 
2504     /**
2505      * Send an ACK frame
2506      * @param frame Aknoledged frame
2507      */
2508     void sendAck(const IAXFullFrame* frame);
2509 
2510     /**
2511      * Send an VNAK frame
2512      */
2513     void sendVNAK();
2514 
2515     /**
2516      * Send an Unsupport frame
2517      * @param subclass Unsupported frame's subclass
2518      */
2519     void sendUnsupport(u_int32_t subclass);
2520 
2521     /**
2522      * Internal protocol outgoing frames processing (PING/LAGRQ)
2523      * @param frame Frame to process
2524      * @param delFrame Delete frame flag. If true on exit, a response was found
2525      * @return 0.
2526      */
2527     IAXEvent* processInternalOutgoingRequest(IAXFrameOut* frame, bool& delFrame);
2528 
2529     /**
2530      * Internal protocol incoming frames processing (PING/LAGRQ)
2531      * @param frame Frame to process
2532      * @param delFrame Delete frame flag. If true on exit, a request was found
2533      * @return 0.
2534      */
2535     IAXEvent* processInternalIncomingRequest(const IAXFullFrame* frame, bool& delFrame);
2536 
2537     /**
2538      * Process mid call control frames
2539      * @param frame Frame to process
2540      * @param delFrame Delete frame flag. If true on exit, a request was found
2541      * @return A valid IAXEvent or 0
2542      */
2543     IAXEvent* processMidCallControl(IAXFullFrame* frame, bool& delFrame);
2544 
2545     /**
2546      * Process mid call IAX control frames
2547      * @param frame Frame to process
2548      * @param delFrame Delete frame flag. If true on exit, a request was found
2549      * @return A valid IAXEvent or 0
2550      */
2551     IAXEvent* processMidCallIAXControl(IAXFullFrame* frame, bool& delFrame);
2552 
2553     /**
2554      * Test if frame is a Reject/RegRej frame
2555      * @param frame Frame to process.
2556      * @param delFrame Delete frame flag. If true on exit, a request was found
2557      * @return A valid IAXEvent or 0.
2558      */
2559     IAXEvent* remoteRejectCall(IAXFullFrame* frame, bool& delFrame);
2560 
2561     /**
2562      * Process received media full frames
2563      * @param frame Received frame
2564      * @param type Media type
2565      * @return 0
2566      */
2567     IAXTransaction* processMediaFrame(const IAXFullFrame* frame, int type);
2568 
2569     /**
2570      * Send all frames from outgoing queue with outbound sequence number starting with seqNo.
2571      * @param seqNo Requested sequence number
2572      * @return 0
2573      */
2574     IAXTransaction* retransmitOnVNAK(u_int16_t seqNo);
2575 
2576     /**
2577      * Generate a Reject event after internally rejecting a transaction
2578      * @param reason The reason of rejecting
2579      * @param code Error code
2580      * @return A valid IAXEvent
2581      */
2582     IAXEvent* internalReject(const char* reason, u_int8_t code);
2583 
2584     /**
2585      * Event terminated feedback
2586      * This method is thread safe
2587      * @param event The event notifying termination
2588      */
2589     void eventTerminated(IAXEvent* event);
2590 
2591     /**
2592      * Set the current event
2593      * @param event The event notifying termination
2594      * @return event
2595      */
keepEvent(IAXEvent * event)2596     inline IAXEvent* keepEvent(IAXEvent* event) {
2597 	m_currentEvent = event;
2598 	return event;
2599     }
2600 
2601 private:
2602     void adjustTStamp(u_int32_t& tStamp);
2603     void postFrame(IAXFrameOut* frame);
2604     void receivedVoiceMiniBeforeFull();
2605     void resetTrunk();
2606     void init();
2607     void setPendingEvent(IAXEvent* ev = 0);
restartTrunkIn(u_int64_t now,u_int32_t ts)2608     inline void restartTrunkIn(u_int64_t now, u_int32_t ts) {
2609 	    m_trunkInStartTime = now;
2610 	    u_int64_t dt = (now - m_lastVoiceFrameIn) / 1000;
2611 	    m_trunkInTsDelta = m_lastVoiceFrameInTs + (u_int32_t)dt;
2612 	    m_trunkInFirstTs = ts;
2613 	}
2614     // Process accept format and caps
2615     bool processAcceptFmt(IAXIEList* list);
2616     // Process queued ACCEPT. Reject with given reason/code if not found
2617     // Reject with 'nomedia' if found and format is not acceptable
2618     IAXEvent* checkAcceptRecv(const char* reason, u_int8_t code);
2619 
2620     // Params
2621     bool m_localInitTrans;			// True: local initiated transaction
2622     bool m_localReqEnd;				// Local client requested terminate
2623     Type m_type;				// Transaction type
2624     State m_state;				// Transaction state
2625     bool m_destroy;                             // Destroy flag
2626     bool m_accepted;                            // ACCEPT received and processed
2627     u_int64_t m_timeStamp;			// Transaction creation timestamp
2628     u_int64_t m_timeout;			// Transaction timeout in Terminating state
2629     SocketAddr m_addr;				// Socket
2630     u_int16_t m_lCallNo;			// Local peer call id
2631     u_int16_t m_rCallNo;			// Remote peer call id
2632     unsigned char m_oSeqNo;			// Outgoing frame sequence number
2633     unsigned char m_iSeqNo;			// Incoming frame sequence number
2634     IAXEngine* m_engine;			// Engine that owns this transaction
2635     void* m_userdata;				// Arbitrary user data
2636     u_int32_t m_lastFullFrameOut;		// Last transmitted full frame timestamp
2637     IAXMediaData m_dataAudio;
2638     IAXMediaData m_dataVideo;
2639     u_int16_t m_lastAck;			// Last ack'd received frame's oseqno
2640     IAXEvent* m_pendingEvent;			// Pointer to a pending event or 0
2641     IAXEvent* m_currentEvent;			// Pointer to last generated event or 0
2642     // Outgoing frames management
2643     ObjList m_outFrames;			// Transaction & protocol control outgoing frames
2644     unsigned int m_retransCount;		// Retransmission counter. 0 --> Timeout
2645     unsigned int m_retransInterval;		// Frame retransmission interval
2646     // Incoming frames management
2647     ObjList m_inFrames;				// Transaction & protocol control incoming frames
2648     static unsigned char m_maxInFrames;		// Max frames number allowed in m_inFrames
2649     // Call leg management
2650     u_int32_t m_pingInterval;			// Ping remote peer interval
2651     u_int64_t m_timeToNextPing;			// Time of the next Ping
2652     // Statistics
2653     u_int32_t m_inTotalFramesCount;		// Total received frames
2654     u_int32_t m_inOutOfOrderFrames;		// Total out of order frames
2655     u_int32_t m_inDroppedFrames;		// Total dropped frames
2656     // Data
2657     IAXAuthMethod::Type m_authmethod;		// Authentication method to use
2658     String m_username;				// Username
2659     String m_callingNo;				// Calling number
2660     String m_callingName;			// Calling name
2661     String m_calledNo;				// Called number
2662     String m_calledContext;			// Called context
2663     String m_challenge;				// Challenge
2664     String m_authdata;				// Auth data received with auth reply
2665     u_int32_t m_expire;				// Registration expiring time
2666     IAXFormat m_format;				// Audio format
2667     IAXFormat m_formatVideo;			// Video format
2668     u_int32_t m_capability;			// Media capability of this transaction
2669     bool m_callToken;                           // Call token supported/expected
2670     unsigned int m_adjustTsOutThreshold;        // Adjust outgoing data timestamp threshold
2671     unsigned int m_adjustTsOutOverrun;          // Value used to adjust outgoing data timestamp on data
2672                                                 //  overrun (incoming data with rate greater then expected)
2673     unsigned int m_adjustTsOutUnderrun;         // Value used to adjust outgoing data timestamp on data
2674                                                 //  underrun (incoming data with rate less then expected)
2675     u_int64_t m_lastVoiceFrameIn;               // Time we received the last voice frame
2676     u_int32_t m_lastVoiceFrameInTs;             // Timestamp in the last received voice frame
2677     int m_reqVoiceVNAK;                         // Send VNAK if not received full voice frame
2678     // Meta trunking
2679     IAXMetaTrunkFrame* m_trunkFrame;		// Reference to a trunk frame if trunking is enabled for this transaction
2680     bool m_trunkFrameCallsSet;                  // Trunk frame calls increased
2681     bool m_trunkOutEfficientUse;                // Use or not the trunk frame based on calls using it
2682     bool m_trunkOutSend;                        // Currently using the trunk frame
2683     bool m_trunkInSyncUsingTs;                  // Incoming trunk without timestamps: generate timestamp
2684                                                 //  using time or using trunk timestamp
2685     u_int64_t m_trunkInStartTime;               // First time we received trunk in data
2686     u_int32_t m_trunkInTsDelta;                 // Value used to re-build ts: last voice timestamp
2687     u_int32_t m_trunkInTsDiffRestart;           // Incoming trunk without timestamp: diff between timestamps at which we restart
2688     u_int32_t m_trunkInFirstTs;                 // Incoming trunk without timestamp: first trunk timestamp
2689     // Postponed start
2690     IAXIEList* m_startIEs;                      // Postponed start
2691 };
2692 
2693 /**
2694  * This class holds an event generated by a transaction
2695  * @short Event class
2696  */
2697 class YIAX_API IAXEvent
2698 {
2699     friend class IAXTransaction;
2700     friend class IAXConnectionlessTransaction;
2701 public:
2702     /**
2703      * Event type as enumeration
2704      */
2705     enum Type {
2706 	DontSet = 0,            // Used internal
2707         Invalid,		// Invalid frame received
2708 	Terminated,		// Transaction terminated
2709         Timeout,		// Transaction timeout
2710 	NotImplemented,		// Feature not implemented
2711 	New,			// New remote transaction
2712 	AuthReq,		// Auth request
2713 	AuthRep,		// Auth reply
2714 	Accept,			// Request accepted
2715 	Hangup,			// Remote hangup
2716 	Reject,			// Remote reject
2717 	Busy,			// Call busy
2718 	Text,			// Text frame received
2719 	Dtmf,			// DTMF frame received
2720 	Noise,			// Noise frame received
2721 	Answer,			// Call answered
2722 	Quelch,			// Quelch the call
2723 	Unquelch,		// Unquelch the call
2724 	Progressing,		// Call progressing
2725 	Ringing,		// Ringing
2726     };
2727 
2728     /**
2729      * Destructor
2730      * Dereferences the transaction possibly causing its destruction
2731      */
2732     ~IAXEvent();
2733 
2734     /**
2735      * Get the type of this event
2736      * @return The type of the event as enumeratio
2737      */
type()2738     inline Type type() const
2739 	{ return m_type; }
2740 
2741     /**
2742      * Check if this is a locally generated event
2743      * @return True if it is a locally generated event
2744      */
local()2745     inline bool local() const
2746         { return m_local; }
2747 
2748     /**
2749      * Check if this is a transaction finalization event
2750      * @return True if the transaction has finalized and will be destroyed
2751      */
final()2752     inline bool final() const
2753         { return m_final; }
2754 
2755     /**
2756      * Set the final flag.
2757      */
setFinal()2758     inline void setFinal()
2759         { m_final = true; }
2760 
2761     /**
2762      * Get the type of the frame that generated the event
2763      * If 0 (internal event), the event consumer must delete the event
2764      * @return Frame type
2765      */
frameType()2766     inline u_int8_t frameType()
2767 	{ return m_frameType; }
2768 
2769     /**
2770      * Get the subclass of the frame that generated the event
2771      * @return Frame subclass
2772      */
subclass()2773     inline u_int32_t subclass()
2774 	{ return m_subClass; }
2775 
2776     /**
2777      * Get the IAX engine this event belongs to, if any
2778      * @return The IAX engine this event belongs to, if any
2779      */
getEngine()2780     inline IAXEngine* getEngine() const
2781 	{ return m_transaction ? m_transaction->getEngine() : 0; }
2782 
2783     /**
2784      * Get the IAX transaction that generated the event, if any
2785      * @return The IAX transaction that generated the event, if any
2786      */
getTransaction()2787     inline IAXTransaction* getTransaction() const
2788 	{ return m_transaction; }
2789 
2790     /**
2791      * Get the opaque user data stored in the transaction
2792      * @return The opaque user data stored in the transaction
2793      */
getUserData()2794     inline void* getUserData() const
2795 	{ return m_transaction ? m_transaction->getUserData() : 0; }
2796 
2797     /**
2798      * Get the IE list
2799      * @return IE list reference
2800      */
getList()2801     inline IAXIEList& getList()
2802 	{ return *m_ieList; }
2803 
2804 protected:
2805     /**
2806      * Constructor
2807      * @param type Event type
2808      * @param local Local flag
2809      * @param final Final flag
2810      * @param transaction IAX transaction that generated the event
2811      * @param frameType The type of the frame that generated the event
2812      * @param subclass The subclass of the frame that generated the event
2813      */
2814     IAXEvent(Type type, bool local, bool final, IAXTransaction* transaction, u_int8_t frameType = 0, u_int32_t subclass = 0);
2815 
2816     /**
2817      * Constructor
2818      * @param type Event type
2819      * @param local Local flag
2820      * @param final Final flag
2821      * @param transaction IAX transaction that generated the event
2822      * @param frame The frame that generated the event
2823      */
2824     IAXEvent(Type type, bool local, bool final, IAXTransaction* transaction, IAXFullFrame* frame = 0);
2825 
2826 private:
IAXEvent()2827     inline IAXEvent() {}		// Default constructor
2828 
2829     Type m_type;			// Event type
2830     u_int8_t m_frameType;		// Frame type
2831     u_int32_t m_subClass;		// Frame subclass
2832     bool m_local;			// If true the event is generated locally, the receiver MUST not respond
2833     bool m_final;			// Final event flag
2834     IAXTransaction* m_transaction;	// Transaction that generated this event
2835     IAXIEList* m_ieList;		// IAXInfoElement list
2836 };
2837 
2838 /**
2839  * This class holds all information needded to manipulate all IAX transactions and events
2840  * @short IAX engine class
2841  */
2842 class YIAX_API IAXEngine : public DebugEnabler, public Mutex
2843 {
2844 public:
2845     /**
2846      * Constructor
2847      * @param iface Address of the interface to use, default all (0.0.0.0)
2848      * @param port UDP port to run the protocol on
2849      * @param format Default media format
2850      * @param capab Media capabilities of this engine
2851      * @param params Optional extra parameter list
2852      * @param name Engine name
2853      */
2854     IAXEngine(const char* iface, int port, u_int32_t format, u_int32_t capab,
2855 	const NamedList* params = 0, const char* name = "iaxengine");
2856 
2857     /**
2858      * Destructor
2859      * Closes all transactions belonging to this engine and flush all queues
2860      */
2861     virtual ~IAXEngine();
2862 
2863     /**
2864      * Retrieve the engine name
2865      * @return Engine name
2866      */
name()2867     inline const String& name() const
2868 	{ return m_name; }
2869 
2870     /**
2871      * Retrieve the default caller number type
2872      * @return Default caller number type
2873      */
callerNumType()2874     inline u_int8_t callerNumType() const
2875 	{ return m_callerNumType; }
2876 
2877     /**
2878      * Retrieve the default caller number presentation and screening concatenated value
2879      * @return Default caller number presentation and screening
2880      */
callingPres()2881     inline u_int8_t callingPres() const
2882 	{ return m_callingPres; }
2883 
2884     /**
2885      * Add a parsed frame to the transaction list
2886      * @param addr Address from which the frame was received
2887      * @param frame A parsed IAX frame
2888      * @return Pointer to the transaction or 0 to deref the frame
2889      */
2890     IAXTransaction* addFrame(const SocketAddr& addr, IAXFrame* frame);
2891 
2892     /**
2893      * Add a raw frame to the transaction list
2894      * @param addr Address from which the message was received
2895      * @param buf Pointer to the start of the buffer holding the IAX frame
2896      * @param len Length of the message buffer
2897      * @return Pointer to the transaction or 0
2898      */
2899     IAXTransaction* addFrame(const SocketAddr& addr, const unsigned char* buf, unsigned int len);
2900 
2901     /**
2902      * Find a complete transaction.
2903      * This method is thread safe
2904      * @param addr Remote address
2905      * @param rCallNo Remote transaction call number
2906      * @return Referrenced pointer to the transaction or 0
2907      */
2908     IAXTransaction* findTransaction(const SocketAddr& addr, u_int16_t rCallNo);
2909 
2910     /**
2911      * Process media from remote peer. Descendents must override this method
2912      * @param transaction IAXTransaction that owns the call leg
2913      * @param data Media data
2914      * @param tStamp Media timestamp
2915      * @param type Media type
2916      * @param mark Mark flag
2917      */
processMedia(IAXTransaction * transaction,DataBlock & data,u_int32_t tStamp,int type,bool mark)2918     virtual void processMedia(IAXTransaction* transaction, DataBlock& data, u_int32_t tStamp,
2919 	int type, bool mark)
2920 	{}
2921 
2922     /**
2923      * Event processor method. Keeps calling getEvent() and passing
2924      *  any events to processEvent() until there are no more events
2925      * @return True if at least one event was processed
2926      */
2927     bool process();
2928 
2929     /**
2930      * Get the timeout interval sent challenge
2931      * @return Sent challenge timeout interval
2932      */
challengeTout()2933     inline unsigned int challengeTout() const
2934         { return m_challengeTout; }
2935 
2936     /**
2937      * Get the maximum allowed frame length
2938      * @return The maximum allowed frame length
2939      */
maxFullFrameDataLen()2940     inline u_int16_t maxFullFrameDataLen() const
2941         { return m_maxFullFrameDataLen; }
2942 
2943     /**
2944      * Get the default media format
2945      * @param audio True to retrieve default audio format, false for video format
2946      * @return The default media format
2947      */
2948     inline u_int32_t format(bool audio = true) const
2949         { return audio ? m_format : m_formatVideo; }
2950 
2951     /**
2952      * Get the media capability of this engine
2953      * @return The media capability of this engine
2954      */
capability()2955     inline u_int32_t capability() const
2956         { return m_capability; }
2957 
2958     /**
2959      * Retrieve outgoing data timestamp adjust values
2960      * @param thres Adjust outgoing data timestamp threshold
2961      * @param over Value used to adjust outgoing data timestamp on data overrun
2962      * @param under Value used to adjust outgoing data timestamp on data underrun
2963      */
getOutDataAdjust(unsigned int & thres,unsigned int & over,unsigned int & under)2964     inline void getOutDataAdjust(unsigned int& thres, unsigned int& over,
2965 	unsigned int& under) const {
2966 	    thres = m_adjustTsOutThreshold;
2967 	    over = m_adjustTsOutOverrun;
2968 	    under = m_adjustTsOutUnderrun;
2969 	}
2970 
2971     /**
2972      * Initialize outgoing data timestamp adjust values.
2973      * This method is thread safe
2974      * @param params Parameters list
2975      * @param tr Optional transaction to init, initialize the engine's data if 0
2976      */
2977     void initOutDataAdjust(const NamedList& params, IAXTransaction* tr = 0);
2978 
2979     /**
2980      * (Re)Initialize the engine
2981      * @param params Parameter list
2982      */
2983     void initialize(const NamedList& params);
2984 
2985     /**
2986      * Read data from socket
2987      * @param addr Socket to read from
2988      */
2989     void readSocket(SocketAddr& addr);
2990 
2991     /**
2992      * Write data to socket.
2993      * @param buf Data to write
2994      * @param len Data length
2995      * @param addr Socket to write to
2996      * @param frame Optional frame to be printed
2997      * @param sent Pointer to variable to be filled with the number of bytes sent
2998      * @return True on success
2999      */
3000     bool writeSocket(const void* buf, int len, const SocketAddr& addr, IAXFullFrame* frame = 0,
3001 	unsigned int* sent = 0);
3002 
3003     /**
3004      * Write a full frame to socket
3005      * @param addr Socket to write to
3006      * @param frame Frame to write
3007      * @return True on success
3008      */
writeSocket(const SocketAddr & addr,IAXFullFrame * frame)3009     inline bool writeSocket(const SocketAddr& addr, IAXFullFrame* frame)
3010 	{ return !frame || writeSocket(frame->data().data(),frame->data().length(),addr,frame); }
3011 
3012     /**
3013      * Read events
3014      */
3015     void runGetEvents();
3016 
3017     /**
3018      * Removes a transaction from queue. Free the allocated local call number
3019      *  Does not delete it
3020      * @param transaction Transaction to remove
3021      */
3022     void removeTransaction(IAXTransaction* transaction);
3023 
3024     /**
3025      * Check if there are any transactions in the engine
3026      * This method is thread safe
3027      * @return True if the engine holds at least 1 transaction
3028      */
3029     bool haveTransactions();
3030 
3031     /**
3032      * Return the transactions count
3033      * This method is thread safe
3034      * @return Transactions count
3035      */
3036     u_int32_t transactionCount();
3037 
3038     /**
3039      * Send an INVAL with call numbers set to 0 to a remote peer to keep it alive
3040      * @param addr Address to send to
3041      */
3042     void keepAlive(const SocketAddr& addr);
3043 
3044     /**
3045      * Process a new format received with a full frame
3046      * @param trans Transaction that received the new format
3047      * @param type Media type
3048      * @param format The received format
3049      * @return True if accepted
3050      */
mediaFormatChanged(IAXTransaction * trans,int type,u_int32_t format)3051     virtual bool mediaFormatChanged(IAXTransaction* trans, int type, u_int32_t format)
3052 	{ return false; }
3053 
3054     /**
3055      * Check call token on incoming call requests.
3056      * This method is called by the engine when processing an incoming call request
3057      * @param addr The address from where the call request was received
3058      * @param frame Received frame
3059      * @return True if accepted, false to ignore the call
3060      */
3061     virtual bool checkCallToken(const SocketAddr& addr, IAXFullFrame& frame);
3062 
3063     /**
3064      * Process the initial received format and capability.
3065      * If accepted on exit will set the transaction format and capability
3066      * @param trans Transaction that received the new format
3067      * @param caps Optional codecs to set in transaction before processing
3068      * @param type Media type
3069      * @return True if accepted
3070      */
3071     bool acceptFormatAndCapability(IAXTransaction* trans, unsigned int* caps = 0,
3072 	int type = IAXFormat::Audio);
3073 
3074     /**
3075      * Default event handler. event MUST NOT be deleted
3076      * @param event The event to handle
3077      */
3078     virtual void defaultEventHandler(IAXEvent* event);
3079 
3080     /**
3081      * Check if the engine is exiting
3082      * @return True if the engine is exiting
3083      */
exiting()3084     inline bool exiting() const
3085 	{ return m_exiting; }
3086 
3087     /**
3088      * Set the exiting flag
3089      */
3090     virtual void setExiting();
3091 
3092     /**
3093      * Enable trunking for the given transaction. Allocate a trunk meta frame if needed.
3094      * Trunk data is ignored if a trunk object for transaction remote address already exists
3095      * @param trans Transaction to enable trunking for
3096      * @param params Trunk parameters list, may be 0
3097      * @param prefix Trunk parameters name prefix
3098      */
3099     void enableTrunking(IAXTransaction* trans, const NamedList* params,
3100 	const String& prefix = String::empty());
3101 
3102     /**
3103      * Enable trunking for the given transaction. Allocate a trunk meta frame if needed.
3104      * Trunk data is ignored if a trunk object for transaction remote address already exists
3105      * @param trans Transaction to enable trunking for
3106      * @param data Trunk info to use
3107      */
3108     void enableTrunking(IAXTransaction* trans, IAXTrunkInfo& data);
3109 
3110     /**
3111      * Init incoming trunking data for a given transaction
3112      * @param trans Transaction to init
3113      * @param params Trunk parameters list, may be 0
3114      * @param prefix Trunk parameters name prefix
3115      */
3116     void initTrunkIn(IAXTransaction* trans, const NamedList* params,
3117 	const String& prefix = String::empty());
3118 
3119     /**
3120      * Init incoming trunking data for a given transaction
3121      * @param trans Transaction to init
3122      * @param data Trunk info to use
3123      */
3124     void initTrunkIn(IAXTransaction* trans, IAXTrunkInfo& data);
3125 
3126     /**
3127      * Retrieve the default trunk info data
3128      * @param info Destination to be set with trunk info pointer
3129      * @return True if destination pointr is valid
3130      */
trunkInfo(RefPointer<IAXTrunkInfo> & info)3131     inline bool trunkInfo(RefPointer<IAXTrunkInfo>& info) {
3132 	    Lock lck(m_trunkInfoMutex);
3133 	    info = m_trunkInfoDef;
3134 	    return info != 0;
3135 	}
3136 
3137     /**
3138      * Send an INVAL frame
3139      * @param frame Frame for which to send an INVAL frame
3140      * @param addr The address from where the call request was received
3141      */
3142     void sendInval(IAXFullFrame* frame, const SocketAddr& addr);
3143 
3144     /**
3145      * Keep calling processTrunkFrames to send trunked media data
3146      */
3147     void runProcessTrunkFrames();
3148 
3149     /**
3150      * Get the socket used for engine operation
3151      * @return Reference to the UDP socket
3152      */
socket()3153     inline Socket& socket()
3154 	{ return m_socket; }
3155 
3156     /**
3157      * Retrieve the socket address on wgich we are bound
3158      * @return Local address we are bound on
3159      */
addr()3160     inline const SocketAddr& addr() const
3161 	{ return m_addr; }
3162 
3163     /**
3164      * Send engine formats
3165      * @param caps Capabilities
3166      * @param fmtAudio Default audio format
3167      * @param fmtVideo Default video format
3168      */
setFormats(u_int32_t caps,u_int32_t fmtAudio,u_int32_t fmtVideo)3169     inline void setFormats(u_int32_t caps, u_int32_t fmtAudio, u_int32_t fmtVideo) {
3170 	    m_format = fmtAudio;
3171 	    m_formatVideo = fmtVideo;
3172 	    m_capability = caps;
3173 	}
3174 
3175     /**
3176      * Retrieve a port parameter
3177      * @param params Parameters list
3178      * @param param Parameter to retrieve
3179      * @return The port (default, 4569, if the parameter is missing or invalid)
3180      */
3181     static inline int getPort(const NamedList& params, const String& param = "port")
3182 	{ return params.getIntValue(param,4569); }
3183 
3184     /**
3185      * Get the MD5 data from a challenge and a password
3186      * @param md5data Destination String
3187      * @param challenge Challenge source
3188      * @param password Password source
3189      */
3190     static void getMD5FromChallenge(String& md5data, const String& challenge, const String& password);
3191 
3192     /**
3193      * Test if a received response to an authentication request is correct
3194      * @param md5data Data to compare with
3195      * @param challenge Received challenge
3196      * @param password Password source
3197      */
3198     static bool isMD5ChallengeCorrect(const String& md5data, const String& challenge, const String& password);
3199 
3200     /**
3201      * Build a time signed secret used to authenticate an IP address
3202      * @param buf Destination buffer
3203      * @param secret Extra secret to add to MD5 sum
3204      * @param addr Socket address
3205      */
3206     static void buildAddrSecret(String& buf, const String& secret,
3207 	const SocketAddr& addr);
3208 
3209     /**
3210      * Decode a secret built using buildAddrSecret()
3211      * @param buf Input buffer
3212      * @param secret Extra secret to check
3213      * @param addr Socket address
3214      * @return Secret age, negative if invalid
3215      */
3216     static int addrSecretAge(const String& buf, const String& secret,
3217 	const SocketAddr& addr);
3218 
3219     /**
3220      * Add string (keyword) if found in a dictionary or integer parameter to a named list
3221      * @param list Destination list
3222      * @param param Parameter to add to the list
3223      * @param tokens The dictionary used to find the given value
3224      * @param val The value to find/add to the list
3225      */
addKeyword(NamedList & list,const char * param,const TokenDict * tokens,unsigned int val)3226     static inline void addKeyword(NamedList& list, const char* param,
3227 	const TokenDict* tokens, unsigned int val) {
3228 	    const char* value = lookup(val,tokens);
3229 	    if (value)
3230 		list.addParam(param,value);
3231 	    else
3232 		list.addParam(param,String(val));
3233 	}
3234 
3235     /**
3236      * Decode a DATETIME value
3237      * @param dt Value to decode
3238      * @param year The year component of the date
3239      * @param month The month component of the date
3240      * @param day The day component of the date
3241      * @param hour The hour component of the time
3242      * @param minute The minute component of the time
3243      * @param sec The seconds component of the time
3244      */
3245     static void decodeDateTime(u_int32_t dt, unsigned int& year, unsigned int& month,
3246 	unsigned int& day, unsigned int& hour, unsigned int& minute, unsigned int& sec);
3247 
3248     /**
3249      * Calculate overall timeout from interval and retransmission counter
3250      * @param interval The first retransmisssion interval
3251      * @param nRetrans The number of retransmissions
3252      * @return The overall timeout
3253      */
3254     static unsigned int overallTout(unsigned int interval = IAX2_RETRANS_INTERVAL_DEF,
3255 	unsigned int nRetrans = IAX2_RETRANS_COUNT_DEF);
3256 
3257 protected:
3258     /**
3259      * Process all trunk meta frames in the queue
3260      * @param time Time of the call
3261      * @return True if at least one frame was sent
3262      */
3263     bool processTrunkFrames(const Time& time = Time());
3264 
3265     /**
3266      * Default event for connection transactions handler. This method may be overriden to perform custom
3267      *  processing
3268      * This method is thread safe
3269      * @param event Event to process
3270      */
3271     virtual void processEvent(IAXEvent* event);
3272 
3273     /**
3274      * Get an IAX event from the queue.
3275      * This method is thread safe.
3276      * @param now Current time
3277      * @return Pointer to an IAXEvent or 0 if none is available
3278      */
3279     IAXEvent* getEvent(const Time& now = Time());
3280 
3281     /**
3282      * Generate call number. Update used call numbers list
3283      * @return Call number or 0 if none available
3284      */
3285     u_int16_t generateCallNo();
3286 
3287     /**
3288      * Release a call number
3289      * @param lcallno Call number to release
3290      */
3291     void releaseCallNo(u_int16_t lcallno);
3292 
3293     /**
3294      * Start a transaction based on a local request
3295      * @param type Transaction type
3296      * @param addr Remote address to send the request
3297      * @param ieList First frame IE list
3298      * @param refTrans Return a refferenced transaction pointer
3299      * @param startTrans Start transaction
3300      * @return IAXTransaction pointer on success
3301      */
3302     IAXTransaction* startLocalTransaction(IAXTransaction::Type type,
3303 	const SocketAddr& addr, IAXIEList& ieList,
3304 	bool refTrans = false, bool startTrans = true);
3305 
3306     /**
3307      * Bind the socket. Terminate it before trying
3308      * @param iface Address of the interface to use, default all (0.0.0.0)
3309      * @param port UDP port to run the protocol on
3310      * @param force Force binding if failed on required port
3311      * @return True on success
3312      */
3313     bool bind(const char* iface, int port, bool force);
3314 
3315     int m_trunking;                             // Trunking capability: negative: ok, otherwise: not enabled
3316 
3317 private:
3318     String m_name;                              // Engine name
3319     Socket m_socket;				// Socket
3320     SocketAddr m_addr;                          // Address we are bound on
3321     ObjList** m_transList;			// Full transactions
3322     ObjList m_incompleteTransList;		// Incomplete transactions (no remote call number)
3323     bool m_lUsedCallNo[IAX2_MAX_CALLNO + 1];	// Used local call numnmbers flags
3324     int m_lastGetEvIndex;			// getEvent: keep last array entry
3325     bool m_exiting;                             // Exiting flag
3326     // Parameters
3327     int m_maxFullFrameDataLen;			// Max full frame data (IE list) length
3328     u_int16_t m_startLocalCallNo;		// Start index of local call number allocation
3329     u_int16_t m_transListCount;			// m_transList count
3330     unsigned int m_challengeTout;		// Sent challenge timeout interval
3331     bool m_callToken;                           // Call token required on incoming calls
3332     String m_callTokenSecret;                   // Secret used to generate call tokens
3333     int m_callTokenAge;                         // Max allowed call token age
3334     bool m_showCallTokenFailures;               // Print incoming call token failures to output
3335     bool m_rejectMissingCallToken;              // Reject/ignore incoming calls without call token if mandatory
3336     bool m_printMsg;                            // Print frame to output
3337     u_int8_t m_callerNumType;                   // Caller number type
3338     u_int8_t m_callingPres;                     // Caller presentation + screening
3339     // Media
3340     u_int32_t m_format;				// The default media format
3341     u_int32_t m_formatVideo;                    // Default video format
3342     u_int32_t m_capability;			// The media capability
3343     unsigned int m_adjustTsOutThreshold;        // Adjust outgoing data timestamp threshold
3344     unsigned int m_adjustTsOutOverrun;          // Value used to adjust outgoing data timestamp on data
3345                                                 //  overrun (incoming data with rate greater then expected)
3346     unsigned int m_adjustTsOutUnderrun;         // Value used to adjust outgoing data timestamp on data
3347                                                 //  underrun (incoming data with rate less then expected)
3348     // Trunking
3349     Mutex m_mutexTrunk;				// Mutex for trunk operations
3350     ObjList m_trunkList;			// Trunk frames list
3351     Mutex m_trunkInfoMutex;                     // Trunk info mutex
3352     RefPointer<IAXTrunkInfo> m_trunkInfoDef;    // Defaults for trunk data
3353 };
3354 
3355 }
3356 
3357 #endif /* __YATEIAX_H */
3358 
3359 /* vi: set ts=8 sw=4 sts=4 noet: */
3360