topos: handle return code for parse_headers()
[sip-router] / src / modules / topos / tps_msg.c
1 /**
2  * Copyright (C) 2016 Daniel-Constantin Mierla (asipto.com)
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * This file is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  *
12  * This file is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 /*!
23  * \file
24  * \brief SIP-router topoh ::
25  * \ingroup topoh
26  * Module: \ref topoh
27  */
28
29 #include <string.h>
30
31 #include "../../core/dprint.h"
32 #include "../../core/mem/mem.h"
33 #include "../../core/data_lump.h"
34 #include "../../core/forward.h"
35 #include "../../core/trim.h"
36 #include "../../core/dset.h"
37 #include "../../core/msg_translator.h"
38 #include "../../core/parser/parse_rr.h"
39 #include "../../core/parser/parse_uri.h"
40 #include "../../core/parser/parse_param.h"
41 #include "../../core/parser/parse_from.h"
42 #include "../../core/parser/parse_to.h"
43 #include "../../core/parser/parse_via.h"
44 #include "../../core/parser/contact/parse_contact.h"
45 #include "../../core/parser/parse_refer_to.h"
46 #include "tps_msg.h"
47 #include "tps_storage.h"
48
49 extern int _tps_param_mask_callid;
50
51 str _sr_hname_xbranch = str_init("P-SR-XBranch");
52 str _sr_hname_xuuid = str_init("P-SR-XUID");
53
54 /**
55  *
56  */
57 int tps_skip_rw(char *s, int len)
58 {
59         while(len>0)
60         {
61                 if(s[len-1]==' ' || s[len-1]=='\t' || s[len-1]=='\n' || s[len-1]=='\r'
62                                 || s[len-1]==',')
63                         len--;
64                 else return len;
65         }
66         return 0;
67 }
68
69 /**
70  *
71  */
72 struct via_param *tps_get_via_param(struct via_body *via, str *name)
73 {
74         struct via_param *p;
75         for(p=via->param_lst; p; p=p->next)
76         {
77                 if(p->name.len==name->len
78                                 && strncasecmp(p->name.s, name->s, name->len)==0)
79                         return p;
80         }
81         return NULL;
82 }
83
84 /**
85  *
86  */
87 int tps_get_param_value(str *in, str *name, str *value)
88 {
89         param_t* params = NULL;
90         param_t* p = NULL;
91         param_hooks_t phooks;
92         if (parse_params(in, CLASS_ANY, &phooks, &params)<0)
93                 return -1;
94         for (p = params; p; p=p->next)
95         {
96                 if (p->name.len==name->len
97                                 && strncasecmp(p->name.s, name->s, name->len)==0)
98                 {
99                         *value = p->body;
100                         free_params(params);
101                         return 0;
102                 }
103         }
104
105         if(params) free_params(params);
106         return 1;
107
108 }
109
110 /**
111  *
112  */
113 int tps_remove_headers(sip_msg_t *msg, uint32_t hdr)
114 {
115         struct hdr_field *hf;
116         struct lump* l;
117
118         if(parse_headers(msg, HDR_EOH_F, 0)<0) {
119                 LM_ERR("failed to parse headers\n");
120                 return -1;
121         }
122         for (hf=msg->headers; hf; hf=hf->next) {
123                 if (hdr!=hf->type)
124                         continue;
125                 l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
126                 if (l==0) {
127                         LM_ERR("failed to remove the header\n");
128                         return -1;
129                 }
130         }
131         return 0;
132 }
133
134 /**
135  *
136  */
137 int tps_add_headers(sip_msg_t *msg, str *hname, str *hbody, int hpos)
138 {
139         struct lump* anchor;
140         str hs;
141
142         if(hname==NULL || hname->len<=0 || hbody==NULL || hbody->len<=0)
143                 return 0;
144
145         if(parse_headers(msg, HDR_EOH_F, 0)<0) {
146                 LM_ERR("failed to parse headers\n");
147                 return -1;
148         }
149
150         if(hpos == 0) { /* append */
151                 /* after last header */
152                 anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
153         } else { /* insert */
154                 /* before first header */
155                 anchor = anchor_lump(msg, msg->headers->name.s - msg->buf, 0, 0);
156         }
157
158         if(anchor == 0) {
159                 LM_ERR("can't get anchor\n");
160                 return -1;
161         }
162
163         hs.len = hname->len + 2 + hbody->len;
164         hs.s  = (char*)pkg_malloc(hs.len + 3);
165         if (hs.s==NULL) {
166                 LM_ERR("no pkg memory left (%.*s - %d)\n",
167                                 hname->len, hname->s, hs.len);
168                 return -1;
169         }
170         memcpy(hs.s, hname->s, hname->len);
171         hs.s[hname->len] = ':';
172         hs.s[hname->len+1] = ' ';
173         memcpy(hs.s + hname->len + 2, hbody->s, hbody->len);
174
175         /* add end of header if not present */
176         if(hs.s[hname->len + 2 + hbody->len - 1]!='\n') {
177                 hs.s[hname->len + 2 + hbody->len] = '\r';
178                 hs.s[hname->len + 2 + hbody->len+1] = '\n';
179                 hs.len += 2;
180         }
181
182         if (insert_new_lump_before(anchor, hs.s, hs.len, 0) == 0) {
183                 LM_ERR("can't insert lump\n");
184                 pkg_free(hs.s);
185                 return -1;
186         }
187
188         return 0;
189 }
190
191 /**
192  *
193  */
194 int tps_get_uri_param_value(str *uri, str *name, str *value)
195 {
196         struct sip_uri puri;
197
198         memset(value, 0, sizeof(str));
199         if(parse_uri(uri->s, uri->len, &puri)<0)
200                 return -1;
201         return tps_get_param_value(&puri.params, name, value);
202 }
203
204 /**
205  *
206  */
207 int tps_get_uri_type(str *uri, int *mode, str *value)
208 {
209         struct sip_uri puri;
210         int ret;
211         str r2 = {"r2", 2};
212
213         memset(value, 0, sizeof(str));
214         *mode = 0;
215         if(parse_uri(uri->s, uri->len, &puri)<0)
216                 return -1;
217
218         LM_DBG("PARAMS [%.*s]\n", puri.params.len, puri.params.s);
219
220         if(check_self(&puri.host, puri.port_no, 0)==1)
221         {
222                 /* myself -- matched on all protos */
223                 ret = tps_get_param_value(&puri.params, &r2, value);
224                 if(ret<0)
225                         return -1;
226                 if(ret==1) /* not found */
227                         return 0; /* skip */
228                 LM_DBG("VALUE [%.*s]\n",
229                                 value->len, value->s);
230                 if(value->len==2 && strncasecmp(value->s, "on", 2)==0)
231                         *mode = 1;
232                 memset(value, 0, sizeof(str));
233                 return 0; /* skip */
234         }
235         /* not myself & not mask ip */
236         return 1; /* encode */
237 }
238
239 /**
240  *
241  */
242 char* tps_msg_update(sip_msg_t *msg, unsigned int *olen)
243 {
244         struct dest_info dst;
245
246         init_dest_info(&dst);
247         dst.proto = PROTO_UDP;
248         return build_req_buf_from_sip_req(msg,
249                         olen, &dst, BUILD_NO_LOCAL_VIA|BUILD_NO_VIA1_UPDATE);
250 }
251
252 /**
253  *
254  */
255 int tps_skip_msg(sip_msg_t *msg)
256 {
257         if (msg->cseq==NULL || get_cseq(msg)==NULL) {
258                 LM_WARN("Invalid/Unparsed CSeq in message. Skipping.");
259                 return 1;
260         }
261
262         if((get_cseq(msg)->method_id)&(METHOD_REGISTER|METHOD_PUBLISH))
263                 return 1;
264
265         return 0;
266 }
267
268 /**
269  *
270  */
271 int tps_dlg_detect_direction(sip_msg_t *msg, tps_data_t *ptsd,
272                 uint32_t *direction)
273 {
274         str ftag = {0, 0};
275         /* detect direction - get from-tag */
276         if(parse_from_header(msg)<0 || msg->from==NULL) {
277                 LM_ERR("failed getting 'from' header!\n");
278                 goto error;
279         }
280         ftag = get_from(msg)->tag_value;
281
282         if(ptsd->a_tag.len!=ftag.len) {
283                 *direction = TPS_DIR_UPSTREAM;
284         } else {
285                 if(memcmp(ptsd->a_tag.s, ftag.s, ftag.len)==0) {
286                         *direction = TPS_DIR_DOWNSTREAM;
287                 } else {
288                         *direction = TPS_DIR_UPSTREAM;
289                 }
290         }
291         return 0;
292
293 error:
294         return -1;
295 }
296
297 /**
298  *
299  */
300 int tps_dlg_message_update(sip_msg_t *msg, tps_data_t *ptsd)
301 {
302         if(parse_sip_msg_uri(msg)<0) {
303                 LM_ERR("failed to parse r-uri\n");
304                 return -1;
305         }
306         if(msg->parsed_uri.user.len<10) {
307                 LM_DBG("not an expected user format\n");
308                 return 1;
309         }
310         if(memcmp(msg->parsed_uri.user.s, "atpsh-", 6)==0) {
311                 ptsd->a_uuid = msg->parsed_uri.user;
312                 return 0;
313         }
314         if(memcmp(msg->parsed_uri.user.s, "btpsh-", 6)==0) {
315                 ptsd->a_uuid = msg->parsed_uri.user;
316                 ptsd->b_uuid = msg->parsed_uri.user;
317                 return 0;
318         }
319         LM_DBG("not an expected user prefix\n");
320
321         return 1;
322 }
323
324 /**
325  *
326  */
327 int tps_pack_message(sip_msg_t *msg, tps_data_t *ptsd)
328 {
329         hdr_field_t *hdr;
330         via_body_t *via;
331         rr_t *rr;
332         int i;
333         int vlen;
334         int r2;
335         int isreq;
336
337         if(ptsd->cp==NULL) {
338                 ptsd->cp = ptsd->cbuf;
339         }
340
341         i = 0;
342         for(hdr=msg->h_via1; hdr; hdr=next_sibling_hdr(hdr)) {
343                 for(via=(struct via_body*)hdr->parsed; via; via=via->next) {
344                         i++;
345                         vlen = tps_skip_rw(via->name.s, via->bsize);
346                         if(ptsd->cp + vlen + 2 >= ptsd->cbuf + TPS_DATA_SIZE) {
347                                 LM_ERR("no more spage to pack via headers\n");
348                                 return -1;
349                         }
350                         if(i>1) {
351                                 *ptsd->cp = ',';
352                                 ptsd->cp++;
353                                 if(i>2) {
354                                         ptsd->x_via2.len++;
355                                 }
356                         }
357                         memcpy(ptsd->cp, via->name.s, vlen);
358                         if(i==1) {
359                                 ptsd->x_via1.s = ptsd->cp;
360                                 ptsd->x_via1.len = vlen;
361                                 if(via->branch!=NULL) {
362                                         ptsd->x_vbranch1.s = ptsd->x_via1.s + (via->branch->value.s - via->name.s);
363                                         ptsd->x_vbranch1.len = via->branch->value.len;
364                                 }
365                         } else {
366                                 if(i==2) {
367                                         ptsd->x_via2.s = ptsd->cp;
368                                 }
369                                 ptsd->x_via2.len += vlen;
370                         }
371                         ptsd->cp += vlen;
372                 }
373         }
374         LM_DBG("compacted headers - x_via1: [%.*s](%d) - x_via2: [%.*s](%d)"
375                         " - x_vbranch1: [%.*s](%d)\n",
376                         ptsd->x_via1.len, ZSW(ptsd->x_via1.s), ptsd->x_via1.len,
377                         ptsd->x_via2.len, ZSW(ptsd->x_via2.s), ptsd->x_via2.len,
378                         ptsd->x_vbranch1.len, ZSW(ptsd->x_vbranch1.s), ptsd->x_vbranch1.len);
379
380         ptsd->a_rr.len = 0;
381         ptsd->s_rr.len = 0;
382         i = 0;
383         r2 = 0;
384         isreq = (msg->first_line.type==SIP_REQUEST)?1:0;
385         for(hdr=msg->record_route; hdr; hdr=next_sibling_hdr(hdr)) {
386                 if (parse_rr(hdr) < 0) {
387                         LM_ERR("failed to parse RR\n");
388                         return -1;
389                 }
390
391                 for(rr =(rr_t*)hdr->parsed; rr; rr=rr->next) {
392                         i++;
393                         if(ptsd->cp + rr->nameaddr.uri.len + 4 >= ptsd->cbuf + TPS_DATA_SIZE) {
394                                 LM_ERR("no more spage to pack rr headers\n");
395                                 return -1;
396                         }
397                         if(isreq==1) {
398                                 /* sip request - get a+s-side record route */
399                                 if(i>1) {
400                                         if(i==2 &&r2==0) {
401                                                 ptsd->s_rr.len = ptsd->a_rr.len;
402                                         }
403                                         if(i==3 &&r2==1) {
404                                                 ptsd->s_rr.len = ptsd->a_rr.len;
405                                         }
406                                         *ptsd->cp = ',';
407                                         ptsd->cp++;
408                                         ptsd->a_rr.len++;
409                                 }
410                                 *ptsd->cp = '<';
411                                 if(i==1) {
412                                         ptsd->a_rr.s = ptsd->cp;
413                                         ptsd->s_rr.s = ptsd->cp;
414                                 }
415                                 if(i==2 && r2==0) {
416                                         ptsd->a_rr.s = ptsd->cp;
417                                         ptsd->a_rr.len = 0;
418                                 }
419                                 if(i==3 && r2==1) {
420                                         ptsd->a_rr.s = ptsd->cp;
421                                         ptsd->a_rr.len = 0;
422                                 }
423
424                                 ptsd->cp++;
425                                 ptsd->a_rr.len++;
426
427                                 memcpy(ptsd->cp, rr->nameaddr.uri.s, rr->nameaddr.uri.len);
428                                 if(i==1) {
429                                         ptsd->bs_contact.s = ptsd->cp;
430                                         ptsd->bs_contact.len = rr->nameaddr.uri.len;
431                                         if(_strnstr(ptsd->bs_contact.s, ";r2=on",
432                                                                 ptsd->bs_contact.len)==0) {
433                                                 LM_DBG("single record routing by proxy\n");
434                                                 ptsd->as_contact.s = ptsd->cp;
435                                                 ptsd->as_contact.len = rr->nameaddr.uri.len;
436                                         } else {
437                                                 r2 = 1;
438                                         }
439                                 } else {
440                                         if(i==2 && ptsd->as_contact.len==0) {
441                                                 LM_DBG("double record routing by proxy\n");
442                                                 ptsd->as_contact.s = ptsd->cp;
443                                                 ptsd->as_contact.len = rr->nameaddr.uri.len;
444                                         }
445                                 }
446                                 ptsd->a_rr.len += rr->nameaddr.uri.len;
447                                 ptsd->cp += rr->nameaddr.uri.len;
448                                 *ptsd->cp = '>';
449                                 ptsd->cp++;
450                                 ptsd->a_rr.len++;
451                         } else {
452                                 /* sip response - get b-side record route */
453                                 if(i==1) {
454                                         ptsd->b_rr.s = ptsd->cp;
455                                 }
456                                 if(i>1) {
457                                         *ptsd->cp = ',';
458                                         ptsd->cp++;
459                                         ptsd->b_rr.len++;
460                                 }
461                                 *ptsd->cp = '<';
462                                 ptsd->cp++;
463                                 ptsd->b_rr.len++;
464                                 memcpy(ptsd->cp, rr->nameaddr.uri.s, rr->nameaddr.uri.len);
465                                 ptsd->cp += rr->nameaddr.uri.len;
466                                 ptsd->b_rr.len += rr->nameaddr.uri.len;
467                                 *ptsd->cp = '>';
468                                 ptsd->cp++;
469                                 ptsd->b_rr.len++;
470                         }
471                 }
472         }
473         if(isreq==1) {
474                 if(i==1) {
475                         ptsd->s_rr.len = ptsd->a_rr.len;
476                         ptsd->a_rr.len = 0;
477                 }
478                 if(i==2 && r2==1) {
479                         ptsd->s_rr.len = ptsd->a_rr.len;
480                         ptsd->a_rr.len = 0;
481                 }
482         }
483         LM_DBG("compacted headers - a_rr: [%.*s](%d) - b_rr: [%.*s](%d)"
484                         " - s_rr: [%.*s](%d)\n",
485                         ptsd->a_rr.len, ZSW(ptsd->a_rr.s), ptsd->a_rr.len,
486                         ptsd->b_rr.len, ZSW(ptsd->b_rr.s), ptsd->b_rr.len,
487                         ptsd->s_rr.len, ZSW(ptsd->s_rr.s), ptsd->s_rr.len);
488         LM_DBG("compacted headers - as_contact: [%.*s](%d) - bs_contact: [%.*s](%d)\n",
489                         ptsd->as_contact.len, ZSW(ptsd->as_contact.s), ptsd->as_contact.len,
490                         ptsd->bs_contact.len, ZSW(ptsd->bs_contact.s), ptsd->bs_contact.len);
491         ptsd->x_rr = ptsd->a_rr;
492         ptsd->s_method_id = get_cseq(msg)->method_id;
493         return 0;
494 }
495
496
497 /**
498  *
499  */
500 int tps_reinsert_via(sip_msg_t *msg, tps_data_t *ptsd, str *hbody)
501 {
502         str hname = str_init("Via");
503
504         if(tps_add_headers(msg, &hname, hbody, 1)<0) {
505                 return -1;
506         }
507
508         return 0;
509 }
510
511 /**
512  *
513  */
514 int tps_reinsert_contact(sip_msg_t *msg, tps_data_t *ptsd, str *hbody)
515 {
516         str hname = str_init("Contact");
517
518         if(tps_add_headers(msg, &hname, hbody, 0)<0) {
519                 return -1;
520         }
521
522         return 0;
523 }
524
525 /**
526  *
527  */
528 int tps_remove_name_headers(sip_msg_t *msg, str *hname)
529 {
530         hdr_field_t *hf;
531         struct lump* l;
532         for (hf=msg->headers; hf; hf=hf->next)
533         {
534                 if (hf->name.len==hname->len
535                                 && strncasecmp(hf->name.s, hname->s,
536                                         hname->len)==0)
537                 {
538                         l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
539                         if (l==0) {
540                                 LM_ERR("unable to delete header [%.*s]\n",
541                                                 hname->len, hname->s);
542                                 return -1;
543                         }
544                         return 0;
545                 }
546         }
547         return 0;
548 }
549
550 /**
551  *
552  */
553 int tps_reappend_via(sip_msg_t *msg, tps_data_t *ptsd, str *hbody)
554 {
555         str hname = str_init("Via");
556
557         if(tps_add_headers(msg, &hname, hbody, 0)<0) {
558                 return -1;
559         }
560
561         return 0;
562 }
563
564 /**
565  *
566  */
567 int tps_append_xbranch(sip_msg_t *msg, str *hbody)
568 {
569         if(tps_add_headers(msg, &_sr_hname_xbranch, hbody, 0)<0) {
570                 LM_ERR("failed to add xbranch header [%.*s]/%d\n",
571                                 hbody->len, hbody->s, hbody->len);
572                 return -1;
573         }
574
575         return 0;
576 }
577
578 /**
579  *
580  */
581 int tps_remove_xbranch(sip_msg_t *msg)
582 {
583         return tps_remove_name_headers(msg, &_sr_hname_xbranch);
584 }
585
586 /**
587  *
588  */
589 int tps_get_xbranch(sip_msg_t *msg, str *hbody)
590 {
591         hdr_field_t *hf;
592         if(parse_headers(msg, HDR_EOH_F, 0)<0) {
593                 return -1;
594         }
595
596         for (hf=msg->headers; hf; hf=hf->next)
597         {
598                 if(_sr_hname_xbranch.len==hf->name.len
599                                 && strncasecmp(_sr_hname_xbranch.s, hf->name.s,
600                                         hf->name.len)==0) {
601                         break;
602                 }
603         }
604         if(hf!=NULL) {
605                 *hbody = hf->body;
606                 return 0;
607         }
608         return -1;
609 }
610
611
612 /**
613  *
614  */
615 int tps_append_xuuid(sip_msg_t *msg, str *hbody)
616 {
617         if(tps_add_headers(msg, &_sr_hname_xuuid, hbody, 0)<0) {
618                 LM_ERR("failed to add xuuid header [%.*s]/%d\n",
619                                 hbody->len, hbody->s, hbody->len);
620                 return -1;
621         }
622
623         return 0;
624 }
625
626 /**
627  *
628  */
629 int tps_remove_xuuid(sip_msg_t *msg)
630 {
631         return tps_remove_name_headers(msg, &_sr_hname_xuuid);
632 }
633
634 /**
635  *
636  */
637 int tps_get_xuuid(sip_msg_t *msg, str *hbody)
638 {
639         hdr_field_t *hf;
640         if(parse_headers(msg, HDR_EOH_F, 0)<0) {
641                 return -1;
642         }
643
644         for (hf=msg->headers; hf; hf=hf->next)
645         {
646                 if(_sr_hname_xuuid.len==hf->name.len
647                                 && strncasecmp(_sr_hname_xuuid.s, hf->name.s,
648                                         hf->name.len)==0) {
649                         break;
650                 }
651         }
652         if(hf!=NULL) {
653                 *hbody = hf->body;
654                 return 0;
655         }
656         return -1;
657 }
658
659 /**
660  *
661  */
662 int tps_reappend_rr(sip_msg_t *msg, tps_data_t *ptsd, str *hbody)
663 {
664         str hname = str_init("Record-Route");
665
666         if(tps_add_headers(msg, &hname, hbody, 0)<0) {
667                 return -1;
668         }
669
670         return 0;
671 }
672
673 /**
674  *
675  */
676 int tps_reappend_route(sip_msg_t *msg, tps_data_t *ptsd, str *hbody, int rev)
677 {
678         str hname = str_init("Route");
679         int i;
680         int c;
681         str sb;
682
683         if(hbody==NULL || hbody->s==NULL || hbody->len<=0 || hbody->s[0]=='\0')
684                 return 0;
685
686         if(rev==1) {
687                 c = 0;
688                 sb.len = 1;
689                 for(i=hbody->len-2; i>=0; i--) {
690                         if(hbody->s[i]==',') {
691                                 c = 1;
692                                 if(sb.len>0) {
693                                         sb.s = hbody->s + i + 1;
694                                         if(sb.s[sb.len-1]==',') sb.len--;
695                                         if(tps_add_headers(msg, &hname, &sb, 0)<0) {
696                                                 return -1;
697                                         }
698                                 }
699                                 sb.len = 0;
700                         }
701                         sb.len++;
702                 }
703                 if(c==1) {
704                         if(sb.len>0) {
705                                 sb.s = hbody->s;
706                                 if(sb.s[sb.len-1]==',') sb.len--;
707                                 if(tps_add_headers(msg, &hname, &sb, 0)<0) {
708                                         return -1;
709                                 }
710                         }
711                         return 0;
712                 }
713         }
714
715         sb = *hbody;
716         if(sb.len>0 && sb.s[sb.len-1]==',') sb.len--;
717         trim_zeros_lr(&sb);
718         trim(&sb);
719         if(sb.len>0 && sb.s[sb.len-1]==',') sb.len--;
720         if(tps_add_headers(msg, &hname, &sb, 0)<0) {
721                 return -1;
722         }
723
724         return 0;
725 }
726
727 /**
728  *
729  */
730 int tps_request_received(sip_msg_t *msg, int dialog)
731 {
732         tps_data_t mtsd;
733         tps_data_t stsd;
734         str lkey;
735         str nuri;
736         uint32_t direction = TPS_DIR_DOWNSTREAM;
737         int ret;
738
739         LM_DBG("handling incoming request\n");
740
741         if(dialog==0) {
742                 /* nothing to do for initial request */
743                 return 0;
744         }
745
746         memset(&mtsd, 0, sizeof(tps_data_t));
747         memset(&stsd, 0, sizeof(tps_data_t));
748
749         if(tps_pack_message(msg, &mtsd)<0) {
750                 LM_ERR("failed to extract and pack the headers\n");
751                 return -1;
752         }
753
754         ret = tps_dlg_message_update(msg, &mtsd);
755         if(ret<0) {
756                 LM_ERR("failed to update on dlg message\n");
757                 return -1;
758         }
759
760         lkey = msg->callid->body;
761
762         tps_storage_lock_get(&lkey);
763
764         if(tps_storage_load_dialog(msg, &mtsd, &stsd)<0) {
765                 goto error;
766         }
767
768         /* detect direction - via from-tag */
769         if(tps_dlg_detect_direction(msg, &stsd, &direction)<0) {
770                 goto error;
771         }
772         mtsd.direction = direction;
773
774         tps_storage_lock_release(&lkey);
775
776         if(direction == TPS_DIR_UPSTREAM) {
777                 nuri = stsd.a_contact;
778         } else {
779                 nuri = stsd.b_contact;
780         }
781         if(nuri.len>0) {
782                 if(rewrite_uri(msg, &nuri)<0) {
783                         LM_ERR("failed to update r-uri\n");
784                         return -1;
785                 }
786         }
787
788         if(tps_reappend_route(msg, &stsd, &stsd.s_rr,
789                                 (direction==TPS_DIR_UPSTREAM)?0:1)<0) {
790                 LM_ERR("failed to reappend s-route\n");
791                 return -1;
792         }
793         if(direction == TPS_DIR_UPSTREAM) {
794                 if(tps_reappend_route(msg, &stsd, &stsd.a_rr, 0)<0) {
795                         LM_ERR("failed to reappend a-route\n");
796                         return -1;
797                 }
798         } else {
799                 if(tps_reappend_route(msg, &stsd, &stsd.b_rr, 1)<0) {
800                         LM_ERR("failed to reappend b-route\n");
801                         return -1;
802                 }
803         }
804         if(dialog!=0) {
805                 tps_append_xuuid(msg, &stsd.a_uuid);
806         }
807         return 0;
808
809 error:
810         tps_storage_lock_release(&lkey);
811         return -1;
812 }
813
814 /**
815  *
816  */
817 int tps_response_received(sip_msg_t *msg)
818 {
819         tps_data_t mtsd;
820         tps_data_t stsd;
821         tps_data_t btsd;
822         str lkey;
823         uint32_t direction = TPS_DIR_DOWNSTREAM;
824
825         LM_DBG("handling incoming response\n");
826
827         if(msg->first_line.u.reply.statuscode==100) {
828                 /* nothing to do - it should be absorbed */
829                 return 0;
830         }
831
832         memset(&mtsd, 0, sizeof(tps_data_t));
833         memset(&stsd, 0, sizeof(tps_data_t));
834         memset(&btsd, 0, sizeof(tps_data_t));
835
836         lkey = msg->callid->body;
837
838         if(tps_pack_message(msg, &mtsd)<0) {
839                 LM_ERR("failed to extract and pack the headers\n");
840                 return -1;
841         }
842         tps_storage_lock_get(&lkey);
843         if(tps_storage_load_branch(msg, &mtsd, &btsd)<0) {
844                 goto error;
845         }
846         LM_DBG("loaded dialog a_uuid [%.*s]\n",
847                         btsd.a_uuid.len, ZSW(btsd.a_uuid.s));
848         if(tps_storage_load_dialog(msg, &btsd, &stsd)<0) {
849                 goto error;
850         }
851
852         /* detect direction - via from-tag */
853         if(tps_dlg_detect_direction(msg, &stsd, &direction)<0) {
854                 goto error;
855         }
856         mtsd.direction = direction;
857         if(tps_storage_update_branch(msg, &mtsd, &btsd,
858                                 TPS_DBU_CONTACT|TPS_DBU_RPLATTRS)<0) {
859                 goto error;
860         }
861         if(tps_storage_update_dialog(msg, &mtsd, &stsd, TPS_DBU_RPLATTRS)<0) {
862                 goto error;
863         }
864         tps_storage_lock_release(&lkey);
865
866         tps_reappend_via(msg, &btsd, &btsd.x_via);
867         tps_reappend_rr(msg, &btsd, &btsd.s_rr);
868         tps_reappend_rr(msg, &btsd, &btsd.x_rr);
869         tps_append_xbranch(msg, &mtsd.x_vbranch1);
870
871         return 0;
872
873 error:
874         tps_storage_lock_release(&lkey);
875         return -1;
876 }
877
878 /**
879  *
880  */
881 int tps_request_sent(sip_msg_t *msg, int dialog, int local)
882 {
883         tps_data_t mtsd;
884         tps_data_t btsd;
885         tps_data_t stsd;
886         tps_data_t *ptsd;
887         str lkey;
888         str xuuid;
889         uint32_t direction = TPS_DIR_DOWNSTREAM;
890
891         LM_DBG("handling outgoing request\n");
892
893         memset(&mtsd, 0, sizeof(tps_data_t));
894         memset(&btsd, 0, sizeof(tps_data_t));
895         memset(&stsd, 0, sizeof(tps_data_t));
896         ptsd = &mtsd;
897
898         if(tps_pack_message(msg, &mtsd)<0) {
899                 LM_ERR("failed to extract and pack the headers\n");
900                 return -1;
901         }
902
903         if(dialog!=0) {
904                 if(tps_get_xuuid(msg, &xuuid)<0) {
905                         LM_DBG("no x-uuid header - nothing to do\n");
906                         return 0;
907                 }
908                 mtsd.a_uuid = xuuid;
909                 tps_remove_xuuid(msg);
910         }
911
912         lkey = msg->callid->body;
913
914         tps_storage_lock_get(&lkey);
915
916         if(tps_storage_load_branch(msg, &mtsd, &btsd)!=0) {
917                 if(tps_storage_record(msg, ptsd, dialog)<0) {
918                         goto error;
919                 }
920         } else {
921                 ptsd = &btsd;
922         }
923
924         if(dialog!=0) {
925                 if(tps_storage_load_dialog(msg, &mtsd, &stsd)==0) {
926                         ptsd = &stsd;
927                 }
928                 /* detect direction - via from-tag */
929                 if(tps_dlg_detect_direction(msg, &stsd, &direction)<0) {
930                         goto error;
931                 }
932                 mtsd.direction = direction;
933         }
934
935         /* local generated requests */
936         if(local) {
937                 /* ACK and CANCEL go downstream */
938                 if(get_cseq(msg)->method_id==METHOD_ACK
939                                 || get_cseq(msg)->method_id==METHOD_CANCEL
940                                 || local==2) {
941                         // ts_mask_callid(&msg);
942                         goto done;
943                 } else {
944                         /* should be for upstream */
945                         goto done;
946                 }
947         }
948
949         tps_remove_headers(msg, HDR_RECORDROUTE_T);
950         tps_remove_headers(msg, HDR_CONTACT_T);
951         tps_remove_headers(msg, HDR_VIA_T);
952
953         tps_reinsert_via(msg, &mtsd, &mtsd.x_via1);
954         if(direction==TPS_DIR_UPSTREAM) {
955                 tps_reinsert_contact(msg, ptsd, &ptsd->as_contact);
956         } else {
957                 tps_reinsert_contact(msg, ptsd, &ptsd->bs_contact);
958         }
959
960         if(dialog!=0) {
961                 tps_storage_end_dialog(msg, &mtsd, ptsd);
962         }
963         if(tps_storage_update_dialog(msg, &mtsd, &stsd, TPS_DBU_CONTACT)<0) {
964                 goto error;
965         }
966
967 done:
968         tps_storage_lock_release(&lkey);
969         return 0;
970
971 error:
972         tps_storage_lock_release(&lkey);
973         return -1;
974 }
975
976 /**
977  *
978  */
979 int tps_response_sent(sip_msg_t *msg)
980 {
981         tps_data_t mtsd;
982         tps_data_t stsd;
983         tps_data_t btsd;
984         str lkey;
985         uint32_t direction = TPS_DIR_UPSTREAM;
986         str xvbranch = {0, 0};
987
988         LM_DBG("handling outgoing response\n");
989
990         memset(&mtsd, 0, sizeof(tps_data_t));
991         memset(&stsd, 0, sizeof(tps_data_t));
992         memset(&btsd, 0, sizeof(tps_data_t));
993
994         if(tps_get_xbranch(msg, &xvbranch)<0) {
995                 LM_DBG("no x-branch header - nothing to do\n");
996                 return 0;
997         }
998
999         if(tps_pack_message(msg, &mtsd)<0) {
1000                 LM_ERR("failed to extract and pack the headers\n");
1001                 return -1;
1002         }
1003         mtsd.x_vbranch1 = xvbranch;
1004         tps_remove_xbranch(msg);
1005
1006         if(get_cseq(msg)->method_id==METHOD_MESSAGE) {
1007                 tps_remove_headers(msg, HDR_RECORDROUTE_T);
1008                 tps_remove_headers(msg, HDR_CONTACT_T);
1009                 return 0;
1010         }
1011
1012         lkey = msg->callid->body;
1013
1014         tps_storage_lock_get(&lkey);
1015         if(tps_storage_load_branch(msg, &mtsd, &btsd)<0) {
1016                 goto error;
1017         }
1018         LM_DBG("loaded branch a_uuid [%.*s]\n",
1019                         btsd.a_uuid.len, ZSW(btsd.a_uuid.s));
1020         if(tps_storage_load_dialog(msg, &btsd, &stsd)<0) {
1021                 goto error;
1022         }
1023         tps_storage_lock_release(&lkey);
1024
1025         /* detect direction - via from-tag */
1026         if(tps_dlg_detect_direction(msg, &stsd, &direction)<0) {
1027                 goto error1;
1028         }
1029         mtsd.direction = direction;
1030
1031         tps_remove_headers(msg, HDR_RECORDROUTE_T);
1032         tps_remove_headers(msg, HDR_CONTACT_T);
1033
1034         if(direction==TPS_DIR_DOWNSTREAM) {
1035                 tps_reinsert_contact(msg, &stsd, &stsd.as_contact);
1036         } else {
1037                 tps_reinsert_contact(msg, &stsd, &stsd.bs_contact);
1038         }
1039
1040         tps_reappend_rr(msg, &btsd, &btsd.x_rr);
1041         if(tps_storage_update_dialog(msg, &mtsd, &stsd, TPS_DBU_CONTACT)<0) {
1042                 goto error1;
1043         }
1044         return 0;
1045
1046 error:
1047         tps_storage_lock_release(&lkey);
1048 error1:
1049         return -1;
1050 }