Prechádzať zdrojové kódy

branch transaction labels added

Jiri Kuthan 24 rokov pred
rodič
commit
0a6afa42a7
10 zmenil súbory, kde vykonal 151 pridanie a 85 odobranie
  1. 3 1
      TODO
  2. 2 0
      modules/tm/TODO
  3. 2 0
      modules/tm/h_table.h
  4. 0 3
      modules/tm/sip_msg.c
  5. 103 75
      modules/tm/t_funcs.c
  6. 4 0
      modules/tm/t_funcs.h
  7. 18 0
      msg_parser.c
  8. 11 0
      msg_parser.h
  9. 3 6
      msg_translator.c
  10. 5 0
      receive.c

+ 3 - 1
TODO

@@ -41,4 +41,6 @@ Low priority:
 - the same for FreeBSD and Slackware
 
 
-
+- jku: branch hash computation over canonical values
+- jku: loop checking
+- jku: try CRC as opposed to MD5

+ 2 - 0
modules/tm/TODO

@@ -23,3 +23,5 @@ Things we have omitted for now:
 To improve:
 - too many memcpies
 - faster syncing
+
+Double-check: revire the T-state-machine

+ 2 - 0
modules/tm/h_table.h

@@ -21,7 +21,9 @@ struct timer;
 
 #define sh_malloc( size )     malloc(size)
 #define sh_free( ptr )           free(ptr)
+/* defined in msg_parser.h
 #define get_cseq( p_msg)    ((struct cseq_body*)p_msg->cseq->parsed)
+*/
 
 
 /* always use a power of 2 for hash table size */

+ 0 - 3
modules/tm/sip_msg.c

@@ -127,9 +127,6 @@ struct sip_msg* sip_msg_cloner( struct sip_msg *org_msg )
     /* repl_add_rm ( struct lump* ) -> have to be changed!!!!!!!  */
     new_msg->repl_add_rm  = 0;
 
-    /* append branch parameter */
-    new_msg->add_to_branch.s = (char *) sh_malloc( org_msg->add_to_branch.len );
-    memcpy( new_msg->add_to_branch.s, org_msg->add_to_branch.s, org_msg->add_to_branch.len );
 }
 
 

+ 103 - 75
modules/tm/t_funcs.c

@@ -1,14 +1,12 @@
 #include "t_funcs.h"
 #include "../../dprint.h"
+#include "../../config.h"
 
 struct cell         *T;
 unsigned int     global_msg_id;
 struct s_table*  hash_table;
 
 
-
-
-
 int tm_startup()
 {
    /* building the hash table*/
@@ -802,6 +800,24 @@ int t_cancel_branch(unsigned int branch)
 }
 
 
+/* copy a header field to an output buffer if space allows */
+int copy_hf( char **dst, struct hdr_field* hf, char *bumper )
+{
+   int n;
+   n=hf->body.len+2+hf->name.len+CRLF_LEN;
+   if (*dst+n >= bumper ) return -1;
+   memcpy(*dst, hf->name.s, hf->name.len );
+   *dst+= hf->name.len ;
+   **dst = ':'; (*dst)++;
+   **dst = ' '; (*dst)++;
+   memcpy(*dst, hf->body.s, hf->body.len);
+   *dst+= hf->body.len;
+   memcpy( *dst, CRLF, CRLF_LEN );
+   *dst+=CRLF_LEN;
+   return 0;
+}
+  
+
 
 
 /* Builds an ACK request based on an INVITE request. ACK is send
@@ -812,106 +828,104 @@ int t_build_and_send_ACK( struct cell *Trans, unsigned int branch)
     struct sip_msg* p_msg = T->inbound_request;
     struct via_body *via;
     struct hdr_field *hdr;
-   char *ack_buf, *p;
+    char *ack_buf=NULL, *p;
     unsigned int len;
+    int n;
+
+   /* enough place for first line and Via ? */
+   if ( 4 + p_msg->first_line.u.request.uri.len + 1 + p_msg->first_line.u.request.version.len +
+	CRLF_LEN + MY_VIA_LEN + names_len[0] + 1 + port_no_str_len + MY_BRANCH_LEN  < MAX_ACK_LEN ) {
+		LOG( L_ERR, "ERROR: t_build_and_send_ACK: no place for FL/Via\n");
+		goto error;
+   }
 
