4 * Copyright (C) 2001-2003 FhG Fokus
6 * This file is part of Kamailio, a free SIP server.
8 * Kamailio is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
13 * Kamailio is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 #include "../../core/comp_defs.h"
30 #include "../../core/hash_func.h"
31 #include "../../core/globals.h"
33 #include "../../core/dprint.h"
34 #include "../../core/config.h"
35 #include "../../core/parser/parser_f.h"
36 #include "../../core/parser/parse_to.h"
37 #include "../../core/ut.h"
38 #include "../../core/srapi.h"
39 #include "../../core/parser/msg_parser.h"
40 #include "../../core/parser/contact/parse_contact.h"
41 #include "lw_parser.h"
42 #include "t_msgbuilder.h"
44 #ifdef USE_DNS_FAILOVER
45 #include "../../core/dns_cache.h"
46 #include "../../core/cfg_core.h" /* cfg_get(core, core_cfg, use_dns_failover) */
50 /* convenience macros */
51 #define memapp(_d,_s,_len) \
53 memcpy((_d),(_s),(_len));\
58 /* Build a local request based on a previous request; main
59 * customers of this function are local ACK and local CANCEL
61 char *build_local(struct cell *Trans,unsigned int branch,
62 unsigned int *len, char *method, int method_len, str *to
63 #ifdef CANCEL_REASON_SUPPORT
64 , struct cancel_reason* reason
65 #endif /* CANCEL_REASON_SUPPORT */
68 char *cancel_buf, *p, *via;
70 struct hdr_field *hdr;
71 char branch_buf[MAX_BRANCH_PARAM_LEN];
76 #ifdef CANCEL_REASON_SUPPORT
77 int reason_len, code_len;
78 struct hdr_field *reas1, *reas_last;
79 #endif /* CANCEL_REASON_SUPPORT */
85 /* method, separators, version: "CANCEL sip:p2@iptel.org SIP/2.0" */
86 *len=SIP_VERSION_LEN + method_len + 2 /* spaces */ + CRLF_LEN;
87 *len+=Trans->uac[branch].uri.len;
90 if (!t_calc_branch(Trans, branch,
91 branch_buf, &branch_len ))
93 branch_str.s=branch_buf;
94 branch_str.len=branch_len;
95 set_hostport(&hp, (is_local(Trans))?0:(Trans->uas.request));
97 if (!is_local(Trans) && ((Trans->uas.request->rcv.proto==PROTO_TCP)
99 || (Trans->uas.request->rcv.proto==PROTO_TLS)
102 if ((via_id.s=id_builder(Trans->uas.request,
103 (unsigned int*)&via_id.len))==0){
104 LM_ERR("id builder failed\n");
105 /* try to continue without id */
109 via=via_builder(&via_len, &Trans->uac[branch].request.dst,
110 &branch_str, via_id.s?&via_id:0 , &hp );
112 /* via_id.s not needed anylonger => free it */
120 LM_ERR("no via header got from builder\n");
125 *len+=Trans->from.len+Trans->callid.len+to->len+
126 +Trans->cseq_n.len+1+method_len+CRLF_LEN+MAXFWD_HEADER_LEN;
129 /* copy'n'paste Route headers */
130 if (!is_local(Trans)) {
131 for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next )
132 if (hdr->type==HDR_ROUTE_T)
137 if (server_signature) {
138 *len += user_agent_hdr.len + CRLF_LEN;
140 /* Content Length, EoM */
141 *len+=CONTENT_LENGTH_LEN+1 + CRLF_LEN;
142 #ifdef CANCEL_REASON_SUPPORT
146 /* compute reason size (if no reason or disabled => reason_len == 0)*/
147 if (reason && reason->cause != CANCEL_REAS_UNKNOWN){
148 if (likely(reason->cause > 0 &&
149 cfg_get(tm, tm_cfg, local_cancel_reason))){
150 /* Reason: SIP;cause=<reason->cause>[;text=<reason->u.text.s>] */
151 reason_len = REASON_PREFIX_LEN + USHORT2SBUF_MAX_LEN +
153 REASON_TEXT_LEN + 1 + reason->u.text.len + 1 : 0) +
155 } else if (likely(reason->cause == CANCEL_REAS_PACKED_HDRS &&
156 !(Trans->flags & T_NO_E2E_CANCEL_REASON))) {
157 reason_len = reason->u.packed_hdrs.len;
158 } else if (reason->cause == CANCEL_REAS_RCVD_CANCEL &&
159 reason->u.e2e_cancel &&
160 !(Trans->flags & T_NO_E2E_CANCEL_REASON)) {
161 /* parse the entire cancel, to get all the Reason headers */
162 if(parse_headers(reason->u.e2e_cancel, HDR_EOH_F, 0)<0) {
163 LM_WARN("failed to parse headers\n");
165 for(hdr=get_hdr(reason->u.e2e_cancel, HDR_REASON_T), reas1=hdr;
166 hdr; hdr=next_sibling_hdr(hdr)) {
167 /* hdr->len includes CRLF */
168 reason_len += hdr->len;
171 } else if (unlikely(reason->cause < CANCEL_REAS_MIN))
172 LM_BUG("unhandled reason cause %d\n", reason->cause);
175 #endif /* CANCEL_REASON_SUPPORT */
176 *len+= CRLF_LEN; /* end of msg. */
178 cancel_buf=shm_malloc( *len+1 );
180 LM_ERR("cannot allocate memory\n");
185 append_str( p, method, method_len );
186 append_str( p, " ", 1 );
187 append_str( p, Trans->uac[branch].uri.s, Trans->uac[branch].uri.len);
188 append_str( p, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN );
191 append_str(p,via,via_len);
194 append_str( p, Trans->from.s, Trans->from.len );
195 append_str( p, Trans->callid.s, Trans->callid.len );
196 append_str( p, to->s, to->len );
198 append_str( p, Trans->cseq_n.s, Trans->cseq_n.len );
199 append_str( p, " ", 1 );
200 append_str( p, method, method_len );
201 append_str( p, CRLF, CRLF_LEN );
202 append_str( p, MAXFWD_HEADER, MAXFWD_HEADER_LEN );
204 if (!is_local(Trans)) {
205 for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next )
206 if(hdr->type==HDR_ROUTE_T) {
207 append_str(p, hdr->name.s, hdr->len );
211 /* User Agent header */
212 if (server_signature) {
213 append_str(p, user_agent_hdr.s, user_agent_hdr.len );
214 append_str(p, CRLF, CRLF_LEN );
217 append_str(p, CONTENT_LENGTH "0" CRLF, CONTENT_LENGTH_LEN + 1 + CRLF_LEN);
218 #ifdef CANCEL_REASON_SUPPORT
219 /* add reason if needed */
221 if (likely(reason->cause > 0)) {
222 append_str(p, REASON_PREFIX, REASON_PREFIX_LEN);
223 code_len=ushort2sbuf(reason->cause, p,
224 *len-(int)(p-cancel_buf));
225 if (unlikely(code_len==0))
226 LM_BUG("not enough space to write reason code");
228 if (reason->u.text.s){
229 append_str(p, REASON_TEXT, REASON_TEXT_LEN);
231 append_str(p, reason->u.text.s, reason->u.text.len);
234 append_str(p, CRLF, CRLF_LEN);
235 } else if (likely(reason->cause == CANCEL_REAS_PACKED_HDRS)) {
236 append_str(p, reason->u.packed_hdrs.s, reason->u.packed_hdrs.len);
237 } else if (reason->cause == CANCEL_REAS_RCVD_CANCEL) {
238 for(hdr=reas1; hdr; hdr=next_sibling_hdr(hdr)) {
239 /* hdr->len includes CRLF */
240 append_str(p, hdr->name.s, hdr->len);
241 if (likely(hdr==reas_last))
246 #endif /* CANCEL_REASON_SUPPORT */
247 append_str(p, CRLF, CRLF_LEN); /* msg. end */
258 /* Re-parsing version of build_local() function:
259 * it builds a local CANCEL or ACK (for non-200 response) request based on
260 * the previous INVITE which was sent out.
262 * Can not be used to build other type of requests!
264 char *build_local_reparse(struct cell *Trans,unsigned int branch,
265 unsigned int *len, char *method, int method_len, str *to
266 #ifdef CANCEL_REASON_SUPPORT
267 , struct cancel_reason *reason
268 #endif /* CANCEL_REASON_SUPPORT */
271 char *invite_buf, *invite_buf_end;
273 char *s, *s1, *d; /* source and destination buffers */
275 enum _hdr_types_t hf_type;
276 int first_via, to_len;
278 #ifdef CANCEL_REASON_SUPPORT
279 int reason_len, code_len;
280 struct hdr_field *reas1, *reas_last, *hdr;
281 #endif /* CANCEL_REASON_SUPPORT */
283 sr_cfgenv_t *cenv = NULL;
285 invite_buf = Trans->uac[branch].request.buffer;
286 invite_len = Trans->uac[branch].request.buffer_len;
288 if (!invite_buf || !invite_len) {
289 LM_ERR("INVITE is missing\n");
292 if ((*invite_buf != 'I') && (*invite_buf != 'i')) {
293 LM_ERR("trying to build with local reparse"
294 " for a non-INVITE request?\n");
298 #ifdef CANCEL_REASON_SUPPORT
302 /* compute reason size (if no reason or disabled => reason_len == 0)*/
303 if (reason && reason->cause != CANCEL_REAS_UNKNOWN){
304 if (likely(reason->cause > 0 &&
305 cfg_get(tm, tm_cfg, local_cancel_reason))){
306 /* Reason: SIP;cause=<reason->cause>[;text=<reason->u.text.s>] */
307 reason_len = REASON_PREFIX_LEN + USHORT2SBUF_MAX_LEN +
309 REASON_TEXT_LEN + 1 + reason->u.text.len + 1 : 0) +
311 } else if (likely(reason->cause == CANCEL_REAS_PACKED_HDRS &&
312 !(Trans->flags & T_NO_E2E_CANCEL_REASON))) {
313 reason_len = reason->u.packed_hdrs.len;
314 } else if (reason->cause == CANCEL_REAS_RCVD_CANCEL &&
315 reason->u.e2e_cancel &&
316 !(Trans->flags & T_NO_E2E_CANCEL_REASON)) {
317 /* parse the entire cancel, to get all the Reason headers */
318 if(parse_headers(reason->u.e2e_cancel, HDR_EOH_F, 0)<0) {
319 LM_WARN("failed to parse headers\n");
321 for(hdr=get_hdr(reason->u.e2e_cancel, HDR_REASON_T), reas1=hdr;
322 hdr; hdr=next_sibling_hdr(hdr)) {
323 /* hdr->len includes CRLF */
324 reason_len += hdr->len;
327 } else if (unlikely(reason->cause < CANCEL_REAS_MIN))
328 LM_BUG("unhandled reason cause %d\n", reason->cause);
330 #endif /* CANCEL_REASON_SUPPORT */
332 invite_buf_end = invite_buf + invite_len;
335 /* Allocate memory for the new message.
336 The new request will be smaller than the INVITE, so the same size is enough.
337 I just extend it with the length of new To HF to be sure.
338 Ugly, but we avoid lots of checks and memory allocations this way */
339 to_len = to ? to->len : 0;
340 #ifdef CANCEL_REASON_SUPPORT
341 cancel_buf_len = invite_len + to_len + reason_len;
343 cancel_buf_len = invite_len + to_len;
344 #endif /* CANCEL_REASON_SUPPORT */
345 cancel_buf = shm_malloc(sizeof(char)*cancel_buf_len);
348 LM_ERR("cannot allocate shared memory\n");
353 /* method name + space */
354 append_str(d, method, method_len);
357 /* skip "INVITE " and copy the rest of the line including CRLF */
360 s = eat_line(s, invite_buf_end - s);
361 append_str(d, s1, s - s1);
363 cenv = sr_cfgenv_get();
365 /* check every header field name,
366 we must exclude and modify some of the headers */
368 while (s < invite_buf_end) {
370 if ((*s == '\n') || (*s == '\r')) {
375 s = lw_get_hf_name(s, invite_buf_end,
381 /* find the method name and replace it */
382 while ((s < invite_buf_end)
383 && ((*s == ':') || (*s == ' ') || (*s == '\t') ||
384 ((*s >= '0') && (*s <= '9')))
386 append_str(d, s1, s - s1);
387 append_str(d, method, method_len);
388 append_str(d, CRLF, CRLF_LEN);
389 s = lw_next_line(s, invite_buf_end);
393 s = lw_next_line(s, invite_buf_end);
396 append_str(d, s1, s - s1);
398 } /* else skip this line, we need olny the first via */
403 /* there is no To tag required, just copy paste
405 s = lw_next_line(s, invite_buf_end);
406 append_str(d, s1, s - s1);
408 /* use the given To HF instead of the original one */
409 append_str(d, to->s, to->len);
410 /* move the pointer to the next line */
411 s = lw_next_line(s, invite_buf_end);
418 case HDR_MAXFORWARDS_T:
420 s = lw_next_line(s, invite_buf_end);
421 append_str(d, s1, s - s1);
425 case HDR_PROXYREQUIRE_T:
427 s = lw_next_line(s, invite_buf_end);
430 case HDR_CONTENTLENGTH_T:
431 /* copy hf name with 0 value */
432 append_str(d, s1, s - s1);
433 append_str(d, ": 0" CRLF, 3 + CRLF_LEN);
434 /* move the pointer to the next line */
435 s = lw_next_line(s, invite_buf_end);
439 /* end of SIP message found */
440 #ifdef CANCEL_REASON_SUPPORT
441 /* add reason if needed */
443 /* if reason_len !=0, no need for any reason enabled
445 if (likely(reason->cause > 0)) {
446 append_str(d, REASON_PREFIX, REASON_PREFIX_LEN);
447 code_len=ushort2sbuf(reason->cause, d,
448 cancel_buf_len-(int)(d-cancel_buf));
449 if (unlikely(code_len==0))
450 LM_BUG("not enough space to write reason code");
452 if (reason->u.text.s){
453 append_str(d, REASON_TEXT, REASON_TEXT_LEN);
455 append_str(d, reason->u.text.s,
459 append_str(d, CRLF, CRLF_LEN);
460 } else if (likely(reason->cause ==
461 CANCEL_REAS_PACKED_HDRS)) {
462 append_str(d, reason->u.packed_hdrs.s,
463 reason->u.packed_hdrs.len);
464 } else if (reason->cause == CANCEL_REAS_RCVD_CANCEL) {
465 for(hdr=reas1; hdr; hdr=next_sibling_hdr(hdr)) {
466 /* hdr->len includes CRLF */
467 append_str(d, hdr->name.s, hdr->len);
468 if (likely(hdr==reas_last))
473 #endif /* CANCEL_REASON_SUPPORT */
474 /* final (end-of-headers) CRLF */
475 append_str(d, CRLF, CRLF_LEN);
476 *len = d - cancel_buf;
477 /* LOG(L_DBG, "DBG: build_local: %.*s\n", *len, cancel_buf); */
481 s = lw_next_line(s, invite_buf_end);
484 /* uac auth headers */
485 if(Trans->uas.request &&
486 (Trans->uas.request->msg_flags & FL_UAC_AUTH)) {
487 if(s1 + cenv->uac_cseq_auth.len + 2 < invite_buf_end) {
488 if(s1[cenv->uac_cseq_auth.len]==':'
489 && strncmp(s1, cenv->uac_cseq_auth.s,
490 cenv->uac_cseq_auth.len)==0) {
492 append_str(d, s1, s - s1);
493 } else if(s1[cenv->uac_cseq_refresh.len]==':'
494 && strncmp(s1, cenv->uac_cseq_refresh.s,
495 cenv->uac_cseq_refresh.len)==0) {
497 append_str(d, s1, s - s1);
502 if(likely(hadded==0)) {
503 if (cfg_get(tm, tm_cfg, ac_extra_hdrs).len
504 && (s1 + cfg_get(tm, tm_cfg, ac_extra_hdrs).len < invite_buf_end)
506 cfg_get(tm, tm_cfg, ac_extra_hdrs).s,
507 cfg_get(tm, tm_cfg, ac_extra_hdrs).len) == 0)) {
508 append_str(d, s1, s - s1);
515 /* HDR_EOH_T was not found in the buffer, the message is corrupt */
516 LM_ERR("HDR_EOH_T was not found\n");
518 shm_free(cancel_buf);
520 LM_ERR("cannot build %.*s request\n", method_len, method);
528 /* 'ptr' above doesn't point to a mem chunk linked to a sip_msg, so it
529 * won't be free'd along with it => it must be free'd "manually" */
535 static inline void free_rte_list(struct rte* list)
549 static inline int calc_routeset_len(struct rte* list, str* contact)
554 if (list || contact) {
555 ret = ROUTE_PREFIX_LEN + CRLF_LEN;
563 ret += ROUTE_SEPARATOR_LEN;
565 ret += ptr->ptr->len;
570 if (list) ret += ROUTE_SEPARATOR_LEN;
571 ret += 2 + contact->len;
579 * Print the route set
581 static inline char* print_rs(char* p, struct rte* list, str* contact)
585 if (list || contact) {
586 memapp(p, ROUTE_PREFIX, ROUTE_PREFIX_LEN);
594 memapp(p, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);
597 memapp(p, ptr->ptr->nameaddr.name.s, ptr->ptr->len);
602 if (list) memapp(p, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);
604 append_str(p, contact->s, contact->len);
608 memapp(p, CRLF, CRLF_LEN);
614 * Parse Contact header field body and extract URI
615 * Does not parse headers !
617 static inline int get_contact_uri(struct sip_msg* msg, str* uri)
622 if (!msg->contact) return 1;
624 if (parse_contact(msg->contact) < 0) {
625 LM_ERR("error while parsing Contact body\n");
629 c = ((contact_body_t*)msg->contact->parsed)->contacts;
632 LM_ERR("empty body or * contact\n");
641 * Extract route set from the message (out of Record-Route, if reply, OR
642 * Route, if request).
643 * The route set is returned into the "UAC-format" (keep order for Rs, reverse
646 static inline int get_uac_rs(sip_msg_t *msg, int is_req, struct rte **rtset)
648 struct hdr_field* ptr;
650 struct rte *t, *head, *old_head;
653 for (ptr = is_req ? msg->route : msg->record_route; ptr; ptr = ptr->next) {
655 case HDR_RECORDROUTE_T:
666 if (parse_rr(ptr) < 0) {
667 LM_ERR("failed to parse Record-/Route HF (%d).\n", ptr->type);
671 p = (rr_t*)ptr->parsed;
673 if (! (t = pkg_malloc(sizeof(struct rte)))) {
674 LM_ERR("out of pkg mem (asked for: %d).\n",
675 (int)sizeof(struct rte));
679 /* in case of requests, the sip_msg structure is free'd before
680 * rte list is evaluated => must do a copy of it */
681 if (duplicate_rr(&new_p, p) < 0) {
683 LM_ERR("failed to duplicate RR");
698 /* harvesting the R/RR HF above inserts at head, which suites RRs (as
699 * they must be reversed, anyway), but not Rs => reverse once more */
704 old_head = old_head->next;
718 static inline unsigned short uri2port(const struct sip_uri *puri)
721 return puri->port_no;
722 } else switch (puri->type) {
725 if (puri->transport_val.len == sizeof("TLS") - 1) {
727 trans = puri->transport_val.s[0] | 0x20; trans <<= 8;
728 trans |= puri->transport_val.s[1] | 0x20; trans <<= 8;
729 trans |= puri->transport_val.s[2] | 0x20;
730 if (trans == 0x746C73) /* t l s */
738 LM_BUG("unexpected URI type %d.\n", puri->type);
744 * Evaluate if next hop is a strict or loose router, by looking at the
745 * retr. buffer of the original INVITE.
747 * orig_inv is a parsed SIP message;
750 * F_RB_NH_LOOSE : next hop was loose router;
751 * F_RB_NH_STRICT: nh is strict;
754 static unsigned long nhop_type(sip_msg_t *orig_inv, rte_t *rtset,
755 const struct dest_info *dst_inv, str *contact)
757 struct sip_uri puri, topr_uri, lastr_uri, inv_ruri, cont_uri;
758 struct ip_addr *uri_ia;
759 union sockaddr_union uri_sau;
760 unsigned int uri_port, dst_port, inv_port, cont_port, lastr_port;
762 #ifdef TM_LOC_ACK_DO_REV_DNS
768 #define PARSE_URI(_str_, _uri_) \
770 /* parse_uri() 0z the puri */ \
771 if (parse_uri((_str_)->s, \
772 (_str_)->len, _uri_) < 0) { \
773 LM_ERR("failed to parse route body '%.*s'.\n", STR_FMT(_str_)); \
778 #define HAS_LR(_rte_) \
780 PARSE_URI(&(_rte_)->ptr->nameaddr.uri, &puri); \
784 #define URI_PORT(_puri_, _port) \
786 if (! (_port = uri2port(_puri_))) \
790 /* examine the easy/fast & positive cases foremost */
792 /* [1] check if 1st route lacks ;lr */
793 LM_DBG("checking lack of ';lr' in 1st route.\n");
795 return F_RB_NH_STRICT;
796 topr_uri = puri; /* save 1st route's URI */
798 /* [2] check if last route shows ;lr */
799 LM_DBG("checking presence of ';lr' in last route.\n");
800 for (last_r = rtset; last_r->next; last_r = last_r->next)
801 /* scroll down to last route */
804 return F_RB_NH_LOOSE;
806 /* [3] 1st route has ;lr -> check if the destination of original INV
807 * equals the address provided by this route; if does -> loose */
808 LM_DBG("checking INVITE's destination against its first route.\n");
809 URI_PORT(&topr_uri, uri_port);
810 if (! (dst_port = su_getport(&dst_inv->to)))
811 return 0; /* not really expected */
812 if (dst_port != uri_port)
813 return F_RB_NH_STRICT;
814 /* if 1st route contains an IP address, comparing it against .dst */
815 if ((uri_ia = str2ip(&topr_uri.host))
816 || (uri_ia = str2ip6(&topr_uri.host))
818 /* we have an IP address in route -> comparison can go swiftly */
819 if (init_su(&uri_sau, uri_ia, uri_port) < 0)
820 return 0; /* not really expected */
821 if (su_cmp(&uri_sau, &dst_inv->to))
822 /* ;lr and sent there */
823 return F_RB_NH_LOOSE;
825 /* ;lr and NOT sent there (probably sent to RURI address) */
826 return F_RB_NH_STRICT;
828 /*if 1st route contains a name, rev resolve the .dst and compare*/
829 LM_INFO("Failed to decode string '%.*s' in route set element as IP"
830 " address. Trying name resolution.\n",STR_FMT(&topr_uri.host));
832 /* TODO: alternatively, rev name and compare against dest. IP. */
833 #ifdef TM_LOC_ACK_DO_REV_DNS
835 su2ip_addr(&ia, (void *)&dst_inv->to);
837 return 0; /* not really expected */
838 if ((he = rev_resolvehost(&ia))) {
839 if ((strlen(he->h_name) == topr_uri.host.len) &&
840 (memcmp(he->h_name, topr_uri.host.s,
841 topr_uri.host.len) == 0))
842 return F_RB_NH_LOOSE;
843 for (alias = he->h_aliases; *alias; alias ++)
844 if ((strlen(*alias) == topr_uri.host.len) &&
845 (memcmp(*alias, topr_uri.host.s,
846 topr_uri.host.len) == 0))
847 return F_RB_NH_LOOSE;
848 return F_RB_NH_STRICT;
850 LM_INFO("failed to resolve address '%s' to a name.\n",
856 LM_WARN("failed to establish with certainty the type of next hop;"
857 " trying an educated guess.\n");
859 /* [4] compare (possibly updated) remote target to original RURI; if
860 * equal, a strict router's address wasn't filled in as RURI -> loose */
861 LM_DBG("checking remote target against INVITE's RURI.\n");
862 PARSE_URI(contact, &cont_uri);
863 PARSE_URI(GET_RURI(orig_inv), &inv_ruri);
864 URI_PORT(&cont_uri, cont_port);
865 URI_PORT(&inv_ruri, inv_port);
866 if ((cont_port == inv_port) && (cont_uri.host.len == inv_ruri.host.len) &&
867 (memcmp(cont_uri.host.s, inv_ruri.host.s, cont_uri.host.len) == 0))
868 return F_RB_NH_LOOSE;
870 /* [5] compare (possibly updated) remote target to last route; if equal,
871 * strict router's address might have been filled as RURI and remote
872 * target appended to route set -> strict */
873 LM_DBG("checking remote target against INVITE's last route.\n");
874 PARSE_URI(&last_r->ptr->nameaddr.uri, &lastr_uri);
875 URI_PORT(&lastr_uri, lastr_port);
876 if ((cont_port == lastr_port) &&
877 (cont_uri.host.len == lastr_uri.host.len) &&
878 (memcmp(cont_uri.host.s, lastr_uri.host.s,
879 lastr_uri.host.len) == 0))
880 return F_RB_NH_STRICT;
882 LM_WARN("failed to establish the type of next hop;"
883 " assuming loose router.\n");
884 return F_RB_NH_LOOSE;
892 * Evaluates the routing elements in locally originated request or reply to
893 * locally originated request.
894 * If original INVITE was in-dialog (had to-tag), it uses the
895 * routes present there (b/c the 2xx for it does not have a RR set, normally).
896 * Otherwise, use the reply (b/c the INVITE does not have yet the complete
899 * @return: negative for failure; out params:
901 * - ruri: RURI to be used in ACK;
902 * - nexthop: where to first send the ACK.
904 * NOTE: assumes rpl's parsed to EOF!
907 static int eval_uac_routing(sip_msg_t *rpl, const struct retr_buf *inv_rb,
908 str* contact, struct rte **list, str *ruri, str *next_hop)
910 sip_msg_t orig_inv, *sipmsg; /* reparse original INVITE */
911 rte_t *t, *prev_t, *rtset = NULL;
914 static size_t chklen;
917 /* parse the retr. buffer */
918 memset(&orig_inv, 0, sizeof(struct sip_msg));
919 orig_inv.buf = inv_rb->buffer;
920 orig_inv.len = inv_rb->buffer_len;
921 LM_DBG("reparsing retransmission buffer of original INVITE:\n%.*s\n",
922 (int)orig_inv.len, orig_inv.buf);
923 if (parse_msg(orig_inv.buf, orig_inv.len, &orig_inv) != 0) {
924 LM_ERR("failed to parse retr buffer (weird!): \n%.*s\n",
925 (int)orig_inv.len, orig_inv.buf);
929 /* check if we need to look at request or reply */
930 if ((parse_headers(&orig_inv, HDR_TO_F, 0) < 0) || (! orig_inv.to)) {
931 /* the bug is at message assembly */
932 LM_BUG("failed to parse INVITE retr. buffer and/or extract 'To' HF:"
933 "\n%.*s\n", (int)orig_inv.len, orig_inv.buf);
936 if (((struct to_body *)orig_inv.to->parsed)->tag_value.len) {
937 LM_DBG("building ACK for in-dialog INVITE (using RS in orig. INV.)\n");
938 if (parse_headers(&orig_inv, HDR_EOH_F, 0) < 0) {
939 LM_BUG("failed to parse INVITE retr. buffer to EOH:"
940 "\n%.*s\n", (int)orig_inv.len, orig_inv.buf);
946 LM_DBG("building ACK for out-of-dialog INVITE (using RS in RR set).\n");
951 /* extract the route set */
952 if (get_uac_rs(sipmsg, is_req, &rtset) < 0) {
953 LM_ERR("failed to extract route set.\n");
957 if (! rtset) { /* No routes */
959 *next_hop = *contact;
960 } else if (! is_req) { /* out of dialog req. */
961 if (parse_uri(rtset->ptr->nameaddr.uri.s, rtset->ptr->nameaddr.uri.len,
963 LM_ERR("failed to parse first route in set.\n");
967 if (puri.lr.s) { /* Next hop is loose router */
969 *next_hop = rtset->ptr->nameaddr.uri;
970 } else { /* Next hop is strict router */
971 *ruri = rtset->ptr->nameaddr.uri;
973 /* consume first route, b/c it will be put in RURI */
979 unsigned long route_flags = inv_rb->flags;
980 LM_DBG("UAC rb flags: 0x%x.\n", (unsigned int)route_flags);
982 switch (route_flags & (F_RB_NH_LOOSE|F_RB_NH_STRICT)) {
984 LM_WARN("calculate_hooks() not called when built the local UAC of "
985 "in-dialog request, or called with empty route set.\n");
986 /* try to figure out what kind of hop is the next one
987 * (strict/loose) by reading the original invite */
988 if ((route_flags = nhop_type(&orig_inv, rtset, &inv_rb->dst,
990 LM_DBG("original request's next hop type evaluated to: 0x%x.\n",
991 (unsigned int)route_flags);
994 LM_ERR("failed to establish what kind of router the next "
1001 *next_hop = rtset->ptr->nameaddr.uri;
1003 case F_RB_NH_STRICT:
1004 /* find ptr to last route body that contains the (possibly) old
1007 for (t = rtset, prev_t = NULL; t->next; prev_t = t, t = t->next)
1009 if ((t->ptr->len == contact->len) &&
1010 (memcmp(t->ptr->nameaddr.name.s, contact->s,
1011 contact->len) == 0)){
1012 /* the remote target didn't update -> keep the whole route set,
1013 * including the last entry */
1016 /* trash last entry and replace with new remote target */
1018 /* compact the rr_t struct along with rte. this way, free'ing
1019 * it can be done along with rte chunk, independent of Route
1020 * header parser's allocator (using pkg/shm) */
1021 chklen = sizeof(struct rte) + sizeof(rr_t);
1022 if (! (t = pkg_malloc(chklen))) {
1023 ERR("out of pkg memory (%d required)\n", (int)chklen);
1024 /* last element was freed, unlink it */
1025 if(prev_t == NULL) {
1026 /* there is only one elem in route set: the remote target */
1029 prev_t->next = NULL;
1034 /* this way, .free_rr is also set to 0 (!!!) */
1035 memset(t, 0, chklen);
1036 ((rr_t *)&t[1])->nameaddr.name = *contact;
1037 ((rr_t *)&t[1])->len = contact->len;
1038 /* chain the new route elem in set */
1040 /* there is only one elem in route set: the remote target */
1046 *ruri = *GET_RURI(&orig_inv); /* reuse original RURI */
1050 /* probably a mem corruption */
1051 LM_BUG("next hop of original request marked as both loose"
1052 " and strict router (buffer: %.*s).\n",
1053 inv_rb->buffer_len, inv_rb->buffer);
1066 free_sip_msg(&orig_inv);
1068 free_rte_list(rtset);
1073 * The function creates an ACK to 200 OK. Route set will be created
1074 * and parsed and the dst parameter will contain the destination to which
1075 * the request should be send. The function is used by tm when it
1076 * generates local ACK to 200 OK (on behalf of applications using uac)
1078 char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans,
1079 unsigned int branch, str *hdrs, str *body,
1080 unsigned int *len, struct dest_info* dst)
1082 char *req_buf, *p, *via;
1083 unsigned int via_len;
1084 char branch_buf[MAX_BRANCH_PARAM_LEN];
1089 str contact, ruri, *cont;
1092 str _to, *to = &_to;
1093 #ifdef USE_DNS_FAILOVER
1094 struct dns_srv_handle dns_h;
1096 #ifdef WITH_AS_SUPPORT
1097 /* With AS support, TM allows for external modules to generate building of
1098 * the ACK; in this case, the ACK's retransmission buffer is built once
1099 * and kept in memory (to help when retransmitted 2xx are received and ACK
1101 * Allocation of the string raw buffer that holds the ACK is piggy-backed
1102 * with allocation of the retransmission buffer (since both have the same
1103 * life-cycle): both the string buffer and retransm. buffer are placed
1104 * into the same allocated chunk of memory (retr. buffer first, string
1105 * buffer follows).In this case, the 'len' param is used as in-out
1106 * parameter: 'in' to give the extra space needed by the retr. buffer,
1107 * 'out' to return the lenght of the allocated string buffer.
1109 unsigned offset = *len;
1112 if (parse_headers(rpl, HDR_EOH_F, 0) == -1 || !rpl->to) {
1113 LM_ERR("Error while parsing headers.\n");
1116 _to.s = rpl->to->name.s;
1117 _to.len = rpl->to->len;
1120 if (get_contact_uri(rpl, &contact) < 0) {
1124 if (eval_uac_routing(rpl, &Trans->uac[branch].request, &contact,
1125 &list, &ruri, &next_hop) < 0) {
1126 LM_ERR("failed to evaluate routing elements.\n");
1129 LM_DBG("ACK RURI: `%.*s', NH: `%.*s'.\n", STR_FMT(&ruri),
1130 STR_FMT(&next_hop));
1132 if ((contact.s != ruri.s) || (contact.len != ruri.len)) {
1133 /* contact != ruri means that the next
1134 * hop is a strict router, cont will be non-zero
1135 * and print_routeset will append it at the end
1140 /* Next hop is a loose router, nothing to append */
1144 /* method, separators, version: "ACK sip:p2@iptel.org SIP/2.0" */
1145 *len = SIP_VERSION_LEN + ACK_LEN + 2 /* spaces */ + CRLF_LEN;
1149 switch(cfg_get(tm, tm_cfg, local_ack_mode)){
1151 /* send the local 200 ack to the same dst as the corresp. invite*/
1152 *dst=Trans->uac[branch].request.dst;
1155 /* send the local 200 ack to the same dst as the 200 reply source*/
1156 init_dst_from_rcv(dst, &rpl->rcv);
1157 dst->send_flags=rpl->fwd_send_flags;
1161 /* rfc conformant behaviour: use the next_hop determined from the
1162 * contact and the route set */
1163 #ifdef USE_DNS_FAILOVER
1164 if (cfg_get(core, core_cfg, use_dns_failover)){
1165 dns_srv_handle_init(&dns_h);
1166 if ((uri2dst(&dns_h , dst, rpl, &next_hop, PROTO_NONE)==0) ||
1167 (dst->send_sock==0)){
1168 dns_srv_handle_put(&dns_h);
1169 LM_ERR("no socket found\n");
1172 dns_srv_handle_put(&dns_h); /* not needed any more */
1174 if ((uri2dst(0 , dst, rpl, &next_hop, PROTO_NONE)==0) ||
1175 (dst->send_sock==0)){
1176 LM_ERR("no socket found\n");
1180 #else /* USE_DNS_FAILOVER */
1181 if ( (uri2dst( dst, rpl, &next_hop, PROTO_NONE)==0) ||
1182 (dst->send_sock==0)){
1183 LM_ERR("no socket found\n");
1186 #endif /* USE_DNS_FAILOVER */
1191 if (!t_calc_branch(Trans, branch, branch_buf, &branch_len)) goto error;
1192 branch_str.s = branch_buf;
1193 branch_str.len = branch_len;
1194 set_hostport(&hp, 0);
1195 via = via_builder(&via_len, dst, &branch_str, 0, &hp);
1197 LM_ERR("No via header got from builder\n");
1203 *len += Trans->from.len + Trans->callid.len + to->len + Trans->cseq_n.len + 1 + ACK_LEN + CRLF_LEN;
1205 /* copy'n'paste Route headers */
1207 *len += calc_routeset_len(list, cont);
1210 if (server_signature) *len += user_agent_hdr.len + CRLF_LEN;
1216 body_len.s = int2str(body->len, &body_len.len);
1220 body_len.s = NULL; /*4gcc*/
1221 *len += 1; /* for the (Cont-Len:) `0' */
1223 /* Content Length, EoM */
1224 *len += CONTENT_LENGTH_LEN + body_len.len + CRLF_LEN + CRLF_LEN;
1227 req_buf = shm_malloc(offset + *len + 1);
1230 req_buf = shm_malloc(*len + 1);
1233 LM_ERR("Cannot allocate memory (%u+1)\n", *len);
1238 append_str( p, ACK, ACK_LEN );
1239 append_str( p, " ", 1 );
1240 append_str(p, ruri.s, ruri.len);
1241 append_str( p, " " SIP_VERSION CRLF, 1 + SIP_VERSION_LEN + CRLF_LEN);
1243 /* insert our via */
1244 append_str(p, via, via_len);
1247 append_str(p, Trans->from.s, Trans->from.len);
1248 append_str(p, Trans->callid.s, Trans->callid.len);
1249 append_str(p, to->s, to->len);
1251 append_str(p, Trans->cseq_n.s, Trans->cseq_n.len);
1252 append_str( p, " ", 1 );
1253 append_str( p, ACK, ACK_LEN);
1254 append_str(p, CRLF, CRLF_LEN);
1257 p = print_rs(p, list, cont);
1259 /* User Agent header */
1260 if (server_signature) {
1261 append_str(p, user_agent_hdr.s, user_agent_hdr.len);
1262 append_str(p, CRLF, CRLF_LEN);
1267 append_str(p, hdrs->s, hdrs->len);
1269 /* Content Length, EoH, (body) */
1271 append_str(p, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
1272 append_str(p, body_len.s, body_len.len);
1273 append_str(p, /*end crr. header*/CRLF /*EoH*/CRLF, CRLF_LEN +
1275 append_str(p, body->s, body->len);
1277 append_str(p, CONTENT_LENGTH "0" CRLF CRLF,
1278 CONTENT_LENGTH_LEN + 1 + CRLF_LEN + CRLF_LEN);
1285 free_rte_list(list);
1291 free_rte_list(list);
1297 * Convert length of body into asciiz
1299 static inline int print_content_length(str* dest, str* body)
1301 static char content_length[10];
1306 /* Print Content-Length */
1307 b_len=body?body->len:0;
1308 tmp = int2str(b_len, &len);
1309 if (len >= sizeof(content_length)) {
1310 LM_ERR("content_len too big\n");
1315 memcpy(content_length, tmp, len);
1316 dest->s = content_length;
1323 * Convert CSeq number into asciiz
1325 static inline int print_cseq_num(str* _s, dlg_t* _d)
1327 static char cseq[INT2STR_MAX_LEN];
1331 tmp = int2str(_d->loc_seq.value, &len);
1332 if (len > sizeof(cseq)) {
1333 LM_ERR("cseq too big\n");
1337 memcpy(cseq, tmp, len);
1347 static inline int assemble_via(str* dest, struct cell* t,
1348 struct dest_info* dst, int branch)
1350 static char branch_buf[MAX_BRANCH_PARAM_LEN];
1353 unsigned int via_len;
1357 if (!t_calc_branch(t, branch, branch_buf, &len)) {
1358 LM_ERR("branch calculation failed\n");
1362 branch_str.s = branch_buf;
1363 branch_str.len = len;
1366 printf("!!!proto: %d\n", sock->proto);
1369 set_hostport(&hp, 0);
1370 via = via_builder(&via_len, dst, &branch_str, 0, &hp);
1372 LM_ERR("via building failed\n");
1377 dest->len = via_len;
1385 static inline char* print_request_uri(char* w, str* method, dlg_t* dialog,
1386 struct cell* t, int branch)
1388 memapp(w, method->s, method->len);
1391 t->uac[branch].uri.s = w;
1392 t->uac[branch].uri.len = dialog->hooks.request_uri->len;
1394 memapp(w, dialog->hooks.request_uri->s, dialog->hooks.request_uri->len);
1395 memapp(w, " " SIP_VERSION CRLF, 1 + SIP_VERSION_LEN + CRLF_LEN);
1402 * Print To header field
1404 static inline char* print_to(char* w, dlg_t* dialog, struct cell* t, int bracket)
1407 t->to.len = TO_LEN + dialog->rem_uri.len + CRLF_LEN
1408 + (((dialog->rem_uri.s[dialog->rem_uri.len - 1]!='>'))?2:0);
1410 memapp(w, TO, TO_LEN);
1411 if(bracket) memapp(w, "<", 1);
1412 memapp(w, dialog->rem_uri.s, dialog->rem_uri.len);
1413 if(bracket) memapp(w, ">", 1);
1415 if (dialog->id.rem_tag.len) {
1416 t->to.len += TOTAG_LEN + dialog->id.rem_tag.len ;
1417 memapp(w, TOTAG, TOTAG_LEN);
1418 memapp(w, dialog->id.rem_tag.s, dialog->id.rem_tag.len);
1421 memapp(w, CRLF, CRLF_LEN);
1427 * Print From header field
1429 static inline char* print_from(char* w, dlg_t* dialog, struct cell* t, int bracket)
1432 t->from.len = FROM_LEN + dialog->loc_uri.len + CRLF_LEN
1433 + ((dialog->loc_uri.s[dialog->loc_uri.len - 1]!='>')?2:0);
1435 memapp(w, FROM, FROM_LEN);
1436 if(bracket) memapp(w, "<", 1);
1437 memapp(w, dialog->loc_uri.s, dialog->loc_uri.len);
1438 if(bracket) memapp(w, ">", 1);
1440 if (dialog->id.loc_tag.len) {
1441 t->from.len += FROMTAG_LEN + dialog->id.loc_tag.len;
1442 memapp(w, FROMTAG, FROMTAG_LEN);
1443 memapp(w, dialog->id.loc_tag.s, dialog->id.loc_tag.len);
1446 memapp(w, CRLF, CRLF_LEN);
1452 * Print CSeq header field
1454 char* print_cseq_mini(char* target, str* cseq, str* method) {
1455 memapp(target, CSEQ, CSEQ_LEN);
1456 memapp(target, cseq->s, cseq->len);
1457 memapp(target, " ", 1);
1458 memapp(target, method->s, method->len);
1462 static inline char* print_cseq(char* w, str* cseq, str* method, struct cell* t)
1465 /* don't include method name and CRLF -- subsequent
1466 * local requests ACK/CANCEL will add their own */
1467 t->cseq_n.len = CSEQ_LEN + cseq->len;
1468 w = print_cseq_mini(w, cseq, method);
1473 * Print Call-ID header field
1474 * created an extra function for pure header field creation,
1475 * that is used by t_cancel for t_uac_cancel FIFO function.
1477 char* print_callid_mini(char* target, str callid) {
1478 memapp(target, CALLID, CALLID_LEN);
1479 memapp(target, callid.s, callid.len);
1480 memapp(target, CRLF, CRLF_LEN);
1484 static inline char* print_callid(char* w, dlg_t* dialog, struct cell* t)
1486 /* begins with CRLF, not included in t->callid, don`t know why...?!? */
1487 memapp(w, CRLF, CRLF_LEN);
1489 t->callid.len = CALLID_LEN + dialog->id.call_id.len + CRLF_LEN;
1491 w = print_callid_mini(w, dialog->id.call_id);
1499 char* build_uac_req(str* method, str* headers, str* body, dlg_t* dialog,
1500 int branch, struct cell *t, int* len, struct dest_info* dst)
1503 str content_length, cseq, via;
1504 unsigned int maxfwd_len;
1505 int tbracket, fbracket;
1506 str fromtag = STR_NULL;
1507 str loc_tag = STR_NULL;
1509 if (!method || !dialog) {
1510 LM_ERR("invalid parameter value\n");
1514 if (dialog->id.loc_tag.len<=0) {
1515 /* From Tag is mandatory in RFC3261 - generate one if not provided */
1516 generate_fromtag(&fromtag, &dialog->id.call_id);
1517 loc_tag = dialog->id.loc_tag;
1518 dialog->id.loc_tag = fromtag;
1520 if (print_content_length(&content_length, body) < 0) {
1521 LM_ERR("error while printing content-length\n");
1524 if (print_cseq_num(&cseq, dialog) < 0) {
1525 LM_ERR("error while printing CSeq number\n");
1529 if(headers==NULL || headers->len<15
1530 || _strnstr(headers->s, "Max-Forwards:", headers->len)==NULL) {
1531 maxfwd_len = MAXFWD_HEADER_LEN;
1536 *len = method->len + 1 + dialog->hooks.request_uri->len + 1
1537 + SIP_VERSION_LEN + CRLF_LEN;
1539 if (assemble_via(&via, t, dst, branch) < 0) {
1540 LM_ERR("error while assembling Via\n");
1545 if((p=q_memrchr(dialog->rem_uri.s, '>', dialog->rem_uri.len))!=NULL) {
1546 if((p==dialog->rem_uri.s + dialog->rem_uri.len - 1)
1555 if((p=q_memrchr(dialog->loc_uri.s, '>', dialog->loc_uri.len))!=NULL) {
1556 if((p==dialog->loc_uri.s + dialog->loc_uri.len - 1)
1566 *len += TO_LEN + dialog->rem_uri.len
1567 + (dialog->id.rem_tag.len ? (TOTAG_LEN + dialog->id.rem_tag.len) : 0)
1568 + CRLF_LEN; /* To */
1569 if(tbracket) *len += 2; /* To-URI < > */
1570 *len += FROM_LEN + dialog->loc_uri.len
1571 + (dialog->id.loc_tag.len ? (FROMTAG_LEN + dialog->id.loc_tag.len) : 0)
1572 + CRLF_LEN; /* From */
1573 if(fbracket) *len += 2; /* From-URI < > */
1574 *len += CALLID_LEN + dialog->id.call_id.len + CRLF_LEN; /* Call-ID */
1575 *len += CSEQ_LEN + cseq.len + 1 + method->len + CRLF_LEN; /* CSeq */
1576 *len += calculate_routeset_length(dialog); /* Route set */
1577 *len += maxfwd_len; /* Max-forwards */
1578 *len += CONTENT_LENGTH_LEN + content_length.len
1579 + CRLF_LEN; /* Content-Length */
1580 *len += ((server_signature && user_agent_hdr.len>0)
1581 ? (user_agent_hdr.len + CRLF_LEN) : 0); /* Signature */
1582 if(headers && headers->len>2) {
1583 /* Additional headers */
1584 *len += headers->len;
1585 /* End of header if missing */
1586 if(headers->s[headers->len - 1] != '\n')
1589 *len += (body ? body->len : 0); /* Message body */
1590 *len += CRLF_LEN; /* End of Header */
1592 buf = shm_malloc(*len + 1);
1594 LM_ERR("no more shared memory (%d)\n", *len);
1600 w = print_request_uri(w, method, dialog, t, branch); /* Request-URI */
1601 memapp(w, via.s, via.len); /* Top-most Via */
1602 w = print_to(w, dialog, t, tbracket); /* To */
1603 w = print_from(w, dialog, t, fbracket); /* From */
1605 dialog->id.loc_tag = loc_tag;
1607 w = print_cseq(w, &cseq, method, t); /* CSeq */
1608 w = print_callid(w, dialog, t); /* Call-ID */
1609 w = print_routeset(w, dialog); /* Route set */
1612 memapp(w, MAXFWD_HEADER, MAXFWD_HEADER_LEN); /* Max-forwards */
1614 /* Content-Length */
1615 memapp(w, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
1616 memapp(w, content_length.s, content_length.len);
1617 memapp(w, CRLF, CRLF_LEN);
1619 /* Server signature */
1620 if (server_signature && user_agent_hdr.len>0) {
1621 memapp(w, user_agent_hdr.s, user_agent_hdr.len);
1622 memapp(w, CRLF, CRLF_LEN);
1624 if(headers && headers->len>2) {
1625 memapp(w, headers->s, headers->len);
1626 if(headers->s[headers->len - 1] != '\n')
1627 memapp(w, CRLF, CRLF_LEN);
1629 memapp(w, CRLF, CRLF_LEN);
1630 if (body) memapp(w, body->s, body->len);
1633 assert(w-buf == *len);
1645 int t_calc_branch(struct cell *t,
1646 int b, char *branch, int *branch_len)
1648 return branch_builder( t->hash_index,
1650 b, branch, branch_len );
1654 * build CANCEL from UAC side
1656 char *build_uac_cancel(str *headers,str *body,struct cell *cancelledT,
1657 unsigned int branch, unsigned int *len, struct dest_info* dst)
1659 char *cancel_buf, *p;
1660 char branch_buf[MAX_BRANCH_PARAM_LEN];
1663 str content_length, via;
1665 LM_DBG("sing FROM=<%.*s>, TO=<%.*s>, CSEQ_N=<%.*s>\n",
1666 cancelledT->from.len, cancelledT->from.s, cancelledT->to.len,
1667 cancelledT->to.s, cancelledT->cseq_n.len, cancelledT->cseq_n.s);
1669 branch_str.s=branch_buf;
1670 if (!t_calc_branch(cancelledT, branch, branch_str.s, &branch_str.len )){
1671 LM_ERR("failed to create branch !\n");
1674 set_hostport(&hp,0);
1676 if (assemble_via(&via, cancelledT, dst, branch) < 0) {
1677 LM_ERR("Error while assembling Via\n");
1681 /* method, separators, version */
1682 *len=CANCEL_LEN + 2 /* spaces */ +SIP_VERSION_LEN + CRLF_LEN;
1683 *len+=cancelledT->uac[branch].uri.len;
1687 *len+=cancelledT->from.len;
1689 *len+=cancelledT->to.len;
1691 *len+=cancelledT->callid.len;
1693 *len+=cancelledT->cseq_n.len+1+CANCEL_LEN+CRLF_LEN;
1695 if (server_signature) {
1696 *len += USER_AGENT_LEN + CRLF_LEN;
1698 /* Content Length */
1699 if (print_content_length(&content_length, body) < 0) {
1700 LM_ERR("failed to print content-length\n");
1703 /* Content-Length */
1704 *len += (body ? (CONTENT_LENGTH_LEN + content_length.len + CRLF_LEN) : 0);
1705 /*Additional headers*/
1706 *len += (headers ? headers->len : 0);
1710 *len += (body ? body->len : 0);
1712 cancel_buf=shm_malloc( *len+1 );
1715 LM_ERR("no more share memory\n");
1720 memapp( p, CANCEL, CANCEL_LEN );
1723 memapp( p, cancelledT->uac[branch].uri.s,
1724 cancelledT->uac[branch].uri.len);
1725 memapp( p, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN );
1727 /* insert our via */
1728 memapp(p,via.s,via.len);
1731 memapp( p, cancelledT->from.s, cancelledT->from.len );
1732 memapp( p, cancelledT->callid.s, cancelledT->callid.len );
1733 memapp( p, cancelledT->to.s, cancelledT->to.len );
1735 memapp( p, cancelledT->cseq_n.s, cancelledT->cseq_n.len );
1737 memapp( p, CANCEL, CANCEL_LEN );
1738 memapp( p, CRLF, CRLF_LEN );
1740 /* User Agent header */
1741 if (server_signature) {
1742 memapp(p,USER_AGENT CRLF, USER_AGENT_LEN+CRLF_LEN );
1746 memapp(p, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
1747 memapp(p, content_length.s, content_length.len);
1748 memapp(p, CRLF, CRLF_LEN);
1750 if(headers && headers->len){
1751 memapp(p,headers->s,headers->len);
1754 memapp(p,CRLF,CRLF_LEN);
1755 if(body && body->len){
1756 memapp(p,body->s,body->len);