More log message fixes.
[sip-router] / modules / tm / t_msgbuilder.c
1 /*
2  * $Id$
3  *
4  * message printing
5  *
6  * Copyright (C) 2001-2003 Fhg Fokus
7  *
8  * This file is part of ser, a free SIP server.
9  *
10  * ser is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * For a license to use the ser software under conditions
16  * other than those described here, or to purchase support for this
17  * software, please contact iptel.org by e-mail at the following addresses:
18  *    info@iptel.org
19  *
20  * ser is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License 
26  * along with this program; if not, write to the Free Software 
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  *
29  *
30  * History:
31  * ----------
32  * 2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
33  * 2003-02-13  build_uac_request uses proto (andrei)
34  * 2003-02-28  scratchpad compatibility abandoned (jiri)
35  * 2003-04-14  build_local no longer checks reply status as it
36  *             is now called before reply status is updated to
37  *             avoid late ACK sending (jiri)
38  * 2003-10-02  added via_builder set host/port support (andrei)
39  * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
40  * 2004-02-13: t->is_invite and t->local replaced with flags (bogdan)
41  */
42
43 #include "defs.h"
44
45
46 #include "../../comp_defs.h"
47 #include "../../hash_func.h"
48 #include "../../globals.h"
49 #include "t_funcs.h"
50 #include "../../dprint.h"
51 #include "../../config.h"
52 #include "../../parser/parser_f.h"
53 #include "../../ut.h"
54 #include "../../parser/msg_parser.h"
55 #include "../../parser/contact/parse_contact.h"
56 #include "t_msgbuilder.h"
57 #include "uac.h"
58
59
60 #define ROUTE_PREFIX "Route: "
61 #define ROUTE_PREFIX_LEN (sizeof(ROUTE_PREFIX) - 1)
62
63 #define ROUTE_SEPARATOR ", "
64 #define ROUTE_SEPARATOR_LEN (sizeof(ROUTE_SEPARATOR) - 1)
65
66 #define  append_mem_block(_d,_s,_len) \
67                 do{\
68                         memcpy((_d),(_s),(_len));\
69                         (_d) += (_len);\
70                 }while(0);
71
72 #define append_str(_p,_str) \
73         do{  \
74                 memcpy((_p), (_str).s, (_str).len); \
75                 (_p)+=(_str).len;  \
76         } while(0);
77
78 /* Build a local request based on a previous request; main
79    customers of this function are local ACK and local CANCEL
80  */
81 char *build_local(struct cell *Trans,unsigned int branch,
82         unsigned int *len, char *method, int method_len, str *to)
83 {
84         char                *cancel_buf, *p, *via;
85         unsigned int         via_len;
86         struct hdr_field    *hdr;
87         char branch_buf[MAX_BRANCH_PARAM_LEN];
88         int branch_len;
89         str branch_str;
90         struct hostport hp;
91
92 #ifdef _OBSO
93         if ( Trans->uac[branch].last_received<100)
94         {
95                 DBG("DEBUG: build_local: no response ever received"
96                         " : dropping local request! \n");
97                 goto error;
98         }
99 #endif
100
101         /* method, separators, version: "CANCEL sip:p2@iptel.org SIP/2.0" */
102         *len=SIP_VERSION_LEN + method_len + 2 /* spaces */ + CRLF_LEN;
103         *len+=Trans->uac[branch].uri.len;
104
105         /*via*/
106         if (!t_calc_branch(Trans,  branch, 
107                 branch_buf, &branch_len ))
108                 goto error;
109         branch_str.s=branch_buf;
110         branch_str.len=branch_len;
111         set_hostport(&hp, (is_local(Trans))?0:(Trans->uas.request));
112         via=via_builder(&via_len, Trans->uac[branch].request.dst.send_sock,
113                 &branch_str, 0, Trans->uac[branch].request.dst.proto, &hp );
114         if (!via)
115         {
116                 LOG(L_ERR, "ERROR: build_local: "
117                         "no via header got from builder\n");
118                 goto error;
119         }
120         *len+= via_len;
121         /*headers*/
122         *len+=Trans->from.len+Trans->callid.len+to->len+
123                 +Trans->cseq_n.len+1+method_len+CRLF_LEN; 
124
125
126         /* copy'n'paste Route headers */
127         if (!is_local(Trans)) {
128                 for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next )
129                          if (hdr->type==HDR_ROUTE)
130                                 *len+=hdr->len;
131         }
132
133         /* User Agent */
134         if (server_signature) {
135                 *len += USER_AGENT_LEN + CRLF_LEN;
136         }
137         /* Content Length, EoM */
138         *len+=CONTENT_LENGTH_LEN+1 + CRLF_LEN + CRLF_LEN;
139
140         cancel_buf=shm_malloc( *len+1 );
141         if (!cancel_buf)
142         {
143                 LOG(L_ERR, "ERROR: build_local: cannot allocate memory\n");
144                 goto error01;
145         }
146         p = cancel_buf;
147
148         append_mem_block( p, method, method_len );
149         append_mem_block( p, " ", 1 );
150         append_str( p, Trans->uac[branch].uri );
151         append_mem_block( p, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN );
152
153         /* insert our via */
154         append_mem_block(p,via,via_len);
155
156         /*other headers*/
157         append_str( p, Trans->from );
158         append_str( p, Trans->callid );
159         append_str( p, *to );
160
161         append_str( p, Trans->cseq_n );
162         append_mem_block( p, " ", 1 );
163         append_mem_block( p, method, method_len );
164         append_mem_block( p, CRLF, CRLF_LEN );
165
166         if (!is_local(Trans))  {
167                 for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next )
168                         if(hdr->type==HDR_ROUTE) {
169                                 append_mem_block(p, hdr->name.s, hdr->len );
170                         }
171         }
172
173         /* User Agent header */
174         if (server_signature) {
175                 append_mem_block(p,USER_AGENT CRLF, USER_AGENT_LEN+CRLF_LEN );
176         }
177         /* Content Length, EoM */
178         append_mem_block(p, CONTENT_LENGTH "0" CRLF CRLF ,
179                 CONTENT_LENGTH_LEN+1 + CRLF_LEN + CRLF_LEN);
180         *p=0;
181
182         pkg_free(via);
183         return cancel_buf;
184 error01:
185         pkg_free(via);
186 error:
187         return NULL;
188 }
189
190
191 struct rte {
192         rr_t* ptr;
193         struct rte* next;
194 };
195
196          
197 static inline void free_rte_list(struct rte* list)
198 {
199         struct rte* ptr;
200         
201         while(list) {
202                 ptr = list;
203                 list = list->next;
204                 pkg_free(ptr);
205         }
206 }
207
208
209 static inline int process_routeset(struct sip_msg* msg, str* contact, struct rte** list, str* ruri, str* next_hop)
210 {
211         struct hdr_field* ptr;
212         rr_t* p;
213         struct rte* t, *head;
214         struct sip_uri puri;
215         
216         ptr = msg->record_route;
217         head = 0;
218         while(ptr) {
219                 if (ptr->type == HDR_RECORDROUTE) {
220                         if (parse_rr(ptr) < 0) {
221                                 LOG(L_ERR, "process_routeset: Error while parsing Record-Route header\n");
222                                 return -1;
223                         }
224                         
225                         p = (rr_t*)ptr->parsed;
226                         while(p) {
227                                 t = (struct rte*)pkg_malloc(sizeof(struct rte));
228                                 if (!t) {
229                                         LOG(L_ERR, "process_routeset: No memory left\n");
230                                         free_rte_list(head);
231                                         return -1;
232                                 }
233                                 t->ptr = p;
234                                 t->next = head;
235                                 head = t;
236                                 p = p->next;
237                         }
238                 }
239                 ptr = ptr->next;
240         }
241         
242         if (head) {
243                 if (parse_uri(head->ptr->nameaddr.uri.s, head->ptr->nameaddr.uri.len, &puri) == -1) {
244                         LOG(L_ERR, "process_routeset: Error while parsing URI\n");
245                         free_rte_list(head);
246                         return -1;
247                 }
248                 
249                 if (puri.lr.s) {
250                              /* Next hop is loose router */
251                         *ruri = *contact;
252                         *next_hop = head->ptr->nameaddr.uri;
253                 } else {
254                              /* Next hop is strict router */
255                         *ruri = head->ptr->nameaddr.uri;
256                         *next_hop = *ruri;
257                         t = head;
258                         head = head->next;
259                         pkg_free(t);
260                 }
261         } else {
262                      /* No routes */
263                 *ruri = *contact;
264                 *next_hop = *contact;
265         }
266         
267         *list = head;
268         return 0;
269 }
270
271
272 static inline int calc_routeset_len(struct rte* list, str* contact)
273 {
274         struct rte* ptr;
275         int ret;
276         
277         if (list || contact) {
278                 ret = ROUTE_PREFIX_LEN + CRLF_LEN;
279         } else {
280                 return 0;
281         }
282         
283         ptr = list;
284         while(ptr) {
285                 if (ptr != list) {
286                         ret += ROUTE_SEPARATOR_LEN;
287                 }
288                 ret += ptr->ptr->len;
289                 ptr = ptr->next;
290         }
291         
292         if (contact) {
293                 if (list) ret += ROUTE_SEPARATOR_LEN;
294                 ret += 2 + contact->len;
295         }
296         
297         return ret;
298 }
299
300
301      /*
302       * Print the route set
303       */
304 static inline char* print_rs(char* p, struct rte* list, str* contact)
305 {
306         struct rte* ptr;
307         
308         if (list || contact) {
309                 memapp(p, ROUTE_PREFIX, ROUTE_PREFIX_LEN);
310         } else {
311                 return p;
312         }
313         
314         ptr = list;
315         while(ptr) {
316                 if (ptr != list) {
317                         memapp(p, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);
318                 }
319                 
320                 memapp(p, ptr->ptr->nameaddr.name.s, ptr->ptr->len);
321                 ptr = ptr->next;
322         }
323         
324         if (contact) {
325                 if (list) memapp(p, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);
326                 *p++ = '<';
327                 append_str(p, *contact);
328                 *p++ = '>';
329         }
330         
331         memapp(p, CRLF, CRLF_LEN);
332         return p;
333 }
334
335
336      /*
337       * Parse Contact header field body and extract URI
338       * Does not parse headers !
339       */
340 static inline int get_contact_uri(struct sip_msg* msg, str* uri)
341 {
342         contact_t* c;
343         
344         uri->len = 0;
345         if (!msg->contact) return 1;
346         
347         if (parse_contact(msg->contact) < 0) {
348                 LOG(L_ERR, "get_contact_uri: Error while parsing Contact body\n");
349                 return -1;
350         }
351         
352         c = ((contact_body_t*)msg->contact->parsed)->contacts;
353         
354         if (!c) {
355                 LOG(L_ERR, "get_contact_uri: Empty body or * contact\n");
356                 return -2;
357         }
358         
359         *uri = c->uri;
360         return 0;
361 }
362
363
364
365      /*
366       * The function creates an ACK to 200 OK. Route set will be created
367       * and parsed and next_hop parameter will contain uri the which the
368       * request should be send. The function is used by tm when it generates
369       * local ACK to 200 OK (on behalf of applications using uac
370       */
371 char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans, unsigned int branch,
372                     str* to, unsigned int *len, str *next_hop)
373 {
374         char *req_buf, *p, *via;
375         unsigned int via_len;
376         char branch_buf[MAX_BRANCH_PARAM_LEN];
377         int branch_len;
378         str branch_str;
379         struct hostport hp;
380         struct rte* list;
381         str contact, ruri, *cont;
382         struct socket_info* send_sock;
383         union sockaddr_union to_su;
384         
385         if (get_contact_uri(rpl, &contact) < 0) {
386                 return 0;
387         }
388         
389         if (process_routeset(rpl, &contact, &list, &ruri, next_hop) < 0) {
390                 return 0;
391         }
392         
393         if ((contact.s != ruri.s) || (contact.len != ruri.len)) {
394                      /* contact != ruri means that the next
395                       * hop is a strict router, cont will be non-zero
396                       * and print_routeset will append it at the end
397                       * of the route set
398                       */
399                 cont = &contact;
400         } else {
401                      /* Next hop is a loose router, nothing to append */
402                 cont = 0;
403         }
404         
405              /* method, separators, version: "ACK sip:p2@iptel.org SIP/2.0" */
406         *len = SIP_VERSION_LEN + ACK_LEN + 2 /* spaces */ + CRLF_LEN;
407         *len += ruri.len;
408         
409         
410              /* via */
411         send_sock = uri2sock(next_hop, &to_su, PROTO_NONE);
412         if (!send_sock) {
413                 LOG(L_ERR, "build_dlg_ack: no socket found\n");
414                 goto error;
415         }
416         
417         if (!t_calc_branch(Trans,  branch, branch_buf, &branch_len)) goto error;
418         branch_str.s = branch_buf;
419         branch_str.len = branch_len;
420         set_hostport(&hp, 0);
421         via = via_builder(&via_len, send_sock, &branch_str, 0, send_sock->proto, &hp);
422         if (!via) {
423                 LOG(L_ERR, "build_dlg_ack: No via header got from builder\n");
424                 goto error;
425         }
426         *len+= via_len;
427         
428              /*headers*/
429         *len += Trans->from.len + Trans->callid.len + to->len + Trans->cseq_n.len + 1 + ACK_LEN + CRLF_LEN;
430         
431              /* copy'n'paste Route headers */
432         
433         *len += calc_routeset_len(list, cont);
434         
435              /* User Agent */
436         if (server_signature) *len += USER_AGENT_LEN + CRLF_LEN;
437              /* Content Length, EoM */
438         *len += CONTENT_LENGTH_LEN + 1 + CRLF_LEN + CRLF_LEN;
439         
440         req_buf = shm_malloc(*len + 1);
441         if (!req_buf) {
442                 LOG(L_ERR, "build_dlg_ack: Cannot allocate memory\n");
443                 goto error01;
444         }
445         p = req_buf;
446         
447         append_mem_block( p, ACK, ACK_LEN );
448         append_mem_block( p, " ", 1 );
449         append_str(p, ruri);
450         append_mem_block( p, " " SIP_VERSION CRLF, 1 + SIP_VERSION_LEN + CRLF_LEN);
451          
452              /* insert our via */
453         append_mem_block(p, via, via_len);
454         
455              /*other headers*/
456         append_str(p, Trans->from);
457         append_str(p, Trans->callid);
458         append_str(p, *to);
459         
460         append_str(p, Trans->cseq_n);
461         append_mem_block( p, " ", 1 );
462         append_mem_block( p, ACK, ACK_LEN);
463         append_mem_block(p, CRLF, CRLF_LEN);
464         
465              /* Routeset */
466         p = print_rs(p, list, cont);
467         
468              /* User Agent header */
469         if (server_signature) {
470                 append_mem_block(p, USER_AGENT CRLF, USER_AGENT_LEN + CRLF_LEN);
471         }
472         
473              /* Content Length, EoM */
474         append_mem_block(p, CONTENT_LENGTH "0" CRLF CRLF, CONTENT_LENGTH_LEN + 1 + CRLF_LEN + CRLF_LEN);
475         *p = 0;
476         
477         pkg_free(via);
478         free_rte_list(list);
479         return req_buf;
480         
481  error01:
482         pkg_free(via);
483  error:
484         free_rte_list(list);
485         return 0;
486          }
487
488
489 /*
490  * Convert lenght of body into asciiz
491  */
492 static inline int print_content_length(str* dest, str* body)
493 {
494         static char content_length[10];
495         int len;
496         char* tmp;
497
498              /* Print Content-Length */
499         if (body) {
500                 tmp = int2str(body->len, &len);
501                 if (len >= sizeof(content_length)) {
502                         LOG(L_ERR, "ERROR: print_content_length: content_len too big\n");
503                         return -1;
504                 }
505                 memcpy(content_length, tmp, len); 
506                 dest->s = content_length;
507                 dest->len = len;
508         } else {
509                 dest->s = 0;
510                 dest->len = 0;
511         }
512         return 0;
513 }
514
515
516 /*
517  * Convert CSeq number into asciiz
518  */
519 static inline int print_cseq_num(str* _s, dlg_t* _d)
520 {
521         static char cseq[INT2STR_MAX_LEN];
522         char* tmp;
523         int len;
524
525         tmp = int2str(_d->loc_seq.value, &len);
526         if (len > sizeof(cseq)) {
527                 LOG(L_ERR, "print_cseq_num: cseq too big\n");
528                 return -1;
529         }
530         
531         memcpy(cseq, tmp, len);
532         _s->s = cseq;
533         _s->len = len;
534         return 0;
535 }
536
537
538 /*
539  * Create Via header
540  */
541 static inline int assemble_via(str* dest, struct cell* t, struct socket_info* sock, int branch)
542 {
543         static char branch_buf[MAX_BRANCH_PARAM_LEN];
544         char* via;
545         int len;
546         unsigned int via_len;
547         str branch_str;
548         struct hostport hp;
549
550         if (!t_calc_branch(t, branch, branch_buf, &len)) {
551                 LOG(L_ERR, "ERROR: assemble_via: branch calculation failed\n");
552                 return -1;
553         }
554         
555         branch_str.s = branch_buf;
556         branch_str.len = len;
557
558 #ifdef XL_DEBUG
559         printf("!!!proto: %d\n", sock->proto);
560 #endif
561
562         set_hostport(&hp, 0);
563         via = via_builder(&via_len, sock, &branch_str, 0, sock->proto, &hp);
564         if (!via) {
565                 LOG(L_ERR, "assemble_via: via building failed\n");
566                 return -2;
567         }
568         
569         dest->s = via;
570         dest->len = via_len;
571         return 0;
572 }
573
574
575 /*
576  * Print Request-URI
577  */
578 static inline char* print_request_uri(char* w, str* method, dlg_t* dialog, struct cell* t, int branch)
579 {
580         memapp(w, method->s, method->len); 
581         memapp(w, " ", 1); 
582
583         t->uac[branch].uri.s = w; 
584         t->uac[branch].uri.len = dialog->hooks.request_uri->len;
585
586         memapp(w, dialog->hooks.request_uri->s, dialog->hooks.request_uri->len); 
587         memapp(w, " " SIP_VERSION CRLF, 1 + SIP_VERSION_LEN + CRLF_LEN);
588
589         return w;
590 }
591
592
593 /*
594  * Print To header field
595  */
596 static inline char* print_to(char* w, dlg_t* dialog, struct cell* t)
597 {
598         t->to.s = w;
599         t->to.len = TO_LEN + dialog->rem_uri.len + CRLF_LEN;
600
601         memapp(w, TO, TO_LEN);
602         memapp(w, dialog->rem_uri.s, dialog->rem_uri.len);
603
604         if (dialog->id.rem_tag.len) {
605                 t->to.len += TOTAG_LEN + dialog->id.rem_tag.len ;
606                 memapp(w, TOTAG, TOTAG_LEN);
607                 memapp(w, dialog->id.rem_tag.s, dialog->id.rem_tag.len);
608         }
609
610         memapp(w, CRLF, CRLF_LEN);
611         return w;
612 }
613
614
615 /*
616  * Print From header field
617  */
618 static inline char* print_from(char* w, dlg_t* dialog, struct cell* t)
619 {
620         t->from.s = w;
621         t->from.len = FROM_LEN + dialog->loc_uri.len + CRLF_LEN;
622
623         memapp(w, FROM, FROM_LEN);
624         memapp(w, dialog->loc_uri.s, dialog->loc_uri.len);
625
626         if (dialog->id.loc_tag.len) {
627                 t->from.len += FROMTAG_LEN + dialog->id.loc_tag.len;
628                 memapp(w, FROMTAG, FROMTAG_LEN);
629                 memapp(w, dialog->id.loc_tag.s, dialog->id.loc_tag.len);
630         }
631
632         memapp(w, CRLF, CRLF_LEN);
633         return w;
634 }
635
636
637 /*
638  * Print CSeq header field
639  */
640 char* print_cseq_mini(char* target, str* cseq, str* method) {
641         memapp(target, CSEQ, CSEQ_LEN);
642         memapp(target, cseq->s, cseq->len);
643         memapp(target, " ", 1);
644         memapp(target, method->s, method->len);
645         return target;
646 }
647
648 static inline char* print_cseq(char* w, str* cseq, str* method, struct cell* t)
649 {
650         t->cseq_n.s = w; 
651         /* don't include method name and CRLF -- subsequent
652          * local reuqests ACK/CANCEl will add their own */
653         t->cseq_n.len = CSEQ_LEN + cseq->len; 
654         w = print_cseq_mini(w, cseq, method);
655         return w;
656 }
657
658 /*
659  * Print Call-ID header field
660  * created an extra function for pure header field creation, that is used by t_cancel for 
661  * t_uac_cancel FIFO function.
662  */
663 char* print_callid_mini(char* target, str callid) {
664         memapp(target, CALLID, CALLID_LEN);
665         memapp(target, callid.s, callid.len);
666         memapp(target, CRLF, CRLF_LEN);
667         return target;
668 }
669
670 static inline char* print_callid(char* w, dlg_t* dialog, struct cell* t)
671 {
672         /* begins with CRLF, not included in t->callid, don`t know why...?!? */
673         memapp(w, CRLF, CRLF_LEN);
674         t->callid.s = w;
675         t->callid.len = CALLID_LEN + dialog->id.call_id.len + CRLF_LEN;
676
677         w = print_callid_mini(w, dialog->id.call_id);
678         return w;
679 }
680
681
682 /*
683  * Create a request
684  */
685 char* build_uac_req(str* method, str* headers, str* body, dlg_t* dialog, int branch, 
686                         struct cell *t, int* len, struct socket_info* send_sock)
687 {
688         char* buf, *w;
689         str content_length, cseq, via;
690
691         if (!method || !dialog) {
692                 LOG(L_ERR, "build_uac_req(): Invalid parameter value\n");
693                 return 0;
694         }
695         if (print_content_length(&content_length, body) < 0) {
696                 LOG(L_ERR, "build_uac_req(): Error while printing content-length\n");
697                 return 0;
698         }
699         if (print_cseq_num(&cseq, dialog) < 0) {
700                 LOG(L_ERR, "build_uac_req(): Error while printing CSeq number\n");
701                 return 0;
702         }
703         *len = method->len + 1 + dialog->hooks.request_uri->len + 1 + SIP_VERSION_LEN + CRLF_LEN;
704
705         if (assemble_via(&via, t, send_sock, branch) < 0) {
706                 LOG(L_ERR, "build_uac_req(): Error while assembling Via\n");
707                 return 0;
708         }
709         *len += via.len;
710
711         *len += TO_LEN + dialog->rem_uri.len
712                 + (dialog->id.rem_tag.len ? (TOTAG_LEN + dialog->id.rem_tag.len) : 0) + CRLF_LEN;    /* To */
713         *len += FROM_LEN + dialog->loc_uri.len
714                 + (dialog->id.loc_tag.len ? (FROMTAG_LEN + dialog->id.loc_tag.len) : 0) + CRLF_LEN;  /* From */
715         *len += CALLID_LEN + dialog->id.call_id.len + CRLF_LEN;                                      /* Call-ID */
716         *len += CSEQ_LEN + cseq.len + 1 + method->len + CRLF_LEN;                                    /* CSeq */
717         *len += calculate_routeset_length(dialog);                                                   /* Route set */
718         *len += (body ? (CONTENT_LENGTH_LEN + content_length.len + CRLF_LEN) : 0);                   /* Content-Length */
719         *len += (server_signature ? (USER_AGENT_LEN + CRLF_LEN) : 0);                                /* Signature */
720         *len += (headers ? headers->len : 0);                                                        /* Additional headers */
721         *len += (body ? body->len : 0);                                                              /* Message body */
722         *len += CRLF_LEN;                                                                            /* End of Header */
723
724         buf = shm_malloc(*len + 1);
725         if (!buf) {
726                 LOG(L_ERR, "build_uac_req(): no shmem\n");
727                 goto error;
728         }
729         
730         w = buf;
731
732         w = print_request_uri(w, method, dialog, t, branch);  /* Request-URI */
733         memapp(w, via.s, via.len);                            /* Top-most Via */
734         w = print_to(w, dialog, t);                           /* To */
735         w = print_from(w, dialog, t);                         /* From */
736         w = print_cseq(w, &cseq, method, t);                  /* CSeq */
737         w = print_callid(w, dialog, t);                       /* Call-ID */
738         w = print_routeset(w, dialog);                        /* Route set */
739
740              /* Content-Length */
741         if (body) {
742                 memapp(w, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
743                 memapp(w, content_length.s, content_length.len);
744                 memapp(w, CRLF, CRLF_LEN);
745         }
746         
747              /* Server signature */
748         if (server_signature) memapp(w, USER_AGENT CRLF, USER_AGENT_LEN + CRLF_LEN);
749         if (headers) memapp(w, headers->s, headers->len);
750         memapp(w, CRLF, CRLF_LEN);
751         if (body) memapp(w, body->s, body->len);
752
753 #ifdef EXTRA_DEBUG
754         if (w-buf != *len ) abort();
755 #endif
756
757         pkg_free(via.s);
758         return buf;
759
760  error:
761         pkg_free(via.s);
762         return 0;
763 }
764
765
766 int t_calc_branch(struct cell *t, 
767         int b, char *branch, int *branch_len)
768 {
769         return syn_branch ?
770                 branch_builder( t->hash_index,
771                         t->label, 0,
772                         b, branch, branch_len )
773                 : branch_builder( t->hash_index,
774                         0, t->md5,
775                         b, branch, branch_len );
776 }
777