-   ack_buf = (char *)malloc( 1024 * 10 );
+   ack_buf = (char *)malloc( MAX_ACK_LEN );
    p = ack_buf;
 
    /* first line */
    memcpy( p , "ACK " , 4);
    p += 4;
+
    memcpy( p , p_msg->first_line.u.request.uri.s , p_msg->first_line.u.request.uri.len );
-   p += p_msg->first_line.u.request.uri.len+1;
-   *(p++)=' ';
+   p += p_msg->first_line.u.request.uri.len;
+
+   *(p++) = ' ';
+
    memcpy( p , p_msg->first_line.u.request.version.s , p_msg->first_line.u.request.version.len );
    p += p_msg->first_line.u.request.version.len;
-   *(p++) = '\n';
+
+   memcpy( p, CRLF, CRLF_LEN );
+   p+=CRLF_LEN;
 
    /* insert our via */
-   memcpy( p , "Via: SIP/2.0/UDP " , 17);
-   p += 17;
+   memcpy( p , MY_VIA , MY_VIA_LEN );
+   p += MY_VIA_LEN;
+
    memcpy( p , names[0] , names_len[0] );
    p += names_len[0];
+
    *(p++) = ':';
+
    memcpy( p , port_no_str , port_no_str_len );
    p += port_no_str_len;
 
-   /* VIA (first we have to find the header) */
-   for( hdr=p_msg->headers ; hdr ; hdr=hdr->next  )
-      if ( hdr->type==HDR_VIA || hdr->type==HDR_FROM || hdr->type==HDR_CALLID )
-      {
-         len = (hdr->body.s+hdr->body.len) - hdr->name.s;
-         memcpy( p , p_msg->orig+(hdr->name.s-p_msg->buf) , len );
-         p += len;
-         *(p++) = '\n';
-      }
-      else if ( hdr->type==HDR_CSEQ )
-      {
-         len = (get_cseq(p_msg)->number.s+get_cseq(p_msg)->number.len) - hdr->name.s;
-         memcpy( p , p_msg->orig+(hdr->name.s-p_msg->buf) , len );
-         p += len;
-         memcpy( p , " ACK\n" , 5);
-         p += 5;
-      }
-      if ( hdr->type==HDR_TO )
-      {
-         len = (T->outbound_response[branch]->to->body.s+T->outbound_response[branch]->to->body.len) - T->outbound_response[branch]->to->name.s;
-         memcpy( p , T->outbound_response[branch]->orig+(T->outbound_response[branch]->to->name.s-T->outbound_response[branch]->buf) , len );
-         p += len;
-         *(p++) = '\n';
-      }
+   memcpy( p, MY_BRANCH, MY_BRANCH_LEN );
+   p+=MY_BRANCH_LEN;
+
+   n=snprintf( p, ack_buf + MAX_ACK_LEN - p, 
+                 ".%h.%h.%h%s",
+                 Trans->hash_index, Trans->label, branch, CRLF );
+   if (n==-1) {
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: not enough memory for branch\n");
+	goto error;
+   }
+   p+=n;
+
+   if (!check_transaction_quadruple( p_msg )) {
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: can't generate a HBH ACK if key HFs in INVITE missing\n");
+	goto error;
+   }
+
+   /* To */
+   if (copy_hf( &p, p_msg->to , ack_buf + MAX_ACK_LEN )==-1) {
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no place for To\n");
+	goto error;
+   }
+   /* From */
+   if (copy_hf( &p, p_msg->from, ack_buf + MAX_ACK_LEN )==-1) {
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no place for From\n");
+	goto error;
+   }
+   /* CallId */
+   if (copy_hf( &p, p_msg->callid, ack_buf + MAX_ACK_LEN )==-1) {
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no place for callid\n");
+	goto error;
+   }
+   /* CSeq, EoH */
+   n=snprintf( p, ack_buf + MAX_ACK_LEN - p, 
+                 "Cseq: %*s ACK%s%s", get_cseq(p_msg)->number.len, 
+		get_cseq(p_msg)->number.s, CRLF, CRLF );
+   if (n==-1) {
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no enough memory for Cseq\n");
+	goto error;
+   }
+   p+=n;
 
