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 800
 }
803 801
 
804 802
 
803
+/* copy a header field to an output buffer if space allows */
804
+int copy_hf( char **dst, struct hdr_field* hf, char *bumper )
805
+{
806
+   int n;
807
+   n=hf->body.len+2+hf->name.len+CRLF_LEN;
808
+   if (*dst+n >= bumper ) return -1;
809
+   memcpy(*dst, hf->name.s, hf->name.len );
810
+   *dst+= hf->name.len ;
811
+   **dst = ':'; (*dst)++;
812
+   **dst = ' '; (*dst)++;
813
+   memcpy(*dst, hf->body.s, hf->body.len);
814
+   *dst+= hf->body.len;
815
+   memcpy( *dst, CRLF, CRLF_LEN );
816
+   *dst+=CRLF_LEN;
817
+   return 0;
818
+}
819
+  
820
+
805 821
 
806 822
 
807 823
 /* 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 828
     struct sip_msg* p_msg = T->inbound_request;
813 829
     struct via_body *via;
814 830
     struct hdr_field *hdr;
815
-   char *ack_buf, *p;
831
+    char *ack_buf=NULL, *p;
816 832
     unsigned int len;
833
+    int n;
834
+
835
+   /* enough place for first line and Via ? */
836
+   if ( 4 + p_msg->first_line.u.request.uri.len + 1 + p_msg->first_line.u.request.version.len +
837
+	CRLF_LEN + MY_VIA_LEN + names_len[0] + 1 + port_no_str_len + MY_BRANCH_LEN  < MAX_ACK_LEN ) {
838
+		LOG( L_ERR, "ERROR: t_build_and_send_ACK: no place for FL/Via\n");
839
+		goto error;
840
+   }
817 841
 
818
-   ack_buf = (char *)malloc( 1024 * 10 );
842
+   ack_buf = (char *)malloc( MAX_ACK_LEN );
819 843
    p = ack_buf;
820 844
 
821 845
    /* first line */
822 846
    memcpy( p , "ACK " , 4);
823 847
    p += 4;
848
+
824 849
    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++)=' ';
850
+   p += p_msg->first_line.u.request.uri.len;
851
+
852
+   *(p++) = ' ';
853
+
827 854
    memcpy( p , p_msg->first_line.u.request.version.s , p_msg->first_line.u.request.version.len );
828 855
    p += p_msg->first_line.u.request.version.len;
829
-   *(p++) = '\n';
856
+
857
+   memcpy( p, CRLF, CRLF_LEN );
858
+   p+=CRLF_LEN;
830 859
 
831 860
    /* insert our via */
832
-   memcpy( p , "Via: SIP/2.0/UDP " , 17);
833
-   p += 17;
861
+   memcpy( p , MY_VIA , MY_VIA_LEN );
862
+   p += MY_VIA_LEN;
863
+
834 864
    memcpy( p , names[0] , names_len[0] );
835 865
    p += names_len[0];
866
+
836 867
    *(p++) = ':';
868
+
837 869
    memcpy( p , port_no_str , port_no_str_len );
838 870
    p += port_no_str_len;
839 871
 
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
-      }
872
+   memcpy( p, MY_BRANCH, MY_BRANCH_LEN );
873
+   p+=MY_BRANCH_LEN;
874
+
875
+   n=snprintf( p, ack_buf + MAX_ACK_LEN - p, 
876
+                 ".%h.%h.%h%s",
877
+                 Trans->hash_index, Trans->label, branch, CRLF );
878
+   if (n==-1) {
879
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: not enough memory for branch\n");
880
+	goto error;
881
+   }
882
+   p+=n;
883
+
884
+   if (!check_transaction_quadruple( p_msg )) {
885
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: can't generate a HBH ACK if key HFs in INVITE missing\n");
886
+	goto error;
887
+   }
888
+
889
+   /* To */
890
+   if (copy_hf( &p, p_msg->to , ack_buf + MAX_ACK_LEN )==-1) {
891
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no place for To\n");
892
+	goto error;
893
+   }
894
+   /* From */
895
+   if (copy_hf( &p, p_msg->from, ack_buf + MAX_ACK_LEN )==-1) {
896
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no place for From\n");
897
+	goto error;
898
+   }
899
+   /* CallId */
900
+   if (copy_hf( &p, p_msg->callid, ack_buf + MAX_ACK_LEN )==-1) {
901
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no place for callid\n");
902
+	goto error;
903
+   }
904
+   /* CSeq, EoH */
905
+   n=snprintf( p, ack_buf + MAX_ACK_LEN - p, 
906
+                 "Cseq: %*s ACK%s%s", get_cseq(p_msg)->number.len, 
907
+		get_cseq(p_msg)->number.s, CRLF, CRLF );
908
+   if (n==-1) {
909
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no enough memory for Cseq\n");
910
+	goto error;
911
+   }
912
+   p+=n;
864 913
 
