branch transaction labels added
authorJiri Kuthan <jiri@iptel.org>
Thu, 29 Nov 2001 19:27:45 +0000 (19:27 +0000)
committerJiri Kuthan <jiri@iptel.org>
Thu, 29 Nov 2001 19:27:45 +0000 (19:27 +0000)
TODO
modules/tm/TODO
modules/tm/h_table.h
modules/tm/sip_msg.c
modules/tm/t_funcs.c
modules/tm/t_funcs.h
msg_parser.c
msg_parser.h
msg_translator.c
receive.c

diff --git a/TODO b/TODO
index 192550b..14e04eb 100644 (file)
--- a/TODO
+++ b/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
index 8a47d47..d491034 100644 (file)
@@ -23,3 +23,5 @@ Things we have omitted for now:
 To improve:
 - too many memcpies
 - faster syncing
+
+Double-check: revire the T-state-machine
index 17db1f5..6135861 100644 (file)
@@ -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 */
index 2011fc0..170f92c 100644 (file)
@@ -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 );
 }
 
 
index 8e8f7b3..e6fda42 100644 (file)
@@ -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;
+}
index 1b100be..7d066b0 100644 (file)
@@ -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();
index d89a3a1..f480590 100644 (file)
@@ -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;
+
+}
 
index a1be01a..79aeb84 100644 (file)
@@ -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
index d06f468..2f7309f 100644 (file)
@@ -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");
index faaf371..b4561f4 100644 (file)
--- a/receive.c
+++ b/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");