Browse Source

parser seems to work

Andrei Pelinescu-Onciul 24 years ago
parent
commit
888ca09df8
18 changed files with 425 additions and 7 deletions
  1. BIN
      .cfg_parser.c.swp
  2. BIN
      .cfg_parser.h.swp
  3. BIN
      .main.c.swp
  4. BIN
      .msg_parser.c.swp
  5. BIN
      .msg_parser.h.swp
  6. BIN
      .parser_f.c.swp
  7. BIN
      .parser_f.h.swp
  8. BIN
      .route.c.swp
  9. BIN
      .route.h.swp
  10. BIN
      .sip_router.cfg.swp
  11. BIN
      .test.c.swp
  12. 137 0
      forward.c
  13. 18 0
      forward.h
  14. 21 1
      main.c
  15. 148 2
      msg_parser.c
  16. 9 4
      msg_parser.h
  17. 80 0
      receive.c
  18. 12 0
      receive.h

BIN
.cfg_parser.c.swp


BIN
.cfg_parser.h.swp


BIN
.main.c.swp


BIN
.msg_parser.c.swp


BIN
.msg_parser.h.swp


BIN
.parser_f.c.swp


BIN
.parser_f.h.swp


BIN
.route.c.swp


BIN
.route.h.swp


BIN
.sip_router.cfg.swp


BIN
.test.c.swp


+ 137 - 0
forward.c

@@ -0,0 +1,137 @@
+/*
+ * $Id$
+ */
+
+
+#include <string.h>
+
+#include "forward.h"
+#include "msg_parser.h"
+#include "route.h"
+#include "dprint.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, 
+					 unsigned int len,
+					 struct sip_msg* msg,
+					 struct route_elem* re)
+{
+	unsigned int new_len, via_len, received_len;
+	char line_buf[MAX_VIA_LINE_SIZE];
+	char received_buf[MAX_RECEIVED_SIZE];
+	char* new_buf;
+	int offset, s_offset, size;
+
+	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);
+	/* 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",
+							"10.11.12.13");
+	
+	new_len=len+via_len+received_len;
+	new_buf=(char*)malloc(new_len+1);
+	if (new_buf==0){
+		DPrint("ERROR: forward_request: out of memory\n");
+		goto error;
+	}
+	printf("1\n");
+ /* 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);
+	offset+=via_len;
+	printf("3\n");
+ /* modify original via if neccesarry (received=...)*/
+ 	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);
+				}
+		}
+		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);
+	 
+	return 0;
+error:
+	return -1;
+
+}
+
+
+
+/* removes first via & sends msg to the second */
+int forward_reply(char * orig, char* buf, 
+					 unsigned int len,
+					 struct sip_msg* msg)
+{
+
+
+	unsigned int new_len, via_len;
+	char* new_buf;
+	int offset, s_offset, size;
+
+
+	/* we must remove 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 ':' */
+		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);
+	
+	return 0;
+
+error:
+	return -1;
+}

+ 18 - 0
forward.h

@@ -0,0 +1,18 @@
+/*
+ *  $Id$
+ */
+
+
+#ifndef forward_h
+#define forward_h
+
+#include "msg_parser.h"
+#include "route.h"
+
+int forward_request(char * orig, char* buf, unsigned int len,
+					 struct sip_msg* msg,  struct route_elem* re);
+
+int forward_reply(char * orig, char* buf, unsigned int len, 
+					struct sip_msg* msg);
+
+#endif

+ 21 - 1
main.c

@@ -12,6 +12,24 @@
 #define CFG_FILE "./sip_router.cfg"
 
 
+/* debuging function */
+
+void receive_stdin_loop()
+{
+	#define BSIZE 1024
+	char buf[BSIZE+1];
+	int len;
+	
+	while(1){
+		len=fread(buf,1,BSIZE,stdin);
+		buf[len+1]=0;
+		receive_msg(buf, len);
+		printf("-------------------------\n");
+	}
+}
+
+
+
 int main(int argc, char** argv)
 {
 
@@ -40,10 +58,12 @@ int main(int argc, char** argv)
 
 
 
-	/* start other processes/threads ? */
+	/* start/init other processes/threads ? */
 
 	/* receive loop */
 
+	receive_stdin_loop();
+
 
 error:
 	return -1;

+ 148 - 2
msg_parser.c

@@ -5,14 +5,18 @@
  *
  */
 
-#include "msg_parser.h"
-#include "string.h"
+#include <string.h>
 
+#include "msg_parser.h"
 #include "parser_f.h"
 #include "dprint.h"
 
 
 
+#define DEBUG
+
+
+
 /* parses the first line, returns pointer to  next line  & fills fl;
    also  modifies buffer (to avoid extra copy ops) */
 char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
@@ -313,3 +317,145 @@ error:
 	return tmp;
 }
 
