diff --git a/apps/app_disa.c b/apps/app_disa.c index a2e738ab7694d68757d1b44849c6c1a6f04497d4..372bcca7a074e92760959566bff2c99fd6f3d572 100755 --- a/apps/app_disa.c +++ b/apps/app_disa.c @@ -330,7 +330,7 @@ static int disa_exec(struct ast_channel *chan, void *data) strncpy(chan->context, ourcontext, sizeof(chan->context) - 1); strncpy(chan->accountcode, acctcode, sizeof(chan->accountcode) - 1); chan->priority = 0; - ast_cdr_init(chan->cdr,chan); + ast_cdr_reset(chan->cdr,AST_CDR_FLAG_POSTED); LOCAL_USER_REMOVE(u); return 0; } diff --git a/channels/chan_agent.c b/channels/chan_agent.c index 526f24e121d9c8f45c521017d641e32be3c0be1b..9dc0ce7a6d954ab81eab294eee33fe4eafd0b69f 100755 --- a/channels/chan_agent.c +++ b/channels/chan_agent.c @@ -1366,9 +1366,14 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode) exten = NULL; } } - if ( options ) { + if (options) { while (*options) { option = (char)options[0]; + if ((option >= 0) && (option <= '9')) + { + options++; + continue; + } if (option=='s') play_announcement = 0; else { diff --git a/channels/chan_zap.c b/channels/chan_zap.c index 9f6475e8a315d9af094c44dd9365ef455ecc075a..76a8c0f7bcdfb469646cd9c9053ce547a50fbbb7 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -196,6 +196,8 @@ static int threewaycalling = 0; static int transfer = 0; +static int canpark = 0; + static int cancallforward = 0; static float rxgain = 0.0; @@ -521,6 +523,7 @@ static struct zt_pvt { int callwaitingcallerid; int threewaycalling; int transfer; + int canpark; int digital; int outgoing; int dnd; @@ -5129,7 +5132,7 @@ static void *ss_thread(void *data) getforward = 0; memset(exten, 0, sizeof(exten)); len = 0; - } else if (p->transfer && !strcmp(exten, ast_parking_ext()) && + } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { /* This is a three way call, the main call being a real channel, @@ -6596,6 +6599,7 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p tmp->confno = -1; tmp->propconfno = -1; } + tmp->canpark = canpark; tmp->transfer = transfer; strncpy(tmp->defcontext,context,sizeof(tmp->defcontext)-1); strncpy(tmp->language, language, sizeof(tmp->language)-1); @@ -9333,6 +9337,8 @@ static int setup_zap(int reload) adsi = ast_true(v->value); } else if (!strcasecmp(v->name, "transfer")) { transfer = ast_true(v->value); + } else if (!strcasecmp(v->name, "canpark")) { + canpark = ast_true(v->value); } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { echocanbridged = ast_true(v->value); } else if (!strcasecmp(v->name, "busydetect")) { diff --git a/configs/zapata.conf.sample b/configs/zapata.conf.sample index 5e87cd76b346f6c520821e9f84aa21d27fea5951..c046dedc062f43839d3eeee3237ce2c5cf8a7499 100755 --- a/configs/zapata.conf.sample +++ b/configs/zapata.conf.sample @@ -193,9 +193,15 @@ callwaitingcallerid=yes threewaycalling=yes ; ; Support flash-hook call transfer (requires three way calling) +; Also enables call parking (overrides the 'canpark' parameter) ; transfer=yes ; +; Allow call parking +; ('canpark=no' is overridden by 'transfer=yes') +; +canpark=yes +; ; Support call forward variable ; cancallforward=yes diff --git a/res/res_features.c b/res/res_features.c index 1010740c9e880769eff1989486e4d06c7454c9e4..548a8744ce2bbd936441ddc3ade88d5bd4633741 100755 --- a/res/res_features.c +++ b/res/res_features.c @@ -28,6 +28,7 @@ #include <asterisk/manager.h> #include <asterisk/utils.h> #include <asterisk/adsi.h> +#include <pthread.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> @@ -49,6 +50,9 @@ static int parkingtime = DEFAULT_PARK_TIME; /* Context for which parking is made accessible */ static char parking_con[AST_MAX_EXTENSION] = "parkedcalls"; +/* Context for dialback for parking (KLUDGE) */ +static char parking_con_dial[AST_MAX_EXTENSION] = "park-dial"; + /* Extension you type to park the call */ static char parking_ext[AST_MAX_EXTENSION] = "700"; @@ -103,6 +107,7 @@ struct parkeduser { int priority; int parkingtime; int notquiteyet; + char peername[1024]; struct parkeduser *next; }; @@ -152,6 +157,7 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou struct ast_context *con; pu = malloc(sizeof(struct parkeduser)); if (pu) { + memset(pu,0,sizeof(struct parkeduser)); ast_mutex_lock(&parking_lock); for (x=parking_start;x<=parking_stop;x++) { cur = parkinglot; @@ -179,6 +185,10 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou pu->parkingtime = parkingtime; if (extout) *extout = x; + if (peer) + { + strncpy(pu->peername,peer->name,sizeof(pu->peername) - 1); + } /* Remember what had been dialed, so that if the parking expires, we try to come back to the same place */ if (!ast_strlen_zero(chan->macrocontext)) @@ -196,7 +206,7 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou pu->next = parkinglot; parkinglot = pu; /* If parking a channel directly, don't quiet yet get parking running on it */ - if (peer == chan) + if (peer == chan) pu->notquiteyet = 1; ast_mutex_unlock(&parking_lock); /* Wake up the (presumably select()ing) thread */ @@ -221,7 +231,6 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou if (adsipark && adsi_available(peer)) { adsi_announce_park(peer, pu->parkingnum); } - ast_say_digits(peer, pu->parkingnum, "", peer->language); if (adsipark && adsi_available(peer)) { adsi_unload_session(peer); } @@ -243,6 +252,7 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou snprintf(exten, sizeof(exten), "%d", x); ast_add_extension2(con, 1, exten, 1, NULL, NULL, parkedcall, strdup(exten), free, registrar); } + if (peer) ast_say_digits(peer, pu->parkingnum, "", peer->language); return 0; } else { ast_log(LOG_WARNING, "No more parking spaces\n"); @@ -558,6 +568,7 @@ static void *do_parking_thread(void *ignore) struct timeval tv; struct ast_frame *f; char exten[AST_MAX_EXTENSION]; + char *peername,*cp; struct ast_context *con; int x; int gc=0; @@ -565,13 +576,13 @@ static void *do_parking_thread(void *ignore) fd_set nrfds, nefds; FD_ZERO(&rfds); FD_ZERO(&efds); + for (;;) { ms = -1; max = -1; ast_mutex_lock(&parking_lock); pl = NULL; pu = parkinglot; - gettimeofday(&tv, NULL); FD_ZERO(&nrfds); FD_ZERO(&nefds); while(pu) { @@ -585,17 +596,40 @@ static void *do_parking_thread(void *ignore) gc++; ast_moh_start(pu->chan,NULL); } + gettimeofday(&tv, NULL); tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000; if (tms > pu->parkingtime) { - /* They've been waiting too long, send them back to where they came. Theoretically they - should have their original extensions and such, but we copy to be on the safe side */ - strncpy(pu->chan->exten, pu->exten, sizeof(pu->chan->exten)-1); - strncpy(pu->chan->context, pu->context, sizeof(pu->chan->context)-1); - pu->chan->priority = pu->priority; - if (option_verbose > 1) - ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d. Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->chan->context, pu->chan->exten, pu->chan->priority); /* Stop music on hold */ ast_moh_stop(pu->chan); + /* Get chan, exten from derived kludge */ + if (pu->peername[0]) + { + peername = strdupa(pu->peername); + cp = strrchr(peername,'-'); + if (cp) *cp = 0; + con = ast_context_find(parking_con_dial); + if (!con) { + con = ast_context_create(NULL,parking_con_dial, registrar); + if (!con) { + ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial); + } + } + if (con) { + ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(peername), free, registrar); + } + strncpy(pu->chan->exten, peername, sizeof(pu->chan->exten)-1); + strncpy(pu->chan->context, parking_con_dial, sizeof(pu->chan->context)-1); + pu->chan->priority = 1; + + } else { + /* They've been waiting too long, send them back to where they came. Theoretically they + should have their original extensions and such, but we copy to be on the safe side */ + strncpy(pu->chan->exten, pu->exten, sizeof(pu->chan->exten)-1); + strncpy(pu->chan->context, pu->context, sizeof(pu->chan->context)-1); + pu->chan->priority = pu->priority; + } + if (option_verbose > 1) + ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d. Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->chan->context, pu->chan->exten, pu->chan->priority); /* Start up the PBX, or hang them up */ if (ast_pbx_start(pu->chan)) { ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name); diff --git a/res/res_monitor.c b/res/res_monitor.c index c90bab775f25e9ede0b6233c4e4400b32ffdc5f1..e2cec0dacbbe45be2bf302f6bafc24c51a41d1cc 100755 --- a/res/res_monitor.c +++ b/res/res_monitor.c @@ -29,7 +29,7 @@ static unsigned long seq = 0; static char *monitor_synopsis = "Monitor a channel"; -static char *monitor_descrip = "Monitor([file_format|[fname_base]|[options]]):\n" +static char *monitor_descrip = "Monitor([file_format[:urlbase]|[fname_base]|[options]]):\n" "Used to start monitoring a channel. The channel's input and output\n" "voice packets are logged to files until the channel hangs up or\n" "monitoring is stopped by the StopMonitor application.\n" @@ -307,6 +307,8 @@ static int start_monitor_exec(struct ast_channel *chan, void *data) char *fname_base = NULL; char *options = NULL; char *delay = NULL; + char *urlprefix = NULL; + char tmp[256]; int joinfiles = 0; int waitforbridge = 0; int res = 0; @@ -315,6 +317,13 @@ static int start_monitor_exec(struct ast_channel *chan, void *data) if (data && !ast_strlen_zero((char*)data)) { arg = ast_strdupa((char*)data); format = arg; + arg = strchr(format,':'); + if (arg) + { + *arg++ = 0; + urlprefix = arg; + } + else arg = format; fname_base = strchr(arg, '|'); if (fname_base) { *fname_base = 0; @@ -329,7 +338,14 @@ static int start_monitor_exec(struct ast_channel *chan, void *data) } } } - + if (urlprefix) + { + snprintf(tmp,sizeof(tmp) - 1,"%s/%s.%s",urlprefix,fname_base, + ((strcmp(format,"gsm")) ? "wav" : "gsm")); + if (!chan->cdr) + chan->cdr = ast_cdr_alloc(); + ast_cdr_setuserfield(chan, tmp); + } if (waitforbridge) { /* We must remove the "b" option if listed. In principle none of the following could give NULL results, but we check just to