<p>Richard Mudgett has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/7715">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">core: Remove unused/incomplete SDP modules from released branches.<br><br>Change-Id: Icc28fbdc46f58e54a21554e6fe8b078f841b1f86<br>---<br>D include/asterisk/sdp.h<br>D include/asterisk/sdp_options.h<br>D include/asterisk/sdp_state.h<br>D include/asterisk/sdp_translator.h<br>D main/sdp.c<br>D main/sdp_options.c<br>D main/sdp_private.h<br>D main/sdp_srtp.c<br>D main/sdp_state.c<br>D main/sdp_translator.c<br>D res/res_sdp_translator_pjmedia.c<br>D tests/test_sdp.c<br>12 files changed, 0 insertions(+), 6,584 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/15/7715/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/include/asterisk/sdp.h b/include/asterisk/sdp.h<br>deleted file mode 100644<br>index 224a0e5..0000000<br>--- a/include/asterisk/sdp.h<br>+++ /dev/null<br>@@ -1,713 +0,0 @@<br>-/*<br>- * Asterisk -- An open source telephony toolkit.<br>- *<br>- * Copyright (C) 2017, Digium, Inc.<br>- *<br>- * Mark Michelson <mmichelson@digium.com><br>- *<br>- * See http://www.asterisk.org for more information about<br>- * the Asterisk project. Please do not directly contact<br>- * any of the maintainers of this project for assistance;<br>- * the project provides a web site, mailing lists and IRC<br>- * channels for your use.<br>- *<br>- * This program is free software, distributed under the terms of<br>- * the GNU General Public License Version 2. See the LICENSE file<br>- * at the top of the source tree.<br>- */<br>-<br>-/* NOTE: It is unlikely that you need to include this file. You probably will only need<br>- * this if you are an SDP translator, or if you are an inner part of the SDP API<br>- */<br>-<br>-#ifndef _SDP_PRIV_H<br>-#define _SDP_PRIV_H<br>-<br>-#include "asterisk/vector.h"<br>-#include "asterisk/format.h"<br>-#include "asterisk/sdp_state.h"<br>-#include "asterisk/stream.h"<br>-<br>-/*!<br>- * \brief Structure representing an SDP Attribute<br>- */<br>-struct ast_sdp_a_line {<br>- /*! Attribute name */<br>- char *name;<br>- /*! Attribute value. For attributes that have no value, this will be an empty string */<br>- char *value;<br>-};<br>-<br>-/*!<br>- * \brief A collection of SDP Attributes<br>- */<br>-AST_VECTOR(ast_sdp_a_lines, struct ast_sdp_a_line *);<br>-<br>-/*!<br>- * \brief Structure representing an SDP Connection<br>- */<br>-struct ast_sdp_c_line {<br>- /* IP family string (e.g. IP4 or IP6) */<br>- char *address_type;<br>- /* Connection address. Can be an IP address or FQDN */<br>- char *address;<br>-};<br>-<br>-/*!<br>- * \brief Structre representing SDP Media Payloads<br>- */<br>-struct ast_sdp_payload {<br>- /* Media format description */<br>- char *fmt;<br>-};<br>-<br>-/*!<br>- * \brief A collection of SDP Media Payloads<br>- */<br>-AST_VECTOR(ast_sdp_payloads, struct ast_sdp_payload *);<br>-<br>-/*!<br>- * \brief Structure representing an SDP Media Stream<br>- *<br>- * This contains both the m line, as well as its<br>- * constituent a lines.<br>- */<br>-struct ast_sdp_m_line {<br>- /*! Media type (e.g. "audio" or "video") */<br>- char *type;<br>- /*! RTP profile string (e.g. "RTP/AVP") */<br>- char *proto;<br>- /*! Port number in m line */<br>- uint16_t port;<br>- /*! Number of ports specified in m line */<br>- uint16_t port_count;<br>- /*! RTP payloads */<br>- struct ast_sdp_payloads *payloads;<br>- /*! Connection information for this media stream */<br>- struct ast_sdp_c_line *c_line;<br>- /*! The attributes for this media stream */<br>- struct ast_sdp_a_lines *a_lines;<br>-};<br>-<br>-/*!<br>- * \brief A collection of SDP Media Streams<br>- */<br>-AST_VECTOR(ast_sdp_m_lines, struct ast_sdp_m_line *);<br>-<br>-/*!<br>- * \brief Structure representing an SDP Origin<br>- */<br>-struct ast_sdp_o_line {<br>- /*! Origin user name */<br>- char *username;<br>- /*! Origin id */<br>- uint64_t session_id;<br>- /*! Origin version */<br>- uint64_t session_version;<br>- /*! Origin IP address type (e.g. "IP4" or "IP6") */<br>- char *address_type;<br>- /*! Origin address. Can be an IP address or FQDN */<br>- char *address;<br>-};<br>-<br>-/*!<br>- * \brief Structure representing an SDP Session Name<br>- */<br>-struct ast_sdp_s_line {<br>- /* Session Name */<br>- char *session_name;<br>-};<br>-<br>-/*!<br>- * \brief Structure representing SDP Timing<br>- */<br>-struct ast_sdp_t_line {<br>- /*! Session start time */<br>- uint64_t start_time;<br>- /*! Session end time */<br>- uint64_t stop_time;<br>-};<br>-<br>-/*!<br>- * \brief An SDP<br>- */<br>-struct ast_sdp {<br>- /*! SDP Origin line */<br>- struct ast_sdp_o_line *o_line;<br>- /*! SDP Session name */<br>- struct ast_sdp_s_line *s_line;<br>- /*! SDP top-level connection information */<br>- struct ast_sdp_c_line *c_line;<br>- /*! SDP timing information */<br>- struct ast_sdp_t_line *t_line;<br>- /*! SDP top-level attributes */<br>- struct ast_sdp_a_lines *a_lines;<br>- /*! SDP media streams */<br>- struct ast_sdp_m_lines *m_lines;<br>-};<br>-<br>-/*!<br>- * \brief A structure representing an SDP rtpmap attribute<br>- */<br>-struct ast_sdp_rtpmap {<br>- /*! The RTP payload number for the rtpmap */<br>- int payload;<br>- /*! The Name of the codec */<br>- char *encoding_name;<br>- /*! The clock rate of the codec */<br>- int clock_rate;<br>- /*! Optional encoding parameters */<br>- char *encoding_parameters;<br>- /*! Area where strings are stored */<br>- char buf[0];<br>-};<br>-<br>-/*!<br>- * \brief Free an SDP Attribute<br>- *<br>- * \param a_line The attribute to free<br>- *<br>- * \since 15<br>- */<br>-void ast_sdp_a_free(struct ast_sdp_a_line *a_line);<br>-<br>-/*!<br>- * \brief Free an SDP Attribute collection<br>- *<br>- * \param a_lines The attribute collection to free<br>- *<br>- * \since 15<br>- */<br>-void ast_sdp_a_lines_free(struct ast_sdp_a_lines *a_lines);<br>-<br>-/*!<br>- * \brief Free SDP Connection Data<br>- *<br>- * \param c_line The connection data to free<br>- *<br>- * \since 15<br>- */<br>-void ast_sdp_c_free(struct ast_sdp_c_line *c_line);<br>-<br>-/*!<br>- * \brief Free an SDP Media Description Payload<br>- *<br>- * \param payload The payload to free<br>- *<br>- * \since 15<br>- */<br>-void ast_sdp_payload_free(struct ast_sdp_payload *payload);<br>-<br>-/*!<br>- * \brief Free an SDP Media Description Payload collection<br>- *<br>- * \param payloads collection to free<br>- *<br>- * \since 15<br>- */<br>-void ast_sdp_payloads_free(struct ast_sdp_payloads *payloads);<br>-<br>-/*!<br>- * \brief Free an SDP Media Description<br>- * Frees the media description and all resources it contains<br>- *<br>- * \param m_line The media description to free<br>- *<br>- * \since 15<br>- */<br>-void ast_sdp_m_free(struct ast_sdp_m_line *m_line);<br>-<br>-/*!<br>- * \brief Free an SDP Media Description collection<br>- *<br>- * \param m_lines The collection description to free<br>- *<br>- * \since 15<br>- */<br>-void ast_sdp_m_lines_free(struct ast_sdp_m_lines *m_lines);<br>-<br>-/*!<br>- * \brief Free an SDP Origin<br>- *<br>- * \param o_line The origin description to free<br>- *<br>- * \since 15<br>- */<br>-void ast_sdp_o_free(struct ast_sdp_o_line *o_line);<br>-<br>-/*!<br>- * \brief Free an SDP Session<br>- *<br>- * \param s_line The session to free<br>- *<br>- * \since 15<br>- */<br>-void ast_sdp_s_free(struct ast_sdp_s_line *s_line);<br>-<br>-/*!<br>- * \brief Free SDP Timing<br>- *<br>- * \param t_line The timing description to free<br>- *<br>- * \since 15<br>- */<br>-void ast_sdp_t_free(struct ast_sdp_t_line *t_line);<br>-<br>-/*!<br>- * \brief Free an SDP<br>- * Frees the sdp and all resources it contains<br>- *<br>- * \param sdp The sdp to free<br>- *<br>- * \since 15<br>- */<br>-void ast_sdp_free(struct ast_sdp *sdp);<br>-<br>-/*!<br>- * \brief Allocate an SDP Attribute<br>- *<br>- * \param name Attribute Name<br>- * \param value Attribute Name<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \since 15<br>- */<br>-struct ast_sdp_a_line *ast_sdp_a_alloc(const char *name, const char *value);<br>-<br>-/*!<br>- * \brief Allocate an SDP Connection<br>- *<br>- * \param family Family ("IN", etc)<br>- * \param addr Address<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \since 15<br>- */<br>-struct ast_sdp_c_line *ast_sdp_c_alloc(const char *family, const char *addr);<br>-<br>-/*!<br>- * \brief Allocate an SDP Media Description Payload<br>- *<br>- * \param fmt The media format description<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \since 15<br>- */<br>-struct ast_sdp_payload *ast_sdp_payload_alloc(const char *fmt);<br>-<br>-/*!<br>- * \brief Allocate an SDP Media Description<br>- *<br>- * \param type ("audio", "video", etc)<br>- * \param port Starting port<br>- * \param port_count Port pairs to allocate<br>- * \param proto ("RTP/AVP", "RTP/SAVP", "udp")<br>- * \param c_line Connection to add. May be NULL<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \since 15<br>- */<br>-struct ast_sdp_m_line *ast_sdp_m_alloc(const char *type, uint16_t port,<br>- uint16_t port_count, const char *proto, struct ast_sdp_c_line *c_line);<br>-<br>-/*!<br>- * \brief Allocate an SDP Session<br>- *<br>- * \param session_name The session name<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \since 15<br>- */<br>-struct ast_sdp_s_line *ast_sdp_s_alloc(const char *session_name);<br>-<br>-/*!<br>- * \brief Allocate SDP Timing<br>- *<br>- * \param start_time (Seconds since 1900)<br>- * \param end_time (Seconds since 1900)<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \since 15<br>- */<br>-struct ast_sdp_t_line *ast_sdp_t_alloc(uint64_t start_time, uint64_t stop_time);<br>-<br>-/*!<br>- * \brief Allocate an SDP Origin<br>- *<br>- * \param username User name<br>- * \param sesison_id Session ID<br>- * \param sesison_version Session Version<br>- * \param address_type Address type ("IN4", "IN6", etc)<br>- * \param address Unicast address<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \since 15<br>- */<br>-struct ast_sdp_o_line *ast_sdp_o_alloc(const char *username, uint64_t session_id,<br>- uint64_t session_version, const char *address_type, const char *address);<br>-<br>-/*!<br>- * \brief Add an SDP Attribute to an SDP<br>- *<br>- * \param sdp SDP<br>- * \param a_line Attribute<br>- *<br>- * \retval 0 Success<br>- * \retval non-0 Failure<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_add_a(struct ast_sdp *sdp, struct ast_sdp_a_line *a_line);<br>-<br>-/*!<br>- * \brief Get the count of Attributes on an SDP<br>- *<br>- * \param sdp SDP<br>- *<br>- * \returns Number of Attributes<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_get_a_count(const struct ast_sdp *sdp);<br>-<br>-/*!<br>- * \brief Get an Attribute from an SDP<br>- *<br>- * \param sdp SDP<br>- * \param index Attribute index<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \since 15<br>- */<br>-struct ast_sdp_a_line *ast_sdp_get_a(const struct ast_sdp *sdp, int index);<br>-<br>-/*!<br>- * \brief Add a Media Description to an SDP<br>- *<br>- * \param sdp SDP<br>- * \param m_line Media Description<br>- *<br>- * \retval 0 Success<br>- * \retval non-0 Failure<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_add_m(struct ast_sdp *sdp, struct ast_sdp_m_line *m_line);<br>-<br>-/*!<br>- * \brief Add an RTP Media Description to an SDP<br>- *<br>- * \param sdp SDP<br>- * \param sdp_state SDP state information<br>- * \param options SDP Options<br>- * \param stream_index stream<br>- *<br>- * \retval 0 Success<br>- * \retval non-0 Failure<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_add_m_from_rtp_stream(struct ast_sdp *sdp, const struct ast_sdp_state *sdp_state,<br>- const struct ast_sdp_options *options, int stream_index);<br>-<br>-/*!<br>- * \brief Get the count of Media Descriptions on an SDP<br>- *<br>- * \param sdp SDP<br>- *<br>- * \returns The number of Media Descriptions<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_get_m_count(const struct ast_sdp *sdp);<br>-<br>-/*!<br>- * \brief Get a Media Descriptions from an SDP<br>- *<br>- * \param sdp SDP<br>- * \param index Media Description index<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \since 15<br>- */<br>-struct ast_sdp_m_line *ast_sdp_get_m(const struct ast_sdp *sdp, int index);<br>-<br>-/*!<br>- * \brief Add an SDP Attribute to a Media Description<br>- *<br>- * \param m_line Media Description<br>- * \param a_line Attribute<br>- *<br>- * \retval 0 Success<br>- * \retval non-0 Failure<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_m_add_a(struct ast_sdp_m_line *m_line, struct ast_sdp_a_line *a_line);<br>-<br>-/*!<br>- * \brief Get the count of Attributes on a Media Description<br>- *<br>- * \param m_line Media Description<br>- *<br>- * \returns Number of Attributes<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_m_get_a_count(const struct ast_sdp_m_line *m_line);<br>-<br>-/*!<br>- * \brief Get an Attribute from a Media Description<br>- *<br>- * \param m_line Media Description<br>- * \param index Attribute index<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \since 15<br>- */<br>-struct ast_sdp_a_line *ast_sdp_m_get_a(const struct ast_sdp_m_line *m_line, int index);<br>-<br>-/*!<br>- * \brief Add a Payload to a Media Description<br>- *<br>- * \param m_line Media Description<br>- * \param payload Payload<br>- *<br>- * \retval 0 Success<br>- * \retval non-0 Failure<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_m_add_payload(struct ast_sdp_m_line *m_line,<br>- struct ast_sdp_payload *payload);<br>-<br>-/*!<br>- * \brief Get the count of Payloads on a Media Description<br>- *<br>- * \param m_line Media Description<br>- *<br>- * \returns Number of Attributes<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_m_get_payload_count(const struct ast_sdp_m_line *m_line);<br>-<br>-/*!<br>- * \brief Get a Payload from a Media Description<br>- *<br>- * \param m_line Media Description<br>- * \param index Payload index<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \since 15<br>- */<br>-struct ast_sdp_payload *ast_sdp_m_get_payload(const struct ast_sdp_m_line *m_line, int index);<br>-<br>-/*!<br>- * \brief Add a Format to a Media Description<br>- *<br>- * \param m_line Media Description<br>- * \param options SDP Options<br>- * \param rtp_code rtp_code from ast_rtp_codecs_payload_code<br>- * \param asterisk_format True if the value in format is to be used.<br>- * \param format Format<br>- * \param code from AST_RTP list<br>- *<br>- * \retval 0 Success<br>- * \retval non-0 Failure<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_m_add_format(struct ast_sdp_m_line *m_line, const struct ast_sdp_options *options,<br>- int rtp_code, int asterisk_format, const struct ast_format *format, int code);<br>-<br>-/*!<br>- * \brief Create an SDP<br>- *<br>- * \param o_line Origin<br>- * \param c_line Connection<br>- * \param s_line Session<br>- * \param t_line Timing<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \since 15<br>- */<br>-struct ast_sdp *ast_sdp_alloc(struct ast_sdp_o_line *o_line,<br>- struct ast_sdp_c_line *c_line, struct ast_sdp_s_line *s_line,<br>- struct ast_sdp_t_line *t_line);<br>-<br>-/*!<br>- * \brief Find the first attribute match index in the top-level SDP<br>- *<br>- * \note This will not search within streams for the given attribute.<br>- *<br>- * \param sdp The SDP in which to search<br>- * \param attr_name The name of the attribute to search for<br>- * \param payload Optional payload number to search for. If irrelevant, set to -1<br>- *<br>- * \retval index of attribute line on success.<br>- * \retval -1 on failure or not found.<br>- *<br>- * \since 15.0.0<br>- */<br>-int ast_sdp_find_a_first(const struct ast_sdp *sdp, const char *attr_name, int payload);<br>-<br>-/*!<br>- * \brief Find the next attribute match index in the top-level SDP<br>- *<br>- * \note This will not search within streams for the given attribute.<br>- *<br>- * \param sdp The SDP in which to search<br>- * \param last The last matching index found<br>- * \param attr_name The name of the attribute to search for<br>- * \param payload Optional payload number to search for. If irrelevant, set to -1<br>- *<br>- * \retval index of attribute line on success.<br>- * \retval -1 on failure or not found.<br>- *<br>- * \since 15.0.0<br>- */<br>-int ast_sdp_find_a_next(const struct ast_sdp *sdp, int last, const char *attr_name, int payload);<br>-<br>-/*!<br>- * \brief Find an attribute in the top-level SDP<br>- *<br>- * \note This will not search within streams for the given attribute.<br>- *<br>- * \param sdp The SDP in which to search<br>- * \param attr_name The name of the attribute to search for<br>- * \param payload Optional payload number to search for. If irrelevant, set to -1<br>- *<br>- * \retval NULL Could not find the given attribute<br>- * \retval Non-NULL The attribute to find<br>- *<br>- * \since 15.0.0<br>- */<br>-struct ast_sdp_a_line *ast_sdp_find_attribute(const struct ast_sdp *sdp,<br>- const char *attr_name, int payload);<br>-<br>-/*!<br>- * \brief Find the first attribute match index in an SDP stream (m-line)<br>- *<br>- * \param m_line The SDP m-line in which to search<br>- * \param attr_name The name of the attribute to search for<br>- * \param payload Optional payload number to search for. If irrelevant, set to -1<br>- *<br>- * \retval index of attribute line on success.<br>- * \retval -1 on failure or not found.<br>- *<br>- * \since 15.0.0<br>- */<br>-int ast_sdp_m_find_a_first(const struct ast_sdp_m_line *m_line, const char *attr_name,<br>- int payload);<br>-<br>-/*!<br>- * \brief Find the next attribute match index in an SDP stream (m-line)<br>- *<br>- * \param m_line The SDP m-line in which to search<br>- * \param last The last matching index found<br>- * \param attr_name The name of the attribute to search for<br>- * \param payload Optional payload number to search for. If irrelevant, set to -1<br>- *<br>- * \retval index of attribute line on success.<br>- * \retval -1 on failure or not found.<br>- *<br>- * \since 15.0.0<br>- */<br>-int ast_sdp_m_find_a_next(const struct ast_sdp_m_line *m_line, int last,<br>- const char *attr_name, int payload);<br>-<br>-/*!<br>- * \brief Find an attribute in an SDP stream (m-line)<br>- *<br>- * \param m_line The SDP m-line in which to search<br>- * \param attr_name The name of the attribute to search for<br>- * \param payload Optional payload number to search for. If irrelevant, set to -1<br>- *<br>- * \retval NULL Could not find the given attribute<br>- * \retval Non-NULL The attribute to find<br>- *<br>- * \since 15.0.0<br>- */<br>-struct ast_sdp_a_line *ast_sdp_m_find_attribute(const struct ast_sdp_m_line *m_line,<br>- const char *attr_name, int payload);<br>-<br>-/*!<br>- * \brief Convert an SDP a_line into an rtpmap<br>- *<br>- * The returned value is heap-allocated and must be freed with<br>- * ast_sdp_rtpmap_free()<br>- *<br>- * \param a_line The SDP a_line to convert<br>- *<br>- * \retval NULL Fail<br>- * \retval non-NULL Success<br>- *<br>- * \since 15.0.0<br>- */<br>-struct ast_sdp_rtpmap *ast_sdp_a_get_rtpmap(const struct ast_sdp_a_line *a_line);<br>-<br>-<br>-/*!<br>- * \brief Allocate a new SDP rtpmap<br>- *<br>- * \param payload The RTP payload number<br>- * \param encoding_name The human-readable name for the codec<br>- * \param clock_rate The rate of the codec, in cycles per second<br>- * \param encoding_parameters Optional codec-specific parameters (such as number of channels)<br>- *<br>- * \retval NULL Fail<br>- * \retval non-NULL Success<br>- *<br>- * \since 15.0.0<br>- */<br>-struct ast_sdp_rtpmap *ast_sdp_rtpmap_alloc(int payload, const char *encoding_name,<br>- int clock_rate, const char *encoding_parameters);<br>-<br>-/*!<br>- * \brief Free an SDP rtpmap<br>- *<br>- * \since 15.0.0<br>- */<br>-void ast_sdp_rtpmap_free(struct ast_sdp_rtpmap *rtpmap);<br>-<br>-/*!<br>- * \brief Turn an SDP into a stream topology<br>- *<br>- * This traverses the m-lines of the SDP and creates a stream topology, with<br>- * each m-line corresponding to a stream in the created topology.<br>- *<br>- * \param sdp The SDP to convert<br>- * \param g726_non_standard Non-zero if G.726 is non-standard<br>- *<br>- * \retval NULL An error occurred when converting<br>- * \retval non-NULL The generated stream topology<br>- *<br>- * \since 15.0.0<br>- */<br>-struct ast_stream_topology *ast_get_topology_from_sdp(const struct ast_sdp *sdp, int g726_non_standard);<br>-#endif /* _SDP_PRIV_H */<br>diff --git a/include/asterisk/sdp_options.h b/include/asterisk/sdp_options.h<br>deleted file mode 100644<br>index b8c1bbd..0000000<br>--- a/include/asterisk/sdp_options.h<br>+++ /dev/null<br>@@ -1,550 +0,0 @@<br>-/*<br>- * Asterisk -- An open source telephony toolkit.<br>- *<br>- * Copyright (C) 2017, Digium, Inc.<br>- *<br>- * Mark Michelson <mmichelson@digium.com><br>- *<br>- * See http://www.asterisk.org for more information about<br>- * the Asterisk project. Please do not directly contact<br>- * any of the maintainers of this project for assistance;<br>- * the project provides a web site, mailing lists and IRC<br>- * channels for your use.<br>- *<br>- * This program is free software, distributed under the terms of<br>- * the GNU General Public License Version 2. See the LICENSE file<br>- * at the top of the source tree.<br>- */<br>-<br>-#ifndef _ASTERISK_SDP_OPTIONS_H<br>-#define _ASTERISK_SDP_OPTIONS_H<br>-<br>-#include "asterisk/udptl.h"<br>-<br>-struct ast_sdp_options;<br>-<br>-/*!<br>- * \brief SDP DTMF mode options<br>- */<br>-enum ast_sdp_options_dtmf {<br>- /*! No DTMF to be used */<br>- AST_SDP_DTMF_NONE,<br>- /*! Use RFC 4733 events for DTMF */<br>- AST_SDP_DTMF_RFC_4733,<br>- /*! Use DTMF in the audio stream */<br>- AST_SDP_DTMF_INBAND,<br>- /*! Use SIP 4733 if supported by the other side or INBAND if not */<br>- AST_SDP_DTMF_AUTO,<br>-};<br>-<br>-/*!<br>- * \brief ICE options<br>- *<br>- * This is an enum because it will support a TRICKLE-ICE option<br>- * in the future.<br>- */<br>-enum ast_sdp_options_ice {<br>- /*! ICE is not enabled on this session */<br>- AST_SDP_ICE_DISABLED,<br>- /*! Standard ICE is enabled on this session */<br>- AST_SDP_ICE_ENABLED_STANDARD,<br>-};<br>-<br>-/*!<br>- * \brief Implementation of the SDP<br>- *<br>- * Users of the SDP API set the implementation based on what they<br>- * natively handle. This indicates the type of SDP that the API expects<br>- * when being given an SDP, and it indicates the type of SDP that the API<br>- * returns when asked for one.<br>- */<br>-enum ast_sdp_options_impl {<br>- /*! SDP is represented as a string */<br>- AST_SDP_IMPL_STRING,<br>- /*! SDP is represented as a pjmedia_sdp_session */<br>- AST_SDP_IMPL_PJMEDIA,<br>- /*! End of the list */<br>- AST_SDP_IMPL_END,<br>-};<br>-<br>-/*!<br>- * \brief SDP encryption options<br>- */<br>-enum ast_sdp_options_encryption {<br>- /*! No encryption */<br>- AST_SDP_ENCRYPTION_DISABLED,<br>- /*! SRTP SDES encryption */<br>- AST_SDP_ENCRYPTION_SRTP_SDES,<br>- /*! DTLS encryption */<br>- AST_SDP_ENCRYPTION_DTLS,<br>-};<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Allocate a new SDP options structure.<br>- *<br>- * This will heap-allocate an SDP options structure and<br>- * initialize it to a set of default values.<br>- *<br>- * \retval NULL Allocation failure<br>- * \retval non-NULL Newly allocated SDP options<br>- */<br>-struct ast_sdp_options *ast_sdp_options_alloc(void);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Free an SDP options structure.<br>- *<br>- * \note This only needs to be called if an error occurs between<br>- * options allocation and a call to ast_sdp_state_alloc()<br>- * Otherwise, the SDP state will take care of freeing the<br>- * options for you.<br>- *<br>- * \param options The options to free<br>- */<br>-void ast_sdp_options_free(struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options media_address<br>- *<br>- * \param options SDP Options<br>- * \param media_address<br>- */<br>-void ast_sdp_options_set_media_address(struct ast_sdp_options *options,<br>- const char *media_address);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options media_address<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns media_address<br>- */<br>-const char *ast_sdp_options_get_media_address(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options interface_address<br>- *<br>- * \param options SDP Options<br>- * \param interface_address<br>- */<br>-void ast_sdp_options_set_interface_address(struct ast_sdp_options *options,<br>- const char *interface_address);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options interface_address<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns interface_address<br>- */<br>-const char *ast_sdp_options_get_interface_address(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options sdpowner<br>- *<br>- * \param options SDP Options<br>- * \param sdpowner<br>- */<br>-void ast_sdp_options_set_sdpowner(struct ast_sdp_options *options,<br>- const char *sdpowner);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options sdpowner<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns sdpowner<br>- */<br>-const char *ast_sdp_options_get_sdpowner(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options sdpsession<br>- *<br>- * \param options SDP Options<br>- * \param sdpsession<br>- */<br>-void ast_sdp_options_set_sdpsession(struct ast_sdp_options *options,<br>- const char *sdpsession);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options sdpsession<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns sdpsession<br>- */<br>-const char *ast_sdp_options_get_sdpsession(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options rtp_engine<br>- *<br>- * \param options SDP Options<br>- * \param rtp_engine<br>- */<br>-void ast_sdp_options_set_rtp_engine(struct ast_sdp_options *options,<br>- const char *rtp_engine);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options rtp_engine<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns rtp_engine<br>- */<br>-const char *ast_sdp_options_get_rtp_engine(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options rtp_symmetric<br>- *<br>- * \param options SDP Options<br>- * \param rtp_symmetric<br>- */<br>-void ast_sdp_options_set_rtp_symmetric(struct ast_sdp_options *options,<br>- unsigned int rtp_symmetric);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options rtp_symmetric<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns rtp_symmetric<br>- */<br>-unsigned int ast_sdp_options_get_rtp_symmetric(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options rtp_ipv6<br>- *<br>- * \param options SDP Options<br>- * \param rtp_ipv6<br>- */<br>-void ast_sdp_options_set_rtp_ipv6(struct ast_sdp_options *options,<br>- unsigned int rtp_ipv6);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options rtp_ipv6<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns rtp_ipv6<br>- */<br>-unsigned int ast_sdp_options_get_rtp_ipv6(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options g726_non_standard<br>- *<br>- * \param options SDP Options<br>- * \param g726_non_standard<br>- */<br>-void ast_sdp_options_set_g726_non_standard(struct ast_sdp_options *options,<br>- unsigned int g726_non_standard);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options g726_non_standard<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns g726_non_standard<br>- */<br>-unsigned int ast_sdp_options_get_g726_non_standard(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options tos_audio<br>- *<br>- * \param options SDP Options<br>- * \param tos_audio<br>- */<br>-void ast_sdp_options_set_tos_audio(struct ast_sdp_options *options,<br>- unsigned int tos_audio);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options tos_audio<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns tos_audio<br>- */<br>-unsigned int ast_sdp_options_get_tos_audio(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options cos_audio<br>- *<br>- * \param options SDP Options<br>- * \param cos_audio<br>- */<br>-void ast_sdp_options_set_cos_audio(struct ast_sdp_options *options,<br>- unsigned int cos_audio);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options cos_audio<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns cos_audio<br>- */<br>-unsigned int ast_sdp_options_get_cos_audio(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options tos_video<br>- *<br>- * \param options SDP Options<br>- * \param tos_video<br>- */<br>-void ast_sdp_options_set_tos_video(struct ast_sdp_options *options,<br>- unsigned int tos_video);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options tos_video<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns tos_video<br>- */<br>-unsigned int ast_sdp_options_get_tos_video(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options cos_video<br>- *<br>- * \param options SDP Options<br>- * \param cos_video<br>- */<br>-void ast_sdp_options_set_cos_video(struct ast_sdp_options *options,<br>- unsigned int cos_video);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options cos_video<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns cos_video<br>- */<br>-unsigned int ast_sdp_options_get_cos_video(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options dtmf<br>- *<br>- * \param options SDP Options<br>- * \param dtmf<br>- */<br>-void ast_sdp_options_set_dtmf(struct ast_sdp_options *options,<br>- enum ast_sdp_options_dtmf dtmf);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options dtmf<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns dtmf<br>- */<br>-enum ast_sdp_options_dtmf ast_sdp_options_get_dtmf(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options ice<br>- *<br>- * \param options SDP Options<br>- * \param ice<br>- */<br>-void ast_sdp_options_set_ice(struct ast_sdp_options *options,<br>- enum ast_sdp_options_ice ice);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options ice<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns ice<br>- */<br>-enum ast_sdp_options_ice ast_sdp_options_get_ice(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options impl<br>- *<br>- * \param options SDP Options<br>- * \param impl<br>- */<br>-void ast_sdp_options_set_impl(struct ast_sdp_options *options,<br>- enum ast_sdp_options_impl impl);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options impl<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns impl<br>- */<br>-enum ast_sdp_options_impl ast_sdp_options_get_impl(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options encryption<br>- *<br>- * \param options SDP Options<br>- * \param encryption<br>- */<br>-void ast_sdp_options_set_encryption(struct ast_sdp_options *options,<br>- enum ast_sdp_options_encryption encryption);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options encryption<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns encryption<br>- */<br>-enum ast_sdp_options_encryption ast_sdp_options_get_encryption(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options RTCP MUX<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns Boolean indicating if RTCP MUX is enabled.<br>- */<br>-unsigned int ast_sdp_options_get_rtcp_mux(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options RTCP MUX<br>- *<br>- * \param options SDP Options<br>- * \param value Boolean that indicates if RTCP MUX should be enabled.<br>- */<br>-void ast_sdp_options_set_rtcp_mux(struct ast_sdp_options *options, unsigned int value);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options udptl_symmetric<br>- *<br>- * \param options SDP Options<br>- * \param udptl_symmetric<br>- */<br>-void ast_sdp_options_set_udptl_symmetric(struct ast_sdp_options *options,<br>- unsigned int udptl_symmetric);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options udptl_symmetric<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns udptl_symmetric<br>- */<br>-unsigned int ast_sdp_options_get_udptl_symmetric(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options udptl_error_correction<br>- *<br>- * \param options SDP Options<br>- * \param error_correction<br>- */<br>-void ast_sdp_options_set_udptl_error_correction(struct ast_sdp_options *options,<br>- enum ast_t38_ec_modes error_correction);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options udptl_error_correction<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns udptl_error_correction<br>- */<br>-enum ast_t38_ec_modes ast_sdp_options_get_udptl_error_correction(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set SDP Options udptl_far_max_datagram<br>- *<br>- * \param options SDP Options<br>- * \param far_max_datagram<br>- */<br>-void ast_sdp_options_set_udptl_far_max_datagram(struct ast_sdp_options *options,<br>- unsigned int far_max_datagram);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options udptl_far_max_datagram<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns udptl_far_max_datagram<br>- */<br>-unsigned int ast_sdp_options_get_udptl_far_max_datagram(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Enable setting SSRC level attributes on SDPs<br>- *<br>- * \param options SDP Options<br>- * \param ssrc Boolean indicating if SSRC attributes should be included in generated SDPs<br>- */<br>-void ast_sdp_options_set_ssrc(struct ast_sdp_options *options, unsigned int ssrc);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get SDP Options ssrc<br>- *<br>- * \param options SDP Options<br>- *<br>- * \returns Whether SSRC-level attributes will be added to our SDP.<br>- */<br>-unsigned int ast_sdp_options_get_ssrc(const struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \brief Set the SDP options scheduler context used to create new streams of the type.<br>- * \since 15.0.0<br>- *<br>- * \param options SDP Options<br>- * \param type Media type the scheduler context is for.<br>- * \param sched Scheduler context to use for the specified media type.<br>- *<br>- * \return Nothing<br>- */<br>-void ast_sdp_options_set_sched_type(struct ast_sdp_options *options,<br>- enum ast_media_type type, struct ast_sched_context *sched);<br>-<br>-/*!<br>- * \brief Get the SDP options scheduler context used to create new streams of the type.<br>- * \since 15.0.0<br>- *<br>- * \param options SDP Options<br>- * \param type Media type the format cap represents.<br>- *<br>- * \return The stored scheduler context to create new streams of the type.<br>- */<br>-struct ast_sched_context *ast_sdp_options_get_sched_type(const struct ast_sdp_options *options,<br>- enum ast_media_type type);<br>-<br>-#endif /* _ASTERISK_SDP_OPTIONS_H */<br>diff --git a/include/asterisk/sdp_state.h b/include/asterisk/sdp_state.h<br>deleted file mode 100644<br>index b8209e1..0000000<br>--- a/include/asterisk/sdp_state.h<br>+++ /dev/null<br>@@ -1,266 +0,0 @@<br>-/*<br>- * Asterisk -- An open source telephony toolkit.<br>- *<br>- * Copyright (C) 2017, Digium, Inc.<br>- *<br>- * Mark Michelson <mmichelson@digium.com><br>- *<br>- * See http://www.asterisk.org for more information about<br>- * the Asterisk project. Please do not directly contact<br>- * any of the maintainers of this project for assistance;<br>- * the project provides a web site, mailing lists and IRC<br>- * channels for your use.<br>- *<br>- * This program is free software, distributed under the terms of<br>- * the GNU General Public License Version 2. See the LICENSE file<br>- * at the top of the source tree.<br>- */<br>-<br>-#ifndef _ASTERISK_SDP_STATE_H<br>-#define _ASTERISK_SDP_STATE_H<br>-<br>-#include "asterisk/stream.h"<br>-#include "asterisk/sdp_options.h"<br>-<br>-struct ast_sdp_state;<br>-struct ast_sockaddr;<br>-struct ast_udptl;<br>-struct ast_control_t38_parameters;<br>-<br>-/*!<br>- * \brief Allocate a new SDP state<br>- *<br>- * SDP state keeps tabs on everything SDP-related for a media session.<br>- * Most SDP operations will require the state to be provided.<br>- * Ownership of the SDP options is taken on by the SDP state.<br>- * A good strategy is to call this during session creation.<br>- */<br>-struct ast_sdp_state *ast_sdp_state_alloc(struct ast_stream_topology *streams,<br>- struct ast_sdp_options *options);<br>-<br>-/*!<br>- * \brief Free the SDP state.<br>- *<br>- * A good strategy is to call this during session destruction<br>- */<br>-void ast_sdp_state_free(struct ast_sdp_state *sdp_state);<br>-<br>-/*!<br>- * \brief Get the associated RTP instance for a particular stream on the SDP state.<br>- *<br>- * Stream numbers correspond to the streams in the topology of the associated channel<br>- */<br>-struct ast_rtp_instance *ast_sdp_state_get_rtp_instance(const struct ast_sdp_state *sdp_state,<br>- int stream_index);<br>-<br>-/*!<br>- * \brief Get the associated UDPTL instance for a particular stream on the SDP state.<br>- *<br>- * Stream numbers correspond to the streams in the topology of the associated channel<br>- */<br>-struct ast_udptl *ast_sdp_state_get_udptl_instance(const struct ast_sdp_state *sdp_state,<br>- int stream_index);<br>-<br>-/*!<br>- * \brief Get the global connection address on the SDP state.<br>- */<br>-const struct ast_sockaddr *ast_sdp_state_get_connection_address(const struct ast_sdp_state *sdp_state);<br>-<br>-/*!<br>- * \brief Get the connection address for a particular stream.<br>- *<br>- * \param sdp_state<br>- * \param stream_index The particular stream to get the connection address of<br>- * \param address[out] A place to store the address in<br>- *<br>- * \retval 0 Success<br>- *<br>- * \note<br>- * Stream numbers correspond to the streams in the topology of the associated channel<br>- */<br>-int ast_sdp_state_get_stream_connection_address(const struct ast_sdp_state *sdp_state,<br>- int stream_index, struct ast_sockaddr *address);<br>-<br>-/*!<br>- * \brief Get the joint negotiated streams based on local and remote capabilities.<br>- *<br>- * If this is called prior to receiving a remote SDP, then this will just mirror<br>- * the local configured endpoint capabilities.<br>- */<br>-const struct ast_stream_topology *ast_sdp_state_get_joint_topology(<br>- const struct ast_sdp_state *sdp_state);<br>-<br>-/*!<br>- * \brief Get the local topology<br>- *<br>- */<br>-const struct ast_stream_topology *ast_sdp_state_get_local_topology(<br>- const struct ast_sdp_state *sdp_state);<br>-<br>-/*!<br>- * \brief Get the sdp_state options<br>- *<br>- */<br>-const struct ast_sdp_options *ast_sdp_state_get_options(<br>- const struct ast_sdp_state *sdp_state);<br>-<br>-<br>-/*!<br>- * \brief Get the local SDP.<br>- *<br>- * \param sdp_state<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \note<br>- * This function will allocate a new SDP with RTP instances if it has not already<br>- * been allocated.<br>- *<br>- */<br>-const struct ast_sdp *ast_sdp_state_get_local_sdp(struct ast_sdp_state *sdp_state);<br>-<br>-/*!<br>- * \brief Get the local SDP Implementation.<br>- *<br>- * \param sdp_state<br>- *<br>- * \retval non-NULL Success<br>- * \retval NULL Failure<br>- *<br>- * \note<br>- * This function calls ast_sdp_state_get_local_sdp then translates it into<br>- * the defined implementation.<br>- *<br>- * The return here is const. The use case for this is so that a channel can add<br>- * the SDP to an outgoing message. The API user should not attempt to modify the SDP.<br>- * SDP modification should only be done through the API.<br>- *<br>- * \since 15<br>- */<br>-const void *ast_sdp_state_get_local_sdp_impl(struct ast_sdp_state *sdp_state);<br>-<br>-/*!<br>- * \brief Set the remote SDP<br>- *<br>- * \param sdp_state<br>- * \param sdp<br>- *<br>- * \note It is assumed that the passed in SDP has been checked for sanity<br>- * already. e.g., There are no syntax errors, a c= line is reachable for<br>- * each m= line, etc...<br>- *<br>- * \retval 0 Success<br>- * \retval non-0 Failure<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_state_set_remote_sdp(struct ast_sdp_state *sdp_state, const struct ast_sdp *sdp);<br>-<br>-/*!<br>- * \brief Set the remote SDP from an Implementation<br>- *<br>- * \param sdp_state<br>- * \param remote The implementation's representation of an SDP.<br>- *<br>- * \retval 0 Success<br>- * \retval non-0 Failure<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_state_set_remote_sdp_from_impl(struct ast_sdp_state *sdp_state, const void *remote);<br>-<br>-/*!<br>- * \brief Reset the SDP state and stream capabilities as if the SDP state had just been allocated.<br>- *<br>- * \param sdp_state<br>- * \param remote The implementation's representation of an SDP.<br>- *<br>- * \retval 0 Success<br>- *<br>- * \note<br>- * This is most useful for when a channel driver is sending a session refresh message<br>- * and needs to re-advertise its initial capabilities instead of the previously-negotiated<br>- * joint capabilities.<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_state_reset(struct ast_sdp_state *sdp_state);<br>-<br>-/*!<br>- * \brief Update the local stream topology on the SDP state.<br>- *<br>- * \param sdp_state<br>- * \param streams The new stream topology.<br>- *<br>- * \retval 0 Success<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_state_update_local_topology(struct ast_sdp_state *sdp_state, struct ast_stream_topology *streams);<br>-<br>-/*!<br>- * \brief Set the local address (IP address) to use for connection addresses<br>- *<br>- * \param sdp_state<br>- * \param address The local address<br>- *<br>- * \note<br>- * Passing NULL as an address will unset the explicit local connection address.<br>- *<br>- * \since 15<br>- */<br>-void ast_sdp_state_set_local_address(struct ast_sdp_state *sdp_state, struct ast_sockaddr *address);<br>-<br>-/*!<br>- * \brief Set the connection address (IP address and port) to use for a specific stream<br>- *<br>- * \param sdp_state<br>- * \param stream_index The stream to set the connection address for<br>- * \param address The connection address<br>- *<br>- * \retval 0 Success<br>- *<br>- * \note<br>- * Passing NULL as an address will unset the explicit local connection address.<br>- *<br>- * \since 15<br>- */<br>-int ast_sdp_state_set_connection_address(struct ast_sdp_state *sdp_state, int stream_index,<br>- struct ast_sockaddr *address);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set a stream to be held or unheld<br>- *<br>- * \param sdp_state<br>- * \param stream_index The stream to set the held value for<br>- * \param locally_held<br>- */<br>-void ast_sdp_state_set_locally_held(struct ast_sdp_state *sdp_state,<br>- int stream_index, unsigned int locally_held);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Set the UDPTL session parameters<br>- *<br>- * \param sdp_state<br>- * \param stream_index The stream to set the UDPTL session parameters for<br>- * \param params<br>- */<br>-void ast_sdp_state_set_t38_parameters(struct ast_sdp_state *sdp_state,<br>- int stream_index, struct ast_control_t38_parameters *params);<br>-<br>-/*!<br>- * \since 15.0.0<br>- * \brief Get whether a stream is held or not<br>- *<br>- * \param sdp_state<br>- * \param stream_index The stream to get the held state for<br>- *<br>- * \returns locally_held<br>- */<br>-unsigned int ast_sdp_state_get_locally_held(const struct ast_sdp_state *sdp_state,<br>- int stream_index);<br>-<br>-#endif /* _ASTERISK_SDP_STATE_H */<br>diff --git a/include/asterisk/sdp_translator.h b/include/asterisk/sdp_translator.h<br>deleted file mode 100644<br>index e1d51f0..0000000<br>--- a/include/asterisk/sdp_translator.h<br>+++ /dev/null<br>@@ -1,103 +0,0 @@<br>-/*<br>- * Asterisk -- An open source telephony toolkit.<br>- *<br>- * Copyright (C) 2017, Digium, Inc.<br>- *<br>- * Mark Michelson <mmichelson@digium.com><br>- *<br>- * See http://www.asterisk.org for more information about<br>- * the Asterisk project. Please do not directly contact<br>- * any of the maintainers of this project for assistance;<br>- * the project provides a web site, mailing lists and IRC<br>- * channels for your use.<br>- *<br>- * This program is free software, distributed under the terms of<br>- * the GNU General Public License Version 2. See the LICENSE file<br>- * at the top of the source tree.<br>- */<br>-<br>-#ifndef _ASTERISK_SDP_TRANSLATOR_H<br>-#define _ASTERISK_SDP_TRANSLATOR_H<br>-<br>-#include "asterisk/sdp_options.h"<br>-<br>-struct sdp;<br>-<br>-/*!<br>- * \brief SDP translator operations<br>- */<br>-struct ast_sdp_translator_ops {<br>- /*! The SDP representation on which this translator operates */<br>- enum ast_sdp_options_impl repr;<br>- /*! Allocate new translator private data for a translator */<br>- void *(*translator_new)(void);<br>- /*! Free translator private data */<br>- void (*translator_free)(void *translator_priv);<br>- /*! Convert the channel-native SDP into an internal Asterisk SDP */<br>- struct ast_sdp *(*to_sdp)(const void *repr_sdp, void *translator_priv);<br>- /*! Convert an internal Asterisk SDP into a channel-native SDP */<br>- const void *(*from_sdp)(const struct ast_sdp *sdp, void *translator_priv);<br>-};<br>-<br>-/*!<br>- * \brief An SDP translator<br>- *<br>- * An SDP translator is responsible for converting between Asterisk's internal<br>- * representation of an SDP and the representation that is native to the channel<br>- * driver. Translators are allocated per-use.<br>- */<br>-struct ast_sdp_translator {<br>- /*! The operations this translator uses */<br>- struct ast_sdp_translator_ops *ops;<br>- /*! Private data this translator uses */<br>- void *translator_priv;<br>-};<br>-<br>-/*!<br>- * \brief Register an SDP translator<br>- * \param ops The SDP operations defined by this translator<br>- * \retval 0 Success<br>- * \retval -1 FAIL<br>- */<br>-int ast_sdp_register_translator(struct ast_sdp_translator_ops *ops);<br>-<br>-/*!<br>- * \brief Unregister an SDP translator<br>- */<br>-void ast_sdp_unregister_translator(struct ast_sdp_translator_ops *ops);<br>-<br>-/*!<br>- * \brief Allocate a new SDP translator<br>- * \param Representation corresponding to the translator_ops to use<br>- * \retval NULL FAIL<br>- * \retval non-NULL New SDP translator<br>- */<br>-struct ast_sdp_translator *ast_sdp_translator_new(enum ast_sdp_options_impl repr);<br>-<br>-/*!<br>- * \brief Free an SDP translator<br>- */<br>-void ast_sdp_translator_free(struct ast_sdp_translator *translator);<br>-<br>-/*!<br>- * \brief Translate a native SDP to internal Asterisk SDP<br>- *<br>- * \param translator The translator to use when translating<br>- * \param native_sdp The SDP from the channel driver<br>- * \retval NULL FAIL<br>- * \retval Non-NULL The translated SDP<br>- */<br>-struct ast_sdp *ast_sdp_translator_to_sdp(struct ast_sdp_translator *translator, const void *native_sdp);<br>-<br>-/*!<br>- * \brief Translate an internal Asterisk SDP to a native SDP<br>- *<br>- * \param translator The translator to use when translating<br>- * \param ast_sdp The Asterisk SDP to translate<br>- * \retval NULL FAIL<br>- * \retval non-NULL The translated SDP<br>- */<br>-const void *ast_sdp_translator_from_sdp(struct ast_sdp_translator *translator,<br>- const struct ast_sdp *ast_sdp);<br>-<br>-#endif /* _ASTERISK_SDP_TRANSLATOR_H */<br>diff --git a/main/sdp.c b/main/sdp.c<br>deleted file mode 100644<br>index 010f9d9..0000000<br>--- a/main/sdp.c<br>+++ /dev/null<br>@@ -1,880 +0,0 @@<br>-/*<br>- * Asterisk -- An open source telephony toolkit.<br>- *<br>- * Copyright (C) 2017, Digium, Inc.<br>- *<br>- * George Joseph <gjoseph@digium.com><br>- *<br>- * See http://www.asterisk.org for more information about<br>- * the Asterisk project. Please do not directly contact<br>- * any of the maintainers of this project for assistance;<br>- * the project provides a web site, mailing lists and IRC<br>- * channels for your use.<br>- *<br>- * This program is free software, distributed under the terms of<br>- * the GNU General Public License Version 2. See the LICENSE file<br>- * at the top of the source tree.<br>- */<br>-<br>-<br>-#include "asterisk.h"<br>-#include "asterisk/utils.h"<br>-#include "asterisk/netsock2.h"<br>-#include "asterisk/codec.h"<br>-#include "asterisk/format.h"<br>-#include "asterisk/format_cap.h"<br>-#include "asterisk/format_cache.h"<br>-#include "asterisk/rtp_engine.h"<br>-#include "asterisk/sdp_state.h"<br>-#include "asterisk/sdp_options.h"<br>-#include "asterisk/sdp_translator.h"<br>-#include "asterisk/sdp.h"<br>-#include "asterisk/vector.h"<br>-#include "asterisk/utils.h"<br>-#include "asterisk/stream.h"<br>-#include "sdp_private.h"<br>-<br>-void ast_sdp_a_free(struct ast_sdp_a_line *a_line)<br>-{<br>- ast_free(a_line);<br>-}<br>-<br>-void ast_sdp_a_lines_free(struct ast_sdp_a_lines *a_lines)<br>-{<br>- if (!a_lines) {<br>- return;<br>- }<br>-<br>- AST_VECTOR_CALLBACK_VOID(a_lines, ast_sdp_a_free);<br>- AST_VECTOR_FREE(a_lines);<br>- ast_free(a_lines);<br>-}<br>-<br>-void ast_sdp_c_free(struct ast_sdp_c_line *c_line)<br>-{<br>- ast_free(c_line);<br>-}<br>-<br>-void ast_sdp_payload_free(struct ast_sdp_payload *payload)<br>-{<br>- ast_free(payload);<br>-}<br>-<br>-void ast_sdp_payloads_free(struct ast_sdp_payloads *payloads)<br>-{<br>- if (!payloads) {<br>- return;<br>- }<br>-<br>- AST_VECTOR_CALLBACK_VOID(payloads, ast_sdp_payload_free);<br>- AST_VECTOR_FREE(payloads);<br>- ast_free(payloads);<br>-}<br>-<br>-void ast_sdp_m_free(struct ast_sdp_m_line *m_line)<br>-{<br>- if (!m_line) {<br>- return;<br>- }<br>-<br>- ast_sdp_a_lines_free(m_line->a_lines);<br>- ast_sdp_payloads_free(m_line->payloads);<br>- ast_sdp_c_free(m_line->c_line);<br>- ast_free(m_line);<br>-}<br>-<br>-void ast_sdp_m_lines_free(struct ast_sdp_m_lines *m_lines)<br>-{<br>- if (!m_lines) {<br>- return;<br>- }<br>-<br>- AST_VECTOR_CALLBACK_VOID(m_lines, ast_sdp_m_free);<br>- AST_VECTOR_FREE(m_lines);<br>- ast_free(m_lines);<br>-}<br>-<br>-void ast_sdp_o_free(struct ast_sdp_o_line *o_line)<br>-{<br>- ast_free(o_line);<br>-}<br>-<br>-void ast_sdp_s_free(struct ast_sdp_s_line *s_line)<br>-{<br>- ast_free(s_line);<br>-}<br>-<br>-void ast_sdp_t_free(struct ast_sdp_t_line *t_line)<br>-{<br>- ast_free(t_line);<br>-}<br>-<br>-void ast_sdp_free(struct ast_sdp *sdp)<br>-{<br>- if (!sdp) {<br>- return;<br>- }<br>-<br>- ast_sdp_o_free(sdp->o_line);<br>- ast_sdp_s_free(sdp->s_line);<br>- ast_sdp_c_free(sdp->c_line);<br>- ast_sdp_t_free(sdp->t_line);<br>- ast_sdp_a_lines_free(sdp->a_lines);<br>- ast_sdp_m_lines_free(sdp->m_lines);<br>- ast_free(sdp);<br>-}<br>-<br>-#define COPY_STR_AND_ADVANCE(p, dest, source) \<br>-({ \<br>- dest = p; \<br>- strcpy(dest, source); \<br>- p += (strlen(source) + 1); \<br>-})<br>-<br>-struct ast_sdp_a_line *ast_sdp_a_alloc(const char *name, const char *value)<br>-{<br>- struct ast_sdp_a_line *a_line;<br>- size_t len;<br>- char *p;<br>-<br>- ast_assert(!ast_strlen_zero(name));<br>-<br>- if (ast_strlen_zero(value)) {<br>- value = "";<br>- }<br>-<br>- len = sizeof(*a_line) + strlen(name) + strlen(value) + 2;<br>- a_line = ast_calloc(1, len);<br>- if (!a_line) {<br>- return NULL;<br>- }<br>-<br>- p = ((char *)a_line) + sizeof(*a_line);<br>-<br>- COPY_STR_AND_ADVANCE(p, a_line->name, name);<br>- COPY_STR_AND_ADVANCE(p, a_line->value, value);<br>-<br>- return a_line;<br>-}<br>-<br>-struct ast_sdp_c_line *ast_sdp_c_alloc(const char *address_type, const char *address)<br>-{<br>- struct ast_sdp_c_line *c_line;<br>- size_t len;<br>- char *p;<br>-<br>- ast_assert(!ast_strlen_zero(address_type) && !ast_strlen_zero(address));<br>-<br>- len = sizeof(*c_line) + strlen(address_type) + strlen(address) + 2;<br>- c_line = ast_calloc(1, len);<br>- if (!c_line) {<br>- return NULL;<br>- }<br>-<br>- p = ((char *)c_line) + sizeof(*c_line);<br>-<br>- COPY_STR_AND_ADVANCE(p, c_line->address_type, address_type);<br>- COPY_STR_AND_ADVANCE(p, c_line->address, address);<br>-<br>- return c_line;<br>-}<br>-<br>-struct ast_sdp_payload *ast_sdp_payload_alloc(const char *fmt)<br>-{<br>- struct ast_sdp_payload *payload;<br>- size_t len;<br>-<br>- ast_assert(!ast_strlen_zero(fmt));<br>-<br>- len = sizeof(*payload) + strlen(fmt) + 1;<br>- payload = ast_calloc(1, len);<br>- if (!payload) {<br>- return NULL;<br>- }<br>-<br>- payload->fmt = ((char *)payload) + sizeof(*payload);<br>- strcpy(payload->fmt, fmt); /* Safe */<br>-<br>- return payload;<br>-}<br>-<br>-struct ast_sdp_m_line *ast_sdp_m_alloc(const char *type, uint16_t port,<br>- uint16_t port_count, const char *proto, struct ast_sdp_c_line *c_line)<br>-{<br>- struct ast_sdp_m_line *m_line;<br>- size_t len;<br>- char *p;<br>-<br>- ast_assert(!ast_strlen_zero(type) && !ast_strlen_zero(proto));<br>-<br>- len = sizeof(*m_line) + strlen(type) + strlen(proto) + 2;<br>- m_line = ast_calloc(1, len);<br>- if (!m_line) {<br>- return NULL;<br>- }<br>-<br>- m_line->a_lines = ast_calloc(1, sizeof(*m_line->a_lines));<br>- if (!m_line->a_lines) {<br>- ast_sdp_m_free(m_line);<br>- return NULL;<br>- }<br>- if (AST_VECTOR_INIT(m_line->a_lines, 20)) {<br>- ast_sdp_m_free(m_line);<br>- return NULL;<br>- }<br>-<br>- m_line->payloads = ast_calloc(1, sizeof(*m_line->payloads));<br>- if (!m_line->payloads) {<br>- ast_sdp_m_free(m_line);<br>- return NULL;<br>- }<br>- if (AST_VECTOR_INIT(m_line->payloads, 20)) {<br>- ast_sdp_m_free(m_line);<br>- return NULL;<br>- }<br>-<br>- p = ((char *)m_line) + sizeof(*m_line);<br>-<br>- COPY_STR_AND_ADVANCE(p, m_line->type, type);<br>- COPY_STR_AND_ADVANCE(p, m_line->proto, proto);<br>- m_line->port = port;<br>- m_line->port_count = port_count;<br>- m_line->c_line = c_line;<br>-<br>- return m_line;<br>-}<br>-<br>-struct ast_sdp_s_line *ast_sdp_s_alloc(const char *session_name)<br>-{<br>- struct ast_sdp_s_line *s_line;<br>- size_t len;<br>-<br>- if (ast_strlen_zero(session_name)) {<br>- session_name = " ";<br>- }<br>-<br>- len = sizeof(*s_line) + strlen(session_name) + 1;<br>- s_line = ast_calloc(1, len);<br>- if (!s_line) {<br>- return NULL;<br>- }<br>-<br>- s_line->session_name = ((char *)s_line) + sizeof(*s_line);<br>- strcpy(s_line->session_name, session_name); /* Safe */<br>-<br>- return s_line;<br>-}<br>-<br>-struct ast_sdp_t_line *ast_sdp_t_alloc(uint64_t start_time, uint64_t stop_time)<br>-{<br>- struct ast_sdp_t_line *t_line;<br>-<br>- t_line = ast_calloc(1, sizeof(*t_line));<br>- if (!t_line) {<br>- return NULL;<br>- }<br>-<br>- t_line->start_time = start_time;<br>- t_line->stop_time = stop_time;<br>-<br>- return t_line;<br>-}<br>-<br>-struct ast_sdp_o_line *ast_sdp_o_alloc(const char *username, uint64_t session_id,<br>- uint64_t session_version, const char *address_type, const char *address)<br>-{<br>- struct ast_sdp_o_line *o_line;<br>- size_t len;<br>- char *p;<br>-<br>- ast_assert(!ast_strlen_zero(username) && !ast_strlen_zero(address_type)<br>- && !ast_strlen_zero(address));<br>-<br>- len = sizeof(*o_line) + strlen(username) + strlen(address_type) + strlen(address) + 3;<br>- o_line = ast_calloc(1, len);<br>- if (!o_line) {<br>- return NULL;<br>- }<br>-<br>- o_line->session_id = session_id;<br>- o_line->session_version = session_version;<br>-<br>- p = ((char *)o_line) + sizeof(*o_line);<br>-<br>- COPY_STR_AND_ADVANCE(p, o_line->username, username);<br>- COPY_STR_AND_ADVANCE(p, o_line->address_type, address_type);<br>- COPY_STR_AND_ADVANCE(p, o_line->address, address);<br>-<br>- return o_line;<br>-}<br>-<br>-struct ast_sdp *ast_sdp_alloc(struct ast_sdp_o_line *o_line,<br>- struct ast_sdp_c_line *c_line, struct ast_sdp_s_line *s_line,<br>- struct ast_sdp_t_line *t_line)<br>-{<br>- struct ast_sdp *new_sdp;<br>-<br>- new_sdp = ast_calloc(1, sizeof *new_sdp);<br>- if (!new_sdp) {<br>- return NULL;<br>- }<br>-<br>- new_sdp->a_lines = ast_calloc(1, sizeof(*new_sdp->a_lines));<br>- if (!new_sdp->a_lines) {<br>- ast_sdp_free(new_sdp);<br>- return NULL;<br>- }<br>- if (AST_VECTOR_INIT(new_sdp->a_lines, 20)) {<br>- ast_sdp_free(new_sdp);<br>- return NULL;<br>- }<br>-<br>- new_sdp->m_lines = ast_calloc(1, sizeof(*new_sdp->m_lines));<br>- if (!new_sdp->m_lines) {<br>- ast_sdp_free(new_sdp);<br>- return NULL;<br>- }<br>- if (AST_VECTOR_INIT(new_sdp->m_lines, 20)) {<br>- ast_sdp_free(new_sdp);<br>- return NULL;<br>- }<br>-<br>- new_sdp->o_line = o_line;<br>- new_sdp->c_line = c_line;<br>- new_sdp->s_line = s_line;<br>- new_sdp->t_line = t_line;<br>-<br>- return new_sdp;<br>-}<br>-<br>-int ast_sdp_add_a(struct ast_sdp *sdp, struct ast_sdp_a_line *a_line)<br>-{<br>- ast_assert(sdp && a_line);<br>-<br>- return AST_VECTOR_APPEND(sdp->a_lines, a_line);<br>-}<br>-<br>-int ast_sdp_get_a_count(const struct ast_sdp *sdp)<br>-{<br>- ast_assert(sdp != NULL);<br>-<br>- return AST_VECTOR_SIZE(sdp->a_lines);<br>-}<br>-<br>-struct ast_sdp_a_line *ast_sdp_get_a(const struct ast_sdp *sdp, int index)<br>-{<br>- ast_assert(sdp != NULL);<br>-<br>- return AST_VECTOR_GET(sdp->a_lines, index);<br>-}<br>-<br>-int ast_sdp_add_m(struct ast_sdp *sdp, struct ast_sdp_m_line *m_line)<br>-{<br>- ast_assert(sdp && m_line);<br>-<br>- return AST_VECTOR_APPEND(sdp->m_lines, m_line);<br>-}<br>-<br>-int ast_sdp_get_m_count(const struct ast_sdp *sdp)<br>-{<br>- ast_assert(sdp != NULL);<br>-<br>- return AST_VECTOR_SIZE(sdp->m_lines);<br>-}<br>-<br>-struct ast_sdp_m_line *ast_sdp_get_m(const struct ast_sdp *sdp, int index)<br>-{<br>- ast_assert(sdp != NULL);<br>-<br>- return AST_VECTOR_GET(sdp->m_lines, index);<br>-}<br>-<br>-int ast_sdp_m_add_a(struct ast_sdp_m_line *m_line, struct ast_sdp_a_line *a_line)<br>-{<br>- ast_assert(m_line && a_line);<br>-<br>- return AST_VECTOR_APPEND(m_line->a_lines, a_line);<br>-}<br>-<br>-int ast_sdp_m_get_a_count(const struct ast_sdp_m_line *m_line)<br>-{<br>- ast_assert(m_line != NULL);<br>-<br>- return AST_VECTOR_SIZE(m_line->a_lines);<br>-}<br>-<br>-struct ast_sdp_a_line *ast_sdp_m_get_a(const struct ast_sdp_m_line *m_line, int index)<br>-{<br>- ast_assert(m_line != NULL);<br>-<br>- return AST_VECTOR_GET(m_line->a_lines, index);<br>-}<br>-<br>-int ast_sdp_m_add_payload(struct ast_sdp_m_line *m_line, struct ast_sdp_payload *payload)<br>-{<br>- ast_assert(m_line && payload);<br>-<br>- return AST_VECTOR_APPEND(m_line->payloads, payload);<br>-}<br>-<br>-int ast_sdp_m_get_payload_count(const struct ast_sdp_m_line *m_line)<br>-{<br>- ast_assert(m_line != NULL);<br>-<br>- return AST_VECTOR_SIZE(m_line->payloads);<br>-}<br>-<br>-struct ast_sdp_payload *ast_sdp_m_get_payload(const struct ast_sdp_m_line *m_line, int index)<br>-{<br>- ast_assert(m_line != NULL);<br>-<br>- return AST_VECTOR_GET(m_line->payloads, index);<br>-}<br>-<br>-static int sdp_m_add_fmtp(struct ast_sdp_m_line *m_line, const struct ast_format *format,<br>- int rtp_code)<br>-{<br>- struct ast_str *fmtp0 = ast_str_alloca(256);<br>- struct ast_sdp_a_line *a_line;<br>- char *tmp;<br>-<br>- ast_format_generate_sdp_fmtp(format, rtp_code, &fmtp0);<br>- if (ast_str_strlen(fmtp0) == 0) {<br>- /* Format doesn't have fmtp attributes */<br>- return 0;<br>- }<br>-<br>- tmp = ast_str_buffer(fmtp0) + ast_str_strlen(fmtp0) - 1;<br>- /* remove any carriage return line feeds */<br>- while (*tmp == '\r' || *tmp == '\n') --tmp;<br>- *++tmp = '\0';<br>-<br>- /*<br>- * ast...generate gives us everything, just need value<br>- *<br>- * It can also give multiple fmtp attribute lines. (silk does)<br>- */<br>- tmp = strchr(ast_str_buffer(fmtp0), ':');<br>- if (tmp && tmp[1] != '\0') {<br>- tmp++;<br>- } else {<br>- tmp = ast_str_buffer(fmtp0);<br>- }<br>-<br>- a_line = ast_sdp_a_alloc("fmtp", tmp);<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- return -1;<br>- }<br>-<br>- return 0;<br>-}<br>-<br>-static int sdp_m_add_rtpmap(struct ast_sdp_m_line *m_line,<br>- const struct ast_sdp_options *options, int rtp_code, int asterisk_format,<br>- const struct ast_format *format, int code)<br>-{<br>- char tmp[64];<br>- const char *enc_name;<br>- struct ast_sdp_payload *payload;<br>- struct ast_sdp_a_line *a_line;<br>-<br>- snprintf(tmp, sizeof(tmp), "%d", rtp_code);<br>- payload = ast_sdp_payload_alloc(tmp);<br>- if (!payload || ast_sdp_m_add_payload(m_line, payload)) {<br>- ast_sdp_payload_free(payload);<br>- return -1;<br>- }<br>-<br>- enc_name = ast_rtp_lookup_mime_subtype2(asterisk_format, format, code,<br>- options->g726_non_standard ? AST_RTP_OPT_G726_NONSTANDARD : 0);<br>-<br>- snprintf(tmp, sizeof(tmp), "%d %s/%d%s%s", rtp_code, enc_name,<br>- ast_rtp_lookup_sample_rate2(asterisk_format, format, code),<br>- strcmp(enc_name, "opus") ? "" : "/", strcmp(enc_name, "opus") ? "" : "2");<br>-<br>- a_line = ast_sdp_a_alloc("rtpmap", tmp);<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- return -1;<br>- }<br>-<br>- return 0;<br>-}<br>-<br>-int ast_sdp_m_add_format(struct ast_sdp_m_line *m_line, const struct ast_sdp_options *options,<br>- int rtp_code, int asterisk_format, const struct ast_format *format, int code)<br>-{<br>- return sdp_m_add_rtpmap(m_line, options, rtp_code, asterisk_format, format, code)<br>- || sdp_m_add_fmtp(m_line, format, rtp_code) ? -1 : 0;<br>-}<br>-<br>-static int sdp_find_a_common(const struct ast_sdp_a_lines *a_lines, int start,<br>- const char *attr_name, int payload)<br>-{<br>- struct ast_sdp_a_line *a_line;<br>- int idx;<br>-<br>- ast_assert(-1 <= start);<br>-<br>- for (idx = start + 1; idx < AST_VECTOR_SIZE(a_lines); ++idx) {<br>- int a_line_payload;<br>-<br>- a_line = AST_VECTOR_GET(a_lines, idx);<br>- if (strcmp(a_line->name, attr_name)) {<br>- continue;<br>- }<br>-<br>- if (payload >= 0) {<br>- int sscanf_res;<br>-<br>- sscanf_res = sscanf(a_line->value, "%30d", &a_line_payload);<br>- if (sscanf_res == 1 && payload == a_line_payload) {<br>- return idx;<br>- }<br>- } else {<br>- return idx;<br>- }<br>- }<br>-<br>- return -1;<br>-}<br>-<br>-int ast_sdp_find_a_first(const struct ast_sdp *sdp, const char *attr_name, int payload)<br>-{<br>- return sdp_find_a_common(sdp->a_lines, -1, attr_name, payload);<br>-}<br>-<br>-int ast_sdp_find_a_next(const struct ast_sdp *sdp, int last, const char *attr_name, int payload)<br>-{<br>- return sdp_find_a_common(sdp->a_lines, last, attr_name, payload);<br>-}<br>-<br>-struct ast_sdp_a_line *ast_sdp_find_attribute(const struct ast_sdp *sdp,<br>- const char *attr_name, int payload)<br>-{<br>- int idx;<br>-<br>- idx = ast_sdp_find_a_first(sdp, attr_name, payload);<br>- if (idx < 0) {<br>- return NULL;<br>- }<br>- return ast_sdp_get_a(sdp, idx);<br>-}<br>-<br>-int ast_sdp_m_find_a_first(const struct ast_sdp_m_line *m_line, const char *attr_name,<br>- int payload)<br>-{<br>- return sdp_find_a_common(m_line->a_lines, -1, attr_name, payload);<br>-}<br>-<br>-int ast_sdp_m_find_a_next(const struct ast_sdp_m_line *m_line, int last,<br>- const char *attr_name, int payload)<br>-{<br>- return sdp_find_a_common(m_line->a_lines, last, attr_name, payload);<br>-}<br>-<br>-struct ast_sdp_a_line *ast_sdp_m_find_attribute(const struct ast_sdp_m_line *m_line,<br>- const char *attr_name, int payload)<br>-{<br>- int idx;<br>-<br>- idx = ast_sdp_m_find_a_first(m_line, attr_name, payload);<br>- if (idx < 0) {<br>- return NULL;<br>- }<br>- return ast_sdp_m_get_a(m_line, idx);<br>-}<br>-<br>-struct ast_sdp_rtpmap *ast_sdp_rtpmap_alloc(int payload, const char *encoding_name,<br>- int clock_rate, const char *encoding_parameters)<br>-{<br>- struct ast_sdp_rtpmap *rtpmap;<br>- char *buf_pos;<br>-<br>- rtpmap = ast_calloc(1, sizeof(*rtpmap) + strlen(encoding_name) + strlen(encoding_parameters) + 2);<br>- if (!rtpmap) {<br>- return NULL;<br>- }<br>-<br>- rtpmap->payload = payload;<br>- rtpmap->clock_rate = clock_rate;<br>-<br>- buf_pos = rtpmap->buf;<br>- COPY_STR_AND_ADVANCE(buf_pos, rtpmap->encoding_name, encoding_name);<br>- COPY_STR_AND_ADVANCE(buf_pos, rtpmap->encoding_parameters, encoding_parameters);<br>-<br>- return rtpmap;<br>-}<br>-<br>-void ast_sdp_rtpmap_free(struct ast_sdp_rtpmap *rtpmap)<br>-{<br>- ast_free(rtpmap);<br>-}<br>-<br>-struct ast_sdp_rtpmap *ast_sdp_a_get_rtpmap(const struct ast_sdp_a_line *a_line)<br>-{<br>- char *value_copy;<br>- char *slash;<br>- int payload;<br>- char encoding_name[64];<br>- int clock_rate;<br>- char *encoding_parameters;<br>- struct ast_sdp_rtpmap *rtpmap;<br>- int clock_rate_len;<br>-<br>- value_copy = ast_strip(ast_strdupa(a_line->value));<br>-<br>- if (sscanf(value_copy, "%30d %63s", &payload, encoding_name) != 2) {<br>- return NULL;<br>- }<br>-<br>- slash = strchr(encoding_name, '/');<br>- if (!slash) {<br>- return NULL;<br>- }<br>- *slash++ = '\0';<br>- if (ast_strlen_zero(encoding_name)) {<br>- return NULL;<br>- }<br>- if (sscanf(slash, "%30d%n", &clock_rate, &clock_rate_len) < 1) {<br>- return NULL;<br>- }<br>-<br>- slash += clock_rate_len;<br>- if (!ast_strlen_zero(slash)) {<br>- if (*slash == '/') {<br>- *slash++ = '\0';<br>- encoding_parameters = slash;<br>- if (ast_strlen_zero(encoding_parameters)) {<br>- return NULL;<br>- }<br>- } else {<br>- return NULL;<br>- }<br>- } else {<br>- encoding_parameters = "";<br>- }<br>-<br>- rtpmap = ast_sdp_rtpmap_alloc(payload, encoding_name, clock_rate,<br>- encoding_parameters);<br>-<br>- return rtpmap;<br>-}<br>-<br>-/*!<br>- * \brief Turn an SDP attribute into an sdp_rtpmap structure<br>- *<br>- * \param m_line The media section where this attribute was found.<br>- * \param payload The RTP payload to find an rtpmap for<br>- * \param[out] rtpmap The rtpmap to fill in.<br>- * \return Zero if successful, otherwise less than zero<br>- */<br>-static struct ast_sdp_rtpmap *sdp_payload_get_rtpmap(const struct ast_sdp_m_line *m_line, int payload)<br>-{<br>- struct ast_sdp_a_line *rtpmap_attr;<br>-<br>- rtpmap_attr = ast_sdp_m_find_attribute(m_line, "rtpmap", payload);<br>- if (!rtpmap_attr) {<br>- return NULL;<br>- }<br>-<br>- return ast_sdp_a_get_rtpmap(rtpmap_attr);<br>-}<br>-<br>-static void process_fmtp_value(const char *value, int payload, struct ast_rtp_codecs *codecs)<br>-{<br>- char *param;<br>- char *param_start;<br>- char *param_end;<br>- size_t len;<br>- struct ast_format *replace;<br>- struct ast_format *format;<br>-<br>- /*<br>- * Extract the "a=fmtp:%d %s" attribute parameter string value which<br>- * starts after the colon.<br>- */<br>- param_start = ast_skip_nonblanks(value);/* Skip payload type */<br>- param_start = ast_skip_blanks(param_start);<br>- param_end = ast_skip_nonblanks(param_start);<br>- if (param_end == param_start) {<br>- /* There is no parameter string */<br>- return;<br>- }<br>- len = param_end - param_start;<br>- param = ast_alloca(len + 1);<br>- memcpy(param, param_start, len);<br>- param[len] = '\0';<br>-<br>- format = ast_rtp_codecs_get_payload_format(codecs, payload);<br>- if (!format) {<br>- return;<br>- }<br>-<br>- replace = ast_format_parse_sdp_fmtp(format, param);<br>- if (replace) {<br>- ast_rtp_codecs_payload_replace_format(codecs, payload, replace);<br>- ao2_ref(replace, -1);<br>- }<br>- ao2_ref(format, -1);<br>-}<br>-<br>-/*!<br>- * \brief Find and process all fmtp attribute lines for a given payload<br>- *<br>- * \param m_line The stream on which to search for the fmtp attributes<br>- * \param payload The specific fmtp attribute to search for<br>- * \param codecs The current RTP codecs that have been built up<br>- */<br>-static void process_fmtp_lines(const struct ast_sdp_m_line *m_line, int payload,<br>- struct ast_rtp_codecs *codecs)<br>-{<br>- const struct ast_sdp_a_line *a_line;<br>- int idx;<br>-<br>- idx = ast_sdp_m_find_a_first(m_line, "fmtp", payload);<br>- for (; 0 <= idx; idx = ast_sdp_m_find_a_next(m_line, idx, "fmtp", payload)) {<br>- a_line = ast_sdp_m_get_a(m_line, idx);<br>- ast_assert(a_line != NULL);<br>-<br>- process_fmtp_value(a_line->value, payload, codecs);<br>- }<br>-}<br>-<br>-/*<br>- * Needed so we don't have an external function referenced as data.<br>- * The dynamic linker doesn't handle that very well.<br>- */<br>-static void rtp_codecs_free(struct ast_rtp_codecs *codecs)<br>-{<br>- if (codecs) {<br>- ast_rtp_codecs_payloads_destroy(codecs);<br>- }<br>-}<br>-<br>-/*!<br>- * \brief Convert an SDP stream into an Asterisk stream<br>- *<br>- * Given an m-line from an SDP, convert it into an ast_stream structure.<br>- * This takes formats, as well as clock-rate and fmtp attributes into account.<br>- *<br>- * \param m_line The SDP media section to convert<br>- * \param g726_non_standard Non-zero if G.726 is non-standard<br>- *<br>- * \retval NULL An error occurred<br>- * \retval non-NULL The converted stream<br>- */<br>-static struct ast_stream *get_stream_from_m(const struct ast_sdp_m_line *m_line, int g726_non_standard)<br>-{<br>- int i;<br>- int non_ast_fmts;<br>- struct ast_rtp_codecs *codecs;<br>- struct ast_format_cap *caps;<br>- struct ast_stream *stream;<br>- enum ast_rtp_options options;<br>-<br>- caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);<br>- if (!caps) {<br>- return NULL;<br>- }<br>- stream = ast_stream_alloc(m_line->type, ast_media_type_from_str(m_line->type));<br>- if (!stream) {<br>- ao2_ref(caps, -1);<br>- return NULL;<br>- }<br>-<br>- switch (ast_stream_get_type(stream)) {<br>- case AST_MEDIA_TYPE_AUDIO:<br>- case AST_MEDIA_TYPE_VIDEO:<br>- codecs = ast_calloc(1, sizeof(*codecs));<br>- if (!codecs || ast_rtp_codecs_payloads_initialize(codecs)) {<br>- rtp_codecs_free(codecs);<br>- ast_stream_free(stream);<br>- ao2_ref(caps, -1);<br>- ast_free(codecs);<br>- return NULL;<br>- }<br>-<br>- options = g726_non_standard ? AST_RTP_OPT_G726_NONSTANDARD : 0;<br>- for (i = 0; i < ast_sdp_m_get_payload_count(m_line); ++i) {<br>- struct ast_sdp_payload *payload_s;<br>- struct ast_sdp_rtpmap *rtpmap;<br>- int payload;<br>-<br>- payload_s = ast_sdp_m_get_payload(m_line, i);<br>- sscanf(payload_s->fmt, "%30d", &payload);<br>-<br>- rtpmap = sdp_payload_get_rtpmap(m_line, payload);<br>- if (!rtpmap) {<br>- /* No rtpmap attribute. Try static payload type format assignment */<br>- ast_rtp_codecs_payloads_set_m_type(codecs, NULL, payload);<br>- continue;<br>- }<br>-<br>- if (!ast_rtp_codecs_payloads_set_rtpmap_type_rate(codecs, NULL, payload,<br>- m_line->type, rtpmap->encoding_name, options, rtpmap->clock_rate)) {<br>- /* Successfully mapped the payload type to format */<br>- process_fmtp_lines(m_line, payload, codecs);<br>- }<br>- ast_sdp_rtpmap_free(rtpmap);<br>- }<br>-<br>- ast_rtp_codecs_payload_formats(codecs, caps, &non_ast_fmts);<br>- ast_stream_set_data(stream, AST_STREAM_DATA_RTP_CODECS, codecs,<br>- (ast_stream_data_free_fn) rtp_codecs_free);<br>- break;<br>- case AST_MEDIA_TYPE_IMAGE:<br>- for (i = 0; i < ast_sdp_m_get_payload_count(m_line); ++i) {<br>- struct ast_sdp_payload *payload;<br>-<br>- /* As we don't carry T.38 over RTP we do our own format check */<br>- payload = ast_sdp_m_get_payload(m_line, i);<br>- if (!strcasecmp(payload->fmt, "t38")) {<br>- ast_format_cap_append(caps, ast_format_t38, 0);<br>- }<br>- }<br>- break;<br>- case AST_MEDIA_TYPE_UNKNOWN:<br>- case AST_MEDIA_TYPE_TEXT:<br>- case AST_MEDIA_TYPE_END:<br>- break;<br>- }<br>-<br>- ast_stream_set_formats(stream, caps);<br>- ao2_ref(caps, -1);<br>-<br>- return stream;<br>-}<br>-<br>-struct ast_stream_topology *ast_get_topology_from_sdp(const struct ast_sdp *sdp, int g726_non_standard)<br>-{<br>- struct ast_stream_topology *topology;<br>- int i;<br>-<br>- topology = ast_stream_topology_alloc();<br>- if (!topology) {<br>- return NULL;<br>- }<br>-<br>- for (i = 0; i < ast_sdp_get_m_count(sdp); ++i) {<br>- struct ast_stream *stream;<br>-<br>- stream = get_stream_from_m(ast_sdp_get_m(sdp, i), g726_non_standard);<br>- if (!stream) {<br>- /*<br>- * The topology cannot match the SDP because<br>- * we failed to create a corresponding stream.<br>- */<br>- ast_stream_topology_free(topology);<br>- return NULL;<br>- }<br>- if (ast_stream_topology_append_stream(topology, stream) < 0) {<br>- /* Failed to add stream to topology */<br>- ast_stream_free(stream);<br>- ast_stream_topology_free(topology);<br>- return NULL;<br>- }<br>- }<br>-<br>- return topology;<br>-}<br>diff --git a/main/sdp_options.c b/main/sdp_options.c<br>deleted file mode 100644<br>index a938583..0000000<br>--- a/main/sdp_options.c<br>+++ /dev/null<br>@@ -1,143 +0,0 @@<br>-/*<br>- * Asterisk -- An open source telephony toolkit.<br>- *<br>- * Copyright (C) 2017, Digium, Inc.<br>- *<br>- * Mark Michelson <mmichelson@digium.com><br>- *<br>- * See http://www.asterisk.org for more information about<br>- * the Asterisk project. Please do not directly contact<br>- * any of the maintainers of this project for assistance;<br>- * the project provides a web site, mailing lists and IRC<br>- * channels for your use.<br>- *<br>- * This program is free software, distributed under the terms of<br>- * the GNU General Public License Version 2. See the LICENSE file<br>- * at the top of the source tree.<br>- */<br>-<br>-#include "asterisk.h"<br>-<br>-#include "asterisk/utils.h"<br>-#include "asterisk/sdp_options.h"<br>-<br>-#include "sdp_private.h"<br>-<br>-#define DEFAULT_DTMF AST_SDP_DTMF_NONE<br>-#define DEFAULT_ICE AST_SDP_ICE_DISABLED<br>-#define DEFAULT_IMPL AST_SDP_IMPL_STRING<br>-#define DEFAULT_ENCRYPTION AST_SDP_ENCRYPTION_DISABLED<br>-<br>-#define DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(field, assert_on_null) \<br>-void ast_sdp_options_set_##field(struct ast_sdp_options *options, const char *value) \<br>-{ \<br>- ast_assert(options != NULL); \<br>- if ((assert_on_null)) ast_assert(!ast_strlen_zero(value)); \<br>- if (!strcmp(value, options->field)) return; \<br>- ast_string_field_set(options, field, value); \<br>-} \<br>-const char *ast_sdp_options_get_##field(const struct ast_sdp_options *options) \<br>-{ \<br>- ast_assert(options != NULL); \<br>- return options->field; \<br>-} \<br>-<br>-#define DEFINE_GETTERS_SETTERS_FOR(type, field) \<br>-void ast_sdp_options_set_##field(struct ast_sdp_options *options, type value) \<br>-{ \<br>- ast_assert(options != NULL); \<br>- options->field = value; \<br>-} \<br>-type ast_sdp_options_get_##field(const struct ast_sdp_options *options) \<br>-{ \<br>- ast_assert(options != NULL); \<br>- return options->field; \<br>-} \<br>-<br>-DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(media_address, 0);<br>-DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(interface_address, 0);<br>-DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(sdpowner, 0);<br>-DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(sdpsession, 0);<br>-DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(rtp_engine, 0);<br>-<br>-DEFINE_GETTERS_SETTERS_FOR(unsigned int, rtp_symmetric);<br>-DEFINE_GETTERS_SETTERS_FOR(unsigned int, udptl_symmetric);<br>-DEFINE_GETTERS_SETTERS_FOR(enum ast_t38_ec_modes, udptl_error_correction);<br>-DEFINE_GETTERS_SETTERS_FOR(unsigned int, udptl_far_max_datagram);<br>-DEFINE_GETTERS_SETTERS_FOR(unsigned int, rtp_ipv6);<br>-DEFINE_GETTERS_SETTERS_FOR(unsigned int, g726_non_standard);<br>-DEFINE_GETTERS_SETTERS_FOR(unsigned int, rtcp_mux);<br>-DEFINE_GETTERS_SETTERS_FOR(unsigned int, tos_audio);<br>-DEFINE_GETTERS_SETTERS_FOR(unsigned int, cos_audio);<br>-DEFINE_GETTERS_SETTERS_FOR(unsigned int, tos_video);<br>-DEFINE_GETTERS_SETTERS_FOR(unsigned int, cos_video);<br>-DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_dtmf, dtmf);<br>-DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_ice, ice);<br>-DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_impl, impl);<br>-DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_encryption, encryption);<br>-DEFINE_GETTERS_SETTERS_FOR(unsigned int, ssrc);<br>-<br>-struct ast_sched_context *ast_sdp_options_get_sched_type(const struct ast_sdp_options *options, enum ast_media_type type)<br>-{<br>- struct ast_sched_context *sched = NULL;<br>-<br>- switch (type) {<br>- case AST_MEDIA_TYPE_AUDIO:<br>- case AST_MEDIA_TYPE_VIDEO:<br>- case AST_MEDIA_TYPE_IMAGE:<br>- case AST_MEDIA_TYPE_TEXT:<br>- sched = options->sched[type];<br>- break;<br>- case AST_MEDIA_TYPE_UNKNOWN:<br>- case AST_MEDIA_TYPE_END:<br>- break;<br>- }<br>- return sched;<br>-}<br>-<br>-void ast_sdp_options_set_sched_type(struct ast_sdp_options *options, enum ast_media_type type, struct ast_sched_context *sched)<br>-{<br>- switch (type) {<br>- case AST_MEDIA_TYPE_AUDIO:<br>- case AST_MEDIA_TYPE_VIDEO:<br>- case AST_MEDIA_TYPE_IMAGE:<br>- case AST_MEDIA_TYPE_TEXT:<br>- options->sched[type] = sched;<br>- break;<br>- case AST_MEDIA_TYPE_UNKNOWN:<br>- case AST_MEDIA_TYPE_END:<br>- break;<br>- }<br>-}<br>-<br>-static void set_defaults(struct ast_sdp_options *options)<br>-{<br>- options->dtmf = DEFAULT_DTMF;<br>- options->ice = DEFAULT_ICE;<br>- options->impl = DEFAULT_IMPL;<br>- options->encryption = DEFAULT_ENCRYPTION;<br>-}<br>-<br>-struct ast_sdp_options *ast_sdp_options_alloc(void)<br>-{<br>- struct ast_sdp_options *options;<br>-<br>- options = ast_calloc(1, sizeof(*options));<br>- if (!options) {<br>- return NULL;<br>- }<br>-<br>- if (ast_string_field_init(options, 256)) {<br>- ast_free(options);<br>- return NULL;<br>- }<br>-<br>- set_defaults(options);<br>- return options;<br>-}<br>-<br>-void ast_sdp_options_free(struct ast_sdp_options *options)<br>-{<br>- ast_string_field_free_memory(options);<br>- ast_free(options);<br>-}<br>diff --git a/main/sdp_private.h b/main/sdp_private.h<br>deleted file mode 100644<br>index 62228a5..0000000<br>--- a/main/sdp_private.h<br>+++ /dev/null<br>@@ -1,63 +0,0 @@<br>-/*<br>- * Asterisk -- An open source telephony toolkit.<br>- *<br>- * Copyright (C) 2017, Digium, Inc.<br>- *<br>- * Mark Michelson <mmichelson@digium.com><br>- *<br>- * See http://www.asterisk.org for more information about<br>- * the Asterisk project. Please do not directly contact<br>- * any of the maintainers of this project for assistance;<br>- * the project provides a web site, mailing lists and IRC<br>- * channels for your use.<br>- *<br>- * This program is free software, distributed under the terms of<br>- * the GNU General Public License Version 2. See the LICENSE file<br>- * at the top of the source tree.<br>- */<br>-<br>-#ifndef _MAIN_SDP_PRIVATE_H<br>-#define _MAIN_SDP_PRIVATE_H<br>-<br>-#include "asterisk/stringfields.h"<br>-#include "asterisk/sdp_options.h"<br>-<br>-struct ast_sdp_options {<br>- AST_DECLARE_STRING_FIELDS(<br>- /*! Media address to use in SDP */<br>- AST_STRING_FIELD(media_address);<br>- /*! Optional address of the interface media should use. */<br>- AST_STRING_FIELD(interface_address);<br>- /*! SDP origin username */<br>- AST_STRING_FIELD(sdpowner);<br>- /*! SDP session name */<br>- AST_STRING_FIELD(sdpsession);<br>- /*! RTP Engine Name */<br>- AST_STRING_FIELD(rtp_engine);<br>- );<br>- /*! Scheduler context for the media stream types (Mainly for RTP) */<br>- struct ast_sched_context *sched[AST_MEDIA_TYPE_END];<br>- struct {<br>- unsigned int rtp_symmetric:1;<br>- unsigned int udptl_symmetric:1;<br>- unsigned int rtp_ipv6:1;<br>- unsigned int g726_non_standard:1;<br>- unsigned int locally_held:1;<br>- unsigned int rtcp_mux:1;<br>- unsigned int ssrc:1;<br>- };<br>- struct {<br>- unsigned int tos_audio;<br>- unsigned int cos_audio;<br>- unsigned int tos_video;<br>- unsigned int cos_video;<br>- unsigned int udptl_far_max_datagram;<br>- };<br>- enum ast_sdp_options_dtmf dtmf;<br>- enum ast_sdp_options_ice ice;<br>- enum ast_sdp_options_impl impl;<br>- enum ast_sdp_options_encryption encryption;<br>- enum ast_t38_ec_modes udptl_error_correction;<br>-};<br>-<br>-#endif /* _MAIN_SDP_PRIVATE_H */<br>diff --git a/main/sdp_srtp.c b/main/sdp_srtp.c<br>deleted file mode 100644<br>index b2ae234..0000000<br>--- a/main/sdp_srtp.c<br>+++ /dev/null<br>@@ -1,137 +0,0 @@<br>-/*<br>- * Asterisk -- An open source telephony toolkit.<br>- *<br>- * Copyright (C) 2006 - 2007, Mikael Magnusson<br>- *<br>- * Mikael Magnusson <mikma@users.sourceforge.net><br>- *<br>- * See http://www.asterisk.org for more information about<br>- * the Asterisk project. Please do not directly contact<br>- * any of the maintainers of this project for assistance;<br>- * the project provides a web site, mailing lists and IRC<br>- * channels for your use.<br>- *<br>- * This program is free software, distributed under the terms of<br>- * the GNU General Public License Version 2. See the LICENSE file<br>- * at the top of the source tree.<br>- */<br>-<br>-/*! \file<br>- *<br>- * \brief SRTP and SDP Security descriptions<br>- *<br>- * Specified in RFC 3711, 6188, 7714, and 4568<br>- *<br>- * \author Mikael Magnusson <mikma@users.sourceforge.net><br>- */<br>-<br>-/*** MODULEINFO<br>- <support_level>core</support_level><br>- ***/<br>-<br>-#include "asterisk.h"<br>-<br>-#include "asterisk/linkedlists.h" /* for AST_LIST_NEXT, etc */<br>-#include "asterisk/logger.h" /* for ast_log, LOG_ERROR, etc */<br>-#include "asterisk/sdp_srtp.h" /* for ast_sdp_srtp, etc */<br>-<br>-/*! Registered SDP crypto API */<br>-static struct ast_sdp_crypto_api *sdp_crypto_api;<br>-<br>-struct ast_sdp_srtp *ast_sdp_srtp_alloc(void)<br>-{<br>- if (!ast_rtp_engine_srtp_is_registered()) {<br>- ast_debug(1, "No SRTP module loaded, can't setup SRTP session.\n");<br>- return NULL;<br>- }<br>-<br>- return ast_calloc(1, sizeof(struct ast_sdp_srtp));<br>-}<br>-<br>-void ast_sdp_srtp_destroy(struct ast_sdp_srtp *srtp)<br>-{<br>- struct ast_sdp_srtp *next;<br>-<br>- for (next = AST_LIST_NEXT(srtp, sdp_srtp_list);<br>- srtp;<br>- srtp = next, next = srtp ? AST_LIST_NEXT(srtp, sdp_srtp_list) : NULL) {<br>- ast_sdp_crypto_destroy(srtp->crypto);<br>- srtp->crypto = NULL;<br>- ast_free(srtp);<br>- }<br>-}<br>-<br>-void ast_sdp_crypto_destroy(struct ast_sdp_crypto *crypto)<br>-{<br>- if (sdp_crypto_api) {<br>- sdp_crypto_api->dtor(crypto);<br>- }<br>-}<br>-<br>-struct ast_sdp_crypto *ast_sdp_crypto_alloc(void)<br>-{<br>- if (!sdp_crypto_api) {<br>- return NULL;<br>- }<br>- return sdp_crypto_api->alloc();<br>-}<br>-<br>-int ast_sdp_crypto_process(struct ast_rtp_instance *rtp, struct ast_sdp_srtp *srtp, const char *attr)<br>-{<br>- if (!sdp_crypto_api) {<br>- return -1;<br>- }<br>- return sdp_crypto_api->parse_offer(rtp, srtp, attr);<br>-}<br>-<br>-int ast_sdp_crypto_build_offer(struct ast_sdp_crypto *p, int taglen)<br>-{<br>- if (!sdp_crypto_api) {<br>- return -1;<br>- }<br>- return sdp_crypto_api->build_offer(p, taglen);<br>-}<br>-<br>-const char *ast_sdp_srtp_get_attrib(struct ast_sdp_srtp *srtp, int dtls_enabled, int default_taglen_32)<br>-{<br>- if (!sdp_crypto_api) {<br>- return NULL;<br>- }<br>- return sdp_crypto_api->get_attr(srtp, dtls_enabled, default_taglen_32);<br>-}<br>-<br>-char *ast_sdp_get_rtp_profile(unsigned int sdes_active, struct ast_rtp_instance *instance, unsigned int using_avpf,<br>- unsigned int force_avp)<br>-{<br>- struct ast_rtp_engine_dtls *dtls;<br>-<br>- if ((dtls = ast_rtp_instance_get_dtls(instance)) && dtls->active(instance)) {<br>- if (force_avp) {<br>- return using_avpf ? "RTP/SAVPF" : "RTP/SAVP";<br>- } else {<br>- return using_avpf ? "UDP/TLS/RTP/SAVPF" : "UDP/TLS/RTP/SAVP";<br>- }<br>- } else {<br>- if (using_avpf) {<br>- return sdes_active ? "RTP/SAVPF" : "RTP/AVPF";<br>- } else {<br>- return sdes_active ? "RTP/SAVP" : "RTP/AVP";<br>- }<br>- }<br>-}<br>-<br>-int ast_sdp_crypto_register(struct ast_sdp_crypto_api *api)<br>-{<br>- if (sdp_crypto_api) {<br>- return -1;<br>- }<br>- sdp_crypto_api = api;<br>- return 0;<br>-}<br>-<br>-void ast_sdp_crypto_unregister(struct ast_sdp_crypto_api *api)<br>-{<br>- if (sdp_crypto_api == api) {<br>- sdp_crypto_api = NULL;<br>- }<br>-}<br>diff --git a/main/sdp_state.c b/main/sdp_state.c<br>deleted file mode 100644<br>index 522c876..0000000<br>--- a/main/sdp_state.c<br>+++ /dev/null<br>@@ -1,1810 +0,0 @@<br>-/*<br>- * Asterisk -- An open source telephony toolkit.<br>- *<br>- * Copyright (C) 2017, Digium, Inc.<br>- *<br>- * Mark Michelson <mmichelson@digium.com><br>- *<br>- * See http://www.asterisk.org for more information about<br>- * the Asterisk project. Please do not directly contact<br>- * any of the maintainers of this project for assistance;<br>- * the project provides a web site, mailing lists and IRC<br>- * channels for your use.<br>- *<br>- * This program is free software, distributed under the terms of<br>- * the GNU General Public License Version 2. See the LICENSE file<br>- * at the top of the source tree.<br>- */<br>-<br>-#include "asterisk.h"<br>-#include "asterisk/sdp_state.h"<br>-#include "asterisk/sdp_options.h"<br>-#include "asterisk/sdp_translator.h"<br>-#include "asterisk/vector.h"<br>-#include "asterisk/utils.h"<br>-#include "asterisk/netsock2.h"<br>-#include "asterisk/rtp_engine.h"<br>-#include "asterisk/format.h"<br>-#include "asterisk/format_cap.h"<br>-#include "asterisk/config.h"<br>-#include "asterisk/codec.h"<br>-#include "asterisk/udptl.h"<br>-<br>-#include "asterisk/sdp.h"<br>-#include "asterisk/stream.h"<br>-<br>-#include "sdp_private.h"<br>-<br>-enum ast_sdp_role {<br>- /*!<br>- * \brief The role has not yet been determined.<br>- *<br>- * When the SDP state is allocated, this is the starting role.<br>- * Similarly, when the SDP state is reset, the role is reverted<br>- * to this.<br>- */<br>- SDP_ROLE_NOT_SET,<br>- /*!<br>- * \brief We are the offerer.<br>- *<br>- * If a local SDP is requested before a remote SDP has been set, then<br>- * we assume the role of offerer. This means that we will generate an<br>- * SDP from the local capabilities and configured options.<br>- */<br>- SDP_ROLE_OFFERER,<br>- /*!<br>- * \brief We are the answerer.<br>- *<br>- * If a remote SDP is set before a local SDP is requested, then we<br>- * assume the role of answerer. This means that we will generate an<br>- * SDP based on a merge of the remote capabilities and our local capabilities.<br>- */<br>- SDP_ROLE_ANSWERER,<br>-};<br>-<br>-typedef int (*state_fn)(struct ast_sdp_state *state);<br>-<br>-struct sdp_state_rtp {<br>- /*! The underlying RTP instance */<br>- struct ast_rtp_instance *instance;<br>-};<br>-<br>-struct sdp_state_udptl {<br>- /*! The underlying UDPTL instance */<br>- struct ast_udptl *instance;<br>-};<br>-<br>-struct sdp_state_stream {<br>- /*! Type of the stream */<br>- enum ast_media_type type;<br>- union {<br>- /*! The underlying RTP instance */<br>- struct sdp_state_rtp *rtp;<br>- /*! The underlying UDPTL instance */<br>- struct sdp_state_udptl *udptl;<br>- };<br>- /*! An explicit connection address for this stream */<br>- struct ast_sockaddr connection_address;<br>- /*! Whether this stream is held or not */<br>- unsigned int locally_held;<br>- /*! UDPTL session parameters */<br>- struct ast_control_t38_parameters t38_local_params;<br>-};<br>-<br>-static void sdp_state_rtp_destroy(void *obj)<br>-{<br>- struct sdp_state_rtp *rtp = obj;<br>-<br>- if (rtp->instance) {<br>- ast_rtp_instance_stop(rtp->instance);<br>- ast_rtp_instance_destroy(rtp->instance);<br>- }<br>-}<br>-<br>-static void sdp_state_udptl_destroy(void *obj)<br>-{<br>- struct sdp_state_udptl *udptl = obj;<br>-<br>- if (udptl->instance) {<br>- ast_udptl_destroy(udptl->instance);<br>- }<br>-}<br>-<br>-static void sdp_state_stream_free(struct sdp_state_stream *state_stream)<br>-{<br>- switch (state_stream->type) {<br>- case AST_MEDIA_TYPE_AUDIO:<br>- case AST_MEDIA_TYPE_VIDEO:<br>- ao2_cleanup(state_stream->rtp);<br>- break;<br>- case AST_MEDIA_TYPE_IMAGE:<br>- ao2_cleanup(state_stream->udptl);<br>- break;<br>- case AST_MEDIA_TYPE_UNKNOWN:<br>- case AST_MEDIA_TYPE_TEXT:<br>- case AST_MEDIA_TYPE_END:<br>- break;<br>- }<br>- ast_free(state_stream);<br>-}<br>-<br>-AST_VECTOR(sdp_state_streams, struct sdp_state_stream *);<br>-<br>-struct sdp_state_capabilities {<br>- /*! Stream topology */<br>- struct ast_stream_topology *topology;<br>- /*! Additional information about the streams */<br>- struct sdp_state_streams streams;<br>- /*! An explicit global connection address */<br>- struct ast_sockaddr connection_address;<br>-};<br>-<br>-static void sdp_state_capabilities_free(struct sdp_state_capabilities *capabilities)<br>-{<br>- if (!capabilities) {<br>- return;<br>- }<br>-<br>- ast_stream_topology_free(capabilities->topology);<br>- AST_VECTOR_CALLBACK_VOID(&capabilities->streams, sdp_state_stream_free);<br>- AST_VECTOR_FREE(&capabilities->streams);<br>- ast_free(capabilities);<br>-}<br>-<br>-/*! \brief Internal function which creates an RTP instance */<br>-static struct sdp_state_rtp *create_rtp(const struct ast_sdp_options *options,<br>- enum ast_media_type media_type)<br>-{<br>- struct sdp_state_rtp *rtp;<br>- struct ast_rtp_engine_ice *ice;<br>- static struct ast_sockaddr address_rtp;<br>- struct ast_sockaddr *media_address = &address_rtp;<br>-<br>- if (!ast_strlen_zero(options->interface_address)) {<br>- if (!ast_sockaddr_parse(&address_rtp, options->interface_address, 0)) {<br>- ast_log(LOG_ERROR, "Attempted to bind RTP to invalid media address: %s\n",<br>- options->interface_address);<br>- return NULL;<br>- }<br>- } else {<br>- if (ast_check_ipv6()) {<br>- ast_sockaddr_parse(&address_rtp, "::", 0);<br>- } else {<br>- ast_sockaddr_parse(&address_rtp, "0.0.0.0", 0);<br>- }<br>- }<br>-<br>- rtp = ao2_alloc_options(sizeof(*rtp), sdp_state_rtp_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);<br>- if (!rtp) {<br>- return NULL;<br>- }<br>-<br>- rtp->instance = ast_rtp_instance_new(options->rtp_engine,<br>- ast_sdp_options_get_sched_type(options, media_type), media_address, NULL);<br>- if (!rtp->instance) {<br>- ast_log(LOG_ERROR, "Unable to create RTP instance using RTP engine '%s'\n",<br>- options->rtp_engine);<br>- ao2_ref(rtp, -1);<br>- return NULL;<br>- }<br>-<br>- ast_rtp_instance_set_prop(rtp->instance, AST_RTP_PROPERTY_RTCP,<br>- AST_RTP_INSTANCE_RTCP_STANDARD);<br>- ast_rtp_instance_set_prop(rtp->instance, AST_RTP_PROPERTY_NAT,<br>- options->rtp_symmetric);<br>-<br>- if (options->ice == AST_SDP_ICE_DISABLED<br>- && (ice = ast_rtp_instance_get_ice(rtp->instance))) {<br>- ice->stop(rtp->instance);<br>- }<br>-<br>- if (options->dtmf == AST_SDP_DTMF_RFC_4733 || options->dtmf == AST_SDP_DTMF_AUTO) {<br>- ast_rtp_instance_dtmf_mode_set(rtp->instance, AST_RTP_DTMF_MODE_RFC2833);<br>- ast_rtp_instance_set_prop(rtp->instance, AST_RTP_PROPERTY_DTMF, 1);<br>- } else if (options->dtmf == AST_SDP_DTMF_INBAND) {<br>- ast_rtp_instance_dtmf_mode_set(rtp->instance, AST_RTP_DTMF_MODE_INBAND);<br>- }<br>-<br>- switch (media_type) {<br>- case AST_MEDIA_TYPE_AUDIO:<br>- if (options->tos_audio || options->cos_audio) {<br>- ast_rtp_instance_set_qos(rtp->instance, options->tos_audio,<br>- options->cos_audio, "SIP RTP Audio");<br>- }<br>- break;<br>- case AST_MEDIA_TYPE_VIDEO:<br>- if (options->tos_video || options->cos_video) {<br>- ast_rtp_instance_set_qos(rtp->instance, options->tos_video,<br>- options->cos_video, "SIP RTP Video");<br>- }<br>- break;<br>- case AST_MEDIA_TYPE_IMAGE:<br>- case AST_MEDIA_TYPE_TEXT:<br>- case AST_MEDIA_TYPE_UNKNOWN:<br>- case AST_MEDIA_TYPE_END:<br>- break;<br>- }<br>-<br>- ast_rtp_instance_set_last_rx(rtp->instance, time(NULL));<br>-<br>- return rtp;<br>-}<br>-<br>-/*! \brief Internal function which creates a UDPTL instance */<br>-static struct sdp_state_udptl *create_udptl(const struct ast_sdp_options *options)<br>-{<br>- struct sdp_state_udptl *udptl;<br>- static struct ast_sockaddr address_udptl;<br>- struct ast_sockaddr *media_address = &address_udptl;<br>-<br>- if (!ast_strlen_zero(options->interface_address)) {<br>- if (!ast_sockaddr_parse(&address_udptl, options->interface_address, 0)) {<br>- ast_log(LOG_ERROR, "Attempted to bind UDPTL to invalid media address: %s\n",<br>- options->interface_address);<br>- return NULL;<br>- }<br>- } else {<br>- if (ast_check_ipv6()) {<br>- ast_sockaddr_parse(&address_udptl, "::", 0);<br>- } else {<br>- ast_sockaddr_parse(&address_udptl, "0.0.0.0", 0);<br>- }<br>- }<br>-<br>- udptl = ao2_alloc_options(sizeof(*udptl), sdp_state_udptl_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);<br>- if (!udptl) {<br>- return NULL;<br>- }<br>-<br>- udptl->instance = ast_udptl_new_with_bindaddr(NULL, NULL, 0, media_address);<br>- if (!udptl->instance) {<br>- ao2_ref(udptl, -1);<br>- return NULL;<br>- }<br>-<br>- ast_udptl_set_error_correction_scheme(udptl->instance, ast_sdp_options_get_udptl_error_correction(options));<br>- ast_udptl_setnat(udptl->instance, ast_sdp_options_get_udptl_symmetric(options));<br>- ast_udptl_set_far_max_datagram(udptl->instance, ast_sdp_options_get_udptl_far_max_datagram(options));<br>-<br>- return udptl;<br>-}<br>-<br>-static struct sdp_state_capabilities *sdp_initialize_state_capabilities(const struct ast_stream_topology *topology,<br>- const struct ast_sdp_options *options)<br>-{<br>- struct sdp_state_capabilities *capabilities;<br>- int i;<br>-<br>- capabilities = ast_calloc(1, sizeof(*capabilities));<br>- if (!capabilities) {<br>- return NULL;<br>- }<br>-<br>- capabilities->topology = ast_stream_topology_clone(topology);<br>- if (!capabilities->topology) {<br>- sdp_state_capabilities_free(capabilities);<br>- return NULL;<br>- }<br>-<br>- if (AST_VECTOR_INIT(&capabilities->streams, ast_stream_topology_get_count(topology))) {<br>- sdp_state_capabilities_free(capabilities);<br>- return NULL;<br>- }<br>- ast_sockaddr_setnull(&capabilities->connection_address);<br>-<br>- for (i = 0; i < ast_stream_topology_get_count(topology); ++i) {<br>- struct sdp_state_stream *state_stream;<br>-<br>- state_stream = ast_calloc(1, sizeof(*state_stream));<br>- if (!state_stream) {<br>- sdp_state_capabilities_free(capabilities);<br>- return NULL;<br>- }<br>-<br>- state_stream->type = ast_stream_get_type(ast_stream_topology_get_stream(topology, i));<br>- switch (state_stream->type) {<br>- case AST_MEDIA_TYPE_AUDIO:<br>- case AST_MEDIA_TYPE_VIDEO:<br>- state_stream->rtp = create_rtp(options, state_stream->type);<br>- if (!state_stream->rtp) {<br>- sdp_state_stream_free(state_stream);<br>- sdp_state_capabilities_free(capabilities);<br>- return NULL;<br>- }<br>- break;<br>- case AST_MEDIA_TYPE_IMAGE:<br>- state_stream->udptl = create_udptl(options);<br>- if (!state_stream->udptl) {<br>- sdp_state_stream_free(state_stream);<br>- sdp_state_capabilities_free(capabilities);<br>- return NULL;<br>- }<br>- break;<br>- case AST_MEDIA_TYPE_UNKNOWN:<br>- case AST_MEDIA_TYPE_TEXT:<br>- case AST_MEDIA_TYPE_END:<br>- ast_assert(0);<br>- sdp_state_stream_free(state_stream);<br>- sdp_state_capabilities_free(capabilities);<br>- return NULL;<br>- }<br>-<br>- if (AST_VECTOR_APPEND(&capabilities->streams, state_stream)) {<br>- sdp_state_stream_free(state_stream);<br>- sdp_state_capabilities_free(capabilities);<br>- return NULL;<br>- }<br>- }<br>-<br>- return capabilities;<br>-}<br>-<br>-/*!<br>- * \brief SDP state, the main structure used to keep track of SDP negotiation<br>- * and settings.<br>- *<br>- * Most fields are pretty self-explanatory, but negotiated_capabilities and<br>- * proposed_capabilities could use some further explanation. When an SDP<br>- * state is allocated, a stream topology is provided that dictates the<br>- * types of streams to offer in the resultant SDP. At the time the SDP<br>- * is allocated, this topology is used to create the proposed_capabilities.<br>- *<br>- * If we are the SDP offerer, then the proposed_capabilities are what are used<br>- * to generate the SDP offer. When the SDP answer arrives, the proposed capabilities<br>- * are merged with the SDP answer to create the negotiated capabilities.<br>- *<br>- * If we are the SDP answerer, then the incoming SDP offer is merged with our<br>- * proposed capabilities to to create the negotiated capabilities. These negotiated<br>- * capabilities are what we send in our SDP answer.<br>- *<br>- * Any changes that a user of the API performs will occur on the proposed capabilities.<br>- * The negotiated capabilities are only altered based on actual SDP negotiation. This is<br>- * done so that the negotiated capabilities can be fallen back on if the proposed<br>- * capabilities run into some sort of issue.<br>- */<br>-struct ast_sdp_state {<br>- /*! Current capabilities */<br>- struct sdp_state_capabilities *negotiated_capabilities;<br>- /*! Proposed capabilities */<br>- struct sdp_state_capabilities *proposed_capabilities;<br>- /*! Local SDP. Generated via the options and currently negotiated/proposed capabilities. */<br>- struct ast_sdp *local_sdp;<br>- /*! SDP options. Configured options beyond media capabilities. */<br>- struct ast_sdp_options *options;<br>- /*! Translator that puts SDPs into the expected representation */<br>- struct ast_sdp_translator *translator;<br>- /*! The role that we occupy in SDP negotiation */<br>- enum ast_sdp_role role;<br>-};<br>-<br>-struct ast_sdp_state *ast_sdp_state_alloc(struct ast_stream_topology *streams,<br>- struct ast_sdp_options *options)<br>-{<br>- struct ast_sdp_state *sdp_state;<br>-<br>- sdp_state = ast_calloc(1, sizeof(*sdp_state));<br>- if (!sdp_state) {<br>- return NULL;<br>- }<br>-<br>- sdp_state->options = options;<br>-<br>- sdp_state->translator = ast_sdp_translator_new(ast_sdp_options_get_impl(sdp_state->options));<br>- if (!sdp_state->translator) {<br>- ast_sdp_state_free(sdp_state);<br>- return NULL;<br>- }<br>-<br>- sdp_state->proposed_capabilities = sdp_initialize_state_capabilities(streams, options);<br>- if (!sdp_state->proposed_capabilities) {<br>- ast_sdp_state_free(sdp_state);<br>- return NULL;<br>- }<br>-<br>- sdp_state->role = SDP_ROLE_NOT_SET;<br>-<br>- return sdp_state;<br>-}<br>-<br>-void ast_sdp_state_free(struct ast_sdp_state *sdp_state)<br>-{<br>- if (!sdp_state) {<br>- return;<br>- }<br>-<br>- sdp_state_capabilities_free(sdp_state->negotiated_capabilities);<br>- sdp_state_capabilities_free(sdp_state->proposed_capabilities);<br>- ast_sdp_free(sdp_state->local_sdp);<br>- ast_sdp_options_free(sdp_state->options);<br>- ast_sdp_translator_free(sdp_state->translator);<br>- ast_free(sdp_state);<br>-}<br>-<br>-static struct sdp_state_stream *sdp_state_get_stream(const struct ast_sdp_state *sdp_state, int stream_index)<br>-{<br>- if (stream_index >= AST_VECTOR_SIZE(&sdp_state->proposed_capabilities->streams)) {<br>- return NULL;<br>- }<br>-<br>- return AST_VECTOR_GET(&sdp_state->proposed_capabilities->streams, stream_index);<br>-}<br>-<br>-struct ast_rtp_instance *ast_sdp_state_get_rtp_instance(<br>- const struct ast_sdp_state *sdp_state, int stream_index)<br>-{<br>- struct sdp_state_stream *stream_state;<br>-<br>- ast_assert(sdp_state != NULL);<br>- ast_assert(ast_stream_get_type(ast_stream_topology_get_stream(sdp_state->proposed_capabilities->topology,<br>- stream_index)) == AST_MEDIA_TYPE_AUDIO || ast_stream_get_type(ast_stream_topology_get_stream(<br>- sdp_state->proposed_capabilities->topology, stream_index)) == AST_MEDIA_TYPE_VIDEO);<br>-<br>- stream_state = sdp_state_get_stream(sdp_state, stream_index);<br>- if (!stream_state || !stream_state->rtp) {<br>- return NULL;<br>- }<br>-<br>- return stream_state->rtp->instance;<br>-}<br>-<br>-struct ast_udptl *ast_sdp_state_get_udptl_instance(<br>- const struct ast_sdp_state *sdp_state, int stream_index)<br>-{<br>- struct sdp_state_stream *stream_state;<br>-<br>- ast_assert(sdp_state != NULL);<br>- ast_assert(ast_stream_get_type(ast_stream_topology_get_stream(sdp_state->proposed_capabilities->topology,<br>- stream_index)) == AST_MEDIA_TYPE_IMAGE);<br>-<br>- stream_state = sdp_state_get_stream(sdp_state, stream_index);<br>- if (!stream_state || !stream_state->udptl) {<br>- return NULL;<br>- }<br>-<br>- return stream_state->udptl->instance;<br>-}<br>-<br>-const struct ast_sockaddr *ast_sdp_state_get_connection_address(const struct ast_sdp_state *sdp_state)<br>-{<br>- ast_assert(sdp_state != NULL);<br>-<br>- return &sdp_state->proposed_capabilities->connection_address;<br>-}<br>-<br>-int ast_sdp_state_get_stream_connection_address(const struct ast_sdp_state *sdp_state,<br>- int stream_index, struct ast_sockaddr *address)<br>-{<br>- struct sdp_state_stream *stream_state;<br>-<br>- ast_assert(sdp_state != NULL);<br>- ast_assert(address != NULL);<br>-<br>- stream_state = sdp_state_get_stream(sdp_state, stream_index);<br>- if (!stream_state) {<br>- return -1;<br>- }<br>-<br>- /* If an explicit connection address has been provided for the stream return it */<br>- if (!ast_sockaddr_isnull(&stream_state->connection_address)) {<br>- ast_sockaddr_copy(address, &stream_state->connection_address);<br>- return 0;<br>- }<br>-<br>- switch (ast_stream_get_type(ast_stream_topology_get_stream(sdp_state->proposed_capabilities->topology,<br>- stream_index))) {<br>- case AST_MEDIA_TYPE_AUDIO:<br>- case AST_MEDIA_TYPE_VIDEO:<br>- ast_rtp_instance_get_local_address(stream_state->rtp->instance, address);<br>- break;<br>- case AST_MEDIA_TYPE_IMAGE:<br>- ast_udptl_get_us(stream_state->udptl->instance, address);<br>- break;<br>- case AST_MEDIA_TYPE_UNKNOWN:<br>- case AST_MEDIA_TYPE_TEXT:<br>- case AST_MEDIA_TYPE_END:<br>- return -1;<br>- }<br>-<br>- /* If an explicit global connection address is set use it here for the IP part */<br>- if (!ast_sockaddr_isnull(&sdp_state->proposed_capabilities->connection_address)) {<br>- int port = ast_sockaddr_port(address);<br>-<br>- ast_sockaddr_copy(address, &sdp_state->proposed_capabilities->connection_address);<br>- ast_sockaddr_set_port(address, port);<br>- }<br>-<br>- return 0;<br>-}<br>-<br>-const struct ast_stream_topology *ast_sdp_state_get_joint_topology(<br>- const struct ast_sdp_state *sdp_state)<br>-{<br>- ast_assert(sdp_state != NULL);<br>-<br>- if (sdp_state->negotiated_capabilities) {<br>- return sdp_state->negotiated_capabilities->topology;<br>- }<br>-<br>- return sdp_state->proposed_capabilities->topology;<br>-}<br>-<br>-const struct ast_stream_topology *ast_sdp_state_get_local_topology(<br>- const struct ast_sdp_state *sdp_state)<br>-{<br>- ast_assert(sdp_state != NULL);<br>-<br>- return sdp_state->proposed_capabilities->topology;<br>-}<br>-<br>-const struct ast_sdp_options *ast_sdp_state_get_options(<br>- const struct ast_sdp_state *sdp_state)<br>-{<br>- ast_assert(sdp_state != NULL);<br>-<br>- return sdp_state->options;<br>-}<br>-<br>-/*!<br>- * \brief Merge two streams into a joint stream.<br>- *<br>- * \param local Our local stream<br>- * \param remote A remote stream<br>- *<br>- * \retval NULL An error occurred<br>- * \retval non-NULL The joint stream created<br>- */<br>-static struct ast_stream *merge_streams(const struct ast_stream *local,<br>- const struct ast_stream *remote)<br>-{<br>- struct ast_stream *joint_stream;<br>- struct ast_format_cap *joint_cap;<br>- struct ast_format_cap *local_cap;<br>- struct ast_format_cap *remote_cap;<br>- struct ast_str *local_buf = ast_str_alloca(128);<br>- struct ast_str *remote_buf = ast_str_alloca(128);<br>- struct ast_str *joint_buf = ast_str_alloca(128);<br>-<br>- joint_stream = ast_stream_alloc(ast_codec_media_type2str(ast_stream_get_type(remote)),<br>- ast_stream_get_type(remote));<br>- if (!joint_stream) {<br>- return NULL;<br>- }<br>-<br>- joint_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);<br>- if (!joint_cap) {<br>- ast_stream_free(joint_stream);<br>- return NULL;<br>- }<br>-<br>- local_cap = ast_stream_get_formats(local);<br>- remote_cap = ast_stream_get_formats(remote);<br>-<br>- ast_format_cap_get_compatible(local_cap, remote_cap, joint_cap);<br>-<br>- ast_debug(3, "Combined local '%s' with remote '%s' to get joint '%s'. Joint has %zu formats\n",<br>- ast_format_cap_get_names(local_cap, &local_buf),<br>- ast_format_cap_get_names(remote_cap, &remote_buf),<br>- ast_format_cap_get_names(joint_cap, &joint_buf),<br>- ast_format_cap_count(joint_cap));<br>-<br>- ast_stream_set_formats(joint_stream, joint_cap);<br>-<br>- ao2_ref(joint_cap, -1);<br>-<br>- return joint_stream;<br>-}<br>-<br>-/*!<br>- * \brief Get a local stream that corresponds with a remote stream.<br>- *<br>- * \param local The local topology<br>- * \param media_type The type of stream we are looking for<br>- * \param[in,out] media_indices Keeps track of where to start searching in the topology<br>- *<br>- * \retval -1 No corresponding stream found<br>- * \retval index The corresponding stream index<br>- */<br>-static int get_corresponding_index(const struct ast_stream_topology *local,<br>- enum ast_media_type media_type, int *media_indices)<br>-{<br>- int i;<br>-<br>- for (i = media_indices[media_type]; i < ast_stream_topology_get_count(local); ++i) {<br>- struct ast_stream *candidate;<br>-<br>- candidate = ast_stream_topology_get_stream(local, i);<br>- if (ast_stream_get_type(candidate) == media_type) {<br>- media_indices[media_type] = i + 1;<br>- return i;<br>- }<br>- }<br>-<br>- /* No stream of the type left in the topology */<br>- media_indices[media_type] = i;<br>- return -1;<br>-}<br>-<br>-/*!<br>- * XXX TODO The merge_capabilities() function needs to be split into<br>- * merging for new local topologies and new remote topologies. Also<br>- * the possibility of changing the stream types needs consideration.<br>- * Audio to video may or may not need us to keep the same RTP instance<br>- * because the stream position is still RTP. A new RTP instance would<br>- * cause us to change ports. Audio to image is definitely going to<br>- * happen for T.38.<br>- *<br>- * A new remote topology as an initial offer needs to dictate the<br>- * number of streams and the order. As a sdp_state option we may<br>- * allow creation of new active streams not defined by the current<br>- * local topology. A subsequent remote offer can change the stream<br>- * types and add streams. The sdp_state option could regulate<br>- * creation of new active streams here as well. An answer cannot<br>- * change stream types or the number of streams but can decline<br>- * streams. Any attempt to do so should report an error and possibly<br>- * disconnect the call.<br>- *<br>- * A local topology update needs to be merged differently. It cannot<br>- * reduce the number of streams already defined without violating the<br>- * SDP RFC. The local merge could take the new topology stream<br>- * verbatim and add declined streams to fill out any shortfall with<br>- * the exiting topology. This strategy is needed if we want to change<br>- * an audio stream to an image stream for T.38 fax and vice versa.<br>- * The local merge could take the new topology and map the streams to<br>- * the existing local topology. The new topology stream format caps<br>- * would be copied into the merged topology so we could change what<br>- * codecs are negotiated.<br>- */<br>-/*!<br>- * \brief Merge existing stream capabilities and a new topology into joint capabilities.<br>- *<br>- * \param sdp_state The state needing capabilities merged<br>- * \param new_topology The new topology to base merged capabilities on<br>- * \param is_local If new_topology is a local update.<br>- *<br>- * \details<br>- * This is a bit complicated. The idea is that we already have some<br>- * capabilities set, and we've now been confronted with a new stream<br>- * topology. We want to take what's been presented to us and merge<br>- * those new capabilities with our own.<br>- *<br>- * For each of the new streams, we try to find a corresponding stream<br>- * in our proposed capabilities. If we find one, then we get the<br>- * compatible formats of the two streams and create a new stream with<br>- * those formats set. We then will re-use the underlying media<br>- * instance (such as an RTP instance) on this merged stream.<br>- *<br>- * The is_local parameter determines whether we should attempt to<br>- * create new media instances. If we do not find a corresponding<br>- * stream, then we create a new one. If the is_local parameter is<br>- * true, this created stream is made a clone of the new stream, and a<br>- * media instance is created. If the is_local parameter is not true,<br>- * then the created stream has no formats set and no media instance is<br>- * created for it.<br>- *<br>- * \retval NULL An error occurred<br>- * \retval non-NULL The merged capabilities<br>- */<br>-static struct sdp_state_capabilities *merge_capabilities(const struct ast_sdp_state *sdp_state,<br>- const struct ast_stream_topology *new_topology, int is_local)<br>-{<br>- const struct sdp_state_capabilities *local = sdp_state->proposed_capabilities;<br>- struct sdp_state_capabilities *joint_capabilities;<br>- int media_indices[AST_MEDIA_TYPE_END] = {0};<br>- int i;<br>- static const char dummy_name[] = "dummy";<br>-<br>- ast_assert(local != NULL);<br>-<br>- joint_capabilities = ast_calloc(1, sizeof(*joint_capabilities));<br>- if (!joint_capabilities) {<br>- return NULL;<br>- }<br>-<br>- joint_capabilities->topology = ast_stream_topology_alloc();<br>- if (!joint_capabilities->topology) {<br>- goto fail;<br>- }<br>-<br>- if (AST_VECTOR_INIT(&joint_capabilities->streams, AST_VECTOR_SIZE(&local->streams))) {<br>- goto fail;<br>- }<br>- ast_sockaddr_copy(&joint_capabilities->connection_address, &local->connection_address);<br>-<br>- for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {<br>- enum ast_media_type new_stream_type;<br>- struct ast_stream *new_stream;<br>- struct ast_stream *local_stream;<br>- struct ast_stream *joint_stream;<br>- struct sdp_state_stream *joint_state_stream;<br>- int local_index;<br>-<br>- joint_state_stream = ast_calloc(1, sizeof(*joint_state_stream));<br>- if (!joint_state_stream) {<br>- goto fail;<br>- }<br>-<br>- new_stream = ast_stream_topology_get_stream(new_topology, i);<br>- new_stream_type = ast_stream_get_type(new_stream);<br>-<br>- local_index = get_corresponding_index(local->topology, new_stream_type, media_indices);<br>- if (0 <= local_index) {<br>- local_stream = ast_stream_topology_get_stream(local->topology, local_index);<br>- if (!strcmp(ast_stream_get_name(local_stream), dummy_name)) {<br>- /* The local stream is a non-exixtent dummy stream. */<br>- local_stream = NULL;<br>- }<br>- } else {<br>- local_stream = NULL;<br>- }<br>- if (local_stream) {<br>- struct sdp_state_stream *local_state_stream;<br>- struct ast_rtp_codecs *codecs;<br>-<br>- if (is_local) {<br>- /* Replace the local stream with the new local stream. */<br>- joint_stream = ast_stream_clone(new_stream, NULL);<br>- } else {<br>- joint_stream = merge_streams(local_stream, new_stream);<br>- }<br>- if (!joint_stream) {<br>- sdp_state_stream_free(joint_state_stream);<br>- goto fail;<br>- }<br>-<br>- local_state_stream = AST_VECTOR_GET(&local->streams, local_index);<br>- joint_state_stream->type = local_state_stream->type;<br>-<br>- switch (joint_state_stream->type) {<br>- case AST_MEDIA_TYPE_AUDIO:<br>- case AST_MEDIA_TYPE_VIDEO:<br>- joint_state_stream->rtp = ao2_bump(local_state_stream->rtp);<br>- if (is_local) {<br>- break;<br>- }<br>- codecs = ast_stream_get_data(new_stream, AST_STREAM_DATA_RTP_CODECS);<br>- ast_assert(codecs != NULL);<br>- if (sdp_state->role == SDP_ROLE_ANSWERER) {<br>- /*<br>- * Setup rx payload type mapping to prefer the mapping<br>- * from the peer that the RFC says we SHOULD use.<br>- */<br>- ast_rtp_codecs_payloads_xover(codecs, codecs, NULL);<br>- }<br>- ast_rtp_codecs_payloads_copy(codecs,<br>- ast_rtp_instance_get_codecs(joint_state_stream->rtp->instance),<br>- joint_state_stream->rtp->instance);<br>- break;<br>- case AST_MEDIA_TYPE_IMAGE:<br>- joint_state_stream->udptl = ao2_bump(local_state_stream->udptl);<br>- joint_state_stream->t38_local_params = local_state_stream->t38_local_params;<br>- break;<br>- case AST_MEDIA_TYPE_UNKNOWN:<br>- case AST_MEDIA_TYPE_TEXT:<br>- case AST_MEDIA_TYPE_END:<br>- break;<br>- }<br>-<br>- if (!ast_sockaddr_isnull(&local_state_stream->connection_address)) {<br>- ast_sockaddr_copy(&joint_state_stream->connection_address,<br>- &local_state_stream->connection_address);<br>- } else {<br>- ast_sockaddr_setnull(&joint_state_stream->connection_address);<br>- }<br>- joint_state_stream->locally_held = local_state_stream->locally_held;<br>- } else if (is_local) {<br>- /* We don't have a stream state that corresponds to the stream in the new topology, so<br>- * create a stream state as appropriate.<br>- */<br>- joint_stream = ast_stream_clone(new_stream, NULL);<br>- if (!joint_stream) {<br>- sdp_state_stream_free(joint_state_stream);<br>- goto fail;<br>- }<br>-<br>- switch (new_stream_type) {<br>- case AST_MEDIA_TYPE_AUDIO:<br>- case AST_MEDIA_TYPE_VIDEO:<br>- joint_state_stream->rtp = create_rtp(sdp_state->options,<br>- new_stream_type);<br>- if (!joint_state_stream->rtp) {<br>- ast_stream_free(joint_stream);<br>- sdp_state_stream_free(joint_state_stream);<br>- goto fail;<br>- }<br>- break;<br>- case AST_MEDIA_TYPE_IMAGE:<br>- joint_state_stream->udptl = create_udptl(sdp_state->options);<br>- if (!joint_state_stream->udptl) {<br>- ast_stream_free(joint_stream);<br>- sdp_state_stream_free(joint_state_stream);<br>- goto fail;<br>- }<br>- break;<br>- case AST_MEDIA_TYPE_UNKNOWN:<br>- case AST_MEDIA_TYPE_TEXT:<br>- case AST_MEDIA_TYPE_END:<br>- break;<br>- }<br>- ast_sockaddr_setnull(&joint_state_stream->connection_address);<br>- joint_state_stream->locally_held = 0;<br>- } else {<br>- /* We don't have a stream that corresponds to the stream in the new topology. Create a<br>- * dummy stream to go in its place so that the resulting SDP created will contain<br>- * the stream but will have no port or codecs set<br>- */<br>- joint_stream = ast_stream_alloc(dummy_name, new_stream_type);<br>- if (!joint_stream) {<br>- sdp_state_stream_free(joint_state_stream);<br>- goto fail;<br>- }<br>- }<br>-<br>- if (ast_stream_topology_append_stream(joint_capabilities->topology, joint_stream) < 0) {<br>- ast_stream_free(joint_stream);<br>- sdp_state_stream_free(joint_state_stream);<br>- goto fail;<br>- }<br>- if (AST_VECTOR_APPEND(&joint_capabilities->streams, joint_state_stream)) {<br>- sdp_state_stream_free(joint_state_stream);<br>- goto fail;<br>- }<br>- }<br>-<br>- return joint_capabilities;<br>-<br>-fail:<br>- sdp_state_capabilities_free(joint_capabilities);<br>- return NULL;<br>-}<br>-<br>-/*!<br>- * \brief Apply remote SDP's ICE information to our RTP session<br>- *<br>- * \param state The SDP state on which negotiation has taken place<br>- * \param options The SDP options we support<br>- * \param remote_sdp The SDP we most recently received<br>- * \param remote_m_line The stream on which we are examining ICE candidates<br>- */<br>-static void update_ice(const struct ast_sdp_state *state, struct ast_rtp_instance *rtp, const struct ast_sdp_options *options,<br>- const struct ast_sdp *remote_sdp, const struct ast_sdp_m_line *remote_m_line)<br>-{<br>- struct ast_rtp_engine_ice *ice;<br>- const struct ast_sdp_a_line *attr;<br>- const struct ast_sdp_a_line *attr_rtcp_mux;<br>- unsigned int attr_i;<br>-<br>- /* If ICE support is not enabled or available exit early */<br>- if (ast_sdp_options_get_ice(options) != AST_SDP_ICE_ENABLED_STANDARD || !(ice = ast_rtp_instance_get_ice(rtp))) {<br>- return;<br>- }<br>-<br>- attr = ast_sdp_m_find_attribute(remote_m_line, "ice-ufrag", -1);<br>- if (!attr) {<br>- attr = ast_sdp_find_attribute(remote_sdp, "ice-ufrag", -1);<br>- }<br>- if (attr) {<br>- ice->set_authentication(rtp, attr->value, NULL);<br>- } else {<br>- return;<br>- }<br>-<br>- attr = ast_sdp_m_find_attribute(remote_m_line, "ice-pwd", -1);<br>- if (!attr) {<br>- attr = ast_sdp_find_attribute(remote_sdp, "ice-pwd", -1);<br>- }<br>- if (attr) {<br>- ice->set_authentication(rtp, NULL, attr->value);<br>- } else {<br>- return;<br>- }<br>-<br>- if (ast_sdp_find_attribute(remote_sdp, "ice-lite", -1)) {<br>- ice->ice_lite(rtp);<br>- }<br>-<br>- attr_rtcp_mux = ast_sdp_m_find_attribute(remote_m_line, "rtcp-mux", -1);<br>-<br>- /* Find all of the candidates */<br>- for (attr_i = 0; attr_i < ast_sdp_m_get_a_count(remote_m_line); ++attr_i) {<br>- char foundation[32];<br>- char transport[32];<br>- char address[INET6_ADDRSTRLEN + 1];<br>- char cand_type[6];<br>- char relay_address[INET6_ADDRSTRLEN + 1] = "";<br>- unsigned int port;<br>- unsigned int relay_port = 0;<br>- struct ast_rtp_engine_ice_candidate candidate = { 0, };<br>-<br>- attr = ast_sdp_m_get_a(remote_m_line, attr_i);<br>-<br>- /* If this is not a candidate line skip it */<br>- if (strcmp(attr->name, "candidate")) {<br>- continue;<br>- }<br>-<br>- if (sscanf(attr->value, "%31s %30u %31s %30u %46s %30u typ %5s %*s %23s %*s %30u",<br>- foundation, &candidate.id, transport, (unsigned *)&candidate.priority, address,<br>- &port, cand_type, relay_address, &relay_port) < 7) {<br>- /* Candidate did not parse properly */<br>- continue;<br>- }<br>-<br>- if (candidate.id > 1<br>- && attr_rtcp_mux<br>- && ast_sdp_options_get_rtcp_mux(options)) {<br>- /* Remote side may have offered RTP and RTCP candidates. However, if we're using RTCP MUX,<br>- * then we should ignore RTCP candidates.<br>- */<br>- continue;<br>- }<br>-<br>- candidate.foundation = foundation;<br>- candidate.transport = transport;<br>-<br>- ast_sockaddr_parse(&candidate.address, address, PARSE_PORT_FORBID);<br>- ast_sockaddr_set_port(&candidate.address, port);<br>-<br>- if (!strcasecmp(cand_type, "host")) {<br>- candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_HOST;<br>- } else if (!strcasecmp(cand_type, "srflx")) {<br>- candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_SRFLX;<br>- } else if (!strcasecmp(cand_type, "relay")) {<br>- candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_RELAYED;<br>- } else {<br>- continue;<br>- }<br>-<br>- if (!ast_strlen_zero(relay_address)) {<br>- ast_sockaddr_parse(&candidate.relay_address, relay_address, PARSE_PORT_FORBID);<br>- }<br>-<br>- if (relay_port) {<br>- ast_sockaddr_set_port(&candidate.relay_address, relay_port);<br>- }<br>-<br>- ice->add_remote_candidate(rtp, &candidate);<br>- }<br>-<br>- if (state->role == SDP_ROLE_OFFERER) {<br>- ice->set_role(rtp, AST_RTP_ICE_ROLE_CONTROLLING);<br>- } else {<br>- ice->set_role(rtp, AST_RTP_ICE_ROLE_CONTROLLED);<br>- }<br>-<br>- ice->start(rtp);<br>-}<br>-<br>-/*!<br>- * \brief Update RTP instances based on merged SDPs<br>- *<br>- * RTP instances, when first allocated, cannot make assumptions about what the other<br>- * side supports and thus has to go with some default behaviors. This function gets<br>- * called after we know both what we support and what the remote endpoint supports.<br>- * This way, we can update the RTP instance to reflect what is supported by both<br>- * sides.<br>- *<br>- * \param state The SDP state in which SDPs have been negotiated<br>- * \param rtp The RTP wrapper that is being updated<br>- * \param options Our locally-supported SDP options<br>- * \param remote_sdp The SDP we most recently received<br>- * \param remote_m_line The remote SDP stream that corresponds to the RTP instance we are modifying<br>- */<br>-static void update_rtp_after_merge(const struct ast_sdp_state *state,<br>- struct sdp_state_rtp *rtp,<br>- const struct ast_sdp_options *options,<br>- const struct ast_sdp *remote_sdp,<br>- const struct ast_sdp_m_line *remote_m_line)<br>-{<br>- struct ast_sdp_c_line *c_line;<br>- struct ast_sockaddr *addrs;<br>-<br>- if (!rtp) {<br>- /* This is a dummy stream */<br>- return;<br>- }<br>-<br>- c_line = remote_m_line->c_line;<br>- if (!c_line) {<br>- c_line = remote_sdp->c_line;<br>- }<br>- /*<br>- * There must be a c= line somewhere but that would be an error by<br>- * the far end that should have been caught by a validation check<br>- * before we processed the SDP.<br>- */<br>- ast_assert(c_line != NULL);<br>-<br>- if (ast_sockaddr_resolve(&addrs, c_line->address, PARSE_PORT_FORBID, AST_AF_UNSPEC) > 0) {<br>- /* Apply connection information to the RTP instance */<br>- ast_sockaddr_set_port(addrs, remote_m_line->port);<br>- ast_rtp_instance_set_remote_address(rtp->instance, addrs);<br>- ast_free(addrs);<br>- }<br>-<br>- if (ast_sdp_options_get_rtcp_mux(options)<br>- && ast_sdp_m_find_attribute(remote_m_line, "rtcp-mux", -1)) {<br>- ast_rtp_instance_set_prop(rtp->instance, AST_RTP_PROPERTY_RTCP,<br>- AST_RTP_INSTANCE_RTCP_MUX);<br>- } else {<br>- ast_rtp_instance_set_prop(rtp->instance, AST_RTP_PROPERTY_RTCP,<br>- AST_RTP_INSTANCE_RTCP_STANDARD);<br>- }<br>-<br>- update_ice(state, rtp->instance, options, remote_sdp, remote_m_line);<br>-}<br>-<br>-/*!<br>- * \brief Update UDPTL instances based on merged SDPs<br>- *<br>- * UDPTL instances, when first allocated, cannot make assumptions about what the other<br>- * side supports and thus has to go with some default behaviors. This function gets<br>- * called after we know both what we support and what the remote endpoint supports.<br>- * This way, we can update the UDPTL instance to reflect what is supported by both<br>- * sides.<br>- *<br>- * \param state The SDP state in which SDPs have been negotiated<br>- * \param udptl The UDPTL instance that is being updated<br>- * \param options Our locally-supported SDP options<br>- * \param remote_sdp The SDP we most recently received<br>- * \param remote_m_line The remote SDP stream that corresponds to the RTP instance we are modifying<br>- */<br>-static void update_udptl_after_merge(const struct ast_sdp_state *state, struct sdp_state_udptl *udptl,<br>- const struct ast_sdp_options *options,<br>- const struct ast_sdp *remote_sdp,<br>- const struct ast_sdp_m_line *remote_m_line)<br>-{<br>- struct ast_sdp_a_line *a_line;<br>- struct ast_sdp_c_line *c_line;<br>- unsigned int fax_max_datagram;<br>- struct ast_sockaddr *addrs;<br>-<br>- if (!udptl) {<br>- /* This is a dummy stream */<br>- return;<br>- }<br>-<br>- a_line = ast_sdp_m_find_attribute(remote_m_line, "t38faxmaxdatagram", -1);<br>- if (!a_line) {<br>- a_line = ast_sdp_m_find_attribute(remote_m_line, "t38maxdatagram", -1);<br>- }<br>- if (a_line && !ast_sdp_options_get_udptl_far_max_datagram(options) &&<br>- (sscanf(a_line->value, "%30u", &fax_max_datagram) == 1)) {<br>- ast_udptl_set_far_max_datagram(udptl->instance, fax_max_datagram);<br>- }<br>-<br>- a_line = ast_sdp_m_find_attribute(remote_m_line, "t38faxudpec", -1);<br>- if (a_line) {<br>- if (!strcasecmp(a_line->value, "t38UDPRedundancy")) {<br>- ast_udptl_set_error_correction_scheme(udptl->instance, UDPTL_ERROR_CORRECTION_REDUNDANCY);<br>- } else if (!strcasecmp(a_line->value, "t38UDPFEC")) {<br>- ast_udptl_set_error_correction_scheme(udptl->instance, UDPTL_ERROR_CORRECTION_FEC);<br>- } else {<br>- ast_udptl_set_error_correction_scheme(udptl->instance, UDPTL_ERROR_CORRECTION_NONE);<br>- }<br>- }<br>-<br>- c_line = remote_m_line->c_line;<br>- if (!c_line) {<br>- c_line = remote_sdp->c_line;<br>- }<br>- /*<br>- * There must be a c= line somewhere but that would be an error by<br>- * the far end that should have been caught by a validation check<br>- * before we processed the SDP.<br>- */<br>- ast_assert(c_line != NULL);<br>-<br>- if (ast_sockaddr_resolve(&addrs, c_line->address, PARSE_PORT_FORBID, AST_AF_UNSPEC) > 0) {<br>- /* Apply connection information to the UDPTL instance */<br>- ast_sockaddr_set_port(addrs, remote_m_line->port);<br>- ast_udptl_set_peer(udptl->instance, addrs);<br>- ast_free(addrs);<br>- }<br>-}<br>-<br>-static void set_negotiated_capabilities(struct ast_sdp_state *sdp_state,<br>- struct sdp_state_capabilities *new_capabilities)<br>-{<br>- struct sdp_state_capabilities *old_capabilities = sdp_state->negotiated_capabilities;<br>-<br>- sdp_state->negotiated_capabilities = new_capabilities;<br>- sdp_state_capabilities_free(old_capabilities);<br>-}<br>-<br>-static void set_proposed_capabilities(struct ast_sdp_state *sdp_state,<br>- struct sdp_state_capabilities *new_capabilities)<br>-{<br>- struct sdp_state_capabilities *old_capabilities = sdp_state->proposed_capabilities;<br>-<br>- sdp_state->proposed_capabilities = new_capabilities;<br>- sdp_state_capabilities_free(old_capabilities);<br>-}<br>-<br>-static struct ast_sdp *sdp_create_from_state(const struct ast_sdp_state *sdp_state,<br>- const struct sdp_state_capabilities *capabilities);<br>-<br>-/*!<br>- * \brief Merge SDPs into a joint SDP.<br>- *<br>- * This function is used to take a remote SDP and merge it with our local<br>- * capabilities to produce a new local SDP. After creating the new local SDP,<br>- * it then iterates through media instances and updates them as necessary. For<br>- * instance, if a specific RTP feature is supported by both us and the far end,<br>- * then we can ensure that the feature is enabled.<br>- *<br>- * \param sdp_state The current SDP state<br>- * \retval -1 Failure<br>- * \retval 0 Success<br>- */<br>-static int merge_sdps(struct ast_sdp_state *sdp_state, const struct ast_sdp *remote_sdp)<br>-{<br>- struct sdp_state_capabilities *joint_capabilities;<br>- struct ast_stream_topology *remote_capabilities;<br>- int i;<br>-<br>- remote_capabilities = ast_get_topology_from_sdp(remote_sdp,<br>- sdp_state->options->g726_non_standard);<br>- if (!remote_capabilities) {<br>- return -1;<br>- }<br>-<br>- joint_capabilities = merge_capabilities(sdp_state, remote_capabilities, 0);<br>- ast_stream_topology_free(remote_capabilities);<br>- if (!joint_capabilities) {<br>- return -1;<br>- }<br>- set_negotiated_capabilities(sdp_state, joint_capabilities);<br>-<br>- if (sdp_state->local_sdp) {<br>- ast_sdp_free(sdp_state->local_sdp);<br>- sdp_state->local_sdp = NULL;<br>- }<br>-<br>- sdp_state->local_sdp = sdp_create_from_state(sdp_state, joint_capabilities);<br>- if (!sdp_state->local_sdp) {<br>- return -1;<br>- }<br>-<br>- for (i = 0; i < AST_VECTOR_SIZE(&joint_capabilities->streams); ++i) {<br>- struct sdp_state_stream *state_stream;<br>-<br>- state_stream = AST_VECTOR_GET(&joint_capabilities->streams, i);<br>-<br>- switch (ast_stream_get_type(ast_stream_topology_get_stream(joint_capabilities->topology, i))) {<br>- case AST_MEDIA_TYPE_AUDIO:<br>- case AST_MEDIA_TYPE_VIDEO:<br>- update_rtp_after_merge(sdp_state, state_stream->rtp, sdp_state->options,<br>- remote_sdp, ast_sdp_get_m(remote_sdp, i));<br>- break;<br>- case AST_MEDIA_TYPE_IMAGE:<br>- update_udptl_after_merge(sdp_state, state_stream->udptl, sdp_state->options,<br>- remote_sdp, ast_sdp_get_m(remote_sdp, i));<br>- break;<br>- case AST_MEDIA_TYPE_UNKNOWN:<br>- case AST_MEDIA_TYPE_TEXT:<br>- case AST_MEDIA_TYPE_END:<br>- break;<br>- }<br>- }<br>-<br>- return 0;<br>-}<br>-<br>-const struct ast_sdp *ast_sdp_state_get_local_sdp(struct ast_sdp_state *sdp_state)<br>-{<br>- ast_assert(sdp_state != NULL);<br>-<br>- if (sdp_state->role == SDP_ROLE_NOT_SET) {<br>- ast_assert(sdp_state->local_sdp == NULL);<br>- sdp_state->role = SDP_ROLE_OFFERER;<br>- sdp_state->local_sdp = sdp_create_from_state(sdp_state, sdp_state->proposed_capabilities);<br>- }<br>-<br>- return sdp_state->local_sdp;<br>-}<br>-<br>-const void *ast_sdp_state_get_local_sdp_impl(struct ast_sdp_state *sdp_state)<br>-{<br>- const struct ast_sdp *sdp = ast_sdp_state_get_local_sdp(sdp_state);<br>-<br>- if (!sdp) {<br>- return NULL;<br>- }<br>-<br>- return ast_sdp_translator_from_sdp(sdp_state->translator, sdp);<br>-}<br>-<br>-int ast_sdp_state_set_remote_sdp(struct ast_sdp_state *sdp_state, const struct ast_sdp *sdp)<br>-{<br>- ast_assert(sdp_state != NULL);<br>-<br>- if (sdp_state->role == SDP_ROLE_NOT_SET) {<br>- sdp_state->role = SDP_ROLE_ANSWERER;<br>- }<br>-<br>- return merge_sdps(sdp_state, sdp);<br>-}<br>-<br>-int ast_sdp_state_set_remote_sdp_from_impl(struct ast_sdp_state *sdp_state, const void *remote)<br>-{<br>- struct ast_sdp *sdp;<br>- int ret;<br>-<br>- ast_assert(sdp_state != NULL);<br>-<br>- sdp = ast_sdp_translator_to_sdp(sdp_state->translator, remote);<br>- if (!sdp) {<br>- return -1;<br>- }<br>- ret = ast_sdp_state_set_remote_sdp(sdp_state, sdp);<br>- ast_sdp_free(sdp);<br>- return ret;<br>-}<br>-<br>-int ast_sdp_state_reset(struct ast_sdp_state *sdp_state)<br>-{<br>- ast_assert(sdp_state != NULL);<br>-<br>- ast_sdp_free(sdp_state->local_sdp);<br>- sdp_state->local_sdp = NULL;<br>-<br>- set_proposed_capabilities(sdp_state, NULL);<br>-<br>- sdp_state->role = SDP_ROLE_NOT_SET;<br>-<br>- return 0;<br>-}<br>-<br>-int ast_sdp_state_update_local_topology(struct ast_sdp_state *sdp_state, struct ast_stream_topology *streams)<br>-{<br>- struct sdp_state_capabilities *capabilities;<br>- ast_assert(sdp_state != NULL);<br>- ast_assert(streams != NULL);<br>-<br>- capabilities = merge_capabilities(sdp_state, streams, 1);<br>- if (!capabilities) {<br>- return -1;<br>- }<br>- set_proposed_capabilities(sdp_state, capabilities);<br>-<br>- return 0;<br>-}<br>-<br>-void ast_sdp_state_set_local_address(struct ast_sdp_state *sdp_state, struct ast_sockaddr *address)<br>-{<br>- ast_assert(sdp_state != NULL);<br>-<br>- if (!address) {<br>- ast_sockaddr_setnull(&sdp_state->proposed_capabilities->connection_address);<br>- } else {<br>- ast_sockaddr_copy(&sdp_state->proposed_capabilities->connection_address, address);<br>- }<br>-}<br>-<br>-int ast_sdp_state_set_connection_address(struct ast_sdp_state *sdp_state, int stream_index,<br>- struct ast_sockaddr *address)<br>-{<br>- struct sdp_state_stream *stream_state;<br>- ast_assert(sdp_state != NULL);<br>-<br>- stream_state = sdp_state_get_stream(sdp_state, stream_index);<br>- if (!stream_state) {<br>- return -1;<br>- }<br>-<br>- if (!address) {<br>- ast_sockaddr_setnull(&stream_state->connection_address);<br>- } else {<br>- ast_sockaddr_copy(&stream_state->connection_address, address);<br>- }<br>-<br>- return 0;<br>-}<br>-<br>-void ast_sdp_state_set_locally_held(struct ast_sdp_state *sdp_state,<br>- int stream_index, unsigned int locally_held)<br>-{<br>- struct sdp_state_stream *stream_state;<br>- ast_assert(sdp_state != NULL);<br>-<br>- stream_state = sdp_state_get_stream(sdp_state, stream_index);<br>- if (!stream_state) {<br>- return;<br>- }<br>-<br>- stream_state->locally_held = locally_held;<br>-}<br>-<br>-unsigned int ast_sdp_state_get_locally_held(const struct ast_sdp_state *sdp_state,<br>- int stream_index)<br>-{<br>- struct sdp_state_stream *stream_state;<br>- ast_assert(sdp_state != NULL);<br>-<br>- stream_state = sdp_state_get_stream(sdp_state, stream_index);<br>- if (!stream_state) {<br>- return 0;<br>- }<br>-<br>- return stream_state->locally_held;<br>-}<br>-<br>-void ast_sdp_state_set_t38_parameters(struct ast_sdp_state *sdp_state,<br>- int stream_index, struct ast_control_t38_parameters *params)<br>-{<br>- struct sdp_state_stream *stream_state;<br>- ast_assert(sdp_state != NULL && params != NULL);<br>-<br>- stream_state = sdp_state_get_stream(sdp_state, stream_index);<br>- if (!stream_state) {<br>- return;<br>- }<br>-<br>- stream_state->t38_local_params = *params;<br>-}<br>-<br>-/*!<br>- * \brief Add SSRC-level attributes if appropriate.<br>- *<br>- * This function does nothing if the SDP options indicate not to add SSRC-level attributes.<br>- *<br>- * Currently, the only attribute added is cname, which is retrieved from the RTP instance.<br>- *<br>- * \param m_line The m_line on which to add the SSRC attributes<br>- * \param options Options that indicate what, if any, SSRC attributes to add<br>- * \param rtp RTP instance from which we get SSRC-level information<br>- */<br>-static void add_ssrc_attributes(struct ast_sdp_m_line *m_line, const struct ast_sdp_options *options,<br>- struct ast_rtp_instance *rtp)<br>-{<br>- struct ast_sdp_a_line *a_line;<br>- char attr_buffer[128];<br>-<br>- if (!ast_sdp_options_get_ssrc(options)) {<br>- return;<br>- }<br>-<br>- snprintf(attr_buffer, sizeof(attr_buffer), "%u cname:%s", ast_rtp_instance_get_ssrc(rtp),<br>- ast_rtp_instance_get_cname(rtp));<br>-<br>- a_line = ast_sdp_a_alloc("ssrc", attr_buffer);<br>- if (!a_line) {<br>- return;<br>- }<br>- ast_sdp_m_add_a(m_line, a_line);<br>-}<br>-<br>-static int sdp_add_m_from_rtp_stream(struct ast_sdp *sdp, const struct ast_sdp_state *sdp_state,<br>- const struct ast_sdp_options *options, const struct sdp_state_capabilities *capabilities, int stream_index)<br>-{<br>- struct ast_stream *stream;<br>- struct ast_sdp_m_line *m_line;<br>- struct ast_format_cap *caps;<br>- int i;<br>- int rtp_code;<br>- int rtp_port;<br>- int min_packet_size = 0;<br>- int max_packet_size = 0;<br>- enum ast_media_type media_type;<br>- char tmp[64];<br>- struct sdp_state_stream *stream_state;<br>- struct ast_rtp_instance *rtp;<br>- struct ast_sdp_a_line *a_line;<br>-<br>- stream = ast_stream_topology_get_stream(capabilities->topology, stream_index);<br>-<br>- ast_assert(sdp && options && stream);<br>-<br>- caps = ast_stream_get_formats(stream);<br>-<br>- stream_state = AST_VECTOR_GET(&capabilities->streams, stream_index);<br>- if (stream_state->rtp && caps && ast_format_cap_count(caps)) {<br>- rtp = stream_state->rtp->instance;<br>- } else {<br>- /* This is a disabled stream */<br>- rtp = NULL;<br>- }<br>-<br>- if (rtp) {<br>- struct ast_sockaddr address_rtp;<br>-<br>- if (ast_sdp_state_get_stream_connection_address(sdp_state, 0, &address_rtp)) {<br>- return -1;<br>- }<br>- rtp_port = ast_sockaddr_port(&address_rtp);<br>- } else {<br>- rtp_port = 0;<br>- }<br>-<br>- m_line = ast_sdp_m_alloc(<br>- ast_codec_media_type2str(ast_stream_get_type(stream)),<br>- rtp_port, 1,<br>- options->encryption != AST_SDP_ENCRYPTION_DISABLED ? "RTP/SAVP" : "RTP/AVP",<br>- NULL);<br>- if (!m_line) {<br>- return -1;<br>- }<br>-<br>- if (rtp_port) {<br>- /* Stream is not declined/disabled */<br>- for (i = 0; i < ast_format_cap_count(caps); i++) {<br>- struct ast_format *format = ast_format_cap_get_format(caps, i);<br>-<br>- rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(rtp), 1,<br>- format, 0);<br>- if (rtp_code == -1) {<br>- ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n",<br>- ast_format_get_name(format));<br>- ao2_ref(format, -1);<br>- continue;<br>- }<br>-<br>- if (ast_sdp_m_add_format(m_line, options, rtp_code, 1, format, 0)) {<br>- ast_sdp_m_free(m_line);<br>- ao2_ref(format, -1);<br>- return -1;<br>- }<br>-<br>- if (ast_format_get_maximum_ms(format)<br>- && ((ast_format_get_maximum_ms(format) < max_packet_size)<br>- || !max_packet_size)) {<br>- max_packet_size = ast_format_get_maximum_ms(format);<br>- }<br>-<br>- ao2_ref(format, -1);<br>- }<br>-<br>- media_type = ast_stream_get_type(stream);<br>- if (media_type != AST_MEDIA_TYPE_VIDEO<br>- && (options->dtmf == AST_SDP_DTMF_RFC_4733 || options->dtmf == AST_SDP_DTMF_AUTO)) {<br>- i = AST_RTP_DTMF;<br>- rtp_code = ast_rtp_codecs_payload_code(<br>- ast_rtp_instance_get_codecs(rtp), 0, NULL, i);<br>- if (-1 < rtp_code) {<br>- if (ast_sdp_m_add_format(m_line, options, rtp_code, 0, NULL, i)) {<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>-<br>- snprintf(tmp, sizeof(tmp), "%d 0-16", rtp_code);<br>- a_line = ast_sdp_a_alloc("fmtp", tmp);<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>- }<br>- }<br>-<br>- /* If ptime is set add it as an attribute */<br>- min_packet_size = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(rtp));<br>- if (!min_packet_size) {<br>- min_packet_size = ast_format_cap_get_framing(caps);<br>- }<br>- if (min_packet_size) {<br>- snprintf(tmp, sizeof(tmp), "%d", min_packet_size);<br>-<br>- a_line = ast_sdp_a_alloc("ptime", tmp);<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>- }<br>-<br>- if (max_packet_size) {<br>- snprintf(tmp, sizeof(tmp), "%d", max_packet_size);<br>- a_line = ast_sdp_a_alloc("maxptime", tmp);<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>- }<br>-<br>- a_line = ast_sdp_a_alloc(ast_sdp_state_get_locally_held(sdp_state, stream_index)<br>- ? "sendonly" : "sendrecv", "");<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>-<br>- add_ssrc_attributes(m_line, options, rtp);<br>- } else {<br>- /* Declined/disabled stream */<br>- struct ast_sdp_payload *payload;<br>- const char *fmt;<br>-<br>- /*<br>- * Add a static payload type placeholder to the declined/disabled stream.<br>- *<br>- * XXX We should use the default payload type in the received offer but<br>- * we don't have that available.<br>- */<br>- switch (ast_stream_get_type(stream)) {<br>- default:<br>- case AST_MEDIA_TYPE_AUDIO:<br>- fmt = "0"; /* ulaw */<br>- break;<br>- case AST_MEDIA_TYPE_VIDEO:<br>- fmt = "31"; /* H.261 */<br>- break;<br>- }<br>- payload = ast_sdp_payload_alloc(fmt);<br>- if (!payload || ast_sdp_m_add_payload(m_line, payload)) {<br>- ast_sdp_payload_free(payload);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>- }<br>-<br>- if (ast_sdp_add_m(sdp, m_line)) {<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>-<br>- return 0;<br>-}<br>-<br>-/*! \brief Get Max T.38 Transmission rate from T38 capabilities */<br>-static unsigned int t38_get_rate(enum ast_control_t38_rate rate)<br>-{<br>- switch (rate) {<br>- case AST_T38_RATE_2400:<br>- return 2400;<br>- case AST_T38_RATE_4800:<br>- return 4800;<br>- case AST_T38_RATE_7200:<br>- return 7200;<br>- case AST_T38_RATE_9600:<br>- return 9600;<br>- case AST_T38_RATE_12000:<br>- return 12000;<br>- case AST_T38_RATE_14400:<br>- return 14400;<br>- default:<br>- return 0;<br>- }<br>-}<br>-<br>-static int sdp_add_m_from_udptl_stream(struct ast_sdp *sdp, const struct ast_sdp_state *sdp_state,<br>- const struct ast_sdp_options *options, const struct sdp_state_capabilities *capabilities, int stream_index)<br>-{<br>- struct ast_stream *stream;<br>- struct ast_sdp_m_line *m_line;<br>- struct ast_sdp_payload *payload;<br>- char tmp[64];<br>- struct sdp_state_udptl *udptl;<br>- struct ast_sdp_a_line *a_line;<br>- struct sdp_state_stream *stream_state;<br>- int udptl_port;<br>-<br>- stream = ast_stream_topology_get_stream(capabilities->topology, stream_index);<br>-<br>- ast_assert(sdp && options && stream);<br>-<br>- stream_state = AST_VECTOR_GET(&capabilities->streams, stream_index);<br>- if (stream_state->udptl) {<br>- udptl = stream_state->udptl;<br>- } else {<br>- /* This is a disabled stream */<br>- udptl = NULL;<br>- }<br>-<br>- if (udptl) {<br>- struct ast_sockaddr address_udptl;<br>-<br>- if (ast_sdp_state_get_stream_connection_address(sdp_state, 0, &address_udptl)) {<br>- return -1;<br>- }<br>- udptl_port = ast_sockaddr_port(&address_udptl);<br>- } else {<br>- udptl_port = 0;<br>- }<br>-<br>- m_line = ast_sdp_m_alloc(<br>- ast_codec_media_type2str(ast_stream_get_type(stream)),<br>- udptl_port, 1, "udptl", NULL);<br>- if (!m_line) {<br>- return -1;<br>- }<br>-<br>- payload = ast_sdp_payload_alloc("t38");<br>- if (!payload || ast_sdp_m_add_payload(m_line, payload)) {<br>- ast_sdp_payload_free(payload);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>-<br>- if (udptl_port) {<br>- /* Stream is not declined/disabled */<br>- stream_state = sdp_state_get_stream(sdp_state, stream_index);<br>-<br>- snprintf(tmp, sizeof(tmp), "%u", stream_state->t38_local_params.version);<br>- a_line = ast_sdp_a_alloc("T38FaxVersion", tmp);<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>-<br>- snprintf(tmp, sizeof(tmp), "%u", t38_get_rate(stream_state->t38_local_params.rate));<br>- a_line = ast_sdp_a_alloc("T38FaxMaxBitRate", tmp);<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>-<br>- if (stream_state->t38_local_params.fill_bit_removal) {<br>- a_line = ast_sdp_a_alloc("T38FaxFillBitRemoval", "");<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>- }<br>-<br>- if (stream_state->t38_local_params.transcoding_mmr) {<br>- a_line = ast_sdp_a_alloc("T38FaxTranscodingMMR", "");<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>- }<br>-<br>- if (stream_state->t38_local_params.transcoding_jbig) {<br>- a_line = ast_sdp_a_alloc("T38FaxTranscodingJBIG", "");<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>- }<br>-<br>- switch (stream_state->t38_local_params.rate_management) {<br>- case AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF:<br>- a_line = ast_sdp_a_alloc("T38FaxRateManagement", "transferredTCF");<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>- break;<br>- case AST_T38_RATE_MANAGEMENT_LOCAL_TCF:<br>- a_line = ast_sdp_a_alloc("T38FaxRateManagement", "localTCF");<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>- break;<br>- }<br>-<br>- snprintf(tmp, sizeof(tmp), "%u", ast_udptl_get_local_max_datagram(udptl->instance));<br>- a_line = ast_sdp_a_alloc("T38FaxMaxDatagram", tmp);<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>-<br>- switch (ast_udptl_get_error_correction_scheme(udptl->instance)) {<br>- case UDPTL_ERROR_CORRECTION_NONE:<br>- break;<br>- case UDPTL_ERROR_CORRECTION_FEC:<br>- a_line = ast_sdp_a_alloc("T38FaxUdpEC", "t38UDPFEC");<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>- break;<br>- case UDPTL_ERROR_CORRECTION_REDUNDANCY:<br>- a_line = ast_sdp_a_alloc("T38FaxUdpEC", "t38UDPRedundancy");<br>- if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>- break;<br>- }<br>- }<br>-<br>- if (ast_sdp_add_m(sdp, m_line)) {<br>- ast_sdp_m_free(m_line);<br>- return -1;<br>- }<br>-<br>- return 0;<br>-}<br>-<br>-/*!<br>- * \brief Create an SDP based on current SDP state<br>- *<br>- * \param sdp_state The current SDP state<br>- * \retval NULL Failed to create SDP<br>- * \retval non-NULL Newly-created SDP<br>- */<br>-static struct ast_sdp *sdp_create_from_state(const struct ast_sdp_state *sdp_state,<br>- const struct sdp_state_capabilities *capabilities)<br>-{<br>- struct ast_sdp *sdp = NULL;<br>- struct ast_stream_topology *topology;<br>- const struct ast_sdp_options *options;<br>- int stream_num;<br>- struct ast_sdp_o_line *o_line = NULL;<br>- struct ast_sdp_c_line *c_line = NULL;<br>- struct ast_sdp_s_line *s_line = NULL;<br>- struct ast_sdp_t_line *t_line = NULL;<br>- char *address_type;<br>- struct timeval tv = ast_tvnow();<br>- uint32_t t;<br>- int stream_count;<br>-<br>- options = ast_sdp_state_get_options(sdp_state);<br>- topology = capabilities->topology;<br>-<br>- t = tv.tv_sec + 2208988800UL;<br>- address_type = (strchr(options->media_address, ':') ? "IP6" : "IP4");<br>-<br>- o_line = ast_sdp_o_alloc(options->sdpowner, t, t, address_type, options->media_address);<br>- if (!o_line) {<br>- goto error;<br>- }<br>- c_line = ast_sdp_c_alloc(address_type, options->media_address);<br>- if (!c_line) {<br>- goto error;<br>- }<br>- s_line = ast_sdp_s_alloc(options->sdpsession);<br>- if (!s_line) {<br>- goto error;<br>- }<br>- t_line = ast_sdp_t_alloc(0, 0);<br>- if (!t_line) {<br>- goto error;<br>- }<br>-<br>- sdp = ast_sdp_alloc(o_line, c_line, s_line, t_line);<br>- if (!sdp) {<br>- goto error;<br>- }<br>-<br>- stream_count = ast_stream_topology_get_count(topology);<br>-<br>- for (stream_num = 0; stream_num < stream_count; stream_num++) {<br>- switch (ast_stream_get_type(ast_stream_topology_get_stream(topology, stream_num))) {<br>- case AST_MEDIA_TYPE_AUDIO:<br>- case AST_MEDIA_TYPE_VIDEO:<br>- if (sdp_add_m_from_rtp_stream(sdp, sdp_state, options, capabilities, stream_num)) {<br>- goto error;<br>- }<br>- break;<br>- case AST_MEDIA_TYPE_IMAGE:<br>- if (sdp_add_m_from_udptl_stream(sdp, sdp_state, options, capabilities, stream_num)) {<br>- goto error;<br>- }<br>- break;<br>- case AST_MEDIA_TYPE_UNKNOWN:<br>- case AST_MEDIA_TYPE_TEXT:<br>- case AST_MEDIA_TYPE_END:<br>- break;<br>- }<br>- }<br>-<br>- return sdp;<br>-<br>-error:<br>- if (sdp) {<br>- ast_sdp_free(sdp);<br>- } else {<br>- ast_sdp_t_free(t_line);<br>- ast_sdp_s_free(s_line);<br>- ast_sdp_c_free(c_line);<br>- ast_sdp_o_free(o_line);<br>- }<br>-<br>- return NULL;<br>-}<br>diff --git a/main/sdp_translator.c b/main/sdp_translator.c<br>deleted file mode 100644<br>index 6fe330a..0000000<br>--- a/main/sdp_translator.c<br>+++ /dev/null<br>@@ -1,104 +0,0 @@<br>-/*<br>- * Asterisk -- An open source telephony toolkit.<br>- *<br>- * Copyright (C) 2017, Digium, Inc.<br>- *<br>- * Mark Michelson <mmichelson@digium.com><br>- *<br>- * See http://www.asterisk.org for more information about<br>- * the Asterisk project. Please do not directly contact<br>- * any of the maintainers of this project for assistance;<br>- * the project provides a web site, mailing lists and IRC<br>- * channels for your use.<br>- *<br>- * This program is free software, distributed under the terms of<br>- * the GNU General Public License Version 2. See the LICENSE file<br>- * at the top of the source tree.<br>- */<br>-<br>-#include "asterisk.h"<br>-#include "asterisk/sdp_options.h"<br>-#include "asterisk/sdp_translator.h"<br>-#include "asterisk/logger.h"<br>-#include "asterisk/utils.h"<br>-#include "asterisk/lock.h"<br>-<br>-AST_RWLOCK_DEFINE_STATIC(registered_ops_lock);<br>-static struct ast_sdp_translator_ops *registered_ops[AST_SDP_IMPL_END];<br>-<br>-int ast_sdp_register_translator(struct ast_sdp_translator_ops *ops)<br>-{<br>- SCOPED_WRLOCK(lock, ®istered_ops_lock);<br>-<br>- if (ops->repr >= AST_SDP_IMPL_END) {<br>- ast_log(LOG_ERROR, "SDP translator has unrecognized representation\n");<br>- return -1;<br>- }<br>-<br>- if (registered_ops[ops->repr] != NULL) {<br>- ast_log(LOG_ERROR, "SDP_translator with this representation already registered\n");<br>- return -1;<br>- }<br>-<br>- registered_ops[ops->repr] = ops;<br>- ast_log(LOG_NOTICE, "Placed ops %p at slot %d\n", ops, ops->repr);<br>- return 0;<br>-}<br>-<br>-void ast_sdp_unregister_translator(struct ast_sdp_translator_ops *ops)<br>-{<br>- SCOPED_WRLOCK(lock, ®istered_ops_lock);<br>-<br>- if (ops->repr >= AST_SDP_IMPL_END) {<br>- return;<br>- }<br>-<br>- registered_ops[ops->repr] = NULL;<br>-}<br>-<br>-struct ast_sdp_translator *ast_sdp_translator_new(enum ast_sdp_options_impl repr)<br>-{<br>- struct ast_sdp_translator *translator;<br>- SCOPED_RDLOCK(lock, ®istered_ops_lock);<br>-<br>- if (registered_ops[repr] == NULL) {<br>- ast_log(LOG_NOTICE, "No registered SDP translator with representation %d\n", repr);<br>- return NULL;<br>- }<br>-<br>- translator = ast_calloc(1, sizeof(*translator));<br>- if (!translator) {<br>- return NULL;<br>- }<br>-<br>- translator->ops = registered_ops[repr];<br>-<br>- translator->translator_priv = translator->ops->translator_new();<br>- if (!translator->translator_priv) {<br>- ast_free(translator);<br>- return NULL;<br>- }<br>-<br>- return translator;<br>-}<br>-<br>-void ast_sdp_translator_free(struct ast_sdp_translator *translator)<br>-{<br>- if (!translator) {<br>- return;<br>- }<br>- translator->ops->translator_free(translator->translator_priv);<br>- ast_free(translator);<br>-}<br>-<br>-struct ast_sdp *ast_sdp_translator_to_sdp(struct ast_sdp_translator *translator,<br>- const void *native_sdp)<br>-{<br>- return translator->ops->to_sdp(native_sdp, translator->translator_priv);<br>-}<br>-<br>-const void *ast_sdp_translator_from_sdp(struct ast_sdp_translator *translator,<br>- const struct ast_sdp *ast_sdp)<br>-{<br>- return translator->ops->from_sdp(ast_sdp, translator->translator_priv);<br>-}<br>diff --git a/res/res_sdp_translator_pjmedia.c b/res/res_sdp_translator_pjmedia.c<br>deleted file mode 100644<br>index 7ee7c46..0000000<br>--- a/res/res_sdp_translator_pjmedia.c<br>+++ /dev/null<br>@@ -1,603 +0,0 @@<br>-/*<br>- * Asterisk -- An open source telephony toolkit.<br>- *<br>- * Copyright (C) 2017, Digium, Inc.<br>- *<br>- * Mark Michelson <mmichelson@digium.com><br>- *<br>- * See http://www.asterisk.org for more information about<br>- * the Asterisk project. Please do not directly contact<br>- * any of the maintainers of this project for assistance;<br>- * the project provides a web site, mailing lists and IRC<br>- * channels for your use.<br>- *<br>- * This program is free software, distributed under the terms of<br>- * the GNU General Public License Version 2. See the LICENSE file<br>- * at the top of the source tree.<br>- */<br>-<br>-#include "asterisk.h"<br>-#include "asterisk/sdp_translator.h"<br>-#include "asterisk/sdp_options.h"<br>-#include "asterisk/vector.h"<br>-#include "asterisk/netsock2.h"<br>-#include "asterisk/utils.h"<br>-#include "asterisk/config.h"<br>-#include "asterisk/test.h"<br>-#include "asterisk/module.h"<br>-<br>-#include "asterisk/sdp.h"<br>-#ifdef HAVE_PJPROJECT<br>-#include <pjlib.h><br>-#include <pjmedia.h><br>-#endif<br>-<br>-/*** MODULEINFO<br>- <depend>pjproject</depend><br>- <support_level>core</support_level><br>- ***/<br>-<br>-/*<br>- * XXX TODO: The memory in the pool is held onto longer than necessary. It<br>- * is kept and grows for the duration of the associated chan_pjsip session.<br>- *<br>- * The translation API does not need to be so generic. The users will know<br>- * at compile time what the non-Asterisk SDP format they have or need. They<br>- * should simply call the specific translation functions. However, to make<br>- * this a loadable module we need to be able to keep it in memory when a<br>- * dependent module is loaded.<br>- *<br>- * To address both issues I propose this API:<br>- *<br>- * void ast_sdp_translate_pjmedia_ref(void) - Inc this module's user ref<br>- * void ast_sdp_translate_pjmedia_unref(void) - Dec this module's user ref.<br>- * The res_pjsip_session.c:ast_sip_session_alloc() can call the module ref<br>- * and the session's destructor can call the module unref.<br>- *<br>- * struct ast_sdp *ast_sdp_translate_pjmedia_from(const pjmedia_sdp_session *pjmedia_sdp);<br>- *<br>- * pjmedia_sdp_session *ast_sdp_translate_pjmedia_to(const struct ast_sdp *sdp, pj_pool_t *pool);<br>- * Passing in a memory pool allows the memory to be obtained from an<br>- * rdata memory pool that will be released when the message processing<br>- * is complete. This prevents memory from accumulating for the duration<br>- * of a call.<br>- *<br>- * int ast_sdp_translate_pjmedia_set_remote_sdp(struct ast_sdp_state *sdp_state, const pjmedia_sdp_session *remote);<br>- * const pjmedia_sdp_session *ast_sdp_translate_pjmedia_get_local_sdp(struct ast_sdp_state *sdp_state, pj_pool_t *pool);<br>- * These two functions just do the bookkeeping to translate and set or get<br>- * the requested SDP.<br>- *<br>- *<br>- * XXX TODO: This code doesn't handle allocation failures very well. i.e.,<br>- * It assumes they will never happen.<br>- *<br>- * XXX TODO: This code uses ast_alloca() inside loops. Doing so if the number<br>- * of times through the loop is unconstrained will blow the stack.<br>- * See dupa_pj_str() usage.<br>- */<br>-<br>-static pj_caching_pool sdp_caching_pool;<br>-<br>-<br>-static void *pjmedia_new(void)<br>-{<br>- pj_pool_t *pool;<br>-<br>- pool = pj_pool_create(&sdp_caching_pool.factory, "pjmedia sdp translator", 1024, 1024, NULL);<br>-<br>- return pool;<br>-}<br>-<br>-static void pjmedia_free(void *translator_priv)<br>-{<br>- pj_pool_t *pool = translator_priv;<br>-<br>- pj_pool_release(pool);<br>-}<br>-<br>-#define dupa_pj_str(pjstr) \<br>-({ \<br>- char *dest = ast_alloca(pjstr.slen + 1); \<br>- memcpy(dest, pjstr.ptr, pjstr.slen); \<br>- dest[pjstr.slen] = '\0'; \<br>- dest; \<br>-})<br>-<br>-static struct ast_sdp_m_line *pjmedia_copy_m_line(struct pjmedia_sdp_media *pjmedia_m_line)<br>-{<br>- int i;<br>-<br>- struct ast_sdp_c_line *c_line = pjmedia_m_line->conn ?<br>- ast_sdp_c_alloc(dupa_pj_str(pjmedia_m_line->conn->addr_type),<br>- dupa_pj_str(pjmedia_m_line->conn->addr)) : NULL;<br>-<br>- struct ast_sdp_m_line *m_line = ast_sdp_m_alloc(dupa_pj_str(pjmedia_m_line->desc.media),<br>- pjmedia_m_line->desc.port, pjmedia_m_line->desc.port_count,<br>- dupa_pj_str(pjmedia_m_line->desc.transport), c_line);<br>-<br>- for (i = 0; i < pjmedia_m_line->desc.fmt_count; ++i) {<br>- ast_sdp_m_add_payload(m_line,<br>- ast_sdp_payload_alloc(dupa_pj_str(pjmedia_m_line->desc.fmt[i])));<br>- }<br>-<br>- for (i = 0; i < pjmedia_m_line->attr_count; ++i) {<br>- ast_sdp_m_add_a(m_line, ast_sdp_a_alloc(dupa_pj_str(pjmedia_m_line->attr[i]->name),<br>- dupa_pj_str(pjmedia_m_line->attr[i]->value)));<br>- }<br>-<br>- return m_line;<br>-}<br>-<br>-static void pjmedia_copy_a_lines(struct ast_sdp *new_sdp, const pjmedia_sdp_session *pjmedia_sdp)<br>-{<br>- int i;<br>-<br>- for (i = 0; i < pjmedia_sdp->attr_count; ++i) {<br>- ast_sdp_add_a(new_sdp, ast_sdp_a_alloc(dupa_pj_str(pjmedia_sdp->attr[i]->name),<br>- dupa_pj_str(pjmedia_sdp->attr[i]->value)));<br>- }<br>-}<br>-<br>-static void pjmedia_copy_m_lines(struct ast_sdp *new_sdp,<br>- const struct pjmedia_sdp_session *pjmedia_sdp)<br>-{<br>- int i;<br>-<br>- for (i = 0; i < pjmedia_sdp->media_count; ++i) {<br>- ast_sdp_add_m(new_sdp, pjmedia_copy_m_line(pjmedia_sdp->media[i]));<br>- }<br>-}<br>-<br>-static struct ast_sdp *pjmedia_to_sdp(const void *in, void *translator_priv)<br>-{<br>- const struct pjmedia_sdp_session *pjmedia_sdp = in;<br>-<br>- struct ast_sdp_o_line *o_line = ast_sdp_o_alloc(dupa_pj_str(pjmedia_sdp->origin.user),<br>- pjmedia_sdp->origin.id, pjmedia_sdp->origin.version,<br>- dupa_pj_str(pjmedia_sdp->origin.addr_type), dupa_pj_str(pjmedia_sdp->origin.addr));<br>-<br>- struct ast_sdp_c_line *c_line = pjmedia_sdp->conn ?<br>- ast_sdp_c_alloc(dupa_pj_str(pjmedia_sdp->conn->addr_type),<br>- dupa_pj_str(pjmedia_sdp->conn->addr)) : NULL;<br>-<br>- struct ast_sdp_s_line *s_line = ast_sdp_s_alloc(dupa_pj_str(pjmedia_sdp->name));<br>-<br>- struct ast_sdp_t_line *t_line = ast_sdp_t_alloc(pjmedia_sdp->time.start,<br>- pjmedia_sdp->time.stop);<br>-<br>- struct ast_sdp *new_sdp = ast_sdp_alloc(o_line, c_line, s_line, t_line);<br>-<br>- pjmedia_copy_a_lines(new_sdp, pjmedia_sdp);<br>- pjmedia_copy_m_lines(new_sdp, pjmedia_sdp);<br>-<br>- return new_sdp;<br>-}<br>-<br>-static void copy_o_line_pjmedia(pj_pool_t *pool, pjmedia_sdp_session *pjmedia_sdp,<br>- struct ast_sdp_o_line *o_line)<br>-{<br>- pjmedia_sdp->origin.id = o_line->session_id;<br>- pjmedia_sdp->origin.version = o_line->session_version;<br>- pj_strdup2(pool, &pjmedia_sdp->origin.user, o_line->username);<br>- pj_strdup2(pool, &pjmedia_sdp->origin.addr_type, o_line->address_type);<br>- pj_strdup2(pool, &pjmedia_sdp->origin.addr, o_line->address);<br>- pj_strdup2(pool, &pjmedia_sdp->origin.net_type, "IN");<br>-}<br>-<br>-static void copy_s_line_pjmedia(pj_pool_t *pool, pjmedia_sdp_session *pjmedia_sdp,<br>- struct ast_sdp_s_line *s_line)<br>-{<br>- pj_strdup2(pool, &pjmedia_sdp->name, s_line->session_name);<br>-}<br>-<br>-static void copy_t_line_pjmedia(pj_pool_t *pool, pjmedia_sdp_session *pjmedia_sdp,<br>- struct ast_sdp_t_line *t_line)<br>-{<br>- pjmedia_sdp->time.start = t_line->start_time;<br>- pjmedia_sdp->time.stop = t_line->stop_time;<br>-}<br>-<br>-static void copy_c_line_pjmedia(pj_pool_t *pool, pjmedia_sdp_conn **conn,<br>- struct ast_sdp_c_line *c_line)<br>-{<br>- pjmedia_sdp_conn *local_conn;<br>- local_conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn);<br>- pj_strdup2(pool, &local_conn->addr_type, c_line->address_type);<br>- pj_strdup2(pool, &local_conn->addr, c_line->address);<br>- pj_strdup2(pool, &local_conn->net_type, "IN");<br>-<br>- *conn = local_conn;<br>-}<br>-<br>-static void copy_a_lines_pjmedia(pj_pool_t *pool, pjmedia_sdp_session *pjmedia_sdp,<br>- const struct ast_sdp *sdp)<br>-{<br>- int i;<br>-<br>- for (i = 0; i < ast_sdp_get_a_count(sdp); ++i) {<br>- pjmedia_sdp_attr *attr;<br>- pj_str_t value;<br>- struct ast_sdp_a_line *a_line;<br>-<br>- a_line = ast_sdp_get_a(sdp, i);<br>- pj_strdup2(pool, &value, a_line->value);<br>- attr = pjmedia_sdp_attr_create(pool, a_line->name, &value);<br>- pjmedia_sdp_session_add_attr(pjmedia_sdp, attr);<br>- }<br>-}<br>-<br>-static void copy_a_lines_pjmedia_media(pj_pool_t *pool, pjmedia_sdp_media *media,<br>- struct ast_sdp_m_line *m_line)<br>-{<br>- int i;<br>-<br>- for (i = 0; i < ast_sdp_m_get_a_count(m_line); ++i) {<br>- pjmedia_sdp_attr *attr;<br>- pj_str_t value;<br>- struct ast_sdp_a_line *a_line;<br>-<br>- a_line = ast_sdp_m_get_a(m_line, i);<br>- pj_strdup2(pool, &value, a_line->value);<br>- attr = pjmedia_sdp_attr_create(pool, a_line->name, &value);<br>- pjmedia_sdp_media_add_attr(media, attr);<br>- }<br>-}<br>-<br>-static void copy_m_line_pjmedia(pj_pool_t *pool, pjmedia_sdp_media *media,<br>- struct ast_sdp_m_line *m_line)<br>-{<br>- int i;<br>-<br>- media->desc.port = m_line->port;<br>- media->desc.port_count = m_line->port_count;<br>- pj_strdup2(pool, &media->desc.transport, m_line->proto);<br>- pj_strdup2(pool, &media->desc.media, m_line->type);<br>-<br>- for (i = 0; i < ast_sdp_m_get_payload_count(m_line); ++i) {<br>- pj_strdup2(pool, &media->desc.fmt[i], ast_sdp_m_get_payload(m_line, i)->fmt);<br>- ++media->desc.fmt_count;<br>- }<br>- if (m_line->c_line && m_line->c_line->address) {<br>- copy_c_line_pjmedia(pool, &media->conn, m_line->c_line);<br>- }<br>- copy_a_lines_pjmedia_media(pool, media, m_line);<br>-}<br>-<br>-static void copy_m_lines_pjmedia(pj_pool_t *pool, pjmedia_sdp_session *pjmedia_sdp,<br>- const struct ast_sdp *sdp)<br>-{<br>- int i;<br>-<br>- for (i = 0; i < ast_sdp_get_m_count(sdp); ++i) {<br>- pjmedia_sdp_media *media;<br>-<br>- media = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media);<br>- copy_m_line_pjmedia(pool, media, ast_sdp_get_m(sdp, i));<br>- pjmedia_sdp->media[pjmedia_sdp->media_count] = media;<br>- ++pjmedia_sdp->media_count;<br>- }<br>-}<br>-<br>-static const void *sdp_to_pjmedia(const struct ast_sdp *sdp, void *translator_priv)<br>-{<br>- pj_pool_t *pool = translator_priv;<br>- pjmedia_sdp_session *pjmedia_sdp;<br>-<br>- pjmedia_sdp = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_session);<br>- copy_o_line_pjmedia(pool, pjmedia_sdp, sdp->o_line);<br>- copy_s_line_pjmedia(pool, pjmedia_sdp, sdp->s_line);<br>- copy_t_line_pjmedia(pool, pjmedia_sdp, sdp->t_line);<br>- copy_c_line_pjmedia(pool, &pjmedia_sdp->conn, sdp->c_line);<br>- copy_a_lines_pjmedia(pool, pjmedia_sdp, sdp);<br>- copy_m_lines_pjmedia(pool, pjmedia_sdp, sdp);<br>- return pjmedia_sdp;<br>-}<br>-<br>-static struct ast_sdp_translator_ops pjmedia_translator = {<br>- .repr = AST_SDP_IMPL_PJMEDIA,<br>- .translator_new = pjmedia_new,<br>- .translator_free = pjmedia_free,<br>- .to_sdp = pjmedia_to_sdp,<br>- .from_sdp = sdp_to_pjmedia,<br>-};<br>-<br>-#ifdef TEST_FRAMEWORK<br>-<br>-static int verify_s_line(struct ast_sdp_s_line *s_line, char *expected)<br>-{<br>- return strcmp(s_line->session_name, expected) == 0;<br>-}<br>-<br>-static int verify_c_line(struct ast_sdp_c_line *c_line, char *family, char *addr)<br>-{<br>- return strcmp(c_line->address_type, family) == 0 && strcmp(c_line->address, addr) == 0;<br>-}<br>-<br>-static int verify_t_line(struct ast_sdp_t_line *t_line, uint32_t start, uint32_t end)<br>-{<br>- return t_line->start_time == start && t_line->stop_time == end;<br>-}<br>-<br>-static int verify_m_line(struct ast_sdp *sdp, int index, char *type, int port,<br>- int port_count, char *profile, ...)<br>-{<br>- struct ast_sdp_m_line *m_line;<br>- int res;<br>- va_list ap;<br>- int i;<br>-<br>- m_line = ast_sdp_get_m(sdp, index);<br>-<br>- res = strcmp(m_line->type, type) == 0;<br>- res |= m_line->port == port;<br>- res |= m_line->port_count == port_count;<br>- res |= strcmp(m_line->proto, profile) == 0;<br>-<br>- va_start(ap, profile);<br>- for (i = 0; i < ast_sdp_m_get_payload_count(m_line); ++i) {<br>- char *payload;<br>-<br>- payload = va_arg(ap, char *);<br>- if (!payload) {<br>- res = -1;<br>- break;<br>- }<br>- res |= strcmp(ast_sdp_m_get_payload(m_line, i)->fmt, payload) == 0;<br>- }<br>- va_end(ap);<br>- return res;<br>-}<br>-<br>-static int verify_a_line(struct ast_sdp *sdp, int m_index, int a_index, char *name,<br>- char *value)<br>-{<br>- struct ast_sdp_m_line *m_line;<br>- struct ast_sdp_a_line *a_line;<br>-<br>- m_line = ast_sdp_get_m(sdp, m_index);<br>- a_line = ast_sdp_m_get_a(m_line, a_index);<br>-<br>- return strcmp(a_line->name, name) == 0 && strcmp(a_line->value, value) == 0;<br>-}<br>-<br>-AST_TEST_DEFINE(pjmedia_to_sdp_test)<br>-{<br>- struct ast_sdp_translator *translator;<br>- pj_pool_t *pool;<br>- char *sdp_str =<br>- "v=0\r\n"<br>- "o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"<br>- "s= \r\n"<br>- "c=IN IP4 host.atlanta.example.com\r\n"<br>- "t=123 456\r\n"<br>- "m=audio 49170 RTP/AVP 0 8 97\r\n"<br>- "a=rtpmap:0 PCMU/8000\r\n"<br>- "a=rtpmap:8 PCMA/8000\r\n"<br>- "a=rtpmap:97 iLBC/8000\r\n"<br>- "a=sendrecv\r\n"<br>- "m=video 51372 RTP/AVP 31 32\r\n"<br>- "a=rtpmap:31 H261/90000\r\n"<br>- "a=rtpmap:32 MPV/90000\r\n";<br>- pjmedia_sdp_session *pjmedia_sdp;<br>- struct ast_sdp *sdp = NULL;<br>- pj_status_t status;<br>- enum ast_test_result_state res = AST_TEST_PASS;<br>-<br>- switch (cmd) {<br>- case TEST_INIT:<br>- info->name = "pjmedia_to_sdp";<br>- info->category = "/main/sdp/";<br>- info->summary = "PJMEDIA to SDP unit test";<br>- info->description =<br>- "Ensures PJMEDIA SDPs are translated correctly";<br>- return AST_TEST_NOT_RUN;<br>- case TEST_EXECUTE:<br>- break;<br>- }<br>-<br>- pool = pj_pool_create(&sdp_caching_pool.factory, "pjmedia to sdp test", 1024, 1024, NULL);<br>-<br>- translator = ast_sdp_translator_new(AST_SDP_IMPL_PJMEDIA);<br>- if (!translator) {<br>- ast_test_status_update(test, "Failed to create SDP translator\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- }<br>-<br>- status = pjmedia_sdp_parse(pool, sdp_str, strlen(sdp_str), &pjmedia_sdp);<br>- if (status != PJ_SUCCESS) {<br>- ast_test_status_update(test, "Error parsing SDP\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- }<br>-<br>- sdp = ast_sdp_translator_to_sdp(translator, pjmedia_sdp);<br>-<br>- if (strcmp(sdp->o_line->username, "alice")) {<br>- ast_test_status_update(test, "Unexpected SDP user '%s'\n", sdp->o_line->username);<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- } else if (sdp->o_line->session_id != 2890844526UL) {<br>- ast_test_status_update(test, "Unexpected SDP id '%" PRId64 "lu'\n", sdp->o_line->session_id);<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- } else if (sdp->o_line->session_version != 2890844527UL) {<br>- ast_test_status_update(test, "Unexpected SDP version '%" PRId64 "'\n", sdp->o_line->session_version);<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- } else if (strcmp(sdp->o_line->address_type, "IP4")) {<br>- ast_test_status_update(test, "Unexpected address family '%s'\n", sdp->o_line->address_type);<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- } else if (strcmp(sdp->o_line->address, "host.atlanta.example.com")) {<br>- ast_test_status_update(test, "Unexpected address '%s'\n", sdp->o_line->address);<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- }<br>-<br>- if (!verify_s_line(sdp->s_line, " ")) {<br>- ast_test_status_update(test, "Bad s line\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- } else if (!verify_c_line(sdp->c_line, "IP4", "host.atlanta.example.com")) {<br>- ast_test_status_update(test, "Bad c line\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- } else if (!verify_t_line(sdp->t_line, 123, 456)) {<br>- ast_test_status_update(test, "Bad t line\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- }<br>-<br>- if (!verify_m_line(sdp, 0, "audio", 49170, 1, "RTP/AVP", "0", "8", "97", NULL)) {<br>- ast_test_status_update(test, "Bad m line 1\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- } else if (!verify_a_line(sdp, 0, 0, "rtpmap", "0 PCMU/8000")) {<br>- ast_test_status_update(test, "Bad a line 1\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- } else if (!verify_a_line(sdp, 0, 1, "rtpmap", "8 PCMA/8000")) {<br>- ast_test_status_update(test, "Bad a line 2\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- } else if (!verify_a_line(sdp, 0, 2, "rtpmap", "97 iLBC/8000")) {<br>- ast_test_status_update(test, "Bad a line 3\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- } else if (!verify_a_line(sdp, 0, 3, "sendrecv", "")) {<br>- ast_test_status_update(test, "Bad a line 3\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- } else if (!verify_m_line(sdp, 1, "video", 51372, 1, "RTP/AVP", "31", "32", NULL)) {<br>- ast_test_status_update(test, "Bad m line 2\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- } else if (!verify_a_line(sdp, 1, 0, "rtpmap", "31 H261/90000")) {<br>- ast_test_status_update(test, "Bad a line 4\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- } else if (!verify_a_line(sdp, 1, 1, "rtpmap", "32 MPV/90000")) {<br>- ast_test_status_update(test, "Bad a line 5\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- }<br>-<br>-cleanup:<br>- ast_sdp_free(sdp);<br>- ast_sdp_translator_free(translator);<br>- pj_pool_release(pool);<br>- return res;<br>-}<br>-<br>-AST_TEST_DEFINE(sdp_to_pjmedia_test)<br>-{<br>- struct ast_sdp_translator *translator;<br>- char *sdp_str =<br>- "v=0\r\n"<br>- "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"<br>- "s= \r\n"<br>- "c=IN IP4 host.atlanta.example.com\r\n"<br>- "t=123 456\r\n"<br>- "m=audio 49170 RTP/AVP 0 8 97\r\n"<br>- "a=rtpmap:0 PCMU/8000\r\n"<br>- "a=rtpmap:8 PCMA/8000\r\n"<br>- "a=rtpmap:97 iLBC/8000\r\n"<br>- "a=sendrecv\r\n"<br>- "m=video 51372 RTP/AVP 31 32\r\n"<br>- "a=rtpmap:31 H261/90000\r\n"<br>- "a=rtpmap:32 MPV/90000\r\n\r\n";<br>- pj_pool_t *pool;<br>- pjmedia_sdp_session *pjmedia_sdp_orig;<br>- const pjmedia_sdp_session *pjmedia_sdp_dup;<br>- struct ast_sdp *sdp = NULL;<br>- pj_status_t status;<br>- enum ast_test_result_state res = AST_TEST_PASS;<br>- char buf[2048];<br>- char errbuf[256];<br>-<br>- switch (cmd) {<br>- case TEST_INIT:<br>- info->name = "sdp_to_pjmedia";<br>- info->category = "/main/sdp/";<br>- info->summary = "SDP to PJMEDIA unit test";<br>- info->description =<br>- "Ensures PJMEDIA SDPs are translated correctly";<br>- return AST_TEST_NOT_RUN;<br>- case TEST_EXECUTE:<br>- break;<br>- }<br>-<br>- pool = pj_pool_create(&sdp_caching_pool.factory, "pjmedia to sdp test", 1024, 1024, NULL);<br>-<br>- translator = ast_sdp_translator_new(AST_SDP_IMPL_PJMEDIA);<br>- if (!translator) {<br>- ast_test_status_update(test, "Failed to create SDP translator\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- }<br>-<br>- status = pjmedia_sdp_parse(pool, sdp_str, strlen(sdp_str), &pjmedia_sdp_orig);<br>- if (status != PJ_SUCCESS) {<br>- ast_test_status_update(test, "Error parsing SDP\n");<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- }<br>-<br>- sdp = ast_sdp_translator_to_sdp(translator, pjmedia_sdp_orig);<br>- pjmedia_sdp_dup = ast_sdp_translator_from_sdp(translator, sdp);<br>-<br>- if ((status = pjmedia_sdp_session_cmp(pjmedia_sdp_orig, pjmedia_sdp_dup, 0)) != PJ_SUCCESS) {<br>- ast_test_status_update(test, "SDPs aren't equal\n");<br>- pjmedia_sdp_print(pjmedia_sdp_orig, buf, sizeof(buf));<br>- ast_test_status_update(test, "Original SDP is %s\n", buf);<br>- pjmedia_sdp_print(pjmedia_sdp_dup, buf, sizeof(buf));<br>- ast_test_status_update(test, "New SDP is %s\n", buf);<br>- pjmedia_strerror(status, errbuf, sizeof(errbuf));<br>- ast_test_status_update(test, "PJMEDIA says %d: '%s'\n", status, errbuf);<br>- res = AST_TEST_FAIL;<br>- goto cleanup;<br>- }<br>-<br>-cleanup:<br>- ast_sdp_free(sdp);<br>- ast_sdp_translator_free(translator);<br>- pj_pool_release(pool);<br>- return res;<br>-}<br>-<br>-#endif /* TEST_FRAMEWORK */<br>-<br>-static int load_module(void)<br>-{<br>- if (ast_sdp_register_translator(&pjmedia_translator)) {<br>- return AST_MODULE_LOAD_DECLINE;<br>- }<br>- pj_caching_pool_init(&sdp_caching_pool, NULL, 1024 * 1024);<br>- AST_TEST_REGISTER(pjmedia_to_sdp_test);<br>- AST_TEST_REGISTER(sdp_to_pjmedia_test);<br>-<br>- return AST_MODULE_LOAD_SUCCESS;<br>-}<br>-<br>-static int unload_module(void)<br>-{<br>- ast_sdp_unregister_translator(&pjmedia_translator);<br>- pj_caching_pool_destroy(&sdp_caching_pool);<br>- AST_TEST_UNREGISTER(pjmedia_to_sdp_test);<br>- AST_TEST_UNREGISTER(sdp_to_pjmedia_test);<br>- return 0;<br>-}<br>-<br>-static int reload_module(void)<br>-{<br>- return 0;<br>-}<br>-<br>-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJMEDIA SDP Translator",<br>- .support_level = AST_MODULE_SUPPORT_CORE,<br>- .load = load_module,<br>- .unload = unload_module,<br>- .reload = reload_module,<br>- .load_pri = AST_MODPRI_CHANNEL_DEPEND,<br>-);<br>diff --git a/tests/test_sdp.c b/tests/test_sdp.c<br>deleted file mode 100644<br>index 7eef3f7..0000000<br>--- a/tests/test_sdp.c<br>+++ /dev/null<br>@@ -1,1212 +0,0 @@<br>-/*<br>- * Asterisk -- An open source telephony toolkit.<br>- *<br>- * Copyright (C) 2017, Digium Inc.<br>- *<br>- * Mark Michelson <mmmichelson@digium.com><br>- *<br>- * See http://www.asterisk.org for more information about<br>- * the Asterisk project. Please do not directly contact<br>- * any of the maintainers of this project for assistance;<br>- * the project provides a web site, mailing lists and IRC<br>- * channels for your use.<br>- *<br>- * This program is free software, distributed under the terms of<br>- * the GNU General Public License Version 2. See the LICENSE file<br>- * at the top of the source tree.<br>- */<br>-<br>-/*** MODULEINFO<br>- <depend>TEST_FRAMEWORK</depend><br>- <support_level>core</support_level><br>- ***/<br>-<br>-#include "asterisk.h"<br>-#include "asterisk/test.h"<br>-#include "asterisk/module.h"<br>-#include "asterisk/sdp.h"<br>-#include "asterisk/stream.h"<br>-#include "asterisk/format.h"<br>-#include "asterisk/format_cache.h"<br>-#include "asterisk/format_cap.h"<br>-#include "asterisk/rtp_engine.h"<br>-<br>-static int validate_o_line(struct ast_test *test, const struct ast_sdp_o_line *o_line,<br>- const char *sdpowner, const char *address_type, const char *address)<br>-{<br>- if (!o_line) {<br>- return -1;<br>- }<br>-<br>- if (strcmp(o_line->username, sdpowner)) {<br>- ast_test_status_update(test, "Expected o-line SDP owner %s but got %s\n",<br>- sdpowner, o_line->username);<br>- return -1;<br>- }<br>-<br>- if (strcmp(o_line->address_type, address_type)) {<br>- ast_test_status_update(test, "Expected o-line SDP address type %s but got %s\n",<br>- address_type, o_line->address_type);<br>- return -1;<br>- }<br>-<br>- if (strcmp(o_line->address, address)) {<br>- ast_test_status_update(test, "Expected o-line SDP address %s but got %s\n",<br>- address, o_line->address);<br>- return -1;<br>- }<br>-<br>- ast_test_status_update(test, "SDP o-line is as expected!\n");<br>- return 0;<br>-}<br>-<br>-static int validate_c_line(struct ast_test *test, const struct ast_sdp_c_line *c_line,<br>- const char *address_type, const char *address)<br>-{<br>- if (strcmp(c_line->address_type, address_type)) {<br>- ast_test_status_update(test, "Expected c-line SDP address type %s but got %s\n",<br>- address_type, c_line->address_type);<br>- return -1;<br>- }<br>-<br>- if (strcmp(c_line->address, address)) {<br>- ast_test_status_update(test, "Expected c-line SDP address %s but got %s\n",<br>- address, c_line->address);<br>- return -1;<br>- }<br>-<br>- ast_test_status_update(test, "SDP c-line is as expected!\n");<br>- return 0;<br>-}<br>-<br>-static int validate_m_line(struct ast_test *test, const struct ast_sdp_m_line *m_line,<br>- const char *media_type, int num_payloads)<br>-{<br>- if (strcmp(m_line->type, media_type)) {<br>- ast_test_status_update(test, "Expected m-line media type %s but got %s\n",<br>- media_type, m_line->type);<br>- return -1;<br>- }<br>-<br>- if (ast_sdp_m_get_payload_count(m_line) != num_payloads) {<br>- ast_test_status_update(test, "Expected m-line payload count %d but got %d\n",<br>- num_payloads, ast_sdp_m_get_payload_count(m_line));<br>- return -1;<br>- }<br>-<br>- ast_test_status_update(test, "SDP m-line is as expected\n");<br>- return 0;<br>-}<br>-<br>-static int validate_rtpmap(struct ast_test *test, const struct ast_sdp_m_line *m_line,<br>- const char *media_name)<br>-{<br>- struct ast_sdp_a_line *a_line;<br>- int i;<br>-<br>- for (i = 0; i < ast_sdp_m_get_a_count(m_line); ++i) {<br>- struct ast_sdp_rtpmap *rtpmap;<br>- int match;<br>-<br>- a_line = ast_sdp_m_get_a(m_line, i);<br>- if (strcmp(a_line->name, "rtpmap")) {<br>- continue;<br>- }<br>-<br>- rtpmap = ast_sdp_a_get_rtpmap(a_line);<br>- if (!rtpmap) {<br>- return -1;<br>- }<br>-<br>- match = !strcmp(rtpmap->encoding_name, media_name);<br>-<br>- ast_sdp_rtpmap_free(rtpmap);<br>- if (match) {<br>- return 0;<br>- }<br>- }<br>-<br>- ast_test_status_update(test, "Could not find rtpmap with encoding name %s\n", media_name);<br>-<br>- return -1;<br>-}<br>-<br>-static enum ast_test_result_state validate_t38(struct ast_test *test, const struct ast_sdp_m_line *m_line)<br>-{<br>- struct ast_sdp_a_line *a_line;<br>-<br>- a_line = ast_sdp_m_find_attribute(m_line, "T38FaxVersion", -1);<br>- ast_test_validate(test, a_line && !strcmp(a_line->value, "0"));<br>-<br>- a_line = ast_sdp_m_find_attribute(m_line, "T38FaxMaxBitRate", -1);<br>- ast_test_validate(test, a_line && !strcmp(a_line->value, "14400"));<br>-<br>- a_line = ast_sdp_m_find_attribute(m_line, "T38FaxRateManagement", -1);<br>- ast_test_validate(test, a_line && !strcmp(a_line->value, "transferredTCF"));<br>-<br>- return AST_TEST_PASS;<br>-}<br>-<br>-AST_TEST_DEFINE(invalid_rtpmap)<br>-{<br>- /* a=rtpmap: is already assumed. This is the part after that */<br>- static const char *invalids[] = {<br>- "J PCMU/8000",<br>- "0 PCMU:8000",<br>- "0 PCMU/EIGHT-THOUSAND",<br>- "0 PCMU/8000million/2",<br>- "0 PCMU//2",<br>- "0 /8000/2",<br>- "0 PCMU/8000/",<br>- "0 PCMU/8000million",<br>- };<br>- int i;<br>- enum ast_test_result_state res = AST_TEST_PASS;<br>-<br>- switch(cmd) {<br>- case TEST_INIT:<br>- info->name = "invalid_rtpmap";<br>- info->category = "/main/sdp/";<br>- info->summary = "Ensure invalid rtpmaps are rejected";<br>- info->description =<br>- "Try to convert several invalid rtpmap attributes. If\n"<br>- "any succeeds, the test fails.";<br>- return AST_TEST_NOT_RUN;<br>- case TEST_EXECUTE:<br>- break;<br>- }<br>-<br>- for (i = 0; i < ARRAY_LEN(invalids); ++i) {<br>- struct ast_sdp_a_line *a_line;<br>- struct ast_sdp_rtpmap *rtpmap;<br>-<br>- a_line = ast_sdp_a_alloc("rtpmap", invalids[i]);<br>- rtpmap = ast_sdp_a_get_rtpmap(a_line);<br>- if (rtpmap) {<br>- ast_test_status_update(test, "Invalid rtpmap '%s' was accepted as valid\n",<br>- invalids[i]);<br>- res = AST_TEST_FAIL;<br>- }<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_rtpmap_free(rtpmap);<br>- }<br>-<br>- return res;<br>-}<br>-<br>-AST_TEST_DEFINE(rtpmap)<br>-{<br>- static const char *valids[] = {<br>- "0 PCMU/8000",<br>- "107 opus/48000/2",<br>- };<br>- static int payloads[] = {<br>- 0,<br>- 107,<br>- };<br>- static const char *encoding_names[] = {<br>- "PCMU",<br>- "opus",<br>- };<br>- static int clock_rates[] = {<br>- 8000,<br>- 48000,<br>- };<br>- static const char *encoding_parameters[] = {<br>- "",<br>- "2",<br>- };<br>- int i;<br>- enum ast_test_result_state res = AST_TEST_PASS;<br>-<br>- switch(cmd) {<br>- case TEST_INIT:<br>- info->name = "rtpmap";<br>- info->category = "/main/sdp/";<br>- info->summary = "Ensure rtpmap attribute values are parsed correctly";<br>- info->description =<br>- "Parse several valid rtpmap attributes. Ensure that the parsed values\n"<br>- "are what we expect";<br>- return AST_TEST_NOT_RUN;<br>- case TEST_EXECUTE:<br>- break;<br>- }<br>-<br>- for (i = 0; i < ARRAY_LEN(valids); ++i) {<br>- struct ast_sdp_a_line *a_line;<br>- struct ast_sdp_rtpmap *rtpmap;<br>-<br>- a_line = ast_sdp_a_alloc("rtpmap", valids[i]);<br>- rtpmap = ast_sdp_a_get_rtpmap(a_line);<br>- if (!rtpmap) {<br>- ast_test_status_update(test, "Valid rtpmap '%s' was rejected as invalid\n",<br>- valids[i]);<br>- res = AST_TEST_FAIL;<br>- continue;<br>- }<br>- if (rtpmap->payload != payloads[i]) {<br>- ast_test_status_update(test, "RTPmap payload '%d' does not match expected '%d'\n",<br>- rtpmap->payload, payloads[i]);<br>- res = AST_TEST_FAIL;<br>- }<br>- if (strcmp(rtpmap->encoding_name, encoding_names[i])) {<br>- ast_test_status_update(test, "RTPmap encoding_name '%s' does not match expected '%s'\n",<br>- rtpmap->encoding_name, encoding_names[i]);<br>- res = AST_TEST_FAIL;<br>- }<br>- if (rtpmap->clock_rate != clock_rates[i]) {<br>- ast_test_status_update(test, "RTPmap clock rate '%d' does not match expected '%d'\n",<br>- rtpmap->clock_rate, clock_rates[i]);<br>- res = AST_TEST_FAIL;<br>- }<br>- if (strcmp(rtpmap->encoding_parameters, encoding_parameters[i])) {<br>- ast_test_status_update(test, "RTPmap encoding_parameter '%s' does not match expected '%s'\n",<br>- rtpmap->encoding_parameters, encoding_parameters[i]);<br>- res = AST_TEST_FAIL;<br>- }<br>- ast_sdp_a_free(a_line);<br>- ast_sdp_rtpmap_free(rtpmap);<br>- }<br>-<br>- return res;<br>-}<br>-<br>-AST_TEST_DEFINE(find_attr)<br>-{<br>- enum ast_test_result_state res = AST_TEST_PASS;<br>- struct ast_sdp_m_line *m_line;<br>- struct ast_sdp_a_line *a_line;<br>- int idx;<br>-<br>- switch(cmd) {<br>- case TEST_INIT:<br>- info->name = "find_attr";<br>- info->category = "/main/sdp/";<br>- info->summary = "Ensure that finding attributes works as expected";<br>- info->description =<br>- "A SDP m-line is created, and attributes are added.\n"<br>- "We then attempt a series of attribute-finding calls that are expected to work\n"<br>- "followed by a series of attribute-finding calls that are expected fo fail.";<br>- return AST_TEST_NOT_RUN;<br>- case TEST_EXECUTE:<br>- break;<br>- }<br>-<br>- m_line = ast_sdp_m_alloc("audio", 666, 1, "RTP/AVP", NULL);<br>- if (!m_line) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>- a_line = ast_sdp_a_alloc("foo", "0 bar");<br>- if (!a_line) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>- ast_sdp_m_add_a(m_line, a_line);<br>- a_line = ast_sdp_a_alloc("foo", "0 bee");<br>- if (!a_line) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>- ast_sdp_m_add_a(m_line, a_line);<br>-<br>- a_line = ast_sdp_a_alloc("baz", "howdy");<br>- if (!a_line) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>- ast_sdp_m_add_a(m_line, a_line);<br>-<br>- /* These should work */<br>- a_line = ast_sdp_m_find_attribute(m_line, "foo", 0);<br>- if (!a_line || strcmp(a_line->value, "0 bar")) {<br>- ast_test_status_update(test, "Failed to find attribute 'foo' with payload '0'\n");<br>- res = AST_TEST_FAIL;<br>- }<br>- a_line = ast_sdp_m_find_attribute(m_line, "foo", -1);<br>- if (!a_line || strcmp(a_line->value, "0 bar")) {<br>- ast_test_status_update(test, "Failed to find attribute 'foo' with unspecified payload\n");<br>- res = AST_TEST_FAIL;<br>- }<br>- a_line = ast_sdp_m_find_attribute(m_line, "baz", -1);<br>- if (!a_line || strcmp(a_line->value, "howdy")) {<br>- ast_test_status_update(test, "Failed to find attribute 'baz' with unspecified payload\n");<br>- res = AST_TEST_FAIL;<br>- }<br>-<br>- idx = ast_sdp_m_find_a_first(m_line, "foo", 0);<br>- if (idx < 0) {<br>- ast_test_status_update(test, "Failed to find first attribute 'foo' with payload '0'\n");<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>- a_line = ast_sdp_m_get_a(m_line, idx);<br>- if (!a_line || strcmp(a_line->value, "0 bar")) {<br>- ast_test_status_update(test, "Find first attribute 'foo' with payload '0' didn't match\n");<br>- res = AST_TEST_FAIL;<br>- }<br>- idx = ast_sdp_m_find_a_next(m_line, idx, "foo", 0);<br>- if (idx < 0) {<br>- ast_test_status_update(test, "Failed to find next attribute 'foo' with payload '0'\n");<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>- a_line = ast_sdp_m_get_a(m_line, idx);<br>- if (!a_line || strcmp(a_line->value, "0 bee")) {<br>- ast_test_status_update(test, "Find next attribute 'foo' with payload '0' didn't match\n");<br>- res = AST_TEST_FAIL;<br>- }<br>- idx = ast_sdp_m_find_a_next(m_line, idx, "foo", 0);<br>- if (0 <= idx) {<br>- ast_test_status_update(test, "Find next attribute 'foo' with payload '0' found too many\n");<br>- res = AST_TEST_FAIL;<br>- }<br>-<br>- idx = ast_sdp_m_find_a_first(m_line, "foo", -1);<br>- if (idx < 0) {<br>- ast_test_status_update(test, "Failed to find first attribute 'foo' with unspecified payload\n");<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>- a_line = ast_sdp_m_get_a(m_line, idx);<br>- if (!a_line || strcmp(a_line->value, "0 bar")) {<br>- ast_test_status_update(test, "Find first attribute 'foo' with unspecified payload didn't match\n");<br>- res = AST_TEST_FAIL;<br>- }<br>- idx = ast_sdp_m_find_a_next(m_line, idx, "foo", -1);<br>- if (idx < 0) {<br>- ast_test_status_update(test, "Failed to find next attribute 'foo' with unspecified payload\n");<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>- a_line = ast_sdp_m_get_a(m_line, idx);<br>- if (!a_line || strcmp(a_line->value, "0 bee")) {<br>- ast_test_status_update(test, "Find next attribute 'foo' with unspecified payload didn't match\n");<br>- res = AST_TEST_FAIL;<br>- }<br>- idx = ast_sdp_m_find_a_next(m_line, idx, "foo", -1);<br>- if (0 <= idx) {<br>- ast_test_status_update(test, "Find next attribute 'foo' with unspecified payload found too many\n");<br>- res = AST_TEST_FAIL;<br>- }<br>-<br>- /* These should fail */<br>- a_line = ast_sdp_m_find_attribute(m_line, "foo", 1);<br>- if (a_line) {<br>- ast_test_status_update(test, "Found non-existent attribute 'foo' with payload '1'\n");<br>- res = AST_TEST_FAIL;<br>- }<br>- a_line = ast_sdp_m_find_attribute(m_line, "baz", 0);<br>- if (a_line) {<br>- ast_test_status_update(test, "Found non-existent attribute 'baz' with payload '0'\n");<br>- res = AST_TEST_FAIL;<br>- }<br>- a_line = ast_sdp_m_find_attribute(m_line, "wibble", 0);<br>- if (a_line) {<br>- ast_test_status_update(test, "Found non-existent attribute 'wibble' with payload '0'\n");<br>- res = AST_TEST_FAIL;<br>- }<br>- a_line = ast_sdp_m_find_attribute(m_line, "wibble", -1);<br>- if (a_line) {<br>- ast_test_status_update(test, "Found non-existent attribute 'wibble' with unspecified payload\n");<br>- res = AST_TEST_FAIL;<br>- }<br>-<br>-end:<br>- ast_sdp_m_free(m_line);<br>- return res;<br>-}<br>-<br>-static struct ast_sdp_options *sdp_options_common(void)<br>-{<br>- struct ast_sdp_options *options;<br>-<br>- options = ast_sdp_options_alloc();<br>- if (!options) {<br>- return NULL;<br>- }<br>- ast_sdp_options_set_media_address(options, "127.0.0.1");<br>- ast_sdp_options_set_sdpowner(options, "me");<br>- ast_sdp_options_set_rtp_engine(options, "asterisk");<br>- ast_sdp_options_set_impl(options, AST_SDP_IMPL_PJMEDIA);<br>-<br>- return options;<br>-}<br>-<br>-struct sdp_format {<br>- enum ast_media_type type;<br>- const char *formats;<br>-};<br>-<br>-/*!<br>- * \brief Common method to build an SDP state for a test.<br>- *<br>- * This uses the passed-in formats to create a stream topology, which is then used to create the SDP<br>- * state.<br>- *<br>- * There is an optional test_options field you can use if your test has specific options you need to<br>- * set. If your test does not require anything special, it can just pass NULL for this parameter. If<br>- * you do pass in test_options, this function steals ownership of those options.<br>- *<br>- * \param num_streams The number of elements in the formats array.<br>- * \param formats Array of media types and formats that will be in the state.<br>- * \param test_options Optional SDP options.<br>- */<br>-static struct ast_sdp_state *build_sdp_state(int num_streams, const struct sdp_format *formats, struct ast_sdp_options *test_options)<br>-{<br>- struct ast_stream_topology *topology = NULL;<br>- struct ast_sdp_state *state = NULL;<br>- struct ast_sdp_options *options;<br>- int i;<br>-<br>- if (!test_options) {<br>- options = sdp_options_common();<br>- if (!options) {<br>- goto end;<br>- }<br>- } else {<br>- options = test_options;<br>- }<br>-<br>- topology = ast_stream_topology_alloc();<br>- if (!topology) {<br>- goto end;<br>- }<br>-<br>- for (i = 0; i < num_streams; ++i) {<br>- RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);<br>- struct ast_stream *stream;<br>-<br>- caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);<br>- if (!caps) {<br>- goto end;<br>- }<br>- if (ast_format_cap_update_by_allow_disallow(caps, formats[i].formats, 1) < 0) {<br>- goto end;<br>- }<br>- stream = ast_stream_alloc("sure_thing", formats[i].type);<br>- if (!stream) {<br>- goto end;<br>- }<br>- ast_stream_set_formats(stream, caps);<br>- ast_stream_topology_append_stream(topology, stream);<br>- }<br>-<br>- state = ast_sdp_state_alloc(topology, options);<br>- if (!state) {<br>- goto end;<br>- }<br>-<br>-end:<br>- ast_stream_topology_free(topology);<br>- if (!state) {<br>- ast_sdp_options_free(options);<br>- }<br>-<br>- return state;<br>-}<br>-<br>-AST_TEST_DEFINE(topology_to_sdp)<br>-{<br>- enum ast_test_result_state res = AST_TEST_FAIL;<br>- struct ast_sdp_state *sdp_state = NULL;<br>- const struct ast_sdp *sdp = NULL;<br>- struct ast_sdp_m_line *m_line = NULL;<br>- struct sdp_format formats[] = {<br>- { AST_MEDIA_TYPE_AUDIO, "ulaw,alaw,g722,opus" },<br>- { AST_MEDIA_TYPE_VIDEO, "h264,vp8" },<br>- { AST_MEDIA_TYPE_IMAGE, "t38" },<br>- };<br>-<br>- switch(cmd) {<br>- case TEST_INIT:<br>- info->name = "topology_to_sdp";<br>- info->category = "/main/sdp/";<br>- info->summary = "Convert a topology into an SDP";<br>- info->description =<br>- "Ensure SDPs get converted to expected stream topology";<br>- return AST_TEST_NOT_RUN;<br>- case TEST_EXECUTE:<br>- break;<br>- }<br>-<br>- sdp_state = build_sdp_state(ARRAY_LEN(formats), formats, NULL);<br>- if (!sdp_state) {<br>- goto end;<br>- }<br>-<br>- sdp = ast_sdp_state_get_local_sdp(sdp_state);<br>- if (!sdp) {<br>- goto end;<br>- }<br>-<br>- if (validate_o_line(test, sdp->o_line, "me", "IP4", "127.0.0.1")) {<br>- goto end;<br>- }<br>-<br>- if (validate_c_line(test, sdp->c_line, "IP4", "127.0.0.1")) {<br>- goto end;<br>- }<br>-<br>- if (ast_sdp_get_m_count(sdp) != 3) {<br>- ast_test_status_update(test, "Unexpected number of streams in generated SDP: %d\n",<br>- ast_sdp_get_m_count(sdp));<br>- goto end;<br>- }<br>-<br>- m_line = ast_sdp_get_m(sdp, 0);<br>-<br>- if (validate_m_line(test, m_line, "audio", 4)) {<br>- goto end;<br>- }<br>-<br>- if (validate_rtpmap(test, m_line, "PCMU")) {<br>- goto end;<br>- }<br>-<br>- if (validate_rtpmap(test, m_line, "PCMA")) {<br>- goto end;<br>- }<br>-<br>- if (validate_rtpmap(test, m_line, "G722")) {<br>- goto end;<br>- }<br>-<br>- if (validate_rtpmap(test, m_line, "opus")) {<br>- goto end;<br>- }<br>-<br>- m_line = ast_sdp_get_m(sdp, 1);<br>- if (validate_m_line(test, m_line, "video", 2)) {<br>- goto end;<br>- }<br>-<br>- if (validate_rtpmap(test, m_line, "VP8")) {<br>- goto end;<br>- }<br>-<br>- if (validate_rtpmap(test, m_line, "H264")) {<br>- goto end;<br>- }<br>-<br>- m_line = ast_sdp_get_m(sdp, 2);<br>- if (validate_m_line(test, m_line, "image", 1)) {<br>- goto end;<br>- }<br>- if (validate_t38(test, m_line) != AST_TEST_PASS) {<br>- goto end;<br>- }<br>-<br>- res = AST_TEST_PASS;<br>-<br>-end:<br>- ast_sdp_state_free(sdp_state);<br>- return res;<br>-}<br>-<br>-static int validate_formats(struct ast_test *test, struct ast_stream_topology *topology, int index,<br>- enum ast_media_type type, int format_count, const char **expected_formats)<br>-{<br>- struct ast_stream *stream;<br>- struct ast_format_cap *caps;<br>- struct ast_format *format;<br>- int i;<br>-<br>- stream = ast_stream_topology_get_stream(topology, index);<br>- if (ast_stream_get_type(stream) != type) {<br>- ast_test_status_update(test, "Unexpected stream type encountered\n");<br>- return -1;<br>- }<br>- caps = ast_stream_get_formats(stream);<br>-<br>- if (ast_format_cap_count(caps) != format_count) {<br>- ast_test_status_update(test, "Unexpected format count '%d'. Expecting '%d'\n",<br>- (int) ast_format_cap_count(caps), format_count);<br>- return -1;<br>- }<br>-<br>- for (i = 0; i < ast_format_cap_count(caps); ++i) {<br>- format = ast_format_cap_get_format(caps, i);<br>- if (strcmp(ast_format_get_name(format), expected_formats[i])) {<br>- ast_test_status_update(test, "Unexpected format '%s'at index %d. Expected '%s'\n",<br>- ast_format_get_name(format), i, expected_formats[i]);<br>- return -1;<br>- }<br>- }<br>-<br>- return 0;<br>-}<br>-<br>-AST_TEST_DEFINE(sdp_to_topology)<br>-{<br>- enum ast_test_result_state res = AST_TEST_PASS;<br>- struct ast_sdp_state *sdp_state;<br>- const struct ast_sdp *sdp;<br>- struct ast_stream_topology *topology = NULL;<br>- struct sdp_format sdp_formats[] = {<br>- { AST_MEDIA_TYPE_AUDIO, "ulaw,alaw,g722,opus" },<br>- { AST_MEDIA_TYPE_VIDEO, "h264,vp8" },<br>- { AST_MEDIA_TYPE_IMAGE, "t38" },<br>- };<br>- static const char *expected_audio_formats[] = {<br>- "ulaw",<br>- "alaw",<br>- "g722",<br>- "opus",<br>- };<br>- static const char *expected_video_formats[] = {<br>- "h264",<br>- "vp8",<br>- };<br>- static const char *expected_image_formats[] = {<br>- "t38",<br>- };<br>-<br>- switch(cmd) {<br>- case TEST_INIT:<br>- info->name = "sdp_to_topology";<br>- info->category = "/main/sdp/";<br>- info->summary = "Convert an SDP into a topology";<br>- info->description =<br>- "Ensure SDPs get converted to expected stream topology";<br>- return AST_TEST_NOT_RUN;<br>- case TEST_EXECUTE:<br>- break;<br>- }<br>-<br>- sdp_state = build_sdp_state(ARRAY_LEN(sdp_formats), sdp_formats, NULL);<br>- if (!sdp_state) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- sdp = ast_sdp_state_get_local_sdp(sdp_state);<br>- if (!sdp) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- topology = ast_get_topology_from_sdp(sdp, 0);<br>- if (!topology) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- if (ast_stream_topology_get_count(topology) != 3) {<br>- ast_test_status_update(test, "Unexpected topology count '%d'. Expecting 3\n",<br>- ast_stream_topology_get_count(topology));<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- if (validate_formats(test, topology, 0, AST_MEDIA_TYPE_AUDIO,<br>- ARRAY_LEN(expected_audio_formats), expected_audio_formats)) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- if (validate_formats(test, topology, 1, AST_MEDIA_TYPE_VIDEO,<br>- ARRAY_LEN(expected_video_formats), expected_video_formats)) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- if (validate_formats(test, topology, 2, AST_MEDIA_TYPE_IMAGE,<br>- ARRAY_LEN(expected_image_formats), expected_image_formats)) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>-end:<br>- ast_sdp_state_free(sdp_state);<br>- ast_stream_topology_free(topology);<br>- return res;<br>-}<br>-<br>-static int validate_merged_sdp(struct ast_test *test, const struct ast_sdp *sdp)<br>-{<br>- struct ast_sdp_m_line *m_line;<br>-<br>- if (!sdp) {<br>- return -1;<br>- }<br>-<br>- m_line = ast_sdp_get_m(sdp, 0);<br>- if (validate_m_line(test, m_line, "audio", 1)) {<br>- return -1;<br>- }<br>- if (validate_rtpmap(test, m_line, "PCMU")) {<br>- return -1;<br>- }<br>-<br>- /* The other audio formats should *NOT* be present */<br>- if (!validate_rtpmap(test, m_line, "PCMA")) {<br>- return -1;<br>- }<br>- if (!validate_rtpmap(test, m_line, "G722")) {<br>- return -1;<br>- }<br>- if (!validate_rtpmap(test, m_line, "opus")) {<br>- return -1;<br>- }<br>-<br>- m_line = ast_sdp_get_m(sdp, 1);<br>- if (validate_m_line(test, m_line, "video", 1)) {<br>- return -1;<br>- }<br>- if (validate_rtpmap(test, m_line, "VP8")) {<br>- return -1;<br>- }<br>- if (!validate_rtpmap(test, m_line, "H264")) {<br>- return -1;<br>- }<br>-<br>- m_line = ast_sdp_get_m(sdp, 2);<br>- if (validate_m_line(test, m_line, "image", 1)) {<br>- return -1;<br>- }<br>-<br>- return 0;<br>-}<br>-<br>-AST_TEST_DEFINE(sdp_merge_symmetric)<br>-{<br>- enum ast_test_result_state res = AST_TEST_PASS;<br>- struct ast_sdp_state *sdp_state_offerer = NULL;<br>- struct ast_sdp_state *sdp_state_answerer = NULL;<br>- const struct ast_sdp *offerer_sdp;<br>- const struct ast_sdp *answerer_sdp;<br>-<br>- static const struct sdp_format offerer_formats[] = {<br>- { AST_MEDIA_TYPE_AUDIO, "ulaw,alaw,g722,opus" },<br>- { AST_MEDIA_TYPE_VIDEO, "h264,vp8" },<br>- { AST_MEDIA_TYPE_IMAGE, "t38" },<br>- };<br>- static const struct sdp_format answerer_formats[] = {<br>- { AST_MEDIA_TYPE_AUDIO, "ulaw" },<br>- { AST_MEDIA_TYPE_VIDEO, "vp8" },<br>- { AST_MEDIA_TYPE_IMAGE, "t38" },<br>- };<br>-<br>- switch(cmd) {<br>- case TEST_INIT:<br>- info->name = "sdp_merge_symmetric";<br>- info->category = "/main/sdp/";<br>- info->summary = "Merge two SDPs with symmetric stream types";<br>- info->description =<br>- "SDPs 1 and 2 each have one audio and one video stream (in that order).\n"<br>- "SDP 1 offers to SDP 2, who answers. We ensure that both local SDPs have\n"<br>- "the expected stream types and the expected formats";<br>- return AST_TEST_NOT_RUN;<br>- case TEST_EXECUTE:<br>- break;<br>- }<br>-<br>- sdp_state_offerer = build_sdp_state(ARRAY_LEN(offerer_formats), offerer_formats, NULL);<br>- if (!sdp_state_offerer) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- sdp_state_answerer = build_sdp_state(ARRAY_LEN(answerer_formats), answerer_formats, NULL);<br>- if (!sdp_state_answerer) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- offerer_sdp = ast_sdp_state_get_local_sdp(sdp_state_offerer);<br>- if (!offerer_sdp) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- ast_sdp_state_set_remote_sdp(sdp_state_answerer, offerer_sdp);<br>- answerer_sdp = ast_sdp_state_get_local_sdp(sdp_state_answerer);<br>- if (!answerer_sdp) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- ast_sdp_state_set_remote_sdp(sdp_state_offerer, answerer_sdp);<br>-<br>- /* Get the offerer SDP again because it's now going to be the joint SDP */<br>- offerer_sdp = ast_sdp_state_get_local_sdp(sdp_state_offerer);<br>- if (validate_merged_sdp(test, offerer_sdp)) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>- if (validate_merged_sdp(test, answerer_sdp)) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>-end:<br>- ast_sdp_state_free(sdp_state_offerer);<br>- ast_sdp_state_free(sdp_state_answerer);<br>-<br>- return res;<br>-}<br>-<br>-AST_TEST_DEFINE(sdp_merge_crisscross)<br>-{<br>- enum ast_test_result_state res = AST_TEST_PASS;<br>- struct ast_sdp_state *sdp_state_offerer = NULL;<br>- struct ast_sdp_state *sdp_state_answerer = NULL;<br>- const struct ast_sdp *offerer_sdp;<br>- const struct ast_sdp *answerer_sdp;<br>-<br>- static const struct sdp_format offerer_formats[] = {<br>- { AST_MEDIA_TYPE_AUDIO, "ulaw,alaw,g722,opus" },<br>- { AST_MEDIA_TYPE_VIDEO, "h264,vp8" },<br>- { AST_MEDIA_TYPE_IMAGE, "t38" },<br>- };<br>- static const struct sdp_format answerer_formats[] = {<br>- { AST_MEDIA_TYPE_IMAGE, "t38" },<br>- { AST_MEDIA_TYPE_VIDEO, "vp8" },<br>- { AST_MEDIA_TYPE_AUDIO, "ulaw" },<br>- };<br>-<br>- switch(cmd) {<br>- case TEST_INIT:<br>- info->name = "sdp_merge_crisscross";<br>- info->category = "/main/sdp/";<br>- info->summary = "Merge two SDPs with symmetric stream types";<br>- info->description =<br>- "SDPs 1 and 2 each have one audio and one video stream. However, SDP 1 and\n"<br>- "2 natively have the formats in a different order.\n"<br>- "SDP 1 offers to SDP 2, who answers. We ensure that both local SDPs have\n"<br>- "the expected stream types and the expected formats. Since SDP 1 was the\n"<br>- "offerer, the format order on SDP 1 should determine the order of formats in the SDPs";<br>- return AST_TEST_NOT_RUN;<br>- case TEST_EXECUTE:<br>- break;<br>- }<br>-<br>- sdp_state_offerer = build_sdp_state(ARRAY_LEN(offerer_formats), offerer_formats, NULL);<br>- if (!sdp_state_offerer) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- sdp_state_answerer = build_sdp_state(ARRAY_LEN(answerer_formats), answerer_formats, NULL);<br>- if (!sdp_state_answerer) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- offerer_sdp = ast_sdp_state_get_local_sdp(sdp_state_offerer);<br>- if (!offerer_sdp) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- ast_sdp_state_set_remote_sdp(sdp_state_answerer, offerer_sdp);<br>- answerer_sdp = ast_sdp_state_get_local_sdp(sdp_state_answerer);<br>- if (!answerer_sdp) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- ast_sdp_state_set_remote_sdp(sdp_state_offerer, answerer_sdp);<br>-<br>- /* Get the offerer SDP again because it's now going to be the joint SDP */<br>- offerer_sdp = ast_sdp_state_get_local_sdp(sdp_state_offerer);<br>- if (validate_merged_sdp(test, offerer_sdp)) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>- if (validate_merged_sdp(test, answerer_sdp)) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>-end:<br>- ast_sdp_state_free(sdp_state_offerer);<br>- ast_sdp_state_free(sdp_state_answerer);<br>-<br>- return res;<br>-}<br>-<br>-static int validate_merged_sdp_asymmetric(struct ast_test *test, const struct ast_sdp *sdp, int is_offer)<br>-{<br>- struct ast_sdp_m_line *m_line;<br>- const char *side = is_offer ? "Offer side" : "Answer side";<br>-<br>- if (!sdp) {<br>- ast_test_status_update(test, "%s does not have a SDP\n", side);<br>- return -1;<br>- }<br>-<br>- /* Stream 0 */<br>- m_line = ast_sdp_get_m(sdp, 0);<br>- if (validate_m_line(test, m_line, "audio", 1)) {<br>- return -1;<br>- }<br>- if (!m_line->port) {<br>- ast_test_status_update(test, "%s stream %d does%s have a port\n", side, 0, "n't");<br>- return -1;<br>- }<br>- if (validate_rtpmap(test, m_line, "PCMU")) {<br>- return -1;<br>- }<br>-<br>- /* The other audio formats should *NOT* be present */<br>- if (!validate_rtpmap(test, m_line, "PCMA")) {<br>- return -1;<br>- }<br>- if (!validate_rtpmap(test, m_line, "G722")) {<br>- return -1;<br>- }<br>- if (!validate_rtpmap(test, m_line, "opus")) {<br>- return -1;<br>- }<br>-<br>- /* The remaining streams should be declined */<br>-<br>- /* Stream 1 */<br>- m_line = ast_sdp_get_m(sdp, 1);<br>- if (validate_m_line(test, m_line, "audio", 1)) {<br>- return -1;<br>- }<br>- if (m_line->port) {<br>- ast_test_status_update(test, "%s stream %d does%s have a port\n", side, 1, "");<br>- return -1;<br>- }<br>-<br>- /* Stream 2 */<br>- m_line = ast_sdp_get_m(sdp, 2);<br>- if (validate_m_line(test, m_line, "video", 1)) {<br>- return -1;<br>- }<br>- if (m_line->port) {<br>- ast_test_status_update(test, "%s stream %d does%s have a port\n", side, 2, "");<br>- return -1;<br>- }<br>-<br>- /* Stream 3 */<br>- m_line = ast_sdp_get_m(sdp, 3);<br>- if (validate_m_line(test, m_line, "image", 1)) {<br>- return -1;<br>- }<br>- if (m_line->port) {<br>- ast_test_status_update(test, "%s stream %d does%s have a port\n", side, 3, "");<br>- return -1;<br>- }<br>-<br>- return 0;<br>-}<br>-<br>-AST_TEST_DEFINE(sdp_merge_asymmetric)<br>-{<br>- enum ast_test_result_state res = AST_TEST_PASS;<br>- struct ast_sdp_state *sdp_state_offerer = NULL;<br>- struct ast_sdp_state *sdp_state_answerer = NULL;<br>- const struct ast_sdp *offerer_sdp;<br>- const struct ast_sdp *answerer_sdp;<br>-<br>- static const struct sdp_format offerer_formats[] = {<br>- { AST_MEDIA_TYPE_AUDIO, "ulaw,alaw,g722,opus" },<br>- { AST_MEDIA_TYPE_AUDIO, "ulaw" },<br>- { AST_MEDIA_TYPE_VIDEO, "h261" },<br>- { AST_MEDIA_TYPE_IMAGE, "t38" },<br>- };<br>- static const struct sdp_format answerer_formats[] = {<br>- { AST_MEDIA_TYPE_AUDIO, "ulaw" },<br>- };<br>-<br>- switch(cmd) {<br>- case TEST_INIT:<br>- info->name = "sdp_merge_asymmetric";<br>- info->category = "/main/sdp/";<br>- info->summary = "Merge two SDPs with an asymmetric number of streams";<br>- info->description =<br>- "SDP 1 offers a four stream topology: Audio,Audio,Video,T.38\n"<br>- "SDP 2 only has a single audio stream topology\n"<br>- "We ensure that both local SDPs have the expected stream types and\n"<br>- "the expected declined streams";<br>- return AST_TEST_NOT_RUN;<br>- case TEST_EXECUTE:<br>- break;<br>- }<br>-<br>- sdp_state_offerer = build_sdp_state(ARRAY_LEN(offerer_formats), offerer_formats, NULL);<br>- if (!sdp_state_offerer) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- sdp_state_answerer = build_sdp_state(ARRAY_LEN(answerer_formats), answerer_formats, NULL);<br>- if (!sdp_state_answerer) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- offerer_sdp = ast_sdp_state_get_local_sdp(sdp_state_offerer);<br>- if (!offerer_sdp) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- ast_sdp_state_set_remote_sdp(sdp_state_answerer, offerer_sdp);<br>- answerer_sdp = ast_sdp_state_get_local_sdp(sdp_state_answerer);<br>- if (!answerer_sdp) {<br>- res = AST_TEST_FAIL;<br>- goto end;<br>- }<br>-<br>- ast_sdp_state_set_remote_sdp(sdp_state_offerer, answerer_sdp);<br>-<br>-#if defined(XXX_TODO_NEED_TO_HANDLE_DECLINED_STREAMS_ON_OFFER_SIDE)<br>- /* Get the offerer SDP again because it's now going to be the joint SDP */<br>- offerer_sdp = ast_sdp_state_get_local_sdp(sdp_state_offerer);<br>- if (validate_merged_sdp_asymmetric(test, offerer_sdp, 1)) {<br>- res = AST_TEST_FAIL;<br>- }<br>-#endif<br>- if (validate_merged_sdp_asymmetric(test, answerer_sdp, 0)) {<br>- res = AST_TEST_FAIL;<br>- }<br>-<br>-end:<br>- ast_sdp_state_free(sdp_state_offerer);<br>- ast_sdp_state_free(sdp_state_answerer);<br>-<br>- return res;<br>-}<br>-<br>-static int validate_ssrc(struct ast_test *test, struct ast_sdp_m_line *m_line,<br>- struct ast_rtp_instance *rtp)<br>-{<br>- unsigned int ssrc;<br>- const char *cname;<br>- struct ast_sdp_a_line *a_line;<br>- char attr_value[128];<br>-<br>- ssrc = ast_rtp_instance_get_ssrc(rtp);<br>- cname = ast_rtp_instance_get_cname(rtp);<br>-<br>- snprintf(attr_value, sizeof(attr_value), "%u cname:%s", ssrc, cname);<br>-<br>- a_line = ast_sdp_m_find_attribute(m_line, "ssrc", -1);<br>- if (!a_line) {<br>- ast_test_status_update(test, "Could not find 'ssrc' attribute\n");<br>- return -1;<br>- }<br>-<br>- if (strcmp(a_line->value, attr_value)) {<br>- ast_test_status_update(test, "SDP attribute '%s' did not match expected attribute '%s'\n",<br>- a_line->value, attr_value);<br>- return -1;<br>- }<br>-<br>- return 0;<br>-}<br>-<br>-AST_TEST_DEFINE(sdp_ssrc_attributes)<br>-{<br>- enum ast_test_result_state res;<br>- struct ast_sdp_state *test_state = NULL;<br>- struct ast_sdp_options *options;<br>- struct sdp_format formats[] = {<br>- { AST_MEDIA_TYPE_AUDIO, "ulaw,alaw,g722,opus" },<br>- };<br>- const struct ast_sdp *sdp;<br>- struct ast_sdp_m_line *m_line;<br>- struct ast_rtp_instance *rtp;<br>-<br>- switch(cmd) {<br>- case TEST_INIT:<br>- info->name = "sdp_ssrc_attributes";<br>- info->category = "/main/sdp/";<br>- info->summary = "Ensure SSRC-level attributes are added to local SDPs";<br>- info->description =<br>- "An SDP is created and is instructed to include SSRC-level attributes.\n"<br>- "This test ensures that the CNAME SSRC-level attribute is present and\n"<br>- "that the values match what the RTP instance reports";<br>- return AST_TEST_NOT_RUN;<br>- case TEST_EXECUTE:<br>- break;<br>- }<br>-<br>- res = AST_TEST_FAIL;<br>-<br>- options = sdp_options_common();<br>- if (!options) {<br>- ast_test_status_update(test, "Failed to allocate SDP options\n");<br>- goto end;<br>- }<br>- ast_sdp_options_set_ssrc(options, 1);<br>-<br>- test_state = build_sdp_state(ARRAY_LEN(formats), formats, options);<br>- if (!test_state) {<br>- ast_test_status_update(test, "Failed to create SDP state\n");<br>- goto end;<br>- }<br>-<br>- sdp = ast_sdp_state_get_local_sdp(test_state);<br>- if (!sdp) {<br>- ast_test_status_update(test, "Failed to get local SDP\n");<br>- goto end;<br>- }<br>-<br>- /* Need a couple of sanity checks */<br>- if (ast_sdp_get_m_count(sdp) != ARRAY_LEN(formats)) {<br>- ast_test_status_update(test, "SDP m count is %d instead of %zu\n",<br>- ast_sdp_get_m_count(sdp), ARRAY_LEN(formats));<br>- goto end;<br>- }<br>-<br>- m_line = ast_sdp_get_m(sdp, 0);<br>- if (!m_line) {<br>- ast_test_status_update(test, "Failed to get SDP m-line\n");<br>- goto end;<br>- }<br>-<br>- rtp = ast_sdp_state_get_rtp_instance(test_state, 0);<br>- if (!rtp) {<br>- ast_test_status_update(test, "Failed to get the RTP instance\n");<br>- goto end;<br>- }<br>-<br>- if (validate_ssrc(test, m_line, rtp)) {<br>- goto end;<br>- }<br>-<br>- res = AST_TEST_PASS;<br>-<br>-end:<br>- ast_sdp_state_free(test_state);<br>- return res;<br>-}<br>-<br>-static int unload_module(void)<br>-{<br>- AST_TEST_UNREGISTER(invalid_rtpmap);<br>- AST_TEST_UNREGISTER(rtpmap);<br>- AST_TEST_UNREGISTER(find_attr);<br>- AST_TEST_UNREGISTER(topology_to_sdp);<br>- AST_TEST_UNREGISTER(sdp_to_topology);<br>- AST_TEST_UNREGISTER(sdp_merge_symmetric);<br>- AST_TEST_UNREGISTER(sdp_merge_crisscross);<br>- AST_TEST_UNREGISTER(sdp_merge_asymmetric);<br>- AST_TEST_UNREGISTER(sdp_ssrc_attributes);<br>-<br>- return 0;<br>-}<br>-<br>-static int load_module(void)<br>-{<br>- AST_TEST_REGISTER(invalid_rtpmap);<br>- AST_TEST_REGISTER(rtpmap);<br>- AST_TEST_REGISTER(find_attr);<br>- AST_TEST_REGISTER(topology_to_sdp);<br>- AST_TEST_REGISTER(sdp_to_topology);<br>- AST_TEST_REGISTER(sdp_merge_symmetric);<br>- AST_TEST_REGISTER(sdp_merge_crisscross);<br>- AST_TEST_REGISTER(sdp_merge_asymmetric);<br>- AST_TEST_REGISTER(sdp_ssrc_attributes);<br>-<br>- return AST_MODULE_LOAD_SUCCESS;<br>-}<br>-<br>-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SDP tests");<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/7715">change 7715</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/7715"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 15 </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Icc28fbdc46f58e54a21554e6fe8b078f841b1f86 </div>
<div style="display:none"> Gerrit-Change-Number: 7715 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Richard Mudgett <rmudgett@digium.com> </div>