00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "asterisk.h"
00025
00026 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 307879 $")
00027
00028 #include "asterisk/astobj2.h"
00029 #include "asterisk/strings.h"
00030 #include "asterisk/ccss.h"
00031 #include "asterisk/channel.h"
00032 #include "asterisk/pbx.h"
00033 #include "asterisk/utils.h"
00034 #include "asterisk/taskprocessor.h"
00035 #include "asterisk/event.h"
00036 #include "asterisk/module.h"
00037 #include "asterisk/app.h"
00038 #include "asterisk/cli.h"
00039 #include "asterisk/manager.h"
00040 #include "asterisk/causes.h"
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 static struct ast_sched_thread *cc_sched_thread;
00074
00075
00076
00077
00078 static int core_id_counter;
00079
00080
00081
00082
00083 static struct ast_taskprocessor *cc_core_taskprocessor;
00084
00085
00086
00087 static const char *CC_LOGGER_LEVEL_NAME = "CC";
00088
00089
00090
00091 static int cc_logger_level;
00092
00093
00094
00095 static unsigned int global_cc_max_requests;
00096
00097
00098
00099 static int cc_request_count;
00100
00101 static inline void *cc_ref(void *obj, const char *debug)
00102 {
00103 ao2_t_ref(obj, +1, debug);
00104 return obj;
00105 }
00106
00107 static inline void *cc_unref(void *obj, const char *debug)
00108 {
00109 ao2_t_ref(obj, -1, debug);
00110 return NULL;
00111 }
00112
00113
00114
00115
00116
00117
00118
00119 struct ast_cc_config_params {
00120 enum ast_cc_agent_policies cc_agent_policy;
00121 enum ast_cc_monitor_policies cc_monitor_policy;
00122 unsigned int cc_offer_timer;
00123 unsigned int ccnr_available_timer;
00124 unsigned int ccbs_available_timer;
00125 unsigned int cc_recall_timer;
00126 unsigned int cc_max_agents;
00127 unsigned int cc_max_monitors;
00128 char cc_callback_macro[AST_MAX_EXTENSION];
00129 char cc_agent_dialstring[AST_MAX_EXTENSION];
00130 };
00131
00132
00133
00134
00135
00136
00137
00138 enum cc_state {
00139
00140 CC_AVAILABLE,
00141
00142 CC_CALLER_OFFERED,
00143
00144
00145 CC_CALLER_REQUESTED,
00146
00147
00148 CC_ACTIVE,
00149
00150
00151 CC_CALLEE_READY,
00152
00153
00154
00155 CC_CALLER_BUSY,
00156
00157
00158
00159 CC_RECALLING,
00160
00161
00162
00163 CC_COMPLETE,
00164
00165
00166
00167
00168 CC_FAILED,
00169 };
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 struct cc_control_payload {
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 const char *monitor_type;
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 void *private_data;
00215
00216
00217
00218
00219
00220
00221
00222
00223 enum ast_cc_service_type service;
00224
00225
00226
00227
00228
00229
00230
00231
00232 struct ast_cc_config_params config_params;
00233
00234
00235
00236
00237
00238
00239
00240
00241 int parent_interface_id;
00242
00243
00244
00245
00246
00247
00248
00249
00250 char device_name[AST_CHANNEL_NAME];
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 char dialstring[AST_CHANNEL_NAME];
00263 };
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 AST_LIST_HEAD(cc_monitor_tree, ast_cc_monitor);
00282
00283 static const int CC_CORE_INSTANCES_BUCKETS = 17;
00284 static struct ao2_container *cc_core_instances;
00285
00286 struct cc_core_instance {
00287
00288
00289
00290 int core_id;
00291
00292
00293
00294 enum cc_state current_state;
00295
00296
00297
00298 struct ast_cc_agent *agent;
00299
00300
00301
00302 struct cc_monitor_tree *monitors;
00303 };
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 static int __attribute__((format(printf, 3, 0))) cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap);
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 static struct cc_core_instance *cc_core_init_instance(struct ast_channel *caller_chan,
00337 struct cc_monitor_tree *called_tree, const int core_id, struct cc_control_payload *cc_data);
00338
00339 static const struct {
00340 enum ast_cc_service_type service;
00341 const char *service_string;
00342 } cc_service_to_string_map[] = {
00343 {AST_CC_NONE, "NONE"},
00344 {AST_CC_CCBS, "CCBS"},
00345 {AST_CC_CCNR, "CCNR"},
00346 {AST_CC_CCNL, "CCNL"},
00347 };
00348
00349 static const struct {
00350 enum cc_state state;
00351 const char *state_string;
00352 } cc_state_to_string_map[] = {
00353 {CC_AVAILABLE, "CC is available"},
00354 {CC_CALLER_OFFERED, "CC offered to caller"},
00355 {CC_CALLER_REQUESTED, "CC requested by caller"},
00356 {CC_ACTIVE, "CC accepted by callee"},
00357 {CC_CALLEE_READY, "Callee has become available"},
00358 {CC_CALLER_BUSY, "Callee was ready, but caller is now unavailable"},
00359 {CC_RECALLING, "Caller is attempting to recall"},
00360 {CC_COMPLETE, "Recall complete"},
00361 {CC_FAILED, "CC has failed"},
00362 };
00363
00364 static const char *cc_state_to_string(enum cc_state state)
00365 {
00366 return cc_state_to_string_map[state].state_string;
00367 }
00368
00369 static const char *cc_service_to_string(enum ast_cc_service_type service)
00370 {
00371 return cc_service_to_string_map[service].service_string;
00372 }
00373
00374 static int cc_core_instance_hash_fn(const void *obj, const int flags)
00375 {
00376 const struct cc_core_instance *core_instance = obj;
00377 return core_instance->core_id;
00378 }
00379
00380 static int cc_core_instance_cmp_fn(void *obj, void *arg, int flags)
00381 {
00382 struct cc_core_instance *core_instance1 = obj;
00383 struct cc_core_instance *core_instance2 = arg;
00384
00385 return core_instance1->core_id == core_instance2->core_id ? CMP_MATCH | CMP_STOP : 0;
00386 }
00387
00388 static struct cc_core_instance *find_cc_core_instance(const int core_id)
00389 {
00390 struct cc_core_instance finder = {.core_id = core_id,};
00391
00392 return ao2_t_find(cc_core_instances, &finder, OBJ_POINTER, "Finding a core_instance");
00393 }
00394
00395 struct cc_callback_helper {
00396 ao2_callback_fn *function;
00397 void *args;
00398 const char *type;
00399 };
00400
00401 static int cc_agent_callback_helper(void *obj, void *args, int flags)
00402 {
00403 struct cc_core_instance *core_instance = obj;
00404 struct cc_callback_helper *helper = args;
00405
00406 if (strcmp(core_instance->agent->callbacks->type, helper->type)) {
00407 return 0;
00408 }
00409
00410 return helper->function(core_instance->agent, helper->args, flags);
00411 }
00412
00413 struct ast_cc_agent *ast_cc_agent_callback(int flags, ao2_callback_fn *function, void *args, const char * const type)
00414 {
00415 struct cc_callback_helper helper = {.function = function, .args = args, .type = type};
00416 struct cc_core_instance *core_instance;
00417 if ((core_instance = ao2_t_callback(cc_core_instances, flags, cc_agent_callback_helper, &helper,
00418 "Calling provided agent callback function"))) {
00419 struct ast_cc_agent *agent = cc_ref(core_instance->agent, "An outside entity needs the agent");
00420 cc_unref(core_instance, "agent callback done with the core_instance");
00421 return agent;
00422 }
00423 return NULL;
00424 }
00425
00426 enum match_flags {
00427
00428
00429
00430 MATCH_NO_REQUEST = (1 << 0),
00431
00432
00433
00434 MATCH_REQUEST = (1 << 1),
00435 };
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 static int match_agent(void *obj, void *arg, void *data, int flags)
00450 {
00451 struct cc_core_instance *core_instance = obj;
00452 const char *name = arg;
00453 unsigned long match_flags = *(unsigned long *)data;
00454 int possible_match = 0;
00455
00456 if ((match_flags & MATCH_NO_REQUEST) && core_instance->current_state < CC_CALLER_REQUESTED) {
00457 possible_match = 1;
00458 }
00459
00460 if ((match_flags & MATCH_REQUEST) && core_instance->current_state >= CC_CALLER_REQUESTED) {
00461 possible_match = 1;
00462 }
00463
00464 if (!possible_match) {
00465 return 0;
00466 }
00467
00468 if (!strcmp(core_instance->agent->device_name, name)) {
00469 return CMP_MATCH | CMP_STOP;
00470 }
00471 return 0;
00472 }
00473
00474 struct count_agents_cb_data {
00475 int count;
00476 int core_id_exception;
00477 };
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 static int count_agents_cb(void *obj, void *arg, void *data, int flags)
00488 {
00489 struct cc_core_instance *core_instance = obj;
00490 const char *name = arg;
00491 struct count_agents_cb_data *cb_data = data;
00492
00493 if (cb_data->core_id_exception == core_instance->core_id) {
00494 ast_log_dynamic_level(cc_logger_level, "Found agent with core_id %d but not counting it toward total\n", core_instance->core_id);
00495 return 0;
00496 }
00497
00498 if (core_instance->current_state >= CC_CALLER_REQUESTED && !strcmp(core_instance->agent->device_name, name)) {
00499 cb_data->count++;
00500 }
00501 return 0;
00502 }
00503
00504 #define CC_OFFER_TIMER_DEFAULT 20
00505 #define CCNR_AVAILABLE_TIMER_DEFAULT 7200
00506 #define CCBS_AVAILABLE_TIMER_DEFAULT 4800
00507 #define CC_RECALL_TIMER_DEFAULT 20
00508 #define CC_MAX_AGENTS_DEFAULT 5
00509 #define CC_MAX_MONITORS_DEFAULT 5
00510 #define GLOBAL_CC_MAX_REQUESTS_DEFAULT 20
00511
00512 static const struct ast_cc_config_params cc_default_params = {
00513 .cc_agent_policy = AST_CC_AGENT_NEVER,
00514 .cc_monitor_policy = AST_CC_MONITOR_NEVER,
00515 .cc_offer_timer = CC_OFFER_TIMER_DEFAULT,
00516 .ccnr_available_timer = CCNR_AVAILABLE_TIMER_DEFAULT,
00517 .ccbs_available_timer = CCBS_AVAILABLE_TIMER_DEFAULT,
00518 .cc_recall_timer = CC_RECALL_TIMER_DEFAULT,
00519 .cc_max_agents = CC_MAX_AGENTS_DEFAULT,
00520 .cc_max_monitors = CC_MAX_MONITORS_DEFAULT,
00521 .cc_callback_macro = "",
00522 .cc_agent_dialstring = "",
00523 };
00524
00525 void ast_cc_default_config_params(struct ast_cc_config_params *params)
00526 {
00527 *params = cc_default_params;
00528 }
00529
00530 struct ast_cc_config_params *__ast_cc_config_params_init(const char *file, int line, const char *function)
00531 {
00532 #if defined(__AST_DEBUG_MALLOC)
00533 struct ast_cc_config_params *params = __ast_malloc(sizeof(*params), file, line, function);
00534 #else
00535 struct ast_cc_config_params *params = ast_malloc(sizeof(*params));
00536 #endif
00537
00538 if (!params) {
00539 return NULL;
00540 }
00541
00542 ast_cc_default_config_params(params);
00543 return params;
00544 }
00545
00546 void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
00547 {
00548 ast_free(params);
00549 }
00550
00551 static enum ast_cc_agent_policies str_to_agent_policy(const char * const value)
00552 {
00553 if (!strcasecmp(value, "never")) {
00554 return AST_CC_AGENT_NEVER;
00555 } else if (!strcasecmp(value, "native")) {
00556 return AST_CC_AGENT_NATIVE;
00557 } else if (!strcasecmp(value, "generic")) {
00558 return AST_CC_AGENT_GENERIC;
00559 } else {
00560 ast_log(LOG_WARNING, "%s is an invalid value for cc_agent_policy. Switching to 'never'\n", value);
00561 return AST_CC_AGENT_NEVER;
00562 }
00563 }
00564
00565 static enum ast_cc_monitor_policies str_to_monitor_policy(const char * const value)
00566 {
00567 if (!strcasecmp(value, "never")) {
00568 return AST_CC_MONITOR_NEVER;
00569 } else if (!strcasecmp(value, "native")) {
00570 return AST_CC_MONITOR_NATIVE;
00571 } else if (!strcasecmp(value, "generic")) {
00572 return AST_CC_MONITOR_GENERIC;
00573 } else if (!strcasecmp(value, "always")) {
00574 return AST_CC_MONITOR_ALWAYS;
00575 } else {
00576 ast_log(LOG_WARNING, "%s is an invalid value for cc_monitor_policy. Switching to 'never'\n", value);
00577 return AST_CC_MONITOR_NEVER;
00578 }
00579 }
00580
00581 static const char *agent_policy_to_str(enum ast_cc_agent_policies policy)
00582 {
00583 switch (policy) {
00584 case AST_CC_AGENT_NEVER:
00585 return "never";
00586 case AST_CC_AGENT_NATIVE:
00587 return "native";
00588 case AST_CC_AGENT_GENERIC:
00589 return "generic";
00590 default:
00591
00592 return "";
00593 }
00594 }
00595
00596 static const char *monitor_policy_to_str(enum ast_cc_monitor_policies policy)
00597 {
00598 switch (policy) {
00599 case AST_CC_MONITOR_NEVER:
00600 return "never";
00601 case AST_CC_MONITOR_NATIVE:
00602 return "native";
00603 case AST_CC_MONITOR_GENERIC:
00604 return "generic";
00605 case AST_CC_MONITOR_ALWAYS:
00606 return "always";
00607 default:
00608
00609 return "";
00610 }
00611 }
00612 int ast_cc_get_param(struct ast_cc_config_params *params, const char * const name,
00613 char *buf, size_t buf_len)
00614 {
00615 const char *value = NULL;
00616
00617 if (!strcasecmp(name, "cc_callback_macro")) {
00618 value = ast_get_cc_callback_macro(params);
00619 } else if (!strcasecmp(name, "cc_agent_policy")) {
00620 value = agent_policy_to_str(ast_get_cc_agent_policy(params));
00621 } else if (!strcasecmp(name, "cc_monitor_policy")) {
00622 value = monitor_policy_to_str(ast_get_cc_monitor_policy(params));
00623 } else if (!strcasecmp(name, "cc_agent_dialstring")) {
00624 value = ast_get_cc_agent_dialstring(params);
00625 }
00626 if (value) {
00627 ast_copy_string(buf, value, buf_len);
00628 return 0;
00629 }
00630
00631
00632
00633
00634
00635 if (!strcasecmp(name, "cc_offer_timer")) {
00636 snprintf(buf, buf_len, "%u", ast_get_cc_offer_timer(params));
00637 } else if (!strcasecmp(name, "ccnr_available_timer")) {
00638 snprintf(buf, buf_len, "%u", ast_get_ccnr_available_timer(params));
00639 } else if (!strcasecmp(name, "ccbs_available_timer")) {
00640 snprintf(buf, buf_len, "%u", ast_get_ccbs_available_timer(params));
00641 } else if (!strcasecmp(name, "cc_max_agents")) {
00642 snprintf(buf, buf_len, "%u", ast_get_cc_max_agents(params));
00643 } else if (!strcasecmp(name, "cc_max_monitors")) {
00644 snprintf(buf, buf_len, "%u", ast_get_cc_max_monitors(params));
00645 } else if (!strcasecmp(name, "cc_recall_timer")) {
00646 snprintf(buf, buf_len, "%u", ast_get_cc_recall_timer(params));
00647 } else {
00648 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
00649 return -1;
00650 }
00651
00652 return 0;
00653 }
00654
00655 int ast_cc_set_param(struct ast_cc_config_params *params, const char * const name,
00656 const char * const value)
00657 {
00658 unsigned int value_as_uint;
00659 if (!strcasecmp(name, "cc_agent_policy")) {
00660 return ast_set_cc_agent_policy(params, str_to_agent_policy(value));
00661 } else if (!strcasecmp(name, "cc_monitor_policy")) {
00662 return ast_set_cc_monitor_policy(params, str_to_monitor_policy(value));
00663 } else if (!strcasecmp(name, "cc_agent_dialstring")) {
00664 ast_set_cc_agent_dialstring(params, value);
00665 } else if (!strcasecmp(name, "cc_callback_macro")) {
00666 ast_set_cc_callback_macro(params, value);
00667 return 0;
00668 }
00669
00670 if (!sscanf(value, "%30u", &value_as_uint) == 1) {
00671 return -1;
00672 }
00673
00674 if (!strcasecmp(name, "cc_offer_timer")) {
00675 ast_set_cc_offer_timer(params, value_as_uint);
00676 } else if (!strcasecmp(name, "ccnr_available_timer")) {
00677 ast_set_ccnr_available_timer(params, value_as_uint);
00678 } else if (!strcasecmp(name, "ccbs_available_timer")) {
00679 ast_set_ccbs_available_timer(params, value_as_uint);
00680 } else if (!strcasecmp(name, "cc_max_agents")) {
00681 ast_set_cc_max_agents(params, value_as_uint);
00682 } else if (!strcasecmp(name, "cc_max_monitors")) {
00683 ast_set_cc_max_monitors(params, value_as_uint);
00684 } else if (!strcasecmp(name, "cc_recall_timer")) {
00685 ast_set_cc_recall_timer(params, value_as_uint);
00686 } else {
00687 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
00688 return -1;
00689 }
00690
00691 return 0;
00692 }
00693
00694 int ast_cc_is_config_param(const char * const name)
00695 {
00696 return (!strcasecmp(name, "cc_agent_policy") ||
00697 !strcasecmp(name, "cc_monitor_policy") ||
00698 !strcasecmp(name, "cc_offer_timer") ||
00699 !strcasecmp(name, "ccnr_available_timer") ||
00700 !strcasecmp(name, "ccbs_available_timer") ||
00701 !strcasecmp(name, "cc_max_agents") ||
00702 !strcasecmp(name, "cc_max_monitors") ||
00703 !strcasecmp(name, "cc_callback_macro") ||
00704 !strcasecmp(name, "cc_agent_dialstring") ||
00705 !strcasecmp(name, "cc_recall_timer"));
00706 }
00707
00708 void ast_cc_copy_config_params(struct ast_cc_config_params *dest, const struct ast_cc_config_params *src)
00709 {
00710 *dest = *src;
00711 }
00712
00713 enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config)
00714 {
00715 return config->cc_agent_policy;
00716 }
00717
00718 int ast_set_cc_agent_policy(struct ast_cc_config_params *config, enum ast_cc_agent_policies value)
00719 {
00720
00721
00722
00723 if (value < AST_CC_AGENT_NEVER || value > AST_CC_AGENT_GENERIC) {
00724 return -1;
00725 }
00726 config->cc_agent_policy = value;
00727 return 0;
00728 }
00729
00730 enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
00731 {
00732 return config->cc_monitor_policy;
00733 }
00734
00735 int ast_set_cc_monitor_policy(struct ast_cc_config_params *config, enum ast_cc_monitor_policies value)
00736 {
00737
00738
00739
00740 if (value < AST_CC_MONITOR_NEVER || value > AST_CC_MONITOR_ALWAYS) {
00741 return -1;
00742 }
00743 config->cc_monitor_policy = value;
00744 return 0;
00745 }
00746
00747 unsigned int ast_get_cc_offer_timer(struct ast_cc_config_params *config)
00748 {
00749 return config->cc_offer_timer;
00750 }
00751
00752 void ast_set_cc_offer_timer(struct ast_cc_config_params *config, unsigned int value)
00753 {
00754
00755 if (value == 0) {
00756 ast_log(LOG_WARNING, "0 is an invalid value for cc_offer_timer. Retaining value as %u\n", config->cc_offer_timer);
00757 return;
00758 }
00759 config->cc_offer_timer = value;
00760 }
00761
00762 unsigned int ast_get_ccnr_available_timer(struct ast_cc_config_params *config)
00763 {
00764 return config->ccnr_available_timer;
00765 }
00766
00767 void ast_set_ccnr_available_timer(struct ast_cc_config_params *config, unsigned int value)
00768 {
00769
00770 if (value == 0) {
00771 ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->ccnr_available_timer);
00772 return;
00773 }
00774 config->ccnr_available_timer = value;
00775 }
00776
00777 unsigned int ast_get_cc_recall_timer(struct ast_cc_config_params *config)
00778 {
00779 return config->cc_recall_timer;
00780 }
00781
00782 void ast_set_cc_recall_timer(struct ast_cc_config_params *config, unsigned int value)
00783 {
00784
00785 if (value == 0) {
00786 ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->cc_recall_timer);
00787 return;
00788 }
00789 config->cc_recall_timer = value;
00790 }
00791
00792 unsigned int ast_get_ccbs_available_timer(struct ast_cc_config_params *config)
00793 {
00794 return config->ccbs_available_timer;
00795 }
00796
00797 void ast_set_ccbs_available_timer(struct ast_cc_config_params *config, unsigned int value)
00798 {
00799
00800 if (value == 0) {
00801 ast_log(LOG_WARNING, "0 is an invalid value for ccbs_available_timer. Retaining value as %u\n", config->ccbs_available_timer);
00802 return;
00803 }
00804 config->ccbs_available_timer = value;
00805 }
00806
00807 const char *ast_get_cc_agent_dialstring(struct ast_cc_config_params *config)
00808 {
00809 return config->cc_agent_dialstring;
00810 }
00811
00812 void ast_set_cc_agent_dialstring(struct ast_cc_config_params *config, const char *const value)
00813 {
00814 if (ast_strlen_zero(value)) {
00815 config->cc_agent_dialstring[0] = '\0';
00816 } else {
00817 ast_copy_string(config->cc_agent_dialstring, value, sizeof(config->cc_agent_dialstring));
00818 }
00819 }
00820
00821 unsigned int ast_get_cc_max_agents(struct ast_cc_config_params *config)
00822 {
00823 return config->cc_max_agents;
00824 }
00825
00826 void ast_set_cc_max_agents(struct ast_cc_config_params *config, unsigned int value)
00827 {
00828 config->cc_max_agents = value;
00829 }
00830
00831 unsigned int ast_get_cc_max_monitors(struct ast_cc_config_params *config)
00832 {
00833 return config->cc_max_monitors;
00834 }
00835
00836 void ast_set_cc_max_monitors(struct ast_cc_config_params *config, unsigned int value)
00837 {
00838 config->cc_max_monitors = value;
00839 }
00840
00841 const char *ast_get_cc_callback_macro(struct ast_cc_config_params *config)
00842 {
00843 return config->cc_callback_macro;
00844 }
00845
00846 void ast_set_cc_callback_macro(struct ast_cc_config_params *config, const char * const value)
00847 {
00848 if (ast_strlen_zero(value)) {
00849 config->cc_callback_macro[0] = '\0';
00850 } else {
00851 ast_copy_string(config->cc_callback_macro, value, sizeof(config->cc_callback_macro));
00852 }
00853 }
00854
00855 struct cc_monitor_backend {
00856 AST_LIST_ENTRY(cc_monitor_backend) next;
00857 const struct ast_cc_monitor_callbacks *callbacks;
00858 };
00859
00860 AST_RWLIST_HEAD_STATIC(cc_monitor_backends, cc_monitor_backend);
00861
00862 int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks)
00863 {
00864 struct cc_monitor_backend *backend = ast_calloc(1, sizeof(*backend));
00865
00866 if (!backend) {
00867 return -1;
00868 }
00869
00870 backend->callbacks = callbacks;
00871
00872 AST_RWLIST_WRLOCK(&cc_monitor_backends);
00873 AST_RWLIST_INSERT_TAIL(&cc_monitor_backends, backend, next);
00874 AST_RWLIST_UNLOCK(&cc_monitor_backends);
00875 return 0;
00876 }
00877
00878 static const struct ast_cc_monitor_callbacks *find_monitor_callbacks(const char * const type)
00879 {
00880 struct cc_monitor_backend *backend;
00881 const struct ast_cc_monitor_callbacks *callbacks = NULL;
00882
00883 AST_RWLIST_RDLOCK(&cc_monitor_backends);
00884 AST_RWLIST_TRAVERSE(&cc_monitor_backends, backend, next) {
00885 if (!strcmp(backend->callbacks->type, type)) {
00886 ast_log_dynamic_level(cc_logger_level, "Returning monitor backend %s\n", backend->callbacks->type);
00887 callbacks = backend->callbacks;
00888 break;
00889 }
00890 }
00891 AST_RWLIST_UNLOCK(&cc_monitor_backends);
00892 return callbacks;
00893 }
00894
00895 void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
00896 {
00897 struct cc_monitor_backend *backend;
00898 AST_RWLIST_WRLOCK(&cc_monitor_backends);
00899 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&cc_monitor_backends, backend, next) {
00900 if (backend->callbacks == callbacks) {
00901 AST_RWLIST_REMOVE_CURRENT(next);
00902 ast_free(backend);
00903 break;
00904 }
00905 }
00906 AST_RWLIST_TRAVERSE_SAFE_END;
00907 AST_RWLIST_UNLOCK(&cc_monitor_backends);
00908 }
00909
00910 struct cc_agent_backend {
00911 AST_LIST_ENTRY(cc_agent_backend) next;
00912 const struct ast_cc_agent_callbacks *callbacks;
00913 };
00914
00915 AST_RWLIST_HEAD_STATIC(cc_agent_backends, cc_agent_backend);
00916
00917 int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
00918 {
00919 struct cc_agent_backend *backend = ast_calloc(1, sizeof(*backend));
00920
00921 if (!backend) {
00922 return -1;
00923 }
00924
00925 backend->callbacks = callbacks;
00926 AST_RWLIST_WRLOCK(&cc_agent_backends);
00927 AST_RWLIST_INSERT_TAIL(&cc_agent_backends, backend, next);
00928 AST_RWLIST_UNLOCK(&cc_agent_backends);
00929 return 0;
00930 }
00931
00932 void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
00933 {
00934 struct cc_agent_backend *backend;
00935 AST_RWLIST_WRLOCK(&cc_agent_backends);
00936 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&cc_agent_backends, backend, next) {
00937 if (backend->callbacks == callbacks) {
00938 AST_RWLIST_REMOVE_CURRENT(next);
00939 ast_free(backend);
00940 break;
00941 }
00942 }
00943 AST_RWLIST_TRAVERSE_SAFE_END;
00944 AST_RWLIST_UNLOCK(&cc_agent_backends);
00945 }
00946
00947 static const struct ast_cc_agent_callbacks *find_agent_callbacks(struct ast_channel *chan)
00948 {
00949 struct cc_agent_backend *backend;
00950 const struct ast_cc_agent_callbacks *callbacks = NULL;
00951 struct ast_cc_config_params *cc_params;
00952 char type[32];
00953
00954 cc_params = ast_channel_get_cc_config_params(chan);
00955 if (!cc_params) {
00956 return NULL;
00957 }
00958 switch (ast_get_cc_agent_policy(cc_params)) {
00959 case AST_CC_AGENT_GENERIC:
00960 ast_copy_string(type, "generic", sizeof(type));
00961 break;
00962 case AST_CC_AGENT_NATIVE:
00963 ast_channel_get_cc_agent_type(chan, type, sizeof(type));
00964 break;
00965 default:
00966 ast_log_dynamic_level(cc_logger_level, "Not returning agent callbacks since this channel is configured not to have a CC agent\n");
00967 return NULL;
00968 }
00969
00970 AST_RWLIST_RDLOCK(&cc_agent_backends);
00971 AST_RWLIST_TRAVERSE(&cc_agent_backends, backend, next) {
00972 if (!strcmp(backend->callbacks->type, type)) {
00973 ast_log_dynamic_level(cc_logger_level, "Returning agent backend %s\n", backend->callbacks->type);
00974 callbacks = backend->callbacks;
00975 break;
00976 }
00977 }
00978 AST_RWLIST_UNLOCK(&cc_agent_backends);
00979 return callbacks;
00980 }
00981
00982 static int cc_generic_monitor_request_cc(struct ast_cc_monitor *monitor, int *available_timer_id);
00983 static int cc_generic_monitor_suspend(struct ast_cc_monitor *monitor);
00984 static int cc_generic_monitor_unsuspend(struct ast_cc_monitor *monitor);
00985 static int cc_generic_monitor_cancel_available_timer(struct ast_cc_monitor *monitor, int *sched_id);
00986 static void cc_generic_monitor_destructor(void *private_data);
00987
00988 static struct ast_cc_monitor_callbacks generic_monitor_cbs = {
00989 .type = "generic",
00990 .request_cc = cc_generic_monitor_request_cc,
00991 .suspend = cc_generic_monitor_suspend,
00992 .unsuspend = cc_generic_monitor_unsuspend,
00993 .cancel_available_timer = cc_generic_monitor_cancel_available_timer,
00994 .destructor = cc_generic_monitor_destructor,
00995 };
00996
00997 struct ao2_container *generic_monitors;
00998
00999 struct generic_monitor_instance {
01000 int core_id;
01001 int is_suspended;
01002 int monitoring;
01003 AST_LIST_ENTRY(generic_monitor_instance) next;
01004 };
01005
01006 struct generic_monitor_instance_list {
01007 const char *device_name;
01008 enum ast_device_state current_state;
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024 int fit_for_recall;
01025 struct ast_event_sub *sub;
01026 AST_LIST_HEAD_NOLOCK(, generic_monitor_instance) list;
01027 };
01028
01029
01030
01031
01032 struct generic_monitor_pvt {
01033
01034
01035
01036
01037 const char *device_name;
01038
01039
01040
01041
01042
01043
01044 int core_id;
01045 };
01046
01047 static int generic_monitor_hash_fn(const void *obj, const int flags)
01048 {
01049 const struct generic_monitor_instance_list *generic_list = obj;
01050 return ast_str_hash(generic_list->device_name);
01051 }
01052
01053 static int generic_monitor_cmp_fn(void *obj, void *arg, int flags)
01054 {
01055 const struct generic_monitor_instance_list *generic_list1 = obj;
01056 const struct generic_monitor_instance_list *generic_list2 = arg;
01057
01058 return !strcmp(generic_list1->device_name, generic_list2->device_name) ? CMP_MATCH | CMP_STOP : 0;
01059 }
01060
01061 static struct generic_monitor_instance_list *find_generic_monitor_instance_list(const char * const device_name)
01062 {
01063 struct generic_monitor_instance_list finder = {.device_name = device_name};
01064
01065 return ao2_t_find(generic_monitors, &finder, OBJ_POINTER, "Finding generic monitor instance list");
01066 }
01067
01068 static void generic_monitor_instance_list_destructor(void *obj)
01069 {
01070 struct generic_monitor_instance_list *generic_list = obj;
01071 struct generic_monitor_instance *generic_instance;
01072
01073 generic_list->sub = ast_event_unsubscribe(generic_list->sub);
01074 while ((generic_instance = AST_LIST_REMOVE_HEAD(&generic_list->list, next))) {
01075 ast_free(generic_instance);
01076 }
01077 ast_free((char *)generic_list->device_name);
01078 }
01079
01080 static void generic_monitor_devstate_cb(const struct ast_event *event, void *userdata);
01081 static struct generic_monitor_instance_list *create_new_generic_list(struct ast_cc_monitor *monitor)
01082 {
01083 struct generic_monitor_instance_list *generic_list = ao2_t_alloc(sizeof(*generic_list),
01084 generic_monitor_instance_list_destructor, "allocate generic monitor instance list");
01085
01086 if (!generic_list) {
01087 return NULL;
01088 }
01089
01090 if (!(generic_list->device_name = ast_strdup(monitor->interface->device_name))) {
01091 cc_unref(generic_list, "Failed to strdup the monitor's device name");
01092 return NULL;
01093 }
01094
01095 if (!(generic_list->sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, generic_monitor_devstate_cb,
01096 "Requesting CC", NULL, AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR,
01097 monitor->interface->device_name, AST_EVENT_IE_END))) {
01098 cc_unref(generic_list, "Failed to subscribe to device state");
01099 return NULL;
01100 }
01101 generic_list->current_state = ast_device_state(monitor->interface->device_name);
01102 ao2_t_link(generic_monitors, generic_list, "linking new generic monitor instance list");
01103 return generic_list;
01104 }
01105
01106 struct generic_tp_cb_data {
01107 const char *device_name;
01108 enum ast_device_state new_state;
01109 };
01110
01111 static int generic_monitor_devstate_tp_cb(void *data)
01112 {
01113 struct generic_tp_cb_data *gtcd = data;
01114 enum ast_device_state new_state = gtcd->new_state;
01115 enum ast_device_state previous_state = gtcd->new_state;
01116 const char *monitor_name = gtcd->device_name;
01117 struct generic_monitor_instance_list *generic_list;
01118 struct generic_monitor_instance *generic_instance;
01119
01120 if (!(generic_list = find_generic_monitor_instance_list(monitor_name))) {
01121
01122
01123
01124
01125 ast_free((char *) gtcd->device_name);
01126 ast_free(gtcd);
01127 return 0;
01128 }
01129
01130 if (generic_list->current_state == new_state) {
01131
01132 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
01133 ast_free((char *) gtcd->device_name);
01134 ast_free(gtcd);
01135 return 0;
01136 }
01137
01138 previous_state = generic_list->current_state;
01139 generic_list->current_state = new_state;
01140
01141 if ((new_state == AST_DEVICE_NOT_INUSE || new_state == AST_DEVICE_UNKNOWN) &&
01142 (previous_state == AST_DEVICE_INUSE || previous_state == AST_DEVICE_UNAVAILABLE ||
01143 previous_state == AST_DEVICE_BUSY)) {
01144 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
01145 if (!generic_instance->is_suspended && generic_instance->monitoring) {
01146 generic_instance->monitoring = 0;
01147 generic_list->fit_for_recall = 1;
01148 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
01149 break;
01150 }
01151 }
01152 }
01153 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
01154 ast_free((char *) gtcd->device_name);
01155 ast_free(gtcd);
01156 return 0;
01157 }
01158
01159 static void generic_monitor_devstate_cb(const struct ast_event *event, void *userdata)
01160 {
01161
01162
01163
01164
01165
01166 struct generic_tp_cb_data *gtcd = ast_calloc(1, sizeof(*gtcd));
01167
01168 if (!gtcd) {
01169 return;
01170 }
01171
01172 if (!(gtcd->device_name = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE)))) {
01173 ast_free(gtcd);
01174 return;
01175 }
01176 gtcd->new_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
01177
01178 if (ast_taskprocessor_push(cc_core_taskprocessor, generic_monitor_devstate_tp_cb, gtcd)) {
01179 ast_free((char *)gtcd->device_name);
01180 ast_free(gtcd);
01181 }
01182 }
01183
01184 int ast_cc_available_timer_expire(const void *data)
01185 {
01186 struct ast_cc_monitor *monitor = (struct ast_cc_monitor *) data;
01187 int res;
01188 monitor->available_timer_id = -1;
01189 res = ast_cc_monitor_failed(monitor->core_id, monitor->interface->device_name, "Available timer expired for monitor");
01190 cc_unref(monitor, "Unref reference from scheduler\n");
01191 return res;
01192 }
01193
01194 static int cc_generic_monitor_request_cc(struct ast_cc_monitor *monitor, int *available_timer_id)
01195 {
01196 struct generic_monitor_instance_list *generic_list;
01197 struct generic_monitor_instance *generic_instance;
01198 struct generic_monitor_pvt *gen_mon_pvt;
01199 enum ast_cc_service_type service = monitor->service_offered;
01200 int when;
01201
01202
01203
01204
01205
01206 if (!(gen_mon_pvt = ast_calloc(1, sizeof(*gen_mon_pvt)))) {
01207 return -1;
01208 }
01209
01210 if (!(gen_mon_pvt->device_name = ast_strdup(monitor->interface->device_name))) {
01211 ast_free(gen_mon_pvt);
01212 return -1;
01213 }
01214
01215 gen_mon_pvt->core_id = monitor->core_id;
01216
01217 monitor->private_data = gen_mon_pvt;
01218
01219 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
01220 if (!(generic_list = create_new_generic_list(monitor))) {
01221 return -1;
01222 }
01223 }
01224
01225 if (!(generic_instance = ast_calloc(1, sizeof(*generic_instance)))) {
01226
01227
01228
01229 cc_unref(generic_list, "Generic monitor instance failed to allocate");
01230 return -1;
01231 }
01232 generic_instance->core_id = monitor->core_id;
01233 generic_instance->monitoring = 1;
01234 AST_LIST_INSERT_TAIL(&generic_list->list, generic_instance, next);
01235 when = service == AST_CC_CCBS ? ast_get_ccbs_available_timer(monitor->interface->config_params) :
01236 ast_get_ccnr_available_timer(monitor->interface->config_params);
01237
01238 *available_timer_id = ast_sched_thread_add(cc_sched_thread, when * 1000,
01239 ast_cc_available_timer_expire, cc_ref(monitor, "Give the scheduler a monitor reference"));
01240 if (*available_timer_id == -1) {
01241 cc_unref(monitor, "Failed to schedule available timer. (monitor)");
01242 cc_unref(generic_list, "Failed to schedule available timer. (generic_list)");
01243 return -1;
01244 }
01245
01246
01247
01248 if (service == AST_CC_CCNR || service == AST_CC_CCNL) {
01249 generic_list->fit_for_recall = 0;
01250 }
01251 ast_cc_monitor_request_acked(monitor->core_id, "Generic monitor for %s subscribed to device state.",
01252 monitor->interface->device_name);
01253 cc_unref(generic_list, "Finished with monitor instance reference in request cc callback");
01254 return 0;
01255 }
01256
01257 static int cc_generic_monitor_suspend(struct ast_cc_monitor *monitor)
01258 {
01259 struct generic_monitor_instance_list *generic_list;
01260 struct generic_monitor_instance *generic_instance;
01261 enum ast_device_state state = ast_device_state(monitor->interface->device_name);
01262
01263 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
01264 return -1;
01265 }
01266
01267
01268 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
01269 if (generic_instance->core_id == monitor->core_id) {
01270 generic_instance->is_suspended = 1;
01271 break;
01272 }
01273 }
01274
01275
01276
01277
01278 if (state != AST_DEVICE_NOT_INUSE && state != AST_DEVICE_UNKNOWN) {
01279 cc_unref(generic_list, "Device is in use. Nothing to do. Unref generic list.");
01280 return 0;
01281 }
01282
01283
01284
01285
01286
01287
01288 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
01289 if (!generic_instance->is_suspended) {
01290 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
01291 break;
01292 }
01293 }
01294 cc_unref(generic_list, "Done with generic list in suspend callback");
01295 return 0;
01296 }
01297
01298 static int cc_generic_monitor_unsuspend(struct ast_cc_monitor *monitor)
01299 {
01300 struct generic_monitor_instance *generic_instance;
01301 struct generic_monitor_instance_list *generic_list = find_generic_monitor_instance_list(monitor->interface->device_name);
01302 enum ast_device_state state = ast_device_state(monitor->interface->device_name);
01303
01304 if (!generic_list) {
01305 return -1;
01306 }
01307
01308
01309
01310 if (state == AST_DEVICE_NOT_INUSE || state == AST_DEVICE_UNKNOWN) {
01311 ast_cc_monitor_callee_available(monitor->core_id, "Generic monitored party has become available");
01312 }
01313
01314
01315 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
01316 if (generic_instance->core_id == monitor->core_id) {
01317 generic_instance->is_suspended = 0;
01318 generic_instance->monitoring = 1;
01319 break;
01320 }
01321 }
01322 cc_unref(generic_list, "Done with generic list in cc_generic_monitor_unsuspend");
01323 return 0;
01324 }
01325
01326 static int cc_generic_monitor_cancel_available_timer(struct ast_cc_monitor *monitor, int *sched_id)
01327 {
01328 ast_assert(sched_id != NULL);
01329
01330 if (*sched_id == -1) {
01331 return 0;
01332 }
01333
01334 ast_log_dynamic_level(cc_logger_level, "Core %d: Canceling generic monitor available timer for monitor %s\n",
01335 monitor->core_id, monitor->interface->device_name);
01336 if (!ast_sched_thread_del(cc_sched_thread, *sched_id)) {
01337 cc_unref(monitor, "Remove scheduler's reference to the monitor");
01338 }
01339 *sched_id = -1;
01340 return 0;
01341 }
01342
01343 static void cc_generic_monitor_destructor(void *private_data)
01344 {
01345 struct generic_monitor_pvt *gen_mon_pvt = private_data;
01346 struct generic_monitor_instance_list *generic_list;
01347 struct generic_monitor_instance *generic_instance;
01348
01349 if (!private_data) {
01350
01351
01352
01353
01354
01355 return;
01356 }
01357
01358 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying generic monitor %s\n",
01359 gen_mon_pvt->core_id, gen_mon_pvt->device_name);
01360
01361 if (!(generic_list = find_generic_monitor_instance_list(gen_mon_pvt->device_name))) {
01362
01363
01364
01365
01366 ast_free((char *)gen_mon_pvt->device_name);
01367 ast_free(gen_mon_pvt);
01368 return;
01369 }
01370
01371 AST_LIST_TRAVERSE_SAFE_BEGIN(&generic_list->list, generic_instance, next) {
01372 if (generic_instance->core_id == gen_mon_pvt->core_id) {
01373 AST_LIST_REMOVE_CURRENT(next);
01374 ast_free(generic_instance);
01375 break;
01376 }
01377 }
01378 AST_LIST_TRAVERSE_SAFE_END;
01379
01380 if (AST_LIST_EMPTY(&generic_list->list)) {
01381
01382
01383
01384 ao2_t_unlink(generic_monitors, generic_list, "Generic list is empty. Unlink it from the container");
01385 } else {
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396 if (generic_list->fit_for_recall && (generic_list->current_state == AST_DEVICE_NOT_INUSE ||
01397 generic_list->current_state == AST_DEVICE_UNKNOWN)) {
01398 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
01399 if (!generic_instance->is_suspended && generic_instance->monitoring) {
01400 ast_cc_monitor_callee_available(generic_instance->core_id, "Signaling generic monitor "
01401 "availability due to other instance's failure.");
01402 break;
01403 }
01404 }
01405 }
01406 }
01407 cc_unref(generic_list, "Done with generic list in generic monitor destructor");
01408 ast_free((char *)gen_mon_pvt->device_name);
01409 ast_free(gen_mon_pvt);
01410 }
01411
01412 static void cc_interface_destroy(void *data)
01413 {
01414 struct ast_cc_interface *interface = data;
01415 ast_log_dynamic_level(cc_logger_level, "Destroying cc interface %s\n", interface->device_name);
01416 ast_cc_config_params_destroy(interface->config_params);
01417 }
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435 struct extension_child_dialstring {
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451 char original_dialstring[AST_CHANNEL_NAME];
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470 char device_name[AST_CHANNEL_NAME];
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485 int is_valid;
01486 AST_LIST_ENTRY(extension_child_dialstring) next;
01487 };
01488
01489
01490
01491
01492 struct extension_monitor_pvt {
01493 AST_LIST_HEAD_NOLOCK(, extension_child_dialstring) child_dialstrings;
01494 };
01495
01496 static void cc_extension_monitor_destructor(void *private_data)
01497 {
01498 struct extension_monitor_pvt *extension_pvt = private_data;
01499 struct extension_child_dialstring *child_dialstring;
01500
01501
01502 if (!extension_pvt) {
01503 return;
01504 }
01505
01506 while ((child_dialstring = AST_LIST_REMOVE_HEAD(&extension_pvt->child_dialstrings, next))) {
01507 ast_free(child_dialstring);
01508 }
01509 ast_free(extension_pvt);
01510 }
01511
01512 static void cc_monitor_destroy(void *data)
01513 {
01514 struct ast_cc_monitor *monitor = data;
01515
01516
01517
01518
01519
01520
01521 ast_log_dynamic_level(cc_logger_level, "Core %d: Calling destructor for monitor %s\n",
01522 monitor->core_id, monitor->interface->device_name);
01523 if (monitor->interface->monitor_class == AST_CC_EXTENSION_MONITOR) {
01524 cc_extension_monitor_destructor(monitor->private_data);
01525 }
01526 if (monitor->callbacks) {
01527 monitor->callbacks->destructor(monitor->private_data);
01528 }
01529 cc_unref(monitor->interface, "Unreffing tree's reference to interface");
01530 ast_free(monitor->dialstring);
01531 }
01532
01533 static void cc_interface_tree_destroy(void *data)
01534 {
01535 struct cc_monitor_tree *cc_interface_tree = data;
01536 struct ast_cc_monitor *monitor;
01537 while ((monitor = AST_LIST_REMOVE_HEAD(cc_interface_tree, next))) {
01538 if (monitor->callbacks) {
01539 monitor->callbacks->cancel_available_timer(monitor, &monitor->available_timer_id);
01540 }
01541 cc_unref(monitor, "Destroying all monitors");
01542 }
01543 AST_LIST_HEAD_DESTROY(cc_interface_tree);
01544 }
01545
01546
01547
01548
01549
01550 static int dialed_cc_interface_counter;
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561 struct dialed_cc_interfaces {
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577 unsigned int dial_parent_id;
01578
01579
01580
01581
01582
01583
01584
01585
01586 int core_id;
01587
01588
01589
01590
01591
01592 char ignore;
01593
01594
01595
01596
01597
01598
01599
01600 char is_original_caller;
01601
01602
01603
01604 struct cc_monitor_tree *interface_tree;
01605 };
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619 static void dialed_cc_interfaces_destroy(void *data)
01620 {
01621 struct dialed_cc_interfaces *cc_interfaces = data;
01622 cc_unref(cc_interfaces->interface_tree, "Unref dial's ref to monitor tree");
01623 ast_free(cc_interfaces);
01624 }
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639 static void *dialed_cc_interfaces_duplicate(void *data)
01640 {
01641 struct dialed_cc_interfaces *old_cc_interfaces = data;
01642 struct dialed_cc_interfaces *new_cc_interfaces = ast_calloc(1, sizeof(*new_cc_interfaces));
01643 if (!new_cc_interfaces) {
01644 return NULL;
01645 }
01646 new_cc_interfaces->ignore = old_cc_interfaces->ignore;
01647 new_cc_interfaces->dial_parent_id = old_cc_interfaces->dial_parent_id;
01648 new_cc_interfaces->is_original_caller = 0;
01649 cc_ref(old_cc_interfaces->interface_tree, "New ref due to duplication of monitor tree");
01650 new_cc_interfaces->core_id = old_cc_interfaces->core_id;
01651 new_cc_interfaces->interface_tree = old_cc_interfaces->interface_tree;
01652 return new_cc_interfaces;
01653 }
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664 static const struct ast_datastore_info dialed_cc_interfaces_info = {
01665 .type = "Dial CC Interfaces",
01666 .duplicate = dialed_cc_interfaces_duplicate,
01667 .destroy = dialed_cc_interfaces_destroy,
01668 };
01669
01670 static struct extension_monitor_pvt *extension_monitor_pvt_init(void)
01671 {
01672 struct extension_monitor_pvt *ext_pvt = ast_calloc(1, sizeof(*ext_pvt));
01673 if (!ext_pvt) {
01674 return NULL;
01675 }
01676 AST_LIST_HEAD_INIT_NOLOCK(&ext_pvt->child_dialstrings);
01677 return ext_pvt;
01678 }
01679
01680 void ast_cc_extension_monitor_add_dialstring(struct ast_channel *incoming, const char * const dialstring, const char * const device_name)
01681 {
01682 struct ast_datastore *cc_datastore;
01683 struct dialed_cc_interfaces *cc_interfaces;
01684 struct ast_cc_monitor *monitor;
01685 struct extension_monitor_pvt *extension_pvt;
01686 struct extension_child_dialstring *child_dialstring;
01687 struct cc_monitor_tree *interface_tree;
01688 int id;
01689
01690 ast_channel_lock(incoming);
01691 if (!(cc_datastore = ast_channel_datastore_find(incoming, &dialed_cc_interfaces_info, NULL))) {
01692 ast_channel_unlock(incoming);
01693 return;
01694 }
01695
01696 cc_interfaces = cc_datastore->data;
01697 interface_tree = cc_interfaces->interface_tree;
01698 id = cc_interfaces->dial_parent_id;
01699 ast_channel_unlock(incoming);
01700
01701 AST_LIST_LOCK(interface_tree);
01702 AST_LIST_TRAVERSE(interface_tree, monitor, next) {
01703 if (monitor->id == id) {
01704 break;
01705 }
01706 }
01707
01708 if (!monitor) {
01709 AST_LIST_UNLOCK(interface_tree);
01710 return;
01711 }
01712
01713 extension_pvt = monitor->private_data;
01714 if (!(child_dialstring = ast_calloc(1, sizeof(*child_dialstring)))) {
01715 AST_LIST_UNLOCK(interface_tree);
01716 return;
01717 }
01718 ast_copy_string(child_dialstring->original_dialstring, dialstring, sizeof(child_dialstring->original_dialstring));
01719 ast_copy_string(child_dialstring->device_name, device_name, sizeof(child_dialstring->device_name));
01720 child_dialstring->is_valid = 1;
01721 AST_LIST_INSERT_TAIL(&extension_pvt->child_dialstrings, child_dialstring, next);
01722 AST_LIST_UNLOCK(interface_tree);
01723 }
01724
01725 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)
01726 {
01727 struct ast_cc_monitor *monitor_iter;
01728 struct extension_monitor_pvt *extension_pvt;
01729 struct extension_child_dialstring *child_dialstring;
01730
01731 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
01732 if (monitor_iter->id == parent_id) {
01733 break;
01734 }
01735 }
01736
01737 if (!monitor_iter) {
01738 return;
01739 }
01740 extension_pvt = monitor_iter->private_data;
01741
01742 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
01743 if (!strcmp(child_dialstring->device_name, device_name)) {
01744 child_dialstring->is_valid = is_valid;
01745 break;
01746 }
01747 }
01748 }
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764 static struct ast_cc_monitor *cc_extension_monitor_init(const char * const exten, const char * const context, const unsigned int parent_id)
01765 {
01766 struct ast_str *str = ast_str_alloca(2 * AST_MAX_EXTENSION);
01767 struct ast_cc_interface *cc_interface;
01768 struct ast_cc_monitor *monitor;
01769
01770 ast_str_set(&str, 0, "%s@%s", exten, context);
01771
01772 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + ast_str_strlen(str), cc_interface_destroy,
01773 "Allocating new ast_cc_interface"))) {
01774 return NULL;
01775 }
01776
01777 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
01778 cc_unref(cc_interface, "failed to allocate the monitor, so unref the interface");
01779 return NULL;
01780 }
01781
01782 if (!(monitor->private_data = extension_monitor_pvt_init())) {
01783 cc_unref(monitor, "Failed to initialize extension monitor private data. uref monitor");
01784 cc_unref(cc_interface, "Failed to initialize extension monitor private data. unref cc_interface");
01785 }
01786
01787 monitor->id = ast_atomic_fetchadd_int(&dialed_cc_interface_counter, +1);
01788 monitor->parent_id = parent_id;
01789 cc_interface->monitor_type = "extension";
01790 cc_interface->monitor_class = AST_CC_EXTENSION_MONITOR;
01791 strcpy(cc_interface->device_name, ast_str_buffer(str));
01792 monitor->interface = cc_interface;
01793 ast_log_dynamic_level(cc_logger_level, "Created an extension cc interface for '%s' with id %d and parent %d\n", cc_interface->device_name, monitor->id, monitor->parent_id);
01794 return monitor;
01795 }
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813 static int cc_interfaces_datastore_init(struct ast_channel *chan) {
01814 struct dialed_cc_interfaces *interfaces;
01815 struct ast_cc_monitor *monitor;
01816 struct ast_datastore *dial_cc_datastore;
01817
01818
01819
01820
01821
01822
01823
01824
01825 if (!ast_cc_request_is_within_limits()) {
01826 return 0;
01827 }
01828
01829 if (!(interfaces = ast_calloc(1, sizeof(*interfaces)))) {
01830 return -1;
01831 }
01832
01833 if (!(monitor = cc_extension_monitor_init(S_OR(chan->macroexten, chan->exten), S_OR(chan->macrocontext, chan->context), 0))) {
01834 ast_free(interfaces);
01835 return -1;
01836 }
01837
01838 if (!(dial_cc_datastore = ast_datastore_alloc(&dialed_cc_interfaces_info, NULL))) {
01839 cc_unref(monitor, "Could not allocate the dialed interfaces datastore. Unreffing monitor");
01840 ast_free(interfaces);
01841 return -1;
01842 }
01843
01844 if (!(interfaces->interface_tree = ao2_t_alloc(sizeof(*interfaces->interface_tree), cc_interface_tree_destroy,
01845 "Allocate monitor tree"))) {
01846 ast_datastore_free(dial_cc_datastore);
01847 cc_unref(monitor, "Could not allocate monitor tree on dialed interfaces datastore. Unreffing monitor");
01848 ast_free(interfaces);
01849 return -1;
01850 }
01851
01852
01853 AST_LIST_HEAD_INIT(interfaces->interface_tree);
01854 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
01855 cc_ref(monitor, "List's reference to extension monitor");
01856 dial_cc_datastore->data = interfaces;
01857 dial_cc_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
01858 interfaces->dial_parent_id = monitor->id;
01859 interfaces->core_id = monitor->core_id = ast_atomic_fetchadd_int(&core_id_counter, +1);
01860 interfaces->is_original_caller = 1;
01861 ast_channel_lock(chan);
01862 ast_channel_datastore_add(chan, dial_cc_datastore);
01863 ast_channel_unlock(chan);
01864 cc_unref(monitor, "Unreffing allocation's reference");
01865 return 0;
01866 }
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891 static void call_destructor_with_no_monitor(const char * const monitor_type, void *private_data)
01892 {
01893 const struct ast_cc_monitor_callbacks *monitor_callbacks = find_monitor_callbacks(monitor_type);
01894
01895 if (!monitor_callbacks) {
01896 return;
01897 }
01898
01899 monitor_callbacks->destructor(private_data);
01900 }
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927 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)
01928 {
01929 struct ast_cc_interface *cc_interface;
01930 struct ast_cc_monitor *monitor;
01931 size_t device_name_len = strlen(device_name);
01932 int parent_id = cc_data->parent_interface_id;
01933
01934 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + device_name_len, cc_interface_destroy,
01935 "Allocating new ast_cc_interface"))) {
01936 return NULL;
01937 }
01938
01939 if (!(cc_interface->config_params = ast_cc_config_params_init())) {
01940 cc_unref(cc_interface, "Failed to allocate config params, unref interface");
01941 return NULL;
01942 }
01943
01944 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
01945 cc_unref(cc_interface, "Failed to allocate monitor, unref interface");
01946 return NULL;
01947 }
01948
01949 if (!(monitor->dialstring = ast_strdup(dialstring))) {
01950 cc_unref(monitor, "Failed to copy dialable name. Unref monitor");
01951 cc_unref(cc_interface, "Failed to copy dialable name");
01952 return NULL;
01953 }
01954
01955 if (!(monitor->callbacks = find_monitor_callbacks(cc_data->monitor_type))) {
01956 cc_unref(monitor, "Failed to find monitor callbacks. Unref monitor");
01957 cc_unref(cc_interface, "Failed to find monitor callbacks");
01958 return NULL;
01959 }
01960
01961 strcpy(cc_interface->device_name, device_name);
01962 monitor->id = ast_atomic_fetchadd_int(&dialed_cc_interface_counter, +1);
01963 monitor->parent_id = parent_id;
01964 monitor->core_id = core_id;
01965 monitor->service_offered = cc_data->service;
01966 monitor->private_data = cc_data->private_data;
01967 cc_interface->monitor_type = cc_data->monitor_type;
01968 cc_interface->monitor_class = AST_CC_DEVICE_MONITOR;
01969 monitor->interface = cc_interface;
01970 monitor->available_timer_id = -1;
01971 ast_cc_copy_config_params(cc_interface->config_params, &cc_data->config_params);
01972 ast_log_dynamic_level(cc_logger_level, "Core %d: Created a device cc interface for '%s' with id %d and parent %d\n",
01973 monitor->core_id, cc_interface->device_name, monitor->id, monitor->parent_id);
01974 return monitor;
01975 }
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993 void ast_handle_cc_control_frame(struct ast_channel *inbound, struct ast_channel *outbound, void *frame_data)
01994 {
01995 char *device_name;
01996 char *dialstring;
01997 struct ast_cc_monitor *monitor;
01998 struct ast_datastore *cc_datastore;
01999 struct dialed_cc_interfaces *cc_interfaces;
02000 struct cc_control_payload *cc_data = frame_data;
02001 struct cc_core_instance *core_instance;
02002
02003 device_name = cc_data->device_name;
02004 dialstring = cc_data->dialstring;
02005
02006 ast_channel_lock(inbound);
02007 if (!(cc_datastore = ast_channel_datastore_find(inbound, &dialed_cc_interfaces_info, NULL))) {
02008 ast_log(LOG_WARNING, "Unable to retrieve CC datastore while processing CC frame from '%s'. CC services will be unavailable.\n", device_name);
02009 ast_channel_unlock(inbound);
02010 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
02011 return;
02012 }
02013
02014 cc_interfaces = cc_datastore->data;
02015
02016 if (cc_interfaces->ignore) {
02017 ast_channel_unlock(inbound);
02018 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
02019 return;
02020 }
02021
02022 if (!cc_interfaces->is_original_caller) {
02023
02024
02025
02026
02027
02028 ast_channel_unlock(inbound);
02029 ast_indicate_data(inbound, AST_CONTROL_CC, cc_data, sizeof(*cc_data));
02030 return;
02031 }
02032
02033 core_instance = find_cc_core_instance(cc_interfaces->core_id);
02034 if (!core_instance) {
02035 core_instance = cc_core_init_instance(inbound, cc_interfaces->interface_tree,
02036 cc_interfaces->core_id, cc_data);
02037 if (!core_instance) {
02038 cc_interfaces->ignore = 1;
02039 ast_channel_unlock(inbound);
02040 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
02041 return;
02042 }
02043 }
02044
02045 ast_channel_unlock(inbound);
02046
02047
02048
02049
02050
02051
02052
02053 AST_LIST_LOCK(cc_interfaces->interface_tree);
02054 AST_LIST_TRAVERSE(cc_interfaces->interface_tree, monitor, next) {
02055 if (!strcmp(monitor->interface->device_name, device_name)) {
02056 ast_log_dynamic_level(cc_logger_level, "Core %d: Device %s sent us multiple CC control frames. Ignoring those beyond the first.\n",
02057 core_instance->core_id, device_name);
02058 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
02059 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
02060 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
02061 return;
02062 }
02063 }
02064 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
02065
02066 if (!(monitor = cc_device_monitor_init(device_name, dialstring, cc_data, core_instance->core_id))) {
02067 ast_log(LOG_WARNING, "Unable to create CC device interface for '%s'. CC services will be unavailable on this interface.\n", device_name);
02068 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
02069 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
02070 return;
02071 }
02072
02073 AST_LIST_LOCK(cc_interfaces->interface_tree);
02074 cc_ref(monitor, "monitor tree's reference to the monitor");
02075 AST_LIST_INSERT_TAIL(cc_interfaces->interface_tree, monitor, next);
02076 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
02077
02078 cc_extension_monitor_change_is_valid(core_instance, monitor->parent_id, monitor->interface->device_name, 0);
02079
02080 manager_event(EVENT_FLAG_CC, "CCAvailable",
02081 "CoreID: %d\r\n"
02082 "Callee: %s\r\n"
02083 "Service: %s\r\n",
02084 cc_interfaces->core_id, device_name, cc_service_to_string(cc_data->service)
02085 );
02086
02087 cc_unref(core_instance, "Done with core_instance after handling CC control frame");
02088 cc_unref(monitor, "Unref reference from allocating monitor");
02089 }
02090
02091 int ast_cc_call_init(struct ast_channel *chan, int *ignore_cc)
02092 {
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113 struct ast_datastore *cc_interfaces_datastore;
02114 struct dialed_cc_interfaces *interfaces;
02115 struct ast_cc_monitor *monitor;
02116 struct ast_cc_config_params *cc_params;
02117
02118 ast_channel_lock(chan);
02119
02120 cc_params = ast_channel_get_cc_config_params(chan);
02121 if (!cc_params) {
02122 ast_channel_unlock(chan);
02123 return -1;
02124 }
02125 if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_NEVER) {
02126
02127
02128 *ignore_cc = 1;
02129 ast_channel_unlock(chan);
02130 ast_log_dynamic_level(cc_logger_level, "Agent policy for %s is 'never'. CC not possible\n", chan->name);
02131 return 0;
02132 }
02133
02134 if (!(cc_interfaces_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
02135
02136 ast_channel_unlock(chan);
02137 return cc_interfaces_datastore_init(chan);
02138 }
02139 interfaces = cc_interfaces_datastore->data;
02140 ast_channel_unlock(chan);
02141
02142 if (interfaces->ignore) {
02143
02144 *ignore_cc = 1;
02145 ast_log_dynamic_level(cc_logger_level, "Datastore is present with ignore flag set. Ignoring CC offers on this call\n");
02146 return 0;
02147 }
02148
02149
02150 if (!(monitor = cc_extension_monitor_init(S_OR(chan->macroexten, chan->exten),
02151 S_OR(chan->macrocontext, chan->context), interfaces->dial_parent_id))) {
02152 return -1;
02153 }
02154 monitor->core_id = interfaces->core_id;
02155 AST_LIST_LOCK(interfaces->interface_tree);
02156 cc_ref(monitor, "monitor tree's reference to the monitor");
02157 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
02158 AST_LIST_UNLOCK(interfaces->interface_tree);
02159 interfaces->dial_parent_id = monitor->id;
02160 cc_unref(monitor, "Unref monitor's allocation reference");
02161 return 0;
02162 }
02163
02164 int ast_cc_request_is_within_limits(void)
02165 {
02166 return cc_request_count < global_cc_max_requests;
02167 }
02168
02169 int ast_cc_get_current_core_id(struct ast_channel *chan)
02170 {
02171 struct ast_datastore *datastore;
02172 struct dialed_cc_interfaces *cc_interfaces;
02173 int core_id_return;
02174
02175 ast_channel_lock(chan);
02176 if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
02177 ast_channel_unlock(chan);
02178 return -1;
02179 }
02180
02181 cc_interfaces = datastore->data;
02182 core_id_return = cc_interfaces->ignore ? -1 : cc_interfaces->core_id;
02183 ast_channel_unlock(chan);
02184 return core_id_return;
02185
02186 }
02187
02188 static long count_agents(const char * const caller, const int core_id_exception)
02189 {
02190 struct count_agents_cb_data data = {.core_id_exception = core_id_exception,};
02191
02192 ao2_t_callback_data(cc_core_instances, OBJ_NODATA, count_agents_cb, (char *)caller, &data, "Counting agents");
02193 ast_log_dynamic_level(cc_logger_level, "Counted %d agents\n", data.count);
02194 return data.count;
02195 }
02196
02197 static void kill_duplicate_offers(char *caller)
02198 {
02199 unsigned long match_flags = MATCH_NO_REQUEST;
02200 ao2_t_callback_data(cc_core_instances, OBJ_UNLINK | OBJ_NODATA, match_agent, caller, &match_flags, "Killing duplicate offers");
02201 }
02202
02203 static void check_callback_sanity(const struct ast_cc_agent_callbacks *callbacks)
02204 {
02205 ast_assert(callbacks->init != NULL);
02206 ast_assert(callbacks->start_offer_timer != NULL);
02207 ast_assert(callbacks->stop_offer_timer != NULL);
02208 ast_assert(callbacks->respond != NULL);
02209 ast_assert(callbacks->status_request != NULL);
02210 ast_assert(callbacks->start_monitoring != NULL);
02211 ast_assert(callbacks->callee_available != NULL);
02212 ast_assert(callbacks->destructor != NULL);
02213 }
02214
02215 static void agent_destroy(void *data)
02216 {
02217 struct ast_cc_agent *agent = data;
02218
02219 if (agent->callbacks) {
02220 agent->callbacks->destructor(agent);
02221 }
02222 ast_cc_config_params_destroy(agent->cc_params);
02223 }
02224
02225 static struct ast_cc_agent *cc_agent_init(struct ast_channel *caller_chan,
02226 const char * const caller_name, const int core_id,
02227 struct cc_monitor_tree *interface_tree)
02228 {
02229 struct ast_cc_agent *agent;
02230 struct ast_cc_config_params *cc_params;
02231
02232 if (!(agent = ao2_t_alloc(sizeof(*agent) + strlen(caller_name), agent_destroy,
02233 "Allocating new ast_cc_agent"))) {
02234 return NULL;
02235 }
02236
02237 agent->core_id = core_id;
02238 strcpy(agent->device_name, caller_name);
02239
02240 cc_params = ast_channel_get_cc_config_params(caller_chan);
02241 if (!cc_params) {
02242 cc_unref(agent, "Could not get channel config params.");
02243 return NULL;
02244 }
02245 if (!(agent->cc_params = ast_cc_config_params_init())) {
02246 cc_unref(agent, "Could not init agent config params.");
02247 return NULL;
02248 }
02249 ast_cc_copy_config_params(agent->cc_params, cc_params);
02250
02251 if (!(agent->callbacks = find_agent_callbacks(caller_chan))) {
02252 cc_unref(agent, "Could not find agent callbacks.");
02253 return NULL;
02254 }
02255 check_callback_sanity(agent->callbacks);
02256
02257 if (agent->callbacks->init(agent, caller_chan)) {
02258 cc_unref(agent, "Agent init callback failed.");
02259 return NULL;
02260 }
02261 ast_log_dynamic_level(cc_logger_level, "Core %d: Created an agent for caller %s\n",
02262 agent->core_id, agent->device_name);
02263 return agent;
02264 }
02265
02266
02267 static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan);
02268 static int cc_generic_agent_start_offer_timer(struct ast_cc_agent *agent);
02269 static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent);
02270 static void cc_generic_agent_respond(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason);
02271 static int cc_generic_agent_status_request(struct ast_cc_agent *agent);
02272 static int cc_generic_agent_stop_ringing(struct ast_cc_agent *agent);
02273 static int cc_generic_agent_start_monitoring(struct ast_cc_agent *agent);
02274 static int cc_generic_agent_recall(struct ast_cc_agent *agent);
02275 static void cc_generic_agent_destructor(struct ast_cc_agent *agent);
02276
02277 static struct ast_cc_agent_callbacks generic_agent_callbacks = {
02278 .type = "generic",
02279 .init = cc_generic_agent_init,
02280 .start_offer_timer = cc_generic_agent_start_offer_timer,
02281 .stop_offer_timer = cc_generic_agent_stop_offer_timer,
02282 .respond = cc_generic_agent_respond,
02283 .status_request = cc_generic_agent_status_request,
02284 .stop_ringing = cc_generic_agent_stop_ringing,
02285 .start_monitoring = cc_generic_agent_start_monitoring,
02286 .callee_available = cc_generic_agent_recall,
02287 .destructor = cc_generic_agent_destructor,
02288 };
02289
02290 struct cc_generic_agent_pvt {
02291
02292
02293
02294
02295
02296
02297
02298
02299 struct ast_event_sub *sub;
02300
02301
02302
02303 int offer_timer_id;
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313 char cid_num[AST_CHANNEL_NAME];
02314
02315
02316
02317
02318
02319
02320
02321 char cid_name[AST_CHANNEL_NAME];
02322
02323
02324
02325
02326
02327
02328
02329 char exten[AST_CHANNEL_NAME];
02330
02331
02332
02333
02334
02335
02336
02337 char context[AST_CHANNEL_NAME];
02338 };
02339
02340 static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
02341 {
02342 struct cc_generic_agent_pvt *generic_pvt = ast_calloc(1, sizeof(*generic_pvt));
02343
02344 if (!generic_pvt) {
02345 return -1;
02346 }
02347
02348 generic_pvt->offer_timer_id = -1;
02349 if (chan->caller.id.number.valid && chan->caller.id.number.str) {
02350 ast_copy_string(generic_pvt->cid_num, chan->caller.id.number.str, sizeof(generic_pvt->cid_num));
02351 }
02352 if (chan->caller.id.name.valid && chan->caller.id.name.str) {
02353 ast_copy_string(generic_pvt->cid_name, chan->caller.id.name.str, sizeof(generic_pvt->cid_name));
02354 }
02355 ast_copy_string(generic_pvt->exten, S_OR(chan->macroexten, chan->exten), sizeof(generic_pvt->exten));
02356 ast_copy_string(generic_pvt->context, S_OR(chan->macrocontext, chan->context), sizeof(generic_pvt->context));
02357 agent->private_data = generic_pvt;
02358 ast_set_flag(agent, AST_CC_AGENT_SKIP_OFFER);
02359 return 0;
02360 }
02361
02362 static int offer_timer_expire(const void *data)
02363 {
02364 struct ast_cc_agent *agent = (struct ast_cc_agent *) data;
02365 struct cc_generic_agent_pvt *agent_pvt = agent->private_data;
02366 ast_log_dynamic_level(cc_logger_level, "Core %d: Queuing change request because offer timer has expired.\n",
02367 agent->core_id);
02368 agent_pvt->offer_timer_id = -1;
02369 ast_cc_failed(agent->core_id, "Generic agent %s offer timer expired", agent->device_name);
02370 cc_unref(agent, "Remove scheduler's reference to the agent");
02371 return 0;
02372 }
02373
02374 static int cc_generic_agent_start_offer_timer(struct ast_cc_agent *agent)
02375 {
02376 int when;
02377 int sched_id;
02378 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
02379
02380 ast_assert(cc_sched_thread != NULL);
02381 ast_assert(agent->cc_params != NULL);
02382
02383 when = ast_get_cc_offer_timer(agent->cc_params) * 1000;
02384 ast_log_dynamic_level(cc_logger_level, "Core %d: About to schedule offer timer expiration for %d ms\n",
02385 agent->core_id, when);
02386 if ((sched_id = ast_sched_thread_add(cc_sched_thread, when, offer_timer_expire, cc_ref(agent, "Give scheduler an agent ref"))) == -1) {
02387 return -1;
02388 }
02389 generic_pvt->offer_timer_id = sched_id;
02390 return 0;
02391 }
02392
02393 static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent)
02394 {
02395 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
02396
02397 if (generic_pvt->offer_timer_id != -1) {
02398 if (!ast_sched_thread_del(cc_sched_thread, generic_pvt->offer_timer_id)) {
02399 cc_unref(agent, "Remove scheduler's reference to the agent");
02400 }
02401 generic_pvt->offer_timer_id = -1;
02402 }
02403 return 0;
02404 }
02405
02406 static void cc_generic_agent_respond(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
02407 {
02408
02409
02410
02411 return;
02412 }
02413
02414 static int cc_generic_agent_status_request(struct ast_cc_agent *agent)
02415 {
02416 ast_cc_agent_status_response(agent->core_id, ast_device_state(agent->device_name));
02417 return 0;
02418 }
02419
02420 static int cc_generic_agent_stop_ringing(struct ast_cc_agent *agent)
02421 {
02422 struct ast_channel *recall_chan = ast_channel_get_by_name_prefix(agent->device_name, strlen(agent->device_name));
02423
02424 if (!recall_chan) {
02425 return 0;
02426 }
02427
02428 ast_softhangup(recall_chan, AST_SOFTHANGUP_EXPLICIT);
02429 return 0;
02430 }
02431
02432 static int generic_agent_devstate_unsubscribe(void *data)
02433 {
02434 struct ast_cc_agent *agent = data;
02435 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
02436
02437 if (generic_pvt->sub != NULL) {
02438 generic_pvt->sub = ast_event_unsubscribe(generic_pvt->sub);
02439 }
02440 cc_unref(agent, "Done unsubscribing from devstate");
02441 return 0;
02442 }
02443
02444 static void generic_agent_devstate_cb(const struct ast_event *event, void *userdata)
02445 {
02446 struct ast_cc_agent *agent = userdata;
02447
02448
02449 if (ast_taskprocessor_push(cc_core_taskprocessor, generic_agent_devstate_unsubscribe,
02450 cc_ref(agent, "ref agent for device state unsubscription"))) {
02451 cc_unref(agent, "Unref agent unsubscribing from devstate failed");
02452 }
02453 ast_cc_agent_caller_available(agent->core_id, "%s is no longer busy", agent->device_name);
02454 }
02455
02456 static int cc_generic_agent_start_monitoring(struct ast_cc_agent *agent)
02457 {
02458 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
02459 struct ast_str *str = ast_str_alloca(128);
02460
02461 ast_assert(generic_pvt->sub == NULL);
02462 ast_str_set(&str, 0, "Starting to monitor %s device state since it is busy\n", agent->device_name);
02463
02464 if (!(generic_pvt->sub = ast_event_subscribe(
02465 AST_EVENT_DEVICE_STATE, generic_agent_devstate_cb, ast_str_buffer(str), agent,
02466 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, agent->device_name,
02467 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, AST_DEVICE_NOT_INUSE,
02468 AST_EVENT_IE_END))) {
02469 return -1;
02470 }
02471 return 0;
02472 }
02473
02474 static void *generic_recall(void *data)
02475 {
02476 struct ast_cc_agent *agent = data;
02477 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
02478 const char *interface = S_OR(ast_get_cc_agent_dialstring(agent->cc_params), ast_strdupa(agent->device_name));
02479 const char *tech;
02480 char *target;
02481 int reason;
02482 struct ast_channel *chan;
02483 const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params);
02484 unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000;
02485
02486 tech = interface;
02487 if ((target = strchr(interface, '/'))) {
02488 *target++ = '\0';
02489 }
02490 if (!(chan = ast_request_and_dial(tech, AST_FORMAT_SLINEAR, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) {
02491
02492
02493 ast_log_dynamic_level(cc_logger_level, "Core %d: Failed to call back %s for reason %d\n",
02494 agent->core_id, agent->device_name, reason);
02495 ast_cc_failed(agent->core_id, "Failed to call back device %s/%s", tech, target);
02496 return NULL;
02497 }
02498
02499
02500
02501
02502
02503
02504 ast_setup_cc_recall_datastore(chan, agent->core_id);
02505 ast_cc_agent_set_interfaces_chanvar(chan);
02506
02507 ast_copy_string(chan->exten, generic_pvt->exten, sizeof(chan->exten));
02508 ast_copy_string(chan->context, generic_pvt->context, sizeof(chan->context));
02509 chan->priority = 1;
02510
02511 pbx_builtin_setvar_helper(chan, "CC_EXTEN", generic_pvt->exten);
02512 pbx_builtin_setvar_helper(chan, "CC_CONTEXT", generic_pvt->context);
02513
02514 if (!ast_strlen_zero(callback_macro)) {
02515 ast_log_dynamic_level(cc_logger_level, "Core %d: There's a callback macro configured for agent %s\n",
02516 agent->core_id, agent->device_name);
02517 if (ast_app_run_macro(NULL, chan, callback_macro, NULL)) {
02518 ast_cc_failed(agent->core_id, "Callback macro to %s failed. Maybe a hangup?", agent->device_name);
02519 ast_hangup(chan);
02520 return NULL;
02521 }
02522 }
02523 ast_cc_agent_recalling(agent->core_id, "Generic agent %s is recalling", agent->device_name);
02524 ast_pbx_start(chan);
02525 return NULL;
02526 }
02527
02528 static int cc_generic_agent_recall(struct ast_cc_agent *agent)
02529 {
02530 pthread_t clotho;
02531 enum ast_device_state current_state = ast_device_state(agent->device_name);
02532
02533 if (current_state != AST_DEVICE_NOT_INUSE && current_state != AST_DEVICE_UNKNOWN) {
02534
02535
02536
02537 ast_cc_agent_caller_busy(agent->core_id, "Generic agent caller %s is busy", agent->device_name);
02538 return 0;
02539 }
02540 ast_pthread_create_detached_background(&clotho, NULL, generic_recall, agent);
02541 return 0;
02542 }
02543
02544 static void cc_generic_agent_destructor(struct ast_cc_agent *agent)
02545 {
02546 struct cc_generic_agent_pvt *agent_pvt = agent->private_data;
02547
02548 if (!agent_pvt) {
02549
02550 return;
02551 }
02552
02553 cc_generic_agent_stop_offer_timer(agent);
02554 if (agent_pvt->sub) {
02555 agent_pvt->sub = ast_event_unsubscribe(agent_pvt->sub);
02556 }
02557
02558 ast_free(agent_pvt);
02559 }
02560
02561 static void cc_core_instance_destructor(void *data)
02562 {
02563 struct cc_core_instance *core_instance = data;
02564 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying core instance\n", core_instance->core_id);
02565 if (core_instance->agent) {
02566 cc_unref(core_instance->agent, "Core instance is done with the agent now");
02567 }
02568 if (core_instance->monitors) {
02569 core_instance->monitors = cc_unref(core_instance->monitors, "Core instance is done with interface list");
02570 }
02571 }
02572
02573 static struct cc_core_instance *cc_core_init_instance(struct ast_channel *caller_chan,
02574 struct cc_monitor_tree *called_tree, const int core_id, struct cc_control_payload *cc_data)
02575 {
02576 char caller[AST_CHANNEL_NAME];
02577 struct cc_core_instance *core_instance;
02578 struct ast_cc_config_params *cc_params;
02579 long agent_count;
02580 int recall_core_id;
02581
02582 ast_channel_get_device_name(caller_chan, caller, sizeof(caller));
02583 cc_params = ast_channel_get_cc_config_params(caller_chan);
02584 if (!cc_params) {
02585 ast_log_dynamic_level(cc_logger_level, "Could not get CC parameters for %s\n",
02586 caller);
02587 return NULL;
02588 }
02589
02590
02591
02592 if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) {
02593 kill_duplicate_offers(caller);
02594 }
02595
02596 ast_cc_is_recall(caller_chan, &recall_core_id, NULL);
02597 agent_count = count_agents(caller, recall_core_id);
02598 if (agent_count >= ast_get_cc_max_agents(cc_params)) {
02599 ast_log_dynamic_level(cc_logger_level, "Caller %s already has the maximum number of agents configured\n", caller);
02600 return NULL;
02601 }
02602
02603
02604 if (agent_count > 0 && ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) {
02605 ast_log_dynamic_level(cc_logger_level, "Generic agents can only have a single outstanding request\n");
02606 return NULL;
02607 }
02608
02609
02610 if (!(core_instance = ao2_t_alloc(sizeof(*core_instance), cc_core_instance_destructor, "Creating core instance for CC"))) {
02611 return NULL;
02612 }
02613
02614 core_instance->core_id = core_id;
02615 if (!(core_instance->agent = cc_agent_init(caller_chan, caller, core_instance->core_id, called_tree))) {
02616 cc_unref(core_instance, "Couldn't allocate agent, unref core_instance");
02617 return NULL;
02618 }
02619
02620 core_instance->monitors = cc_ref(called_tree, "Core instance getting ref to monitor tree");
02621
02622 ao2_t_link(cc_core_instances, core_instance, "Link core instance into container");
02623
02624 return core_instance;
02625 }
02626
02627 struct cc_state_change_args {
02628 struct cc_core_instance *core_instance;
02629 enum cc_state state;
02630 int core_id;
02631 char debug[1];
02632 };
02633
02634 static int is_state_change_valid(enum cc_state current_state, const enum cc_state new_state, struct ast_cc_agent *agent)
02635 {
02636 int is_valid = 0;
02637 switch (new_state) {
02638 case CC_AVAILABLE:
02639 ast_log_dynamic_level(cc_logger_level, "Core %d: Asked to change to state %d? That should never happen.\n",
02640 agent->core_id, new_state);
02641 break;
02642 case CC_CALLER_OFFERED:
02643 if (current_state == CC_AVAILABLE) {
02644 is_valid = 1;
02645 }
02646 break;
02647 case CC_CALLER_REQUESTED:
02648 if (current_state == CC_CALLER_OFFERED ||
02649 (current_state == CC_AVAILABLE && ast_test_flag(agent, AST_CC_AGENT_SKIP_OFFER))) {
02650 is_valid = 1;
02651 }
02652 break;
02653 case CC_ACTIVE:
02654 if (current_state == CC_CALLER_REQUESTED || current_state == CC_CALLER_BUSY) {
02655 is_valid = 1;
02656 }
02657 break;
02658 case CC_CALLEE_READY:
02659 if (current_state == CC_ACTIVE) {
02660 is_valid = 1;
02661 }
02662 break;
02663 case CC_CALLER_BUSY:
02664 if (current_state == CC_CALLEE_READY) {
02665 is_valid = 1;
02666 }
02667 break;
02668 case CC_RECALLING:
02669 if (current_state == CC_CALLEE_READY) {
02670 is_valid = 1;
02671 }
02672 break;
02673 case CC_COMPLETE:
02674 if (current_state == CC_RECALLING) {
02675 is_valid = 1;
02676 }
02677 break;
02678 case CC_FAILED:
02679 is_valid = 1;
02680 break;
02681 default:
02682 ast_log_dynamic_level(cc_logger_level, "Core %d: Asked to change to unknown state %d\n",
02683 agent->core_id, new_state);
02684 break;
02685 }
02686
02687 return is_valid;
02688 }
02689
02690 static int cc_available(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02691 {
02692
02693 ast_log(LOG_WARNING, "Someone requested to change to CC_AVAILABLE? Ignoring.\n");
02694 return -1;
02695 }
02696
02697 static int cc_caller_offered(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02698 {
02699 if (core_instance->agent->callbacks->start_offer_timer(core_instance->agent)) {
02700 ast_cc_failed(core_instance->core_id, "Failed to start the offer timer for %s\n",
02701 core_instance->agent->device_name);
02702 return -1;
02703 }
02704 manager_event(EVENT_FLAG_CC, "CCOfferTimerStart",
02705 "CoreID: %d\r\n"
02706 "Caller: %s\r\n"
02707 "Expires: %u\r\n",
02708 core_instance->core_id, core_instance->agent->device_name, core_instance->agent->cc_params->cc_offer_timer);
02709 ast_log_dynamic_level(cc_logger_level, "Core %d: Started the offer timer for the agent %s!\n",
02710 core_instance->core_id, core_instance->agent->device_name);
02711 return 0;
02712 }
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730 static int has_device_monitors(struct cc_core_instance *core_instance)
02731 {
02732 struct ast_cc_monitor *iter;
02733 int res = 0;
02734
02735 AST_LIST_TRAVERSE(core_instance->monitors, iter, next) {
02736 if (iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
02737 res = 1;
02738 break;
02739 }
02740 }
02741
02742 return res;
02743 }
02744
02745 static void request_cc(struct cc_core_instance *core_instance)
02746 {
02747 struct ast_cc_monitor *monitor_iter;
02748 AST_LIST_LOCK(core_instance->monitors);
02749 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
02750 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
02751 if (monitor_iter->callbacks->request_cc(monitor_iter, &monitor_iter->available_timer_id)) {
02752 AST_LIST_REMOVE_CURRENT(next);
02753 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
02754 monitor_iter->interface->device_name, 1);
02755 cc_unref(monitor_iter, "request_cc failed. Unref list's reference to monitor");
02756 } else {
02757 manager_event(EVENT_FLAG_CC, "CCRequested",
02758 "CoreID: %d\r\n"
02759 "Caller: %s\r\n"
02760 "Callee: %s\r\n",
02761 core_instance->core_id, core_instance->agent->device_name, monitor_iter->interface->device_name);
02762 }
02763 }
02764 }
02765 AST_LIST_TRAVERSE_SAFE_END;
02766
02767 if (!has_device_monitors(core_instance)) {
02768 ast_cc_failed(core_instance->core_id, "All device monitors failed to request CC");
02769 }
02770 AST_LIST_UNLOCK(core_instance->monitors);
02771 }
02772
02773 static int cc_caller_requested(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02774 {
02775 if (!ast_cc_request_is_within_limits()) {
02776 ast_log(LOG_WARNING, "Cannot request CC since there is no more room for requests\n");
02777 core_instance->agent->callbacks->respond(core_instance->agent,
02778 AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY);
02779 ast_cc_failed(core_instance->core_id, "Too many requests in the system");
02780 return -1;
02781 }
02782 core_instance->agent->callbacks->stop_offer_timer(core_instance->agent);
02783 request_cc(core_instance);
02784 return 0;
02785 }
02786
02787 static void unsuspend(struct cc_core_instance *core_instance)
02788 {
02789 struct ast_cc_monitor *monitor_iter;
02790 AST_LIST_LOCK(core_instance->monitors);
02791 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
02792 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
02793 if (monitor_iter->callbacks->unsuspend(monitor_iter)) {
02794 AST_LIST_REMOVE_CURRENT(next);
02795 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
02796 monitor_iter->interface->device_name, 1);
02797 cc_unref(monitor_iter, "unsuspend failed. Unref list's reference to monitor");
02798 }
02799 }
02800 }
02801 AST_LIST_TRAVERSE_SAFE_END;
02802
02803 if (!has_device_monitors(core_instance)) {
02804 ast_cc_failed(core_instance->core_id, "All device monitors failed to unsuspend CC");
02805 }
02806 AST_LIST_UNLOCK(core_instance->monitors);
02807 }
02808
02809 static int cc_active(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02810 {
02811
02812
02813
02814
02815
02816 if (previous_state == CC_CALLER_REQUESTED) {
02817 core_instance->agent->callbacks->respond(core_instance->agent,
02818 AST_CC_AGENT_RESPONSE_SUCCESS);
02819 manager_event(EVENT_FLAG_CC, "CCRequestAcknowledged",
02820 "CoreID: %d\r\n"
02821 "Caller: %s\r\n",
02822 core_instance->core_id, core_instance->agent->device_name);
02823 } else if (previous_state == CC_CALLER_BUSY) {
02824 manager_event(EVENT_FLAG_CC, "CCCallerStopMonitoring",
02825 "CoreID: %d\r\n"
02826 "Caller: %s\r\n",
02827 core_instance->core_id, core_instance->agent->device_name);
02828 unsuspend(core_instance);
02829 }
02830
02831 return 0;
02832 }
02833
02834 static int cc_callee_ready(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02835 {
02836 core_instance->agent->callbacks->callee_available(core_instance->agent);
02837 return 0;
02838 }
02839
02840 static void suspend(struct cc_core_instance *core_instance)
02841 {
02842 struct ast_cc_monitor *monitor_iter;
02843 AST_LIST_LOCK(core_instance->monitors);
02844 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
02845 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
02846 if (monitor_iter->callbacks->suspend(monitor_iter)) {
02847 AST_LIST_REMOVE_CURRENT(next);
02848 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
02849 monitor_iter->interface->device_name, 1);
02850 cc_unref(monitor_iter, "suspend failed. Unref list's reference to monitor");
02851 }
02852 }
02853 }
02854 AST_LIST_TRAVERSE_SAFE_END;
02855
02856 if (!has_device_monitors(core_instance)) {
02857 ast_cc_failed(core_instance->core_id, "All device monitors failed to suspend CC");
02858 }
02859 AST_LIST_UNLOCK(core_instance->monitors);
02860 }
02861
02862 static int cc_caller_busy(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02863 {
02864
02865
02866
02867 suspend(core_instance);
02868 core_instance->agent->callbacks->start_monitoring(core_instance->agent);
02869 manager_event(EVENT_FLAG_CC, "CCCallerStartMonitoring",
02870 "CoreID: %d\r\n"
02871 "Caller: %s\r\n",
02872 core_instance->core_id, core_instance->agent->device_name);
02873 return 0;
02874 }
02875
02876 static void cancel_available_timer(struct cc_core_instance *core_instance)
02877 {
02878 struct ast_cc_monitor *monitor_iter;
02879 AST_LIST_LOCK(core_instance->monitors);
02880 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
02881 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
02882 if (monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id)) {
02883 AST_LIST_REMOVE_CURRENT(next);
02884 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
02885 monitor_iter->interface->device_name, 1);
02886 cc_unref(monitor_iter, "cancel_available_timer failed. Unref list's reference to monitor");
02887 }
02888 }
02889 }
02890 AST_LIST_TRAVERSE_SAFE_END;
02891
02892 if (!has_device_monitors(core_instance)) {
02893 ast_cc_failed(core_instance->core_id, "All device monitors failed to cancel their available timers");
02894 }
02895 AST_LIST_UNLOCK(core_instance->monitors);
02896 }
02897
02898 static int cc_recalling(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02899 {
02900
02901
02902 cancel_available_timer(core_instance);
02903 manager_event(EVENT_FLAG_CC, "CCCallerRecalling",
02904 "CoreID: %d\r\n"
02905 "Caller: %s\r\n",
02906 core_instance->core_id, core_instance->agent->device_name);
02907 return 0;
02908 }
02909
02910 static int cc_complete(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02911 {
02912
02913
02914 manager_event(EVENT_FLAG_CC, "CCRecallComplete",
02915 "CoreID: %d\r\n"
02916 "Caller: %s\r\n",
02917 core_instance->core_id, core_instance->agent->device_name);
02918 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC recall has completed");
02919 return 0;
02920 }
02921
02922 static int cc_failed(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02923 {
02924 manager_event(EVENT_FLAG_CC, "CCFailure",
02925 "CoreID: %d\r\n"
02926 "Caller: %s\r\n"
02927 "Reason: %s\r\n",
02928 core_instance->core_id, core_instance->agent->device_name, args->debug);
02929 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC failed");
02930 return 0;
02931 }
02932
02933 static int (* const state_change_funcs [])(struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state) = {
02934 [CC_AVAILABLE] = cc_available,
02935 [CC_CALLER_OFFERED] = cc_caller_offered,
02936 [CC_CALLER_REQUESTED] = cc_caller_requested,
02937 [CC_ACTIVE] = cc_active,
02938 [CC_CALLEE_READY] = cc_callee_ready,
02939 [CC_CALLER_BUSY] = cc_caller_busy,
02940 [CC_RECALLING] = cc_recalling,
02941 [CC_COMPLETE] = cc_complete,
02942 [CC_FAILED] = cc_failed,
02943 };
02944
02945 static int cc_do_state_change(void *datap)
02946 {
02947 struct cc_state_change_args *args = datap;
02948 struct cc_core_instance *core_instance;
02949 enum cc_state previous_state;
02950 int res;
02951
02952 ast_log_dynamic_level(cc_logger_level, "Core %d: State change to %d requested. Reason: %s\n",
02953 args->core_id, args->state, args->debug);
02954
02955 core_instance = args->core_instance;
02956
02957 if (!is_state_change_valid(core_instance->current_state, args->state, core_instance->agent)) {
02958 ast_log_dynamic_level(cc_logger_level, "Core %d: Invalid state change requested. Cannot go from %s to %s\n",
02959 args->core_id, cc_state_to_string(core_instance->current_state), cc_state_to_string(args->state));
02960 if (args->state == CC_CALLER_REQUESTED) {
02961
02962
02963
02964
02965 core_instance->agent->callbacks->respond(core_instance->agent,
02966 AST_CC_AGENT_RESPONSE_FAILURE_INVALID);
02967 }
02968 ast_free(args);
02969 cc_unref(core_instance, "Unref core instance from when it was found earlier");
02970 return -1;
02971 }
02972
02973
02974 previous_state = core_instance->current_state;
02975 core_instance->current_state = args->state;
02976 res = state_change_funcs[core_instance->current_state](core_instance, args, previous_state);
02977
02978 ast_free(args);
02979 cc_unref(core_instance, "Unref since state change has completed");
02980 return res;
02981 }
02982
02983 static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
02984 {
02985 int res;
02986 int debuglen;
02987 char dummy[1];
02988 va_list aq;
02989 struct cc_core_instance *core_instance;
02990 struct cc_state_change_args *args;
02991
02992
02993
02994 va_copy(aq, ap);
02995
02996
02997
02998 debuglen = vsnprintf(dummy, sizeof(dummy), debug, aq) + 1;
02999 va_end(aq);
03000
03001 if (!(args = ast_calloc(1, sizeof(*args) + debuglen))) {
03002 return -1;
03003 }
03004
03005 core_instance = find_cc_core_instance(core_id);
03006 if (!core_instance) {
03007 ast_log_dynamic_level(cc_logger_level, "Core %d: Unable to find core instance.\n",
03008 core_id);
03009 ast_free(args);
03010 return -1;
03011 }
03012
03013 args->core_instance = core_instance;
03014 args->state = state;
03015 args->core_id = core_id;
03016 vsnprintf(args->debug, debuglen, debug, ap);
03017
03018 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_do_state_change, args);
03019 if (res) {
03020 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
03021 ast_free(args);
03022 }
03023 return res;
03024 }
03025
03026 struct cc_recall_ds_data {
03027 int core_id;
03028 char ignore;
03029 char nested;
03030 struct cc_monitor_tree *interface_tree;
03031 };
03032
03033 static void *cc_recall_ds_duplicate(void *data)
03034 {
03035 struct cc_recall_ds_data *old_data = data;
03036 struct cc_recall_ds_data *new_data = ast_calloc(1, sizeof(*new_data));
03037
03038 if (!new_data) {
03039 return NULL;
03040 }
03041 new_data->interface_tree = cc_ref(old_data->interface_tree, "Bump refcount of monitor tree for recall datastore duplicate");
03042 new_data->core_id = old_data->core_id;
03043 new_data->nested = 1;
03044 return new_data;
03045 }
03046
03047 static void cc_recall_ds_destroy(void *data)
03048 {
03049 struct cc_recall_ds_data *recall_data = data;
03050 recall_data->interface_tree = cc_unref(recall_data->interface_tree, "Unref recall monitor tree");
03051 ast_free(recall_data);
03052 }
03053
03054 static struct ast_datastore_info recall_ds_info = {
03055 .type = "cc_recall",
03056 .duplicate = cc_recall_ds_duplicate,
03057 .destroy = cc_recall_ds_destroy,
03058 };
03059
03060 int ast_setup_cc_recall_datastore(struct ast_channel *chan, const int core_id)
03061 {
03062 struct ast_datastore *recall_datastore = ast_datastore_alloc(&recall_ds_info, NULL);
03063 struct cc_recall_ds_data *recall_data;
03064 struct cc_core_instance *core_instance;
03065
03066 if (!recall_datastore) {
03067 return -1;
03068 }
03069
03070 if (!(recall_data = ast_calloc(1, sizeof(*recall_data)))) {
03071 ast_datastore_free(recall_datastore);
03072 return -1;
03073 }
03074
03075 if (!(core_instance = find_cc_core_instance(core_id))) {
03076 ast_free(recall_data);
03077 ast_datastore_free(recall_datastore);
03078 return -1;
03079 }
03080
03081 recall_data->interface_tree = cc_ref(core_instance->monitors,
03082 "Bump refcount for monitor tree for recall datastore");
03083 recall_data->core_id = core_id;
03084 recall_datastore->data = recall_data;
03085 recall_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
03086 ast_channel_lock(chan);
03087 ast_channel_datastore_add(chan, recall_datastore);
03088 ast_channel_unlock(chan);
03089 cc_unref(core_instance, "Recall datastore set up. No need for core_instance ref");
03090 return 0;
03091 }
03092
03093 int ast_cc_is_recall(struct ast_channel *chan, int *core_id, const char * const monitor_type)
03094 {
03095 struct ast_datastore *recall_datastore;
03096 struct cc_recall_ds_data *recall_data;
03097 struct cc_monitor_tree *interface_tree;
03098 char device_name[AST_CHANNEL_NAME];
03099 struct ast_cc_monitor *device_monitor;
03100 int core_id_candidate;
03101
03102 ast_assert(core_id != NULL);
03103
03104 *core_id = -1;
03105
03106 ast_channel_lock(chan);
03107 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
03108
03109 ast_channel_unlock(chan);
03110 return 0;
03111 }
03112
03113 recall_data = recall_datastore->data;
03114
03115 if (recall_data->ignore) {
03116
03117
03118
03119
03120 ast_channel_unlock(chan);
03121 return 0;
03122 }
03123
03124 if (!recall_data->nested) {
03125
03126
03127
03128
03129
03130
03131 *core_id = recall_data->core_id;
03132 ast_channel_unlock(chan);
03133 return 1;
03134 }
03135
03136 if (ast_strlen_zero(monitor_type)) {
03137
03138
03139
03140
03141
03142 ast_channel_unlock(chan);
03143 return 0;
03144 }
03145
03146 interface_tree = recall_data->interface_tree;
03147 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
03148
03149
03150
03151
03152
03153 core_id_candidate = recall_data->core_id;
03154 ast_channel_unlock(chan);
03155
03156
03157
03158
03159
03160 AST_LIST_LOCK(interface_tree);
03161 AST_LIST_TRAVERSE(interface_tree, device_monitor, next) {
03162 if (!strcmp(device_monitor->interface->device_name, device_name) &&
03163 !strcmp(device_monitor->interface->monitor_type, monitor_type)) {
03164
03165 *core_id = core_id_candidate;
03166 AST_LIST_UNLOCK(interface_tree);
03167 return 1;
03168 }
03169 }
03170 AST_LIST_UNLOCK(interface_tree);
03171 return 0;
03172 }
03173
03174 struct ast_cc_monitor *ast_cc_get_monitor_by_recall_core_id(const int core_id, const char * const device_name)
03175 {
03176 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
03177 struct ast_cc_monitor *monitor_iter;
03178
03179 if (!core_instance) {
03180 return NULL;
03181 }
03182
03183 AST_LIST_LOCK(core_instance->monitors);
03184 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
03185 if (!strcmp(monitor_iter->interface->device_name, device_name)) {
03186
03187 cc_ref(monitor_iter, "Hand the requester of the monitor a reference");
03188 break;
03189 }
03190 }
03191 AST_LIST_UNLOCK(core_instance->monitors);
03192 cc_unref(core_instance, "Done with core instance ref in ast_cc_get_monitor_by_recall_core_id");
03193 return monitor_iter;
03194 }
03195
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213 static void cc_unique_append(struct ast_str *str, const char *dialstring)
03214 {
03215 char dialstring_search[AST_CHANNEL_NAME];
03216
03217 if (ast_strlen_zero(dialstring)) {
03218
03219 return;
03220 }
03221 snprintf(dialstring_search, sizeof(dialstring_search), "%s%c", dialstring, '&');
03222 if (strstr(ast_str_buffer(str), dialstring_search)) {
03223 return;
03224 }
03225 ast_str_append(&str, 0, "%s", dialstring_search);
03226 }
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243 static void build_cc_interfaces_chanvar(struct ast_cc_monitor *starting_point, struct ast_str *str)
03244 {
03245 struct extension_monitor_pvt *extension_pvt;
03246 struct extension_child_dialstring *child_dialstring;
03247 struct ast_cc_monitor *monitor_iter = starting_point;
03248 int top_level_id = starting_point->id;
03249 size_t length;
03250
03251
03252 ast_str_truncate(str, 0);
03253
03254
03255
03256
03257
03258 extension_pvt = starting_point->private_data;
03259 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
03260 if (child_dialstring->is_valid) {
03261 cc_unique_append(str, child_dialstring->original_dialstring);
03262 }
03263 }
03264
03265
03266 while ((monitor_iter = AST_LIST_NEXT(monitor_iter, next))) {
03267 if (monitor_iter->parent_id == top_level_id) {
03268 cc_unique_append(str, monitor_iter->dialstring);
03269 }
03270 }
03271
03272
03273
03274
03275 length = ast_str_strlen(str);
03276 if (length) {
03277 ast_str_truncate(str, length - 1);
03278 }
03279 if (length <= 1) {
03280
03281 ast_log(LOG_ERROR, "CC_INTERFACES is empty. starting device_name:'%s'\n",
03282 starting_point->interface->device_name);
03283 }
03284 }
03285
03286 int ast_cc_agent_set_interfaces_chanvar(struct ast_channel *chan)
03287 {
03288 struct ast_datastore *recall_datastore;
03289 struct cc_monitor_tree *interface_tree;
03290 struct ast_cc_monitor *monitor;
03291 struct cc_recall_ds_data *recall_data;
03292 struct ast_str *str = ast_str_create(64);
03293 int core_id;
03294
03295 if (!str) {
03296 return -1;
03297 }
03298
03299 ast_channel_lock(chan);
03300 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
03301 ast_channel_unlock(chan);
03302 ast_free(str);
03303 return -1;
03304 }
03305 recall_data = recall_datastore->data;
03306 interface_tree = recall_data->interface_tree;
03307 core_id = recall_data->core_id;
03308 ast_channel_unlock(chan);
03309
03310 AST_LIST_LOCK(interface_tree);
03311 monitor = AST_LIST_FIRST(interface_tree);
03312 build_cc_interfaces_chanvar(monitor, str);
03313 AST_LIST_UNLOCK(interface_tree);
03314
03315 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
03316 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
03317 core_id, ast_str_buffer(str));
03318
03319 ast_free(str);
03320 return 0;
03321 }
03322
03323 int ast_set_cc_interfaces_chanvar(struct ast_channel *chan, const char * const extension)
03324 {
03325 struct ast_datastore *recall_datastore;
03326 struct cc_monitor_tree *interface_tree;
03327 struct ast_cc_monitor *monitor_iter;
03328 struct cc_recall_ds_data *recall_data;
03329 struct ast_str *str = ast_str_create(64);
03330 int core_id;
03331
03332 if (!str) {
03333 return -1;
03334 }
03335
03336 ast_channel_lock(chan);
03337 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
03338 ast_channel_unlock(chan);
03339 ast_free(str);
03340 return -1;
03341 }
03342 recall_data = recall_datastore->data;
03343 interface_tree = recall_data->interface_tree;
03344 core_id = recall_data->core_id;
03345 ast_channel_unlock(chan);
03346
03347 AST_LIST_LOCK(interface_tree);
03348 AST_LIST_TRAVERSE(interface_tree, monitor_iter, next) {
03349 if (!strcmp(monitor_iter->interface->device_name, extension)) {
03350 break;
03351 }
03352 }
03353
03354 if (!monitor_iter) {
03355
03356
03357
03358
03359 AST_LIST_UNLOCK(interface_tree);
03360 ast_free(str);
03361 return -1;
03362 }
03363
03364 build_cc_interfaces_chanvar(monitor_iter, str);
03365 AST_LIST_UNLOCK(interface_tree);
03366
03367 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
03368 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
03369 core_id, ast_str_buffer(str));
03370
03371 ast_free(str);
03372 return 0;
03373 }
03374
03375 void ast_ignore_cc(struct ast_channel *chan)
03376 {
03377 struct ast_datastore *cc_datastore;
03378 struct ast_datastore *cc_recall_datastore;
03379 struct dialed_cc_interfaces *cc_interfaces;
03380 struct cc_recall_ds_data *recall_cc_data;
03381
03382 ast_channel_lock(chan);
03383 if ((cc_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
03384 cc_interfaces = cc_datastore->data;
03385 cc_interfaces->ignore = 1;
03386 }
03387
03388 if ((cc_recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
03389 recall_cc_data = cc_recall_datastore->data;
03390 recall_cc_data->ignore = 1;
03391 }
03392 ast_channel_unlock(chan);
03393 }
03394
03395 static __attribute__((format(printf, 2, 3))) int cc_offer(const int core_id, const char * const debug, ...)
03396 {
03397 va_list ap;
03398 int res;
03399
03400 va_start(ap, debug);
03401 res = cc_request_state_change(CC_CALLER_OFFERED, core_id, debug, ap);
03402 va_end(ap);
03403 return res;
03404 }
03405
03406 int ast_cc_offer(struct ast_channel *caller_chan)
03407 {
03408 int core_id;
03409 int res = -1;
03410 struct ast_datastore *datastore;
03411 struct dialed_cc_interfaces *cc_interfaces;
03412 char cc_is_offerable;
03413
03414 ast_channel_lock(caller_chan);
03415 if (!(datastore = ast_channel_datastore_find(caller_chan, &dialed_cc_interfaces_info, NULL))) {
03416 ast_channel_unlock(caller_chan);
03417 return res;
03418 }
03419
03420 cc_interfaces = datastore->data;
03421 cc_is_offerable = cc_interfaces->is_original_caller;
03422 core_id = cc_interfaces->core_id;
03423 ast_channel_unlock(caller_chan);
03424
03425 if (cc_is_offerable) {
03426 res = cc_offer(core_id, "CC offered to caller %s", caller_chan->name);
03427 }
03428 return res;
03429 }
03430
03431 int ast_cc_agent_accept_request(int core_id, const char * const debug, ...)
03432 {
03433 va_list ap;
03434 int res;
03435
03436 va_start(ap, debug);
03437 res = cc_request_state_change(CC_CALLER_REQUESTED, core_id, debug, ap);
03438 va_end(ap);
03439 return res;
03440 }
03441
03442 int ast_cc_monitor_request_acked(int core_id, const char * const debug, ...)
03443 {
03444 va_list ap;
03445 int res;
03446
03447 va_start(ap, debug);
03448 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
03449 va_end(ap);
03450 return res;
03451 }
03452
03453 int ast_cc_monitor_callee_available(const int core_id, const char * const debug, ...)
03454 {
03455 va_list ap;
03456 int res;
03457
03458 va_start(ap, debug);
03459 res = cc_request_state_change(CC_CALLEE_READY, core_id, debug, ap);
03460 va_end(ap);
03461 return res;
03462 }
03463
03464 int ast_cc_agent_caller_busy(int core_id, const char * debug, ...)
03465 {
03466 va_list ap;
03467 int res;
03468
03469 va_start(ap, debug);
03470 res = cc_request_state_change(CC_CALLER_BUSY, core_id, debug, ap);
03471 va_end(ap);
03472 return res;
03473 }
03474
03475 int ast_cc_agent_caller_available(int core_id, const char * const debug, ...)
03476 {
03477 va_list ap;
03478 int res;
03479
03480 va_start(ap, debug);
03481 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
03482 va_end(ap);
03483 return res;
03484 }
03485
03486 int ast_cc_agent_recalling(int core_id, const char * const debug, ...)
03487 {
03488 va_list ap;
03489 int res;
03490
03491 va_start(ap, debug);
03492 res = cc_request_state_change(CC_RECALLING, core_id, debug, ap);
03493 va_end(ap);
03494 return res;
03495 }
03496
03497 int ast_cc_completed(struct ast_channel *chan, const char * const debug, ...)
03498 {
03499 struct ast_datastore *recall_datastore;
03500 struct cc_recall_ds_data *recall_data;
03501 int core_id;
03502 va_list ap;
03503 int res;
03504
03505 ast_channel_lock(chan);
03506 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
03507
03508 ast_channel_unlock(chan);
03509 return -1;
03510 }
03511 recall_data = recall_datastore->data;
03512 if (recall_data->nested || recall_data->ignore) {
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523 ast_channel_unlock(chan);
03524 return -1;
03525 }
03526 core_id = recall_data->core_id;
03527 ast_channel_unlock(chan);
03528 va_start(ap, debug);
03529 res = cc_request_state_change(CC_COMPLETE, core_id, debug, ap);
03530 va_end(ap);
03531 return res;
03532 }
03533
03534 int ast_cc_failed(int core_id, const char * const debug, ...)
03535 {
03536 va_list ap;
03537 int res;
03538
03539 va_start(ap, debug);
03540 res = cc_request_state_change(CC_FAILED, core_id, debug, ap);
03541 va_end(ap);
03542 return res;
03543 }
03544
03545 struct ast_cc_monitor_failure_data {
03546 const char *device_name;
03547 char *debug;
03548 int core_id;
03549 };
03550
03551 static int cc_monitor_failed(void *data)
03552 {
03553 struct ast_cc_monitor_failure_data *failure_data = data;
03554 struct cc_core_instance *core_instance;
03555 struct ast_cc_monitor *monitor_iter;
03556
03557 core_instance = find_cc_core_instance(failure_data->core_id);
03558 if (!core_instance) {
03559
03560 ast_log_dynamic_level(cc_logger_level,
03561 "Core %d: Could not find core instance for device %s '%s'\n",
03562 failure_data->core_id, failure_data->device_name, failure_data->debug);
03563 ast_free((char *) failure_data->device_name);
03564 ast_free((char *) failure_data->debug);
03565 ast_free(failure_data);
03566 return -1;
03567 }
03568
03569 AST_LIST_LOCK(core_instance->monitors);
03570 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
03571 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
03572 if (!strcmp(monitor_iter->interface->device_name, failure_data->device_name)) {
03573 AST_LIST_REMOVE_CURRENT(next);
03574 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
03575 monitor_iter->interface->device_name, 1);
03576 monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id);
03577 manager_event(EVENT_FLAG_CC, "CCMonitorFailed",
03578 "CoreID: %d\r\n"
03579 "Callee: %s\r\n",
03580 monitor_iter->core_id, monitor_iter->interface->device_name);
03581 cc_unref(monitor_iter, "Monitor reported failure. Unref list's reference.");
03582 }
03583 }
03584 }
03585 AST_LIST_TRAVERSE_SAFE_END;
03586
03587 if (!has_device_monitors(core_instance)) {
03588 ast_cc_failed(core_instance->core_id, "All monitors have failed\n");
03589 }
03590 AST_LIST_UNLOCK(core_instance->monitors);
03591 cc_unref(core_instance, "Finished with core_instance in cc_monitor_failed\n");
03592
03593 ast_free((char *) failure_data->device_name);
03594 ast_free((char *) failure_data->debug);
03595 ast_free(failure_data);
03596 return 0;
03597 }
03598
03599 int ast_cc_monitor_failed(int core_id, const char *const monitor_name, const char * const debug, ...)
03600 {
03601 struct ast_cc_monitor_failure_data *failure_data;
03602 int res;
03603 va_list ap;
03604
03605 if (!(failure_data = ast_calloc(1, sizeof(*failure_data)))) {
03606 return -1;
03607 }
03608
03609 if (!(failure_data->device_name = ast_strdup(monitor_name))) {
03610 ast_free(failure_data);
03611 return -1;
03612 }
03613
03614 va_start(ap, debug);
03615 if (ast_vasprintf(&failure_data->debug, debug, ap) == -1) {
03616 va_end(ap);
03617 ast_free((char *)failure_data->device_name);
03618 ast_free(failure_data);
03619 return -1;
03620 }
03621 va_end(ap);
03622
03623 failure_data->core_id = core_id;
03624
03625 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_monitor_failed, failure_data);
03626 if (res) {
03627 ast_free((char *)failure_data->device_name);
03628 ast_free((char *)failure_data->debug);
03629 ast_free(failure_data);
03630 }
03631 return res;
03632 }
03633
03634 static int cc_status_request(void *data)
03635 {
03636 struct cc_core_instance *core_instance= data;
03637 int res;
03638
03639 res = core_instance->agent->callbacks->status_request(core_instance->agent);
03640 cc_unref(core_instance, "Status request finished. Unref core instance");
03641 return res;
03642 }
03643
03644 int ast_cc_monitor_status_request(int core_id)
03645 {
03646 int res;
03647 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
03648
03649 if (!core_instance) {
03650 return -1;
03651 }
03652
03653 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_request, core_instance);
03654 if (res) {
03655 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
03656 }
03657 return res;
03658 }
03659
03660 static int cc_stop_ringing(void *data)
03661 {
03662 struct cc_core_instance *core_instance = data;
03663 int res = 0;
03664
03665 if (core_instance->agent->callbacks->stop_ringing) {
03666 res = core_instance->agent->callbacks->stop_ringing(core_instance->agent);
03667 }
03668
03669
03670
03671
03672
03673
03674
03675 ast_cc_monitor_request_acked(core_instance->core_id, "Agent %s asked to stop ringing. Be prepared to be recalled again.",
03676 core_instance->agent->device_name);
03677 cc_unref(core_instance, "Stop ringing finished. Unref core_instance");
03678 return res;
03679 }
03680
03681 int ast_cc_monitor_stop_ringing(int core_id)
03682 {
03683 int res;
03684 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
03685
03686 if (!core_instance) {
03687 return -1;
03688 }
03689
03690 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_stop_ringing, core_instance);
03691 if (res) {
03692 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
03693 }
03694 return res;
03695 }
03696
03697 static int cc_party_b_free(void *data)
03698 {
03699 struct cc_core_instance *core_instance = data;
03700 int res = 0;
03701
03702 if (core_instance->agent->callbacks->party_b_free) {
03703 res = core_instance->agent->callbacks->party_b_free(core_instance->agent);
03704 }
03705 cc_unref(core_instance, "Party B free finished. Unref core_instance");
03706 return res;
03707 }
03708
03709 int ast_cc_monitor_party_b_free(int core_id)
03710 {
03711 int res;
03712 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
03713
03714 if (!core_instance) {
03715 return -1;
03716 }
03717
03718 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_party_b_free, core_instance);
03719 if (res) {
03720 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
03721 }
03722 return res;
03723 }
03724
03725 struct cc_status_response_args {
03726 struct cc_core_instance *core_instance;
03727 enum ast_device_state devstate;
03728 };
03729
03730 static int cc_status_response(void *data)
03731 {
03732 struct cc_status_response_args *args = data;
03733 struct cc_core_instance *core_instance = args->core_instance;
03734 struct ast_cc_monitor *monitor_iter;
03735 enum ast_device_state devstate = args->devstate;
03736
03737 ast_free(args);
03738
03739 AST_LIST_LOCK(core_instance->monitors);
03740 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
03741 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR &&
03742 monitor_iter->callbacks->status_response) {
03743 monitor_iter->callbacks->status_response(monitor_iter, devstate);
03744 }
03745 }
03746 AST_LIST_UNLOCK(core_instance->monitors);
03747 cc_unref(core_instance, "Status response finished. Unref core instance");
03748 return 0;
03749 }
03750
03751 int ast_cc_agent_status_response(int core_id, enum ast_device_state devstate)
03752 {
03753 struct cc_status_response_args *args;
03754 struct cc_core_instance *core_instance;
03755 int res;
03756
03757 args = ast_calloc(1, sizeof(*args));
03758 if (!args) {
03759 return -1;
03760 }
03761
03762 core_instance = find_cc_core_instance(core_id);
03763 if (!core_instance) {
03764 ast_free(args);
03765 return -1;
03766 }
03767
03768 args->core_instance = core_instance;
03769 args->devstate = devstate;
03770
03771 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_response, args);
03772 if (res) {
03773 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
03774 ast_free(args);
03775 }
03776 return res;
03777 }
03778
03779 static int cc_build_payload(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
03780 const char *monitor_type, const char * const device_name, const char * dialstring,
03781 enum ast_cc_service_type service, void *private_data, struct cc_control_payload *payload)
03782 {
03783 struct ast_datastore *datastore;
03784 struct dialed_cc_interfaces *cc_interfaces;
03785 int dial_parent_id;
03786
03787 ast_channel_lock(chan);
03788 datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL);
03789 if (!datastore) {
03790 ast_channel_unlock(chan);
03791 return -1;
03792 }
03793 cc_interfaces = datastore->data;
03794 dial_parent_id = cc_interfaces->dial_parent_id;
03795 ast_channel_unlock(chan);
03796
03797 payload->monitor_type = monitor_type;
03798 payload->private_data = private_data;
03799 payload->service = service;
03800 ast_cc_copy_config_params(&payload->config_params, cc_params);
03801 payload->parent_interface_id = dial_parent_id;
03802 ast_copy_string(payload->device_name, device_name, sizeof(payload->device_name));
03803 ast_copy_string(payload->dialstring, dialstring, sizeof(payload->dialstring));
03804 return 0;
03805 }
03806
03807 int ast_queue_cc_frame(struct ast_channel *chan, const char *monitor_type,
03808 const char * const dialstring, enum ast_cc_service_type service, void *private_data)
03809 {
03810 struct ast_frame frame = {0,};
03811 char device_name[AST_CHANNEL_NAME];
03812 int retval;
03813 struct ast_cc_config_params *cc_params;
03814
03815 cc_params = ast_channel_get_cc_config_params(chan);
03816 if (!cc_params) {
03817 return -1;
03818 }
03819 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
03820 if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) {
03821 ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name);
03822 return -1;
03823 }
03824
03825 if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, &frame)) {
03826
03827 return -1;
03828 }
03829 retval = ast_queue_frame(chan, &frame);
03830 ast_frfree(&frame);
03831 return retval;
03832 }
03833
03834 int ast_cc_build_frame(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
03835 const char *monitor_type, const char * const device_name,
03836 const char * const dialstring, enum ast_cc_service_type service, void *private_data,
03837 struct ast_frame *frame)
03838 {
03839 struct cc_control_payload *payload = ast_calloc(1, sizeof(*payload));
03840
03841 if (!payload) {
03842 return -1;
03843 }
03844 if (cc_build_payload(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, payload)) {
03845
03846 ast_free(payload);
03847 return -1;
03848 }
03849 frame->frametype = AST_FRAME_CONTROL;
03850 frame->subclass.integer = AST_CONTROL_CC;
03851 frame->data.ptr = payload;
03852 frame->datalen = sizeof(*payload);
03853 frame->mallocd = AST_MALLOCD_DATA;
03854 return 0;
03855 }
03856
03857 void ast_cc_call_failed(struct ast_channel *incoming, struct ast_channel *outgoing, const char * const dialstring)
03858 {
03859 char device_name[AST_CHANNEL_NAME];
03860 struct cc_control_payload payload;
03861 struct ast_cc_config_params *cc_params;
03862
03863 if (outgoing->hangupcause != AST_CAUSE_BUSY && outgoing->hangupcause != AST_CAUSE_CONGESTION) {
03864
03865
03866
03867 return;
03868 }
03869
03870 cc_params = ast_channel_get_cc_config_params(outgoing);
03871 if (!cc_params) {
03872 return;
03873 }
03874 if (ast_get_cc_monitor_policy(cc_params) != AST_CC_MONITOR_GENERIC) {
03875
03876
03877
03878 return;
03879 }
03880
03881 ast_channel_get_device_name(outgoing, device_name, sizeof(device_name));
03882 if (cc_build_payload(outgoing, cc_params, AST_CC_GENERIC_MONITOR_TYPE, device_name,
03883 dialstring, AST_CC_CCBS, NULL, &payload)) {
03884
03885 return;
03886 }
03887 ast_handle_cc_control_frame(incoming, outgoing, &payload);
03888 }
03889
03890 void ast_cc_busy_interface(struct ast_channel *inbound, struct ast_cc_config_params *cc_params,
03891 const char *monitor_type, const char * const device_name, const char * const dialstring, void *private_data)
03892 {
03893 struct cc_control_payload payload;
03894 if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialstring, AST_CC_CCBS, private_data, &payload)) {
03895
03896 call_destructor_with_no_monitor(monitor_type, private_data);
03897 return;
03898 }
03899 ast_handle_cc_control_frame(inbound, NULL, &payload);
03900 }
03901
03902 int ast_cc_callback(struct ast_channel *inbound, const char * const tech, const char * const dest, ast_cc_callback_fn callback)
03903 {
03904 const struct ast_channel_tech *chantech = ast_get_channel_tech(tech);
03905
03906 if (chantech && chantech->cc_callback) {
03907 chantech->cc_callback(inbound, dest, callback);
03908 }
03909
03910 return 0;
03911 }
03912
03913 static const char *ccreq_app = "CallCompletionRequest";
03914
03915 static int ccreq_exec(struct ast_channel *chan, const char *data)
03916 {
03917 struct cc_core_instance *core_instance;
03918 char device_name[AST_CHANNEL_NAME];
03919 unsigned long match_flags;
03920 int res;
03921
03922 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
03923
03924 match_flags = MATCH_NO_REQUEST;
03925 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionRequest"))) {
03926 ast_log_dynamic_level(cc_logger_level, "Couldn't find a core instance for caller %s\n", device_name);
03927 return -1;
03928 }
03929
03930 ast_log_dynamic_level(cc_logger_level, "Core %d: Found core_instance for caller %s\n",
03931 core_instance->core_id, device_name);
03932
03933 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
03934 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest is only for generic agent types.\n",
03935 core_instance->core_id);
03936 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
03937 cc_unref(core_instance, "Unref core_instance since CallCompletionRequest was called with native agent");
03938 return 0;
03939 }
03940
03941 if (!ast_cc_request_is_within_limits()) {
03942 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest failed. Too many requests in the system\n",
03943 core_instance->core_id);
03944 ast_cc_failed(core_instance->core_id, "Too many CC requests\n");
03945 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
03946 cc_unref(core_instance, "Unref core_instance since too many CC requests");
03947 return 0;
03948 }
03949
03950 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);
03951 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", res ? "FAIL" : "SUCCESS");
03952 cc_unref(core_instance, "Done with CallCompletionRequest");
03953 return res;
03954 }
03955
03956 static const char *cccancel_app = "CallCompletionCancel";
03957
03958 static int cccancel_exec(struct ast_channel *chan, const char *data)
03959 {
03960 struct cc_core_instance *core_instance;
03961 char device_name[AST_CHANNEL_NAME];
03962 unsigned long match_flags;
03963 int res;
03964
03965 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
03966
03967 match_flags = MATCH_REQUEST;
03968 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionCancel"))) {
03969 ast_log(LOG_WARNING, "Cannot find CC transaction to cancel for caller %s\n", device_name);
03970 return -1;
03971 }
03972
03973 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
03974 ast_log(LOG_WARNING, "CallCompletionCancel may only be used for calles with a generic agent\n");
03975 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
03976 return -1;
03977 }
03978 res = ast_cc_failed(core_instance->core_id, "Call completion request Cancelled for core ID %d by caller %s",
03979 core_instance->core_id, device_name);
03980 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
03981 return res;
03982 }
03983
03984 struct count_monitors_cb_data {
03985 const char *device_name;
03986 const char *monitor_type;
03987 int count;
03988 };
03989
03990 static int count_monitors_cb(void *obj, void *arg, int flags)
03991 {
03992 struct cc_core_instance *core_instance = obj;
03993 struct count_monitors_cb_data *cb_data = arg;
03994 const char *device_name = cb_data->device_name;
03995 const char *monitor_type = cb_data->monitor_type;
03996 struct ast_cc_monitor *monitor_iter;
03997
03998 AST_LIST_LOCK(core_instance->monitors);
03999 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
04000 if (!strcmp(monitor_iter->interface->device_name, device_name) &&
04001 !strcmp(monitor_iter->interface->monitor_type, monitor_type)) {
04002 cb_data->count++;
04003 break;
04004 }
04005 }
04006 AST_LIST_UNLOCK(core_instance->monitors);
04007 return 0;
04008 }
04009
04010 int ast_cc_monitor_count(const char * const name, const char * const type)
04011 {
04012 struct count_monitors_cb_data data = {.device_name = name, .monitor_type = type,};
04013
04014 ao2_t_callback(cc_core_instances, OBJ_NODATA, count_monitors_cb, &data, "Counting agents");
04015 ast_log_dynamic_level(cc_logger_level, "Counted %d monitors\n", data.count);
04016 return data.count;
04017 }
04018
04019 static void initialize_cc_max_requests(void)
04020 {
04021 struct ast_config *cc_config;
04022 const char *cc_max_requests_str;
04023 struct ast_flags config_flags = {0,};
04024 char *endptr;
04025
04026 cc_config = ast_config_load2("ccss.conf", "ccss", config_flags);
04027 if (!cc_config || cc_config == CONFIG_STATUS_FILEINVALID) {
04028 ast_log(LOG_WARNING, "Could not find valid ccss.conf file. Using cc_max_requests default\n");
04029 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT;
04030 return;
04031 }
04032
04033 if (!(cc_max_requests_str = ast_variable_retrieve(cc_config, "general", "cc_max_requests"))) {
04034 ast_config_destroy(cc_config);
04035 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT;
04036 return;
04037 }
04038
04039 global_cc_max_requests = strtol(cc_max_requests_str, &endptr, 10);
04040
04041 if (!ast_strlen_zero(endptr)) {
04042 ast_log(LOG_WARNING, "Invalid input given for cc_max_requests. Using default\n");
04043 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT;
04044 }
04045
04046 ast_config_destroy(cc_config);
04047 return;
04048 }
04049
04050 static void cc_cli_print_monitor_stats(struct ast_cc_monitor *monitor, int fd, int parent_id)
04051 {
04052 struct ast_cc_monitor *child_monitor_iter = monitor;
04053 if (!monitor) {
04054 return;
04055 }
04056
04057 ast_cli(fd, "\t\t|-->%s", monitor->interface->device_name);
04058 if (monitor->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
04059 ast_cli(fd, "(%s)", cc_service_to_string(monitor->service_offered));
04060 }
04061 ast_cli(fd, "\n");
04062
04063 while ((child_monitor_iter = AST_LIST_NEXT(child_monitor_iter, next))) {
04064 if (child_monitor_iter->parent_id == monitor->id) {
04065 cc_cli_print_monitor_stats(child_monitor_iter, fd, child_monitor_iter->id);
04066 }
04067 }
04068 }
04069
04070 static int print_stats_cb(void *obj, void *arg, int flags)
04071 {
04072 int *cli_fd = arg;
04073 struct cc_core_instance *core_instance = obj;
04074
04075 ast_cli(*cli_fd, "%d\t\t%s\t\t%s\n", core_instance->core_id, core_instance->agent->device_name,
04076 cc_state_to_string(core_instance->current_state));
04077 AST_LIST_LOCK(core_instance->monitors);
04078 cc_cli_print_monitor_stats(AST_LIST_FIRST(core_instance->monitors), *cli_fd, 0);
04079 AST_LIST_UNLOCK(core_instance->monitors);
04080 return 0;
04081 }
04082
04083 static int cc_cli_output_status(void *data)
04084 {
04085 int *cli_fd = data;
04086 int count = ao2_container_count(cc_core_instances);
04087
04088 if (!count) {
04089 ast_cli(*cli_fd, "There are currently no active call completion transactions\n");
04090 } else {
04091 ast_cli(*cli_fd, "%d Call completion transactions\n", count);
04092 ast_cli(*cli_fd, "Core ID\t\tCaller\t\t\t\tStatus\n");
04093 ast_cli(*cli_fd, "----------------------------------------------------------------------------\n");
04094 ao2_t_callback(cc_core_instances, OBJ_NODATA, print_stats_cb, cli_fd, "Printing stats to CLI");
04095 }
04096 ast_free(cli_fd);
04097 return 0;
04098 }
04099
04100 static char *handle_cc_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04101 {
04102 int *cli_fd;
04103
04104 switch (cmd) {
04105 case CLI_INIT:
04106 e->command = "cc report status";
04107 e->usage =
04108 "Usage: cc report status\n"
04109 " Report the current status of any ongoing CC transactions\n";
04110 return NULL;
04111 case CLI_GENERATE:
04112 return NULL;
04113 }
04114
04115 if (a->argc != 3) {
04116 return CLI_SHOWUSAGE;
04117 }
04118
04119 cli_fd = ast_malloc(sizeof(*cli_fd));
04120 if (!cli_fd) {
04121 return CLI_FAILURE;
04122 }
04123
04124 *cli_fd = a->fd;
04125
04126 if (ast_taskprocessor_push(cc_core_taskprocessor, cc_cli_output_status, cli_fd)) {
04127 ast_free(cli_fd);
04128 return CLI_FAILURE;
04129 }
04130 return CLI_SUCCESS;
04131 }
04132
04133 static int kill_cores(void *obj, void *arg, int flags)
04134 {
04135 int *core_id = arg;
04136 struct cc_core_instance *core_instance = obj;
04137
04138 if (!core_id || (core_instance->core_id == *core_id)) {
04139 ast_cc_failed(core_instance->core_id, "CC transaction canceled administratively\n");
04140 }
04141 return 0;
04142 }
04143
04144 static char *complete_core_id(const char *line, const char *word, int pos, int state)
04145 {
04146 int which = 0;
04147 int wordlen = strlen(word);
04148 char *ret = NULL;
04149 struct ao2_iterator core_iter = ao2_iterator_init(cc_core_instances, 0);
04150 struct cc_core_instance *core_instance;
04151
04152 for (; (core_instance = ao2_t_iterator_next(&core_iter, "Next core instance"));
04153 cc_unref(core_instance, "CLI tab completion iteration")) {
04154 char core_id_str[20];
04155 snprintf(core_id_str, sizeof(core_id_str), "%d", core_instance->core_id);
04156 if (!strncmp(word, core_id_str, wordlen) && ++which > state) {
04157 ret = ast_strdup(core_id_str);
04158 cc_unref(core_instance, "Found a matching core ID for CLI tab-completion");
04159 break;
04160 }
04161 }
04162 ao2_iterator_destroy(&core_iter);
04163
04164 return ret;
04165 }
04166
04167 static char *handle_cc_kill(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04168 {
04169 static const char * const option[] = { "core", "all", NULL };
04170
04171 switch (cmd) {
04172 case CLI_INIT:
04173 e->command = "cc cancel";
04174 e->usage =
04175 "Usage: cc cancel can be used in two ways.\n"
04176 " 1. 'cc cancel core [core ID]' will cancel the CC transaction with\n"
04177 " core ID equal to the specified core ID.\n"
04178 " 2. 'cc cancel all' will cancel all active CC transactions.\n";
04179 return NULL;
04180 case CLI_GENERATE:
04181 if (a->pos == 2) {
04182 return ast_cli_complete(a->word, option, a->n);
04183 }
04184 if (a->pos == 3) {
04185 return complete_core_id(a->line, a->word, a->pos, a->n);
04186 }
04187 return NULL;
04188 }
04189
04190 if (a->argc == 4) {
04191 int core_id;
04192 char *endptr;
04193 if (strcasecmp(a->argv[2], "core")) {
04194 return CLI_SHOWUSAGE;
04195 }
04196 core_id = strtol(a->argv[3], &endptr, 10);
04197 if ((errno != 0 && core_id == 0) || (endptr == a->argv[3])) {
04198 return CLI_SHOWUSAGE;
04199 }
04200 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, &core_id, "CLI Killing Core Id");
04201 } else if (a->argc == 3) {
04202 if (strcasecmp(a->argv[2], "all")) {
04203 return CLI_SHOWUSAGE;
04204 }
04205 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, NULL, "CLI Killing all CC cores");
04206 } else {
04207 return CLI_SHOWUSAGE;
04208 }
04209
04210 return CLI_SUCCESS;
04211 }
04212
04213 static struct ast_cli_entry cc_cli[] = {
04214 AST_CLI_DEFINE(handle_cc_status, "Reports CC stats"),
04215 AST_CLI_DEFINE(handle_cc_kill, "Kill a CC transaction"),
04216 };
04217
04218 int ast_cc_init(void)
04219 {
04220 int res;
04221
04222 if (!(cc_core_instances = ao2_t_container_alloc(CC_CORE_INSTANCES_BUCKETS,
04223 cc_core_instance_hash_fn, cc_core_instance_cmp_fn,
04224 "Create core instance container"))) {
04225 return -1;
04226 }
04227 if (!(generic_monitors = ao2_t_container_alloc(CC_CORE_INSTANCES_BUCKETS,
04228 generic_monitor_hash_fn, generic_monitor_cmp_fn,
04229 "Create generic monitor container"))) {
04230 return -1;
04231 }
04232 if (!(cc_core_taskprocessor = ast_taskprocessor_get("CCSS core", TPS_REF_DEFAULT))) {
04233 return -1;
04234 }
04235 if (!(cc_sched_thread = ast_sched_thread_create())) {
04236 return -1;
04237 }
04238 res = ast_register_application2(ccreq_app, ccreq_exec, NULL, NULL, NULL);
04239 res |= ast_register_application2(cccancel_app, cccancel_exec, NULL, NULL, NULL);
04240 res |= ast_cc_monitor_register(&generic_monitor_cbs);
04241 res |= ast_cc_agent_register(&generic_agent_callbacks);
04242 ast_cli_register_multiple(cc_cli, ARRAY_LEN(cc_cli));
04243 cc_logger_level = ast_logger_register_level(CC_LOGGER_LEVEL_NAME);
04244 dialed_cc_interface_counter = 1;
04245 initialize_cc_max_requests();
04246 return res;
04247 }