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