--- /dev/null
+/*
+ * $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;
+}
--- /dev/null
+/*
+ * $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
#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)
{
- /* start other processes/threads ? */
+ /* start/init other processes/threads ? */
/* receive loop */
+ receive_stdin_loop();
+
error:
return -1;
*
*/
-#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)
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;
+}
+
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;
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);
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
-
-
--- /dev/null
+/*
+ *$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;
+
+}
+
--- /dev/null
+/*
+ * $Id$
+ */
+
+
+#ifndef receive_h
+#define receive_h
+
+int receive_msg(char* buf, unsigned int len);
+
+
+#endif