+
+
+/* returns 0 if ok, -1 for errors */
+int parse_msg(char* buf, unsigned int len, struct sip_msg* msg)
+{
+
+	char *tmp, *bar;
+	char* rest;
+	char* first_via;
+	char* second_via;
+	struct msg_start fl;
+	struct hdr_field hf;
+	struct via_body vb1, vb2;
+	int offset;
+	int r;
+
+	
+	/* eat crlf from the beginning */
+	for (tmp=buf; (*tmp=='\n' || *tmp=='\r')&&
+			tmp-buf < len ; tmp++);
+	offset=tmp-buf;
+	rest=parse_first_line(tmp, len-offset, &fl);
+	offset+=rest-tmp;
+	tmp=rest;
+	switch(fl.type){
+		case SIP_INVALID:
+			DPrint("invalid message\n");
+			goto error;
+			break;
+		case SIP_REQUEST:
+			DPrint("SIP Request:\n");
+			DPrint(" method:  <%s>\n",fl.u.request.method);
+			DPrint(" uri:     <%s>\n",fl.u.request.uri);
+			DPrint(" version: <%s>\n",fl.u.request.version);
+			break;
+		case SIP_REPLY:
+			DPrint("SIP Reply  (status):\n");
+			DPrint(" version: <%s>\n",fl.u.reply.version);
+			DPrint(" status:  <%s>\n",fl.u.reply.status);
+			DPrint(" reason:  <%s>\n",fl.u.reply.reason);
+			break;
+		default:
+			DPrint("unknown type %d\n",fl.type);
+	}
+	
+	/*find first Via: */
+	hf.type=HDR_ERROR;
+	first_via=0;
+	second_via=0;
+	do{
+		rest=get_hdr_field(tmp, len-offset, &hf);
+		offset+=rest-tmp;
+		switch (hf.type){
+			case HDR_ERROR:
+				DPrint("ERROR: bad header  field\n");
+				goto  error;
+			case HDR_EOH: 
+				goto skip;
+			case HDR_VIA:
+				if (first_via==0){
+						first_via=hf.body;
+						vb1.hdr=hf.name;
+						/* replace cr/lf with space in first via */
+						for (bar=first_via;(first_via) && (*bar);bar++)
+							if ((*bar=='\r')||(*bar=='\n'))	*bar=' ';
+				#ifdef DEBUG
+						printf("first via: <%s>\n", first_via);
+				#endif
+						bar=parse_via_body(first_via, strlen(first_via), &vb1);
+						if (vb1.error!=VIA_PARSE_OK){
+							DPrint("ERROR: parsing via body: %s\n", first_via);
+							goto error;
+						}
+						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 if (second_via==0){
+							second_via=hf.body;
+							vb2.hdr=hf.name;
+							goto skip;
+				}
+				break;
+		}
+	#ifdef DEBUG
+		printf("header field type %d, name=<%s>, body=<%s>\n",
+			hf.type, hf.name, hf.body);
+	#endif
+		tmp=rest;
+	}while(hf.type!=HDR_EOH && rest-buf < len);
+
+skip:
+	/* replace cr/lf with space in the second via */
+	for (tmp=second_via;(second_via) && (*tmp);tmp++)
+		if ((*tmp=='\r')||(*tmp=='\n'))	*tmp=' ';
+
+	if (second_via) {
+		tmp=parse_via_body(second_via, strlen(second_via), &vb2);
+		if (vb2.error!=VIA_PARSE_OK){
+			DPrint("ERROR: parsing via body: %s\n", second_via);
+			goto error;
+		}
+		vb2.size=tmp-second_via;
+		if (vb2.hdr) vb2.size+=second_via-vb2.hdr;
+	}
+	
+
+#ifdef DEBUG
+	/* dump parsed data */
+	printf(" first  via: <%s/%s/%s> <%s:%d>",
+			vb1.name, vb1.version, vb1.transport, vb1.host, vb1.port);
+	if (vb1.params) printf(";<%s>", vb1.params);
+	if (vb1.comment) printf(" <%s>", vb1.comment);
+	printf ("\n");
+	if (second_via){
+		printf(" second via: <%s/%s/%s> <%s:%d>",
+				vb2.name, vb2.version, vb2.transport, vb2.host, vb2.port);
+		if (vb2.params) printf(";<%s>", vb2.params);
+		if (vb2.comment) printf(" <%s>", vb2.comment);
+		printf ("\n");
+	}
+#endif
+	
+	/* copy data into msg */
+	memcpy(&(msg->first_line), &fl, sizeof(struct msg_start));
+	memcpy(&(msg->via1), &vb1, sizeof(struct via_body));
+	memcpy(&(msg->via2), &vb2, sizeof(struct via_body));
+
+#ifdef DEBUG
+	printf ("exiting parse_msg\n");
+#endif
+
+	return 0;
+	
+error:
+	return -1;
+}
+

+ 9 - 4
msg_parser.h

@@ -48,6 +48,7 @@ struct hdr_field{   /* format: name':' body */
 
 struct via_body{  /* format: name/version/transport host:port;params comment */
 	int error;
+	char *hdr;   /* contains "Via" or "v" */
 	char* name;
 	char* version;
 	char* transport;
@@ -55,9 +56,16 @@ struct via_body{  /* format: name/version/transport host:port;params comment */
 	int port;
 	char* params;
 	char* comment;
+	int size;    /* full size, including hdr */
 	char* next; /* pointer to next via body string if compact via or null */
 };
 
+struct sip_msg{
+	struct msg_start first_line;
+	struct via_body via1;
+	struct via_body via2;
+};
+
 
 
 char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl);
@@ -65,11 +73,8 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f);
 int field_name(char *s);
 char* parse_hostport(char* buf, char** host, short int* port);
 char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb);
