bugfix: Call-ID generation repaired, from_tags introduced,
[sip-router] / modules / tm / t_msgbuilder.c
1 /*
2  * $Id$
3  *
4  * message printing
5  *
6  * Copyright (C) 2001-2003 Fhg Fokus
7  *
8  * This file is part of ser, a free SIP server.
9  *
10  * ser is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * For a license to use the ser software under conditions
16  * other than those described here, or to purchase support for this
17  * software, please contact iptel.org by e-mail at the following addresses:
18  *    info@iptel.org
19  *
20  * ser is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License 
26  * along with this program; if not, write to the Free Software 
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  */
29
30
31 #include "../../hash_func.h"
32 #include "../../globals.h"
33 #include "t_funcs.h"
34 #include "../../dprint.h"
35 #include "../../config.h"
36 #include "../../parser/parser_f.h"
37 #include "../../ut.h"
38 #include "../../parser/msg_parser.h"
39 #include "t_msgbuilder.h"
40 #include "uac.h"
41
42
43
44 #define  append_mem_block(_d,_s,_len) \
45                 do{\
46                         memcpy((_d),(_s),(_len));\
47                         (_d) += (_len);\
48                 }while(0);
49
50 #define append_str(_p,_str) \
51         do{  \
52                 memcpy((_p), (_str).s, (_str).len); \
53                 (_p)+=(_str).len;  \
54         } while(0);
55
56 /* Build a local request based on a previous request; main
57    customers of this function are local ACK and local CANCEL
58  */
59 char *build_local(struct cell *Trans,unsigned int branch,
60         unsigned int *len, char *method, int method_len, str *to)
61 {
62         char                *cancel_buf, *p, *via;
63         unsigned int         via_len;
64         struct hdr_field    *hdr;
65         char branch_buf[MAX_BRANCH_PARAM_LEN];
66         int branch_len;
67
68         if ( Trans->uac[branch].last_received<100)
69         {
70                 DBG("DEBUG: build_local: no response ever received"
71                         " : dropping local request! \n");
72                 goto error;
73         }
74
75         /* method, separators, version: "CANCEL sip:p2@iptel.org SIP/2.0" */
76         *len=SIP_VERSION_LEN + method_len + 2 /* spaces */ + CRLF_LEN;
77         *len+=Trans->uac[branch].uri.len;
78
79         /*via*/
80         if (!t_calc_branch(Trans,  branch, 
81                 branch_buf, &branch_len ))
82                 goto error;
83         via=via_builder(&via_len, Trans->uac[branch].request.send_sock,
84                 branch_buf, branch_len );
85         if (!via)
86         {
87                 LOG(L_ERR, "ERROR: t_build_and_send_CANCEL: "
88                         "no via header got from builder\n");
89                 goto error;
90         }
91         *len+= via_len;
92         /*headers*/
93         *len+=Trans->from.len+CRLF_LEN
94                 +Trans->callid.len+CRLF_LEN
95                 +to->len+CRLF_LEN
96                 /* CSeq: 101 CANCEL */
97                 +Trans->cseq_n.len+1+method_len+CRLF_LEN; 
98
99         /* copy'n'paste Route headers */
100         if (!Trans->local) {
101                 for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next )
102                          if (hdr->type==HDR_ROUTE)
103                                 len+=((hdr->body.s+hdr->body.len ) - hdr->name.s ) + 
104                                         CRLF_LEN ;
105         }
106
107         /* User Agent */
108         if (server_signature) {
109                 *len += USER_AGENT_LEN + CRLF_LEN;
110         }
111         /* Content Length, EoM */
112         *len+=CONTENT_LENGTH_LEN+1 + CRLF_LEN + CRLF_LEN;
113
114         cancel_buf=shm_malloc( *len+1 );
115         if (!cancel_buf)
116         {
117                 LOG(L_ERR, "ERROR: t_build_and_send_CANCEL: cannot allocate memory\n");
118                 goto error01;
119         }
120         p = cancel_buf;
121
122         append_mem_block( p, method, method_len );
123         append_mem_block( p, " ", 1 );
124         append_str( p, Trans->uac[branch].uri );
125         append_mem_block( p, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN );
126
127         /* insert our via */
128         append_mem_block(p,via,via_len);
129
130         /*other headers*/
131         append_str( p, Trans->from );
132         append_mem_block( p, CRLF, CRLF_LEN );
133         append_str( p, Trans->callid );
134         append_mem_block( p, CRLF, CRLF_LEN );
135         append_str( p, *to );
136         append_mem_block( p, CRLF, CRLF_LEN );
137         append_str( p, Trans->cseq_n );
138         append_mem_block( p, " ", 1 );
139         append_mem_block( p, method, method_len );
140         append_mem_block( p, CRLF, CRLF_LEN );
141
142         if (!Trans->local)  {
143                 for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next )
144                         if(hdr->type==HDR_ROUTE) {
145                                 append_mem_block(p, hdr->name.s,
146                                         hdr->body.s+hdr->body.len-hdr->name.s );
147                                 append_mem_block(p, CRLF, CRLF_LEN );
148                         }
149         }
150
151         /* User Agent header */
152         if (server_signature) {
153                 append_mem_block(p,USER_AGENT CRLF, USER_AGENT_LEN+CRLF_LEN );
154         }
155         /* Content Length, EoM */
156         append_mem_block(p, CONTENT_LENGTH "0" CRLF CRLF ,
157                 CONTENT_LENGTH_LEN+1 + CRLF_LEN + CRLF_LEN);
158         *p=0;
159
160         pkg_free(via);
161         return cancel_buf;
162 error01:
163         pkg_free(via);
164 error:
165         return NULL;
166 }
167
168
169
170 char *build_uac_request(  str msg_type, str dst, str from,
171         str fromtag, int cseq, str callid, str headers, 
172         str body, int branch, 
173         struct cell *t, unsigned int *len)
174 {
175         char *via;
176         unsigned int via_len;
177         char content_len[10];
178         int content_len_len;
179         char cseq_str[10];
180         int cseq_str_len;
181         char *buf;
182         char *w;
183 #ifdef _OBSOLETED
184         int dummy;
185 #endif
186
187         char branch_buf[MAX_BRANCH_PARAM_LEN];
188         int branch_len;
189
190         int from_len;
191         char *from_str;
192
193         buf=0;
194
195         /* print content length */
196         content_len_len=snprintf(
197                 content_len, sizeof(content_len), 
198                 "%d", body.len );
199         if (content_len_len==-1) {
200                 LOG(L_ERR, "ERROR: uac: content_len too big\n");
201                 return 0;
202         }
203         /* print cseq */
204         cseq_str_len=snprintf( 
205                 cseq_str, sizeof(cseq_str),
206                 "%d", cseq );
207         if (cseq_str_len==-1) {
208                 LOG(L_ERR, "ERROR: uac: cseq too big\n");
209                 return 0;
210         }
211
212         if (from.len) {
213                 from_len=from.len;
214                 from_str=from.s;
215         } else {
216                 from_len=strlen(uac_from);
217                 from_str=uac_from;
218         }
219         
220         *len=SIP_VERSION_LEN+msg_type.len+2/*spaces*/+CRLF_LEN+
221                 dst.len;
222
223         if (!t_calc_branch(t, branch, branch_buf, &branch_len )) {
224                 LOG(L_ERR, "ERROR: build_uac_request: branch calculation failed\n");
225                 goto error;
226         }
227         via=via_builder(&via_len, t->uac[branch].request.send_sock,
228                 branch_buf, branch_len );
229         
230         if (!via) {
231                 LOG(L_ERR, "ERROR: build_uac_request: via building failed\n");
232                 goto error;
233         }
234         *len+=via_len;
235         /* header names and separators */
236         *len+=
237                 +CSEQ_LEN+CRLF_LEN
238                 +TO_LEN+CRLF_LEN
239                 +CALLID_LEN+CRLF_LEN
240                 +CONTENT_LENGTH_LEN+CRLF_LEN
241                 + (server_signature ? USER_AGENT_LEN + CRLF_LEN : 0 )
242                 +FROM_LEN+CRLF_LEN
243                 +CRLF_LEN; /* EoM */
244         /* header field value and body length */
245         *len+= msg_type.len+1+cseq_str_len /* CSeq: method, delimitor, number  */
246                 + dst.len /* To */
247                 + callid.len /* call-id */
248                 + from_len+FROMTAG_LEN+fromtag.len
249                 + content_len_len
250                 + headers.len
251                 + body.len;
252         
253         buf=shm_malloc( *len+1 );
254         if (!buf) {
255                 LOG(L_ERR, "ERROR: t_uac: no shmem\n");
256                 goto error1;
257         }
258         w=buf;
259         memapp( w, msg_type.s, msg_type.len ); 
260         memapp( w, " ", 1); 
261         t->uac[branch].uri.s=w; t->uac[branch].uri.len=dst.len;
262         memapp( w, dst.s, dst.len ); 
263         memapp( w, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN );
264         memapp( w, via, via_len );
265
266         /* CSeq */
267         t->cseq_n.s=w; 
268         t->cseq_n.len=CSEQ_LEN+cseq_str_len;
269         memapp(w, CSEQ, CSEQ_LEN );
270         memapp(w, cseq_str, cseq_str_len );
271         memapp(w, " ", 1 );
272
273         memapp( w, msg_type.s, msg_type.len );
274         t->to.s=w+CRLF_LEN; t->to.len=TO_LEN+dst.len;
275         memapp( w, CRLF TO, CRLF_LEN + TO_LEN  );
276         memapp( w, dst.s, dst.len );
277         t->callid.s=w+CRLF_LEN; t->callid.len=callid.len;
278         memapp( w, CRLF CALLID, CRLF_LEN + CALLID_LEN  );
279         memapp( w, callid.s, callid.len );
280         memapp( w, CRLF CONTENT_LENGTH, CRLF_LEN + CONTENT_LENGTH_LEN);
281         memapp( w, content_len, content_len_len );
282         if (server_signature) {
283                 memapp( w, CRLF USER_AGENT CRLF FROM, 
284                         CRLF_LEN+USER_AGENT_LEN+CRLF_LEN+FROM_LEN);
285         } else {
286                 memapp( w, CRLF  FROM, 
287                         CRLF_LEN+FROM_LEN);
288         }
289         t->from.s=w-FROM_LEN; 
290         t->from.len=FROM_LEN+from_len+FROMTAG_LEN+fromtag.len;
291         memapp( w, from_str, from_len );
292         memapp( w, FROMTAG, FROMTAG_LEN );
293         memapp( w, fromtag.s, fromtag.len );
294         memapp( w, CRLF, CRLF_LEN );
295
296         memapp( w, headers.s, headers.len );
297         /* EoH */
298         memapp( w, CRLF, CRLF_LEN );
299         if ( body.s ) {
300                 memapp( w, body.s, body.len );
301         }
302 #ifdef _OBSOLETED
303         /* ugly HACK -- debugging has shown len shorter by one */
304         dummy=*len+1;
305         *len=dummy;
306 #endif
307 #       ifdef EXTRA_DEBUG
308         if (w-buf != *len ) abort();
309 #       endif
310         
311         
312 error1:
313         pkg_free(via);  
314 error:
315         return buf;
316         
317 }
318
319
320 int t_calc_branch(struct cell *t, 
321         int b, char *branch, int *branch_len)
322 {
323         return syn_branch ?
324                 branch_builder( t->hash_index,
325                         t->label, 0,
326                         b, branch, branch_len )
327                 : branch_builder( t->hash_index,
328                         0, t->md5,
329                         b, branch, branch_len );
330 }
331
332 int t_setbranch( struct cell *t, struct sip_msg *msg, int b )
333 {
334         return t_calc_branch( t, b, 
335                 msg->add_to_branch_s, &msg->add_to_branch_len );
336 }