3651ebac0b799bd1b6a0b00906ed50e53806e5eb
[sip-router] / modules / tm / sip_msg.c
1 /*
2  * $Id$
3  * 
4  * cloning a message into shared memory (TM keeps a snapshot
5  * of messages in memory); note that many operations, which
6  * allocate pkg memory (such as parsing) cannot be used with
7  * a cloned message -- it would result in linking pkg structures
8  * to shmem msg and eventually in a memory error 
9  *
10  * the cloned message is stored in a single memory fragment to
11  * save too many shm_mallocs -- these are expensive as they
12  * not only take lookup in fragment table but also a shmem lock
13  * operation (the same for shm_free)
14  */
15
16 #include <stdio.h>
17 #include "sip_msg.h"
18 #include "../../dprint.h"
19 #include "../../mem/mem.h"
20 #include "../../data_lump.h"
21 #include "../../data_lump_rpl.h"
22 #include "../../ut.h"
23
24
25
26 #define ROUND4(s) \
27         (((s)+3)&(~(3UL)))
28 #define lump_len( _lump) \
29         (ROUND4(sizeof(struct lump)) +\
30         ROUND4(((_lump)->op==LUMP_ADD)?(_lump)->len:0))
31 #define lump_clone( _new,_old,_ptr) \
32         {\
33                 (_new) = (struct lump*)(_ptr);\
34                 memcpy( (_new), (_old), sizeof(struct lump) );\
35                 (_ptr)+=ROUND4(sizeof(struct lump));\
36                 if ( (_old)->op==LUMP_ADD) {\
37                         (_new)->u.value = (char*)(_ptr);\
38                         memcpy( (_new)->u.value , (_old)->u.value , (_old)->len);\
39                         (_ptr)+=ROUND4((_old)->len);}\
40         }
41
42
43
44
45 inline struct via_body* via_body_cloner( char* new_buf,
46                                         char *org_buf, struct via_body *param_org_via, char **p)
47 {
48         struct via_body *new_via;
49         struct via_body *first_via, *last_via;
50         struct via_body *org_via;
51
52         first_via = last_via = 0;
53         org_via = param_org_via;
54
55         do
56         {
57                 /* clones the via_body structure */
58                 new_via = (struct via_body*)(*p);
59                 memcpy( new_via , org_via , sizeof( struct via_body) );
60                 (*p) += ROUND4(sizeof( struct via_body ));
61
62                 /* hdr (str type) */
63                 new_via->hdr.s=translate_pointer(new_buf,org_buf,org_via->hdr.s);
64                 /* name (str type) */
65                 new_via->name.s=translate_pointer(new_buf,org_buf,org_via->name.s);
66                 /* version (str type) */
67                 new_via->version.s=
68                         translate_pointer(new_buf,org_buf,org_via->version.s);
69                 /* transport (str type) */
70                 new_via->transport.s=
71                         translate_pointer(new_buf,org_buf,org_via->transport.s);
72                 /* host (str type) */
73                 new_via->host.s=translate_pointer(new_buf,org_buf,org_via->host.s);
74                 /* port_str (str type) */
75                 new_via->port_str.s=
76                         translate_pointer(new_buf,org_buf,org_via->port_str.s);
77                 /* params (str type) */
78                 new_via->params.s=translate_pointer(new_buf,org_buf,org_via->params.s);
79                 /* comment (str type) */
80                 new_via->comment.s=
81                         translate_pointer(new_buf,org_buf,org_via->comment.s);
82
83                 if ( org_via->param_lst )
84                 {
85                         struct via_param *vp, *new_vp, *last_new_vp;
86                         for( vp=org_via->param_lst, last_new_vp=0 ; vp ; vp=vp->next )
87                         {
88                                 new_vp = (struct via_param*)(*p);
89                                 memcpy( new_vp , vp , sizeof(struct via_param));
90                                 (*p) += ROUND4(sizeof(struct via_param));
91                                 new_vp->name.s=translate_pointer(new_buf,org_buf,vp->name.s);
92                                 new_vp->value.s=translate_pointer(new_buf,org_buf,vp->value.s);
93
94                                 if (new_vp->type==PARAM_BRANCH)
95                                         new_via->branch = new_vp;
96
97                                 if (last_new_vp)
98                                         last_new_vp->next = new_vp;
99                                 else
100                                         new_via->param_lst = new_vp;
101
102                                 last_new_vp = new_vp;
103                                 last_new_vp->next = NULL;
104                         }
105                         new_via->last_param = new_vp;
106                 }/*end if via has params */
107
108                 if (last_via)
109                         last_via->next = new_via;
110                 else
111                         first_via = new_via;
112                 last_via = new_via;
113                 org_via = org_via->next;
114         }while(org_via);
115
116         return first_via;
117 }
118
119
120
121
122 struct sip_msg*  sip_msg_cloner( struct sip_msg *org_msg )
123 {
124         unsigned int      len;
125         struct hdr_field  *hdr,*new_hdr,*last_hdr;
126         struct via_body   *via;
127         struct via_param  *prm;
128         struct to_param   *to_prm,*new_to_prm;
129         struct sip_msg    *new_msg;
130         struct lump       *lump_chain, *lump_tmp, **lump_anchor, **lump_anchor2;
131         struct lump_rpl   *rpl_lump, **rpl_lump_anchor;
132         char              *p,*foo;
133
134
135         /*computing the length of entire sip_msg structure*/
136         len = ROUND4(sizeof( struct sip_msg ));
137         /*we will keep only the original msg +ZT */
138         len += ROUND4(org_msg->len + 1);
139         /*the new uri (if any)*/
140         if (org_msg->new_uri.s && org_msg->new_uri.len)
141                 len+= ROUND4(org_msg->new_uri.len);
142         /*all the headers*/
143         for( hdr=org_msg->headers ; hdr ; hdr=hdr->next )
144         {
145                 /*size of header struct*/
146                 len += ROUND4(sizeof( struct hdr_field));
147                 switch (hdr->type)
148                 {
149                         case HDR_CSEQ:
150                                 len+=ROUND4(sizeof(struct cseq_body));
151                                 break;
152                         case HDR_TO:
153                                 len+=ROUND4(sizeof(struct to_body));
154                                 /*to param*/
155                                 to_prm = ((struct to_body*)(hdr->parsed))->param_lst;
156                                 for(;to_prm;to_prm=to_prm->next)
157                                         len+=ROUND4(sizeof(struct to_param ));
158                                 break;
159                         case HDR_VIA:
160                                 for (via=(struct via_body*)hdr->parsed;via;via=via->next)
161                                 {
162                                         len+=ROUND4(sizeof(struct via_body));
163                                         /*via param*/
164                                         for(prm=via->param_lst;prm;prm=prm->next)
165                                                 len+=ROUND4(sizeof(struct via_param ));
166                                 }
167                                 break;
168                         case HDR_PROXYAUTH:
169                                 /* we frequently parse this HF but don't use it in TM --
170                                    just keep silent about it
171                                 */
172                                 break;
173                         default:
174                                 if (hdr->parsed) {
175                                         LOG(L_WARN, "WARNING: sip_msg_cloner: "
176                                                 "header body ignored: %d\n", hdr->type );
177                                 }
178                                 break;
179                 }/*switch*/
180         }/*for all headers*/
181
182         /* length of the data lump structures */
183         if (org_msg->first_line.type==SIP_REQUEST)
184                 lump_chain = org_msg->add_rm;
185         else
186                 lump_chain = org_msg->repl_add_rm;
187         while (lump_chain)
188         {
189                 len += lump_len( lump_chain );
190                 lump_tmp = lump_chain->before;
191                 while ( lump_tmp )
192                 {
193                         len += lump_len( lump_tmp );
194                         lump_tmp = lump_tmp->before;
195                 }
196                 lump_tmp = lump_chain->after;
197                 while ( lump_tmp )
198                 {
199                         len += lump_len( lump_tmp );
200                         lump_tmp = lump_tmp->after;
201                 }
202                 lump_chain = lump_chain->next;
203         }
204
205         /*length of reply lump structures*/
206         for(rpl_lump=org_msg->reply_lump;rpl_lump;rpl_lump=rpl_lump->next)
207                 len+=rpl_lump->text.len;
208
209         p=(char *)shm_malloc(len);foo=p;
210         if (!p)
211         {
212                 LOG(L_ERR , "ERROR: sip_msg_cloner: cannot allocate memory\n" );
213                 return 0;
214         }
215
216         /* filling up the new structure */
217         new_msg = (struct sip_msg*)p;
218         /* sip msg structure */
219         memcpy( new_msg , org_msg , sizeof(struct sip_msg) );
220         p += ROUND4(sizeof(struct sip_msg));
221         new_msg->add_rm = new_msg->repl_add_rm = 0;
222         /* new_uri */
223         if (org_msg->new_uri.s && org_msg->new_uri.len)
224         {
225                 new_msg->new_uri.s = p;
226                 memcpy( p , org_msg->new_uri.s , org_msg->new_uri.len);
227                 p += ROUND4(org_msg->new_uri.len);
228         }
229         /* message buffers(org and scratch pad) */
230         memcpy( p , org_msg->orig , org_msg->len);
231         /* ZT to be safer */
232         *(p+org_msg->len)=0;
233         new_msg->orig = new_msg->buf = p;
234         p += ROUND4(new_msg->len+1);
235         /* unparsed and eoh pointer */
236         new_msg->unparsed = translate_pointer(new_msg->buf ,org_msg->buf,
237                 org_msg->unparsed );
238         new_msg->eoh = translate_pointer(new_msg->buf,org_msg->buf,org_msg->eoh);
239         /* first line, updating the pointers*/
240         if ( org_msg->first_line.type==SIP_REQUEST )
241         {
242                 new_msg->first_line.u.request.method.s =
243                         translate_pointer( new_msg->buf , org_msg->buf ,
244                         org_msg->first_line.u.request.method.s );
245                 new_msg->first_line.u.request.uri.s =
246                         translate_pointer( new_msg->buf , org_msg->buf ,
247                         org_msg->first_line.u.request.uri.s );
248                 new_msg->first_line.u.request.version.s =
249                         translate_pointer( new_msg->buf , org_msg->buf ,
250                         org_msg->first_line.u.request.version.s );
251         }
252         else if ( org_msg->first_line.type==SIP_REPLY )
253         {
254                 new_msg->first_line.u.reply.version.s =
255                         translate_pointer( new_msg->buf , org_msg->buf ,
256                         org_msg->first_line.u.reply.version.s );
257                 new_msg->first_line.u.reply.status.s =
258                         translate_pointer( new_msg->buf , org_msg->buf ,
259                         org_msg->first_line.u.reply.status.s );
260                 new_msg->first_line.u.reply.reason.s =
261                         translate_pointer( new_msg->buf , org_msg->buf ,
262                         org_msg->first_line.u.reply.reason.s );
263         }
264
265         /*headers list*/
266         new_msg->via1=0;
267         new_msg->via2=0;
268         for( hdr=org_msg->headers,last_hdr=0 ; hdr ; hdr=hdr->next )
269         {
270                 new_hdr = (struct hdr_field*)p;
271                 memcpy(new_hdr, hdr, sizeof(struct hdr_field) );
272                 p += ROUND4(sizeof( struct hdr_field));
273                 new_hdr->name.s = translate_pointer(new_msg->buf, org_msg->buf,
274                         hdr->name.s);
275                 new_hdr->body.s = translate_pointer(new_msg->buf, org_msg->buf,
276                         hdr->body.s);
277                 /* by default, we assume we don't understand this header in TM
278                    and better set it to zero; if we do, we will set a specific
279                    valu in the following switch statement
280                 */
281                 new_hdr->parsed=0;
282
283                 switch (hdr->type)
284                 {
285                         case HDR_VIA:
286                                 /*fprintf(stderr,"prepare to clone via |%.*s|\n",
287                                         via_len((struct via_body*)hdr->parsed),
288                                         via_s((struct via_body*)hdr->parsed,org_msg));*/
289                                 if ( !new_msg->via1 )
290                                 {
291                                         new_msg->h_via1 = new_hdr;
292                                         new_msg->via1 = via_body_cloner(new_msg->buf,
293                                                 org_msg->buf, (struct via_body*)hdr->parsed, &p);
294                                         new_hdr->parsed  = (void*)new_msg->via1;
295                                         /*fprintf(stderr,"setting via1 |%.*s|\n",
296                                                 via_len(new_msg->via1),
297                                                 via_s(new_msg->via1,new_msg));*/
298                                         if ( new_msg->via1->next )
299                                                 new_msg->via2 = new_msg->via1->next;
300                                 }
301                                 else if ( !new_msg->via2 && new_msg->via1 )
302                                 {
303                                         new_msg->h_via2 = new_hdr;
304                                         if ( new_msg->via1->next )
305                                                 new_hdr->parsed = (void*)new_msg->via1->next;
306                                         else{
307                                                 new_msg->via2 = via_body_cloner( new_msg->buf,
308                                                         org_msg->buf, (struct via_body*)hdr->parsed, &p);
309                                                 new_hdr->parsed  = (void*)new_msg->via2;
310                                         }
311                                 }
312                                 else if ( new_msg->via2 && new_msg->via1 )
313                                 {
314                                         new_hdr->parsed =  
315                                                 via_body_cloner( new_msg->buf , org_msg->buf ,
316                                                 (struct via_body*)hdr->parsed , &p);
317                                 }
318                 /*fprintf(stderr," via1 is |%.*s|\n",
319                         via_len(new_msg->via1),
320                         via_s(new_msg->via1,new_msg));*/
321   
322                                 break;
323                         case HDR_CSEQ:
324                                 new_hdr->parsed = p;
325                                 p +=ROUND4(sizeof(struct cseq_body));
326                                 memcpy(new_hdr->parsed, hdr->parsed, sizeof(struct cseq_body));
327                                 ((struct cseq_body*)new_hdr->parsed)->number.s =
328                                         translate_pointer(new_msg->buf ,org_msg->buf,
329                                         ((struct cseq_body*)hdr->parsed)->number.s );
330                                 ((struct cseq_body*)new_hdr->parsed)->method.s =
331                                         translate_pointer(new_msg->buf ,org_msg->buf,
332                                         ((struct cseq_body*)hdr->parsed)->method.s );
333                                 new_msg->cseq = new_hdr;
334                                 break;
335                         case HDR_TO:
336                                 new_hdr->parsed = p;
337                                 p +=ROUND4(sizeof(struct to_body));
338                                 memcpy(new_hdr->parsed, hdr->parsed, sizeof(struct to_body));
339                                 ((struct to_body*)new_hdr->parsed)->body.s =
340                                         translate_pointer( new_msg->buf , org_msg->buf ,
341                                         ((struct to_body*)hdr->parsed)->body.s );
342                                 ((struct to_body*)new_hdr->parsed)->uri.s =
343                                         translate_pointer( new_msg->buf , org_msg->buf ,
344                                         ((struct to_body*)hdr->parsed)->uri.s );
345                                 if ( ((struct to_body*)hdr->parsed)->tag_value.s )
346                                         ((struct to_body*)new_hdr->parsed)->tag_value.s =
347                                                 translate_pointer( new_msg->buf , org_msg->buf ,
348                                                 ((struct to_body*)hdr->parsed)->tag_value.s );
349                                 /*to params*/
350                                 to_prm = ((struct to_body*)(hdr->parsed))->param_lst;
351                                 for(;to_prm;to_prm=to_prm->next)
352                                 {
353                                         /*alloc*/
354                                         new_to_prm = (struct to_param*)p;
355                                         p +=ROUND4(sizeof(struct to_param ));
356                                         /*coping*/
357                                         memcpy( new_to_prm, to_prm, sizeof(struct to_param ));
358                                         ((struct to_body*)new_hdr->parsed)->param_lst = 0;
359                                         new_to_prm->name.s = translate_pointer( new_msg->buf,
360                                                 org_msg->buf , to_prm->name.s );
361                                         new_to_prm->value.s = translate_pointer( new_msg->buf,
362                                                 org_msg->buf , to_prm->value.s );
363                                         /*linking*/
364                                         if ( !((struct to_body*)new_hdr->parsed)->param_lst )
365                                                 ((struct to_body*)new_hdr->parsed)->param_lst
366                                                         = new_to_prm;
367                                         else
368                                                 ((struct to_body*)new_hdr->parsed)->last_param->next
369                                                         = new_to_prm;
370                                         ((struct to_body*)new_hdr->parsed)->last_param
371                                                 = new_to_prm;
372                                 }
373                                 new_msg->to = new_hdr;
374                                 break;
375                         case HDR_CALLID:
376                                 new_msg->callid = new_hdr;
377                                 break;
378                         case HDR_FROM:
379                                 new_msg->from = new_hdr;
380                                 break;
381                         case HDR_CONTACT:
382                                 new_msg->contact = new_hdr;
383                                 break;
384                         case HDR_MAXFORWARDS :
385                                 new_msg->maxforwards = new_hdr;
386                                 break;
387                         case HDR_ROUTE :
388                                 new_msg->route = new_hdr;
389                                 break;
390                         case HDR_RECORDROUTE :
391                                 new_msg->record_route = new_hdr;
392                                 break;
393                         case HDR_CONTENTTYPE :
394                                 new_msg->content_type = new_hdr;
395                                 break;
396                         case HDR_CONTENTLENGTH :
397                                 new_msg->content_length = new_hdr;
398                                 break;
399                         case HDR_AUTHORIZATION :
400                                 new_msg->authorization = new_hdr;
401                                 break;
402                         case HDR_EXPIRES :
403                                 new_msg->expires = new_hdr;
404                                 break;
405                         case HDR_PROXYAUTH :
406                                 new_msg->proxy_auth = new_hdr;
407                                 break;
408                         case HDR_WWWAUTH :
409                                 new_msg->www_auth = new_hdr;
410                                 break;
411                         case HDR_SUPPORTED :
412                                 new_msg->supported = new_hdr;
413                                 break;
414                         case HDR_REQUIRE :
415                                 new_msg->require = new_hdr;
416                                 break;
417                         case HDR_PROXYREQUIRE :
418                                 new_msg->proxy_require = new_hdr;
419                                 break;
420                         case HDR_UNSUPPORTED :
421                                 new_msg->unsupported = new_hdr;
422                                 break;
423                         case HDR_ALLOW :
424                                 new_msg->unsupported = new_hdr; 
425                                 break;
426                 }/*switch*/
427
428                 if ( last_hdr )
429                 {
430                         last_hdr->next = new_hdr;
431                         last_hdr=last_hdr->next;
432                 }
433                 else
434                 {
435                         last_hdr=new_hdr;
436                         new_msg->headers =new_hdr;
437                 }
438                 last_hdr->next = 0;
439                 new_msg->last_header = last_hdr;
440         }
441
442         /* clonning data lump */
443         if (org_msg->first_line.type==SIP_REQUEST) {
444                 lump_chain = org_msg->add_rm;
445                 lump_anchor = &(new_msg->add_rm);
446         }else{
447                 lump_chain = org_msg->repl_add_rm;
448                 lump_anchor = &(new_msg->repl_add_rm);
449         }
450         while (lump_chain)
451         {
452                 lump_clone( (*lump_anchor) , lump_chain , p );
453                 /*before list*/
454                 lump_tmp = lump_chain->before;
455                 lump_anchor2 = &((*lump_anchor)->before);
456                 while ( lump_tmp )
457                 {
458                         lump_clone( (*lump_anchor2) , lump_tmp , p );
459                         lump_anchor2 = &((*lump_anchor2)->before);
460                         lump_tmp = lump_tmp->before;
461                 }
462                 /*after list*/
463                 lump_tmp = lump_chain->after;
464                 lump_anchor2 = &((*lump_anchor)->after);
465                 while ( lump_tmp )
466                 {
467                         lump_clone( (*lump_anchor2) , lump_tmp , p );
468                         lump_anchor2 = &((*lump_anchor2)->after);
469                         lump_tmp = lump_tmp->after;
470                 }
471                 lump_anchor = &((*lump_anchor)->next);
472                 lump_chain = lump_chain->next;
473         }
474
475         /*cloning reply lump structures*/
476         rpl_lump_anchor = &(new_msg->reply_lump);
477         for(rpl_lump=org_msg->reply_lump;rpl_lump;rpl_lump=rpl_lump->next)
478         {
479                 *(rpl_lump_anchor)=(struct lump_rpl*)p;
480                 p+=sizeof( struct lump_rpl );
481                 (*rpl_lump_anchor)->text.len = rpl_lump->text.len;
482                 (*rpl_lump_anchor)->text.s=p;
483                 p+=rpl_lump->text.len;
484                 memcpy((*rpl_lump_anchor)->text.s,rpl_lump->text.s,rpl_lump->text.len);
485                 (*rpl_lump_anchor)->next=0;
486                 rpl_lump_anchor = &((*rpl_lump_anchor)->next);
487         }
488
489         return new_msg;
490 }
491
492
493
494
495