瀏覽代碼

- changed sip_msg (new rcv member containing all the ips, ports, protocol)
- added a "proto" parameter to forward_request, via_builder, get_send_sock etc.
- added 2 new script commands: forward_udp & forward_tcp
- lots of tcp bloat
- changed parse_via to recognize TCP
- more functions added to ip_addr.h (cmp for ips & sockaddrs etc.)

Andrei Pelinescu-Onciul 22 年之前
父節點
當前提交
f2f969dda6
共有 25 個文件被更改,包括 565 次插入168 次删除
  1. 1 1
      Makefile.defs
  2. 3 1
      TODO
  3. 15 4
      action.c
  4. 2 0
      cfg.lex
  5. 130 0
      cfg.y
  6. 110 30
      forward.c
  7. 6 4
      forward.h
  8. 3 1
      globals.h
  9. 17 2
      ip_addr.h
  10. 21 0
      main.c
  11. 16 8
      msg_translator.c
  12. 3 2
      msg_translator.h
  13. 11 7
      parser/msg_parser.h
  14. 89 57
      parser/parse_via.c
  15. 2 0
      parser/parse_via.h
  16. 2 3
      receive.c
  17. 1 1
      receive.h
  18. 3 2
      route.c
  19. 3 0
      route_struct.c
  20. 1 0
      route_struct.h
  21. 10 7
      tcp_conn.h
  22. 39 0
      tcp_init.h
  23. 63 35
      tcp_main.c
  24. 2 1
      tcp_read.c
  25. 12 2
      udp_server.c

+ 1 - 1
Makefile.defs

@@ -8,7 +8,7 @@
 VERSION = 0
 PATCHLEVEL = 8
 SUBLEVEL =   11
-EXTRAVERSION = pre2
+EXTRAVERSION = pre3-tcp0
 
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")

+ 3 - 1
TODO

@@ -63,4 +63,6 @@ x jku: branch hash computation over canonical values
 
 
 x freopen stdin, stdout, stderr to /dev/null
-
+- add a section on building ser & configuring it for maximum performance
+ (-DF_MALLOC, -DNO_DBG, ... sip_warning=0, a.s.o)
+- add src_port, dst_port, proto to cfg.{y,lex}

+ 15 - 4
action.c

@@ -77,6 +77,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 	struct sip_uri uri;
 	struct sip_uri* u;
 	unsigned short port;
+	int proto;
 
 	/* reset the value of error to E_UNSPEC so avoid unknowledgable
 	   functions to return with errror (status<0) and not setting it
@@ -86,11 +87,21 @@ int do_action(struct action* a, struct sip_msg* msg)
 	ser_error=E_UNSPEC;
 
 	ret=E_BUG;
-	switch (a->type){
+	switch ((unsigned char)a->type){
 		case DROP_T:
 				ret=0;
 			break;
 		case FORWARD_T:
+#ifdef USE_TCP
+		case FORWARD_TCP_T:
+#endif
+		case FORWARD_UDP_T:
+
+			if (a->type==FORWARD_UDP_T) proto=PROTO_UDP;
+#ifdef USE_TCP
+			else if (a->type==FORWARD_TCP_T) proto= PROTO_TCP;
+#endif
+			else proto=msg->rcv.proto;
 			if (a->p1_type==URIHOST_ST){
 				/*parse uri*/
 				ret=parse_sip_msg_uri(msg);
@@ -121,13 +132,13 @@ int do_action(struct action* a, struct sip_msg* msg)
 					ret=E_BAD_ADDRESS;
 					goto error_fwd_uri;
 				}
-				ret=forward_request(msg, p);
+				ret=forward_request(msg, p, proto);
 				/*free_uri(&uri); -- no longer needed, in sip_msg*/
 				free_proxy(p); /* frees only p content, not p itself */
 				free(p);
 				if (ret>=0) ret=1;
 			}else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){
-				ret=forward_request(msg,(struct proxy_l*)a->p1.data);
+				ret=forward_request(msg,(struct proxy_l*)a->p1.data, proto);
 				if (ret>=0) ret=1;
 			}else{
 				LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
@@ -167,7 +178,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 				p->tx_bytes+=msg->len;
 				if (a->type==SEND_T){
 					/*udp*/
-					send_sock=get_send_socket(to);
+					send_sock=get_send_socket(to, PROTO_UDP);
 					if (send_sock!=0){
 						ret=udp_send(send_sock, msg->orig, msg->len, to);
 					}else{

+ 2 - 0
cfg.lex

@@ -42,6 +42,7 @@
 /* action keywords */
 FORWARD	forward
 FORWARD_TCP	forward_tcp
+FORWARD_UDP	forward_udp
 DROP	"drop"|"break"
 SEND	send
 SEND_TCP	send_tcp
@@ -155,6 +156,7 @@ EAT_ABLE	[\ \t\b\r]
 
 <INITIAL>{FORWARD}	{count(); yylval.strval=yytext; return FORWARD; }
 <INITIAL>{FORWARD_TCP}	{count(); yylval.strval=yytext; return FORWARD_TCP; }
+<INITIAL>{FORWARD_UDP}	{count(); yylval.strval=yytext; return FORWARD_UDP; }
 <INITIAL>{DROP}	{ count(); yylval.strval=yytext; return DROP; }
 <INITIAL>{SEND}	{ count(); yylval.strval=yytext; return SEND; }
 <INITIAL>{SEND_TCP}	{ count(); yylval.strval=yytext; return SEND_TCP; }

+ 130 - 0
cfg.y

@@ -64,6 +64,7 @@ struct id_list* lst_tmp;
 /* keywords */
 %token FORWARD
 %token FORWARD_TCP
+%token FORWARD_UDP
 %token SEND
 %token SEND_TCP
 %token DROP
@@ -683,6 +684,135 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
 		| FORWARD error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| FORWARD LPAREN error RPAREN { $$=0; yyerror("bad forward"
 										"argument"); }
+		| FORWARD_UDP LPAREN host RPAREN	{ $$=mk_action(	FORWARD_UDP_T,
+														STRING_ST,
+														NUMBER_ST,
+														$3,
+														0);
+										}
+		| FORWARD_UDP LPAREN STRING RPAREN	{ $$=mk_action(	FORWARD_UDP_T,
+														STRING_ST,
+														NUMBER_ST,
+														$3,
+														0);
+										}
+		| FORWARD_UDP LPAREN ip RPAREN	{ $$=mk_action(	FORWARD_UDP_T,
+														IP_ST,
+														NUMBER_ST,
+														(void*)$3,
+														0);
+										}
+		| FORWARD_UDP LPAREN host COMMA NUMBER RPAREN { $$=mk_action(
+																FORWARD_UDP_T,
+																 STRING_ST,
+																 NUMBER_ST,
+																$3,
+																(void*)$5);
+												 }
+		| FORWARD_UDP LPAREN STRING COMMA NUMBER RPAREN {$$=mk_action(
+																FORWARD_UDP_T,
+																 STRING_ST,
+																 NUMBER_ST,
+																$3,
+																(void*)$5);
+													}
+		| FORWARD_UDP LPAREN ip COMMA NUMBER RPAREN { $$=mk_action(
+																FORWARD_UDP_T,
+																 IP_ST,
+																 NUMBER_ST,
+																 (void*)$3,
+																(void*)$5);
+												  }
+		| FORWARD_UDP LPAREN URIHOST COMMA URIPORT RPAREN {
+													$$=mk_action(FORWARD_UDP_T,
+																 URIHOST_ST,
+																 URIPORT_ST,
+																0,
+																0);
+													}
+													
+									
+		| FORWARD_UDP LPAREN URIHOST COMMA NUMBER RPAREN {
+													$$=mk_action(FORWARD_UDP_T,
+																 URIHOST_ST,
+																 NUMBER_ST,
+																0,
+																(void*)$5);
+													}
+		| FORWARD_UDP LPAREN URIHOST RPAREN {
+													$$=mk_action(FORWARD_UDP_T,
+																 URIHOST_ST,
+																 NUMBER_ST,
+																0,
+																0);
+										}
+		| FORWARD_UDP error { $$=0; yyerror("missing '(' or ')' ?"); }
+		| FORWARD_UDP LPAREN error RPAREN { $$=0; yyerror("bad forward_udp"
+										"argument"); }
+		| FORWARD_TCP LPAREN host RPAREN	{ $$=mk_action(	FORWARD_TCP_T,
+														STRING_ST,
+														NUMBER_ST,
+														$3,
+														0);
+										}
+		| FORWARD_TCP LPAREN STRING RPAREN	{ $$=mk_action(	FORWARD_TCP_T,
+														STRING_ST,
+														NUMBER_ST,
+														$3,
+														0);
+										}
+		| FORWARD_TCP LPAREN ip RPAREN	{ $$=mk_action(	FORWARD_TCP_T,
+														IP_ST,
+														NUMBER_ST,
+														(void*)$3,
+														0);
+										}
+		| FORWARD_TCP LPAREN host COMMA NUMBER RPAREN { $$=mk_action(
+																FORWARD_TCP_T,
+																 STRING_ST,
+																 NUMBER_ST,
+																$3,
+																(void*)$5);
+												 }
+		| FORWARD_TCP LPAREN STRING COMMA NUMBER RPAREN {$$=mk_action(
+																FORWARD_TCP_T,
+																 STRING_ST,
+																 NUMBER_ST,
+																$3,
+																(void*)$5);
+													}
+		| FORWARD_TCP LPAREN ip COMMA NUMBER RPAREN { $$=mk_action(FORWARD_TCP_T,
+																 IP_ST,
+																 NUMBER_ST,
+																 (void*)$3,
+																(void*)$5);
+												  }
+		| FORWARD_TCP LPAREN URIHOST COMMA URIPORT RPAREN {
+													$$=mk_action(FORWARD_TCP_T,
+																 URIHOST_ST,
+																 URIPORT_ST,
+																0,
+																0);
+													}
+													
+									
+		| FORWARD_TCP LPAREN URIHOST COMMA NUMBER RPAREN {
+													$$=mk_action(FORWARD_TCP_T,
+																 URIHOST_ST,
+																 NUMBER_ST,
+																0,
+																(void*)$5);
+													}
+		| FORWARD_TCP LPAREN URIHOST RPAREN {
+													$$=mk_action(FORWARD_TCP_T,
+																 URIHOST_ST,
+																 NUMBER_ST,
+																0,
+																0);
+										}
+		| FORWARD_TCP error { $$=0; yyerror("missing '(' or ')' ?"); }
+		| FORWARD_TCP LPAREN error RPAREN { $$=0; yyerror("bad forward_tcp"
+										"argument"); }
 		| SEND LPAREN host RPAREN	{ $$=mk_action(	SEND_T,
 													STRING_ST,
 													NUMBER_ST,

+ 110 - 30
forward.c

@@ -53,6 +53,9 @@
 #include "ip_addr.h"
 #include "resolve.h"
 #include "name_alias.h"
+#ifdef USE_TCP
+#include "tcp_server.h"
+#endif
 
 #ifdef DEBUG_DMALLOC
 #include <dmalloc.h>
@@ -63,14 +66,31 @@
 /* returns a socket_info pointer to the sending socket or 0 on error
  * params: destination socket_union pointer
  */
-struct socket_info* get_send_socket(union sockaddr_union* to)
+struct socket_info* get_send_socket(union sockaddr_union* to, int proto)
 {
 	struct socket_info* send_sock;
 	
 	send_sock=0;
 	/* check if we need to change the socket (different address families -
 	 * eg: ipv4 -> ipv6 or ipv6 -> ipv4) */
-	if ((bind_address==0) ||(to->s.sa_family!=bind_address->address.af)){
+#ifdef USE_TCP
+	if (proto==PROTO_TCP){
+		/* on tcp just use the "main address", we don't really now the
+		 * sending address (we can find it out, but we'll find also to see
+		 * if we listen on it, and if yes on which port -> too complicated*/
+		switch(to->s.sa_family){
+			case AF_INET:	send_sock=sendipv4_tcp;
+							break;
+#ifdef USE_IPV6
+			case AF_INET6:	send_sock=sendipv6_tcp;
+							break;
+#endif
+			default:		LOG(L_ERR, "get_send_socket: BUG: don't know how"
+									" to forward to af %d\n", to->s.sa_family);
+		}
+	}else
+#endif
+	      if ((bind_address==0) ||(to->s.sa_family!=bind_address->address.af)){
 		switch(to->s.sa_family){
 			case AF_INET:	send_sock=sendipv4;
 							break;
@@ -139,16 +159,18 @@ int check_self(str* host, unsigned short port)
 
 
 
-int forward_request( struct sip_msg* msg, struct proxy_l * p)
+int forward_request( struct sip_msg* msg, struct proxy_l * p, int proto)
 {
 	unsigned int len;
 	char* buf;
 	union sockaddr_union* to;
 	struct socket_info* send_sock;
 	char md5[MD5_LEN];
+	int id; /* used as branch for tcp! */
 	
 	to=0;
 	buf=0;
+	id=0;
 	
 	to=(union sockaddr_union*)malloc(sizeof(union sockaddr_union));
 	if (to==0){
@@ -172,7 +194,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 	p->tx_bytes+=len;
 	
 
-	send_sock=get_send_socket(to);
+	send_sock=get_send_socket(to, proto);
 	if (send_sock==0){
 		LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d "
 				"no coresponding listening socket\n", to->s.sa_family);
@@ -190,6 +212,9 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 	   value in there; better for performance
 	*/
 
+#ifdef USE_TCP
+	if (msg->rcv.proto==PROTO_TCP) id=msg->rcv.proto_reserved1;
+#endif
 	if (syn_branch ) {
 		*msg->add_to_branch_s='0';
 		msg->add_to_branch_len=1;
@@ -199,31 +224,52 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 			goto error1;
 		}
 		msg->hash_index=hash( msg->callid->body, get_cseq(msg)->number);
-		if (!branch_builder( msg->hash_index, 0, md5, 0 /* 0-th branch */,
+		if (!branch_builder( msg->hash_index, 0, md5, id /* 0-th branch */,
 					msg->add_to_branch_s, &msg->add_to_branch_len )) {
 			LOG(L_ERR, "ERROR: forward_request: branch_builder failed\n");
 			goto error1;
 		}
 	}
 
-	buf = build_req_buf_from_sip_req( msg, &len, send_sock);
+	buf = build_req_buf_from_sip_req( msg, &len, send_sock,  proto);
 	if (!buf){
 		LOG(L_ERR, "ERROR: forward_request: building failed\n");
 		goto error1;
 	}
 	 /* send it! */
 	DBG("Sending:\n%s.\n", buf);
-	DBG("orig. len=%d, new_len=%d\n", msg->len, len );
+	DBG("orig. len=%d, new_len=%d, proto=%d\n", msg->len, len, proto );
 	
-	if (udp_send(send_sock, buf, len,  to)==-1){
-			ser_error=E_SEND;
-			p->errors++;
-			p->ok=0;
-			STATS_TX_DROPS;
-			goto error1;
+	
+	if (proto==PROTO_UDP){
+		if (udp_send(send_sock, buf, len,  to)==-1){
+				ser_error=E_SEND;
+				p->errors++;
+				p->ok=0;
+				STATS_TX_DROPS;
+				goto error1;
+		}
+	}
+#ifdef USE_TCP
+	 else if (proto==PROTO_TCP){
+		if (tcp_send(buf, len, to, 0)==-1){
+				ser_error=E_SEND;
+				p->errors++;
+				p->ok=0;
+				STATS_TX_DROPS;
+				goto error1;
+		}
+	}
+#endif
+	 else{
+		LOG(L_CRIT, "BUG: forward_request: unknown proto %d\n", proto);
+		ser_error=E_SEND;
+		STATS_TX_DROPS;
+		goto error1;
 	}
+
 	/* sent requests stats */
-	else STATS_TX_REQUEST(  msg->first_line.u.request.method_value );
+	STATS_TX_REQUEST(  msg->first_line.u.request.method_value );
 	
 	pkg_free(buf);
 	free(to);
@@ -238,14 +284,6 @@ error:
 }
 
 
-int update_sock_struct_from_ip( union sockaddr_union* to,
-	struct sip_msg *msg )
-{
-
-	init_su(to, &msg->src_ip, 
-		(msg->via1->port)?htons(msg->via1->port): htons(SIP_PORT) );
-	return 1;
-}
 
 int update_sock_struct_from_via( union sockaddr_union* to,
 								 struct via_body* via )
@@ -310,6 +348,13 @@ int forward_reply(struct sip_msg* msg)
 	struct socket_info* send_sock;
 	unsigned int new_len;
 	struct sr_module *mod;
+	int proto;
+#ifdef USE_TCP
+	char* s;
+	char* p;
+	int len;
+	int id;
+#endif
 	
 	to=0;
 	new_buf=0;
@@ -355,22 +400,57 @@ int forward_reply(struct sip_msg* msg)
 	}
 
 	if (update_sock_struct_from_via( to, msg->via2 )==-1) goto error;
-	send_sock=get_send_socket(to);
+	send_sock=get_send_socket(to, msg->rcv.proto);
 	if (send_sock==0){
 		LOG(L_ERR, "forward_reply: ERROR: no sending socket found\n");
 		goto error;
 	}
 
-	if (udp_send(send_sock, new_buf,new_len,  to)==-1)
-	{
-		STATS_TX_DROPS;
+	proto=msg->via2->proto;
+	if (proto==PROTO_UDP){
+		if (udp_send(send_sock, new_buf,new_len,  to)==-1)
+		{
+			STATS_TX_DROPS;
+			goto error;
+		}
+	}
+#ifdef USE_TCP
+	 else if (proto==PROTO_TCP){
+		 id=0;
+		/* find id in branch if it exists */
+		if ((msg->via1->branch)&&(msg->via1->branch->value.len>MCOOKIE_LEN) &&
+			(memcmp(msg->via1->branch->value.s, MCOOKIE, MCOOKIE_LEN)==0)){
+			DBG("forward_reply: found branch\n");
+			s=msg->via1->branch->value.s+MCOOKIE_LEN;
+			len=msg->via1->branch->value.len-MCOOKIE_LEN;
+			for (p=s; p<s+len  && *p!=BRANCH_SEPARATOR; p++);
+			p++;
+			for(;p<s+len && *p!=BRANCH_SEPARATOR; p++);
+			p++;
+			if (p<s+len){
+				/* we found the second BRANCH_SEPARATOR, p points after it */
+				len-=(int)(p-s);
+				id=reverse_hex2int(p, len);
+				DBG("forward_reply: id= %x\n", id);
+			}else{
+				DBG("forward_reply: no id in branch\n");
+			}
+		}		
+				
+		if (tcp_send(new_buf, new_len,  to, id)==-1)
+		{
+			STATS_TX_DROPS;
+			goto error;
+		}
+	} 
+#endif
+	else{
+		LOG(L_CRIT, "BUG: forward_reply: unknown proto %d\n", proto);
 		goto error;
-	} else {
+	}
 #ifdef STATS
-		int j = msg->first_line.u.reply.statuscode/100;
-		STATS_TX_RESPONSE(  j );
+		STATS_TX_RESPONSE(  (msg->first_line.u.reply.statuscode/100) );
 #endif
-	}
 
 	DBG(" reply forwarded to %s:%d\n", msg->via2->host.s,
 		(unsigned short) msg->via2->port);

+ 6 - 4
forward.h

@@ -36,13 +36,15 @@
 #include "ip_addr.h"
 
 
-struct socket_info* get_send_socket(union sockaddr_union* su);
+struct socket_info* get_send_socket(union sockaddr_union* su, int proto);
 int check_self(str* host, unsigned short port);
-int forward_request( struct sip_msg* msg,  struct proxy_l* p);
+int forward_request( struct sip_msg* msg,  struct proxy_l* p, int proto);
 int update_sock_struct_from_via( union sockaddr_union* to,
 								struct via_body* via );
-int update_sock_struct_from_ip( union sockaddr_union* to,
-    struct sip_msg *msg );
+#define update_sock_struct_from_ip(  to, msg ) \
+	init_su((to), &(msg)->rcv.src_ip, \
+			((msg)->via1->port)?htons((msg)->via1->port): htons(SIP_PORT) )
+
 int forward_reply( struct sip_msg* msg);
 
 #endif

+ 3 - 1
globals.h

@@ -65,8 +65,10 @@ extern int bind_idx; /* same as above but index in the bound[] array */
 extern struct socket_info* sendipv4; /* ipv4 socket to use when msg.
 										comes from ipv6*/
 extern struct socket_info* sendipv6; /* same as above for ipv6 */
-
 #ifdef USE_TCP
+extern struct socket_info* sendipv4_tcp; /* ipv4 socket to use when msg.
+										comes from ipv6*/
+extern struct socket_info* sendipv6_tcp; /* same as above for ipv6 */
 extern int unix_tcp_sock; /* socket used for communication with tcp main*/
 #endif
 

+ 17 - 2
ip_addr.h

@@ -40,8 +40,8 @@
 
 #include "dprint.h"
 
-#define SOCKET_TCP	1
-#define SOCKET_UDP	0
+enum sip_protos { PROTO_UDP, PROTO_TCP, PROTO_TLS };
+
 
 struct ip_addr{
 	unsigned int af; /* address family: AF_INET6 or AF_INET */
@@ -85,6 +85,21 @@ struct socket_info{
 };
 
 
+struct receive_info{
+	struct ip_addr src_ip;
+	struct ip_addr dst_ip;
+	short src_port;
+	short dst_port;
+	int proto;
+	int proto_reserved1;
+	int proto_reserved2;
+	union sockaddr_union src_su; /* usefull for replies*/
+	struct socket_info* bind_address; /* sock_info structure on which 
+									  the msg was received*/
+	/* no need for dst_su yet */
+};
+
+
 /* len of the sockaddr */
 #ifdef HAVE_SOCKADDR_SA_LEN
 #define sockaddru_len(su)	((su).s.sa_len)

+ 21 - 0
main.c

@@ -73,6 +73,9 @@
 #include "name_alias.h"
 #include "hash_func.h"
 #include "pt.h"
+#ifdef USE_TCP
+#include "tcp_init.h"
+#endif
 
 
 #include "stats.h"
@@ -281,6 +284,10 @@ struct socket_info* bind_address=0; /* pointer to the crt. proc.
 int bind_idx; /* same as above but index in the bound[] array */
 struct socket_info* sendipv4; /* ipv4 socket to use when msg. comes from ipv6*/
 struct socket_info* sendipv6; /* same as above for ipv6 */
+#ifdef USE_TCP
+struct socket_info* sendipv4_tcp; 
+struct socket_info* sendipv6_tcp; 
+#endif
 
 unsigned short port_no=0; /* default port*/
 
@@ -623,6 +630,7 @@ int main_loop()
 		*/
 		for(r=0;r<sock_no;r++){
 			/* create the listening socket (for each address)*/
+			/* udp */
 			if (udp_init(&sock_info[r])==-1) goto error;
 			/* get first ipv4/ipv6 socket*/
 			if ((sock_info[r].address.af==AF_INET)&&
@@ -632,6 +640,19 @@ int main_loop()
 			if((sendipv6==0)&&(sock_info[r].address.af==AF_INET6))
 				sendipv6=&sock_info[r];
 	#endif
+#ifdef USE_TCP
+			tcp_info[r]=sock_info[r]; /* copy the sockets */
+			/* same thing for tcp */
+			if (tcp_init(&tcp_info[r])==-1)  goto error;
+			/* get first ipv4/ipv6 socket*/
+			if ((tcp_info[r].address.af==AF_INET)&&
+					((sendipv4_tcp==0)||(sendipv4_tcp->is_lo)))
+				sendipv4_tcp=&tcp_info[r];
+	#ifdef USE_IPV6
+			if((sendipv6_tcp==0)&&(tcp_info[r].address.af==AF_INET6))
+				sendipv6_tcp=&tcp_info[r];
+	#endif
+#endif
 			/* all procs should have access to all the sockets (for sending)
 			 * so we open all first*/
 		}

+ 16 - 8
msg_translator.c

@@ -147,7 +147,7 @@ char * warning_builder( struct sip_msg *msg, unsigned int *returned_len)
 	print_len=snprintf(buf+fix_len, MAX_WARNING_LEN-fix_len,
 		"pid=%d req_src_ip=%s in_uri=%.*s out_uri=%.*s via_cnt%c=%d\"",
 		my_pid(),
-		ip_addr2a(&msg->src_ip),
+		ip_addr2a(&msg->rcv.src_ip),
 		msg->first_line.u.request.uri.len, msg->first_line.u.request.uri.s,
 		foo->len, foo->s, 
 		msg->parsed_flag & HDR_EOH ? '=' : '>', /* should be = */
@@ -175,7 +175,7 @@ char* received_builder(struct sip_msg *msg, unsigned int *received_len)
 	int extra_len;
 
 	extra_len = 0;
-	source_ip=&msg->src_ip;
+	source_ip=&msg->rcv.src_ip;
 	buf = 0;
 
 	buf=pkg_malloc(sizeof(char)*MAX_RECEIVED_SIZE);
@@ -393,7 +393,7 @@ static inline void process_lumps(	struct lump* l,	char* new_buf,
 
 char * build_req_buf_from_sip_req( struct sip_msg* msg,
 								unsigned int *returned_len,
-								struct socket_info* send_sock)
+								struct socket_info* send_sock, int proto)
 {
 	unsigned int len, new_len, received_len, uri_len, via_len;
 	char* line_buf;
@@ -416,7 +416,7 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
 
 
 	line_buf = via_builder( &via_len, send_sock, 
-		msg->add_to_branch_s, msg->add_to_branch_len);
+		msg->add_to_branch_s, msg->add_to_branch_len, proto);
 	if (!line_buf){
 		LOG(L_ERR,"ERROR: build_req_buf_from_sip_req: no via received!\n");
 		goto error00;
@@ -424,7 +424,7 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
 	/* check if received needs to be added */
 	backup = msg->via1->host.s[msg->via1->host.len];
 	msg->via1->host.s[msg->via1->host.len] = 0;
-	r=check_address(&msg->src_ip, msg->via1->host.s, received_dns);
+	r=check_address(&msg->rcv.src_ip, msg->via1->host.s, received_dns);
 	msg->via1->host.s[msg->via1->host.len] = backup;
 	if (r!=0){
 		if ((received_buf=received_builder(msg,&received_len))==0)
@@ -612,7 +612,7 @@ char * build_res_buf_from_sip_req( unsigned int code, char *text,
 	/* check if received needs to be added */
 	backup = msg->via1->host.s[msg->via1->host.len];
 	msg->via1->host.s[msg->via1->host.len] = 0;
-	r=check_address(&msg->src_ip, msg->via1->host.s, received_dns);
+	r=check_address(&msg->rcv.src_ip, msg->via1->host.s, received_dns);
 	msg->via1->host.s[msg->via1->host.len] = backup;
 	if (r!=0) {
 		if ((received_buf=received_builder(msg,&received_len))==0) {
@@ -843,7 +843,7 @@ int branch_builder( unsigned int hash_index,
 
 char* via_builder( unsigned int *len, 
 	struct socket_info* send_sock,
-	char *branch, int branch_len )
+	char *branch, int branch_len, int proto )
 {
 	unsigned int  via_len, extra_len;
 	char               *line_buf;
@@ -865,7 +865,15 @@ char* via_builder( unsigned int *len,
 
 	via_len=MY_VIA_LEN+send_sock->address_str.len; /*space included in MY_VIA*/
 
-	memcpy(line_buf, MY_VIA, MY_VIA_LEN);
+	memcpy(line_buf, MY_VIA, MY_VIA_LEN-4); /* without "UPD " */
+	if (proto==PROTO_UDP)
+		memcpy(line_buf+MY_VIA_LEN-4, "UDP ", 4);
+	else if (proto==PROTO_TCP)
+		memcpy(line_buf+MY_VIA_LEN-4, "TCP ", 4);
+	else{
+		LOG(L_CRIT, "BUG: via_builder: unknown proto %d\n", proto);
+		return 0;
+	}
 #	ifdef USE_IPV6
 	if (send_sock->address.af==AF_INET6) {
 		line_buf[MY_VIA_LEN]='[';

+ 3 - 2
msg_translator.h

@@ -38,7 +38,8 @@
 #include "ip_addr.h"
 
 char * build_req_buf_from_sip_req (	struct sip_msg* msg, 
-				unsigned int *returned_len, struct socket_info* send_sock);
+				unsigned int *returned_len, struct socket_info* send_sock,
+				int proto);
 
 char * build_res_buf_from_sip_res(	struct sip_msg* msg,
 				unsigned int *returned_len);
@@ -52,7 +53,7 @@ char * build_res_buf_from_sip_req(	unsigned int code ,
 
 char* via_builder( unsigned int *len,
 	struct socket_info* send_sock,
-	char *branch, int branch_len );
+	char *branch, int branch_len, int proto );
 
 #ifdef _OBSOLETED
 char* via_builder( struct sip_msg *msg ,

+ 11 - 7
parser/msg_parser.h

@@ -53,6 +53,7 @@
 enum request_method { METHOD_INVITE=1, METHOD_CANCEL=2, METHOD_ACK=4, 
 	METHOD_BYE=8, METHOD_OTHER=16 };
 
+
 #define IFISMETHOD(methodname,firstchar)                                  \
 if (  (*tmp==(firstchar) || *tmp==((firstchar) | 32)) &&                  \
         strncasecmp( tmp+1, #methodname +1, methodname##_LEN-1)==0 &&     \
@@ -116,14 +117,12 @@ struct sip_msg {
 
 	char* eoh;        /* pointer to the end of header (if found) or null */
 	char* unparsed;   /* here we stopped parsing*/
-
-	struct ip_addr src_ip;
-	struct ip_addr dst_ip;
+	
+	struct receive_info rcv; /* source & dest ip, ports, proto a.s.o*/
 	
 	char* orig;       /* original message copy */
 	char* buf;        /* scratch pad, holds a modfied message,
-			   *  via, etc. point into it 
-			   */
+					   *  via, etc. point into it */
 	unsigned int len; /* message len (orig) */
 
 	     /* modifications */
@@ -214,13 +213,18 @@ inline static int char_msg_val( struct sip_msg *msg, char *cv )
 inline static char* get_body(struct sip_msg *msg)
 {
 	int offset;
+	int len;
 
 	if ( parse_headers(msg,HDR_EOH, 0)==-1 )
 		return 0;
 
-	if ( strncmp(CRLF,msg->unparsed,CRLF_LEN)==0 )
+	if (msg->unparsed){
+		len=(int)(msg->unparsed-msg->buf);
+	}else return 0;
+	if ((len+2<=msg->len) && (strncmp(CRLF,msg->unparsed,CRLF_LEN)==0) )
 		offset = CRLF_LEN;
-	else if (*(msg->unparsed)=='\n' || *(msg->unparsed)=='\r' )
+	else if ( (len+1<=msg->len) &&
+				(*(msg->unparsed)=='\n' || *(msg->unparsed)=='\r' ) )
 		offset = 1;
 	else
 		return 0;

+ 89 - 57
parser/parse_via.c

@@ -46,6 +46,7 @@
 #include "../dprint.h"
 #include "../ut.h"
 #include "../mem/mem.h"
+#include "../ip_addr.h"
 #include "parse_via.h"
 #include "parse_def.h"
 
@@ -72,7 +73,9 @@ enum {
 	SIP1, SIP2, FIN_SIP,
 	L_VER, F_VER,
 	VER1, VER2, FIN_VER,
-	L_PROTO, F_PROTO, P_PROTO
+	UDP1, UDP2, FIN_UDP,
+	TCP1, TCP2, FIN_TCP,
+	L_PROTO, F_PROTO
 };
 
 
@@ -99,12 +102,14 @@ enum {
  * output state = L_PARAM or F_PARAM or END_OF_HEADER
  * (and saved_state= last state); everything else => error 
  */
-static /*inline*/ char* parse_via_param(char* p, char* end, int* pstate, 
-				    int* psaved_state, struct via_param* param)
+static /*inline*/ char* parse_via_param(char* p, char* end,
+										unsigned char* pstate, 
+				    					unsigned char* psaved_state,
+										struct via_param* param)
 {
 	char* tmp;
-	register int state;
-	int saved_state;
+	register unsigned char state;
+	unsigned char saved_state;
 
 	state=*pstate;
 	saved_state=*psaved_state;
@@ -866,8 +871,8 @@ static /*inline*/ char* parse_via_param(char* p, char* end, int* pstate,
 char* parse_via(char* buffer, char* end, struct via_body *vb)
 {
 	char* tmp;
-	int state;
-	int saved_state;
+	unsigned char state;
+	unsigned char saved_state;
 	int c_nest;
 	int err;
 
@@ -888,9 +893,16 @@ parse_again:
 					case F_VER:
 					case F_PROTO:
 						break;
-					case P_PROTO:
+					case FIN_UDP:
 						*tmp=0;  /* finished proto parsing */
 						vb->transport.len=tmp-vb->transport.s;
+						vb->proto=PROTO_UDP;
+						state=F_HOST; /* start looking for host*/
+						goto main_via;
+					case FIN_TCP:
+						*tmp=0;  /* finished proto parsing */
+						vb->transport.len=tmp-vb->transport.s;
+						vb->proto=PROTO_TCP;
 						state=F_HOST; /* start looking for host*/
 						goto main_via;
 					case FIN_SIP:
@@ -924,9 +936,17 @@ parse_again:
 						saved_state=state;
 						state=F_LF;
 						break;
-					case P_PROTO:
+					case FIN_UDP:
+						*tmp=0;
+						vb->transport.len=tmp-vb->transport.s;
+						vb->proto=PROTO_UDP;
+						state=F_LF;
+						saved_state=F_HOST; /* start looking for host*/
+						goto main_via;
+					case FIN_TCP:
 						*tmp=0;
 						vb->transport.len=tmp-vb->transport.s;
+						vb->proto=PROTO_TCP;
 						state=F_LF;
 						saved_state=F_HOST; /* start looking for host*/
 						goto main_via;
@@ -965,9 +985,17 @@ parse_again:
 						saved_state=state;
 						state=F_CR;
 						break;
-					case P_PROTO:
+					case FIN_UDP:
 						*tmp=0;
 						vb->transport.len=tmp-vb->transport.s;
+						vb->proto=PROTO_UDP;
+						state=F_CR;
+						saved_state=F_HOST;
+						goto main_via;
+					case FIN_TCP:
+						*tmp=0;
+						vb->transport.len=tmp-vb->transport.s;
+						vb->proto=PROTO_TCP;
 						state=F_CR;
 						saved_state=F_HOST;
 						goto main_via;
@@ -1027,13 +1055,6 @@ parse_again:
 						state=SIP1;
 						vb->name.s=tmp;
 						break;
-					/* allow S in PROTO */
-					case F_PROTO:
-						state=P_PROTO;
-						vb->transport.s=tmp;
-						break;
-					case P_PROTO:
-						break;
 					default:
 						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
 								" state %d\n", *tmp, state);
@@ -1046,13 +1067,6 @@ parse_again:
 					case SIP1:
 						state=SIP2;
 						break;
-					/* allow i in PROTO */
-					case F_PROTO:
-						vb->transport.s=tmp;
-						state=P_PROTO;
-						break;
-					case P_PROTO:
-						break;
 					default:
 						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
 								" state %d\n", *tmp, state);
@@ -1066,11 +1080,59 @@ parse_again:
 						state=FIN_SIP;
 						break;
 					/* allow p in PROTO */
+					case UDP2:
+						state=FIN_UDP;
+						break;
+					case TCP2:
+						state=FIN_TCP;
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+			case 'U':
+			case 'u':
+				switch(state){
+					case F_PROTO:
+						state=UDP1;
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+			case 'D':
+			case 'd':
+				switch(state){
+					case UDP1:
+						state=UDP2;
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+			case 'T':
+			case 't':
+				switch(state){
 					case F_PROTO:
-						state=P_PROTO;
-						vb->transport.s=tmp;
+						state=TCP1;
 						break;
-					case P_PROTO:
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+			case 'C':
+			case 'c':
+				switch(state){
+					case TCP1:
+						state=TCP2;
 						break;
 					default:
 						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
@@ -1085,13 +1147,6 @@ parse_again:
 						state=VER1;
 						vb->version.s=tmp;
 						break;
-					/* allow 2 in PROTO*/
-					case F_PROTO:
-						vb->transport.s=tmp;
-						state=P_PROTO;
-						break;
-					case P_PROTO:
-						break;
 					default:
 						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
 								" state %d\n", *tmp, state);
@@ -1103,13 +1158,6 @@ parse_again:
 					case VER1:
 						state=VER2;
 						break;
-					/* allow . in PROTO */
-					case F_PROTO:
-						vb->transport.s=tmp;
-						state=P_PROTO;
-						break;
-					case P_PROTO:
-						break;
 					default:
 						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
 								" state %d\n", *tmp, state);
@@ -1121,13 +1169,6 @@ parse_again:
 					case VER2:
 						state=FIN_VER;
 						break;
-					/* allow 0 in PROTO*/
-					case F_PROTO:
-						vb->transport.s=tmp;
-						state=P_PROTO;
-						break;
-					case P_PROTO:
-						break;
 					default:
 						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
 								" state %d\n", *tmp, state);
@@ -1136,18 +1177,9 @@ parse_again:
 				break;
 			
 			default:
-				switch(state){
-					case F_PROTO:
-						vb->transport.s=tmp;
-						state=P_PROTO;
-						break;
-					case P_PROTO:
-						break;
-					default:
 						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
 								" state %d\n", *tmp, state);
 						goto error;
-				}
 				break;
 		}
 	} /* for tmp*/

+ 2 - 0
parser/parse_via.h

@@ -41,6 +41,7 @@ enum {
 };
 
 
+
 struct via_param {
 	int type;               /* Type of the parameter */
 	str name;               /* Name of the parameter */
@@ -57,6 +58,7 @@ struct via_body {
 	str name;
 	str version;   
 	str transport;
+	int proto; /* transport */
 	str host;
 	int port;
 	str port_str;

+ 2 - 3
receive.c

@@ -50,7 +50,7 @@
 
 unsigned int msg_no=0;
 
-int receive_msg(char* buf, unsigned int len, union sockaddr_union* src_su)
+int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) 
 {
 	struct sip_msg* msg;
 #ifdef STATS
@@ -76,8 +76,7 @@ int receive_msg(char* buf, unsigned int len, union sockaddr_union* src_su)
 	/* zero termination (termination of orig message bellow not that
 	   useful as most of the work is done with scrath-pad; -jiri  */
 	/* buf[len]=0; */ /* WARNING: zero term removed! */
-	su2ip_addr(&msg->src_ip, src_su);
-	msg->dst_ip=bind_address->address; /* won't work if listening on 0.0.0.0 */
+	msg->rcv=*rcv_info;
 	msg->id=msg_no;
 	/* make a copy of the message */
 	msg->orig=(char*) pkg_malloc(len+1);

+ 1 - 1
receive.h

@@ -32,7 +32,7 @@
 
 #include "ip_addr.h"
 
-int receive_msg(char* buf, unsigned int len, union sockaddr_union *src_su);
+int receive_msg(char* buf, unsigned int len, struct receive_info *ri);
 
 
 #endif

+ 3 - 2
route.c

@@ -146,6 +146,7 @@ static int fix_actions(struct action* a)
 		switch(t->type){
 			case FORWARD_T:
 			case FORWARD_TCP_T:
+			case FORWARD_UDP_T:
 			case SEND_T:
 			case SEND_TCP_T:
 					switch(t->p1_type){
@@ -360,10 +361,10 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 				}
 				break;
 		case SRCIP_O:
-				ret=comp_ip(&msg->src_ip, e->r.param, e->op, e->subtype);
+				ret=comp_ip(&msg->rcv.src_ip, e->r.param, e->op, e->subtype);
 				break;
 		case DSTIP_O:
-				ret=comp_ip(&msg->dst_ip, e->r.param, e->op, e->subtype);
+				ret=comp_ip(&msg->rcv.dst_ip, e->r.param, e->op, e->subtype);
 				break;
 		case NUMBER_O:
 				ret=!(!e->r.intval); /* !! to transform it in {0,1} */

+ 3 - 0
route_struct.c

@@ -235,6 +235,9 @@ void print_action(struct action* a)
 			case FORWARD_TCP_T:
 					DBG("forward_tcp(");
 					break;
+			case FORWARD_UDP_T:
+					DBG("forward_udp(");
+					break;
 			case SEND_T:
 					DBG("send(");
 					break;

+ 1 - 0
route_struct.h

@@ -56,6 +56,7 @@ enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
 		APPEND_BRANCH_T,
 		REVERT_URI_T,
 		FORWARD_TCP_T,
+		FORWARD_UDP_T,
 		SEND_TCP_T};
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
 		EXPR_ST, ACTIONS_ST, CMDF_ST, MODFIXUP_ST, URIHOST_ST, URIPORT_ST,

+ 10 - 7
tcp_conn.h

@@ -41,9 +41,9 @@
 #define TCP_CHILD_SELECT_TIMEOUT 2 /* the same as above but for children */
 
 
-enum {	TCP_REQ_INIT, TCP_REQ_OK, TCP_READ_ERROR, TCP_REQ_OVERRUN, 
-	 	TCP_REQ_BAD_LEN };
-enum {	H_SKIP, H_LF, H_LFCR,  H_BODY, H_STARTWS,
+enum tcp_req_errors {	TCP_REQ_INIT, TCP_REQ_OK, TCP_READ_ERROR,
+						TCP_REQ_OVERRUN, TCP_REQ_BAD_LEN };
+enum tcp_req_states {	H_SKIP, H_LF, H_LFCR,  H_BODY, H_STARTWS,
 		H_CONT_LEN1, H_CONT_LEN2, H_CONT_LEN3, H_CONT_LEN4, H_CONT_LEN5,
 		H_CONT_LEN6, H_CONT_LEN7, H_CONT_LEN8, H_CONT_LEN9, H_CONT_LEN10,
 		H_CONT_LEN11, H_CONT_LEN12, H_CONT_LEN13, H_L_COLON, 
@@ -51,8 +51,8 @@ enum {	H_SKIP, H_LF, H_LFCR,  H_BODY, H_STARTWS,
 	};
 
 /* fd communication commands */
-enum { CONN_DESTROY=-3, CONN_ERROR=-2, CONN_EOF=-1, CONN_RELEASE, CONN_GET_FD,
-	   CONN_NEW };
+enum conn_cmds { CONN_DESTROY=-3, CONN_ERROR=-2, CONN_EOF=-1, CONN_RELEASE, 
+					CONN_GET_FD, CONN_NEW };
 
 struct tcp_req{
 	struct tcp_req* next;
@@ -65,8 +65,8 @@ struct tcp_req{
 	int has_content_len; /* 1 if content_length was parsed ok*/
 	int complete; /* 1 if one req has been fully read, 0 otherwise*/
 	int bytes_to_go; /* how many bytes we have still to read from the body*/
-	int error;
-	int state;
+	enum tcp_req_errors error;
+	enum tcp_req_states state;
 };
 
 
@@ -77,10 +77,13 @@ struct tcp_connection{
 	int fd; /* used only by "children" */
 	int id; /* id (unique!) used to retrieve a specific connection when
 	           reply-ing*/
+	struct receive_info rcv; /* src & dst ip, ports, proto a.s.o*/
+#if 0
 	struct ip_addr ip; /* peer ip */
 	int port; /* peer port */
 	int sock_idx; /* receiving socket index in the tcp_info array */
 	union sockaddr_union su;
+#endif
 	struct tcp_req req; /* request data */
 	int refcnt;
 	int timeout; /* connection timeout, after this it will be removed*/

+ 39 - 0
tcp_init.h

@@ -0,0 +1,39 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2001-2003 Fhg Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef tcp_init_h
+#define tcp_init_h
+#include "ip_addr.h"
+
+int init_tcp();
+int tcp_init(struct socket_info* sock_info);
+int tcp_init_children();
+void tcp_main_loop();
+void tcp_receive_loop(int unix_sock);
+
+
+#endif

+ 63 - 35
tcp_main.c

@@ -55,6 +55,7 @@
 #include "mem/shm_mem.h"
 #include "timer.h"
 #include "tcp_server.h"
+#include "tcp_init.h"
 
 
 
@@ -81,7 +82,8 @@ int unix_tcp_sock;
 
 
 
-struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su, int i)
+struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su,
+									struct socket_info* ba)
 {
 	struct tcp_connection *c;
 	
@@ -93,14 +95,22 @@ struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su, int i)
 	}
 	c->s=sock;
 	c->fd=sock;
-	c->su=*su;
-	c->sock_idx=i;
+	c->rcv.src_su=*su;
+	
 	c->refcnt=0;
-	su2ip_addr(&c->ip, su);
-	c->port=su_getport(su);
+	su2ip_addr(&c->rcv.src_ip, su);
+	c->rcv.src_port=su_getport(su);
+	c->rcv.proto=PROTO_TCP;
+	c->rcv.bind_address=ba;
+	if (ba){
+		c->rcv.dst_ip=ba->address;
+		c->rcv.dst_port=ba->port_no;
+	}
 	init_tcp_req(&c->req);
 	c->timeout=get_ticks()+TCP_CON_TIMEOUT;
 	c->id=connection_id++;
+	c->rcv.proto_reserved1=0; /* this will be filled before receive_message*/
+	c->rcv.proto_reserved2=0;
 	return c;
 	
 error:
@@ -157,14 +167,16 @@ struct tcp_connection* tcpconn_find(int id, struct ip_addr* ip, int port)
 
 	struct tcp_connection *c;
 	
-	DBG("tcpconn_find: %d ",id ); print_ip(ip); DBG(" %d\n", port);
+	DBG("tcpconn_find: %d ",id ); print_ip(ip); DBG(" %d\n", ntohs(port));
 	for (c=*conn_list; c; c=c->next){
 		DBG("c=%p, c->id=%d, ip=",c, c->id);
-		print_ip(&c->ip);
-		DBG(" port=%d\n", c->port);
+		print_ip(&c->rcv.src_ip);
+		DBG(" port=%d\n", ntohs(c->rcv.src_port));
 		if (id){
 			if (id==c->id) return c;
-		}else if ((port==c->port)&&(ip_addr_cmp(ip, &c->ip))) return c;
+		}else if (ip &&	(port==c->rcv.src_port)&&
+					(ip_addr_cmp(ip, &c->rcv.src_ip)))
+			return c;
 	}
 	return 0;
 }
@@ -199,17 +211,31 @@ int tcp_send(char* buf, unsigned len, union sockaddr_union* to, int id)
 	long response[2];
 	int n;
 	
-	su2ip_addr(&ip, to);
-	port=su_getport(to);
+	port=0;
+	if (to){
+		su2ip_addr(&ip, to);
+		port=su_getport(to);
+		c=tcpconn_get(id, &ip, port); /* lock ;inc refcnt; unlock */
+	}else if (id){
+		c=tcpconn_get(id, 0, 0);
+	}else{
+		LOG(L_CRIT, "BUG: tcp_send called with null id & to\n");
+		return -1;
+	}
 	
-	c=tcpconn_get(id, &ip, port); /* lock ;inc refcnt; unlock */
 	if (id){
 		if (c==0) {
-		LOG(L_ERR, "ERROR: tcp_send: id %d not found, dropping\n",
-					id);
-			return -1;
-		}
-	}else{
+			if (to){
+				c=tcpconn_get(0, &ip, port); /* try again w/o id */
+				goto no_id;
+			}else{
+				LOG(L_ERR, "ERROR: tcp_send: id %d not found, dropping\n",
+						id);
+				return -1;
+			}
+		}else goto get_fd;
+	}
+no_id:
 		if (c==0){
 			DBG("tcp_send: no open tcp connection found, opening new one\n");
 			/* create tcp connection */
@@ -224,18 +250,24 @@ int tcp_send(char* buf, unsigned len, union sockaddr_union* to, int id)
 			response[1]=CONN_NEW;
 			n=write(unix_tcp_sock, response, sizeof(response));
 			n=send_fd(unix_tcp_sock, &c, sizeof(c), c->s);
-		}else{
+			goto send_it;
+		}
+get_fd:
 			DBG("tcp_send: tcp connection found, acquiring fd\n");
 			/* get the fd */
 			response[0]=(long)c;
 			response[1]=CONN_GET_FD;
 			n=write(unix_tcp_sock, response, sizeof(response));
+			DBG("tcp_send, c= %p, n=%d\n", c, n);
 			n=receive_fd(unix_tcp_sock, &c, sizeof(c), &c->fd);
-		}
+			DBG("tcp_send: after receive_fd: c= %p n=%d fd=%d\n",c, n, c->fd);
+		
 	
-	}
+	
+send_it:
 	DBG("tcp_send: sending...\n");
 	n=write(c->fd, buf, len);
+	DBG("tcp_send: after write: c= %p n=%d fd=%d\n",c, n, c->fd);
 	close(c->fd);
 	tcpconn_put(c); /* release c (lock; dec refcnt; unlock) */
 	return n;
@@ -269,12 +301,12 @@ void tcpconn_timeout(fd_set* set)
 
 
 
-int tcp_init_sock(struct socket_info* sock_info)
+int tcp_init(struct socket_info* sock_info)
 {
 	union sockaddr_union* addr;
 	
 	addr=&sock_info->su;
-	sock_info->proto=SOCKET_TCP;
+	sock_info->proto=PROTO_TCP;
 	if (init_su(addr, &sock_info->address, htons(sock_info->port_no))<0){
 		LOG(L_ERR, "ERROR: tcp_init: could no init sockaddr_union\n");
 		goto error;
@@ -369,14 +401,14 @@ void tcp_main_loop()
 	FD_ZERO(&master_set);
 	/* set all the listen addresses */
 	for (r=0; r<sock_no; r++){
-		if ((tcp_info[r].proto==SOCKET_TCP) &&(tcp_info[r].socket!=-1)){
+		if ((tcp_info[r].proto==PROTO_TCP) &&(tcp_info[r].socket!=-1)){
 			FD_SET(tcp_info[r].socket, &master_set);
 			if (tcp_info[r].socket>maxfd) maxfd=tcp_info[r].socket;
 		}
 	}
 	/* set all the unix sockets used for child comm */
-	for (r=0; r<process_no; r++){
-		if (pt[r].unix_sock>=0){
+	for (r=1; r<process_no; r++){
+		if (pt[r].unix_sock>0){ /* we can't have 0, we never close it!*/
 			FD_SET(pt[r].unix_sock, &master_set);
 			if (pt[r].unix_sock>maxfd) maxfd=pt[r].unix_sock;
 		}
@@ -399,8 +431,7 @@ void tcp_main_loop()
 		}
 		
 		for (r=0; r<sock_no && n; r++){
-			if ((tcp_info[r].proto==SOCKET_TCP) &&
-					(FD_ISSET(tcp_info[r].socket, &sel_set))){
+			if ((FD_ISSET(tcp_info[r].socket, &sel_set))){
 				/* got a connection on r */
 				su_len=sizeof(su);
 				new_sock=accept(tcp_info[r].socket, &(su.s), &su_len);
@@ -412,7 +443,7 @@ void tcp_main_loop()
 				}
 				
 				/* add socket to list */
-				tcpconn=tcpconn_new(new_sock, &su, r);
+				tcpconn=tcpconn_new(new_sock, &su, &tcp_info[r]);
 				if (tcpconn){
 					tcpconn_add(tcpconn);
 					DBG("tcp_main_loop: new connection: %p %d\n",
@@ -449,7 +480,8 @@ void tcp_main_loop()
 		/* check unix sockets & listen | destroy connections */
 		/* start from 1, the "main" process does not transmit anything*/
 		for (r=1; r<process_no && n; r++){
-			if ( (pt[r].unix_sock>=0) && FD_ISSET(pt[r].unix_sock, &sel_set)){
+			if ( (pt[r].unix_sock>0) && FD_ISSET(pt[r].unix_sock, &sel_set)){
+				/* (we can't have a fd==0, 0 i s never closed )*/
 				n--;
 				/* errno==EINTR !!! TODO*/
 read_again:
@@ -560,7 +592,7 @@ int init_tcp()
 	/* allocate list head*/
 	conn_list=shm_malloc(sizeof(struct tcp_connection*));
 	if (conn_list==0){
-		LOG(L_CRIT, "ERROR: tcp_init: memory allocation failure\n");
+		LOG(L_CRIT, "ERROR: init_tcp: memory allocation failure\n");
 		goto error;
 	}
 	*conn_list=0;
@@ -580,11 +612,7 @@ int tcp_init_children()
 	
 	
 	/* create the tcp sock_info structures */
-	/* copy the sockets*/
-	for (r=0; r<sock_no ; r++){
-		tcp_info[r]=sock_info[r];
-		tcp_init_sock(&tcp_info[r]);
-	}
+	/* copy the sockets --moved to main_loop*/
 	
 	/* fork children & create the socket pairs*/
 	for(r=0; r<tcp_children_no; r++){

+ 2 - 1
tcp_read.c

@@ -366,7 +366,8 @@ int tcp_read_req(struct tcp_connection* con)
 			DBG("calling receive_msg(%p, %d, )\n",
 					req->buf, (int)(req->parsed-req->buf));
 			bind_address=sendipv4; /*&tcp_info[con->sock_idx];*/
-			if (receive_msg(req->buf, req->parsed-req->buf, &con->su)<0){
+			con->rcv.proto_reserved1=con->id; /* copy the id */
+			if (receive_msg(req->buf, req->parsed-req->buf, &con->rcv)<0){
 				resp=CONN_ERROR;
 				goto end_req;
 			}

+ 12 - 2
udp_server.c

@@ -213,6 +213,7 @@ int udp_init(struct socket_info* sock_info)
 		goto error;
 	}
 */
+	sock_info->proto=PROTO_UDP;
 	if (init_su(addr, &sock_info->address, htons(sock_info->port_no))<0){
 		LOG(L_ERR, "ERROR: udp_init: could not init sockaddr_union\n");
 		goto error;
@@ -278,6 +279,7 @@ int udp_rcv_loop()
 
 	union sockaddr_union* from;
 	unsigned int fromlen;
+	struct receive_info ri;
 
 
 	from=(union sockaddr_union*) malloc(sizeof(union sockaddr_union));
@@ -286,7 +288,11 @@ int udp_rcv_loop()
 		goto error;
 	}
 	memset(from, 0 , sizeof(union sockaddr_union));
-
+	ri.bind_address=bind_address; /* this will not change, we do it only once*/
+	ri.dst_port=bind_address->port_no;
+	ri.dst_ip=bind_address->address;
+	ri.proto=PROTO_UDP;
+	ri.proto_reserved1=ri.proto_reserved2=0;
 	for(;;){
 #ifdef DYN_BUF
 		buf=pkg_malloc(BUF_SIZE+1);
@@ -327,9 +333,13 @@ int udp_rcv_loop()
 			continue;
 		}
 #endif
+		ri.src_su=*from;
+		su2ip_addr(&ri.src_ip, from);
+		ri.src_port=su_getport(from);
+		
 		
 		/* receive_msg must free buf too!*/
-		receive_msg(buf, len, from);
+		receive_msg(buf, len, &ri);
 		
 	/* skip: do other stuff */