a3107ad17b409f4f47b82b8437924fb379a34ce1
[sip-router] / modules / tm / t_msgbuilder.c
1 /*
2  * $Id$
3  *
4  * message printing
5  */
6
7 #include "../../hash_func.h"
8 #include "../../globals.h"
9 #include "t_funcs.h"
10 #include "../../dprint.h"
11 #include "../../config.h"
12 #include "../../parser/parser_f.h"
13 #include "../../ut.h"
14 #include "../../parser/msg_parser.h"
15 #include "t_msgbuilder.h"
16 #include "uac.h"
17
18
19
20 #define  append_mem_block(_d,_s,_len) \
21                 do{\
22                         memcpy((_d),(_s),(_len));\
23                         (_d) += (_len);\
24                 }while(0);
25
26 #define append_str(_p,_str) \
27         do{  \
28                 memcpy((_p), (_str).s, (_str).len); \
29                 (_p)+=(_str).len;  \
30         } while(0);
31
32 /* Build a local request based on a previous request; main
33    customers of this function are local ACK and local CANCEL
34  */
35 char *build_local(struct cell *Trans,unsigned int branch,
36         unsigned int *len, char *method, int method_len, str *to)
37 {
38         char                *cancel_buf, *p, *via;
39         unsigned int         via_len;
40         struct hdr_field    *hdr;
41         char branch_buf[MAX_BRANCH_PARAM_LEN];
42         int branch_len;
43
44         if ( Trans->uac[branch].last_received<100)
45         {
46                 DBG("DEBUG: build_local: no response ever received"
47                         " : dropping local request! \n");
48                 goto error;
49         }
50
51         /* method, separators, version: "CANCEL sip:p2@iptel.org SIP/2.0" */
52         *len=SIP_VERSION_LEN + method_len + 2 /* spaces */ + CRLF_LEN;
53         *len+=Trans->uac[branch].uri.len;
54
55         /*via*/
56         if (!t_calc_branch(Trans,  branch, 
57                 branch_buf, &branch_len ))
58                 goto error;
59         via=via_builder(&via_len, Trans->uac[branch].request.send_sock,
60                 branch_buf, branch_len );
61         if (!via)
62         {
63                 LOG(L_ERR, "ERROR: t_build_and_send_CANCEL: "
64                         "no via header got from builder\n");
65                 goto error;
66         }
67         *len+= via_len;
68         /*headers*/
69         *len+=Trans->from.len+CRLF_LEN
70                 +Trans->callid.len+CRLF_LEN
71                 +to->len+CRLF_LEN
72                 /* CSeq: 101 CANCEL */
73                 +Trans->cseq_n.len+1+method_len+CRLF_LEN; 
74
75         /* copy'n'paste Route headers */
76         if (!Trans->local) {
77                 for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next )
78                          if (hdr->type==HDR_ROUTE)
79                                 len+=((hdr->body.s+hdr->body.len ) - hdr->name.s ) + 
80                                         CRLF_LEN ;
81         }
82
83         /* User Agent */
84         if (server_signature) {
85                 *len += USER_AGENT_LEN + CRLF_LEN;
86         }
87         /* Content Length, EoM */
88         *len+=CONTENT_LEN_LEN + CRLF_LEN + CRLF_LEN;
89
90         cancel_buf=shm_malloc( *len+1 );
91         if (!cancel_buf)
92         {
93                 LOG(L_ERR, "ERROR: t_build_and_send_CANCEL: cannot allocate memory\n");
94                 goto error01;
95         }
96         p = cancel_buf;
97
98         append_mem_block( p, method, method_len );
99         append_mem_block( p, " ", 1 );
100         append_str( p, Trans->uac[branch].uri );
101         append_mem_block( p, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN );
102
103         /* insert our via */
104         append_mem_block(p,via,via_len);
105
106         /*other headers*/
107         append_str( p, Trans->from );
108         append_mem_block( p, CRLF, CRLF_LEN );
109         append_str( p, Trans->callid );
110         append_mem_block( p, CRLF, CRLF_LEN );
111         append_str( p, *to );
112         append_mem_block( p, CRLF, CRLF_LEN );
113         append_str( p, Trans->cseq_n );
114         append_mem_block( p, " ", 1 );
115         append_mem_block( p, method, method_len );
116         append_mem_block( p, CRLF, CRLF_LEN );
117
118         if (!Trans->local)  {
119                 for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next )
120                         if(hdr->type==HDR_ROUTE) {
121                                 append_mem_block(p, hdr->name.s,
122                                         hdr->body.s+hdr->body.len-hdr->name.s );
123                                 append_mem_block(p, CRLF, CRLF_LEN );
124                         }
125         }
126
127         /* User Agent header */
128         if (server_signature) {
129                 append_mem_block(p,USER_AGENT CRLF, USER_AGENT_LEN+CRLF_LEN );
130         }
131         /* Content Length, EoM */
132         append_mem_block(p, CONTENT_LEN CRLF CRLF ,
133                 CONTENT_LEN_LEN + CRLF_LEN + CRLF_LEN);
134         *p=0;
135
136         pkg_free(via);
137         return cancel_buf;
138 error01:
139         pkg_free(via);
140 error:
141         return NULL;
142 }
143
144
145
146 char *build_uac_request(  str msg_type, str dst, str from,
147         str headers, str body, int branch, 
148                 struct cell *t, int *len)
149 {
150         char *via;
151         int via_len;
152         char content_len[10];
153         int content_len_len;
154         char *buf;
155         char *w;
156         int dummy;
157
158         char branch_buf[MAX_BRANCH_PARAM_LEN];
159         int branch_len;
160
161         int from_len;
162         char *from_str;
163
164         buf=0;
165
166         if (from.len) {
167                 from_len=from.len;
168                 from_str=from.s;
169         } else {
170                 from_len=strlen(uac_from);
171                 from_str=uac_from;
172         }
173         
174         *len=SIP_VERSION_LEN+msg_type.len+2/*spaces*/+CRLF_LEN+
175                 dst.len;
176
177         if (!t_calc_branch(t, branch, branch_buf, &branch_len )) {
178                 LOG(L_ERR, "ERROR: build_uac_request: branch calculation failed\n");
179                 goto error;
180         }
181         via=via_builder(&via_len, t->uac[branch].request.send_sock,
182                 branch_buf, branch_len );
183         
184         if (!via) {
185                 LOG(L_ERR, "ERROR: build_uac_request: via building failed\n");
186                 goto error;
187         }
188         *len+=via_len;
189         /* content length */
190         content_len_len=snprintf(
191                 content_len, sizeof(content_len), "%d", body.len );
192         /* header names and separators */
193         *len+=
194                 +CSEQ_LEN+CRLF_LEN
195                 +TO_LEN+CRLF_LEN
196                 +CALLID_LEN+CRLF_LEN
197                 +CONTENT_LENGTH_LEN+CRLF_LEN
198                 + (server_signature ? USER_AGENT_LEN + CRLF_LEN : 0 )
199                 +FROM_LEN+CRLF_LEN
200                 +CRLF_LEN; /* EoM */
201         /* header field value and body length */
202         *len+= msg_type.len+1+UAC_CSEQNR_LEN /* CSeq: method, delimitor, number  */
203                 + dst.len /* To */
204                 + RAND_DIGITS+1+MAX_PID_LEN+1+MAX_SEQ_LEN /* call-id */
205                 + from_len+FROMTAG_LEN+MD5_LEN+
206                 + content_len_len
207                 + headers.len
208                 + body.len;
209         
210         buf=shm_malloc( *len+1 );
211         if (!buf) {
212                 LOG(L_ERR, "ERROR: t_uac: no shmem\n");
213                 goto error1;
214         }
215         w=buf;
216         memapp( w, msg_type.s, msg_type.len ); 
217         memapp( w, " ", 1); 
218         t->uac[branch].uri.s=w; t->uac[branch].uri.len=dst.len;
219         memapp( w, dst.s, dst.len ); 
220         memapp( w, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN );
221         memapp( w, via, via_len );
222         t->cseq_n.s=w; t->cseq_n.len=CSEQ_LEN+UAC_CSEQNR_LEN;
223         memapp( w, CSEQ UAC_CSEQNR " ", CSEQ_LEN + UAC_CSEQNR_LEN+ 1 );
224         memapp( w, msg_type.s, msg_type.len );
225         t->to.s=w+CRLF_LEN; t->to.len=TO_LEN+dst.len;
226         memapp( w, CRLF TO, CRLF_LEN + TO_LEN  );
227         memapp( w, dst.s, dst.len );
228         t->callid.s=w+CRLF_LEN; t->callid.len=CALLID_LEN+RAND_DIGITS+1+
229                 MAX_PID_LEN+1+MAX_SEQ_LEN;
230         memapp( w, CRLF CALLID, CRLF_LEN + CALLID_LEN  );
231         memapp( w, call_id, RAND_DIGITS+1+MAX_PID_LEN+1+MAX_SEQ_LEN );
232         memapp( w, CRLF CONTENT_LEN, CRLF_LEN + CONTENT_LEN_LEN);
233         memapp( w, content_len, content_len_len );
234         if (server_signature) {
235                 memapp( w, CRLF USER_AGENT CRLF FROM, 
236                         CRLF_LEN+USER_AGENT_LEN+CRLF_LEN+FROM_LEN);
237         } else {
238                 memapp( w, CRLF  FROM, 
239                         CRLF_LEN+FROM_LEN);
240         }
241         t->from.s=w-FROM_LEN; t->from.len=FROM_LEN+from_len+FROMTAG_LEN+MD5_LEN;
242         memapp( w, from_str, from_len );
243         memapp( w, FROMTAG, FROMTAG_LEN );
244         memapp( w, from_tag, MD5_LEN );
245         memapp( w, CRLF, CRLF_LEN );
246
247         memapp( w, headers.s, headers.len );
248         /* EoH */
249         memapp( w, CRLF, CRLF_LEN );
250         if ( body.s ) {
251                 memapp( w, body.s, body.len );
252         }
253         /* ugly HACK -- debugging has shown len shorter by one */
254         dummy=*len+1;
255         *len=dummy;
256 #       ifdef EXTRA_DEBUG
257         if (w-buf != *len ) abort();
258 #       endif
259         
260         
261 error1:
262         pkg_free(via);  
263 error:
264         return buf;
265         
266 }
267
268
269 int t_calc_branch(struct cell *t, 
270         int b, char *branch, int *branch_len)
271 {
272         return syn_branch ?
273                 branch_builder( t->hash_index,
274                         t->label, 0,
275                         b, branch, branch_len )
276                 : branch_builder( t->hash_index,
277                         0, t->md5,
278                         b, branch, branch_len );
279 }
280
281 int t_setbranch( struct cell *t, struct sip_msg *msg, int b )
282 {
283         return t_calc_branch( t, b, 
284                 msg->add_to_branch_s, &msg->add_to_branch_len );
285 }