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