2 The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3 Copyright (C) 2001,2002,2003 Aymeric MOIZARD jack@atosc.org
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <osipparser2/osip_port.h>
24 #include <osipparser2/osip_message.h>
25 #include <osipparser2/osip_parser.h>
28 /* adds the via header to message. */
29 /* INPUT : const char *hvalue | value of header. */
30 /* OUTPUT: osip_message_t *sip | structure to save results. */
31 /* returns -1 on error. */
33 osip_message_set_via (osip_message_t * sip, const char *hvalue)
38 if (hvalue == NULL || hvalue[0] == '\0')
41 i = osip_via_init (&via);
44 i = osip_via_parse (via, hvalue);
50 sip->message_property = 2;
51 osip_list_add (sip->vias, via, -1);
55 /* adds the via header to message in the first position. (to be used by proxy) */
56 /* INPUT : const char *hvalue | value of header. */
57 /* OUTPUT: osip_message_t *sip | structure to save results. */
58 /* returns -1 on error. */
60 osip_message_append_via (osip_message_t * sip, const char *hvalue)
65 i = osip_via_init (&via);
68 i = osip_via_parse (via, hvalue);
74 sip->message_property = 2;
75 osip_list_add (sip->vias, via, 0);
79 /* returns the via header. */
80 /* INPUT : int pos | pos of via header. */
81 /* INPUT : osip_message_t *sip | sip message. */
82 /* OUTPUT: osip_via_t *via | structure to save results. */
83 /* returns null on error. */
85 osip_message_get_via (const osip_message_t * sip, int pos, osip_via_t ** dest)
90 if (osip_list_size (sip->vias) <= pos)
92 *dest = (osip_via_t *) osip_list_get (sip->vias, pos);
99 osip_via_init (osip_via_t ** via)
101 *via = (osip_via_t *) osip_malloc (sizeof (osip_via_t));
104 (*via)->version = NULL;
105 (*via)->protocol = NULL;
108 (*via)->comment = NULL;
110 (*via)->via_params = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
111 if ((*via)->via_params == NULL)
117 osip_list_init ((*via)->via_params);
123 osip_via_free (osip_via_t * via)
127 osip_free (via->version);
128 osip_free (via->protocol);
129 osip_free (via->host);
130 osip_free (via->port);
131 osip_free (via->comment);
132 osip_generic_param_freelist (via->via_params);
138 osip_via_parse (osip_via_t * via, const char *hvalue)
141 const char *protocol;
143 const char *ipv6host;
145 const char *via_params;
148 version = strchr (hvalue, '/');
152 protocol = strchr (version + 1, '/');
153 if (protocol == NULL)
156 /* set the version */
157 if (protocol - version < 2)
159 via->version = (char *) osip_malloc (protocol - version);
160 if (via->version == NULL)
162 osip_strncpy (via->version, version + 1, protocol - version - 1);
163 osip_clrspace (via->version);
165 /* Here: we avoid matching an additionnal space */
166 host = strchr (protocol + 1, ' ');
168 return -1; /* fixed in 0.8.4 */
169 if (host == protocol + 1) /* there are extra SPACE characters */
171 while (0 == strncmp (host, " ", 1))
174 if (strlen (host) == 1)
175 return -1; /* via is malformed */
177 /* here, we match the real space located after the protocol name */
178 host = strchr (host + 1, ' ');
180 return -1; /* fixed in 0.8.4 */
183 /* set the protocol */
184 if (host - protocol < 2)
186 via->protocol = (char *) osip_malloc (host - protocol);
187 if (via->protocol == NULL)
189 osip_strncpy (via->protocol, protocol + 1, host - protocol - 1);
190 osip_clrspace (via->protocol);
192 /* comments in Via are not allowed any more in the latest draft (09) */
193 comment = strchr (host, '(');
199 end_comment = strchr (host, ')');
200 if (end_comment == NULL)
201 return -1; /* if '(' exist ')' MUST exist */
202 if (end_comment - comment < 2)
204 via->comment = (char *) osip_malloc (end_comment - comment);
205 if (via->comment == NULL)
207 osip_strncpy (via->comment, comment + 1, end_comment - comment - 1);
211 comment = host + strlen (host);
213 via_params = strchr (host, ';');
215 if ((via_params != NULL) && (via_params < comment))
216 /* via params exist */
220 if (comment - via_params + 1 < 2)
222 tmp = (char *) osip_malloc (comment - via_params + 1);
225 osip_strncpy (tmp, via_params, comment - via_params);
226 __osip_generic_param_parseall (via->via_params, tmp);
230 if (via_params == NULL)
231 via_params = comment;
233 /* add ipv6 support (0.8.4) */
234 /* Via: SIP/2.0/UDP [mlke::zeezf:ezfz:zef:zefzf]:port;.... */
235 ipv6host = strchr (host, '[');
236 if (ipv6host != NULL && ipv6host < via_params)
238 port = strchr (ipv6host, ']');
239 if (port == NULL || port > via_params)
242 if (port - ipv6host < 2)
244 via->host = (char *) osip_malloc (port - ipv6host);
245 if (via->host == NULL)
247 osip_strncpy (via->host, ipv6host + 1, port - ipv6host - 1);
248 osip_clrspace (via->host);
250 port = strchr (port, ':');
254 port = strchr (host, ':');
258 if ((port != NULL) && (port < via_params))
260 if (via_params - port < 2)
262 via->port = (char *) osip_malloc (via_params - port);
263 if (via->port == NULL)
265 osip_strncpy (via->port, port + 1, via_params - port - 1);
266 osip_clrspace (via->port);
271 /* host is already set in the case of ipv6 */
272 if (ipv6host != NULL)
277 via->host = (char *) osip_malloc (port - host);
278 if (via->host == NULL)
280 osip_strncpy (via->host, host + 1, port - host - 1);
281 osip_clrspace (via->host);
287 /* returns the via header as a string. */
288 /* INPUT : osip_via_t via* | via header. */
289 /* returns null on error. */
291 osip_via_to_str (const osip_via_t * via, char **dest)
299 if ((via == NULL) || (via->host == NULL)
300 || (via->version == NULL) || (via->protocol == NULL))
303 len = strlen (via->version) + 1 + strlen (via->protocol) + 1 + 3 + 2; /* sip/xxx/xxx */
304 len = len + strlen (via->host) + 3 + 1;
305 if (via->port != NULL)
306 len = len + strlen (via->port) + 2;
308 buf = (char *) osip_malloc (len);
312 if (strchr (via->host, ':') != NULL)
314 if (via->port == NULL)
315 sprintf (buf, "SIP/%s/%s [%s]", via->version, via->protocol,
318 sprintf (buf, "SIP/%s/%s [%s]:%s", via->version, via->protocol,
319 via->host, via->port);
323 if (via->port == NULL)
324 sprintf (buf, "SIP/%s/%s %s", via->version, via->protocol, via->host);
326 sprintf (buf, "SIP/%s/%s %s:%s", via->version, via->protocol,
327 via->host, via->port);
334 osip_generic_param_t *u_param;
336 while (!osip_list_eol (via->via_params, pos))
339 (osip_generic_param_t *) osip_list_get (via->via_params, pos);
341 if (u_param->gvalue == NULL)
342 plen = strlen (u_param->gname) + 2;
344 plen = strlen (u_param->gname) + strlen (u_param->gvalue) + 3;
346 buf = (char *) realloc (buf, len);
348 tmp = tmp + strlen (tmp);
349 if (u_param->gvalue == NULL)
350 sprintf (tmp, ";%s", u_param->gname);
352 sprintf (tmp, ";%s=%s", u_param->gname, u_param->gvalue);
357 if (via->comment != NULL)
359 len = len + strlen (via->comment) + 4;
360 buf = (char *) realloc (buf, len);
362 tmp = tmp + strlen (tmp);
363 sprintf (tmp, " (%s)", via->comment);
370 via_set_version (osip_via_t * via, char *version)
372 via->version = version;
376 via_get_version (osip_via_t * via)
384 via_set_protocol (osip_via_t * via, char *protocol)
386 via->protocol = protocol;
390 via_get_protocol (osip_via_t * via)
394 return via->protocol;
398 via_set_host (osip_via_t * via, char *host)
404 via_get_host (osip_via_t * via)
412 via_set_port (osip_via_t * via, char *port)
418 via_get_port (osip_via_t * via)
426 via_set_comment (osip_via_t * via, char *comment)
428 via->comment = comment;
432 via_get_comment (osip_via_t * via)
440 osip_via_clone (const osip_via_t * via, osip_via_t ** dest)
448 if (via->version == NULL)
450 if (via->protocol == NULL)
452 if (via->host == NULL)
455 i = osip_via_init (&vi);
458 vi->version = osip_strdup (via->version);
459 vi->protocol = osip_strdup (via->protocol);
460 vi->host = osip_strdup (via->host);
461 if (via->port != NULL)
462 vi->port = osip_strdup (via->port);
463 if (via->comment != NULL)
464 vi->comment = osip_strdup (via->comment);
468 osip_generic_param_t *u_param;
469 osip_generic_param_t *dest_param;
471 while (!osip_list_eol (via->via_params, pos))
474 (osip_generic_param_t *) osip_list_get (via->via_params, pos);
475 i = osip_generic_param_clone (u_param, &dest_param);
481 osip_list_add (vi->via_params, dest_param, -1);
490 osip_via_match (osip_via_t * via1, osip_via_t * via2)
492 /* Can I really compare it this way??
493 There exist matching rules for via header, but this method
494 should only be used to detect retransmissions so the result should
495 be exactly equivalent. (This may not be true if the retransmission
496 traverse a different set of proxy... */
501 if (via1 == NULL || via2 == NULL)
503 i = osip_via_to_str (via1, &_via1);
506 i = osip_via_to_str (via2, &_via2);
513 i = strcmp (_via1, _via2);