Bläddra i källkod

- more struct dest_info conversions (via_builder, tm: build_uac_req,
assemble_via a.s.o)
- basic support for comp=method (where mehtod=sigcomp|sergz) parsing
(via, various uris) and adding (via, rr lumps). The code is compiled
only if USE_COMP is defined. NOTE: for now the code is useless
(no compression code yet and no compression hooks), so by default it's
not compiled.

WARNING: lots of changes and very lightly tested

Andrei Pelinescu-Onciul 19 år sedan
förälder
incheckning
7a068ff3c5

+ 5 - 1
Makefile.defs

@@ -66,7 +66,7 @@ MAIN_NAME=ser
 VERSION = 0
 PATCHLEVEL = 10
 SUBLEVEL =   99
-EXTRAVERSION = -dev39
+EXTRAVERSION = -dev40
 
 SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
 			$(SUBLEVEL) )
@@ -335,6 +335,10 @@ endif
 # -DHAVE_RESOLV_RES
 #		support for changing some of the resolver parameters present
 #		 (_res structure in <resolv.h>)
+# -DUSE_COMP
+#		compiles in comp=[sergz|sigcomp] support (parsing uri & via, 
+#		adding it to via, lumps a.s.o). WARNING: right now this option
+#		is useless since the compression code doesn't exist yet.
 
 
 DEFS+= $(extra_defs) \

+ 5 - 1
action.c

@@ -146,7 +146,8 @@ int do_action(struct action* a, struct sip_msg* msg)
 				/*parse uri*/
 
 				if (msg->dst_uri.len) {
-					ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len, &next_hop);
+					ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len,
+									&next_hop);
 					u = &next_hop;
 				} else {
 					ret = parse_sip_msg_uri(msg);
@@ -212,6 +213,9 @@ int do_action(struct action* a, struct sip_msg* msg)
 					ret=E_BAD_ADDRESS;
 					goto error_fwd_uri;
 				}
+#ifdef USE_COMP
+				dst.comp=u->comp;
+#endif
 				ret=forward_request(msg, &dst);
 				if (ret>=0) ret=1;
 			}else if ((a->val[0].type==PROXY_ST) && (a->val[1].type==NUMBER_ST)){

+ 9 - 0
config.h

@@ -99,6 +99,15 @@
 #define TRANSPORT_PARAM ";transport="
 #define TRANSPORT_PARAM_LEN (sizeof(TRANSPORT_PARAM) - 1)
 
+#define COMP_PARAM ";comp="
+#define COMP_PARAM_LEN (sizeof(COMP_PARAM)-1)
+
+#define SIGCOMP_NAME "sigcomp"
+#define SIGCOMP_NAME_LEN (sizeof(SIGCOMP_NAME)-1)
+
+#define SERGZ_NAME "sergz"
+#define SERGZ_NAME_LEN (sizeof(SERGZ_NAME)-1)
+
 #define TOTAG_TOKEN ";tag="
 #define TOTAG_TOKEN_LEN (sizeof(TOTAG_TOKEN)-1)
 

+ 5 - 3
forward.c

@@ -49,6 +49,7 @@
  *  2005-12-11  onsend_router support; forward_request to no longer
  *              pkg_malloc'ed (andrei)
  *  2006-04-12  forward_{request,reply} use now struct dest_info (andrei)
+ *  2006-04-21  basic comp via param support (andrei)
  */
 
 
@@ -315,8 +316,7 @@ int forward_request(struct sip_msg* msg, struct dest_info* send_info)
 		}
 	}
 
