/*
The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
Copyright (C) 2001,2002,2003,2004,2005 Aymeric MOIZARD jack@atosc.org
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <osipparser2/osip_const.h>
#include <osipparser2/sdp_message.h>
#include <osipparser2/osip_message.h>
#include <osipparser2/osip_port.h>
#include <stdio.h>
#include <stdlib.h>
#define ERR_ERROR -1 /* bad header */
#define ERR_DISCARD 0 /* wrong header */
#define WF 1 /* well formed header */
static int sdp_message_parse_v (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_o (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_s (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_i (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_u (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_e (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_p (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_c (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_b (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_t (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_r (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_z (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_k (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_a (sdp_message_t * sdp, char *buf, char **next);
static int sdp_message_parse_m (sdp_message_t * sdp, char *buf, char **next);
static int sdp_append_media (char *string, int size, char *tmp,
sdp_media_t * media, char **next_tmp);
static int sdp_append_attribute (char *string, int size, char *tmp,
sdp_attribute_t * attribute, char **next_tmp);
static int sdp_append_key (char *string, int size, char *tmp, sdp_key_t * key,
char **next_tmp);
static int sdp_append_time_descr (char *string, int size, char *tmp,
sdp_time_descr_t * time_descr, char **next_tmp);
static int sdp_append_bandwidth (char *string, int size, char *tmp,
sdp_bandwidth_t * bandwidth, char **next_tmp);
static int sdp_append_connection (char *string, int size, char *tmp,
sdp_connection_t * conn, char **next_tmp);
int
sdp_bandwidth_init (sdp_bandwidth_t ** b)
{
*b = (sdp_bandwidth_t *) osip_malloc (sizeof (sdp_bandwidth_t));
if (*b == NULL)
return -1;
(*b)->b_bwtype = NULL;
(*b)->b_bandwidth = NULL;
return 0;
}
void
sdp_bandwidth_free (sdp_bandwidth_t * b)
{
if (b == NULL)
return;
osip_free (b->b_bwtype);
osip_free (b->b_bandwidth);
osip_free (b);
}
int
sdp_time_descr_init (sdp_time_descr_t ** td)
{
*td = (sdp_time_descr_t *) osip_malloc (sizeof (sdp_time_descr_t));
if (*td == NULL)
return -1;
(*td)->t_start_time = NULL;
(*td)->t_stop_time = NULL;
osip_list_init (&(*td)->r_repeats);
return 0;
}
void
sdp_time_descr_free (sdp_time_descr_t * td)
{
if (td == NULL)
return;
osip_free (td->t_start_time);
osip_free (td->t_stop_time);
osip_list_ofchar_free (&td->r_repeats);
osip_free (td);
}
int
sdp_key_init (sdp_key_t ** key)
{
*key = (sdp_key_t *) osip_malloc (sizeof (sdp_key_t));
if (*key == NULL)
return -1;
(*key)->k_keytype = NULL;
(*key)->k_keydata = NULL;
return 0;
}
void
sdp_key_free (sdp_key_t * key)
{
if (key == NULL)
return;
osip_free (key->k_keytype);
osip_free (key->k_keydata);
osip_free (key);
}
int
sdp_attribute_init (sdp_attribute_t ** attribute)
{
*attribute = (sdp_attribute_t *) osip_malloc (sizeof (sdp_attribute_t));
if (*attribute == NULL)
return -1;
(*attribute)->a_att_field = NULL;
(*attribute)->a_att_value = NULL;
return 0;
}
void
sdp_attribute_free (sdp_attribute_t * attribute)
{
if (attribute == NULL)
return;
osip_free (attribute->a_att_field);
osip_free (attribute->a_att_value);
osip_free (attribute);
}
int
sdp_connection_init (sdp_connection_t ** connection)
{
*connection = (sdp_connection_t *) osip_malloc (sizeof (sdp_connection_t));
if (*connection == NULL)
return -1;
(*connection)->c_nettype = NULL;
(*connection)->c_addrtype = NULL;
(*connection)->c_addr = NULL;
(*connection)->c_addr_multicast_ttl = NULL;
(*connection)->c_addr_multicast_int = NULL;
return 0;
}
void
sdp_connection_free (sdp_connection_t * connection)
{
if (connection == NULL)
return;
osip_free (connection->c_nettype);
osip_free (connection->c_addrtype);
osip_free (connection->c_addr);
osip_free (connection->c_addr_multicast_ttl);
osip_free (connection->c_addr_multicast_int);
osip_free (connection);
}
int
sdp_media_init (sdp_media_t ** media)
{
*media = (sdp_media_t *) osip_malloc (sizeof (sdp_media_t));
if (*media == NULL)
return -1;
(*media)->m_media = NULL;
(*media)->m_port = NULL;
(*media)->m_number_of_port = NULL;
(*media)->m_proto = NULL;
osip_list_init (&(*media)->m_payloads);
(*media)->i_info = NULL;
osip_list_init (&(*media)->c_connections);
osip_list_init (&(*media)->b_bandwidths);
osip_list_init (&(*media)->a_attributes);
(*media)->k_key = NULL;
return 0;
}
void
sdp_media_free (sdp_media_t * media)
{
if (media == NULL)
return;
osip_free (media->m_media);
osip_free (media->m_port);
osip_free (media->m_number_of_port);
osip_free (media->m_proto);
osip_list_ofchar_free (&media->m_payloads);
osip_free (media->i_info);
osip_list_special_free (&media->c_connections,
(void *(*)(void *)) &sdp_connection_free);
osip_list_special_free (&media->b_bandwidths,
(void *(*)(void *)) &sdp_bandwidth_free);
osip_list_special_free (&media->a_attributes,
(void *(*)(void *)) &sdp_attribute_free);
sdp_key_free (media->k_key);
osip_free (media);
}
/* to be changed to sdp_message_init(sdp_message_t **dest) */
int
sdp_message_init (sdp_message_t ** sdp)
{
(*sdp) = (sdp_message_t *) osip_malloc (sizeof (sdp_message_t));
if (*sdp == NULL)
return -1;
(*sdp)->v_version = NULL;
(*sdp)->o_username = NULL;
(*sdp)->o_sess_id = NULL;
(*sdp)->o_sess_version = NULL;
(*sdp)->o_nettype = NULL;
(*sdp)->o_addrtype = NULL;
(*sdp)->o_addr = NULL;
(*sdp)->s_name = NULL;
(*sdp)->i_info = NULL;
(*sdp)->u_uri = NULL;
osip_list_init (&(*sdp)->e_emails);
osip_list_init (&(*sdp)->p_phones);
(*sdp)->c_connection = NULL;
osip_list_init (&(*sdp)->b_bandwidths);
osip_list_init (&(*sdp)->t_descrs);
(*sdp)->z_adjustments = NULL;
(*sdp)->k_key = NULL;
osip_list_init (&(*sdp)->a_attributes);
osip_list_init (&(*sdp)->m_medias);
return 0;
}
static int
sdp_message_parse_v (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
if (equal == buf)
return ERR_DISCARD;
/* check if header is "v" */
if (equal[-1] != 'v')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /*v=\r ?? bad header */
sdp->v_version = osip_malloc (crlf - (equal + 1) + 1);
osip_strncpy (sdp->v_version, equal + 1, crlf - (equal + 1));
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_o (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
char *tmp;
char *tmp_next;
int i;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "o" */
if (equal[-1] != 'o')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /* o=\r ?? bad header */
tmp = equal + 1;
/* o=username sess-id sess-version nettype addrtype addr */
/* useranme can contain any char (ascii) except "space" and CRLF */
#ifdef FIREFLY_BUG_SUPPORT
if (tmp[0] == ' ')
{
sdp->o_username = osip_strdup ("firefly");
tmp++;
} else
{
i = __osip_set_next_token (&(sdp->o_username), tmp, ' ', &tmp_next);
if (i != 0)
return -1;
tmp = tmp_next;
}
#else
i = __osip_set_next_token (&(sdp->o_username), tmp, ' ', &tmp_next);
if (i != 0)
return -1;
tmp = tmp_next;
#endif
/* sess_id contains only numeric characters */
i = __osip_set_next_token (&(sdp->o_sess_id), tmp, ' ', &tmp_next);
if (i != 0)
return -1;
tmp = tmp_next;
/* sess_id contains only numeric characters */
i = __osip_set_next_token (&(sdp->o_sess_version), tmp, ' ', &tmp_next);
if (i != 0)
return -1;
tmp = tmp_next;
/* nettype is "IN" but will surely be extented!!! assume it's some alpha-char */
i = __osip_set_next_token (&(sdp->o_nettype), tmp, ' ', &tmp_next);
if (i != 0)
return -1;
tmp = tmp_next;
/* addrtype is "IP4" or "IP6" but will surely be extented!!! */
i = __osip_set_next_token (&(sdp->o_addrtype), tmp, ' ', &tmp_next);
if (i != 0)
return -1;
tmp = tmp_next;
/* addr is "IP4" or "IP6" but will surely be extented!!! */
i = __osip_set_next_token (&(sdp->o_addr), tmp, '\r', &tmp_next);
if (i != 0)
{ /* could it be "\n" only??? rfc says to accept CR or LF instead of CRLF */
i = __osip_set_next_token (&(sdp->o_addr), tmp, '\n', &tmp_next);
if (i != 0)
return -1;
}
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_s (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "s" */
if (equal[-1] != 's')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
#ifdef FIREFLY_BUG_SUPPORT
if (crlf == equal + 1)
{
sdp->s_name = osip_strdup (" ");
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF; /* o=\r ?? bad header */
}
#else
if (crlf == equal + 1)
return ERR_ERROR; /* o=\r ?? bad header */
#endif
/* s=text */
/* text is interpreted as ISO-10646 UTF8! */
/* using ISO 8859-1 requires "a=charset:ISO-8859-1 */
sdp->s_name = osip_malloc (crlf - (equal + 1) + 1);
osip_strncpy (sdp->s_name, equal + 1, crlf - (equal + 1));
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_i (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
int i;
char *i_info;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "i" */
if (equal[-1] != 'i')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /* o=\r ?? bad header */
/* s=text */
/* text is interpreted as ISO-10646 UTF8! */
/* using ISO 8859-1 requires "a=charset:ISO-8859-1 */
i_info = osip_malloc (crlf - (equal + 1) + 1);
osip_strncpy (i_info, equal + 1, crlf - (equal + 1));
/* add the bandwidth at the correct place:
if there is no media line yet, then the "b=" is the
global one.
*/
i = osip_list_size (&sdp->m_medias);
if (i == 0)
sdp->i_info = i_info;
else
{
sdp_media_t *last_sdp_media =
(sdp_media_t *) osip_list_get (&sdp->m_medias, i - 1);
last_sdp_media->i_info = i_info;
}
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_u (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "u" */
if (equal[-1] != 'u')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /* u=\r ?? bad header */
/* u=uri */
/* we assume this is a URI */
sdp->u_uri = osip_malloc (crlf - (equal + 1) + 1);
osip_strncpy (sdp->u_uri, equal + 1, crlf - (equal + 1));
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_e (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
char *e_email;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "e" */
if (equal[-1] != 'e')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /* e=\r ?? bad header */
/* e=email */
/* we assume this is an EMAIL-ADDRESS */
e_email = osip_malloc (crlf - (equal + 1) + 1);
osip_strncpy (e_email, equal + 1, crlf - (equal + 1));
osip_list_add (&sdp->e_emails, e_email, -1);
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_p (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
char *p_phone;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "p" */
if (equal[-1] != 'p')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /* p=\r ?? bad header */
/* e=email */
/* we assume this is an EMAIL-ADDRESS */
p_phone = osip_malloc (crlf - (equal + 1) + 1);
osip_strncpy (p_phone, equal + 1, crlf - (equal + 1));
osip_list_add (&sdp->p_phones, p_phone, -1);
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_c (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
char *tmp;
char *tmp_next;
sdp_connection_t *c_header;
int i;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "c" */
if (equal[-1] != 'c')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /* c=\r ?? bad header */
tmp = equal + 1;
i = sdp_connection_init (&c_header);
if (i != 0)
return ERR_ERROR;
/* c=nettype addrtype (multicastaddr | addr) */
/* nettype is "IN" and will be extended */
i = __osip_set_next_token (&(c_header->c_nettype), tmp, ' ', &tmp_next);
if (i != 0)
{
sdp_connection_free (c_header);
return -1;
}
tmp = tmp_next;
/* nettype is "IP4" or "IP6" and will be extended */
i = __osip_set_next_token (&(c_header->c_addrtype), tmp, ' ', &tmp_next);
if (i != 0)
{
sdp_connection_free (c_header);
return -1;
}
tmp = tmp_next;
/* there we have a multicast or unicast address */
/* multicast can be ip/ttl [/integer] */
/* unicast is FQDN or ip (no ttl, no integer) */
/* is MULTICAST? */
{
char *slash = strchr (tmp, '/');
if (slash != NULL && slash < crlf) /* it's a multicast address! */
{
i = __osip_set_next_token (&(c_header->c_addr), tmp, '/', &tmp_next);
if (i != 0)
{
sdp_connection_free (c_header);
return -1;
}
tmp = tmp_next;
slash = strchr (slash + 1, '/');
if (slash != NULL && slash < crlf) /* optionnal integer is there! */
{
i =
__osip_set_next_token (&(c_header->c_addr_multicast_ttl), tmp,
'/', &tmp_next);
if (i != 0)
{
sdp_connection_free (c_header);
return -1;
}
tmp = tmp_next;
i =
__osip_set_next_token (&(c_header->c_addr_multicast_int), tmp,
'\r', &tmp_next);
if (i != 0)
{
i =
__osip_set_next_token (&(c_header->c_addr_multicast_int),
tmp, '\n', &tmp_next);
if (i != 0)
{
sdp_connection_free (c_header);
return -1;
}
}
} else
{
i =
__osip_set_next_token (&(c_header->c_addr_multicast_ttl), tmp,
'\r', &tmp_next);
if (i != 0)
{
i =
__osip_set_next_token (&(c_header->c_addr_multicast_ttl),
tmp, '\n', &tmp_next);
if (i != 0)
{
sdp_connection_free (c_header);
return -1;
}
}
}
} else
{
/* in this case, we have a unicast address */
i = __osip_set_next_token (&(c_header->c_addr), tmp, '\r', &tmp_next);
if (i != 0)
{
i = __osip_set_next_token (&(c_header->c_addr), tmp, '\n', &tmp_next);
if (i != 0)
{
sdp_connection_free (c_header);
return -1;
}
}
}
}
/* add the connection at the correct place:
if there is no media line yet, then the "c=" is the
global one.
*/
i = osip_list_size (&sdp->m_medias);
if (i == 0)
sdp->c_connection = c_header;
else
{
sdp_media_t *last_sdp_media =
(sdp_media_t *) osip_list_get (&sdp->m_medias, i - 1);
osip_list_add (&last_sdp_media->c_connections, c_header, -1);
}
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_b (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
char *tmp;
char *tmp_next;
int i;
sdp_bandwidth_t *b_header;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "b" */
if (equal[-1] != 'b')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /* b=\r ?? bad header */
tmp = equal + 1;
/* b = bwtype: bandwidth */
i = sdp_bandwidth_init (&b_header);
if (i != 0)
return ERR_ERROR;
/* bwtype is alpha-numeric */
i = __osip_set_next_token (&(b_header->b_bwtype), tmp, ':', &tmp_next);
if (i != 0)
{
sdp_bandwidth_free (b_header);
return -1;
}
tmp = tmp_next;
i = __osip_set_next_token (&(b_header->b_bandwidth), tmp, '\r', &tmp_next);
if (i != 0)
{
i = __osip_set_next_token (&(b_header->b_bandwidth), tmp, '\n', &tmp_next);
if (i != 0)
{
sdp_bandwidth_free (b_header);
return -1;
}
}
/* add the bandwidth at the correct place:
if there is no media line yet, then the "b=" is the
global one.
*/
i = osip_list_size (&sdp->m_medias);
if (i == 0)
osip_list_add (&sdp->b_bandwidths, b_header, -1);
else
{
sdp_media_t *last_sdp_media =
(sdp_media_t *) osip_list_get (&sdp->m_medias, i - 1);
osip_list_add (&last_sdp_media->b_bandwidths, b_header, -1);
}
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_t (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
char *tmp;
char *tmp_next;
int i;
sdp_time_descr_t *t_header;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "t" */
if (equal[-1] != 't')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /* t=\r ?? bad header */
tmp = equal + 1;
/* t = start_time stop_time */
i = sdp_time_descr_init (&t_header);
if (i != 0)
return ERR_ERROR;
i = __osip_set_next_token (&(t_header->t_start_time), tmp, ' ', &tmp_next);
if (i != 0)
{
sdp_time_descr_free (t_header);
return -1;
}
tmp = tmp_next;
i = __osip_set_next_token (&(t_header->t_stop_time), tmp, '\r', &tmp_next);
if (i != 0)
{
i = __osip_set_next_token (&(t_header->t_stop_time), tmp, '\n', &tmp_next);
if (i != 0)
{
sdp_time_descr_free (t_header);
return -1;
}
}
/* add the new time_description header */
osip_list_add (&sdp->t_descrs, t_header, -1);
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_r (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
int index;
char *r_header;
sdp_time_descr_t *t_descr;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "r" */
if (equal[-1] != 'r')
return ERR_DISCARD;
index = osip_list_size (&sdp->t_descrs);
if (index == 0)
return ERR_ERROR; /* r field can't come alone! */
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /* r=\r ?? bad header */
/* r=far too complexe and somewhat useless... I don't parse it! */
r_header = osip_malloc (crlf - (equal + 1) + 1);
osip_strncpy (r_header, equal + 1, crlf - (equal + 1));
/* r field carry information for the last "t" field */
t_descr = (sdp_time_descr_t *) osip_list_get (&sdp->t_descrs, index - 1);
osip_list_add (&t_descr->r_repeats, r_header, -1);
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_z (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
char *z_header;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "z" */
if (equal[-1] != 'z')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /* z=\r ?? bad header */
/* z=somewhat useless... I don't parse it! */
z_header = osip_malloc (crlf - (equal + 1) + 1);
osip_strncpy (z_header, equal + 1, crlf - (equal + 1));
sdp->z_adjustments = z_header;
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_k (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
int i;
char *colon;
sdp_key_t *k_header;
char *tmp;
char *tmp_next;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "k" */
if (equal[-1] != 'k')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /* k=\r ?? bad header */
tmp = equal + 1;
i = sdp_key_init (&k_header);
if (i != 0)
return ERR_ERROR;
/* k=key-type[:key-data] */
/* is there any key-data? */
colon = strchr (equal + 1, ':');
if ((colon != NULL) && (colon < crlf))
{
/* att-field is alpha-numeric */
i = __osip_set_next_token (&(k_header->k_keytype), tmp, ':', &tmp_next);
if (i != 0)
{
sdp_key_free (k_header);
return -1;
}
tmp = tmp_next;
i = __osip_set_next_token (&(k_header->k_keydata), tmp, '\r', &tmp_next);
if (i != 0)
{
i = __osip_set_next_token (&(k_header->k_keydata), tmp, '\n', &tmp_next);
if (i != 0)
{
sdp_key_free (k_header);
return -1;
}
}
} else
{
i = __osip_set_next_token (&(k_header->k_keytype), tmp, '\r', &tmp_next);
if (i != 0)
{
i = __osip_set_next_token (&(k_header->k_keytype), tmp, '\n', &tmp_next);
if (i != 0)
{
sdp_key_free (k_header);
return -1;
}
}
}
/* add the key at the correct place:
if there is no media line yet, then the "k=" is the
global one.
*/
i = osip_list_size (&sdp->m_medias);
if (i == 0)
sdp->k_key = k_header;
else
{
sdp_media_t *last_sdp_media =
(sdp_media_t *) osip_list_get (&sdp->m_medias, i - 1);
last_sdp_media->k_key = k_header;
}
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_a (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
char *tmp;
char *tmp_next;
int i;
sdp_attribute_t *a_attribute;
char *colon;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "a" */
if (equal[-1] != 'a')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /* a=\r ?? bad header */
tmp = equal + 1;
i = sdp_attribute_init (&a_attribute);
if (i != 0)
return ERR_ERROR;
/* a=att-field[:att-value] */
/* is there any att-value? */
colon = strchr (equal + 1, ':');
if ((colon != NULL) && (colon < crlf))
{
/* att-field is alpha-numeric */
i = __osip_set_next_token (&(a_attribute->a_att_field), tmp, ':', &tmp_next);
if (i != 0)
{
sdp_attribute_free (a_attribute);
return -1;
}
tmp = tmp_next;
i =
__osip_set_next_token (&(a_attribute->a_att_value), tmp, '\r', &tmp_next);
if (i != 0)
{
i =
__osip_set_next_token (&(a_attribute->a_att_value), tmp, '\n',
&tmp_next);
if (i != 0)
{
sdp_attribute_free (a_attribute);
return -1;
}
}
} else
{
i =
__osip_set_next_token (&(a_attribute->a_att_field), tmp, '\r', &tmp_next);
if (i != 0)
{
i =
__osip_set_next_token (&(a_attribute->a_att_field), tmp, '\n',
&tmp_next);
if (i != 0)
{
sdp_attribute_free (a_attribute);
return -1;
}
}
}
/* add the attribute at the correct place:
if there is no media line yet, then the "a=" is the
global one.
*/
i = osip_list_size (&sdp->m_medias);
if (i == 0)
osip_list_add (&sdp->a_attributes, a_attribute, -1);
else
{
sdp_media_t *last_sdp_media =
(sdp_media_t *) osip_list_get (&sdp->m_medias, i - 1);
osip_list_add (&last_sdp_media->a_attributes, a_attribute, -1);
}
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
static int
sdp_message_parse_m (sdp_message_t * sdp, char *buf, char **next)
{
char *equal;
char *crlf;
char *tmp;
char *tmp_next;
int i;
sdp_media_t *m_header;
char *slash;
char *space;
*next = buf;
equal = buf;
while ((*equal != '=') && (*equal != '\0'))
equal++;
if (*equal == '\0')
return ERR_ERROR;
/* check if header is "m" */
if (equal[-1] != 'm')
return ERR_DISCARD;
crlf = equal + 1;
while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
crlf++;
if (*crlf == '\0')
return ERR_ERROR;
if (crlf == equal + 1)
return ERR_ERROR; /* a=\r ?? bad header */
tmp = equal + 1;
i = sdp_media_init (&m_header);
if (i != 0)
return ERR_ERROR;
/* m=media port ["/"integer] proto *(payload_number) */
/* media is "audio" "video" "application" "data" or other... */
i = __osip_set_next_token (&(m_header->m_media), tmp, ' ', &tmp_next);
if (i != 0)
{
sdp_media_free (m_header);
return -1;
}
tmp = tmp_next;
slash = strchr (tmp, '/');
space = strchr (tmp, ' ');
if (space == NULL) /* not possible! */
{
sdp_media_free (m_header);
return ERR_ERROR;
}
if ((slash != NULL) && (slash < space))
{ /* a number of port is specified! */
i = __osip_set_next_token (&(m_header->m_port), tmp, '/', &tmp_next);
if (i != 0)
{
sdp_media_free (m_header);
return -1;
}
tmp = tmp_next;
i =
__osip_set_next_token (&(m_header->m_number_of_port), tmp, ' ', &tmp_next);
if (i != 0)
{
sdp_media_free (m_header);
return -1;
}
tmp = tmp_next;
} else
{
i = __osip_set_next_token (&(m_header->m_port), tmp, ' ', &tmp_next);
if (i != 0)
{
sdp_media_free (m_header);
return -1;
}
tmp = tmp_next;
}
i = __osip_set_next_token (&(m_header->m_proto), tmp, ' ', &tmp_next);
if (i != 0)
{
/* a few stack don't add SPACE after m_proto when rejecting all payloads */
i = __osip_set_next_token (&(m_header->m_proto), tmp, '\r', &tmp_next);
if (i != 0)
{
i = __osip_set_next_token (&(m_header->m_proto), tmp, '\n', &tmp_next);
if (i != 0)
{
sdp_media_free (m_header);
return -1;
}
}
}
tmp = tmp_next;
{
char *str;
int more_space_before_crlf;
space = strchr (tmp + 1, ' ');
if (space == NULL)
more_space_before_crlf = 1;
else if ((space != NULL) && (space > crlf))
more_space_before_crlf = 1;
else
more_space_before_crlf = 0;
while (more_space_before_crlf == 0)
{
i = __osip_set_next_token (&str, tmp, ' ', &tmp_next);
if (i != 0)
{
sdp_media_free (m_header);
return -1;
}
tmp = tmp_next;
osip_list_add (&m_header->m_payloads, str, -1);
space = strchr (tmp + 1, ' ');
if (space == NULL)
more_space_before_crlf = 1;
else if ((space != NULL) && (space > crlf))
more_space_before_crlf = 1;
else
more_space_before_crlf = 0;
}
if (tmp_next < crlf)
{ /* tmp_next is still less than clrf: no space */
i = __osip_set_next_token (&str, tmp, '\r', &tmp_next);
if (i != 0)
{
i = __osip_set_next_token (&str, tmp, '\n', &tmp_next);
if (i != 0)
{
sdp_media_free (m_header);
return -1;
}
}
osip_list_add (&m_header->m_payloads, str, -1);
}
}
osip_list_add (&sdp->m_medias, m_header, -1);
if (crlf[1] == '\n')
*next = crlf + 2;
else
*next = crlf + 1;
return WF;
}
int
sdp_message_parse (sdp_message_t * sdp, const char *buf)
{
/* In SDP, headers must be in the right order */
/* This is a simple example
v=0
o=user1 53655765 2353687637 IN IP4 128.3.4.5
s=Mbone Audio
i=Discussion of Mbone Engineering Issues
e=mbone@somewhere.com
c=IN IP4 224.2.0.1/127
t=0 0
m=audio 3456 RTP/AVP 0
a=rtpmap:0 PCMU/8000
*/
char *next_buf;
char *ptr;
int i;
ptr = (char *) buf;
/* mandatory */
i = sdp_message_parse_v (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
else if (0 == i) /* header is not "v" */
return -1;
ptr = next_buf;
/* adtech phone use the wrong ordering and place "s" before "o" */
i = sdp_message_parse_s (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
/* else if (0==i) header is not "s" */
/* else ADTECH PHONE DETECTED */
ptr = next_buf;
i = sdp_message_parse_o (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
else if (0 == i) /* header is not "o" */
return -1;
ptr = next_buf;
i = sdp_message_parse_s (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
else if (0 == i) /* header is not "s" */
/* return -1; */
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO4, NULL,
"The \"s\" parameter is mandatory, but this packet does not contain any! - anyway, we don't mind about it.\n"));
}
ptr = next_buf;
i = sdp_message_parse_i (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
i = sdp_message_parse_u (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
i = 1;
while (i == 1)
{
i = sdp_message_parse_e (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
}
i = 1;
while (i == 1)
{
i = sdp_message_parse_p (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
}
/* rfc2327: there should be at least of email or phone number! */
if (osip_list_size (&sdp->e_emails) == 0 && osip_list_size (&sdp->p_phones) == 0)
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO4, NULL,
"The rfc2327 says there should be at least an email or a phone header!- anyway, we don't mind about it.\n"));
}
i = sdp_message_parse_c (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
i = 1;
while (i == 1)
{
i = sdp_message_parse_b (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
}
/* 1 or more "t" header + 0 or more "r" header for each "t" header */
i = sdp_message_parse_t (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
else if (i == ERR_DISCARD)
return -1; /* t is mandatory */
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
i = 1;
while (i == 1) /* is a "r" header */
{
i = sdp_message_parse_r (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
}
{
int more_t_header = 1;
i = sdp_message_parse_t (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
while (more_t_header == 1)
{
i = 1;
while (i == 1) /* is a "r" header */
{
i = sdp_message_parse_r (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
}
i = sdp_message_parse_t (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
else if (i == ERR_DISCARD)
more_t_header = 0;
else
more_t_header = 1; /* no more "t" headers */
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
}
}
i = sdp_message_parse_z (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
i = sdp_message_parse_k (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
/* 0 or more "a" header */
i = 1;
while (i == 1) /* no more "a" header */
{
i = sdp_message_parse_a (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
}
/* 0 or more media headers */
{
int more_m_header = 1;
while (more_m_header == 1)
{
more_m_header = sdp_message_parse_m (sdp, ptr, &next_buf);
if (more_m_header == -1) /* header is bad */
return -1;
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
i = sdp_message_parse_i (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
i = 1;
while (i == 1)
{
i = sdp_message_parse_c (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
}
i = 1;
while (i == 1)
{
i = sdp_message_parse_b (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
}
i = sdp_message_parse_k (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
/* 0 or more a headers */
i = 1;
while (i == 1)
{
i = sdp_message_parse_a (sdp, ptr, &next_buf);
if (i == -1) /* header is bad */
return -1;
ptr = next_buf;
if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
return 0;
}
}
}
return 0;
}
static int
sdp_append_connection (char *string, int size, char *tmp,
sdp_connection_t * conn, char **next_tmp)
{
if (conn->c_nettype == NULL)
return -1;
if (conn->c_addrtype == NULL)
return -1;
if (conn->c_addr == NULL)
return -1;
tmp = __osip_sdp_append_string (string, size, tmp, "c=");
tmp = __osip_sdp_append_string (string, size, tmp, conn->c_nettype);
tmp = __osip_sdp_append_string (string, size, tmp, " ");
tmp = __osip_sdp_append_string (string, size, tmp, conn->c_addrtype);
tmp = __osip_sdp_append_string (string, size, tmp, " ");
tmp = __osip_sdp_append_string (string, size, tmp, conn->c_addr);
if (conn->c_addr_multicast_ttl != NULL)
{
tmp = __osip_sdp_append_string (string, size, tmp, "/");
tmp =
__osip_sdp_append_string (string, size, tmp, conn->c_addr_multicast_ttl);
}
if (conn->c_addr_multicast_int != NULL)
{
tmp = __osip_sdp_append_string (string, size, tmp, "/");
tmp =
__osip_sdp_append_string (string, size, tmp, conn->c_addr_multicast_int);
}
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
*next_tmp = tmp;
return 0;
}
static int
sdp_append_bandwidth (char *string, int size, char *tmp,
sdp_bandwidth_t * bandwidth, char **next_tmp)
{
if (bandwidth->b_bwtype == NULL)
return -1;
if (bandwidth->b_bandwidth == NULL)
return -1;
tmp = __osip_sdp_append_string (string, size, tmp, "b=");
tmp = __osip_sdp_append_string (string, size, tmp, bandwidth->b_bwtype);
tmp = __osip_sdp_append_string (string, size, tmp, ":");
tmp = __osip_sdp_append_string (string, size, tmp, bandwidth->b_bandwidth);
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
*next_tmp = tmp;
return 0;
}
static int
sdp_append_time_descr (char *string, int size, char *tmp,
sdp_time_descr_t * time_descr, char **next_tmp)
{
int pos;
if (time_descr->t_start_time == NULL)
return -1;
if (time_descr->t_stop_time == NULL)
return -1;
tmp = __osip_sdp_append_string (string, size, tmp, "t=");
tmp = __osip_sdp_append_string (string, size, tmp, time_descr->t_start_time);
tmp = __osip_sdp_append_string (string, size, tmp, " ");
tmp = __osip_sdp_append_string (string, size, tmp, time_descr->t_stop_time);
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
pos = 0;
while (!osip_list_eol (&time_descr->r_repeats, pos))
{
char *str = (char *) osip_list_get (&time_descr->r_repeats, pos);
tmp = __osip_sdp_append_string (string, size, tmp, "r=");
tmp = __osip_sdp_append_string (string, size, tmp, str);
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
pos++;
}
*next_tmp = tmp;
return 0;
}
static int
sdp_append_key (char *string, int size, char *tmp, sdp_key_t * key,
char **next_tmp)
{
if (key->k_keytype == NULL)
return -1;
tmp = __osip_sdp_append_string (string, size, tmp, "k=");
tmp = __osip_sdp_append_string (string, size, tmp, key->k_keytype);
if (key->k_keydata != NULL)
{
tmp = __osip_sdp_append_string (string, size, tmp, ":");
tmp = __osip_sdp_append_string (string, size, tmp, key->k_keydata);
}
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
*next_tmp = tmp;
return 0;
}
static int
sdp_append_attribute (char *string, int size, char *tmp,
sdp_attribute_t * attribute, char **next_tmp)
{
if (attribute->a_att_field == NULL)
return -1;
tmp = __osip_sdp_append_string (string, size, tmp, "a=");
tmp = __osip_sdp_append_string (string, size, tmp, attribute->a_att_field);
if (attribute->a_att_value != NULL)
{
tmp = __osip_sdp_append_string (string, size, tmp, ":");
tmp = __osip_sdp_append_string (string, size, tmp, attribute->a_att_value);
}
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
*next_tmp = tmp;
return 0;
}
/* internal facility */
static int
sdp_append_media (char *string, int size, char *tmp, sdp_media_t * media,
char **next_tmp)
{
int pos;
if (media->m_media == NULL)
return -1;
if (media->m_port == NULL)
return -1;
if (media->m_proto == NULL)
return -1;
tmp = __osip_sdp_append_string (string, size, tmp, "m=");
tmp = __osip_sdp_append_string (string, size, tmp, media->m_media);
tmp = __osip_sdp_append_string (string, size, tmp, " ");
tmp = __osip_sdp_append_string (string, size, tmp, media->m_port);
if (media->m_number_of_port != NULL)
{
tmp = __osip_sdp_append_string (string, size, tmp, "/");
tmp = __osip_sdp_append_string (string, size, tmp, media->m_number_of_port);
}
tmp = __osip_sdp_append_string (string, size, tmp, " ");
tmp = __osip_sdp_append_string (string, size, tmp, media->m_proto);
pos = 0;
while (!osip_list_eol (&media->m_payloads, pos))
{
char *str = (char *) osip_list_get (&media->m_payloads, pos);
tmp = __osip_sdp_append_string (string, size, tmp, " ");
tmp = __osip_sdp_append_string (string, size, tmp, str);
pos++;
}
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
if (media->i_info != NULL)
{
tmp = __osip_sdp_append_string (string, size, tmp, "i=");
tmp = __osip_sdp_append_string (string, size, tmp, media->i_info);
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
}
pos = 0;
while (!osip_list_eol (&media->c_connections, pos))
{
sdp_connection_t *conn =
(sdp_connection_t *) osip_list_get (&media->c_connections, pos);
char *next_tmp2;
int i;
i = sdp_append_connection (string, size, tmp, conn, &next_tmp2);
if (i != 0)
return -1;
tmp = next_tmp2;
pos++;
}
pos = 0;
while (!osip_list_eol (&media->b_bandwidths, pos))
{
sdp_bandwidth_t *band =
(sdp_bandwidth_t *) osip_list_get (&media->b_bandwidths, pos);
char *next_tmp2;
int i;
i = sdp_append_bandwidth (string, size, tmp, band, &next_tmp2);
if (i != 0)
return -1;
tmp = next_tmp2;
pos++;
}
if (media->k_key != NULL)
{
char *next_tmp2;
int i;
i = sdp_append_key (string, size, tmp, media->k_key, &next_tmp2);
if (i != 0)
return -1;
tmp = next_tmp2;
}
pos = 0;
while (!osip_list_eol (&media->a_attributes, pos))
{
sdp_attribute_t *attr =
(sdp_attribute_t *) osip_list_get (&media->a_attributes, pos);
char *next_tmp2;
int i;
i = sdp_append_attribute (string, size, tmp, attr, &next_tmp2);
if (i != 0)
return -1;
tmp = next_tmp2;
pos++;
}
*next_tmp = tmp;
return 0;
}
int
sdp_message_to_str (sdp_message_t * sdp, char **dest)
{
int size;
int pos;
char *tmp;
char *string;
*dest = NULL;
if (!sdp || sdp->v_version == NULL)
return -1;
if (sdp->o_username == NULL ||
sdp->o_sess_id == NULL ||
sdp->o_sess_version == NULL ||
sdp->o_nettype == NULL || sdp->o_addrtype == NULL || sdp->o_addr == NULL)
return -1;
/* RFC says "s=" is mandatory... rfc2543 (SIP) recommends to
accept SDP datas without s_name... as some buggy implementations
often forget it...
*/
/* if (sdp->s_name == NULL)
return -1; */
size = BODY_MESSAGE_MAX_SIZE;
tmp = (char *) osip_malloc (size);
string = tmp;
tmp = __osip_sdp_append_string (string, size, tmp, "v=");
tmp = __osip_sdp_append_string (string, size, tmp, sdp->v_version);
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
tmp = __osip_sdp_append_string (string, size, tmp, "o=");
tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_username);
tmp = __osip_sdp_append_string (string, size, tmp, " ");
tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_sess_id);
tmp = __osip_sdp_append_string (string, size, tmp, " ");
tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_sess_version);
tmp = __osip_sdp_append_string (string, size, tmp, " ");
tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_nettype);
tmp = __osip_sdp_append_string (string, size, tmp, " ");
tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_addrtype);
tmp = __osip_sdp_append_string (string, size, tmp, " ");
tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_addr);
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
if (sdp->s_name != NULL)
{
tmp = __osip_sdp_append_string (string, size, tmp, "s=");
tmp = __osip_sdp_append_string (string, size, tmp, sdp->s_name);
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
}
if (sdp->i_info != NULL)
{
tmp = __osip_sdp_append_string (string, size, tmp, "i=");
tmp = __osip_sdp_append_string (string, size, tmp, sdp->i_info);
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
}
if (sdp->u_uri != NULL)
{
tmp = __osip_sdp_append_string (string, size, tmp, "u=");
tmp = __osip_sdp_append_string (string, size, tmp, sdp->u_uri);
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
}
pos = 0;
while (!osip_list_eol (&sdp->e_emails, pos))
{
char *email = (char *) osip_list_get (&sdp->e_emails, pos);
tmp = __osip_sdp_append_string (string, size, tmp, "e=");
tmp = __osip_sdp_append_string (string, size, tmp, email);
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
pos++;
}
pos = 0;
while (!osip_list_eol (&sdp->p_phones, pos))
{
char *phone = (char *) osip_list_get (&sdp->p_phones, pos);
tmp = __osip_sdp_append_string (string, size, tmp, "p=");
tmp = __osip_sdp_append_string (string, size, tmp, phone);
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
pos++;
}
if (sdp->c_connection != NULL)
{
char *next_tmp;
int i;
i = sdp_append_connection (string, size, tmp, sdp->c_connection, &next_tmp);
if (i != 0)
{
osip_free (string);
return -1;
}
tmp = next_tmp;
}
pos = 0;
while (!osip_list_eol (&sdp->b_bandwidths, pos))
{
sdp_bandwidth_t *header =
(sdp_bandwidth_t *) osip_list_get (&sdp->b_bandwidths, pos);
char *next_tmp;
int i;
i = sdp_append_bandwidth (string, size, tmp, header, &next_tmp);
if (i != 0)
{
osip_free (string);
return -1;
}
tmp = next_tmp;
pos++;
}
pos = 0;
while (!osip_list_eol (&sdp->t_descrs, pos))
{
sdp_time_descr_t *header =
(sdp_time_descr_t *) osip_list_get (&sdp->t_descrs, pos);
char *next_tmp;
int i;
i = sdp_append_time_descr (string, size, tmp, header, &next_tmp);
if (i != 0)
{
osip_free (string);
return -1;
}
tmp = next_tmp;
pos++;
}
if (sdp->z_adjustments != NULL)
{
tmp = __osip_sdp_append_string (string, size, tmp, "z=");
tmp = __osip_sdp_append_string (string, size, tmp, sdp->z_adjustments);
tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
}
if (sdp->k_key != NULL)
{
char *next_tmp;
int i;
i = sdp_append_key (string, size, tmp, sdp->k_key, &next_tmp);
if (i != 0)
{
osip_free (string);
return -1;
}
tmp = next_tmp;
}
pos = 0;
while (!osip_list_eol (&sdp->a_attributes, pos))
{
sdp_attribute_t *header =
(sdp_attribute_t *) osip_list_get (&sdp->a_attributes, pos);
char *next_tmp;
int i;
i = sdp_append_attribute (string, size, tmp, header, &next_tmp);
if (i != 0)
{
osip_free (string);
return -1;
}
tmp = next_tmp;
pos++;
}
pos = 0;
while (!osip_list_eol (&sdp->m_medias, pos))
{
sdp_media_t *header = (sdp_media_t *) osip_list_get (&sdp->m_medias, pos);
char *next_tmp;
int i;
i = sdp_append_media (string, size, tmp, header, &next_tmp);
if (i != 0)
{
osip_free (string);
return -1;
}
tmp = next_tmp;
pos++;
}
*dest = string;
return 0;
}
void
sdp_message_free (sdp_message_t * sdp)
{
if (sdp == NULL)
return;
osip_free (sdp->v_version);
osip_free (sdp->o_username);
osip_free (sdp->o_sess_id);
osip_free (sdp->o_sess_version);
osip_free (sdp->o_nettype);
osip_free (sdp->o_addrtype);
osip_free (sdp->o_addr);
osip_free (sdp->s_name);
osip_free (sdp->i_info);
osip_free (sdp->u_uri);
osip_list_ofchar_free (&sdp->e_emails);
osip_list_ofchar_free (&sdp->p_phones);
sdp_connection_free (sdp->c_connection);
osip_list_special_free (&sdp->b_bandwidths,
(void *(*)(void *)) &sdp_bandwidth_free);
osip_list_special_free (&sdp->t_descrs, (void *(*)(void *)) &sdp_time_descr_free);
osip_free (sdp->z_adjustments);
sdp_key_free (sdp->k_key);
osip_list_special_free (&sdp->a_attributes,
(void *(*)(void *)) &sdp_attribute_free);
osip_list_special_free (&sdp->m_medias, (void *(*)(void *)) &sdp_media_free);
osip_free (sdp);
}
int
sdp_message_clone (sdp_message_t * sdp, sdp_message_t ** dest)
{
int i;
char *body;
i = sdp_message_init (dest);
if (i != 0)
return -1;
i = sdp_message_to_str (sdp, &body);
if (i != 0)
goto error_sc1;
i = sdp_message_parse (*dest, body);
osip_free (body);
if (i != 0)
goto error_sc1;
return 0;
error_sc1:
sdp_message_free (*dest);
return -1;
}
syntax highlighted by Code2HTML, v. 0.9.1