1 /**
2  * yatephone.h
3  * This file is part of the YATE Project http://YATE.null.ro
4  *
5  * Drivers, channels and telephony related classes
6  *
7  * Yet Another Telephony Engine - a fully featured software PBX and IVR
8  * Copyright (C) 2004-2014 Null Team
9  *
10  * This software is distributed under multiple licenses;
11  * see the COPYING file in the main directory for licensing
12  * information for this specific distribution.
13  *
14  * This use of this software may be subject to additional restrictions.
15  * See the LEGAL file in the main directory for details.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  */
21 
22 #ifndef __YATEPHONE_H
23 #define __YATEPHONE_H
24 
25 #ifndef __cplusplus
26 #error C++ is required
27 #endif
28 
29 #include <yatengine.h>
30 
31 /**
32  * Holds all Telephony Engine related classes.
33  */
34 namespace TelEngine {
35 
36 /**
37  * A structure to hold information about a static picture or video frame.
38  */
39 struct YATE_API ImageInfo {
40     /**
41      * Width of the image in pixels
42      */
43     int width;
44 
45     /**
46      * Height of the image in pixels
47      */
48     int height;
49 
50     /**
51      * Bit depth of the image, 0 for unknown/irrelevant
52      */
53     int depth;
54 };
55 
56 /**
57  * A structure to hold information about a data format.
58  */
59 struct YATE_API FormatInfo {
60     /**
61      * Standard no-blanks lowercase format name
62      */
63     const char* name;
64 
65     /**
66      * Format type: "audio", "video", "text"
67      */
68     const char* type;
69 
70     /**
71      * Frame size in octets/frame, 0 for non-framed formats
72      */
73     int frameSize;
74 
75     /**
76      * Frame time in microseconds, 0 for variable
77      */
78     int frameTime;
79 
80     /**
81      * Rate in samples/second (audio) or 1e-6 frames/second (video), 0 for unknown
82      */
83     int sampleRate;
84 
85     /**
86      * Number of channels, typically 1
87      */
88     int numChannels;
89 
90     /**
91      * If this is a valid candidate for conversion
92      */
93     bool converter;
94 
95     /**
96      * Guess the number of samples in an encoded data block
97      * @param len Length of the data block in octets
98      * @return Number of samples or 0 if unknown
99      */
100     int guessSamples(int len) const;
101 
102     /**
103      * Get the data rate in bytes/s
104      * @return Data rate or 0 if variable/undefined
105      */
106     int dataRate() const;
107 
108     /**
109      * Default constructor - used to initialize arrays
110      */
FormatInfoFormatInfo111     inline FormatInfo()
112 	: name(0), type("audio"),
113 	  frameSize(0), frameTime(0),
114 	  sampleRate(8000), numChannels(1),
115 	  converter(false)
116 	{ }
117 
118     /**
119      * Normal constructor
120      */
121     inline explicit FormatInfo(const char* _name, int fsize = 0, int ftime = 10000,
122 	const char* _type = "audio", int srate = 8000, int nchan = 1, bool convert = false)
nameFormatInfo123 	: name(_name), type(_type),
124 	  frameSize(fsize), frameTime(ftime),
125 	  sampleRate(srate), numChannels(nchan),
126 	  converter(convert)
127 	{ }
128 };
129 
130 class DataEndpoint;
131 class CallEndpoint;
132 class Driver;
133 
134 /**
135  * A structure to build (mainly static) translator capability tables.
136  * A table of such structures must end with an entry with null format names.
137  */
138 struct YATE_API TranslatorCaps {
139     /** Description of source (input) data format */
140     const FormatInfo* src;
141     /** Description of destination (output) data format */
142     const FormatInfo* dest;
143     /** Computing cost in KIPS of converting a stream from src to dest */
144     int cost;
145 };
146 
147 /**
148  * This is just a holder for the list of media formats supported by Yate
149  * @short A repository for media formats
150  */
151 class YATE_API FormatRepository
152 {
153     YNOCOPY(FormatRepository); // no automatic copies please
154 private:
155     FormatRepository();
156 public:
157     /**
158      * Retrieve a format by name and type
159      * @param name Standard name of the format to find
160      * @return Pointer to the format info or NULL if not found
161      */
162     static const FormatInfo* getFormat(const String& name);
163 
164     /**
165      * Add a new format to the repository
166      * @param name Standard no-blanks lowercase format name
167      * @param fsize Data frame size in octets/frame, 0 for non-framed formats
168      * @param ftime Data frame duration in microseconds, 0 for variable
169      * @param type Format type: "audio", "video", "text"
170      * @param srate Rate in samples/second (audio) or 1e-6 frames/second (video), 0 for unknown
171      * @param nchan Number of channels, typically 1
172      * @return Pointer to the format info or NULL if another incompatible
173      *  format with the same name was already registered
174     */
175     static const FormatInfo* addFormat(const String& name, int fsize, int ftime, const String& type = "audio", int srate = 8000, int nchan = 1);
176 };
177 
178 /**
179  * An extension of a String that can parse data formats
180  * @short A Data format
181  */
182 class YATE_API DataFormat : public NamedList
183 {
184 public:
185     /**
186      * Creates a new, empty format string.
187      */
DataFormat()188     inline DataFormat()
189 	: NamedList((const char*)0), m_parsed(0)
190 	{ }
191 
192     /**
193      * Creates a new initialized format.
194      * @param value Initial value of the format
195      */
DataFormat(const char * value)196     inline DataFormat(const char* value)
197 	: NamedList(value), m_parsed(0)
198 	{ }
199 
200     /**
201      * Copy constructor.
202      * @param value Initial value of the format
203      */
DataFormat(const DataFormat & value)204     inline DataFormat(const DataFormat& value)
205 	: NamedList(value), m_parsed(value.getInfo())
206 	{ }
207 
208     /**
209      * Constructor from String reference
210      * @param value Initial value of the format
211      */
DataFormat(const String & value)212     inline DataFormat(const String& value)
213 	: NamedList(value), m_parsed(0)
214 	{ }
215 
216     /**
217      * Constructor from NamedList reference
218      * @param value Initial value of the format and parameters
219      */
DataFormat(const NamedList & value)220     inline DataFormat(const NamedList& value)
221 	: NamedList(value), m_parsed(0)
222 	{ }
223 
224     /**
225      * Constructor from String pointer.
226      * @param value Initial value of the format
227      */
DataFormat(const String * value)228     inline DataFormat(const String* value)
229 	: NamedList(value ? value->c_str() : (const char*)0), m_parsed(0)
230 	{ }
231 
232     /**
233      * Constructor from format information
234      * @param format Pointer to existing FormatInfo
235      */
DataFormat(const FormatInfo * format)236     inline explicit DataFormat(const FormatInfo* format)
237 	: NamedList(format ? format->name : (const char*)0), m_parsed(format)
238 	{ }
239 
240     /**
241      * Assignment operator.
242      */
243     inline DataFormat& operator=(const DataFormat& value)
244 	{ NamedList::operator=(value); m_parsed = value.getInfo(); return *this; }
245 
246     /**
247      * Retrieve a pointer to the format information
248      * @return Pointer to the associated format info or NULL if error
249      */
250     const FormatInfo* getInfo() const;
251 
252     /**
253      * Retrieve the frame size
254      * @param defValue Default value to return if format is unknown
255      * @return Frame size in octets/frame, 0 for non-framed, defValue if unknown
256      */
257     inline int frameSize(int defValue = 0) const
258 	{ return getInfo() ? getInfo()->frameSize : defValue; }
259 
260     /**
261      * Retrieve the frame time
262      * @param defValue Default value to return if format is unknown
263      * @return Frame time in microseconds, 0 for variable, defValue if unknown
264      */
265     inline int frameTime(int defValue = 0) const
266 	{ return getInfo() ? getInfo()->frameTime : defValue; }
267 
268     /**
269      * Retrieve the sample rate
270      * @param defValue Default value to return if format is unknown
271      * @return Rate in samples/second (audio) or 1e-6 frames/second (video),
272      *  0 for unknown, defValue if unknown format
273      */
274     inline int sampleRate(int defValue = 0) const
275 	{ return getInfo() ? getInfo()->sampleRate : defValue; }
276 
277     /**
278      * Retrieve the number of channels
279      * @param defValue Default value to return if format is unknown
280      * @return Number of channels (typically 1), defValue if unknown format
281      */
282     inline int numChannels(int defValue = 1) const
283 	{ return getInfo() ? getInfo()->numChannels : defValue; }
284 
285 protected:
286     /**
287      * Called whenever the value changed (except in constructors).
288      */
289     virtual void changed();
290 
291 private:
292     mutable const FormatInfo* m_parsed;
293 };
294 
295 /**
296  * A generic data handling object
297  */
298 class YATE_API DataNode : public RefObject
299 {
300     friend class DataEndpoint;
301     YNOCOPY(DataNode); // no automatic copies please
302 public:
303     /**
304      * Flags associated with the DataBlocks forwarded between nodes
305      */
306     enum DataFlags {
307 	DataStart   = 0x0001,
308 	DataEnd     = 0x0002,
309 	DataMark    = 0x0004,
310 	DataSilent  = 0x0008,
311 	DataMissed  = 0x0010,
312 	DataError   = 0x0020,
313 	DataPrivate = 0x0100
314     };
315 
316     /**
317      * Construct a DataNode
318      * @param format Description of the data format, default none
319      */
320     inline explicit DataNode(const char* format = 0)
m_format(format)321 	: m_format(format), m_timestamp(0)
322 	{ }
323 
324     /**
325      * Get the computing cost of converting the data to the format asked
326      * @param format Name of the format to check for
327      * @return -1 if unsupported, 0 for native format else cost in KIPS
328      */
costFormat(const DataFormat & format)329     virtual int costFormat(const DataFormat& format)
330 	{ return -1; }
331 
332     /**
333      * Change the format used to transfer data
334      * @param format Name of the format to set for data
335      * @return True if the format changed successfully, false if not changed
336      */
setFormat(const DataFormat & format)337     virtual bool setFormat(const DataFormat& format)
338 	{ return false; }
339 
340     /**
341      * Get the description of the format currently in use
342      * @return Pointer to the data format
343      */
getFormat()344     inline const DataFormat& getFormat() const
345 	{ return m_format; }
346 
347     /**
348      * Get the current position in the data stream
349      * @return Timestamp of current data position
350      */
timeStamp()351     inline unsigned long timeStamp() const
352 	{ return m_timestamp; }
353 
354     /**
355      * Check if this data node is still valid
356      * @return True if still valid, false if node should be removed
357      */
valid()358     virtual bool valid() const
359 	{ return true; }
360 
361     /**
362      * Modify node parameters
363      * @param params The list of parameters to change
364      * @return True if processed
365      */
control(NamedList & params)366     virtual bool control(NamedList& params)
367 	{ return false; }
368 
369     /**
370      * Get the internal representation of an invalid or unknown timestamp
371      * @return Invalid timestamp - unsigned long conversion of -1
372      */
invalidStamp()373     inline static unsigned long invalidStamp()
374 	{ return (unsigned long)-1; }
375 
376     /**
377      * Owner attach and detach notification.
378      * This method is called with @ref DataEndpoint::commonMutex() held
379      * @param added True if a new owner was added, false if it was removed
380      */
attached(bool added)381     virtual void attached(bool added)
382 	{ }
383 
384 protected:
385     DataFormat m_format;
386     unsigned long m_timestamp;
387 };
388 
389 class DataSource;
390 class DataTranslator;
391 class TranslatorFactory;
392 class ThreadedSourcePrivate;
393 
394 /**
395  * A data consumer
396  */
397 class YATE_API DataConsumer : public DataNode
398 {
399     friend class DataSource;
400 
401 public:
402     /**
403      * Consumer constructor
404      * @param format Name of the data format, default "slin" (Signed Linear)
405      */
406     inline explicit DataConsumer(const char* format = "slin")
DataNode(format)407 	: DataNode(format),
408 	  m_source(0), m_override(0),
409 	  m_regularTsDelta(0), m_overrideTsDelta(0), m_lastTsTime(0)
410 	{ }
411 
412     /**
413      * Destruct notification - complains loudly if still attached to a source
414      */
415     virtual void destroyed();
416 
417     /**
418      * Get a pointer to a derived class given that class name
419      * @param name Name of the class we are asking for
420      * @return Pointer to the requested class or NULL if this object doesn't implement it
421      */
422     virtual void* getObject(const String& name) const;
423 
424     /**
425      * Consumes the data sent to it from a source
426      * @param data The raw data block to process
427      * @param tStamp Timestamp of data - typically samples
428      * @param flags Indicator flags associated with the data block
429      * @return Number of samples actually consumed,
430      *  use invalidStamp() to indicate that all data was consumed,
431      *  return zero for consumers that become invalid
432      */
433     virtual unsigned long Consume(const DataBlock& data, unsigned long tStamp, unsigned long flags) = 0;
434 
435     /**
436      * Get the data source of this object if it's connected
437      * @return A pointer to the DataSource object or NULL
438      */
getConnSource()439     inline DataSource* getConnSource() const
440 	{ return m_source; }
441 
442     /**
443      * Get the override data source of this object if it's connected
444      * @return A pointer to the DataSource object or NULL
445      */
getOverSource()446     inline DataSource* getOverSource() const
447 	{ return m_override; }
448 
449     /**
450      * Get the data source of a translator object
451      * @return A pointer to the DataSource object or NULL
452      */
getTransSource()453     virtual DataSource* getTransSource() const
454 	{ return 0; }
455 
456 protected:
457     /**
458      * Synchronize the consumer with a source
459      * @param source Data source to copy the timestamp from
460      * @return True if we could synchronize with the source
461      */
462     virtual bool synchronize(DataSource* source);
463 
464 private:
465     unsigned long Consume(const DataBlock& data, unsigned long tStamp,
466 	unsigned long flags, DataSource* source);
467     DataSource* m_source;
468     DataSource* m_override;
469     long m_regularTsDelta;
470     long m_overrideTsDelta;
471     u_int64_t m_lastTsTime;
472 };
473 
474 /**
475  * A data source
476  */
477 class YATE_API DataSource : public DataNode, public Mutex
478 {
479     friend class DataTranslator;
480     YNOCOPY(DataSource); // no automatic copies please
481 public:
482     /**
483      * Source constructor
484      * @param format Name of the data format, default "slin" (Signed Linear)
485      */
486     inline explicit DataSource(const char* format = "slin")
DataNode(format)487 	: DataNode(format), Mutex(false,"DataSource"),
488 	  m_nextStamp(invalidStamp()), m_translator(0) { }
489 
490     /**
491      * Source's destruct notification - detaches all consumers
492      */
493     virtual void destroyed();
494 
495     /**
496      * Get a pointer to a derived class given that class name
497      * @param name Name of the class we are asking for
498      * @return Pointer to the requested class or NULL if this object doesn't implement it
499      */
500     virtual void* getObject(const String& name) const;
501 
502     /**
503      * Check if this data source is still valid
504      * @return True if still valid, false if node should be removed
505      */
506     virtual bool valid() const;
507 
508     /**
509      * Modify source parameters, calls translator if one is set
510      * @param params The list of parameters to change
511      * @return True if processed
512      */
513     virtual bool control(NamedList& params);
514 
515     /**
516      * Forwards the data to its consumers
517      * @param data The raw data block to forward
518      * @param tStamp Timestamp of data - typically samples
519      * @param flags Indicator flags associated with the data block
520      * @return Number of samples actually forwarded to all consumers
521      */
522     unsigned long Forward(const DataBlock& data, unsigned long tStamp = invalidStamp(),
523 	unsigned long flags = 0);
524 
525     /**
526      * Attach a data consumer
527      * @param consumer Data consumer to attach
528      * @param override Attach as temporary source override
529      * @return True on success, false on failure
530      */
531     bool attach(DataConsumer* consumer, bool override = false);
532 
533     /**
534      * Detach a data consumer
535      * @param consumer Data consumer to detach
536      * @return True on success, false on failure
537      */
538     bool detach(DataConsumer* consumer);
539 
540     /**
541      * Detach all data consumers
542      */
543     void clear();
544 
545     /**
546      * Get the master translator object if this source is part of a translator
547      * @return A pointer to the DataTranslator object or NULL
548      */
getTranslator()549     inline DataTranslator* getTranslator() const
550 	{ return m_translator; }
551 
552     /**
553      * Synchronize the source and attached consumers with another timestamp
554      * @param tStamp New timestamp of data - typically samples
555      */
556     void synchronize(unsigned long tStamp);
557 
558     /**
559      * Get the next expected position in the data stream
560      * @return Timestamp of next expected data position, may be invalid/unknown
561      */
nextStamp()562     inline unsigned long nextStamp() const
563 	{ return m_nextStamp; }
564 
565 protected:
566     unsigned long m_nextStamp;
567     ObjList m_consumers;
568 private:
setTranslator(DataTranslator * translator)569     inline void setTranslator(DataTranslator* translator) {
570 	    Lock mylock(this);
571 	    m_translator = translator;
572 	}
573     bool detachInternal(DataConsumer* consumer);
574     DataTranslator* m_translator;
575 };
576 
577 /**
578  * A data source with a thread of its own
579  * @short Data source with own thread
580  */
581 class YATE_API ThreadedSource : public DataSource
582 {
583     friend class ThreadedSourcePrivate;
584 public:
585     /**
586      * The destruction notification, checks that the thread is gone
587      */
588     virtual void destroyed();
589 
590     /**
591      * Starts the worker thread
592      * @param name Static name of this thread
593      * @param prio Thread's priority
594      * @return True if started, false if an error occured
595      */
596     bool start(const char* name = "ThreadedSource", Thread::Priority prio = Thread::Normal);
597 
598     /**
599      * Stops and destroys the worker thread if running
600      */
601     void stop();
602 
603     /**
604      * Return a pointer to the worker thread
605      * @return Pointer to running worker thread or NULL
606      */
607     Thread* thread() const;
608 
609     /**
610      * Check if the data thread is running
611      * @return True if the data thread was started and is running
612      */
613     bool running() const;
614 
615 protected:
616     /**
617      * Threaded Source constructor
618      * @param format Name of the data format, default "slin" (Signed Linear)
619      */
620     inline explicit ThreadedSource(const char* format = "slin")
DataSource(format)621 	: DataSource(format), m_thread(0)
622 	{ }
623 
624     /**
625      * The worker method. You have to reimplement it as you need
626      */
627     virtual void run() = 0;
628 
629     /**
630      * The cleanup after thread method, deletes the source if already
631      *  dereferenced and set for asynchronous deletion
632      */
633     virtual void cleanup();
634 
635     /**
636      * Check if the calling thread should keep looping the worker method
637      * @param runConsumers True to keep running as long consumers are attached
638      * @return True if the calling thread should remain in the run() method
639      */
640     bool looping(bool runConsumers = false) const;
641 
642 private:
643     ThreadedSourcePrivate* m_thread;
644 };
645 
646 /**
647  * The DataTranslator holds a translator (codec) capable of unidirectional
648  * conversion of data from one type to another.
649  * @short An unidirectional data translator (codec)
650  */
651 class YATE_API DataTranslator : public DataConsumer
652 {
653     friend class TranslatorFactory;
654 public:
655     /**
656      * Construct a data translator.
657      * @param sFormat Name of the source format (data received from the consumer)
658      * @param dFormat Name of the destination format (data supplied to the source)
659      */
660     DataTranslator(const char* sFormat, const char* dFormat);
661 
662     /**
663      * Creates a data translator from an existing source,
664      *  does not increment the source's reference counter.
665      * @param sFormat Name of the source format (data received from the consumer)
666      * @param source Optional pointer to a DataSource object
667      */
668     explicit DataTranslator(const char* sFormat, DataSource* source = 0);
669 
670     /**
671      * Destroys the translator and its source
672      */
673     ~DataTranslator();
674 
675     /**
676      * Get a pointer to a derived class given that class name
677      * @param name Name of the class we are asking for
678      * @return Pointer to the requested class or NULL if this object doesn't implement it
679      */
680     virtual void* getObject(const String& name) const;
681 
682     /**
683      * Check if the data translator has a valid source
684      * @return True if still valid, false if node should be removed
685      */
valid()686     virtual bool valid() const
687 	{ return m_tsource && m_tsource->valid(); }
688 
689     /**
690      * Get the data source of a translator object
691      * @return A pointer to the DataSource object or NULL
692      */
getTransSource()693     virtual DataSource* getTransSource() const
694 	{ return m_tsource; }
695 
696     /**
697      * Get the first translator from a chain
698      * @return Pointer to the first translator in a chain
699      */
700     DataTranslator* getFirstTranslator();
701 
702     /**
703      * Constant version to get the first translator from a chain
704      * @return Pointer to the first translator in a chain
705      */
706     const DataTranslator* getFirstTranslator() const;
707 
708     /**
709      * Get a list of formats supported for a given output format.
710      * @param dFormat Name of destination format
711      * @param maxCost Maximum cost of candidates to consider, -1 to accept all
712      * @param maxLen Maximum length of codec chains to consider, 0 to accept all
713      * @param lst Initial list, will append to it if not empty
714      * @return List of source format names, must be freed by the caller
715      */
716     static ObjList* srcFormats(const DataFormat& dFormat = "slin", int maxCost = -1, unsigned int maxLen = 0, ObjList* lst = 0);
717 
718     /**
719      * Get a list of formats supported for a given input format
720      * @param sFormat Name of source format
721      * @param maxCost Maximum cost of candidates to consider, -1 to accept all
722      * @param maxLen Maximum length of codec chains to consider, 0 to accept all
723      * @param lst Initial list, will append to it if not empty
724      * @return List of destination format names, must be freed by the caller
725      */
726     static ObjList* destFormats(const DataFormat& sFormat = "slin", int maxCost = -1, unsigned int maxLen = 0, ObjList* lst = 0);
727 
728     /**
729      * Get a list of formats supported by transcoding for a given format list
730      * @param formats List of data format names
731      * @param existing Also return formats already existing in the initial list
732      * @param sameRate Only return formats with same sampling rate
733      * @param sameChans Only return formats with same number of channels
734      * @return List of format names, must be freed by the caller
735      */
736     static ObjList* allFormats(const ObjList* formats, bool existing = true, bool sameRate = true, bool sameChans = true);
737 
738     /**
739      * Get a list of formats supported by transcoding for a given format list
740      * @param formats Data format names as comma separated list
741      * @param existing Also return formats already existing in the initial list
742      * @param sameRate Only return formats with same sampling rate
743      * @param sameChans Only return formats with same number of channels
744      * @return List of format names, must be freed by the caller
745      */
746     static ObjList* allFormats(const String& formats, bool existing = true, bool sameRate = true, bool sameChans = true);
747 
748     /**
749      * Check if bidirectional conversion can be performed by installed translators
750      * @param fmt1 Name of the first data format
751      * @param fmt2 Name of the second data format
752      * @return True if translators can be created for both directions
753      */
754     static bool canConvert(const DataFormat& fmt1, const DataFormat& fmt2 = "slin");
755 
756     /**
757      * Finds the cost of a translator given the source and destination format names
758      * @param sFormat Name of the source format (data received from the consumer)
759      * @param dFormat Name of the destination format (data supplied to the source)
760      * @return Cost of best (cheapest) codec or -1 if no known codec exists
761      */
762     static int cost(const DataFormat& sFormat, const DataFormat& dFormat);
763 
764     /**
765      * Creates a translator given the source and destination format names
766      * @param sFormat Name of the source format (data received from the consumer)
767      * @param dFormat Name of the destination format (data supplied to the source)
768      * @return A pointer to a DataTranslator object or NULL if no known codec exists
769      */
770     static DataTranslator* create(const DataFormat& sFormat, const DataFormat& dFormat);
771 
772     /**
773      * Attach a consumer to a source, possibly trough a chain of translators
774      * @param source Source to attach the chain to
775      * @param consumer Consumer where the chain ends
776      * @param override Attach chain for temporary source override
777      * @return True if successfull, false if no translator chain could be built
778      */
779     static bool attachChain(DataSource* source, DataConsumer* consumer, bool override = false);
780 
781     /**
782      * Detach a consumer from a source, possibly trough a chain of translators
783      * @param source Source to dettach the chain from
784      * @param consumer Consumer where the chain ends
785      * @return True if successfull, false if source and consumers were not attached
786      */
787     static bool detachChain(DataSource* source, DataConsumer* consumer);
788 
789     /**
790      * Set the length of the longest translator chain we are allowed to create
791      * @param maxChain Desired longest chain length
792      */
793     static void setMaxChain(unsigned int maxChain);
794 
795 protected:
796     /**
797      * Get access to the list of consumers of the data source
798      * @return Pointer to list entry of first consumer, NULL if none attached
799      */
getConsumers()800     inline ObjList* getConsumers() const
801 	{ return m_tsource ? m_tsource->m_consumers.skipNull() : 0; }
802 
803     /**
804      * Synchronize the consumer with a source
805      * @param source Data source to copy the timestamp from
806      * @return True if we could synchronize with the source
807      */
808     virtual bool synchronize(DataSource* source);
809 
810     /**
811      * Install a Translator Factory in the list of known codecs
812      * @param factory A pointer to a TranslatorFactory instance
813      */
814     static void install(TranslatorFactory* factory);
815 
816     /**
817      * Remove a Translator Factory from the list of known codecs
818      * @param factory A pointer to a TranslatorFactory instance
819      */
820     static void uninstall(TranslatorFactory* factory);
821 
822 private:
823     DataTranslator(); // No default constructor please
824     static void compose();
825     static void compose(TranslatorFactory* factory);
826     static bool canConvert(const FormatInfo* fmt1, const FormatInfo* fmt2);
827     DataSource* m_tsource;
828     static Mutex s_mutex;
829     static ObjList s_factories;
830     static unsigned int s_maxChain;
831 };
832 
833 /**
834  * A factory for constructing data translators by format name
835  * conversion of data from one type to another
836  * @short An unidirectional data translator (codec)
837  */
838 class YATE_API TranslatorFactory : public GenObject
839 {
840     YNOCOPY(TranslatorFactory); // no automatic copies please
841 protected:
842     /**
843      * Constructor - registers the factory in the global list
844      * @param name Static name of the factory, used for debugging
845      */
846     inline explicit TranslatorFactory(const char* name = 0)
847 	: m_name(name ? name : "?")
848 	{ m_counter = Thread::getCurrentObjCounter(true); DataTranslator::install(this); }
849 
850 public:
851     /**
852      * Destructor - unregisters from the global list
853      */
854     virtual ~TranslatorFactory();
855 
856     /**
857      * Notification that another factory was removed from the list
858      * @param factory Pointer to the factory that just got removed
859      */
860     virtual void removed(const TranslatorFactory* factory);
861 
862     /**
863      * Creates a translator given the source and destination format names
864      * @param sFormat Name of the source format (data received from the consumer)
865      * @param dFormat Name of the destination format (data supplied to the source)
866      * @return A pointer to the end of a DataTranslator chain or NULL
867      */
868     virtual DataTranslator* create(const DataFormat& sFormat, const DataFormat& dFormat) = 0;
869 
870     /**
871      * Get the capabilities table of this translator
872      * @return A pointer to the first element of the capabilities table
873      */
874     virtual const TranslatorCaps* getCapabilities() const = 0;
875 
876     /**
877      * Check if this factory can build a translator for given data formats
878      * @param sFormat Name of the source format
879      * @param dFormat Name of the destination format
880      * @return True if a conversion between formats is possible
881      */
882     virtual bool converts(const DataFormat& sFormat, const DataFormat& dFormat) const;
883 
884     /**
885      * Get the length of the translator chain built by this factory
886      * @return How many translators will build the factory
887      */
888     virtual unsigned int length() const;
889 
890     /**
891      * Check if a data format is used as intermediate in a translator chain
892      * @param info Format to check for
893      * @return True if the format is used internally as intermediate
894      */
895     virtual bool intermediate(const FormatInfo* info) const;
896 
897     /**
898      * Get the intermediate format used by a translator chain
899      * @return Pointer to intermediate format or NULL
900      */
901     virtual const FormatInfo* intermediate() const;
902 
903     /**
904      * Get the name of this factory, useful for debugging purposes
905      * @return Name of the factory as specified in the constructor
906      */
name()907     virtual const char* name() const
908 	{ return m_name; }
909 
910     /**
911      * Retrive the objects counter associated to this factory
912      * @return Pointer to factory's objects counter or NULL
913      */
objectsCounter()914     inline NamedCounter* objectsCounter() const
915 	{ return m_counter; }
916 
917 private:
918     const char* m_name;
919     NamedCounter* m_counter;
920 };
921 
922 /**
923  * The DataEndpoint holds an endpoint capable of performing unidirectional
924  * or bidirectional data transfers
925  * @short A data transfer endpoint capable of sending and/or receiving data
926  */
927 class YATE_API DataEndpoint : public RefObject
928 {
929     YNOCOPY(DataEndpoint); // no automatic copies please
930 public:
931     /**
932      * Creates an empty data endpoint
933      */
934     explicit DataEndpoint(CallEndpoint* call = 0, const char* name = "audio");
935 
936     /**
937      * Endpoint destruct notification, clears source and consumer
938      */
939     virtual void destroyed();
940 
941     /**
942      * Get a pointer to a derived class given that class name
943      * @param name Name of the class we are asking for
944      * @return Pointer to the requested class or NULL if this object doesn't implement it
945      */
946     virtual void* getObject(const String& name) const;
947 
948     /**
949      * Get a string identification of the endpoint
950      * @return A reference to this endpoint's name
951      */
952     virtual const String& toString() const;
953 
954     /**
955      * Get the mutex that serializes access to this data endpoint, if any
956      * @return Pointer to the call's mutex object or NULL
957      */
958     Mutex* mutex() const;
959 
960     /**
961      * Get the big mutex that serializes access to all data endpoints
962      * @return A reference to the mutex
963      */
964     static Mutex& commonMutex();
965 
966     /**
967      * Connect the source and consumer of the endpoint to a peer
968      * @param peer Pointer to the peer data endpoint
969      * @return True if connected, false if incompatible source/consumer
970      */
971     bool connect(DataEndpoint* peer);
972 
973     /**
974      * Disconnect from the connected endpoint
975      * @return True if the object was deleted, false if it still exists
976      */
977     bool disconnect();
978 
979     /**
980      * Set the data source of this object
981      * @param source A pointer to the new source or NULL
982      */
983     void setSource(DataSource* source = 0);
984 
985     /**
986      * Get the data source of this object
987      * @return A pointer to the DataSource object or NULL
988      */
getSource()989     inline DataSource* getSource() const
990 	{ return m_source; }
991 
992     /**
993      * Set the data consumer of this object
994      * @param consumer A pointer to the new consumer or NULL
995      */
996     void setConsumer(DataConsumer* consumer = 0);
997 
998     /**
999      * Get the data consumer of this object
1000      * @return A pointer to the DataConsumer object or NULL
1001      */
getConsumer()1002     inline DataConsumer* getConsumer() const
1003 	{ return m_consumer; }
1004 
1005     /**
1006      * Set the data consumer for recording peer generated data.
1007      * This will be connected to the peer data source.
1008      * @param consumer A pointer to the new consumer or NULL
1009      */
1010     void setPeerRecord(DataConsumer* consumer = 0);
1011 
1012     /**
1013      * Get the data consumer used for recording peer generated data.
1014      * @return A pointer to the DataConsumer object or NULL
1015      */
getPeerRecord()1016     inline DataConsumer* getPeerRecord() const
1017 	{ return m_peerRecord; }
1018 
1019     /**
1020      * Set the data consumer for recording local call generated data
1021      * This will be connected to the local data source.
1022      * @param consumer A pointer to the new consumer or NULL
1023      */
1024     void setCallRecord(DataConsumer* consumer = 0);
1025 
1026     /**
1027      * Get the data consumer used for recording local call generated data.
1028      * @return A pointer to the DataConsumer object or NULL
1029      */
getCallRecord()1030     inline DataConsumer* getCallRecord() const
1031 	{ return m_callRecord; }
1032 
1033     /**
1034      * Clear a data node from any slot of this object
1035      * @param node Pointer to DataSource or DataConsumer to clear
1036      * @return True if the node was removed from at least one slot
1037      */
1038     bool clearData(DataNode* node);
1039 
1040     /**
1041      * Adds a data consumer to the list of sniffers of the local call data
1042      * @param sniffer Pointer to the DataConsumer to add to sniffer list
1043      * @return True if the sniffer was added to list, false if NULL or already added
1044      */
1045     bool addSniffer(DataConsumer* sniffer);
1046 
1047     /**
1048      * Remove a data consumer from the list of sniffers of the local call data
1049      * @param sniffer Pointer to the DataConsumer to remove from sniffer list
1050      * @return True if the sniffer was removed from list
1051      */
1052     bool delSniffer(DataConsumer* sniffer);
1053 
1054     /**
1055      * Find a sniffer by name
1056      * @param name Name of the sniffer to find
1057      * @param ref Increment the reference counter before returning
1058      * @return Pointer to DataConsumer or NULL if not found
1059      */
1060     DataConsumer* getSniffer(const String& name, bool ref = false);
1061 
1062     /**
1063      * Removes all sniffers from the list and dereferences them
1064      */
1065     void clearSniffers();
1066 
1067     /**
1068      * Get a pointer to the peer endpoint
1069      * @return A pointer to the peer endpoint or NULL
1070      */
getPeer()1071     inline DataEndpoint* getPeer() const
1072 	{ return m_peer; }
1073 
1074     /**
1075      * Get a pointer to the owner call
1076      * @return A pointer to the owner call or NULL
1077      */
getCall()1078     inline CallEndpoint* getCall() const
1079 	{ return m_call; }
1080 
1081     /**
1082      * Get the name set in constructor
1083      * @return A reference to the name as hashed string
1084      */
name()1085     inline const String& name() const
1086 	{ return m_name; }
1087 
1088     /**
1089      * Clear the owner call endpoint.
1090      * Works only if the caller provides the correct owner pointer
1091      * @param call Pointer to the call endpoint that is to be cleared
1092      */
clearCall(const CallEndpoint * call)1093     inline void clearCall(const CallEndpoint* call)
1094 	{ if (call == m_call) m_call = 0; }
1095 
1096     /**
1097      * Modify data parameters
1098      * @param params The list of parameters to change
1099      * @return True if processed
1100      */
1101     virtual bool control(NamedList& params);
1102 
1103 protected:
1104     /**
1105      * Attempt to connect the endpoint to a peer of the same type
1106      * @param peer Pointer to the endpoint data driver
1107      * @return True if connected, false if failed native connection
1108      */
nativeConnect(DataEndpoint * peer)1109     virtual bool nativeConnect(DataEndpoint* peer)
1110 	{ return false; }
1111 
1112 private:
1113     String m_name;
1114     DataSource* m_source;
1115     DataConsumer* m_consumer;
1116     DataEndpoint* m_peer;
1117     CallEndpoint* m_call;
1118     DataConsumer* m_peerRecord;
1119     DataConsumer* m_callRecord;
1120     ObjList m_sniffers;
1121 };
1122 
1123 /**
1124  * A class that holds common call control and data related features
1125  * @short An abstract call endpoint
1126  */
1127 class YATE_API CallEndpoint : public RefObject
1128 {
1129     friend class DataEndpoint;
1130     YNOCOPY(CallEndpoint); // no automatic copies please
1131 private:
1132     CallEndpoint* m_peer;
1133     const void* m_lastPeer;
1134     String m_id;
1135     String m_lastPeerId;
1136 
1137 protected:
1138     ObjList m_data;
1139     Mutex* m_mutex;
1140 
1141 public:
1142     /**
1143      * Destruct notification, performs cleanups
1144      */
1145     virtual void destroyed();
1146 
1147     /**
1148      * Get a pointer to a derived class given that class name
1149      * @param name Name of the class we are asking for
1150      * @return Pointer to the requested class or NULL if this object doesn't implement it
1151      */
1152     virtual void* getObject(const String& name) const;
1153 
1154     /**
1155      * Get a string representation of this channel
1156      * @return A reference to the name of this object
1157      */
toString()1158     virtual const String& toString() const
1159 	{ return m_id; }
1160 
1161     /**
1162      * Get the unique channel identifier
1163      * @return A String holding the unique channel id
1164      */
id()1165     inline const String& id() const
1166 	{ return m_id; }
1167 
1168     /**
1169      * Get the connected peer call
1170      * @return Pointer to connected peer call or NULL
1171      */
getPeer()1172     inline CallEndpoint* getPeer() const
1173 	{ return m_peer; }
1174 
1175     /**
1176      * Get the connected peer call id in a caller supplied String
1177      * @param id String to fill in
1178      * @return True if the call endpoint has a peer
1179      */
1180     bool getPeerId(String& id) const;
1181 
1182     /**
1183      * Get the connected peer call id
1184      * @return Connected peer call id or empty string
1185      */
1186     String getPeerId() const;
1187 
1188     /**
1189      * Get the last connected peer call id in a caller supplied String
1190      * @param id String to fill in
1191      * @return True if the call endpoint ever had a peer
1192      */
1193     bool getLastPeerId(String& id) const;
1194 
1195     /**
1196      * Copy the current peer ID as the last connected peer ID, does nothing if not connected
1197      */
1198     void setLastPeerId();
1199 
1200     /**
1201      * Get the mutex that serializes access to this call endpoint, if any
1202      * @return Pointer to the call's mutex object or NULL
1203      */
mutex()1204     inline Mutex* mutex() const
1205 	{ return m_mutex; }
1206 
1207     /**
1208      * Get the big mutex that serializes access to all call endpoints
1209      * @return A reference to the mutex
1210      */
1211     static Mutex& commonMutex();
1212 
1213     /**
1214      * Connect the call endpoint to a peer.
1215      * @param peer Pointer to the peer call endpoint.
1216      * @param reason Text that describes connect reason.
1217      * @param notify Call disconnected() notification method on old peer
1218      * @return True if connected, false if an error occured.
1219      */
1220     bool connect(CallEndpoint* peer, const char* reason = 0, bool notify = true);
1221 
1222     /**
1223      * Disconnect from the connected peer call endpoint.
1224      * @param reason Text that describes disconnect reason.
1225      * @param notify Call disconnected() notification method on old peer
1226      * @param params Optional pointer to extra parameters for disconnect cause
1227      * @return True if the object was deleted, false if it still exists
1228      */
1229     inline bool disconnect(const char* reason = 0, bool notify = true, const NamedList* params = 0)
1230 	{ return disconnect(false,reason,notify,params); }
1231 
1232     /**
1233      * Disconnect from the connected peer call endpoint and notify old peer.
1234      * @param reason Text that describes disconnect reason.
1235      * @param params Extra parameters for disconnect cause
1236      * @return True if the object was deleted, false if it still exists
1237      */
disconnect(const char * reason,const NamedList & params)1238     inline bool disconnect(const char* reason, const NamedList& params)
1239 	{ return disconnect(false,reason,true,&params); }
1240 
1241     /**
1242      * Get a data endpoint of this object
1243      * @param type Type of data endpoint: "audio", "video", "text"
1244      * @return A pointer to the DataEndpoint object or NULL if not found
1245      */
1246     DataEndpoint* getEndpoint(const String& type = CallEndpoint::audioType()) const;
1247 
1248     /**
1249      * Get a data endpoint of this object, create if required
1250      * @param type Type of data endpoint: "audio", "video", "text"
1251      * @return A pointer to the DataEndpoint object or NULL if an error occured
1252      */
1253     DataEndpoint* setEndpoint(const String& type = CallEndpoint::audioType());
1254 
1255     /**
1256      * Clear one or all data endpoints of this object
1257      * @param type Type of data endpoint: "audio", "video", "text", NULL to clear all
1258      */
1259     void clearEndpoint(const String& type = String::empty());
1260 
1261     /**
1262      * Set a data source of this object
1263      * @param source A pointer to the new source or NULL
1264      * @param type Type of data node: "audio", "video", "text"
1265      */
1266     void setSource(DataSource* source = 0, const String& type = CallEndpoint::audioType());
1267 
1268     /**
1269      * Get a data source of this object
1270      * @param type Type of data node: "audio", "video", "text"
1271      * @return A pointer to the DataSource object or NULL
1272      */
1273     DataSource* getSource(const String& type = CallEndpoint::audioType()) const;
1274 
1275     /**
1276      * Set the data consumer of this object
1277      * @param consumer A pointer to the new consumer or NULL
1278      * @param type Type of data node: "audio", "video", "text"
1279      */
1280     void setConsumer(DataConsumer* consumer = 0, const String& type = CallEndpoint::audioType());
1281 
1282     /**
1283      * Get the data consumer of this object
1284      * @param type Type of data node: "audio", "video", "text"
1285      * @return A pointer to the DataConsumer object or NULL
1286      */
1287     DataConsumer* getConsumer(const String& type = CallEndpoint::audioType()) const;
1288 
1289     /**
1290      * Clear a data node from any slot of a DataEndpoint of this object
1291      * @param node Pointer to DataSource or DataConsumer to clear
1292      * @param type Type of data node: "audio", "video", "text"
1293      * @return True if the node was removed from at least one slot
1294      */
1295     bool clearData(DataNode* node, const String& type = CallEndpoint::audioType());
1296 
1297     /**
1298      * Return the defaul audio type "audio"
1299      * @return Return a string naming the "audio" type
1300      */
1301     static const String& audioType();
1302 
1303 protected:
1304     /**
1305      * Constructor
1306      */
1307     CallEndpoint(const char* id = 0);
1308 
1309     /**
1310      * Connect notification method.
1311      * @param reason Text that describes connect reason.
1312      */
connected(const char * reason)1313     virtual void connected(const char* reason) { }
1314 
1315     /**
1316      * Disconnect notification method.
1317      * @param final True if this disconnect was called from the destructor.
1318      * @param reason Text that describes disconnect reason.
1319      */
disconnected(bool final,const char * reason)1320     virtual void disconnected(bool final, const char* reason) { }
1321 
1322     /**
1323      * Set disconnect parameters
1324      * @param params Pointer to disconnect cause parameters, NULL to reset them
1325      */
setDisconnect(const NamedList * params)1326     virtual void setDisconnect(const NamedList* params) { }
1327 
1328     /**
1329      * Set the peer call endpoint pointer.
1330      * @param peer A pointer to the new peer or NULL.
1331      * @param reason Text describing the reason in case of disconnect.
1332      * @param notify Call notification methods - connected() or disconnected()
1333      * @param params Optional pointer to extra parameters for disconnect cause
1334      */
1335     void setPeer(CallEndpoint* peer, const char* reason = 0, bool notify = true, const NamedList* params = 0);
1336 
1337     /**
1338      * Set a foreign data endpoint in this object
1339      * @param endPoint Data endpoint to set, will replace one with same type
1340      */
1341     void setEndpoint(DataEndpoint* endPoint);
1342 
1343     /**
1344      * Set a new ID for this call endpoint
1345      * @param newId New ID to set to this call
1346      */
1347     virtual void setId(const char* newId);
1348 
1349 private:
1350     bool disconnect(bool final, const char* reason, bool notify, const NamedList* params);
1351 };
1352 
1353 /**
1354  * Module is a descendent of Plugin specialized in implementing modules
1355  * @short A Plugin that implements a module
1356  */
1357 class YATE_API Module : public Plugin, public Mutex, public MessageReceiver
1358 {
1359     YNOCOPY(Module); // no automatic copies please
1360 private:
1361     bool m_init;
1362     int m_relays;
1363     String m_type;
1364     Regexp m_filter;
1365     u_int64_t m_changed;
1366     static unsigned int s_delay;
1367 
1368 public:
1369     /**
1370      * Get a pointer to a derived class given that class name
1371      * @param name Name of the class we are asking for
1372      * @return Pointer to the requested class or NULL if this object doesn't implement it
1373      */
1374     virtual void* getObject(const String& name) const;
1375 
1376     /**
1377      * Retrieve the type of the module
1378      * @return The module's type as String
1379      */
type()1380     inline const String& type() const
1381 	{ return m_type; }
1382 
1383     /**
1384      * Mark the driver statistics "dirty" therefore triggring a delayed
1385      *  status update.
1386      */
1387     void changed();
1388 
1389     /**
1390      * Retrieve the global update notification delay
1391      * @return Update delay value in seconds
1392      */
updateDelay()1393     inline static unsigned int updateDelay()
1394 	{ return s_delay; }
1395 
1396     /**
1397      * Set the global update notification delay
1398      * @param delay New update delay value in seconds, 0 to disable
1399      */
updateDelay(unsigned int delay)1400     inline static void updateDelay(unsigned int delay)
1401 	{ s_delay = delay; }
1402 
1403     /**
1404      * Check if a debug filter is installed
1405      * @return True if debugging should be filtered
1406      */
filterInstalled()1407     inline bool filterInstalled() const
1408 	{ return !m_filter.null(); }
1409 
1410     /**
1411      * Check by filter rule if debugging should be active
1412      * @param item Value of the item to match
1413      * @return True if debugging should be activated
1414      */
1415     bool filterDebug(const String& item) const;
1416 
1417     /**
1418      * Helper function to complete just one item on a command line
1419      * @param itemList Tab separated list of possible values to complete
1420      * @param item Item to possibly insert in the list
1421      * @param partWord Partial word to complete, may be empty
1422      * @return True if the item was added to list, false if it didn't match
1423      */
1424     static bool itemComplete(String& itemList, const String& item, const String& partWord);
1425 
1426 protected:
1427     /**
1428      * IDs of the installed relays
1429      */
1430     enum {
1431 	// Module messages
1432 	Status     = 0x00000001,
1433 	Timer      = 0x00000002,
1434 	Level      = 0x00000004,
1435 	Command    = 0x00000008,
1436 	Help       = 0x00000010,
1437 	Halt       = 0x00000020,
1438 	Route	   = 0x00000040,
1439 	Stop	   = 0x00000080,
1440 	// Driver messages
1441 	Execute    = 0x00000100,
1442 	Drop       = 0x00000200,
1443 	// Channel messages
1444 	Locate     = 0x00000400,
1445 	Masquerade = 0x00000800,
1446 	Ringing    = 0x00001000,
1447 	Answered   = 0x00002000,
1448 	Tone       = 0x00004000,
1449 	Text       = 0x00008000,
1450 	Progress   = 0x00010000,
1451 	Update     = 0x00020000,
1452 	Transfer   = 0x00040000,
1453 	Control	   = 0x00080000,
1454 	// Instant messaging related
1455 	MsgExecute = 0x00100000,
1456 	// Last possible public ID
1457 	PubLast    = 0x00ffffff,
1458 	// Private messages base ID
1459 	Private    = 0x01000000
1460     } RelayID;
1461 
1462     /**
1463      * Find the name of a specific Relay ID
1464      * @param id RelayID of the message
1465      * @return Pointer to name of the message or NULL if not found
1466      */
1467     static const char* messageName(int id);
1468 
1469     /**
1470      * Find the ID or a specific Relay name
1471      * @param name Name of the Relay to search for
1472      * @return ID of the Relay, zero if not found
1473      */
relayId(const char * name)1474     static inline int relayId(const char* name)
1475 	{ return lookup(name,s_messages); }
1476 
1477     /**
1478      * Constructor
1479      * @param name Plugin name of this driver
1480      * @param type Type of the driver: "misc", "route", etc.
1481      * @param earlyInit True to attempt to initialize module before others
1482      */
1483     Module(const char* name, const char* type = 0, bool earlyInit = false);
1484 
1485     /**
1486      * Destructor
1487      */
1488     virtual ~Module();
1489 
1490     /**
1491      * This method is called to initialize the loaded module
1492      */
1493     virtual void initialize();
1494 
1495     /**
1496      * Install standard message relays
1497      */
1498     void setup();
1499 
1500     /**
1501      * Check if a specific relay ID is installed
1502      * @param id RelayID to test for
1503      * @return True if such a relay is installed
1504      */
relayInstalled(int id)1505     inline bool relayInstalled(int id) const
1506 	{ return (id & m_relays) != 0; }
1507 
1508     /**
1509      * Install a standard message relay
1510      * @param id RelayID of the new relay to create
1511      * @param priority Priority of the handler, 0 = top
1512      * @return True if installed or already was one installed
1513      */
1514     bool installRelay(int id, unsigned priority = 100);
1515 
1516     /**
1517      * Install a standard message relay
1518      * @param name Name of the relay to create, must match a RelayID
1519      * @param priority Priority of the handler, 0 = top
1520      * @return True if installed or already was one installed
1521      */
1522     bool installRelay(const char* name, unsigned priority = 100);
1523 
1524     /**
1525      * Install a custom message relay
1526      * @param id RelayID of the new relay to create
1527      * @param name Name of the custom relay to create
1528      * @param priority Priority of the handler, 0 = top
1529      * @return True if installed or already was one installed
1530      */
1531     bool installRelay(int id, const char* name, unsigned priority = 100);
1532 
1533     /**
1534      * Install a custom message relay
1535      * @param relay Custom message relay
1536      * @return True if installed, false if there was already one with same ID
1537      */
1538     bool installRelay(MessageRelay* relay);
1539 
1540     /**
1541      * Uninstall a message relay
1542      * @param relay Pointer to message relay
1543      * @param delRelay True to delete the relay after removing it
1544      * @return True if uninstalled, false if if was not present
1545      */
1546     bool uninstallRelay(MessageRelay* relay, bool delRelay = true);
1547 
1548     /**
1549      * Uninstall a message relay
1550      * @param id RelayID to uninstall, relay will be deleted
1551      * @param delRelay True to delete the relay after removing it
1552      * @return True if uninstalled, false if if was not present
1553      */
1554     bool uninstallRelay(int id, bool delRelay = true);
1555 
1556     /**
1557      * Uninstall all installed relays in preparation for unloading
1558      * @return True if all relays were uninstalled, false if something wrong
1559      */
1560     bool uninstallRelays();
1561 
1562     /**
1563      * Message receiver handler
1564      * @param msg The received message
1565      * @param id The identifier with which the relay was created
1566      * @return True to stop processing, false to try other handlers
1567      */
1568     virtual bool received(Message &msg, int id);
1569 
1570     /**
1571      * Opportunity to modify the update message
1572      * @param msg Status update message
1573      */
1574     virtual void genUpdate(Message& msg);
1575 
1576     /**
1577      * Timer message handler.
1578      * @param msg Time message
1579      */
1580     virtual void msgTimer(Message& msg);
1581 
1582     /**
1583      * Status message handler that is invoked only for matching messages.
1584      * @param msg Status message
1585      */
1586     virtual void msgStatus(Message& msg);
1587 
1588     /**
1589      * Routing message handler that is invoked for all call.route messages.
1590      * @param msg Call routing message
1591      * @return True to stop processing the message, false to try other handlers
1592      */
1593     virtual bool msgRoute(Message& msg);
1594 
1595     /**
1596      * Handler for special commands and line completion requests.
1597      * By default it calls @ref commandExecute() or @ref commandComplete().
1598      * @param msg Command message
1599      * @return True to stop processing the message, false to try other handlers
1600      */
1601     virtual bool msgCommand(Message& msg);
1602 
1603     /**
1604      * Build the module identification part of the status answer
1605      * @param str String variable to fill up
1606      */
1607     virtual void statusModule(String& str);
1608 
1609     /**
1610      * Build the parameter reporting part of the status answer
1611      * @param str String variable to fill up
1612      */
1613     virtual void statusParams(String& str);
1614 
1615     /**
1616      * Build the details reporting part of the status answer
1617      * @param str String variable to fill up
1618      */
1619     virtual void statusDetail(String& str);
1620 
1621     /**
1622      * Execute a specific command
1623      * @param retVal String to append the textual command output to
1624      * @param line Command line to attempt to execute
1625      * @return True to stop processing the message, false to try other handlers
1626      */
1627     virtual bool commandExecute(String& retVal, const String& line);
1628 
1629     /**
1630      * Complete a command line
1631      * @param msg Message to return completion into
1632      * @param partLine Partial line to complete, excluding the last word
1633      * @param partWord Partial word to complete
1634      * @return True to stop processing the message, false to try other handlers
1635      */
1636     virtual bool commandComplete(Message& msg, const String& partLine, const String& partWord);
1637 
1638     /**
1639      * Set the local debugging level
1640      * @param msg Debug setting message
1641      * @param target String to match for local settings
1642      */
1643     virtual bool setDebug(Message& msg, const String& target);
1644 
1645 private:
1646     Module(); // no default constructor please
1647     static TokenDict s_messages[];
1648     ObjList m_relayList;
1649 };
1650 
1651 /**
1652  * A class that holds common channel related features (a.k.a. call leg)
1653  * @short An abstract communication channel
1654  */
1655 class YATE_API Channel : public CallEndpoint, public DebugEnabler, public MessageNotifier
1656 {
1657     friend class Driver;
1658     friend class Router;
1659     YNOCOPY(Channel); // no automatic copies please
1660 private:
1661     NamedList m_parameters;
1662     NamedList* m_chanParams;     // Channel parameters to be set in all messages
1663     Driver* m_driver;
1664     bool m_outgoing;
1665     u_int64_t m_timeout;
1666     u_int64_t m_maxcall;
1667     u_int64_t m_maxPDD;          // Timeout while waiting for some progress on outgoing calls
1668     u_int64_t m_dtmfTime;
1669     unsigned int m_toutAns;
1670     unsigned int m_dtmfSeq;
1671     String m_dtmfText;
1672     String m_dtmfDetected;
1673 
1674 protected:
1675     String m_status;
1676     String m_address;
1677     String m_targetid;
1678     String m_billid;
1679     bool m_answered;
1680 
1681 public:
1682     /**
1683      * Destructor
1684      */
1685     virtual ~Channel();
1686 
1687     /**
1688      * Get a pointer to a derived class given that class name
1689      * @param name Name of the class we are asking for
1690      * @return Pointer to the requested class or NULL if this object doesn't implement it
1691      */
1692     virtual void* getObject(const String& name) const;
1693 
1694     /**
1695      * Get the big mutex that serializes access to all disconnect parameter lists
1696      * @return A reference to the mutex
1697      */
1698     static Mutex& paramMutex();
1699 
1700     /**
1701      * Put channel variables into a message
1702      * @param msg Message to fill in
1703      * @param minimal True to fill in only a minimum of parameters
1704      */
1705     virtual void complete(Message& msg, bool minimal = false) const;
1706 
1707     /**
1708      * Create a filled notification message
1709      * @param name Name of the message to create
1710      * @param minimal Set to true to fill in only a minimum of parameters
1711      * @param data Set the channel as message data
1712      * @return A new allocated and parameter filled message
1713      */
1714     Message* message(const char* name, bool minimal = false, bool data = false);
1715 
1716     /**
1717      * Create a filled notification message, copy some parameters from another message
1718      * @param name Name of the message to create
1719      * @param original Parameters to copy from, can be NULL
1720      * @param params Comma separated list of parameters to copy,
1721      *  if NULL will be taken from the "copyparams" parameter of original
1722      * @param minimal Set to true to fill in only a minimum of parameters
1723      * @param data Set the channel as message data
1724      * @return A new allocated and parameter filled message
1725      */
1726     Message* message(const char* name, const NamedList* original, const char* params = 0, bool minimal = false, bool data = false);
1727 
1728     /**
1729      * Create a filled notification message, copy some parameters from another message
1730      * @param name Name of the message to create
1731      * @param original Parameters to copy from
1732      * @param params Comma separated list of parameters to copy,
1733      *  if NULL will be taken from the "copyparams" parameter of original
1734      * @param minimal Set to true to fill in only a minimum of parameters
1735      * @param data Set the channel as message data
1736      * @return A new allocated and parameter filled message
1737      */
1738     inline Message* message(const char* name, const NamedList& original, const char* params = 0, bool minimal = false, bool data = false)
1739 	{ return message(name,&original,params,minimal,data); }
1740 
1741     /**
1742      * Notification on remote call making some progress, not enabled by default
1743      * @param msg Notification message
1744      * @return True to stop processing the message, false to let it flow
1745      */
1746     virtual bool msgProgress(Message& msg);
1747 
1748     /**
1749      * Notification on remote ringing
1750      * @param msg Notification message
1751      * @return True to stop processing the message, false to let it flow
1752      */
1753     virtual bool msgRinging(Message& msg);
1754 
1755     /**
1756      * Notification on remote answered. Note that the answered flag will be set
1757      * @param msg Notification message
1758      * @return True to stop processing the message, false to let it flow
1759      */
1760     virtual bool msgAnswered(Message& msg);
1761 
1762     /**
1763      * Notification on remote tone(s)
1764      * @param msg Notification message
1765      * @param tone Pointer to the received tone(s)
1766      * @return True to stop processing the message, false to let it flow
1767      */
1768     virtual bool msgTone(Message& msg, const char* tone);
1769 
1770     /**
1771      * Notification on remote text messaging (sms)
1772      * @param msg Notification message
1773      * @param text Pointer to the received text
1774      * @return True to stop processing the message, false to let it flow
1775      */
1776     virtual bool msgText(Message& msg, const char* text);
1777 
1778     /**
1779      * Notification on current call drop request
1780      * @param msg Notification message
1781      * @param reason Pointer to drop reason text or NULL if none provided
1782      * @return True if initiated call drop, false if failed
1783      */
1784     virtual bool msgDrop(Message& msg, const char* reason);
1785 
1786     /**
1787      * Notification on native transfer request
1788      * @param msg Notification message
1789      * @return True to stop processing the message, false to let it flow
1790      */
1791     virtual bool msgTransfer(Message& msg);
1792 
1793     /**
1794      * Notification on call parameters update request
1795      * @param msg Notification message
1796      * @return True to stop processing the message, false to let it flow
1797      */
1798     virtual bool msgUpdate(Message& msg);
1799 
1800     /**
1801      * Notification on message masquerade as channel request
1802      * @param msg Message already modified to masquerade as this channel
1803      * @return True to stop processing the message, false to masquerade it
1804      */
1805     virtual bool msgMasquerade(Message& msg);
1806 
1807     /**
1808      * Status message handler that is invoked only for messages to this channel
1809      * @param msg Status message
1810      */
1811     virtual void msgStatus(Message& msg);
1812 
1813     /**
1814      * Control message handler that is invoked only for messages to this channel
1815      * @param msg Control message
1816      * @return True to stop processing the message, false to let it flow
1817      */
1818     virtual bool msgControl(Message& msg);
1819 
1820     /**
1821      * Timer check method, by default handles channel timeouts
1822      * @param msg Timer message
1823      * @param tmr Current time against which timers are compared
1824      */
1825     virtual void checkTimers(Message& msg, const Time& tmr);
1826 
1827     /**
1828      * Notification on progress of prerouting incoming call
1829      * @param msg Notification call.preroute message just after being dispatched
1830      * @param handled True if a handler claimed having handled prerouting
1831      * @return True to continue with the call, false to abort the route
1832      */
1833     virtual bool callPrerouted(Message& msg, bool handled);
1834 
1835     /**
1836      * Notification on progress of routing incoming call
1837      * @param msg Notification call.route message just after being dispatched
1838      * @return True to continue with the call, false to abort the route
1839      */
1840     virtual bool callRouted(Message& msg);
1841 
1842     /**
1843      * Notification on success of incoming call
1844      * @param msg Notification call.execute message just after being dispatched
1845      */
1846     virtual void callAccept(Message& msg);
1847 
1848     /**
1849      * Notification on failure of incoming call
1850      * @param error Standard error keyword
1851      * @param reason Textual failure reason
1852      * @param msg Pointer to message causing the rejection, if any
1853      */
1854     virtual void callRejected(const char* error, const char* reason = 0, const Message* msg = 0);
1855 
1856     /**
1857      * Common processing after connecting the outgoing call, should be called
1858      *  from Driver's msgExecute()
1859      * @param msg Notification call.execute message while being dispatched
1860      */
1861     virtual void callConnect(Message& msg);
1862 
1863     /**
1864      * Set the local debugging level
1865      * @param msg Debug setting message
1866      */
1867     virtual bool setDebug(Message& msg);
1868 
1869     /**
1870      * Get the current status of the channel
1871      * This method is thread safe
1872      * @param buf Destination buffer
1873      * @param append True to append to destination buffer, false to set (replace contents)
1874      * @return Destination buffer reference
1875      */
1876     inline String& getStatus(String& buf, bool append = true) const {
1877 	    Lock lck(chanDataMutex());
1878 	    if (append)
1879 		buf += m_status;
1880 	    else
1881 		buf = m_status;
1882 	    return buf;
1883 	}
1884 
1885     /**
1886      * Get the current status of the channel. Add it in list parameters
1887      * This method is thread safe
1888      * @param list Destination list
1889      * @param param Parameter name
1890      * @param append True to append parameter to list, false to replace
1891      */
1892     inline void putStatus(NamedList& list, const char* param = "status", bool append = true) const {
1893 	    NamedString* ns = new NamedString(param);
1894 	    getStatus(*ns);
1895 	    if (append)
1896 		list.addParam(ns);
1897 	    else
1898 		list.setParam(ns);
1899 	}
1900 
1901     /**
1902      * Get the current link address of the channel
1903      * @return The protocol dependent address as String
1904      */
address()1905     inline const String& address() const
1906 	{ return m_address; }
1907 
1908     /**
1909      * Get the direction of the channel
1910      * @return True if the channel is an outgoing call (generated locally)
1911      */
isOutgoing()1912     inline bool isOutgoing() const
1913 	{ return m_outgoing; }
1914 
1915     /**
1916      * Get the direction of the channel
1917      * @return True if the channel is an incoming call (generated remotely)
1918      */
isIncoming()1919     inline bool isIncoming() const
1920 	{ return !m_outgoing; }
1921 
1922     /**
1923      * Check if the call was answered or not
1924      * @return True if the call was answered
1925      */
isAnswered()1926     inline bool isAnswered() const
1927 	{ return m_answered; }
1928 
1929     /**
1930      * Get the direction of the channel as string
1931      * @return "incoming" or "outgoing" according to the direction
1932      */
1933     const char* direction() const;
1934 
1935     /**
1936      * Get the driver of this channel
1937      * @return Pointer to this channel's driver
1938      */
driver()1939     inline Driver* driver() const
1940 	{ return m_driver; }
1941 
1942     /**
1943      * Get the time this channel will time out
1944      * @return Timeout time or zero if no timeout
1945      */
timeout()1946     inline u_int64_t timeout() const
1947 	{ return m_timeout; }
1948 
1949     /**
1950      * Set the time this channel will time out
1951      * @param tout New timeout time or zero to disable
1952      */
timeout(u_int64_t tout)1953     inline void timeout(u_int64_t tout)
1954 	{ m_timeout = tout; }
1955 
1956     /**
1957      * Get the time this channel will time out on outgoing calls
1958      * @return Timeout time or zero if no timeout
1959      */
maxcall()1960     inline u_int64_t maxcall() const
1961 	{ return m_maxcall; }
1962 
1963     /**
1964      * Set the time this channel will time out on outgoing calls
1965      * @param tout New timeout time or zero to disable
1966      */
maxcall(u_int64_t tout)1967     inline void maxcall(u_int64_t tout)
1968 	{ m_maxcall = tout; }
1969 
1970     /**
1971      * Set the time this channel will time out on outgoing calls
1972      * @param msg Reference of message possibly holding "maxcall" parameter
1973      * @param defTout Default timeout to apply, negative to not alter
1974      */
1975     inline void setMaxcall(const Message& msg, int defTout = -1)
1976 	{ setMaxcall(&msg,defTout); }
1977 
1978     /**
1979      * Set the time this channel will time out on outgoing calls
1980      * @param msg Pointer to message possibly holding "maxcall" parameter
1981      * @param defTout Default timeout to apply, negative to not alter
1982      */
1983     void setMaxcall(const Message* msg, int defTout = -1);
1984 
1985     /**
1986      * Get the time this channel will time out while waiting for some progress
1987      *  on outgoing calls
1988      * @return Timeout time or zero if no timeout
1989      */
maxPDD()1990     inline u_int64_t maxPDD() const
1991 	{ return m_maxPDD; }
1992 
1993     /**
1994      * Set the time this channel will time out while waiting for some progress
1995      *  on outgoing calls
1996      * @param tout New timeout time or zero to disable
1997      */
maxPDD(u_int64_t tout)1998     inline void maxPDD(u_int64_t tout)
1999 	{ m_maxPDD = tout; }
2000 
2001     /**
2002      * Set the time this channel will time out while waiting for some progress
2003      *  on outgoing calls
2004      * @param msg Reference of message possibly holding "maxpdd" parameter
2005      */
2006     void setMaxPDD(const Message& msg);
2007 
2008     /**
2009      * Get the connected channel identifier.
2010      * @return A String holding the unique channel id of the target or an empty
2011      *  string if this channel is not connected to a target.
2012      */
targetid()2013     inline const String& targetid() const
2014 	{ return m_targetid; }
2015 
2016     /**
2017      * Get the billing identifier.
2018      * @return An identifier of the call or account that will be billed for
2019      *  calls made by this channel.
2020      */
billid()2021     inline const String& billid() const
2022 	{ return m_billid; }
2023 
2024     /**
2025      * Add the channel to the parent driver list
2026      * This method must be called exactly once after the object is fully constructed
2027      */
2028     void initChan();
2029 
2030     /**
2031      * Start a routing thread for this channel, dereference dynamic channels
2032      * @param msg Pointer to message to route, typically a "call.route", will be
2033      *  destroyed after routing fails or completes
2034      * @return True if routing thread started successfully, false if failed
2035      */
2036     bool startRouter(Message* msg);
2037 
2038     /**
2039      * Allocate an unique (per engine run) call ID
2040      * @return Unique call ID number
2041      */
2042     static unsigned int allocId();
2043 
2044     /**
2045      * Enable or disable debugging according to driver's filter rules
2046      * @param item Value of the item to match
2047      */
2048     void filterDebug(const String& item);
2049 
2050     /**
2051      * Get the disconnect parameters list
2052      * @return Constant reference to disconnect parameters
2053      */
parameters()2054     inline const NamedList& parameters() const
2055 	{ return m_parameters; }
2056 
2057     /**
2058      * Set channel parameters
2059      * @param list List of parameters
2060      * @param in True if set for incoming channel (called for (pre)routed/rejected,accepted)
2061      */
2062     inline void setChanParams(const NamedList& list, bool in = false) {
2063 	    const String& pref = in ? list[YSTRING("ichanparams-prefix")] : list[YSTRING("chanparams-prefix")];
2064 	    if (!pref)
2065 		return;
2066 	    Lock lck(paramMutex());
2067 	    if (!m_chanParams)
2068 		m_chanParams = new NamedList("");
2069 	    m_chanParams->copySubParams(list,pref,true,true);
2070 	}
2071 
2072     /**
2073      * Copy channel parameters
2074      * @param list Destination list
2075      */
copyChanParams(NamedList & list)2076     inline void copyChanParams(NamedList& list) const {
2077 	    if (!m_chanParams)
2078 		return;
2079 	    Lock lck(paramMutex());
2080 	    list.copyParams(*m_chanParams);
2081 	}
2082 
2083     /**
2084      * Notification for dispatched messages
2085      * @param msg Message that was dispatched
2086      * @param handled Result of handling the message
2087      */
2088     virtual void dispatched(const Message& msg, bool handled);
2089 
2090 protected:
2091     /**
2092      * Constructor
2093      */
2094     Channel(Driver* driver, const char* id = 0, bool outgoing = false);
2095 
2096     /**
2097      * Alternate constructor provided for convenience
2098      */
2099     Channel(Driver& driver, const char* id = 0, bool outgoing = false);
2100 
2101     /**
2102      * Perform destruction time cleanup. You can call this method earlier
2103      *  if destruction is to be postponed.
2104      */
2105     void cleanup();
2106 
2107     /**
2108      * Remove the channel from the parent driver list
2109      */
2110     void dropChan();
2111 
2112     /**
2113      * This method is overriden to safely remove the channel from the parent
2114      *  driver list before actually destroying the channel.
2115      */
2116     virtual void zeroRefs();
2117 
2118     /**
2119      * Connect notification method.
2120      * @param reason Text that describes connect reason.
2121      */
2122     virtual void connected(const char* reason);
2123 
2124     /**
2125      * Disconnect notification method.
2126      * @param final True if this disconnect was called from the destructor.
2127      * @param reason Text that describes disconnect reason.
2128      */
2129     virtual void disconnected(bool final, const char* reason);
2130 
2131     /**
2132      * Set disconnect parameters
2133      * @param params Pointer to disconnect cause parameters, NULL to reset them
2134      */
2135     virtual void setDisconnect(const NamedList* params);
2136 
2137     /**
2138      * Notification after chan.disconnected handling
2139      * @param msg The chan.disconnected message
2140      * @param handled True if the message was handled
2141      */
2142     virtual void endDisconnect(const Message& msg, bool handled);
2143 
2144     /**
2145      * Set a new ID for this channel
2146      * @param newId New ID to set to this channel
2147      */
2148     virtual void setId(const char* newId);
2149 
2150     /**
2151      * Create a properly populated chan.disconnect message
2152      * @param reason Channel disconnect reason if available
2153      * @return A new allocated and parameter filled chan.disconnected message
2154      */
2155     virtual Message* getDisconnect(const char* reason);
2156 
2157     /**
2158      * Set the current status of the channel.
2159      * Note that a value of "answered" will set the answered flag
2160      * @param newstat The new status as String
2161      */
2162     void status(const char* newstat);
2163 
2164     /**
2165      * Retrieve Channel status
2166      * This method is not thread safe
2167      * @return Channel status
2168      */
getStatus()2169     inline const String& getStatus() const
2170 	{ return m_status; }
2171 
2172     /**
2173      * Build the parameter reporting part of the status answer
2174      * @param str String variable to fill up
2175      */
2176     virtual void statusParams(String& str);
2177 
2178     /**
2179      * Set the current direction of the channel
2180      * @param outgoing True if this is an outgoing call channel
2181      */
2182     inline void setOutgoing(bool outgoing = true)
2183 	{ m_outgoing = outgoing; }
2184 
2185     /**
2186      * Add sequence number to chan.dtmf message, check for duplicates
2187      * @param msg chan.dtmf message to apply sequence number
2188      * @return True if the message is a duplicate (same tone, different method)
2189      */
2190     bool dtmfSequence(Message& msg);
2191 
2192     /**
2193      * Add sequence number to chan.dtmf and enqueue it, delete if duplicate
2194      * @param msg chan.dtmf message to sequence and enqueue
2195      * @return True if the message was enqueued, false if was a duplicate
2196      */
2197     bool dtmfEnqueue(Message* msg);
2198 
2199     /**
2200      * Attempt to install an override data source to send DTMF inband.
2201      * Needs a tone generator module capable to override with "tone/dtmfstr/xyz"
2202      * @param tone Pointer to the tone sequence to send
2203      * @return True on success
2204      */
2205     bool dtmfInband(const char* tone);
2206 
2207     /**
2208      * Attempt to install a data sniffer to detect inband tones
2209      * Needs a tone detector module capable of attaching sniffer consumers.
2210      * @param sniffer Name of the sniffer to install, default will detect all tones
2211      * @return True on success
2212      */
2213     bool toneDetect(const char* sniffer = 0);
2214 
2215     /**
2216      * Get the disconnect parameters list
2217      * @return Reference to disconnect parameters
2218      */
parameters()2219     inline NamedList& parameters()
2220 	{ return m_parameters; }
2221 
2222 private:
2223     void init();
2224     Channel(); // no default constructor please
2225     static Mutex s_chanDataMutex;
2226     // Just in case we are going to (re)move the channel data mutex!
chanDataMutex()2227     static inline Mutex* chanDataMutex()
2228 	{ return &s_chanDataMutex; }
2229 };
2230 
2231 /**
2232  * Driver is a module specialized for implementing channel drivers
2233  * @short A Channel driver module
2234  */
2235 class YATE_API Driver : public Module
2236 {
2237     friend class Router;
2238     friend class Channel;
2239 
2240 private:
2241     bool m_init;
2242     bool m_varchan;
2243     String m_prefix;
2244     ObjList m_chans;
2245     int m_routing;
2246     int m_routed;
2247     int m_total;
2248     unsigned int m_nextid;
2249     int m_timeout;
2250     int m_maxroute;
2251     int m_maxchans;
2252     int m_chanCount;
2253     bool m_dtmfDups;
2254     volatile bool m_doExpire;
2255 
2256 public:
2257     /**
2258      * Get a pointer to a derived class given that class name
2259      * @param name Name of the class we are asking for
2260      * @return Pointer to the requested class or NULL if this object doesn't implement it
2261      */
2262     virtual void* getObject(const String& name) const;
2263 
2264     /**
2265      * Retrieve the prefix that is used as base for all channels
2266      * @return The driver's prefix
2267      */
prefix()2268     inline const String& prefix() const
2269 	{ return m_prefix; }
2270 
2271     /**
2272      * Check if this driver is for dynamic (variable number) channels
2273      * @return True if the channels are dynamic, false for fixed
2274      */
varchan()2275     inline bool varchan() const
2276 	{ return m_varchan; }
2277 
2278     /**
2279      * Get the list of channels of this driver
2280      * @return A reference to the channel list
2281      */
channels()2282     inline ObjList& channels()
2283 	{ return m_chans; }
2284 
2285     /**
2286      * Find a channel by id
2287      * @param id Unique identifier of the channel to find
2288      * @return Pointer to the channel or NULL if not found
2289      */
2290     virtual Channel* find(const String& id) const;
2291 
2292     /**
2293      * Check if the driver is actively used.
2294      * @return True if the driver is in use, false if should be ok to restart
2295      */
2296     virtual bool isBusy() const;
2297 
2298     /**
2299      * Drop all current channels
2300      * @param msg Notification message
2301      */
2302     virtual void dropAll(Message &msg);
2303 
2304     /**
2305      * Check if new connections can be accepted
2306      * @param routers Set to true to check routing threads for incoming connections
2307      * @return True if at least one new connection can be accepted, false if not
2308      */
2309     virtual bool canAccept(bool routers = true);
2310 
2311     /**
2312      * Check if new incoming connections can be routed
2313      * @return True if at least one new connection can be routed, false if not
2314      */
2315     virtual bool canRoute();
2316 
2317     /**
2318      * Get the next unique numeric id from a sequence
2319      * @return A driver unique number that increments by 1 at each call
2320      */
2321     unsigned int nextid();
2322 
2323     /**
2324      * Get the current (last used) unique numeric id from a sequence
2325      * @return The driver unique number
2326      */
lastid()2327     inline unsigned int lastid() const
2328 	{ return m_nextid; }
2329 
2330     /**
2331      * Get the default driver timeout
2332      * @return Timeout value in milliseconds
2333      */
timeout()2334     inline int timeout() const
2335 	{ return m_timeout; }
2336 
2337     /**
2338      * Get the number of calls currently in the routing stage
2339      * @return Number of router threads currently running
2340      */
routing()2341     inline int routing() const
2342 	{ return m_routing; }
2343 
2344     /**
2345      * Get the number of calls successfully routed
2346      * @return Number of calls that have gone past the routing stage
2347      */
routed()2348     inline int routed() const
2349 	{ return m_routed; }
2350 
2351     /**
2352      * Get the total number of calls ever created
2353      * @return Number of channels ever created for this driver
2354      */
total()2355     inline int total() const
2356 	{ return m_total; }
2357 
2358     /**
2359      * Get the number of running channels
2360      * @return Number of channels running at this time
2361      */
chanCount()2362     inline int chanCount() const
2363 	{ return m_chanCount; }
2364 
2365     /**
2366      * Get the maximum number of running channels for this driver
2367      * @return Maximum number of calls to run simultaneously, zero to accept all
2368      */
maxChans()2369     inline int maxChans() const
2370 	{ return m_maxchans; }
2371 
2372 protected:
2373     /**
2374      * Constructor
2375      * @param name Plugin name of this driver
2376      * @param type Type of the driver: "fixchans", "varchans", etc.
2377      */
2378     Driver(const char* name, const char* type = 0);
2379 
2380     /**
2381      * This method is called to initialize the loaded module
2382      */
2383     virtual void initialize();
2384 
2385     /**
2386      * Install standard message relays and set up the prefix
2387      * @param prefix Prefix to use with channels of this driver
2388      * @param minimal Install just a minimal set of message relays
2389      */
2390     void setup(const char* prefix = 0, bool minimal = false);
2391 
2392     /**
2393      * Message receiver handler
2394      * @param msg The received message
2395      * @param id The identifier with which the relay was created
2396      * @return True to stop processing, false to try other handlers
2397      */
2398     virtual bool received(Message &msg, int id);
2399 
2400     /**
2401      * Opportunity to modify the update message
2402      * @param msg Status update message
2403      */
2404     virtual void genUpdate(Message& msg);
2405 
2406     /**
2407      * Check if driver owns a client line (registered to an external server)
2408      * @param line Name of the line to check
2409      * @return True if this driver owns  line with the specified name
2410      *
2411      */
2412     virtual bool hasLine(const String& line) const;
2413 
2414     /**
2415      * Routing message handler. The default implementation routes to this
2416      *  driver if it owns a line named in the "account" or "line" parameter.
2417      * @param msg Call routing message
2418      * @return True to stop processing the message, false to try other handlers
2419      */
2420     virtual bool msgRoute(Message& msg);
2421 
2422     /**
2423      * Create an outgoing calling channel
2424      * @param msg Call execute message
2425      * @param dest Destination of the new call
2426      * @return True if outgoing call was created
2427      */
2428     virtual bool msgExecute(Message& msg, String& dest) = 0;
2429 
2430     /**
2431      * Complete a command line
2432      * @param msg Message to return completion into
2433      * @param partLine Partial line to complete, excluding the last word
2434      * @param partWord Partial word to complete
2435      * @return True to stop processing the message, false to try other handlers
2436      */
2437     virtual bool commandComplete(Message& msg, const String& partLine, const String& partWord);
2438 
2439     /**
2440      * Build the module identification part of the status answer
2441      * @param str String variable to fill up
2442      */
2443     virtual void statusModule(String& str);
2444 
2445     /**
2446      * Build the parameter reporting part of the status answer
2447      * @param str String variable to fill up
2448      */
2449     virtual void statusParams(String& str);
2450 
2451     /**
2452      * Build the channel list part of the status answer
2453      * @param str String variable to fill up
2454      */
2455     virtual void statusDetail(String& str);
2456 
2457     /**
2458      * Set the local debugging level
2459      * @param msg Debug setting message
2460      * @param target String to match for local settings
2461      */
2462     virtual bool setDebug(Message& msg, const String& target);
2463 
2464     /**
2465      * Load the global limits from the main config file
2466      */
2467     virtual void loadLimits();
2468 
2469     /**
2470      * Module is able to simulate a call without generating anything at protocol layer
2471      * @return True if module is able
2472      */
canStopCall()2473     virtual bool canStopCall() const
2474 	{ return false; }
2475 
2476     /**
2477      * Set if this driver is for dynamic (variable number) channels
2478      * @param variable True if the channels are dynamic, false for fixed
2479      */
varchan(bool variable)2480     inline void varchan(bool variable)
2481 	{ m_varchan = variable; }
2482 
2483     /**
2484      * Set the default driver timeout
2485      * @param tout New timeout in milliseconds or zero to disable
2486      */
timeout(int tout)2487     inline void timeout(int tout)
2488 	{ m_timeout = tout; }
2489 
2490     /**
2491      * Set the maximum number of routing messages for this driver
2492      * @param ncalls Number of calls to route simultaneously, zero to accept all
2493      */
maxRoute(int ncalls)2494     inline void maxRoute(int ncalls)
2495 	{ m_maxroute = ncalls; }
2496 
2497     /**
2498      * Set the maximum number of running channels for this driver
2499      * @param ncalls Number of calls to run simultaneously, zero to accept all
2500      */
maxChans(int ncalls)2501     inline void maxChans(int ncalls)
2502 	{ m_maxchans = ncalls; }
2503 
2504     /**
2505      * Set the DTMF duplicates allowed flag
2506      * @param duplicates True to allow DTMF duplicate messages
2507      */
dtmfDups(bool duplicates)2508     inline void dtmfDups(bool duplicates)
2509 	{ m_dtmfDups = duplicates; }
2510 
2511 private:
2512     Driver(); // no default constructor please
2513 };
2514 
2515 /**
2516  * Asynchronous call routing thread
2517  * @short Call routing thread
2518  */
2519 class YATE_API Router : public Thread
2520 {
2521     YNOCOPY(Router); // no automatic copies please
2522 private:
2523     Driver* m_driver;
2524     String m_id;
2525     Message* m_msg;
2526 
2527 public:
2528     /**
2529      * Constructor - creates a new routing thread
2530      * @param driver Pointer to the driver that asked for routing
2531      * @param id Unique identifier of the channel being routed
2532      * @param msg Pointer to an already filled message
2533      */
2534     Router(Driver* driver, const char* id, Message* msg);
2535 
2536     /**
2537      * Main thread running method
2538      */
2539     virtual void run();
2540 
2541     /**
2542      * Actual routing method
2543      * @return True if call was successfully routed
2544      */
2545     virtual bool route();
2546 
2547     /**
2548      * Thread cleanup handler
2549      */
2550     virtual void cleanup();
2551 
2552 protected:
2553     /**
2554      * Get the routed channel identifier
2555      * @return Unique id of the channel being routed
2556      */
id()2557     const String& id() const
2558 	{ return m_id; }
2559 };
2560 
2561 /**
2562  * This helper class holds generic account parameters that are applied to calls
2563  * @short Settings for an account handling calls
2564  */
2565 class YATE_API CallAccount
2566 {
2567     YNOCOPY(CallAccount);
2568 private:
2569     Mutex* m_mutex;
2570     NamedList m_inbParams;
2571     NamedList m_outParams;
2572     NamedList m_regParams;
2573 
2574 public:
2575     /**
2576      * Make a copy of the inbound and outbound parameter templates
2577      * @param params List of parameters to copy from
2578      */
2579     void pickAccountParams(const NamedList& params);
2580 
2581 
2582     /**
2583      * Patch the inbound call parameters
2584      * @param params List of parameters to be patched
2585      */
2586     void setInboundParams(NamedList& params);
2587 
2588     /**
2589      * Patch the outbound call parameters
2590      * @param params List of parameters to be patched
2591      */
2592     void setOutboundParams(NamedList& params);
2593 
2594     /**
2595      * Patch registration parameters
2596      * @param params List of parameters to be patched
2597      */
2598     void setRegisterParams(NamedList& params);
2599 
2600     /**
2601      * Accessor for the inbound call parameters list
2602      * @return Reference to the inbound call parameters
2603      */
inboundParams()2604     inline const NamedList& inboundParams() const
2605 	{ return m_inbParams; }
2606 
2607     /**
2608      * Accessor for the outbound call parameters list
2609      * @return Reference to the outbound call parameters
2610      */
outboundParams()2611     inline const NamedList& outboundParams() const
2612 	{ return m_outParams; }
2613 
2614     /**
2615      * Accessor for the registration parameters list
2616      * @return Reference to the registration parameters
2617      */
registerParams()2618     inline const NamedList& registerParams() const
2619 	{ return m_regParams; }
2620 
2621 protected:
2622     /**
2623      * Constructor
2624      * @param mutex The mutex that is used to lock object's variables
2625      */
CallAccount(Mutex * mutex)2626     inline CallAccount(Mutex* mutex)
2627 	: m_mutex(mutex), m_inbParams(""), m_outParams(""), m_regParams("")
2628 	{ }
2629 };
2630 
2631 /**
2632  * Find if a string appears to be an E164 phone number
2633  * @param str String to check
2634  * @return True if str appears to be a valid E164 number
2635  */
2636 YATE_API bool isE164(const char* str);
2637 
2638 }; // namespace TelEngine
2639 
2640 #endif /* __YATEPHONE_H */
2641 
2642 /* vi: set ts=8 sw=4 sts=4 noet: */
2643