Browse code

branch transaction labels added

Jiri Kuthan authored on 29/11/2001 19:27:45
Showing 10 changed files
... ...
@@ -41,4 +41,6 @@ Low priority:
41 41
 - the same for FreeBSD and Slackware
42 42
 
43 43
 
44
-
44
+- jku: branch hash computation over canonical values
45
+- jku: loop checking
46
+- jku: try CRC as opposed to MD5
... ...
@@ -23,3 +23,5 @@ Things we have omitted for now:
23 23
 To improve:
24 24
 - too many memcpies
25 25
 - faster syncing
26
+
27
+Double-check: revire the T-state-machine
... ...
@@ -21,7 +21,9 @@ struct timer;
21 21
 
22 22
 #define sh_malloc( size )     malloc(size)
23 23
 #define sh_free( ptr )           free(ptr)
24
+/* defined in msg_parser.h
24 25
 #define get_cseq( p_msg)    ((struct cseq_body*)p_msg->cseq->parsed)
26
+*/
25 27
 
26 28
 
27 29
 /* always use a power of 2 for hash table size */
... ...
@@ -127,9 +127,6 @@ struct sip_msg* sip_msg_cloner( struct sip_msg *org_msg )
127 127
     /* repl_add_rm ( struct lump* ) -> have to be changed!!!!!!!  */
128 128
     new_msg->repl_add_rm  = 0;
129 129
 
130
-    /* append branch parameter */
131
-    new_msg->add_to_branch.s = (char *) sh_malloc( org_msg->add_to_branch.len );
132
-    memcpy( new_msg->add_to_branch.s, org_msg->add_to_branch.s, org_msg->add_to_branch.len );
133 130
 }
134 131
 
135 132
 
... ...
@@ -1,14 +1,12 @@
1 1
 #include "t_funcs.h"
2 2
 #include "../../dprint.h"
3
+#include "../../config.h"
3 4
 
4 5
 struct cell         *T;
5 6
 unsigned int     global_msg_id;
6 7
 struct s_table*  hash_table;
7 8
 
8 9
 
9
-
10
-
11
-
12 10
 int tm_startup()
13 11
 {
14 12
    /* building the hash table*/
... ...
@@ -802,6 +800,24 @@ int t_cancel_branch(unsigned int branch)
802 802
 }
803 803
 
804 804
 
805
+/* copy a header field to an output buffer if space allows */
806
+int copy_hf( char **dst, struct hdr_field* hf, char *bumper )
807
+{
808
+   int n;
809
+   n=hf->body.len+2+hf->name.len+CRLF_LEN;
810
+   if (*dst+n >= bumper ) return -1;
811
+   memcpy(*dst, hf->name.s, hf->name.len );
812
+   *dst+= hf->name.len ;
813
+   **dst = ':'; (*dst)++;
814
+   **dst = ' '; (*dst)++;
815
+   memcpy(*dst, hf->body.s, hf->body.len);
816
+   *dst+= hf->body.len;
817
+   memcpy( *dst, CRLF, CRLF_LEN );
818
+   *dst+=CRLF_LEN;
819
+   return 0;
820
+}
821
+  
822
+
805 823
 
806 824
 
807 825
 /* 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)
812 812
     struct sip_msg* p_msg = T->inbound_request;
813 813
     struct via_body *via;
814 814
     struct hdr_field *hdr;
815
-   char *ack_buf, *p;
815
+    char *ack_buf=NULL, *p;
816 816
     unsigned int len;
817
+    int n;
818
+
819
+   /* enough place for first line and Via ? */
820
+   if ( 4 + p_msg->first_line.u.request.uri.len + 1 + p_msg->first_line.u.request.version.len +
821
+	CRLF_LEN + MY_VIA_LEN + names_len[0] + 1 + port_no_str_len + MY_BRANCH_LEN  < MAX_ACK_LEN ) {
822
+		LOG( L_ERR, "ERROR: t_build_and_send_ACK: no place for FL/Via\n");
823
+		goto error;
824
+   }
817 825
 
818
-   ack_buf = (char *)malloc( 1024 * 10 );
826
+   ack_buf = (char *)malloc( MAX_ACK_LEN );
819 827
    p = ack_buf;
820 828
 
821 829
    /* first line */
822 830
    memcpy( p , "ACK " , 4);
823 831
    p += 4;
832
+
824 833
    memcpy( p , p_msg->first_line.u.request.uri.s , p_msg->first_line.u.request.uri.len );
