[Freeswitch-svn] [commit] r4216 - in freeswitch/trunk/src: . mod/endpoints/mod_sofia

Freeswitch SVN anthm at freeswitch.org
Mon Feb 12 20:22:17 EST 2007


Author: anthm
Date: Mon Feb 12 20:22:17 2007
New Revision: 4216

Modified:
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
   freeswitch/trunk/src/switch_ivr.c

Log:
Sofia Behaviour Modification (please document)

1) This commit adds the ability to override the To: header so you
   can place an outbound SIP call to a paticular destination.

   For instance, if you have a user registered to your machine as 'gateway' and
   you want to call another extension at that machine 'foo' you can now call:

  sofia/mydomain.com/gateway:foo at anydomain.com

  or if you just want to call some SIP url and put an alternate To:
  so you can do forwarding:

  sofia/mydomain.com/1000 at somwhere.com:12122551234 at realdest.com


2) You can add headers to outbound SIP calls by
   prefixing the string 'SIP_h_' to any channel variable:

   <action application="set" data="SIP_h_X-Answer=42"/>
   <action application="bridge" data="sofia/mydomain.com/1000 at somehost.com"/>

3) All inbound SIP calls will install any X- headers into local variables
   this means in conjunction with item 2, all X- headers will pass across 
   bridged calls auto-magicly.

4) The switch_ivr_transfer_variable function in switch_ivr.c has been modified so if the last arguement
   'var' starts with a ~ it will copy anything that is prefixed with that string rather than an exact match.

*NOTE* you are not required to put an X- prefix in the SIP_h_ vars but 
it is reccommended because most SIP devices will ignore any unknown headers that don't.




Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	Mon Feb 12 20:22:17 2007
@@ -65,6 +65,8 @@
 #define SOFIA_REPLACES_HEADER "_sofia_replaces_"
 #define SOFIA_USER_AGENT "FreeSWITCH(mod_sofia)"
 #define SOFIA_CHAT_PROTO "sip"
+#define SOFIA_SIP_HEADER_PREFIX "sip_h_"
+#define SOFIA_SIP_HEADER_PREFIX_T "~sip_h_"
 
 #include <sofia-sip/nua.h>
 #include <sofia-sip/sip_status.h>
@@ -301,6 +303,7 @@
 	char *remote_sdp_str;
 	char *local_sdp_str;
 	char *dest;
+	char *dest_to;
 	char *key;
 	char *xferto;
 	char *kick;
@@ -963,6 +966,11 @@
 	char *cid_name, *cid_num;
 	char *e_dest = NULL;
 	char *holdstr = "";
+	switch_stream_handle_t stream = {0};
+	switch_hash_index_t *hi;
+	void *vval;
+	char *extra_headers;
+	const void *vvar;
 
     channel = switch_core_session_get_channel(session);
     assert(channel != NULL);
