Index: apps/app_dial.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_dial.c,v retrieving revision 1.140 diff -u -r1.140 app_dial.c --- apps/app_dial.c 11 Feb 2005 06:53:18 -0000 1.140 +++ apps/app_dial.c 11 Feb 2005 16:14:09 -0000 @@ -37,6 +37,7 @@ #include #include #include +#define MAX_RECEIVE_VARS 250 static char *tdesc = "Dialing Application"; @@ -72,6 +73,8 @@ " making/redirecting the outgoing call. For example, some PSTNs\n" " don't allow callerids from other extensions then the ones\n" " that are assigned to you.\n" +" 'v' -- *Send Variables to callee.\n" +" 'V' -- *Obtain Variables from callee.\n" " 'o' -- Original (inbound) Caller*ID should be placed on the outbound leg of the call\n" " instead of using the destination extension (old style asterisk behavior)\n" " 'r' -- indicate ringing to the calling party, pass no audio until answered.\n" @@ -115,6 +118,7 @@ " ANSWEREDTIME Time for actual call\n" " DIALSTATUS The status of the call as a text string, one of\n" " CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n" +"\n*requires an addditional app to be called on the other end of the call.\n" ""; /* RetryDial App by Anthony Minessale II Jan/2005 */ @@ -131,6 +135,24 @@ "All arguments after 'loops' are passed directly to the Dial() application.\n" ""; +/* SendVars / ReceiveVars by Anthony Minessale II Feb/2005 */ +static char *svapp = "SendVars"; +static char *svsynopsis = "Send variables over supported channels.\n"; +static char *svdescrip = " SendVars():\n" +"To be used in conjunction with the 'V' flag on app_dial.\n\n" +"Remote usage: Dial(||V)\n\n" +"All Variables will be sent over text frames to the caller.\n" +"\n"; + +static char *rvapp = "ReceiveVars"; +static char *rvsynopsis = "Receive variables over supported channels.\n"; +static char *rvdescrip = " ReceiveVars():\n" +"To be used in conjunction with the 'v' flag on app_dial.\n\n" +"Remote usage: Dial(||v)\n\n" +"All Variables will be received over text frames from the caller.\n" +"\n"; + + /* We define a customer "local user" structure because we use it not only for keeping track of what is in use but @@ -149,6 +171,8 @@ #define DIAL_GO_ON (1 << 10) #define DIAL_HALT_ON_DTMF (1 << 11) #define DIAL_PRESERVE_CALLERID (1 << 12) +#define DIAL_RECEIVE_VARS (1 << 13) +#define DIAL_SEND_VARS (1 << 14) struct localuser { struct ast_channel *chan; @@ -197,6 +221,74 @@ } while (0) +#define get_frame_or_break(f,chan) f = ast_read(chan); if (!f) break; +#define clean_frame(f) if(f) {ast_frfree(f); f = NULL;} + +static void receive_vars(struct ast_channel *chan, struct ast_channel *peer, int frames) { + int ready = 0; + char *vname = NULL, *vval = NULL; + struct ast_frame *f = NULL; + int count = 0; + + if (! (chan && peer) ) + return; + + while (count < frames && ready > -1 && ast_waitfor(chan, -1) > -1) { + count++; + get_frame_or_break(f, chan); + if (f->frametype == AST_FRAME_TEXT && !strcmp(f->data, "variables")) + ready = 1; + else if (f->frametype == AST_FRAME_TEXT && !strcmp(f->data, "/variables")) + ready = -1; + else if(ready == 1 && f->frametype == AST_FRAME_TEXT) { + if((vname = ast_strdupa(f->data)) && (vval = strchr(vname,'='))) { + *vval = '\0'; + vval++; + ast_log(LOG_DEBUG,"VARIABLE XFER: set %s %s=%s\n", peer->name, vname, vval); + pbx_builtin_setvar_helper(peer, vname, vval); + } + } + clean_frame(f); + } +} + +static void send_vars(struct ast_channel *chan, struct ast_channel *peer) { + struct varshead *headp; + struct ast_var_t *variable; + char *vname, *vval, *remote_text; + size_t size; + + if (! (chan && peer) ) + return; + + ast_sendtext(peer, "variables"); + headp = &chan->varshead; + AST_LIST_TRAVERSE(headp, variable, entries) { + vname = ast_var_name(variable); + vval = ast_var_value(variable); + size = strlen(vname) + strlen(vval) + 2; + remote_text = alloca(size); + snprintf(remote_text, size, "%s=%s", vname, vval); + ast_log(LOG_DEBUG,"VARIABLE XFER: transmit %s\n", remote_text); + ast_sendtext(peer, remote_text); + } + ast_sendtext(peer, "/variables"); +} + +static int receive_vars_exec(struct ast_channel *chan, void *data) { + + receive_vars(chan, chan, MAX_RECEIVE_VARS); + return 0; +} + +static int send_vars_exec(struct ast_channel *chan, void *data) { + + send_vars(chan, chan); + return 0; +} + + + static int ast_onedigit_goto(struct ast_channel *chan, char *context, char exten, int pri, char *cid) { char rexten[2]; @@ -292,6 +384,14 @@ numlines = prestart; watchers[0] = in; while (o) { + if(ast_test_flag(peerflags, DIAL_SEND_VARS)) { + ast_log(LOG_DEBUG,"VARIABLE XFER: SEND\n"); + send_vars(in, o->chan); + } + if(ast_test_flag(peerflags, DIAL_RECEIVE_VARS)) { + receive_vars(o->chan, in , MAX_RECEIVE_VARS); + ast_log(LOG_DEBUG,"VARIABLE XFER: RECEIVE\n"); + } /* Keep track of important channels */ if (ast_test_flag(o, DIAL_STILLGOING) && o->chan) { watchers[pos++] = o->chan; @@ -324,6 +424,7 @@ o = outgoing; while (o) { if (ast_test_flag(o, DIAL_STILLGOING) && o->chan && (o->chan->_state == AST_STATE_UP)) { + if (!peer) { if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name); @@ -430,6 +531,7 @@ ast_hangup(winner); continue; } + f = ast_read(winner); if (f) { if (f->frametype == AST_FRAME_CONTROL) { @@ -906,6 +1008,8 @@ ast_set2_flag(tmp, strchr(transfer, 'h'), DIAL_ALLOWDISCONNECT_IN); ast_set2_flag(peerflags, strchr(transfer, 'h'), DIAL_ALLOWDISCONNECT_IN); ast_set2_flag(tmp, strchr(transfer, 'f'), DIAL_FORCECALLERID); + ast_set2_flag(peerflags, strchr(transfer, 'v'), DIAL_SEND_VARS); + ast_set2_flag(peerflags, strchr(transfer, 'V'), DIAL_RECEIVE_VARS); ast_set2_flag(peerflags, strchr(transfer, 'w'), DIAL_MONITOR_IN); ast_set2_flag(peerflags, strchr(transfer, 'W'), DIAL_MONITOR_OUT); ast_set2_flag(peerflags, strchr(transfer, 'd'), DIAL_HALT_ON_DTMF); @@ -1100,6 +1204,8 @@ conversation. */ hanguptree(outgoing, peer); outgoing = NULL; + + /* If appropriate, log that we have a destination channel */ if (chan->cdr) ast_cdr_setdestchan(chan->cdr, peer->name); @@ -1395,18 +1501,26 @@ } + int unload_module(void) { STANDARD_HANGUP_LOCALUSERS; + ast_unregister_application(svapp); + ast_unregister_application(rvapp); ast_unregister_application(app); return ast_unregister_application(rapp); } int load_module(void) { - int res; - if (!(res = ast_register_application(app, dial_exec, synopsis, descrip))) - res = ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip); + int res = 0; + if (!(res = ast_register_application(app, dial_exec, synopsis, descrip))) { + if(!(res = ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip))) { + if(!(res = ast_register_application(svapp,send_vars_exec,svsynopsis,svdescrip))) + res = ast_register_application(rvapp,receive_vars_exec,rvsynopsis,rvdescrip); + } + } + return res; }