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