First working release
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 4 Sep 2001 20:55:41 +0000 (20:55 +0000)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 4 Sep 2001 20:55:41 +0000 (20:55 +0000)
13 files changed:
Makefile [new file with mode: 0644]
cfg_parser.c
cfg_parser.h
config.h [new file with mode: 0644]
forward.c
main.c
msg_parser.c
route.c
route.h
sip_router.cfg
test.c.bak [moved from test.c with 100% similarity]
udp_server.c [new file with mode: 0644]
udp_server.h [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..655ec72
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,48 @@
+# $Id$
+#
+# sip_router makefile
+#
+
+sources= $(wildcard *.c)
+objs= $((sources:.c=.o)
+depends= $(sources:.c=.d)
+
+NAME=sip_router
+
+CC=gcc
+COPTS=-O2
+ALLDEP=Makefile
+
+MKDEP=gcc -M
+
+
+#implicit rules
+
+%.o:%.c $(ALLDEP)
+       $(CC) $(COPTS) -c $< -o $@
+
+%.d: %.c
+       $(MKDEP) $< >$@
+
+$(NAME): $(objs)
+       $(CC) $(COPTS) $(objs) -o $(NAME)
+
+.PHONY: all
+all: $(NAME)
+
+.PHONY: dep
+dep: $(depends)
+
+.PHONY: clean
+clean:
+       -rm $(objs) $(NAME)
+
+.PHONY: proper
+proper: clean
+       -rm $(depends)
+
+include $(depends)
+
+
+
+
index 85ec804..e35e2b5 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdio.h>
 
 #include "cfg_parser.h"
+#include "msg_parser.h" /* parse_hostport */
 #include "dprint.h"
 #include "parser_f.h"
 #include "route.h"
@@ -40,28 +41,23 @@ int cfg_parse_line(char* line, struct cfg_line* cl)
        cl->method=tmp;
        tmp=eat_token(cl->method,end-cl->method);
        if (tmp==end) goto error;
-       printf("%d\n", tmp-line);
        *tmp=0;
        tmp++;
        cl->uri=eat_space(tmp,end-tmp);
        if (tmp==end) goto error;
        tmp=eat_token(cl->uri,end-cl->uri);
        if (tmp==end) goto error;
-       printf("%d\n", tmp-line);
        *tmp=0;
        tmp++;
        cl->address=eat_space(tmp,end-tmp);
        if (tmp==end) goto error;
        tmp=eat_token(cl->address, end-cl->address);
-       printf("%d(%02x)\n", tmp-line, *tmp);
        if (tmp<end) {
                *tmp=0;
                if (tmp+1<end){
                        if (!is_empty(tmp+1,end-tmp-1)){
-                               printf("%d(%02x) e: %d\n", tmp-line, *tmp, end-line);
                                /* check if comment */
                                tmp=eat_space(tmp+1, end-tmp-1);
-                               printf("%d(%02x) e: %d\n", tmp-line, *tmp, end-line);
                                if (*tmp!='#'){
                                        /* extra chars at the end of line */
                                        goto error;
@@ -69,7 +65,11 @@ int cfg_parse_line(char* line, struct cfg_line* cl)
                        }
                }
        }
-               
+       /* find port */
+       if (parse_hostport(cl->address, &tmp, &cl->port)==0){
+                       goto error;
+       }
+       
        cl->type=CFG_RULE;
 skip:
        return 0;
index 627afbf..2f1e0ff 100644 (file)
@@ -20,6 +20,7 @@ struct cfg_line{
        char* method;
        char* uri;
        char* address;
+       short int port;
 };
 
 
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..58ac4d6
--- /dev/null
+++ b/config.h
@@ -0,0 +1,18 @@
+/*
+ *  $Id
+ */
+
+
+
+#ifndef config_h
+#define config_h
+
+/* default sip port if none specified */
+#define SIP_PORT 5060
+
+#define CFG_FILE "./sip_router.cfg"
+
+/* receive buffer size */
+#define BUF_SIZE 65507
+
+#endif
index 4f9c6b9..1342656 100644 (file)
--- a/forward.c
+++ b/forward.c
@@ -4,17 +4,19 @@
 
 
 #include <string.h>
+#include <netdb.h>
+#include <netinet/in.h>
 
 #include "forward.h"
+#include "config.h"
 #include "msg_parser.h"
 #include "route.h"
 #include "dprint.h"
+#include "udp_server.h"
 
 #define MAX_VIA_LINE_SIZE      240
 #define MAX_RECEIVED_SIZE  57
 
-#define our_address "dorian.fokus.gmd.de"
-#define our_port 1234
 
 
 int forward_request(char * orig, char* buf, 
@@ -27,12 +29,12 @@ int forward_request(char * orig, char* buf,
        char received_buf[MAX_RECEIVED_SIZE];
        char* new_buf;
        int offset, s_offset, size;
+       struct sockaddr_in to;
 
        received_len=0;
-       printf("0\n");
 
        via_len=snprintf(line_buf, MAX_VIA_LINE_SIZE, "Via: SIP/2.0/UDP %s:%d\r\n",
-                                               our_address, our_port);
+                                               our_name, our_port);
        /* check if received needs to be added */
        /* if check_address(source_ip, msg->via1.host) */
        received_len=snprintf(received_buf, MAX_RECEIVED_SIZE, ";received=%s",
@@ -42,49 +44,67 @@ int forward_request(char * orig, char* buf,
        new_buf=(char*)malloc(new_len+1);
        if (new_buf==0){
                DPrint("ERROR: forward_request: out of memory\n");
-               goto error;
+               goto error1;
        }
-       printf("1\n");
- /* copy msg till first via */
-       offset=s_offset=0;
-       size=msg->via1.hdr-buf;
-       memcpy(new_buf, orig, size);
+/* copy msg till first via */
+       offset=s_offset=0;
+       size=msg->via1.hdr-buf;
+       memcpy(new_buf, orig, size);
        offset+=size;
        s_offset+=size;
-       printf("2\n");
  /* add our via */
-       memcpy(new_buf+offset, line_buf, via_len);
+       memcpy(new_buf+offset, line_buf, via_len);
        offset+=via_len;
-       printf("3\n");
  /* modify original via if neccesarry (received=...)*/
-       if (received_len){
+       if (received_len){
                if (msg->via1.params){
                                size= msg->via1.params-msg->via1.hdr-1; /*compensate for ';' */
                }else{
                                size= msg->via1.host-msg->via1.hdr+strlen(msg->via1.host);
                                if (msg->via1.port!=0){
-                                       size+=strlen(msg->via1.hdr+size+1);
+                                       size+=strlen(msg->via1.hdr+size+1)+1; /* +1 for ':'*/
                                }
                }
                memcpy(new_buf+offset, orig+s_offset, 
                                                                size);
                offset+=size;
                s_offset+=size;
-               printf("4\n");
                memcpy(new_buf+offset, received_buf, received_len);
-               printf("5\n");
                offset+=received_len;
        }
        /* copy the rest of the msg */
        memcpy(new_buf+offset, orig+s_offset, len-s_offset);
-       printf("6\n");
        new_buf[new_len]=0;
 
         /* send it! */
-        printf("Sending:\n%s.\n", new_buf);
-        
+       printf("Sending:\n%s.\n", new_buf);
+       printf("orig. len=%d, new_len=%d, via_len=%d, received_len=%d\n",
+                       len, new_len, via_len, received_len);
+
+       to.sin_family = AF_INET;
+       to.sin_port = (re->port)?htons(re->port):htons(SIP_PORT);
+       /* if error try next ip address if possible */
+       if (re->ok==0){
+               if (re->host.h_addr_list[re->current_addr_idx+1])
+                       re->current_addr_idx++;
+               re->ok=1;
+       }
+       /* ? not 64bit clean?*/
+       to.sin_addr.s_addr=*((long*)re->host.h_addr_list[re->current_addr_idx]);
+
+       re->tx++;
+       re->tx_bytes+=new_len;
+       if (udp_send(new_buf, new_len, &to, sizeof(to))==-1){
+                       re->errors++;
+                       re->ok=0;
+                       goto error;
+       }
+
+       free(new_buf);
        return 0;
 error:
+       free(new_buf);
+error1:
        return -1;
 
 }
@@ -101,37 +121,51 @@ int forward_reply(char * orig, char* buf,
        unsigned int new_len, via_len;
        char* new_buf;
        int offset, s_offset, size;
+       struct hostent* he;
+       struct sockaddr_in to;
 
 
-       /* we must remove first via */
+       /* we must remove the first via */
        via_len=msg->via1.size;
        size=msg->via1.hdr-buf;
        if (msg->via1.next){
-               via_len-=strlen(msg->via1.hdr)+1; /* +1 from ':' */
+               /* keep hdr =substract hdr size +1 (hdr':') and add
+                */
+               via_len-=strlen(msg->via1.hdr)+1;
                size+=strlen(msg->via1.hdr)+1;
        }
        new_len=len-size;
-       printf("r1\n");
        new_buf=(char*)malloc(new_len);
        if (new_buf==0){
                DPrint("ERROR: forward_reply: out of memory\n");
                goto error;
        }
-       printf("r2\n");
        memcpy(new_buf, orig, size);
        offset=size;
        s_offset=size+via_len;
-       printf("r3\n");
        memcpy(new_buf+offset,orig+s_offset, len-s_offset);
-       printf("r4\n");
         /* send it! */
        printf("Sending: to %s:%d, \n%s.\n",
                        msg->via2.host, 
                        (unsigned short)msg->via2.port,
                        new_buf);
+       /* fork? gethostbyname will probably block... */
+       he=gethostbyname(msg->via2.host);
+       if (he==0){
+               DPrint("ERROR:forward_reply:gethostbyname failure\n");
+               goto error;
+       }
+       to.sin_family = AF_INET;
+       to.sin_port = (msg->via2.port)?htons(msg->via2.port):htons(SIP_PORT);
+       to.sin_addr.s_addr=*((long*)he->h_addr_list[0]);
+       
+       if (udp_send(new_buf,new_len, &to, sizeof(to))==-1)
+               goto error;
        
+       free(new_buf);
        return 0;
 
 error:
+       if (new_buf) free(new_buf);
        return -1;
 }
diff --git a/main.c b/main.c
index 564dfd5..1ad999c 100644 (file)
--- a/main.c
+++ b/main.c
@@ -5,15 +5,17 @@
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
+#include <netdb.h>
 
+#include "config.h"
 #include "dprint.h"
 #include "route.h"
+#include "udp_server.h"
 
-#define CFG_FILE "./sip_router.cfg"
 
 
 /* debuging function */
-
+/*
 void receive_stdin_loop()
 {
        #define BSIZE 1024
@@ -27,7 +29,9 @@ void receive_stdin_loop()
                printf("-------------------------\n");
        }
 }
+*/
 
+#define NAME "dorian.fokus.gmd.de"
 
 
 int main(int argc, char** argv)
@@ -35,12 +39,29 @@ int main(int argc, char** argv)
 
        char * cfg_file;
        FILE* cfg_stream;
+       struct hostent* he;
 
        cfg_file=CFG_FILE;
        
        /* process command line (get port no, cfg. file path etc) */
        /* ...*/
 
+       our_port=SIP_PORT;
+       our_name=NAME;
+       /* get ip */
+       he=gethostbyname(our_name);
+       if (he==0){
+               DPrint("ERROR: could not resolve %s\n", our_name);
+               goto error;
+       }
+       our_address=*((long*)he->h_addr_list[0]);
+       printf("Listening on %s[%x]:%d\n",our_name,
+                               (unsigned long)our_address,
+                               (unsigned short)our_port);
+               
+       
+       
+
        /* load config file or die */
        cfg_stream=fopen (cfg_file, "r");
        if (cfg_stream==0){
@@ -57,12 +78,12 @@ int main(int argc, char** argv)
        print_rl();
 
 
-
+       /* init_daemon? */
+       if (udp_init(our_address,our_port)==-1) goto error;
        /* start/init other processes/threads ? */
 
        /* receive loop */
-
-       receive_stdin_loop();
+       udp_rcv_loop();
 
 
 error:
index f276061..a4d4f8f 100644 (file)
@@ -390,13 +390,18 @@ int parse_msg(char* buf, unsigned int len, struct sip_msg* msg)
                                                        DPrint("ERROR: parsing via body: %s\n", first_via);
                                                        goto error;
                                                }
-                                               vb1.size=bar-first_via+first_via-vb1.hdr;
+                                               
+                                               vb1.size=bar-first_via+first_via-vb1.hdr; 
                                                
                                                /* compact via */
                                                if (vb1.next) {
                                                        second_via=vb1.next;
                                                        /* not interested in the rest of the header */
                                                        goto skip;
+                                               }else{
+                                               /*  add 1 (we don't see the trailing lf which
+                                                *  was zeroed by get_hfr_field */
+                                                       vb1.size+=1;
                                                }
                                }else if (second_via==0){
                                                        second_via=hf.body;
@@ -423,7 +428,8 @@ skip:
                        DPrint("ERROR: parsing via body: %s\n", second_via);
                        goto error;
                }
-               vb2.size=tmp-second_via;
+               vb2.size=tmp-second_via; 
+               if (vb2.next==0) vb2.size+=1; /* +1 from trailing lf */
                if (vb2.hdr) vb2.size+=second_via-vb2.hdr;
        }
        
diff --git a/route.c b/route.c
index 06cb2b7..a161a52 100644 (file)
--- a/route.c
+++ b/route.c
@@ -162,7 +162,7 @@ int add_rule(struct cfg_line* cl, struct route_elem** head)
        /*finished hostent copy */
 
        
-       
+       re->port=cl->port;
        re->current_addr_idx=0;
        re->ok=1;
 
@@ -205,7 +205,7 @@ void print_rl()
        int i,j;
 
        if (rlist==0){
-               DPrint("the routing table is emty\n");
+               DPrint("the routing table is empty\n");
                return;
        }
        
@@ -221,7 +221,8 @@ void print_rl()
                                (unsigned char) t->host.h_addr_list[j][3]
                                  );
                                
-               DPrint("\n   Statistics: tx=%d, errors=%d, tx_bytes=%d, idx=%d\n",
+               DPrint("\n   port:%d\n", (unsigned short)t->port);
+               DPrint("   Statistics: tx=%d, errors=%d, tx_bytes=%d, idx=%d\n",
                                t->tx, t->errors, t->tx_bytes, t->current_addr_idx);
        }
 
diff --git a/route.h b/route.h
index bb27f7f..980876d 100644 (file)
--- a/route.h
+++ b/route.h
@@ -21,6 +21,8 @@ struct route_elem{
        regex_t uri;
        struct hostent host;
        int current_addr_idx;
+       short int port;
+       short int reserved; /* pad */
        int ok; /* set to 0 if an error was found sendig a pkt*/
        /*counters*/
        int errors;
index 56d90c1..783eb3c 100644 (file)
@@ -5,7 +5,7 @@
 # (warning: re cannot contain space)
 
 ^R.*        ^sip:.*@dorian.*   ekina.fokus.gmd.de        
-^INVITE     .*                 ape             # my laptop
+^INVITE     .*                 ape:5061             # my laptop
 .           .                  192.168.46.55
 .*                     .*andrei                   helios.fokus.gmd.de
 
similarity index 100%
rename from test.c
rename to test.c.bak
diff --git a/udp_server.c b/udp_server.c
new file mode 100644 (file)
index 0000000..58871c5
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+
+
+#include "udp_server.h"
+#include "config.h"
+#include "dprint.h"
+
+
+int udp_sock;
+
+char* our_name;
+unsigned long our_address;
+unsigned short our_port;
+
+
+
+int udp_init(unsigned long ip, unsigned short port)
+{
+       struct sockaddr_in addr;
+
+       addr.sin_family=AF_INET;
+       addr.sin_port=htons(port);
+       addr.sin_addr.s_addr=ip;
+
+       udp_sock = socket(PF_INET, SOCK_DGRAM, 0);
+       if (udp_sock==-1){
+               DPrint("ERROR: udp_init: socket: %s\n", strerror());
+               goto error;
+       }
+
+       if (bind(udp_sock, (struct sockaddr*) &addr, sizeof(addr))==-1){
+               DPrint("ERROR: udp_init: socket: %s\n", strerror());
+               goto error;
+       }
+
+       /* set sock opts? */
+
+       return 0;
+
+error:
+       return -1;
+}
+
+
+
+int udp_rcv_loop()
+{
+       int len;
+       char buf[BUF_SIZE+1];
+       struct sockaddr* from;
+       int fromlen;
+
+       from=(struct sockaddr*) malloc(sizeof(struct sockaddr));
+       if (from==0){
+               DPrint("ERROR: udp_rcv_loop: out of memory\n");
+               goto error;
+       }
+
+       for(;;){
+               fromlen=sizeof(*from);
+               len=recvfrom(udp_sock, buf, BUF_SIZE, 0, from, &fromlen);
+               if (len==-1){
+                       DPrint("ERROR: udp_rcv_loop:recvfrom: %s\n", strerror());
+                       if (errno==EINTR)       goto skip;
+                       else goto error;
+               }
+               /*debugging, make print* msg work */
+               buf[len+1]=0;
+
+               receive_msg(buf, len, from, fromlen);
+
+       skip: /* do other stuff */
+               
+       }
+
+       return 0;
+       
+error:
+       return -1;
+}
+
+
+
+/* which socket to use? main socket or new one? */
+int udp_send(char *buf, int len, struct sockaddr*  to, int tolen)
+{
+
+       int n;
+again:
+       n=sendto(udp_sock, buf, len, 0, to, tolen);
+       if (n==-1){
+               DPrint("ERROR: udp_send: sendto: %s\n", strerror());
+               if (errno==EINTR) goto again;
+       }
+       return n;
+}
diff --git a/udp_server.h b/udp_server.h
new file mode 100644 (file)
index 0000000..317e297
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * $Id$
+ */
+
+#ifndef udp_server_h
+#define udp_server_h
+
+
+
+extern int udp_sock;
+
+extern char* our_name;
+extern unsigned long  our_address;
+extern unsigned short our_port;
+
+int udp_init(unsigned long ip, unsigned short port);
+int udp_rcv_loop();
+
+
+#endif