@@ -1023,7 +1031,8 @@
 
 		if (!tech_pvt->nh) {
 			tech_pvt->nh = nua_handle(tech_pvt->profile->nua, NULL,
-									  SIPTAG_TO_STR(tech_pvt->dest),
+									  NUTAG_URL(tech_pvt->dest),
+									  SIPTAG_TO_STR(tech_pvt->dest_to),
 									  SIPTAG_FROM_STR(tech_pvt->from_str),
 									  SIPTAG_CONTACT_STR(tech_pvt->profile->url),
 									  TAG_END());
@@ -1056,9 +1065,29 @@
 
 		holdstr = switch_test_flag(tech_pvt, TFLAG_SIP_HOLD) ? "*" : "";
 
+
+		SWITCH_STANDARD_STREAM(stream);
+		for (hi = switch_channel_variable_first(channel, switch_core_session_get_pool(tech_pvt->session)); hi; hi = switch_hash_next(hi)) {
+            switch_hash_this(hi, &vvar, NULL, &vval);
+            if (vvar && vval) {
+				char *name = (char *) vvar;
+				char *value = (char *) vval;
+
+				if (!strncasecmp(name, SOFIA_SIP_HEADER_PREFIX, strlen(SOFIA_SIP_HEADER_PREFIX))) {
+					char *hname = name + strlen(SOFIA_SIP_HEADER_PREFIX);
+					stream.write_function(&stream, "%s: %s\r\n", hname, value);
+				}
+			}
+		}
+		
+		if (stream.data) {
+			extra_headers = stream.data;
+		}
+
 		nua_invite(tech_pvt->nh,
 				   TAG_IF(!switch_strlen_zero(rpid), SIPTAG_HEADER_STR(rpid)),
 				   TAG_IF(!switch_strlen_zero(alert_info), SIPTAG_HEADER_STR(alert_info)),
+				   TAG_IF(!switch_strlen_zero(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
 				   TAG_IF(!switch_strlen_zero(max_forwards),SIPTAG_MAX_FORWARDS_STR(max_forwards)),
 				   //SIPTAG_CONTACT_STR(tech_pvt->profile->url),
 				   SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
@@ -1067,7 +1096,8 @@
 				   TAG_IF(rep, SIPTAG_REPLACES_STR(rep)),
 				   SOATAG_HOLD(holdstr),
 				   TAG_END());
-
+		
+		switch_safe_free(stream.data);
 	} else {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
 	}
@@ -2197,7 +2227,7 @@
 	switch_caller_profile_t *caller_profile = NULL;
 	private_object_t *tech_pvt = NULL;
 	switch_channel_t *nchannel;
-	char *host;
+	char *host, *dest_to;
 
 	*new_session = NULL;
 
@@ -2231,6 +2261,12 @@
         goto done;
 	}
 
+	if ((dest_to = strchr(dest, ':'))) {
+		*dest_to++ = '\0';
+		tech_pvt->dest_to = switch_core_session_alloc(nsession, strlen(dest_to) + 5);
+		snprintf(tech_pvt->dest_to, strlen(dest_to) + 5, "sip:%s", dest_to);
+	}
+
 	if ((host = strchr(dest, '%'))) {
 		char buf[128];
 		*host = '@';
@@ -2260,8 +2296,11 @@
 		snprintf(tech_pvt->dest, strlen(dest) + 5, "sip:%s", dest);
 	}
 
-	attach_private(nsession, profile, tech_pvt, dest);
+	if (!tech_pvt->dest_to) {
+		tech_pvt->dest_to = tech_pvt->dest;
+	}
 
+	attach_private(nsession, profile, tech_pvt, dest);
 
 	nchannel = switch_core_session_get_channel(nsession);
 	caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
@@ -2275,6 +2314,8 @@
 		//char *val;
 		//switch_channel_t *channel = switch_core_session_get_channel(session);
 		switch_ivr_transfer_variable(session, nsession, SOFIA_REPLACES_HEADER);
+		switch_ivr_transfer_variable(session, nsession, SOFIA_SIP_HEADER_PREFIX_T);
+
 	}
 
  done:
@@ -4457,8 +4498,15 @@
                         free(mydata);
                     }
                 }
-                break;
-            }
+			} else if (!strncasecmp(un->un_name, "X-", 2)) {
+				if (!switch_strlen_zero(un->un_value)) { 
+					char *new_name;
+					if ((new_name = switch_mprintf("%s%s", SOFIA_SIP_HEADER_PREFIX, (char *)un->un_name))) {
+						switch_channel_set_variable(channel, new_name, (char *)un->un_value);
+						free(new_name);
+					}
+				}
+			}
         }
 
         switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);

Modified: freeswitch/trunk/src/switch_ivr.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr.c	(original)
+++ freeswitch/trunk/src/switch_ivr.c	Mon Feb 12 20:22:17 2007
@@ -3693,8 +3693,15 @@
 	switch_channel_t *chana = switch_core_session_get_channel(sessa);
 	switch_channel_t *chanb = switch_core_session_get_channel(sessb);
 	char *val = NULL;
+	uint8_t prefix = 0;
 
-	if (var) {
+	if (var && *var == '~') {
+		var++;
+		prefix = 1;
+	}
+
+
+	if (var && !prefix) {
 		if ((val = switch_channel_get_variable(chana, var))) {
 			switch_channel_set_variable(chanb, var, val);
 		}
@@ -3705,7 +3712,7 @@
 
 		for (hi = switch_channel_variable_first(chana, switch_core_session_get_pool(sessa)); hi; hi = switch_hash_next(hi)) {
 			switch_hash_this(hi, &vvar, NULL, &vval);
-			if (vvar && vval) {
+			if (vvar && vval && (!prefix || (var && !strncmp((char *)vvar, var, strlen(var))))) {
 				switch_channel_set_variable(chanb, (char *) vvar, (char *) vval);
 			}
 		}



More information about the Freeswitch-svn mailing list