-	buf = build_req_buf_from_sip_req(msg, &len, send_info->send_sock,
-											send_info->proto);
+	buf = build_req_buf_from_sip_req(msg, &len, send_info);
 	if (!buf){
 		LOG(L_ERR, "ERROR: forward_request: building failed\n");
 		goto error;
@@ -468,7 +468,9 @@ int forward_reply(struct sip_msg* msg)
 
 	dst.proto=msg->via2->proto;
 	if (update_sock_struct_from_via( &dst.to, msg, msg->via2 )==-1) goto error;
-
+#ifdef USE_COMP
+	dst.comp=msg->via2->comp_no;
+#endif
 
 #ifdef USE_TCP
 	if (dst.proto==PROTO_TCP

+ 32 - 9
ip_addr.h

@@ -30,6 +30,8 @@
  * --------
  *  2003-02-13  added struct dest_info (andrei)
  *  2003-04-06  all ports are stored/passed in host byte order now (andrei)
+ *  2006-04-20  comp support in recv_info and dest_info (andrei)
+ *  2006-04-21  added init_dst_from_rcv (andrei)
  */
 
 #ifndef ip_addr_h
@@ -46,7 +48,9 @@
 #include "dprint.h"
 
 enum sip_protos { PROTO_NONE, PROTO_UDP, PROTO_TCP, PROTO_TLS, PROTO_SCTP };
-
+#ifdef USE_COMP
+enum comp_methods { COMP_NONE, COMP_SIGCOMP, COMP_SERGZ };
+#endif
 
 struct ip_addr{
 	unsigned int af; /* address family: AF_INET6 or AF_INET */
@@ -100,21 +104,27 @@ struct receive_info{
 	struct ip_addr dst_ip;
 	unsigned short src_port; /* host byte order */
 	unsigned short dst_port; /* host byte order */
-	int proto;
 	int proto_reserved1; /* tcp stores the connection id here */
 	int proto_reserved2;
 	union sockaddr_union src_su; /* useful for replies*/
 	struct socket_info* bind_address; /* sock_info structure on which 
 									  the msg was received*/
+	short proto;
+#ifdef USE_COMP
+	short comp; /* compression */
+#endif
 	/* no need for dst_su yet */
 };
 
 
 struct dest_info{
-	int proto;
-	int id; /* tcp stores the connection id here */ 
-	union sockaddr_union to;
 	struct socket_info* send_sock;
+	union sockaddr_union to;
+	int id; /* tcp stores the connection id here */ 
+	short proto;
+#ifdef USE_COMP
+	short comp;
+#endif
 };
 
 
@@ -553,10 +563,23 @@ static inline struct hostent* ip_addr2he(str* name, struct ip_addr* ip)
 /* init a dest_info structure */
 #define init_dest_info(dst) \
 	do{ \
-		(dst)->proto=0; \
-		(dst)->id=0; \
-		(dst)->send_sock=0; \
-		memset(&(dst)->to, 0, sizeof(union sockaddr_union)); \
+		memset((dst), 0, sizeof(struct dest_info)); \
 	} while(0) 
 
+
+
+/* init a dest_info structure from a recv_info structure */
+inline static void init_dst_from_rcv(struct dest_info* dst,
+									struct receive_info* rcv)
+{
+		dst->send_sock=rcv->bind_address;
+		dst->to=rcv->src_su;
+		dst->id=rcv->proto_reserved1;
+		dst->proto=rcv->proto;
+#ifdef USE_COMP
+		dst->comp=rcv->comp;
+#endif
+}
+
+
 #endif

+ 7 - 0
modules/tm/sip_msg.c

@@ -46,6 +46,7 @@
  *  2003-05-07  received, rport & i via shortcuts are also translated (andrei)
  *  2003-11-11  updated cloning of lump_rpl (bogdan)
  *  2004-03-31  alias shortcuts are also translated (andrei)
+ *  2006-04-20  via->comp is also translated (andrei)
  */
 
 #include "defs.h"
@@ -154,6 +155,12 @@ inline struct via_body* via_body_cloner( char* new_buf,
 					case PARAM_ALIAS:
 							new_via->alias = new_vp;
 							break;
+							
+#ifdef USE_COMP
+					case PARAM_COMP:
+							new_via->comp = new_vp;
+							break;
+#endif
 				}
 
 				if (last_new_vp)

+ 3 - 1
modules/tm/t_funcs.c

@@ -230,7 +230,7 @@ int t_relay_to( struct sip_msg  *p_msg , struct proxy_l *proxy, int proto,
 		DBG( "SER: forwarding ACK  statelessly \n");
 		if (proxy==0) {
 			uri = GET_RURI(p_msg);
-			if (uri2dst(&dst, GET_NEXT_HOP(p_msg), proto)==0){
+			if (uri2dst(&dst, p_msg, GET_NEXT_HOP(p_msg), proto)==0){
 				ret=E_BAD_ADDRESS;
 				goto done;
 			}
@@ -239,6 +239,8 @@ int t_relay_to( struct sip_msg  *p_msg , struct proxy_l *proxy, int proto,
 			init_dest_info(&dst);
 			dst.proto=get_proto(proto, proxy->proto);
 			proxy2su(&dst.to, proxy);
+			/* dst->send_sock not set, but forward_request will take care
+			 * of it */
 			ret=forward_request( p_msg , &dst) ;
 		}
 		goto done;

+ 16 - 17
modules/tm/t_fwd.c

@@ -49,6 +49,7 @@
  *              already canceled transaction is attempted (andrei)
  *  2006-02-07  named routes support (andrei)
  *  2006-04-18  add_uac simplified + switched to struct dest_info (andrei)
+ *  2006-04-20  pint_uac_request uses now struct dest_info (andrei)
  */
 
 #include "defs.h"
@@ -98,9 +99,8 @@ unsigned int get_on_branch(void)
 }
 
 
-char *print_uac_request( struct cell *t, struct sip_msg *i_req,
-	int branch, str *uri, unsigned int *len, struct socket_info *send_sock,
-	enum sip_protos proto )
+static char *print_uac_request( struct cell *t, struct sip_msg *i_req,
+	int branch, str *uri, unsigned int *len, struct dest_info* dst)
 {
 	char *buf, *shbuf;
 	str* msg_uri;
@@ -139,7 +139,7 @@ char *print_uac_request( struct cell *t, struct sip_msg *i_req,
 	run_trans_callbacks( TMCB_REQUEST_FWDED , t, i_req, 0, -i_req->REQ_METHOD);
 
 	/* ... and build it now */
-	buf=build_req_buf_from_sip_req( i_req, len, send_sock, proto );
+	buf=build_req_buf_from_sip_req( i_req, len, dst);
 #ifdef DBG_MSG_QA
 	if (buf[*len-1]==0) {
 		LOG(L_ERR, "ERROR: print_uac_request: sanity check failed\n");
@@ -246,25 +246,26 @@ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
 		goto error;
 	}
 
-	init_dest_info(&t->uac[branch].request.dst);
 	/* check DNS resolution */
 	if (proxy){
 		/* dst filled from the proxy */
+		init_dest_info(&t->uac[branch].request.dst);
 		t->uac[branch].request.dst.proto=get_proto(proto, proxy->proto);
 		proxy2su(&t->uac[branch].request.dst.to, proxy);
+		/* fill dst send_sock */
+		t->uac[branch].request.dst.send_sock =
+		get_send_socket( request, &t->uac[branch].request.dst.to,
+								t->uac[branch].request.dst.proto);
 	}else {
-		/* dst filled from the uri */
-		if (uri2dst(&t->uac[branch].request.dst,
+		/* dst filled from the uri & request (send_socket) */
+		if (uri2dst(&t->uac[branch].request.dst, request,
 						next_hop ? next_hop: uri, proto)==0){
 			ret=E_BAD_ADDRESS;
 			goto error;
 		}
 	}
-
-	/* fill dst send_sock */
-	t->uac[branch].request.dst.send_sock =
-			get_send_socket( request, &t->uac[branch].request.dst.to,
-								t->uac[branch].request.dst. proto);
+	
+	/* check if send_sock is ok */
 	if (t->uac[branch].request.dst.send_sock==0) {
 		LOG(L_ERR, "ERROR: add_uac: can't fwd to af %d, proto %d "
 			" (no corresponding listening socket)\n",
@@ -276,8 +277,7 @@ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
 
 	/* now message printing starts ... */
 	shbuf=print_uac_request( t, request, branch, uri, 
-		&len, t->uac[branch].request.dst.send_sock, 
-			t->uac[branch].request.dst.proto );
+							&len, &t->uac[branch].request.dst);
 	if (!shbuf) {
 		ret=ser_error=E_OUT_OF_MEM;
 		goto error01;
@@ -322,9 +322,8 @@ int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel,
 
 	/* print */
 	shbuf=print_uac_request( t_cancel, cancel_msg, branch, 
-		&t_invite->uac[branch].uri, &len, 
-		t_invite->uac[branch].request.dst.send_sock,
-		t_invite->uac[branch].request.dst.proto);
+							&t_invite->uac[branch].uri, &len, 
+							&t_invite->uac[branch].request.dst);
 	if (!shbuf) {
 		LOG(L_ERR, "ERROR: e2e_cancel_branch: printing e2e cancel failed\n");
 		ret=ser_error=E_OUT_OF_MEM;

+ 3 - 2
modules/tm/t_fwd.h

@@ -45,9 +45,10 @@ typedef int (*taddblind_f)( /*struct cell *t */ );
 void t_on_branch(unsigned int go_to);
 unsigned int get_on_branch();
 int t_replicate(struct sip_msg *p_msg, struct proxy_l * proxy, int proto);
+/*  -- not use outside t_fwd.c for noe
 char *print_uac_request( struct cell *t, struct sip_msg *i_req,
-    int branch, str *uri, unsigned int *len, struct socket_info *send_sock,
-    enum sip_protos proto);
+    int branch, str *uri, unsigned int *len, struct dest_info *dst);
+*/
 void e2e_cancel( struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell *t_invite );
 int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell *t_invite, int branch );
 int add_uac(	struct cell *t, struct sip_msg *request, str *uri, str* next_hop,

+ 4 - 1
modules/tm/t_lookup.c

@@ -82,7 +82,6 @@
  * 2005-12-09  added t_set_fr()  (andrei)
  * 2006-01-27  transaction lookup function will set up a cancel flag
  *             if the searched transaction was pre-canceled (andrei)
- * 
  */
 
 #include "defs.h"
@@ -988,6 +987,7 @@ int init_rb( struct retr_buf *rb, struct sip_msg *msg)
 
 	/* rb. timers are init. init_t()/new_cell() */
 	via=msg->via1;
+	/* rb->dst is already init (0) by new_t()/build_cell() */
 	if (!reply_to_via) {
 		update_sock_struct_from_ip( &rb->dst.to, msg );
 		proto=msg->rcv.proto;
@@ -1003,6 +1003,9 @@ int init_rb( struct retr_buf *rb, struct sip_msg *msg)
 	}
 	rb->dst.proto=proto;
 	rb->dst.id=msg->rcv.proto_reserved1;
+#ifdef USE_COMP
+	rb->dst.comp=via->comp_no;
+#endif
 	/* turn off mhomed for generating replies -- they are ideally sent to where
 	   request came from to make life with NATs and other beasts easier
 	*/

+ 14 - 13
modules/tm/t_msgbuilder.c

@@ -38,6 +38,8 @@
  * 2003-10-02  added via_builder set host/port support (andrei)
  * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
  * 2004-02-13: t->is_invite and t->local replaced with flags (bogdan)
+ * 2006-04-21  build_uac_req, assemble_via use struct dest_info now;
+ *              uri2sock replaced with uri2dst (andrei)
  */
 
 #include "defs.h"
@@ -100,8 +102,8 @@ char *build_local(struct cell *Trans,unsigned int branch,
 	branch_str.s=branch_buf;
 	branch_str.len=branch_len;
 	set_hostport(&hp, (is_local(Trans))?0:(Trans->uas.request));
-	via=via_builder(&via_len, Trans->uac[branch].request.dst.send_sock,
-		&branch_str, 0, Trans->uac[branch].request.dst.proto, &hp );
+	via=via_builder(&via_len, &Trans->uac[branch].request.dst,
+		&branch_str, 0, &hp );
 	if (!via)
 	{
 		LOG(L_ERR, "ERROR: build_local: "
@@ -355,7 +357,7 @@ static inline int get_contact_uri(struct sip_msg* msg, str* uri)
 
      /*
       * The function creates an ACK to 200 OK. Route set will be created
-      * and parsed and next_hop parameter will contain uri the which the
+      * and parsed and next_hop parameter will contain the uri to which the
       * request should be send. The function is used by tm when it generates
       * local ACK to 200 OK (on behalf of applications using uac
       */
@@ -370,8 +372,7 @@ char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans, unsigned int branch
 	struct hostport hp;
 	struct rte* list;
 	str contact, ruri, *cont;
-	struct socket_info* send_sock;
-	union sockaddr_union to_su;
+	struct dest_info dst;
 	
 	if (get_contact_uri(rpl, &contact) < 0) {
 		return 0;
@@ -399,9 +400,8 @@ char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans, unsigned int branch
 	
 	
 	     /* via */
-	send_sock = uri2sock(rpl, next_hop, &to_su, PROTO_NONE);
-	if (!send_sock) {
-		LOG(L_ERR, "build_dlg_ack: no socket found\n");
+	if ((uri2dst(&dst, rpl, next_hop, PROTO_NONE)==0) || (dst.send_sock==0)){
+			LOG(L_ERR, "build_dlg_ack: no socket found\n");
 		goto error;
 	}
 	
@@ -409,7 +409,7 @@ char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans, unsigned int branch
 	branch_str.s = branch_buf;
 	branch_str.len = branch_len;
 	set_hostport(&hp, 0);
-	via = via_builder(&via_len, send_sock, &branch_str, 0, send_sock->proto, &hp);
+	via = via_builder(&via_len, &dst, &branch_str, 0, &hp);
 	if (!via) {
 		LOG(L_ERR, "build_dlg_ack: No via header got from builder\n");
 		goto error;
@@ -529,7 +529,8 @@ static inline int print_cseq_num(str* _s, dlg_t* _d)
 /*
  * Create Via header
  */
-static inline int assemble_via(str* dest, struct cell* t, struct socket_info* sock, int branch)
+static inline int assemble_via(str* dest, struct cell* t, 
+								struct dest_info* dst, int branch)
 {
 	static char branch_buf[MAX_BRANCH_PARAM_LEN];
 	char* via;
@@ -551,7 +552,7 @@ static inline int assemble_via(str* dest, struct cell* t, struct socket_info* so
 #endif
 
 	set_hostport(&hp, 0);
-	via = via_builder(&via_len, sock, &branch_str, 0, sock->proto, &hp);
+	via = via_builder(&via_len, dst, &branch_str, 0, &hp);
 	if (!via) {
 		LOG(L_ERR, "assemble_via: via building failed\n");
 		return -2;
@@ -674,7 +675,7 @@ static inline char* print_callid(char* w, dlg_t* dialog, struct cell* t)
  * Create a request
  */
 char* build_uac_req(str* method, str* headers, str* body, dlg_t* dialog, int branch, 
-			struct cell *t, int* len, struct socket_info* send_sock)
+			struct cell *t, int* len, struct dest_info* dst)
 {
 	char* buf, *w;
 	str content_length, cseq, via;
@@ -693,7 +694,7 @@ char* build_uac_req(str* method, str* headers, str* body, dlg_t* dialog, int bra
 	}
 	*len = method->len + 1 + dialog->hooks.request_uri->len + 1 + SIP_VERSION_LEN + CRLF_LEN;
 
-	if (assemble_via(&via, t, send_sock, branch) < 0) {
+	if (assemble_via(&via, t, dst, branch) < 0) {
 		LOG(L_ERR, "build_uac_req(): Error while assembling Via\n");
 		return 0;
 	}

+ 1 - 1
modules/tm/t_msgbuilder.h

@@ -89,7 +89,7 @@ char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans, unsigned int branch
  * Create a request
  */
 char* build_uac_req(str* method, str* headers, str* body, dlg_t* dialog, int branch, 
-		    struct cell *t, int* len, struct socket_info* send_sock);
+		    struct cell *t, int* len, struct dest_info* dst);
 
 
 int t_calc_branch(struct cell *t,

+ 1 - 4
modules/tm/t_reply.c

@@ -322,13 +322,10 @@ static int send_local_ack(struct sip_msg* msg, str* next_hop,
 		LOG(L_ERR, "send_local_ack: Invalid parameter value\n");
 		return -1;
 	}
-	init_dest_info(&dst);
-	dst.send_sock = uri2sock(msg, next_hop, &dst.to, PROTO_NONE);
-	if (!dst.send_sock) {
+	if ((uri2dst(&dst, msg,  next_hop, PROTO_NONE)==0) || (dst.send_sock==0)){
 		LOG(L_ERR, "send_local_ack: no socket found\n");
 		return -1;
 	}
-	dst.id=0;
 	return msg_send(&dst, ack, ack_len);
 }
 

+ 6 - 10
modules/tm/uac.c

@@ -170,8 +170,7 @@ static inline unsigned int dlg2hash( dlg_t* dlg )
 int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
 	  transaction_cb cb, void* cbp)
 {
-	struct socket_info* send_sock;
-	union sockaddr_union to_su;
+	struct dest_info dst;
 	struct cell *new_cell;
 	struct retr_buf *request;
 	char* buf;
@@ -189,8 +188,9 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
 	DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
 			dialog->hooks.next_hop->s);
 	/* it's a new message, so we will take the default socket */
-	send_sock = uri2sock(0, dialog->hooks.next_hop, &to_su, PROTO_NONE);
-	if (!send_sock) {
+	if ((uri2dst(&dst, 0, dialog->hooks.next_hop, PROTO_NONE)==0) ||
+			(dst.send_sock==0)){
+		ser_error = E_NO_SOCKET;
 		ret=ser_error;
 		LOG(L_ERR, "t_uac: no socket found\n");
 		goto error2;
@@ -233,11 +233,7 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
 
 	request = &new_cell->uac[0].request;
 	
-	init_dest_info(&request->dst);
-	request->dst.to = to_su;
-	request->dst.send_sock = send_sock;
-	request->dst.proto = send_sock->proto;
-	request->dst.id = 0;
+	request->dst = dst;
 
 	hi=dlg2hash(dialog);
 	LOCK_HASH(hi);
@@ -245,7 +241,7 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
 	UNLOCK_HASH(hi);
 
 	buf = build_uac_req(method, headers, body, dialog, 0, new_cell,
-		&buf_len, send_sock);
+		&buf_len, &dst);
 	if (!buf) {
 		LOG(L_ERR, "t_uac: Error while building message\n");
 		ret=E_OUT_OF_MEM;

+ 29 - 9
modules/tm/ut.h

@@ -135,13 +135,17 @@ inline static struct proxy_l *uri2proxy( str *uri, int proto )
 
 /*
  * Convert a URI into a dest_info structure
- * params: dst - will be filled
+ * params: msg - sip message used to set dst->send_sock, if 0 dst->send_sock
+ *               will be set to the default w/o using msg->force_send_socket 
+ *               (see get_send_socket()) 
+ *         dst - will be filled
  *         uri - uri in str form
  *         proto - if != PROTO_NONE, this protocol will be forced over the
  *                 uri_proto, otherwise the uri proto will be used
  * returns 0 on error, dst on success
  */
-inline static struct dest_info *uri2dst(struct dest_info* dst, str *uri, 
+inline static struct dest_info *uri2dst(struct dest_info* dst,
+										struct sip_msg *msg, str *uri, 
 											int proto )
 {
 	struct sip_uri parsed_uri;
@@ -165,37 +169,53 @@ inline static struct dest_info *uri2dst(struct dest_info* dst, str *uri,
 	
 	init_dest_info(dst);
 	dst->proto= get_proto(proto, uri_proto);
+#ifdef USE_COMP
+	dst->comp=parsed_uri.comp;
+#endif
 	sip_hostport2su(&dst->to, &parsed_uri.host, parsed_uri.port_no,
 						dst->proto);
+	if (msg){
+		dst->send_sock = get_send_socket(msg, &dst->to, dst->proto);
+		if (dst->send_sock==0) {
+			LOG(L_ERR, "ERROR: uri2sock: no corresponding socket for af %d\n", 
+					dst->to.s.sa_family);
+			/* ser_error = E_NO_SOCKET;*/
+			/* try to continue */
+		}
+	}
 	return dst;
 }
 
 
 
 /*
- * Convert a URI into socket_info
+ * Convert a URI into the corresponding sockaddr_union (address to send to) and
+ *  send socket_info (socket/address from which to send)
+ *  to_su is filled with the destination and the socket_info that will be 
+ *  used for sending is returned.
+ *  On error return 0.
+ *
+ *  NOTE: this function is deprecated, you should use uri2dst instead
  */
 static inline struct socket_info *uri2sock(struct sip_msg* msg, str *uri,
 									union sockaddr_union *to_su, int proto)
 {
-	struct socket_info* send_sock;
 	struct dest_info dst;
 
-	if (uri2dst(&dst, uri, proto)==0){
+	if (uri2dst(&dst, msg, uri, proto)==0){
 		LOG(L_ERR, "ERROR: uri2sock: Can't create a dst proxy\n");
 		ser_error=E_BAD_ADDRESS;
 		return 0;
 	}
 	*to_su=dst.to; /* copy su */
 	
-	/* we use dst->proto since uri2dst just set it correctly*/
-	send_sock = get_send_socket(msg, to_su, dst.proto);
-	if (!send_sock) {
+	/* we use dst->send_socket since uri2dst just set it correctly*/
+	if (dst.send_sock==0) {
 		LOG(L_ERR, "ERROR: uri2sock: no corresponding socket for af %d\n", 
 		    to_su->s.sa_family);
 		ser_error = E_NO_SOCKET;
 	}
-	return send_sock;
+	return dst.send_sock;
 }
 
 

+ 195 - 38
msg_translator.c

@@ -56,6 +56,9 @@
  * 2003-10-08  receive_test function-alized (jiri)
  * 2003-10-20  added body_lump list (sip_msg), adjust_clen (andrei & jan)
  * 2003-11-11  type of rpl_lumps replaced by flags (bogdan)
+ * 2006-04-20  build_req_from_sip_req, via_builder and lump_* functions
+ *              use now struct dest_info; lumps & via comp param support
+ *              (rfc3486) (andrei)
  *
  */
 /* Via special params:
@@ -436,7 +439,7 @@ char* clen_builder(struct sip_msg* msg, int *clen_len, int diff)
  * returns 1 if cond is true, 0 if false */
 static inline int lump_check_opt(	enum lump_conditions cond,
 									struct sip_msg* msg,
-									struct socket_info* snd_s
+									struct dest_info* snd_i
 									)
 {
 	struct ip_addr* ip;
@@ -444,7 +447,7 @@ static inline int lump_check_opt(	enum lump_conditions cond,
 	int proto;
 
 #define get_ip_port_proto \
-			if (snd_s==0){ \
+			if ((snd_i==0) || (snd_i->send_sock==0)){ \
 				LOG(L_CRIT, "ERROR: lump_check_opt: null send socket\n"); \
 				return 1; /* we presume they are different :-) */ \
 			} \
@@ -466,30 +469,34 @@ static inline int lump_check_opt(	enum lump_conditions cond,
 		case COND_IF_DIFF_REALMS:
 			get_ip_port_proto;
 			/* faster tests first */
-			if ((port==snd_s->port_no)&&(proto==snd_s->proto)&&
-				(ip_addr_cmp(ip, &snd_s->address)))
+			if ((port==snd_i->send_sock->port_no) && 
+					(proto==snd_i->send_sock->proto) &&
+#ifdef USE_COMP
+					(msg->rcv.comp==snd_i->comp) &&
+#endif
+					(ip_addr_cmp(ip, &snd_i->send_sock->address)))
 				return 0;
 			else return 1;
 		case COND_IF_DIFF_AF:
 			get_ip_port_proto;
-			if (ip->af!=snd_s->address.af) return 1;
+			if (ip->af!=snd_i->send_sock->address.af) return 1;
 			else return 0;
 		case COND_IF_DIFF_PROTO:
 			get_ip_port_proto;
-			if (proto!=snd_s->proto) return 1;
+			if (proto!=snd_i->send_sock->proto) return 1;
 			else return 0;
 		case COND_IF_DIFF_PORT:
 			get_ip_port_proto;
-			if (port!=snd_s->port_no) return 1;
+			if (port!=snd_i->send_sock->port_no) return 1;
 			else return 0;
 		case COND_IF_DIFF_IP:
 			get_ip_port_proto;
-			if (ip_addr_cmp(ip, &snd_s->address)) return 0;
+			if (ip_addr_cmp(ip, &snd_i->send_sock->address)) return 0;
 			else return 1;
 		case COND_IF_RAND:
 			return (rand()>=RAND_MAX/2);
 		default:
-			LOG(L_CRIT, "BUG: lump_check_opt: unknown lump condition %d\n",
+			LOG(L_CRIT, "BUG: lump:w_check_opt: unknown lump condition %d\n",
 					cond);
 	}
 	return 0; /* false */
@@ -499,7 +506,8 @@ static inline int lump_check_opt(	enum lump_conditions cond,
 
 /* computes the "unpacked" len of a lump list,
    code moved from build_req_from_req */
-static inline int lumps_len(struct sip_msg* msg, struct lump* lumps, struct socket_info* send_sock)
+static inline int lumps_len(struct sip_msg* msg, struct lump* lumps, 
+								struct dest_info* send_info)
 {
 	int s_offset;
 	int new_len;
@@ -507,7 +515,46 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps, struct sock
 	struct lump* r;
 	str* send_address_str;
 	str* send_port_str;
+	struct socket_info* send_sock;
+	
+
+#ifdef USE_COMP
+	#define RCVCOMP_LUMP_LEN \
+						/* add;comp=xxx */ \
+					switch(msg->rcv.comp){ \
+						case COMP_NONE: \
+								break; \
+						case COMP_SIGCOMP: \
+								new_len+=COMP_PARAM_LEN+SIGCOMP_NAME_LEN; \
+								break; \
+						case COMP_SERGZ: \
+								new_len+=COMP_PARAM_LEN+SERGZ_NAME_LEN ; \
+								break; \
+						default: \
+						LOG(L_CRIT, "BUG: lumps_len: unknown comp %d\n", \
+								msg->rcv.comp); \
+					}
 
+	#define SENDCOMP_LUMP_LEN \
+					/* add;comp=xxx */ \
+					switch(send_info->comp){ \
+						case COMP_NONE: \
+								break; \
+						case COMP_SIGCOMP: \
+								new_len+=COMP_PARAM_LEN+SIGCOMP_NAME_LEN; \
+								break; \
+						case COMP_SERGZ: \
+								new_len+=COMP_PARAM_LEN+SERGZ_NAME_LEN ; \
+								break; \
+						default: \
+						LOG(L_CRIT, "BUG: lumps_len: unknown comp %d\n", \
+								send_info->comp); \
+					}
+#else
+	#define RCVCOMP_LUMP_LEN
+	#define SENDCOMP_LUMP_LEN
+#endif /*USE_COMP */
+	
 #define SUBST_LUMP_LEN(subst_l) \
 		switch((subst_l)->u.subst){ \
 			case SUBST_RCV_IP: \
@@ -574,6 +621,7 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps, struct sock
 						LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
 								msg->rcv.bind_address->proto); \
 					}\
+					RCVCOMP_LUMP_LEN \
 				}else{ \
 					/* FIXME */ \
 					LOG(L_CRIT, "FIXME: null bind_address\n"); \
@@ -646,6 +694,7 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps, struct sock
 						LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
 								send_sock->proto); \
 					}\
+					SENDCOMP_LUMP_LEN \
 				}else{ \
 					/* FIXME */ \
 					LOG(L_CRIT, "FIXME: lumps_len called with" \
@@ -658,7 +707,12 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps, struct sock
 				LOG(L_CRIT, "BUG: unknown subst type %d\n", \
 						(subst_l)->u.subst); \
 		}
-
+	
+	if (send_info){
+		send_sock=send_info->send_sock;
+	}else{
+		send_sock=0;
+	};
 	s_offset=0;
 	new_len=0;
 	/* init send_address_str & send_port_str */
@@ -674,7 +728,7 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps, struct sock
 
 	for(t=lumps;t;t=t->next){
 		/* skip if this is an OPT lump and the condition is not satisfied */
-		if ((t->op==LUMP_ADD_OPT) && !lump_check_opt(t->u.cond, msg, send_sock))
+		if ((t->op==LUMP_ADD_OPT)&& !lump_check_opt(t->u.cond, msg, send_info))
 			continue;
 		for(r=t->before;r;r=r->before){
 			switch(r->op){
@@ -687,7 +741,7 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps, struct sock
 				case LUMP_ADD_OPT:
 					/* skip if this is an OPT lump and the condition is
 					 * not satisfied */
-					if (!lump_check_opt(r->u.cond, msg, send_sock))
+					if (!lump_check_opt(r->u.cond, msg, send_info))
 						goto skip_before;
 					break;
 				default:
@@ -743,7 +797,7 @@ skip_before:
 				case LUMP_ADD_OPT:
 					/* skip if this is an OPT lump and the condition is
 					 * not satisfied */
-					if (!lump_check_opt(r->u.cond, msg, send_sock))
+					if (!lump_check_opt(r->u.cond, msg, send_info))
 						goto skip_after;
 					break;
 				default:
@@ -756,6 +810,8 @@ skip_after:
 		; /* to make gcc 3.* happy */
 	}
 	return new_len;
+#undef RCVCOMP_LUMP_LEN
+#undef SENDCOMP_LUMP_LEN
 }
 
 
@@ -768,7 +824,7 @@ static inline void process_lumps(	struct sip_msg* msg,
 									char* new_buf,
 									unsigned int* new_buf_offs,
 									unsigned int* orig_offs,
-									struct socket_info* send_sock)
+									struct dest_info* send_info)
 {
 	struct lump *t;
 	struct lump *r;
@@ -778,6 +834,58 @@ static inline void process_lumps(	struct sip_msg* msg,
 	int s_offset;
 	str* send_address_str;
 	str* send_port_str;
+	struct socket_info* send_sock;
+
+#ifdef USE_COMP
+	#define RCVCOMP_PARAM_ADD \
+				/* add ;comp=xxxx */ \
+				switch(msg->rcv.comp){ \
+					case COMP_NONE: \
+						break; \
+					case COMP_SIGCOMP: \
+						memcpy(new_buf+offset, COMP_PARAM, COMP_PARAM_LEN);\
+						offset+=COMP_PARAM_LEN; \
+						memcpy(new_buf+offset, SIGCOMP_NAME, \
+								SIGCOMP_NAME_LEN); \
+						offset+=SIGCOMP_NAME_LEN; \
+						break; \
+					case COMP_SERGZ: \
+						memcpy(new_buf+offset, COMP_PARAM, COMP_PARAM_LEN);\
+						offset+=COMP_PARAM_LEN; \
+						memcpy(new_buf+offset, SERGZ_NAME, SERGZ_NAME_LEN); \
+						offset+=SERGZ_NAME_LEN; \
+						break;\
+					default:\
+						LOG(L_CRIT, "BUG: process_lumps: unknown comp %d\n", \
+								msg->rcv.comp); \
+				}
+	
+	#define SENDCOMP_PARAM_ADD \
+				/* add ;comp=xxxx */ \
+				switch(send_info->comp){ \
+					case COMP_NONE: \
+						break; \
+					case COMP_SIGCOMP: \
+						memcpy(new_buf+offset, COMP_PARAM, COMP_PARAM_LEN);\
+						offset+=COMP_PARAM_LEN; \
+						memcpy(new_buf+offset, SIGCOMP_NAME, \
+								SIGCOMP_NAME_LEN); \
+						offset+=SIGCOMP_NAME_LEN; \
+						break; \
+					case COMP_SERGZ: \
+						memcpy(new_buf+offset, COMP_PARAM, COMP_PARAM_LEN);\
+						offset+=COMP_PARAM_LEN; \
+						memcpy(new_buf+offset, SERGZ_NAME, SERGZ_NAME_LEN); \
+						offset+=SERGZ_NAME_LEN; \
+						break;\
+					default:\
+						LOG(L_CRIT, "BUG: process_lumps: unknown comp %d\n", \
+								msg->rcv.comp); \
+				} 
+#else
+	#define RCVCOMP_PARAM_ADD
+	#define SENDCOMP_PARAM_ADD
+#endif /* USE_COMP */
 
 #define SUBST_LUMP(subst_l) \
 	switch((subst_l)->u.subst){ \
@@ -856,6 +964,7 @@ static inline void process_lumps(	struct sip_msg* msg,
 						LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
 								msg->rcv.bind_address->proto); \
 				} \
+				RCVCOMP_PARAM_ADD \
 			}else{  \
 				/*FIXME*/ \
 				LOG(L_CRIT, "FIXME: process_lumps: null bind_address\n"); \
@@ -942,6 +1051,7 @@ static inline void process_lumps(	struct sip_msg* msg,
 						LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
 								send_sock->proto); \
 				} \
+				SENDCOMP_PARAM_ADD \
 			}else{  \
 				/*FIXME*/ \
 				LOG(L_CRIT, "FIXME: process_lumps: null bind_address\n"); \
@@ -1008,11 +1118,15 @@ static inline void process_lumps(	struct sip_msg* msg,
 			}; \
 			break; \
 		default: \
-					LOG(L_CRIT, "BUG: process_lumps: unknown subst type %d\n", \
+				LOG(L_CRIT, "BUG: process_lumps: unknown subst type %d\n", \
 							(subst_l)->u.subst); \
-	} \
- \
+	}
 
+	if (send_info){
+		send_sock=send_info->send_sock;
+	}else{
+		send_sock=0;
+	}
 	/* init send_address_str & send_port_str */
 	if (msg->set_global_address.len)
 		send_address_str=&(msg->set_global_address);
@@ -1036,7 +1150,7 @@ static inline void process_lumps(	struct sip_msg* msg,
 				/* skip if this is an OPT lump and the condition is
 				 * not satisfied */
 				if ((t->op==LUMP_ADD_OPT) &&
-						(!lump_check_opt(t->u.cond, msg, send_sock)))
+						(!lump_check_opt(t->u.cond, msg, send_info)))
 					continue;
 				/* just add it here! */
 				/* process before  */
@@ -1053,7 +1167,7 @@ static inline void process_lumps(	struct sip_msg* msg,
 						case LUMP_ADD_OPT:
 							/* skip if this is an OPT lump and the condition is
 					 		* not satisfied */
-							if (!lump_check_opt(r->u.cond, msg, send_sock))
+							if (!lump_check_opt(r->u.cond, msg, send_info))
 								goto skip_before;
 							break;
 						default:
@@ -1094,7 +1208,7 @@ skip_before:
 						case LUMP_ADD_OPT:
 							/* skip if this is an OPT lump and the condition is
 					 		* not satisfied */
-							if (!lump_check_opt(r->u.cond, msg, send_sock))
+							if (!lump_check_opt(r->u.cond, msg, send_info))
 								goto skip_after;
 							break;
 						default:
@@ -1135,7 +1249,7 @@ skip_after:
 						case LUMP_ADD_OPT:
 							/* skip if this is an OPT lump and the condition is
 					 		* not satisfied */
-							if (!lump_check_opt(r->u.cond, msg, send_sock))
+							if (!lump_check_opt(r->u.cond, msg, send_info))
 								goto skip_nop_before;
 							break;
 						default:
@@ -1164,7 +1278,7 @@ skip_nop_before:
 						case LUMP_ADD_OPT:
 							/* skip if this is an OPT lump and the condition is
 					 		* not satisfied */
-							if (!lump_check_opt(r->u.cond, msg, send_sock))
+							if (!lump_check_opt(r->u.cond, msg, send_info))
 								goto skip_nop_after;
 							break;
 						default:
@@ -1182,6 +1296,8 @@ skip_nop_after:
 	}
 	*new_buf_offs=offset;
 	*orig_offs=s_offset;
+#undef RCVCOMP_PARAM_ADD 
+#undef SENDCOMP_PARAM_ADD
 }
 
 
@@ -1285,7 +1401,7 @@ error:
 
 char * build_req_buf_from_sip_req( struct sip_msg* msg,
 								unsigned int *returned_len,
-								struct socket_info* send_sock, int proto)
+								struct dest_info* send_info)
 {
 	unsigned int len, new_len, received_len, rport_len, uri_len, via_len, body_delta;
 	char* line_buf;
@@ -1343,8 +1459,8 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
 	     /* Calculate message body difference and adjust
 	      * Content-Length
 	      */
-	body_delta = lumps_len(msg, msg->body_lumps, send_sock);
-	if (adjust_clen(msg, body_delta, proto) < 0) {
+	body_delta = lumps_len(msg, msg->body_lumps, send_info);
+	if (adjust_clen(msg, body_delta, send_info->proto) < 0) {
 		LOG(L_ERR, "ERROR: build_req_buf_from_sip_req: Error while adjusting"
 				" Content-Length\n");
 		goto error00;
@@ -1353,8 +1469,8 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
 	branch.s=msg->add_to_branch_s;
 	branch.len=msg->add_to_branch_len;
 	set_hostport(&hp, msg);
-	line_buf = via_builder( &via_len, send_sock, &branch,
-							extra_params.len?&extra_params:0, proto, &hp);
+	line_buf = via_builder( &via_len, send_info, &branch,
+							extra_params.len?&extra_params:0, &hp);
 	if (!line_buf){
 		LOG(L_ERR,"ERROR: build_req_buf_from_sip_req: no via received!\n");
 		goto error00;
@@ -1441,7 +1557,7 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
 	}
 
 	/* compute new msg len and fix overlapping zones*/
-	new_len=len+body_delta+lumps_len(msg, msg->add_rm, send_sock);
+	new_len=len+body_delta+lumps_len(msg, msg->add_rm, send_info);
 #ifdef XL_DEBUG
 	LOG(L_ERR, "DEBUG: new_len(%d)=len(%d)+lumps_len\n", new_len, len);
 #endif
@@ -1471,8 +1587,8 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
 	}
 	new_buf[new_len]=0;
 	/* copy msg adding/removing lumps */
-	process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_sock);
-	process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset,send_sock);
+	process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info);
+	process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset,send_info);
 	/* copy the rest of the message */
 	memcpy(new_buf+offset, buf+s_offset, len-s_offset);
 	new_buf[new_len]=0;
@@ -1931,16 +2047,24 @@ int branch_builder( unsigned int hash_index,
 }
 
 
+
+/* uses only the send_info->send_socket, send_info->proto and 
+ * send_info->comp (so that a send_info used for sending can be passed
+ * to this function w/o changes and the correct via will be built) */
 char* via_builder( unsigned int *len,
-	struct socket_info* send_sock,
-	str* branch, str* extra_params, int proto, struct hostport* hp)
+	struct dest_info* send_info /* where to send the reply */,
+	str* branch, str* extra_params, struct hostport* hp)
 {
 	unsigned int  via_len, extra_len;
 	char               *line_buf;
 	int max_len;
 	str* address_str; /* address displayed in via */
 	str* port_str; /* port no displayed in via */
+	struct socket_info* send_sock;
+	int comp_len, comp_name_len;
+	char* comp_name;
 
+	send_sock=send_info->send_sock;
 	/* use pre-set address in via or the outbound socket one */
 	if ( hp && hp->host->len)
 		address_str=hp->host;
@@ -1950,12 +2074,36 @@ char* via_builder( unsigned int *len,
 		port_str=hp->port;
 	else
 		port_str=&(send_sock->port_no_str);
-
+	
+	comp_len=comp_name_len=0;
+	comp_name=0;
+#ifdef USE_COMP
+	switch(send_info->comp){
+		case COMP_NONE:
+			break;
+		case COMP_SIGCOMP:
+			comp_len=COMP_PARAM_LEN;
+			comp_name_len=SIGCOMP_NAME_LEN;
+			comp_name=SIGCOMP_NAME;
+			break;
+		case COMP_SERGZ:
+			comp_len=COMP_PARAM_LEN;
+			comp_name_len=SERGZ_NAME_LEN;
+			comp_name=SERGZ_NAME;
+			break;
+		default:
+			LOG(L_CRIT, "BUG: via_builder: unknown comp %d\n",
+					send_info->comp);
+			/* continue, we'll just ignore comp */
+	}
+#endif /* USE_COMP */
+			
 	max_len=MY_VIA_LEN+address_str->len /* space in MY_VIA */
 		+2 /* just in case it is a v6 address ... [ ] */
 		+1 /*':'*/+port_str->len
 		+(branch?(MY_BRANCH_LEN+branch->len):0)
 		+(extra_params?extra_params->len:0)
+		+comp_len+comp_name_len
 		+CRLF_LEN+1;
 	line_buf=pkg_malloc( max_len );
 	if (line_buf==0){
@@ -1969,14 +2117,14 @@ char* via_builder( unsigned int *len,
 	via_len=MY_VIA_LEN+address_str->len; /*space included in MY_VIA*/
 
 	memcpy(line_buf, MY_VIA, MY_VIA_LEN);
-	if (proto==PROTO_UDP){
+	if (send_info->proto==PROTO_UDP){
 		/* do nothing */
-	}else if (proto==PROTO_TCP){
+	}else if (send_info->proto==PROTO_TCP){
 		memcpy(line_buf+MY_VIA_LEN-4, "TCP ", 4);
-	}else if (proto==PROTO_TLS){
+	}else if (send_info->proto==PROTO_TLS){
 		memcpy(line_buf+MY_VIA_LEN-4, "TLS ", 4);
 	}else{
-		LOG(L_CRIT, "BUG: via_builder: unknown proto %d\n", proto);
+		LOG(L_CRIT, "BUG: via_builder: unknown proto %d\n", send_info->proto);
 		return 0;
 	}
 #	ifdef USE_IPV6
@@ -2009,6 +2157,15 @@ char* via_builder( unsigned int *len,
 		memcpy(line_buf+via_len, extra_params->s, extra_params->len);
 		via_len+=extra_params->len;
 	}
+#ifdef USE_COMP
+	/* comp */
+	if (comp_len){
+		memcpy(line_buf+via_len, COMP_PARAM, COMP_PARAM_LEN);
+		via_len+=COMP_PARAM_LEN;
+		memcpy(line_buf+via_len, comp_name, comp_name_len);
+		via_len+=comp_name_len;
+	}
+#endif
 
 	memcpy(line_buf+via_len, CRLF, CRLF_LEN);
 	via_len+=CRLF_LEN;

+ 3 - 4
msg_translator.h

@@ -76,8 +76,7 @@ struct hostport {
 	}while(0)
 
 char * build_req_buf_from_sip_req (	struct sip_msg* msg, 
-				unsigned int *returned_len, struct socket_info* send_sock,
-				int proto);
+				unsigned int *returned_len, struct dest_info* send_info);
 
 char * build_res_buf_from_sip_res(	struct sip_msg* msg,
 				unsigned int *returned_len);
@@ -103,8 +102,8 @@ char * build_res_buf_with_body_from_sip_req(	unsigned int code ,
 				struct bookmark *bmark);
 */
 char* via_builder( unsigned int *len,
-	struct socket_info* send_sock,
-	str *branch, str* extra_params, int proto, struct hostport *hp );
+	struct dest_info* send_info,
+	str *branch, str* extra_params, struct hostport *hp );
 
 
 int branch_builder( unsigned int hash_index, 

+ 4 - 0
parser/msg_parser.h

@@ -38,6 +38,7 @@
  *  2003-11-02  added diversion header field to sip_msg (jh)
  *  2004-11-08  added force_send_socket (andrei)
  *  2005-02-25  uri types added (sip, sips & tel)  (andrei)
+ *  2006-04-20  uri comp member (only if USE_COMP is defined) (andrei)
  */
 
 
@@ -140,6 +141,9 @@ struct sip_uri {
 	unsigned short port_no;
 	unsigned short proto; /* from transport */
 	uri_type type; /* uri scheme */
+#ifdef USE_COMP
+	unsigned short comp;
+#endif
 	/* parameters */
 	str transport;
 	str ttl;

+ 128 - 1
parser/parse_uri.c

@@ -35,6 +35,7 @@
  * 2003-07-03  sips:, r2, lr=on support added (andrei)
  * 2005-02-25  preliminary tel uri support (andrei)
  * 2005-03-03  more tel uri fixes (andrei)
+ * 2006-04-20  comp uri param. support (rfc3486) if defined USE_COMP  (andrei)
  */
 
 
@@ -73,6 +74,19 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 					PLR_L, PLR_R_FIN, PLR_eq,
 					/* r2 */
 					PR2_R, PR2_2_FIN, PR2_eq,
+#ifdef USE_COMP
+					/* comp */
+					PCOMP_C, PCOMP_O, PCOMP_M, PCOMP_P, PCOMP_eq,
+					
+					/* comp values */
+					/* sigcomp */
+					VCOMP_S, VCOMP_SIGC_I, VCOMP_SIGC_G,
+					VCOMP_SIGC_C, VCOMP_SIGC_O,  VCOMP_SIGC_M,
+					VCOMP_SIGC_P_FIN,
+					/* sergz */
+							VCOMP_SGZ_E, VCOMP_SGZ_R, VCOMP_SGZ_G,
+							VCOMP_SGZ_Z_FIN,
+#endif
 					
 					/* transport values */
 					/* udp */
@@ -100,6 +114,10 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 	int error_headers;
 	unsigned int scheme;
 	uri_type backup;
+#ifdef USE_COMP
+	str comp_str; /* not returned for now */
+	str comp_val; /* not returned for now */
+#endif
 	
 #define SIP_SCH		0x3a706973
 #define SIPS_SCH	0x73706973
@@ -313,7 +331,30 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 				} \
 				break
 			
-	
+
+#ifdef USE_COMP
+#define comp_fin(c_state, comp_no) \
+			case c_state: \
+				switch(*p){ \
+					case '@': \
+						still_at_user; \
+						break; \
+					semicolon_case; \
+						/* param_set(b, v); */ \
+						uri->comp=(comp_no); \
+						break; \
+					question_case; \
+						/* param_set(b, v) */; \
+						uri->comp=(comp_no); \
+						break; \
+					colon_case;  \
+					default: \
+						state=URI_VAL_P; \
+						break; \
+				} \
+				break
+			
+#endif
 
 	/* init */
 	end=buf+len;
@@ -579,6 +620,13 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 						b=p;
 						state=PR2_R;
 						break;
+#ifdef USE_COMP
+					case 'c':
+					case 'C':
+						b=p;
+						state=PCOMP_C;
+						break;
+#endif
 					default:
 						state=URI_PARAM_P;
 				}
@@ -784,6 +832,44 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 						state=URI_VAL_P;
 				}
 				break;
+#ifdef USE_COMP
+			param_switch(PCOMP_C,  'o', 'O' , PCOMP_O);
+			param_switch(PCOMP_O,  'm', 'M' , PCOMP_M);
+			param_switch(PCOMP_M,  'p', 'P' , PCOMP_P);
+			param_switch1(PCOMP_P,  '=', PCOMP_eq);
+			/* value */
+			case PCOMP_eq:
+				param=&comp_str;
+				param_val=&comp_val;
+				switch (*p){
+					param_common_cases;
+					case 's':
+					case 'S':
+						v=p;
+						state=VCOMP_S;
+						break;
+					default:
+						v=p;
+						state=URI_VAL_P;
+				}
+				break;
+			/* sigcomp*/
+			value_switch_big(VCOMP_S, 'i', 'I', 'e', 'E',
+									VCOMP_SIGC_I, VCOMP_SGZ_E);
+			value_switch(VCOMP_SIGC_I, 'g', 'G', VCOMP_SIGC_G);
+			value_switch(VCOMP_SIGC_G, 'c', 'C', VCOMP_SIGC_C);
+			value_switch(VCOMP_SIGC_C, 'o', 'O', VCOMP_SIGC_O);
+			value_switch(VCOMP_SIGC_O, 'm', 'M', VCOMP_SIGC_M);
+			value_switch(VCOMP_SIGC_M, 'p', 'P', VCOMP_SIGC_P_FIN);
+			comp_fin(VCOMP_SIGC_P_FIN, COMP_SIGCOMP);
+			
+			/* sergz*/
+			value_switch(VCOMP_SGZ_E, 'r', 'R', VCOMP_SGZ_R);
+			value_switch(VCOMP_SGZ_R, 'g', 'G', VCOMP_SGZ_G);
+			value_switch(VCOMP_SGZ_G, 'z', 'Z', VCOMP_SGZ_Z_FIN);
+			comp_fin(VCOMP_SGZ_Z_FIN, COMP_SERGZ);
+#endif
+				
 				
 				
 			case URI_HEADERS:
@@ -893,6 +979,13 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 		case PM_eq:
 		case PLR_L: /* lr */
 		case PR2_R:  /* r2 */
+#ifdef USE_COMP
+		case PCOMP_C:
+		case PCOMP_O:
+		case PCOMP_M:
+		case PCOMP_P:
+		case PCOMP_eq:
+#endif
 			uri->params.s=s;
 			uri->params.len=p-s;
 			break;
@@ -925,6 +1018,22 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 			uri->params.len=p-s;
 			param_set(b, v);
 			break;
+#ifdef USE_COMP
+		case VCOMP_S:
+		case VCOMP_SIGC_I:
+		case VCOMP_SIGC_G:
+		case VCOMP_SIGC_C:
+		case VCOMP_SIGC_O:
+		case VCOMP_SIGC_M:
+		case VCOMP_SGZ_E:
+		case VCOMP_SGZ_R:
+		case VCOMP_SGZ_G:
+			/* unrecognized comp method, assume none */
+			uri->params.s=s;
+			uri->params.len=p-s;
+			/* uri->comp=COMP_NONE ; */
+			break;
+#endif
 		/* fin value states */
 		case VU_P_FIN:
 			uri->params.s=s;
@@ -950,6 +1059,20 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 			param_set(b, v);
 			uri->proto=PROTO_SCTP;
 			break;
+#ifdef USE_COMP
+		case VCOMP_SIGC_P_FIN:
+			uri->params.s=s;
+			uri->params.len=p-s;
+			/* param_set(b, v); */
+			uri->comp=COMP_SIGCOMP;
+			break;
+		case VCOMP_SGZ_Z_FIN:
+			uri->params.s=s;
+			uri->params.len=p-s;
+			/* param_set(b, v); */
+			uri->comp=COMP_SERGZ;
+			break;
+#endif
 		/* headers */
 		case URI_HEADERS:
 			uri->headers.s=s;
@@ -1027,6 +1150,10 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 			uri->maddr_val.len, ZSW(uri->maddr_val.s));
 	DBG("   lr=<%.*s>\n", uri->lr.len, ZSW(uri->lr.s)); 
 	DBG("   r2=<%.*s>\n", uri->r2.len, ZSW(uri->r2.s));
+#ifdef USE_COMP
+	DBG("   comp=%d\n", uri->comp);
+#endif
+
 #endif
 	return 0;
 	

+ 342 - 2
parser/parse_via.c

@@ -49,6 +49,7 @@
  *  2004-03-31  fixed rport set instead of i bug (andrei)
  *  2005-03-02  if via has multiple bodies, and one of them is bad set
  *               also the first one as bad (andrei)
+ *  2006-02-24  added support for comp parameter parsing (see rfc3486) (andrei)
  */
 
 
@@ -106,9 +107,20 @@ enum {
 	RECEIVED7,
 	RPORT1, RPORT2, RPORT3,
 	ALIAS1, ALIAS2, ALIAS3, ALIAS4,
+#ifdef USE_COMP
+	COMP1, COMP2, COMP3, 
+	/* values */
+	L_COMP_VALUE, F_COMP_VALUE,
+	V_COMP_S, V_SIGCOMP_I, V_SIGCOMP_G, V_SIGCOMP_C, V_SIGCOMP_O, V_SIGCOMP_M,
+	FIN_V_SIGCOMP_P,
+	V_SERGZ_E, V_SERGZ_R, V_SERGZ_G, FIN_V_SERGZ_Z,
+#endif
 	     /* fin states (227-...)*/
 	FIN_HIDDEN = 230, FIN_TTL, FIN_BRANCH,
 	FIN_MADDR, FIN_RECEIVED, FIN_RPORT, FIN_I, FIN_ALIAS
+#ifdef USE_COMP
+	, FIN_COMP
+#endif
 	     /*GEN_PARAM,
 	       PARAM_ERROR*/ /* declared in msg_parser.h*/
 };
@@ -124,12 +136,94 @@ enum {
 static /*inline*/ char* parse_via_param(char* p, char* end,
 										unsigned char* pstate, 
 				    					unsigned char* psaved_state,
-										struct via_param* param)
+										struct via_param* param,
+										struct via_body* vb)
 {
 	char* tmp;
 	register unsigned char state;
 	unsigned char saved_state;
 
+#define value_case(c, C, oldstate, newstate, start_of_value) \
+			case (c): \
+			case (C): \
+				switch(state){ \
+					case (oldstate): \
+						state=(newstate); \
+						if ((start_of_value))  param->value.s=tmp; \
+						break; \
+					default_value_cases \
+				} \
+				break
+
+#define value_case_double(c, C, oldstate1, newstate1, oldstate2, newstate2) \
+			case (c): \
+			case (C): \
+				switch(state){ \
+					case (oldstate1): \
+						state=(newstate1); \
+						break; \
+					case (oldstate2): \
+						state=(newstate2); \
+						break; \
+					default_value_cases \
+				} \
+				break
+
+#define default_value_cases \
+					case F_VALUE: \
+						state=P_VALUE; \
+						param->value.s=tmp; \
+						break; \
+					case P_VALUE: \
+					case P_STRING: \
+						break; \
+					case F_LF: \
+					case F_CR:  \
+					case F_CRLF: \
+						state=END_OF_HEADER; \
+						goto end_via; \
+					default: \
+						switch(state){ \
+							case F_COMP_VALUE: \
+								comp_unexpected_char; \
+								state=P_VALUE; \
+								param->value.s=tmp; \
+								break; \
+							comp_states_cases \
+							comp_fin_states_cases \
+								comp_unexpected_char; \
+								state=P_VALUE; \
+								break; \
+							default: \
+								LOG(L_ERR, "ERROR: parse_via_param: invalid " \
+									"char <%c> in state %d\n", *tmp, state); \
+								goto error; \
+						}
+
+#define comp_states_cases \
+					case V_COMP_S: \
+					case V_SIGCOMP_I: \
+					case V_SIGCOMP_G: \
+					case V_SIGCOMP_C: \
+					case V_SIGCOMP_O: \
+					case V_SIGCOMP_M: \
+					case V_SERGZ_E: \
+					case V_SERGZ_R: \
+					case V_SERGZ_G: 
+
+#define comp_fin_states_cases \
+					case FIN_V_SIGCOMP_P: \
+					case FIN_V_SERGZ_Z:
+
+
+/* if unrecognized/bad comp, don't return error, just ignore comp */
+#define comp_unexpected_char \
+							LOG(L_ERR, "parse_via_param: bad/unrecognized" \
+									" comp method\n"); \
+							vb->comp_no=0
+								
+
+
 	state=*pstate;
 	saved_state=*psaved_state;
 	param->type=PARAM_ERROR;
@@ -155,6 +249,13 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						param->name.len=tmp-param->name.s;
 						state=L_VALUE;
 						goto find_value;
+#ifdef USE_COMP
+					case FIN_COMP:
+						param->type=state;
+						param->name.len=tmp-param->name.s;
+						state=L_COMP_VALUE;
+						goto find_value;
+#endif
 					case F_PARAM:
 						break;
 					case F_LF:
@@ -193,6 +294,15 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						saved_state=L_VALUE;
 						state=F_LF;
 						goto find_value;
+#ifdef USE_COMP
+					case FIN_COMP:
+						param->type=state;
+						param->name.len=tmp-param->name.s;
+						param->size=tmp-param->start; 
+						saved_state=L_COMP_VALUE;
+						state=F_LF;
+						goto find_value;
+#endif
 					case F_PARAM:
 						saved_state=state;
 						state=F_LF;
@@ -236,6 +346,15 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						saved_state=L_VALUE;
 						state=F_CR;
 						goto find_value;
+#ifdef USE_COMP
+					case FIN_COMP:
+						param->type=state;
+						param->name.len=tmp-param->name.s;
+						param->size=tmp-param->start; 
+						saved_state=L_COMP_VALUE;
+						state=F_LF;
+						goto find_value;
+#endif
 					case F_PARAM:
 						saved_state=state;
 						state=F_CR;
@@ -267,6 +386,13 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						param->name.len=tmp-param->name.s;
 						state=F_VALUE;
 						goto find_value;
+#ifdef USE_COMP
+					case FIN_COMP:
+						param->type=state;
+						param->name.len=tmp-param->name.s;
+						state=F_COMP_VALUE;
+						goto find_value;
+#endif
 					case F_PARAM:
 					case FIN_HIDDEN:
 					case FIN_ALIAS:
@@ -300,6 +426,9 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case FIN_TTL:
 					case FIN_RECEIVED:
 					case FIN_I:
+#ifdef USE_COMP
+					case FIN_COMP:
+#endif
 						LOG(L_ERR, "ERROR: parse_via: invalid char <%c> in"
 								" state %d\n", *tmp, state);
 						goto error;
@@ -330,6 +459,9 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case FIN_TTL:
 					case FIN_RECEIVED:
 					case FIN_I:
+#ifdef USE_COMP
+					case FIN_COMP:
+#endif
 						LOG(L_ERR, "ERROR: parse_via_param: new via found" 
 								"(',') when '=' expected (state %d=)\n",
 								state);
@@ -539,6 +671,11 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						state=MADDR1;
 						param->name.s=tmp;
 						break;
+#ifdef USE_COMP
+					case COMP2:
+						state=COMP3;
+						break;
+#endif
 					case GEN_PARAM:
 						break;
 					case F_CR:
@@ -608,7 +745,11 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 			case 'C':
 				switch(state){
 					case F_PARAM:
+#ifdef USE_COMP
+						state=COMP1;
+#else
 						state=GEN_PARAM;
+#endif
 						param->name.s=tmp;
 						break;
 					case RECEIVED2:
@@ -677,6 +818,11 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case RECEIVED1:
 						state=RPORT1;
 						break;
+#ifdef USE_COMP
+					case COMP3:
+						state=FIN_COMP;
+						break;
+#endif
 					case F_CR:
 					case F_LF:
 					case F_CRLF:
@@ -696,6 +842,11 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case RPORT1:
 						state=RPORT2;
 						break;
+#ifdef USE_COMP
+					case COMP1:
+						state=COMP2;
+						break;
+#endif
 					case F_CR:
 					case F_LF:
 					case F_CRLF:
@@ -762,6 +913,26 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						state=L_PARAM;
 						param->value.len=tmp-param->value.s;
 						goto endofvalue;
+#ifdef USE_COMP
+					case L_COMP_VALUE:
+					case F_COMP_VALUE:
+						break; /* eat space */
+					case FIN_V_SIGCOMP_P:
+						state=L_PARAM;
+						param->value.len=tmp-param->value.s;
+						vb->comp_no=COMP_SIGCOMP;
+						goto endofvalue;
+					case FIN_V_SERGZ_Z:
+						state=L_PARAM;
+						param->value.len=tmp-param->value.s;
+						vb->comp_no=COMP_SIGCOMP;
+						goto endofvalue;
+					comp_states_cases
+						state=L_PARAM;
+						param->value.len=tmp-param->value.s;
+						comp_unexpected_char;
+						goto endofvalue;
+#endif
 					case P_STRING:
 						break;
 					case F_CR:
@@ -779,6 +950,10 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 				switch(state){
 					case L_VALUE:
 					case F_VALUE: /*eat space*/
+#ifdef USE_COMP
+					case L_COMP_VALUE:
+					case F_COMP_VALUE:
+#endif
 					case P_STRING:
 						saved_state=state;
 						param->size=tmp-param->start;
@@ -789,6 +964,26 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						state=F_LF;
 						param->value.len=tmp-param->value.s;
 						goto endofvalue;
+#ifdef USE_COMP
+					case FIN_V_SIGCOMP_P:
+						saved_state=L_PARAM;
+						state=F_LF;
+						param->value.len=tmp-param->value.s;
+						vb->comp_no=COMP_SIGCOMP;
+						goto endofvalue;
+					case FIN_V_SERGZ_Z:
+						saved_state=L_PARAM;
+						state=F_LF;
+						param->value.len=tmp-param->value.s;
+						vb->comp_no=COMP_SIGCOMP;
+						goto endofvalue;
+					comp_states_cases
+						saved_state=L_PARAM;
+						state=F_LF;
+						param->value.len=tmp-param->value.s;
+						comp_unexpected_char;
+						goto endofvalue;
+#endif
 					case F_LF:
 					case F_CRLF:
 						state=END_OF_HEADER;
@@ -806,6 +1001,10 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 				switch(state){
 					case L_VALUE:
 					case F_VALUE: /*eat space*/
+#ifdef USE_COMP
+					case L_COMP_VALUE:
+					case F_COMP_VALUE:
+#endif
 					case P_STRING:
 						saved_state=state;
 						param->size=tmp-param->start;
@@ -816,6 +1015,26 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						saved_state=L_PARAM;
 						state=F_CR;
 						goto endofvalue;
+#ifdef USE_COMP
+					case FIN_V_SIGCOMP_P:
+						saved_state=L_PARAM;
+						state=F_CR;
+						param->value.len=tmp-param->value.s;
+						vb->comp_no=COMP_SIGCOMP;
+						goto endofvalue;
+					case FIN_V_SERGZ_Z:
+						saved_state=L_PARAM;
+						state=F_CR;
+						param->value.len=tmp-param->value.s;
+						vb->comp_no=COMP_SIGCOMP;
+						goto endofvalue;
+					comp_states_cases
+						saved_state=L_PARAM;
+						state=F_CR;
+						param->value.len=tmp-param->value.s;
+						comp_unexpected_char;
+						goto endofvalue;
+#endif
 					case F_LF:
 					case F_CR:
 					case F_CRLF:
@@ -833,6 +1052,13 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case L_VALUE:
 						state=F_VALUE;
 						break;
+#ifdef USE_COMP
+					case L_COMP_VALUE:
+						state=F_COMP_VALUE;
+						break;
+					/* '=' in any other COMP value state is an error,
+					 * and it will be catched by the default branch */
+#endif
 					case P_STRING:
 						break;
 					case F_LF:
@@ -863,6 +1089,35 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case F_CRLF:
 						state=END_OF_HEADER;
 						goto end_via;
+#ifdef USE_COMP
+					case L_COMP_VALUE:
+						comp_unexpected_char;
+						/* we want to contine with no comp */
+						state=F_PARAM;
+						param->value.len=0;
+						param->value.s=0;
+						goto endofvalue;
+					case F_COMP_VALUE:
+						comp_unexpected_char;
+						param->value.len=0;
+						state=F_PARAM;
+						goto endofvalue;
+					comp_states_cases
+						comp_unexpected_char;
+						param->value.len=tmp-param->value.s;
+						state=F_PARAM;
+						goto endofvalue;
+					case FIN_V_SIGCOMP_P:
+						vb->comp_no=COMP_SIGCOMP;
+						param->value.len=tmp-param->value.s;
+						state=F_PARAM;
+						goto endofvalue;
+					case FIN_V_SERGZ_Z:
+						vb->comp_no=COMP_SIGCOMP;
+						param->value.len=tmp-param->value.s;
+						state=F_PARAM;
+						goto endofvalue;
+#endif
 					case L_VALUE:
 						if (param->type==FIN_RPORT){
 							param->value.len=0;
@@ -889,6 +1144,35 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case F_CRLF:
 						state=END_OF_HEADER;
 						goto end_via;
+#ifdef USE_COMP
+					case L_COMP_VALUE:
+						comp_unexpected_char;
+						/* we want to contine with no comp */
+						state=F_VIA;
+						param->value.len=0;
+						param->value.s=0;
+						goto endofvalue;
+					case F_COMP_VALUE:
+						comp_unexpected_char;
+						param->value.len=0;
+						state=F_VIA;
+						goto endofvalue;
+					comp_states_cases
+						comp_unexpected_char;
+						param->value.len=tmp-param->value.s;
+						state=F_VIA;
+						goto endofvalue;
+					case FIN_V_SIGCOMP_P:
+						vb->comp_no=COMP_SIGCOMP;
+						param->value.len=tmp-param->value.s;
+						state=F_VIA;
+						goto endofvalue;
+					case FIN_V_SERGZ_Z:
+						vb->comp_no=COMP_SIGCOMP;
+						param->value.len=tmp-param->value.s;
+						state=F_VIA;
+						goto endofvalue;
+#endif
 					case L_VALUE:
 						if (param->type==FIN_RPORT){
 							param->value.len=0;
@@ -924,6 +1208,21 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						goto error;
 				}
 				break;
+#ifdef USE_COMP
+			value_case('s', 'S', F_COMP_VALUE, V_COMP_S, 1);
+			value_case('i', 'I', V_COMP_S, V_SIGCOMP_I, 0);
+			value_case_double('g', 'G', V_SIGCOMP_I, V_SIGCOMP_G,
+					                    V_SERGZ_R,   V_SERGZ_G);
+			value_case('c', 'C', V_SIGCOMP_G, V_SIGCOMP_C, 0);
+			value_case('o', 'O', V_SIGCOMP_C, V_SIGCOMP_O, 0);
+			value_case('m', 'M', V_SIGCOMP_O, V_SIGCOMP_M, 0);
+			value_case('p', 'P', V_SIGCOMP_M, FIN_V_SIGCOMP_P, 0);
+			
+			value_case('e', 'E', V_COMP_S, V_SERGZ_E, 0);
+			value_case('r', 'R', V_SERGZ_E, V_SERGZ_R, 0);
+			value_case('z', 'Z', V_SERGZ_G, FIN_V_SERGZ_Z, 0);
+#endif /* USE_COMP */
+				
 			default:
 				switch(state){
 					case F_VALUE:
@@ -939,9 +1238,28 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						state=END_OF_HEADER;
 						goto end_via;
 					default:
+#ifdef USE_COMP
+						switch(state){
+							case F_COMP_VALUE:
+								comp_unexpected_char;
+								state=P_VALUE;
+								param->value.s=tmp;
+								break;
+							comp_states_cases
+							comp_fin_states_cases
+								comp_unexpected_char;
+								state=P_VALUE;
+								break;
+							default:
+								LOG(L_ERR, "ERROR: parse_via_param: invalid "
+									"char <%c> in state %d\n", *tmp, state);
+								goto error;
+						}
+#else
 						LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
 								" in state %d\n", *tmp, state);
 						goto error;
+#endif /* USE_COMP */
 				}
 		}
 	} /* for2 tmp*/
@@ -1830,7 +2148,7 @@ parse_again:
 						memset(param,0, sizeof(struct via_param));
 						param->start=param_start;
 						tmp=parse_via_param(tmp, end, &state, &saved_state,
-											param);
+											param, vb);
 
 						switch(state){
 							case F_PARAM:
@@ -1879,6 +2197,28 @@ parse_again:
 							case PARAM_ALIAS:
 								vb->alias=param;
 								break;
+#ifdef USE_COMP
+							case PARAM_COMP:
+								vb->comp=param;
+								/*  moved comp value parsing in via_param */
+								/*
+								if  ((param->value.len==SIGCOMP_NAME_LEN) &&
+									(strncasecmp(param->value.s, SIGCOMP_NAME,
+												SIGCOMP_NAME_LEN)==0)){
+									vb->comp_no=COMP_SIGCOMP;
+								}else if ((param->value.len==SERGZ_NAME_LEN) &&
+										(strncasecmp(param->value.s,
+													SERGZ_NAME,
+													SERGZ_NAME_LEN)==0)){
+									vb->comp_no=COMP_SERGZ;
+								}else{
+									LOG(L_ERR, "ERROR: parse_via: unrecognized"
+										" compression method in comp=%.*s\n",
+										param->value.len, param->value.s);
+								}
+								*/
+								break;
+#endif
 						}
 						
 						if (state==END_OF_HEADER){

+ 13 - 3
parser/parse_via.h

@@ -32,6 +32,7 @@
  *               by tcp to identify the sending socket, by andrei
  *  2003-01-27  added a new member (start) to via_param, by andrei
  *  2003-10-27  added alias to via && PARAM_ALIAS (andrei)
+ *  2006-02-24  added comp/PARAM_COMP support (andrei)
  */
 
 
@@ -48,7 +49,10 @@
 enum {
 	PARAM_HIDDEN=230, PARAM_TTL, PARAM_BRANCH, 
 	PARAM_MADDR, PARAM_RECEIVED, PARAM_RPORT, PARAM_I, PARAM_ALIAS,
-	GEN_PARAM,
+#ifdef USE_COMP
+	PARAM_COMP,
+#endif
+	GEN_PARAM=253,
 	PARAM_ERROR
 };
 
@@ -74,9 +78,12 @@ struct via_body {
 	str name;
 	str version;   
 	str transport;
-	int proto; /* transport */
 	str host;
-	int port;
+	short proto; /* transport */
+	unsigned short port;
+#ifdef USE_COMP
+	short comp_no;
+#endif
 	str port_str;
 	str params;
 	str comment;
@@ -91,6 +98,9 @@ struct via_body {
 	struct via_param* rport;
 	struct via_param* i;
 	struct via_param* alias; /* alias see draft-ietf-sip-connect-reuse-00 */
+#ifdef USE_COMP
+	struct via_param* comp; /* see rfc3486 */
+#endif
 	struct via_body* next; /* pointer to next via body string if
 				  compact via or null */
 };

+ 8 - 1
version.h

@@ -194,6 +194,13 @@
 #endif
 
 
+#ifdef USE_COMP
+#define USE_COMP_STR ", USE_COMP"
+#else
+#define USE_COMP_STR ""
+#endif
+
+
 #define SER_COMPILE_FLAGS \
 	STATS_STR EXTRA_DEBUG_STR USE_IPV6_STR USE_TCP_STR USE_TLS_STR \
 	DISABLE_NAGLE_STR USE_MCAST_STR NO_DEBUG_STR NO_LOG_STR DNS_IP_HACK_STR \
@@ -201,7 +208,7 @@
 	USE_SHM_MEM_STR DBG_QM_MALLOC_STR DBG_F_MALLOC_STR DEBUG_DMALLOC_STR \
 	TIMER_DEBUG_STR \
 	FAST_LOCK_STR NOSMP_STR USE_PTHREAD_MUTEX_STR USE_POSIX_SEM_STR \
-	USE_SYSV_SEM_STR
+	USE_SYSV_SEM_STR USE_COMP_STR
 
 
 #endif