<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, &registered_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, &registered_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, &registered_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>