1 /**
2  * yatengine.h
3  * This file is part of the YATE Project http://YATE.null.ro
4  *
5  * Engine, plugins and messages 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 __YATENGINE_H
23 #define __YATENGINE_H
24 
25 #ifndef __cplusplus
26 #error C++ is required
27 #endif
28 
29 #include <yateclass.h>
30 
31 /**
32  * Holds all Telephony Engine related classes.
33  */
34 namespace TelEngine {
35 
36 /**
37  * A class for parsing and quickly accessing INI style configuration files
38  * @short Configuration file handling
39  */
40 class YATE_API Configuration : public String
41 {
42     YNOCOPY(Configuration); // no automatic copies please
43 public:
44     /**
45      * Create an empty configuration
46      */
47     Configuration();
48 
49     /**
50      * Create a configuration from a file
51      * @param filename Name of file to initialize from
52      * @param warn True to warn if the configuration could not be loaded
53      */
54     explicit Configuration(const char* filename, bool warn = true);
55 
56     /**
57      * Assignment from string operator
58      */
59     inline Configuration& operator=(const String& value)
60 	{ String::operator=(value); return *this; }
61 
62     /**
63      * Get the number of sections
64      * @return Count of sections
65      */
sections()66     inline unsigned int sections() const
67 	{ return m_sections.length(); }
68 
69     /**
70      * Get the number of non null sections
71      * @return Count of sections
72      */
count()73     inline unsigned int count() const
74 	{ return m_sections.count(); }
75 
76     /**
77      * Retrieve an entire section
78      * @param index Index of the section
79      * @return The section's content or NULL if no such section
80      */
81     NamedList* getSection(unsigned int index) const;
82 
83     /**
84      * Retrieve an entire section
85      * @param sect Name of the section
86      * @return The section's content or NULL if no such section
87      */
88     NamedList* getSection(const String& sect) const;
89 
90     /**
91      * Locate a key/value pair in the section.
92      * @param sect Name of the section
93      * @param key Name of the key in section
94      * @return A pointer to the key/value pair or NULL.
95      */
96     NamedString* getKey(const String& sect, const String& key) const;
97 
98     /**
99      * Retrieve the value of a key in a section.
100      * @param sect Name of the section
101      * @param key Name of the key in section
102      * @param defvalue Default value to return if not found
103      * @return The string contained in the key or the default
104      */
105     const char* getValue(const String& sect, const String& key, const char* defvalue = 0) const;
106 
107     /**
108      * Retrieve the numeric value of a key in a section.
109      * @param sect Name of the section
110      * @param key Name of the key in section
111      * @param defvalue Default value to return if not found
112      * @param minvalue Minimum value allowed for the parameter
113      * @param maxvalue Maximum value allowed for the parameter
114      * @param clamp Control the out of bound values: true to adjust to the nearest
115      *  bound, false to return the default value
116      * @return The number contained in the key or the default
117      */
118     int getIntValue(const String& sect, const String& key, int defvalue = 0,
119 	int minvalue = INT_MIN, int maxvalue = INT_MAX, bool clamp = true) const;
120 
121     /**
122      * Retrieve the numeric value of a key in a section trying first a table lookup.
123      * @param sect Name of the section
124      * @param key Name of the key in section
125      * @param tokens A pointer to an array of tokens to try to lookup
126      * @param defvalue Default value to return if not found
127      * @return The number contained in the key or the default
128      */
129     int getIntValue(const String& sect, const String& key, const TokenDict* tokens, int defvalue = 0) const;
130 
131     /**
132      * Retrieve the 64-bit numeric value of a key in a section.
133      * @param sect Name of the section
134      * @param key Name of the key in section
135      * @param defvalue Default value to return if not found
136      * @param minvalue Minimum value allowed for the parameter
137      * @param maxvalue Maximum value allowed for the parameter
138      * @param clamp Control the out of bound values: true to adjust to the nearest
139      *  bound, false to return the default value
140      * @return The number contained in the key or the default
141      */
142     int64_t getInt64Value(const String& sect, const String& key, int64_t defvalue = 0,
143 	int64_t minvalue = LLONG_MIN, int64_t maxvalue = LLONG_MAX, bool clamp = true) const;
144 
145     /**
146      * Retrieve the floating point value of a key in a section.
147      * @param sect Name of the section
148      * @param key Name of the key in section
149      * @param defvalue Default value to return if not found
150      * @return The numeric value contained in the key or the default
151      */
152     double getDoubleValue(const String& sect, const String& key, double defvalue = 0.0) const;
153 
154     /**
155      * Retrieve the boolean value of a key in a section.
156      * @param sect Name of the section
157      * @param key Name of the key in section
158      * @param defvalue Default value to return if not found
159      * @return The boolean value contained in the key or the default
160      */
161     bool getBoolValue(const String& sect, const String& key, bool defvalue = false) const;
162 
163     /**
164      * Deletes an entire section
165      * @param sect Name of section to delete, NULL to delete all
166      */
167     void clearSection(const char* sect = 0);
168 
169     /**
170      * Makes sure a section with a given name exists, creates if required
171      * @param sect Name of section to check or create
172      * @return The section's content or NULL if no such section
173      */
174     NamedList* createSection(const String& sect);
175 
176     /**
177      * Deletes a key/value pair
178      * @param sect Name of section
179      * @param key Name of the key to delete
180      */
181     void clearKey(const String& sect, const String& key);
182 
183     /**
184      * Add the value of a key in a section.
185      * @param sect Name of the section, will be created if missing
186      * @param key Name of the key to add in the section
187      * @param value Value to set in the key
188      */
189     void addValue(const String& sect, const char* key, const char* value = 0);
190 
191     /**
192      * Set the value of a key in a section.
193      * @param sect Name of the section, will be created if missing
194      * @param key Name of the key in section, will be created if missing
195      * @param value Value to set in the key
196      */
197     void setValue(const String& sect, const char* key, const char* value = 0);
198 
199     /**
200      * Set the numeric value of a key in a section.
201      * @param sect Name of the section, will be created if missing
202      * @param key Name of the key in section, will be created if missing
203      * @param value Value to set in the key
204      */
205     void setValue(const String& sect, const char* key, int value);
206 
207     /**
208      * Set the boolean value of a key in a section.
209      * @param sect Name of the section, will be created if missing
210      * @param key Name of the key in section, will be created if missing
211      * @param value Value to set in the key
212      */
213     void setValue(const String& sect, const char* key, bool value);
214 
215     /**
216      * Load the configuration from file
217      * @param warn True to also warn if the configuration could not be loaded
218      * @return True if successfull, false for failure
219      */
220     bool load(bool warn = true);
221 
222     /**
223      * Save the configuration to file
224      * @return True if successfull, false for failure
225      */
226     bool save() const;
227 
228 private:
229     ObjList *getSectHolder(const String& sect) const;
230     ObjList *makeSectHolder(const String& sect);
231     bool loadFile(const char* file, String sect, unsigned int depth, bool warn);
232     ObjList m_sections;
233 };
234 
235 /**
236  * Class that implements atomic / locked access and operations to its shared variables
237  * @short Atomic access and operations to shared variables
238  */
239 class YATE_API SharedVars : public Mutex
240 {
241 public:
242     /**
243      * Constructor
244      */
SharedVars()245     inline SharedVars()
246 	: Mutex(false,"SharedVars"), m_vars("")
247 	{ }
248 
249     /**
250      * Get the string value of a variable
251      * @param name Name of the variable
252      * @param rval String to return the value into
253      */
254     void get(const String& name, String& rval);
255 
256     /**
257      * Set the string value of a variable
258      * @param name Name of the variable to set
259      * @param val New value to assign to a variable
260      */
261     void set(const String& name, const char* val);
262 
263     /**
264      * Create and set a variable only if the variable is not already set
265      * @param name Name of the variable to set
266      * @param val New value to assign to a variable
267      * @return True if a new variable was created
268      */
269     bool create(const String& name, const char* val = 0);
270 
271     /**
272      * Clear a variable
273      * @param name Name of the variable to clear
274      */
275     void clear(const String& name);
276 
277     /**
278      * Check if a variable exists
279      * @param name Name of the variable
280      * @return True if the variable exists
281      */
282     bool exists(const String& name);
283 
284     /**
285      * Atomically increment a variable as unsigned integer
286      * @param name Name of the variable
287      * @param wrap Value to wrap around at, zero disables
288      * @return Value of the variable before increment, zero if it was not defined or not numeric
289      */
290     unsigned int inc(const String& name, unsigned int wrap = 0);
291 
292     /**
293      * Atomically decrement a variable as unsigned integer
294      * @param name Name of the variable
295      * @param wrap Value to wrap around at, zero disables (stucks at zero)
296      * @return Value of the variable after decrement, zero if it was not defined or not numeric
297      */
298     unsigned int dec(const String& name, unsigned int wrap = 0);
299 
300 private:
301     NamedList m_vars;
302 };
303 
304 class MessageDispatcher;
305 class MessageRelay;
306 class Engine;
307 
308 /**
309  * This class holds the messages that are moved around in the engine.
310  * @short A message container class
311  */
312 class YATE_API Message : public NamedList
313 {
314     friend class MessageDispatcher;
315 public:
316     /**
317      * Creates a new message.
318      *
319      * @param name Name of the message - must not be NULL or empty
320      * @param retval Default return value
321      * @param broadcast Broadcast flag, true if handling the mesage must not stop it
322      */
323     explicit Message(const char* name, const char* retval = 0, bool broadcast = false);
324 
325     /**
326      * Copy constructor.
327      * Note that user data and notification are not copied
328      * @param original Message we are copying from
329      */
330     Message(const Message& original);
331 
332     /**
333      * Copy constructor that can alter the broadcast flag.
334      * Note that user data and notification are not copied
335      * @param original Message we are copying from
336      * @param broadcast Broadcast flag, true if handling the mesage must not stop it
337      */
338     Message(const Message& original, bool broadcast);
339 
340     /**
341      * Destruct the message and dereferences any user data
342      */
343     ~Message();
344 
345     /**
346      * Get a pointer to a derived class given that class name
347      * @param name Name of the class we are asking for
348      * @return Pointer to the requested class or NULL if this object doesn't implement it
349      */
350     virtual void* getObject(const String& name) const;
351 
352     /**
353      * Retrieve a reference to the value returned by the message.
354      * @return A reference to the value the message will return
355      */
retValue()356     inline String& retValue()
357 	{ return m_return; }
358 
359     /**
360      * Retrieve a const reference to the value returned by the message.
361      * @return A reference to the value the message will return
362      */
retValue()363     inline const String& retValue() const
364 	{ return m_return; }
365 
366     /**
367      * Retrieve the object associated with the message
368      * @return Pointer to arbitrary user RefObject
369      */
userData()370     inline RefObject* userData() const
371 	{ return m_data; }
372 
373     /**
374      * Set obscure data associated with the message.
375      * The user data is reference counted to avoid stray pointers.
376      * Note that setting new user data will disable any notification.
377      * @param data Pointer to arbitrary user data
378      */
379     void userData(RefObject* data);
380 
381     /**
382      * Get a pointer to a derived class of user data given that class name
383      * @param name Name of the class we are asking for
384      * @return Pointer to the requested class or NULL if user object id NULL or doesn't implement it
385      */
userObject(const String & name)386     inline void* userObject(const String& name) const
387 	{ return m_data ? m_data->getObject(name) : 0; }
388 
389 
390     /**
391      * Enable or disable notification of any @ref MessageNotifier that was set
392      *  as user data. This method must be called after userData()
393      * @param notify True to have the message call the notifier
394      */
395     inline void setNotify(bool notify = true)
396 	{ m_notify = notify; }
397 
398     /**
399      * Retrieve the broadcast flag
400      * @return True if the message is a broadcast (handling does not stop it)
401      */
broadcast()402     inline bool broadcast() const
403 	{ return m_broadcast; }
404 
405     /**
406      * Retrieve a reference to the creation time of the message.
407      * @return A reference to the @ref Time when the message was created
408      */
msgTime()409     inline Time& msgTime()
410 	{ return m_time; }
411 
412     /**
413      * Retrieve a const reference to the creation time of the message.
414      * @return A reference to the @ref Time when the message was created
415      */
msgTime()416     inline const Time& msgTime() const
417 	{ return m_time; }
418 
419     /**
420      * Name assignment operator
421      */
422     inline Message& operator=(const char* value)
423 	{ String::operator=(value); return *this; }
424 
425     /**
426      * Encode the message into a string adequate for sending for processing
427      * to an external communication interface
428      * @param id Unique identifier to add to the string
429      */
430     String encode(const char* id) const;
431 
432     /**
433      * Encode the message into a string adequate for sending as answer
434      * to an external communication interface
435      * @param received True if message was processed locally
436      * @param id Unique identifier to add to the string
437      */
438     String encode(bool received, const char* id) const;
439 
440     /**
441      * Decode a string from an external communication interface for processing
442      * in the engine. The message is modified accordingly.
443      * @param str String to decode
444      * @param id A String object in which the identifier is stored
445      * @return -2 for success, -1 if the string was not a text form of a
446      * message, index of first erroneous character if failed
447      */
448     int decode(const char* str, String& id);
449 
450     /**
451      * Decode a string from an external communication interface that is an
452      * answer to a specific external processing request.
453      * @param str String to decode
454      * @param received Pointer to variable to store the dispatch return value
455      * @param id The identifier expected
456      * @return -2 for success, -1 if the string was not the expected answer,
457      * index of first erroneous character if failed
458      */
459     int decode(const char* str, bool& received, const char* id);
460 
461 protected:
462     /**
463      * Notify the message it has been dispatched.
464      * The default behaviour is to call the dispatched() method of the user
465      *  data if it implements @ref MessageNotifier
466      * @param accepted True if one handler accepted the message
467      */
468     virtual void dispatched(bool accepted);
469 
470 private:
471     Message(); // no default constructor please
472     Message& operator=(const Message& value); // no assignment please
473     String m_return;
474     Time m_time;
475     RefObject* m_data;
476     bool m_notify;
477     bool m_broadcast;
478     void commonEncode(String& str) const;
479     int commonDecode(const char* str, int offs);
480 };
481 
482 /**
483  * The purpose of this class is to hold a message received method that is
484  *  called for matching messages. It holds as well the matching criteria
485  *  and priority among other handlers.
486  * @short A message handler
487  */
488 class YATE_API MessageHandler : public String
489 {
490     friend class MessageDispatcher;
491     YNOCOPY(MessageHandler); // no automatic copies please
492 public:
493     /**
494      * Creates a new message handler.
495      * @param name Name of the handled message - may be NULL
496      * @param priority Priority of the handler, 0 = top
497      * @param trackName Name to be used in handler tracking
498      * @param addPriority True to append :priority to trackName
499      */
500     explicit MessageHandler(const char* name, unsigned priority = 100,
501 	const char* trackName = 0, bool addPriority = true);
502 
503     /**
504      * Handler destructor.
505      */
506     virtual ~MessageHandler();
507 
508     /**
509      * Destroys the object, performs cleanup first
510      */
511     virtual void destruct();
512 
513     /**
514      * This method is called whenever the registered name matches the message.
515      * @param msg The received message
516      * @return True to stop processing, false to try other handlers
517      */
518     virtual bool received(Message& msg) = 0;
519 
520     /**
521      * Find out the priority of the handler
522      * @return Stored priority of the handler, 0 = top
523      */
priority()524     inline unsigned priority() const
525 	{ return m_priority; }
526 
527     /**
528      * Retrieve the tracking name of this handler
529      * @return Name that is to be used in tracking operation
530      */
trackName()531     inline const String& trackName() const
532 	{ return m_trackName; }
533 
534     /**
535      * Set a new tracking name for this handler.
536      * Works only if the handler was not yet inserted into a dispatcher
537      * @param name Name that is to be used in tracking operation
538      */
trackName(const char * name)539     inline void trackName(const char* name)
540 	{ if (!m_dispatcher) m_trackName = name; }
541 
542     /**
543      * Retrive the objects counter associated to this handler
544      * @return Pointer to handler's objects counter or NULL
545      */
objectsCounter()546     inline NamedCounter* objectsCounter() const
547 	{ return m_counter; }
548 
549     /**
550      * Retrieve the filter (if installed) associated to this handler
551      */
filter()552     inline const NamedString* filter() const
553 	{ return m_filter; }
554 
555     /**
556      * Retrieve the Regexp filter (if installed) associated to this handler
557      */
filterRegexp()558     inline const Regexp* filterRegexp() const
559 	{ return m_filterRegexp; }
560 
561     /**
562      * Set a filter for this handler
563      * @param filter Pointer to the filter to install, will be owned and
564      *  destroyed by the handler. The filter may be a NamedPointer carrying a Regexp
565      */
566     void setFilter(NamedString* filter);
567 
568     /**
569      * Set a filter for this handler
570      * @param name Name of the parameter to filter
571      * @param value Value of the parameter to filter
572      */
setFilter(const char * name,const char * value)573     inline void setFilter(const char* name, const char* value)
574 	{ setFilter(new NamedString(name,value)); }
575 
576     /**
577      * Remove and destroy any filter associated to this handler
578      */
579     void clearFilter();
580 
581 protected:
582     /**
583      * Remove the handler from its dispatcher, remove any installed filter.
584      * This method is called internally from destruct and the destructor
585      */
586     void cleanup();
587 
588     /**
589      * Internal use received function, do not call or override!
590      * @param msg The received message
591      * @return True if message was processed
592      */
593     virtual bool receivedInternal(Message& msg);
594 
595     /**
596      * Internal use handler unlock, do not call!
597      */
598     void safeNowInternal();
599 
600 private:
601     String m_trackName;
602     unsigned m_priority;
603     int m_unsafe;
604     MessageDispatcher* m_dispatcher;
605     NamedString* m_filter;
606     Regexp* m_filterRegexp;
607     NamedCounter* m_counter;
608 };
609 
610 /**
611  * A multiple message receiver to be invoked by a message relay
612  * @short A multiple message receiver
613  */
614 class YATE_API MessageReceiver : public GenObject
615 {
616 public:
617     /**
618      * This method is called from the message relay.
619      * @param msg The received message
620      * @param id The identifier with which the relay was created
621      * @return True to stop processing, false to try other handlers
622      */
623     virtual bool received(Message& msg, int id) = 0;
624 };
625 
626 /**
627  * A message handler that allows to relay several messages to a single receiver
628  * @short A message handler relay
629  */
630 class YATE_API MessageRelay : public MessageHandler
631 {
632     YNOCOPY(MessageRelay); // no automatic copies please
633 public:
634     /**
635      * Creates a new message relay.
636      * @param name Name of the handled message - may be NULL
637      * @param receiver Receiver of th relayed messages
638      * @param id Numeric identifier to pass to receiver
639      * @param priority Priority of the handler, 0 = top
640      * @param trackName Name to be used in handler tracking
641      * @param addPriority True to append :priority to trackName
642      */
643     inline MessageRelay(const char* name, MessageReceiver* receiver, int id,
644 	int priority = 100, const char* trackName = 0, bool addPriority = true)
MessageHandler(name,priority,trackName,addPriority)645 	: MessageHandler(name,priority,trackName,addPriority),
646 	  m_receiver(receiver), m_id(id)
647 	{ }
648 
649     /**
650      * This method is not called from MessageHandler through polymorphism
651      *  and should not be used or reimplemented.
652      * @param msg The received message
653      * @return True if the receiver exists and has handled the message
654      */
received(Message & msg)655     virtual bool received(Message& msg)
656 	{ return m_receiver && m_receiver->received(msg,m_id); }
657 
658     /**
659      * Get the ID of this message relay
660      * @return Numeric identifier passed to receiver
661      */
id()662     inline int id() const
663 	{ return m_id; }
664 
665     /**
666      * Internal use received function, do not call or override!
667      * @param msg The received message
668      * @return True if message was processed
669      */
670     virtual bool receivedInternal(Message& msg);
671 
672 private:
673     MessageReceiver* m_receiver;
674     int m_id;
675 };
676 
677 /**
678  * An abstract class to implement hook methods called after any message has
679  *  been dispatched. If an object implementing MessageNotifier is set as user
680  *  data in a @ref Message then the dispatched() method will be called.
681  * @short Post-dispatching message hook
682  */
683 class YATE_API MessageNotifier
684 {
685 public:
686     /**
687      * Destructor. Keeps compiler form complaining.
688      */
689     virtual ~MessageNotifier();
690 
691     /**
692      * This method is called after a message was dispatched.
693      * @param msg The already dispatched message message
694      * @param handled True if a handler claimed to have handled the message
695      */
696     virtual void dispatched(const Message& msg, bool handled) = 0;
697 };
698 
699 /**
700  * An abstract message notifier that can be inserted in a @ref MessageDispatcher
701  *  to implement hook methods called after any message has been dispatched.
702  * No new methods are provided - we only need the multiple inheritance.
703  * @short Post-dispatching message hook that can be added to a list
704  */
705 class YATE_API MessagePostHook : public RefObject, public MessageNotifier
706 {
707 };
708 
709 /**
710  * The dispatcher class is a hub that holds a list of handlers to be called
711  *  for the messages that pass trough the hub. It can also handle a queue of
712  *  messages that are typically dispatched by a separate thread.
713  * @short A message dispatching hub
714  */
715 class YATE_API MessageDispatcher : public GenObject, public Mutex
716 {
717     friend class Engine;
718     YNOCOPY(MessageDispatcher); // no automatic copies please
719 public:
720     /**
721      * Creates a new message dispatcher.
722      * @param trackParam Name of the parameter used in tracking handlers
723      */
724     MessageDispatcher(const char* trackParam = 0);
725 
726     /**
727      * Destroys the dispatcher and the installed handlers.
728      */
729     ~MessageDispatcher();
730 
731     /**
732      * Retrieve the tracker parameter name
733      * @return Name of the parameter used to track message dispatching
734      */
trackParam()735     inline const String& trackParam() const
736 	{ return m_trackParam; }
737 
738     /**
739      * Installs a handler in the dispatcher.
740      * The handlers are installed in ascending order of their priorities.
741      * There is NO GUARANTEE on the order of handlers with equal priorities
742      *  although for avoiding uncertainity such handlers are sorted by address.
743      * @param handler A pointer to the handler to install
744      * @return True on success, false on failure
745      */
746     bool install(MessageHandler* handler);
747 
748     /**
749      * Uninstalls a handler from the dispatcher.
750      * @param handler A pointer to the handler to uninstall
751      * @return True on success, false on failure
752      */
753     bool uninstall(MessageHandler* handler);
754 
755     /**
756      * Synchronously dispatch a message to the installed handlers.
757      * Handlers matching the message name and filter parameter are called in
758      *  their installed order (based on priority) until one returns true.
759      * If the message has the broadcast flag set all matching handlers are
760      *  called and the return value is true if any handler returned true.
761      * Note that in some cases when a handler is removed from the list
762      *  other handlers with equal priority may be called twice.
763      * @param msg The message to dispatch
764      * @return True if one handler accepted it, false if all ignored
765      */
766     bool dispatch(Message& msg);
767 
768     /**
769      * Put a message in the waiting queue for asynchronous dispatching
770      * @param msg The message to enqueue, will be destroyed after dispatching
771      * @return True if successfully queued, false otherwise
772      */
773     bool enqueue(Message* msg);
774 
775     /**
776      * Dispatch all messages from the waiting queue
777      */
778     void dequeue();
779 
780     /**
781      * Dispatch one message from the waiting queue
782      * @return True if success, false if the queue is empty
783      */
784     bool dequeueOne();
785 
786     /**
787      * Set a limit to generate warning when a message took too long to dispatch
788      * @param usec Warning time limit in microseconds, zero to disable
789      */
warnTime(u_int64_t usec)790     inline void warnTime(u_int64_t usec)
791 	{ m_warnTime = usec; }
792 
793     /**
794      * Clear all the message handlers and post-dispatch hooks
795      */
clear()796     inline void clear()
797 	{ m_handlers.clear(); m_hookAppend = &m_hooks; m_hooks.clear(); }
798 
799     /**
800      * Check if there is at least one message in the queue
801      * @return True if the queue holds at least one message
802      */
hasMessages()803     inline bool hasMessages() const
804 	{ return m_messages.get() || m_messages.next(); }
805 
806     /**
807      * Check if there is at least one handler installed
808      * @return True if at least one handler is installed
809      */
hasHandlers()810     inline bool hasHandlers() const
811 	{ return m_handlers.get() || m_handlers.next(); }
812 
813     /**
814      * Check if there is at least one message hook installed
815      * @return True if at least one hook is installed
816      */
hasHooks()817     inline bool hasHooks() const
818 	{ return m_hooks.get() || m_hooks.next(); }
819 
820     /**
821      * Get the number of messages waiting in the queue
822      * @return Count of messages in the queue
823      */
824     unsigned int messageCount();
825 
826     /**
827      * Get the number of handlers in this dispatcher
828      * @return Count of handlers
829      */
830     unsigned int handlerCount();
831 
832     /**
833      * Get the number of post-handling hooks in this dispatcher
834      * @return Count of hooks
835      */
836     unsigned int postHookCount();
837 
838     /**
839      * Get the total number of enqueued messages
840      * @return Count of enqueued messages
841      */
enqueueCount()842     u_int64_t enqueueCount() const
843 	{ return m_enqueueCount; }
844 
845     /**
846      * Get the total number of dequeued messages
847      * @return Count of dequeued messages
848      */
dequeueCount()849     u_int64_t dequeueCount() const
850 	{ return m_dequeueCount; }
851 
852     /**
853      * Get the total number of dispatched messages
854      * @return Count of dispatched messages
855      */
dispatchCount()856     u_int64_t dispatchCount() const
857 	{ return m_dispatchCount; }
858 
859     /**
860      * Get the queued messages high watermark
861      * @return Highest number of messages in queue
862      */
queuedMax()863     u_int64_t queuedMax() const
864 	{ return m_queuedMax; }
865 
866     /**
867      * Get the average dequeued message age in milliseconds or microseconds
868      * @param usec True to return microseconds instead of milliseconds
869      * @return Average age of dequeued messages
870      */
871     u_int64_t messageAge(bool usec = false) const
872 	{ return usec ? m_msgAvgAge : ((m_msgAvgAge + 500) / 1000); }
873 
874     /**
875      * Retrieve all statistics counters
876      * @param enqueued Returns count of enqueued messages
877      * @param dequeued Returns count of dequeued messages
878      * @param dispatched Returns count of all dispatched messages, including dequeued ones
879      * @param queueMax Returns queued high watermark
880      */
881     void getStats(u_int64_t& enqueued, u_int64_t& dequeued, u_int64_t& dispatched, u_int64_t& queueMax);
882 
883     /**
884      * Install or remove a hook to catch messages after being dispatched
885      * @param hook Pointer to a post-dispatching message hook
886      * @param remove Set to True to remove the hook instead of adding
887      */
888     void setHook(MessagePostHook* hook, bool remove = false);
889 
890 protected:
891     /**
892      * Set the tracked parameter name
893      * @param paramName Name of the parameter used in tracking handlers
894      */
trackParam(const char * paramName)895     inline void trackParam(const char* paramName)
896 	{ m_trackParam = paramName; }
897 
898 private:
899     ObjList m_handlers;
900     ObjList m_messages;
901     ObjList m_hooks;
902     Mutex m_hookMutex;
903     ObjList* m_msgAppend;
904     ObjList* m_hookAppend;
905     String m_trackParam;
906     unsigned int m_changes;
907     u_int64_t m_warnTime;
908     u_int64_t m_enqueueCount;
909     u_int64_t m_dequeueCount;
910     u_int64_t m_dispatchCount;
911     u_int64_t m_queuedMax;
912     u_int64_t m_msgAvgAge;
913     int m_hookCount;
914     bool m_hookHole;
915 };
916 
917 /**
918  * Abstract class for message hook
919  * @short Abstract message hook
920  */
921 class YATE_API MessageHook : public RefObject
922 {
923 public:
924     /**
925      * Try to enqueue a message to this hook's queue
926      * @param msg The message to enqueue
927      * @return True if the message was enqueued.
928      */
929     virtual bool enqueue(Message* msg) = 0;
930 
931     /**
932      * Clear this hook data
933      */
934     virtual void clear() = 0;
935 
936     /**
937      * Check if the given message can be inserted in this queue
938      * @param msg The message to check
939      * @return True if the message can be inserted in this queue
940      */
941     virtual bool matchesFilter(const Message& msg) = 0;
942 };
943 
944 
945 /**
946  * MessageQueue class allows to create a private queue for a message who matches
947  * the specified filters.
948  * @short A message queue
949  */
950 class YATE_API MessageQueue : public MessageHook, public Mutex
951 {
952     friend class Engine;
953 public:
954     /**
955      * Creates a new message queue.
956      * @param hookName Name of the message served by this queue
957      * @param numWorkers The number of workers who serve this queue
958      */
959     MessageQueue(const char* hookName, int numWorkers = 0);
960 
961     /**
962      * Destroys the message queue
963      */
964     ~MessageQueue();
965 
966     /**
967      * Append a message in the queue
968      * @param msg The message to enqueue, will be destroyed after the processing is done
969      * @return True if successfully queued, false otherwise
970      */
971     virtual bool enqueue(Message* msg);
972 
973     /**
974      * Process a message from the waiting queue
975      * @return False if the message queue is empty
976      */
977     bool dequeue();
978 
979     /**
980      * Add a new filter to this queue
981      * @param name The filter name
982      * @param value The filter value
983      */
984     void addFilter(const char* name, const char* value);
985 
986     /**
987      * Remove a filter form this queue
988      * @param name The filter name
989      */
990     void removeFilter(const String& name);
991 
992     /**
993      * Clear private data
994      */
995     virtual void clear();
996 
997     /**
998      * Remove a thread from workers list
999      * @param thread The thread to remove
1000      */
1001     void removeThread(Thread* thread);
1002 
1003     /**
1004      * Helper method to obtain the number of unprocessed messages in the queue
1005      * @return The number of queued messages.
1006      */
count()1007     inline unsigned int count() const
1008 	{ return m_count; }
1009 
1010     /**
1011      * Obtain the filter list for this queue
1012      * @return The filter list
1013      */
getFilters()1014     inline const NamedList& getFilters() const
1015 	{ return m_filters; }
1016 
1017     /**
1018      * Check if the given message can be inserted in this queue
1019      * @param msg The message to check
1020      * @return True if the message can be inserted in this queue
1021      */
1022     virtual bool matchesFilter(const Message& msg);
1023 protected:
1024 
1025     /**
1026      * Callback method for message processing
1027      * Default calls Engine::dispatch
1028      * @param msg The message to process
1029      */
1030     virtual void received(Message& msg);
1031 
1032 private:
1033     NamedList m_filters;
1034     ObjList m_messages;
1035     ObjList m_workers;
1036     ObjList* m_append;
1037     unsigned int m_count;
1038 };
1039 
1040 
1041 /**
1042  * Initialization and information about plugins.
1043  * Plugins are located in @em shared libraries that are loaded at runtime.
1044  *
1045  *<pre>
1046  * // Create static Plugin object by using the provided macro
1047  * INIT_PLUGIN(Plugin);
1048  *</pre>
1049  * @short Plugin support
1050  */
1051 class YATE_API Plugin : public GenObject, public DebugEnabler
1052 {
1053 public:
1054     /**
1055      * Creates a new Plugin container.
1056      * @param name the undecorated name of the library that contains the plugin
1057      * @param earlyInit True to initialize the plugin early
1058      */
1059     explicit Plugin(const char* name, bool earlyInit = false);
1060 
1061     /**
1062      * Destroys the plugin.
1063      * The destructor must never be called directly - the Loader will do it
1064      *  when the shared object's reference count reaches zero.
1065      */
1066     virtual ~Plugin();
1067 
1068     /**
1069      * Get a string representation of this object
1070      * @return Name of the plugin
1071      */
toString()1072     virtual const String& toString() const
1073 	{ return m_name; }
1074 
1075     /**
1076      * Get a pointer to a derived class given that class name
1077      * @param name Name of the class we are asking for
1078      * @return Pointer to the requested class or NULL if this object doesn't implement it
1079      */
1080     virtual void* getObject(const String& name) const;
1081 
1082     /**
1083      * Initialize the plugin after it was loaded and registered.
1084      */
1085     virtual void initialize() = 0;
1086 
1087     /**
1088      * Check if the module is actively used.
1089      * @return True if the plugin is in use, false if should be ok to restart
1090      */
isBusy()1091     virtual bool isBusy() const
1092 	{ return false; }
1093 
1094     /**
1095      * Retrieve the name of the plugin
1096      * @return The plugin's name as String
1097      */
name()1098     inline const String& name() const
1099 	{ return m_name; }
1100 
1101     /**
1102      * Retrive the objects counter associated to this plugin
1103      * @return Pointer to plugin's objects counter or NULL
1104      */
objectsCounter()1105     inline NamedCounter* objectsCounter() const
1106 	{ return m_counter; }
1107 
1108     /**
1109      * Check if the module is to be initialized early
1110      * @return True if the module should be initialized before regular ones
1111      */
earlyInit()1112     bool earlyInit() const
1113 	{ return m_early; }
1114 
1115 private:
1116     Plugin(); // no default constructor please
1117     String m_name;
1118     NamedCounter* m_counter;
1119     bool m_early;
1120 };
1121 
1122 #if 0 /* for documentation generator */
1123 /**
1124  * Macro to create static instance of the plugin
1125  * @param pclass Class of the plugin to create
1126  */
1127 void INIT_PLUGIN(class pclass);
1128 
1129 /**
1130  * Macro to create the unloading function
1131  * @param unloadNow True if asked to unload immediately, false if just checking
1132  * @return True if the plugin can be unloaded, false if not
1133  */
1134 bool UNLOAD_PLUGIN(bool unloadNow);
1135 #endif
1136 
1137 #define INIT_PLUGIN(pclass) static pclass __plugin
1138 #ifdef DISABLE_UNLOAD
1139 #define UNLOAD_PLUGIN(arg) static bool _unused_unload(bool arg)
1140 #else
1141 #ifdef _WINDOWS
1142 #define UNLOAD_PLUGIN(arg) extern "C" __declspec(dllexport) bool _unload(bool arg)
1143 #else
1144 #define UNLOAD_PLUGIN(arg) extern "C" bool _unload(bool arg)
1145 #endif
1146 #endif
1147 
1148 /**
1149  * Base class for engine running stage checkers.
1150  * Descendants may check specific conditions and decide to stop the engine.
1151  * There should be only one (static) instance of an engine checker
1152  * @short Engine checker interface
1153  */
1154 class YATE_API EngineCheck
1155 {
1156 public:
1157     /**
1158      * Do-nothing destructor of base class
1159      */
~EngineCheck()1160     virtual ~EngineCheck()
1161 	{ }
1162 
1163     /**
1164      * Check running conditions. This method is called by the engine in the initialize process
1165      * @param cmds Optional list of strings containing extra command line parameters
1166      *  (not parsed by the engine)
1167      * @return False to stop the program
1168      */
1169     virtual bool check(const ObjList* cmds) = 0;
1170 
1171     /**
1172      * Set the current engine checker
1173      * @param ptr The new engine checker. May be 0 to reset it
1174      */
1175     static void setChecker(EngineCheck* ptr = 0);
1176 };
1177 
1178 /**
1179  * Prototype for engine main loop callback
1180  */
1181 typedef int (*EngineLoop)();
1182 
1183 /**
1184  * This class holds global information about the engine.
1185  * Note: this is a singleton class.
1186  *
1187  * @short Engine globals
1188  */
1189 class YATE_API Engine
1190 {
1191     friend class EnginePrivate;
1192     friend class EngineCommand;
1193     YNOCOPY(Engine); // no automatic copies please
1194 public:
1195     /**
1196      * Running modes - run the engine as Console, Client or Server.
1197      */
1198     enum RunMode {
1199 	Stopped = 0,
1200 	Console = 1,
1201 	Server = 2,
1202 	Client = 3,
1203 	ClientProxy = 4,
1204     };
1205 
1206     enum CallAccept {
1207 	Accept = 0,
1208 	Partial = 1,
1209 	Congestion = 2,
1210 	Reject = 3,
1211     };
1212 
1213     /**
1214      * Plugin load and initialization modes.
1215      * Default is LoadLate that initailizes the plugin after others.
1216      * LoadEarly will move the plugin to the front of the init order.
1217      * LoadFail causes the plugin to be unloaded.
1218      */
1219     enum PluginMode {
1220 	LoadFail = 0,
1221 	LoadLate,
1222 	LoadEarly
1223     };
1224 
1225     /**
1226      * Main entry point to be called directly from a wrapper program
1227      * @param argc Argument count
1228      * @param argv Argument array
1229      * @param env Environment variables
1230      * @param mode Mode the engine must run as - Console, Client or Server
1231      * @param loop Callback function to the main thread's loop
1232      * @param fail Fail and return after parsing command line arguments
1233      * @return Program exit code
1234      */
1235     static int main(int argc, const char** argv, const char** env,
1236 	RunMode mode = Console, EngineLoop loop = 0, bool fail = false);
1237 
1238     /**
1239      * Display the help information on console
1240      * @param client Display help for client running mode
1241      * @param errout Display on stderr intead of stdout
1242      */
1243     static void help(bool client, bool errout = false);
1244 
1245     /**
1246      * Initialize the engine
1247      * @return Error code, 0 for success
1248      */
1249     int engineInit();
1250 
1251     /**
1252      * Do engine cleanup
1253      * @return Error code, 0 for success
1254      */
1255     int engineCleanup();
1256 
1257     /**
1258      * Run the engine.
1259      * @return Error code, 0 for success
1260      */
1261     int run();
1262 
1263     /**
1264      * Get a pointer to the unique instance.
1265      * @return A pointer to the singleton instance of the engine
1266      */
1267     static Engine* self();
1268 
1269     /**
1270      * Get the running mode of the engine
1271      * @return Engine's run mode as enumerated value
1272      */
mode()1273     static RunMode mode()
1274 	{ return s_mode; }
1275 
1276     /**
1277      * Get call accept status
1278      * @return Engine's call accept status as enumerated value
1279      */
accept()1280     inline static CallAccept accept() {
1281 	return (s_congestion && (s_accept < Congestion)) ? Congestion : s_accept;
1282     }
1283 
1284     /**
1285      * Set call accept status
1286      * @param ca New call accept status as enumerated value
1287      */
setAccept(CallAccept ca)1288     inline static void setAccept(CallAccept ca) {
1289 	s_accept = ca;
1290     }
1291 
1292     /**
1293      * Get call accept states
1294      * @return states Pointer to the call accept states TokenDict
1295      */
getCallAcceptStates()1296     inline static const TokenDict* getCallAcceptStates() {
1297 	return s_callAccept;
1298     }
1299 
1300     /**
1301      * Alter the congestion state counter.
1302      * @param reason Reason to enter congested state, NULL to leave congestion
1303      */
1304     static void setCongestion(const char* reason = 0);
1305 
1306     /**
1307      * Get the congestion state counter
1308      * @return Zero if not congested else the number of congested components
1309      */
getCongestion()1310     static unsigned int getCongestion()
1311 	{ return s_congestion; }
1312 
1313     /**
1314      * Check if the engine is running as telephony client
1315      * @return True if the engine is running in client mode
1316      */
clientMode()1317     inline static bool clientMode()
1318 	{ return (s_mode == Client) || (s_mode == ClientProxy); }
1319 
1320     /**
1321      * Register or unregister a plugin to the engine.
1322      * @param plugin A pointer to the plugin to (un)register
1323      * @param reg True to register (default), false to unregister
1324      * @return True on success, false on failure
1325      */
1326     static bool Register(const Plugin* plugin, bool reg = true);
1327 
1328     /**
1329      * Get the server node name, should be unique in a cluster
1330      * @return Node identifier string, defaults to host name
1331      */
nodeName()1332     inline static const String& nodeName()
1333 	{ return s_node; }
1334 
1335     /**
1336      * Get the application's shared directory path
1337      * @return The base path for shared files and directories
1338      */
sharedPath()1339     inline static const String& sharedPath()
1340 	{ return s_shrpath; }
1341 
1342     /**
1343      * Get the filename for a specific configuration
1344      * @param name Name of the configuration requested
1345      * @param user True to build a user settings path
1346      * @return A full path configuration file name
1347      */
1348     static String configFile(const char* name, bool user = false);
1349 
1350     /**
1351      * Get the system or user configuration directory path
1352      * @param user True to get the user settings path
1353      * @return The directory path for system or user configuration files
1354      */
1355     static const String& configPath(bool user = false);
1356 
1357     /**
1358      * Get the configuration file suffix
1359      * @return The suffix for configuration files
1360      */
configSuffix()1361     inline static const String& configSuffix()
1362 	{ return s_cfgsuffix; }
1363 
1364     /**
1365      * The module loading path
1366      */
modulePath()1367     inline static const String& modulePath()
1368 	{ return s_modpath; }
1369 
1370     /**
1371      * Add a relative extra module loading path. The list is empty by default
1372      *  but can be filled by a main program before calling @ref main()
1373      * @param path Relative path to extra modules to be loaded
1374      */
1375     static void extraPath(const String& path);
1376 
1377     /**
1378      * Set the per user application data path. This method must be called
1379      *  by a main program before calling @ref main() or @ref help()
1380      * Path separators are not allowed. The default is taken from CFG_DIR.
1381      * @param path Single relative path component to write user specific data
1382      */
1383     static void userPath(const String& path);
1384 
1385     /**
1386      * Get the module filename suffix
1387      * @return The suffix for module files
1388      */
moduleSuffix()1389     inline static const String& moduleSuffix()
1390 	{ return s_modsuffix; }
1391 
1392     /**
1393      * Get the canonical path element separator for the operating system
1394      * @return The operating system specific path element separator
1395      */
1396     static const char* pathSeparator();
1397 
1398     /**
1399      * The global configuration of the engine.
1400      * You must use this resource with caution.
1401      * Note that sections [general], [modules], [preload] and [postload] are
1402      *  reserved by the engine. Also [telephony] is reserved by the drivers.
1403      * @return A reference to the read-only engine configuration
1404      */
1405     static const Configuration& config();
1406 
1407     /**
1408      * Get a - supposedly unique - instance ID
1409      * @return Unique ID of the current running instance
1410      */
1411     static unsigned int runId();
1412 
1413     /**
1414      * Get the engine parameters specific to this run.
1415      * @return A reference to the list of run specific parameters
1416      */
runParams()1417     inline static const NamedList& runParams()
1418 	{ return s_params; }
1419 
1420     /**
1421      * Reinitialize the plugins
1422      */
1423     static void init();
1424 
1425     /**
1426      * Reinitialize one plugin
1427      * @param name Name of the plugin to initialize, emplty, "*" or "all" to initialize all
1428      * @return True if plugin(s) were reinitialized
1429      */
1430     static bool init(const String& name);
1431 
1432     /**
1433      * Stop the engine and the entire program
1434      * @param code Return code of the program
1435      */
1436     static void halt(unsigned int code);
1437 
1438     /**
1439      * Stop and restart the engine and the entire program
1440      * @param code Return code of the program
1441      * @param gracefull Attempt to wait until no plugin is busy
1442      * @return True if restart was initiated, false if exiting or no supervisor
1443      */
1444     static bool restart(unsigned int code, bool gracefull = false);
1445 
1446     /**
1447      * Check if the engine was started
1448      * @return True if the engine has gone through the start phase
1449      */
started()1450     static bool started()
1451 	{ return s_started; }
1452 
1453     /**
1454      * Check if the engine is currently exiting
1455      * @return True if exiting, false in normal operation
1456      */
exiting()1457     static bool exiting()
1458 	{ return (s_haltcode != -1); }
1459 
1460     /**
1461      * Installs a handler in the dispatcher.
1462      * @param handler A pointer to the handler to install
1463      * @return True on success, false on failure
1464      */
1465     static bool install(MessageHandler* handler);
1466 
1467     /**
1468      * Uninstalls a handler drom the dispatcher.
1469      * @param handler A pointer to the handler to uninstall
1470      * @return True on success, false on failure
1471      */
1472     static bool uninstall(MessageHandler* handler);
1473 
1474     /**
1475      * Enqueue a message in the message queue for asynchronous dispatching
1476      * @param msg The message to enqueue, will be destroyed after dispatching
1477      * @param skipHooks True to append the message directly into the main queue
1478      * @return True if enqueued, false on error (already queued)
1479      */
1480     static bool enqueue(Message* msg, bool skipHooks = false);
1481 
1482     /**
1483      * Convenience function.
1484      * Enqueue a new parameterless message in the message queue
1485      * @param name Name of the parameterless message to put in queue
1486      * @param broadcast Broadcast flag, true if handling the mesage must not stop it
1487      * @return True if enqueued, false on error (already queued)
1488      */
1489     inline static bool enqueue(const char* name, bool broadcast = false)
1490 	{ return name && *name && enqueue(new Message(name,0,broadcast)); }
1491 
1492     /**
1493      * Synchronously dispatch a message to the registered handlers
1494      * @param msg Pointer to the message to dispatch
1495      * @return True if one handler accepted it, false if all ignored
1496      */
1497     static bool dispatch(Message* msg);
1498 
1499     /**
1500      * Synchronously dispatch a message to the registered handlers
1501      * @param msg The message to dispatch
1502      * @return True if one handler accepted it, false if all ignored
1503      */
1504     static bool dispatch(Message& msg);
1505 
1506     /**
1507      * Convenience function.
1508      * Dispatch a parameterless message to the registered handlers
1509      * @param name The name of the message to create and dispatch
1510      * @param broadcast Broadcast flag, true if handling the mesage must not stop it
1511      * @return True if one handler accepted it, false if all ignored
1512      */
1513     static bool dispatch(const char* name, bool broadcast = false);
1514 
1515     /**
1516      * Install or remove a hook to catch messages after being dispatched
1517      * @param hook Pointer to a post-dispatching message hook
1518      * @param remove Set to True to remove the hook instead of adding
1519      */
1520     inline void setHook(MessagePostHook* hook, bool remove = false)
1521 	{ m_dispatcher.setHook(hook,remove); }
1522 
1523     /**
1524      * Retrieve the tracker parameter name
1525      * @return Name of the parameter used to track message dispatching
1526      */
trackParam()1527     inline static const String& trackParam()
1528 	{ return s_self ? s_self->m_dispatcher.trackParam() : String::empty(); }
1529 
1530     /**
1531      * Appends a new message hook to the hooks list.
1532      * @param hook The message hook to append.
1533      * @return True if the message hook was successfully appended to the hooks list
1534      */
1535     static bool installHook(MessageHook* hook);
1536 
1537     /**
1538      * Remove a message hook from the hooks list.
1539      * @param hook The hook to remove.
1540      */
1541     static void uninstallHook(MessageHook* hook);
1542 
1543     /**
1544      * Get a count of plugins that are actively in use
1545      * @return Count of plugins in use
1546      */
1547     int usedPlugins();
1548 
1549     /**
1550      * Get the number of messages waiting in the queue
1551      * @return Count of messages in the queue
1552      */
messageCount()1553     inline unsigned int messageCount()
1554 	{ return m_dispatcher.messageCount(); }
1555 
1556     /**
1557      * Get the number of handlers in the dispatcher
1558      * @return Count of handlers
1559      */
handlerCount()1560     inline unsigned int handlerCount()
1561 	{ return m_dispatcher.handlerCount(); }
1562 
1563     /**
1564      * Get the number of post-handling hooks in the dispatcher
1565      * @return Count of hooks
1566      */
postHookCount()1567     inline unsigned int postHookCount()
1568 	{ return m_dispatcher.postHookCount(); }
1569 
1570     /**
1571      * Get the rate of dispatched messages per second
1572      * @return Number of messages dispatched in the last second
1573      */
messageRate()1574     inline unsigned int messageRate() const
1575 	{ return m_messageRate; }
1576 
1577     /**
1578      * Get the maximum rate of dispatched messages per second
1579      * @return Maximum number of messages dispatched per second
1580      */
messageMaxRate()1581     inline unsigned int messageMaxRate() const
1582 	{ return m_maxMsgRate; }
1583 
1584     /**
1585      * Get the average dequeued message age in milliseconds or microseconds
1586      * @param usec True to return microseconds instead of milliseconds
1587      * @return Average age of dequeued messages
1588      */
1589     unsigned int messageAge(bool usec = false) const
1590 	{ return (unsigned int)m_dispatcher.messageAge(usec); }
1591 
1592     /**
1593      * Retrieve dispatcher's statistics counters
1594      * @param enqueued Returns count of enqueued messages
1595      * @param dequeued Returns count of dequeued messages
1596      * @param dispatched Returns count of all dispatched messages, including dequeued ones
1597      * @param queueMax Returns queued high watermark
1598      */
getStats(u_int64_t & enqueued,u_int64_t & dequeued,u_int64_t & dispatched,u_int64_t & queueMax)1599     inline void getStats(u_int64_t& enqueued, u_int64_t& dequeued, u_int64_t& dispatched, u_int64_t& queueMax)
1600 	{ m_dispatcher.getStats(enqueued,dequeued,dispatched,queueMax); }
1601 
1602     /**
1603      * Reset the high water mark of the stat counters
1604      */
resetMax()1605     inline void resetMax()
1606 	{ m_maxMsgRate = m_messageRate; m_dispatcher.m_queuedMax = m_dispatcher.messageCount(); }
1607 
1608     /**
1609      * Check if a plugin is currently loaded
1610      * @param name Name of the plugin to check
1611      * @return True if the named plugin is loaded
1612      */
pluginLoaded(const String & name)1613     inline bool pluginLoaded(const String& name) const
1614 	{ return !!m_libs[name]; }
1615 
1616     /**
1617      * Loads the plugins from an extra plugins directory or just an extra plugin
1618      * @param relPath Path to the extra directory, relative to the main modules
1619      * @return True if the plugin was loaded or the directory could at least be opened
1620      */
1621     bool loadPluginDir(const String& relPath);
1622 
1623     /**
1624      * Set the load and init mode of the currently loading @ref Plugin
1625      * @param mode Load and init mode, default LoadLate
1626      */
1627     static void pluginMode(PluginMode mode);
1628 
1629     /**
1630      * Retrive the list of captured events of a specific type
1631      * @param type Type of captured events, an empty name returns engine events
1632      * @return List containing captured events of specified type, NULL if not found
1633      */
1634     static const ObjList* events(const String& type);
1635 
1636     /**
1637      * Clear the list of captured events of a specific type
1638      * @param type Type of captured events, an empty name clear engine events
1639      */
1640     static void clearEvents(const String& type);
1641 
1642     /**
1643      * Access the engine's shared variables
1644      * @return Reference to the static variables shared between modules
1645      */
1646     static SharedVars& sharedVars();
1647 
1648     /**
1649      * Append command line arguments form current config.
1650      * The following parameters are added: -Dads, -v, -q, Debugger timestamp.
1651      * This method should be used when starting another libyate based application
1652      * @param line Destination string
1653      */
1654     static void buildCmdLine(String& line);
1655 
1656     /**
1657      * Initialize library from command line arguments.
1658      * Enable debugger output.
1659      * This method should be used in initialization stage of libyate based applications
1660      * @param line Command line arguments string
1661      * @param output Optional string to be filled with invalid argument errors
1662      *  or any output to be displyed later
1663      */
1664     static void initLibrary(const String& line, String* output = 0);
1665 
1666     /**
1667      * Cleanup library. Set late abort, kill all threads.
1668      * This method should be used in cleanup stage of libyate based applications
1669      * @return Halt code
1670      */
1671     static int cleanupLibrary();
1672 
1673 protected:
1674     /**
1675      * Destroys the engine and everything. You must not call it directly,
1676      * @ref run() will do it for you.
1677      */
1678     ~Engine();
1679 
1680     /**
1681      * Loads one plugin from a shared object file
1682      * @param file Name of the plugin file to load
1683      * @param local Attempt to keep symbols local if supported by the system
1684      * @param nounload Never unload the module from memory, finalize if possible
1685      * @return True if success, false on failure
1686      */
1687     bool loadPlugin(const char* file, bool local = false, bool nounload = false);
1688 
1689     /**
1690      * Loads the plugins from the plugins directory
1691      */
1692     void loadPlugins();
1693 
1694     /**
1695      * Initialize all registered plugins
1696      */
1697     void initPlugins();
1698 
1699 private:
1700     Engine();
1701     void internalStatisticsStart();
1702     void tryPluginFile(const String& name, const String& path, bool defload);
1703     ObjList m_libs;
1704     MessageDispatcher m_dispatcher;
1705     uint64_t m_dispatchedLast;
1706     unsigned int m_messageRate;
1707     unsigned int m_maxMsgRate;
1708     bool m_rateCongested;
1709     bool m_queueCongested;
1710     bool m_ageCongested;
1711     static Engine* s_self;
1712     static String s_node;
1713     static String s_shrpath;
1714     static String s_cfgsuffix;
1715     static String s_modpath;
1716     static String s_modsuffix;
1717     static ObjList s_extramod;
1718     static NamedList s_params;
1719     static int s_haltcode;
1720     static RunMode s_mode;
1721     static bool s_started;
1722     static unsigned int s_congestion;
1723     static CallAccept s_accept;
1724     static const TokenDict s_callAccept[];
1725 };
1726 
1727 }; // namespace TelEngine
1728 
1729 #endif /* __YATENGINE_H */
1730 
1731 /* vi: set ts=8 sw=4 sts=4 noet: */
1732