34 #include "asterisk/_private.h"
39 #include <sys/signal.h>
40 #include <netinet/in.h>
383 #define DEFAULT_PARK_TIME 45000
384 #define DEFAULT_PARK_EXTENSION "700"
385 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
386 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 1000
387 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
388 #define DEFAULT_ATXFER_DROP_CALL 0
389 #define DEFAULT_ATXFER_LOOP_DELAY 10000
390 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
392 #define AST_MAX_WATCHERS 256
393 #define MAX_DIAL_FEATURE_OPTIONS 30
428 unsigned int exclusive:1;
454 struct parking_dp_ramp_map access_extens;
456 struct parking_dp_space_map spaces;
472 struct timeval start;
481 unsigned int notquiteyet:1;
482 unsigned int options_specified:1;
546 unsigned int parkfindnext:1;
548 unsigned int parkext_exclusive:1;
550 unsigned int parkaddhints:1;
552 unsigned int is_invalid:1;
566 unsigned int the_mark:1;
568 unsigned int disabled:1;
656 #if defined(ATXFER_NULL_TECH)
665 static void set_kill_chan_tech(
struct ast_channel *chan)
702 #if defined(ATXFER_NULL_TECH)
711 static void set_new_chan_name(
struct ast_channel *chan)
713 static int seq_num_last;
722 len = snprintf(dummy,
sizeof(dummy),
"%s<XFER_%x>", chan->
name, seq_num) + 1;
724 snprintf(chan_name, len,
"%s<XFER_%x>", chan->
name, seq_num);
735 if (!(df_copy =
ast_calloc(1,
sizeof(*df)))) {
739 memcpy(df_copy, df,
sizeof(*df));
753 .
type =
"dial-features",
787 dialfeatures =
ast_calloc(1,
sizeof(*dialfeatures));
796 datastore->
data = dialfeatures;
827 const char *app_at_exten;
829 ast_debug(4,
"Checking if %s@%s is a parking exten\n", exten_str, context);
837 if (!app_at_exten || strcasecmp(
parkcall, app_at_exten)) {
859 unsigned int return_to_pbx:1;
900 char *goto_on_transfer;
912 ast_debug(1,
"Attempting GOTO_ON_BLINDXFR=%s for %s.\n", val, chan->
name);
930 for (x = goto_on_transfer; *x; ++x) {
948 const char *caller_name,
struct ast_channel *requestor,
950 int timeout,
int *outstate,
const char *
language);
953 .
type =
"Channel appdata datastore",
967 dst_app_data =
ast_malloc(strlen(src_app_data) + 1);
973 chan->
data = strcpy(dst_app_data, src_app_data);
974 datastore->
data = dst_app_data;
1040 pthread_attr_t attr;
1041 struct sched_param sched;
1043 pthread_attr_init(&attr);
1044 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1050 pthread_attr_destroy(&attr);
1051 memset(&sched, 0,
sizeof(sched));
1052 pthread_setschedparam(thread, SCHED_RR, &sched);
1068 char *
message[5] = {NULL, NULL, NULL, NULL, NULL};
1070 snprintf(tmp,
sizeof(tmp),
"Parked on %s", parkingexten);
1098 ast_debug(4,
"Notification of state change to metermaids %s@%s\n to state '%s'",
1112 exten =
strsep(&context,
"@");
1116 ast_debug(4,
"Checking state of exten %s in context %s\n", exten, context);
1167 const char *dyn_context;
1168 const char *dyn_exten;
1169 const char *dyn_range;
1170 const char *template_name;
1185 if (!template_parkinglot) {
1186 ast_debug(1,
"PARKINGDYNAMIC lot %s does not exist.\n",
1189 ast_debug(1,
"PARKINGDYNAMIC lot %s has invalid config.\n",
1192 template_parkinglot = NULL;
1195 if (!template_parkinglot) {
1197 ast_debug(1,
"Using default parking lot for template\n");
1214 if (sscanf(dyn_range,
"%30d-%30d", &dyn_start, &dyn_end) != 2) {
1216 "Format for parking positions is a-b, where a and b are numbers\n");
1217 }
else if (dyn_end < dyn_start || dyn_start <= 0 || dyn_end <= 0) {
1219 "Format for parking positions is a-b, where a <= b\n");
1237 "Parking lot '%s' conflicts with template parking lot '%s'!\n"
1238 "Change either PARKINGDYNCONTEXT or PARKINGDYNEXTEN.\n",
1239 parkinglot->
name, template_parkinglot->
name);
1248 "Parking lot '%s' parking spaces overlap template parking lot '%s'!\n"
1249 "Change PARKINGDYNPOS.\n",
1250 parkinglot->
name, template_parkinglot->
name);
1301 struct parkeduser *pu;
1303 int parking_space = -1;
1304 const char *parkinglotname;
1306 struct parkeduser *cur;
1311 parkinglotname = parkinglot->
name;
1322 ast_debug(4,
"This could be an indication channel driver needs updating, using default lot.\n");
1364 if (sscanf(parkingexten,
"%30d", &parking_space) != 1 || parking_space <= 0) {
1393 parking_space, parkinglot->
name);
1403 int start_checked = 0;
1420 for (i = start; ; i++) {
1428 if (start_checked) {
1447 if (parking_space == -1) {
1472 struct parkeduser *pu = args->
pu;
1473 const char *event_from;
1483 chan->
appl =
"Parked Call";
1518 if (!strcasecmp(peer->
tech->
type,
"Local")) {
1524 if ((c = strrchr(other_side,
';'))) {
1577 ast_verb(2,
"Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n",
1586 "Parkinglot: %s\r\n"
1589 "CallerIDNum: %s\r\n"
1590 "CallerIDName: %s\r\n"
1591 "ConnectedLineNum: %s\r\n"
1592 "ConnectedLineName: %s\r\n"
1602 ast_debug(4,
"peer->name: %s\n", peer ? peer->
name :
"-No peer-");
1606 ast_debug(4,
"AMI ParkedCall From: %s\n", event_from);
1613 snprintf(app_data,
sizeof(app_data),
"%s,%s", pu->
parkingexten,
1659 const char *app_data;
1667 if (!park_exten || !park_context) {
1675 if (parker && parker != park_me) {
1695 if (parker && parker != park_me) {
1736 if (peer == rchan) {
1751 if (peer == rchan) {
1771 if (peer == rchan) {
1793 if (peer == rchan) {
1807 const char *app_data;
1818 if (!park_exten || !park_context) {
1826 if (parker && parker != park_me) {
1846 if (parker && parker != park_me) {
1894 const char *app_data;
1895 const char *pl_name;
2008 set_peers(&parker, &parkee, peer, chan, sense);
2100 char *caller_chan_id = NULL, *callee_chan_id = NULL, *
args = NULL, *touch_filename = NULL;
2104 const char *automon_message_start = NULL;
2105 const char *automon_message_stop = NULL;
2106 const char *touch_format = NULL;
2107 const char *touch_monitor = NULL;
2108 const char *touch_monitor_prefix = NULL;
2111 ast_log(
LOG_ERROR,
"Cannot record the call. The monitor application is disabled.\n");
2117 ast_log(
LOG_ERROR,
"Cannot record the call. The monitor application is disabled.\n");
2121 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
2135 "UserEvent: StopRec\r\n"
2138 ast_verb(4,
"User hit '%s' to stop recording call.\n", code);
2156 if (!touch_monitor_prefix)
2159 if (touch_monitor) {
2160 len = strlen(touch_monitor) + 50;
2163 snprintf(touch_filename, len,
"%s-%ld-%s",
S_OR(touch_monitor_prefix,
"auto"), (
long)time(NULL), touch_monitor);
2164 snprintf(args, len,
"%s,%s,m",
S_OR(touch_format,
"wav"), touch_filename);
2170 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
2173 snprintf(touch_filename, len,
"%s-%ld-%s-%s",
S_OR(touch_monitor_prefix,
"auto"), (
long)time(NULL), caller_chan_id, callee_chan_id);
2174 snprintf(args, len,
"%s,%s,m",
S_OR(touch_format,
"wav"), touch_filename);
2177 for(x = 0; x < strlen(args); x++) {
2183 "UserEvent: Rec\r\n"
2186 caller_chan->
uniqueid, touch_filename);
2187 ast_verb(4,
"User hit '%s' to record call. filename: %s\n", code, args);
2202 char *caller_chan_id = NULL, *callee_chan_id = NULL, *
args = NULL, *touch_filename = NULL;
2207 const char *touch_format;
2208 const char *touch_monitor;
2212 ast_log(
LOG_ERROR,
"Cannot record the call. The mixmonitor application is disabled.\n");
2218 ast_log(
LOG_ERROR,
"Cannot record the call. The mixmonitor application is disabled.\n");
2222 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
2243 ast_verb(3,
"User hit '%s' to stop recording call.\n", code);
2251 ast_log(
LOG_ERROR,
"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
2256 ast_log(
LOG_ERROR,
"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
2276 if (touch_monitor) {
2277 len = strlen(touch_monitor) + 50;
2280 snprintf(touch_filename, len,
"auto-%ld-%s", (
long)time(NULL), touch_monitor);
2281 snprintf(args, len,
"%s.%s,b", touch_filename, (touch_format) ? touch_format :
"wav");
2287 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
2290 snprintf(touch_filename, len,
"auto-%ld-%s-%s", (
long)time(NULL), caller_chan_id, callee_chan_id);
2291 snprintf(args, len,
"%s.%s,b", touch_filename,
S_OR(touch_format,
"wav"));
2294 for( x = 0; x < strlen(args); x++) {
2299 ast_verb(3,
"User hit '%s' to record call. filename: %s\n", code, touch_filename);
2309 ast_verb(4,
"User hit '%s' to disconnect call.\n", code);
2355 const char *transferer_real_context;
2356 char xferto[256] =
"";
2359 ast_debug(1,
"Executing Blind Transfer %s, %s (sense=%d) \n", chan->
name, peer->
name, sense);
2360 set_peers(&transferer, &transferee, peer, chan, sense);
2361 transferer_real_context =
real_ctx(transferer, transferee);
2374 xferto[0] = (char) res;
2385 xferto, transferer_real_context);
2402 ast_verb(3,
"Blind transferring %s to '%s' (context %s) priority 1\n",
2403 transferee->
name, xferto, transferer_real_context);
2409 if (!transferer->
cdr) {
2411 if (transferer->
cdr) {
2417 if (transferer->
cdr) {
2421 "transferer=%s; transferee=%s; lastapp=%s; lastdata=%s; chan=%s; dstchan=%s\n",
2425 ast_debug(1,
"TRANSFEREE; lastapp=%s; lastdata=%s, chan=%s; dstchan=%s\n",
2428 ast_debug(1,
"transferer_real_context=%s; xferto=%s\n",
2429 transferer_real_context, xferto);
2431 transferer->
cdr = transferee->
cdr;
2432 transferee->
cdr = swap;
2434 if (!transferee->
pbx) {
2436 ast_debug(1,
"About to ast_async_goto %s.\n", transferee->
name);
2437 if (
ast_async_goto(transferee, transferer_real_context, xferto, 1)) {
2445 ast_debug(1,
"About to explicit goto %s, it has a PBX.\n", transferee->
name);
2447 set_c_e_p(transferee, transferer_real_context, xferto, 0);
2469 ast_log(
LOG_WARNING,
"Had to drop call because I couldn't make %s compatible with %s\n",
2526 const char *chan1_attended_sound;
2527 const char *chan2_attended_sound;
2528 const char *transferer_real_context;
2529 char xferto[256] =
"";
2540 char *transferer_tech;
2541 char *transferer_name;
2542 char *transferer_name_orig;
2545 ast_debug(1,
"Executing Attended Transfer %s, %s (sense=%d) \n", chan->
name, peer->
name, sense);
2546 set_peers(&transferer, &transferee, peer, chan, sense);
2547 transferer_real_context =
real_ctx(transferer, transferee);
2560 xferto[0] = (char) res;
2573 xferto, transferer_real_context);
2596 snprintf(xferto + l,
sizeof(xferto) - l,
"@%s/n", transferer_real_context);
2611 transferer_name =
ast_strdupa(transferer_name_orig);
2612 transferer_tech =
strsep(&transferer_name,
"/");
2613 dash = strrchr(transferer_name,
'-');
2636 ast_debug(2,
"Dial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate);
2639 int hangup_dont = 0;
2642 ast_debug(1,
"Actually doing an attended transfer.\n");
2733 ast_debug(1,
"Actually doing a blonde transfer.\n");
2737 unsigned int tries = 0;
2741 "Transferer channel name: '%s' cannot be used for callback.\n",
2742 transferer_name_orig);
2751 ast_debug(1,
"We're trying to callback %s/%s\n",
2752 transferer_tech, transferer_name);
2754 transferee, transferee, transferer_tech,
2757 ast_debug(2,
"Dial party B result: newchan:%d, outstate:%d\n",
2758 !!newchan, outstate);
2768 if (features_datastore && (dialfeatures = features_datastore->
data)) {
2795 ast_debug(1,
"Sleeping for %u ms before retrying atxfer.\n",
2805 ast_debug(1,
"We're retrying to call %s/%s\n",
"Local", xferto);
2807 transferer, transferee,
"Local",
2810 ast_debug(2,
"Redial party C result: newchan:%d, outstate:%d\n",
2811 !!newchan, outstate);
2850 xferchan =
ast_channel_alloc(0,
AST_STATE_DOWN, 0, 0,
"",
"",
"", transferee->
linkedid, 0,
"Transfered/%s", transferee->
name);
2871 dash = strrchr(xferto,
'@');
2893 tobj->
chan = newchan;
2894 tobj->
peer = xferchan;
2899 if (features_datastore && (dialfeatures = features_datastore->
data)) {
2907 if (features_datastore && (dialfeatures = features_datastore->
data)) {
2977 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
3017 struct feature_group *fg;
3070 ast_verb(2,
"Registered feature '%s' for group '%s' at exten '%s'\n",
3105 if (!strcasecmp(tmp->
sname, name)) {
3116 struct feature_group *fg;
3140 struct feature_group *fg = NULL;
3143 if (!strcasecmp(fg->
gname, name))
3164 if (!strcasecmp(name, builtin_features[x].
sname))
3165 return &builtin_features[x];
3229 if (!strcasecmp(
"Gosub", feature->
app)) {
3231 }
else if (!strcasecmp(
"Macro", feature->
app)) {
3254 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
3264 if (strcasecmp(builtin_features[x].sname, name))
3267 ast_copy_string(builtin_features[x].exten, value,
sizeof(builtin_features[x].exten));
3291 struct feature_group *fg = NULL;
3296 int feature_detected = 0;
3307 if (!strcmp(builtin_features[x].exten, code)) {
3308 ast_debug(3,
"Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].
fname, builtin_features[x].
sname, builtin_features[x].exten);
3312 res = builtin_features[x].
operation(chan, peer, config, code, sense, NULL);
3315 memcpy(feature, &builtin_features[x],
sizeof(*feature));
3317 feature_detected = 1;
3319 }
else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
3332 tmp = dynamic_features_buf;
3334 while ((tok =
strsep(&tmp,
"#"))) {
3341 if (!strcmp(fge->
exten, code)) {
3346 memcpy(feature, fge->
feature,
sizeof(*feature));
3353 }
else if (!strncmp(fge->
exten, code, strlen(code))) {
3372 if (!strcmp(tmpfeature->
exten, code)) {
3373 ast_verb(3,
" Feature Found: %s exten: %s\n",tmpfeature->
sname, tok);
3377 res = tmpfeature->
operation(chan, peer, config, code, sense, tmpfeature);
3380 memcpy(feature, tmpfeature,
sizeof(*feature));
3387 }
else if (!strncmp(tmpfeature->
exten, code, strlen(code)))
3405 char dynamic_features_buf[128];
3406 const char *peer_dynamic_features, *chan_dynamic_features;
3426 snprintf(dynamic_features_buf,
sizeof(dynamic_features_buf),
"%s%s%s",
S_OR(chan_dynamic_features,
""), chan_dynamic_features && peer_dynamic_features ?
"#" :
"",
S_OR(peer_dynamic_features,
""));
3428 ast_debug(3,
"Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%u, dynamic=%s\n", chan->
name, peer->
name, code, sense, features.
flags, dynamic_features_buf);
3441 char *chan_dynamic_features;
3471 if (dynamic_features) {
3477 while ((tok =
strsep(&tmp,
"#"))) {
3478 struct feature_group *fg;
3545 const char *caller_name,
struct ast_channel *requestor,
3547 int timeout,
int *outstate,
const char *
language)
3553 int transferee_hungup;
3559 struct timeval started;
3561 char *disconnect_code = NULL, *dialed_code = NULL;
3567 if (!(chan =
ast_request(type, format, requestor, data, &cause))) {
3591 if (
ast_call(chan, data, timeout)) {
3610 if (strcasecmp(builtin_features[x].sname,
"disconnect"))
3613 disconnect_code = builtin_features[x].
exten;
3614 len = strlen(disconnect_code) + 1;
3616 memset(dialed_code, 0, len);
3627 transferee_hungup = 0;
3631 monitor_chans[num_chans++] = transferee;
3632 monitor_chans[num_chans++] = chan;
3633 if (!caller_hungup) {
3637 #if defined(ATXFER_NULL_TECH)
3639 set_new_chan_name(caller);
3645 set_kill_chan_tech(caller);
3649 monitor_chans[num_chans++] = caller;
3660 active_channel =
ast_waitfor_n(monitor_chans, num_chans, &to);
3661 if (!active_channel)
3665 if (transferee == active_channel) {
3670 transferee_hungup = 1;
3683 }
else if (chan == active_channel) {
3721 ast_verb(3,
"%s dialed incomplete extension %s; ignoring\n", chan->
name, chan->
exten);
3735 if (caller_hungup) {
3755 if (!caller_hungup) {
3772 }
else if (caller == active_channel) {
3777 dialed_code[x] =
'\0';
3778 if (strlen(dialed_code) == len) {
3780 }
else if (x && strncmp(dialed_code, disconnect_code, x)) {
3782 dialed_code[x] =
'\0';
3784 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
3808 if (!transferee_hungup) {
3835 ast_log(
LOG_NOTICE,
"CHAN: name: %s; appl: %s; data: %s; contxt: %s; exten: %s; pri: %d;\n",
3836 chan->name, chan->appl, chan->data, chan->context, chan->exten, chan->priority);
3837 ast_log(
LOG_NOTICE,
"CHAN: acctcode: %s; dialcontext: %s; amaflags: %x; maccontxt: %s; macexten: %s; macpri: %d;\n",
3838 chan->accountcode, chan->dialcontext, (
unsigned)chan->amaflags, chan->macrocontext, chan->macroexten, chan->macropriority);
3839 ast_log(
LOG_NOTICE,
"CHAN: masq: %p; masqr: %p; _bridge: %p; uniqueID: %s; linkedID:%s\n",
3840 chan->masq, chan->masqr,
3841 chan->_bridge, chan->uniqueid, chan->linkedid);
3844 chan->masqr->name, chan->masqr->cdr);
3856 struct ast_cdr *cdr_orig = cdr;
3873 for (feature = features; *
feature; feature++) {
3918 ast_log(
LOG_DEBUG,
"Removing dialed interfaces datastore on %s since we're bridging\n", chan->
name);
3944 ast_log(
LOG_DTMF,
"DTMF end '%c' simulated on %s due to %s, duration %ld ms\n",
3945 digit, chan->
name, why, duration);
3975 int sendingdtmfdigit = 0;
3976 int we_disabled_peer_cdr = 0;
3978 struct ast_cdr *bridge_cdr = NULL;
3981 struct ast_cdr *new_chan_cdr = NULL;
3982 struct ast_cdr *new_peer_cdr = NULL;
3984 const char *h_context;
4004 const char *monitor_exec;
4051 we_disabled_peer_cdr = 1;
4065 chan_cdr->
next = NULL;
4097 ast_debug(4,
"bridge answer set, chan answer set\n");
4186 ast_debug(1,
"Timed out for feature!\n");
4189 memset(peer_featurecode, 0,
sizeof(peer_featurecode));
4193 memset(chan_featurecode, 0,
sizeof(chan_featurecode));
4202 hadfeatures = hasfeatures;
4237 other = (who == chan) ? peer : chan;
4269 switch (ntohs(aoh->option)) {
4288 featurelen = strlen(chan_featurecode);
4291 featurelen = strlen(peer_featurecode);
4300 ast_log(
LOG_DEBUG,
"Passing DTMF through, since it is not a feature code\n");
4303 sendingdtmfdigit = 1;
4312 ast_log(
LOG_DEBUG,
"Not passing DTMF through, since it may be a feature code\n");
4319 hadfeatures = hasfeatures;
4323 featurecode = chan_featurecode;
4326 featurecode = peer_featurecode;
4329 if (sendingdtmfdigit == 1) {
4333 sendingdtmfdigit = 0;
4354 memset(featurecode, 0,
sizeof(chan_featurecode));
4363 if (hadfeatures && !hasfeatures) {
4366 }
else if (hasfeatures) {
4441 struct ast_cdr *swapper = NULL;
4448 int spawn_error = 0;
4466 swapper = chan->
cdr;
4469 chan->
cdr = bridge_cdr;
4474 if (h_context != chan->
context) {
4487 if (found && spawn_error) {
4499 if (chan->
cdr == bridge_cdr) {
4500 chan->
cdr = swapper;
4522 if (new_chan_cdr && bridge_cdr && !h_context) {
4565 if (strcasecmp(orig_channame, chan->
name) != 0) {
4571 for (cur = chan_ptr->
cdr; cur; cur = cur->
next) {
4572 if (cur == chan_cdr) {
4595 if (strcasecmp(orig_peername, peer->
name) != 0) {
4601 for (cur = chan_ptr->
cdr; cur; cur = cur->
next) {
4602 if (cur == peer_cdr) {
4618 if (we_disabled_peer_cdr) {
4634 "Parkinglot: %s\r\n"
4635 "CallerIDNum: %s\r\n"
4636 "CallerIDName: %s\r\n"
4637 "ConnectedLineNum: %s\r\n"
4638 "ConnectedLineName: %s\r\n"
4655 OPT_CALLEE_REDIRECT =
't',
4656 OPT_CALLER_REDIRECT =
'T',
4657 OPT_CALLEE_AUTOMON =
'w',
4658 OPT_CALLER_AUTOMON =
'W',
4659 OPT_CALLEE_DISCONNECT =
'h',
4660 OPT_CALLER_DISCONNECT =
'H',
4661 OPT_CALLEE_PARKCALL =
'k',
4662 OPT_CALLER_PARKCALL =
'K',
4665 memset(options, 0, len);
4667 options[i++] = OPT_CALLER_REDIRECT;
4670 options[i++] = OPT_CALLER_AUTOMON;
4673 options[i++] = OPT_CALLER_DISCONNECT;
4676 options[i++] = OPT_CALLER_PARKCALL;
4680 options[i++] = OPT_CALLEE_REDIRECT;
4683 options[i++] = OPT_CALLEE_AUTOMON;
4686 options[i++] = OPT_CALLEE_DISCONNECT;
4689 options[i++] = OPT_CALLEE_PARKCALL;
4703 static int manage_parked_call(
struct parkeduser *pu,
const struct pollfd *pfds,
int nfds,
struct pollfd **new_pfds,
int *new_nfds,
int *ms)
4731 char *peername_flat;
4735 dash = strrchr(peername,
'-');
4741 for (i = 0; peername_flat[i]; i++) {
4742 if (peername_flat[i] ==
'/') {
4743 peername_flat[i] =
'_';
4749 "Parking dial context '%s' does not exist and unable to create\n",
4756 if (!strncmp(peername,
"Parked/", 7)) {
4766 if (features_datastore && (dialfeatures = features_datastore->
data)) {
4769 snprintf(returnexten,
sizeof(returnexten),
"%s,30,%s", peername,
4775 snprintf(returnexten,
sizeof(returnexten),
"%s,30,t", peername);
4780 int parkdialprio = 1;
4781 char parkciddata[512];
4782 char parkalertinfodata[512];
4785 snprintf(parkciddata,
sizeof(parkciddata),
"CALLERID(name)=%s",
parkingretcidname);
4790 snprintf(parkalertinfodata,
sizeof(parkalertinfodata),
"Alert-Info: %s",
parkingretalertinfo);
4797 "Could not create parking return dial exten: %s@%s\n",
4812 snprintf(parkingslot,
sizeof(parkingslot),
"%d", pu->
parkingnum);
4814 set_c_e_p(chan,
"parkedcallstimeout", peername_flat, 1);
4827 ast_verb(2,
"Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n",
4834 "Unable to restart the PBX for user on '%s', hanging them up...\n",
4849 if (chan->
fds[x] == -1) {
4853 for (y = 0; y < nfds; y++) {
4854 if (pfds[y].fd == chan->
fds[x]) {
4864 if (!(pfds[y].revents & (POLLIN | POLLERR | POLLPRI))) {
4869 if (pfds[y].revents & POLLPRI) {
4889 ast_verb(2,
"%s got tired of being parked\n", chan->
name);
4901 "MOH on parked call stopped by outside source. Restarting on channel %s.\n",
4916 if (chan->
fds[x] > -1) {
4918 (*new_nfds + 1) *
sizeof(
struct pollfd));
4924 (*new_pfds)[*new_nfds].fd = chan->
fds[x];
4925 (*new_pfds)[*new_nfds].events = POLLIN | POLLERR | POLLPRI;
4926 (*new_pfds)[*new_nfds].revents = 0;
4931 if (tms < *ms || *ms < 0) {
4942 struct parkeduser *pu;
4957 "Whoa, failed to remove the parking extension %s@%s!\n",
4964 "Whoa, parking lot '%s' context '%s' does not exist.\n",
4986 struct pollfd *pfds = NULL, *new_pfds = NULL;
4987 int nfds = 0, new_nfds = 0;
5010 pthread_testcancel();
5048 ast_debug(1,
"Building parking lot %s\n", name);
5051 copylot->
cfg = parkinglot->
cfg;
5070 const char *pl_name;
5131 strcpy(chan->
exten,
"s");
5177 struct parkeduser *pu;
5180 const char *pl_name;
5181 unsigned int park = 0;
5194 if (sscanf(app_args.pl_space,
"%30u", &park) != 1) {
5202 pl_name = app_args.pl_name;
5218 "pbx-invalidpark", chan->
name);
5221 "Channel %s tried to retrieve parked call from unknown parking lot '%s'\n",
5222 chan->
name, pl_name);
5255 "Parkinglot: %s\r\n"
5257 "CallerIDNum: %s\r\n"
5258 "CallerIDName: %s\r\n"
5259 "ConnectedLineNum: %s\r\n"
5260 "ConnectedLineName: %s\r\n"
5332 static const char msg[] =
"courtesy tone";
5364 ast_verb(3,
"Channel %s connected to parked call %u\n", chan->
name, park);
5373 if (features_datastore && (dialfeatures = features_datastore->
data)) {
5416 ast_verb(3,
"Channel %s tried to retrieve nonexistent parked call %u\n",
5430 ast_debug(3,
"Multiparking: %s refcount now %d\n", parkinglot->
name,
5439 refcount =
ao2_ref(parkinglot, +1);
5440 ast_debug(3,
"Multiparking: %s refcount now %d\n", parkinglot->
name, refcount + 1);
5490 for (numext = start; numext <=
stop; numext++) {
5491 snprintf(exten,
sizeof(exten),
"%d", numext);
5492 snprintf(device,
sizeof(device),
"park:%s@%s", exten, context);
5501 .parking_con =
"parkedcalls",
5502 .parking_start = 701,
5503 .parking_stop = 750,
5526 if (!strcasecmp(var->
value,
"both")) {
5528 }
else if (!strcasecmp(var->
value,
"caller")) {
5530 }
else if (!strcasecmp(var->
value,
"callee")) {
5551 if (!strcasecmp(var->
name,
"context")) {
5553 }
else if (!strcasecmp(var->
name,
"parkext")) {
5555 }
else if (!strcasecmp(var->
name,
"parkext_exclusive")) {
5557 }
else if (!strcasecmp(var->
name,
"parkinghints")) {
5559 }
else if (!strcasecmp(var->
name,
"parkedmusicclass")) {
5561 }
else if (!strcasecmp(var->
name,
"parkingtime")) {
5562 int parkingtime = 0;
5564 if ((sscanf(var->
value,
"%30d", &parkingtime) != 1) || parkingtime < 1) {
5570 }
else if (!strcasecmp(var->
name,
"parkpos")) {
5574 if (sscanf(var->
value,
"%30d-%30d", &start, &end) != 2) {
5576 "Format for parking positions is a-b, where a and b are numbers at line %d of %s\n",
5579 }
else if (end < start || start <= 0 || end <= 0) {
5587 }
else if (!strcasecmp(var->
name,
"findslot")) {
5589 }
else if (!strcasecmp(var->
name,
"parkedcalltransfers")) {
5591 }
else if (!strcasecmp(var->
name,
"parkedcallreparking")) {
5593 }
else if (!strcasecmp(var->
name,
"parkedcallhangup")) {
5595 }
else if (!strcasecmp(var->
name,
"parkedcallrecording")) {
5597 }
else if (!strcasecmp(var->
name,
"parkingretcidname")) {
5599 }
else if (!strcasecmp(var->
name,
"parkingretdahdiring")) {
5601 }
else if (!strcasecmp(var->
name,
"parkingretalertinfo")) {
5648 snprintf(app_data,
sizeof(app_data),
",,,,,%s", parkinglot->
name);
5656 ast_log(
LOG_ERROR,
"Parking context '%s' does not exist and unable to create\n",
5685 return disabled ? -1 : 0;
5695 int oldparkinglot = 0;
5711 new_cfg = *cfg_defaults;
5713 ast_debug(1,
"Building parking lot %s\n", parkinglot->
name);
5719 if (oldparkinglot) {
5726 && memcmp(&new_cfg, &parkinglot->
cfg,
sizeof(parkinglot->
cfg))) {
5729 "Parking lot %s has parked calls. Parking lot changes discarded.\n",
5734 parkinglot->
cfg = new_cfg;
5738 parkinglot->
cfg = new_cfg;
5752 if (!oldparkinglot) {
5771 char *activateon, *new_syn;
5790 "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
5795 if ((new_syn = strchr(
args.app,
'('))) {
5798 args.app_args = new_syn;
5799 *
args.app_args++ =
'\0';
5800 if (
args.app_args[strlen(
args.app_args) - 1] ==
')') {
5801 args.app_args[strlen(
args.app_args) - 1] =
'\0';
5814 if (!(feature =
ast_calloc(1,
sizeof(*feature)))) {
5822 if (
args.app_args) {
5826 if (
args.moh_class) {
5835 if (!strcasecmp(activateon,
"self") || !strcasecmp(activateon,
"caller")) {
5837 }
else if (!strcasecmp(activateon,
"peer") || !strcasecmp(activateon,
"callee")) {
5841 " must be 'self', or 'peer'\n", var->
name);
5848 }
else if (!strcasecmp(
args.activatedby,
"caller")) {
5850 }
else if (!strcasecmp(
args.activatedby,
"callee")) {
5852 }
else if (!strcasecmp(
args.activatedby,
"both")) {
5856 " must be 'caller', or 'callee', or 'both'\n", var->
name);
5863 ast_verb(2,
"Mapping Feature '%s' to app '%s(%s)' with code '%s'\n",
5871 struct feature_group *fg = NULL;
5873 static const char *
const categories[] = {
5886 strcpy(pickup_ext,
"*8");
5908 for (;
var; var = var->
next) {
5909 if (!strcasecmp(var->
name,
"parkeddynamic")) {
5911 }
else if (!strcasecmp(var->
name,
"adsipark")) {
5913 }
else if (!strcasecmp(var->
name,
"transferdigittimeout")) {
5920 }
else if (!strcasecmp(var->
name,
"featuredigittimeout")) {
5925 }
else if (!strcasecmp(var->
name,
"atxfernoanswertimeout")) {
5932 }
else if (!strcasecmp(var->
name,
"atxferloopdelay")) {
5939 }
else if (!strcasecmp(var->
name,
"atxferdropcall")) {
5941 }
else if (!strcasecmp(var->
name,
"atxfercallbackretries")) {
5946 }
else if (!strcasecmp(var->
name,
"courtesytone")) {
5948 }
else if (!strcasecmp(var->
name,
"parkedplay")) {
5949 if (!strcasecmp(var->
value,
"both")) {
5951 }
else if (!strcasecmp(var->
value,
"parked")) {
5956 }
else if (!strcasecmp(var->
name,
"xfersound")) {
5958 }
else if (!strcasecmp(var->
name,
"xferfailsound")) {
5960 }
else if (!strcasecmp(var->
name,
"pickupexten")) {
5962 }
else if (!strcasecmp(var->
name,
"pickupsound")) {
5964 }
else if (!strcasecmp(var->
name,
"pickupfailsound")) {
5966 }
else if (!strcasecmp(var->
name,
"comebacktoorigin")) {
5990 if (!strncasecmp(ctg,
"parkinglot_", strlen(
"parkinglot_"))) {
5991 ast_debug(2,
"Found configuration section %s, assume parking context\n", ctg);
5993 ast_log(
LOG_ERROR,
"Could not build parking lot %s. Configuration error.\n", ctg);
5995 ast_debug(1,
"Configured parking context %s\n", ctg);
6001 for (i = 0; i <
ARRAY_LEN(categories); i++) {
6002 if (!strcasecmp(categories[i], ctg)) {
6045 struct parking_dp_ramp *ramp;
6046 struct parking_dp_spaces *spaces;
6070 struct parking_dp_context *item;
6089 struct parking_dp_ramp *ramp_node;
6091 ramp_node =
ast_calloc(1,
sizeof(*ramp_node) + strlen(exten));
6096 strcpy(ramp_node->
exten, exten);
6115 struct parking_dp_ramp *cur_ramp;
6116 struct parking_dp_ramp *new_ramp;
6125 cmp = strcmp(exten, cur_ramp->
exten);
6132 if (complain && (cur_ramp->
exclusive || exclusive)) {
6134 "Parking lot '%s' parkext %s@%s used by another parking lot.\n",
6170 struct parking_dp_spaces *spaces_node;
6172 spaces_node =
ast_calloc(1,
sizeof(*spaces_node));
6196 struct parking_dp_spaces *cur_node;
6197 struct parking_dp_spaces *expand_node;
6198 struct parking_dp_spaces *new_node;
6205 if (expand_node->
stop + 1 < cur_node->
start) {
6211 && ((cur_node->
start <= start && start <= cur_node->stop)
6212 || (cur_node->
start <= stop && stop <= cur_node->stop)
6213 || (start < cur_node->start && cur_node->
stop < stop))) {
6217 "Parking lot '%s' parkpos %d-%d@%s overlaps another parking lot.\n",
6222 if (expand_node->
stop < cur_node->
stop) {
6223 expand_node->
stop = cur_node->
stop;
6230 if (cur_node->
stop + 1 < start) {
6234 if (stop + 1 < cur_node->
start) {
6245 && ((cur_node->
start <= start && start <= cur_node->stop)
6246 || (cur_node->
start <= stop && stop <= cur_node->stop)
6247 || (start < cur_node->start && cur_node->
stop < stop))) {
6251 "Parking lot '%s' parkpos %d-%d@%s overlaps another parking lot.\n",
6256 if (start < cur_node->start) {
6260 if (stop <= cur_node->stop) {
6265 expand_node = cur_node;
6326 struct parking_dp_context *ctx_node;
6353 struct parking_dp_context *cur_ctx;
6354 struct parking_dp_context *new_ctx;
6433 ast_debug(1,
"Removing unneeded parking lot exten: %s@%s priority:%d\n",
6434 context, exten, priority);
6453 static void remove_dead_ramp_usage(
const char *context,
struct parking_dp_ramp_map *old_ramps,
struct parking_dp_ramp_map *new_ramps)
6455 struct parking_dp_ramp *old_ramp;
6456 struct parking_dp_ramp *new_ramp;
6467 cmp = strcmp(old_ramp->
exten, new_ramp->
exten);
6484 for (; old_ramp; old_ramp =
AST_LIST_NEXT(old_ramp, node)) {
6503 snprintf(exten,
sizeof(exten),
"%d", space);
6524 struct parking_dp_space_map *old_spaces,
struct parking_dp_space_map *new_spaces,
6527 struct parking_dp_spaces *old_range;
6528 struct parking_dp_spaces *new_range;
6537 if (space < old_range->start) {
6538 space = old_range->
start;
6541 if (space < new_range->start) {
6543 if (old_range->
stop < new_range->
start) {
6545 stop = old_range->
stop;
6549 stop = new_range->
start - 1;
6551 }
else if ( space <= new_range->stop) {
6553 if (old_range->
stop <= new_range->
stop) {
6558 space = new_range->
stop + 1;
6569 stop = old_range->
stop;
6574 for (; space <=
stop; ++space) {
6619 struct parking_dp_context *old_ctx;
6620 struct parking_dp_context *new_ctx;
6680 "Parking lot %s has parked calls. Could not remove.\n",
6709 ast_debug(1,
"Parking lot %s now open for business. (parkpos %d-%d)\n",
6732 ast_log(
LOG_ERROR,
"Configuration of default default parking lot failed.\n");
6735 ast_debug(1,
"Configuration of default default parking lot done.\n");
6741 ast_debug(1,
"features.conf did not change.\n");
6760 "callback to mark all parking lots");
6764 "callback to remove marked parking lots");
6785 "callback to activate all parking lots");
6805 #define HFS_FORMAT "%-25s %-7s %-7s\n"
6812 "Usage: features show\n"
6813 " Lists configured features\n";
6847 struct feature_group *fg;
6862 ast_cli(a->
fd,
"\nCall parking (Parking lot: %s)\n", curlot->
name);
6866 ast_cli(a->
fd,
"%-22s: %d-%d\n",
"Parked call extensions",
6909 e->
command =
"features reload";
6911 "Usage: features reload\n"
6912 " Reloads configured call features from features.conf\n";
6980 struct ast_channel *chana = NULL, *chanb = NULL, *chans[2];
6981 struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
6994 snprintf(buf,
sizeof(buf),
"Channel1 does not exists: %s", channela);
7005 NULL, NULL, chana->
linkedid, 0,
"Bridge/%s", chana->
name))) {
7012 snprintf(buf,
sizeof(buf),
"Unable to masquerade channel %s!", channela);
7024 snprintf(buf,
sizeof(buf),
"Channel2 does not exists: %s", channelb);
7036 NULL, NULL, chanb->linkedid, 0,
"Bridge/%s", chanb->name))) {
7044 snprintf(buf,
sizeof(buf),
"Unable to masquerade channel %s!", channelb);
7056 ast_log(
LOG_WARNING,
"Could not make channels %s and %s compatible for manager bridge\n", tmpchana->
name, tmpchanb->name);
7057 astman_send_error(s, m,
"Could not make channels compatible for manager bridge");
7064 if (!(tobj =
ast_calloc(1,
sizeof(*tobj)))) {
7072 tobj->
chan = tmpchana;
7073 tobj->
peer = tmpchanb;
7083 chans[0] = tmpchana;
7084 chans[1] = tmpchanb;
7087 "Response: Success\r\n"
7089 "Channel2: %s\r\n", tmpchana->
name, tmpchanb->name);
7111 struct parkeduser *cur;
7118 e->
command =
"parkedcalls show";
7120 "Usage: parkedcalls show\n"
7121 " List currently parked calls\n";
7130 ast_cli(a->
fd,
"%-10s %-25s (%-15s %-12s %4s) %s\n",
"Num",
"Channel",
7131 "Context",
"Extension",
"Pri",
"Timeout");
7143 ast_cli(a->
fd,
"%-10.10s %-25s (%-15s %-12s %4d) %6lds\n",
7151 numparked += lotparked;
7152 ast_cli(a->
fd,
" %d parked call%s in parking lot %s\n", lotparked,
7153 ESS(lotparked), curlot->
name);
7160 ast_cli(a->
fd,
"---\n%d parked call%s in total.\n", numparked,
ESS(numparked));
7181 struct parkeduser *cur;
7183 char idText[256] =
"";
7189 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n",
id);
7198 "Parkinglot: %s\r\n"
7203 "CallerIDNum: %s\r\n"
7204 "CallerIDName: %s\r\n"
7205 "ConnectedLineNum: %s\r\n"
7206 "ConnectedLineName: %s\r\n"
7211 (
long) cur->
start.tv_sec + (
long) (cur->
parkingtime / 1000) - (
long) time(NULL),
7225 "Event: ParkedCallsComplete\r\n"
7288 if (sscanf(timeout,
"%30d", &args.
timeout) != 1) {
7295 snprintf(buf,
sizeof(buf),
"Channel does not exist: %s", channel);
7301 snprintf(buf,
sizeof(buf),
"Channel does not exist: %s", channel2);
7335 .
type =
"pickup-active",
7404 ast_debug(1,
"No call pickup possible... for %s\n", chan->
name);
7419 const char *chan_name;
7420 const char *target_name;
7424 ast_debug(1,
"Call pickup on '%s' by '%s'\n", target_name, chan->
name);
7430 "Unable to create channel datastore on '%s' for call pickup\n", target_name);
7476 "TargetChannel: %s\r\n",
7477 chan_name, target_name);
7533 char *
parse,
struct timeval *calldurationlimit)
7536 char *limit_str, *warning_str, *warnfreq_str;
7538 int play_to_caller = 0, play_to_callee = 0;
7541 limit_str =
strsep(&stringp,
":");
7542 warning_str =
strsep(&stringp,
":");
7543 warnfreq_str =
strsep(&stringp,
":");
7585 play_to_caller = var ?
ast_true(var) : 1;
7588 play_to_callee = var ?
ast_true(var) : 0;
7590 if (!play_to_caller && !play_to_callee)
7611 calldurationlimit->tv_sec = 0;
7612 calldurationlimit->tv_usec = 0;
7616 calldurationlimit->tv_sec = config->
timelimit / 1000;
7617 calldurationlimit->tv_usec = (config->
timelimit % 1000) * 1000;
7618 ast_verb(3,
"Setting call duration limit to %.3lf seconds.\n",
7619 calldurationlimit->tv_sec + calldurationlimit->tv_usec / 1000000.0);
7620 config->
timelimit = play_to_caller = play_to_callee =
7623 ast_verb(4,
"Limit Data for this call:\n");
7626 ast_verb(4,
"play_to_caller = %s\n", play_to_caller ?
"yes" :
"no");
7627 ast_verb(4,
"play_to_callee = %s\n", play_to_callee ?
"yes" :
"no");
7652 struct ast_channel *current_dest_chan, *final_dest_chan, *chans[2];
7653 char *tmp_data = NULL;
7657 struct timeval calldurationlimit = { 0, };
7665 ast_log(
LOG_WARNING,
"Bridge require at least 1 argument specifying the other end of the bridge\n");
7675 if (!strcmp(chan->
name,
args.dest_chan)) {
7678 "Response: Failed\r\n"
7679 "Reason: Unable to bridge channel to itself\r\n"
7689 strlen(
args.dest_chan)))) {
7693 "Response: Failed\r\n"
7694 "Reason: Channel2 does not exist\r\n"
7696 "Channel2: %s\r\n", chan->
name,
args.dest_chan);
7703 NULL, NULL, current_dest_chan->
linkedid, 0,
"Bridge/%s", current_dest_chan->
name))) {
7706 "Response: Failed\r\n"
7707 "Reason: Cannot create placeholder channel\r\n"
7709 "Channel2: %s\r\n", chan->
name,
args.dest_chan);
7717 &&
ast_bridge_timelimit(chan, &bconfig, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit)) {
7719 "Response: Failed\r\n"
7720 "Reason: Cannot setup bridge time limit\r\n"
7722 "Channel2: %s\r\n", chan->
name,
args.dest_chan);
7731 "Response: Failed\r\n"
7732 "Reason: Cannot masquerade channels\r\n"
7734 "Channel2: %s\r\n", chan->
name,
args.dest_chan);
7746 chans[0] = current_dest_chan;
7747 chans[1] = final_dest_chan;
7754 "Response: Failed\r\n"
7755 "Reason: Could not make channels compatible for bridge\r\n"
7757 "Channel2: %s\r\n", chan->
name, final_dest_chan->
name);
7769 "Response: Success\r\n"
7771 "Channel2: %s\r\n", chan->
name, final_dest_chan->
name);
7813 ast_debug(1,
"starting new PBX in %s,%s,%d for chan %s\n",
7821 ast_debug(1,
"SUCCESS continuing PBX on chan %s\n", final_dest_chan->
name);
7827 ast_debug(1,
"chan %s was hungup\n", final_dest_chan->
name);
7838 #if defined(TEST_FRAMEWORK)
7848 static void create_spaces_str(
struct ast_str **
str,
struct parking_dp_space_map *spaces)
7851 struct parking_dp_spaces *cur;
7866 #if defined(TEST_FRAMEWORK)
7879 static int check_spaces(
struct ast_test *test,
struct parking_dp_space_map *spaces,
const char *expected,
const char *what)
7884 create_spaces_str(&str, spaces);
7888 "Unexpected parking space map for %s. Expect:'%s' Got:'%s'\n",
7895 #if defined(TEST_FRAMEWORK)
7905 static void test_add_dead_space(
const char *context,
int space)
7907 struct parking_dp_space_map *dead_spaces = (
struct parking_dp_space_map *) context;
7913 #if defined(TEST_FRAMEWORK)
7934 static struct parking_dp_context *test_build_maps(
struct ast_test *test,
7938 struct parking_dp_context *ctx_node;
7942 snprintf(what,
sizeof(what),
"%s[%d]", table_name, cur_index);
7952 if (check_spaces(test, &ctx_node->
spaces, table->expect, what)) {
7956 while (--num_entries) {
7959 snprintf(what,
sizeof(what),
"%s[%d]", table_name, cur_index);
7968 if (check_spaces(test, &ctx_node->
spaces, table->expect, what)) {
7976 static const struct test_map test_old_ctx[] = {
7978 {
"702", 14, 15,
"14-15" },
7979 {
"700", 10, 11,
"10-11,14-15" },
7980 {
"701", 18, 19,
"10-11,14-15,18-19" },
7981 {
"703", 12, 13,
"10-15,18-19" },
7982 {
"704", 16, 17,
"10-19" },
7985 {
"704", 9, 19,
"9-19" },
7986 {
"704", 9, 20,
"9-20" },
7987 {
"704", 8, 21,
"8-21" },
7990 {
"705", 23, 25,
"8-21,23-25" },
7991 {
"706", 28, 31,
"8-21,23-25,28-31" },
7992 {
"707", 33, 34,
"8-21,23-25,28-31,33-34" },
7993 {
"708", 38, 40,
"8-21,23-25,28-31,33-34,38-40" },
7994 {
"709", 42, 43,
"8-21,23-25,28-31,33-34,38-40,42-43" },
7997 static const struct test_map test_new_ctx[] = {
7998 {
"702", 4, 5,
"4-5" },
7999 {
"704", 24, 26,
"4-5,24-26" },
8000 {
"709", 29, 30,
"4-5,24-26,29-30" },
8001 {
"710", 32, 35,
"4-5,24-26,29-30,32-35" },
8002 {
"711", 37, 39,
"4-5,24-26,29-30,32-35,37-39" },
8006 #if defined(TEST_FRAMEWORK)
8016 static int test_dialplan_usage_map(
struct ast_test *test)
8018 struct parking_dp_context *old_ctx;
8019 struct parking_dp_context *new_ctx;
8021 struct parking_dp_spaces *spaces;
8035 "Build old_ctx map\n");
8037 old_ctx = test_build_maps(test, lot,
"test_old_ctx", test_old_ctx,
8045 new_ctx = test_build_maps(test, lot,
"test_new_ctx", test_new_ctx,
8054 &new_ctx->
spaces, test_add_dead_space);
8055 if (check_spaces(test, &dead_spaces,
"8-21,23,28,31,40,42-43",
"dead_spaces")) {
8057 goto fail_dead_spaces;
8075 #if defined(TEST_FRAMEWORK)
8082 #if defined(TEST_FRAMEWORK)
8088 NULL, NULL, 0, 0,
"TestChannel1"))) {
8099 test_channel1->
tech = fake_tech;
8101 return test_channel1;
8105 #if defined(TEST_FRAMEWORK)
8109 struct parkeduser *pu_toremove;
8116 if (pu_toremove == args->
pu) {
8147 if (!res && toremove) {
8154 #if defined(TEST_FRAMEWORK)
8167 .
fixup = fake_fixup,
8170 static const char unique_lot_1[] =
"myuniquetestparkinglot314";
8171 static const char unique_lot_2[] =
"myuniquetestparkinglot3141592654";
8172 static const char unique_context_1[] =
"myuniquetestcontext314";
8173 static const char unique_context_2[] =
"myuniquetestcontext3141592654";
8174 static const char parkinglot_parkext[] =
"750";
8175 static const char parkinglot_range[] =
"751-760";
8179 info->name =
"features_test";
8180 info->category =
"/main/features/";
8181 info->summary =
"Features unit test";
8183 "Tests whether parking respects PARKINGLOT settings";
8189 if (test_dialplan_usage_map(test)) {
8191 goto exit_features_test;
8198 if (!(test_channel1 = create_test_channel(&fake_tech))) {
8200 goto exit_features_test;
8204 goto exit_features_test;
8206 if (unpark_test_channel(test_channel1, &args)) {
8208 goto exit_features_test;
8213 if (!(test_channel1 = create_test_channel(&fake_tech))) {
8215 goto exit_features_test;
8223 goto exit_features_test;
8228 || strcmp(dynlot->
name, unique_lot_1)
8230 || strcmp(dynlot->
cfg.
parkext, parkinglot_parkext)
8240 if (!unpark_test_channel(test_channel1, &args)) {
8241 test_channel1 = NULL;
8244 goto exit_features_test;
8248 if (unpark_test_channel(test_channel1, &args)) {
8250 goto exit_features_test;
8255 if (!(test_channel1 = create_test_channel(&fake_tech))) {
8257 goto exit_features_test;
8265 goto exit_features_test;
8269 test_channel1 = NULL;
8273 || strcmp(dynlot->
name, unique_lot_2)
8275 || strcmp(dynlot->
cfg.
parkext, parkinglot_parkext)
8292 if (unpark_test_channel(parked_chan, &args)) {
8303 if (test_channel1) {
8325 #if defined(TEST_FRAMEWORK)
8364 #if defined(TEST_FRAMEWORK)
char exten[FEATURE_MAX_LEN]
struct ast_flags peer_features
static void * do_parking_thread(void *ignore)
Take care of parked calls and unpark them if needed.
struct ast_channel * ast_waitfor_n(struct ast_channel **chan, int n, int *ms)
Waits for input on a group of channels Wait for input on an array of channels for a given # of millis...
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
static int parkinglot_hash_cb(const void *obj, const int flags)
char context[AST_MAX_CONTEXT]
union ast_frame_subclass subclass
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
enum sip_cc_notify_state state
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
const ast_string_field gname
static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Find devicestate as text message for output.
#define ast_rwlock_rdlock(a)
#define ast_channel_lock(chan)
void ast_bridge_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why)
Simulate a DTMF end on a broken bridge channel.
static struct ast_channel * feature_request_and_dial(struct ast_channel *caller, const char *caller_name, struct ast_channel *requestor, struct ast_channel *transferee, const char *type, format_t format, void *data, int timeout, int *outstate, const char *language)
static void * dial_features_duplicate(void *data)
Main Channel structure associated with a channel.
#define AST_DEFINE_APP_ARGS_TYPE(type, arglist)
Define a structure type to hold an application's arguments.
char accountcode[AST_MAX_ACCOUNT_CODE]
static ast_rwlock_t features_lock
static const char * parkedcall
#define AST_CLI_DEFINE(fn, txt,...)
ast_device_state
Device States.
char * str
Subscriber phone number (Malloced)
static struct ast_parkinglot * parkinglot_addref(struct ast_parkinglot *parkinglot)
struct ast_channel * masq
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
struct ast_party_connected_line connected
Channel Connected Line ID information.
static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
static int play_message_to_chans(struct ast_channel *left, struct ast_channel *right, int which, const char *msg, const char *audiofile)
#define AST_LIST_LOCK(head)
Locks a list.
static void process_applicationmap_line(struct ast_variable *var)
static int parkinglot_markall_cb(void *obj, void *arg, int flags)
static void parkinglot_destroy(void *obj)
Destroy a parking lot.
Asterisk locking-related definitions:
void astman_append(struct mansession *s, const char *fmt,...)
Asterisk main include file. File version handling, generic pbx functions.
void ast_poll_channel_add(struct ast_channel *chan0, struct ast_channel *chan1)
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
#define ao2_link(arg1, arg2)
struct ast_channel * peer
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
#define AST_OPTION_AUDIO_MODE
int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
Present a dialtone and collect a certain length extension.
static int transferdigittimeout
#define AST_RWLOCK_DEFINE_STATIC(rwlock)
void(* end_bridge_callback_data_fixup)(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
static const char config[]
static struct ast_call_feature * find_dynamic_feature(const char *name)
find a call feature by name
static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
static char parkinglot[AST_MAX_CONTEXT]
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame with payload.
struct ast_frame ast_null_frame
struct timeval feature_start_time
struct ast_party_caller caller
Channel Caller ID information.
static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
char * strsep(char **str, const char *delims)
#define AST_FEATURE_RETURN_SUCCESSBREAK
struct ast_app * pbx_findapp(const char *app)
Look up an application.
unsigned int parkaddhints
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
struct ast_channel * chan
const ast_string_field uniqueid
static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
exec an app by feature
struct ast_flags features_callee
static struct parkinglot_cfg parkinglot_cfg_default
int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
Weird function made for call transfers.
static void clear_dialed_interfaces(struct ast_channel *chan)
char exten[AST_MAX_EXTENSION]
static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_channel *transferer, struct ast_party_connected_line *connected_line)
char dstchannel[AST_MAX_EXTENSION]
static int bridge_exec(struct ast_channel *chan, const char *data)
Bridge channels.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
struct ast_party_id id
Connected party ID.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define ast_channel_unref(c)
Decrease channel reference count.
#define DEFAULT_PARK_TIME
static void features_shutdown(void)
#define ast_set2_flag(p, value, flag)
void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
Initialize the given connected line structure using the given guide for a set update operation...
#define ast_test_flag(p, flag)
static void remove_dead_context_usage(const char *context, struct parking_dp_context *old_ctx, struct parking_dp_context *new_ctx)
static struct parking_dp_context * build_dialplan_useage_context(struct ast_parkinglot *lot)
Support for translation of data formats. translate.c.
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
void ast_cdr_end(struct ast_cdr *cdr)
End a call.
static struct parking_dp_spaces * build_dialplan_useage_spaces(int start, int stop)
struct ast_party_name name
Subscriber name.
static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
Attended transfer.
static struct ast_parkinglot * copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot)
Copy parkinglot and store it with new name.
static void unmap_features(void)
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
char context[AST_MAX_CONTEXT]
struct feature_group::@266 features
int ast_cdr_appenduserfield(struct ast_channel *chan, const char *userfield)
Append to CDR user field for channel (stored in CDR)
#define ao2_iterator_next(arg1)
#define ast_set_flag(p, flag)
descriptor for a cli entry.
static int set_chan_app_data(struct ast_channel *chan, const char *src_app_data)
int ast_cel_report_event(struct ast_channel *chan, enum ast_cel_event_type event_type, const char *userdefevname, const char *extra, struct ast_channel *peer2)
Report a channel event.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
static struct ast_cli_entry cli_features[]
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
const char * ast_get_extension_app(struct ast_exten *e)
static int park_call_exec(struct ast_channel *chan, const char *data)
Park a call.
static void dummy(char *unused,...)
void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Indicate that the connected line information has changed.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile)
char dcontext[AST_MAX_EXTENSION]
static unsigned int atxferloopdelay
static struct ast_parkinglot * default_parkinglot
Default parking lot.
static void remove_dead_ramp_usage(const char *context, struct parking_dp_ramp_map *old_ramps, struct parking_dp_ramp_map *new_ramps)
#define ast_opt_end_cdr_before_h_exten
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
int ast_cdr_setaccount(struct ast_channel *chan, const char *account)
Set account code, will generate AMI event.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_OPTION_DIGIT_DETECT
#define MAX_DIAL_FEATURE_OPTIONS
static struct feature_group * find_group(const char *name)
Find a group by name.
Structure for variables, used for configurations and for channel variables.
static char * handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command to list configured features.
static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
globally accessible channel datastores
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
int ast_adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
Check if scripts for a given app are already loaded. Version may be -1, if any version is okay...
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
void ast_cdr_setdisposition(struct ast_cdr *cdr, long int disposition)
Set the disposition for a call.
static struct ast_app_option park_call_options[128]
static char xferfailsound[256]
void ast_unregister_feature(struct ast_call_feature *feature)
unregister feature from feature_set
#define AST_TEST_REGISTER(cb)
int ast_devstate_prov_del(const char *label)
Remove device state provider.
struct ast_channel * chan
Structure for a data store type.
Configuration File Parser.
char * str
Subscriber name (Malloced)
int ast_say_digits(struct ast_channel *chan, int num, const char *ints, const char *lang)
says digits
int ast_features_init(void)
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
const char * orig_chan_name
static struct ast_app_option bridge_exec_options[128]
static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
Play message to both caller and callee in bridged call, plays synchronously, autoservicing the other ...
static int atxfernoanswertimeout
int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
Run a subroutine on a channel, placing an optional second channel into autoservice.
int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
Bridge a call, optionally allowing redirection.
void * ast_get_extension_app_data(struct ast_exten *e)
static ast_mutex_t features_reload_lock
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
int parkedcallreparking
Enable DTMF based parking on bridge when picking up parked calls.
static int finishup(struct ast_channel *chan)
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
format_t ast_best_codec(format_t fmts)
Pick the best audio codec.
static void playtone(struct ast_channel *chan, int tone, int len)
int(* stop)(struct ast_channel *chan, int need_lock)
struct ast_flags my_features
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
static enum ast_device_state metermaidstate(const char *data)
metermaids callback from devicestate.c
#define AST_OPTION_TONE_VERIFY
static struct ast_app * stopmixmonitor_app
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
#define ast_mutex_lock(a)
#define ast_opt_transmit_silence
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
static const char * findparkinglotname(struct ast_channel *chan)
Find parking lot name from channel.
#define ast_copy_flags(dest, src, flagz)
#define ast_str_alloca(init_len)
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
static struct ast_cdr * pick_unlocked_cdr(struct ast_cdr *cdr)
return the first unlocked cdr in a possible chain
Structure for a data store object.
static int parkinglot_is_marked_cb(void *obj, void *arg, int flags)
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
struct ast_frame * ast_frisolate(struct ast_frame *fr)
Makes a frame independent of any static storage.
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame)
Run a connected line interception macro and update a channel's connected line information.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static struct adsi_event justify[]
#define DEFAULT_ATXFER_DROP_CALL
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
static void parkinglot_unref(struct ast_parkinglot *parkinglot)
Unreference parkinglot object.
static struct ast_exten * get_parking_exten(const char *exten_str, struct ast_channel *chan, const char *context)
static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
Park call via masqueraded channel and announce parking spot on peer channel.
void ast_cli(int fd, const char *fmt,...)
ADSI Support (built upon Caller*ID)
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
const ast_string_field linkedid
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
int(*const fixup)(struct ast_channel *oldchan, struct ast_channel *newchan)
Fix up a channel: If a channel is consumed, this is called. Basically update any ->owner links...
#define ast_rwlock_unlock(a)
int ast_unregister_application(const char *app)
Unregister an application.
static struct ao2_container * hints
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
void ast_free_ptr(void *ptr)
static void dial_features_destroy(void *data)
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
#define ast_verb(level,...)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
support routing for one touch call parking
static char parkingretdahdiring[3]
static struct ast_datastore_info channel_app_data_datastore
int ast_features_reload(void)
Reload call features from features.conf.
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
static unsigned int atxferdropcall
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
int args
This gets set in ast_cli_register()
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
static void remove_exten_if_exist(const char *context, const char *exten, int priority)
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
#define ast_manager_event(chan, category, event, contents,...)
int ast_cdr_setuserfield(struct ast_channel *chan, const char *userfield)
Set CDR user field for channel (stored in CDR)
#define CONFIG_STATUS_FILEMISSING
int ast_masq_park_call(struct ast_channel *park_me, struct ast_channel *parker, int timeout, int *extout)
Park a call via a masqueraded channel.
static void ast_unregister_groups(void)
Remove all feature groups in the list.
void ast_register_feature(struct ast_call_feature *feature)
register new feature into feature_set
static void destroy_dialplan_usage_context(struct parking_dp_context *doomed)
unsigned int options_specified
struct ast_party_id id
Caller party ID.
char app[FEATURE_APP_LEN]
int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *chan)
Initialize based on a channel.
int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
Bridge two channels together.
char lastdata[AST_MAX_EXTENSION]
static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
void ast_change_name(struct ast_channel *chan, const char *newname)
Change channel name.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define AST_RWLIST_INSERT_HEAD
#define DEFAULT_PARK_EXTENSION
static void ast_unregister_features(void)
Remove all features in the list.
int ast_channel_audiohook_count_by_source(struct ast_channel *chan, const char *source, enum ast_audiohook_type type)
Find out how many audiohooks from a certain source exist on a given channel, regardless of status...
#define ast_debug(level,...)
Log a DEBUG message.
static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
Announce call parking by ADSI.
char parking_con[AST_MAX_EXTENSION]
void ast_rdlock_call_features(void)
static int do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
Actual bridge.
Description of one parked call, added to a list while active, then removed. The list belongs to a par...
static struct parkinglot_cfg parkinglot_cfg_default_default
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Queue a connected line update frame on a channel.
struct ast_channel * ast_call_forward(struct ast_channel *caller, struct ast_channel *orig, int *timeout, format_t format, struct outgoing_helper *oh, int *outstate)
Forwards a call to a new channel specified by the original channel's call_forward str...
General Asterisk PBX channel definitions.
struct parking_dp_space_map hints
unsigned int parkext_exclusive
static const char *const mixmonitor_spy_type
int ast_raw_answer(struct ast_channel *chan, int cdr_answer)
Answer a channel.
int(*const hangup)(struct ast_channel *chan)
Hangup (and possibly destroy) the channel.
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
#define AST_FEATURE_RETURN_HANGUP
static int parked_call_exec(struct ast_channel *chan, const char *data)
Pickup parked call.
#define ast_test_status_update(a, b, c...)
static char pickup_ext[AST_MAX_EXTENSION]
static struct feature_group * register_group(const char *fgname)
Add new feature group.
static char pickupsound[256]
#define ast_manager_register_xml(a, b, c)
Register a manager callback using XML documentation to describe the manager.
int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duration)
Send a DTMF digit to a channel.
static struct parking_dp_ramp * build_dialplan_useage_ramp(const char *exten, int exclusive)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
struct ast_datastore_info dialed_interface_info
#define ast_poll(a, b, c)
static struct ast_datastore_info pickup_active
char app_args[FEATURE_APP_ARGS_LEN]
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
#define AST_MAX_EXTENSION
#define AST_RWLIST_TRAVERSE
void ast_cdr_answer(struct ast_cdr *cdr)
Answer a call.
#define AST_STRING_FIELD(name)
Declare a string field.
void * end_bridge_callback_data
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
#define ao2_ref(o, delta)
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
long int ast_random(void)
static void manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
Run management on parkinglots, called once per parkinglot.
const ast_string_field parkinglot
void ast_cdr_setanswer(struct ast_cdr *cdr, struct timeval t)
Set the answer time for a call.
static char * orig_exten(int fd, const char *chan, const char *data)
orginate from extension
#define AST_BRIDGE_DTMF_CHANNEL_1
Report DTMF on channel 1.
#define AST_FEATURE_RETURN_PASSDIGITS
char dst[AST_MAX_EXTENSION]
struct ast_call_feature * feature
#define AST_FEATURE_RETURN_KEEPTRYING
static char language[MAX_LANGUAGE]
static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
make channels compatible
char channel[AST_MAX_EXTENSION]
void ast_channel_set_linkgroup(struct ast_channel *chan, struct ast_channel *peer)
propagate the linked id between chan and peer
const ast_string_field exten
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
static pthread_t parking_thread
static struct ast_datastore_info dial_features_info
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
static int parkinglot_activate(struct ast_parkinglot *parkinglot)
static struct ast_app * monitor_app
Structure to describe a channel "technology", ie a channel driver See for examples: ...
struct ast_cdr * ast_cdr_dup_unique_swap(struct ast_cdr *cdr)
Duplicate a record and increment the sequence number of the old record.
Core PBX routines and definitions.
static int force_reload_load
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
int ast_cdr_update(struct ast_channel *chan)
Update CDR on a channel.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
#define AST_OPTION_FAX_DETECT
Structure for parking lots which are put in a container.
struct ast_flags features_caller
struct ast_channel * ast_channel_callback(ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
Call a function with every active channel.
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
static const char * real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
Find the context for the transfer.
static void park_space_abort(struct parkeduser *pu)
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define ast_strdupa(s)
duplicate a string in memory from the stack
int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, struct ast_party_connected_line *connected)
Parse connected line indication frame data.
static char parking_con_dial[]
Context for parking dialback to parker.
Responsible for call detail data.
#define DEFAULT_ATXFER_CALLBACK_RETRIES
char lastapp[AST_MAX_EXTENSION]
static int usage_context_add_ramp(struct parking_dp_ramp_map *ramp_map, const char *exten, int exclusive, struct ast_parkinglot *lot, int complain)
ast_control_frame_type
Internal control frame subtype field values.
struct ast_channel_tech ast_kill_tech
Kill the channel channel driver technology descriptor.
struct parking_dp_ramp_map access_extens
char moh_class[FEATURE_MOH_LEN]
void ast_cdr_start(struct ast_cdr *cdr)
Start a call.
#define AST_OPTION_FLAG_REQUEST
static char parkingretcidname[256]
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compres two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
static int feature_check(struct ast_channel *chan, struct ast_flags *features, char *code)
Check if a feature exists.
struct parkeduser::@270 list
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
#define AST_OPTION_RELAXDTMF
static unsigned int atxfercallbackretries
static int remap_feature(const char *name, const char *value)
#define AST_TEST_UNREGISTER(cb)
struct timeval sending_dtmf_tv
struct parkinglot_cfg cfg
static struct parkeduser * park_space_reserve(struct ast_channel *park_me, struct ast_channel *parker, struct ast_park_call_args *args)
const ast_string_field call_forward
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_cdr_detach(struct ast_cdr *cdr)
Detaches the detail record for posting (and freeing) either now or at a later time in bulk with other...
enum ast_channel_state _state
struct ast_channel * ast_bridged_channel(struct ast_channel *chan)
Find bridged channel.
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
static int xfer_park_call_helper(struct ast_channel *park_me, struct ast_channel *parker, struct ast_exten *park_exten)
static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
Connected Line/Party information.
const ast_string_field name
static void check_goto_on_transfer(struct ast_channel *chan)
Check goto on transfer.
static void remove_dead_spaces_usage(const char *context, struct parking_dp_space_map *old_spaces, struct parking_dp_space_map *new_spaces, void(*destroy_space)(const char *context, int space))
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
void ast_cdr_specialized_reset(struct ast_cdr *cdr, struct ast_flags *flags)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
static void * bridge_call_thread(void *data)
bridge the call
static char * handle_features_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dialplan_usage_add_parkinglot(struct parking_dp_map *usage_map, struct ast_parkinglot *lot, int complain)
#define ao2_alloc(data_size, destructor_fn)
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
static void remove_dead_dialplan_useage(struct parking_dp_map *old_map, struct parking_dp_map *new_map)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_FEATURE_RETURN_STOREDIGITS
static char parkingretalertinfo[256]
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
char default_exten[FEATURE_MAX_LEN]
#define ao2_find(arg1, arg2, arg3)
#define ast_channel_unlock(chan)
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
Stops a previously-started silence generator on the given channel.
static char courtesytone[256]
static void parse(struct mgcp_request *req)
int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
Pickup a call target.
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
int source
Information about the source of an update.
#define ast_pthread_create(a, b, c, d)
char macrocontext[AST_MAX_CONTEXT]
static char xfersound[256]
static int add_features_datastore(struct ast_channel *chan, const struct ast_flags *my_features, const struct ast_flags *peer_features)
char parkext[AST_MAX_EXTENSION]
static struct ast_parkinglot * create_dynamic_parkinglot(const char *name, struct ast_channel *chan)
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
static int process_config(struct ast_config *cfg)
int ast_cdr_copy_vars(struct ast_cdr *to_cdr, struct ast_cdr *from_cdr)
static void destroy_dialplan_usage_map(struct parking_dp_map *doomed)
static int featuredigittimeout
enum ast_control_frame_type hold_method
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
static void post_manager_event(const char *s, struct parkeduser *pu)
Output parking event to manager.
#define AST_RWLIST_REMOVE_HEAD
char sname[FEATURE_SNAME_LEN]
int ast_call(struct ast_channel *chan, char *addr, int timeout)
Make a call.
#define DATASTORE_INHERIT_FOREVER
static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
store context, extension and priority
static int stopmixmonitor_ok
struct ast_parkinglot * parkinglot
Parkinglot to be parked in.
#define FEATURE_SNAME_LEN
static struct ast_call_feature builtin_features[]
if(yyss+yystacksize-1<=yyssp)
static void destroy_space(const char *context, int space)
static struct ast_parkinglot * create_parkinglot(const char *name)
Allocate parking lot structure.
static int action_bridge(struct mansession *s, const struct message *m)
Bridge channels together.
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
int ast_autoservice_ignore(struct ast_channel *chan, enum ast_frame_type ftype)
Ignore certain frame types.
Structure used to handle boolean flags.
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
static int parkinglot_activate_cb(void *obj, void *arg, int flags)
#define ast_clear_flag(p, flag)
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
Launch a new extension (i.e. new stack)
unsigned int parkfindnext
static void parkinglot_feature_flag_cfg(const char *pl_name, int *param, struct ast_variable *var)
#define FEATURE_SENSE_PEER
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
static int manager_park(struct mansession *s, const struct message *m)
Create manager event for parked calls.
char macroexten[AST_MAX_EXTENSION]
int parkedcallrecording
Enable DTMF based recording on a bridge when picking up parked calls.
#define ast_rwlock_wrlock(a)
struct ast_parkinglot::parkinglot_parklist parkings
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
int parkedcalltransfers
Enable DTMF based transfers on bridge when picking up parked calls.
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
char parkingexten[AST_MAX_EXTENSION]
static int parkinglot_config_read(const char *pl_name, struct parkinglot_cfg *cfg, struct ast_variable *var)
#define DEFAULT_PARKINGLOT
void ast_poll_channel_del(struct ast_channel *chan0, struct ast_channel *chan1)
void ast_cdr_discard(struct ast_cdr *cdr)
Discard and free a CDR record.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
static struct ast_app * mixmonitor_app
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
Copy the source connected line information to the destination connected line.
struct feature_group_exten::@264 entry
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
int ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1)
Makes two channel formats compatible.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Standard Command Line Interface.
int parkedcallhangup
Enable DTMF based hangup on a bridge when pickup up parked calls.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
ast_feature_operation operation
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
#define ao2_container_alloc(arg1, arg2, arg3)
struct ast_parkinglot * parkinglot
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
ast_app: A registered application
static int usage_context_add_spaces(struct parking_dp_space_map *space_map, int start, int stop, struct ast_parkinglot *lot, int complain)
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
#define ast_realloc(a, b)
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
static char pickupfailsound[256]
#define FEATURE_APP_ARGS_LEN
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
#define DEFAULT_FEATURE_DIGIT_TIMEOUT
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
int ast_answer(struct ast_channel *chan)
Answer a channel.
static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
Blind transfer user to another extension.
int ast_park_call(struct ast_channel *park_me, struct ast_channel *parker, int timeout, const char *park_exten, int *extout)
Park a call and read back parked location.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
int ast_is_deferrable_frame(const struct ast_frame *frame)
Should we keep this frame for later?
const ast_string_field accountcode
int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
This functionc locks given context, search for the right extension and fires out all peer in this ext...
Data structure associated with a single frame of data.
#define DEFAULT_ATXFER_LOOP_DELAY
static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
Monitor a channel by DTMF.
Internal Asterisk hangup causes.
#define ast_manager_event_multichan(category, event, nchans, chans, contents,...)
char name[AST_MAX_CONTEXT]
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context (or ANY context if NULL)
static struct ast_parkinglot * find_parkinglot(const char *name)
Find parkinglot by name.
#define AST_FEATURE_RETURN_SUCCESS
#define AST_TEST_DEFINE(hdr)
static int load_config(int reload)
int ast_register_application2(const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
Register an application.
int ast_masq_park_call_exten(struct ast_channel *park_me, struct ast_channel *parker, const char *park_exten, const char *park_context, int timeout, int *extout)
Park a call via a masqueraded channel.
static struct ao2_container * parkinglots
The configured parking lots container. Always at least one - the default parking lot.
#define FEATURE_EXTEN_LEN
#define AST_RWLIST_REMOVE
static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
static int manager_parking_status(struct mansession *s, const struct message *m)
Dump parking lot status.
static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, char *dynamic_features_buf, struct ast_flags *features, feature_interpret_op operation, struct ast_call_feature *feature)
Helper function for feature_interpret and ast_feature_detect.
int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context)
Determine if parking extension exists in a given context.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
enum ast_frame_type frametype
struct ast_variable * next
static char * callback_dialoptions(struct ast_flags *features_callee, struct ast_flags *features_caller, char *options, size_t len)
const char * warning_sound
static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
Add feature to group.
static int build_dialplan_useage_map(struct parking_dp_map *usage_map, int complain)
struct ast_bridge_config bconfig
static char * handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command to list parked calls.
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
#define AST_CLI_YESNO(x)
return Yes or No depending on the argument. This is used in many places in CLI command, having a function to generate this helps maintaining a consistent output (and possibly emitting the output in other languages, at some point).
static struct ast_parkinglot * build_parkinglot(const char *pl_name, struct ast_variable *var)
Build parkinglot from configuration and chain it in if it doesn't already exist.
unsigned char valid
TRUE if the name information is valid/present.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
Notify metermaids that we've changed an extension.
#define CONFIG_STATUS_FILEINVALID
static char context[AST_MAX_CONTEXT]
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
#define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER
int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
Send DTMF to a channel.
struct ast_channel_monitor * monitor
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
static const char * parkcall
int ast_adsi_unload_session(struct ast_channel *chan)
void(* end_bridge_callback)(void *)
void ast_channel_log(char *title, struct ast_channel *chan)
void ast_unlock_call_features(void)
struct parking_dp_space_map spaces
int ast_queue_frame_head(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to the head of a channel's frame queue.
Say numbers and dates (maybe words one day too)
static void park_add_hints(const char *context, int start, int stop)
Add parking hints for all defined parking spaces.
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Asterisk module definitions.
#define DEFAULT_TRANSFER_DIGIT_TIMEOUT
char peername[AST_CHANNEL_NAME]
unsigned int return_to_pbx
struct ast_channel * ast_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *status)
Requests a channel.
int ast_app_exec_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char *macro_args)
Run a macro on a channel, placing an optional second channel into autoservice.
static snd_pcm_format_t format
union ast_frame::@172 data
struct ast_channel_tech * tech
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
struct ast_call_feature::@170 feature_entry
static int dialplan_usage_add_parkinglot_data(struct parking_dp_context *ctx_node, struct ast_parkinglot *lot, int complain)
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
ast_context: An extension context
void ast_cdr_setdestchan(struct ast_cdr *cdr, const char *chan)
Set the destination channel, if there was one.
a directed pickup was performed on this channel
unsigned char valid
TRUE if the number information is valid/present.
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *chan)
Initialize based on a channel.
const ast_string_field language
void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Set the connected line information in the Asterisk channel.
#define AST_CAUSE_CONGESTION
struct ast_context * ast_context_find(const char *name)
Find a context.
struct ast_cdr * ast_cdr_alloc(void)
Allocate a CDR record.
static void bridge_call_thread_launch(struct ast_bridge_thread_obj *data)
create thread for the parked call
#define AST_BRIDGE_DTMF_CHANNEL_0
Report DTMF on channel 0.
int ast_do_masquerade(struct ast_channel *chan)
Start masquerading a channel.
int ast_channel_audiohook_count_by_source_running(struct ast_channel *chan, const char *source, enum ast_audiohook_type type)
Find out how many spies of a certain type exist on a given channel, and are in state running...
char exten[AST_MAX_EXTENSION]
#define AST_MUTEX_DEFINE_STATIC(mutex)
const char * ast_pickup_ext(void)
Determine system call pickup extension.
struct ast_call_feature * ast_find_call_feature(const char *name)
look for a call feature entry by its sname
#define FEATURE_SENSE_CHAN
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
static int comebacktoorigin
int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature)
detect a feature before bridging
int ast_manager_unregister(char *action)
Unregister a registered manager command.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *redirecting_info, int is_caller, int is_frame)
Run a redirecting interception macro and update a channel's redirecting information.
char mohclass[MAX_MUSICCLASS]
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
char userfield[AST_MAX_USER_FIELD]
#define CONFIG_STATUS_FILEUNCHANGED
#define ast_mutex_unlock(a)
static void set_peers(struct ast_channel **caller, struct ast_channel **callee, struct ast_channel *peer, struct ast_channel *chan, int sense)
set caller and callee according to the direction
int ast_adsi_print(struct ast_channel *chan, char **lines, int *align, int voice)
Display some stuff on the screen.
int ast_bridge_timelimit(struct ast_channel *chan, struct ast_bridge_config *config, char *parse, struct timeval *calldurationlimit)
parse L option and read associated channel variables to set warning, warning frequency, and timelimit
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
int ast_can_pickup(struct ast_channel *chan)
Test if a channel can be picked up.
struct ast_party_number number
Subscriber phone number.
int ast_park_call_exten(struct ast_channel *park_me, struct ast_channel *parker, const char *park_exten, const char *park_context, int timeout, int *extout)
Park a call and read back parked location.
static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense)
Check the dynamic features.