825
-   p += p_msg->first_line.u.request.uri.len+1;
826
-   *(p++)=' ';
834
+   p += p_msg->first_line.u.request.uri.len;
835
+
836
+   *(p++) = ' ';
837
+
827 838
    memcpy( p , p_msg->first_line.u.request.version.s , p_msg->first_line.u.request.version.len );
828 839
    p += p_msg->first_line.u.request.version.len;
829
-   *(p++) = '\n';
840
+
841
+   memcpy( p, CRLF, CRLF_LEN );
842
+   p+=CRLF_LEN;
830 843
 
831 844
    /* insert our via */
832
-   memcpy( p , "Via: SIP/2.0/UDP " , 17);
833
-   p += 17;
845
+   memcpy( p , MY_VIA , MY_VIA_LEN );
846
+   p += MY_VIA_LEN;
847
+
834 848
    memcpy( p , names[0] , names_len[0] );
835 849
    p += names_len[0];
850
+
836 851
    *(p++) = ':';
852
+
837 853
    memcpy( p , port_no_str , port_no_str_len );
838 854
    p += port_no_str_len;
839 855
 
840
-   /* VIA (first we have to find the header) */
841
-   for( hdr=p_msg->headers ; hdr ; hdr=hdr->next  )
842
-      if ( hdr->type==HDR_VIA || hdr->type==HDR_FROM || hdr->type==HDR_CALLID )
843
-      {
844
-         len = (hdr->body.s+hdr->body.len) - hdr->name.s;
845
-         memcpy( p , p_msg->orig+(hdr->name.s-p_msg->buf) , len );
846
-         p += len;
847
-         *(p++) = '\n';
848
-      }
849
-      else if ( hdr->type==HDR_CSEQ )
850
-      {
851
-         len = (get_cseq(p_msg)->number.s+get_cseq(p_msg)->number.len) - hdr->name.s;
852
-         memcpy( p , p_msg->orig+(hdr->name.s-p_msg->buf) , len );
853
-         p += len;
854
-         memcpy( p , " ACK\n" , 5);
855
-         p += 5;
856
-      }
857
-      if ( hdr->type==HDR_TO )
858
-      {
859
-         len = (T->outbound_response[branch]->to->body.s+T->outbound_response[branch]->to->body.len) - T->outbound_response[branch]->to->name.s;
860
-         memcpy( p , T->outbound_response[branch]->orig+(T->outbound_response[branch]->to->name.s-T->outbound_response[branch]->buf) , len );
861
-         p += len;
862
-         *(p++) = '\n';
863
-      }
856
+   memcpy( p, MY_BRANCH, MY_BRANCH_LEN );
857
+   p+=MY_BRANCH_LEN;
858
+
859
+   n=snprintf( p, ack_buf + MAX_ACK_LEN - p, 
860
+                 ".%h.%h.%h%s",
861
+                 Trans->hash_index, Trans->label, branch, CRLF );
862
+   if (n==-1) {
863
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: not enough memory for branch\n");
864
+	goto error;
865
+   }
866
+   p+=n;
867
+
868
+   if (!check_transaction_quadruple( p_msg )) {
869
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: can't generate a HBH ACK if key HFs in INVITE missing\n");
870
+	goto error;
871
+   }
872
+
873
+   /* To */
874
+   if (copy_hf( &p, p_msg->to , ack_buf + MAX_ACK_LEN )==-1) {
875
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no place for To\n");
876
+	goto error;
877
+   }
878
+   /* From */
879
+   if (copy_hf( &p, p_msg->from, ack_buf + MAX_ACK_LEN )==-1) {
880
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no place for From\n");
881
+	goto error;
882
+   }
883
+   /* CallId */
884
+   if (copy_hf( &p, p_msg->callid, ack_buf + MAX_ACK_LEN )==-1) {
885
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no place for callid\n");
886
+	goto error;
887
+   }
888
+   /* CSeq, EoH */
889
+   n=snprintf( p, ack_buf + MAX_ACK_LEN - p, 
890
+                 "Cseq: %*s ACK%s%s", get_cseq(p_msg)->number.len, 
891
+		get_cseq(p_msg)->number.s, CRLF, CRLF );
892
+   if (n==-1) {
893
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no enough memory for Cseq\n");
894
+	goto error;
895
+   }
896
+   p+=n;
864 897
 
865
-   /* end of message*/
866
-   *(p++) = '\n';
867 898
 
868 899
    /* sends the ACK message to the same destination as the INVITE */
