core, lib, modules: restructured source code tree
[sip-router] / src / modules / mangler / contact_ops.c
1 /*
2  * mangler module
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
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
12  *
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.
17  *
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
21  */
22
23 #include "contact_ops.h"
24 #include "utils.h"
25 #include "common.h"
26 #include "../../mem/mem.h"
27 #include "../../data_lump.h"
28 #include "../../parser/hf.h"
29 #include "../../parser/parse_uri.h"
30 #include "../../parser/contact/parse_contact.h"
31 #include "../../ut.h"
32 #include "../../dset.h"
33
34 #include <stdio.h>
35 #include <string.h>
36
37 #define SIP_SCH "sip:"
38 #define SIP_SCH_LEN     (sizeof(SIP_SCH)-1)
39
40
41 int
42 encode_contact (struct sip_msg *msg, char *encoding_prefix,char *public_ip)
43 {
44
45         contact_body_t *cb;
46         contact_t *c;
47         str* uri;
48         str newUri;
49         int res;
50         char separator;
51
52
53
54         /*
55          * I have a list of contacts in contact->parsed which is of type contact_body_t 
56          * inside i have a contact->parsed->contact which is the head of the list of contacts
57          * inside it is a 
58          * str uri;
59          * struct contact *next;
60          * I just have to visit each uri and encode each uri according to a scheme
61          */
62         
63         if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) ||
64                                 (msg->contact == NULL) ))
65                 {
66                 LOG(L_ERR,"ERROR: encode_contact: no Contact header present\n");
67                 return -1;
68                 }
69
70
71         separator = DEFAULT_SEPARATOR[0];
72         if (contact_flds_separator != NULL)
73                 if (strlen(contact_flds_separator)>=1)
74                         separator = contact_flds_separator[0];
75         
76         if (msg->contact->parsed == NULL)       parse_contact (msg->contact);
77         if (msg->contact->parsed != NULL)
78         {
79                 cb = (contact_body_t *) msg->contact->parsed;
80                 c = cb->contacts;
81                 /* we visit each contact */
82                 if (c != NULL)
83                 {
84                         uri = &c->uri;
85                         res = encode_uri(msg, uri, encoding_prefix, public_ip,
86                                                                 separator, &newUri);
87                         
88                         if (res != 0)
89                                 {
90                                 LOG (L_ERR,"ERROR: encode_contact: Failed encoding contact.Code %d\n", res);
91                                 return res;
92                                 }
93                         else
94                                 if (patch (msg, uri->s, uri->len, newUri.s, newUri.len) < 0)
95                                 {
96                                         LOG (L_ERR,"ERROR: encode_contact: lumping failed in mangling port \n");
97                                         return -2;
98                                 }
99                         
100                         /* encoding next contacts too?*/
101 #ifdef ENCODE_ALL_CONTACTS
102                         while (c->next != NULL)
103                         {
104                                 c = c->next;
105                                 uri = &c->uri;
106                                 
107                                 res = encode_uri (msg, uri, encoding_prefix, public_ip, 
108                                                                         separator, &newUri);
109                                 if (res != 0)
110                                         {
111                                         LOG(L_ERR,"ERROR: encode_contact: Failed encode_uri.Code %d\n",res);
112 #ifdef STRICT_CHECK
113                                 return res;
114 #endif
115                                         }
116                                 else
117                                 if (patch (msg, uri->s, uri->len, newUri.s, newUri.len)< 0)
118                                 {
119                                         LOG (L_ERR,"ERROR: encode_contact: lumping failed in mangling port \n");
120                                         return -3;
121                                 }
122                         } /* while */
123 #endif /* ENCODE_ALL_CONTACTS */
124                 } /* if c != NULL */
125
126         } /* end if */
127         else /* after parsing still NULL */
128                 {
129                         LOG(L_ERR,"ERROR: encode_contact: Unable to parse Contact header\n");
130 #ifdef EXTRA_DEBUG
131                         printf("ERROR: encode_contact: Unable to parse Contact header\n");
132 #endif                        
133                         return -4;
134                 }
135 #ifdef EXTRA_DEBUG
136         fprintf (stdout,"---END--------ENCODE CONTACT-----------------\n");
137 #endif
138         return 1;
139 }
140
141 int
142 decode_contact (struct sip_msg *msg,char *unused1,char *unused2)
143 {
144
145         str* uri;
146         str newUri;
147         str dst_uri;
148         char separator;
149         int res;
150         
151
152         separator = DEFAULT_SEPARATOR[0];
153         if (contact_flds_separator != NULL)
154                 if (strlen(contact_flds_separator)>=1)
155                         separator = contact_flds_separator[0];
156                 
157         if ((msg->new_uri.s == NULL) || (msg->new_uri.len == 0)) {
158                 uri = &msg->first_line.u.request.uri;
159         }else{
160                 uri = &msg->new_uri;
161         }
162         
163         res = decode_uri (uri, separator, &newUri, &dst_uri);
164         
165         if (res != 0) {
166                         LOG (L_ERR,"ERROR: decode_contact:Failed decoding contact."
167                                                 "Code %d\n", res);
168                         return res;
169         } else {
170                 /* we do not modify the original first line */
171                 if (msg->new_uri.s)
172                         pkg_free(msg->new_uri.s);
173                 msg->new_uri = newUri;
174                 msg->parsed_uri_ok=0;
175                 msg->dst_uri = dst_uri;
176                 ruri_mark_new();
177         }
178         return 1;
179 }
180
181 int
182 decode_contact_header (struct sip_msg *msg,char *unused1,char *unused2)
183 {
184
185         contact_body_t *cb;
186         contact_t *c;
187         str* uri;
188         str newUri;
189         char separator;
190         int res;
191         
192         
193
194         if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) || 
195                                 (msg->contact== NULL) ))
196                 {
197                 LOG(L_ERR,"ERROR: decode_contact_header: no Contact header present\n");
198                 return -1;
199                 }
200
201         separator = DEFAULT_SEPARATOR[0];
202         if (contact_flds_separator != NULL)
203                 if (strlen(contact_flds_separator)>=1)
204                         separator = contact_flds_separator[0];
205                 
206         if (msg->contact->parsed == NULL) parse_contact (msg->contact);
207         if (msg->contact->parsed != NULL)
208         {
209                 cb = (contact_body_t *) msg->contact->parsed;
210                 c = cb->contacts;
211                 // we visit each contact 
212          if (c != NULL)
213           {
214                 uri = &c->uri;
215
216                 res = decode_uri (uri, separator, &newUri, 0);
217                 if (res != 0)
218                 {
219                         LOG (L_ERR,"ERROR: decode_contact_header:Failed decoding contact.Code %d\n", res);
220 #ifdef STRICT_CHECK
221                                 return res;
222 #endif
223                 }
224                 else
225                 if (patch (msg, uri->s, uri->len, newUri.s, newUri.len) < 0)
226                 {
227                         LOG (L_ERR,"ERROR: decode_contact:lumping failed in mangling port \n");
228                         return -2;
229                 }
230
231 #ifdef DECODE_ALL_CONTACTS
232                 while (c->next != NULL)
233                 {
234                         c = c->next;
235                         uri = &c->uri;
236
237                         res = decode_uri (uri, separator, &newUri, 0);
238                         if (res != 0)
239                                 {
240                                 LOG (L_ERR,"ERROR: decode_contact: Failed decoding contact.Code %d\n",res);
241 #ifdef STRICT_CHECK
242                                 return res;
243 #endif
244                                 }
245                         else
246                         if (patch (msg, uri->s, uri->len, newUri.s, newUri.len) < 0)
247                         {
248                                 LOG (L_ERR,"ERROR: decode_contact:lumping failed in mangling port \n");
249                                 return -3;
250                         }
251                 } // end while 
252 #endif
253            } // if c!= NULL 
254         } // end if 
255         else // after parsing still NULL 
256                 {
257                         LOG(L_ERR,"ERROR: decode_contact: Unable to parse Contact header\n");
258                         return -4;
259                 }
260         return 1;
261 }
262
263
264 static str      s_tcp  = STR_STATIC_INIT("tcp");
265 static str      s_tls  = STR_STATIC_INIT("tls");
266 static str      s_sctp = STR_STATIC_INIT("sctp");
267
268
269
270 int
271 encode2format (struct sip_msg* msg, str* uri, struct uri_format *format)
272 {
273         int foo;
274         char *string, *pos, *start, *end;
275         struct sip_uri sipUri;
276         int scheme_len;
277
278
279         if (uri->s == NULL)
280                 return -1;
281         string = uri->s;
282
283
284         pos = q_memchr (string, '<', uri->len);
285         if (pos != NULL)        /* we are only interested of chars inside <> */
286         {
287                 start = q_memchr (string, ':', uri->len);
288                 if (start == NULL)      return -2;
289                 if (start - pos < 4) return -3;
290                 if ((*(start-1)|0x20)=='s' && (start-pos)>4)
291                         /* if it ends in s: it is a sips or tels uri */
292                         scheme_len=4;
293                 else
294                         scheme_len=3;
295                 start-=scheme_len;
296                 end = strchr (start, '>');
297                 if (end == NULL)
298                         return -4;      /* must be a match to < */
299         }
300         else                    /* we do not have  <> */
301         {
302                 pos=string;
303                 start = q_memchr (string, ':', uri->len);
304                 if (start == NULL)
305                         return -5;
306                 if (start - pos < 3)
307                         return -6;
308                 if ((*(start-1)|0x20)=='s' && (start-pos)>3)
309                         /* if it ends in s: it is a sips or tels uri */
310                         scheme_len=4;
311                 else
312                         scheme_len=3;
313                 start = start - scheme_len;
314                 end = string + uri->len;
315         }
316         memset(format,0,sizeof(struct uri_format));
317         format->first = start - string + scheme_len+1 /* ':' */;
318         format->second = end - string;
319         /* --------------------------testing ------------------------------- */
320         /* sip:gva@pass@10.0.0.1;;transport=udp>;expires=2 INCORECT BEHAVIOR OF parse_uri,myfunction works good */
321         foo = parse_uri (start, end - start, &sipUri);
322         if (foo != 0)
323         {
324                 LOG(L_ERR,"ERROR: encode2format: parse_uri failed on [%.*s]."
325                                 "Code %d \n", uri->len, uri->s, foo);
326                 return foo-10;
327         }
328
329         
330         format->username = sipUri.user;
331         format->password = sipUri.passwd;
332         format->ip = sipUri.host;
333         format->port = sipUri.port;
334         format->protocol = sipUri.transport_val;
335         format->transport=sipUri.transport; /* the whole transport header */
336         format->rest.s = sipUri.port.s?(sipUri.port.s+sipUri.port.len):
337                                                 (sipUri.host.s+sipUri.host.len);
338         format->rest.len = (int)(end-format->rest.s);
339         format->rcv_ip.s=ip_addr2a(&msg->rcv.src_ip);
340         format->rcv_ip.len=strlen(format->rcv_ip.s);
341         if (msg->rcv.src_port!=SIP_PORT){
342                 format->rcv_port.s=
343                                 int2str(msg->rcv.src_port, &format->rcv_port.len);
344         }else{
345                 format->rcv_port.s=0;
346                 format->rcv_port.len=0;
347         }
348         if (msg->rcv.proto!=PROTO_UDP){
349                 switch(msg->rcv.proto){
350                         case PROTO_TCP:
351                                 format->rcv_proto=s_tcp;
352                                 break;
353                         case PROTO_TLS:
354                                 format->rcv_proto=s_tls;
355                                 break;
356                         case PROTO_SCTP:
357                                 format->rcv_proto=s_sctp;
358                                 break;
359                         default:
360                                 BUG("unknown proto %d\n", msg->rcv.proto);
361                 }
362         }else{
363                 format->rcv_proto.s=0;
364                 format->rcv_proto.len=0;
365         }
366         
367 #ifdef EXTRA_DEBUG      
368         fprintf (stdout, "transport=[%.*s] transportval=[%.*s]\n", sipUri.transport.len,sipUri.transport.s,sipUri.transport_val.len,sipUri.transport_val.s);
369         fprintf(stdout,"First %d,second %d\n",format->first,format->second);
370         #endif
371         
372         return 0;
373
374 }
375
376
377 int
378 encode_uri (struct sip_msg* msg, str* uri, char *encoding_prefix,
379                                 char *public_ip,char separator, str * result)
380 {
381         struct uri_format format;
382         char *pos;
383         int foo,res;
384
385         
386         result->s = NULL;
387         result->len = 0;
388         if (uri->len <= 1)
389                 return -1;      /* no contact or an invalid one */
390         if (public_ip == NULL) 
391                 {
392                         LOG(L_ERR,"ERROR: encode_uri: Invalid NULL value for public_ip parameter\n");
393                         return -2;
394                 }
395         foo = encode2format (msg, uri, &format);
396         if (foo < 0)
397                 {
398                 LOG(L_ERR,"ERROR: encode_uri: Unable to encode Contact URI"
399                                 " [%.*s].Return code %d\n",uri->len, uri->s, foo);
400                 return foo - 20;
401                 }
402
403         /* a complete uri would be sip:username@ip:port;transport=protocol goes to
404          * sip:enc_pref*username*ip*port*protocol@public_ip
405          */
406
407         foo = 1;                /*strlen(separator); */
408         result->len = format.first + uri->s+uri->len - format.rest.s +
409                 strlen (encoding_prefix) + foo +
410                 format.username.len + foo +
411                 format.password.len + foo +
412                 format.ip.len + foo + format.port.len + foo +
413                 format.protocol.len + foo + format.rcv_ip.len + foo +
414                 format.rcv_port.len + foo + format.rcv_proto.len +
415                 1 + strlen (public_ip);
416         /* adding one comes from @ */
417         result->s = pkg_malloc (result->len);
418         pos = result->s;
419         if (pos == NULL)
420                 {
421                         LOG(L_ERR,"ERROR: encode_uri:Unable to alloc memory\n");
422                         return -3;
423                 }
424                 
425         res = snprintf(pos,result->len,"%.*s%s%c%.*s%c%.*s%c%.*s%c%.*s%c%.*s%c"
426                                                                         "%.*s%c%.*s%c%.*s@",
427                         format.first, uri->s,encoding_prefix,separator,
428                         format.username.len,format.username.s,separator,
429                         format.password.len,format.password.s,
430                         separator,format.ip.len,format.ip.s,separator,format.port.len,
431                         format.port.s,separator,format.protocol.len,format.protocol.s,
432                         separator, format.rcv_ip.len, format.rcv_ip.s, separator,
433                         format.rcv_port.len, format.rcv_port.s, separator,
434                         format.rcv_proto.len, format.rcv_proto.s
435                         );
436
437         if ((res < 0 )||(res>result->len)) 
438                 {
439                         LOG(L_ERR,"ERROR: encode_uri: Unable to construct new uri.\n");
440                         if (result->s != NULL) pkg_free(result->s);
441                         return -4;
442                 }
443         pos = pos + res ;/* overwriting the \0 from snprintf */
444         memcpy (pos, public_ip, strlen (public_ip));
445         pos = pos + strlen (public_ip);
446         /* copy the rest of the parameters and the rest of uri line*/
447         memcpy (pos, format.rest.s, uri->s+uri->len - format.rest.s);
448         /*memcpy (pos, uri.s + format.second, uri.len - format.second);*/
449
450         /* Because called parse_uri format contains pointers to the inside of msg,
451          *  must not deallocate */
452
453         return 0;
454 }
455
456
457 int
458 decode2format (str* uri, char separator, struct uri_format *format)
459 {
460         char *start, *end, *pos,*lastpos;
461         str tmp;
462         enum {EX_PREFIX=0,EX_USER,EX_PASS,EX_IP,EX_PORT,EX_PROT, EX_RCVIP,
463                         EX_RCVPORT, EX_RCVPROTO, EX_FINAL} state;
464
465         memset (format, 0, sizeof(struct uri_format));
466
467         if (uri->s == NULL)
468                 {
469                 LOG(L_ERR,"ERROR: decode2format: Invalid parameter uri.It is NULL\n");
470                 return -1;
471                 }
472         /* sip:enc_pref*username*password*ip*port*protocol@public_ip */
473         
474         start = q_memchr (uri->s, ':', uri->len);
475         if (start == NULL)
476         {
477                 LOG(L_ERR,"ERROR: decode2format: Invalid SIP uri.Missing :\n");
478                 return -2;
479         }                       /* invalid uri */
480         start = start + 1;
481         if (start >= (uri->s+uri->len)){
482                 LOG(L_ERR, "ERROR: decode2format> Invalid sip uri: too short: %.*s\n",
483                                 uri->len, uri->s);
484                 return -2;
485         }
486         format->first = start - uri->s;
487         
488         /* start */
489
490         end = q_memchr(start,'@',uri->len-(start-uri->s));
491         if (end == NULL) 
492                 {
493                 LOG(L_ERR,"ERROR: decode2format: Invalid SIP uri.Missing @\n");
494                 return -3;/* no host address found */
495                 }
496
497 #ifdef EXTRA_DEBUG
498                 fprintf (stdout, "Decoding %.*s\n",(int)(long)(end-start), start);
499 #endif
500         
501         state = EX_PREFIX;
502         lastpos = start;
503         
504         for (pos = start;pos<end;pos++)
505                 {
506                         if (*pos == separator)
507                                 {
508                                         /* we copy between lastpos and pos */
509                                         tmp.len = pos - lastpos;
510                                         if (tmp.len>0) tmp.s = lastpos;
511                                                 else tmp.s = NULL;
512                                         switch (state)
513                                                 {
514                                                         case EX_PREFIX: state = EX_USER;break;
515                                                         case EX_USER:format->username = tmp;state = EX_PASS;break;
516                                                         case EX_PASS:format->password = tmp;state = EX_IP;break;
517                                                         case EX_IP:format->ip = tmp;state = EX_PORT;break;
518                                                         case EX_PORT:format->port = tmp;state = EX_PROT;break;
519                                                         case EX_PROT:
520                                                                                  format->protocol=tmp;
521                                                                                  state=EX_RCVIP;
522                                                                                  break;
523                                                         case EX_RCVIP:
524                                                                                  format->rcv_ip=tmp;
525                                                                                  state=EX_RCVPORT;
526                                                                                  break;
527                                                         case EX_RCVPORT:
528                                                                                  format->rcv_port=tmp;
529                                                                                  state=EX_RCVPROTO;
530                                                                                  break;
531                                                         default:
532                                                                 {
533                                                                 /* this should not happen, we should find @ not separator */
534                                                                 return -4;
535                                                                 break;
536                                                                 }
537                                                 }
538                                                 
539                                         lastpos = pos+1;
540                                 
541                                 }
542                         else
543                         if (((*pos) == '>')||(*pos == ';'))
544                                 {
545                                 /* invalid chars inside username part */
546                                 return -5;
547                                 }
548                 }
549                 
550                 
551         /* we must be in state EX_RCVPROTO and protocol is between lastpos and 
552          * end@ */
553         if (state != EX_RCVPROTO) return -6;
554         format->rcv_proto.len = end - lastpos;
555         if (format->rcv_proto.len>0) format->rcv_proto.s = lastpos;
556         /* I should check perhaps that  after @ there is something */
557                 
558         /* looking for the end of public ip */
559         start = end;/*we are now at @ */
560         for(pos = start;pos<(uri->s+uri->len);pos++)
561                 {
562                         if ((*pos == ';')||(*pos == '>'))
563                                 {
564                                 /* found end */
565                                 format->second = pos - uri->s;
566                                 return 0;
567                                 }
568                 }
569         /* if we are here we did not find > or ; */
570         format->second = uri->len;
571         return 0;       
572         
573 }
574
575
576 int
577 decode_uri (str* uri, char separator, str * result, str* dst_uri)
578 {
579         char *pos;
580         struct uri_format format;
581         int foo;
582
583         result->s = NULL;
584         result->len = 0;
585         if (dst_uri){
586                 dst_uri->s=0;
587                 dst_uri->len=0;
588         }
589
590         if ((uri->len <= 0) || (uri->s == NULL))
591                 {
592                 LOG(L_ERR,"ERROR: decode_uri: Invalid value for uri\n");
593                 return -1;
594                 }
595
596         foo = decode2format (uri, separator, &format);
597         if (foo < 0)
598                 {
599                 LOG(L_ERR,"ERROR: decode_uri: Error decoding Contact uri .Error code %d\n",foo);
600                 return foo - 20;
601                 }
602         /* sanity check */
603         if (format.ip.len <= 0)
604                 {
605                         LOG(L_ERR,"ERROR: decode_uri: Unable to decode host address \n");
606                         return -2;/* should I quit or ignore ? */
607                 }                       
608
609         if ((format.password.len > 0) && (format.username.len <= 0))
610                 {
611                         LOG(L_ERR,"ERROR: decode_uri: Password decoded but no username available\n");
612                         return -3;
613                 }
614                 
615         /* a complete uri would be sip:username:password@ip:port;transport=protocol goes to
616          * sip:enc_pref#username#password#ip#port#protocol@public_ip
617          */
618         result->len = format.first + (uri->len - format.second);        /* not NULL terminated */
619         if (format.username.len > 0) result->len += format.username.len + 1;    //: or @
620         if (format.password.len > 0) result->len += format.password.len + 1;    //@
621                 
622         /* if (format.ip.len > 0) */         result->len += format.ip.len;
623                 
624         if (format.port.len > 0)     result->len += 1 + format.port.len;        //:
625         if (format.protocol.len > 0) result->len += 1 + 10 + format.protocol.len;       //;transport=
626         
627         /* adding one comes from * */
628         result->s = pkg_malloc (result->len);
629         if (result->s == NULL)
630                 {
631                         LOG(L_ERR,"ERROR: decode_contact: Unable to allocate memory\n");
632                         return -4;
633                 }
634         pos = result->s;
635         memcpy (pos, uri->s, format.first);     /* till sip: */
636         pos = pos + format.first;
637         
638         if (format.username.len > 0)
639         {
640                 memcpy (pos, format.username.s, format.username.len);
641                 pos = pos + format.username.len;
642                 if (format.password.len > 0)
643                         memcpy (pos, ":", 1);
644                 else
645                         memcpy (pos, "@", 1);
646                 pos = pos + 1;
647         }
648         if (format.password.len > 0)
649         {
650                 memcpy (pos, format.password.s, format.password.len);
651                 pos = pos + format.password.len;
652                 memcpy (pos, "@", 1);
653                 pos = pos + 1;
654         }
655         /* if (format.ip.len > 0) */
656
657                 memcpy (pos, format.ip.s, format.ip.len);
658                 pos = pos + format.ip.len;
659         
660         if (format.port.len > 0)
661         {
662                 memcpy (pos, ":", 1);
663                 pos = pos + 1;
664                 memcpy (pos, format.port.s, format.port.len);
665                 pos = pos + format.port.len;
666         }
667         if (format.protocol.len > 0)
668         {
669                 memcpy (pos, ";transport=", 11);
670                 pos = pos + 11;
671                 memcpy (pos, format.protocol.s, format.protocol.len);
672                 pos = pos + format.protocol.len;
673         }
674         
675         memcpy (pos, uri->s + format.second, uri->len - format.second); /* till end: */
676         
677         /* dst_uri */
678         if (dst_uri && format.rcv_ip.s){
679                 dst_uri->len=4 /* sip: */ + format.rcv_ip.len;
680                 if (format.rcv_port.len){
681                         dst_uri->len+=1 /* : */+format.rcv_port.len;
682                 }
683                 if (format.rcv_proto.len){
684                         dst_uri->len+=TRANSPORT_PARAM_LEN+format.rcv_proto.len;
685                 }
686                 dst_uri->s=pkg_malloc(dst_uri->len);
687                 if (dst_uri->s==0){
688                         LOG(L_ERR,"ERROR: decode_contact: dst_uri: memory allocation"
689                                         " failed\n");
690                         dst_uri->len=0;
691                         pkg_free(result->s);
692                         result->s=0;
693                         result->len=0;
694                         return -4;
695                 }
696                 pos=dst_uri->s;
697                 memcpy(pos, SIP_SCH, SIP_SCH_LEN);
698                 pos+=SIP_SCH_LEN;
699                 memcpy(pos, format.rcv_ip.s, format.rcv_ip.len);
700                 pos+=format.rcv_ip.len;
701                 if (format.rcv_port.len){
702                         *pos=':';
703                         pos++;
704                         memcpy(pos, format.rcv_port.s, format.rcv_port.len);
705                         pos+=format.rcv_port.len;
706                 }
707                 if (format.rcv_proto.len){
708                         memcpy(pos, TRANSPORT_PARAM, TRANSPORT_PARAM_LEN);
709                         pos+=TRANSPORT_PARAM_LEN;
710                         memcpy(pos, format.rcv_proto.s, format.rcv_proto.len);
711                 }
712         }
713         return 0;
714 }
715