Index: apps/app_dial.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_dial.c,v
retrieving revision 1.138
diff -u -r1.138 app_dial.c
--- apps/app_dial.c	7 Feb 2005 15:19:34 -0000	1.138
+++ apps/app_dial.c	8 Feb 2005 03:50:02 -0000
@@ -37,6 +37,7 @@
 #include <sys/time.h>
 #include <sys/signal.h>
 #include <netinet/in.h>
+#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 <anthmct@yahoo.com> Jan/2005 */
@@ -131,6 +135,24 @@
 "All arguements after 'loops' are passed directly to the Dial() application.\n"
 "";
 
+/* SendVars / ReceiveVars by Anthony Minessale II <anthmct@yahoo.com> 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(<chan url>|<timeout>|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(<chan url>|<timeout>|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,68 @@
 } 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;
+
+	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;
+
+	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 +378,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 +418,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 +525,7 @@
 					ast_hangup(winner);
 					continue;
 				}
+				
 				f = ast_read(winner);
 				if (f) {
 					if (f->frametype == AST_FRAME_CONTROL) {
@@ -906,6 +1002,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 +1198,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 +1495,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;
 }
 
