Andrei Pelinescu-Onciul пре 24 година
родитељ
комит
e60a9728a5
13 измењених фајлова са 297 додато и 43 уклоњено
  1. 48 0
      Makefile
  2. 6 6
      cfg_parser.c
  3. 1 0
      cfg_parser.h
  4. 18 0
      config.h
  5. 60 26
      forward.c
  6. 26 5
      main.c
  7. 8 2
      msg_parser.c
  8. 4 3
      route.c
  9. 2 0
      route.h
  10. 1 1
      sip_router.cfg
  11. 0 0
      test.c.bak
  12. 103 0
      udp_server.c
  13. 20 0
      udp_server.h

+ 48 - 0
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)
+
+
+
+

+ 6 - 6
cfg_parser.c

@@ -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;

+ 1 - 0
cfg_parser.h

@@ -20,6 +20,7 @@ struct cfg_line{
 	char* method;
 	char* uri;
 	char* address;
+	short int port;
 };
 
 

+ 18 - 0
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

+ 60 - 26
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;
 }

+ 26 - 5
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:

+ 8 - 2
msg_parser.c

@@ -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;
 	}
 	

+ 4 - 3
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);
 	}
 

+ 2 - 0
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;

+ 1 - 1
sip_router.cfg

@@ -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
 

+ 0 - 0
test.c → test.c.bak


+ 103 - 0
udp_server.c

@@ -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;
+}

+ 20 - 0
udp_server.h

@@ -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