869 900
    udp_send( ack_buf, p-ack_buf, (struct sockaddr*)&(T->outbound_request[branch]->to) , sizeof(struct sockaddr_in) );
870 901
 
871 902
    /* free mem*/
872
-   free( ack_buf );
873
-
903
+   if (ack_buf) free( ack_buf );
874 904
    return 0;
875
-}
876
-
877
-
878 905
 
879
-
880
-/* append appropriate branch labels for fast reply-transaction matching
881
-   to outgoing requests
882
-*/
883
-int add_branch_label( struct cell *trans, struct sip_msg *p_msg, int branch )
884
-{
885
-	char *c;
886
-
887
-
888
-	/* check size now */
889
-/*
890
-	if (p_msg->add_to_branch.len+ .... > MAX_BRANCH_PARAM_LEN ) {
891
-		LOG(L_ERR, "ERROR: add_branch_label: too small branch buffer\n");
892
-		return -1;
893
-	}
894
-*/
895
-
896
-	/* check if there already was something else -- if not, allocate */
897
-
898
-/*
899
- = (char*)sh_malloc( MAX_BRANCH_PARAM_LEN );
900
-
901
-
902
-
903
-	trans->label;
904
-	trans->hash_index;
905
-	p_msg->add_to_branch;
906
-	branch;
907
-*/
906
+error:
907
+   	if (ack_buf) free( ack_buf );
908
+	return -1;
908 909
 }
909 910
 
910 911
 
911 912
 
912
-
913
-
914
-
915 913
 /*---------------------------------TIMEOUT HANDLERS--------------------------------------*/
916 914
 
917 915
 
... ...
@@ -976,6 +990,20 @@ void delete_handler( void *attr)
976 976
        add_to_tail_of_timer_list( hash_table, &(p_cell->dele_tl), DELETE_LIST, DEL_TIME_OUT );
977 977
 }
978 978
 
979
+/* append appropriate branch labels for fast reply-transaction matching
980
+   to outgoing requests
981
+*/
982
+int add_branch_label( struct cell *trans, struct sip_msg *p_msg, int branch )
983
+{
984
+	char *c;
985
+	short n;
979 986
 
980
-
981
-
987
+	n=snprintf( p_msg->add_to_branch_s+p_msg->add_to_branch_len, 
988
+		  MAX_BRANCH_PARAM_LEN - p_msg->add_to_branch_len,
989
+		 ".%h.%h.%h",
990
+		 trans->hash_index, trans->label, branch );
991
+	if (n==-1) {
992
+		LOG(L_ERR, "ERROR: add_branch_label: too small branch buffer\n");
993
+		return -1;
994
+	} else return 0;
995
+}
... ...
@@ -21,8 +21,12 @@ struct cell;
21 21
 
22 22
 #define sh_malloc( size )     malloc(size)
23 23
 #define sh_free( ptr )           free(ptr)
24
+/* already defined in msg_parser.h
24 25
 #define get_cseq( p_msg)    ((struct cseq_body*)p_msg->cseq->parsed)
26
+*/
25 27
 
28
+/* maximumum length of localy generated acknowledgement */
29
+#define MAX_ACK_LEN 1024
26 30
 
27 31
 
28 32
 int tm_startup();
... ...
@@ -670,6 +670,12 @@ error:
670 670
 /* parse the headers and adds them to msg->headers and msg->to, from etc.
671 671
  * It stops when all the headers requested in flags were parsed, on error
672 672
  * (bad header) or end of headers */
673
+/* note: it continues where it previously stopped and goes ahead until
674
+   end is encountered or desired HFs are found; if you call it twice
675
+   for the same HF which is present only once, it will fail the second
676
+   time; if you want to use a dumbie convenience function which will
677
+   give you the header you are interested in, look at check_transaction_quadruple
678
+*/
673 679
 int parse_headers(struct sip_msg* msg, int flags)
674 680
 {
675 681
 	struct hdr_field* hf;
... ...
@@ -942,4 +948,16 @@ void free_sip_msg(struct sip_msg* msg)
942 942
 }
943 943
 
944 944
 
945
+/* make sure all HFs needed for transaction identification have been
946
+   parsed; return 0 if those HFs can't be found
947
+*/
948
+int check_transaction_quadruple( struct sip_msg* msg )
949
+{
950
+   return 
951
+   ( (msg->from || (parse_headers( msg, HDR_FROM)!=-1 && msg->from)) &&
952
+   (msg->to|| (parse_headers( msg, HDR_TO)!=-1 && msg->to)) &&
953
+   (msg->callid|| (parse_headers( msg, HDR_CALLID)!=-1 && msg->callid)) &&
954
+   (msg->cseq|| (parse_headers( msg, HDR_CSEQ)!=-1 && msg->cseq)) ) ? 1 : 0;
955
+
956
+}
945 957
 