-   /* end of message*/
-   *(p++) = '\n';
 
    /* sends the ACK message to the same destination as the INVITE */
    udp_send( ack_buf, p-ack_buf, (struct sockaddr*)&(T->outbound_request[branch]->to) , sizeof(struct sockaddr_in) );
 
    /* free mem*/
-   free( ack_buf );
-
+   if (ack_buf) free( ack_buf );
    return 0;
-}
-
-
 
-
-/* append appropriate branch labels for fast reply-transaction matching
-   to outgoing requests
-*/
-int add_branch_label( struct cell *trans, struct sip_msg *p_msg, int branch )
-{
-	char *c;
-
-
-	/* check size now */
-/*
-	if (p_msg->add_to_branch.len+ .... > MAX_BRANCH_PARAM_LEN ) {
-		LOG(L_ERR, "ERROR: add_branch_label: too small branch buffer\n");
-		return -1;
-	}
-*/
-
-	/* check if there already was something else -- if not, allocate */
-
-/*
- = (char*)sh_malloc( MAX_BRANCH_PARAM_LEN );
-
-
-
-	trans->label;
-	trans->hash_index;
-	p_msg->add_to_branch;
-	branch;
-*/
+error:
+   	if (ack_buf) free( ack_buf );
+	return -1;
 }
 
 
 
-
-
-
 /*---------------------------------TIMEOUT HANDLERS--------------------------------------*/
 
 
@@ -976,6 +990,20 @@ void delete_handler( void *attr)
        add_to_tail_of_timer_list( hash_table, &(p_cell->dele_tl), DELETE_LIST, DEL_TIME_OUT );
 }
 
+/* append appropriate branch labels for fast reply-transaction matching
+   to outgoing requests
+*/
+int add_branch_label( struct cell *trans, struct sip_msg *p_msg, int branch )
+{
+	char *c;
+	short n;
 
-
-
+	n=snprintf( p_msg->add_to_branch_s+p_msg->add_to_branch_len, 
+		  MAX_BRANCH_PARAM_LEN - p_msg->add_to_branch_len,
+		 ".%h.%h.%h",
+		 trans->hash_index, trans->label, branch );
+	if (n==-1) {
+		LOG(L_ERR, "ERROR: add_branch_label: too small branch buffer\n");
+		return -1;
+	} else return 0;
+}

+ 4 - 0
modules/tm/t_funcs.h

@@ -21,8 +21,12 @@ struct cell;
 
 #define sh_malloc( size )     malloc(size)
 #define sh_free( ptr )           free(ptr)
+/* already defined in msg_parser.h
 #define get_cseq( p_msg)    ((struct cseq_body*)p_msg->cseq->parsed)
+*/
 
+/* maximumum length of localy generated acknowledgement */
+#define MAX_ACK_LEN 1024
 
 
 int tm_startup();

+ 18 - 0
msg_parser.c

@@ -670,6 +670,12 @@ error:
 /* parse the headers and adds them to msg->headers and msg->to, from etc.
  * It stops when all the headers requested in flags were parsed, on error
  * (bad header) or end of headers */
+/* note: it continues where it previously stopped and goes ahead until
+   end is encountered or desired HFs are found; if you call it twice
+   for the same HF which is present only once, it will fail the second
+   time; if you want to use a dumbie convenience function which will
+   give you the header you are interested in, look at check_transaction_quadruple
+*/
 int parse_headers(struct sip_msg* msg, int flags)
 {
 	struct hdr_field* hf;
@@ -942,4 +948,16 @@ void free_sip_msg(struct sip_msg* msg)
 }
 
 
+/* make sure all HFs needed for transaction identification have been
+   parsed; return 0 if those HFs can't be found
+*/
+int check_transaction_quadruple( struct sip_msg* msg )
+{
+   return 
+   ( (msg->from || (parse_headers( msg, HDR_FROM)!=-1 && msg->from)) &&
+   (msg->to|| (parse_headers( msg, HDR_TO)!=-1 && msg->to)) &&
+   (msg->callid|| (parse_headers( msg, HDR_CALLID)!=-1 && msg->callid)) &&
+   (msg->cseq|| (parse_headers( msg, HDR_CSEQ)!=-1 && msg->cseq)) ) ? 1 : 0;
+
+}
 

