--- /dev/null
+/*
+ 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 <stdlib.h>
+
+#include <osipparser2/osip_port.h>
+#include <osipparser2/osip_rfc3264.h>
+#include <osip_rfc3264i.h> /* internal include */
+
+/**
+ * Initialize negotiation facility..
+ * @param config The element to work on.
+ */
+int
+osip_rfc3264_init (struct osip_rfc3264 **config)
+{
+ osip_rfc3264_t *cnf;
+
+ *config = NULL;
+ cnf = (osip_rfc3264_t *) osip_malloc (sizeof (osip_rfc3264_t));
+ if (cnf == NULL)
+ return -1;
+ memset (cnf, 0, sizeof (osip_rfc3264_t));
+ *config = cnf;
+ return 0;
+}
+
+
+/**
+ * Free negotiation facility.
+ * @param config The element to work on.
+ */
+void
+osip_rfc3264_free (struct osip_rfc3264 *config)
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+ int i;
+
+ if (config == NULL)
+ return;
+
+ for (i = 0; i < MAX_AUDIO_CODECS; i++)
+ {
+ if (cnf->audio_medias[i] != NULL)
+ {
+ sdp_media_free (cnf->audio_medias[i]);
+ cnf->audio_medias[i] = NULL;
+ }
+ }
+ for (i = 0; i < MAX_VIDEO_CODECS; i++)
+ {
+ if (cnf->video_medias[i] != NULL)
+ {
+ sdp_media_free (cnf->video_medias[i]);
+ cnf->video_medias[i] = NULL;
+ }
+ }
+ for (i = 0; i < MAX_T38_CODECS; i++)
+ {
+ if (cnf->t38_medias[i] != NULL)
+ {
+ sdp_media_free (cnf->t38_medias[i]);
+ cnf->t38_medias[i] = NULL;
+ }
+ }
+ for (i = 0; i < MAX_APP_CODECS; i++)
+ {
+ if (cnf->app_medias[i] != NULL)
+ {
+ sdp_media_free (cnf->app_medias[i]);
+ cnf->app_medias[i] = NULL;
+ }
+ }
+ osip_free (cnf);
+}
+
+
+/**
+ * Test if a media exist in the configuration.
+ * @param config The element to work on.
+ * @param pos The index of the media element.
+ */
+int
+osip_rfc3264_endof_media (struct osip_rfc3264 *config, int pos)
+{
+ if (config == NULL)
+ return -1;
+
+ return 0;
+}
+
+
+/**
+ * Get a media from the configuration.
+ * @param config The element to work on.
+ * @param pos The index of the media element to get.
+ */
+sdp_media_t *
+osip_rfc3264_get (struct osip_rfc3264 * config, int pos)
+{
+ if (config == NULL)
+ return NULL;
+
+ return NULL;
+}
+
+
+/**
+ * Remove a media from the configuration.
+ * @param config The element to work on.
+ * @param pos The index of the media element to remove.
+ */
+int
+osip_rfc3264_remove (struct osip_rfc3264 *config, int pos)
+{
+ if (config == NULL)
+ return -1;
+
+ return 0;
+}
+
+
+/**
+ * Remove all medias from the configuration.
+ * @param config The element to work on.
+ */
+int
+osip_rfc3264_reset_media (struct osip_rfc3264 *config)
+{
+ if (config == NULL)
+ return -1;
+
+ return 0;
+}
+
+
+/**
+ * Add a media (for audio) in the configuration.
+ * @param config The element to work on.
+ * @param med The media element to add.
+ * @param pos The index of the media element to add.
+ */
+int
+osip_rfc3264_add_audio_media (struct osip_rfc3264 *config, sdp_media_t * med,
+ int pos)
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+
+ if (config == NULL)
+ return -1;
+ if (pos >= MAX_AUDIO_CODECS)
+ return -1;
+
+ if (pos == -1)
+ {
+ for (pos = 0; pos < MAX_AUDIO_CODECS && cnf->audio_medias[pos] != NULL;
+ pos++)
+ {
+ }
+ }
+ if (pos >= MAX_AUDIO_CODECS)
+ return -1; /* no space left */
+
+ cnf->audio_medias[pos] = med;
+ return 0;
+}
+
+
+/**
+ * Remove a media in the configuration.
+ * @param config The element to work on.
+ * @param pos The index of the media element to remove.
+ */
+int
+osip_rfc3264_del_audio_media (struct osip_rfc3264 *config, int pos)
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+
+ if (config == NULL)
+ return -1;
+ if (pos >= MAX_AUDIO_CODECS)
+ return -1;
+ sdp_media_free (cnf->audio_medias[pos]);
+ cnf->audio_medias[pos] = NULL;
+ return 0;
+}
+
+/**
+ * Add a media (for video) in the configuration.
+ * @param config The element to work on.
+ * @param med The media element to add.
+ * @param pos The index of the media element to add.
+ */
+int
+osip_rfc3264_add_video_media (struct osip_rfc3264 *config, sdp_media_t * med,
+ int pos)
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+
+ if (config == NULL)
+ return -1;
+ if (pos >= MAX_VIDEO_CODECS)
+ return -1;
+
+ if (pos == -1)
+ {
+ for (pos = 0; pos < MAX_VIDEO_CODECS && cnf->video_medias[pos] != NULL;
+ pos++)
+ {
+ }
+ }
+ if (pos >= MAX_VIDEO_CODECS)
+ return -1; /* no space left */
+
+ cnf->video_medias[pos] = med;
+ return 0;
+}
+
+
+/**
+ * Remove a media in the configuration.
+ * @param config The element to work on.
+ * @param pos The index of the media element to remove.
+ */
+int
+osip_rfc3264_del_video_media (struct osip_rfc3264 *config, int pos)
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+
+ if (config == NULL)
+ return -1;
+ if (pos >= MAX_VIDEO_CODECS)
+ return -1;
+ sdp_media_free (cnf->video_medias[pos]);
+ cnf->video_medias[pos] = NULL;
+ return 0;
+}
+
+/**
+ * Add a media (for t38) in the configuration.
+ * @param config The element to work on.
+ * @param med The media element to add.
+ * @param pos The index of the media element to add.
+ */
+int
+osip_rfc3264_add_t38_media (struct osip_rfc3264 *config, sdp_media_t * med,
+ int pos)
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+
+ if (config == NULL)
+ return -1;
+ if (pos >= MAX_T38_CODECS)
+ return -1;
+
+ if (pos == -1)
+ {
+ for (pos = 0; pos < MAX_T38_CODECS && cnf->t38_medias[pos] != NULL; pos++)
+ {
+ }
+ }
+ if (pos >= MAX_T38_CODECS)
+ return -1; /* no space left */
+
+ cnf->t38_medias[pos] = med;
+ return 0;
+}
+
+
+/**
+ * Remove a media in the configuration.
+ * @param config The element to work on.
+ * @param pos The index of the media element to remove.
+ */
+int
+osip_rfc3264_del_t38_media (struct osip_rfc3264 *config, int pos)
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+
+ if (config == NULL)
+ return -1;
+ if (pos >= MAX_T38_CODECS)
+ return -1;
+ sdp_media_free (cnf->t38_medias[pos]);
+ cnf->t38_medias[pos] = NULL;
+ return 0;
+}
+
+/**
+ * Search for support of a special codec.
+ * @param config The element to work on.
+ * @param payload The payload to find.
+ * @param rtpmap The rtpmap for the payload.
+ */
+sdp_media_t *
+osip_rfc3264_find_audio (struct osip_rfc3264 * config, char *payload, char *rtpmap)
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+ int i;
+
+ if (config == NULL)
+ return NULL;
+
+ if (rtpmap == NULL)
+ {
+ for (i = 0; i < MAX_AUDIO_CODECS; i++)
+ {
+ if (cnf->audio_medias[i] != NULL)
+ {
+ sdp_media_t *med = cnf->audio_medias[i];
+ char *str = (char *) osip_list_get (med->m_payloads, 0);
+
+ /* static payload?: only compare payload number */
+ if (strlen (str) == strlen (payload)
+ && 0 == osip_strcasecmp (str, payload))
+ return med;
+ }
+ }
+ return NULL;
+ }
+
+ for (i = 0; i < MAX_AUDIO_CODECS; i++)
+ {
+ if (cnf->audio_medias[i] != NULL)
+ {
+ sdp_media_t *med = cnf->audio_medias[i];
+
+ int pos = 0;
+
+ while (!osip_list_eol (med->a_attributes, pos))
+ {
+ sdp_attribute_t *attr =
+ (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
+
+ if (0 == osip_strcasecmp ("rtpmap", attr->a_att_field)
+ && attr->a_att_value != NULL)
+ {
+ char *tmp = strchr (attr->a_att_value, ' ');
+ char *tmp2 = strchr (rtpmap, ' ');
+
+ if (tmp != NULL && tmp2 != NULL)
+ {
+ if (0 == osip_strcasecmp (tmp, tmp2))
+ return med;
+ }
+ }
+ pos++;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Search for support of a special codec.
+ * @param config The element to work on.
+ * @param payload The payload to find.
+ * @param rtpmap The rtpmap for the payload.
+ */
+sdp_media_t *
+osip_rfc3264_find_video (struct osip_rfc3264 * config, char *payload, char *rtpmap)
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+ int i;
+
+ if (config == NULL)
+ return NULL;
+
+ if (rtpmap == NULL)
+ {
+ for (i = 0; i < MAX_VIDEO_CODECS; i++)
+ {
+ if (cnf->video_medias[i] != NULL)
+ {
+ sdp_media_t *med = cnf->video_medias[i];
+ char *str = (char *) osip_list_get (med->m_payloads, 0);
+
+ /* static payload?: only compare payload number */
+ if (strlen (str) == strlen (payload)
+ && 0 == osip_strcasecmp (str, payload))
+ return med;
+ }
+ }
+ return NULL;
+ }
+
+ for (i = 0; i < MAX_VIDEO_CODECS; i++)
+ {
+ if (cnf->video_medias[i] != NULL)
+ {
+ sdp_media_t *med = cnf->video_medias[i];
+
+ int pos = 0;
+
+ while (!osip_list_eol (med->a_attributes, pos))
+ {
+ sdp_attribute_t *attr =
+ (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
+
+ if (0 == osip_strcasecmp ("rtpmap", attr->a_att_field)
+ && attr->a_att_value != NULL)
+ {
+ char *tmp = strchr (attr->a_att_value, ' ');
+ char *tmp2 = strchr (rtpmap, ' ');
+
+ if (tmp != NULL && tmp2 != NULL)
+ {
+ if (0 == osip_strcasecmp (tmp, tmp2))
+ return med;
+ }
+ }
+ pos++;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Search for support of a special codec.
+ * @param config The element to work on.
+ * @param payload The payload to find.
+ */
+sdp_media_t *
+osip_rfc3264_find_t38 (struct osip_rfc3264 * config, char *payload)
+{
+ //osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+
+ if (config == NULL)
+ return NULL;
+ return NULL;
+}
+
+/**
+ * Search for support of a special codec.
+ * @param config The element to work on.
+ * @param payload The payload to find.
+ */
+sdp_media_t *
+osip_rfc3264_find_app (struct osip_rfc3264 * config, char *payload)
+{
+ // osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+
+ if (config == NULL)
+ return NULL;
+ return NULL;
+}
+
+/**
+ * Compare remote sdp packet against local supported media.
+ * Only one media line is checked.
+ *
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param audio_tab The local list of media supported by both side.
+ * @param video_tab The local list of media supported by both side.
+ * @param t38_tab The local list of media supported by both side.
+ * @param app_tab The local list of media supported by both side.
+ * @param pos_media The position of the media line to match.
+ */
+int
+osip_rfc3264_match (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ sdp_media_t * audio_tab[],
+ sdp_media_t * video_tab[],
+ sdp_media_t * t38_tab[],
+ sdp_media_t * app_tab[], int pos_media)
+{
+ sdp_media_t *remote_med;
+ int pos;
+
+ audio_tab[0] = NULL;
+ video_tab[0] = NULL;
+ t38_tab[0] = NULL;
+ app_tab[0] = NULL;
+
+ if (config == NULL)
+ return -1;
+
+ pos = 0;
+ while (!sdp_message_endof_media (remote_sdp, pos))
+ {
+ if (pos_media == 0)
+ {
+ remote_med = osip_list_get (remote_sdp->m_medias, pos);
+ if (remote_med->m_media != NULL
+ && 0 == osip_strcasecmp (remote_med->m_media, "audio"))
+ {
+ osip_rfc3264_match_audio (config, remote_sdp, remote_med, audio_tab);
+ } else if (remote_med->m_media != NULL
+ && 0 == osip_strcasecmp (remote_med->m_media, "video"))
+ {
+ osip_rfc3264_match_video (config, remote_sdp, remote_med, video_tab);
+ } else if (remote_med->m_media != NULL
+ && 0 == osip_strcasecmp (remote_med->m_media, "image"))
+ {
+ osip_rfc3264_match_t38 (config, remote_sdp, remote_med, t38_tab);
+ } else if (remote_med->m_media != NULL
+ && 0 == osip_strcasecmp (remote_med->m_media, "application"))
+ {
+ osip_rfc3264_match_app (config, remote_sdp, remote_med, app_tab);
+ }
+ return 0;
+ }
+
+ remote_med = NULL;
+ pos++;
+ pos_media--;
+ }
+
+ return -1;
+}
+
+/**
+ * Compare remote sdp packet against local supported media for audio.
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param remote_med The remote Media SDP line.
+ * @param audio_tab The local list of media supported by both side.
+ */
+int
+osip_rfc3264_match_audio (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ sdp_media_t * remote_med, sdp_media_t * audio_tab[])
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+ int num = 0;
+ int pos;
+
+ audio_tab[0] = NULL;
+
+ if (cnf == NULL)
+ return -1;
+
+ /* search for the audio media line */
+ pos = 0;
+ while (!osip_list_eol (remote_med->m_payloads, pos))
+ {
+ char *payload = (char *) osip_list_get (remote_med->m_payloads, pos);
+ sdp_media_t *local_med;
+ char *rtpmap = NULL;
+ int posattr = 0;
+
+ /* search for the rtpmap associated to the payload */
+ while (!osip_list_eol (remote_med->a_attributes, posattr))
+ {
+ sdp_attribute_t *attr =
+ (sdp_attribute_t *) osip_list_get (remote_med->a_attributes,
+ posattr);
+
+ if (0 == osip_strncasecmp (attr->a_att_field, "rtpmap", 6))
+ {
+ if (attr->a_att_value != NULL &&
+ 0 == osip_strncasecmp (attr->a_att_value, payload,
+ strlen (payload)))
+ {
+ /* TODO check if it was not like 101: == 10 */
+ rtpmap = attr->a_att_value;
+ break;
+ }
+ }
+ posattr++;
+ }
+
+ local_med = osip_rfc3264_find_audio (config, payload, rtpmap);
+ if (local_med != NULL)
+ {
+ /* found a supported codec? */
+ audio_tab[num] = local_med;
+ num++;
+ }
+
+ /* search for support of this codec in local media list */
+ pos++;
+ }
+
+ audio_tab[num] = NULL;
+ return 0;
+}
+
+/**
+ * Compare remote sdp packet against local supported media for video.
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param remote_med The remote Media SDP line.
+ * @param video_tab The local list of media supported by both side.
+ */
+int
+osip_rfc3264_match_video (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ sdp_media_t * remote_med, sdp_media_t * video_tab[])
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+ int num = 0;
+ int pos;
+
+ video_tab[0] = NULL;
+
+ if (cnf == NULL)
+ return -1;
+
+ /* search for the video media line */
+
+ pos = 0;
+ while (!osip_list_eol (remote_med->m_payloads, pos))
+ {
+ char *payload = (char *) osip_list_get (remote_med->m_payloads, pos);
+ sdp_media_t *local_med;
+ char *rtpmap = NULL;
+ int posattr = 0;
+
+ /* search for the rtpmap associated to the payload */
+ while (!osip_list_eol (remote_med->a_attributes, posattr))
+ {
+ sdp_attribute_t *attr =
+ (sdp_attribute_t *) osip_list_get (remote_med->a_attributes,
+ posattr);
+
+ if (0 == osip_strncasecmp (attr->a_att_field, "rtpmap", 6))
+ {
+ if (attr->a_att_value != NULL &&
+ 0 == osip_strncasecmp (attr->a_att_value, payload,
+ strlen (payload)))
+ {
+ /* TODO check if it was not like 101: == 10 */
+ rtpmap = attr->a_att_value;
+ break;
+ }
+ }
+ posattr++;
+ }
+
+ local_med = osip_rfc3264_find_video (config, payload, rtpmap);
+ if (local_med != NULL)
+ {
+ /* found a supported codec? */
+ video_tab[num] = local_med;
+ num++;
+ }
+
+ /* search for support of this codec in local media list */
+ pos++;
+ }
+
+ video_tab[num] = NULL;
+ return 0;
+}
+
+/**
+ * Compare remote sdp packet against local supported media for t38.
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param remote_med The remote Media SDP line.
+ * @param t38_tab The local list of media supported by both side.
+ */
+int
+osip_rfc3264_match_t38 (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ sdp_media_t * remote_med, sdp_media_t * t38_tab[])
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+
+ t38_tab[0] = NULL;
+
+ if (cnf == NULL)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * Compare remote sdp packet against local supported media for application.
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param remote_med The remote Media SDP line.
+ * @param app_tab The local list of media supported by both side.
+ */
+int
+osip_rfc3264_match_app (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ sdp_media_t * remote_med, sdp_media_t * app_tab[])
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+
+ app_tab[0] = NULL;
+
+ if (cnf == NULL)
+ return -1;
+
+ return 0;
+}
+
+
+/**
+ * Prepare an uncomplete answer.
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param local_sdp The local SDP packet to prepare.
+ * @param length The local SDP packet's length.
+ */
+int
+osip_rfc3264_prepare_answer (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ char *local_sdp, int length)
+{
+ int pos, pos2;
+
+ if (config == NULL)
+ return -1;
+ if (remote_sdp == NULL)
+ return -1;
+
+ if (osip_list_size (remote_sdp->t_descrs) > 0)
+
+#if !defined __PALMOS__ && (defined WIN32 || defined _WIN32_WCE)
+ _snprintf (local_sdp, 4096, "v=0\r\n\
+o=userX 20000001 20000001 IN IP4 TOREPLACE\r\n\
+s=-\r\n\
+c=IN IP4 TOREPLACE\r\n");
+#else
+ snprintf (local_sdp, 4096, "v=0\r\n\
+o=userX 20000001 20000001 IN IP4 TOREPLACE\r\n\
+s=-\r\n\
+c=IN IP4 TOREPLACE\r\n");
+#endif
+ /* Fill t= (and r=) fields */
+ pos = 0;
+ while (!osip_list_eol (remote_sdp->t_descrs, pos))
+ {
+ char tmp[100];
+ sdp_time_descr_t *td;
+
+ td = (sdp_time_descr_t *) osip_list_get (remote_sdp->t_descrs, pos);
+ if (td->t_start_time != NULL && td->t_stop_time != NULL)
+#if !defined __PALMOS__ && (defined WIN32 || defined _WIN32_WCE)
+ _snprintf (tmp, 100, "t=%s %s\r\n", td->t_start_time, td->t_stop_time);
+#else
+ snprintf (tmp, 100, "t=%s %s\r\n", td->t_start_time, td->t_stop_time);
+#endif
+ else
+#if !defined __PALMOS__ && (defined WIN32 || defined _WIN32_WCE)
+ _snprintf (tmp, 100, "t=0 0\r\n");
+#else
+ snprintf (tmp, 100, "t=0 0\r\n");
+#endif
+ if ((int) (strlen (local_sdp) + strlen (tmp) + 1) < length)
+
+ {
+ strcat (local_sdp, tmp);
+
+ pos2 = 0;
+ while (!osip_list_eol (td->r_repeats, pos2))
+ {
+ char *str = (char *) osip_list_get (td->r_repeats, pos2);
+
+ if ((int) (strlen (local_sdp) + strlen (str) + 5 + 1) < length)
+ {
+ strcat (local_sdp, "r=");
+ strcat (local_sdp, str);
+ strcat (local_sdp, "\r\n");
+ } else
+ return -1;
+ pos2++;
+ }
+ } else
+ return -1;
+ pos++;
+ }
+
+
+ pos = 0;
+ while (!osip_list_eol (remote_sdp->m_medias, pos))
+ {
+ int posattr = 0;
+ char tmp[200];
+ char tmp2[200];
+ char inactive = 'X';
+ sdp_media_t *med;
+
+#if !defined __PALMOS__ && (defined WIN32 || defined _WIN32_WCE)
+ _snprintf (tmp2, 199, "\r\n");
+#else
+ snprintf (tmp2, 199, "\r\n");
+#endif
+ med = (sdp_media_t *) osip_list_get (remote_sdp->m_medias, pos);
+
+ /* search for the rtpmap associated to the payload */
+ while (!osip_list_eol (med->a_attributes, posattr))
+ {
+ sdp_attribute_t *attr =
+ (sdp_attribute_t *) osip_list_get (med->a_attributes, posattr);
+ if (strlen (attr->a_att_field) == 8 && attr->a_att_value == NULL)
+ {
+ if (0 == osip_strncasecmp (attr->a_att_field, "sendonly", 8))
+ {
+#if !defined __PALMOS__ && (defined WIN32 || defined _WIN32_WCE)
+ _snprintf (tmp2, 199, "\r\na=recvonly\r\n");
+#else
+ snprintf (tmp2, 199, "\r\na=recvonly\r\n");
+#endif
+ break;
+ } else if (0 == osip_strncasecmp (attr->a_att_field, "recvonly", 8))
+ {
+#if !defined __PALMOS__ && (defined WIN32 || defined _WIN32_WCE)
+ _snprintf (tmp2, 199, "\r\na=sendonly\r\n");
+#else
+ snprintf (tmp2, 199, "\r\na=sendonly\r\n");
+#endif
+ break;
+ } else if (0 == osip_strncasecmp (attr->a_att_field, "sendrecv", 8))
+ {
+ break;
+ } else if (0 == osip_strncasecmp (attr->a_att_field, "inactive", 8))
+ {
+#if !defined __PALMOS__ && (defined WIN32 || defined _WIN32_WCE)
+ _snprintf (tmp2, 199, "\r\na=inactive\r\n");
+#else
+ snprintf (tmp2, 199, "\r\na=inactive\r\n");
+#endif
+ inactive = '0';
+ break;
+ }
+ }
+ posattr++;
+ }
+
+ if (med->m_media != NULL && med->m_proto != NULL
+ && med->m_number_of_port == NULL)
+ {
+#if !defined __PALMOS__ && (defined WIN32 || defined _WIN32_WCE)
+ _snprintf (tmp, 199, "m=%s %c %s ", med->m_media, inactive,
+ med->m_proto);
+#else
+ snprintf (tmp, 199, "m=%s %c %s ", med->m_media, inactive, med->m_proto);
+#endif
+ } else if (med->m_media != NULL && med->m_proto != NULL
+ && med->m_number_of_port != NULL)
+ {
+#if !defined __PALMOS__ && (defined WIN32 || defined _WIN32_WCE)
+ _snprintf (tmp, 199, "m=%s %c %s/%s ", med->m_media, inactive,
+ med->m_proto, med->m_number_of_port);
+#else
+ snprintf (tmp, 199, "m=%s %c %s/%s ", med->m_media, inactive,
+ med->m_proto, med->m_number_of_port);
+#endif
+ } else
+ return -1;
+
+ if ((int) (strlen (local_sdp) + strlen (tmp) + 1) < length)
+ strcat (local_sdp, tmp);
+ else
+ return -1;
+
+ if ((int) (strlen (local_sdp) + strlen (tmp2) + 1) < length)
+ strcat (local_sdp, tmp2);
+ else
+ return -1;
+
+ pos++;
+ }
+
+ return 0;
+}
+
+/**
+ * Agree to support a specific codec.
+ * This method should be called for each codec returned by
+ * osip_rfc3264_match(...) that the calle agree to support.
+ *
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param local_sdp The local SDP packet to complete.
+ * @param med One of the media returned by osip_rfc3264_match.
+ * @param mline The position of the media line to complete.
+ */
+int
+osip_rfc3264_complete_answer (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ sdp_message_t * local_sdp,
+ sdp_media_t * med, int mline)
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+ sdp_media_t *remote_med = NULL;
+ sdp_media_t *local_med = NULL;
+ int pos;
+
+ if (cnf == NULL)
+ return -1;
+ if (remote_sdp == NULL)
+ return -1;
+ if (med == NULL)
+ return -1;
+ if (mline < 0)
+ return -1;
+ if (local_sdp == NULL)
+ return -1;
+ pos = 0;
+ while (!osip_list_eol (remote_sdp->m_medias, pos))
+ {
+ remote_med = (sdp_media_t *) osip_list_get (remote_sdp->m_medias, pos);
+ local_med = (sdp_media_t *) osip_list_get (local_sdp->m_medias, pos);
+ if (pos == mline)
+ break;
+ remote_med = NULL;
+ local_med = NULL;
+ pos++;
+ }
+ if (remote_med == NULL)
+ return -1;
+
+ pos = 0;
+ while (!osip_list_eol (med->a_attributes, pos))
+ {
+ sdp_attribute_t *attr =
+ (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
+
+ if (0 == osip_strcasecmp ("rtpmap", attr->a_att_field)
+ && attr->a_att_value != NULL)
+ {
+ sdp_attribute_t *mattr;
+ char *tmp;
+
+ /* fill the m= line */
+ tmp = (char *) osip_list_get (med->m_payloads, 0);
+ if (tmp != NULL)
+ osip_list_add (local_med->m_payloads, osip_strdup (tmp), -1);
+ else
+ return -1;
+
+ sdp_attribute_init (&mattr);
+ mattr->a_att_field = osip_strdup (attr->a_att_field);
+ mattr->a_att_value = osip_strdup (attr->a_att_value);
+
+ /* fill the a= line */
+ osip_list_add (local_med->a_attributes, mattr, -1);
+ return 0;
+ }
+ }
+
+ return -1; /* no rtpmap found? It is mandatory in audio and video media */
+}
+
+/**
+ * Agree to support a specific codec.
+ * This method should be called for each codec returned by
+ * osip_rfc3264_match(...)
+ *
+ * @param config The element to work on.
+ * @param med One of the media returned by osip_rfc3264_match
+ * @param remote_sdp The remote SDP packet.
+ * @param local_sdp The local SDP packet to prepare.
+ */
+int
+osip_rfc3264_accept_codec (struct osip_rfc3264 *config,
+ sdp_media_t * med,
+ sdp_message_t * remote_sdp, sdp_message_t * local_sdp)
+{
+ if (config == NULL)
+ return -1;
+
+ return 0;
+}
+
+
+/* #ifdef RFC3264_DEBUG */
+
+/**
+ * List supported codecs. (for debugging purpose only)
+ *
+ * @param config The element to work on.
+ */
+int
+__osip_rfc3264_print_codecs (struct osip_rfc3264 *config)
+{
+ osip_rfc3264_t *cnf = (osip_rfc3264_t *) config;
+ int i, pos;
+
+ if (config == NULL)
+ return -1;
+
+ fprintf (stdout, "Audio codecs Supported:\n");
+ for (i = 0; i < MAX_AUDIO_CODECS; i++)
+ {
+ if (cnf->audio_medias[i] != NULL)
+ {
+ sdp_media_t *med = cnf->audio_medias[i];
+ char *str = (char *) osip_list_get (med->m_payloads, 0);
+
+ fprintf (stdout, "\tm=%s %s %s %s\n",
+ med->m_media, med->m_port, med->m_proto, str);
+ pos = 0;
+ while (!osip_list_eol (med->a_attributes, pos))
+ {
+ sdp_attribute_t *attr =
+ (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
+ fprintf (stdout, "\ta=%s:%s\n",
+ attr->a_att_field, attr->a_att_value);
+ pos++;
+ }
+ fprintf (stdout, "\n");
+ }
+ }
+
+ fprintf (stdout, "Video codecs Supported:\n");
+ for (i = 0; i < MAX_VIDEO_CODECS; i++)
+ {
+ if (cnf->video_medias[i] != NULL)
+ {
+ sdp_media_t *med = cnf->video_medias[i];
+ char *str = (char *) osip_list_get (med->m_payloads, 0);
+
+ fprintf (stdout, "\tm=%s %s %s %s\n",
+ med->m_media, med->m_port, med->m_proto, str);
+ pos = 0;
+ while (!osip_list_eol (med->a_attributes, pos))
+ {
+ sdp_attribute_t *attr =
+ (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
+ fprintf (stdout, "\ta=%s:%s\n",
+ attr->a_att_field, attr->a_att_value);
+ pos++;
+ }
+ fprintf (stdout, "\n");
+ }
+ }
+
+ fprintf (stdout, "t38 configs Supported:\n");
+ for (i = 0; i < MAX_T38_CODECS; i++)
+ {
+ if (cnf->t38_medias[i] != NULL)
+ {
+ sdp_media_t *med = cnf->t38_medias[i];
+
+ fprintf (stdout, "m=%s %s %s X\n",
+ med->m_media, med->m_port, med->m_proto);
+ pos = 0;
+ while (!osip_list_eol (med->a_attributes, pos))
+ {
+ sdp_attribute_t *attr =
+ (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
+ fprintf (stdout, "\ta=%s:%s\n",
+ attr->a_att_field, attr->a_att_value);
+ pos++;
+ }
+ fprintf (stdout, "\n");
+ }
+ }
+
+ fprintf (stdout, "Application config Supported:\n");
+ for (i = 0; i < MAX_APP_CODECS; i++)
+ {
+ if (cnf->app_medias[i] != NULL)
+ {
+ sdp_media_t *med = cnf->app_medias[i];
+
+ fprintf (stdout, "m=%s %s %s X\n",
+ med->m_media, med->m_port, med->m_proto);
+ pos = 0;
+ while (!osip_list_eol (med->a_attributes, pos))
+ {
+ sdp_attribute_t *attr =
+ (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
+ fprintf (stdout, "\ta=%s:%s\n",
+ attr->a_att_field, attr->a_att_value);
+ pos++;
+ }
+ fprintf (stdout, "\n");
+ }
+ }
+
+ return 0;
+}
+
+/* #endif */
--- /dev/null
+/*
+ The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
+ Copyright (C) 2001,2002,2003,2004 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
+*/
+
+#ifndef __SDP_RFC3264_H__
+#define __SDP_RFC3264_H__
+
+#include <osipparser2/osip_list.h>
+#include <osipparser2/sdp_message.h>
+
+/**
+ * @file osip_rfc3264.h
+ * @brief oSIP sdp negotiation facility.
+ */
+
+/**
+ * @defgroup oSIP_rfc3264 oSIP sdp negotiation facility.
+ * @ingroup osip2_sdp
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * Structure to hold support for codecs.
+ * @struct osip_rfc3264
+ */
+ struct osip_rfc3264;
+
+/**
+ * Maximum number of supported audio payload.
+ * @def MAX_AUDIO_CODECS
+ */
+#define MAX_AUDIO_CODECS 100
+/**
+ * Maximum number of supported video payload.
+ * @def MAX_VIDEO_CODECS
+ */
+#define MAX_VIDEO_CODECS 100
+/**
+ * Maximum number of supported t38 config.
+ * @def MAX_T38_CODECS
+ */
+#define MAX_T38_CODECS 2
+/**
+ * Maximum number of supported application config.
+ * @def MAX_APP_CODECS
+ */
+#define MAX_APP_CODECS 100
+
+/**
+ * Initialize negotiation facility..
+ * @param config The element to work on.
+ */
+ int osip_rfc3264_init (struct osip_rfc3264 **config);
+
+/**
+ * Free negotiation facility.
+ * @param config The element to work on.
+ */
+ void osip_rfc3264_free (struct osip_rfc3264 *config);
+
+/**
+ * Test if a media exist in the configuration.
+ * @param config The element to work on.
+ * @param pos The index of the media element.
+ */
+ int osip_rfc3264_endof_media (struct osip_rfc3264 *config, int pos);
+
+/**
+ * Get a media from the configuration.
+ * @param config The element to work on.
+ * @param pos The index of the media element to get.
+ */
+ sdp_media_t *osip_rfc3264_get (struct osip_rfc3264 *config, int pos);
+
+/**
+ * Remove a media from the configuration.
+ * @param config The element to work on.
+ * @param pos The index of the media element to remove.
+ */
+ int osip_rfc3264_remove (struct osip_rfc3264 *config, int pos);
+
+/**
+ * Remove all medias from the configuration.
+ * @param config The element to work on.
+ */
+ int osip_rfc3264_reset_media (struct osip_rfc3264 *config);
+
+/**
+ * Add a media in the configuration.
+ * @param config The element to work on.
+ * @param med The media element to add.
+ * @param pos The index of the media element to add.
+ */
+ int osip_rfc3264_add_audio_media (struct osip_rfc3264 *config,
+ sdp_media_t * med, int pos);
+
+/**
+ * Remove a media in the configuration.
+ * @param config The element to work on.
+ * @param pos The index of the media element to remove.
+ */
+ int osip_rfc3264_del_audio_media (struct osip_rfc3264 *config, int pos);
+
+/**
+ * Add a media (for T.38) in the configuration.
+ * @param config The element to work on.
+ * @param med The media element to add.
+ * @param pos The index of the media element to add.
+ */
+ int osip_rfc3264_add_t38_media (struct osip_rfc3264 *config,
+ sdp_media_t * med, int pos);
+
+/**
+ * Remove a media (for T.38) in the configuration.
+ * @param config The element to work on.
+ * @param pos The index of the media element to remove.
+ */
+ int osip_rfc3264_del_t38_media (struct osip_rfc3264 *config, int pos);
+
+/**
+ * Add a media (for video) in the configuration.
+ * @param config The element to work on.
+ * @param med The media element to add.
+ * @param pos The index of the media element to add.
+ */
+ int osip_rfc3264_add_video_media (struct osip_rfc3264 *config,
+ sdp_media_t * med, int pos);
+
+/**
+ * Remove a media in the configuration.
+ * @param config The element to work on.
+ * @param pos The index of the media element to remove.
+ */
+ int osip_rfc3264_del_video_media (struct osip_rfc3264 *config, int pos);
+
+
+/**
+ * Search for support of a special codec.
+ * @param config The element to work on.
+ */
+ sdp_media_t *osip_rfc3264_find_audio (struct osip_rfc3264 *config,
+ char *payload, char *rtpmap);
+
+/**
+ * Search for support of a special codec.
+ * @param config The element to work on.
+ * @param payload The payload to find.
+ * @param rtpmap The rtpmap for the payload.
+ */
+ sdp_media_t *osip_rfc3264_find_video (struct osip_rfc3264 *config,
+ char *payload, char *rtpmap);
+
+/**
+ * Search for support of a special codec.
+ * @param config The element to work on.
+ * @param payload The payload to find.
+ */
+ sdp_media_t *osip_rfc3264_find_t38 (struct osip_rfc3264 *config, char *payload);
+
+/**
+ * Search for support of a special codec.
+ * @param config The element to work on.
+ * @param payload The payload to find.
+ */
+ sdp_media_t *osip_rfc3264_find_app (struct osip_rfc3264 *config, char *payload);
+
+/**
+ * Compare remote sdp packet against local supported media.
+ * Only one media line is checked.
+ *
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param audio_tab The local list of media supported by both side.
+ * @param video_tab The local list of media supported by both side.
+ * @param t38_tab The local list of media supported by both side.
+ * @param app_tab The local list of media supported by both side.
+ * @param pos_media The position of the media line to match.
+ */
+ int osip_rfc3264_match (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ sdp_media_t * audio_tab[],
+ sdp_media_t * video_tab[],
+ sdp_media_t * t38_tab[],
+ sdp_media_t * app_tab[], int pos_media);
+
+/**
+ * Compare remote sdp packet against local supported media for audio.
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param remote_med The remote Media SDP line.
+ * @param audio_tab The local list of media supported by both side.
+ */
+ int osip_rfc3264_match_audio (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ sdp_media_t * remote_med,
+ sdp_media_t * audio_tab[]);
+
+/**
+ * Compare remote sdp packet against local supported media for video.
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param remote_med The remote Media SDP line.
+ * @param video_tab The local list of media supported by both side.
+ */
+ int osip_rfc3264_match_video (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ sdp_media_t * remote_med,
+ sdp_media_t * video_tab[]);
+
+/**
+ * Compare remote sdp packet against local supported media for t38.
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param remote_med The remote Media SDP line.
+ * @param t38_tab The local list of media supported by both side.
+ */
+ int osip_rfc3264_match_t38 (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ sdp_media_t * remote_med, sdp_media_t * t38_tab[]);
+
+/**
+ * Compare remote sdp packet against local supported media for application.
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param remote_med The remote Media SDP line.
+ * @param app_tab The local list of media supported by both side.
+ */
+ int osip_rfc3264_match_app (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ sdp_media_t * remote_med, sdp_media_t * app_tab[]);
+
+
+/**
+ * Prepare an uncomplete answer.
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param local_sdp The local SDP packet to prepare.
+ * @param length The local SDP packet's length.
+ */
+ int osip_rfc3264_prepare_answer (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ char *local_sdp, int length);
+
+/**
+ * Agree to support a specific codec.
+ * This method should be called for each codec returned by
+ * osip_rfc3264_match(...) that the calle agree to support.
+ *
+ * @param config The element to work on.
+ * @param remote_sdp The remote SDP packet.
+ * @param local_sdp The local SDP packet to complete.
+ * @param med One of the media returned by osip_rfc3264_match.
+ * @param mline The position of the media line to complete.
+ */
+ int
+ osip_rfc3264_complete_answer (struct osip_rfc3264 *config,
+ sdp_message_t * remote_sdp,
+ sdp_message_t * local_sdp,
+ sdp_media_t * med, int mline);
+
+/**
+ * Agree to support a specific codec.
+ * This method should be called for each codec returned by
+ * osip_rfc3264_match(...)
+ *
+ * @param config The element to work on.
+ * @param med One of the media returned by osip_rfc3264_match
+ * @param remote_sdp The remote SDP packet.
+ * @param local_sdp The local SDP packet to prepare.
+ */
+ int osip_rfc3264_accept_codec (struct osip_rfc3264 *config,
+ sdp_media_t * med,
+ sdp_message_t * remote_sdp,
+ sdp_message_t * local_sdp);
+
+
+/**
+ * List supported codecs. (for debugging purpose only)
+ *
+ * @param config The element to work on.
+ */
+ int __osip_rfc3264_print_codecs (struct osip_rfc3264 *config);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif