- changed sip_msg (new rcv member containing all the ips, ports, protocol)
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Thu, 12 Dec 2002 21:46:37 +0000 (21:46 +0000)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Thu, 12 Dec 2002 21:46:37 +0000 (21:46 +0000)
- 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.)

25 files changed:
Makefile.defs
TODO
action.c
cfg.lex
cfg.y
forward.c
forward.h
globals.h
ip_addr.h
main.c
msg_translator.c
msg_translator.h
parser/msg_parser.h
parser/parse_via.c
parser/parse_via.h
receive.c
receive.h
route.c
route_struct.c
route_struct.h
tcp_conn.h
tcp_init.h [new file with mode: 0644]
tcp_main.c
tcp_read.c
udp_server.c

index 705dc0f..6e8644c 100644 (file)
@@ -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]")
diff --git a/TODO b/TODO
index c881e17..7181abd 100644 (file)
--- a/TODO
+++ b/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}
index ae90047..7ef9bf8 100644 (file)
--- a/action.c
+++ b/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{
diff --git a/cfg.lex b/cfg.lex
index b105854..0145975 100644 (file)
--- a/cfg.lex
+++ b/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; }
diff --git a/cfg.y b/cfg.y
index aae6738..098d405 100644 (file)
--- a/cfg.y
+++ b/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,
index 689a86d..323a4b1 100644 (file)
--- a/forward.c
+++ b/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>
 /* 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);
index 1abf278..711d51b 100644 (file)
--- a/forward.h
+++ b/forward.h
 #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
index e5b758b..2e5a1ed 100644 (file)
--- a/globals.h
+++ b/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
 
index 9242116..7cfed92 100644 (file)
--- a/ip_addr.h
+++ b/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)
diff --git a/main.c b/main.c
index 12335a3..d54ae5f 100644 (file)
--- a/main.c
+++ b/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*/
                }
index 293f5b2..5c04f10 100644 (file)
@@ -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]='[';
index c9fd235..a228193 100644 (file)
@@ -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 ,
index d152443..2cf428d 100644 (file)
@@ -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;
index 082af41..6c57258 100644 (file)
@@ -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*/
index fba9b1b..767cbc8 100644 (file)
@@ -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;
index 01ed8fa..8c7112e 100644 (file)
--- a/receive.c
+++ b/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);
index 9878dd8..40ae47f 100644 (file)
--- a/receive.h
+++ b/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
diff --git a/route.c b/route.c
index d68c6d2..04235ae 100644 (file)
--- a/route.c
+++ b/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} */
index 17b3414..f76d65f 100644 (file)
@@ -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;
index 8bfbad5..b752fd7 100644 (file)
@@ -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,
index 387f095..018a790 100644 (file)
@@ -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*/
diff --git a/tcp_init.h b/tcp_init.h
new file mode 100644 (file)
index 0000000..383cec0
--- /dev/null
@@ -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:
+ *    info@iptel.org
+ *
+ * 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
index e4bd5bf..7438d81 100644 (file)
@@ -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++){
index 631d6d1..2038825 100644 (file)
@@ -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;
                        }
index 4352e2a..cd27e65 100644 (file)
@@ -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 */