... | ... |
@@ -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"); |