865
-   /* end of message*/
866
-   *(p++) = '\n';
867 914
 
868 915
    /* sends the ACK message to the same destination as the INVITE */
869 916
    udp_send( ack_buf, p-ack_buf, (struct sockaddr*)&(T->outbound_request[branch]->to) , sizeof(struct sockaddr_in) );
870 917
 
871 918
    /* free mem*/
872
-   free( ack_buf );
873
-
919
+   if (ack_buf) free( ack_buf );
874 920
    return 0;
875
-}
876
-
877
-
878 921
 
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
-*/
922
+error:
923
+   	if (ack_buf) free( ack_buf );
924
+	return -1;
908 925
 }
909 926
 
910 927
 
911 928
 
912
-
913
-
914
-
915 929
 /*---------------------------------TIMEOUT HANDLERS--------------------------------------*/
916 930
 
917 931
 
... ...
@@ -976,6 +990,20 @@ void delete_handler( void *attr)
976 990
        add_to_tail_of_timer_list( hash_table, &(p_cell->dele_tl), DELETE_LIST, DEL_TIME_OUT );
977 991
 }
978 992
 
993
+/* append appropriate branch labels for fast reply-transaction matching
994
+   to outgoing requests
995
+*/
996
+int add_branch_label( struct cell *trans, struct sip_msg *p_msg, int branch )
997
+{
998
+	char *c;
999
+	short n;
979 1000
 
980
-
981
-
1001
+	n=snprintf( p_msg->add_to_branch_s+p_msg->add_to_branch_len, 
1002
+		  MAX_BRANCH_PARAM_LEN - p_msg->add_to_branch_len,
1003
+		 ".%h.%h.%h",
1004
+		 trans->hash_index, trans->label, branch );
1005
+	if (n==-1) {
1006
+		LOG(L_ERR, "ERROR: add_branch_label: too small branch buffer\n");
1007
+		return -1;
1008
+	} else return 0;
1009
+}
... ...
@@ -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 948
 }
943 949
 
944 950
 
951
+/* make sure all HFs needed for transaction identification have been
952
+   parsed; return 0 if those HFs can't be found
953
+*/
954
+int check_transaction_quadruple( struct sip_msg* msg )
955
+{
956
+   return 
957
+   ( (msg->from || (parse_headers( msg, HDR_FROM)!=-1 && msg->from)) &&
958
+   (msg->to|| (parse_headers( msg, HDR_TO)!=-1 && msg->to)) &&
959
+   (msg->callid|| (parse_headers( msg, HDR_CALLID)!=-1 && msg->callid)) &&
960
+   (msg->cseq|| (parse_headers( msg, HDR_CSEQ)!=-1 && msg->cseq)) ) ? 1 : 0;
961
+
962
+}
945 963
 
... ...
@@ -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 40
 		PARAM_ERROR
38 41
 };
39 42
 
43
+/* casting macro for accessing CSEQ body */
44
+#define get_cseq( p_msg)    ((struct cseq_body*)p_msg->cseq->parsed)
45
+
40 46
 
41 47
 
42 48
 #define INVITE_LEN	6
... ...
@@ -169,6 +175,9 @@ struct sip_msg{
169 175
 	struct lump* repl_add_rm; /* only for localy generated replies !!!*/
170 176
 
171 177
 	str add_to_branch; /* whatever whoever want to append to branch comes here */
178
+	char add_to_branch_s[MAX_BRANCH_PARAM_LEN];
179
+	short add_to_branch_len;
180
+
172 181
 	
173 182
 };
174 183
 
... ...
@@ -213,5 +222,7 @@ void clean_hdr_field(struct hdr_field* hf);
213 222
 void free_hdr_field_lst(struct hdr_field* hf);
214 223
 void free_sip_msg(struct sip_msg* msg);
215 224
 
225
+int check_transaction_quadruple( struct sip_msg* msg );
226
+
216 227
 
217 228
 #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 172
 				src[1]= msg->to->body; 
177 173
 				src[2]= msg->callid->body; 
178 174
 				src[3]= msg->first_line.u.request.uri; 
179
-				src[4]= ((struct cseq_body *)(msg->cseq->parsed))->number;
175
+				src[4]= get_cseq( msg )->number;
180 176
 
181 177
 				MDStringArray ( line_buf+via_len-1, src, 5 );
182 178
 				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 180
 					msg->first_line.u.request.uri.s,
185 181
 					((struct cseq_body *)(msg->cseq->parsed))->number.s,
186 182
 					line_buf+via_len-1 );
183
+				DBG("WARNING: build_req_buf_from_sip_req: branch computation NOT over canonical values\n");
187 184
 				via_len+=MD5_LEN - 1;
188 185
 				
189 186
 			} 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");