Asterisk - The Open Source Telephony Project GIT-master-9647a4f
Loading...
Searching...
No Matches
ccss.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2010, Digium, Inc.
5 *
6 * Mark Michelson <mmichelson@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 * \brief Call Completion Supplementary Services implementation
21 * \author Mark Michelson <mmichelson@digium.com>
22 */
23
24/*! \li \ref ccss.c uses the configuration file \ref ccss.conf
25 * \addtogroup configuration_file Configuration Files
26 */
27
28/*!
29 * \page ccss.conf ccss.conf
30 * \verbinclude ccss.conf.sample
31 */
32
33/*** MODULEINFO
34 <support_level>core</support_level>
35 ***/
36
37#include "asterisk.h"
38
39#include "asterisk/astobj2.h"
40#include "asterisk/strings.h"
41#include "asterisk/ccss.h"
42#include "asterisk/channel.h"
43#include "asterisk/pbx.h"
44#include "asterisk/utils.h"
47#include "asterisk/module.h"
48#include "asterisk/app.h"
49#include "asterisk/cli.h"
50#include "asterisk/manager.h"
51#include "asterisk/causes.h"
54
55/*** DOCUMENTATION
56 <application name="CallCompletionRequest" language="en_US">
57 <since>
58 <version>1.8.0</version>
59 </since>
60 <synopsis>
61 Request call completion service for previous call
62 </synopsis>
63 <syntax />
64 <description>
65 <para>Request call completion service for a previously failed
66 call attempt.</para>
67 <para>This application sets the following channel variables:</para>
68 <variablelist>
69 <variable name="CC_REQUEST_RESULT">
70 <para>This is the returned status of the request.</para>
71 <value name="SUCCESS" />
72 <value name="FAIL" />
73 </variable>
74 <variable name="CC_REQUEST_REASON">
75 <para>This is the reason the request failed.</para>
76 <value name="NO_CORE_INSTANCE" />
77 <value name="NOT_GENERIC" />
78 <value name="TOO_MANY_REQUESTS" />
79 <value name="UNSPECIFIED" />
80 </variable>
81 </variablelist>
82 </description>
83 </application>
84 <application name="CallCompletionCancel" language="en_US">
85 <since>
86 <version>1.8.0</version>
87 </since>
88 <synopsis>
89 Cancel call completion service
90 </synopsis>
91 <syntax />
92 <description>
93 <para>Cancel a Call Completion Request.</para>
94 <para>This application sets the following channel variables:</para>
95 <variablelist>
96 <variable name="CC_CANCEL_RESULT">
97 <para>This is the returned status of the cancel.</para>
98 <value name="SUCCESS" />
99 <value name="FAIL" />
100 </variable>
101 <variable name="CC_CANCEL_REASON">
102 <para>This is the reason the cancel failed.</para>
103 <value name="NO_CORE_INSTANCE" />
104 <value name="NOT_GENERIC" />
105 <value name="UNSPECIFIED" />
106 </variable>
107 </variablelist>
108 </description>
109 </application>
110 ***/
111
112/* These are some file-scoped variables. It would be
113 * nice to define them closer to their first usage, but since
114 * they are used in many places throughout the file, defining
115 * them here at the top is easiest.
116 */
117
118static int global_enabled;
119
120#define RETURN_IF_NOT_ENABLED(rc) \
121({ \
122 if (!global_enabled) { \
123 ast_debug(3, "CCSS disabled globally\n"); \
124 return rc; \
125 } \
126})
127
128/*!
129 * The ast_sched_context used for all generic CC timeouts
130 */
132/*!
133 * Counter used to create core IDs for CC calls. Each new
134 * core ID is created by atomically adding 1 to the core_id_counter
135 */
137/*!
138 * Taskprocessor from which all CC agent and monitor callbacks
139 * are called.
140 */
142/*!
143 * Name printed on all CC log messages.
144 */
145static const char *CC_LOGGER_LEVEL_NAME = "CC";
146/*!
147 * Logger level registered by the CC core.
148 */
150/*!
151 * Parsed configuration value for cc_max_requests
152 */
153static unsigned int global_cc_max_requests;
154/*!
155 * The current number of CC requests in the system
156 */
158
159static inline void *cc_ref(void *obj, const char *debug)
160{
161 ao2_t_ref(obj, +1, debug);
162 return obj;
163}
164
165static inline void *cc_unref(void *obj, const char *debug)
166{
167 ao2_t_ref(obj, -1, debug);
168 return NULL;
169}
170
171/*!
172 * \since 1.8
173 * \internal
174 * \brief A structure for holding the configuration parameters
175 * relating to CCSS
176 */
189
190/*!
191 * \since 1.8
192 * \brief The states used in the CCSS core state machine
193 *
194 * For more information, see doc/CCSS_architecture.pdf
195 */
197 /*! Entered when it is determined that CCSS may be used for the call */
199 /*! Entered when a CCSS agent has offered CCSS to a caller */
201 /*! Entered when a CCSS agent confirms that a caller has
202 * requested CCSS */
204 /*! Entered when a CCSS monitor confirms acknowledgment of an
205 * outbound CCSS request */
207 /*! Entered when a CCSS monitor alerts the core that the called party
208 * has become available */
210 /*! Entered when a CCSS agent alerts the core that the calling party
211 * may not be recalled because he is unavailable
212 */
214 /*! Entered when a CCSS agent alerts the core that the calling party
215 * is attempting to recall the called party
216 */
218 /*! Entered when an application alerts the core that the calling party's
219 * recall attempt has had a call progress response indicated
220 */
222 /*! Entered any time that something goes wrong during the process, thus
223 * resulting in the failure of the attempted CCSS transaction. Note also
224 * that cancellations of CC are treated as failures.
225 */
227};
228
229/*!
230 * \brief The payload for an AST_CONTROL_CC frame
231 *
232 * \details
233 * This contains all the necessary data regarding
234 * a called device so that the CC core will be able
235 * to allocate the proper monitoring resources.
236 */
238 /*!
239 * \brief The type of monitor to allocate.
240 *
241 * \details
242 * The type of monitor to allocate. This is a string which corresponds
243 * to a set of monitor callbacks registered. Examples include "generic"
244 * and "SIP"
245 *
246 * \note This really should be an array of characters in case this payload
247 * is sent across an IAX2 link. However, this would not make too much sense
248 * given this type may not be recognized by the other end.
249 * Protection may be necessary to prevent it from being transmitted.
250 *
251 * In addition the following other problems are also possible:
252 * 1) Endian issues with the integers/enums stored in the config_params.
253 * 2) Alignment padding issues for the element types.
254 */
255 const char *monitor_type;
256 /*!
257 * \brief Private data allocated by the callee
258 *
259 * \details
260 * All channel drivers that monitor endpoints will need to allocate
261 * data that is not usable by the CC core. In most cases, some or all
262 * of this data is allocated at the time that the channel driver offers
263 * CC to the caller. There are many opportunities for failures to occur
264 * between when a channel driver offers CC and when a monitor is actually
265 * allocated to watch the endpoint. For this reason, the channel driver
266 * must give the core a pointer to the private data that was allocated so
267 * that the core can call back into the channel driver to destroy it if
268 * a failure occurs. If no private data has been allocated at the time that
269 * CC is offered, then it is perfectly acceptable to pass NULL for this
270 * field.
271 */
273 /*!
274 * \brief Service offered by the endpoint
275 *
276 * \details
277 * This indicates the type of call completion service offered by the
278 * endpoint. This data is not crucial to the machinations of the CC core,
279 * but it is helpful for debugging purposes.
280 */
282 /*!
283 * \brief Configuration parameters used by this endpoint
284 *
285 * \details
286 * Each time an endpoint offers call completion, it must provide its call
287 * completion configuration parameters. This is because settings may be different
288 * depending on the circumstances.
289 */
291 /*!
292 * \brief ID of parent extension
293 *
294 * \details
295 * This is the only datum that the CC core derives on its own and is not
296 * provided by the offerer of CC. This provides the core with information on
297 * which extension monitor is the most immediate parent of this device.
298 */
300 /*!
301 * \brief Name of device to be monitored
302 *
303 * \details
304 * The device name by which this monitored endpoint will be referred in the
305 * CC core. It is highly recommended that this device name is derived by using
306 * the function ast_channel_get_device_name.
307 */
309 /*!
310 * \brief Recall dialstring
311 *
312 * \details
313 * Certain channel drivers (DAHDI in particular) will require that a special
314 * dialstring be used to indicate that the outgoing call is to interpreted as
315 * a CC recall. If the channel driver has such a requirement, then this is
316 * where that special recall dialstring is placed. If no special dialstring
317 * is to be used, then the channel driver must provide the original dialstring
318 * used to call this endpoint.
319 */
321};
322
323/*!
324 * \brief The "tree" of interfaces that is dialed.
325 *
326 * \details
327 * Though this is a linked list, it is logically treated
328 * as a tree of monitors. Each monitor has an id and a parent_id
329 * associated with it. The id is a unique ID for that monitor, and
330 * the parent_id is the unique ID of the monitor's parent in the
331 * tree. The tree is structured such that all of a parent's children
332 * will appear after the parent in the tree. However, it cannot be
333 * guaranteed exactly where after the parent the children are.
334 *
335 * The tree is reference counted since several threads may need
336 * to use it, and it may last beyond the lifetime of a single
337 * thread.
338 */
340
341static const int CC_CORE_INSTANCES_BUCKETS = 17;
343
345 /*!
346 * Unique identifier for this instance of the CC core.
347 */
349 /*!
350 * The current state for this instance of the CC core.
351 */
353 /*!
354 * The CC agent in use for this call
355 */
357 /*!
358 * Reference to the monitor tree formed during the initial call
359 */
361};
362
363/*!
364 * \internal
365 * \brief Request that the core change states
366 * \param state The state to which we wish to change
367 * \param core_id The unique identifier for this instance of the CCSS core state machine
368 * \param debug Optional message explaining the reason for the state change
369 * \param ap varargs list
370 * \retval 0 State change successfully queued
371 * \retval -1 Unable to queue state change request
372 */
373static int __attribute__((format(printf, 3, 0))) cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap);
374
375/*!
376 * \internal
377 * \brief create a new instance of the CC core and an agent for the calling channel
378 *
379 * This function will check to make sure that the incoming channel
380 * is allowed to request CC by making sure that the incoming channel
381 * has not exceeded its maximum number of allowed agents.
382 *
383 * Should that check pass, the core instance is created, and then the
384 * agent for the channel.
385 *
386 * \param caller_chan The incoming channel for this particular call
387 * \param called_tree A reference to the tree of called devices. The agent
388 * will gain a reference to this tree as well
389 * \param core_id The core_id that this core_instance will assume
390 * \param cc_data
391 * \retval NULL Failed to create the core instance either due to memory allocation
392 * errors or due to the agent count for the caller being too high
393 * \retval non-NULL A reference to the newly created cc_core_instance
394 */
395static struct cc_core_instance *cc_core_init_instance(struct ast_channel *caller_chan,
396 struct cc_monitor_tree *called_tree, const int core_id, struct cc_control_payload *cc_data);
397
398static const struct {
400 const char *service_string;
402 {AST_CC_NONE, "NONE"},
403 {AST_CC_CCBS, "CCBS"},
404 {AST_CC_CCNR, "CCNR"},
405 {AST_CC_CCNL, "CCNL"},
407
408static const struct {
410 const char *state_string;
412 {CC_AVAILABLE, "CC is available"},
413 {CC_CALLER_OFFERED, "CC offered to caller"},
414 {CC_CALLER_REQUESTED, "CC requested by caller"},
415 {CC_ACTIVE, "CC accepted by callee"},
416 {CC_CALLEE_READY, "Callee has become available"},
417 {CC_CALLER_BUSY, "Callee was ready, but caller is now unavailable"},
418 {CC_RECALLING, "Caller is attempting to recall"},
419 {CC_COMPLETE, "Recall complete"},
420 {CC_FAILED, "CC has failed"},
422
423static const char *cc_state_to_string(enum cc_state state)
424{
425 return cc_state_to_string_map[state].state_string;
426}
427
429{
430 return cc_service_to_string_map[service].service_string;
431}
432
433static int cc_core_instance_hash_fn(const void *obj, const int flags)
434{
435 const struct cc_core_instance *core_instance = obj;
436 return core_instance->core_id;
437}
438
439static int cc_core_instance_cmp_fn(void *obj, void *arg, int flags)
440{
441 struct cc_core_instance *core_instance1 = obj;
442 struct cc_core_instance *core_instance2 = arg;
443
444 return core_instance1->core_id == core_instance2->core_id ? CMP_MATCH | CMP_STOP : 0;
445}
446
448{
449 struct cc_core_instance finder = {.core_id = core_id,};
450
451 return ao2_t_find(cc_core_instances, &finder, OBJ_POINTER, "Finding a core_instance");
452}
453
459
460static int cc_agent_callback_helper(void *obj, void *args, int flags)
461{
462 struct cc_core_instance *core_instance = obj;
463 struct cc_callback_helper *helper = args;
464
465 if (strcmp(core_instance->agent->callbacks->type, helper->type)) {
466 return 0;
467 }
468
469 return helper->function(core_instance->agent, helper->args, flags);
470}
471
472struct ast_cc_agent *ast_cc_agent_callback(int flags, ao2_callback_fn *function, void *args, const char * const type)
473{
474 struct cc_callback_helper helper = {.function = function, .args = args, .type = type};
475 struct cc_core_instance *core_instance;
476
478
479 if ((core_instance = ao2_t_callback(cc_core_instances, flags, cc_agent_callback_helper, &helper,
480 "Calling provided agent callback function"))) {
481 struct ast_cc_agent *agent = cc_ref(core_instance->agent, "An outside entity needs the agent");
482 cc_unref(core_instance, "agent callback done with the core_instance");
483 return agent;
484 }
485 return NULL;
486}
487
489 /* Only match agents that have not yet
490 * made a CC request
491 */
493 /* Only match agents that have made
494 * a CC request
495 */
496 MATCH_REQUEST = (1 << 1),
497};
498
499/* ao2_callbacks for cc_core_instances */
500
501/*!
502 * \internal
503 * \brief find a core instance based on its agent
504 *
505 * The match flags tell whether we wish to find core instances
506 * that have a monitor or core instances that do not. Core instances
507 * with no monitor are core instances for which a caller has not yet
508 * requested CC. Core instances with a monitor are ones for which the
509 * caller has requested CC.
510 */
511static int match_agent(void *obj, void *arg, void *data, int flags)
512{
513 struct cc_core_instance *core_instance = obj;
514 const char *name = arg;
515 unsigned long match_flags = *(unsigned long *)data;
516 int possible_match = 0;
517
519 possible_match = 1;
520 }
521
522 if ((match_flags & MATCH_REQUEST) && core_instance->current_state >= CC_CALLER_REQUESTED) {
523 possible_match = 1;
524 }
525
526 if (!possible_match) {
527 return 0;
528 }
529
530 if (!strcmp(core_instance->agent->device_name, name)) {
531 return CMP_MATCH | CMP_STOP;
532 }
533 return 0;
534}
535
540
541/*!
542 * \internal
543 * \brief Count the number of agents a specific interface is using
544 *
545 * We're only concerned with the number of agents that have requested
546 * CC, so we restrict our search to core instances which have a non-NULL
547 * monitor pointer
548 */
549static int count_agents_cb(void *obj, void *arg, void *data, int flags)
550{
551 struct cc_core_instance *core_instance = obj;
552 const char *name = arg;
553 struct count_agents_cb_data *cb_data = data;
554
555 if (cb_data->core_id_exception == core_instance->core_id) {
556 ast_log_dynamic_level(cc_logger_level, "Found agent with core_id %d but not counting it toward total\n", core_instance->core_id);
557 return 0;
558 }
559
560 if (core_instance->current_state >= CC_CALLER_REQUESTED && !strcmp(core_instance->agent->device_name, name)) {
561 cb_data->count++;
562 }
563 return 0;
564}
565
566/* default values mapping from cc_state to ast_dev_state */
567
568#define CC_AVAILABLE_DEVSTATE_DEFAULT AST_DEVICE_NOT_INUSE
569#define CC_CALLER_OFFERED_DEVSTATE_DEFAULT AST_DEVICE_NOT_INUSE
570#define CC_CALLER_REQUESTED_DEVSTATE_DEFAULT AST_DEVICE_NOT_INUSE
571#define CC_ACTIVE_DEVSTATE_DEFAULT AST_DEVICE_INUSE
572#define CC_CALLEE_READY_DEVSTATE_DEFAULT AST_DEVICE_RINGING
573#define CC_CALLER_BUSY_DEVSTATE_DEFAULT AST_DEVICE_ONHOLD
574#define CC_RECALLING_DEVSTATE_DEFAULT AST_DEVICE_RINGING
575#define CC_COMPLETE_DEVSTATE_DEFAULT AST_DEVICE_NOT_INUSE
576#define CC_FAILED_DEVSTATE_DEFAULT AST_DEVICE_NOT_INUSE
577
578/*!
579 * \internal
580 * \brief initialization of defaults for CC_STATE to DEVICE_STATE map
581 */
593
594/*!
595 * \internal
596 * \brief lookup the ast_device_state mapped to cc_state
597 *
598 * \param state
599 *
600 * \return the corresponding DEVICE STATE from the cc_state_to_devstate_map
601 * when passed an internal state.
602 */
607
608/*!
609 * \internal
610 * \brief Callback for devicestate providers
611 *
612 * \details
613 * Initialize with ast_devstate_prov_add() and returns the corresponding
614 * DEVICE STATE based on the current CC_STATE state machine if the requested
615 * device is found and is a generic device. Returns the equivalent of
616 * CC_FAILED, which defaults to NOT_INUSE, if no device is found. NOT_INUSE would
617 * indicate that there is no presence of any pending call back.
618 */
619static enum ast_device_state ccss_device_state(const char *device_name)
620{
621 struct cc_core_instance *core_instance;
622 unsigned long match_flags;
623 enum ast_device_state cc_current_state;
624
627 (char *) device_name, &match_flags,
628 "Find Core Instance for ccss_device_state request.");
629 if (!core_instance) {
631 "Couldn't find a core instance for caller %s\n", device_name);
633 }
634
636 "Core %d: Found core_instance for caller %s in state %s\n",
637 core_instance->core_id, device_name, cc_state_to_string(core_instance->current_state));
638
639 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
641 "Core %d: Device State is only for generic agent types.\n",
642 core_instance->core_id);
643 cc_unref(core_instance, "Unref core_instance since ccss_device_state was called with native agent");
645 }
646 cc_current_state = cc_state_to_devstate(core_instance->current_state);
647 cc_unref(core_instance, "Unref core_instance done with ccss_device_state");
648 return cc_current_state;
649}
650
651/*!
652 * \internal
653 * \brief Notify Device State Changes from CC STATE MACHINE
654 *
655 * \details
656 * Any time a state is changed, we call this function to notify the DEVICE STATE
657 * subsystem of the change so that subscribed phones to any corresponding hints that
658 * are using that state are updated.
659 */
660static void ccss_notify_device_state_change(const char *device, enum cc_state state)
661{
662 enum ast_device_state devstate;
663
664 devstate = cc_state_to_devstate(state);
665
667 "Notification of CCSS state change to '%s', device state '%s' for device '%s'\n",
668 cc_state_to_string(state), ast_devstate2str(devstate), device);
669
670 ast_devstate_changed(devstate, AST_DEVSTATE_CACHABLE, "ccss:%s", device);
671}
672
673#define CC_OFFER_TIMER_DEFAULT 20 /* Seconds */
674#define CCNR_AVAILABLE_TIMER_DEFAULT 7200 /* Seconds */
675#define CCBS_AVAILABLE_TIMER_DEFAULT 4800 /* Seconds */
676#define CC_RECALL_TIMER_DEFAULT 20 /* Seconds */
677#define CC_MAX_AGENTS_DEFAULT 5
678#define CC_MAX_MONITORS_DEFAULT 5
679#define GLOBAL_CC_MAX_REQUESTS_DEFAULT 20
680
683 .cc_monitor_policy = AST_CC_MONITOR_NEVER,
684 .cc_offer_timer = CC_OFFER_TIMER_DEFAULT,
685 .ccnr_available_timer = CCNR_AVAILABLE_TIMER_DEFAULT,
686 .ccbs_available_timer = CCBS_AVAILABLE_TIMER_DEFAULT,
687 .cc_recall_timer = CC_RECALL_TIMER_DEFAULT,
688 .cc_max_agents = CC_MAX_AGENTS_DEFAULT,
689 .cc_max_monitors = CC_MAX_MONITORS_DEFAULT,
690 .cc_callback_sub = "",
691 .cc_agent_dialstring = "",
692};
693
695{
696 *params = cc_default_params;
697}
698
699struct ast_cc_config_params *__ast_cc_config_params_init(const char *file, int line, const char *function)
700{
701 struct ast_cc_config_params *params;
702
704
705 params = __ast_malloc(sizeof(*params), file, line, function);
706 if (!params) {
707 return NULL;
708 }
709
711 return params;
712}
713
715{
716 ast_free(params);
717}
718
719static enum ast_cc_agent_policies str_to_agent_policy(const char * const value)
720{
721 if (!strcasecmp(value, "never")) {
722 return AST_CC_AGENT_NEVER;
723 } else if (!strcasecmp(value, "native")) {
724 return AST_CC_AGENT_NATIVE;
725 } else if (!strcasecmp(value, "generic")) {
727 } else {
728 ast_log(LOG_WARNING, "%s is an invalid value for cc_agent_policy. Switching to 'never'\n", value);
729 return AST_CC_AGENT_NEVER;
730 }
731}
732
734{
735 if (!strcasecmp(value, "never")) {
737 } else if (!strcasecmp(value, "native")) {
739 } else if (!strcasecmp(value, "generic")) {
741 } else if (!strcasecmp(value, "always")) {
743 } else {
744 ast_log(LOG_WARNING, "%s is an invalid value for cc_monitor_policy. Switching to 'never'\n", value);
746 }
747}
748
749static const char *agent_policy_to_str(enum ast_cc_agent_policies policy)
750{
751 switch (policy) {
753 return "never";
755 return "native";
757 return "generic";
758 default:
759 /* This should never happen... */
760 return "";
761 }
762}
763
764static const char *monitor_policy_to_str(enum ast_cc_monitor_policies policy)
765{
766 switch (policy) {
768 return "never";
770 return "native";
772 return "generic";
774 return "always";
775 default:
776 /* This should never happen... */
777 return "";
778 }
779}
780int ast_cc_get_param(struct ast_cc_config_params *params, const char * const name,
781 char *buf, size_t buf_len)
782{
783 const char *value = NULL;
784
785 if (!strcasecmp(name, "cc_callback_sub")) {
787 } else if (!strcasecmp(name, "cc_agent_policy")) {
789 } else if (!strcasecmp(name, "cc_monitor_policy")) {
791 } else if (!strcasecmp(name, "cc_agent_dialstring")) {
793 }
794 if (value) {
795 ast_copy_string(buf, value, buf_len);
796 return 0;
797 }
798
799 /* The rest of these are all ints of some sort and require some
800 * snprintf-itude
801 */
802
803 if (!strcasecmp(name, "cc_offer_timer")) {
804 snprintf(buf, buf_len, "%u", ast_get_cc_offer_timer(params));
805 } else if (!strcasecmp(name, "ccnr_available_timer")) {
806 snprintf(buf, buf_len, "%u", ast_get_ccnr_available_timer(params));
807 } else if (!strcasecmp(name, "ccbs_available_timer")) {
808 snprintf(buf, buf_len, "%u", ast_get_ccbs_available_timer(params));
809 } else if (!strcasecmp(name, "cc_max_agents")) {
810 snprintf(buf, buf_len, "%u", ast_get_cc_max_agents(params));
811 } else if (!strcasecmp(name, "cc_max_monitors")) {
812 snprintf(buf, buf_len, "%u", ast_get_cc_max_monitors(params));
813 } else if (!strcasecmp(name, "cc_recall_timer")) {
814 snprintf(buf, buf_len, "%u", ast_get_cc_recall_timer(params));
815 } else {
816 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
817 return -1;
818 }
819
820 return 0;
821}
822
823int ast_cc_set_param(struct ast_cc_config_params *params, const char * const name,
824 const char * const value)
825{
826 unsigned int value_as_uint;
827 if (!strcasecmp(name, "cc_agent_policy")) {
829 } else if (!strcasecmp(name, "cc_monitor_policy")) {
831 } else if (!strcasecmp(name, "cc_agent_dialstring")) {
833 } else if (!strcasecmp(name, "cc_callback_sub")) {
835 return 0;
836 }
837
838 if (sscanf(value, "%30u", &value_as_uint) != 1) {
839 return -1;
840 }
841
842 if (!strcasecmp(name, "cc_offer_timer")) {
843 ast_set_cc_offer_timer(params, value_as_uint);
844 } else if (!strcasecmp(name, "ccnr_available_timer")) {
845 ast_set_ccnr_available_timer(params, value_as_uint);
846 } else if (!strcasecmp(name, "ccbs_available_timer")) {
847 ast_set_ccbs_available_timer(params, value_as_uint);
848 } else if (!strcasecmp(name, "cc_max_agents")) {
849 ast_set_cc_max_agents(params, value_as_uint);
850 } else if (!strcasecmp(name, "cc_max_monitors")) {
851 ast_set_cc_max_monitors(params, value_as_uint);
852 } else if (!strcasecmp(name, "cc_recall_timer")) {
853 ast_set_cc_recall_timer(params, value_as_uint);
854 } else {
855 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
856 return -1;
857 }
858
859 return 0;
860}
861
862int ast_cc_is_config_param(const char * const name)
863{
864 return (!strcasecmp(name, "cc_agent_policy") ||
865 !strcasecmp(name, "cc_monitor_policy") ||
866 !strcasecmp(name, "cc_offer_timer") ||
867 !strcasecmp(name, "ccnr_available_timer") ||
868 !strcasecmp(name, "ccbs_available_timer") ||
869 !strcasecmp(name, "cc_max_agents") ||
870 !strcasecmp(name, "cc_max_monitors") ||
871 !strcasecmp(name, "cc_callback_sub") ||
872 !strcasecmp(name, "cc_agent_dialstring") ||
873 !strcasecmp(name, "cc_recall_timer"));
874}
875
877{
878 if (dest && src) {
879 *dest = *src;
880 }
881}
882
887
889{
890 /* Screw C and its weak type checking for making me have to do this
891 * validation at runtime.
892 */
893 if (value < AST_CC_AGENT_NEVER || value > AST_CC_AGENT_GENERIC) {
894 return -1;
895 }
896 config->cc_agent_policy = value;
897 return 0;
898}
899
901{
902 return config->cc_monitor_policy;
903}
904
906{
907 /* Screw C and its weak type checking for making me have to do this
908 * validation at runtime.
909 */
910 if (value < AST_CC_MONITOR_NEVER || value > AST_CC_MONITOR_ALWAYS) {
911 return -1;
912 }
913 config->cc_monitor_policy = value;
914 return 0;
915}
916
918{
919 return config->cc_offer_timer;
920}
921
923{
924 /* 0 is an unreasonable value for any timer. Stick with the default */
925 if (value == 0) {
926 ast_log(LOG_WARNING, "0 is an invalid value for cc_offer_timer. Retaining value as %u\n", config->cc_offer_timer);
927 return;
928 }
929 config->cc_offer_timer = value;
930}
931
933{
934 return config->ccnr_available_timer;
935}
936
938{
939 /* 0 is an unreasonable value for any timer. Stick with the default */
940 if (value == 0) {
941 ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->ccnr_available_timer);
942 return;
943 }
944 config->ccnr_available_timer = value;
945}
946
948{
949 return config->cc_recall_timer;
950}
951
953{
954 /* 0 is an unreasonable value for any timer. Stick with the default */
955 if (value == 0) {
956 ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->cc_recall_timer);
957 return;
958 }
959 config->cc_recall_timer = value;
960}
961
963{
964 return config->ccbs_available_timer;
965}
966
968{
969 /* 0 is an unreasonable value for any timer. Stick with the default */
970 if (value == 0) {
971 ast_log(LOG_WARNING, "0 is an invalid value for ccbs_available_timer. Retaining value as %u\n", config->ccbs_available_timer);
972 return;
973 }
974 config->ccbs_available_timer = value;
975}
976
978{
979 return config->cc_agent_dialstring;
980}
981
983{
984 if (ast_strlen_zero(value)) {
985 config->cc_agent_dialstring[0] = '\0';
986 } else {
987 ast_copy_string(config->cc_agent_dialstring, value, sizeof(config->cc_agent_dialstring));
988 }
989}
990
992{
993 return config->cc_max_agents;
994}
995
997{
998 config->cc_max_agents = value;
999}
1000
1002{
1003 return config->cc_max_monitors;
1004}
1005
1007{
1008 config->cc_max_monitors = value;
1009}
1010
1012{
1013 return config->cc_callback_sub;
1014}
1015
1017{
1018 if (ast_strlen_zero(value)) {
1019 config->cc_callback_sub[0] = '\0';
1020 } else {
1021 ast_copy_string(config->cc_callback_sub, value, sizeof(config->cc_callback_sub));
1022 }
1023}
1024
1025static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
1026{
1027 struct ast_json *blob;
1028 struct ast_json_payload *payload;
1029 struct stasis_message *message;
1030
1031 if (!message_type) {
1032 return -1;
1033 }
1034
1035 blob = ast_json_pack("{s: i}",
1036 "core_id", core_id);
1037 if (!blob) {
1038 return -1;
1039 }
1040
1041 if (extras) {
1042 ast_json_object_update(blob, extras);
1043 }
1044
1045 payload = ast_json_payload_create(blob);
1046 ast_json_unref(blob);
1047
1048 if (!payload) {
1049 return -1;
1050 }
1051
1052 message = stasis_message_create(message_type, payload);
1053 ao2_ref(payload, -1);
1054
1055 if (!message) {
1056 return -1;
1057 }
1058
1060 ao2_ref(message, -1);
1061
1062 return 0;
1063}
1064
1065static void cc_publish_available(int core_id, const char *callee, const char *service)
1066{
1067 struct ast_json *extras;
1068
1069 extras = ast_json_pack("{s: s, s: s}",
1070 "callee", callee,
1071 "service", service);
1072
1073 cc_publish(ast_cc_available_type(), core_id, extras);
1074 ast_json_unref(extras);
1075}
1076
1077static void cc_publish_offertimerstart(int core_id, const char *caller, unsigned int expires)
1078{
1079 struct ast_json *extras;
1080
1081 extras = ast_json_pack("{s: s, s: I}",
1082 "caller", caller,
1083 "expires", (ast_json_int_t)expires);
1084
1085 cc_publish(ast_cc_offertimerstart_type(), core_id, extras);
1086 ast_json_unref(extras);
1087}
1088
1089static void cc_publish_requested(int core_id, const char *caller, const char *callee)
1090{
1091 struct ast_json *extras;
1092
1093 extras = ast_json_pack("{s: s, s: s}",
1094 "caller", caller,
1095 "callee", callee);
1096
1097 cc_publish(ast_cc_requested_type(), core_id, extras);
1098 ast_json_unref(extras);
1099}
1100
1101static void cc_publish_requestacknowledged(int core_id, const char *caller)
1102{
1103 struct ast_json *extras;
1104
1105 extras = ast_json_pack("{s: s}",
1106 "caller", caller);
1107
1108 cc_publish(ast_cc_requestacknowledged_type(), core_id, extras);
1109 ast_json_unref(extras);
1110}
1111
1112static void cc_publish_callerstopmonitoring(int core_id, const char *caller)
1113{
1114 struct ast_json *extras;
1115
1116 extras = ast_json_pack("{s: s}",
1117 "caller", caller);
1118
1119 cc_publish(ast_cc_callerstopmonitoring_type(), core_id, extras);
1120 ast_json_unref(extras);
1121}
1122
1123static void cc_publish_callerstartmonitoring(int core_id, const char *caller)
1124{
1125 struct ast_json *extras;
1126
1127 extras = ast_json_pack("{s: s}",
1128 "caller", caller);
1129
1131 ast_json_unref(extras);
1132}
1133
1134static void cc_publish_callerrecalling(int core_id, const char *caller)
1135{
1136 struct ast_json *extras;
1137
1138 extras = ast_json_pack("{s: s}",
1139 "caller", caller);
1140
1141 cc_publish(ast_cc_callerrecalling_type(), core_id, extras);
1142 ast_json_unref(extras);
1143}
1144
1145static void cc_publish_recallcomplete(int core_id, const char *caller)
1146{
1147 struct ast_json *extras;
1148
1149 extras = ast_json_pack("{s: s}",
1150 "caller", caller);
1151
1152 cc_publish(ast_cc_recallcomplete_type(), core_id, extras);
1153 ast_json_unref(extras);
1154}
1155
1156static void cc_publish_failure(int core_id, const char *caller, const char *reason)
1157{
1158 struct ast_json *extras;
1159
1160 extras = ast_json_pack("{s: s, s: s}",
1161 "caller", caller,
1162 "reason", reason);
1163
1164 cc_publish(ast_cc_failure_type(), core_id, extras);
1165 ast_json_unref(extras);
1166}
1167
1168static void cc_publish_monitorfailed(int core_id, const char *callee)
1169{
1170 struct ast_json *extras;
1171
1172 extras = ast_json_pack("{s: s}",
1173 "callee", callee);
1174
1175 cc_publish(ast_cc_monitorfailed_type(), core_id, extras);
1176 ast_json_unref(extras);
1177}
1178
1183
1185
1187{
1188 struct cc_monitor_backend *backend;
1189
1191
1192 backend = ast_calloc(1, sizeof(*backend));
1193 if (!backend) {
1194 return -1;
1195 }
1196
1197 backend->callbacks = callbacks;
1198
1202 return 0;
1203}
1204
1205static const struct ast_cc_monitor_callbacks *find_monitor_callbacks(const char * const type)
1206{
1207 struct cc_monitor_backend *backend;
1208 const struct ast_cc_monitor_callbacks *callbacks = NULL;
1209
1211 AST_RWLIST_TRAVERSE(&cc_monitor_backends, backend, next) {
1212 if (!strcmp(backend->callbacks->type, type)) {
1213 ast_log_dynamic_level(cc_logger_level, "Returning monitor backend %s\n", backend->callbacks->type);
1214 callbacks = backend->callbacks;
1215 break;
1216 }
1217 }
1219 return callbacks;
1220}
1221
1239
1244
1246
1248{
1249 struct cc_agent_backend *backend;
1250
1252
1253 backend = ast_calloc(1, sizeof(*backend));
1254 if (!backend) {
1255 return -1;
1256 }
1257
1258 backend->callbacks = callbacks;
1262 return 0;
1263}
1264
1266{
1267 struct cc_agent_backend *backend;
1268
1270
1273 if (backend->callbacks == callbacks) {
1275 ast_free(backend);
1276 break;
1277 }
1278 }
1281}
1282
1284{
1285 struct cc_agent_backend *backend;
1286 const struct ast_cc_agent_callbacks *callbacks = NULL;
1287 struct ast_cc_config_params *cc_params;
1288 char type[32];
1289
1290 cc_params = ast_channel_get_cc_config_params(chan);
1291 if (!cc_params) {
1292 return NULL;
1293 }
1294 switch (ast_get_cc_agent_policy(cc_params)) {
1296 ast_copy_string(type, "generic", sizeof(type));
1297 break;
1299 ast_channel_get_cc_agent_type(chan, type, sizeof(type));
1300 break;
1301 default:
1302 ast_log_dynamic_level(cc_logger_level, "Not returning agent callbacks since this channel is configured not to have a CC agent\n");
1303 return NULL;
1304 }
1305
1307 AST_RWLIST_TRAVERSE(&cc_agent_backends, backend, next) {
1308 if (!strcmp(backend->callbacks->type, type)) {
1309 ast_log_dynamic_level(cc_logger_level, "Returning agent backend %s\n", backend->callbacks->type);
1310 callbacks = backend->callbacks;
1311 break;
1312 }
1313 }
1315 return callbacks;
1316}
1317
1318/*!
1319 * \internal
1320 * \brief Determine if the given device state is considered available by generic CCSS.
1321 * \since 1.8
1322 *
1323 * \param state Device state to test.
1324 *
1325 * \retval TRUE if the given device state is considered available by generic CCSS.
1326 */
1331
1332static int cc_generic_monitor_request_cc(struct ast_cc_monitor *monitor, int *available_timer_id);
1333static int cc_generic_monitor_suspend(struct ast_cc_monitor *monitor);
1334static int cc_generic_monitor_unsuspend(struct ast_cc_monitor *monitor);
1335static int cc_generic_monitor_cancel_available_timer(struct ast_cc_monitor *monitor, int *sched_id);
1336static void cc_generic_monitor_destructor(void *private_data);
1337
1339 .type = "generic",
1340 .request_cc = cc_generic_monitor_request_cc,
1341 .suspend = cc_generic_monitor_suspend,
1342 .unsuspend = cc_generic_monitor_unsuspend,
1343 .cancel_available_timer = cc_generic_monitor_cancel_available_timer,
1344 .destructor = cc_generic_monitor_destructor,
1345};
1346
1348
1355
1357 const char *device_name;
1359 /* If there are multiple instances monitoring the
1360 * same device and one should fail, we need to know
1361 * whether to signal that the device can be recalled.
1362 * The problem is that the device state is not enough
1363 * to check. If a caller has requested CCNR, then the
1364 * fact that the device is available does not indicate
1365 * that the device is ready to be recalled. Instead, as
1366 * soon as one instance of the monitor becomes available
1367 * for a recall, we mark the entire list as being fit
1368 * for recall. If a CCNR request comes in, then we will
1369 * have to mark the list as unfit for recall since this
1370 * is a clear indicator that the person at the monitored
1371 * device has gone away and is actually not fit to be
1372 * recalled
1373 */
1377};
1378
1379/*!
1380 * \brief private data for generic device monitor
1381 */
1383 /*!
1384 * We need the device name during destruction so we
1385 * can find the appropriate item to destroy.
1386 */
1387 const char *device_name;
1388 /*!
1389 * We need the core ID for similar reasons. Once we
1390 * find the appropriate item in our ao2_container, we
1391 * need to remove the appropriate cc_monitor from the
1392 * list of monitors.
1393 */
1395};
1396
1399
1400static struct generic_monitor_instance_list *find_generic_monitor_instance_list(const char * const device_name)
1401{
1402 struct generic_monitor_instance_list finder = {0};
1403 char *uppertech = ast_strdupa(device_name);
1404 ast_tech_to_upper(uppertech);
1405 finder.device_name = uppertech;
1406
1407 return ao2_t_find(generic_monitors, &finder, OBJ_POINTER, "Finding generic monitor instance list");
1408}
1409
1411{
1412 struct generic_monitor_instance_list *generic_list = obj;
1413 struct generic_monitor_instance *generic_instance;
1414
1415 generic_list->sub = stasis_unsubscribe(generic_list->sub);
1416 while ((generic_instance = AST_LIST_REMOVE_HEAD(&generic_list->list, next))) {
1417 ast_free(generic_instance);
1418 }
1419 ast_free((char *)generic_list->device_name);
1420}
1421
1422static void generic_monitor_devstate_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg);
1424{
1425 struct generic_monitor_instance_list *generic_list = ao2_t_alloc(sizeof(*generic_list),
1426 generic_monitor_instance_list_destructor, "allocate generic monitor instance list");
1427 char * device_name;
1428 struct stasis_topic *device_specific_topic;
1429
1430 if (!generic_list) {
1431 return NULL;
1432 }
1433
1434 if (!(device_name = ast_strdup(monitor->interface->device_name))) {
1435 cc_unref(generic_list, "Failed to strdup the monitor's device name");
1436 return NULL;
1437 }
1438 ast_tech_to_upper(device_name);
1439 generic_list->device_name = device_name;
1440
1441 device_specific_topic = ast_device_state_topic(device_name);
1442 if (!device_specific_topic) {
1443 return NULL;
1444 }
1445
1446 if (!(generic_list->sub = stasis_subscribe(device_specific_topic, generic_monitor_devstate_cb, NULL))) {
1447 cc_unref(generic_list, "Failed to subscribe to device state");
1448 return NULL;
1449 }
1452 generic_list->current_state = ast_device_state(monitor->interface->device_name);
1453 ao2_t_link(generic_monitors, generic_list, "linking new generic monitor instance list");
1454 return generic_list;
1455}
1456
1458{
1459 RAII_VAR(struct ast_device_state_message *, dev_state, data, ao2_cleanup);
1460 enum ast_device_state new_state = dev_state->state;
1461 enum ast_device_state previous_state;
1462 struct generic_monitor_instance_list *generic_list;
1463 struct generic_monitor_instance *generic_instance;
1464
1465 if (!(generic_list = find_generic_monitor_instance_list(dev_state->device))) {
1466 /* The most likely cause for this is that we destroyed the monitor in the
1467 * time between subscribing to its device state and the time this executes.
1468 * Not really a big deal.
1469 */
1470 return 0;
1471 }
1472
1473 if (generic_list->current_state == new_state) {
1474 /* The device state hasn't actually changed, so we don't really care */
1475 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
1476 return 0;
1477 }
1478
1479 previous_state = generic_list->current_state;
1480 generic_list->current_state = new_state;
1481
1482 if (cc_generic_is_device_available(new_state) &&
1483 (previous_state == AST_DEVICE_INUSE || previous_state == AST_DEVICE_UNAVAILABLE ||
1484 previous_state == AST_DEVICE_BUSY)) {
1485 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1486 if (!generic_instance->is_suspended && generic_instance->monitoring) {
1487 generic_instance->monitoring = 0;
1488 generic_list->fit_for_recall = 1;
1489 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
1490 break;
1491 }
1492 }
1493 }
1494 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
1495 return 0;
1496}
1497
1498static void generic_monitor_devstate_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
1499{
1500 /* Wow, it's cool that we've picked up on a state change, but we really want
1501 * the actual work to be done in the core's taskprocessor execution thread
1502 * so that all monitor operations can be serialized. Locks?! We don't need
1503 * no steenkin' locks!
1504 */
1505 struct ast_device_state_message *dev_state;
1507 return;
1508 }
1509
1510 dev_state = stasis_message_data(msg);
1511 if (dev_state->eid) {
1512 /* ignore non-aggregate states */
1513 return;
1514 }
1515
1516 ao2_t_ref(dev_state, +1, "Bumping dev_state ref for cc_core_taskprocessor");
1518 ao2_cleanup(dev_state);
1519 return;
1520 }
1521}
1522
1524{
1525 struct ast_cc_monitor *monitor = (struct ast_cc_monitor *) data;
1526 int res;
1527
1529
1530 monitor->available_timer_id = -1;
1531 res = ast_cc_monitor_failed(monitor->core_id, monitor->interface->device_name, "Available timer expired for monitor");
1532 cc_unref(monitor, "Unref reference from scheduler\n");
1533 return res;
1534}
1535
1537{
1538 struct generic_monitor_instance_list *generic_list;
1539 struct generic_monitor_instance *generic_instance;
1540 struct generic_monitor_pvt *gen_mon_pvt;
1542 int when;
1543
1544 /* First things first. Native channel drivers will have their private data allocated
1545 * at the time that they tell the core that they can offer CC. Generic is quite a bit
1546 * different, and we wait until this point to allocate our private data.
1547 */
1548 if (!(gen_mon_pvt = ast_calloc(1, sizeof(*gen_mon_pvt)))) {
1549 return -1;
1550 }
1551
1552 if (!(gen_mon_pvt->device_name = ast_strdup(monitor->interface->device_name))) {
1553 ast_free(gen_mon_pvt);
1554 return -1;
1555 }
1556
1557 gen_mon_pvt->core_id = monitor->core_id;
1558
1559 monitor->private_data = gen_mon_pvt;
1560
1561 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
1562 if (!(generic_list = create_new_generic_list(monitor))) {
1563 return -1;
1564 }
1565 }
1566
1567 if (!(generic_instance = ast_calloc(1, sizeof(*generic_instance)))) {
1568 /* The generic monitor destructor will take care of the appropriate
1569 * deallocations
1570 */
1571 cc_unref(generic_list, "Generic monitor instance failed to allocate");
1572 return -1;
1573 }
1574 generic_instance->core_id = monitor->core_id;
1575 generic_instance->monitoring = 1;
1576 AST_LIST_INSERT_TAIL(&generic_list->list, generic_instance, next);
1579
1580 *available_timer_id = ast_sched_add(cc_sched_context, when * 1000,
1581 ast_cc_available_timer_expire, cc_ref(monitor, "Give the scheduler a monitor reference"));
1582 if (*available_timer_id == -1) {
1583 cc_unref(monitor, "Failed to schedule available timer. (monitor)");
1584 cc_unref(generic_list, "Failed to schedule available timer. (generic_list)");
1585 return -1;
1586 }
1587 /* If the new instance was created as CCNR, then that means this device is not currently
1588 * fit for recall even if it previously was.
1589 */
1590 if (service == AST_CC_CCNR || service == AST_CC_CCNL) {
1591 generic_list->fit_for_recall = 0;
1592 }
1593 ast_cc_monitor_request_acked(monitor->core_id, "Generic monitor for %s subscribed to device state.",
1594 monitor->interface->device_name);
1595 cc_unref(generic_list, "Finished with monitor instance reference in request cc callback");
1596 return 0;
1597}
1598
1600{
1601 struct generic_monitor_instance_list *generic_list;
1602 struct generic_monitor_instance *generic_instance;
1604
1605 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
1606 return -1;
1607 }
1608
1609 /* First we need to mark this particular monitor as being suspended. */
1610 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1611 if (generic_instance->core_id == monitor->core_id) {
1612 generic_instance->is_suspended = 1;
1613 break;
1614 }
1615 }
1616
1617 /* If the device being suspended is currently in use, then we don't need to
1618 * take any further actions
1619 */
1621 cc_unref(generic_list, "Device is in use. Nothing to do. Unref generic list.");
1622 return 0;
1623 }
1624
1625 /* If the device is not in use, though, then it may be possible to report the
1626 * device's availability using a different monitor which is monitoring the
1627 * same device
1628 */
1629
1630 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1631 if (!generic_instance->is_suspended) {
1632 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
1633 break;
1634 }
1635 }
1636 cc_unref(generic_list, "Done with generic list in suspend callback");
1637 return 0;
1638}
1639
1641{
1642 struct generic_monitor_instance *generic_instance;
1645
1646 if (!generic_list) {
1647 return -1;
1648 }
1649 /* If the device is currently available, we can immediately announce
1650 * its availability
1651 */
1653 ast_cc_monitor_callee_available(monitor->core_id, "Generic monitored party has become available");
1654 }
1655
1656 /* In addition, we need to mark this generic_monitor_instance as not being suspended anymore */
1657 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1658 if (generic_instance->core_id == monitor->core_id) {
1659 generic_instance->is_suspended = 0;
1660 generic_instance->monitoring = 1;
1661 break;
1662 }
1663 }
1664 cc_unref(generic_list, "Done with generic list in cc_generic_monitor_unsuspend");
1665 return 0;
1666}
1667
1669{
1671
1672 if (*sched_id == -1) {
1673 return 0;
1674 }
1675
1676 ast_log_dynamic_level(cc_logger_level, "Core %d: Canceling generic monitor available timer for monitor %s\n",
1677 monitor->core_id, monitor->interface->device_name);
1679 cc_unref(monitor, "Remove scheduler's reference to the monitor");
1680 }
1681 *sched_id = -1;
1682 return 0;
1683}
1684
1685static void cc_generic_monitor_destructor(void *private_data)
1686{
1687 struct generic_monitor_pvt *gen_mon_pvt = private_data;
1688 struct generic_monitor_instance_list *generic_list;
1689 struct generic_monitor_instance *generic_instance;
1690
1691 if (!private_data) {
1692 /* If the private data is NULL, that means that the monitor hasn't even
1693 * been created yet, but that the destructor was called. While this sort
1694 * of behavior is useful for native monitors, with a generic one, there is
1695 * nothing in particular to do.
1696 */
1697 return;
1698 }
1699
1700 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying generic monitor %s\n",
1701 gen_mon_pvt->core_id, gen_mon_pvt->device_name);
1702
1703 if (!(generic_list = find_generic_monitor_instance_list(gen_mon_pvt->device_name))) {
1704 /* If there's no generic list, that means that the monitor is being destroyed
1705 * before we actually got to request CC. Not a biggie. Same in the situation
1706 * below if the list traversal should complete without finding an entry.
1707 */
1708 ast_free((char *)gen_mon_pvt->device_name);
1709 ast_free(gen_mon_pvt);
1710 return;
1711 }
1712
1713 AST_LIST_TRAVERSE_SAFE_BEGIN(&generic_list->list, generic_instance, next) {
1714 if (generic_instance->core_id == gen_mon_pvt->core_id) {
1716 ast_free(generic_instance);
1717 break;
1718 }
1719 }
1721
1722 if (AST_LIST_EMPTY(&generic_list->list)) {
1723 /* No more monitors with this device name exist. Time to unlink this
1724 * list from the container
1725 */
1726 ao2_t_unlink(generic_monitors, generic_list, "Generic list is empty. Unlink it from the container");
1727 } else {
1728 /* There are still instances for this particular device. The situation
1729 * may be that we were attempting a CC recall and a failure occurred, perhaps
1730 * on the agent side. If a failure happens here and the device being monitored
1731 * is available, then we need to signal on the first unsuspended instance that
1732 * the device is available for recall.
1733 */
1734
1735 /* First things first. We don't even want to consider this action if
1736 * the device in question isn't available right now.
1737 */
1738 if (generic_list->fit_for_recall
1740 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1741 if (!generic_instance->is_suspended && generic_instance->monitoring) {
1742 ast_cc_monitor_callee_available(generic_instance->core_id, "Signaling generic monitor "
1743 "availability due to other instance's failure.");
1744 break;
1745 }
1746 }
1747 }
1748 }
1749 cc_unref(generic_list, "Done with generic list in generic monitor destructor");
1750 ast_free((char *)gen_mon_pvt->device_name);
1751 ast_free(gen_mon_pvt);
1752}
1753
1754static void cc_interface_destroy(void *data)
1755{
1756 struct ast_cc_interface *interface = data;
1757 ast_log_dynamic_level(cc_logger_level, "Destroying cc interface %s\n", interface->device_name);
1758 ast_cc_config_params_destroy(interface->config_params);
1759}
1760
1761/*!
1762 * \brief Data regarding an extension monitor's child's dialstrings
1763 *
1764 * \details
1765 * In developing CCSS, we had most aspects of its operation finished,
1766 * but there was one looming problem that we had failed to get right.
1767 * In our design document, we stated that when a CC recall occurs, all
1768 * endpoints that had been dialed originally would be called back.
1769 * Unfortunately, our implementation only allowed for devices which had
1770 * active monitors to inhabit the CC_INTERFACES channel variable, thus
1771 * making the automated recall only call monitored devices.
1772 *
1773 * Devices that were not CC-capable, or devices which failed CC at some
1774 * point during the process would not make it into the CC_INTERFACES
1775 * channel variable. This struct is meant as a remedy for the problem.
1776 */
1778 /*!
1779 * \brief the original dialstring used to call a particular device
1780 *
1781 * \details
1782 * When someone dials a particular endpoint, the dialstring used in
1783 * the dialplan is copied into this buffer. What's important here is
1784 * that this is the ORIGINAL dialstring, not the dialstring saved on
1785 * a device monitor. The dialstring on a device monitor is what should
1786 * be used when recalling that device. The two dialstrings may not be
1787 * the same.
1788 *
1789 * By keeping a copy of the original dialstring used, we can fall back
1790 * to using it if the device either does not ever offer CC or if the
1791 * device at some point fails for some reason, such as a timer expiration.
1792 */
1794 /*!
1795 * \brief The name of the device being dialed
1796 *
1797 * \details
1798 * This serves mainly as a key when searching for a particular dialstring.
1799 * For instance, let's say that we have called device SIP/400\@somepeer. This
1800 * device offers call completion, but then due to some unforeseen circumstance,
1801 * this device backs out and makes CC unavailable. When that happens, we need
1802 * to find the dialstring that corresponds to that device, and we use the
1803 * stored device name as a way to find it.
1804 *
1805 * \note There is one particular case where the device name stored here
1806 * will be empty. This is the case where we fail to request a channel, but we
1807 * still can make use of generic call completion. In such a case, since we never
1808 * were able to request the channel, we can't find what its device name is. In
1809 * this case, however, it is not important because the dialstring is guaranteed
1810 * to be the same both here and in the device monitor.
1811 */
1813 /*!
1814 * \brief Is this structure valid for use in CC_INTERFACES?
1815 *
1816 * \details
1817 * When this structure is first created, all information stored here is planned
1818 * to be used, so we set the is_valid flag. However, if a device offers call
1819 * completion, it will potentially have its own dialstring to use for the recall,
1820 * so we find this structure and clear the is_valid flag. By clearing the is_valid
1821 * flag, we won't try to populate the CC_INTERFACES variable with the dialstring
1822 * stored in this struct. Now, if later, the device which had offered CC should fail,
1823 * perhaps due to a timer expiration, then we need to re-set the is_valid flag. This
1824 * way, we still will end up placing a call to the device again, and the dialstring
1825 * used will be the same as was originally used.
1826 */
1829};
1830
1831/*!
1832 * \brief Private data for an extension monitor
1833 */
1837
1838static void cc_extension_monitor_destructor(void *private_data)
1839{
1840 struct extension_monitor_pvt *extension_pvt = private_data;
1841 struct extension_child_dialstring *child_dialstring;
1842
1843 /* This shouldn't be possible, but I'm paranoid */
1844 if (!extension_pvt) {
1845 return;
1846 }
1847
1848 while ((child_dialstring = AST_LIST_REMOVE_HEAD(&extension_pvt->child_dialstrings, next))) {
1849 ast_free(child_dialstring);
1850 }
1851 ast_free(extension_pvt);
1852}
1853
1854static void cc_monitor_destroy(void *data)
1855{
1856 struct ast_cc_monitor *monitor = data;
1857 /* During the monitor creation process, it is possible for this
1858 * function to be called prior to when callbacks are assigned
1859 * to the monitor. Also, extension monitors do not have callbacks
1860 * assigned to them, so we wouldn't want to segfault when we try
1861 * to destroy one of them.
1862 */
1863 ast_log_dynamic_level(cc_logger_level, "Core %d: Calling destructor for monitor %s\n",
1864 monitor->core_id, monitor->interface->device_name);
1867 }
1868 if (monitor->callbacks) {
1869 monitor->callbacks->destructor(monitor->private_data);
1870 }
1871 cc_unref(monitor->interface, "Unreffing tree's reference to interface");
1872 ast_free(monitor->dialstring);
1873}
1874
1875static void cc_interface_tree_destroy(void *data)
1876{
1877 struct cc_monitor_tree *cc_interface_tree = data;
1878 struct ast_cc_monitor *monitor;
1879 while ((monitor = AST_LIST_REMOVE_HEAD(cc_interface_tree, next))) {
1880 if (monitor->callbacks) {
1881 monitor->callbacks->cancel_available_timer(monitor, &monitor->available_timer_id);
1882 }
1883 cc_unref(monitor, "Destroying all monitors");
1884 }
1885 AST_LIST_HEAD_DESTROY(cc_interface_tree);
1886}
1887
1888/*!
1889 * This counter is used for assigning unique ids
1890 * to CC-enabled dialed interfaces.
1891 */
1893
1894/*!
1895 * \internal
1896 * \brief data stored in CC datastore
1897 *
1898 * The datastore creates a list of interfaces that were
1899 * dialed, including both extensions and devices. In addition
1900 * to the intrinsic data of the tree, some extra information
1901 * is needed for use by app_dial.
1902 */
1904 /*!
1905 * This value serves a dual-purpose. When dial starts, if the
1906 * dialed_cc_interfaces datastore currently exists on the calling
1907 * channel, then the dial_parent_id will serve as a means of
1908 * letting the new extension cc_monitor we create know
1909 * who his parent is. This value will be the extension
1910 * cc_monitor that dialed the local channel that resulted
1911 * in the new Dial app being called.
1912 *
1913 * In addition, once an extension cc_monitor is created,
1914 * the dial_parent_id will be changed to the id of that newly
1915 * created interface. This way, device interfaces created from
1916 * receiving AST_CONTROL_CC frames can use this field to determine
1917 * who their parent extension interface should be.
1918 */
1919 unsigned int dial_parent_id;
1920 /*!
1921 * Identifier for the potential CC request that may be made
1922 * based on this call. Even though an instance of the core may
1923 * not be made (since the caller may not request CC), we allocate
1924 * a new core_id at the beginning of the call so that recipient
1925 * channel drivers can have the information handy just in case
1926 * the caller does end up requesting CC.
1927 */
1929 /*!
1930 * When a new Dial application is started, and the datastore
1931 * already exists on the channel, we can determine if we
1932 * should be adding any new interface information to tree.
1933 */
1935 /*!
1936 * When it comes time to offer CC to the caller, we only want to offer
1937 * it to the original incoming channel. For nested Dials and outbound
1938 * channels, it is incorrect to attempt such a thing. This flag indicates
1939 * if the channel to which this datastore is attached may be legally
1940 * offered CC when the call is finished.
1941 */
1943 /*!
1944 * Reference-counted "tree" of interfaces.
1945 */
1947};
1948
1949/*!
1950 * \internal
1951 * \brief Destructor function for cc_interfaces datastore
1952 *
1953 * This function will free the actual datastore and drop
1954 * the refcount for the monitor tree by one. In cases
1955 * where CC can actually be used, this unref will not
1956 * result in the destruction of the monitor tree, because
1957 * the CC core will still have a reference.
1958 *
1959 * \param data The dialed_cc_interfaces struct to destroy
1960 */
1961static void dialed_cc_interfaces_destroy(void *data)
1962{
1963 struct dialed_cc_interfaces *cc_interfaces = data;
1964 cc_unref(cc_interfaces->interface_tree, "Unref dial's ref to monitor tree");
1965 ast_free(cc_interfaces);
1966}
1967
1968/*!
1969 * \internal
1970 * \brief Duplicate callback for cc_interfaces datastore
1971 *
1972 * Integers are copied by value, but the monitor tree
1973 * is done via a shallow copy and a bump of the refcount.
1974 * This way, sub-Dials will be appending interfaces onto
1975 * the same list as this call to Dial.
1976 *
1977 * \param data The old dialed_cc_interfaces we want to copy
1978 * \retval NULL Could not allocate memory for new dialed_cc_interfaces
1979 * \retval non-NULL The new copy of the dialed_cc_interfaces
1980 */
1981static void *dialed_cc_interfaces_duplicate(void *data)
1982{
1983 struct dialed_cc_interfaces *old_cc_interfaces = data;
1984 struct dialed_cc_interfaces *new_cc_interfaces = ast_calloc(1, sizeof(*new_cc_interfaces));
1985 if (!new_cc_interfaces) {
1986 return NULL;
1987 }
1988 new_cc_interfaces->ignore = old_cc_interfaces->ignore;
1989 new_cc_interfaces->dial_parent_id = old_cc_interfaces->dial_parent_id;
1990 new_cc_interfaces->is_original_caller = 0;
1991 cc_ref(old_cc_interfaces->interface_tree, "New ref due to duplication of monitor tree");
1992 new_cc_interfaces->core_id = old_cc_interfaces->core_id;
1993 new_cc_interfaces->interface_tree = old_cc_interfaces->interface_tree;
1994 return new_cc_interfaces;
1995}
1996
1997/*!
1998 * \internal
1999 * \brief information regarding the dialed_cc_interfaces datastore
2000 *
2001 * The dialed_cc_interfaces datastore is responsible for keeping track
2002 * of what CC-enabled interfaces have been dialed by the caller. For
2003 * more information regarding the actual structure of the tree, see
2004 * the documentation provided in include/asterisk/ccss.h
2005 */
2007 .type = "Dial CC Interfaces",
2008 .duplicate = dialed_cc_interfaces_duplicate,
2010};
2011
2013{
2014 struct extension_monitor_pvt *ext_pvt = ast_calloc(1, sizeof(*ext_pvt));
2015 if (!ext_pvt) {
2016 return NULL;
2017 }
2019 return ext_pvt;
2020}
2021
2022void ast_cc_extension_monitor_add_dialstring(struct ast_channel *incoming, const char * const dialstring, const char * const device_name)
2023{
2024 struct ast_datastore *cc_datastore;
2025 struct dialed_cc_interfaces *cc_interfaces;
2026 struct ast_cc_monitor *monitor;
2027 struct extension_monitor_pvt *extension_pvt;
2028 struct extension_child_dialstring *child_dialstring;
2029 struct cc_monitor_tree *interface_tree;
2030 int id;
2031
2033
2034 ast_channel_lock(incoming);
2035 if (!(cc_datastore = ast_channel_datastore_find(incoming, &dialed_cc_interfaces_info, NULL))) {
2036 ast_channel_unlock(incoming);
2037 return;
2038 }
2039
2040 cc_interfaces = cc_datastore->data;
2041 interface_tree = cc_interfaces->interface_tree;
2042 id = cc_interfaces->dial_parent_id;
2043 ast_channel_unlock(incoming);
2044
2045 AST_LIST_LOCK(interface_tree);
2046 AST_LIST_TRAVERSE(interface_tree, monitor, next) {
2047 if (monitor->id == id) {
2048 break;
2049 }
2050 }
2051
2052 if (!monitor) {
2053 AST_LIST_UNLOCK(interface_tree);
2054 return;
2055 }
2056
2057 extension_pvt = monitor->private_data;
2058 if (!(child_dialstring = ast_calloc(1, sizeof(*child_dialstring)))) {
2059 AST_LIST_UNLOCK(interface_tree);
2060 return;
2061 }
2062 ast_copy_string(child_dialstring->original_dialstring, dialstring, sizeof(child_dialstring->original_dialstring));
2063 ast_copy_string(child_dialstring->device_name, device_name, sizeof(child_dialstring->device_name));
2064 child_dialstring->is_valid = 1;
2065 AST_LIST_INSERT_TAIL(&extension_pvt->child_dialstrings, child_dialstring, next);
2066 AST_LIST_UNLOCK(interface_tree);
2067}
2068
2069static void cc_extension_monitor_change_is_valid(struct cc_core_instance *core_instance, unsigned int parent_id, const char * const device_name, int is_valid)
2070{
2071 struct ast_cc_monitor *monitor_iter;
2072 struct extension_monitor_pvt *extension_pvt;
2073 struct extension_child_dialstring *child_dialstring;
2074
2075 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
2076 if (monitor_iter->id == parent_id) {
2077 break;
2078 }
2079 }
2080
2081 if (!monitor_iter) {
2082 return;
2083 }
2084 extension_pvt = monitor_iter->private_data;
2085
2086 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
2087 if (!strcmp(child_dialstring->device_name, device_name)) {
2088 child_dialstring->is_valid = is_valid;
2089 break;
2090 }
2091 }
2092}
2093
2094/*!
2095 * \internal
2096 * \brief Allocate and initialize an "extension" interface for CC purposes
2097 *
2098 * When app_dial starts, this function is called in order to set up the
2099 * information about the extension in which this Dial is occurring. Any
2100 * devices dialed will have this particular cc_monitor as a parent.
2101 *
2102 * \param exten Extension from which Dial is occurring
2103 * \param context Context to which exten belongs
2104 * \param parent_id What should we set the parent_id of this interface to?
2105 * \retval NULL Memory allocation failure
2106 * \retval non-NULL The newly-created cc_monitor for the extension
2107 */
2108static struct ast_cc_monitor *cc_extension_monitor_init(const char * const exten, const char * const context, const unsigned int parent_id)
2109{
2111 struct ast_cc_interface *cc_interface;
2112 struct ast_cc_monitor *monitor;
2113
2114 ast_str_set(&str, 0, "%s@%s", exten, context);
2115
2116 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + ast_str_strlen(str), cc_interface_destroy,
2117 "Allocating new ast_cc_interface"))) {
2118 return NULL;
2119 }
2120
2121 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
2122 cc_unref(cc_interface, "failed to allocate the monitor, so unref the interface");
2123 return NULL;
2124 }
2125
2126 if (!(monitor->private_data = extension_monitor_pvt_init())) {
2127 cc_unref(monitor, "Failed to initialize extension monitor private data. uref monitor");
2128 cc_unref(cc_interface, "Failed to initialize extension monitor private data. unref cc_interface");
2129 }
2130
2132 monitor->parent_id = parent_id;
2133 cc_interface->monitor_type = "extension";
2135 strcpy(cc_interface->device_name, ast_str_buffer(str));
2136 monitor->interface = cc_interface;
2137 ast_log_dynamic_level(cc_logger_level, "Created an extension cc interface for '%s' with id %u and parent %u\n", cc_interface->device_name, monitor->id, monitor->parent_id);
2138 return monitor;
2139}
2140
2141/*!
2142 * \internal
2143 * \brief allocate dialed_cc_interfaces datastore and initialize fields
2144 *
2145 * This function is called when Situation 1 occurs in ast_cc_call_init.
2146 * See that function for more information on what Situation 1 is.
2147 *
2148 * In this particular case, we have to do a lot of memory allocation in order
2149 * to create the datastore, the data for the datastore, the tree of interfaces
2150 * that we'll be adding to, and the initial extension interface for this Dial
2151 * attempt.
2152 *
2153 * \param chan The channel onto which the datastore should be added.
2154 * \retval -1 An error occurred
2155 * \retval 0 Success
2156 */
2159 struct ast_cc_monitor *monitor;
2160 struct ast_datastore *dial_cc_datastore;
2161
2162 /*XXX This may be a bit controversial. In an attempt to not allocate
2163 * extra resources, I make sure that a future request will be within
2164 * limits. The problem here is that it is reasonable to think that
2165 * even if we're not within the limits at this point, we may be by
2166 * the time the requestor will have made his request. This may be
2167 * deleted at some point.
2168 */
2170 return 0;
2171 }
2172
2173 if (!(interfaces = ast_calloc(1, sizeof(*interfaces)))) {
2174 return -1;
2175 }
2176
2177 if (!(monitor = cc_extension_monitor_init(ast_channel_exten(chan), ast_channel_context(chan), 0))) {
2179 return -1;
2180 }
2181
2182 if (!(dial_cc_datastore = ast_datastore_alloc(&dialed_cc_interfaces_info, NULL))) {
2183 cc_unref(monitor, "Could not allocate the dialed interfaces datastore. Unreffing monitor");
2185 return -1;
2186 }
2187
2188 if (!(interfaces->interface_tree = ao2_t_alloc(sizeof(*interfaces->interface_tree), cc_interface_tree_destroy,
2189 "Allocate monitor tree"))) {
2190 ast_datastore_free(dial_cc_datastore);
2191 cc_unref(monitor, "Could not allocate monitor tree on dialed interfaces datastore. Unreffing monitor");
2193 return -1;
2194 }
2195
2196 /* Finally, all that allocation is done... */
2197 AST_LIST_HEAD_INIT(interfaces->interface_tree);
2198 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
2199 cc_ref(monitor, "List's reference to extension monitor");
2200 dial_cc_datastore->data = interfaces;
2201 dial_cc_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
2202 interfaces->dial_parent_id = monitor->id;
2203 interfaces->core_id = monitor->core_id = ast_atomic_fetchadd_int(&core_id_counter, +1);
2204 interfaces->is_original_caller = 1;
2205 ast_channel_lock(chan);
2206 ast_channel_datastore_add(chan, dial_cc_datastore);
2207 ast_channel_unlock(chan);
2208 cc_unref(monitor, "Unreffing allocation's reference");
2209 return 0;
2210}
2211
2212/*!
2213 * \internal
2214 * \brief Call a monitor's destructor before the monitor has been allocated
2215 * \since 1.8
2216 *
2217 * \param monitor_type The type of monitor callbacks to use when calling the destructor
2218 * \param private_data Data allocated by a channel driver that must be freed
2219 *
2220 * \details
2221 * I'll admit, this is a bit evil.
2222 *
2223 * When a channel driver determines that it can offer a call completion service to
2224 * a caller, it is very likely that the channel driver will need to allocate some
2225 * data so that when the time comes to request CC, the channel driver will have the
2226 * necessary data at hand.
2227 *
2228 * The problem is that there are many places where failures may occur before the monitor
2229 * has been properly allocated and had its callbacks assigned to it. If one of these
2230 * failures should occur, then we still need to let the channel driver know that it
2231 * must destroy the data that it allocated.
2232 */
2233static void call_destructor_with_no_monitor(const char * const monitor_type, void *private_data)
2234{
2235 const struct ast_cc_monitor_callbacks *monitor_callbacks = find_monitor_callbacks(monitor_type);
2236
2237 if (!monitor_callbacks) {
2238 return;
2239 }
2240
2241 monitor_callbacks->destructor(private_data);
2242}
2243
2244/*!
2245 * \internal
2246 * \brief Allocate and initialize a device cc_monitor
2247 *
2248 * For all intents and purposes, this is the same as
2249 * cc_extension_monitor_init, except that there is only
2250 * a single parameter used for naming the interface.
2251 *
2252 * This function is called when handling AST_CONTROL_CC frames.
2253 * The device has reported that CC is possible, so we add it
2254 * to the interface_tree.
2255 *
2256 * Note that it is not necessarily erroneous to add the same
2257 * device to the tree twice. If the same device is called by
2258 * two different extension during the same call, then
2259 * that is a legitimate situation.
2260 *
2261 * \param device_name The name of the device being added to the tree
2262 * \param dialstring The dialstring used to dial the device being added
2263 * \param core_id
2264 * \param cc_data
2265 * \retval NULL Memory allocation failure
2266 * \retval non-NULL The new ast_cc_interface created.
2267 */
2268static struct ast_cc_monitor *cc_device_monitor_init(const char * const device_name, const char * const dialstring, const struct cc_control_payload *cc_data, int core_id)
2269{
2270 struct ast_cc_interface *cc_interface;
2271 struct ast_cc_monitor *monitor;
2272 size_t device_name_len = strlen(device_name);
2273 int parent_id = cc_data->parent_interface_id;
2274
2275 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + device_name_len, cc_interface_destroy,
2276 "Allocating new ast_cc_interface"))) {
2277 return NULL;
2278 }
2279
2280 if (!(cc_interface->config_params = ast_cc_config_params_init())) {
2281 cc_unref(cc_interface, "Failed to allocate config params, unref interface");
2282 return NULL;
2283 }
2284
2285 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
2286 cc_unref(cc_interface, "Failed to allocate monitor, unref interface");
2287 return NULL;
2288 }
2289
2290 if (!(monitor->dialstring = ast_strdup(dialstring))) {
2291 cc_unref(monitor, "Failed to copy dialable name. Unref monitor");
2292 cc_unref(cc_interface, "Failed to copy dialable name");
2293 return NULL;
2294 }
2295
2296 if (!(monitor->callbacks = find_monitor_callbacks(cc_data->monitor_type))) {
2297 cc_unref(monitor, "Failed to find monitor callbacks. Unref monitor");
2298 cc_unref(cc_interface, "Failed to find monitor callbacks");
2299 return NULL;
2300 }
2301
2302 strcpy(cc_interface->device_name, device_name);
2304 monitor->parent_id = parent_id;
2305 monitor->core_id = core_id;
2306 monitor->service_offered = cc_data->service;
2307 monitor->private_data = cc_data->private_data;
2308 cc_interface->monitor_type = cc_data->monitor_type;
2309 cc_interface->monitor_class = AST_CC_DEVICE_MONITOR;
2310 monitor->interface = cc_interface;
2311 monitor->available_timer_id = -1;
2312 ast_cc_copy_config_params(cc_interface->config_params, &cc_data->config_params);
2313 ast_log_dynamic_level(cc_logger_level, "Core %d: Created a device cc interface for '%s' with id %u and parent %u\n",
2314 monitor->core_id, cc_interface->device_name, monitor->id, monitor->parent_id);
2315 return monitor;
2316}
2317
2318/*!
2319 * \details
2320 * Unless we are ignoring CC for some reason, we will always
2321 * call this function when we read an AST_CONTROL_CC frame
2322 * from an outbound channel.
2323 *
2324 * This function will call cc_device_monitor_init to
2325 * create the new cc_monitor for the device from which
2326 * we read the frame. In addition, the new device will be added
2327 * to the monitor tree on the dialed_cc_interfaces datastore
2328 * on the inbound channel.
2329 *
2330 * If this is the first AST_CONTROL_CC frame that we have handled
2331 * for this call, then we will also initialize the CC core for
2332 * this call.
2333 */
2334void ast_handle_cc_control_frame(struct ast_channel *inbound, struct ast_channel *outbound, void *frame_data)
2335{
2336 char *device_name;
2337 char *dialstring;
2338 struct ast_cc_monitor *monitor;
2339 struct ast_datastore *cc_datastore;
2340 struct dialed_cc_interfaces *cc_interfaces;
2341 struct cc_control_payload *cc_data = frame_data;
2342 struct cc_core_instance *core_instance;
2343
2345
2346 device_name = cc_data->device_name;
2347 dialstring = cc_data->dialstring;
2348
2349 ast_channel_lock(inbound);
2350 if (!(cc_datastore = ast_channel_datastore_find(inbound, &dialed_cc_interfaces_info, NULL))) {
2351 ast_log(LOG_WARNING, "Unable to retrieve CC datastore while processing CC frame from '%s'. CC services will be unavailable.\n", device_name);
2352 ast_channel_unlock(inbound);
2354 return;
2355 }
2356
2357 cc_interfaces = cc_datastore->data;
2358
2359 if (cc_interfaces->ignore) {
2360 ast_channel_unlock(inbound);
2362 return;
2363 }
2364
2365 if (!cc_interfaces->is_original_caller) {
2366 /* If the is_original_caller is not set on the *inbound* channel, then
2367 * it must be a local channel. As such, we do not want to create a core instance
2368 * or an agent for the local channel. Instead, we want to pass this along to the
2369 * other side of the local channel so that the original caller can benefit.
2370 */
2371 ast_channel_unlock(inbound);
2372 ast_indicate_data(inbound, AST_CONTROL_CC, cc_data, sizeof(*cc_data));
2373 return;
2374 }
2375
2376 core_instance = find_cc_core_instance(cc_interfaces->core_id);
2377 if (!core_instance) {
2378 core_instance = cc_core_init_instance(inbound, cc_interfaces->interface_tree,
2379 cc_interfaces->core_id, cc_data);
2380 if (!core_instance) {
2381 cc_interfaces->ignore = 1;
2382 ast_channel_unlock(inbound);
2384 return;
2385 }
2386 }
2387
2388 ast_channel_unlock(inbound);
2389
2390 /* Yeah this kind of sucks, but luckily most people
2391 * aren't dialing thousands of interfaces on every call
2392 *
2393 * This traversal helps us to not create duplicate monitors in
2394 * case a device queues multiple CC control frames.
2395 */
2396 AST_LIST_LOCK(cc_interfaces->interface_tree);
2397 AST_LIST_TRAVERSE(cc_interfaces->interface_tree, monitor, next) {
2398 if (!strcmp(monitor->interface->device_name, device_name)) {
2399 ast_log_dynamic_level(cc_logger_level, "Core %d: Device %s sent us multiple CC control frames. Ignoring those beyond the first.\n",
2400 core_instance->core_id, device_name);
2401 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2402 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
2404 return;
2405 }
2406 }
2407 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2408
2409 if (!(monitor = cc_device_monitor_init(device_name, dialstring, cc_data, core_instance->core_id))) {
2410 ast_log(LOG_WARNING, "Unable to create CC device interface for '%s'. CC services will be unavailable on this interface.\n", device_name);
2411 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
2413 return;
2414 }
2415
2416 AST_LIST_LOCK(cc_interfaces->interface_tree);
2417 cc_ref(monitor, "monitor tree's reference to the monitor");
2418 AST_LIST_INSERT_TAIL(cc_interfaces->interface_tree, monitor, next);
2419 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2420
2421 cc_extension_monitor_change_is_valid(core_instance, monitor->parent_id, monitor->interface->device_name, 0);
2422
2423 cc_publish_available(cc_interfaces->core_id, device_name, cc_service_to_string(cc_data->service));
2424
2425 cc_unref(core_instance, "Done with core_instance after handling CC control frame");
2426 cc_unref(monitor, "Unref reference from allocating monitor");
2427}
2428
2429int ast_cc_call_init(struct ast_channel *chan, int *ignore_cc)
2430{
2431 /* There are three situations to deal with here:
2432 *
2433 * 1. The channel does not have a dialed_cc_interfaces datastore on
2434 * it. This means that this is the first time that Dial has
2435 * been called. We need to create/initialize the datastore.
2436 *
2437 * 2. The channel does have a cc_interface datastore on it and
2438 * the "ignore" indicator is 0. This means that a Local channel
2439 * was called by a "parent" dial. We can check the datastore's
2440 * parent field to see who the root of this particular dial tree
2441 * is.
2442 *
2443 * 3. The channel does have a cc_interface datastore on it and
2444 * the "ignore" indicator is 1. This means that a second Dial call
2445 * is being made from an extension. In this case, we do not
2446 * want to make any additions/modifications to the datastore. We
2447 * will instead set a flag to indicate that CCSS is completely
2448 * disabled for this Dial attempt.
2449 */
2450
2451 struct ast_datastore *cc_interfaces_datastore;
2453 struct ast_cc_monitor *monitor;
2454 struct ast_cc_config_params *cc_params;
2455
2456 if (!global_enabled) {
2457 ast_debug(3, "CCSS disabled globally\n");
2458 *ignore_cc = 1;
2459 return 0;
2460 }
2461
2462 ast_channel_lock(chan);
2463
2464 cc_params = ast_channel_get_cc_config_params(chan);
2465 if (!cc_params) {
2466 ast_channel_unlock(chan);
2467 return -1;
2468 }
2469 if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_NEVER) {
2470 /* We can't offer CC to this caller anyway, so don't bother with CC on this call
2471 */
2472 *ignore_cc = 1;
2473 ast_channel_unlock(chan);
2474 ast_log_dynamic_level(cc_logger_level, "Agent policy for %s is 'never'. CC not possible\n", ast_channel_name(chan));
2475 return 0;
2476 }
2477
2478 if (!(cc_interfaces_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
2479 /* Situation 1 has occurred */
2480 ast_channel_unlock(chan);
2481 return cc_interfaces_datastore_init(chan);
2482 }
2483 interfaces = cc_interfaces_datastore->data;
2484 ast_channel_unlock(chan);
2485
2486 if (interfaces->ignore) {
2487 /* Situation 3 has occurred */
2488 *ignore_cc = 1;
2489 ast_log_dynamic_level(cc_logger_level, "Datastore is present with ignore flag set. Ignoring CC offers on this call\n");
2490 return 0;
2491 }
2492
2493 /* Situation 2 has occurred */
2494 if (!(monitor = cc_extension_monitor_init(ast_channel_exten(chan),
2495 ast_channel_context(chan),
2496 interfaces->dial_parent_id))) {
2497 return -1;
2498 }
2499 monitor->core_id = interfaces->core_id;
2500 AST_LIST_LOCK(interfaces->interface_tree);
2501 cc_ref(monitor, "monitor tree's reference to the monitor");
2502 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
2503 AST_LIST_UNLOCK(interfaces->interface_tree);
2504 interfaces->dial_parent_id = monitor->id;
2505 cc_unref(monitor, "Unref monitor's allocation reference");
2506 return 0;
2507}
2508
2513
2515{
2516 struct ast_datastore *datastore;
2517 struct dialed_cc_interfaces *cc_interfaces;
2518 int core_id_return;
2519
2521
2522 ast_channel_lock(chan);
2523 if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
2524 ast_channel_unlock(chan);
2525 return -1;
2526 }
2527
2528 cc_interfaces = datastore->data;
2529 core_id_return = cc_interfaces->ignore ? -1 : cc_interfaces->core_id;
2530 ast_channel_unlock(chan);
2531 return core_id_return;
2532
2533}
2534
2535static long count_agents(const char * const caller, const int core_id_exception)
2536{
2538
2539 ao2_t_callback_data(cc_core_instances, OBJ_NODATA, count_agents_cb, (char *)caller, &data, "Counting agents");
2540 ast_log_dynamic_level(cc_logger_level, "Counted %d agents\n", data.count);
2541 return data.count;
2542}
2543
2544static void kill_duplicate_offers(char *caller)
2545{
2546 unsigned long match_flags = MATCH_NO_REQUEST;
2547 struct ao2_iterator *dups_iter;
2548
2549 /*
2550 * Must remove the ref that was in cc_core_instances outside of
2551 * the container lock to prevent deadlock.
2552 */
2554 match_agent, caller, &match_flags, "Killing duplicate offers");
2555 if (dups_iter) {
2556 /* Now actually unref any duplicate offers by simply destroying the iterator. */
2557 ao2_iterator_destroy(dups_iter);
2558 }
2559}
2560
2562{
2563 ast_assert(callbacks->init != NULL);
2564 ast_assert(callbacks->start_offer_timer != NULL);
2565 ast_assert(callbacks->stop_offer_timer != NULL);
2566 ast_assert(callbacks->respond != NULL);
2567 ast_assert(callbacks->status_request != NULL);
2568 ast_assert(callbacks->start_monitoring != NULL);
2569 ast_assert(callbacks->callee_available != NULL);
2570 ast_assert(callbacks->destructor != NULL);
2571}
2572
2573static void agent_destroy(void *data)
2574{
2575 struct ast_cc_agent *agent = data;
2576
2577 if (agent->callbacks) {
2578 agent->callbacks->destructor(agent);
2579 }
2581}
2582
2583static struct ast_cc_agent *cc_agent_init(struct ast_channel *caller_chan,
2584 const char * const caller_name, const int core_id,
2585 struct cc_monitor_tree *interface_tree)
2586{
2587 struct ast_cc_agent *agent;
2588 struct ast_cc_config_params *cc_params;
2589
2590 if (!(agent = ao2_t_alloc(sizeof(*agent) + strlen(caller_name), agent_destroy,
2591 "Allocating new ast_cc_agent"))) {
2592 return NULL;
2593 }
2594
2595 agent->core_id = core_id;
2596 strcpy(agent->device_name, caller_name);
2597
2598 cc_params = ast_channel_get_cc_config_params(caller_chan);
2599 if (!cc_params) {
2600 cc_unref(agent, "Could not get channel config params.");
2601 return NULL;
2602 }
2603 if (!(agent->cc_params = ast_cc_config_params_init())) {
2604 cc_unref(agent, "Could not init agent config params.");
2605 return NULL;
2606 }
2607 ast_cc_copy_config_params(agent->cc_params, cc_params);
2608
2609 if (!(agent->callbacks = find_agent_callbacks(caller_chan))) {
2610 cc_unref(agent, "Could not find agent callbacks.");
2611 return NULL;
2612 }
2614
2615 if (agent->callbacks->init(agent, caller_chan)) {
2616 cc_unref(agent, "Agent init callback failed.");
2617 return NULL;
2618 }
2619 ast_log_dynamic_level(cc_logger_level, "Core %u: Created an agent for caller %s\n",
2620 agent->core_id, agent->device_name);
2621 return agent;
2622}
2623
2624/* Generic agent callbacks */
2625static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan);
2626static int cc_generic_agent_start_offer_timer(struct ast_cc_agent *agent);
2627static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent);
2628static void cc_generic_agent_respond(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason);
2629static int cc_generic_agent_status_request(struct ast_cc_agent *agent);
2630static int cc_generic_agent_stop_ringing(struct ast_cc_agent *agent);
2631static int cc_generic_agent_start_monitoring(struct ast_cc_agent *agent);
2632static int cc_generic_agent_recall(struct ast_cc_agent *agent);
2633static void cc_generic_agent_destructor(struct ast_cc_agent *agent);
2634
2636 .type = "generic",
2637 .init = cc_generic_agent_init,
2638 .start_offer_timer = cc_generic_agent_start_offer_timer,
2639 .stop_offer_timer = cc_generic_agent_stop_offer_timer,
2640 .respond = cc_generic_agent_respond,
2641 .status_request = cc_generic_agent_status_request,
2642 .stop_ringing = cc_generic_agent_stop_ringing,
2643 .start_monitoring = cc_generic_agent_start_monitoring,
2644 .callee_available = cc_generic_agent_recall,
2645 .destructor = cc_generic_agent_destructor,
2646};
2647
2649 /*!
2650 * Subscription to device state
2651 *
2652 * Used in the CC_CALLER_BUSY state. The
2653 * generic agent will subscribe to the
2654 * device state of the caller in order to
2655 * determine when we may move on
2656 */
2658 /*!
2659 * Scheduler id of offer timer.
2660 */
2662 /*!
2663 * Caller ID number
2664 *
2665 * When we re-call the caller, we need
2666 * to provide this information to
2667 * ast_request_and_dial so that the
2668 * information will be present in the
2669 * call to the callee
2670 */
2672 /*!
2673 * Caller ID name
2674 *
2675 * See the description of cid_num.
2676 * The same applies here, except this
2677 * is the caller's name.
2678 */
2680 /*!
2681 * Extension dialed
2682 *
2683 * The original extension dialed. This is used
2684 * so that when performing a recall, we can
2685 * call the proper extension.
2686 */
2688 /*!
2689 * Context dialed
2690 *
2691 * The original context dialed. This is used
2692 * so that when performing a recall, we can
2693 * call into the proper context
2694 */
2696};
2697
2698static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
2699{
2700 struct cc_generic_agent_pvt *generic_pvt = ast_calloc(1, sizeof(*generic_pvt));
2701
2702 if (!generic_pvt) {
2703 return -1;
2704 }
2705
2706 generic_pvt->offer_timer_id = -1;
2707 if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) {
2708 ast_copy_string(generic_pvt->cid_num, ast_channel_caller(chan)->id.number.str, sizeof(generic_pvt->cid_num));
2709 }
2710 if (ast_channel_caller(chan)->id.name.valid && ast_channel_caller(chan)->id.name.str) {
2711 ast_copy_string(generic_pvt->cid_name, ast_channel_caller(chan)->id.name.str, sizeof(generic_pvt->cid_name));
2712 }
2713 ast_copy_string(generic_pvt->exten, ast_channel_exten(chan), sizeof(generic_pvt->exten));
2714 ast_copy_string(generic_pvt->context, ast_channel_context(chan), sizeof(generic_pvt->context));
2715 agent->private_data = generic_pvt;
2717 return 0;
2718}
2719
2720static int offer_timer_expire(const void *data)
2721{
2722 struct ast_cc_agent *agent = (struct ast_cc_agent *) data;
2724 ast_log_dynamic_level(cc_logger_level, "Core %u: Queuing change request because offer timer has expired.\n",
2725 agent->core_id);
2726 agent_pvt->offer_timer_id = -1;
2727 ast_cc_failed(agent->core_id, "Generic agent %s offer timer expired", agent->device_name);
2728 cc_unref(agent, "Remove scheduler's reference to the agent");
2729 return 0;
2730}
2731
2733{
2734 int when;
2735 int sched_id;
2736 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2737
2739 ast_assert(agent->cc_params != NULL);
2740
2741 when = ast_get_cc_offer_timer(agent->cc_params) * 1000;
2742 ast_log_dynamic_level(cc_logger_level, "Core %u: About to schedule offer timer expiration for %d ms\n",
2743 agent->core_id, when);
2744 if ((sched_id = ast_sched_add(cc_sched_context, when, offer_timer_expire, cc_ref(agent, "Give scheduler an agent ref"))) == -1) {
2745 return -1;
2746 }
2747 generic_pvt->offer_timer_id = sched_id;
2748 return 0;
2749}
2750
2752{
2753 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2754
2755 if (generic_pvt->offer_timer_id != -1) {
2756 if (!ast_sched_del(cc_sched_context, generic_pvt->offer_timer_id)) {
2757 cc_unref(agent, "Remove scheduler's reference to the agent");
2758 }
2759 generic_pvt->offer_timer_id = -1;
2760 }
2761 return 0;
2762}
2763
2765{
2766 /* The generic agent doesn't have to do anything special to
2767 * acknowledge a CC request. Just return.
2768 */
2769 return;
2770}
2771
2773{
2775 return 0;
2776}
2777
2779{
2780 struct ast_channel *recall_chan = ast_channel_get_by_name_prefix(agent->device_name, strlen(agent->device_name));
2781
2782 if (!recall_chan) {
2783 return 0;
2784 }
2785
2787 return 0;
2788}
2789
2790static void generic_agent_devstate_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
2791{
2792 struct ast_cc_agent *agent = userdata;
2793 enum ast_device_state new_state;
2794 struct ast_device_state_message *dev_state;
2795 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2796
2798 cc_unref(agent, "Done holding ref for subscription");
2799 return;
2801 return;
2802 }
2803
2804 dev_state = stasis_message_data(msg);
2805 if (dev_state->eid) {
2806 /* ignore non-aggregate states */
2807 return;
2808 }
2809
2810 new_state = dev_state->state;
2811 if (!cc_generic_is_device_available(new_state)) {
2812 /* Not interested in this new state of the device. It is still busy. */
2813 return;
2814 }
2815
2816 generic_pvt->sub = stasis_unsubscribe(sub);
2817 ast_cc_agent_caller_available(agent->core_id, "%s is no longer busy", agent->device_name);
2818}
2819
2821{
2822 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2823 struct ast_str *str = ast_str_alloca(128);
2824 struct stasis_topic *device_specific_topic;
2825
2826 ast_assert(generic_pvt->sub == NULL);
2827 ast_str_set(&str, 0, "Agent monitoring %s device state since it is busy\n",
2828 agent->device_name);
2829
2830 device_specific_topic = ast_device_state_topic(agent->device_name);
2831 if (!device_specific_topic) {
2832 return -1;
2833 }
2834
2835 if (!(generic_pvt->sub = stasis_subscribe(device_specific_topic, generic_agent_devstate_cb, agent))) {
2836 return -1;
2837 }
2841 cc_ref(agent, "Ref agent for subscription");
2842 return 0;
2843}
2844
2845static void *generic_recall(void *data)
2846{
2847 struct ast_cc_agent *agent = data;
2848 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2849 const char *interface = S_OR(ast_get_cc_agent_dialstring(agent->cc_params), ast_strdupa(agent->device_name));
2850 const char *tech;
2851 char *target;
2852 int reason;
2853 struct ast_channel *chan;
2854 const char *callback_sub = ast_get_cc_callback_sub(agent->cc_params);
2855 unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000;
2857
2858 if (!tmp_cap) {
2859 return NULL;
2860 }
2861
2862 tech = interface;
2863 if ((target = strchr(interface, '/'))) {
2864 *target++ = '\0';
2865 }
2866
2868 if (!(chan = ast_request_and_dial(tech, tmp_cap, NULL, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) {
2869 /* Hmm, no channel. Sucks for you, bud.
2870 */
2871 ast_log_dynamic_level(cc_logger_level, "Core %u: Failed to call back %s for reason %d\n",
2872 agent->core_id, agent->device_name, reason);
2873 ast_cc_failed(agent->core_id, "Failed to call back device %s/%s", tech, target);
2874 ao2_ref(tmp_cap, -1);
2875 return NULL;
2876 }
2877 ao2_ref(tmp_cap, -1);
2878
2879 /* We have a channel. It's time now to set up the datastore of recalled CC interfaces.
2880 * This will be a common task for all recall functions. If it were possible, I'd have
2881 * the core do it automatically, but alas I cannot. Instead, I will provide a public
2882 * function to do so.
2883 */
2886
2887 ast_channel_exten_set(chan, generic_pvt->exten);
2888 ast_channel_context_set(chan, generic_pvt->context);
2889 ast_channel_priority_set(chan, 1);
2890
2891 pbx_builtin_setvar_helper(chan, "CC_EXTEN", generic_pvt->exten);
2892 pbx_builtin_setvar_helper(chan, "CC_CONTEXT", generic_pvt->context);
2893
2894 if (!ast_strlen_zero(callback_sub)) {
2895 ast_log_dynamic_level(cc_logger_level, "Core %u: There's a callback subroutine configured for agent %s\n",
2896 agent->core_id, agent->device_name);
2897 if (ast_app_exec_sub(NULL, chan, callback_sub, 0)) {
2898 ast_cc_failed(agent->core_id, "Callback subroutine to %s failed. Maybe a hangup?", agent->device_name);
2899 ast_hangup(chan);
2900 return NULL;
2901 }
2902 }
2903 if (ast_pbx_start(chan)) {
2904 ast_cc_failed(agent->core_id, "PBX failed to start for %s.", agent->device_name);
2905 ast_hangup(chan);
2906 return NULL;
2907 }
2908 ast_cc_agent_recalling(agent->core_id, "Generic agent %s is recalling",
2909 agent->device_name);
2910 return NULL;
2911}
2912
2913static int cc_generic_agent_recall(struct ast_cc_agent *agent)
2914{
2915 pthread_t clotho;
2916 enum ast_device_state current_state = ast_device_state(agent->device_name);
2917
2918 if (!cc_generic_is_device_available(current_state)) {
2919 /* We can't try to contact the device right now because he's not available
2920 * Let the core know he's busy.
2921 */
2922 ast_cc_agent_caller_busy(agent->core_id, "Generic agent caller %s is busy", agent->device_name);
2923 return 0;
2924 }
2926 return 0;
2927}
2928
2930{
2932
2933 if (!agent_pvt) {
2934 /* The agent constructor probably failed. */
2935 return;
2936 }
2937
2939 if (agent_pvt->sub) {
2941 }
2942
2944}
2945
2946static void cc_core_instance_destructor(void *data)
2947{
2948 struct cc_core_instance *core_instance = data;
2949 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying core instance\n", core_instance->core_id);
2950 if (core_instance->agent) {
2951 cc_unref(core_instance->agent, "Core instance is done with the agent now");
2952 }
2953 if (core_instance->monitors) {
2954 core_instance->monitors = cc_unref(core_instance->monitors, "Core instance is done with interface list");
2955 }
2956}
2957
2958static struct cc_core_instance *cc_core_init_instance(struct ast_channel *caller_chan,
2959 struct cc_monitor_tree *called_tree, const int core_id, struct cc_control_payload *cc_data)
2960{
2961 char caller[AST_CHANNEL_NAME];
2962 struct cc_core_instance *core_instance;
2963 struct ast_cc_config_params *cc_params;
2964 long agent_count;
2965 int recall_core_id;
2966
2967 ast_channel_get_device_name(caller_chan, caller, sizeof(caller));
2968 cc_params = ast_channel_get_cc_config_params(caller_chan);
2969 if (!cc_params) {
2970 ast_log_dynamic_level(cc_logger_level, "Could not get CC parameters for %s\n",
2971 caller);
2972 return NULL;
2973 }
2974 /* First, we need to kill off other pending CC offers from caller. If the caller is going
2975 * to request a CC service, it may only be for the latest call he made.
2976 */
2978 kill_duplicate_offers(caller);
2979 }
2980
2981 ast_cc_is_recall(caller_chan, &recall_core_id, NULL);
2982 agent_count = count_agents(caller, recall_core_id);
2983 if (agent_count >= ast_get_cc_max_agents(cc_params)) {
2984 ast_log_dynamic_level(cc_logger_level, "Caller %s already has the maximum number of agents configured\n", caller);
2985 return NULL;
2986 }
2987
2988 /* Generic agents can only have a single outstanding CC request per caller. */
2989 if (agent_count > 0 && ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) {
2990 ast_log_dynamic_level(cc_logger_level, "Generic agents can only have a single outstanding request\n");
2991 return NULL;
2992 }
2993
2994 /* Next, we need to create the core instance for this call */
2995 if (!(core_instance = ao2_t_alloc(sizeof(*core_instance), cc_core_instance_destructor, "Creating core instance for CC"))) {
2996 return NULL;
2997 }
2998
2999 core_instance->core_id = core_id;
3000 if (!(core_instance->agent = cc_agent_init(caller_chan, caller, core_instance->core_id, called_tree))) {
3001 cc_unref(core_instance, "Couldn't allocate agent, unref core_instance");
3002 return NULL;
3003 }
3004
3005 core_instance->monitors = cc_ref(called_tree, "Core instance getting ref to monitor tree");
3006
3007 ao2_t_link(cc_core_instances, core_instance, "Link core instance into container");
3008
3009 return core_instance;
3010}
3011
3013 struct cc_core_instance *core_instance;/*!< Holds reference to core instance. */
3016 char debug[1];
3017};
3018
3019static int is_state_change_valid(enum cc_state current_state, const enum cc_state new_state, struct ast_cc_agent *agent)
3020{
3021 int is_valid = 0;
3022 switch (new_state) {
3023 case CC_AVAILABLE:
3024 ast_log_dynamic_level(cc_logger_level, "Core %u: Asked to change to state %u? That should never happen.\n",
3025 agent->core_id, new_state);
3026 break;
3027 case CC_CALLER_OFFERED:
3028 if (current_state == CC_AVAILABLE) {
3029 is_valid = 1;
3030 }
3031 break;
3035 is_valid = 1;
3036 }
3037 break;
3038 case CC_ACTIVE:
3040 is_valid = 1;
3041 }
3042 break;
3043 case CC_CALLEE_READY:
3044 if (current_state == CC_ACTIVE) {
3045 is_valid = 1;
3046 }
3047 break;
3048 case CC_CALLER_BUSY:
3050 is_valid = 1;
3051 }
3052 break;
3053 case CC_RECALLING:
3055 is_valid = 1;
3056 }
3057 break;
3058 case CC_COMPLETE:
3059 if (current_state == CC_RECALLING) {
3060 is_valid = 1;
3061 }
3062 break;
3063 case CC_FAILED:
3064 is_valid = 1;
3065 break;
3066 default:
3067 ast_log_dynamic_level(cc_logger_level, "Core %u: Asked to change to unknown state %u\n",
3068 agent->core_id, new_state);
3069 break;
3070 }
3071
3072 return is_valid;
3073}
3074
3075static int cc_available(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
3076{
3077 /* This should never happen... */
3078 ast_log(LOG_WARNING, "Someone requested to change to CC_AVAILABLE? Ignoring.\n");
3079 return -1;
3080}
3081
3082static int cc_caller_offered(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
3083{
3084 if (core_instance->agent->callbacks->start_offer_timer(core_instance->agent)) {
3085 ast_cc_failed(core_instance->core_id, "Failed to start the offer timer for %s\n",
3086 core_instance->agent->device_name);
3087 return -1;
3088 }
3089 cc_publish_offertimerstart(core_instance->core_id, core_instance->agent->device_name, core_instance->agent->cc_params->cc_offer_timer);
3090 ast_log_dynamic_level(cc_logger_level, "Core %d: Started the offer timer for the agent %s!\n",
3091 core_instance->core_id, core_instance->agent->device_name);
3092 return 0;
3093}
3094
3095/*!
3096 * \brief check if the core instance has any device monitors
3097 *
3098 * In any case where we end up removing a device monitor from the
3099 * list of device monitors, it is important to see what the state
3100 * of the list is afterwards. If we find that we only have extension
3101 * monitors left, then no devices are actually being monitored.
3102 * In such a case, we need to declare that CC has failed for this
3103 * call. This function helps those cases to determine if they should
3104 * declare failure.
3105 *
3106 * \param core_instance The core instance we are checking for the existence
3107 * of device monitors
3108 * \retval 0 No device monitors exist on this core_instance
3109 * \retval 1 There is still at least 1 device monitor remaining
3110 */
3111static int has_device_monitors(struct cc_core_instance *core_instance)
3112{
3113 struct ast_cc_monitor *iter;
3114 int res = 0;
3115
3116 AST_LIST_TRAVERSE(core_instance->monitors, iter, next) {
3118 res = 1;
3119 break;
3120 }
3121 }
3122
3123 return res;
3124}
3125
3126static void request_cc(struct cc_core_instance *core_instance)
3127{
3128 struct ast_cc_monitor *monitor_iter;
3129 AST_LIST_LOCK(core_instance->monitors);
3130 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3131 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3132 if (monitor_iter->callbacks->request_cc(monitor_iter, &monitor_iter->available_timer_id)) {
3134 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3135 monitor_iter->interface->device_name, 1);
3136 cc_unref(monitor_iter, "request_cc failed. Unref list's reference to monitor");
3137 } else {
3138 cc_publish_requested(core_instance->core_id, core_instance->agent->device_name, monitor_iter->interface->device_name);
3139 }
3140 }
3141 }
3143
3144 if (!has_device_monitors(core_instance)) {
3145 ast_cc_failed(core_instance->core_id, "All device monitors failed to request CC");
3146 }
3147 AST_LIST_UNLOCK(core_instance->monitors);
3148}
3149
3150static int cc_caller_requested(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
3151{
3153 ast_log(LOG_WARNING, "Cannot request CC since there is no more room for requests\n");
3154 core_instance->agent->callbacks->respond(core_instance->agent,
3156 ast_cc_failed(core_instance->core_id, "Too many requests in the system");
3157 return -1;
3158 }
3159 core_instance->agent->callbacks->stop_offer_timer(core_instance->agent);
3160 request_cc(core_instance);
3161 return 0;
3162}
3163
3164static void unsuspend(struct cc_core_instance *core_instance)
3165{
3166 struct ast_cc_monitor *monitor_iter;
3167 AST_LIST_LOCK(core_instance->monitors);
3168 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3169 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3170 if (monitor_iter->callbacks->unsuspend(monitor_iter)) {
3172 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3173 monitor_iter->interface->device_name, 1);
3174 cc_unref(monitor_iter, "unsuspend failed. Unref list's reference to monitor");
3175 }
3176 }
3177 }
3179
3180 if (!has_device_monitors(core_instance)) {
3181 ast_cc_failed(core_instance->core_id, "All device monitors failed to unsuspend CC");
3182 }
3183 AST_LIST_UNLOCK(core_instance->monitors);
3184}
3185
3186static int cc_active(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
3187{
3188 /* Either
3189 * 1. Callee accepted CC request, call agent's ack callback.
3190 * 2. Caller became available, call agent's stop_monitoring callback and
3191 * call monitor's unsuspend callback.
3192 */
3193 if (previous_state == CC_CALLER_REQUESTED) {
3194 core_instance->agent->callbacks->respond(core_instance->agent,
3196 cc_publish_requestacknowledged(core_instance->core_id, core_instance->agent->device_name);
3197 } else if (previous_state == CC_CALLER_BUSY) {
3198 cc_publish_callerstopmonitoring(core_instance->core_id, core_instance->agent->device_name);
3199 unsuspend(core_instance);
3200 }
3201 /* Not possible for previous_state to be anything else due to the is_state_change_valid check at the beginning */
3202 return 0;
3203}
3204
3205static int cc_callee_ready(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
3206{
3207 core_instance->agent->callbacks->callee_available(core_instance->agent);
3208 return 0;
3209}
3210
3211static void suspend(struct cc_core_instance *core_instance)
3212{
3213 struct ast_cc_monitor *monitor_iter;
3214 AST_LIST_LOCK(core_instance->monitors);
3215 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3216 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3217 if (monitor_iter->callbacks->suspend(monitor_iter)) {
3219 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3220 monitor_iter->interface->device_name, 1);
3221 cc_unref(monitor_iter, "suspend failed. Unref list's reference to monitor");
3222 }
3223 }
3224 }
3226
3227 if (!has_device_monitors(core_instance)) {
3228 ast_cc_failed(core_instance->core_id, "All device monitors failed to suspend CC");
3229 }
3230 AST_LIST_UNLOCK(core_instance->monitors);
3231}
3232
3233static int cc_caller_busy(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
3234{
3235 /* Callee was available, but caller was busy, call agent's begin_monitoring callback
3236 * and call monitor's suspend callback.
3237 */
3238 suspend(core_instance);
3239 core_instance->agent->callbacks->start_monitoring(core_instance->agent);
3240 cc_publish_callerstartmonitoring(core_instance->core_id, core_instance->agent->device_name);
3241 return 0;
3242}
3243
3244static void cancel_available_timer(struct cc_core_instance *core_instance)
3245{
3246 struct ast_cc_monitor *monitor_iter;
3247 AST_LIST_LOCK(core_instance->monitors);
3248 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3249 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3250 if (monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id)) {
3252 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3253 monitor_iter->interface->device_name, 1);
3254 cc_unref(monitor_iter, "cancel_available_timer failed. Unref list's reference to monitor");
3255 }
3256 }
3257 }
3259
3260 if (!has_device_monitors(core_instance)) {
3261 ast_cc_failed(core_instance->core_id, "All device monitors failed to cancel their available timers");
3262 }
3263 AST_LIST_UNLOCK(core_instance->monitors);
3264}
3265
3266static int cc_recalling(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
3267{
3268 /* Both caller and callee are available, call agent's recall callback
3269 */
3270 cancel_available_timer(core_instance);
3271 cc_publish_callerrecalling(core_instance->core_id, core_instance->agent->device_name);
3272 return 0;
3273}
3274
3275static int cc_complete(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
3276{
3277 /* Recall has made progress, call agent and monitor destructor functions
3278 */
3279 cc_publish_recallcomplete(core_instance->core_id, core_instance->agent->device_name);
3280 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC recall has completed");
3281 return 0;
3282}
3283
3284static int cc_failed(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
3285{
3286 cc_publish_failure(core_instance->core_id, core_instance->agent->device_name, args->debug);
3287 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC failed");
3288 return 0;
3289}
3290
3302
3303static int cc_do_state_change(void *datap)
3304{
3305 struct cc_state_change_args *args = datap;
3306 struct cc_core_instance *core_instance;
3307 enum cc_state previous_state;
3308 int res;
3309
3310 ast_log_dynamic_level(cc_logger_level, "Core %d: State change to %u requested. Reason: %s\n",
3311 args->core_id, args->state, args->debug);
3312
3313 core_instance = args->core_instance;
3314
3315 if (!is_state_change_valid(core_instance->current_state, args->state, core_instance->agent)) {
3316 ast_log_dynamic_level(cc_logger_level, "Core %d: Invalid state change requested. Cannot go from %s to %s\n",
3317 args->core_id, cc_state_to_string(core_instance->current_state), cc_state_to_string(args->state));
3318 if (args->state == CC_CALLER_REQUESTED) {
3319 /*
3320 * For out-of-order requests, we need to let the requester know that
3321 * we can't handle the request now.
3322 */
3323 core_instance->agent->callbacks->respond(core_instance->agent,
3325 }
3326 ast_free(args);
3327 cc_unref(core_instance, "Unref core instance from when it was found earlier");
3328 return -1;
3329 }
3330
3331 /* We can change to the new state now. */
3332 previous_state = core_instance->current_state;
3333 core_instance->current_state = args->state;
3334 res = state_change_funcs[core_instance->current_state](core_instance, args, previous_state);
3335
3336 /* If state change successful then notify any device state watchers of the change */
3337 if (!res && !strcmp(core_instance->agent->callbacks->type, "generic")) {
3338 ccss_notify_device_state_change(core_instance->agent->device_name, core_instance->current_state);
3339 }
3340
3341 ast_free(args);
3342 cc_unref(core_instance, "Unref since state change has completed"); /* From ao2_find */
3343 return res;
3344}
3345
3346static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
3347{
3348 int res;
3349 int debuglen;
3350 char dummy[1];
3351 va_list aq;
3352 struct cc_core_instance *core_instance;
3353 struct cc_state_change_args *args;
3354 /* This initial call to vsnprintf is simply to find what the
3355 * size of the string needs to be
3356 */
3357 va_copy(aq, ap);
3358 /* We add 1 to the result since vsnprintf's return does not
3359 * include the terminating null byte
3360 */
3361 debuglen = vsnprintf(dummy, sizeof(dummy), debug, aq) + 1;
3362 va_end(aq);
3363
3364 if (!(args = ast_calloc(1, sizeof(*args) + debuglen))) {
3365 return -1;
3366 }
3367
3369 if (!core_instance) {
3370 ast_log_dynamic_level(cc_logger_level, "Core %d: Unable to find core instance.\n",
3371 core_id);
3372 ast_free(args);
3373 return -1;
3374 }
3375
3376 args->core_instance = core_instance;
3377 args->state = state;
3378 args->core_id = core_id;
3379 vsnprintf(args->debug, debuglen, debug, ap);
3380
3382 if (res) {
3383 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
3384 ast_free(args);
3385 }
3386 return res;
3387}
3388
3395
3396static void *cc_recall_ds_duplicate(void *data)
3397{
3398 struct cc_recall_ds_data *old_data = data;
3399 struct cc_recall_ds_data *new_data = ast_calloc(1, sizeof(*new_data));
3400
3401 if (!new_data) {
3402 return NULL;
3403 }
3404 new_data->interface_tree = cc_ref(old_data->interface_tree, "Bump refcount of monitor tree for recall datastore duplicate");
3405 new_data->core_id = old_data->core_id;
3406 new_data->nested = 1;
3407 return new_data;
3408}
3409
3410static void cc_recall_ds_destroy(void *data)
3411{
3412 struct cc_recall_ds_data *recall_data = data;
3413 recall_data->interface_tree = cc_unref(recall_data->interface_tree, "Unref recall monitor tree");
3414 ast_free(recall_data);
3415}
3416
3417static const struct ast_datastore_info recall_ds_info = {
3418 .type = "cc_recall",
3419 .duplicate = cc_recall_ds_duplicate,
3420 .destroy = cc_recall_ds_destroy,
3421};
3422
3423int ast_setup_cc_recall_datastore(struct ast_channel *chan, const int core_id)
3424{
3425 struct ast_datastore *recall_datastore;
3426 struct cc_recall_ds_data *recall_data;
3427 struct cc_core_instance *core_instance;
3428
3430
3431 recall_datastore = ast_datastore_alloc(&recall_ds_info, NULL);
3432 if (!recall_datastore) {
3433 return -1;
3434 }
3435
3436 if (!(recall_data = ast_calloc(1, sizeof(*recall_data)))) {
3437 ast_datastore_free(recall_datastore);
3438 return -1;
3439 }
3440
3441 if (!(core_instance = find_cc_core_instance(core_id))) {
3442 ast_free(recall_data);
3443 ast_datastore_free(recall_datastore);
3444 return -1;
3445 }
3446
3447 recall_data->interface_tree = cc_ref(core_instance->monitors,
3448 "Bump refcount for monitor tree for recall datastore");
3449 recall_data->core_id = core_id;
3450 recall_datastore->data = recall_data;
3451 recall_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
3452 ast_channel_lock(chan);
3453 ast_channel_datastore_add(chan, recall_datastore);
3454 ast_channel_unlock(chan);
3455 cc_unref(core_instance, "Recall datastore set up. No need for core_instance ref");
3456 return 0;
3457}
3458
3459int ast_cc_is_recall(struct ast_channel *chan, int *core_id, const char * const monitor_type)
3460{
3461 struct ast_datastore *recall_datastore;
3462 struct cc_recall_ds_data *recall_data;
3463 struct cc_monitor_tree *interface_tree;
3464 char device_name[AST_CHANNEL_NAME];
3465 struct ast_cc_monitor *device_monitor;
3466 int core_id_candidate;
3467
3469
3471
3472 *core_id = -1;
3473
3474 ast_channel_lock(chan);
3475 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3476 /* Obviously not a recall if the datastore isn't present */
3477 ast_channel_unlock(chan);
3478 return 0;
3479 }
3480
3481 recall_data = recall_datastore->data;
3482
3483 if (recall_data->ignore) {
3484 /* Though this is a recall, the call to this particular interface is not part of the
3485 * recall either because this is a call forward or because this is not the first
3486 * invocation of Dial during this call
3487 */
3488 ast_channel_unlock(chan);
3489 return 0;
3490 }
3491
3492 if (!recall_data->nested) {
3493 /* If the nested flag is not set, then this means that
3494 * the channel passed to this function is the caller making
3495 * the recall. This means that we shouldn't look through
3496 * the monitor tree for the channel because it shouldn't be
3497 * there. However, this is a recall though, so return true.
3498 */
3499 *core_id = recall_data->core_id;
3500 ast_channel_unlock(chan);
3501 return 1;
3502 }
3503
3504 if (ast_strlen_zero(monitor_type)) {
3505 /* If someone passed a NULL or empty monitor type, then it is clear
3506 * the channel they passed in was an incoming channel, and so searching
3507 * the list of dialed interfaces is not going to be helpful. Just return
3508 * false immediately.
3509 */
3510 ast_channel_unlock(chan);
3511 return 0;
3512 }
3513
3514 interface_tree = recall_data->interface_tree;
3515 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
3516 /* We grab the value of the recall_data->core_id so that we
3517 * can unlock the channel before we start looking through the
3518 * interface list. That way we don't have to worry about a possible
3519 * clash between the channel lock and the monitor tree lock.
3520 */
3521 core_id_candidate = recall_data->core_id;
3522 ast_channel_unlock(chan);
3523
3524 /*
3525 * Now we need to find out if the channel device name
3526 * is in the list of interfaces in the called tree.
3527 */
3528 AST_LIST_LOCK(interface_tree);
3529 AST_LIST_TRAVERSE(interface_tree, device_monitor, next) {
3530 if (!strcmp(device_monitor->interface->device_name, device_name) &&
3531 !strcmp(device_monitor->interface->monitor_type, monitor_type)) {
3532 /* BOOM! Device is in the tree! We have a winner! */
3533 *core_id = core_id_candidate;
3534 AST_LIST_UNLOCK(interface_tree);
3535 return 1;
3536 }
3537 }
3538 AST_LIST_UNLOCK(interface_tree);
3539 return 0;
3540}
3541
3542struct ast_cc_monitor *ast_cc_get_monitor_by_recall_core_id(const int core_id, const char * const device_name)
3543{
3544 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3545 struct ast_cc_monitor *monitor_iter;
3546
3548
3549 if (!core_instance) {
3550 return NULL;
3551 }
3552
3553 AST_LIST_LOCK(core_instance->monitors);
3554 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
3555 if (!strcmp(monitor_iter->interface->device_name, device_name)) {
3556 /* Found a monitor. */
3557 cc_ref(monitor_iter, "Hand the requester of the monitor a reference");
3558 break;
3559 }
3560 }
3561 AST_LIST_UNLOCK(core_instance->monitors);
3562 cc_unref(core_instance, "Done with core instance ref in ast_cc_get_monitor_by_recall_core_id");
3563 return monitor_iter;
3564}
3565
3566/*!
3567 * \internal
3568 * \brief uniquely append a dialstring to our CC_INTERFACES chanvar string.
3569 *
3570 * We will only append a string if it has not already appeared in our channel
3571 * variable earlier. We ensure that we don't erroneously match substrings by
3572 * adding an ampersand to the end of our potential dialstring and searching for
3573 * it plus the ampersand in our variable.
3574 *
3575 * It's important to note that once we have built the full CC_INTERFACES string,
3576 * there will be an extra ampersand at the end which must be stripped off by
3577 * the caller of this function.
3578 *
3579 * \param str An ast_str holding what we will add to CC_INTERFACES
3580 * \param dialstring A new dialstring to add
3581 */
3582static void cc_unique_append(struct ast_str **str, const char *dialstring)
3583{
3584 char dialstring_search[AST_CHANNEL_NAME + 1];
3585
3587 /* No dialstring to append. */
3588 return;
3589 }
3590 snprintf(dialstring_search, sizeof(dialstring_search), "%s%c", dialstring, '&');
3591 if (strstr(ast_str_buffer(*str), dialstring_search)) {
3592 return;
3593 }
3594 ast_str_append(str, 0, "%s", dialstring_search);
3595}
3596
3597/*!
3598 * \internal
3599 * \brief Build the CC_INTERFACES channel variable
3600 *
3601 * The method used is to traverse the child dialstrings in the
3602 * passed-in extension monitor, adding any that have the is_valid
3603 * flag set. Then, traverse the monitors, finding all children
3604 * of the starting extension monitor and adding their dialstrings
3605 * as well.
3606 *
3607 * \param starting_point The extension monitor that is the parent to all
3608 * monitors whose dialstrings should be added to CC_INTERFACES
3609 * \param str Where we will store CC_INTERFACES
3610 */
3611static void build_cc_interfaces_chanvar(struct ast_cc_monitor *starting_point, struct ast_str **str)
3612{
3613 struct extension_monitor_pvt *extension_pvt;
3614 struct extension_child_dialstring *child_dialstring;
3615 struct ast_cc_monitor *monitor_iter = starting_point;
3616 int top_level_id = starting_point->id;
3617 size_t length;
3618
3619 /* Init to an empty string. */
3620 ast_str_truncate(*str, 0);
3621
3622 /* First we need to take all of the is_valid child_dialstrings from
3623 * the extension monitor we found and add them to the CC_INTERFACES
3624 * chanvar
3625 */
3626 extension_pvt = starting_point->private_data;
3627 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
3628 if (child_dialstring->is_valid) {
3629 cc_unique_append(str, child_dialstring->original_dialstring);
3630 }
3631 }
3632
3633 /* And now we get the dialstrings from each of the device monitors */
3634 while ((monitor_iter = AST_LIST_NEXT(monitor_iter, next))) {
3635 if (monitor_iter->parent_id == top_level_id) {
3636 cc_unique_append(str, monitor_iter->dialstring);
3637 }
3638 }
3639
3640 /* str will have an extra '&' tacked onto the end of it, so we need
3641 * to get rid of that.
3642 */
3643 length = ast_str_strlen(*str);
3644 if (length) {
3645 ast_str_truncate(*str, length - 1);
3646 }
3647 if (length <= 1) {
3648 /* Nothing to recall? This should not happen. */
3649 ast_log(LOG_ERROR, "CC_INTERFACES is empty. starting device_name:'%s'\n",
3650 starting_point->interface->device_name);
3651 }
3652}
3653
3655{
3656 struct ast_datastore *recall_datastore;
3657 struct cc_monitor_tree *interface_tree;
3658 struct ast_cc_monitor *monitor;
3659 struct cc_recall_ds_data *recall_data;
3660 struct ast_str *str = ast_str_create(64);
3661 int core_id;
3662
3664
3665 if (!str) {
3666 return -1;
3667 }
3668
3669 ast_channel_lock(chan);
3670 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3671 ast_channel_unlock(chan);
3672 ast_free(str);
3673 return -1;
3674 }
3675 recall_data = recall_datastore->data;
3676 interface_tree = recall_data->interface_tree;
3677 core_id = recall_data->core_id;
3678 ast_channel_unlock(chan);
3679
3680 AST_LIST_LOCK(interface_tree);
3681 monitor = AST_LIST_FIRST(interface_tree);
3683 AST_LIST_UNLOCK(interface_tree);
3684
3685 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
3686 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
3687 core_id, ast_str_buffer(str));
3688
3689 ast_free(str);
3690 return 0;
3691}
3692
3693int ast_set_cc_interfaces_chanvar(struct ast_channel *chan, const char * const extension)
3694{
3695 struct ast_datastore *recall_datastore;
3696 struct cc_monitor_tree *interface_tree;
3697 struct ast_cc_monitor *monitor_iter;
3698 struct cc_recall_ds_data *recall_data;
3699 struct ast_str *str = ast_str_create(64);
3700 int core_id;
3701
3703
3704 if (!str) {
3705 return -1;
3706 }
3707
3708 ast_channel_lock(chan);
3709 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3710 ast_channel_unlock(chan);
3711 ast_free(str);
3712 return -1;
3713 }
3714 recall_data = recall_datastore->data;
3715 interface_tree = recall_data->interface_tree;
3716 core_id = recall_data->core_id;
3717 ast_channel_unlock(chan);
3718
3719 AST_LIST_LOCK(interface_tree);
3720 AST_LIST_TRAVERSE(interface_tree, monitor_iter, next) {
3721 if (!strcmp(monitor_iter->interface->device_name, extension)) {
3722 break;
3723 }
3724 }
3725
3726 if (!monitor_iter) {
3727 /* We couldn't find this extension. This may be because
3728 * we have been directed into an unexpected extension because
3729 * the admin has changed a CC_INTERFACES variable at some point.
3730 */
3731 AST_LIST_UNLOCK(interface_tree);
3732 ast_free(str);
3733 return -1;
3734 }
3735
3736 build_cc_interfaces_chanvar(monitor_iter, &str);
3737 AST_LIST_UNLOCK(interface_tree);
3738
3739 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
3740 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
3741 core_id, ast_str_buffer(str));
3742
3743 ast_free(str);
3744 return 0;
3745}
3746
3747void ast_ignore_cc(struct ast_channel *chan)
3748{
3749 struct ast_datastore *cc_datastore;
3750 struct ast_datastore *cc_recall_datastore;
3751 struct dialed_cc_interfaces *cc_interfaces;
3752 struct cc_recall_ds_data *recall_cc_data;
3753
3755
3756 ast_channel_lock(chan);
3757 if ((cc_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
3758 cc_interfaces = cc_datastore->data;
3759 cc_interfaces->ignore = 1;
3760 }
3761
3762 if ((cc_recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3763 recall_cc_data = cc_recall_datastore->data;
3764 recall_cc_data->ignore = 1;
3765 }
3766 ast_channel_unlock(chan);
3767}
3768
3769static __attribute__((format(printf, 2, 3))) int cc_offer(const int core_id, const char * const debug, ...)
3770{
3771 va_list ap;
3772 int res;
3773
3774 va_start(ap, debug);
3776 va_end(ap);
3777 return res;
3778}
3779
3780int ast_cc_offer(struct ast_channel *caller_chan)
3781{
3782 int core_id;
3783 int res = -1;
3784 struct ast_datastore *datastore;
3785 struct dialed_cc_interfaces *cc_interfaces;
3786 char cc_is_offerable;
3787
3789
3790 ast_channel_lock(caller_chan);
3791 if (!(datastore = ast_channel_datastore_find(caller_chan, &dialed_cc_interfaces_info, NULL))) {
3792 ast_channel_unlock(caller_chan);
3793 return res;
3794 }
3795
3796 cc_interfaces = datastore->data;
3797 cc_is_offerable = cc_interfaces->is_original_caller;
3798 core_id = cc_interfaces->core_id;
3799 ast_channel_unlock(caller_chan);
3800
3801 if (cc_is_offerable) {
3802 res = cc_offer(core_id, "CC offered to caller %s", ast_channel_name(caller_chan));
3803 }
3804 return res;
3805}
3806
3807int ast_cc_agent_accept_request(int core_id, const char * const debug, ...)
3808{
3809 va_list ap;
3810 int res;
3811
3813
3814 va_start(ap, debug);
3816 va_end(ap);
3817 return res;
3818}
3819
3820int ast_cc_monitor_request_acked(int core_id, const char * const debug, ...)
3821{
3822 va_list ap;
3823 int res;
3824
3826
3827 va_start(ap, debug);
3829 va_end(ap);
3830 return res;
3831}
3832
3833int ast_cc_monitor_callee_available(const int core_id, const char * const debug, ...)
3834{
3835 va_list ap;
3836 int res;
3837
3839
3840 va_start(ap, debug);
3842 va_end(ap);
3843 return res;
3844}
3845
3846int ast_cc_agent_caller_busy(int core_id, const char * debug, ...)
3847{
3848 va_list ap;
3849 int res;
3850
3852
3853 va_start(ap, debug);
3855 va_end(ap);
3856 return res;
3857}
3858
3859int ast_cc_agent_caller_available(int core_id, const char * const debug, ...)
3860{
3861 va_list ap;
3862 int res;
3863
3865
3866 va_start(ap, debug);
3868 va_end(ap);
3869 return res;
3870}
3871
3872int ast_cc_agent_recalling(int core_id, const char * const debug, ...)
3873{
3874 va_list ap;
3875 int res;
3876
3878
3879 va_start(ap, debug);
3881 va_end(ap);
3882 return res;
3883}
3884
3885int ast_cc_completed(struct ast_channel *chan, const char * const debug, ...)
3886{
3887 struct ast_datastore *recall_datastore;
3888 struct cc_recall_ds_data *recall_data;
3889 int core_id;
3890 va_list ap;
3891 int res;
3892
3894
3895 ast_channel_lock(chan);
3896 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3897 /* Silly! Why did you call this function if there's no recall DS? */
3898 ast_channel_unlock(chan);
3899 return -1;
3900 }
3901 recall_data = recall_datastore->data;
3902 if (recall_data->nested || recall_data->ignore) {
3903 /* If this is being called from a nested Dial, it is too
3904 * early to determine if the recall has actually completed.
3905 * The outermost dial is the only one with the authority to
3906 * declare the recall to be complete.
3907 *
3908 * Similarly, if this function has been called when the
3909 * recall has progressed beyond the first dial, this is not
3910 * a legitimate time to declare the recall to be done. In fact,
3911 * that should have been done already.
3912 */
3913 ast_channel_unlock(chan);
3914 return -1;
3915 }
3916 core_id = recall_data->core_id;
3917 ast_channel_unlock(chan);
3918 va_start(ap, debug);
3920 va_end(ap);
3921 return res;
3922}
3923
3924int ast_cc_failed(int core_id, const char * const debug, ...)
3925{
3926 va_list ap;
3927 int res;
3928
3930
3931 va_start(ap, debug);
3933 va_end(ap);
3934 return res;
3935}
3936
3942
3943static int cc_monitor_failed(void *data)
3944{
3945 struct ast_cc_monitor_failure_data *failure_data = data;
3946 struct cc_core_instance *core_instance;
3947 struct ast_cc_monitor *monitor_iter;
3948
3949 core_instance = find_cc_core_instance(failure_data->core_id);
3950 if (!core_instance) {
3951 /* Core instance no longer exists or invalid core_id. */
3953 "Core %d: Could not find core instance for device %s '%s'\n",
3954 failure_data->core_id, failure_data->device_name, failure_data->debug);
3955 ast_free((char *) failure_data->device_name);
3956 ast_free((char *) failure_data->debug);
3957 ast_free(failure_data);
3958 return -1;
3959 }
3960
3961 AST_LIST_LOCK(core_instance->monitors);
3962 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3963 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3964 if (!strcmp(monitor_iter->interface->device_name, failure_data->device_name)) {
3966 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3967 monitor_iter->interface->device_name, 1);
3968 monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id);
3969 cc_publish_monitorfailed(monitor_iter->core_id, monitor_iter->interface->device_name);
3970 cc_unref(monitor_iter, "Monitor reported failure. Unref list's reference.");
3971 }
3972 }
3973 }
3975
3976 if (!has_device_monitors(core_instance)) {
3977 ast_cc_failed(core_instance->core_id, "All monitors have failed\n");
3978 }
3979 AST_LIST_UNLOCK(core_instance->monitors);
3980 cc_unref(core_instance, "Finished with core_instance in cc_monitor_failed\n");
3981
3982 ast_free((char *) failure_data->device_name);
3983 ast_free((char *) failure_data->debug);
3984 ast_free(failure_data);
3985 return 0;
3986}
3987
3988int ast_cc_monitor_failed(int core_id, const char *const monitor_name, const char * const debug, ...)
3989{
3990 struct ast_cc_monitor_failure_data *failure_data;
3991 int res;
3992 va_list ap;
3993
3995
3996 if (!(failure_data = ast_calloc(1, sizeof(*failure_data)))) {
3997 return -1;
3998 }
3999
4000 if (!(failure_data->device_name = ast_strdup(monitor_name))) {
4001 ast_free(failure_data);
4002 return -1;
4003 }
4004
4005 va_start(ap, debug);
4006 if (ast_vasprintf(&failure_data->debug, debug, ap) == -1) {
4007 va_end(ap);
4008 ast_free((char *)failure_data->device_name);
4009 ast_free(failure_data);
4010 return -1;
4011 }
4012 va_end(ap);
4013
4014 failure_data->core_id = core_id;
4015
4017 if (res) {
4018 ast_free((char *)failure_data->device_name);
4019 ast_free((char *)failure_data->debug);
4020 ast_free(failure_data);
4021 }
4022 return res;
4023}
4024
4025static int cc_status_request(void *data)
4026{
4027 struct cc_core_instance *core_instance= data;
4028 int res;
4029
4030 res = core_instance->agent->callbacks->status_request(core_instance->agent);
4031 cc_unref(core_instance, "Status request finished. Unref core instance");
4032 return res;
4033}
4034
4036{
4037 int res;
4038 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
4039
4041
4042 if (!core_instance) {
4043 return -1;
4044 }
4045
4047 if (res) {
4048 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4049 }
4050 return res;
4051}
4052
4053static int cc_stop_ringing(void *data)
4054{
4055 struct cc_core_instance *core_instance = data;
4056 int res = 0;
4057
4058 if (core_instance->agent->callbacks->stop_ringing) {
4059 res = core_instance->agent->callbacks->stop_ringing(core_instance->agent);
4060 }
4061 /* If an agent is being asked to stop ringing, then he needs to be prepared if for
4062 * whatever reason he needs to be called back again. The proper state to be in to
4063 * detect such a circumstance is the CC_ACTIVE state.
4064 *
4065 * We get to this state using the slightly unintuitive method of calling
4066 * ast_cc_monitor_request_acked because it gets us to the proper state.
4067 */
4068 ast_cc_monitor_request_acked(core_instance->core_id, "Agent %s asked to stop ringing. Be prepared to be recalled again.",
4069 core_instance->agent->device_name);
4070 cc_unref(core_instance, "Stop ringing finished. Unref core_instance");
4071 return res;
4072}
4073
4075{
4076 int res;
4077 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
4078
4080
4081 if (!core_instance) {
4082 return -1;
4083 }
4084
4086 if (res) {
4087 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4088 }
4089 return res;
4090}
4091
4092static int cc_party_b_free(void *data)
4093{
4094 struct cc_core_instance *core_instance = data;
4095 int res = 0;
4096
4097 if (core_instance->agent->callbacks->party_b_free) {
4098 res = core_instance->agent->callbacks->party_b_free(core_instance->agent);
4099 }
4100 cc_unref(core_instance, "Party B free finished. Unref core_instance");
4101 return res;
4102}
4103
4105{
4106 int res;
4107 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
4108
4110
4111 if (!core_instance) {
4112 return -1;
4113 }
4114
4116 if (res) {
4117 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4118 }
4119 return res;
4120}
4121
4126
4127static int cc_status_response(void *data)
4128{
4129 struct cc_status_response_args *args = data;
4130 struct cc_core_instance *core_instance = args->core_instance;
4131 struct ast_cc_monitor *monitor_iter;
4132 enum ast_device_state devstate = args->devstate;
4133
4134 ast_free(args);
4135
4136 AST_LIST_LOCK(core_instance->monitors);
4137 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
4138 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR &&
4139 monitor_iter->callbacks->status_response) {
4140 monitor_iter->callbacks->status_response(monitor_iter, devstate);
4141 }
4142 }
4143 AST_LIST_UNLOCK(core_instance->monitors);
4144 cc_unref(core_instance, "Status response finished. Unref core instance");
4145 return 0;
4146}
4147
4149{
4151 struct cc_core_instance *core_instance;
4152 int res;
4153
4155
4156 args = ast_calloc(1, sizeof(*args));
4157 if (!args) {
4158 return -1;
4159 }
4160
4161 core_instance = find_cc_core_instance(core_id);
4162 if (!core_instance) {
4163 ast_free(args);
4164 return -1;
4165 }
4166
4167 args->core_instance = core_instance;
4168 args->devstate = devstate;
4169
4171 if (res) {
4172 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4173 ast_free(args);
4174 }
4175 return res;
4176}
4177
4178static int cc_build_payload(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
4179 const char *monitor_type, const char * const device_name, const char * dialstring,
4180 enum ast_cc_service_type service, void *private_data, struct cc_control_payload *payload)
4181{
4182 struct ast_datastore *datastore;
4183 struct dialed_cc_interfaces *cc_interfaces;
4184 int dial_parent_id;
4185
4186 ast_channel_lock(chan);
4188 if (!datastore) {
4189 ast_channel_unlock(chan);
4190 return -1;
4191 }
4192 cc_interfaces = datastore->data;
4193 dial_parent_id = cc_interfaces->dial_parent_id;
4194 ast_channel_unlock(chan);
4195
4196 payload->monitor_type = monitor_type;
4197 payload->private_data = private_data;
4198 payload->service = service;
4199 ast_cc_copy_config_params(&payload->config_params, cc_params);
4201 ast_copy_string(payload->device_name, device_name, sizeof(payload->device_name));
4202 ast_copy_string(payload->dialstring, dialstring, sizeof(payload->dialstring));
4203 return 0;
4204}
4205
4206int ast_queue_cc_frame(struct ast_channel *chan, const char *monitor_type,
4207 const char * const dialstring, enum ast_cc_service_type service, void *private_data)
4208{
4209 struct ast_frame frame = {0,};
4210 char device_name[AST_CHANNEL_NAME];
4211 int retval;
4212 struct ast_cc_config_params *cc_params;
4213
4215
4216 cc_params = ast_channel_get_cc_config_params(chan);
4217 if (!cc_params) {
4218 return -1;
4219 }
4220 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4221 if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) {
4222 ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name);
4223 return -1;
4224 }
4225
4226 if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, &frame)) {
4227 /* Frame building failed. We can't use this. */
4228 return -1;
4229 }
4230 retval = ast_queue_frame(chan, &frame);
4231 ast_frfree(&frame);
4232 return retval;
4233}
4234
4235int ast_cc_build_frame(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
4236 const char *monitor_type, const char * const device_name,
4237 const char * const dialstring, enum ast_cc_service_type service, void *private_data,
4238 struct ast_frame *frame)
4239{
4240 struct cc_control_payload *payload;
4241
4243
4244 payload = ast_calloc(1, sizeof(*payload));
4245 if (!payload) {
4246 return -1;
4247 }
4248 if (cc_build_payload(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, payload)) {
4249 /* Something screwed up, we can't make a frame with this */
4250 ast_free(payload);
4251 return -1;
4252 }
4255 frame->data.ptr = payload;
4256 frame->datalen = sizeof(*payload);
4257 frame->mallocd = AST_MALLOCD_DATA;
4258 return 0;
4259}
4260
4261void ast_cc_call_failed(struct ast_channel *incoming, struct ast_channel *outgoing, const char * const dialstring)
4262{
4264 struct cc_control_payload payload;
4265 struct ast_cc_config_params *cc_params;
4266
4268
4270 /* It doesn't make sense to try to offer CCBS to the caller if the reason for ast_call
4271 * failing is something other than busy or congestion
4272 */
4273 return;
4274 }
4275
4277 if (!cc_params) {
4278 return;
4279 }
4281 /* This sort of CCBS only works if using generic CC. For native, we would end up sending
4282 * a CC request for a non-existent call. The far end will reject this every time
4283 */
4284 return;
4285 }
4286
4287 ast_channel_get_device_name(outgoing, device_name, sizeof(device_name));
4288 if (cc_build_payload(outgoing, cc_params, AST_CC_GENERIC_MONITOR_TYPE, device_name,
4289 dialstring, AST_CC_CCBS, NULL, &payload)) {
4290 /* Something screwed up, we can't make a frame with this */
4291 return;
4292 }
4293 ast_handle_cc_control_frame(incoming, outgoing, &payload);
4294}
4295
4296void ast_cc_busy_interface(struct ast_channel *inbound, struct ast_cc_config_params *cc_params,
4297 const char *monitor_type, const char * const device_name, const char * const dialstring, void *private_data)
4298{
4299 struct cc_control_payload payload;
4300
4302
4303 if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialstring, AST_CC_CCBS, private_data, &payload)) {
4304 /* Something screwed up. Don't try to handle this payload */
4306 return;
4307 }
4308 ast_handle_cc_control_frame(inbound, NULL, &payload);
4309}
4310
4311int ast_cc_callback(struct ast_channel *inbound, const char * const tech, const char * const dest, ast_cc_callback_fn callback)
4312{
4313 const struct ast_channel_tech *chantech;
4314
4316
4317 chantech = ast_get_channel_tech(tech);
4318 if (chantech && chantech->cc_callback) {
4319 chantech->cc_callback(inbound, dest, callback);
4320 }
4321
4322 return 0;
4323}
4324
4325static const char *ccreq_app = "CallCompletionRequest";
4326
4327static int ccreq_exec(struct ast_channel *chan, const char *data)
4328{
4329 struct cc_core_instance *core_instance;
4330 char device_name[AST_CHANNEL_NAME];
4331 unsigned long match_flags;
4332 int res;
4333
4334 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4335
4337 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionRequest"))) {
4338 ast_log_dynamic_level(cc_logger_level, "Couldn't find a core instance for caller %s\n", device_name);
4339 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4340 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NO_CORE_INSTANCE");
4341 return 0;
4342 }
4343
4344 ast_log_dynamic_level(cc_logger_level, "Core %d: Found core_instance for caller %s\n",
4345 core_instance->core_id, device_name);
4346
4347 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
4348 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest is only for generic agent types.\n",
4349 core_instance->core_id);
4350 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4351 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NOT_GENERIC");
4352 cc_unref(core_instance, "Unref core_instance since CallCompletionRequest was called with native agent");
4353 return 0;
4354 }
4355
4357 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest failed. Too many requests in the system\n",
4358 core_instance->core_id);
4359 ast_cc_failed(core_instance->core_id, "Too many CC requests\n");
4360 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4361 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "TOO_MANY_REQUESTS");
4362 cc_unref(core_instance, "Unref core_instance since too many CC requests");
4363 return 0;
4364 }
4365
4366 res = ast_cc_agent_accept_request(core_instance->core_id, "CallCompletionRequest called by caller %s for core_id %d", device_name, core_instance->core_id);
4367 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", res ? "FAIL" : "SUCCESS");
4368 if (res) {
4369 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "UNSPECIFIED");
4370 }
4371
4372 cc_unref(core_instance, "Done with CallCompletionRequest");
4373 return 0;
4374}
4375
4376static const char *cccancel_app = "CallCompletionCancel";
4377
4378static int cccancel_exec(struct ast_channel *chan, const char *data)
4379{
4380 struct cc_core_instance *core_instance;
4381 char device_name[AST_CHANNEL_NAME];
4382 unsigned long match_flags;
4383 int res;
4384
4385 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4386
4388 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionCancel"))) {
4389 ast_log_dynamic_level(cc_logger_level, "Cannot find CC transaction to cancel for caller %s\n", device_name);
4390 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
4391 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NO_CORE_INSTANCE");
4392 return 0;
4393 }
4394
4395 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
4396 ast_log(LOG_WARNING, "CallCompletionCancel may only be used for calls with a generic agent\n");
4397 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
4398 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
4399 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NOT_GENERIC");
4400 return 0;
4401 }
4402 res = ast_cc_failed(core_instance->core_id, "Call completion request Cancelled for core ID %d by caller %s",
4403 core_instance->core_id, device_name);
4404 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
4405 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", res ? "FAIL" : "SUCCESS");
4406 if (res) {
4407 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "UNSPECIFIED");
4408 }
4409 return 0;
4410}
4411
4413 const char *device_name;
4414 const char *monitor_type;
4416};
4417
4418static int count_monitors_cb(void *obj, void *arg, int flags)
4419{
4420 struct cc_core_instance *core_instance = obj;
4421 struct count_monitors_cb_data *cb_data = arg;
4422 const char *device_name = cb_data->device_name;
4423 const char *monitor_type = cb_data->monitor_type;
4424 struct ast_cc_monitor *monitor_iter;
4425
4426 AST_LIST_LOCK(core_instance->monitors);
4427 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
4428 if (!strcmp(monitor_iter->interface->device_name, device_name) &&
4429 !strcmp(monitor_iter->interface->monitor_type, monitor_type)) {
4430 cb_data->count++;
4431 break;
4432 }
4433 }
4434 AST_LIST_UNLOCK(core_instance->monitors);
4435 return 0;
4436}
4437
4438int ast_cc_monitor_count(const char * const name, const char * const type)
4439{
4440 struct count_monitors_cb_data data = {.device_name = name, .monitor_type = type,};
4441
4443
4444 ao2_t_callback(cc_core_instances, OBJ_NODATA, count_monitors_cb, &data, "Counting agents");
4445 ast_log_dynamic_level(cc_logger_level, "Counted %d monitors\n", data.count);
4446 return data.count;
4447}
4448
4449static void initialize_cc_max_requests(struct ast_config *cc_config)
4450{
4451 const char *cc_max_requests_str;
4452 char *endptr;
4453
4454 if (!(cc_max_requests_str = ast_variable_retrieve(cc_config, "general", "cc_max_requests"))) {
4456 return;
4457 }
4458
4459 global_cc_max_requests = strtol(cc_max_requests_str, &endptr, 10);
4460
4461 if (!ast_strlen_zero(endptr)) {
4462 ast_log(LOG_WARNING, "Invalid input given for cc_max_requests. Using default\n");
4464 }
4465
4466 return;
4467}
4468
4469/*!
4470 * \internal
4471 * \brief helper function to parse and configure each devstate map
4472 */
4473static void initialize_cc_devstate_map_helper(struct ast_config *cc_config, enum cc_state state, const char *cc_setting)
4474{
4475 const char *cc_devstate_str;
4476 enum ast_device_state this_devstate;
4477
4478 if ((cc_devstate_str = ast_variable_retrieve(cc_config, "general", cc_setting))) {
4479 this_devstate = ast_devstate_val(cc_devstate_str);
4480 if (this_devstate != AST_DEVICE_UNKNOWN) {
4481 cc_state_to_devstate_map[state] = this_devstate;
4482 }
4483 }
4484}
4485
4486/*!
4487 * \internal
4488 * \brief initializes cc_state_to_devstate_map from ccss.conf
4489 *
4490 * \details
4491 * The cc_state_to_devstate_map[] is already initialized with all the
4492 * default values. This will update that structure with any changes
4493 * from the ccss.conf file. The configuration parameters in ccss.conf
4494 * should use any valid device state form that is recognized by
4495 * ast_devstate_val() function.
4496 */
4497static void initialize_cc_devstate_map(struct ast_config *cc_config)
4498{
4499 initialize_cc_devstate_map_helper(cc_config, CC_AVAILABLE, "cc_available_devstate");
4500 initialize_cc_devstate_map_helper(cc_config, CC_CALLER_OFFERED, "cc_caller_offered_devstate");
4501 initialize_cc_devstate_map_helper(cc_config, CC_CALLER_REQUESTED, "cc_caller_requested_devstate");
4502 initialize_cc_devstate_map_helper(cc_config, CC_ACTIVE, "cc_active_devstate");
4503 initialize_cc_devstate_map_helper(cc_config, CC_CALLEE_READY, "cc_callee_ready_devstate");
4504 initialize_cc_devstate_map_helper(cc_config, CC_CALLER_BUSY, "cc_caller_busy_devstate");
4505 initialize_cc_devstate_map_helper(cc_config, CC_RECALLING, "cc_recalling_devstate");
4506 initialize_cc_devstate_map_helper(cc_config, CC_COMPLETE, "cc_complete_devstate");
4507 initialize_cc_devstate_map_helper(cc_config, CC_FAILED, "cc_failed_devstate");
4508
4509}
4510
4511static int load_config(void)
4512{
4513 struct ast_flags config_flags = { 0, };
4514 const char *enabled = NULL;
4515 struct ast_config *cc_config = ast_config_load2("ccss.conf", "ccss", config_flags);
4516
4517 global_enabled = 1;
4518
4519 if (!cc_config || cc_config == CONFIG_STATUS_FILEINVALID) {
4520 ast_log(LOG_WARNING, "Could not find valid ccss.conf file. Using cc_max_requests and devstate defaults\n");
4522 return 0;
4523 }
4524
4525 if ((enabled = ast_variable_retrieve(cc_config, "general", "enabled"))) {
4527 }
4528
4529 if (global_enabled) {
4530 initialize_cc_max_requests(cc_config);
4531 initialize_cc_devstate_map(cc_config);
4532 } else {
4533 ast_log(LOG_NOTICE, "CCSS disabled globally\n");
4534 }
4535 ast_config_destroy(cc_config);
4536
4537 return !global_enabled;
4538}
4539
4541{
4542 return global_enabled;
4543}
4544
4545static void cc_cli_print_monitor_stats(struct ast_cc_monitor *monitor, int fd, int parent_id)
4546{
4547 struct ast_cc_monitor *child_monitor_iter = monitor;
4548 if (!monitor) {
4549 return;
4550 }
4551
4552 ast_cli(fd, "\t\t|-->%s", monitor->interface->device_name);
4554 ast_cli(fd, "(%s)", cc_service_to_string(monitor->service_offered));
4555 }
4556 ast_cli(fd, "\n");
4557
4558 while ((child_monitor_iter = AST_LIST_NEXT(child_monitor_iter, next))) {
4559 if (child_monitor_iter->parent_id == monitor->id) {
4560 cc_cli_print_monitor_stats(child_monitor_iter, fd, child_monitor_iter->id);
4561 }
4562 }
4563}
4564
4565static int print_stats_cb(void *obj, void *arg, int flags)
4566{
4567 int *cli_fd = arg;
4568 struct cc_core_instance *core_instance = obj;
4569
4570 ast_cli(*cli_fd, "%d\t\t%s\t\t%s\n", core_instance->core_id, core_instance->agent->device_name,
4571 cc_state_to_string(core_instance->current_state));
4572 AST_LIST_LOCK(core_instance->monitors);
4573 cc_cli_print_monitor_stats(AST_LIST_FIRST(core_instance->monitors), *cli_fd, 0);
4574 AST_LIST_UNLOCK(core_instance->monitors);
4575 return 0;
4576}
4577
4578static int cc_cli_output_status(void *data)
4579{
4580 int *cli_fd = data;
4582
4583 if (!count) {
4584 ast_cli(*cli_fd, "There are currently no active call completion transactions\n");
4585 } else {
4586 ast_cli(*cli_fd, "%d Call completion transactions\n", count);
4587 ast_cli(*cli_fd, "Core ID\t\tCaller\t\t\t\tStatus\n");
4588 ast_cli(*cli_fd, "----------------------------------------------------------------------------\n");
4589 ao2_t_callback(cc_core_instances, OBJ_NODATA, print_stats_cb, cli_fd, "Printing stats to CLI");
4590 }
4591 ast_free(cli_fd);
4592 return 0;
4593}
4594
4595static char *handle_cc_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4596{
4597 int *cli_fd;
4598
4599 switch (cmd) {
4600 case CLI_INIT:
4601 e->command = "cc report status";
4602 e->usage =
4603 "Usage: cc report status\n"
4604 " Report the current status of any ongoing CC transactions\n";
4605 return NULL;
4606 case CLI_GENERATE:
4607 return NULL;
4608 }
4609
4610 if (a->argc != 3) {
4611 return CLI_SHOWUSAGE;
4612 }
4613
4614 cli_fd = ast_malloc(sizeof(*cli_fd));
4615 if (!cli_fd) {
4616 return CLI_FAILURE;
4617 }
4618
4619 *cli_fd = a->fd;
4620
4622 ast_free(cli_fd);
4623 return CLI_FAILURE;
4624 }
4625 return CLI_SUCCESS;
4626}
4627
4628static int kill_cores(void *obj, void *arg, int flags)
4629{
4630 int *core_id = arg;
4631 struct cc_core_instance *core_instance = obj;
4632
4633 if (!core_id || (core_instance->core_id == *core_id)) {
4634 ast_cc_failed(core_instance->core_id, "CC transaction canceled administratively\n");
4635 }
4636 return 0;
4637}
4638
4639static char *complete_core_id(const char *word)
4640{
4641 int wordlen = strlen(word);
4642 struct ao2_iterator core_iter = ao2_iterator_init(cc_core_instances, 0);
4643 struct cc_core_instance *core_instance;
4644
4645 for (; (core_instance = ao2_t_iterator_next(&core_iter, "Next core instance"));
4646 cc_unref(core_instance, "CLI tab completion iteration")) {
4647 char core_id_str[20];
4648 snprintf(core_id_str, sizeof(core_id_str), "%d", core_instance->core_id);
4649 if (!strncmp(word, core_id_str, wordlen)) {
4650 if (ast_cli_completion_add(ast_strdup(core_id_str))) {
4651 cc_unref(core_instance, "Found a matching core ID for CLI tab-completion");
4652 break;
4653 }
4654 }
4655 }
4656 ao2_iterator_destroy(&core_iter);
4657
4658 return NULL;
4659}
4660
4661static char *handle_cc_kill(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4662{
4663 switch (cmd) {
4664 case CLI_INIT:
4665 e->command = "cc cancel [core|all]";
4666 e->usage =
4667 "Usage: cc cancel can be used in two ways.\n"
4668 " 1. 'cc cancel core [core ID]' will cancel the CC transaction with\n"
4669 " core ID equal to the specified core ID.\n"
4670 " 2. 'cc cancel all' will cancel all active CC transactions.\n";
4671 return NULL;
4672 case CLI_GENERATE:
4673 if (a->pos == 3 && !strcasecmp(a->argv[2], "core")) {
4674 return complete_core_id(a->word);
4675 }
4676 return NULL;
4677 }
4678
4679 if (a->argc == 4) {
4680 int core_id;
4681 char *endptr;
4682 if (strcasecmp(a->argv[2], "core")) {
4683 return CLI_SHOWUSAGE;
4684 }
4685 core_id = strtol(a->argv[3], &endptr, 10);
4686 if ((errno != 0 && core_id == 0) || (endptr == a->argv[3])) {
4687 return CLI_SHOWUSAGE;
4688 }
4689 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, &core_id, "CLI Killing Core Id");
4690 } else if (a->argc == 3) {
4691 if (strcasecmp(a->argv[2], "all")) {
4692 return CLI_SHOWUSAGE;
4693 }
4694 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, NULL, "CLI Killing all CC cores");
4695 } else {
4696 return CLI_SHOWUSAGE;
4697 }
4698
4699 return CLI_SUCCESS;
4700}
4701
4702static struct ast_cli_entry cc_cli[] = {
4703 AST_CLI_DEFINE(handle_cc_status, "Reports CC stats"),
4704 AST_CLI_DEFINE(handle_cc_kill, "Kill a CC transaction"),
4705};
4706
4707static int unload_module(void)
4708{
4709 if (!global_enabled) {
4710 return 0;
4711 }
4712
4713 ast_devstate_prov_del("ccss");
4720
4721 if (cc_sched_context) {
4724 }
4727 }
4728 /* Note that core instances must be destroyed prior to the generic_monitors */
4729 if (cc_core_instances) {
4730 ao2_t_ref(cc_core_instances, -1, "Unref cc_core_instances container in cc_shutdown");
4732 }
4733 if (generic_monitors) {
4734 ao2_t_ref(generic_monitors, -1, "Unref generic_monitor container in cc_shutdown");
4736 }
4737
4738 return 0;
4739}
4740
4741static int load_module(void)
4742{
4743 int res;
4744
4745 res = load_config();
4746 if (res != 0) {
4748 }
4749
4753 "Create core instance container");
4754 if (!cc_core_instances) {
4756 }
4757
4760 generic_monitor_instance_list_hash_fn, NULL, generic_monitor_instance_list_cmp_fn,
4761 "Create generic monitor container");
4762 if (!generic_monitors) {
4764 }
4767 }
4770 }
4773 }
4778
4783
4785}
4786
4787AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Call Completion Supplementary Services",
4788 .support_level = AST_MODULE_SUPPORT_CORE,
4789 .load = load_module,
4790 .unload = unload_module,
4791 .load_pri = AST_MODPRI_CORE,
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
const char * str
Definition app_jack.c:150
enum queue_result id
Definition app_queue.c:1771
Asterisk main include file. File version handling, generic pbx functions.
void * __ast_malloc(size_t size, const char *file, int lineno, const char *func) attribute_malloc
Definition astmm.c:1628
#define ast_free(a)
Definition astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define ast_vasprintf(ret, fmt, ap)
A wrapper for vasprintf()
Definition astmm.h:278
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define ast_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
#define ast_log
Definition astobj2.c:42
#define ao2_t_ref(o, delta, tag)
Definition astobj2.h:460
@ CMP_MATCH
Definition astobj2.h:1027
@ CMP_STOP
Definition astobj2.h:1028
#define OBJ_POINTER
Definition astobj2.h:1150
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition astobj2.h:363
#define ao2_t_iterator_next(iter, tag)
Definition astobj2.h:1909
#define ao2_t_find(container, arg, flags, tag)
Definition astobj2.h:1734
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define AO2_STRING_FIELD_CMP_FN(stype, field)
Creates a compare function for a structure string field.
Definition astobj2.h:2048
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define ao2_t_link(container, obj, tag)
Definition astobj2.h:1534
int() ao2_callback_fn(void *obj, void *arg, int flags)
Type of a generic callback function.
Definition astobj2.h:1226
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
#define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag)
ao2_callback_data() is a generic function that applies cb_fn() to all objects in a container....
Definition astobj2.h:1721
#define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag)
Definition astobj2.h:1306
#define ao2_t_unlink(container, obj, tag)
Definition astobj2.h:1580
#define AO2_STRING_FIELD_HASH_FN(stype, field)
Creates a hash function for a structure string field.
Definition astobj2.h:2032
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition astobj2.h:407
@ OBJ_NODATA
Definition astobj2.h:1044
@ OBJ_MULTIPLE
Definition astobj2.h:1049
@ OBJ_UNLINK
Definition astobj2.h:1039
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
Definition astobj2.h:1696
Internal Asterisk hangup causes.
#define AST_CAUSE_CONGESTION
Definition causes.h:153
#define AST_CAUSE_BUSY
Definition causes.h:149
static int dialed_cc_interface_counter
Definition ccss.c:1892
static const struct ast_datastore_info recall_ds_info
Definition ccss.c:3417
static void cc_generic_agent_respond(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Definition ccss.c:2764
unsigned int ast_get_cc_recall_timer(struct ast_cc_config_params *config)
Get the cc_recall_timer.
Definition ccss.c:947
int ast_cc_available_timer_expire(const void *data)
Scheduler callback for available timer expiration.
Definition ccss.c:1523
static int cc_complete(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3275
int ast_cc_agent_caller_busy(int core_id, const char *debug,...)
Indicate that the caller is busy.
Definition ccss.c:3846
int ast_cc_agent_accept_request(int core_id, const char *const debug,...)
Accept inbound CC request.
Definition ccss.c:3807
static int cc_recalling(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3266
int ast_set_cc_agent_policy(struct ast_cc_config_params *config, enum ast_cc_agent_policies value)
Set the cc_agent_policy.
Definition ccss.c:888
static void cc_publish_requestacknowledged(int core_id, const char *caller)
Definition ccss.c:1101
#define CC_CALLER_REQUESTED_DEVSTATE_DEFAULT
Definition ccss.c:570
static struct ast_sched_context * cc_sched_context
Definition ccss.c:131
static int cc_caller_offered(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3082
static int cc_generic_agent_recall(struct ast_cc_agent *agent)
Definition ccss.c:2913
void ast_cc_call_failed(struct ast_channel *incoming, struct ast_channel *outgoing, const char *const dialstring)
Make CCBS available in the case that ast_call fails.
Definition ccss.c:4261
static struct extension_monitor_pvt * extension_monitor_pvt_init(void)
Definition ccss.c:2012
void ast_set_cc_max_monitors(struct ast_cc_config_params *config, unsigned int value)
Set the cc_max_monitors.
Definition ccss.c:1006
static int generic_monitor_devstate_tp_cb(void *data)
Definition ccss.c:1457
int ast_cc_monitor_party_b_free(int core_id)
Alert a caller that though the callee has become free, the caller himself is not and may not call bac...
Definition ccss.c:4104
static int cc_caller_requested(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3150
struct ast_cc_config_params * __ast_cc_config_params_init(const char *file, int line, const char *function)
Allocate and initialize an ast_cc_config_params structure.
Definition ccss.c:699
static void generic_monitor_instance_list_destructor(void *obj)
Definition ccss.c:1410
static void cc_interface_destroy(void *data)
Definition ccss.c:1754
static int cc_status_request(void *data)
Definition ccss.c:4025
static enum ast_device_state ccss_device_state(const char *device_name)
Definition ccss.c:619
int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks)
Register a set of monitor callbacks with the core.
Definition ccss.c:1186
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition ccss.c:714
static void unsuspend(struct cc_core_instance *core_instance)
Definition ccss.c:3164
static void cc_publish_callerstopmonitoring(int core_id, const char *caller)
Definition ccss.c:1112
void ast_set_ccbs_available_timer(struct ast_cc_config_params *config, unsigned int value)
Set the ccbs_available_timer.
Definition ccss.c:967
static void cc_publish_available(int core_id, const char *callee, const char *service)
Definition ccss.c:1065
void ast_ignore_cc(struct ast_channel *chan)
Mark the channel to ignore further CC activity.
Definition ccss.c:3747
int ast_cc_is_recall(struct ast_channel *chan, int *core_id, const char *const monitor_type)
Decide if a call to a particular channel is a CC recall.
Definition ccss.c:3459
void ast_handle_cc_control_frame(struct ast_channel *inbound, struct ast_channel *outbound, void *frame_data)
Properly react to a CC control frame.
Definition ccss.c:2334
static const char * agent_policy_to_str(enum ast_cc_agent_policies policy)
Definition ccss.c:749
static int cc_callee_ready(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3205
static const struct ast_cc_config_params cc_default_params
Definition ccss.c:681
unsigned int ast_get_cc_offer_timer(struct ast_cc_config_params *config)
Get the cc_offer_timer.
Definition ccss.c:917
static const int CC_CORE_INSTANCES_BUCKETS
Definition ccss.c:341
static void cancel_available_timer(struct cc_core_instance *core_instance)
Definition ccss.c:3244
static void cc_extension_monitor_destructor(void *private_data)
Definition ccss.c:1838
int ast_cc_monitor_stop_ringing(int core_id)
Alert a caller to stop ringing.
Definition ccss.c:4074
static const char * ccreq_app
Definition ccss.c:4325
int ast_setup_cc_recall_datastore(struct ast_channel *chan, const int core_id)
Set up a CC recall datastore on a channel.
Definition ccss.c:3423
static void * cc_unref(void *obj, const char *debug)
Definition ccss.c:165
#define CC_FAILED_DEVSTATE_DEFAULT
Definition ccss.c:576
static int cc_offer(const int core_id, const char *const debug,...)
Definition ccss.c:3769
static int cccancel_exec(struct ast_channel *chan, const char *data)
Definition ccss.c:4378
static void cc_recall_ds_destroy(void *data)
Definition ccss.c:3410
static void * cc_ref(void *obj, const char *debug)
Definition ccss.c:159
enum ast_cc_service_type service
Definition ccss.c:399
static struct ao2_container * cc_core_instances
Definition ccss.c:342
#define CC_COMPLETE_DEVSTATE_DEFAULT
Definition ccss.c:575
static unsigned int global_cc_max_requests
Definition ccss.c:153
static const char * cccancel_app
Definition ccss.c:4376
#define CC_AVAILABLE_DEVSTATE_DEFAULT
Definition ccss.c:568
static int(*const state_change_funcs[])(struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state)
Definition ccss.c:3291
int ast_cc_offer(struct ast_channel *caller_chan)
Offer CC to a caller.
Definition ccss.c:3780
void ast_set_cc_callback_sub(struct ast_cc_config_params *config, const char *const value)
Set the callback subroutine name.
Definition ccss.c:1016
#define CC_CALLER_BUSY_DEVSTATE_DEFAULT
Definition ccss.c:573
static int cc_generic_agent_stop_ringing(struct ast_cc_agent *agent)
Definition ccss.c:2778
static int cc_failed(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3284
static void ccss_notify_device_state_change(const char *device, enum cc_state state)
Definition ccss.c:660
void ast_cc_default_config_params(struct ast_cc_config_params *params)
Set the specified CC config params to default values.
Definition ccss.c:694
static void agent_destroy(void *data)
Definition ccss.c:2573
static void build_cc_interfaces_chanvar(struct ast_cc_monitor *starting_point, struct ast_str **str)
Definition ccss.c:3611
static int cc_generic_monitor_unsuspend(struct ast_cc_monitor *monitor)
Definition ccss.c:1640
static void initialize_cc_devstate_map(struct ast_config *cc_config)
Definition ccss.c:4497
static void initialize_cc_devstate_map_helper(struct ast_config *cc_config, enum cc_state state, const char *cc_setting)
Definition ccss.c:4473
static void cc_publish_monitorfailed(int core_id, const char *callee)
Definition ccss.c:1168
static int cc_core_instance_cmp_fn(void *obj, void *arg, int flags)
Definition ccss.c:439
static int global_enabled
Definition ccss.c:118
cc_state
The states used in the CCSS core state machine.
Definition ccss.c:196
@ CC_COMPLETE
Definition ccss.c:221
@ CC_CALLEE_READY
Definition ccss.c:209
@ CC_CALLER_OFFERED
Definition ccss.c:200
@ CC_ACTIVE
Definition ccss.c:206
@ CC_FAILED
Definition ccss.c:226
@ CC_CALLER_BUSY
Definition ccss.c:213
@ CC_AVAILABLE
Definition ccss.c:198
@ CC_RECALLING
Definition ccss.c:217
@ CC_CALLER_REQUESTED
Definition ccss.c:203
static void kill_duplicate_offers(char *caller)
Definition ccss.c:2544
int ast_cc_monitor_request_acked(int core_id, const char *const debug,...)
Indicate that an outbound entity has accepted our CC request.
Definition ccss.c:3820
#define GLOBAL_CC_MAX_REQUESTS_DEFAULT
Definition ccss.c:679
static void cc_publish_callerstartmonitoring(int core_id, const char *caller)
Definition ccss.c:1123
static int cc_caller_busy(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3233
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
Definition ccss.c:1247
static char * handle_cc_kill(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition ccss.c:4661
static void cc_publish_callerrecalling(int core_id, const char *caller)
Definition ccss.c:1134
void ast_set_cc_agent_dialstring(struct ast_cc_config_params *config, const char *const value)
Set the cc_agent_dialstring.
Definition ccss.c:982
static int cc_do_state_change(void *datap)
Definition ccss.c:3303
static void cc_publish_recallcomplete(int core_id, const char *caller)
Definition ccss.c:1145
#define CC_OFFER_TIMER_DEFAULT
Definition ccss.c:673
static const char * CC_LOGGER_LEVEL_NAME
Definition ccss.c:145
static struct ast_cc_monitor_callbacks generic_monitor_cbs
Definition ccss.c:1338
static void cc_publish_offertimerstart(int core_id, const char *caller, unsigned int expires)
Definition ccss.c:1077
static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
Definition ccss.c:2698
static int cc_cli_output_status(void *data)
Definition ccss.c:4578
static int ccreq_exec(struct ast_channel *chan, const char *data)
Definition ccss.c:4327
int ast_cc_agent_recalling(int core_id, const char *const debug,...)
Tell the CC core that a caller is currently recalling.
Definition ccss.c:3872
void ast_set_cc_offer_timer(struct ast_cc_config_params *config, unsigned int value)
Set the cc_offer_timer.
Definition ccss.c:922
static const struct @342 cc_state_to_string_map[]
static int offer_timer_expire(const void *data)
Definition ccss.c:2720
void ast_cc_copy_config_params(struct ast_cc_config_params *dest, const struct ast_cc_config_params *src)
copy CCSS configuration parameters from one structure to another
Definition ccss.c:876
void ast_set_cc_max_agents(struct ast_cc_config_params *config, unsigned int value)
Set the cc_max_agents.
Definition ccss.c:996
static void cc_core_instance_destructor(void *data)
Definition ccss.c:2946
static int cc_build_payload(struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *dialstring, enum ast_cc_service_type service, void *private_data, struct cc_control_payload *payload)
Definition ccss.c:4178
static int cc_generic_monitor_cancel_available_timer(struct ast_cc_monitor *monitor, int *sched_id)
Definition ccss.c:1668
#define CCNR_AVAILABLE_TIMER_DEFAULT
Definition ccss.c:674
int ast_cc_completed(struct ast_channel *chan, const char *const debug,...)
Indicate recall has been acknowledged.
Definition ccss.c:3885
unsigned int ast_get_ccbs_available_timer(struct ast_cc_config_params *config)
Get the ccbs_available_timer.
Definition ccss.c:962
match_flags
Definition ccss.c:488
@ MATCH_REQUEST
Definition ccss.c:496
@ MATCH_NO_REQUEST
Definition ccss.c:492
static const struct @341 cc_service_to_string_map[]
static struct ast_taskprocessor * cc_core_taskprocessor
Definition ccss.c:141
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition ccss.c:1025
static enum ast_device_state cc_state_to_devstate(enum cc_state state)
Definition ccss.c:603
static void request_cc(struct cc_core_instance *core_instance)
Definition ccss.c:3126
static const char * cc_state_to_string(enum cc_state state)
Definition ccss.c:423
static const struct ast_datastore_info dialed_cc_interfaces_info
Definition ccss.c:2006
struct ast_cc_agent * ast_cc_agent_callback(int flags, ao2_callback_fn *function, void *args, const char *const type)
Call a callback on all agents of a specific type.
Definition ccss.c:472
int ast_cc_set_param(struct ast_cc_config_params *params, const char *const name, const char *const value)
set a CCSS configuration parameter, given its name
Definition ccss.c:823
static void cc_generic_agent_destructor(struct ast_cc_agent *agent)
Definition ccss.c:2929
static int cc_generic_agent_start_monitoring(struct ast_cc_agent *agent)
Definition ccss.c:2820
static void cc_publish_requested(int core_id, const char *caller, const char *callee)
Definition ccss.c:1089
static int count_agents_cb(void *obj, void *arg, void *data, int flags)
Definition ccss.c:549
static struct cc_core_instance * cc_core_init_instance(struct ast_channel *caller_chan, struct cc_monitor_tree *called_tree, const int core_id, struct cc_control_payload *cc_data)
Definition ccss.c:2958
static struct ast_cc_agent * cc_agent_init(struct ast_channel *caller_chan, const char *const caller_name, const int core_id, struct cc_monitor_tree *interface_tree)
Definition ccss.c:2583
static enum ast_cc_monitor_policies str_to_monitor_policy(const char *const value)
Definition ccss.c:733
static const struct ast_cc_monitor_callbacks * find_monitor_callbacks(const char *const type)
Definition ccss.c:1205
int ast_cc_monitor_count(const char *const name, const char *const type)
Return the number of outstanding CC requests to a specific device.
Definition ccss.c:4438
static void suspend(struct cc_core_instance *core_instance)
Definition ccss.c:3211
unsigned int ast_get_ccnr_available_timer(struct ast_cc_config_params *config)
Get the ccnr_available_timer.
Definition ccss.c:932
void ast_set_ccnr_available_timer(struct ast_cc_config_params *config, unsigned int value)
Set the ccnr_available_timer.
Definition ccss.c:937
const char * service_string
Definition ccss.c:400
static void cc_cli_print_monitor_stats(struct ast_cc_monitor *monitor, int fd, int parent_id)
Definition ccss.c:4545
int ast_cc_monitor_callee_available(const int core_id, const char *const debug,...)
Alert the core that a device being monitored has become available.
Definition ccss.c:3833
unsigned int ast_get_cc_max_agents(struct ast_cc_config_params *config)
Get the cc_max_agents.
Definition ccss.c:991
void ast_cc_busy_interface(struct ast_channel *inbound, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, void *private_data)
Callback made from ast_cc_callback for certain channel types.
Definition ccss.c:4296
static enum ast_cc_agent_policies str_to_agent_policy(const char *const value)
Definition ccss.c:719
static void cc_monitor_destroy(void *data)
Definition ccss.c:1854
int ast_set_cc_monitor_policy(struct ast_cc_config_params *config, enum ast_cc_monitor_policies value)
Set the cc_monitor_policy.
Definition ccss.c:905
int ast_cc_build_frame(struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, enum ast_cc_service_type service, void *private_data, struct ast_frame *frame)
Create a CC Control frame.
Definition ccss.c:4235
void ast_set_cc_recall_timer(struct ast_cc_config_params *config, unsigned int value)
Set the cc_recall_timer.
Definition ccss.c:952
static int cc_generic_is_device_available(enum ast_device_state state)
Definition ccss.c:1327
int ast_set_cc_interfaces_chanvar(struct ast_channel *chan, const char *const extension)
Set the CC_INTERFACES channel variable for a channel using an.
Definition ccss.c:3693
static struct ast_cc_monitor * cc_device_monitor_init(const char *const device_name, const char *const dialstring, const struct cc_control_payload *cc_data, int core_id)
Definition ccss.c:2268
static int cc_party_b_free(void *data)
Definition ccss.c:4092
static int cc_generic_monitor_suspend(struct ast_cc_monitor *monitor)
Definition ccss.c:1599
int ast_cc_monitor_status_request(int core_id)
Request the status of a caller or callers.
Definition ccss.c:4035
enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config)
Get the cc_agent_policy.
Definition ccss.c:883
static int cc_request_count
Definition ccss.c:157
static int cc_generic_agent_status_request(struct ast_cc_agent *agent)
Definition ccss.c:2772
static int cc_active(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3186
static int cc_generic_agent_start_offer_timer(struct ast_cc_agent *agent)
Definition ccss.c:2732
struct ast_cc_monitor * ast_cc_get_monitor_by_recall_core_id(const int core_id, const char *const device_name)
Get the associated monitor given the device name and core_id.
Definition ccss.c:3542
static void * generic_recall(void *data)
Definition ccss.c:2845
enum cc_state state
Definition ccss.c:409
static void generic_monitor_devstate_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
Definition ccss.c:1498
const char * ast_get_cc_callback_sub(struct ast_cc_config_params *config)
Get the name of the callback subroutine.
Definition ccss.c:1011
static struct ast_cc_monitor * cc_extension_monitor_init(const char *const exten, const char *const context, const unsigned int parent_id)
Definition ccss.c:2108
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition ccss.c:447
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition ccss.c:3111
static int is_state_change_valid(enum cc_state current_state, const enum cc_state new_state, struct ast_cc_agent *agent)
Definition ccss.c:3019
void ast_cc_extension_monitor_add_dialstring(struct ast_channel *incoming, const char *const dialstring, const char *const device_name)
Add a child dialstring to an extension monitor.
Definition ccss.c:2022
struct ao2_container * generic_monitors
Definition ccss.c:1347
static int cc_logger_level
Definition ccss.c:149
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
Definition ccss.c:1222
static void cc_extension_monitor_change_is_valid(struct cc_core_instance *core_instance, unsigned int parent_id, const char *const device_name, int is_valid)
Definition ccss.c:2069
#define CC_MAX_AGENTS_DEFAULT
Definition ccss.c:677
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition ccss.c:900
const char * state_string
Definition ccss.c:410
static void check_callback_sanity(const struct ast_cc_agent_callbacks *callbacks)
Definition ccss.c:2561
unsigned int ast_get_cc_max_monitors(struct ast_cc_config_params *config)
Get the cc_max_monitors.
Definition ccss.c:1001
int ast_queue_cc_frame(struct ast_channel *chan, const char *monitor_type, const char *const dialstring, enum ast_cc_service_type service, void *private_data)
Queue an AST_CONTROL_CC frame.
Definition ccss.c:4206
static int cc_available(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3075
static int cc_generic_monitor_request_cc(struct ast_cc_monitor *monitor, int *available_timer_id)
Definition ccss.c:1536
static int cc_stop_ringing(void *data)
Definition ccss.c:4053
static int cc_interfaces_datastore_init(struct ast_channel *chan)
Definition ccss.c:2157
static int match_agent(void *obj, void *arg, void *data, int flags)
Definition ccss.c:511
static const struct ast_cc_agent_callbacks * find_agent_callbacks(struct ast_channel *chan)
Definition ccss.c:1283
static int count_monitors_cb(void *obj, void *arg, int flags)
Definition ccss.c:4418
#define RETURN_IF_NOT_ENABLED(rc)
Definition ccss.c:120
static struct generic_monitor_instance_list * create_new_generic_list(struct ast_cc_monitor *monitor)
Definition ccss.c:1423
int ast_cc_agent_caller_available(int core_id, const char *const debug,...)
Indicate that a previously unavailable caller has become available.
Definition ccss.c:3859
static int load_module(void)
Definition ccss.c:4741
static struct ast_cli_entry cc_cli[]
Definition ccss.c:4702
#define CCBS_AVAILABLE_TIMER_DEFAULT
Definition ccss.c:675
#define CC_CALLEE_READY_DEVSTATE_DEFAULT
Definition ccss.c:572
int ast_cc_get_param(struct ast_cc_config_params *params, const char *const name, char *buf, size_t buf_len)
get a CCSS configuration parameter, given its name
Definition ccss.c:780
static void generic_agent_devstate_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
Definition ccss.c:2790
static void cc_unique_append(struct ast_str **str, const char *dialstring)
Definition ccss.c:3582
int ast_cc_agent_set_interfaces_chanvar(struct ast_channel *chan)
Set the first level CC_INTERFACES channel variable for a channel.
Definition ccss.c:3654
static const char * monitor_policy_to_str(enum ast_cc_monitor_policies policy)
Definition ccss.c:764
static char * handle_cc_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition ccss.c:4595
int ast_cc_call_init(struct ast_channel *chan, int *ignore_cc)
Start the CC process on a call.
Definition ccss.c:2429
int ast_cc_agent_status_response(int core_id, enum ast_device_state devstate)
Response with a caller's current status.
Definition ccss.c:4148
int ast_cc_is_enabled(void)
Determine if CCSS is enabled.
Definition ccss.c:4540
static enum ast_device_state cc_state_to_devstate_map[]
Definition ccss.c:582
static int unload_module(void)
Definition ccss.c:4707
int ast_cc_monitor_failed(int core_id, const char *const monitor_name, const char *const debug,...)
Indicate that a failure has occurred on a specific monitor.
Definition ccss.c:3988
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition ccss.c:3924
static void call_destructor_with_no_monitor(const char *const monitor_type, void *private_data)
Definition ccss.c:2233
static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent)
Definition ccss.c:2751
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition ccss.c:1265
static int print_stats_cb(void *obj, void *arg, int flags)
Definition ccss.c:4565
static void dialed_cc_interfaces_destroy(void *data)
Definition ccss.c:1961
static int cc_agent_callback_helper(void *obj, void *args, int flags)
Definition ccss.c:460
static void cc_publish_failure(int core_id, const char *caller, const char *reason)
Definition ccss.c:1156
int ast_cc_request_is_within_limits(void)
Check if the incoming CC request is within the bounds set by the cc_max_requests configuration option...
Definition ccss.c:2509
#define CC_RECALL_TIMER_DEFAULT
Definition ccss.c:676
static void cc_interface_tree_destroy(void *data)
Definition ccss.c:1875
static long count_agents(const char *const caller, const int core_id_exception)
Definition ccss.c:2535
#define CC_CALLER_OFFERED_DEVSTATE_DEFAULT
Definition ccss.c:569
#define CC_RECALLING_DEVSTATE_DEFAULT
Definition ccss.c:574
static void * dialed_cc_interfaces_duplicate(void *data)
Definition ccss.c:1981
static int kill_cores(void *obj, void *arg, int flags)
Definition ccss.c:4628
static int load_config(void)
Definition ccss.c:4511
static void * cc_recall_ds_duplicate(void *data)
Definition ccss.c:3396
static struct generic_monitor_instance_list * find_generic_monitor_instance_list(const char *const device_name)
Definition ccss.c:1400
static char * complete_core_id(const char *word)
Definition ccss.c:4639
int ast_cc_callback(struct ast_channel *inbound, const char *const tech, const char *const dest, ast_cc_callback_fn callback)
Run a callback for potential matching destinations.
Definition ccss.c:4311
static int cc_core_instance_hash_fn(const void *obj, const int flags)
Definition ccss.c:433
static int cc_status_response(void *data)
Definition ccss.c:4127
int ast_cc_get_current_core_id(struct ast_channel *chan)
Get the core id for the current call.
Definition ccss.c:2514
static int cc_monitor_failed(void *data)
Definition ccss.c:3943
int ast_cc_is_config_param(const char *const name)
Is this a CCSS configuration parameter?
Definition ccss.c:862
static int core_id_counter
Definition ccss.c:136
#define CC_MAX_MONITORS_DEFAULT
Definition ccss.c:678
static void initialize_cc_max_requests(struct ast_config *cc_config)
Definition ccss.c:4449
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition ccss.c:3346
#define CC_ACTIVE_DEVSTATE_DEFAULT
Definition ccss.c:571
const char * ast_get_cc_agent_dialstring(struct ast_cc_config_params *config)
Get the cc_agent_dialstring.
Definition ccss.c:977
static void cc_generic_monitor_destructor(void *private_data)
Definition ccss.c:1685
static const char * cc_service_to_string(enum ast_cc_service_type service)
Definition ccss.c:428
static struct ast_cc_agent_callbacks generic_agent_callbacks
Definition ccss.c:2635
Call Completion Supplementary Services API.
#define ast_cc_config_params_init()
Allocate and initialize an ast_cc_config_params structure.
Definition ccss.h:135
#define AST_CC_GENERIC_MONITOR_TYPE
Definition ccss.h:455
void(* ast_cc_callback_fn)(struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, void *private_data)
Callback made from ast_cc_callback for certain channel types.
Definition ccss.h:1562
ast_cc_agent_response_reason
Definition ccss.h:841
@ AST_CC_AGENT_RESPONSE_FAILURE_INVALID
Definition ccss.h:845
@ AST_CC_AGENT_RESPONSE_SUCCESS
Definition ccss.h:843
@ AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY
Definition ccss.h:847
ast_cc_service_type
Definition ccss.h:32
@ AST_CC_CCNL
Definition ccss.h:40
@ AST_CC_CCBS
Definition ccss.h:36
@ AST_CC_NONE
Definition ccss.h:34
@ AST_CC_CCNR
Definition ccss.h:38
ast_cc_monitor_policies
The various possibilities for cc_monitor_policy values.
Definition ccss.h:74
@ AST_CC_MONITOR_NEVER
Definition ccss.h:76
@ AST_CC_MONITOR_ALWAYS
Definition ccss.h:87
@ AST_CC_MONITOR_NATIVE
Definition ccss.h:78
@ AST_CC_MONITOR_GENERIC
Definition ccss.h:83
ast_cc_agent_policies
The various possibilities for cc_agent_policy values.
Definition ccss.h:47
@ AST_CC_AGENT_NEVER
Definition ccss.h:49
@ AST_CC_AGENT_GENERIC
Definition ccss.h:53
@ AST_CC_AGENT_NATIVE
Definition ccss.h:51
@ AST_CC_AGENT_SKIP_OFFER
Definition ccss.h:67
@ AST_CC_EXTENSION_MONITOR
Definition ccss.h:464
@ AST_CC_DEVICE_MONITOR
Definition ccss.h:463
static const char type[]
static const char config[]
static void dummy(char *unused,...)
General Asterisk PBX channel definitions.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_get_device_name(struct ast_channel *chan, char *device_name, size_t name_buffer_length)
Get a device name given its channel structure.
Definition channel.c:10544
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition channel.c:2375
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition channel.c:2538
#define DATASTORE_INHERIT_FOREVER
Definition channel.h:194
#define ast_channel_lock(chan)
Definition channel.h:2982
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition channel.c:1170
const char * ast_channel_context(const struct ast_channel *chan)
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
Definition channel.c:1399
int ast_channel_hangupcause(const struct ast_channel *chan)
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition channel.c:4648
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition channel.c:2461
#define AST_CHANNEL_NAME
Definition channel.h:173
struct ast_channel * ast_request_and_dial(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int timeout, int *reason, const char *cid_num, const char *cid_name)
Request a channel of a given type, with data as optional information used by the low level module and...
Definition channel.c:6169
void ast_channel_context_set(struct ast_channel *chan, const char *value)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_priority_set(struct ast_channel *chan, int value)
const struct ast_channel_tech * ast_get_channel_tech(const char *name)
Get a channel technology structure by name.
Definition channel.c:592
const char * ast_channel_exten(const struct ast_channel *chan)
@ AST_SOFTHANGUP_EXPLICIT
Definition channel.h:1168
struct ast_cc_config_params * ast_channel_get_cc_config_params(struct ast_channel *chan)
Get the CCSS parameters from a channel.
Definition channel.c:10518
#define ast_channel_unlock(chan)
Definition channel.h:2983
#define AST_MAX_EXTENSION
Definition channel.h:134
int ast_channel_get_cc_agent_type(struct ast_channel *chan, char *agent_type, size_t size)
Find the appropriate CC agent type to use given a channel.
Definition channel.c:10561
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition channel.c:2389
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int rdlock)
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition cli.h:45
#define CLI_SUCCESS
Definition cli.h:44
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition main/cli.c:2737
void ast_cli(int fd, const char *fmt,...)
Definition clicompat.c:6
@ CLI_INIT
Definition cli.h:152
@ CLI_GENERATE
Definition cli.h:153
#define CLI_FAILURE
Definition cli.h:46
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition cli.h:265
short word
#define ast_datastore_alloc(info, uid)
Definition datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition datastore.c:68
Device state management.
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
int ast_devstate_prov_del(const char *label)
Remove device state provider.
@ AST_DEVSTATE_CACHABLE
Definition devicestate.h:70
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Convert device state to text string for output.
enum ast_device_state ast_devstate_val(const char *val)
Convert device state from text to integer value.
struct stasis_topic * ast_device_state_topic(const char *device)
Get the Stasis topic for device state messages for a specific device.
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
ast_device_state
Device States.
Definition devicestate.h:52
@ AST_DEVICE_INUSE
Definition devicestate.h:55
@ AST_DEVICE_UNKNOWN
Definition devicestate.h:53
@ AST_DEVICE_BUSY
Definition devicestate.h:56
@ AST_DEVICE_NOT_INUSE
Definition devicestate.h:54
@ AST_DEVICE_UNAVAILABLE
Definition devicestate.h:58
static int enabled
Definition dnsmgr.c:91
char buf[BUFSIZE]
Definition eagi_proxy.c:66
static struct ao2_container * interfaces
Container for registered format interfaces.
Definition format.c:65
Media Format Cache API.
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition format_cap.h:49
static const char name[]
Definition format_mp3.c:68
struct stasis_message_type * stasis_subscription_change_type(void)
Gets the message type for subscription change notices.
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
Run a subroutine on a channel, placing an optional second channel into autoservice.
Definition main/app.c:297
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
#define ast_frfree(fr)
#define AST_MALLOCD_DATA
@ AST_FRAME_CONTROL
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition logger.c:2821
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition logger.c:2879
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition json.c:73
struct ast_json_payload * ast_json_payload_create(struct ast_json *json)
Create an ao2 object to pass json blobs as data payloads for stasis.
Definition json.c:756
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition json.c:612
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition json.h:87
int ast_json_object_update(struct ast_json *object, struct ast_json *other)
Update object with all of the fields of other.
Definition json.c:426
#define AST_RWLIST_REMOVE_CURRENT
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition linkedlists.h:78
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_RWLIST_TRAVERSE_SAFE_END
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_LOCK(head)
Locks a list.
Definition linkedlists.h:40
#define AST_RWLIST_TRAVERSE
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_RWLIST_INSERT_TAIL
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition lock.h:764
int errno
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition module.h:331
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition module.h:330
int ast_register_application2(const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
Register an application.
Definition pbx_app.c:104
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition module.h:557
@ AST_MODPRI_CORE
Definition module.h:338
@ AST_MODULE_SUPPORT_CORE
Definition module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition module.h:46
int ast_unregister_application(const char *app)
Unregister an application.
Definition pbx_app.c:392
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
Definition module.h:102
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
Core PBX routines and definitions.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition pbx.c:4729
static struct stasis_subscription * sub
Statsd channel stats. Exmaple of how to subscribe to Stasis events.
struct @506 callbacks
static struct @519 args
static int debug
Global debug status.
Definition res_xmpp.c:570
#define NULL
Definition resample.c:96
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
Definition sched.c:614
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition sched.c:567
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition sched.c:271
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Definition sched.c:197
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition sched.c:238
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition stasis.h:297
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition stasis.c:1090
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition stasis.c:1144
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
int stasis_subscription_final_message(struct stasis_subscription *sub, struct stasis_message *msg)
Determine whether a message is the final message to be received on a subscription.
Definition stasis.c:1241
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
Definition stasis.c:1038
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition stasis.c:1578
#define stasis_subscribe(topic, callback, data)
Definition stasis.h:649
struct stasis_message_type * ast_cc_monitorfailed_type(void)
A stasis_message_type for CCSS Monitor Failed messages.
struct stasis_message_type * ast_cc_recallcomplete_type(void)
A stasis_message_type for CCSS Recall Complete messages.
struct stasis_message_type * ast_cc_callerrecalling_type(void)
A stasis_message_type for CCSS Caller Recalling messages.
struct stasis_topic * ast_system_topic(void)
A Stasis Message Bus API topic which publishes messages regarding system changes.
struct stasis_message_type * ast_cc_failure_type(void)
A stasis_message_type for CCSS Failure messages.
struct stasis_message_type * ast_cc_callerstopmonitoring_type(void)
A stasis_message_type for CCSS Caller Stop Monitoring messages.
struct stasis_message_type * ast_cc_available_type(void)
A stasis_message_type for CCSS Available messages.
struct stasis_message_type * ast_cc_requestacknowledged_type(void)
A stasis_message_type for CCSS Request Acknowledged messages.
struct stasis_message_type * ast_cc_callerstartmonitoring_type(void)
A stasis_message_type for CCSS Caller Start Monitoring messages.
struct stasis_message_type * ast_cc_offertimerstart_type(void)
A stasis_message_type for CCSS Offer Timer Start messages.
struct stasis_message_type * ast_cc_requested_type(void)
A stasis_message_type for CCSS Requested messages.
String manipulation functions.
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Definition strings.h:786
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition strings.h:1139
size_t attribute_pure ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition strings.h:730
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition utils.c:2235
char * ast_tech_to_upper(char *dev_str)
Convert the tech portion of a device string to upper case.
Definition strings.h:1236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
#define ast_str_alloca(init_len)
Definition strings.h:848
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition strings.h:1113
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
Structure representing an agent.
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition astobj2.h:1821
int(* party_b_free)(struct ast_cc_agent *agent)
Let the caller know that the callee has become free but that the caller cannot attempt to call back b...
Definition ccss.h:986
int(* status_request)(struct ast_cc_agent *agent)
Request the status of the agent's device.
Definition ccss.h:943
int(* stop_ringing)(struct ast_cc_agent *agent)
Request for an agent's phone to stop ringing.
Definition ccss.h:965
const char * type
Type of agent the callbacks belong to.
Definition ccss.h:857
int(* start_offer_timer)(struct ast_cc_agent *agent)
Start the offer timer.
Definition ccss.h:897
int(* start_monitoring)(struct ast_cc_agent *agent)
Begin monitoring a busy device.
Definition ccss.h:1002
void(* respond)(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Respond to a CC request.
Definition ccss.h:928
void(* destructor)(struct ast_cc_agent *agent)
Destroy private data on the agent.
Definition ccss.h:1035
int(* stop_offer_timer)(struct ast_cc_agent *agent)
Stop the offer timer.
Definition ccss.h:910
int(* callee_available)(struct ast_cc_agent *agent)
Alert the caller that it is time to try recalling.
Definition ccss.h:1021
int(* init)(struct ast_cc_agent *agent, struct ast_channel *chan)
CC agent initialization.
Definition ccss.h:876
unsigned int core_id
Definition ccss.h:812
const struct ast_cc_agent_callbacks * callbacks
Definition ccss.h:817
unsigned int flags
Flags for agent operation.
Definition ccss.h:832
struct ast_cc_config_params * cc_params
Definition ccss.h:822
void * private_data
Definition ccss.h:834
char device_name[1]
Definition ccss.h:838
enum ast_cc_monitor_policies cc_monitor_policy
Definition ccss.c:179
unsigned int cc_recall_timer
Definition ccss.c:183
unsigned int ccnr_available_timer
Definition ccss.c:181
unsigned int cc_max_monitors
Definition ccss.c:185
char cc_callback_sub[AST_MAX_EXTENSION]
Definition ccss.c:186
char cc_agent_dialstring[AST_MAX_EXTENSION]
Definition ccss.c:187
enum ast_cc_agent_policies cc_agent_policy
Definition ccss.c:178
unsigned int cc_offer_timer
Definition ccss.c:180
unsigned int ccbs_available_timer
Definition ccss.c:182
unsigned int cc_max_agents
Definition ccss.c:184
Structure with information about an outbound interface.
Definition ccss.h:781
const char * monitor_type
The type of monitor that should be used for this interface.
Definition ccss.h:793
enum ast_cc_monitor_class monitor_class
Definition ccss.h:784
struct ast_cc_config_params * config_params
Definition ccss.h:797
char device_name[1]
Definition ccss.h:802
Callbacks defined by CC monitors.
Definition ccss.h:542
int(* status_response)(struct ast_cc_monitor *monitor, enum ast_device_state devstate)
Status response to an ast_cc_monitor_status_request().
Definition ccss.h:594
int(* request_cc)(struct ast_cc_monitor *monitor, int *available_timer_id)
Request CCSS.
Definition ccss.h:565
int(* cancel_available_timer)(struct ast_cc_monitor *monitor, int *sched_id)
Cancel the running available timer.
Definition ccss.h:623
void(* destructor)(void *private_data)
Destroy private data on the monitor.
Definition ccss.h:634
const char * type
Type of monitor the callbacks belong to.
Definition ccss.h:549
int(* unsuspend)(struct ast_cc_monitor *monitor)
Unsuspend monitoring.
Definition ccss.h:606
int(* suspend)(struct ast_cc_monitor *monitor)
Suspend monitoring.
Definition ccss.h:578
const char * device_name
Definition ccss.c:3938
const struct ast_cc_monitor_callbacks * callbacks
Definition ccss.h:517
struct ast_cc_interface * interface
Definition ccss.h:480
int core_id
Definition ccss.h:494
unsigned int parent_id
Definition ccss.h:490
unsigned int id
Definition ccss.h:485
struct ast_cc_monitor * next
Definition ccss.h:528
void * private_data
Data that is private to a monitor technology.
Definition ccss.h:527
int available_timer_id
Definition ccss.h:513
enum ast_cc_service_type service_offered
Definition ccss.h:498
char * dialstring
Name that should be used to recall specified interface.
Definition ccss.h:509
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition channel.h:648
int(* cc_callback)(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
Call a function with cc parameters as a function parameter.
Definition channel.h:847
Main Channel structure associated with a channel.
descriptor for a cli entry.
Definition cli.h:171
char * command
Definition cli.h:186
const char * usage
Definition cli.h:177
Structure for a data store type.
Definition datastore.h:31
const char * type
Definition datastore.h:32
Structure for a data store object.
Definition datastore.h:64
struct ast_datastore * next
Definition datastore.h:70
void * data
Definition datastore.h:66
unsigned int inheritance
Definition datastore.h:69
The structure that contains device state.
enum ast_device_state state
const struct ast_eid * eid
The EID of the server where this message originated.
Structure used to handle boolean flags.
Definition utils.h:220
Format capabilities structure, holds formats + preference order + etc.
Definition format_cap.c:54
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
union ast_frame::@239 data
Abstract JSON element (object, array, string, int, ...).
Support for dynamic strings.
Definition strings.h:623
A ast_taskprocessor structure is a singleton by name.
const struct ast_cc_agent_callbacks * callbacks
Definition ccss.c:1242
struct cc_agent_backend * next
Definition ccss.c:1241
const char * type
Definition ccss.c:457
ao2_callback_fn * function
Definition ccss.c:455
The payload for an AST_CONTROL_CC frame.
Definition ccss.c:237
const char * monitor_type
The type of monitor to allocate.
Definition ccss.c:255
int parent_interface_id
ID of parent extension.
Definition ccss.c:299
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition ccss.c:308
enum ast_cc_service_type service
Service offered by the endpoint.
Definition ccss.c:281
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition ccss.c:320
void * private_data
Private data allocated by the callee.
Definition ccss.c:272
struct ast_cc_config_params config_params
Configuration parameters used by this endpoint.
Definition ccss.c:290
enum cc_state current_state
Definition ccss.c:352
struct ast_cc_agent * agent
Definition ccss.c:356
struct cc_monitor_tree * monitors
Definition ccss.c:360
struct stasis_subscription * sub
Definition ccss.c:2657
char context[AST_CHANNEL_NAME]
Definition ccss.c:2695
char cid_num[AST_CHANNEL_NAME]
Definition ccss.c:2671
char cid_name[AST_CHANNEL_NAME]
Definition ccss.c:2679
char exten[AST_CHANNEL_NAME]
Definition ccss.c:2687
const struct ast_cc_monitor_callbacks * callbacks
Definition ccss.c:1181
struct cc_monitor_backend * next
Definition ccss.c:1180
The "tree" of interfaces that is dialed.
Definition ccss.c:339
struct cc_monitor_tree * interface_tree
Definition ccss.c:3393
enum cc_state state
Definition ccss.c:3014
struct cc_core_instance * core_instance
Definition ccss.c:3013
enum ast_device_state devstate
Definition ccss.c:4124
struct cc_core_instance * core_instance
Definition ccss.c:4123
const char * monitor_type
Definition ccss.c:4414
const char * device_name
Definition ccss.c:4413
struct cc_monitor_tree * interface_tree
Definition ccss.c:1946
char is_original_caller
Definition ccss.c:1942
unsigned int dial_parent_id
Definition ccss.c:1919
Data regarding an extension monitor's child's dialstrings.
Definition ccss.c:1777
char device_name[AST_CHANNEL_NAME]
The name of the device being dialed.
Definition ccss.c:1812
int is_valid
Is this structure valid for use in CC_INTERFACES?
Definition ccss.c:1827
struct extension_child_dialstring * next
Definition ccss.c:1828
char original_dialstring[AST_CHANNEL_NAME]
the original dialstring used to call a particular device
Definition ccss.c:1793
Private data for an extension monitor.
Definition ccss.c:1834
struct extension_monitor_pvt::@348 child_dialstrings
structure to hold extensions
struct stasis_subscription * sub
Definition ccss.c:1375
enum ast_device_state current_state
Definition ccss.c:1358
struct generic_monitor_instance_list::@346 list
struct generic_monitor_instance * next
Definition ccss.c:1353
private data for generic device monitor
Definition ccss.c:1382
const char * device_name
Definition ccss.c:1387
Number structure.
Scheduler ID holder.
Definition sched.c:70
int value
Definition syslog.c:37
An API for managing task processing threads that can be shared across modules.
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
@ TPS_REF_DEFAULT
return a reference to a taskprocessor, create one if it does not exist
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct test_val a
Utility functions.
#define ast_test_flag(p, flag)
Definition utils.h:64
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981
#define ast_assert(a)
Definition utils.h:779
#define ast_pthread_create_detached_background(a, b, c, d)
Definition utils.h:637
#define ast_set_flag(p, flag)
Definition utils.h:71
#define ARRAY_LEN(a)
Definition utils.h:706