Browse Source

- added support for new jjanak API (fix_param).
New function t_replicate_to, t_relay_to, t_forward_nonack have 2 param, 1st is protocol, 2nd ip:port. Both support fix_param.
It enables set destination e.g. using an AVP

Tomas Mandys 19 years ago
parent
commit
0914a203aa
1 changed files with 164 additions and 8 deletions
  1. 164 8
      modules/tm/tm.c

+ 164 - 8
modules/tm/tm.c

@@ -116,6 +116,7 @@ MODULE_VERSION
 
 /* fixup functions */
 static int fixup_hostport2proxy(void** param, int param_no);
+static int fixup_proto_hostport2proxy(void** param, int param_no);
 static int fixup_on_failure(void** param, int param_no);
 static int fixup_on_reply(void** param, int param_no);
 static int fixup_on_branch(void** param, int param_no);
@@ -145,6 +146,7 @@ inline static int w_t_relay_to_tcp( struct sip_msg  *p_msg , char *proxy,
 inline static int w_t_relay_to_tls( struct sip_msg  *p_msg , char *proxy,
 				char *);
 #endif
+inline static int w_t_relay_to(struct sip_msg* msg, char* str,char*);
 inline static int w_t_replicate( struct sip_msg  *p_msg ,
 				char *proxy, /* struct proxy_l *proxy expected */
 				char *_foo       /* nothing expected */ );
@@ -161,6 +163,7 @@ inline static int w_t_replicate_tls( struct sip_msg  *p_msg ,
 				char *proxy, /* struct proxy_l *proxy expected */
 				char *_foo       /* nothing expected */ );
 #endif
+inline static int w_t_replicate_to(struct sip_msg* msg, char* str,char*);
 inline static int w_t_forward_nonack(struct sip_msg* msg, char* str, char* );
 inline static int w_t_forward_nonack_uri(struct sip_msg* msg, char* str,char*);
 inline static int w_t_forward_nonack_udp(struct sip_msg* msg, char* str,char*);
@@ -170,6 +173,7 @@ inline static int w_t_forward_nonack_tcp(struct sip_msg* msg, char* str,char*);
 #ifdef USE_TLS
 inline static int w_t_forward_nonack_tls(struct sip_msg* msg, char* str,char*);
 #endif
+inline static int w_t_forward_nonack_to(struct sip_msg* msg, char* str,char*);
 inline static int w_t_on_negative(struct sip_msg* msg, char *go_to, char *foo);
 inline static int w_t_on_branch(struct sip_msg* msg, char *go_to, char *foo);
 inline static int w_t_on_reply(struct sip_msg* msg, char *go_to, char *foo );
@@ -216,8 +220,12 @@ static cmd_export_t cmds[]={
 	{"t_replicate_tls",    w_t_replicate_tls,       2, fixup_hostport2proxy,
 			REQUEST_ROUTE},
 #endif
+	{"t_replicate_to", w_t_replicate_to,  		2, fixup_proto_hostport2proxy,
+			REQUEST_ROUTE},
 	{T_RELAY,              w_t_relay,               0, 0,
 			REQUEST_ROUTE | FAILURE_ROUTE },
+	{"t_relay_to", w_t_relay_to,  			2, fixup_proto_hostport2proxy,
+			REQUEST_ROUTE},
 	{T_FORWARD_NONACK,     w_t_forward_nonack,      2, fixup_hostport2proxy,
 			REQUEST_ROUTE},
 	{T_FORWARD_NONACK_URI, w_t_forward_nonack_uri,  0, 0,
@@ -232,6 +240,8 @@ static cmd_export_t cmds[]={
 	{T_FORWARD_NONACK_TLS, w_t_forward_nonack_tls,  2, fixup_hostport2proxy,
 			REQUEST_ROUTE},
 #endif
+	{"t_forward_nonack_to", w_t_forward_nonack_to,  2, fixup_proto_hostport2proxy,
+			REQUEST_ROUTE},
 	{"t_on_failure",       w_t_on_negative,         1, fixup_on_failure,
 			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
 	{"t_on_reply",         w_t_on_reply,            1, fixup_on_reply,
@@ -419,6 +429,19 @@ static int fixup_hostport2proxy(void** param, int param_no)
 	}
 }
 
+/* (char *$proto, char *$host:port) ==> (fparam, fparam)  */
+static int fixup_proto_hostport2proxy(void** param, int param_no) {
+	int ret;
+
+	ret = fix_param(FPARAM_AVP, param);
+	if (ret <= 0) return ret;
+/*	if (param_no = 1) {		FIXME: param_str currently does not offer INT/STR overloading
+                ret = fix_param(FPARAM_INT, param);
+		if (ret <= 0) return ret;
+	} */
+	return fix_param(FPARAM_ASCIIZ, param);
+}
+
 
 /***************************** init functions *****************************/
 static int w_t_unref( struct sip_msg *foo, void *bar)
@@ -606,9 +629,103 @@ inline static int w_t_check(struct sip_msg* msg, char* str, char* str2)
 	return t_check( msg , 0  ) ? 1 : -1;
 }
 
+inline static int str2proto(char *s, int len) {
+	if (len == 3 && !strncasecmp(s, "udp", 3))
+		return PROTO_UDP;
+	else if (len == 3 && !strncasecmp(s, "tcp", 3))  /* tcp&tls checks will be passed in getproto() */
+		return PROTO_TCP;
+	else if (len == 3 && !strncasecmp(s, "tls", 3))
+		return PROTO_TLS;	
+	else
+		return PROTO_NONE;
+}
+
+inline static struct proxy_l* t_protoaddr2proxy(char *proto_par, char *addr_par) {
+	struct proxy_l *proxy = 0;
+	avp_t* avp;
+	avp_value_t val;
+	int proto, port, err;
+	str s;
+	char *c;
+	
+	switch(((fparam_t *)proto_par)->type) {
+	case FPARAM_AVP:
+		if (!(avp = search_first_avp(((fparam_t *)proto_par)->v.avp.flags, ((fparam_t *)proto_par)->v.avp.name, &val, 0))) {
+			proto = PROTO_NONE;
+		} else {
+			if (avp->flags & AVP_VAL_STR) {
+				proto = str2proto(val.s.s, val.s.len);
+			}
+			else {
+	                        proto = val.n;
+			}
+		}
+                break;
+
+	case FPARAM_INT:
+		proto = ((fparam_t *)proto_par)->v.i;
+		break;
+	case FPARAM_ASCIIZ:
+		proto = str2proto( ((fparam_t *)proto_par)->v.asciiz, strlen(((fparam_t *)proto_par)->v.asciiz));
+		break;
+	default:
+		ERR("BUG: Invalid proto parameter value in t_protoaddr2proxy\n");
+		return 0;
+        }
+
+
+	switch(((fparam_t *)addr_par)->type) {
+	case FPARAM_AVP:
+		if (!(avp = search_first_avp(((fparam_t *)addr_par)->v.avp.flags, ((fparam_t *)addr_par)->v.avp.name, &val, 0))) {
+			s.len = 0;
+		} else {
+			if ((avp->flags & AVP_VAL_STR) == 0) {
+				LOG(L_ERR, "tm:t_protoaddr2proxy: avp <%.*s> value is not string\n",
+					((fparam_t *)addr_par)->v.avp.name.s.len, ((fparam_t *)addr_par)->v.avp.name.s.s);
+				return 0;
+			}
+			s = val.s;
+		}
+		break;
+
+	case FPARAM_ASCIIZ:
+		s.s = ((fparam_t *) addr_par)->v.asciiz;
+		s.len = strlen(s.s);
+		break;
+
+	default:
+		ERR("BUG: Invalid addr parameter value in t_protoaddr2proxy\n");
+		return 0;
+	}
+
+	port = 5060;
+	if (s.len) {
+		c = memchr(s.s, ':', s.len);
+		if (c) {
+			port = str2s(c+1, s.len-(c-s.s+1), &err);
+			if (err!=0) {
+				LOG(L_ERR, "tm:t_protoaddr2proxy: bad port number <%.*s>\n",
+					s.len, s.s);
+				 return 0;
+			}
+			s.len = c-s.s;
+		}
+	}
+	if (!s.len) {
+		LOG(L_ERR, "tm: protoaddr2proxy: host name is empty\n");
+		return 0;
+	}
+	proxy=mk_proxy(&s, port, proto);
+	if (proxy==0) {
+		LOG(L_ERR, "tm: protoaddr2proxy: bad host name in URI <%.*s>\n",
+			s.len, s.s );
+		return 0;
+	}
+	return proxy;
+}
 
-inline static int _w_t_forward_nonack(struct sip_msg* msg, char* proxy,
-																	int proto)
+inline static int _w_t_forward_nonack(struct sip_msg* msg, struct proxy_l* proxy,
+	int proto)
 {
 	struct cell *t;
 	if (t_check( msg , 0 )==-1) {
@@ -622,7 +739,7 @@ inline static int _w_t_forward_nonack(struct sip_msg* msg, char* proxy,
 			LOG(L_WARN,"WARNING: you don't really want to fwd hbh ACK\n");
 			return -1;
 		}
-		return t_forward_nonack(t, msg, ( struct proxy_l *) proxy, proto );
+		return t_forward_nonack(t, msg, proxy, proto );
 	} else {
 		DBG("DEBUG: forward_nonack: no transaction found\n");
 		return -1;
@@ -633,7 +750,7 @@ inline static int _w_t_forward_nonack(struct sip_msg* msg, char* proxy,
 inline static int w_t_forward_nonack( struct sip_msg* msg, char* proxy,
 										char* foo)
 {
-	return _w_t_forward_nonack(msg, proxy, PROTO_NONE);
+	return _w_t_forward_nonack(msg, ( struct proxy_l *) proxy, PROTO_NONE);
 }
 
 
@@ -647,7 +764,7 @@ inline static int w_t_forward_nonack_uri(struct sip_msg* msg, char *foo,
 inline static int w_t_forward_nonack_udp( struct sip_msg* msg, char* proxy,
 										char* foo)
 {
-	return _w_t_forward_nonack(msg, proxy, PROTO_UDP);
+	return _w_t_forward_nonack(msg, ( struct proxy_l *) proxy, PROTO_UDP);
 }
 
 
@@ -655,7 +772,7 @@ inline static int w_t_forward_nonack_udp( struct sip_msg* msg, char* proxy,
 inline static int w_t_forward_nonack_tcp( struct sip_msg* msg, char* proxy,
 										char* foo)
 {
-	return _w_t_forward_nonack(msg, proxy, PROTO_TCP);
+	return _w_t_forward_nonack(msg, ( struct proxy_l *) proxy, PROTO_TCP);
 }
 #endif
 
@@ -664,10 +781,23 @@ inline static int w_t_forward_nonack_tcp( struct sip_msg* msg, char* proxy,
 inline static int w_t_forward_nonack_tls( struct sip_msg* msg, char* proxy,
 										char* foo)
 {
-	return _w_t_forward_nonack(msg, proxy, PROTO_TLS);
+	return _w_t_forward_nonack(msg, proxy, ( struct proxy_l *) PROTO_TLS);
 }
 #endif
 
+inline static int w_t_forward_nonack_to( struct sip_msg  *p_msg ,
+	char *proto_par, 
+	char *addr_par   )
+{
+	struct proxy_l *proxy;
+	int r = -1;
+	proxy = t_protoaddr2proxy(proto_par, addr_par);
+	if (proxy) {
+		r = _w_t_forward_nonack(p_msg, proxy, proxy->proto);		
+		free_proxy(proxy);
+	}
+	return r;
+}
 
 static int get_param_val(int* code, char** reason, fparam_t* c, fparam_t* r) {
 
@@ -873,6 +1003,20 @@ inline static int w_t_relay_to_tls( struct sip_msg  *p_msg ,
 }
 #endif
 
+inline static int w_t_relay_to( struct sip_msg  *p_msg ,
+	char *proto_par, 
+	char *addr_par   )
+{
+	struct proxy_l *proxy;
+	int r = -1;
+	proxy = t_protoaddr2proxy(proto_par, addr_par);
+	if (proxy) {
+		r = _w_t_relay_to(p_msg, proxy);		
+		free_proxy(proxy);
+	}
+	return r;
+}
+
 
 inline static int w_t_replicate( struct sip_msg  *p_msg ,
 	char *proxy, /* struct proxy_l *proxy expected */
@@ -881,7 +1025,6 @@ inline static int w_t_replicate( struct sip_msg  *p_msg ,
 	return t_replicate(p_msg, ( struct proxy_l *) proxy, p_msg->rcv.proto );
 }
 
-
 inline static int w_t_replicate_udp( struct sip_msg  *p_msg ,
 	char *proxy, /* struct proxy_l *proxy expected */
 	char *_foo       /* nothing expected */ )
@@ -909,6 +1052,19 @@ inline static int w_t_replicate_tls( struct sip_msg  *p_msg ,
 }
 #endif
 
+inline static int w_t_replicate_to( struct sip_msg  *p_msg ,
+	char *proto_par, 
+	char *addr_par   )
+{
+	struct proxy_l *proxy;
+	int r = -1;
+	proxy = t_protoaddr2proxy(proto_par, addr_par);
+	if (proxy) {
+		r = t_replicate(p_msg, proxy, proxy->proto);		
+		free_proxy(proxy);
+	}
+	return r;
+}
 
 inline static int w_t_relay( struct sip_msg  *p_msg ,
 						char *_foo, char *_bar)