-
-
+int parse_msg(char* buf, unsigned int len, struct sip_msg* msg);
 
 
 
 #endif
- 
-

+ 80 - 0
receive.c

@@ -0,0 +1,80 @@
+/* 
+ *$Id$
+ */
+
+#include <string.h>
+
+#include "receive.h"
+#include "dprint.h"
+#include "route.h"
+#include "msg_parser.h"
+#include "forward.h"
+
+
+int receive_msg(char* buf, unsigned int len)
+{
+	struct sip_msg msg;
+	struct route_elem *re;
+	char * orig;
+
+	/* make a copy of the message */
+	orig=(char*) malloc(len);
+	if (orig==0){
+		DPrint("ERROR: memory allocation failure\n");
+		goto error;
+	}
+	memcpy(orig, buf, len);
+	
+	if (parse_msg(buf,len, &msg)!=0){
+		goto error;
+	}
+	
+	if (msg.first_line.type==SIP_REQUEST){
+		/* sanity checks */
+		if (msg.via1.error!=VIA_PARSE_OK){
+			/* no via, send back error ? */
+			goto skip;
+		}
+		/* check if neccesarry to add receive? */
+		
+		/* find route */
+		re=route_match(  msg.first_line.u.request.method,
+						 msg.first_line.u.request.uri,
+						 &rlist
+					  );
+		if (re==0){
+			/* no route found, send back error msg? */
+			DPrint("WARNING: no route found!\n");
+			goto skip;
+		}
+		re->tx++;
+		/* send msg */
+		forward_request(orig, buf, len, &msg, re);
+		DPrint(" found route to: %s\n", re->host.h_name);
+	}else if (msg.first_line.type==SIP_REPLY){
+		/* sanity checks */
+		if (msg.via1.error!=VIA_PARSE_OK){
+			/* no via, send back error ? */
+			goto skip;
+		}
+		if (msg.via2.error!=VIA_PARSE_OK){
+			/* no second via => error? */
+			goto skip;
+		}
+		/* check if via1 == us */
+		
+		/* send the msg */
+		forward_reply(orig, buf, len, &msg);
+		DPrint(" reply forwarded to %s:%d\n", 
+					msg.via2.host,
+					(unsigned short) msg.via2.port
+				);
+	}
+skip:
+	free(orig);
+	return 0;
+error:
+	return -1;
+
+}
+

+ 12 - 0
receive.h

@@ -0,0 +1,12 @@
+/*
+ * $Id$
+ */
+
+
+#ifndef receive_h
+#define receive_h
+
+int receive_msg(char* buf, unsigned int len);
+
+
+#endif