From 155f9d742ff4df39ba149f47baec8d518da36551 Mon Sep 17 00:00:00 2001 From: ben Date: Mon, 26 Jun 2006 17:37:55 +0000 Subject: [PATCH] new imported library in libmpdemux: freesdp (will be used by native rtsp demuxer) git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@18827 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libmpdemux/Makefile | 7 +- libmpdemux/freesdp/common.c | 226 ++++ libmpdemux/freesdp/common.h | 352 ++++++ libmpdemux/freesdp/errorlist.c | 72 ++ libmpdemux/freesdp/parser.c | 1958 +++++++++++++++++++++++++++++++ libmpdemux/freesdp/parser.h | 728 ++++++++++++ libmpdemux/freesdp/parserpriv.h | 118 ++ libmpdemux/freesdp/priv.h | 274 +++++ 8 files changed, 3734 insertions(+), 1 deletion(-) create mode 100644 libmpdemux/freesdp/common.c create mode 100644 libmpdemux/freesdp/common.h create mode 100644 libmpdemux/freesdp/errorlist.c create mode 100644 libmpdemux/freesdp/parser.c create mode 100644 libmpdemux/freesdp/parser.h create mode 100644 libmpdemux/freesdp/parserpriv.h create mode 100644 libmpdemux/freesdp/priv.h diff --git a/libmpdemux/Makefile b/libmpdemux/Makefile index ab32d53a61..2179ea3e36 100644 --- a/libmpdemux/Makefile +++ b/libmpdemux/Makefile @@ -141,6 +141,10 @@ SRCS += realrtsp/asmrp.c \ SRCS += librtsp/rtsp.c \ librtsp/rtsp_session.c \ +SRCS += freesdp/common.c \ + freesdp/errorlist.c \ + freesdp/parser.c \ + ifeq ($(STREAMING_LIVE555),yes) CPLUSPLUSSRCS = demux_rtp.cpp demux_rtp_codec.cpp CPLUSPLUSINCLUDE = $(LIVE_INCLUDES) @@ -188,7 +192,8 @@ test: $(LIBNAME) test.c clean: rm -f *.o *.a *~ \ realrtsp/*.o realrtsp/*.a realrtsp/*~ \ - librtsp/*.o librtsp/*.a librtsp/*~ + librtsp/*.o librtsp/*.a librtsp/*~ \ + freesdp/*.o freesdp/*.a freesdp/*~ distclean: clean rm -f .depend test diff --git a/libmpdemux/freesdp/common.c b/libmpdemux/freesdp/common.c new file mode 100644 index 0000000000..6ea625d2ed --- /dev/null +++ b/libmpdemux/freesdp/common.c @@ -0,0 +1,226 @@ +/* + This file is part of FreeSDP + Copyright (C) 2001,2002,2003 Federico Montesino Pouzols + + FreeSDP is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** + * @file common.c + * + * @short Implementation of routines common to parse and formatting + * modules . + * + * This file implements the routines that operate over data structures + * that are used in both the parse and formatting modules. + **/ + +#include "priv.h" +#include "common.h" + +static void +safe_free (void *ptr) +{ + if (ptr) + free (ptr); +} + +fsdp_description_t * +fsdp_description_new (void) +{ + fsdp_description_t *result = malloc (sizeof (fsdp_description_t)); + + result->version = 0; + result->o_username = result->o_session_id = + result->o_announcement_version = NULL; + result->o_network_type = FSDP_NETWORK_TYPE_UNDEFINED; + result->o_address_type = FSDP_ADDRESS_TYPE_UNDEFINED; + result->o_address = NULL; + result->s_name = NULL; + result->i_information = NULL; + result->u_uri = NULL; + result->emails = NULL; + result->emails_count = 0; + result->phones = NULL; + result->phones_count = 0; + /* At first, there is no session-level definition for these + parameters */ + result->c_network_type = FSDP_NETWORK_TYPE_UNDEFINED; + result->c_address_type = FSDP_ADDRESS_TYPE_UNDEFINED; + result->c_address.address = NULL; + /* there is no session-level definition for these parameters */ + result->bw_modifiers = NULL; + result->bw_modifiers_count = 0; + result->time_periods = NULL; + result->time_periods_count = 0; + result->timezone_adj = NULL; + result->k_encryption_method = FSDP_ENCRYPTION_METHOD_UNDEFINED; + result->k_encryption_content = NULL; + /* Default/undefined values for attributes */ + result->a_category = result->a_keywords = result->a_tool = NULL; + result->a_type = FSDP_SESSION_TYPE_UNDEFINED; + result->a_sendrecv_mode = FSDP_SENDRECV_UNDEFINED; + result->a_charset = NULL; + result->a_sdplangs = result->a_langs = NULL; + result->a_controls = NULL; + result->a_range = NULL; + result->a_rtpmaps = NULL; + result->a_rtpmaps_count = 0; + result->a_sdplangs_count = 0; + result->a_langs_count = 0; + result->a_controls_count = 0; + result->unidentified_attributes = NULL; + result->unidentified_attributes_count = 0; + result->media_announcements = NULL; + result->media_announcements_count = 0; + + return result; +} + +void +fsdp_description_delete (fsdp_description_t * dsc) +{ + fsdp_description_recycle (dsc); + safe_free (dsc); +} + +void +fsdp_description_recycle (fsdp_description_t * dsc) +{ + /* Recursively free all strings and arrays */ + unsigned int i, j; + + if (!dsc) + return; + + safe_free (dsc->o_username); + safe_free (dsc->o_session_id); + safe_free (dsc->o_announcement_version); + safe_free (dsc->o_address); + safe_free (dsc->s_name); + safe_free (dsc->i_information); + safe_free (dsc->u_uri); + + for (i = 0; i < dsc->emails_count; i++) + safe_free ((char *) dsc->emails[i]); + safe_free (dsc->emails); + + for (i = 0; i < dsc->phones_count; i++) + safe_free ((char *) dsc->phones[i]); + safe_free (dsc->phones); + + safe_free (dsc->c_address.address); + + for (i = 0; i < dsc->bw_modifiers_count; i++) + safe_free (dsc->bw_modifiers[i].b_unknown_bw_modt); + safe_free (dsc->bw_modifiers); + + for (i = 0; i < dsc->time_periods_count; i++) + { + for (j = 0; j < dsc->time_periods[i]->repeats_count; j++) + { + safe_free (dsc->time_periods[i]->repeats[j]->offsets); + safe_free (dsc->time_periods[i]->repeats[j]); + } + safe_free (dsc->time_periods[i]->repeats); + safe_free (dsc->time_periods[i]); + } + safe_free (dsc->time_periods); + + safe_free (dsc->timezone_adj); + safe_free (dsc->a_category); + safe_free (dsc->a_keywords); + safe_free (dsc->a_tool); + + for (i = 0; i < dsc->a_rtpmaps_count; i++) + safe_free (dsc->a_rtpmaps[i]); + safe_free (dsc->a_rtpmaps); + + safe_free (dsc->a_charset); + + for (i = 0; i < dsc->a_sdplangs_count; i++) + safe_free (dsc->a_sdplangs[i]); + safe_free (dsc->a_sdplangs); + + for (i = 0; i < dsc->a_langs_count; i++) + safe_free (dsc->a_langs[i]); + safe_free (dsc->a_langs); + + for (i = 0; i < dsc->a_controls_count; i++) + safe_free (dsc->a_controls[i]); + safe_free (dsc->a_controls); + + safe_free (dsc->a_range); + + for (i = 0; i < dsc->media_announcements_count; i++) + { + for (j = 0; j < dsc->media_announcements[i]->formats_count; j++) + safe_free (dsc->media_announcements[i]->formats[j]); + safe_free (dsc->media_announcements[i]->formats); + safe_free (dsc->media_announcements[i]->i_title); + + for (j = 0; j < dsc->media_announcements[i]->bw_modifiers_count; j++) + { + if (FSDP_BW_MOD_TYPE_UNKNOWN == + dsc->media_announcements[i]->bw_modifiers[j].b_mod_type) + safe_free (dsc->media_announcements[i]->bw_modifiers[j]. + b_unknown_bw_modt); + } + safe_free (dsc->media_announcements[i]->bw_modifiers); + + safe_free (dsc->media_announcements[i]->k_encryption_content); + + for (j = 0; j < dsc->media_announcements[i]->a_rtpmaps_count; j++) + { + safe_free (dsc->media_announcements[i]->a_rtpmaps[j]->pt); + safe_free (dsc->media_announcements[i]->a_rtpmaps[j]-> + encoding_name); + safe_free (dsc->media_announcements[i]->a_rtpmaps[j]->parameters); + safe_free (dsc->media_announcements[i]->a_rtpmaps[j]); + } + safe_free (dsc->media_announcements[i]->a_rtpmaps); + + for (j = 0; j < dsc->media_announcements[i]->a_sdplangs_count; j++) + safe_free (dsc->media_announcements[i]->a_sdplangs[j]); + safe_free (dsc->media_announcements[i]->a_sdplangs); + + for (j = 0; j < dsc->media_announcements[i]->a_langs_count; j++) + safe_free (dsc->media_announcements[i]->a_langs[j]); + safe_free (dsc->media_announcements[i]->a_langs); + + for (j = 0; j < dsc->media_announcements[i]->a_controls_count; j++) + safe_free (dsc->media_announcements[i]->a_controls[j]); + safe_free (dsc->media_announcements[i]->a_controls); + + for (j = 0; j < dsc->media_announcements[i]->a_fmtps_count; j++) + safe_free (dsc->media_announcements[i]->a_fmtps[j]); + safe_free (dsc->media_announcements[i]->a_fmtps); + + for (j = 0; + j < dsc->media_announcements[i]->unidentified_attributes_count; j++) + safe_free (dsc->media_announcements[i]->unidentified_attributes[j]); + safe_free (dsc->media_announcements[i]->unidentified_attributes); + safe_free (dsc->media_announcements[i]); + } + safe_free (dsc->media_announcements); + + /* This prevents the user to make the library crash when incorrectly + using recycled but not rebuilt descriptions */ + dsc->emails_count = 0; + dsc->phones_count = 0; + dsc->bw_modifiers_count = 0; + dsc->time_periods_count = 0; + dsc->media_announcements_count = 0; +} diff --git a/libmpdemux/freesdp/common.h b/libmpdemux/freesdp/common.h new file mode 100644 index 0000000000..ae59406049 --- /dev/null +++ b/libmpdemux/freesdp/common.h @@ -0,0 +1,352 @@ +/* + This file is part of FreeSDP. + Copyright (C) 2001,2002,2003 Federico Montesino Pouzols + + FreeSDP is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** + * @file common.h + * @ingroup common + * @short Public header common for both parsing and formatting modules. + **/ + +#ifndef FSDP_COMMON_H +#define FSDP_COMMON_H + +/* Macros to avoid name mangling when compiling with a C++ compiler */ +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +#include +#include + +BEGIN_C_DECLS +/** + * @defgroup common FreeSDP Common Facilities + * + * Data types and routines common for both parsing and formatting + * modules. + **/ +/** @addtogroup common */ +/*@{*/ +/** + * @enum fsdp_error_t freesdp/common.h + * @short Error codes in the FreeSDP library. + * + * There is a FSDPE_MISSING_XXXX for each mandatory line, as + * FSDPE_MISSING_OWNER. This kind of error is reported when a + * mandatory description line, such as the owner line, is not found + * where it should be in the SDP description. There are also several + * error codes like FSDPE_INVALID_XXXX. These are returned when there + * is a recognized line in the parsed description that violates the + * SDP syntax or gives wrong parameters, for instance "c=foo bar", + * which would cause a FSDPE_INVALID_CONNECTION error code to be + * returned. + **/ +typedef enum +{ + FSDPE_OK = 0, + FSDPE_ILLEGAL_CHARACTER, /**< Misplaced '\r', '\n' or '\0' */ + FSDPE_MISSING_VERSION, /**< The first line is not like + v=... */ + FSDPE_INVALID_VERSION, /**< Parse error in version line, + perhaps, the version specified in + v=... is not valid for FreeSDP */ + FSDPE_MISSING_OWNER, /**< No owner line found in its + place */ + FSDPE_INVALID_OWNER, /**< Parse error in owner line */ + FSDPE_MISSING_NAME, /**< No session name found in its + place */ + FSDPE_EMPTY_NAME, /**< Empty session name line */ + + FSDPE_INVALID_CONNECTION, /**< Syntax error in connection + line */ + + FSDPE_INVALID_CONNECTION_ADDRTYPE, /**< Unrecognized address type in + connection line */ + FSDPE_INVALID_CONNECTION_NETTYPE, /**< Unrecognized network type in + connection line */ + FSDPE_INVALID_BANDWIDTH, /**< Parse error in bandwidth + line */ + FSDPE_MISSING_TIME, /**< No time period has been given + for the session */ + FSDPE_INVALID_TIME, /**< Parse error in time line */ + FSDPE_INVALID_REPEAT, /**< Parse error in repeat time + line */ + FSDPE_INVALID_TIMEZONE, /**< Parse error in timezone line */ + FSDPE_INVALID_ENCRYPTION_METHOD, /**< Unknown encryption method */ + FSDPE_INVALID_ATTRIBUTE, /**< Syntax error in an attribute + line */ + + FSDPE_INVALID_ATTRIBUTE_RTPMAP,/**< Parse error in a=rtpmap:... line */ + FSDPE_INVALID_SESSION_TYPE, /**< An unknown session type has been + specified in a `type:' + session-level attribute */ + + FSDPE_INVALID_MEDIA, /**< Parse error in media line */ + FSDPE_UNKNOWN_MEDIA_TYPE, /**< Unknown media type in media + line */ + + FSDPE_UNKNOWN_MEDIA_TRANSPORT, /**< A media transport has been + specified that is unknown */ + + FSDPE_OVERFILLED, /**< extra unknown lines are at the + end of the description */ + FSDPE_INVALID_LINE, /**< a line unknown to FreeSDP has been + found */ + FSDPE_MISSING_CONNECTION_INFO, /**< No connection information has + been provided for the whole + session nor one or more media */ + FSDPE_INVALID_INDEX, + /* FSDPE_MAXSIZE, description does not fit requested maximun size */ + FSDPE_INTERNAL_ERROR, + + FSDPE_INVALID_PARAMETER, /**< Some parameter of the called + FreeSDP routine has been given an + invalid value. This includes + cases such as NULL pointers. */ + FSDPE_BUFFER_OVERFLOW +} fsdp_error_t; + +/** + * @short Type of network + * + * Initially, SDP defines "Internet". New network types may be + * registered with IANA. However, the number of types is expected to + * be small and rarely extended. In addition, every new network type + * requires at least one new address type. + **/ +typedef enum +{ + FSDP_NETWORK_TYPE_UNDEFINED, /**< Not provided */ + FSDP_NETWORK_TYPE_INET /**< Internet */ +} fsdp_network_type_t; + +/** + * @short Type of address + * + * Initially, IPv4 and IPv6 are defined for the network type + * Internet. New address types may be registered with IANA. + **/ +typedef enum +{ + FSDP_ADDRESS_TYPE_UNDEFINED, /**< Not provided */ + FSDP_ADDRESS_TYPE_IPV4, /**< IP version 4 */ + FSDP_ADDRESS_TYPE_IPV6 /**< IP version 6 */ +} fsdp_address_type_t; + +/** + * @short Type of bandwith modifiers + * + * Bandwidth modifiers specify the meaning of the bandwidth + * value. Initially "Conference Total" and "Application Specific" are + * defined. Both use kilobits as bandwidth unit. "Conference Total" + * specifies that the bandwidth value is a proposed upper limit to the + * session bandwidth. "Application Specific" specifies thath the + * bandwidth value is the application concept of maximum bandwidth. + **/ +typedef enum +{ + FSDP_BW_MOD_TYPE_UNDEFINED, /**< Not provided */ + FSDP_BW_MOD_TYPE_UNKNOWN, /**< Unknown bandwidth + modifier (FreeSDP + ignores it) */ + FSDP_BW_MOD_TYPE_CONFERENCE_TOTAL, /**< "CT - Conference Total" */ + FSDP_BW_MOD_TYPE_APPLICATION_SPECIFIC, /**< "AS - Application specific" */ + FSDP_BW_MOD_TYPE_RTCP_SENDERS, /**< "RS - RTCP bandwidth for + senders */ + FSDP_BW_MOD_TYPE_RTCP_RECEIVERS, /**< "RR - RTCP bandwidth for + receivers */ +} fsdp_bw_modifier_type_t; + +/** + * @short encryption method + * + * The encryption method specifies the way to get the encryption key. + **/ +typedef enum +{ + FSDP_ENCRYPTION_METHOD_UNDEFINED, /**< Not provided */ + FSDP_ENCRYPTION_METHOD_CLEAR, /**< The key field is the + untransformed key */ + FSDP_ENCRYPTION_METHOD_BASE64, /**< The key is base64 + encoded */ + FSDP_ENCRYPTION_METHOD_URI, /**< The key value provided is + a URI pointing to the actual + key */ + FSDP_ENCRYPTION_METHOD_PROMPT /**< The key is not provided + but should be got prompting + the user */ +} fsdp_encryption_method_t; + +/** + * @short Advised reception/transmission mode + * + * Depending on wheter sendrecv, recvonly, sendonly or inactive + * attribute is given, the tools used to participate in the session + * should be started in the corresponding transmission + * mode. FSDP_SENDRECV_SENDRECV is the default for sessions which are + * not of the conference type broadcast or H332. + **/ +typedef enum +{ + FSDP_SENDRECV_UNDEFINED, /**< Not specified */ + FSDP_SENDRECV_SENDRECV, /**< Send and receive */ + FSDP_SENDRECV_RECVONLY, /**< Receive only */ + FSDP_SENDRECV_SENDONLY, /**< Send only */ + FSDP_SENDRECV_INACTIVE /**< Do not send nor receive */ +} fsdp_sendrecv_mode_t; + +/** + * @short Values for `orient' media attribute. + * + * Normally used with whiteboard media, this attribute specifies the + * orientation of the whiteboard. + **/ +typedef enum +{ + FSDP_ORIENT_UNDEFINED, /**< Not specified */ + FSDP_ORIENT_PORTRAIT, /**< Portrait */ + FSDP_ORIENT_LANDSCAPE, /**< Landscape */ + FSDP_ORIENT_SEASCAPE /**< Upside down landscape */ +} fsdp_orient_t; + +/** + * @short Type of the conference + * + * The following types are initially defined: broadcast, meeting, + * moderated, test and H332. + **/ +typedef enum +{ + FSDP_SESSION_TYPE_UNDEFINED, /**< Not specified */ + FSDP_SESSION_TYPE_BROADCAST, /**< Broadcast session */ + FSDP_SESSION_TYPE_MEETING, /**< Meeting session */ + FSDP_SESSION_TYPE_MODERATED, /**< Moderated session */ + FSDP_SESSION_TYPE_TEST, /**< Test (do not display) */ + FSDP_SESSION_TYPE_H332 /**< H332 session */ +} fsdp_session_type_t; + +/** + * @short Media type + * + * The following types are defined initially: audio, video, + * application, data and control. + **/ +typedef enum +{ + FSDP_MEDIA_UNDEFINED, /**< Not specified */ + FSDP_MEDIA_VIDEO, /**< Video */ + FSDP_MEDIA_AUDIO, /**< Audio */ + FSDP_MEDIA_APPLICATION, /**< Application, such as whiteboard */ + FSDP_MEDIA_DATA, /**< bulk data */ + FSDP_MEDIA_CONTROL /**< Control channel */ +} fsdp_media_t; + +/** + * @short Transport protocol + * + * The transport protocol used depends on the address type. Initially, + * RTP over UDP Audio/Video Profile, and UDP are defined. + * + **/ +typedef enum +{ + FSDP_TP_UNDEFINED, /**< Not specified */ + FSDP_TP_RTP_AVP, /**< RTP Audio/Video Profile */ + FSDP_TP_UDP, /**< UDP */ + FSDP_TP_TCP, /**< TCP */ + FSDP_TP_UDPTL, /**< ITU-T T.38*/ + FSDP_TP_VAT, /**< old vat protocol (historic)*/ + FSDP_TP_OLD_RTP, /**< old rtp protocols (historic)*/ + FSDP_TP_H320 /**< TODO: add to the parser */ +} fsdp_transport_protocol_t; + +/** + * Session-level attributes whose value is specified as a character + * string in FreeSDP. These values are usually given to + * fsdp_get_strn_att() in order to get the corresponding value. + * + **/ +typedef enum +{ + FSDP_SESSION_STR_ATT_CATEGORY, + FSDP_SESSION_STR_ATT_KEYWORDS, + FSDP_SESSION_STR_ATT_TOOL, + FSDP_SESSION_STR_ATT_CHARSET, +} fsdp_session_str_att_t; + +/** + * @short FreeSDP SDP description media object. + * + * Object for media specific information in SDP descriptions. Each SDP + * description may include any number of media section. A + * fsdp_media_description_t object encapsulates the information in a + * media section, such as video, audio or whiteboard. + **/ +typedef struct fsdp_media_description_t_s fsdp_media_description_t; + +/** + * @short FreeSDP SDP session description object. + * + * Contains all the information extracted from a textual SDP + * description, including all the media announcements. + **/ +typedef struct fsdp_description_t_s fsdp_description_t; + +/** + * Allocates memory and initializes values for a new + * fsdp_description_t object. If you call this routine, do not forget + * about fsdp_description_delete() + * + * @return new fsdp_description_t object + **/ +fsdp_description_t *fsdp_description_new (void); + +/** + * Destroys a fsdp_description_t object. + * + * @param dsc pointer to the fsdp_description_t object to delete. + **/ +void fsdp_description_delete (fsdp_description_t * dsc); + +/** + * Calling this function over a description is equivalent to calling + * fsdp_description_delete and then fsdp_description_delete. This + * function is however more suitable and efficient for description + * processing loops. + * + * @param dsc pointer to the fsdp_description_t object to + * renew/recycle. + **/ +void fsdp_description_recycle (fsdp_description_t * dsc); + +/** + * * Returns a string correspondent to the error number. + * * + * * @param err_no error number. + * **/ +const char *fsdp_strerror (fsdp_error_t err_no); + + /*@}*//* closes addtogroup common */ + +END_C_DECLS +#endif /* FSDP_COMMON_H */ diff --git a/libmpdemux/freesdp/errorlist.c b/libmpdemux/freesdp/errorlist.c new file mode 100644 index 0000000000..e934cd6da5 --- /dev/null +++ b/libmpdemux/freesdp/errorlist.c @@ -0,0 +1,72 @@ +/* + This file is part of FreeSDP + Copyright (C) 2001, 2002 Federico Montesino Pouzols + + FreeSDP is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** + * @file errorlist.c + * + * @short Translation table for error numbers + * + */ + +#ifndef FSDP_ERRORLIST_C +#define FSDP_ERRORLIST_C + +#include "common.h" + +const char *fsdp_error_t_s[] = { + "No error",/** FSDPE_OK **/ + "Illegal character detected",/** FSDPE_ILLEGAL_CHARACTER **/ + "Missing version item", /** FSDPE_MISSING_VERSION **/ + "Invalid version item", /** FSDPE_INVALID_VERSION **/ + "Owner item not present", /** FSDPE_MISSING_OWNER **/ + "Parse error in owner item", /** FSDPE_INVALID_OWNER **/ + "Session name not present", /** FSDPE_MISSING_NAME **/ + "Empty session name item", /** FSDPE_EMPTY_NAME **/ + "Syntax error in connection item", /** FSDPE_INVALID_CONNECTION **/ + "Unrecognized address type in connection item", /** FSDPE_INVALID_CONNECTION_ADDRTYPE **/ + "Unrecognized network type in connection item", /** FSDPE_INVALID_CONNECTION_NETTYPE **/ + "Parse error in bandwith item", /** FSDPE_INVALID_BANDWIDTH **/ + "No time period for the session", /** FSDPE_MISSING_TIME **/ + "Parse error in time item", /** FSDPE_INVALID_TIME **/ + "Parse error in repeat time item", /** FSDPE_INVALID_REPEAT **/ + "Parse error in timezone item", /** FSDPE_INVALID_TIMEZONE **/ + "Unknown encryption method", /** FSDPE_INVALID_ENCRYPTION_METHOD **/ + "Syntax error in an attribute item", /** FSDPE_INVALID_ATTRIBUTE **/ + "Syntax error in an rtpmap attribute item", /** FSDPE_INVALID_ATTRIBUTE_RTPMAP **/ + "Unknown session type in a session-level attribute", /** FSDPE_INVALID_SESSION_TYPE **/ + "Parse error in media item", /** FSDPE_INVALID_MEDIA **/ + "Unknown media type in media item", /** FSDPE_UNKNOWN_MEDIA_TYPE **/ + "Unknown media transport", /** FSDPE_UNKNOWN_MEDIA_TRANSPORT **/ + "Unknown extra lines in description item", /** FSDPE_OVERFILLED **/ + "Unknown line found", /** FSDPE_INVALID_LINE **/ + "No connection information provided", /** FSDPE_MISSING_CONNECTION_INFO **/ + "Description item does not fit in MAXSIZE", /** FSDPE_INVALID_INDEX **/ + "Internal error", /** FSDPE_INTERNAL_ERROR **/ + "Invalid function parameters", /** FSDPE_INVALID_PARAMETER **/ + "Buffer overflow" /** FSDPE_BUFFER_OVERFLOW **/ +}; + + +const char * +fsdp_strerror (fsdp_error_t err_no) +{ + return (fsdp_error_t_s[err_no]); +} + +#endif diff --git a/libmpdemux/freesdp/parser.c b/libmpdemux/freesdp/parser.c new file mode 100644 index 0000000000..b92ddd4862 --- /dev/null +++ b/libmpdemux/freesdp/parser.c @@ -0,0 +1,1958 @@ +/* + This file is part of FreeSDP + Copyright (C) 2001,2002,2003 Federico Montesino Pouzols + + FreeSDP is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Benjamin Zores, (C) 2006 + added support in parser for the a=control: lines. + added support in parser for the a=range: lines. +*/ + +/** + * @file parser.c + * + * @short Parsing module implementation. + * + * This file implements the parsing routine fsdp_parse + * and the fsdp_get_xxxx routines that allow to get the + * session properties from a session description object build through + * the application of fsdp_parse to a textual SDP session + * description. + **/ + +#include "parserpriv.h" + +/** + * Moves the c pointer up to the beginning of the next + * line. + * + * @param c char pointer to pointer + * @retval FSDPE_ILLEGAL_CHARACTER, when an illegal '\r' character + * (not followed by a '\n') is found, returns + */ +#define NEXT_LINE(c) \ +({ \ + while ((*(c) != '\0') && (*(c) != '\r') && (*(c) != '\n')) { \ + (c)++; \ + } \ + if (*(c) == '\n') { \ + (c)++; \ + } else if (*(c) == '\r') { \ + (c)++; \ + if (*(c) == '\n') { \ + (c)++; \ + } else { \ + return FSDPE_ILLEGAL_CHARACTER; \ + } \ + } \ +}) + +fsdp_error_t +fsdp_parse (const char *text_description, fsdp_description_t * dsc) +{ + fsdp_error_t result; + const char *p = text_description, *p2; + unsigned int index, j; + /* temps for sscanf */ + const unsigned int TEMPCHARS = 6; + char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN]; + char longfsdp_buf[MAXLONGFIELDLEN]; + const unsigned int TEMPINTS = 2; + unsigned long int wuint[TEMPINTS]; + + if ((NULL == text_description) || (NULL == dsc)) + return FSDPE_INVALID_PARAMETER; + + /***************************************************************************/ + /* A) parse session-level description */ + /***************************************************************************/ + + /* `v=' line (protocol version) */ + /* according to the RFC, only `v=0' is valid */ + if (sscanf (p, "v=%1lu", &wuint[0])) + { + if (wuint[0] != 0) + return FSDPE_INVALID_VERSION; + } + else + { + return FSDPE_MISSING_VERSION; + } + NEXT_LINE (p); + + /* `o=' line (owner/creator and session identifier) */ + /* o=
+
*/ + if (!strncmp (p, "o=", 2)) + { + p += 2; + /* note that the following max lengths may vary in the future and + are quite arbitary */ + if (sscanf + (p, + "%" MSFLENS "[\x21-\xFF] %" MSFLENS "[0-9] %" MSFLENS + "[0-9] %2s %3s %" MSFLENS "s", fsdp_buf[0], fsdp_buf[1], + fsdp_buf[2], fsdp_buf[3], fsdp_buf[4], fsdp_buf[5]) != 6) + return FSDPE_INVALID_OWNER; + dsc->o_username = strdup (fsdp_buf[0]); + dsc->o_session_id = strdup (fsdp_buf[1]); + dsc->o_announcement_version = strdup (fsdp_buf[2]); + if (!strncmp (fsdp_buf[3], "IN", 2)) + { + dsc->o_network_type = FSDP_NETWORK_TYPE_INET; + if (!strncmp (fsdp_buf[4], "IP4", 3)) + dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV4; + else if (!strncmp (fsdp_buf[4], "IP6", 3)) + dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV6; + else + return FSDPE_INVALID_OWNER; + } + else + { + return FSDPE_INVALID_OWNER; + } + /* TODO? check valid unicast address/FQDN */ + dsc->o_address = strdup (fsdp_buf[5]); + } + else + { + return FSDPE_MISSING_OWNER; + } + NEXT_LINE (p); + + /* `s=' line (session name) -note that the name string cannot be empty */ + /* s= */ + if (!strncmp (p, "s=", 2)) + { + if (sscanf (p, "s=%" MLFLENS "[^\r\n]", longfsdp_buf) < 1) + return FSDPE_EMPTY_NAME; + dsc->s_name = strdup (longfsdp_buf); + } + else + { + return FSDPE_MISSING_NAME; + } + NEXT_LINE (p); + + /* `i=' line (session information) [optional] */ + /* i= */ + if (!strncmp (p, "i=", 2) + && sscanf (p, "i=%" MLFLENS "[^\r\n]", longfsdp_buf)) + { + dsc->i_information = strdup (longfsdp_buf); + NEXT_LINE (p); + } + else + { + /* (optional) information absent */ + } + + /* `u=' line (URI of description) [optional] */ + /* u= */ + if (!strncmp (p, "u=", 2) + && sscanf (p, "u=%" MLFLENS "[^\r\n]", longfsdp_buf)) + { + /* TODO? check valid uri */ + dsc->u_uri = strdup (longfsdp_buf); + NEXT_LINE (p); + } + else + { + /* (optional) uri absent */ + } + + /* `e=' lines (email address) [zero or more] */ + /* e= */ + p2 = p; + j = 0; + while (!strncmp (p2, "e=", 2)) + { + /* First, count how many emails are there */ + j++; + NEXT_LINE (p2); + } + dsc->emails_count = j; + if (dsc->emails_count > 0) + { + /* Then, build the array of emails */ + dsc->emails = calloc (j, sizeof (const char *)); + for (j = 0; j < dsc->emails_count; j++) + { + sscanf (p, "e=%" MLFLENS "[^\r\n]", longfsdp_buf); + /* TODO? check valid email-address. */ + dsc->emails[j] = strdup (longfsdp_buf); + NEXT_LINE (p); + } + } + + /* `p=' lines (phone number) [zero or more] */ + /* p= */ + j = 0; + /* assert ( p2 == p ); */ + while (!strncmp (p2, "p=", 2)) + { + j++; + NEXT_LINE (p2); + } + dsc->phones_count = j; + if (dsc->phones_count > 0) + { + dsc->phones = calloc (j, sizeof (const char *)); + for (j = 0; j < dsc->phones_count; j++) + { + sscanf (p, "p=%" MLFLENS "[^\r\n]", longfsdp_buf); + /* TODO? check valid phone-number. */ + dsc->phones[j] = strdup (longfsdp_buf); + NEXT_LINE (p); + } + } + + /* `c=' line (connection information - not required if included in all media) [optional] */ + /* c=
*/ + result = fsdp_parse_c (&p, &(dsc->c_network_type), &(dsc->c_address_type), + &(dsc->c_address)); + if (FSDPE_OK != result) + return result; + + /* `b=' lines (bandwidth information) [optional] */ + /* b=: */ + result = + fsdp_parse_b (&p, &(dsc->bw_modifiers), &(dsc->bw_modifiers_count)); + if (FSDPE_OK != result) + return result; + + /* A.1) Time descriptions: */ + + /* `t=' lines (time the session is active) [1 or more] */ + /* t= */ + j = 0; + p2 = p; + while (!strncmp (p2, "t=", 2)) + { + j++; + NEXT_LINE (p2); + while (!strncmp (p2, "r=", 2)) + NEXT_LINE (p2); + } + dsc->time_periods_count = j; + if (dsc->time_periods_count == 0) + return FSDPE_MISSING_TIME; + dsc->time_periods = calloc (dsc->time_periods_count, + sizeof (fsdp_time_period_t *)); + index = 0; + for (j = 0; j < dsc->time_periods_count; j++) + { + unsigned int h = 0; + if (sscanf (p, "t=%10lu %10lu", &wuint[0], &wuint[1]) != 2) + { + /* not all periods have been successfully parsed */ + dsc->time_periods_count = j; + return FSDPE_INVALID_TIME; + } + dsc->time_periods[j] = calloc (1, sizeof (fsdp_time_period_t)); + + /* convert from NTP to time_t time */ + if (wuint[0] != 0) + wuint[0] -= NTP_EPOCH_OFFSET; + if (wuint[1] != 0) + wuint[1] -= NTP_EPOCH_OFFSET; + dsc->time_periods[j]->start = wuint[0]; + dsc->time_periods[j]->stop = wuint[1]; + NEXT_LINE (p); + + /* `r' lines [zero or more repeat times for each t=] */ + /*r= */ + p2 = p; + while (!strncmp (p2, "r=", 2)) + { + h++; + NEXT_LINE (p2); + } + dsc->time_periods[j]->repeats_count = h; + if (h > 0) + { + unsigned int index2 = 0; + dsc->time_periods[j]->repeats = + calloc (h, sizeof (fsdp_repeat_t *)); + for (h = 0; h < dsc->time_periods[j]->repeats_count; h++) + { + /* + get_repeat_values(p,&(dsc->time_periods[index].repeats[index2])); + fsdp_error_t get_repeat_values (const char *r, fsdp_repeat_t + *repeat); + */ + if (sscanf (p, "r=%10s %10s %" MLFLENS "[^\r\n]", + fsdp_buf[0], fsdp_buf[1], longfsdp_buf) == 3) + { + fsdp_repeat_t *repeat; + dsc->time_periods[j]->repeats[h] = + calloc (1, sizeof (fsdp_repeat_t)); + repeat = dsc->time_periods[j]->repeats[h]; + /* get interval, duration and list of offsets */ + result = + fsdp_repeat_time_to_uint (fsdp_buf[0], + &(repeat->interval)); + if (result == FSDPE_OK) + { + result = + fsdp_repeat_time_to_uint (fsdp_buf[1], + &(repeat->duration)); + if (result == FSDPE_OK) + { + unsigned int k = 1; + const char *i = longfsdp_buf; + while (NULL != (i = strchr (i, ' '))) + { + k++; + if (NULL != i) + i++; + } + repeat->offsets_count = k; + repeat->offsets = calloc (k, sizeof (time_t)); + i = longfsdp_buf; + for (k = 0; + (k < repeat->offsets_count) + && (result == FSDPE_OK); k++) + { + result = + fsdp_repeat_time_to_uint (i, + &(repeat-> + offsets[k])); + i = strchr (i, ' '); + if (NULL != i) + i++; + } + if (k < repeat->offsets_count) + { + /* there where invalid repeat offsets */ + dsc->time_periods[j]->repeats_count = k; + return FSDPE_INVALID_REPEAT; + } + } + } + if (result != FSDPE_OK) + { + /* not all repeats have been succesfully parsed */ + dsc->time_periods[j]->repeats_count = h; + return FSDPE_INVALID_REPEAT; + } + NEXT_LINE (p); + } + else + { + /* not all repeats have been succesfully parsed */ + dsc->time_periods[j]->repeats_count = h; + return FSDPE_INVALID_REPEAT; + } + index2++; + } + } + } + + /* `z=' line (time zone adjustments) [zero or more] */ + /* z= .... */ + if (!strncmp (p, "z=", 2)) + { + if (sscanf (p, "z=%" MLFLENS "[^\r\n]", longfsdp_buf)) + { + /* TODO: guess how many pairs are there and process them */ + dsc->timezone_adj = strdup (longfsdp_buf); + NEXT_LINE (p); + } + else + { + return FSDPE_INVALID_TIMEZONE; + } + } + + /* `k=' line (encryption key) [optional] */ + /* k= + k=: */ + result = fsdp_parse_k (&p, &(dsc->k_encryption_method), + &(dsc->k_encryption_content)); + if (result != FSDPE_OK) + return result; + + /* A.2) Attributes */ + /* `a=' lines (session attribute) [0 or more] */ + /* a= + a=: */ + while (!strncmp (p, "a=", 2)) + { + /* The "9" lenght specifier of the first string is subject to + changes */ + if (sscanf + (p, "a=%9[^:\r\n]:%" MSFLENS "[^\r\n]", fsdp_buf[0], + fsdp_buf[1]) == 2) + { + /* session-level value attributes */ + if (!strncmp (fsdp_buf[0], "cat", 3)) + dsc->a_category = strdup (fsdp_buf[1]); + else if (!strncmp (fsdp_buf[0], "keywds", 6)) + dsc->a_keywords = strdup (fsdp_buf[1]); + else if (!strncmp (fsdp_buf[0], "tool", 4)) + dsc->a_keywords = strdup (fsdp_buf[1]); + else if (!strncmp (fsdp_buf[0], "rtpmap", 6)) + fsdp_parse_rtpmap (&(dsc->a_rtpmaps), + &(dsc->a_rtpmaps_count), fsdp_buf[1]); + else if (!strncmp (fsdp_buf[0], "type", 4)) + { + if (!strncmp (fsdp_buf[1], "broadcast", 9)) + dsc->a_type = FSDP_SESSION_TYPE_BROADCAST; + else if (!strncmp (fsdp_buf[1], "meeting", 7)) + dsc->a_type = FSDP_SESSION_TYPE_MEETING; + else if (!strncmp (fsdp_buf[1], "moderated", 9)) + dsc->a_type = FSDP_SESSION_TYPE_MODERATED; + else if (!strncmp (fsdp_buf[1], "test", 4)) + dsc->a_type = FSDP_SESSION_TYPE_TEST; + else if (!strncmp (fsdp_buf[1], "H332", 4)) + dsc->a_type = FSDP_SESSION_TYPE_H332; + else + return FSDPE_INVALID_SESSION_TYPE; + } + else if (!strncmp (fsdp_buf[0], "charset", 7)) + dsc->a_charset = strdup (fsdp_buf[1]); + else if (!strncmp (fsdp_buf[0], "sdplang", 7)) + { + if (NULL == dsc->a_sdplangs) + { + dsc->a_sdplangs_count = 0; + dsc->a_sdplangs = + calloc (SDPLANGS_MAX_COUNT, sizeof (char *)); + } + if (dsc->a_sdplangs_count < SDPLANGS_MAX_COUNT) + { + dsc->a_sdplangs[dsc->a_sdplangs_count] = + strdup (fsdp_buf[1]); + dsc->a_sdplangs_count++; + } + } + else if (!strncmp (fsdp_buf[0], "lang", 4)) + { + if (NULL == dsc->a_langs) + { + dsc->a_langs_count = 0; + dsc->a_langs = calloc (SDPLANGS_MAX_COUNT, sizeof (char *)); + } + if (dsc->a_langs_count < SDPLANGS_MAX_COUNT) + { + dsc->a_langs[dsc->a_langs_count] = strdup (fsdp_buf[1]); + dsc->a_langs_count++; + } + } + else if (!strncmp (fsdp_buf[0], "control", 7)) + { + if (NULL == dsc->a_controls) + { + dsc->a_controls_count = 0; + dsc->a_controls = + calloc (SDPCONTROLS_MAX_COUNT, sizeof (char *)); + } + if (dsc->a_controls_count < SDPCONTROLS_MAX_COUNT) + { + dsc->a_controls[dsc->a_controls_count] = + strdup (fsdp_buf[1]); + dsc->a_controls_count++; + } + } + else if (!strncmp (fsdp_buf[0], "range", 5)) + { + if (dsc->a_range) + free (dsc->a_range); + dsc->a_range = strdup (fsdp_buf[1]); + } + else + { + /* ignore unknown attributes, but provide access to them */ + *longfsdp_buf = '\0'; + strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN); + strncat (longfsdp_buf, ":", MAXLONGFIELDLEN); + strncat (longfsdp_buf, fsdp_buf[1], MAXLONGFIELDLEN); + if (NULL == dsc->unidentified_attributes) + { + dsc->unidentified_attributes_count = 0; + dsc->unidentified_attributes = + calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT, + sizeof (char *)); + } + if (dsc->unidentified_attributes_count < + UNIDENTIFIED_ATTRIBUTES_MAX_COUNT) + { + dsc->unidentified_attributes + [dsc->unidentified_attributes_count] = + strdup (longfsdp_buf); + dsc->unidentified_attributes_count++; + } + } + NEXT_LINE (p); + } + else if (sscanf (p, "a=%20s", fsdp_buf[0]) == 1) + { + /* session-level property attributes */ + if (!strncmp (fsdp_buf[0], "recvonly", 8)) + dsc->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY; + else if (!strncmp (fsdp_buf[0], "sendonly", 8)) + dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY; + else if (!strncmp (fsdp_buf[0], "inactive", 8)) + dsc->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE; + else if (!strncmp (fsdp_buf[0], "sendrecv", 8)) + dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV; + else + { + /* ignore unknown attributes, but provide access to them */ + *longfsdp_buf = '\0'; + strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN); + if (NULL == dsc->unidentified_attributes) + { + dsc->unidentified_attributes_count = 0; + dsc->unidentified_attributes = + calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT, + sizeof (char *)); + } + if (dsc->unidentified_attributes_count < + UNIDENTIFIED_ATTRIBUTES_MAX_COUNT) + { + dsc->unidentified_attributes + [dsc->unidentified_attributes_count] = + strdup (longfsdp_buf); + dsc->unidentified_attributes_count++; + } + } + NEXT_LINE (p); + } + else + return FSDPE_INVALID_ATTRIBUTE; + } + + /***************************************************************************/ + /* B) parse media-level descriptions */ + /***************************************************************************/ + p2 = p; + j = 0; + while ((*p2 != '\0') && !strncmp (p2, "m=", 2)) + { + char c; + j++; + NEXT_LINE (p2); + while (sscanf (p2, "%c=", &c) == 1) + { + if (c == 'i' || c == 'c' || c == 'b' || c == 'k' || c == 'a') + { + NEXT_LINE (p2); + } + else if (c == 'm') + { + break; + } + else + { + return FSDPE_INVALID_LINE; + } + } + } + dsc->media_announcements_count = j; + if (dsc->media_announcements_count == 0) + { + ; + /*return FSDPE_MISSING_MEDIA; */ + } + else + { /* dsc->media_announcements_count > 0 */ + dsc->media_announcements = + calloc (j, sizeof (fsdp_media_announcement_t *)); + for (j = 0; j < dsc->media_announcements_count; j++) + { + fsdp_media_announcement_t *media = NULL; + /* `m=' line (media name, transport address and format list) */ + /* m= */ + /* The max. string lengths are subject to change */ + if (sscanf (p, "m=%11s %8s %7s %" MLFLENS "[^\r\n]", + fsdp_buf[0], fsdp_buf[1], fsdp_buf[2], + longfsdp_buf) != 4) + { + return FSDPE_INVALID_MEDIA; + } + else + { + dsc->media_announcements[j] = + calloc (1, sizeof (fsdp_media_announcement_t)); + media = dsc->media_announcements[j]; + if (!strncmp (fsdp_buf[0], "audio", 5)) + media->media_type = FSDP_MEDIA_AUDIO; + else if (!strncmp (fsdp_buf[0], "video", 5)) + media->media_type = FSDP_MEDIA_VIDEO; + else if (!strncmp (fsdp_buf[0], "application", 11)) + media->media_type = FSDP_MEDIA_APPLICATION; + else if (!strncmp (fsdp_buf[0], "data", 4)) + media->media_type = FSDP_MEDIA_DATA; + else if (!strncmp (fsdp_buf[0], "control", 7)) + media->media_type = FSDP_MEDIA_CONTROL; + else + return FSDPE_UNKNOWN_MEDIA_TYPE; + { /* try to get port specification as port/number */ + char *slash; + if ((slash = strchr (fsdp_buf[1], '/'))) + { + *slash = '\0'; + slash++; + media->port = strtol (fsdp_buf[1], NULL, 10); + media->port_count = strtol (slash, NULL, 10); + } + else + { + media->port = strtol (fsdp_buf[1], NULL, 10); + media->port_count = 0; + } + } + if (!strncmp (fsdp_buf[2], "RTP/AVP", 7)) + media->transport = FSDP_TP_RTP_AVP; + else if (!strncmp (fsdp_buf[2], "udp", 3)) + media->transport = FSDP_TP_UDP; + else if (!strncmp (fsdp_buf[2], "TCP", 3)) + media->transport = FSDP_TP_TCP; + else if (!strncmp (fsdp_buf[2], "UDPTL", 5)) + media->transport = FSDP_TP_UDPTL; + else if (!strncmp (fsdp_buf[2], "vat", 3)) + media->transport = FSDP_TP_VAT; + else if (!strncmp (fsdp_buf[2], "rtp", 3)) + media->transport = FSDP_TP_OLD_RTP; + else + return FSDPE_UNKNOWN_MEDIA_TRANSPORT; + { + unsigned int k = 0; + char *s = longfsdp_buf; + while (NULL != (s = strchr (s, ' '))) + { + k++; + if (NULL != s) + s++; + } + k++; /* when there is no space left, count the last format */ + media->formats_count = k; + media->formats = calloc (k, sizeof (char *)); + s = longfsdp_buf; + for (k = 0; k < media->formats_count; k++) + { + char *space = strchr (s, ' '); + if (NULL != space) + *space = '\0'; + media->formats[k] = strdup (s); + s = space + 1; + } + } + NEXT_LINE (p); + } + + /* `i=' line (media title) [optional] */ + /* i= */ + if (!strncmp (p, "i=", 2) + && sscanf (p, "i=%" MLFLENS "[^\r\n]", longfsdp_buf)) + { + media->i_title = strdup (longfsdp_buf); + NEXT_LINE (p); + } + else + { + /* (optional) information absent */ + } + + /* `c=' line (connection information - overrides session-level + line) [optional if provided at session-level] */ + /* c=
*/ + result = fsdp_parse_c (&p, &(media->c_network_type), + &(media->c_address_type), + &(media->c_address)); + if (result != FSDPE_OK) + return result; + + /* `b=' lines (bandwidth information) [optional] */ + /* b=: */ + result = fsdp_parse_b (&p, &(media->bw_modifiers), + &(media->bw_modifiers_count)); + if (FSDPE_OK != result) + return result; + + /* `k=' line (encryption key) [optional] */ + /* k= + k=: */ + result = fsdp_parse_k (&p, &(media->k_encryption_method), + &(media->k_encryption_content)); + if (result != FSDPE_OK) + return result; + + /* B.1) Attributes */ + + /* `a=' lines (zero or more media attribute lines) [optional] */ + /* a= + a=: */ + while (!strncmp (p, "a=", 2)) + { + if (sscanf + (p, "a=%9[^:\r\n]:%" MLFLENS "[^\r\n]", fsdp_buf[0], + longfsdp_buf) == 2) + { + /* media-level value attributes */ + if (!strncmp (fsdp_buf[0], "ptime", 5)) + media->a_ptime = strtoul (longfsdp_buf, NULL, 10); + else if (!strncmp (fsdp_buf[0], "maxptime", 8)) + media->a_maxptime = strtoul (longfsdp_buf, NULL, 10); + else if (!strncmp (fsdp_buf[0], "rtpmap", 6)) + fsdp_parse_rtpmap (&(media->a_rtpmaps), + &(media->a_rtpmaps_count), + longfsdp_buf); + else if (!strncmp (fsdp_buf[0], "orient", 6)) + { + if (!strncmp (longfsdp_buf, "portrait", 8)) + media->a_orient = FSDP_ORIENT_PORTRAIT; + else if (!strncmp (longfsdp_buf, "landscape", 9)) + media->a_orient = FSDP_ORIENT_LANDSCAPE; + else if (!strncmp (longfsdp_buf, "seascape", 9)) + media->a_orient = FSDP_ORIENT_SEASCAPE; + } + else if (!strncmp (fsdp_buf[0], "sdplang", 7)) + { + if (NULL == dsc->a_sdplangs) + { + media->a_sdplangs_count = 0; + media->a_sdplangs = + calloc (SDPLANGS_MAX_COUNT, sizeof (char *)); + } + if (media->a_sdplangs_count < SDPLANGS_MAX_COUNT) + { + media->a_sdplangs[dsc->a_sdplangs_count] = + strdup (longfsdp_buf); + media->a_sdplangs_count++; + } + } + else if (!strncmp (fsdp_buf[0], "lang", 4)) + { + if (NULL == dsc->a_langs) + { + media->a_langs_count = 0; + media->a_langs = + calloc (SDPLANGS_MAX_COUNT, sizeof (char *)); + } + if (media->a_langs_count < SDPLANGS_MAX_COUNT) + { + media->a_langs[dsc->a_langs_count] = + strdup (longfsdp_buf); + media->a_langs_count++; + } + } + else if (!strncmp (fsdp_buf[0], "control", 7)) + { + if (NULL == media->a_controls) + { + media->a_controls_count = 0; + media->a_controls = + calloc (SDPCONTROLS_MAX_COUNT, sizeof (char *)); + } + if (media->a_controls_count < SDPCONTROLS_MAX_COUNT) + { + media->a_controls[media->a_controls_count] = + strdup (longfsdp_buf); + media->a_controls_count++; + } + } + else if (!strncmp (fsdp_buf[0], "range", 5)) + { + if (media->a_range) + free (media->a_range); + media->a_range = strdup (fsdp_buf[1]); + } + else if (!strncmp (fsdp_buf[0], "framerate", 9)) + media->a_framerate = strtof (longfsdp_buf, NULL); + else if (!strncmp (fsdp_buf[0], "fmtp", 4)) + { + if (NULL == media->a_fmtps) + { + media->a_fmtps_count = 0; + media->a_fmtps = + calloc (SDPLANGS_MAX_COUNT, sizeof (char *)); + } + if (media->a_fmtps_count < SDPLANGS_MAX_COUNT) + { + media->a_fmtps[media->a_fmtps_count] = + strdup (longfsdp_buf); + media->a_fmtps_count++; + } + } + else if (!strncmp (fsdp_buf[0], "rtcp", 4)) + { + int opts = 0; + /* rtcp attribute: a=rtcp:
*/ + opts = + sscanf (longfsdp_buf, "%lu %2s %3s %" MSFLENS "s", + &wuint[0], fsdp_buf[0], fsdp_buf[1], + fsdp_buf[2]); + if (opts >= 1) + { + media->a_rtcp_port = wuint[0]; + if (opts >= 2) + { + if (!strncmp (fsdp_buf[0], "IN", 2)) + { + media->a_rtcp_network_type = + FSDP_NETWORK_TYPE_INET; + } /* else + ; TODO: define error code? */ + if (opts >= 3) + { + if (!strncmp (fsdp_buf[1], "IP4", 3)) + media->a_rtcp_address_type = + FSDP_ADDRESS_TYPE_IPV4; + else if (!strncmp (fsdp_buf[1], "IP6", 3)) + media->a_rtcp_address_type = + FSDP_ADDRESS_TYPE_IPV6; + else + return FSDPE_INVALID_CONNECTION_NETTYPE; + /*add specific code? */ + if (opts >= 4) + media->a_rtcp_address = + strdup (fsdp_buf[2]); + } + } + } + } + else + { + /* ignore unknown attributes, but provide access to them */ + *fsdp_buf[1] = '\0'; + strncat (fsdp_buf[1], fsdp_buf[0], MAXLONGFIELDLEN); + strncat (fsdp_buf[1], ":", MAXLONGFIELDLEN); + strncat (fsdp_buf[1], longfsdp_buf, MAXLONGFIELDLEN); + if (NULL == media->unidentified_attributes) + { + media->unidentified_attributes_count = 0; + media->unidentified_attributes = + calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT, + sizeof (char *)); + } + if (media->unidentified_attributes_count < + UNIDENTIFIED_ATTRIBUTES_MAX_COUNT) + { + media->unidentified_attributes + [media->unidentified_attributes_count] = + strdup (fsdp_buf[1]); + media->unidentified_attributes_count++; + } + } + NEXT_LINE (p); + } + else if (sscanf (p, "a=%8s", fsdp_buf[0]) == 1) + { + /* media-level property attributes */ + if (!strncmp (fsdp_buf[0], "recvonly", 8)) + media->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY; + else if (!strncmp (fsdp_buf[0], "sendonly", 8)) + media->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY; + else if (!strncmp (fsdp_buf[0], "inactive", 8)) + media->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE; + else if (!strncmp (fsdp_buf[0], "sendrecv", 8)) + media->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV; + else + { + /* ignore unknown attributes, but provide access to them */ + *longfsdp_buf = '\0'; + strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN); + if (NULL == media->unidentified_attributes) + { + media->unidentified_attributes_count = 0; + media->unidentified_attributes = + calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT, + sizeof (char *)); + } + if (media->unidentified_attributes_count < + UNIDENTIFIED_ATTRIBUTES_MAX_COUNT) + { + media->unidentified_attributes + [media->unidentified_attributes_count] = + strdup (longfsdp_buf); + media->unidentified_attributes_count++; + } + } + NEXT_LINE (p); + } + else + return FSDPE_INVALID_ATTRIBUTE; + } + } /* end of for */ + } + + /* Check c= has been given at session level or at media level for + all media */ + if (NULL == dsc->c_address.address) + { + unsigned int c; + for (c = 0; c < dsc->media_announcements_count; c++) + if (NULL == dsc->media_announcements[c]->c_address.address) + return FSDPE_MISSING_CONNECTION_INFO; + } + + /* finish */ + if (*p == '\0') + return FSDPE_OK; + else + return FSDPE_OVERFILLED; +} + +static fsdp_error_t +fsdp_parse_c (const char **p, fsdp_network_type_t * ntype, + fsdp_address_type_t * atype, + fsdp_connection_address_t * address) +{ + const unsigned int TEMPCHARS = 3; + char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN]; + + if (!strncmp (*p, "c=", 2)) + { + if (sscanf (*p, "c=%2s %3s %" MSFLENS "s", + fsdp_buf[0], fsdp_buf[1], fsdp_buf[2])) + { + if (!strncmp (fsdp_buf[0], "IN", 2)) + { + *ntype = FSDP_NETWORK_TYPE_INET; + if (!strncmp (fsdp_buf[1], "IP4", 3)) + *atype = FSDP_ADDRESS_TYPE_IPV4; + else if (!strncmp (fsdp_buf[1], "IP6", 3)) + *atype = FSDP_ADDRESS_TYPE_IPV6; + else + return FSDPE_INVALID_CONNECTION_NETTYPE; + } + else + { + return FSDPE_INVALID_CONNECTION_ADDRTYPE; + } + { + char *slash = strchr (fsdp_buf[2], '/'); + if (NULL == slash) + { + address->address = strdup (fsdp_buf[2]); + address->address_ttl = 0; + address->address_count = 0; + } + else + { + /* address is IP4 multicast */ + char *slash2; + *slash = '\0'; + slash++; + address->address = strdup (fsdp_buf[2]); + slash2 = strchr (slash + 1, '/'); + if (NULL == slash2) + { + address->address_ttl = strtol (slash, NULL, 10); + address->address_count = 0; + } + else + { + *slash2 = '\0'; + slash2++; + address->address_ttl = strtol (slash, NULL, 10); + address->address_count = strtol (slash2, NULL, 10); + } + } + } + NEXT_LINE (*p); + } + else + { + return FSDPE_INVALID_CONNECTION; + } + } + return FSDPE_OK; +} + +static fsdp_error_t +fsdp_parse_b (const char **p, fsdp_bw_modifier_t ** bw_modifiers, + unsigned int *bw_modifiers_count) +{ + char fsdp_buf[MAXSHORTFIELDLEN]; + unsigned long int wuint; + unsigned int i = 0; + char *lp = (char *) *p; + + /* count b= lines */ + while (!strncmp (lp, "b=", 2)) + { + NEXT_LINE (lp); + i++; + } + *bw_modifiers = calloc (i, sizeof (fsdp_bw_modifier_t)); + *bw_modifiers_count = i; + + while (i > 0) + { + unsigned int index = *bw_modifiers_count - i; + if (2 == sscanf (*p, "b=%20[^:\r\n]:%lu", fsdp_buf, &wuint)) + { + if (!strncmp (fsdp_buf, "CT", 2)) + (*bw_modifiers)[index].b_mod_type = + FSDP_BW_MOD_TYPE_CONFERENCE_TOTAL; + else if (!strncmp (fsdp_buf, "AS", 2)) + (*bw_modifiers)[index].b_mod_type = + FSDP_BW_MOD_TYPE_APPLICATION_SPECIFIC; + else if (!strncmp (fsdp_buf, "RS", 2)) + (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_RTCP_SENDERS; + else if (!strncmp (fsdp_buf, "RR", 2)) + (*bw_modifiers)[index].b_mod_type = + FSDP_BW_MOD_TYPE_RTCP_RECEIVERS; + else + { + (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_UNKNOWN; + (*bw_modifiers)[index].b_unknown_bw_modt = + (char *) strdup (fsdp_buf); + } + (*bw_modifiers)[index].b_value = wuint; + NEXT_LINE (*p); + } + else + { + *bw_modifiers_count -= i; + return FSDPE_INVALID_BANDWIDTH; + } + i--; + } + return FSDPE_OK; +} + +static fsdp_error_t +fsdp_parse_k (const char **p, fsdp_encryption_method_t * method, + char **content) +{ + char fsdp_buf[MAXSHORTFIELDLEN]; + char longfsdp_buf[MAXLONGFIELDLEN]; + + if (!strncmp (*p, "k=", 2)) + { + if (sscanf (*p, "k=prompt")) + { + *method = FSDP_ENCRYPTION_METHOD_PROMPT; + *content = NULL; + NEXT_LINE (*p); + } + else + { + if (sscanf + (*p, "k=%6[^:\r\n]:%" MLFLENS "s", fsdp_buf, longfsdp_buf)) + { + if (!strncmp (fsdp_buf, "clear", 5)) + *method = FSDP_ENCRYPTION_METHOD_CLEAR; + else if (!strncmp (fsdp_buf, "base64", 6)) + *method = FSDP_ENCRYPTION_METHOD_BASE64; + else if (!strncmp (fsdp_buf, "uri", 3)) + *method = FSDP_ENCRYPTION_METHOD_URI; + else + return FSDPE_INVALID_ENCRYPTION_METHOD; + *content = strdup (longfsdp_buf); + NEXT_LINE (*p); + } + } + } + return FSDPE_OK; +} + +static fsdp_error_t +fsdp_parse_rtpmap (fsdp_rtpmap_t *** rtpmap, unsigned int *counter, + const char *value) +{ + fsdp_error_t result = FSDPE_OK; + + if (0 == *counter) + { + *counter = 0; + *rtpmap = calloc (MEDIA_RTPMAPS_MAX_COUNT, sizeof (fsdp_rtpmap_t *)); + } + if (*counter < MEDIA_RTPMAPS_MAX_COUNT) + { + unsigned int c = *counter; + fsdp_rtpmap_t **map = *rtpmap; + char fsdp_buf[MAXSHORTFIELDLEN]; + char longfsdp_buf[MAXLONGFIELDLEN]; + map[c] = calloc (1, sizeof (fsdp_rtpmap_t)); + + /* a=rtpmap: /[/ */ + if (2 == sscanf (value, "%s %s", fsdp_buf, longfsdp_buf)) + { + char *slash1; + map[c]->pt = strdup (fsdp_buf); + /* parse /[/] */ + slash1 = strchr (longfsdp_buf, '/'); + if (NULL == slash1) + { + result = FSDPE_INVALID_ATTRIBUTE_RTPMAP; + } + else + { + char *slash2; + *slash1 = '\0'; + slash1++; + map[c]->encoding_name = strdup (longfsdp_buf); + slash2 = strchr (slash1, '/'); + if (NULL != slash2) + { + *slash2 = '\0'; + slash2++; + map[c]->parameters = strdup (slash2); + } + map[c]->clock_rate = strtol (slash1, NULL, 10); + } + (*counter)++; + } + } + return result; +} + +static fsdp_error_t +fsdp_repeat_time_to_uint (const char *time, unsigned long int *seconds) +{ + const unsigned long SECONDS_PER_DAY = 86400; + const unsigned long SECONDS_PER_HOUR = 3600; + const unsigned long SECONDS_PER_MINUTE = 60; + char c; + unsigned long int wuint; + + if (sscanf (time, "%lu%c", &wuint, &c) == 2) + { + /* time with unit specification character */ + switch (c) + { + case 'd': + *seconds = wuint * SECONDS_PER_DAY; + break; + case 'h': + *seconds = wuint * SECONDS_PER_HOUR; + break; + case 'm': + *seconds = wuint * SECONDS_PER_MINUTE; + break; + case 's': + *seconds = wuint; + break; + default: + return FSDPE_INVALID_REPEAT; + break; + } + } + else if (sscanf (time, "%lu", &wuint) == 1) + { + /* time without unit specification character */ + *seconds = wuint; + } + else + { + return FSDPE_INVALID_REPEAT; + } + return FSDPE_OK; +} + +unsigned int +fsdp_get_version (const fsdp_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->version; +} + +const char * +fsdp_get_owner_username (const fsdp_description_t * dsc) +{ + if (!dsc) + return NULL; + return dsc->o_username; +} + +const char * +fsdp_get_session_id (const fsdp_description_t * dsc) +{ + if (!dsc) + return NULL; + return dsc->o_session_id; +} + +const char * +fsdp_get_announcement_version (const fsdp_description_t * dsc) +{ + if (!dsc) + return NULL; + return dsc->o_announcement_version; +} + +fsdp_network_type_t +fsdp_get_owner_network_type (const fsdp_description_t * dsc) +{ + if (!dsc) + return FSDP_NETWORK_TYPE_UNDEFINED; + return dsc->o_network_type; +} + +fsdp_address_type_t +fsdp_get_owner_address_type (const fsdp_description_t * dsc) +{ + if (!dsc) + return FSDP_ADDRESS_TYPE_UNDEFINED; + return dsc->o_address_type; +} + +const char * +fsdp_get_owner_address (const fsdp_description_t * dsc) +{ + if (!dsc) + return NULL; + return dsc->o_address; +} + +const char * +fsdp_get_name (const fsdp_description_t * dsc) +{ + if (!dsc) + return NULL; + return dsc->s_name; +} + +const char * +fsdp_get_information (const fsdp_description_t * dsc) +{ + if (!dsc) + return NULL; + return dsc->i_information; +} + +const char * +fsdp_get_uri (const fsdp_description_t * dsc) +{ + if (!dsc) + return NULL; + return dsc->u_uri; +} + +unsigned int +fsdp_get_emails_count (const fsdp_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->emails_count; +} + +const char * +fsdp_get_email (const fsdp_description_t * dsc, unsigned int index) +{ + if ((!dsc) || (index >= dsc->emails_count)) + return NULL; + return dsc->emails[index]; +} + +unsigned int +fsdp_get_phones_count (const fsdp_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->phones_count; +} + +const char * +fsdp_get_phone (const fsdp_description_t * dsc, unsigned int index) +{ + if ((!dsc) || (index >= dsc->phones_count)) + return NULL; + return dsc->phones[index]; +} + +fsdp_network_type_t +fsdp_get_global_conn_network_type (const fsdp_description_t * dsc) +{ + if (!dsc) + return FSDP_NETWORK_TYPE_UNDEFINED; + return dsc->c_network_type; +} + +fsdp_address_type_t +fsdp_get_global_conn_address_type (const fsdp_description_t * dsc) +{ + if (!dsc) + return FSDP_ADDRESS_TYPE_UNDEFINED; + return dsc->c_address_type; +} + +const char * +fsdp_get_global_conn_address (const fsdp_description_t * dsc) +{ + if (!dsc) + return NULL; + return dsc->c_address.address; +} + +unsigned int +fsdp_get_global_conn_address_ttl (const fsdp_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->c_address.address_ttl; +} + +unsigned int +fsdp_get_global_conn_address_count (const fsdp_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->c_address.address_count; +} + +unsigned int +fsdp_get_bw_modifier_count (const fsdp_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->bw_modifiers_count; +} + +fsdp_bw_modifier_type_t +fsdp_get_bw_modifier_type (const fsdp_description_t * dsc, unsigned int index) +{ + if ((!dsc) || (index >= dsc->bw_modifiers_count)) + return FSDP_BW_MOD_TYPE_UNDEFINED; + return dsc->bw_modifiers[index].b_mod_type; +} + +const char * +fsdp_get_bw_modifier_type_unknown (const fsdp_description_t * dsc, + unsigned int index) +{ + if ((!dsc) || (index >= dsc->bw_modifiers_count) || + (dsc->bw_modifiers[index].b_mod_type != FSDP_BW_MOD_TYPE_UNKNOWN)) + return NULL; + return dsc->bw_modifiers[index].b_unknown_bw_modt; +} + +unsigned long int +fsdp_get_bw_value (const fsdp_description_t * dsc, unsigned int index) +{ + if ((!dsc) || (index >= dsc->bw_modifiers_count)) + return 0; + return dsc->bw_modifiers[index].b_value; +} + +time_t +fsdp_get_period_start (const fsdp_description_t * dsc, unsigned int index) +{ + if ((!dsc) || (index >= dsc->time_periods_count)) + return 0; + return dsc->time_periods[index]->start; +} + +time_t +fsdp_get_period_stop (const fsdp_description_t * dsc, unsigned int index) +{ + if ((!dsc) || (index >= dsc->time_periods_count)) + return 0; + return dsc->time_periods[index]->stop; +} + +unsigned int +fsdp_get_period_repeats_count (const fsdp_description_t * dsc, + unsigned int index) +{ + if ((!dsc) || (index >= dsc->time_periods_count)) + return 0; + return dsc->time_periods[index]->repeats_count; +} + +unsigned long int +fsdp_get_period_repeat_interval (const fsdp_description_t * dsc, + unsigned int index, unsigned int rindex) +{ + if ((!dsc) || (index >= dsc->time_periods_count)) + return 0; + return dsc->time_periods[index]->repeats[rindex]->interval; +} + +unsigned long int +fsdp_get_period_repeat_duration (const fsdp_description_t * dsc, + unsigned int index, unsigned int rindex) +{ + if ((!dsc) || (index >= dsc->time_periods_count)) + return 0; + return dsc->time_periods[index]->repeats[rindex]->duration; +} + +const unsigned long int * +fsdp_get_period_repeat_offsets (const fsdp_description_t * dsc, + unsigned int index, unsigned int rindex) +{ + if ((!dsc) || (index >= dsc->time_periods_count)) + return NULL; + return dsc->time_periods[index]->repeats[rindex]->offsets; +} + +const char * +fsdp_get_timezone_adj (const fsdp_description_t * dsc) +{ + if (!dsc) + return NULL; + return dsc->timezone_adj; +} + +unsigned int +fsdp_get_unidentified_attribute_count (const fsdp_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->unidentified_attributes_count; +} + +const char * +fsdp_get_unidentified_attribute (const fsdp_description_t * dsc, + unsigned int index) +{ + if (!dsc || (index < dsc->unidentified_attributes_count)) + return NULL; + return dsc->unidentified_attributes[index]; +} + +fsdp_encryption_method_t +fsdp_get_encryption_method (const fsdp_description_t * dsc) +{ + if (!dsc) + return FSDP_ENCRYPTION_METHOD_UNDEFINED; + return dsc->k_encryption_method; +} + +const char * +fsdp_get_encryption_content (const fsdp_description_t * dsc) +{ + if (!dsc || (dsc->k_encryption_method == FSDP_ENCRYPTION_METHOD_UNDEFINED)) + return NULL; + return dsc->k_encryption_content; +} + +unsigned int +fsdp_get_rtpmap_count (const fsdp_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->a_rtpmaps_count; +} + +const char * +fsdp_get_rtpmap_payload_type (const fsdp_description_t * dsc, + unsigned int index) +{ + if ((!dsc) || (index >= dsc->a_rtpmaps_count)) + return NULL; + return dsc->a_rtpmaps[index]->pt; +} + +const char * +fsdp_get_rtpmap_encoding_name (const fsdp_description_t * dsc, + unsigned int index) +{ + if ((!dsc) || (index >= dsc->a_rtpmaps_count)) + return NULL; + return dsc->a_rtpmaps[index]->encoding_name; +} + +unsigned int +fsdp_get_rtpmap_clock_rate (const fsdp_description_t * dsc, + unsigned int index) +{ + if ((!dsc) || (index >= dsc->a_rtpmaps_count)) + return 0; + return dsc->a_rtpmaps[index]->clock_rate; +} + +const char * +fsdp_get_rtpmap_encoding_parameters (const fsdp_description_t * dsc, + unsigned int index) +{ + if ((!dsc) || (index >= dsc->a_rtpmaps_count)) + return NULL; + return dsc->a_rtpmaps[index]->parameters; +} + +const char * +fsdp_get_str_att (const fsdp_description_t * dsc, fsdp_session_str_att_t att) +{ + /*TODO: change these individual attributes with a table, thus + avoiding this slow switch */ + char *result; + + if (!dsc) + return NULL; + + switch (att) + { + case FSDP_SESSION_STR_ATT_CATEGORY: + result = dsc->a_category; + break; + case FSDP_SESSION_STR_ATT_KEYWORDS: + result = dsc->a_keywords; + break; + case FSDP_SESSION_STR_ATT_TOOL: + result = dsc->a_tool; + break; + case FSDP_SESSION_STR_ATT_CHARSET: + result = dsc->a_charset; + break; + default: + result = NULL; + } + return result; +} + +unsigned int +fsdp_get_sdplang_count (const fsdp_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->a_sdplangs_count; +} + +const char * +fsdp_get_sdplang (const fsdp_description_t * dsc, unsigned int index) +{ + if ((!dsc) || (index >= dsc->a_sdplangs_count)) + return NULL; + return dsc->a_sdplangs[index]; +} + +unsigned int +fsdp_get_lang_count (const fsdp_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->a_langs_count; +} + +const char * +fsdp_get_lang (const fsdp_description_t * dsc, unsigned int index) +{ + if ((!dsc) || (index >= dsc->a_langs_count)) + return NULL; + return dsc->a_langs[index]; +} + +unsigned int +fsdp_get_control_count (const fsdp_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->a_controls_count; +} + +const char * +fsdp_get_control (const fsdp_description_t * dsc, unsigned int index) +{ + if ((!dsc) || (index >= dsc->a_controls_count)) + return NULL; + return dsc->a_controls[index]; +} + +const char * +fsdp_get_range (const fsdp_description_t * dsc) +{ + return dsc->a_range; +} + +fsdp_sendrecv_mode_t +fsdp_get_sendrecv_mode (const fsdp_description_t * dsc) +{ + if (!dsc) + return FSDP_SENDRECV_UNDEFINED; + return dsc->a_sendrecv_mode; +} + +fsdp_session_type_t +fsdp_get_session_type (const fsdp_description_t * dsc) +{ + if (!dsc) + return FSDP_SESSION_TYPE_UNDEFINED; + return dsc->a_type; +} + +unsigned int +fsdp_get_media_count (const fsdp_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->media_announcements_count; +} + +const fsdp_media_description_t * +fsdp_get_media (const fsdp_description_t * dsc, unsigned int index) +{ + if ((index >= dsc->media_announcements_count)) + return NULL; + return dsc->media_announcements[index]; +} + +fsdp_media_t +fsdp_get_media_type (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return FSDP_MEDIA_UNDEFINED; + return dsc->media_type; +} + +unsigned int +fsdp_get_media_port (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->port; +} + +unsigned int +fsdp_get_media_port_count (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->port_count; +} + +fsdp_transport_protocol_t +fsdp_get_media_transport_protocol (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return FSDP_TP_UNDEFINED; + return dsc->transport; +} + +unsigned int +fsdp_get_media_formats_count (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->formats_count; +} + +const char * +fsdp_get_media_format (const fsdp_media_description_t * dsc, + unsigned int index) +{ + if (!dsc && (index < dsc->formats_count)) + return NULL; + return dsc->formats[index]; +} + +const char * +fsdp_get_media_title (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return NULL; + return dsc->i_title; +} + +fsdp_network_type_t +fsdp_get_media_network_type (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return FSDP_NETWORK_TYPE_UNDEFINED; + return dsc->c_network_type; +} + +fsdp_address_type_t +fsdp_get_media_address_type (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return FSDP_ADDRESS_TYPE_UNDEFINED; + return dsc->c_address_type; +} + +const char * +fsdp_get_media_address (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return NULL; + return dsc->c_address.address; +} + +unsigned int +fsdp_get_media_address_ttl (const fsdp_media_description_t * mdsc) +{ + if (!mdsc) + return 0; + return mdsc->c_address.address_ttl; +} + +unsigned int +fsdp_get_media_address_count (const fsdp_media_description_t * mdsc) +{ + if (!mdsc) + return 0; + return mdsc->c_address.address_count; +} + +fsdp_bw_modifier_type_t +fsdp_get_media_bw_modifier_type (const fsdp_media_description_t * dsc, + unsigned int index) +{ + if (!dsc || (index >= dsc->bw_modifiers_count)) + return FSDP_BW_MOD_TYPE_UNDEFINED; + return dsc->bw_modifiers[index].b_mod_type; +} + +const char * +fsdp_get_media_bw_modifier_type_unknown (const fsdp_media_description_t * dsc, + unsigned int index) +{ + if (!dsc || (index >= dsc->bw_modifiers_count) || + (FSDP_BW_MOD_TYPE_UNKNOWN != dsc->bw_modifiers[index].b_mod_type)) + return NULL; + return dsc->bw_modifiers[index].b_unknown_bw_modt; +} + +unsigned long int +fsdp_get_media_bw_value (const fsdp_media_description_t * dsc, + unsigned int index) +{ + if (!dsc || (index >= dsc->bw_modifiers_count)) + return 0; + return dsc->bw_modifiers[index].b_value; +} + +fsdp_encryption_method_t +fsdp_get_media_encryption_method (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return FSDP_ENCRYPTION_METHOD_UNDEFINED; + return dsc->k_encryption_method; +} + +const char * +fsdp_get_media_encryption_content (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return NULL; + return dsc->k_encryption_content; +} + +unsigned int +fsdp_get_media_ptime (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->a_ptime; +} + +unsigned int +fsdp_get_media_maxptime (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->a_maxptime; +} + +unsigned int +fsdp_get_media_rtpmap_count (const fsdp_media_description_t * mdsc) +{ + if (!mdsc) + return 0; + return mdsc->a_rtpmaps_count; +} + +const char * +fsdp_get_media_rtpmap_payload_type (const fsdp_media_description_t * mdsc, + unsigned int index) +{ + if (!mdsc || (index >= mdsc->a_rtpmaps_count)) + return NULL; + return mdsc->a_rtpmaps[index]->pt; +} + +const char * +fsdp_get_media_rtpmap_encoding_name (const fsdp_media_description_t * mdsc, + unsigned int index) +{ + if (!mdsc || (index >= mdsc->a_rtpmaps_count)) + return NULL; + return mdsc->a_rtpmaps[index]->encoding_name; +} + +unsigned int +fsdp_get_media_rtpmap_clock_rate (const fsdp_media_description_t * mdsc, + unsigned int index) +{ + if (!mdsc || (index >= mdsc->a_rtpmaps_count)) + return 0; + return mdsc->a_rtpmaps[index]->clock_rate; +} + +const char * +fsdp_get_media_rtpmap_encoding_parameters (const fsdp_description_t * mdsc, + unsigned int index) +{ + if (!mdsc || (index >= mdsc->a_rtpmaps_count)) + return NULL; + return mdsc->a_rtpmaps[index]->parameters; +} + +unsigned int +fsdp_get_media_sdplang_count (const fsdp_media_description_t * mdsc) +{ + if (!mdsc) + return 0; + return mdsc->a_sdplangs_count; +} + +const char * +fsdp_get_media_sdplang (const fsdp_media_description_t * mdsc, + unsigned int index) +{ + if (!mdsc || (index >= mdsc->a_sdplangs_count)) + return NULL; + return mdsc->a_sdplangs[index]; +} + +unsigned int +fsdp_get_media_lang_count (const fsdp_media_description_t * mdsc) +{ + if (!mdsc) + return 0; + return mdsc->a_langs_count; +} + +const char * +fsdp_get_media_lang (const fsdp_media_description_t * mdsc, + unsigned int index) +{ + if (!mdsc || (index >= mdsc->a_langs_count)) + return NULL; + return mdsc->a_langs[index]; +} + +unsigned int +fsdp_get_media_control_count (const fsdp_media_description_t * mdsc) +{ + if (!mdsc) + return 0; + return mdsc->a_controls_count; +} + +char * +fsdp_get_media_control (const fsdp_media_description_t * mdsc, + unsigned int index) +{ + if (!mdsc || (index >= mdsc->a_controls_count)) + return NULL; + return mdsc->a_controls[index]; +} + +char * +fsdp_get_media_range (const fsdp_media_description_t * mdsc) +{ + return mdsc->a_range; +} + +unsigned int +fsdp_get_media_fmtp_count (const fsdp_media_description_t * mdsc) +{ + if (!mdsc) + return 0; + return mdsc->a_fmtps_count; +} + +const char * +fsdp_get_media_fmtp (const fsdp_media_description_t * mdsc, + unsigned int index) +{ + if (!mdsc || (index >= mdsc->a_fmtps_count)) + return NULL; + return mdsc->a_fmtps[index]; +} + +fsdp_orient_t +fsdp_get_media_orient (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return FSDP_ORIENT_UNDEFINED; + return dsc->a_orient; +} + +fsdp_sendrecv_mode_t +fsdp_get_media_sendrecv (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return FSDP_SENDRECV_UNDEFINED; + return dsc->a_sendrecv_mode; +} + +float +fsdp_get_media_framerate (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->a_framerate; +} + +unsigned int +fsdp_get_media_quality (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->a_quality; +} + +unsigned int +fsdp_get_media_rtcp_port (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return 0; + return dsc->a_rtcp_port; +} + +fsdp_network_type_t +fsdp_get_media_rtcp_network_type (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return FSDP_NETWORK_TYPE_UNDEFINED; + return dsc->a_rtcp_network_type; +} + +fsdp_address_type_t +fsdp_get_media_rtcp_address_type (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return FSDP_ADDRESS_TYPE_UNDEFINED; + return dsc->a_rtcp_address_type; +} + +const char * +fsdp_get_media_rtcp_address (const fsdp_media_description_t * dsc) +{ + if (!dsc) + return NULL; + return dsc->a_rtcp_address; +} + +unsigned int +fsdp_get_media_unidentified_attribute_count (const fsdp_media_description_t + * mdsc) +{ + if (!mdsc) + return 0; + return mdsc->unidentified_attributes_count; +} + +const char * +fsdp_get_media_unidentified_attribute (const fsdp_media_description_t * mdsc, + unsigned int index) +{ + if (!mdsc || (index < mdsc->unidentified_attributes_count)) + return NULL; + return mdsc->unidentified_attributes[index]; +} diff --git a/libmpdemux/freesdp/parser.h b/libmpdemux/freesdp/parser.h new file mode 100644 index 0000000000..80c61d0115 --- /dev/null +++ b/libmpdemux/freesdp/parser.h @@ -0,0 +1,728 @@ +/* + This file is part of FreeSDP + Copyright (C) 2001,2002,2003 Federico Montesino Pouzols + + FreeSDP is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Benjamin Zores, (C) 2006 + added support in parser for the a=control: lines. + added support in parser for the a=range: lines. +*/ + +/** + * @file parser.h + * @ingroup parser + * @short Specific public header for parsing module. + **/ + +#ifndef FSDP_PARSER_H +#define FSDP_PARSER_H + +#include "common.h" + +BEGIN_C_DECLS +/** + * @defgroup parser FreeSDP Parsing Module + * + * SDP descriptions parsing routines. + * @{ + **/ +/** + * Parse a SDP description in description, extracting the + * session properties into dsc. These properties can be + * obtained individually later using the fsdp_get_xxxx + * functions. + * + * @param description a multimedia session description formatted in + * SDP. + * @param dsc pointer that is updated to point to a fsdp_description_t + * object. This fsdp_description_t object should have been previously + * allocated using fsdp_description_new(); to free it, + * fsdp_description_delete() should be used. + * + * @return FSDPE_OK when parsing completes successfully. Otherwise, + * another error code is returned. + **/ +fsdp_error_t fsdp_parse (const char *description, fsdp_description_t * dsc); + +/** + * Get the SDP protocol version of the description. + * + * @return SDP protocol version number. + **/ +unsigned int fsdp_get_version (const fsdp_description_t * dsc); + +/** + * Get the username provided by the originator of the session. + * + * @param dsc SDP description object. + * @return username of the session owner + **/ +const char *fsdp_get_owner_username (const fsdp_description_t * dsc); + +/** + * Get the id for the session described in dsc. + * + * @param dsc SDP description object. + * @return id string for this session. + **/ +const char *fsdp_get_session_id (const fsdp_description_t * dsc); + +/** + * Get the announcement version for the session description in + * dsc. + * + * @param dsc SDP description object. + * @return announcement version string for this description. + **/ +const char *fsdp_get_announcement_version (const fsdp_description_t * dsc); + +/** + * Get the the type of network the owner of the session described in + * dsc is based on. + * + * @param dsc SDP description object. + * @return network type for the owner of this session. + **/ +fsdp_network_type_t +fsdp_get_owner_network_type (const fsdp_description_t * dsc); + +/** + * Get the the type of address the owner of the session described in + * dsc is based on. + * + * @param dsc SDP description object. + * @return network address type for the owner of this session. + **/ +fsdp_address_type_t +fsdp_get_owner_address_type (const fsdp_description_t * dsc); + +/** + * Get the network address of the owner of the session described in + * dsc. + * + * @param dsc SDP description object. + * @return network address for the owner this session. + **/ +const char *fsdp_get_owner_address (const fsdp_description_t * dsc); + +/** + * Get the name of the session described in dsc. + * + * @param dsc SDP description object. + * @return name of this session. + **/ +const char *fsdp_get_name (const fsdp_description_t * dsc); + +/** + * Get the information about the session provided in the description + * dsc. + * + * @param dsc SDP description object. + * @return information of this session. + **/ +const char *fsdp_get_information (const fsdp_description_t * dsc); + +/** + * Get an URI about the session provided in the description + * dsc. + * + * @param dsc SDP description object. + * @return string containing an URI about the session. NULL if the + * session uri is missing. + **/ +const char *fsdp_get_uri (const fsdp_description_t * dsc); + +/** + * Get the number of emails specified for the session in the description + * dsc. + * + * @param dsc SDP description object. + * @return number of emails. + **/ +unsigned int fsdp_get_emails_count (const fsdp_description_t * dsc); + +/** + * Get the n-th email specified for the session in the description + * dsc. + * + * @param dsc SDP description object. + * @param index number of URI. Note that this index follows the + * traditional C convention: from 0 to fsdp_get_emails_count() - 1. + * @return string containing an email about the session. NULL if there + * is no such index. + **/ +const char *fsdp_get_email (const fsdp_description_t * dsc, + unsigned int index); + +/** + * Get the number of phones specified for the session in the description + * dsc. + * + * @param dsc SDP description object. + * @return number of emails. + **/ +unsigned int fsdp_get_phones_count (const fsdp_description_t * dsc); + +/** + * Get the n-th phone specified for the session in the description + * dsc. + * + * @param dsc SDP description object. + * @param index number of URI. Note that this index follows the + * traditional C convention: from 0 to fsdp_get_phones_count() - 1. + * @return string containing a phone about the session. NULL if there + * is no such index. + **/ +const char *fsdp_get_phone (const fsdp_description_t * dsc, + unsigned int index); + +/** + * Get the the global type of network of the multimedia session + * connection. + * + * @param dsc SDP description object. + * @return global network type for this + * connection. FSDP_NETWORK_TYPE_UNDEFINED if no global network + * address type is included in the description. + **/ +fsdp_network_type_t +fsdp_get_global_conn_network_type (const fsdp_description_t * dsc); + +/** + * Get the the global type of network address of the multimedia + * session connection. + * + * @param dsc SDP description object. + * @return global network address type for this connection. + * FSDP_ADDRESS_TYPE_UNDEFINED if no global network address type is + * included in the description. + **/ +fsdp_address_type_t +fsdp_get_global_conn_address_type (const fsdp_description_t * dsc); + +/** + * Get the the global address of the multimedia session connection. + * + * @param dsc SDP description object. + * @return global address for this connection. + **/ +const char *fsdp_get_global_conn_address (const fsdp_description_t * dsc); + +unsigned int +fsdp_get_global_conn_address_ttl (const fsdp_description_t * dsc); + +unsigned int +fsdp_get_global_conn_address_count (const fsdp_description_t * dsc); + +/** + * Get the number of bandwidth modifiers specified for this session. + * + * @param dsc SDP description object. + * @return number of bandwidth modifiers. + **/ +unsigned int fsdp_get_bw_modifier_count (const fsdp_description_t * dsc); + +/** + * Get the bandwidth modifier type for the session. + * + * @param dsc SDP description object. + * @param index number of bandwidth modifier. + * + * @return global bandwidth modifier type. + * @retval FSDP_BW_MOD_TYPE_UNDEFINED if no global bandwith modifier + * type is defined or invalid index. + * @retval FSDP_BW_MOD_TYPE_UNKNOWN if an unknown bandwith modifier is + * specified or an invalid index is provided. In this case + * fsdp_get_bw_modifer_type_unknown() can be called to get the + * modifier as a character string. + **/ +fsdp_bw_modifier_type_t +fsdp_get_bw_modifier_type (const fsdp_description_t * dsc, + unsigned int index); + +/** + * Get the textual bandwidth modifier type when it is unknown. + * + * @param dsc SDP description object. + * @param index number of bandwidth modifier. + * + * @return global bandwidth modifier type. + * @retval empty string if the provided bandwidth type is not unknown, + * the provided index is invalid or or there was a parse error. + **/ +const char *fsdp_get_bw_modifier_type_unknown (const fsdp_description_t * dsc, + unsigned int index); + +/** + * Get the value for the bandwidth modifier. + * + * @param dsc SDP description object. + * @param index number of bandwidth modifier. + * @return global bandwidth value. + * @retval 0 if no bandwidth is specified for this session or an + * invalid index has been provided. + **/ +unsigned long int +fsdp_get_bw_value (const fsdp_description_t * dsc, unsigned int index); + +/** + * Get the number of time periods specified for this session + * + * @param dsc SDP description object. + * @return number of time periods + **/ +unsigned long int fsdp_get_period_count (const fsdp_description_t * dsc); + +/** + * Get the start time for the period selected by index. + * + * @param dsc SDP description object. + * @param index number of time period. Note that this index follows the + * traditional C convention: from 0 to fsdp_get_period_count() - 1. + * @return start time + * @retval 0 if an invalid index is provided. + **/ +time_t +fsdp_get_period_start (const fsdp_description_t * dsc, unsigned int index); + +/** + * Get the stop time for the period selected by index. + * + * @param dsc SDP description object. + * @param index number of time period. Note that this index follows the + * traditional C convention: from 0 to fsdp_get_period_count() - 1. + * @return stop time + * @retval 0 if an invalid index is provided. + **/ +time_t +fsdp_get_period_stop (const fsdp_description_t * dsc, unsigned int index); + +/** + * Get the number of repeats for the period selected by index. + * + * @param dsc SDP description object. + * @param index number of the period. Note that this index follows the + * traditional C convention: from 0 to fsdp_get_period_count() - 1. + * @return number of repeats + * @retval 0 if an invalid index is provided. + **/ +unsigned int +fsdp_get_period_repeats_count (const fsdp_description_t * dsc, + unsigned int index); + +/** + * Get the interval time of the repeat selected by rindex for the + * period selected by index. + * + * @param dsc SDP description object. + * @param index number of time period. Note that this index follows the + * traditional C convention: from 0 to fsdp_get_period_count() - 1. + * @param rindex number of repeat + * @return interval time + * @retval 0 if an invalid index is provided. + **/ +unsigned long int +fsdp_get_period_repeat_interval (const fsdp_description_t * dsc, + unsigned int index, unsigned int rindex); + +/** + * Get the duration of the repeat selected by rindex for the period + * selected by index. + * + * @param dsc SDP description object. + * @param index number of time period. Note that this index follows the + * traditional C convention: from 0 to fsdp_get_period_count() - 1. + * @param rindex number of repeat + * @return duration + * @retval 0 if an invalid index is provided. + **/ +unsigned long int +fsdp_get_period_repeat_duration (const fsdp_description_t * dsc, + unsigned int index, unsigned int rindex); + +/** + * Get the offsets of the repeat selected by rindex for the period + * selected by index. + * + * @param dsc SDP description object. + * @param index number of time period. Note that this index follows the + * traditional C convention: from 0 to fsdp_get_period_count() - 1. + * @param rindex number of repeat + * @return array of offsets + * @retval NULL if an invalid index is provided. + **/ +const unsigned long int *fsdp_get_period_repeat_offsets (const + fsdp_description_t * + dsc, + unsigned int index, + unsigned int rindex); + +/** + * Get the encryption method defined for this session. + * + * @param dsc SDP description object. + * @return encryption method. FSDP_ENCRYPTION_METHOD_UNDEFINED if no + * encryption method is specified. + **/ +fsdp_encryption_method_t +fsdp_get_encryption_method (const fsdp_description_t * dsc); + +/** + * Get the encryption key or a URI pointing to the encryption key for + * this session. + * + * @param dsc SDP description object. + * @return encryption key unless FSDP_ENCRYPTION_METHOD_URI is + * specified, in which case a URI pointing to the key is returned. If + * the global encryption method is undefined, NULL is returned. + **/ +const char *fsdp_get_encryption_content (const fsdp_description_t * dsc); + +/** + * Get timezone adjustments. + * + * @param dsc SDP description object. + * @return string with list of timezone adjustments + * @retval NULL if no timezone adjustment list was specified or there + * was a parse error. + **/ +const char *fsdp_get_timezone_adj (const fsdp_description_t * dsc); + +/** + * + **/ +unsigned int +fsdp_get_unidentified_attribute_count (const fsdp_description_t * dsc); + +/** + * + **/ +const char *fsdp_get_unidentified_attribute (const fsdp_description_t * dsc, + unsigned int index); + +/** + * + **/ +unsigned int +fsdp_get_media_rtpmap_count (const fsdp_media_description_t * mdsc); + +/** + * + **/ +const char *fsdp_get_media_rtpmap_payload_type (const fsdp_media_description_t + * mdsc, unsigned int index); + +/** + * + **/ +const char *fsdp_get_media_rtpmap_encoding_name (const + fsdp_media_description_t * + mdsc, unsigned int index); + +/** + * + **/ +unsigned int +fsdp_get_media_rtpmap_clock_rate (const fsdp_media_description_t * mdsc, + unsigned int index); + +/** + * + **/ +const char *fsdp_get_media_rtpmap_encoding_parameters (const + fsdp_description_t * + mdsc, + unsigned int index); + +/** + * Get the value of the session attribute specified in + * att. This function works for all the session + * attributes whose value is a character string. These attributes are + * defined in the session_string_attribute_t enumerated type. + * + * @param dsc SDP description object. + * @param att attribute to get. + * + * @return value of the attribute att. + * @retval NULL if the attribute was not specified or there was a + * parse error or an invalid att is given. + **/ +const char *fsdp_get_str_att (const fsdp_description_t * dsc, + fsdp_session_str_att_t att); + +/** + * + **/ +unsigned int fsdp_get_sdplang_count (const fsdp_description_t * dsc); + +/** + * + **/ +const char *fsdp_get_sdplang (const fsdp_description_t * dsc, + unsigned int index); + +/** + * Get the mode of the conference, specified with attributes sendrecv, + * sendonly, recvonly and inactive. + * + * @param dsc SDP description object. + * @return send/rec conference mode. + * @retval FSDP_SENDRECV_UNDEFINED if conference mode not provided. + **/ +fsdp_sendrecv_mode_t fsdp_get_sendrecv_mode (const fsdp_description_t * dsc); + +/** + * Get the type of conference, such as broadcast, meeting, moderated, + * test or H332. + * + * @param dsc SDP description object. + * @return conference type. + * @retval FSDP_SESSION_TYPE_UNDEFINED if conference type not provided. + **/ +fsdp_session_type_t fsdp_get_session_type (const fsdp_description_t * dsc); + +/** + * + **/ +unsigned int fsdp_get_media_count (const fsdp_description_t * dsc); + +/** + * + **/ +const fsdp_media_description_t *fsdp_get_media (const fsdp_description_t * + dsc, unsigned int index); + +/** + * + **/ +fsdp_media_t fsdp_get_media_type (const fsdp_media_description_t * dsc); + +/** + * + **/ +unsigned int fsdp_get_media_port (const fsdp_media_description_t * dsc); + +unsigned int fsdp_get_media_port_count (const fsdp_media_description_t * dsc); + +/** + * + **/ +fsdp_transport_protocol_t +fsdp_get_media_transport_protocol (const fsdp_media_description_t * dsc); + +/** + * + **/ +const char *fsdp_get_media_formats (const fsdp_media_description_t * dsc); + +/** + * + **/ +unsigned int +fsdp_get_media_formats_count (const fsdp_media_description_t * dsc); + +/** + * + **/ +const char *fsdp_get_media_format (const fsdp_media_description_t * dsc, + unsigned int index); + +/** + * + **/ +const char *fsdp_get_media_title (const fsdp_media_description_t * dsc); + +/** + * + **/ +fsdp_network_type_t +fsdp_get_media_network_type (const fsdp_media_description_t * dsc); + +/** + * + **/ +fsdp_address_type_t +fsdp_get_media_address_type (const fsdp_media_description_t * dsc); + +/** + * + **/ +const char *fsdp_get_media_address (const fsdp_media_description_t * dsc); + +unsigned int +fsdp_get_media_address_ttl (const fsdp_media_description_t * mdsc); + +unsigned int +fsdp_get_media_address_count (const fsdp_media_description_t * mdsc); + +/** + * + **/ +fsdp_bw_modifier_type_t +fsdp_get_media_bw_modifier_type (const fsdp_media_description_t * dsc, + unsigned int index); + +/** + * + **/ +const char *fsdp_get_media_bw_modifier_type_unknown (const + fsdp_media_description_t + * dsc, + unsigned int index); + +/** + * + **/ +unsigned long int +fsdp_get_media_bw_value (const fsdp_media_description_t * dsc, + unsigned int index); + +/** + * + **/ +fsdp_encryption_method_t +fsdp_get_media_encryption_method (const fsdp_media_description_t * dsc); + +/** + * + **/ +const char *fsdp_get_media_encryption_content (const fsdp_media_description_t + * dsc); + +/** + * + **/ +unsigned int fsdp_get_media_ptime (const fsdp_media_description_t * dsc); + +/** + * + **/ +unsigned int fsdp_get_media_maxptime (const fsdp_media_description_t * dsc); + +/** + * + **/ +unsigned int +fsdp_get_media_fmtp_count (const fsdp_media_description_t * mdsc); + +/** + * + **/ +const char *fsdp_get_media_fmtp (const fsdp_media_description_t * mdsc, + unsigned int index); + +/** + * + **/ +unsigned int +fsdp_get_media_sdplang_count (const fsdp_media_description_t * dsc); + +/** + * + **/ +const char *fsdp_get_media_sdplang (const fsdp_media_description_t * dsc, + unsigned int index); + +/** + * + **/ +unsigned int fsdp_get_media_lang_count (const fsdp_media_description_t * dsc); + +/** + * + **/ +const char *fsdp_get_media_lang (const fsdp_media_description_t * dsc, + unsigned int index); + + +unsigned int fsdp_get_control_count (const fsdp_description_t * dsc); + +const char *fsdp_get_control (const fsdp_description_t * dsc, + unsigned int index); + +const char *fsdp_get_range (const fsdp_description_t * dsc); + +unsigned int +fsdp_get_media_control_count (const fsdp_media_description_t * mdsc); + +char *fsdp_get_media_control (const fsdp_media_description_t * mdsc, + unsigned int index); + +char *fsdp_get_media_range (const fsdp_media_description_t * mdsc); + +/** + * + **/ +fsdp_orient_t fsdp_get_media_orient (const fsdp_media_description_t * dsc); + +/** + * + **/ +fsdp_sendrecv_mode_t +fsdp_get_media_sendrecv (const fsdp_media_description_t * dsc); + +/** + * + **/ +float fsdp_get_media_framerate (const fsdp_media_description_t * dsc); + +/** + * + **/ +unsigned int fsdp_get_media_quality (const fsdp_media_description_t * dsc); + +/** + * + **/ +unsigned int fsdp_get_media_rtcp_port (const fsdp_media_description_t * dsc); + +/** + * + **/ +fsdp_network_type_t +fsdp_get_media_rtcp_network_type (const fsdp_media_description_t * dsc); + +/** + * + **/ +fsdp_address_type_t +fsdp_get_media_rtcp_address_type (const fsdp_media_description_t * dsc); + +/** + * + **/ +const char *fsdp_get_media_rtcp_address (const fsdp_media_description_t * + dsc); + +/** + * + **/ +unsigned int +fsdp_get_media_unidentified_attribute_count (const fsdp_media_description_t + * mdsc); + +/** + * + **/ +const char *fsdp_get_media_unidentified_attribute (const + fsdp_media_description_t * + mdsc, unsigned int index); + + + /** @} *//* closes parser group */ + +END_C_DECLS +#endif /* FSDP_PARSER_H */ diff --git a/libmpdemux/freesdp/parserpriv.h b/libmpdemux/freesdp/parserpriv.h new file mode 100644 index 0000000000..9d44102d31 --- /dev/null +++ b/libmpdemux/freesdp/parserpriv.h @@ -0,0 +1,118 @@ +/* + This file is part of FreeSDP + Copyright (C) 2001,2002,2003 Federico Montesino Pouzols + + FreeSDP is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** + * @file parserpriv.h + * + * @short Private header for parser module. + **/ + +#ifndef FSDP_PARSERPRIV_H +#define FSDP_PARSERPRIV_H + +#include "priv.h" +#include "parser.h" + +/** + * Parse a connection (c=
) line. If the textual description in p begins + * with a connection line, it is parsed. If not, nothing is done. + * + * @param p fraction of textual SDP description. + * @param ntype where to store the network type. + * @param atype where to store the address type. + * @param address where to store the connection address as a string. + * + * @return parse error code. + **/ +static fsdp_error_t +fsdp_parse_c (const char **p, fsdp_network_type_t * ntype, + fsdp_address_type_t * atype, + fsdp_connection_address_t * address); + +/** + * Parse b (b=:) consecutive lines. If the + * textual description in p begins with a bandwidth line, + * it is parsed as well as all b lines inmediately after it. If not, + * nothing is done. + * + * @param p fraction of textual SDP description. + * @param bw_modifiers pointer to empty array of bandwidth modifiers to fill. + * @param bw_modifiers_count where to set the number of bandwidth + * modifiers successfully parsed. + * + * @return parse error code. + **/ +static fsdp_error_t +fsdp_parse_b (const char **p, fsdp_bw_modifier_t ** bw_modifiers, + unsigned int *bw_modifiers_count); + +/** + * Parse a k (k=) or (k=:) line. If + * the textual description in p begins with an encryption + * line, it is parsed. If not, nothing is done. + * + * @param p fraction of textual SDP description. + * @param method where to store the encryption method. + * @param content where to store the encryption key if provided. + * + * @return parse error code. + **/ +static fsdp_error_t +fsdp_parse_k (const char **p, fsdp_encryption_method_t * method, + char **content); + + +/** + * Parses a string whose first token (first characters before the + * first space or end of string) is supposed to be a time in SDP + * syntax. Some examples of SDP times are: 2d, 5h, 3444, 7778s, + * + * @param time time in SDP syntax as a string. + * @param seconds where to store the value in seconds as an integer. + * + * @return parse error code. + **/ +static fsdp_error_t +fsdp_repeat_time_to_uint (const char *time, unsigned long int *seconds); + +static fsdp_error_t +fsdp_parse_rtpmap (fsdp_rtpmap_t *** rtpmap, unsigned int *counter, + const char *value); + +/** + * Maximun default field len for "expected to be short" fields, like + * username, session_id or inet addresses. + * + * MDFLENS value must be MAXSHORTFIELDLEN - 1 + **/ +#define MAXSHORTFIELDLEN 96 +#define MSFLENS "95" + +/** + * Maximun default field len for "maybe very long" fields, like + * information, attribute values. This can also be used for lines + * where there is only a string field, like phone and email. + * + * MLFLENS value must be MAXLONGFIELDLEN - 1 + **/ +#define MAXLONGFIELDLEN 1024 +#define MLFLENS "1023" + +#endif /* FSDP_PARSERPRIV_H */ diff --git a/libmpdemux/freesdp/priv.h b/libmpdemux/freesdp/priv.h new file mode 100644 index 0000000000..c39a493c5f --- /dev/null +++ b/libmpdemux/freesdp/priv.h @@ -0,0 +1,274 @@ +/* + This file is part of FreeSDP + Copyright (C) 2001,2002,2003 Federico Montesino Pouzols + + FreeSDP is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Benjamin Zores, (C) 2006 + added support in parser for the a=control: lines. + added support in parser for the a=range: lines. +*/ + +/** + * @file priv.h + * + * @short Common private header for both formatting and parsing modules. + **/ + +#ifndef FSDP_PRIV_H +#define FSDP_PRIV_H + +#define _GNU_SOURCE + +#include +#include +#include + +#include "common.h" + +#define NTP_EPOCH_OFFSET 2208988800UL + +#define FSDP_MAX_LENGTH 2000 + +/* Tags for doxygen documentation */ + +/** + * @mainpage FreeSDP Library Reference Manual + * @section overview Overview (README) + * @verbinclude ../../README + * + **/ + +/** + * @example formatdemo.c + * + * A basic SDP descriptions formatter based on FreeSDP. + **/ + +/** + * @example parsedemo.c + * + * A basic SDP descriptions parser based on FreeSDP. + **/ + +/* Private routines declarations */ + +BEGIN_C_DECLS +/** + * @short bandwidth modifier + * + * Holds type of modifier and value. Also holds the literal bandwidth + * modifier if unknown. + **/ + typedef struct +{ + fsdp_bw_modifier_type_t b_mod_type; + unsigned long int b_value; + char *b_unknown_bw_modt; +} fsdp_bw_modifier_t; + +/** + * @short a=rtpmap: attribute + * + * Holds payload type, enconding name, RTP clock rate, and encofing + * parameters. + **/ +typedef struct +{ + char *pt; + char *encoding_name; + unsigned int clock_rate; + char *parameters; +} fsdp_rtpmap_t; + +/** + * @short Connection address specification + * + * Holds address (unicast or multicast) as well as TTL and number of + * ports, when it is an IP4 multicast address. + **/ +typedef struct fsdp_connection_address_t_s +{ + char *address; + unsigned int address_ttl; + unsigned int address_count; +} fsdp_connection_address_t; + +/** + * @short Struct for each media in a session description. + **/ +struct fsdp_media_description_t_s +{ + /* from `m= ' line */ + fsdp_media_t media_type; + unsigned int port; + unsigned int port_count; + fsdp_transport_protocol_t transport; + char **formats; + unsigned int formats_count; + /* from i= */ + char *i_title; + /* from `c=
' line + (optional) */ + fsdp_network_type_t c_network_type; + fsdp_address_type_t c_address_type; + fsdp_connection_address_t c_address; + /* from `b=:' lines (optional) */ + fsdp_bw_modifier_t *bw_modifiers; + unsigned int bw_modifiers_count; + /* from `k=' or `k=:' line + (optional) */ + fsdp_encryption_method_t k_encryption_method; + char *k_encryption_content; + /* from `a=' or `a=:' lines (opt) */ + unsigned long int a_ptime; + unsigned long int a_maxptime; + /* rtpmap */ + fsdp_rtpmap_t **a_rtpmaps; + unsigned int a_rtpmaps_count; + fsdp_orient_t a_orient; + fsdp_sendrecv_mode_t a_sendrecv_mode; + + char **a_sdplangs; + unsigned int a_sdplangs_count; + char **a_langs; + unsigned int a_langs_count; + + char **a_controls; + unsigned int a_controls_count; + + char *a_range; + + float a_framerate; + unsigned int a_quality; + char **a_fmtps; + unsigned int a_fmtps_count; + /* rtcp attribute */ + unsigned int a_rtcp_port; + fsdp_network_type_t a_rtcp_network_type; + fsdp_address_type_t a_rtcp_address_type; + char *a_rtcp_address; + /* media attributes that are not directly supported */ + char **unidentified_attributes; + unsigned int unidentified_attributes_count; +}; + +typedef struct fsdp_media_description_t_s fsdp_media_announcement_t; + +/** + * @short Information for a repeat (struct for r= lines) + **/ +typedef struct +{ + /* times in seconds */ + unsigned long int interval; + unsigned long int duration; + unsigned long int *offsets; + unsigned int offsets_count; +} fsdp_repeat_t; + +/** + * @short Information about a time period + * + * The start and stop times as well as the information from the r= + * lines for a t= line are stored in this structures. + **/ +typedef struct +{ + time_t start; + time_t stop; + fsdp_repeat_t **repeats; + unsigned int repeats_count; +} fsdp_time_period_t; + +/** + * @short Struct for session descriptions. + **/ +struct fsdp_description_t_s +{ + /* from v=... line */ + unsigned int version; + /* from o=... line */ + char *o_username; + char *o_session_id; + char *o_announcement_version; + fsdp_network_type_t o_network_type; + fsdp_address_type_t o_address_type; + char *o_address; + /* from s=... line */ + char *s_name; + /* from i=... line (opt) */ + char *i_information; + /* from u=... line (opt) */ + char *u_uri; + /* from e=... lines (0 or more) */ + const char **emails; + unsigned int emails_count; + /* from p=... lines (0 or more) */ + const char **phones; + unsigned int phones_count; + /* from `c=
' line */ + fsdp_network_type_t c_network_type; + fsdp_address_type_t c_address_type; + fsdp_connection_address_t c_address; + /* from `b=:' lines (optional) */ + fsdp_bw_modifier_t *bw_modifiers; + unsigned int bw_modifiers_count; + /* from `t= ' lines (1 or more) */ + /* from `r= ' */ + fsdp_time_period_t **time_periods; + unsigned int time_periods_count; + /* from `z= + ....' lines */ + char *timezone_adj; + /* from `k=' or `k=:' line (opt) */ + fsdp_encryption_method_t k_encryption_method; + char *k_encryption_content; + /* from `a=' or `a=:' lines (opt) */ + char *a_category; + char *a_keywords; + char *a_tool; + char *a_range; + /* rtpmap */ + fsdp_rtpmap_t **a_rtpmaps; + unsigned int a_rtpmaps_count; + fsdp_sendrecv_mode_t a_sendrecv_mode; + fsdp_session_type_t a_type; + char *a_charset; + + char **a_sdplangs; + unsigned int a_sdplangs_count; + char **a_langs; + unsigned int a_langs_count; + + char **a_controls; + unsigned int a_controls_count; + /* from `m= / ' + lines [one or more] */ + fsdp_media_announcement_t **media_announcements; + unsigned int media_announcements_count; + /* session attributes that are not directly supported */ + char **unidentified_attributes; + unsigned int unidentified_attributes_count; +}; + +#define MEDIA_RTPMAPS_MAX_COUNT 5 +#define SDPLANGS_MAX_COUNT 5 +#define SDPCONTROLS_MAX_COUNT 10 +#define UNIDENTIFIED_ATTRIBUTES_MAX_COUNT 5 + +END_C_DECLS +#endif /* FSDP_PRIV_H */