+ 11 - 0
msg_parser.h

@@ -29,6 +29,9 @@
 #define HDR_ROUTE        256
 #define HDR_OTHER       65536 /*unknown header type*/
 
+/* maximum length of values appended to Via-branch parameter */
+#define	MAX_BRANCH_PARAM_LEN	32
+
 /* via param types
  * WARNING: keep in sync w/ FIN_*, GEN_PARAM and PARAM_ERROR from via_parse.c*/
 enum{
@@ -37,6 +40,9 @@ enum{
 		PARAM_ERROR
 };
 
+/* casting macro for accessing CSEQ body */
+#define get_cseq( p_msg)    ((struct cseq_body*)p_msg->cseq->parsed)
+
 
 
 #define INVITE_LEN	6
@@ -169,6 +175,9 @@ struct sip_msg{
 	struct lump* repl_add_rm; /* only for localy generated replies !!!*/
 
 	str add_to_branch; /* whatever whoever want to append to branch comes here */
+	char add_to_branch_s[MAX_BRANCH_PARAM_LEN];
+	short add_to_branch_len;
+
 	
 };
 
@@ -213,5 +222,7 @@ void clean_hdr_field(struct hdr_field* hf);
 void free_hdr_field_lst(struct hdr_field* hf);
 void free_sip_msg(struct sip_msg* msg);
 
+int check_transaction_quadruple( struct sip_msg* msg );
+
 
 #endif

+ 3 - 6
msg_translator.c

@@ -164,11 +164,7 @@ char * build_req_buf_from_sip_req(struct sip_msg* msg, unsigned int *returned_le
 		/* loop checks ? */
 		if (loop_checks) {
 
-			if (	(msg->from || (parse_headers( msg, HDR_FROM)!=-1 && msg->from)) &&
-				(msg->to|| (parse_headers( msg, HDR_TO)!=-1 && msg->to)) &&
-				(msg->callid|| (parse_headers( msg, HDR_CALLID)!=-1 && msg->callid)) &&
-				(msg->cseq|| (parse_headers( msg, HDR_CSEQ)!=-1 && msg->cseq)) ) {
-
+			if (check_transaction_quadruple( msg )) {
 				str src[5];
 				int r;
 			
@@ -176,7 +172,7 @@ char * build_req_buf_from_sip_req(struct sip_msg* msg, unsigned int *returned_le
 				src[1]= msg->to->body; 
 				src[2]= msg->callid->body; 
 				src[3]= msg->first_line.u.request.uri; 
-				src[4]= ((struct cseq_body *)(msg->cseq->parsed))->number;
+				src[4]= get_cseq( msg )->number;
 
 				MDStringArray ( line_buf+via_len-1, src, 5 );
 				DBG("DEBUG: build_req_buf_from_sip_req: branch loop detection: %s, %s, %s, %s, %s -> %s32\n",
@@ -184,6 +180,7 @@ char * build_req_buf_from_sip_req(struct sip_msg* msg, unsigned int *returned_le
 					msg->first_line.u.request.uri.s,
 					((struct cseq_body *)(msg->cseq->parsed))->number.s,
 					line_buf+via_len-1 );
+				DBG("WARNING: build_req_buf_from_sip_req: branch computation NOT over canonical values\n");
 				via_len+=MD5_LEN - 1;
 				
 			} else DBG("DEBUG: build_req_buf_from_sip_req: required HFs for loop checking missing\n");

+ 5 - 0
receive.c

@@ -64,6 +64,11 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 			goto error;
 		}
 		/* check if neccesarry to add receive?->moved to forward_req */
+
+		/* loop checks */
+		if (loop_checks) {
+			DBG("WARNING: receive_msg: Placeholder for loop check. NOT implemented yet.\n");
+		}
 		
 		/* exec routing script */
 		DBG("preparing to run routing scripts...\n");