- replaced msg->src_ip w/ msg->rcv.src_ip (to be in sync w/ core)$
[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, Trans->uac[branch].request.send_sock->proto );
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, t->uac[branch].request.send_sock->proto);
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 char *build_uac_request_dlg(str* msg,           /* Method */
321                             str* ruri,          /* Request-URI */
322                             str* to,            /* To */
323                             str* from,          /* From */
324                             str* totag,         /* To header tag */
325                             str* fromtag,       /* From header tag */
326                             unsigned int cseq,  /* CSeq number */
327                             str* callid,        /* Call-ID */
328                             str* headers,       /* Headers to be appended */
329                             str* body,          /* Body of the message */
330                             int branch,         /* Branch */
331                             struct cell *t,     
332                             unsigned int *len)
333 {
334         char *via, *buf, *w, content_len[10], cseq_str[10], branch_buf[MAX_BRANCH_PARAM_LEN];
335         int content_len_len, cseq_str_len, branch_len;
336         unsigned int via_len;
337
338         buf=0;
339         content_len_len = 0; /* Makes gcc happy */
340
341              /* 
342               * Print Content-Length
343               */
344         if (body) {
345                 content_len_len = snprintf(content_len, sizeof(content_len), "%d", body->len);
346                 if (content_len_len == -1) {
347                         LOG(L_ERR, "ERROR: build_uac_request_dlg: content_len too big\n");
348                         return 0;
349                 }
350         }
351         
352              /* 
353               * Print CSeq 
354               */
355         cseq_str_len = snprintf(cseq_str, sizeof(cseq_str), "%d", cseq);
356         if (cseq_str_len == -1) {
357                 LOG(L_ERR, "ERROR: build_uac_request_dlg: cseq too big\n");
358                 return 0;
359         }
360         
361         *len = msg->len + 1 + ruri->len + 1 + SIP_VERSION_LEN + CRLF_LEN;
362
363         if (!t_calc_branch(t, branch, branch_buf, &branch_len)) {
364                 LOG(L_ERR, "ERROR: build_uac_request_dlg: branch calculation failed\n");
365                 goto error;
366         }
367
368         via = via_builder(&via_len, t->uac[branch].request.send_sock, 
369                         branch_buf, branch_len, t->uac[branch].request.send_sock->proto);
370         if (!via) {
371                 LOG(L_ERR, "ERROR: build_uac_request_dlg: via building failed\n");
372                 goto error;
373         }
374         
375         *len += via_len;
376         
377         /* header names and separators */
378         *len +=   TO_LEN + CRLF_LEN
379                 + FROM_LEN + CRLF_LEN
380                 + CSEQ_LEN + CRLF_LEN
381                 + CALLID_LEN + CRLF_LEN
382                 + ((body) ? (CONTENT_LENGTH_LEN + CRLF_LEN) : 0)
383                 + (server_signature ? USER_AGENT_LEN + CRLF_LEN : 0)
384                 + CRLF_LEN; /* EoM */
385         
386              /* header field value and body length */
387         *len +=   to->len + ((totag) ? (TOTAG_LEN + totag->len) : 0) /* To */
388                 + from->len + FROMTAG_LEN + fromtag->len             /* From */
389                 + cseq_str_len + 1 + msg->len                        /* CSeq */
390                 + callid->len                                        /* Call-ID */
391                 + ((body) ? (content_len_len) : 0)                   /* Content-Length */
392                 + ((headers) ? (headers->len) : 0)                   /* Headers */
393                 + ((body) ? (body->len) : 0);                        /* Body */
394         
395         buf = shm_malloc(*len + 1);
396         if (!buf) {
397                 LOG(L_ERR, "ERROR: build_uac_request_dlg: no shmem\n");
398                 goto error1;
399         }
400         
401         w = buf;
402
403              /* First line */
404         memapp(w, msg->s, msg->len); 
405         memapp(w, " ", 1); 
406
407         t->uac[branch].uri.s = w; 
408         t->uac[branch].uri.len = ruri->len;
409
410         memapp(w, ruri->s, ruri->len); 
411         memapp(w, " " SIP_VERSION CRLF, 1 + SIP_VERSION_LEN + CRLF_LEN);
412
413              /* First Via */
414         memapp(w, via, via_len);
415
416              /* To */
417         t->to.s = w;
418         t->to.len = TO_LEN + to->len + ((totag) ? (TOTAG_LEN + totag->len) : 0);
419
420         memapp(w, TO, TO_LEN);
421         memapp(w, to->s, to->len);
422         if (totag) {
423                 memapp(w, TOTAG, TOTAG_LEN);
424                 memapp(w, totag->s, totag->len);
425         }
426         memapp(w, CRLF, CRLF_LEN);
427
428              /* From */
429         t->from.s = w;
430         t->from.len = FROM_LEN + from->len + FROMTAG_LEN + fromtag->len;
431
432         memapp(w, FROM, FROM_LEN);
433         memapp(w, from->s, from->len);
434         memapp(w, FROMTAG, FROMTAG_LEN);
435         memapp(w, fromtag->s, fromtag->len);
436         memapp(w, CRLF, CRLF_LEN);
437         
438              /* CSeq */
439         t->cseq_n.s = w; 
440         t->cseq_n.len = CSEQ_LEN + cseq_str_len;
441
442         memapp(w, CSEQ, CSEQ_LEN);
443         memapp(w, cseq_str, cseq_str_len);
444         memapp(w, " ", 1);
445         memapp(w, msg->s, msg->len);
446
447              /* Call-ID */
448         t->callid.s = w + CRLF_LEN; 
449         t->callid.len = callid->len;
450         memapp(w, CRLF CALLID, CRLF_LEN + CALLID_LEN);
451         memapp(w, callid->s, callid->len);
452
453              /* Content-Length */
454         if (body) {
455                 memapp(w, CRLF CONTENT_LENGTH, CRLF_LEN + CONTENT_LENGTH_LEN);
456                 memapp(w, content_len, content_len_len);
457                 memapp(w, CRLF, CRLF_LEN);
458         }
459         
460              /* Server signature */
461         if (server_signature) {
462                 memapp(w, USER_AGENT CRLF, USER_AGENT_LEN + CRLF_LEN);
463         }
464
465              /* Headers */
466         if (headers) {
467                 memapp(w, headers->s, headers->len);
468         }
469
470              /* EoH */
471         memapp(w, CRLF, CRLF_LEN);
472         
473              /* Body */
474         if (body) {
475                 memapp(w, body->s, body->len);
476         }
477
478 #ifdef EXTRA_DEBUG
479         if (w-buf != *len ) abort();
480 #endif
481         
482  error1:
483         pkg_free(via);  
484  error:
485         return buf;
486 }
487
488
489 int t_calc_branch(struct cell *t, 
490         int b, char *branch, int *branch_len)
491 {
492         return syn_branch ?
493                 branch_builder( t->hash_index,
494                         t->label, 0,
495                         b, branch, branch_len )
496                 : branch_builder( t->hash_index,
497                         0, t->md5,
498                         b, branch, branch_len );
499 }
500