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: 357940 $")
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 = {0};
01107 char *uppertech = ast_strdupa(device_name);
01108 ast_tech_to_upper(uppertech);
01109 finder.device_name = uppertech;
01110
01111 return ao2_t_find(generic_monitors, &finder, OBJ_POINTER, "Finding generic monitor instance list");
01112 }
01113
01114 static void generic_monitor_instance_list_destructor(void *obj)
01115 {
01116 struct generic_monitor_instance_list *generic_list = obj;
01117 struct generic_monitor_instance *generic_instance;
01118
01119 generic_list->sub = ast_event_unsubscribe(generic_list->sub);
01120 while ((generic_instance = AST_LIST_REMOVE_HEAD(&generic_list->list, next))) {
01121 ast_free(generic_instance);
01122 }
01123 ast_free((char *)generic_list->device_name);
01124 }
01125
01126 static void generic_monitor_devstate_cb(const struct ast_event *event, void *userdata);
01127 static struct generic_monitor_instance_list *create_new_generic_list(struct ast_cc_monitor *monitor)
01128 {
01129 struct generic_monitor_instance_list *generic_list = ao2_t_alloc(sizeof(*generic_list),
01130 generic_monitor_instance_list_destructor, "allocate generic monitor instance list");
01131 char * device_name;
01132
01133 if (!generic_list) {
01134 return NULL;
01135 }
01136
01137 if (!(device_name = ast_strdup(monitor->interface->device_name))) {
01138 cc_unref(generic_list, "Failed to strdup the monitor's device name");
01139 return NULL;
01140 }
01141 ast_tech_to_upper(device_name);
01142 generic_list->device_name = device_name;
01143
01144 if (!(generic_list->sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE,
01145 generic_monitor_devstate_cb, "Requesting CC", NULL,
01146 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, monitor->interface->device_name,
01147 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_EXISTS,
01148 AST_EVENT_IE_END))) {
01149 cc_unref(generic_list, "Failed to subscribe to device state");
01150 return NULL;
01151 }
01152 generic_list->current_state = ast_device_state(monitor->interface->device_name);
01153 ao2_t_link(generic_monitors, generic_list, "linking new generic monitor instance list");
01154 return generic_list;
01155 }
01156
01157 struct generic_tp_cb_data {
01158 const char *device_name;
01159 enum ast_device_state new_state;
01160 };
01161
01162 static int generic_monitor_devstate_tp_cb(void *data)
01163 {
01164 struct generic_tp_cb_data *gtcd = data;
01165 enum ast_device_state new_state = gtcd->new_state;
01166 enum ast_device_state previous_state = gtcd->new_state;
01167 const char *monitor_name = gtcd->device_name;
01168 struct generic_monitor_instance_list *generic_list;
01169 struct generic_monitor_instance *generic_instance;
01170
01171 if (!(generic_list = find_generic_monitor_instance_list(monitor_name))) {
01172
01173
01174
01175
01176 ast_free((char *) gtcd->device_name);
01177 ast_free(gtcd);
01178 return 0;
01179 }
01180
01181 if (generic_list->current_state == new_state) {
01182
01183 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
01184 ast_free((char *) gtcd->device_name);
01185 ast_free(gtcd);
01186 return 0;
01187 }
01188
01189 previous_state = generic_list->current_state;
01190 generic_list->current_state = new_state;
01191
01192 if (cc_generic_is_device_available(new_state) &&
01193 (previous_state == AST_DEVICE_INUSE || previous_state == AST_DEVICE_UNAVAILABLE ||
01194 previous_state == AST_DEVICE_BUSY)) {
01195 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
01196 if (!generic_instance->is_suspended && generic_instance->monitoring) {
01197 generic_instance->monitoring = 0;
01198 generic_list->fit_for_recall = 1;
01199 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
01200 break;
01201 }
01202 }
01203 }
01204 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
01205 ast_free((char *) gtcd->device_name);
01206 ast_free(gtcd);
01207 return 0;
01208 }
01209
01210 static void generic_monitor_devstate_cb(const struct ast_event *event, void *userdata)
01211 {
01212
01213
01214
01215
01216
01217 struct generic_tp_cb_data *gtcd = ast_calloc(1, sizeof(*gtcd));
01218
01219 if (!gtcd) {
01220 return;
01221 }
01222
01223 if (!(gtcd->device_name = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE)))) {
01224 ast_free(gtcd);
01225 return;
01226 }
01227 gtcd->new_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
01228
01229 if (ast_taskprocessor_push(cc_core_taskprocessor, generic_monitor_devstate_tp_cb, gtcd)) {
01230 ast_free((char *)gtcd->device_name);
01231 ast_free(gtcd);
01232 }
01233 }
01234
01235 int ast_cc_available_timer_expire(const void *data)
01236 {
01237 struct ast_cc_monitor *monitor = (struct ast_cc_monitor *) data;
01238 int res;
01239 monitor->available_timer_id = -1;
01240 res = ast_cc_monitor_failed(monitor->core_id, monitor->interface->device_name, "Available timer expired for monitor");
01241 cc_unref(monitor, "Unref reference from scheduler\n");
01242 return res;
01243 }
01244
01245 static int cc_generic_monitor_request_cc(struct ast_cc_monitor *monitor, int *available_timer_id)
01246 {
01247 struct generic_monitor_instance_list *generic_list;
01248 struct generic_monitor_instance *generic_instance;
01249 struct generic_monitor_pvt *gen_mon_pvt;
01250 enum ast_cc_service_type service = monitor->service_offered;
01251 int when;
01252
01253
01254
01255
01256
01257 if (!(gen_mon_pvt = ast_calloc(1, sizeof(*gen_mon_pvt)))) {
01258 return -1;
01259 }
01260
01261 if (!(gen_mon_pvt->device_name = ast_strdup(monitor->interface->device_name))) {
01262 ast_free(gen_mon_pvt);
01263 return -1;
01264 }
01265
01266 gen_mon_pvt->core_id = monitor->core_id;
01267
01268 monitor->private_data = gen_mon_pvt;
01269
01270 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
01271 if (!(generic_list = create_new_generic_list(monitor))) {
01272 return -1;
01273 }
01274 }
01275
01276 if (!(generic_instance = ast_calloc(1, sizeof(*generic_instance)))) {
01277
01278
01279
01280 cc_unref(generic_list, "Generic monitor instance failed to allocate");
01281 return -1;
01282 }
01283 generic_instance->core_id = monitor->core_id;
01284 generic_instance->monitoring = 1;
01285 AST_LIST_INSERT_TAIL(&generic_list->list, generic_instance, next);
01286 when = service == AST_CC_CCBS ? ast_get_ccbs_available_timer(monitor->interface->config_params) :
01287 ast_get_ccnr_available_timer(monitor->interface->config_params);
01288
01289 *available_timer_id = ast_sched_thread_add(cc_sched_thread, when * 1000,
01290 ast_cc_available_timer_expire, cc_ref(monitor, "Give the scheduler a monitor reference"));
01291 if (*available_timer_id == -1) {
01292 cc_unref(monitor, "Failed to schedule available timer. (monitor)");
01293 cc_unref(generic_list, "Failed to schedule available timer. (generic_list)");
01294 return -1;
01295 }
01296
01297
01298
01299 if (service == AST_CC_CCNR || service == AST_CC_CCNL) {
01300 generic_list->fit_for_recall = 0;
01301 }
01302 ast_cc_monitor_request_acked(monitor->core_id, "Generic monitor for %s subscribed to device state.",
01303 monitor->interface->device_name);
01304 cc_unref(generic_list, "Finished with monitor instance reference in request cc callback");
01305 return 0;
01306 }
01307
01308 static int cc_generic_monitor_suspend(struct ast_cc_monitor *monitor)
01309 {
01310 struct generic_monitor_instance_list *generic_list;
01311 struct generic_monitor_instance *generic_instance;
01312 enum ast_device_state state = ast_device_state(monitor->interface->device_name);
01313
01314 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
01315 return -1;
01316 }
01317
01318
01319 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
01320 if (generic_instance->core_id == monitor->core_id) {
01321 generic_instance->is_suspended = 1;
01322 break;
01323 }
01324 }
01325
01326
01327
01328
01329 if (!cc_generic_is_device_available(state)) {
01330 cc_unref(generic_list, "Device is in use. Nothing to do. Unref generic list.");
01331 return 0;
01332 }
01333
01334
01335
01336
01337
01338
01339 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
01340 if (!generic_instance->is_suspended) {
01341 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
01342 break;
01343 }
01344 }
01345 cc_unref(generic_list, "Done with generic list in suspend callback");
01346 return 0;
01347 }
01348
01349 static int cc_generic_monitor_unsuspend(struct ast_cc_monitor *monitor)
01350 {
01351 struct generic_monitor_instance *generic_instance;
01352 struct generic_monitor_instance_list *generic_list = find_generic_monitor_instance_list(monitor->interface->device_name);
01353 enum ast_device_state state = ast_device_state(monitor->interface->device_name);
01354
01355 if (!generic_list) {
01356 return -1;
01357 }
01358
01359
01360
01361 if (cc_generic_is_device_available(state)) {
01362 ast_cc_monitor_callee_available(monitor->core_id, "Generic monitored party has become available");
01363 }
01364
01365
01366 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
01367 if (generic_instance->core_id == monitor->core_id) {
01368 generic_instance->is_suspended = 0;
01369 generic_instance->monitoring = 1;
01370 break;
01371 }
01372 }
01373 cc_unref(generic_list, "Done with generic list in cc_generic_monitor_unsuspend");
01374 return 0;
01375 }
01376
01377 static int cc_generic_monitor_cancel_available_timer(struct ast_cc_monitor *monitor, int *sched_id)
01378 {
01379 ast_assert(sched_id != NULL);
01380
01381 if (*sched_id == -1) {
01382 return 0;
01383 }
01384
01385 ast_log_dynamic_level(cc_logger_level, "Core %d: Canceling generic monitor available timer for monitor %s\n",
01386 monitor->core_id, monitor->interface->device_name);
01387 if (!ast_sched_thread_del(cc_sched_thread, *sched_id)) {
01388 cc_unref(monitor, "Remove scheduler's reference to the monitor");
01389 }
01390 *sched_id = -1;
01391 return 0;
01392 }
01393
01394 static void cc_generic_monitor_destructor(void *private_data)
01395 {
01396 struct generic_monitor_pvt *gen_mon_pvt = private_data;
01397 struct generic_monitor_instance_list *generic_list;
01398 struct generic_monitor_instance *generic_instance;
01399
01400 if (!private_data) {
01401
01402
01403
01404
01405
01406 return;
01407 }
01408
01409 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying generic monitor %s\n",
01410 gen_mon_pvt->core_id, gen_mon_pvt->device_name);
01411
01412 if (!(generic_list = find_generic_monitor_instance_list(gen_mon_pvt->device_name))) {
01413
01414
01415
01416
01417 ast_free((char *)gen_mon_pvt->device_name);
01418 ast_free(gen_mon_pvt);
01419 return;
01420 }
01421
01422 AST_LIST_TRAVERSE_SAFE_BEGIN(&generic_list->list, generic_instance, next) {
01423 if (generic_instance->core_id == gen_mon_pvt->core_id) {
01424 AST_LIST_REMOVE_CURRENT(next);
01425 ast_free(generic_instance);
01426 break;
01427 }
01428 }
01429 AST_LIST_TRAVERSE_SAFE_END;
01430
01431 if (AST_LIST_EMPTY(&generic_list->list)) {
01432
01433
01434
01435 ao2_t_unlink(generic_monitors, generic_list, "Generic list is empty. Unlink it from the container");
01436 } else {
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447 if (generic_list->fit_for_recall
01448 && cc_generic_is_device_available(generic_list->current_state)) {
01449 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
01450 if (!generic_instance->is_suspended && generic_instance->monitoring) {
01451 ast_cc_monitor_callee_available(generic_instance->core_id, "Signaling generic monitor "
01452 "availability due to other instance's failure.");
01453 break;
01454 }
01455 }
01456 }
01457 }
01458 cc_unref(generic_list, "Done with generic list in generic monitor destructor");
01459 ast_free((char *)gen_mon_pvt->device_name);
01460 ast_free(gen_mon_pvt);
01461 }
01462
01463 static void cc_interface_destroy(void *data)
01464 {
01465 struct ast_cc_interface *interface = data;
01466 ast_log_dynamic_level(cc_logger_level, "Destroying cc interface %s\n", interface->device_name);
01467 ast_cc_config_params_destroy(interface->config_params);
01468 }
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486 struct extension_child_dialstring {
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502 char original_dialstring[AST_CHANNEL_NAME];
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521 char device_name[AST_CHANNEL_NAME];
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536 int is_valid;
01537 AST_LIST_ENTRY(extension_child_dialstring) next;
01538 };
01539
01540
01541
01542
01543 struct extension_monitor_pvt {
01544 AST_LIST_HEAD_NOLOCK(, extension_child_dialstring) child_dialstrings;
01545 };
01546
01547 static void cc_extension_monitor_destructor(void *private_data)
01548 {
01549 struct extension_monitor_pvt *extension_pvt = private_data;
01550 struct extension_child_dialstring *child_dialstring;
01551
01552
01553 if (!extension_pvt) {
01554 return;
01555 }
01556
01557 while ((child_dialstring = AST_LIST_REMOVE_HEAD(&extension_pvt->child_dialstrings, next))) {
01558 ast_free(child_dialstring);
01559 }
01560 ast_free(extension_pvt);
01561 }
01562
01563 static void cc_monitor_destroy(void *data)
01564 {
01565 struct ast_cc_monitor *monitor = data;
01566
01567
01568
01569
01570
01571
01572 ast_log_dynamic_level(cc_logger_level, "Core %d: Calling destructor for monitor %s\n",
01573 monitor->core_id, monitor->interface->device_name);
01574 if (monitor->interface->monitor_class == AST_CC_EXTENSION_MONITOR) {
01575 cc_extension_monitor_destructor(monitor->private_data);
01576 }
01577 if (monitor->callbacks) {
01578 monitor->callbacks->destructor(monitor->private_data);
01579 }
01580 cc_unref(monitor->interface, "Unreffing tree's reference to interface");
01581 ast_free(monitor->dialstring);
01582 }
01583
01584 static void cc_interface_tree_destroy(void *data)
01585 {
01586 struct cc_monitor_tree *cc_interface_tree = data;
01587 struct ast_cc_monitor *monitor;
01588 while ((monitor = AST_LIST_REMOVE_HEAD(cc_interface_tree, next))) {
01589 if (monitor->callbacks) {
01590 monitor->callbacks->cancel_available_timer(monitor, &monitor->available_timer_id);
01591 }
01592 cc_unref(monitor, "Destroying all monitors");
01593 }
01594 AST_LIST_HEAD_DESTROY(cc_interface_tree);
01595 }
01596
01597
01598
01599
01600
01601 static int dialed_cc_interface_counter;
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612 struct dialed_cc_interfaces {
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628 unsigned int dial_parent_id;
01629
01630
01631
01632
01633
01634
01635
01636
01637 int core_id;
01638
01639
01640
01641
01642
01643 char ignore;
01644
01645
01646
01647
01648
01649
01650
01651 char is_original_caller;
01652
01653
01654
01655 struct cc_monitor_tree *interface_tree;
01656 };
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670 static void dialed_cc_interfaces_destroy(void *data)
01671 {
01672 struct dialed_cc_interfaces *cc_interfaces = data;
01673 cc_unref(cc_interfaces->interface_tree, "Unref dial's ref to monitor tree");
01674 ast_free(cc_interfaces);
01675 }
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690 static void *dialed_cc_interfaces_duplicate(void *data)
01691 {
01692 struct dialed_cc_interfaces *old_cc_interfaces = data;
01693 struct dialed_cc_interfaces *new_cc_interfaces = ast_calloc(1, sizeof(*new_cc_interfaces));
01694 if (!new_cc_interfaces) {
01695 return NULL;
01696 }
01697 new_cc_interfaces->ignore = old_cc_interfaces->ignore;
01698 new_cc_interfaces->dial_parent_id = old_cc_interfaces->dial_parent_id;
01699 new_cc_interfaces->is_original_caller = 0;
01700 cc_ref(old_cc_interfaces->interface_tree, "New ref due to duplication of monitor tree");
01701 new_cc_interfaces->core_id = old_cc_interfaces->core_id;
01702 new_cc_interfaces->interface_tree = old_cc_interfaces->interface_tree;
01703 return new_cc_interfaces;
01704 }
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 static const struct ast_datastore_info dialed_cc_interfaces_info = {
01716 .type = "Dial CC Interfaces",
01717 .duplicate = dialed_cc_interfaces_duplicate,
01718 .destroy = dialed_cc_interfaces_destroy,
01719 };
01720
01721 static struct extension_monitor_pvt *extension_monitor_pvt_init(void)
01722 {
01723 struct extension_monitor_pvt *ext_pvt = ast_calloc(1, sizeof(*ext_pvt));
01724 if (!ext_pvt) {
01725 return NULL;
01726 }
01727 AST_LIST_HEAD_INIT_NOLOCK(&ext_pvt->child_dialstrings);
01728 return ext_pvt;
01729 }
01730
01731 void ast_cc_extension_monitor_add_dialstring(struct ast_channel *incoming, const char * const dialstring, const char * const device_name)
01732 {
01733 struct ast_datastore *cc_datastore;
01734 struct dialed_cc_interfaces *cc_interfaces;
01735 struct ast_cc_monitor *monitor;
01736 struct extension_monitor_pvt *extension_pvt;
01737 struct extension_child_dialstring *child_dialstring;
01738 struct cc_monitor_tree *interface_tree;
01739 int id;
01740
01741 ast_channel_lock(incoming);
01742 if (!(cc_datastore = ast_channel_datastore_find(incoming, &dialed_cc_interfaces_info, NULL))) {
01743 ast_channel_unlock(incoming);
01744 return;
01745 }
01746
01747 cc_interfaces = cc_datastore->data;
01748 interface_tree = cc_interfaces->interface_tree;
01749 id = cc_interfaces->dial_parent_id;
01750 ast_channel_unlock(incoming);
01751
01752 AST_LIST_LOCK(interface_tree);
01753 AST_LIST_TRAVERSE(interface_tree, monitor, next) {
01754 if (monitor->id == id) {
01755 break;
01756 }
01757 }
01758
01759 if (!monitor) {
01760 AST_LIST_UNLOCK(interface_tree);
01761 return;
01762 }
01763
01764 extension_pvt = monitor->private_data;
01765 if (!(child_dialstring = ast_calloc(1, sizeof(*child_dialstring)))) {
01766 AST_LIST_UNLOCK(interface_tree);
01767 return;
01768 }
01769 ast_copy_string(child_dialstring->original_dialstring, dialstring, sizeof(child_dialstring->original_dialstring));
01770 ast_copy_string(child_dialstring->device_name, device_name, sizeof(child_dialstring->device_name));
01771 child_dialstring->is_valid = 1;
01772 AST_LIST_INSERT_TAIL(&extension_pvt->child_dialstrings, child_dialstring, next);
01773 AST_LIST_UNLOCK(interface_tree);
01774 }
01775
01776 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)
01777 {
01778 struct ast_cc_monitor *monitor_iter;
01779 struct extension_monitor_pvt *extension_pvt;
01780 struct extension_child_dialstring *child_dialstring;
01781
01782 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
01783 if (monitor_iter->id == parent_id) {
01784 break;
01785 }
01786 }
01787
01788 if (!monitor_iter) {
01789 return;
01790 }
01791 extension_pvt = monitor_iter->private_data;
01792
01793 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
01794 if (!strcmp(child_dialstring->device_name, device_name)) {
01795 child_dialstring->is_valid = is_valid;
01796 break;
01797 }
01798 }
01799 }
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815 static struct ast_cc_monitor *cc_extension_monitor_init(const char * const exten, const char * const context, const unsigned int parent_id)
01816 {
01817 struct ast_str *str = ast_str_alloca(2 * AST_MAX_EXTENSION);
01818 struct ast_cc_interface *cc_interface;
01819 struct ast_cc_monitor *monitor;
01820
01821 ast_str_set(&str, 0, "%s@%s", exten, context);
01822
01823 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + ast_str_strlen(str), cc_interface_destroy,
01824 "Allocating new ast_cc_interface"))) {
01825 return NULL;
01826 }
01827
01828 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
01829 cc_unref(cc_interface, "failed to allocate the monitor, so unref the interface");
01830 return NULL;
01831 }
01832
01833 if (!(monitor->private_data = extension_monitor_pvt_init())) {
01834 cc_unref(monitor, "Failed to initialize extension monitor private data. uref monitor");
01835 cc_unref(cc_interface, "Failed to initialize extension monitor private data. unref cc_interface");
01836 }
01837
01838 monitor->id = ast_atomic_fetchadd_int(&dialed_cc_interface_counter, +1);
01839 monitor->parent_id = parent_id;
01840 cc_interface->monitor_type = "extension";
01841 cc_interface->monitor_class = AST_CC_EXTENSION_MONITOR;
01842 strcpy(cc_interface->device_name, ast_str_buffer(str));
01843 monitor->interface = cc_interface;
01844 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);
01845 return monitor;
01846 }
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864 static int cc_interfaces_datastore_init(struct ast_channel *chan) {
01865 struct dialed_cc_interfaces *interfaces;
01866 struct ast_cc_monitor *monitor;
01867 struct ast_datastore *dial_cc_datastore;
01868
01869
01870
01871
01872
01873
01874
01875
01876 if (!ast_cc_request_is_within_limits()) {
01877 return 0;
01878 }
01879
01880 if (!(interfaces = ast_calloc(1, sizeof(*interfaces)))) {
01881 return -1;
01882 }
01883
01884 if (!(monitor = cc_extension_monitor_init(S_OR(chan->macroexten, chan->exten), S_OR(chan->macrocontext, chan->context), 0))) {
01885 ast_free(interfaces);
01886 return -1;
01887 }
01888
01889 if (!(dial_cc_datastore = ast_datastore_alloc(&dialed_cc_interfaces_info, NULL))) {
01890 cc_unref(monitor, "Could not allocate the dialed interfaces datastore. Unreffing monitor");
01891 ast_free(interfaces);
01892 return -1;
01893 }
01894
01895 if (!(interfaces->interface_tree = ao2_t_alloc(sizeof(*interfaces->interface_tree), cc_interface_tree_destroy,
01896 "Allocate monitor tree"))) {
01897 ast_datastore_free(dial_cc_datastore);
01898 cc_unref(monitor, "Could not allocate monitor tree on dialed interfaces datastore. Unreffing monitor");
01899 ast_free(interfaces);
01900 return -1;
01901 }
01902
01903
01904 AST_LIST_HEAD_INIT(interfaces->interface_tree);
01905 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
01906 cc_ref(monitor, "List's reference to extension monitor");
01907 dial_cc_datastore->data = interfaces;
01908 dial_cc_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
01909 interfaces->dial_parent_id = monitor->id;
01910 interfaces->core_id = monitor->core_id = ast_atomic_fetchadd_int(&core_id_counter, +1);
01911 interfaces->is_original_caller = 1;
01912 ast_channel_lock(chan);
01913 ast_channel_datastore_add(chan, dial_cc_datastore);
01914 ast_channel_unlock(chan);
01915 cc_unref(monitor, "Unreffing allocation's reference");
01916 return 0;
01917 }
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942 static void call_destructor_with_no_monitor(const char * const monitor_type, void *private_data)
01943 {
01944 const struct ast_cc_monitor_callbacks *monitor_callbacks = find_monitor_callbacks(monitor_type);
01945
01946 if (!monitor_callbacks) {
01947 return;
01948 }
01949
01950 monitor_callbacks->destructor(private_data);
01951 }
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978 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)
01979 {
01980 struct ast_cc_interface *cc_interface;
01981 struct ast_cc_monitor *monitor;
01982 size_t device_name_len = strlen(device_name);
01983 int parent_id = cc_data->parent_interface_id;
01984
01985 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + device_name_len, cc_interface_destroy,
01986 "Allocating new ast_cc_interface"))) {
01987 return NULL;
01988 }
01989
01990 if (!(cc_interface->config_params = ast_cc_config_params_init())) {
01991 cc_unref(cc_interface, "Failed to allocate config params, unref interface");
01992 return NULL;
01993 }
01994
01995 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
01996 cc_unref(cc_interface, "Failed to allocate monitor, unref interface");
01997 return NULL;
01998 }
01999
02000 if (!(monitor->dialstring = ast_strdup(dialstring))) {
02001 cc_unref(monitor, "Failed to copy dialable name. Unref monitor");
02002 cc_unref(cc_interface, "Failed to copy dialable name");
02003 return NULL;
02004 }
02005
02006 if (!(monitor->callbacks = find_monitor_callbacks(cc_data->monitor_type))) {
02007 cc_unref(monitor, "Failed to find monitor callbacks. Unref monitor");
02008 cc_unref(cc_interface, "Failed to find monitor callbacks");
02009 return NULL;
02010 }
02011
02012 strcpy(cc_interface->device_name, device_name);
02013 monitor->id = ast_atomic_fetchadd_int(&dialed_cc_interface_counter, +1);
02014 monitor->parent_id = parent_id;
02015 monitor->core_id = core_id;
02016 monitor->service_offered = cc_data->service;
02017 monitor->private_data = cc_data->private_data;
02018 cc_interface->monitor_type = cc_data->monitor_type;
02019 cc_interface->monitor_class = AST_CC_DEVICE_MONITOR;
02020 monitor->interface = cc_interface;
02021 monitor->available_timer_id = -1;
02022 ast_cc_copy_config_params(cc_interface->config_params, &cc_data->config_params);
02023 ast_log_dynamic_level(cc_logger_level, "Core %d: Created a device cc interface for '%s' with id %d and parent %d\n",
02024 monitor->core_id, cc_interface->device_name, monitor->id, monitor->parent_id);
02025 return monitor;
02026 }
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044 void ast_handle_cc_control_frame(struct ast_channel *inbound, struct ast_channel *outbound, void *frame_data)
02045 {
02046 char *device_name;
02047 char *dialstring;
02048 struct ast_cc_monitor *monitor;
02049 struct ast_datastore *cc_datastore;
02050 struct dialed_cc_interfaces *cc_interfaces;
02051 struct cc_control_payload *cc_data = frame_data;
02052 struct cc_core_instance *core_instance;
02053
02054 device_name = cc_data->device_name;
02055 dialstring = cc_data->dialstring;
02056
02057 ast_channel_lock(inbound);
02058 if (!(cc_datastore = ast_channel_datastore_find(inbound, &dialed_cc_interfaces_info, NULL))) {
02059 ast_log(LOG_WARNING, "Unable to retrieve CC datastore while processing CC frame from '%s'. CC services will be unavailable.\n", device_name);
02060 ast_channel_unlock(inbound);
02061 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
02062 return;
02063 }
02064
02065 cc_interfaces = cc_datastore->data;
02066
02067 if (cc_interfaces->ignore) {
02068 ast_channel_unlock(inbound);
02069 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
02070 return;
02071 }
02072
02073 if (!cc_interfaces->is_original_caller) {
02074
02075
02076
02077
02078
02079 ast_channel_unlock(inbound);
02080 ast_indicate_data(inbound, AST_CONTROL_CC, cc_data, sizeof(*cc_data));
02081 return;
02082 }
02083
02084 core_instance = find_cc_core_instance(cc_interfaces->core_id);
02085 if (!core_instance) {
02086 core_instance = cc_core_init_instance(inbound, cc_interfaces->interface_tree,
02087 cc_interfaces->core_id, cc_data);
02088 if (!core_instance) {
02089 cc_interfaces->ignore = 1;
02090 ast_channel_unlock(inbound);
02091 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
02092 return;
02093 }
02094 }
02095
02096 ast_channel_unlock(inbound);
02097
02098
02099
02100
02101
02102
02103
02104 AST_LIST_LOCK(cc_interfaces->interface_tree);
02105 AST_LIST_TRAVERSE(cc_interfaces->interface_tree, monitor, next) {
02106 if (!strcmp(monitor->interface->device_name, device_name)) {
02107 ast_log_dynamic_level(cc_logger_level, "Core %d: Device %s sent us multiple CC control frames. Ignoring those beyond the first.\n",
02108 core_instance->core_id, device_name);
02109 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
02110 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
02111 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
02112 return;
02113 }
02114 }
02115 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
02116
02117 if (!(monitor = cc_device_monitor_init(device_name, dialstring, cc_data, core_instance->core_id))) {
02118 ast_log(LOG_WARNING, "Unable to create CC device interface for '%s'. CC services will be unavailable on this interface.\n", device_name);
02119 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
02120 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
02121 return;
02122 }
02123
02124 AST_LIST_LOCK(cc_interfaces->interface_tree);
02125 cc_ref(monitor, "monitor tree's reference to the monitor");
02126 AST_LIST_INSERT_TAIL(cc_interfaces->interface_tree, monitor, next);
02127 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
02128
02129 cc_extension_monitor_change_is_valid(core_instance, monitor->parent_id, monitor->interface->device_name, 0);
02130
02131 manager_event(EVENT_FLAG_CC, "CCAvailable",
02132 "CoreID: %d\r\n"
02133 "Callee: %s\r\n"
02134 "Service: %s\r\n",
02135 cc_interfaces->core_id, device_name, cc_service_to_string(cc_data->service)
02136 );
02137
02138 cc_unref(core_instance, "Done with core_instance after handling CC control frame");
02139 cc_unref(monitor, "Unref reference from allocating monitor");
02140 }
02141
02142 int ast_cc_call_init(struct ast_channel *chan, int *ignore_cc)
02143 {
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164 struct ast_datastore *cc_interfaces_datastore;
02165 struct dialed_cc_interfaces *interfaces;
02166 struct ast_cc_monitor *monitor;
02167 struct ast_cc_config_params *cc_params;
02168
02169 ast_channel_lock(chan);
02170
02171 cc_params = ast_channel_get_cc_config_params(chan);
02172 if (!cc_params) {
02173 ast_channel_unlock(chan);
02174 return -1;
02175 }
02176 if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_NEVER) {
02177
02178
02179 *ignore_cc = 1;
02180 ast_channel_unlock(chan);
02181 ast_log_dynamic_level(cc_logger_level, "Agent policy for %s is 'never'. CC not possible\n", chan->name);
02182 return 0;
02183 }
02184
02185 if (!(cc_interfaces_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
02186
02187 ast_channel_unlock(chan);
02188 return cc_interfaces_datastore_init(chan);
02189 }
02190 interfaces = cc_interfaces_datastore->data;
02191 ast_channel_unlock(chan);
02192
02193 if (interfaces->ignore) {
02194
02195 *ignore_cc = 1;
02196 ast_log_dynamic_level(cc_logger_level, "Datastore is present with ignore flag set. Ignoring CC offers on this call\n");
02197 return 0;
02198 }
02199
02200
02201 if (!(monitor = cc_extension_monitor_init(S_OR(chan->macroexten, chan->exten),
02202 S_OR(chan->macrocontext, chan->context), interfaces->dial_parent_id))) {
02203 return -1;
02204 }
02205 monitor->core_id = interfaces->core_id;
02206 AST_LIST_LOCK(interfaces->interface_tree);
02207 cc_ref(monitor, "monitor tree's reference to the monitor");
02208 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
02209 AST_LIST_UNLOCK(interfaces->interface_tree);
02210 interfaces->dial_parent_id = monitor->id;
02211 cc_unref(monitor, "Unref monitor's allocation reference");
02212 return 0;
02213 }
02214
02215 int ast_cc_request_is_within_limits(void)
02216 {
02217 return cc_request_count < global_cc_max_requests;
02218 }
02219
02220 int ast_cc_get_current_core_id(struct ast_channel *chan)
02221 {
02222 struct ast_datastore *datastore;
02223 struct dialed_cc_interfaces *cc_interfaces;
02224 int core_id_return;
02225
02226 ast_channel_lock(chan);
02227 if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
02228 ast_channel_unlock(chan);
02229 return -1;
02230 }
02231
02232 cc_interfaces = datastore->data;
02233 core_id_return = cc_interfaces->ignore ? -1 : cc_interfaces->core_id;
02234 ast_channel_unlock(chan);
02235 return core_id_return;
02236
02237 }
02238
02239 static long count_agents(const char * const caller, const int core_id_exception)
02240 {
02241 struct count_agents_cb_data data = {.core_id_exception = core_id_exception,};
02242
02243 ao2_t_callback_data(cc_core_instances, OBJ_NODATA, count_agents_cb, (char *)caller, &data, "Counting agents");
02244 ast_log_dynamic_level(cc_logger_level, "Counted %d agents\n", data.count);
02245 return data.count;
02246 }
02247
02248 static void kill_duplicate_offers(char *caller)
02249 {
02250 unsigned long match_flags = MATCH_NO_REQUEST;
02251 struct ao2_iterator *dups_iter;
02252
02253
02254
02255
02256
02257 dups_iter = ao2_t_callback_data(cc_core_instances, OBJ_MULTIPLE | OBJ_UNLINK,
02258 match_agent, caller, &match_flags, "Killing duplicate offers");
02259 if (dups_iter) {
02260
02261 ao2_iterator_destroy(dups_iter);
02262 }
02263 }
02264
02265 static void check_callback_sanity(const struct ast_cc_agent_callbacks *callbacks)
02266 {
02267 ast_assert(callbacks->init != NULL);
02268 ast_assert(callbacks->start_offer_timer != NULL);
02269 ast_assert(callbacks->stop_offer_timer != NULL);
02270 ast_assert(callbacks->respond != NULL);
02271 ast_assert(callbacks->status_request != NULL);
02272 ast_assert(callbacks->start_monitoring != NULL);
02273 ast_assert(callbacks->callee_available != NULL);
02274 ast_assert(callbacks->destructor != NULL);
02275 }
02276
02277 static void agent_destroy(void *data)
02278 {
02279 struct ast_cc_agent *agent = data;
02280
02281 if (agent->callbacks) {
02282 agent->callbacks->destructor(agent);
02283 }
02284 ast_cc_config_params_destroy(agent->cc_params);
02285 }
02286
02287 static struct ast_cc_agent *cc_agent_init(struct ast_channel *caller_chan,
02288 const char * const caller_name, const int core_id,
02289 struct cc_monitor_tree *interface_tree)
02290 {
02291 struct ast_cc_agent *agent;
02292 struct ast_cc_config_params *cc_params;
02293
02294 if (!(agent = ao2_t_alloc(sizeof(*agent) + strlen(caller_name), agent_destroy,
02295 "Allocating new ast_cc_agent"))) {
02296 return NULL;
02297 }
02298
02299 agent->core_id = core_id;
02300 strcpy(agent->device_name, caller_name);
02301
02302 cc_params = ast_channel_get_cc_config_params(caller_chan);
02303 if (!cc_params) {
02304 cc_unref(agent, "Could not get channel config params.");
02305 return NULL;
02306 }
02307 if (!(agent->cc_params = ast_cc_config_params_init())) {
02308 cc_unref(agent, "Could not init agent config params.");
02309 return NULL;
02310 }
02311 ast_cc_copy_config_params(agent->cc_params, cc_params);
02312
02313 if (!(agent->callbacks = find_agent_callbacks(caller_chan))) {
02314 cc_unref(agent, "Could not find agent callbacks.");
02315 return NULL;
02316 }
02317 check_callback_sanity(agent->callbacks);
02318
02319 if (agent->callbacks->init(agent, caller_chan)) {
02320 cc_unref(agent, "Agent init callback failed.");
02321 return NULL;
02322 }
02323 ast_log_dynamic_level(cc_logger_level, "Core %d: Created an agent for caller %s\n",
02324 agent->core_id, agent->device_name);
02325 return agent;
02326 }
02327
02328
02329 static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan);
02330 static int cc_generic_agent_start_offer_timer(struct ast_cc_agent *agent);
02331 static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent);
02332 static void cc_generic_agent_respond(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason);
02333 static int cc_generic_agent_status_request(struct ast_cc_agent *agent);
02334 static int cc_generic_agent_stop_ringing(struct ast_cc_agent *agent);
02335 static int cc_generic_agent_start_monitoring(struct ast_cc_agent *agent);
02336 static int cc_generic_agent_recall(struct ast_cc_agent *agent);
02337 static void cc_generic_agent_destructor(struct ast_cc_agent *agent);
02338
02339 static struct ast_cc_agent_callbacks generic_agent_callbacks = {
02340 .type = "generic",
02341 .init = cc_generic_agent_init,
02342 .start_offer_timer = cc_generic_agent_start_offer_timer,
02343 .stop_offer_timer = cc_generic_agent_stop_offer_timer,
02344 .respond = cc_generic_agent_respond,
02345 .status_request = cc_generic_agent_status_request,
02346 .stop_ringing = cc_generic_agent_stop_ringing,
02347 .start_monitoring = cc_generic_agent_start_monitoring,
02348 .callee_available = cc_generic_agent_recall,
02349 .destructor = cc_generic_agent_destructor,
02350 };
02351
02352 struct cc_generic_agent_pvt {
02353
02354
02355
02356
02357
02358
02359
02360
02361 struct ast_event_sub *sub;
02362
02363
02364
02365 int offer_timer_id;
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375 char cid_num[AST_CHANNEL_NAME];
02376
02377
02378
02379
02380
02381
02382
02383 char cid_name[AST_CHANNEL_NAME];
02384
02385
02386
02387
02388
02389
02390
02391 char exten[AST_CHANNEL_NAME];
02392
02393
02394
02395
02396
02397
02398
02399 char context[AST_CHANNEL_NAME];
02400 };
02401
02402 static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
02403 {
02404 struct cc_generic_agent_pvt *generic_pvt = ast_calloc(1, sizeof(*generic_pvt));
02405
02406 if (!generic_pvt) {
02407 return -1;
02408 }
02409
02410 generic_pvt->offer_timer_id = -1;
02411 if (chan->caller.id.number.valid && chan->caller.id.number.str) {
02412 ast_copy_string(generic_pvt->cid_num, chan->caller.id.number.str, sizeof(generic_pvt->cid_num));
02413 }
02414 if (chan->caller.id.name.valid && chan->caller.id.name.str) {
02415 ast_copy_string(generic_pvt->cid_name, chan->caller.id.name.str, sizeof(generic_pvt->cid_name));
02416 }
02417 ast_copy_string(generic_pvt->exten, S_OR(chan->macroexten, chan->exten), sizeof(generic_pvt->exten));
02418 ast_copy_string(generic_pvt->context, S_OR(chan->macrocontext, chan->context), sizeof(generic_pvt->context));
02419 agent->private_data = generic_pvt;
02420 ast_set_flag(agent, AST_CC_AGENT_SKIP_OFFER);
02421 return 0;
02422 }
02423
02424 static int offer_timer_expire(const void *data)
02425 {
02426 struct ast_cc_agent *agent = (struct ast_cc_agent *) data;
02427 struct cc_generic_agent_pvt *agent_pvt = agent->private_data;
02428 ast_log_dynamic_level(cc_logger_level, "Core %d: Queuing change request because offer timer has expired.\n",
02429 agent->core_id);
02430 agent_pvt->offer_timer_id = -1;
02431 ast_cc_failed(agent->core_id, "Generic agent %s offer timer expired", agent->device_name);
02432 cc_unref(agent, "Remove scheduler's reference to the agent");
02433 return 0;
02434 }
02435
02436 static int cc_generic_agent_start_offer_timer(struct ast_cc_agent *agent)
02437 {
02438 int when;
02439 int sched_id;
02440 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
02441
02442 ast_assert(cc_sched_thread != NULL);
02443 ast_assert(agent->cc_params != NULL);
02444
02445 when = ast_get_cc_offer_timer(agent->cc_params) * 1000;
02446 ast_log_dynamic_level(cc_logger_level, "Core %d: About to schedule offer timer expiration for %d ms\n",
02447 agent->core_id, when);
02448 if ((sched_id = ast_sched_thread_add(cc_sched_thread, when, offer_timer_expire, cc_ref(agent, "Give scheduler an agent ref"))) == -1) {
02449 return -1;
02450 }
02451 generic_pvt->offer_timer_id = sched_id;
02452 return 0;
02453 }
02454
02455 static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent)
02456 {
02457 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
02458
02459 if (generic_pvt->offer_timer_id != -1) {
02460 if (!ast_sched_thread_del(cc_sched_thread, generic_pvt->offer_timer_id)) {
02461 cc_unref(agent, "Remove scheduler's reference to the agent");
02462 }
02463 generic_pvt->offer_timer_id = -1;
02464 }
02465 return 0;
02466 }
02467
02468 static void cc_generic_agent_respond(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
02469 {
02470
02471
02472
02473 return;
02474 }
02475
02476 static int cc_generic_agent_status_request(struct ast_cc_agent *agent)
02477 {
02478 ast_cc_agent_status_response(agent->core_id, ast_device_state(agent->device_name));
02479 return 0;
02480 }
02481
02482 static int cc_generic_agent_stop_ringing(struct ast_cc_agent *agent)
02483 {
02484 struct ast_channel *recall_chan = ast_channel_get_by_name_prefix(agent->device_name, strlen(agent->device_name));
02485
02486 if (!recall_chan) {
02487 return 0;
02488 }
02489
02490 ast_softhangup(recall_chan, AST_SOFTHANGUP_EXPLICIT);
02491 return 0;
02492 }
02493
02494 static int generic_agent_devstate_unsubscribe(void *data)
02495 {
02496 struct ast_cc_agent *agent = data;
02497 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
02498
02499 if (generic_pvt->sub != NULL) {
02500 generic_pvt->sub = ast_event_unsubscribe(generic_pvt->sub);
02501 }
02502 cc_unref(agent, "Done unsubscribing from devstate");
02503 return 0;
02504 }
02505
02506 static void generic_agent_devstate_cb(const struct ast_event *event, void *userdata)
02507 {
02508 struct ast_cc_agent *agent = userdata;
02509 enum ast_device_state new_state;
02510
02511 new_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
02512 if (!cc_generic_is_device_available(new_state)) {
02513
02514 return;
02515 }
02516
02517
02518 if (ast_taskprocessor_push(cc_core_taskprocessor, generic_agent_devstate_unsubscribe,
02519 cc_ref(agent, "ref agent for device state unsubscription"))) {
02520 cc_unref(agent, "Unref agent unsubscribing from devstate failed");
02521 }
02522 ast_cc_agent_caller_available(agent->core_id, "%s is no longer busy", agent->device_name);
02523 }
02524
02525 static int cc_generic_agent_start_monitoring(struct ast_cc_agent *agent)
02526 {
02527 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
02528 struct ast_str *str = ast_str_alloca(128);
02529
02530 ast_assert(generic_pvt->sub == NULL);
02531 ast_str_set(&str, 0, "Agent monitoring %s device state since it is busy\n",
02532 agent->device_name);
02533
02534 if (!(generic_pvt->sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE,
02535 generic_agent_devstate_cb, ast_str_buffer(str), agent,
02536 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, agent->device_name,
02537 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_EXISTS,
02538 AST_EVENT_IE_END))) {
02539 return -1;
02540 }
02541 return 0;
02542 }
02543
02544 static void *generic_recall(void *data)
02545 {
02546 struct ast_cc_agent *agent = data;
02547 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
02548 const char *interface = S_OR(ast_get_cc_agent_dialstring(agent->cc_params), ast_strdupa(agent->device_name));
02549 const char *tech;
02550 char *target;
02551 int reason;
02552 struct ast_channel *chan;
02553 const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params);
02554 unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000;
02555
02556 tech = interface;
02557 if ((target = strchr(interface, '/'))) {
02558 *target++ = '\0';
02559 }
02560 if (!(chan = ast_request_and_dial(tech, AST_FORMAT_SLINEAR, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) {
02561
02562
02563 ast_log_dynamic_level(cc_logger_level, "Core %d: Failed to call back %s for reason %d\n",
02564 agent->core_id, agent->device_name, reason);
02565 ast_cc_failed(agent->core_id, "Failed to call back device %s/%s", tech, target);
02566 return NULL;
02567 }
02568
02569
02570
02571
02572
02573
02574 ast_setup_cc_recall_datastore(chan, agent->core_id);
02575 ast_cc_agent_set_interfaces_chanvar(chan);
02576
02577 ast_copy_string(chan->exten, generic_pvt->exten, sizeof(chan->exten));
02578 ast_copy_string(chan->context, generic_pvt->context, sizeof(chan->context));
02579 chan->priority = 1;
02580
02581 pbx_builtin_setvar_helper(chan, "CC_EXTEN", generic_pvt->exten);
02582 pbx_builtin_setvar_helper(chan, "CC_CONTEXT", generic_pvt->context);
02583
02584 if (!ast_strlen_zero(callback_macro)) {
02585 ast_log_dynamic_level(cc_logger_level, "Core %d: There's a callback macro configured for agent %s\n",
02586 agent->core_id, agent->device_name);
02587 if (ast_app_run_macro(NULL, chan, callback_macro, NULL)) {
02588 ast_cc_failed(agent->core_id, "Callback macro to %s failed. Maybe a hangup?", agent->device_name);
02589 ast_hangup(chan);
02590 return NULL;
02591 }
02592 }
02593 ast_cc_agent_recalling(agent->core_id, "Generic agent %s is recalling", agent->device_name);
02594 ast_pbx_start(chan);
02595 return NULL;
02596 }
02597
02598 static int cc_generic_agent_recall(struct ast_cc_agent *agent)
02599 {
02600 pthread_t clotho;
02601 enum ast_device_state current_state = ast_device_state(agent->device_name);
02602
02603 if (!cc_generic_is_device_available(current_state)) {
02604
02605
02606
02607 ast_cc_agent_caller_busy(agent->core_id, "Generic agent caller %s is busy", agent->device_name);
02608 return 0;
02609 }
02610 ast_pthread_create_detached_background(&clotho, NULL, generic_recall, agent);
02611 return 0;
02612 }
02613
02614 static void cc_generic_agent_destructor(struct ast_cc_agent *agent)
02615 {
02616 struct cc_generic_agent_pvt *agent_pvt = agent->private_data;
02617
02618 if (!agent_pvt) {
02619
02620 return;
02621 }
02622
02623 cc_generic_agent_stop_offer_timer(agent);
02624 if (agent_pvt->sub) {
02625 agent_pvt->sub = ast_event_unsubscribe(agent_pvt->sub);
02626 }
02627
02628 ast_free(agent_pvt);
02629 }
02630
02631 static void cc_core_instance_destructor(void *data)
02632 {
02633 struct cc_core_instance *core_instance = data;
02634 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying core instance\n", core_instance->core_id);
02635 if (core_instance->agent) {
02636 cc_unref(core_instance->agent, "Core instance is done with the agent now");
02637 }
02638 if (core_instance->monitors) {
02639 core_instance->monitors = cc_unref(core_instance->monitors, "Core instance is done with interface list");
02640 }
02641 }
02642
02643 static struct cc_core_instance *cc_core_init_instance(struct ast_channel *caller_chan,
02644 struct cc_monitor_tree *called_tree, const int core_id, struct cc_control_payload *cc_data)
02645 {
02646 char caller[AST_CHANNEL_NAME];
02647 struct cc_core_instance *core_instance;
02648 struct ast_cc_config_params *cc_params;
02649 long agent_count;
02650 int recall_core_id;
02651
02652 ast_channel_get_device_name(caller_chan, caller, sizeof(caller));
02653 cc_params = ast_channel_get_cc_config_params(caller_chan);
02654 if (!cc_params) {
02655 ast_log_dynamic_level(cc_logger_level, "Could not get CC parameters for %s\n",
02656 caller);
02657 return NULL;
02658 }
02659
02660
02661
02662 if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) {
02663 kill_duplicate_offers(caller);
02664 }
02665
02666 ast_cc_is_recall(caller_chan, &recall_core_id, NULL);
02667 agent_count = count_agents(caller, recall_core_id);
02668 if (agent_count >= ast_get_cc_max_agents(cc_params)) {
02669 ast_log_dynamic_level(cc_logger_level, "Caller %s already has the maximum number of agents configured\n", caller);
02670 return NULL;
02671 }
02672
02673
02674 if (agent_count > 0 && ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) {
02675 ast_log_dynamic_level(cc_logger_level, "Generic agents can only have a single outstanding request\n");
02676 return NULL;
02677 }
02678
02679
02680 if (!(core_instance = ao2_t_alloc(sizeof(*core_instance), cc_core_instance_destructor, "Creating core instance for CC"))) {
02681 return NULL;
02682 }
02683
02684 core_instance->core_id = core_id;
02685 if (!(core_instance->agent = cc_agent_init(caller_chan, caller, core_instance->core_id, called_tree))) {
02686 cc_unref(core_instance, "Couldn't allocate agent, unref core_instance");
02687 return NULL;
02688 }
02689
02690 core_instance->monitors = cc_ref(called_tree, "Core instance getting ref to monitor tree");
02691
02692 ao2_t_link(cc_core_instances, core_instance, "Link core instance into container");
02693
02694 return core_instance;
02695 }
02696
02697 struct cc_state_change_args {
02698 struct cc_core_instance *core_instance;
02699 enum cc_state state;
02700 int core_id;
02701 char debug[1];
02702 };
02703
02704 static int is_state_change_valid(enum cc_state current_state, const enum cc_state new_state, struct ast_cc_agent *agent)
02705 {
02706 int is_valid = 0;
02707 switch (new_state) {
02708 case CC_AVAILABLE:
02709 ast_log_dynamic_level(cc_logger_level, "Core %d: Asked to change to state %d? That should never happen.\n",
02710 agent->core_id, new_state);
02711 break;
02712 case CC_CALLER_OFFERED:
02713 if (current_state == CC_AVAILABLE) {
02714 is_valid = 1;
02715 }
02716 break;
02717 case CC_CALLER_REQUESTED:
02718 if (current_state == CC_CALLER_OFFERED ||
02719 (current_state == CC_AVAILABLE && ast_test_flag(agent, AST_CC_AGENT_SKIP_OFFER))) {
02720 is_valid = 1;
02721 }
02722 break;
02723 case CC_ACTIVE:
02724 if (current_state == CC_CALLER_REQUESTED || current_state == CC_CALLER_BUSY) {
02725 is_valid = 1;
02726 }
02727 break;
02728 case CC_CALLEE_READY:
02729 if (current_state == CC_ACTIVE) {
02730 is_valid = 1;
02731 }
02732 break;
02733 case CC_CALLER_BUSY:
02734 if (current_state == CC_CALLEE_READY) {
02735 is_valid = 1;
02736 }
02737 break;
02738 case CC_RECALLING:
02739 if (current_state == CC_CALLEE_READY) {
02740 is_valid = 1;
02741 }
02742 break;
02743 case CC_COMPLETE:
02744 if (current_state == CC_RECALLING) {
02745 is_valid = 1;
02746 }
02747 break;
02748 case CC_FAILED:
02749 is_valid = 1;
02750 break;
02751 default:
02752 ast_log_dynamic_level(cc_logger_level, "Core %d: Asked to change to unknown state %d\n",
02753 agent->core_id, new_state);
02754 break;
02755 }
02756
02757 return is_valid;
02758 }
02759
02760 static int cc_available(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02761 {
02762
02763 ast_log(LOG_WARNING, "Someone requested to change to CC_AVAILABLE? Ignoring.\n");
02764 return -1;
02765 }
02766
02767 static int cc_caller_offered(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02768 {
02769 if (core_instance->agent->callbacks->start_offer_timer(core_instance->agent)) {
02770 ast_cc_failed(core_instance->core_id, "Failed to start the offer timer for %s\n",
02771 core_instance->agent->device_name);
02772 return -1;
02773 }
02774 manager_event(EVENT_FLAG_CC, "CCOfferTimerStart",
02775 "CoreID: %d\r\n"
02776 "Caller: %s\r\n"
02777 "Expires: %u\r\n",
02778 core_instance->core_id, core_instance->agent->device_name, core_instance->agent->cc_params->cc_offer_timer);
02779 ast_log_dynamic_level(cc_logger_level, "Core %d: Started the offer timer for the agent %s!\n",
02780 core_instance->core_id, core_instance->agent->device_name);
02781 return 0;
02782 }
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800 static int has_device_monitors(struct cc_core_instance *core_instance)
02801 {
02802 struct ast_cc_monitor *iter;
02803 int res = 0;
02804
02805 AST_LIST_TRAVERSE(core_instance->monitors, iter, next) {
02806 if (iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
02807 res = 1;
02808 break;
02809 }
02810 }
02811
02812 return res;
02813 }
02814
02815 static void request_cc(struct cc_core_instance *core_instance)
02816 {
02817 struct ast_cc_monitor *monitor_iter;
02818 AST_LIST_LOCK(core_instance->monitors);
02819 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
02820 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
02821 if (monitor_iter->callbacks->request_cc(monitor_iter, &monitor_iter->available_timer_id)) {
02822 AST_LIST_REMOVE_CURRENT(next);
02823 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
02824 monitor_iter->interface->device_name, 1);
02825 cc_unref(monitor_iter, "request_cc failed. Unref list's reference to monitor");
02826 } else {
02827 manager_event(EVENT_FLAG_CC, "CCRequested",
02828 "CoreID: %d\r\n"
02829 "Caller: %s\r\n"
02830 "Callee: %s\r\n",
02831 core_instance->core_id, core_instance->agent->device_name, monitor_iter->interface->device_name);
02832 }
02833 }
02834 }
02835 AST_LIST_TRAVERSE_SAFE_END;
02836
02837 if (!has_device_monitors(core_instance)) {
02838 ast_cc_failed(core_instance->core_id, "All device monitors failed to request CC");
02839 }
02840 AST_LIST_UNLOCK(core_instance->monitors);
02841 }
02842
02843 static int cc_caller_requested(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02844 {
02845 if (!ast_cc_request_is_within_limits()) {
02846 ast_log(LOG_WARNING, "Cannot request CC since there is no more room for requests\n");
02847 core_instance->agent->callbacks->respond(core_instance->agent,
02848 AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY);
02849 ast_cc_failed(core_instance->core_id, "Too many requests in the system");
02850 return -1;
02851 }
02852 core_instance->agent->callbacks->stop_offer_timer(core_instance->agent);
02853 request_cc(core_instance);
02854 return 0;
02855 }
02856
02857 static void unsuspend(struct cc_core_instance *core_instance)
02858 {
02859 struct ast_cc_monitor *monitor_iter;
02860 AST_LIST_LOCK(core_instance->monitors);
02861 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
02862 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
02863 if (monitor_iter->callbacks->unsuspend(monitor_iter)) {
02864 AST_LIST_REMOVE_CURRENT(next);
02865 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
02866 monitor_iter->interface->device_name, 1);
02867 cc_unref(monitor_iter, "unsuspend failed. Unref list's reference to monitor");
02868 }
02869 }
02870 }
02871 AST_LIST_TRAVERSE_SAFE_END;
02872
02873 if (!has_device_monitors(core_instance)) {
02874 ast_cc_failed(core_instance->core_id, "All device monitors failed to unsuspend CC");
02875 }
02876 AST_LIST_UNLOCK(core_instance->monitors);
02877 }
02878
02879 static int cc_active(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02880 {
02881
02882
02883
02884
02885
02886 if (previous_state == CC_CALLER_REQUESTED) {
02887 core_instance->agent->callbacks->respond(core_instance->agent,
02888 AST_CC_AGENT_RESPONSE_SUCCESS);
02889 manager_event(EVENT_FLAG_CC, "CCRequestAcknowledged",
02890 "CoreID: %d\r\n"
02891 "Caller: %s\r\n",
02892 core_instance->core_id, core_instance->agent->device_name);
02893 } else if (previous_state == CC_CALLER_BUSY) {
02894 manager_event(EVENT_FLAG_CC, "CCCallerStopMonitoring",
02895 "CoreID: %d\r\n"
02896 "Caller: %s\r\n",
02897 core_instance->core_id, core_instance->agent->device_name);
02898 unsuspend(core_instance);
02899 }
02900
02901 return 0;
02902 }
02903
02904 static int cc_callee_ready(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02905 {
02906 core_instance->agent->callbacks->callee_available(core_instance->agent);
02907 return 0;
02908 }
02909
02910 static void suspend(struct cc_core_instance *core_instance)
02911 {
02912 struct ast_cc_monitor *monitor_iter;
02913 AST_LIST_LOCK(core_instance->monitors);
02914 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
02915 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
02916 if (monitor_iter->callbacks->suspend(monitor_iter)) {
02917 AST_LIST_REMOVE_CURRENT(next);
02918 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
02919 monitor_iter->interface->device_name, 1);
02920 cc_unref(monitor_iter, "suspend failed. Unref list's reference to monitor");
02921 }
02922 }
02923 }
02924 AST_LIST_TRAVERSE_SAFE_END;
02925
02926 if (!has_device_monitors(core_instance)) {
02927 ast_cc_failed(core_instance->core_id, "All device monitors failed to suspend CC");
02928 }
02929 AST_LIST_UNLOCK(core_instance->monitors);
02930 }
02931
02932 static int cc_caller_busy(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02933 {
02934
02935
02936
02937 suspend(core_instance);
02938 core_instance->agent->callbacks->start_monitoring(core_instance->agent);
02939 manager_event(EVENT_FLAG_CC, "CCCallerStartMonitoring",
02940 "CoreID: %d\r\n"
02941 "Caller: %s\r\n",
02942 core_instance->core_id, core_instance->agent->device_name);
02943 return 0;
02944 }
02945
02946 static void cancel_available_timer(struct cc_core_instance *core_instance)
02947 {
02948 struct ast_cc_monitor *monitor_iter;
02949 AST_LIST_LOCK(core_instance->monitors);
02950 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
02951 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
02952 if (monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id)) {
02953 AST_LIST_REMOVE_CURRENT(next);
02954 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
02955 monitor_iter->interface->device_name, 1);
02956 cc_unref(monitor_iter, "cancel_available_timer failed. Unref list's reference to monitor");
02957 }
02958 }
02959 }
02960 AST_LIST_TRAVERSE_SAFE_END;
02961
02962 if (!has_device_monitors(core_instance)) {
02963 ast_cc_failed(core_instance->core_id, "All device monitors failed to cancel their available timers");
02964 }
02965 AST_LIST_UNLOCK(core_instance->monitors);
02966 }
02967
02968 static int cc_recalling(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02969 {
02970
02971
02972 cancel_available_timer(core_instance);
02973 manager_event(EVENT_FLAG_CC, "CCCallerRecalling",
02974 "CoreID: %d\r\n"
02975 "Caller: %s\r\n",
02976 core_instance->core_id, core_instance->agent->device_name);
02977 return 0;
02978 }
02979
02980 static int cc_complete(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02981 {
02982
02983
02984 manager_event(EVENT_FLAG_CC, "CCRecallComplete",
02985 "CoreID: %d\r\n"
02986 "Caller: %s\r\n",
02987 core_instance->core_id, core_instance->agent->device_name);
02988 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC recall has completed");
02989 return 0;
02990 }
02991
02992 static int cc_failed(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
02993 {
02994 manager_event(EVENT_FLAG_CC, "CCFailure",
02995 "CoreID: %d\r\n"
02996 "Caller: %s\r\n"
02997 "Reason: %s\r\n",
02998 core_instance->core_id, core_instance->agent->device_name, args->debug);
02999 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC failed");
03000 return 0;
03001 }
03002
03003 static int (* const state_change_funcs [])(struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state) = {
03004 [CC_AVAILABLE] = cc_available,
03005 [CC_CALLER_OFFERED] = cc_caller_offered,
03006 [CC_CALLER_REQUESTED] = cc_caller_requested,
03007 [CC_ACTIVE] = cc_active,
03008 [CC_CALLEE_READY] = cc_callee_ready,
03009 [CC_CALLER_BUSY] = cc_caller_busy,
03010 [CC_RECALLING] = cc_recalling,
03011 [CC_COMPLETE] = cc_complete,
03012 [CC_FAILED] = cc_failed,
03013 };
03014
03015 static int cc_do_state_change(void *datap)
03016 {
03017 struct cc_state_change_args *args = datap;
03018 struct cc_core_instance *core_instance;
03019 enum cc_state previous_state;
03020 int res;
03021
03022 ast_log_dynamic_level(cc_logger_level, "Core %d: State change to %d requested. Reason: %s\n",
03023 args->core_id, args->state, args->debug);
03024
03025 core_instance = args->core_instance;
03026
03027 if (!is_state_change_valid(core_instance->current_state, args->state, core_instance->agent)) {
03028 ast_log_dynamic_level(cc_logger_level, "Core %d: Invalid state change requested. Cannot go from %s to %s\n",
03029 args->core_id, cc_state_to_string(core_instance->current_state), cc_state_to_string(args->state));
03030 if (args->state == CC_CALLER_REQUESTED) {
03031
03032
03033
03034
03035 core_instance->agent->callbacks->respond(core_instance->agent,
03036 AST_CC_AGENT_RESPONSE_FAILURE_INVALID);
03037 }
03038 ast_free(args);
03039 cc_unref(core_instance, "Unref core instance from when it was found earlier");
03040 return -1;
03041 }
03042
03043
03044 previous_state = core_instance->current_state;
03045 core_instance->current_state = args->state;
03046 res = state_change_funcs[core_instance->current_state](core_instance, args, previous_state);
03047
03048 ast_free(args);
03049 cc_unref(core_instance, "Unref since state change has completed");
03050 return res;
03051 }
03052
03053 static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
03054 {
03055 int res;
03056 int debuglen;
03057 char dummy[1];
03058 va_list aq;
03059 struct cc_core_instance *core_instance;
03060 struct cc_state_change_args *args;
03061
03062
03063
03064 va_copy(aq, ap);
03065
03066
03067
03068 debuglen = vsnprintf(dummy, sizeof(dummy), debug, aq) + 1;
03069 va_end(aq);
03070
03071 if (!(args = ast_calloc(1, sizeof(*args) + debuglen))) {
03072 return -1;
03073 }
03074
03075 core_instance = find_cc_core_instance(core_id);
03076 if (!core_instance) {
03077 ast_log_dynamic_level(cc_logger_level, "Core %d: Unable to find core instance.\n",
03078 core_id);
03079 ast_free(args);
03080 return -1;
03081 }
03082
03083 args->core_instance = core_instance;
03084 args->state = state;
03085 args->core_id = core_id;
03086 vsnprintf(args->debug, debuglen, debug, ap);
03087
03088 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_do_state_change, args);
03089 if (res) {
03090 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
03091 ast_free(args);
03092 }
03093 return res;
03094 }
03095
03096 struct cc_recall_ds_data {
03097 int core_id;
03098 char ignore;
03099 char nested;
03100 struct cc_monitor_tree *interface_tree;
03101 };
03102
03103 static void *cc_recall_ds_duplicate(void *data)
03104 {
03105 struct cc_recall_ds_data *old_data = data;
03106 struct cc_recall_ds_data *new_data = ast_calloc(1, sizeof(*new_data));
03107
03108 if (!new_data) {
03109 return NULL;
03110 }
03111 new_data->interface_tree = cc_ref(old_data->interface_tree, "Bump refcount of monitor tree for recall datastore duplicate");
03112 new_data->core_id = old_data->core_id;
03113 new_data->nested = 1;
03114 return new_data;
03115 }
03116
03117 static void cc_recall_ds_destroy(void *data)
03118 {
03119 struct cc_recall_ds_data *recall_data = data;
03120 recall_data->interface_tree = cc_unref(recall_data->interface_tree, "Unref recall monitor tree");
03121 ast_free(recall_data);
03122 }
03123
03124 static struct ast_datastore_info recall_ds_info = {
03125 .type = "cc_recall",
03126 .duplicate = cc_recall_ds_duplicate,
03127 .destroy = cc_recall_ds_destroy,
03128 };
03129
03130 int ast_setup_cc_recall_datastore(struct ast_channel *chan, const int core_id)
03131 {
03132 struct ast_datastore *recall_datastore = ast_datastore_alloc(&recall_ds_info, NULL);
03133 struct cc_recall_ds_data *recall_data;
03134 struct cc_core_instance *core_instance;
03135
03136 if (!recall_datastore) {
03137 return -1;
03138 }
03139
03140 if (!(recall_data = ast_calloc(1, sizeof(*recall_data)))) {
03141 ast_datastore_free(recall_datastore);
03142 return -1;
03143 }
03144
03145 if (!(core_instance = find_cc_core_instance(core_id))) {
03146 ast_free(recall_data);
03147 ast_datastore_free(recall_datastore);
03148 return -1;
03149 }
03150
03151 recall_data->interface_tree = cc_ref(core_instance->monitors,
03152 "Bump refcount for monitor tree for recall datastore");
03153 recall_data->core_id = core_id;
03154 recall_datastore->data = recall_data;
03155 recall_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
03156 ast_channel_lock(chan);
03157 ast_channel_datastore_add(chan, recall_datastore);
03158 ast_channel_unlock(chan);
03159 cc_unref(core_instance, "Recall datastore set up. No need for core_instance ref");
03160 return 0;
03161 }
03162
03163 int ast_cc_is_recall(struct ast_channel *chan, int *core_id, const char * const monitor_type)
03164 {
03165 struct ast_datastore *recall_datastore;
03166 struct cc_recall_ds_data *recall_data;
03167 struct cc_monitor_tree *interface_tree;
03168 char device_name[AST_CHANNEL_NAME];
03169 struct ast_cc_monitor *device_monitor;
03170 int core_id_candidate;
03171
03172 ast_assert(core_id != NULL);
03173
03174 *core_id = -1;
03175
03176 ast_channel_lock(chan);
03177 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
03178
03179 ast_channel_unlock(chan);
03180 return 0;
03181 }
03182
03183 recall_data = recall_datastore->data;
03184
03185 if (recall_data->ignore) {
03186
03187
03188
03189
03190 ast_channel_unlock(chan);
03191 return 0;
03192 }
03193
03194 if (!recall_data->nested) {
03195
03196
03197
03198
03199
03200
03201 *core_id = recall_data->core_id;
03202 ast_channel_unlock(chan);
03203 return 1;
03204 }
03205
03206 if (ast_strlen_zero(monitor_type)) {
03207
03208
03209
03210
03211
03212 ast_channel_unlock(chan);
03213 return 0;
03214 }
03215
03216 interface_tree = recall_data->interface_tree;
03217 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
03218
03219
03220
03221
03222
03223 core_id_candidate = recall_data->core_id;
03224 ast_channel_unlock(chan);
03225
03226
03227
03228
03229
03230 AST_LIST_LOCK(interface_tree);
03231 AST_LIST_TRAVERSE(interface_tree, device_monitor, next) {
03232 if (!strcmp(device_monitor->interface->device_name, device_name) &&
03233 !strcmp(device_monitor->interface->monitor_type, monitor_type)) {
03234
03235 *core_id = core_id_candidate;
03236 AST_LIST_UNLOCK(interface_tree);
03237 return 1;
03238 }
03239 }
03240 AST_LIST_UNLOCK(interface_tree);
03241 return 0;
03242 }
03243
03244 struct ast_cc_monitor *ast_cc_get_monitor_by_recall_core_id(const int core_id, const char * const device_name)
03245 {
03246 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
03247 struct ast_cc_monitor *monitor_iter;
03248
03249 if (!core_instance) {
03250 return NULL;
03251 }
03252
03253 AST_LIST_LOCK(core_instance->monitors);
03254 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
03255 if (!strcmp(monitor_iter->interface->device_name, device_name)) {
03256
03257 cc_ref(monitor_iter, "Hand the requester of the monitor a reference");
03258 break;
03259 }
03260 }
03261 AST_LIST_UNLOCK(core_instance->monitors);
03262 cc_unref(core_instance, "Done with core instance ref in ast_cc_get_monitor_by_recall_core_id");
03263 return monitor_iter;
03264 }
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283 static void cc_unique_append(struct ast_str *str, const char *dialstring)
03284 {
03285 char dialstring_search[AST_CHANNEL_NAME];
03286
03287 if (ast_strlen_zero(dialstring)) {
03288
03289 return;
03290 }
03291 snprintf(dialstring_search, sizeof(dialstring_search), "%s%c", dialstring, '&');
03292 if (strstr(ast_str_buffer(str), dialstring_search)) {
03293 return;
03294 }
03295 ast_str_append(&str, 0, "%s", dialstring_search);
03296 }
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313 static void build_cc_interfaces_chanvar(struct ast_cc_monitor *starting_point, struct ast_str *str)
03314 {
03315 struct extension_monitor_pvt *extension_pvt;
03316 struct extension_child_dialstring *child_dialstring;
03317 struct ast_cc_monitor *monitor_iter = starting_point;
03318 int top_level_id = starting_point->id;
03319 size_t length;
03320
03321
03322 ast_str_truncate(str, 0);
03323
03324
03325
03326
03327
03328 extension_pvt = starting_point->private_data;
03329 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
03330 if (child_dialstring->is_valid) {
03331 cc_unique_append(str, child_dialstring->original_dialstring);
03332 }
03333 }
03334
03335
03336 while ((monitor_iter = AST_LIST_NEXT(monitor_iter, next))) {
03337 if (monitor_iter->parent_id == top_level_id) {
03338 cc_unique_append(str, monitor_iter->dialstring);
03339 }
03340 }
03341
03342
03343
03344
03345 length = ast_str_strlen(str);
03346 if (length) {
03347 ast_str_truncate(str, length - 1);
03348 }
03349 if (length <= 1) {
03350
03351 ast_log(LOG_ERROR, "CC_INTERFACES is empty. starting device_name:'%s'\n",
03352 starting_point->interface->device_name);
03353 }
03354 }
03355
03356 int ast_cc_agent_set_interfaces_chanvar(struct ast_channel *chan)
03357 {
03358 struct ast_datastore *recall_datastore;
03359 struct cc_monitor_tree *interface_tree;
03360 struct ast_cc_monitor *monitor;
03361 struct cc_recall_ds_data *recall_data;
03362 struct ast_str *str = ast_str_create(64);
03363 int core_id;
03364
03365 if (!str) {
03366 return -1;
03367 }
03368
03369 ast_channel_lock(chan);
03370 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
03371 ast_channel_unlock(chan);
03372 ast_free(str);
03373 return -1;
03374 }
03375 recall_data = recall_datastore->data;
03376 interface_tree = recall_data->interface_tree;
03377 core_id = recall_data->core_id;
03378 ast_channel_unlock(chan);
03379
03380 AST_LIST_LOCK(interface_tree);
03381 monitor = AST_LIST_FIRST(interface_tree);
03382 build_cc_interfaces_chanvar(monitor, str);
03383 AST_LIST_UNLOCK(interface_tree);
03384
03385 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
03386 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
03387 core_id, ast_str_buffer(str));
03388
03389 ast_free(str);
03390 return 0;
03391 }
03392
03393 int ast_set_cc_interfaces_chanvar(struct ast_channel *chan, const char * const extension)
03394 {
03395 struct ast_datastore *recall_datastore;
03396 struct cc_monitor_tree *interface_tree;
03397 struct ast_cc_monitor *monitor_iter;
03398 struct cc_recall_ds_data *recall_data;
03399 struct ast_str *str = ast_str_create(64);
03400 int core_id;
03401
03402 if (!str) {
03403 return -1;
03404 }
03405
03406 ast_channel_lock(chan);
03407 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
03408 ast_channel_unlock(chan);
03409 ast_free(str);
03410 return -1;
03411 }
03412 recall_data = recall_datastore->data;
03413 interface_tree = recall_data->interface_tree;
03414 core_id = recall_data->core_id;
03415 ast_channel_unlock(chan);
03416
03417 AST_LIST_LOCK(interface_tree);
03418 AST_LIST_TRAVERSE(interface_tree, monitor_iter, next) {
03419 if (!strcmp(monitor_iter->interface->device_name, extension)) {
03420 break;
03421 }
03422 }
03423
03424 if (!monitor_iter) {
03425
03426
03427
03428
03429 AST_LIST_UNLOCK(interface_tree);
03430 ast_free(str);
03431 return -1;
03432 }
03433
03434 build_cc_interfaces_chanvar(monitor_iter, str);
03435 AST_LIST_UNLOCK(interface_tree);
03436
03437 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
03438 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
03439 core_id, ast_str_buffer(str));
03440
03441 ast_free(str);
03442 return 0;
03443 }
03444
03445 void ast_ignore_cc(struct ast_channel *chan)
03446 {
03447 struct ast_datastore *cc_datastore;
03448 struct ast_datastore *cc_recall_datastore;
03449 struct dialed_cc_interfaces *cc_interfaces;
03450 struct cc_recall_ds_data *recall_cc_data;
03451
03452 ast_channel_lock(chan);
03453 if ((cc_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
03454 cc_interfaces = cc_datastore->data;
03455 cc_interfaces->ignore = 1;
03456 }
03457
03458 if ((cc_recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
03459 recall_cc_data = cc_recall_datastore->data;
03460 recall_cc_data->ignore = 1;
03461 }
03462 ast_channel_unlock(chan);
03463 }
03464
03465 static __attribute__((format(printf, 2, 3))) int cc_offer(const int core_id, const char * const debug, ...)
03466 {
03467 va_list ap;
03468 int res;
03469
03470 va_start(ap, debug);
03471 res = cc_request_state_change(CC_CALLER_OFFERED, core_id, debug, ap);
03472 va_end(ap);
03473 return res;
03474 }
03475
03476 int ast_cc_offer(struct ast_channel *caller_chan)
03477 {
03478 int core_id;
03479 int res = -1;
03480 struct ast_datastore *datastore;
03481 struct dialed_cc_interfaces *cc_interfaces;
03482 char cc_is_offerable;
03483
03484 ast_channel_lock(caller_chan);
03485 if (!(datastore = ast_channel_datastore_find(caller_chan, &dialed_cc_interfaces_info, NULL))) {
03486 ast_channel_unlock(caller_chan);
03487 return res;
03488 }
03489
03490 cc_interfaces = datastore->data;
03491 cc_is_offerable = cc_interfaces->is_original_caller;
03492 core_id = cc_interfaces->core_id;
03493 ast_channel_unlock(caller_chan);
03494
03495 if (cc_is_offerable) {
03496 res = cc_offer(core_id, "CC offered to caller %s", caller_chan->name);
03497 }
03498 return res;
03499 }
03500
03501 int ast_cc_agent_accept_request(int core_id, const char * const debug, ...)
03502 {
03503 va_list ap;
03504 int res;
03505
03506 va_start(ap, debug);
03507 res = cc_request_state_change(CC_CALLER_REQUESTED, core_id, debug, ap);
03508 va_end(ap);
03509 return res;
03510 }
03511
03512 int ast_cc_monitor_request_acked(int core_id, const char * const debug, ...)
03513 {
03514 va_list ap;
03515 int res;
03516
03517 va_start(ap, debug);
03518 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
03519 va_end(ap);
03520 return res;
03521 }
03522
03523 int ast_cc_monitor_callee_available(const int core_id, const char * const debug, ...)
03524 {
03525 va_list ap;
03526 int res;
03527
03528 va_start(ap, debug);
03529 res = cc_request_state_change(CC_CALLEE_READY, core_id, debug, ap);
03530 va_end(ap);
03531 return res;
03532 }
03533
03534 int ast_cc_agent_caller_busy(int core_id, const char * debug, ...)
03535 {
03536 va_list ap;
03537 int res;
03538
03539 va_start(ap, debug);
03540 res = cc_request_state_change(CC_CALLER_BUSY, core_id, debug, ap);
03541 va_end(ap);
03542 return res;
03543 }
03544
03545 int ast_cc_agent_caller_available(int core_id, const char * const debug, ...)
03546 {
03547 va_list ap;
03548 int res;
03549
03550 va_start(ap, debug);
03551 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
03552 va_end(ap);
03553 return res;
03554 }
03555
03556 int ast_cc_agent_recalling(int core_id, const char * const debug, ...)
03557 {
03558 va_list ap;
03559 int res;
03560
03561 va_start(ap, debug);
03562 res = cc_request_state_change(CC_RECALLING, core_id, debug, ap);
03563 va_end(ap);
03564 return res;
03565 }
03566
03567 int ast_cc_completed(struct ast_channel *chan, const char * const debug, ...)
03568 {
03569 struct ast_datastore *recall_datastore;
03570 struct cc_recall_ds_data *recall_data;
03571 int core_id;
03572 va_list ap;
03573 int res;
03574
03575 ast_channel_lock(chan);
03576 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
03577
03578 ast_channel_unlock(chan);
03579 return -1;
03580 }
03581 recall_data = recall_datastore->data;
03582 if (recall_data->nested || recall_data->ignore) {
03583
03584
03585
03586
03587
03588
03589
03590
03591
03592
03593 ast_channel_unlock(chan);
03594 return -1;
03595 }
03596 core_id = recall_data->core_id;
03597 ast_channel_unlock(chan);
03598 va_start(ap, debug);
03599 res = cc_request_state_change(CC_COMPLETE, core_id, debug, ap);
03600 va_end(ap);
03601 return res;
03602 }
03603
03604 int ast_cc_failed(int core_id, const char * const debug, ...)
03605 {
03606 va_list ap;
03607 int res;
03608
03609 va_start(ap, debug);
03610 res = cc_request_state_change(CC_FAILED, core_id, debug, ap);
03611 va_end(ap);
03612 return res;
03613 }
03614
03615 struct ast_cc_monitor_failure_data {
03616 const char *device_name;
03617 char *debug;
03618 int core_id;
03619 };
03620
03621 static int cc_monitor_failed(void *data)
03622 {
03623 struct ast_cc_monitor_failure_data *failure_data = data;
03624 struct cc_core_instance *core_instance;
03625 struct ast_cc_monitor *monitor_iter;
03626
03627 core_instance = find_cc_core_instance(failure_data->core_id);
03628 if (!core_instance) {
03629
03630 ast_log_dynamic_level(cc_logger_level,
03631 "Core %d: Could not find core instance for device %s '%s'\n",
03632 failure_data->core_id, failure_data->device_name, failure_data->debug);
03633 ast_free((char *) failure_data->device_name);
03634 ast_free((char *) failure_data->debug);
03635 ast_free(failure_data);
03636 return -1;
03637 }
03638
03639 AST_LIST_LOCK(core_instance->monitors);
03640 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
03641 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
03642 if (!strcmp(monitor_iter->interface->device_name, failure_data->device_name)) {
03643 AST_LIST_REMOVE_CURRENT(next);
03644 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
03645 monitor_iter->interface->device_name, 1);
03646 monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id);
03647 manager_event(EVENT_FLAG_CC, "CCMonitorFailed",
03648 "CoreID: %d\r\n"
03649 "Callee: %s\r\n",
03650 monitor_iter->core_id, monitor_iter->interface->device_name);
03651 cc_unref(monitor_iter, "Monitor reported failure. Unref list's reference.");
03652 }
03653 }
03654 }
03655 AST_LIST_TRAVERSE_SAFE_END;
03656
03657 if (!has_device_monitors(core_instance)) {
03658 ast_cc_failed(core_instance->core_id, "All monitors have failed\n");
03659 }
03660 AST_LIST_UNLOCK(core_instance->monitors);
03661 cc_unref(core_instance, "Finished with core_instance in cc_monitor_failed\n");
03662
03663 ast_free((char *) failure_data->device_name);
03664 ast_free((char *) failure_data->debug);
03665 ast_free(failure_data);
03666 return 0;
03667 }
03668
03669 int ast_cc_monitor_failed(int core_id, const char *const monitor_name, const char * const debug, ...)
03670 {
03671 struct ast_cc_monitor_failure_data *failure_data;
03672 int res;
03673 va_list ap;
03674
03675 if (!(failure_data = ast_calloc(1, sizeof(*failure_data)))) {
03676 return -1;
03677 }
03678
03679 if (!(failure_data->device_name = ast_strdup(monitor_name))) {
03680 ast_free(failure_data);
03681 return -1;
03682 }
03683
03684 va_start(ap, debug);
03685 if (ast_vasprintf(&failure_data->debug, debug, ap) == -1) {
03686 va_end(ap);
03687 ast_free((char *)failure_data->device_name);
03688 ast_free(failure_data);
03689 return -1;
03690 }
03691 va_end(ap);
03692
03693 failure_data->core_id = core_id;
03694
03695 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_monitor_failed, failure_data);
03696 if (res) {
03697 ast_free((char *)failure_data->device_name);
03698 ast_free((char *)failure_data->debug);
03699 ast_free(failure_data);
03700 }
03701 return res;
03702 }
03703
03704 static int cc_status_request(void *data)
03705 {
03706 struct cc_core_instance *core_instance= data;
03707 int res;
03708
03709 res = core_instance->agent->callbacks->status_request(core_instance->agent);
03710 cc_unref(core_instance, "Status request finished. Unref core instance");
03711 return res;
03712 }
03713
03714 int ast_cc_monitor_status_request(int core_id)
03715 {
03716 int res;
03717 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
03718
03719 if (!core_instance) {
03720 return -1;
03721 }
03722
03723 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_request, core_instance);
03724 if (res) {
03725 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
03726 }
03727 return res;
03728 }
03729
03730 static int cc_stop_ringing(void *data)
03731 {
03732 struct cc_core_instance *core_instance = data;
03733 int res = 0;
03734
03735 if (core_instance->agent->callbacks->stop_ringing) {
03736 res = core_instance->agent->callbacks->stop_ringing(core_instance->agent);
03737 }
03738
03739
03740
03741
03742
03743
03744
03745 ast_cc_monitor_request_acked(core_instance->core_id, "Agent %s asked to stop ringing. Be prepared to be recalled again.",
03746 core_instance->agent->device_name);
03747 cc_unref(core_instance, "Stop ringing finished. Unref core_instance");
03748 return res;
03749 }
03750
03751 int ast_cc_monitor_stop_ringing(int core_id)
03752 {
03753 int res;
03754 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
03755
03756 if (!core_instance) {
03757 return -1;
03758 }
03759
03760 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_stop_ringing, core_instance);
03761 if (res) {
03762 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
03763 }
03764 return res;
03765 }
03766
03767 static int cc_party_b_free(void *data)
03768 {
03769 struct cc_core_instance *core_instance = data;
03770 int res = 0;
03771
03772 if (core_instance->agent->callbacks->party_b_free) {
03773 res = core_instance->agent->callbacks->party_b_free(core_instance->agent);
03774 }
03775 cc_unref(core_instance, "Party B free finished. Unref core_instance");
03776 return res;
03777 }
03778
03779 int ast_cc_monitor_party_b_free(int core_id)
03780 {
03781 int res;
03782 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
03783
03784 if (!core_instance) {
03785 return -1;
03786 }
03787
03788 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_party_b_free, core_instance);
03789 if (res) {
03790 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
03791 }
03792 return res;
03793 }
03794
03795 struct cc_status_response_args {
03796 struct cc_core_instance *core_instance;
03797 enum ast_device_state devstate;
03798 };
03799
03800 static int cc_status_response(void *data)
03801 {
03802 struct cc_status_response_args *args = data;
03803 struct cc_core_instance *core_instance = args->core_instance;
03804 struct ast_cc_monitor *monitor_iter;
03805 enum ast_device_state devstate = args->devstate;
03806
03807 ast_free(args);
03808
03809 AST_LIST_LOCK(core_instance->monitors);
03810 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
03811 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR &&
03812 monitor_iter->callbacks->status_response) {
03813 monitor_iter->callbacks->status_response(monitor_iter, devstate);
03814 }
03815 }
03816 AST_LIST_UNLOCK(core_instance->monitors);
03817 cc_unref(core_instance, "Status response finished. Unref core instance");
03818 return 0;
03819 }
03820
03821 int ast_cc_agent_status_response(int core_id, enum ast_device_state devstate)
03822 {
03823 struct cc_status_response_args *args;
03824 struct cc_core_instance *core_instance;
03825 int res;
03826
03827 args = ast_calloc(1, sizeof(*args));
03828 if (!args) {
03829 return -1;
03830 }
03831
03832 core_instance = find_cc_core_instance(core_id);
03833 if (!core_instance) {
03834 ast_free(args);
03835 return -1;
03836 }
03837
03838 args->core_instance = core_instance;
03839 args->devstate = devstate;
03840
03841 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_response, args);
03842 if (res) {
03843 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
03844 ast_free(args);
03845 }
03846 return res;
03847 }
03848
03849 static int cc_build_payload(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
03850 const char *monitor_type, const char * const device_name, const char * dialstring,
03851 enum ast_cc_service_type service, void *private_data, struct cc_control_payload *payload)
03852 {
03853 struct ast_datastore *datastore;
03854 struct dialed_cc_interfaces *cc_interfaces;
03855 int dial_parent_id;
03856
03857 ast_channel_lock(chan);
03858 datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL);
03859 if (!datastore) {
03860 ast_channel_unlock(chan);
03861 return -1;
03862 }
03863 cc_interfaces = datastore->data;
03864 dial_parent_id = cc_interfaces->dial_parent_id;
03865 ast_channel_unlock(chan);
03866
03867 payload->monitor_type = monitor_type;
03868 payload->private_data = private_data;
03869 payload->service = service;
03870 ast_cc_copy_config_params(&payload->config_params, cc_params);
03871 payload->parent_interface_id = dial_parent_id;
03872 ast_copy_string(payload->device_name, device_name, sizeof(payload->device_name));
03873 ast_copy_string(payload->dialstring, dialstring, sizeof(payload->dialstring));
03874 return 0;
03875 }
03876
03877 int ast_queue_cc_frame(struct ast_channel *chan, const char *monitor_type,
03878 const char * const dialstring, enum ast_cc_service_type service, void *private_data)
03879 {
03880 struct ast_frame frame = {0,};
03881 char device_name[AST_CHANNEL_NAME];
03882 int retval;
03883 struct ast_cc_config_params *cc_params;
03884
03885 cc_params = ast_channel_get_cc_config_params(chan);
03886 if (!cc_params) {
03887 return -1;
03888 }
03889 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
03890 if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) {
03891 ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name);
03892 return -1;
03893 }
03894
03895 if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, &frame)) {
03896
03897 return -1;
03898 }
03899 retval = ast_queue_frame(chan, &frame);
03900 ast_frfree(&frame);
03901 return retval;
03902 }
03903
03904 int ast_cc_build_frame(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
03905 const char *monitor_type, const char * const device_name,
03906 const char * const dialstring, enum ast_cc_service_type service, void *private_data,
03907 struct ast_frame *frame)
03908 {
03909 struct cc_control_payload *payload = ast_calloc(1, sizeof(*payload));
03910
03911 if (!payload) {
03912 return -1;
03913 }
03914 if (cc_build_payload(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, payload)) {
03915
03916 ast_free(payload);
03917 return -1;
03918 }
03919 frame->frametype = AST_FRAME_CONTROL;
03920 frame->subclass.integer = AST_CONTROL_CC;
03921 frame->data.ptr = payload;
03922 frame->datalen = sizeof(*payload);
03923 frame->mallocd = AST_MALLOCD_DATA;
03924 return 0;
03925 }
03926
03927 void ast_cc_call_failed(struct ast_channel *incoming, struct ast_channel *outgoing, const char * const dialstring)
03928 {
03929 char device_name[AST_CHANNEL_NAME];
03930 struct cc_control_payload payload;
03931 struct ast_cc_config_params *cc_params;
03932
03933 if (outgoing->hangupcause != AST_CAUSE_BUSY && outgoing->hangupcause != AST_CAUSE_CONGESTION) {
03934
03935
03936
03937 return;
03938 }
03939
03940 cc_params = ast_channel_get_cc_config_params(outgoing);
03941 if (!cc_params) {
03942 return;
03943 }
03944 if (ast_get_cc_monitor_policy(cc_params) != AST_CC_MONITOR_GENERIC) {
03945
03946
03947
03948 return;
03949 }
03950
03951 ast_channel_get_device_name(outgoing, device_name, sizeof(device_name));
03952 if (cc_build_payload(outgoing, cc_params, AST_CC_GENERIC_MONITOR_TYPE, device_name,
03953 dialstring, AST_CC_CCBS, NULL, &payload)) {
03954
03955 return;
03956 }
03957 ast_handle_cc_control_frame(incoming, outgoing, &payload);
03958 }
03959
03960 void ast_cc_busy_interface(struct ast_channel *inbound, struct ast_cc_config_params *cc_params,
03961 const char *monitor_type, const char * const device_name, const char * const dialstring, void *private_data)
03962 {
03963 struct cc_control_payload payload;
03964 if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialstring, AST_CC_CCBS, private_data, &payload)) {
03965
03966 call_destructor_with_no_monitor(monitor_type, private_data);
03967 return;
03968 }
03969 ast_handle_cc_control_frame(inbound, NULL, &payload);
03970 }
03971
03972 int ast_cc_callback(struct ast_channel *inbound, const char * const tech, const char * const dest, ast_cc_callback_fn callback)
03973 {
03974 const struct ast_channel_tech *chantech = ast_get_channel_tech(tech);
03975
03976 if (chantech && chantech->cc_callback) {
03977 chantech->cc_callback(inbound, dest, callback);
03978 }
03979
03980 return 0;
03981 }
03982
03983 static const char *ccreq_app = "CallCompletionRequest";
03984
03985 static int ccreq_exec(struct ast_channel *chan, const char *data)
03986 {
03987 struct cc_core_instance *core_instance;
03988 char device_name[AST_CHANNEL_NAME];
03989 unsigned long match_flags;
03990 int res;
03991
03992 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
03993
03994 match_flags = MATCH_NO_REQUEST;
03995 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionRequest"))) {
03996 ast_log_dynamic_level(cc_logger_level, "Couldn't find a core instance for caller %s\n", device_name);
03997 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
03998 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NO_CORE_INSTANCE");
03999 return 0;
04000 }
04001
04002 ast_log_dynamic_level(cc_logger_level, "Core %d: Found core_instance for caller %s\n",
04003 core_instance->core_id, device_name);
04004
04005 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
04006 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest is only for generic agent types.\n",
04007 core_instance->core_id);
04008 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
04009 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NOT_GENERIC");
04010 cc_unref(core_instance, "Unref core_instance since CallCompletionRequest was called with native agent");
04011 return 0;
04012 }
04013
04014 if (!ast_cc_request_is_within_limits()) {
04015 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest failed. Too many requests in the system\n",
04016 core_instance->core_id);
04017 ast_cc_failed(core_instance->core_id, "Too many CC requests\n");
04018 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
04019 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "TOO_MANY_REQUESTS");
04020 cc_unref(core_instance, "Unref core_instance since too many CC requests");
04021 return 0;
04022 }
04023
04024 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);
04025 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", res ? "FAIL" : "SUCCESS");
04026 if (res) {
04027 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "UNSPECIFIED");
04028 }
04029
04030 cc_unref(core_instance, "Done with CallCompletionRequest");
04031 return 0;
04032 }
04033
04034 static const char *cccancel_app = "CallCompletionCancel";
04035
04036 static int cccancel_exec(struct ast_channel *chan, const char *data)
04037 {
04038 struct cc_core_instance *core_instance;
04039 char device_name[AST_CHANNEL_NAME];
04040 unsigned long match_flags;
04041 int res;
04042
04043 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
04044
04045 match_flags = MATCH_REQUEST;
04046 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionCancel"))) {
04047 ast_log_dynamic_level(cc_logger_level, "Cannot find CC transaction to cancel for caller %s\n", device_name);
04048 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
04049 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NO_CORE_INSTANCE");
04050 return 0;
04051 }
04052
04053 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
04054 ast_log(LOG_WARNING, "CallCompletionCancel may only be used for calles with a generic agent\n");
04055 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
04056 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
04057 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NOT_GENERIC");
04058 return 0;
04059 }
04060 res = ast_cc_failed(core_instance->core_id, "Call completion request Cancelled for core ID %d by caller %s",
04061 core_instance->core_id, device_name);
04062 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
04063 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", res ? "FAIL" : "SUCCESS");
04064 if (res) {
04065 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "UNSPECIFIED");
04066 }
04067 return 0;
04068 }
04069
04070 struct count_monitors_cb_data {
04071 const char *device_name;
04072 const char *monitor_type;
04073 int count;
04074 };
04075
04076 static int count_monitors_cb(void *obj, void *arg, int flags)
04077 {
04078 struct cc_core_instance *core_instance = obj;
04079 struct count_monitors_cb_data *cb_data = arg;
04080 const char *device_name = cb_data->device_name;
04081 const char *monitor_type = cb_data->monitor_type;
04082 struct ast_cc_monitor *monitor_iter;
04083
04084 AST_LIST_LOCK(core_instance->monitors);
04085 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
04086 if (!strcmp(monitor_iter->interface->device_name, device_name) &&
04087 !strcmp(monitor_iter->interface->monitor_type, monitor_type)) {
04088 cb_data->count++;
04089 break;
04090 }
04091 }
04092 AST_LIST_UNLOCK(core_instance->monitors);
04093 return 0;
04094 }
04095
04096 int ast_cc_monitor_count(const char * const name, const char * const type)
04097 {
04098 struct count_monitors_cb_data data = {.device_name = name, .monitor_type = type,};
04099
04100 ao2_t_callback(cc_core_instances, OBJ_NODATA, count_monitors_cb, &data, "Counting agents");
04101 ast_log_dynamic_level(cc_logger_level, "Counted %d monitors\n", data.count);
04102 return data.count;
04103 }
04104
04105 static void initialize_cc_max_requests(void)
04106 {
04107 struct ast_config *cc_config;
04108 const char *cc_max_requests_str;
04109 struct ast_flags config_flags = {0,};
04110 char *endptr;
04111
04112 cc_config = ast_config_load2("ccss.conf", "ccss", config_flags);
04113 if (!cc_config || cc_config == CONFIG_STATUS_FILEINVALID) {
04114 ast_log(LOG_WARNING, "Could not find valid ccss.conf file. Using cc_max_requests default\n");
04115 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT;
04116 return;
04117 }
04118
04119 if (!(cc_max_requests_str = ast_variable_retrieve(cc_config, "general", "cc_max_requests"))) {
04120 ast_config_destroy(cc_config);
04121 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT;
04122 return;
04123 }
04124
04125 global_cc_max_requests = strtol(cc_max_requests_str, &endptr, 10);
04126
04127 if (!ast_strlen_zero(endptr)) {
04128 ast_log(LOG_WARNING, "Invalid input given for cc_max_requests. Using default\n");
04129 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT;
04130 }
04131
04132 ast_config_destroy(cc_config);
04133 return;
04134 }
04135
04136 static void cc_cli_print_monitor_stats(struct ast_cc_monitor *monitor, int fd, int parent_id)
04137 {
04138 struct ast_cc_monitor *child_monitor_iter = monitor;
04139 if (!monitor) {
04140 return;
04141 }
04142
04143 ast_cli(fd, "\t\t|-->%s", monitor->interface->device_name);
04144 if (monitor->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
04145 ast_cli(fd, "(%s)", cc_service_to_string(monitor->service_offered));
04146 }
04147 ast_cli(fd, "\n");
04148
04149 while ((child_monitor_iter = AST_LIST_NEXT(child_monitor_iter, next))) {
04150 if (child_monitor_iter->parent_id == monitor->id) {
04151 cc_cli_print_monitor_stats(child_monitor_iter, fd, child_monitor_iter->id);
04152 }
04153 }
04154 }
04155
04156 static int print_stats_cb(void *obj, void *arg, int flags)
04157 {
04158 int *cli_fd = arg;
04159 struct cc_core_instance *core_instance = obj;
04160
04161 ast_cli(*cli_fd, "%d\t\t%s\t\t%s\n", core_instance->core_id, core_instance->agent->device_name,
04162 cc_state_to_string(core_instance->current_state));
04163 AST_LIST_LOCK(core_instance->monitors);
04164 cc_cli_print_monitor_stats(AST_LIST_FIRST(core_instance->monitors), *cli_fd, 0);
04165 AST_LIST_UNLOCK(core_instance->monitors);
04166 return 0;
04167 }
04168
04169 static int cc_cli_output_status(void *data)
04170 {
04171 int *cli_fd = data;
04172 int count = ao2_container_count(cc_core_instances);
04173
04174 if (!count) {
04175 ast_cli(*cli_fd, "There are currently no active call completion transactions\n");
04176 } else {
04177 ast_cli(*cli_fd, "%d Call completion transactions\n", count);
04178 ast_cli(*cli_fd, "Core ID\t\tCaller\t\t\t\tStatus\n");
04179 ast_cli(*cli_fd, "----------------------------------------------------------------------------\n");
04180 ao2_t_callback(cc_core_instances, OBJ_NODATA, print_stats_cb, cli_fd, "Printing stats to CLI");
04181 }
04182 ast_free(cli_fd);
04183 return 0;
04184 }
04185
04186 static char *handle_cc_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04187 {
04188 int *cli_fd;
04189
04190 switch (cmd) {
04191 case CLI_INIT:
04192 e->command = "cc report status";
04193 e->usage =
04194 "Usage: cc report status\n"
04195 " Report the current status of any ongoing CC transactions\n";
04196 return NULL;
04197 case CLI_GENERATE:
04198 return NULL;
04199 }
04200
04201 if (a->argc != 3) {
04202 return CLI_SHOWUSAGE;
04203 }
04204
04205 cli_fd = ast_malloc(sizeof(*cli_fd));
04206 if (!cli_fd) {
04207 return CLI_FAILURE;
04208 }
04209
04210 *cli_fd = a->fd;
04211
04212 if (ast_taskprocessor_push(cc_core_taskprocessor, cc_cli_output_status, cli_fd)) {
04213 ast_free(cli_fd);
04214 return CLI_FAILURE;
04215 }
04216 return CLI_SUCCESS;
04217 }
04218
04219 static int kill_cores(void *obj, void *arg, int flags)
04220 {
04221 int *core_id = arg;
04222 struct cc_core_instance *core_instance = obj;
04223
04224 if (!core_id || (core_instance->core_id == *core_id)) {
04225 ast_cc_failed(core_instance->core_id, "CC transaction canceled administratively\n");
04226 }
04227 return 0;
04228 }
04229
04230 static char *complete_core_id(const char *line, const char *word, int pos, int state)
04231 {
04232 int which = 0;
04233 int wordlen = strlen(word);
04234 char *ret = NULL;
04235 struct ao2_iterator core_iter = ao2_iterator_init(cc_core_instances, 0);
04236 struct cc_core_instance *core_instance;
04237
04238 for (; (core_instance = ao2_t_iterator_next(&core_iter, "Next core instance"));
04239 cc_unref(core_instance, "CLI tab completion iteration")) {
04240 char core_id_str[20];
04241 snprintf(core_id_str, sizeof(core_id_str), "%d", core_instance->core_id);
04242 if (!strncmp(word, core_id_str, wordlen) && ++which > state) {
04243 ret = ast_strdup(core_id_str);
04244 cc_unref(core_instance, "Found a matching core ID for CLI tab-completion");
04245 break;
04246 }
04247 }
04248 ao2_iterator_destroy(&core_iter);
04249
04250 return ret;
04251 }
04252
04253 static char *handle_cc_kill(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04254 {
04255 static const char * const option[] = { "core", "all", NULL };
04256
04257 switch (cmd) {
04258 case CLI_INIT:
04259 e->command = "cc cancel";
04260 e->usage =
04261 "Usage: cc cancel can be used in two ways.\n"
04262 " 1. 'cc cancel core [core ID]' will cancel the CC transaction with\n"
04263 " core ID equal to the specified core ID.\n"
04264 " 2. 'cc cancel all' will cancel all active CC transactions.\n";
04265 return NULL;
04266 case CLI_GENERATE:
04267 if (a->pos == 2) {
04268 return ast_cli_complete(a->word, option, a->n);
04269 }
04270 if (a->pos == 3) {
04271 return complete_core_id(a->line, a->word, a->pos, a->n);
04272 }
04273 return NULL;
04274 }
04275
04276 if (a->argc == 4) {
04277 int core_id;
04278 char *endptr;
04279 if (strcasecmp(a->argv[2], "core")) {
04280 return CLI_SHOWUSAGE;
04281 }
04282 core_id = strtol(a->argv[3], &endptr, 10);
04283 if ((errno != 0 && core_id == 0) || (endptr == a->argv[3])) {
04284 return CLI_SHOWUSAGE;
04285 }
04286 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, &core_id, "CLI Killing Core Id");
04287 } else if (a->argc == 3) {
04288 if (strcasecmp(a->argv[2], "all")) {
04289 return CLI_SHOWUSAGE;
04290 }
04291 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, NULL, "CLI Killing all CC cores");
04292 } else {
04293 return CLI_SHOWUSAGE;
04294 }
04295
04296 return CLI_SUCCESS;
04297 }
04298
04299 static struct ast_cli_entry cc_cli[] = {
04300 AST_CLI_DEFINE(handle_cc_status, "Reports CC stats"),
04301 AST_CLI_DEFINE(handle_cc_kill, "Kill a CC transaction"),
04302 };
04303
04304 int ast_cc_init(void)
04305 {
04306 int res;
04307
04308 if (!(cc_core_instances = ao2_t_container_alloc(CC_CORE_INSTANCES_BUCKETS,
04309 cc_core_instance_hash_fn, cc_core_instance_cmp_fn,
04310 "Create core instance container"))) {
04311 return -1;
04312 }
04313 if (!(generic_monitors = ao2_t_container_alloc(CC_CORE_INSTANCES_BUCKETS,
04314 generic_monitor_hash_fn, generic_monitor_cmp_fn,
04315 "Create generic monitor container"))) {
04316 return -1;
04317 }
04318 if (!(cc_core_taskprocessor = ast_taskprocessor_get("CCSS core", TPS_REF_DEFAULT))) {
04319 return -1;
04320 }
04321 if (!(cc_sched_thread = ast_sched_thread_create())) {
04322 return -1;
04323 }
04324 res = ast_register_application2(ccreq_app, ccreq_exec, NULL, NULL, NULL);
04325 res |= ast_register_application2(cccancel_app, cccancel_exec, NULL, NULL, NULL);
04326 res |= ast_cc_monitor_register(&generic_monitor_cbs);
04327 res |= ast_cc_agent_register(&generic_agent_callbacks);
04328 ast_cli_register_multiple(cc_cli, ARRAY_LEN(cc_cli));
04329 cc_logger_level = ast_logger_register_level(CC_LOGGER_LEVEL_NAME);
04330 dialed_cc_interface_counter = 1;
04331 initialize_cc_max_requests();
04332 return res;
04333 }