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