... ...
@@ -29,6 +29,9 @@
29 29
 #define HDR_ROUTE        256
30 30
 #define HDR_OTHER       65536 /*unknown header type*/
31 31
 
32
+/* maximum length of values appended to Via-branch parameter */
33
+#define	MAX_BRANCH_PARAM_LEN	32
34
+
32 35
 /* via param types
33 36
  * WARNING: keep in sync w/ FIN_*, GEN_PARAM and PARAM_ERROR from via_parse.c*/
34 37
 enum{
... ...
@@ -37,6 +40,9 @@ enum{
37 37
 		PARAM_ERROR
38 38
 };
39 39
 
40
+/* casting macro for accessing CSEQ body */
41
+#define get_cseq( p_msg)    ((struct cseq_body*)p_msg->cseq->parsed)
42
+
40 43
 
41 44
 
42 45
 #define INVITE_LEN	6
... ...
@@ -169,6 +175,9 @@ struct sip_msg{
169 169
 	struct lump* repl_add_rm; /* only for localy generated replies !!!*/
170 170
 
171 171
 	str add_to_branch; /* whatever whoever want to append to branch comes here */
172
+	char add_to_branch_s[MAX_BRANCH_PARAM_LEN];
173
+	short add_to_branch_len;
174
+
172 175
 	
173 176
 };
174 177
 
... ...
@@ -213,5 +222,7 @@ void clean_hdr_field(struct hdr_field* hf);
213 213
 void free_hdr_field_lst(struct hdr_field* hf);
214 214
 void free_sip_msg(struct sip_msg* msg);
215 215
 
216
+int check_transaction_quadruple( struct sip_msg* msg );
217
+
216 218
 
217 219
 #endif
... ...
@@ -164,11 +164,7 @@ char * build_req_buf_from_sip_req(struct sip_msg* msg, unsigned int *returned_le
164 164
 		/* loop checks ? */
165 165
 		if (loop_checks) {
166 166
 
167
-			if (	(msg->from || (parse_headers( msg, HDR_FROM)!=-1 && msg->from)) &&
168
-				(msg->to|| (parse_headers( msg, HDR_TO)!=-1 && msg->to)) &&
169
-				(msg->callid|| (parse_headers( msg, HDR_CALLID)!=-1 && msg->callid)) &&
170
-				(msg->cseq|| (parse_headers( msg, HDR_CSEQ)!=-1 && msg->cseq)) ) {
171
-
167
+			if (check_transaction_quadruple( msg )) {
172 168
 				str src[5];
173 169
 				int r;
174 170
 			
... ...
@@ -176,7 +172,7 @@ char * build_req_buf_from_sip_req(struct sip_msg* msg, unsigned int *returned_le
176 176
 				src[1]= msg->to->body; 
177 177
 				src[2]= msg->callid->body; 
178 178
 				src[3]= msg->first_line.u.request.uri; 
179
-				src[4]= ((struct cseq_body *)(msg->cseq->parsed))->number;
179
+				src[4]= get_cseq( msg )->number;
180 180
 
181 181
 				MDStringArray ( line_buf+via_len-1, src, 5 );
182 182
 				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
184 184
 					msg->first_line.u.request.uri.s,
185 185
 					((struct cseq_body *)(msg->cseq->parsed))->number.s,
186 186
 					line_buf+via_len-1 );
187
+				DBG("WARNING: build_req_buf_from_sip_req: branch computation NOT over canonical values\n");
187 188
 				via_len+=MD5_LEN - 1;
188 189
 				
189 190
 			} else DBG("DEBUG: build_req_buf_from_sip_req: required HFs for loop checking missing\n");
... ...
@@ -64,6 +64,11 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
64 64
 			goto error;
65 65
 		}
66 66
 		/* check if neccesarry to add receive?->moved to forward_req */
67
+
68
+		/* loop checks */
69
+		if (loop_checks) {
70
+			DBG("WARNING: receive_msg: Placeholder for loop check. NOT implemented yet.\n");
71
+		}
67 72
 		
68 73
 		/* exec routing script */
69 74
 		DBG("preparing to run routing scripts...\n");