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
23 #include "contact_ops.h"
26 #include "../../core/mem/mem.h"
27 #include "../../core/data_lump.h"
28 #include "../../core/parser/hf.h"
29 #include "../../core/parser/parse_uri.h"
30 #include "../../core/parser/contact/parse_contact.h"
31 #include "../../core/ut.h"
32 #include "../../core/dset.h"
37 #define SIP_SCH "sip:"
38 #define SIP_SCH_LEN (sizeof(SIP_SCH)-1)
42 encode_contact (struct sip_msg *msg, char *encoding_prefix,char *public_ip)
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
59 * struct contact *next;
60 * I just have to visit each uri and encode each uri according to a scheme
63 if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) ||
64 (msg->contact == NULL) ))
66 LOG(L_ERR,"ERROR: encode_contact: no Contact header present\n");
71 separator = DEFAULT_SEPARATOR[0];
72 if (contact_flds_separator != NULL)
73 if (strlen(contact_flds_separator)>=1)
74 separator = contact_flds_separator[0];
76 if (msg->contact->parsed == NULL) parse_contact (msg->contact);
77 if (msg->contact->parsed != NULL)
79 cb = (contact_body_t *) msg->contact->parsed;
81 /* we visit each contact */
85 res = encode_uri(msg, uri, encoding_prefix, public_ip,
90 LOG (L_ERR,"ERROR: encode_contact: Failed encoding contact.Code %d\n", res);
94 if (patch (msg, uri->s, uri->len, newUri.s, newUri.len) < 0)
96 LOG (L_ERR,"ERROR: encode_contact: lumping failed in mangling port \n");
100 /* encoding next contacts too?*/
101 #ifdef ENCODE_ALL_CONTACTS
102 while (c->next != NULL)
107 res = encode_uri (msg, uri, encoding_prefix, public_ip,
111 LOG(L_ERR,"ERROR: encode_contact: Failed encode_uri.Code %d\n",res);
117 if (patch (msg, uri->s, uri->len, newUri.s, newUri.len)< 0)
119 LOG (L_ERR,"ERROR: encode_contact: lumping failed in mangling port \n");
123 #endif /* ENCODE_ALL_CONTACTS */
127 else /* after parsing still NULL */
129 LOG(L_ERR,"ERROR: encode_contact: Unable to parse Contact header\n");
131 printf("ERROR: encode_contact: Unable to parse Contact header\n");
136 fprintf (stdout,"---END--------ENCODE CONTACT-----------------\n");
142 decode_contact (struct sip_msg *msg,char *unused1,char *unused2)
152 separator = DEFAULT_SEPARATOR[0];
153 if (contact_flds_separator != NULL)
154 if (strlen(contact_flds_separator)>=1)
155 separator = contact_flds_separator[0];
157 if ((msg->new_uri.s == NULL) || (msg->new_uri.len == 0)) {
158 uri = &msg->first_line.u.request.uri;
163 res = decode_uri (uri, separator, &newUri, &dst_uri);
166 LOG (L_ERR,"ERROR: decode_contact:Failed decoding contact."
170 /* we do not modify the original first line */
172 pkg_free(msg->new_uri.s);
173 msg->new_uri = newUri;
174 msg->parsed_uri_ok=0;
175 msg->dst_uri = dst_uri;
182 decode_contact_header (struct sip_msg *msg,char *unused1,char *unused2)
194 if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) ||
195 (msg->contact== NULL) ))
197 LOG(L_ERR,"ERROR: decode_contact_header: no Contact header present\n");
201 separator = DEFAULT_SEPARATOR[0];
202 if (contact_flds_separator != NULL)
203 if (strlen(contact_flds_separator)>=1)
204 separator = contact_flds_separator[0];
206 if (msg->contact->parsed == NULL) parse_contact (msg->contact);
207 if (msg->contact->parsed != NULL)
209 cb = (contact_body_t *) msg->contact->parsed;
211 // we visit each contact
216 res = decode_uri (uri, separator, &newUri, 0);
219 LOG (L_ERR,"ERROR: decode_contact_header:Failed decoding contact.Code %d\n", res);
225 if (patch (msg, uri->s, uri->len, newUri.s, newUri.len) < 0)
227 LOG (L_ERR,"ERROR: decode_contact:lumping failed in mangling port \n");
231 #ifdef DECODE_ALL_CONTACTS
232 while (c->next != NULL)
237 res = decode_uri (uri, separator, &newUri, 0);
240 LOG (L_ERR,"ERROR: decode_contact: Failed decoding contact.Code %d\n",res);
246 if (patch (msg, uri->s, uri->len, newUri.s, newUri.len) < 0)
248 LOG (L_ERR,"ERROR: decode_contact:lumping failed in mangling port \n");
255 else // after parsing still NULL
257 LOG(L_ERR,"ERROR: decode_contact: Unable to parse Contact header\n");
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");
271 encode2format (struct sip_msg* msg, str* uri, struct uri_format *format)
274 char *string, *pos, *start, *end;
275 struct sip_uri sipUri;
284 pos = q_memchr (string, '<', uri->len);
285 if (pos != NULL) /* we are only interested of chars inside <> */
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 */
296 end = strchr (start, '>');
298 return -4; /* must be a match to < */
300 else /* we do not have <> */
303 start = q_memchr (string, ':', uri->len);
308 if ((*(start-1)|0x20)=='s' && (start-pos)>3)
309 /* if it ends in s: it is a sips or tels uri */
313 start = start - scheme_len;
314 end = string + uri->len;
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);
324 LOG(L_ERR,"ERROR: encode2format: parse_uri failed on [%.*s]."
325 "Code %d \n", uri->len, uri->s, foo);
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){
343 int2str(msg->rcv.src_port, &format->rcv_port.len);
345 format->rcv_port.s=0;
346 format->rcv_port.len=0;
348 if (msg->rcv.proto!=PROTO_UDP){
349 switch(msg->rcv.proto){
351 format->rcv_proto=s_tcp;
354 format->rcv_proto=s_tls;
357 format->rcv_proto=s_sctp;
360 BUG("unknown proto %d\n", msg->rcv.proto);
363 format->rcv_proto.s=0;
364 format->rcv_proto.len=0;
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);
378 encode_uri (struct sip_msg* msg, str* uri, char *encoding_prefix,
379 char *public_ip,char separator, str * result)
381 struct uri_format format;
389 return -1; /* no contact or an invalid one */
390 if (public_ip == NULL)
392 LOG(L_ERR,"ERROR: encode_uri: Invalid NULL value for public_ip parameter\n");
395 foo = encode2format (msg, uri, &format);
398 LOG(L_ERR,"ERROR: encode_uri: Unable to encode Contact URI"
399 " [%.*s].Return code %d\n",uri->len, uri->s, foo);
403 /* a complete uri would be sip:username@ip:port;transport=protocol goes to
404 * sip:enc_pref*username*ip*port*protocol@public_ip
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);
421 LOG(L_ERR,"ERROR: encode_uri:Unable to alloc memory\n");
425 res = snprintf(pos,result->len,"%.*s%s%c%.*s%c%.*s%c%.*s%c%.*s%c%.*s%c"
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
437 if ((res < 0 )||(res>result->len))
439 LOG(L_ERR,"ERROR: encode_uri: Unable to construct new uri.\n");
440 if (result->s != NULL) pkg_free(result->s);
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);*/
450 /* Because called parse_uri format contains pointers to the inside of msg,
451 * must not deallocate */
458 decode2format (str* uri, char separator, struct uri_format *format)
460 char *start, *end, *pos,*lastpos;
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;
465 memset (format, 0, sizeof(struct uri_format));
469 LOG(L_ERR,"ERROR: decode2format: Invalid parameter uri.It is NULL\n");
472 /* sip:enc_pref*username*password*ip*port*protocol@public_ip */
474 start = q_memchr (uri->s, ':', uri->len);
477 LOG(L_ERR,"ERROR: decode2format: Invalid SIP uri.Missing :\n");
481 if (start >= (uri->s+uri->len)){
482 LOG(L_ERR, "ERROR: decode2format> Invalid sip uri: too short: %.*s\n",
486 format->first = start - uri->s;
490 end = q_memchr(start,'@',uri->len-(start-uri->s));
493 LOG(L_ERR,"ERROR: decode2format: Invalid SIP uri.Missing @\n");
494 return -3;/* no host address found */
498 fprintf (stdout, "Decoding %.*s\n",(int)(long)(end-start), start);
504 for (pos = start;pos<end;pos++)
506 if (*pos == separator)
508 /* we copy between lastpos and pos */
509 tmp.len = pos - lastpos;
510 if (tmp.len>0) tmp.s = lastpos;
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;
520 format->protocol=tmp;
528 format->rcv_port=tmp;
533 /* this should not happen, we should find @ not separator */
543 if (((*pos) == '>')||(*pos == ';'))
545 /* invalid chars inside username part */
551 /* we must be in state EX_RCVPROTO and protocol is between lastpos and
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 */
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++)
562 if ((*pos == ';')||(*pos == '>'))
565 format->second = pos - uri->s;
569 /* if we are here we did not find > or ; */
570 format->second = uri->len;
577 decode_uri (str* uri, char separator, str * result, str* dst_uri)
580 struct uri_format format;
590 if ((uri->len <= 0) || (uri->s == NULL))
592 LOG(L_ERR,"ERROR: decode_uri: Invalid value for uri\n");
596 foo = decode2format (uri, separator, &format);
599 LOG(L_ERR,"ERROR: decode_uri: Error decoding Contact uri .Error code %d\n",foo);
603 if (format.ip.len <= 0)
605 LOG(L_ERR,"ERROR: decode_uri: Unable to decode host address \n");
606 return -2;/* should I quit or ignore ? */
609 if ((format.password.len > 0) && (format.username.len <= 0))
611 LOG(L_ERR,"ERROR: decode_uri: Password decoded but no username available\n");
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
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; //@
622 /* if (format.ip.len > 0) */ result->len += format.ip.len;
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=
627 /* adding one comes from * */
628 result->s = pkg_malloc (result->len);
629 if (result->s == NULL)
631 LOG(L_ERR,"ERROR: decode_contact: Unable to allocate memory\n");
635 memcpy (pos, uri->s, format.first); /* till sip: */
636 pos = pos + format.first;
638 if (format.username.len > 0)
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);
645 memcpy (pos, "@", 1);
648 if (format.password.len > 0)
650 memcpy (pos, format.password.s, format.password.len);
651 pos = pos + format.password.len;
652 memcpy (pos, "@", 1);
655 /* if (format.ip.len > 0) */
657 memcpy (pos, format.ip.s, format.ip.len);
658 pos = pos + format.ip.len;
660 if (format.port.len > 0)
662 memcpy (pos, ":", 1);
664 memcpy (pos, format.port.s, format.port.len);
665 pos = pos + format.port.len;
667 if (format.protocol.len > 0)
669 memcpy (pos, ";transport=", 11);
671 memcpy (pos, format.protocol.s, format.protocol.len);
672 pos = pos + format.protocol.len;
675 memcpy (pos, uri->s + format.second, uri->len - format.second); /* till end: */
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;
683 if (format.rcv_proto.len){
684 dst_uri->len+=TRANSPORT_PARAM_LEN+format.rcv_proto.len;
686 dst_uri->s=pkg_malloc(dst_uri->len);
688 LOG(L_ERR,"ERROR: decode_contact: dst_uri: memory allocation"
697 memcpy(pos, SIP_SCH, 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){
704 memcpy(pos, format.rcv_port.s, format.rcv_port.len);
705 pos+=format.rcv_port.len;
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);