core: Remove unused/incomplete SDP modules.
Change-Id: Icc28fbdc46f58e54a21554e6fe8b078f841b1f86
This commit is contained in:
parent
1dedc73951
commit
661fec4b59
|
@ -1,703 +0,0 @@
|
|||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2017, Digium, Inc.
|
||||
*
|
||||
* Mark Michelson <mmichelson@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/* NOTE: It is unlikely that you need to include this file. You probably will only need
|
||||
* this if you are an SDP translator, or if you are an inner part of the SDP API
|
||||
*/
|
||||
|
||||
#ifndef _SDP_PRIV_H
|
||||
#define _SDP_PRIV_H
|
||||
|
||||
#include "asterisk/vector.h"
|
||||
#include "asterisk/format.h"
|
||||
#include "asterisk/sdp_state.h"
|
||||
#include "asterisk/stream.h"
|
||||
|
||||
/*!
|
||||
* \brief Structure representing an SDP Attribute
|
||||
*/
|
||||
struct ast_sdp_a_line {
|
||||
/*! Attribute name */
|
||||
char *name;
|
||||
/*! Attribute value. For attributes that have no value, this will be an empty string */
|
||||
char *value;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief A collection of SDP Attributes
|
||||
*/
|
||||
AST_VECTOR(ast_sdp_a_lines, struct ast_sdp_a_line *);
|
||||
|
||||
/*!
|
||||
* \brief Structure representing an SDP Connection
|
||||
*/
|
||||
struct ast_sdp_c_line {
|
||||
/* IP family string (e.g. IP4 or IP6) */
|
||||
char *address_type;
|
||||
/* Connection address. Can be an IP address or FQDN */
|
||||
char *address;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Structre representing SDP Media Payloads
|
||||
*/
|
||||
struct ast_sdp_payload {
|
||||
/* Media format description */
|
||||
char *fmt;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief A collection of SDP Media Payloads
|
||||
*/
|
||||
AST_VECTOR(ast_sdp_payloads, struct ast_sdp_payload *);
|
||||
|
||||
/*!
|
||||
* \brief Structure representing an SDP Media Stream
|
||||
*
|
||||
* This contains both the m line, as well as its
|
||||
* constituent a lines.
|
||||
*/
|
||||
struct ast_sdp_m_line {
|
||||
/*! Media type (e.g. "audio" or "video") */
|
||||
char *type;
|
||||
/*! RTP profile string (e.g. "RTP/AVP") */
|
||||
char *proto;
|
||||
/*! Port number in m line */
|
||||
uint16_t port;
|
||||
/*! Number of ports specified in m line */
|
||||
uint16_t port_count;
|
||||
/*! RTP payloads */
|
||||
struct ast_sdp_payloads *payloads;
|
||||
/*! Connection information for this media stream */
|
||||
struct ast_sdp_c_line *c_line;
|
||||
/*! The attributes for this media stream */
|
||||
struct ast_sdp_a_lines *a_lines;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief A collection of SDP Media Streams
|
||||
*/
|
||||
AST_VECTOR(ast_sdp_m_lines, struct ast_sdp_m_line *);
|
||||
|
||||
/*!
|
||||
* \brief Structure representing an SDP Origin
|
||||
*/
|
||||
struct ast_sdp_o_line {
|
||||
/*! Origin user name */
|
||||
char *username;
|
||||
/*! Origin id */
|
||||
uint64_t session_id;
|
||||
/*! Origin version */
|
||||
uint64_t session_version;
|
||||
/*! Origin IP address type (e.g. "IP4" or "IP6") */
|
||||
char *address_type;
|
||||
/*! Origin address. Can be an IP address or FQDN */
|
||||
char *address;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Structure representing an SDP Session Name
|
||||
*/
|
||||
struct ast_sdp_s_line {
|
||||
/* Session Name */
|
||||
char *session_name;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Structure representing SDP Timing
|
||||
*/
|
||||
struct ast_sdp_t_line {
|
||||
/*! Session start time */
|
||||
uint64_t start_time;
|
||||
/*! Session end time */
|
||||
uint64_t stop_time;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief An SDP
|
||||
*/
|
||||
struct ast_sdp {
|
||||
/*! SDP Origin line */
|
||||
struct ast_sdp_o_line *o_line;
|
||||
/*! SDP Session name */
|
||||
struct ast_sdp_s_line *s_line;
|
||||
/*! SDP top-level connection information */
|
||||
struct ast_sdp_c_line *c_line;
|
||||
/*! SDP timing information */
|
||||
struct ast_sdp_t_line *t_line;
|
||||
/*! SDP top-level attributes */
|
||||
struct ast_sdp_a_lines *a_lines;
|
||||
/*! SDP media streams */
|
||||
struct ast_sdp_m_lines *m_lines;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief A structure representing an SDP rtpmap attribute
|
||||
*/
|
||||
struct ast_sdp_rtpmap {
|
||||
/*! The RTP payload number for the rtpmap */
|
||||
int payload;
|
||||
/*! The Name of the codec */
|
||||
char *encoding_name;
|
||||
/*! The clock rate of the codec */
|
||||
int clock_rate;
|
||||
/*! Optional encoding parameters */
|
||||
char *encoding_parameters;
|
||||
/*! Area where strings are stored */
|
||||
char buf[0];
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Free an SDP Attribute
|
||||
*
|
||||
* \param a_line The attribute to free
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
void ast_sdp_a_free(struct ast_sdp_a_line *a_line);
|
||||
|
||||
/*!
|
||||
* \brief Free an SDP Attribute collection
|
||||
*
|
||||
* \param a_lines The attribute collection to free
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
void ast_sdp_a_lines_free(struct ast_sdp_a_lines *a_lines);
|
||||
|
||||
/*!
|
||||
* \brief Free SDP Connection Data
|
||||
*
|
||||
* \param c_line The connection data to free
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
void ast_sdp_c_free(struct ast_sdp_c_line *c_line);
|
||||
|
||||
/*!
|
||||
* \brief Free an SDP Media Description Payload
|
||||
*
|
||||
* \param payload The payload to free
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
void ast_sdp_payload_free(struct ast_sdp_payload *payload);
|
||||
|
||||
/*!
|
||||
* \brief Free an SDP Media Description Payload collection
|
||||
*
|
||||
* \param payloads collection to free
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
void ast_sdp_payloads_free(struct ast_sdp_payloads *payloads);
|
||||
|
||||
/*!
|
||||
* \brief Free an SDP Media Description
|
||||
* Frees the media description and all resources it contains
|
||||
*
|
||||
* \param m_line The media description to free
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
void ast_sdp_m_free(struct ast_sdp_m_line *m_line);
|
||||
|
||||
/*!
|
||||
* \brief Free an SDP Media Description collection
|
||||
*
|
||||
* \param m_lines The collection description to free
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
void ast_sdp_m_lines_free(struct ast_sdp_m_lines *m_lines);
|
||||
|
||||
/*!
|
||||
* \brief Free an SDP Origin
|
||||
*
|
||||
* \param o_line The origin description to free
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
void ast_sdp_o_free(struct ast_sdp_o_line *o_line);
|
||||
|
||||
/*!
|
||||
* \brief Free an SDP Session
|
||||
*
|
||||
* \param s_line The session to free
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
void ast_sdp_s_free(struct ast_sdp_s_line *s_line);
|
||||
|
||||
/*!
|
||||
* \brief Free SDP Timing
|
||||
*
|
||||
* \param t_line The timing description to free
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
void ast_sdp_t_free(struct ast_sdp_t_line *t_line);
|
||||
|
||||
/*!
|
||||
* \brief Allocate an SDP Attribute
|
||||
*
|
||||
* \param name Attribute Name
|
||||
* \param value Attribute Name
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
struct ast_sdp_a_line *ast_sdp_a_alloc(const char *name, const char *value);
|
||||
|
||||
/*!
|
||||
* \brief Allocate an SDP Connection
|
||||
*
|
||||
* \param family Family ("IN", etc)
|
||||
* \param addr Address
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
struct ast_sdp_c_line *ast_sdp_c_alloc(const char *family, const char *addr);
|
||||
|
||||
/*!
|
||||
* \brief Allocate an SDP Media Description Payload
|
||||
*
|
||||
* \param fmt The media format description
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
struct ast_sdp_payload *ast_sdp_payload_alloc(const char *fmt);
|
||||
|
||||
/*!
|
||||
* \brief Allocate an SDP Media Description
|
||||
*
|
||||
* \param type ("audio", "video", etc)
|
||||
* \param port Starting port
|
||||
* \param port_count Port pairs to allocate
|
||||
* \param proto ("RTP/AVP", "RTP/SAVP", "udp")
|
||||
* \param c_line Connection to add. May be NULL
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
struct ast_sdp_m_line *ast_sdp_m_alloc(const char *type, uint16_t port,
|
||||
uint16_t port_count, const char *proto, struct ast_sdp_c_line *c_line);
|
||||
|
||||
/*!
|
||||
* \brief Allocate an SDP Session
|
||||
*
|
||||
* \param session_name The session name
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
struct ast_sdp_s_line *ast_sdp_s_alloc(const char *session_name);
|
||||
|
||||
/*!
|
||||
* \brief Allocate SDP Timing
|
||||
*
|
||||
* \param start_time (Seconds since 1900)
|
||||
* \param end_time (Seconds since 1900)
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
struct ast_sdp_t_line *ast_sdp_t_alloc(uint64_t start_time, uint64_t stop_time);
|
||||
|
||||
/*!
|
||||
* \brief Allocate an SDP Origin
|
||||
*
|
||||
* \param username User name
|
||||
* \param sesison_id Session ID
|
||||
* \param sesison_version Session Version
|
||||
* \param address_type Address type ("IN4", "IN6", etc)
|
||||
* \param address Unicast address
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
struct ast_sdp_o_line *ast_sdp_o_alloc(const char *username, uint64_t session_id,
|
||||
uint64_t session_version, const char *address_type, const char *address);
|
||||
|
||||
/*!
|
||||
* \brief Add an SDP Attribute to an SDP
|
||||
*
|
||||
* \param sdp SDP
|
||||
* \param a_line Attribute
|
||||
*
|
||||
* \retval 0 Success
|
||||
* \retval non-0 Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_add_a(struct ast_sdp *sdp, struct ast_sdp_a_line *a_line);
|
||||
|
||||
/*!
|
||||
* \brief Get the count of Attributes on an SDP
|
||||
*
|
||||
* \param sdp SDP
|
||||
*
|
||||
* \returns Number of Attributes
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_get_a_count(const struct ast_sdp *sdp);
|
||||
|
||||
/*!
|
||||
* \brief Get an Attribute from an SDP
|
||||
*
|
||||
* \param sdp SDP
|
||||
* \param index Attribute index
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
struct ast_sdp_a_line *ast_sdp_get_a(const struct ast_sdp *sdp, int index);
|
||||
|
||||
/*!
|
||||
* \brief Add a Media Description to an SDP
|
||||
*
|
||||
* \param sdp SDP
|
||||
* \param m_line Media Description
|
||||
*
|
||||
* \retval 0 Success
|
||||
* \retval non-0 Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_add_m(struct ast_sdp *sdp, struct ast_sdp_m_line *m_line);
|
||||
|
||||
/*!
|
||||
* \brief Add an RTP Media Description to an SDP
|
||||
*
|
||||
* \param sdp SDP
|
||||
* \param sdp_state SDP state information
|
||||
* \param options SDP Options
|
||||
* \param stream_index stream
|
||||
*
|
||||
* \retval 0 Success
|
||||
* \retval non-0 Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_add_m_from_rtp_stream(struct ast_sdp *sdp, const struct ast_sdp_state *sdp_state,
|
||||
const struct ast_sdp_options *options, int stream_index);
|
||||
|
||||
/*!
|
||||
* \brief Get the count of Media Descriptions on an SDP
|
||||
*
|
||||
* \param sdp SDP
|
||||
*
|
||||
* \returns The number of Media Descriptions
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_get_m_count(const struct ast_sdp *sdp);
|
||||
|
||||
/*!
|
||||
* \brief Get a Media Descriptions from an SDP
|
||||
*
|
||||
* \param sdp SDP
|
||||
* \param index Media Description index
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
struct ast_sdp_m_line *ast_sdp_get_m(const struct ast_sdp *sdp, int index);
|
||||
|
||||
/*!
|
||||
* \brief Add an SDP Attribute to a Media Description
|
||||
*
|
||||
* \param m_line Media Description
|
||||
* \param a_line Attribute
|
||||
*
|
||||
* \retval 0 Success
|
||||
* \retval non-0 Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_m_add_a(struct ast_sdp_m_line *m_line, struct ast_sdp_a_line *a_line);
|
||||
|
||||
/*!
|
||||
* \brief Get the count of Attributes on a Media Description
|
||||
*
|
||||
* \param m_line Media Description
|
||||
*
|
||||
* \returns Number of Attributes
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_m_get_a_count(const struct ast_sdp_m_line *m_line);
|
||||
|
||||
/*!
|
||||
* \brief Get an Attribute from a Media Description
|
||||
*
|
||||
* \param m_line Media Description
|
||||
* \param index Attribute index
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
struct ast_sdp_a_line *ast_sdp_m_get_a(const struct ast_sdp_m_line *m_line, int index);
|
||||
|
||||
/*!
|
||||
* \brief Add a Payload to a Media Description
|
||||
*
|
||||
* \param m_line Media Description
|
||||
* \param payload Payload
|
||||
*
|
||||
* \retval 0 Success
|
||||
* \retval non-0 Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_m_add_payload(struct ast_sdp_m_line *m_line,
|
||||
struct ast_sdp_payload *payload);
|
||||
|
||||
/*!
|
||||
* \brief Get the count of Payloads on a Media Description
|
||||
*
|
||||
* \param m_line Media Description
|
||||
*
|
||||
* \returns Number of Attributes
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_m_get_payload_count(const struct ast_sdp_m_line *m_line);
|
||||
|
||||
/*!
|
||||
* \brief Get a Payload from a Media Description
|
||||
*
|
||||
* \param m_line Media Description
|
||||
* \param index Payload index
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
struct ast_sdp_payload *ast_sdp_m_get_payload(const struct ast_sdp_m_line *m_line, int index);
|
||||
|
||||
/*!
|
||||
* \brief Add a Format to a Media Description
|
||||
*
|
||||
* \param m_line Media Description
|
||||
* \param options SDP Options
|
||||
* \param rtp_code rtp_code from ast_rtp_codecs_payload_code
|
||||
* \param asterisk_format True if the value in format is to be used.
|
||||
* \param format Format
|
||||
* \param code from AST_RTP list
|
||||
*
|
||||
* \retval 0 Success
|
||||
* \retval non-0 Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_m_add_format(struct ast_sdp_m_line *m_line, const struct ast_sdp_options *options,
|
||||
int rtp_code, int asterisk_format, const struct ast_format *format, int code);
|
||||
|
||||
/*!
|
||||
* \brief Create an SDP ao2 object
|
||||
*
|
||||
* \param o_line Origin
|
||||
* \param c_line Connection
|
||||
* \param s_line Session
|
||||
* \param t_line Timing
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
struct ast_sdp *ast_sdp_alloc(struct ast_sdp_o_line *o_line,
|
||||
struct ast_sdp_c_line *c_line, struct ast_sdp_s_line *s_line,
|
||||
struct ast_sdp_t_line *t_line);
|
||||
|
||||
/*!
|
||||
* \brief Find the first attribute match index in the top-level SDP
|
||||
*
|
||||
* \note This will not search within streams for the given attribute.
|
||||
*
|
||||
* \param sdp The SDP in which to search
|
||||
* \param attr_name The name of the attribute to search for
|
||||
* \param payload Optional payload number to search for. If irrelevant, set to -1
|
||||
*
|
||||
* \retval index of attribute line on success.
|
||||
* \retval -1 on failure or not found.
|
||||
*
|
||||
* \since 15.0.0
|
||||
*/
|
||||
int ast_sdp_find_a_first(const struct ast_sdp *sdp, const char *attr_name, int payload);
|
||||
|
||||
/*!
|
||||
* \brief Find the next attribute match index in the top-level SDP
|
||||
*
|
||||
* \note This will not search within streams for the given attribute.
|
||||
*
|
||||
* \param sdp The SDP in which to search
|
||||
* \param last The last matching index found
|
||||
* \param attr_name The name of the attribute to search for
|
||||
* \param payload Optional payload number to search for. If irrelevant, set to -1
|
||||
*
|
||||
* \retval index of attribute line on success.
|
||||
* \retval -1 on failure or not found.
|
||||
*
|
||||
* \since 15.0.0
|
||||
*/
|
||||
int ast_sdp_find_a_next(const struct ast_sdp *sdp, int last, const char *attr_name, int payload);
|
||||
|
||||
/*!
|
||||
* \brief Find an attribute in the top-level SDP
|
||||
*
|
||||
* \note This will not search within streams for the given attribute.
|
||||
*
|
||||
* \param sdp The SDP in which to search
|
||||
* \param attr_name The name of the attribute to search for
|
||||
* \param payload Optional payload number to search for. If irrelevant, set to -1
|
||||
*
|
||||
* \retval NULL Could not find the given attribute
|
||||
* \retval Non-NULL The attribute to find
|
||||
*
|
||||
* \since 15.0.0
|
||||
*/
|
||||
struct ast_sdp_a_line *ast_sdp_find_attribute(const struct ast_sdp *sdp,
|
||||
const char *attr_name, int payload);
|
||||
|
||||
/*!
|
||||
* \brief Find the first attribute match index in an SDP stream (m-line)
|
||||
*
|
||||
* \param m_line The SDP m-line in which to search
|
||||
* \param attr_name The name of the attribute to search for
|
||||
* \param payload Optional payload number to search for. If irrelevant, set to -1
|
||||
*
|
||||
* \retval index of attribute line on success.
|
||||
* \retval -1 on failure or not found.
|
||||
*
|
||||
* \since 15.0.0
|
||||
*/
|
||||
int ast_sdp_m_find_a_first(const struct ast_sdp_m_line *m_line, const char *attr_name,
|
||||
int payload);
|
||||
|
||||
/*!
|
||||
* \brief Find the next attribute match index in an SDP stream (m-line)
|
||||
*
|
||||
* \param m_line The SDP m-line in which to search
|
||||
* \param last The last matching index found
|
||||
* \param attr_name The name of the attribute to search for
|
||||
* \param payload Optional payload number to search for. If irrelevant, set to -1
|
||||
*
|
||||
* \retval index of attribute line on success.
|
||||
* \retval -1 on failure or not found.
|
||||
*
|
||||
* \since 15.0.0
|
||||
*/
|
||||
int ast_sdp_m_find_a_next(const struct ast_sdp_m_line *m_line, int last,
|
||||
const char *attr_name, int payload);
|
||||
|
||||
/*!
|
||||
* \brief Find an attribute in an SDP stream (m-line)
|
||||
*
|
||||
* \param m_line The SDP m-line in which to search
|
||||
* \param attr_name The name of the attribute to search for
|
||||
* \param payload Optional payload number to search for. If irrelevant, set to -1
|
||||
*
|
||||
* \retval NULL Could not find the given attribute
|
||||
* \retval Non-NULL The attribute to find
|
||||
*
|
||||
* \since 15.0.0
|
||||
*/
|
||||
struct ast_sdp_a_line *ast_sdp_m_find_attribute(const struct ast_sdp_m_line *m_line,
|
||||
const char *attr_name, int payload);
|
||||
|
||||
/*!
|
||||
* \brief Convert an SDP a_line into an rtpmap
|
||||
*
|
||||
* The returned value is heap-allocated and must be freed with
|
||||
* ast_sdp_rtpmap_free()
|
||||
*
|
||||
* \param a_line The SDP a_line to convert
|
||||
*
|
||||
* \retval NULL Fail
|
||||
* \retval non-NULL Success
|
||||
*
|
||||
* \since 15.0.0
|
||||
*/
|
||||
struct ast_sdp_rtpmap *ast_sdp_a_get_rtpmap(const struct ast_sdp_a_line *a_line);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Allocate a new SDP rtpmap
|
||||
*
|
||||
* \param payload The RTP payload number
|
||||
* \param encoding_name The human-readable name for the codec
|
||||
* \param clock_rate The rate of the codec, in cycles per second
|
||||
* \param encoding_parameters Optional codec-specific parameters (such as number of channels)
|
||||
*
|
||||
* \retval NULL Fail
|
||||
* \retval non-NULL Success
|
||||
*
|
||||
* \since 15.0.0
|
||||
*/
|
||||
struct ast_sdp_rtpmap *ast_sdp_rtpmap_alloc(int payload, const char *encoding_name,
|
||||
int clock_rate, const char *encoding_parameters);
|
||||
|
||||
/*!
|
||||
* \brief Free an SDP rtpmap
|
||||
*
|
||||
* \since 15.0.0
|
||||
*/
|
||||
void ast_sdp_rtpmap_free(struct ast_sdp_rtpmap *rtpmap);
|
||||
|
||||
/*!
|
||||
* \brief Turn an SDP into a stream topology
|
||||
*
|
||||
* This traverses the m-lines of the SDP and creates a stream topology, with
|
||||
* each m-line corresponding to a stream in the created topology.
|
||||
*
|
||||
* \param sdp The SDP to convert
|
||||
* \param g726_non_standard Non-zero if G.726 is non-standard
|
||||
*
|
||||
* \retval NULL An error occurred when converting
|
||||
* \retval non-NULL The generated stream topology
|
||||
*
|
||||
* \since 15.0.0
|
||||
*/
|
||||
struct ast_stream_topology *ast_get_topology_from_sdp(const struct ast_sdp *sdp, int g726_non_standard);
|
||||
#endif /* _SDP_PRIV_H */
|
|
@ -1,774 +0,0 @@
|
|||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2017, Digium, Inc.
|
||||
*
|
||||
* Mark Michelson <mmichelson@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_SDP_OPTIONS_H
|
||||
#define _ASTERISK_SDP_OPTIONS_H
|
||||
|
||||
#include "asterisk/udptl.h"
|
||||
#include "asterisk/format_cap.h"
|
||||
|
||||
struct ast_sdp_options;
|
||||
|
||||
/*!
|
||||
* \brief SDP DTMF mode options
|
||||
*/
|
||||
enum ast_sdp_options_dtmf {
|
||||
/*! No DTMF to be used */
|
||||
AST_SDP_DTMF_NONE,
|
||||
/*! Use RFC 4733 events for DTMF */
|
||||
AST_SDP_DTMF_RFC_4733,
|
||||
/*! Use DTMF in the audio stream */
|
||||
AST_SDP_DTMF_INBAND,
|
||||
/*! Use SIP 4733 if supported by the other side or INBAND if not */
|
||||
AST_SDP_DTMF_AUTO,
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief ICE options
|
||||
*
|
||||
* This is an enum because it will support a TRICKLE-ICE option
|
||||
* in the future.
|
||||
*/
|
||||
enum ast_sdp_options_ice {
|
||||
/*! ICE is not enabled on this session */
|
||||
AST_SDP_ICE_DISABLED,
|
||||
/*! Standard ICE is enabled on this session */
|
||||
AST_SDP_ICE_ENABLED_STANDARD,
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Implementation of the SDP
|
||||
*
|
||||
* Users of the SDP API set the implementation based on what they
|
||||
* natively handle. This indicates the type of SDP that the API expects
|
||||
* when being given an SDP, and it indicates the type of SDP that the API
|
||||
* returns when asked for one.
|
||||
*/
|
||||
enum ast_sdp_options_impl {
|
||||
/*! SDP is represented as a string */
|
||||
AST_SDP_IMPL_STRING,
|
||||
/*! SDP is represented as a pjmedia_sdp_session */
|
||||
AST_SDP_IMPL_PJMEDIA,
|
||||
/*! End of the list */
|
||||
AST_SDP_IMPL_END,
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief SDP encryption options
|
||||
*/
|
||||
enum ast_sdp_options_encryption {
|
||||
/*! No encryption */
|
||||
AST_SDP_ENCRYPTION_DISABLED,
|
||||
/*! SRTP SDES encryption */
|
||||
AST_SDP_ENCRYPTION_SRTP_SDES,
|
||||
/*! DTLS encryption */
|
||||
AST_SDP_ENCRYPTION_DTLS,
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Callback when processing an offer SDP for our answer SDP.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \details
|
||||
* This callback is called after merging our last negotiated topology
|
||||
* with the remote's offer topology and before we have sent our answer
|
||||
* SDP. At this point you can alter new_topology streams. You can
|
||||
* decline, remove formats, or rename streams. Changing anything else
|
||||
* on the streams is likely to not end well.
|
||||
*
|
||||
* * To decline a stream simply set the stream state to
|
||||
* AST_STREAM_STATE_REMOVED. You could implement a maximum number
|
||||
* of active streams of a given type policy.
|
||||
*
|
||||
* * To remove formats use the format API to remove any formats from a
|
||||
* stream. The streams have the current joint negotiated formats.
|
||||
* Most likely you would want to remove all but the first format.
|
||||
*
|
||||
* * To rename a stream you need to clone the stream and give it a
|
||||
* new name and then set it in new_topology using
|
||||
* ast_stream_topology_set_stream().
|
||||
*
|
||||
* \note Removing all formats is an error. You should decline the
|
||||
* stream instead.
|
||||
*
|
||||
* \param context User supplied context data pointer for the SDP
|
||||
* state.
|
||||
* \param old_topology Active negotiated topology. NULL if this is
|
||||
* the first SDP negotiation. The old topology is available so you
|
||||
* can tell if any streams are new or changing type.
|
||||
* \param new_topology New negotiated topology that we intend to
|
||||
* generate the answer SDP.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
typedef void (*ast_sdp_answerer_modify_cb)(void *context,
|
||||
const struct ast_stream_topology *old_topology,
|
||||
struct ast_stream_topology *new_topology);
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Callback when generating a topology for our SDP offer.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \details
|
||||
* This callback is called after merging any topology updates from the
|
||||
* system by ast_sdp_state_update_local_topology() and before we have
|
||||
* sent our offer SDP. At this point you can alter new_topology
|
||||
* streams. You can decline, add/remove/update formats, or rename
|
||||
* streams. Changing anything else on the streams is likely to not
|
||||
* end well.
|
||||
*
|
||||
* * To decline a stream simply set the stream state to
|
||||
* AST_STREAM_STATE_REMOVED. You could implement a maximum number
|
||||
* of active streams of a given type policy.
|
||||
*
|
||||
* * To update formats use the format API to change formats of the
|
||||
* streams. The streams have the current proposed formats. You
|
||||
* could do whatever you want for formats but you should stay within
|
||||
* the configured formats for the stream type's endpoint. However,
|
||||
* you should use ast_sdp_state_update_local_topology() instead of
|
||||
* this backdoor method.
|
||||
*
|
||||
* * To rename a stream you need to clone the stream and give it a
|
||||
* new name and then set it in new_topology using
|
||||
* ast_stream_topology_set_stream().
|
||||
*
|
||||
* \note Removing all formats is an error. You should decline the
|
||||
* stream instead.
|
||||
*
|
||||
* \note Declined new streams that are in slots higher than present in
|
||||
* old_topology are removed so the SDP can be smaller. The remote has
|
||||
* never seen those slots so we shouldn't bother keeping them.
|
||||
*
|
||||
* \param context User supplied context data pointer for the SDP
|
||||
* state.
|
||||
* \param old_topology Active negotiated topology. NULL if this is
|
||||
* the first SDP negotiation. The old topology is available so you
|
||||
* can tell if any streams are new or changing type.
|
||||
* \param new_topology Merged topology that we intend to generate the
|
||||
* offer SDP.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
typedef void (*ast_sdp_offerer_modify_cb)(void *context,
|
||||
const struct ast_stream_topology *old_topology,
|
||||
struct ast_stream_topology *new_topology);
|
||||
|
||||
/*!
|
||||
* \brief Callback when generating an offer SDP to configure extra stream data.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \details
|
||||
* This callback is called after any ast_sdp_offerer_modify_cb
|
||||
* callback and before we have sent our offer SDP. The callback can
|
||||
* call several SDP API calls to configure the proposed capabilities
|
||||
* of streams before we create the SDP offer. For example, the
|
||||
* callback could configure a stream specific connection address, T.38
|
||||
* parameters, RTP instance, or UDPTL instance parameters.
|
||||
*
|
||||
* \param context User supplied context data pointer for the SDP
|
||||
* state.
|
||||
* \param topology Topology ready to configure extra stream options.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
typedef void (*ast_sdp_offerer_config_cb)(void *context, const struct ast_stream_topology *topology);
|
||||
|
||||
/*!
|
||||
* \brief Callback before applying a topology.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \details
|
||||
* This callback is called before the topology is applied so the
|
||||
* using module can do what is necessary before the topology becomes
|
||||
* active.
|
||||
*
|
||||
* \param context User supplied context data pointer for the SDP
|
||||
* state.
|
||||
* \param topology Topology ready to be applied.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
typedef void (*ast_sdp_preapply_cb)(void *context, const struct ast_stream_topology *topology);
|
||||
|
||||
/*!
|
||||
* \brief Callback after applying a topology.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \details
|
||||
* This callback is called after the topology is applied so the
|
||||
* using module can do what is necessary after the topology becomes
|
||||
* active.
|
||||
*
|
||||
* \param context User supplied context data pointer for the SDP
|
||||
* state.
|
||||
* \param topology Topology already applied.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
typedef void (*ast_sdp_postapply_cb)(void *context, const struct ast_stream_topology *topology);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Allocate a new SDP options structure.
|
||||
*
|
||||
* This will heap-allocate an SDP options structure and
|
||||
* initialize it to a set of default values.
|
||||
*
|
||||
* \retval NULL Allocation failure
|
||||
* \retval non-NULL Newly allocated SDP options
|
||||
*/
|
||||
struct ast_sdp_options *ast_sdp_options_alloc(void);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Free an SDP options structure.
|
||||
*
|
||||
* \note This only needs to be called if an error occurs between
|
||||
* options allocation and a call to ast_sdp_state_alloc()
|
||||
* Otherwise, the SDP state will take care of freeing the
|
||||
* options for you.
|
||||
*
|
||||
* \param options The options to free
|
||||
*/
|
||||
void ast_sdp_options_free(struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options media_address
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param media_address
|
||||
*/
|
||||
void ast_sdp_options_set_media_address(struct ast_sdp_options *options,
|
||||
const char *media_address);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options media_address
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns media_address
|
||||
*/
|
||||
const char *ast_sdp_options_get_media_address(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options interface_address
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param interface_address
|
||||
*/
|
||||
void ast_sdp_options_set_interface_address(struct ast_sdp_options *options,
|
||||
const char *interface_address);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options interface_address
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns interface_address
|
||||
*/
|
||||
const char *ast_sdp_options_get_interface_address(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options sdpowner
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param sdpowner
|
||||
*/
|
||||
void ast_sdp_options_set_sdpowner(struct ast_sdp_options *options,
|
||||
const char *sdpowner);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options sdpowner
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns sdpowner
|
||||
*/
|
||||
const char *ast_sdp_options_get_sdpowner(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options sdpsession
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param sdpsession
|
||||
*/
|
||||
void ast_sdp_options_set_sdpsession(struct ast_sdp_options *options,
|
||||
const char *sdpsession);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options sdpsession
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns sdpsession
|
||||
*/
|
||||
const char *ast_sdp_options_get_sdpsession(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options rtp_engine
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param rtp_engine
|
||||
*/
|
||||
void ast_sdp_options_set_rtp_engine(struct ast_sdp_options *options,
|
||||
const char *rtp_engine);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options rtp_engine
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns rtp_engine
|
||||
*/
|
||||
const char *ast_sdp_options_get_rtp_engine(const struct ast_sdp_options *options);
|
||||
|
||||
void ast_sdp_options_set_state_context(struct ast_sdp_options *options, void *state_context);
|
||||
void *ast_sdp_options_get_state_context(const struct ast_sdp_options *options);
|
||||
|
||||
void ast_sdp_options_set_answerer_modify_cb(struct ast_sdp_options *options, ast_sdp_answerer_modify_cb answerer_modify_cb);
|
||||
ast_sdp_answerer_modify_cb ast_sdp_options_get_answerer_modify_cb(const struct ast_sdp_options *options);
|
||||
|
||||
void ast_sdp_options_set_offerer_modify_cb(struct ast_sdp_options *options, ast_sdp_offerer_modify_cb offerer_modify_cb);
|
||||
ast_sdp_offerer_modify_cb ast_sdp_options_get_offerer_modify_cb(const struct ast_sdp_options *options);
|
||||
|
||||
void ast_sdp_options_set_offerer_config_cb(struct ast_sdp_options *options, ast_sdp_offerer_config_cb offerer_config_cb);
|
||||
ast_sdp_offerer_config_cb ast_sdp_options_get_offerer_config_cb(const struct ast_sdp_options *options);
|
||||
|
||||
void ast_sdp_options_set_preapply_cb(struct ast_sdp_options *options, ast_sdp_preapply_cb preapply_cb);
|
||||
ast_sdp_preapply_cb ast_sdp_options_get_preapply_cb(const struct ast_sdp_options *options);
|
||||
|
||||
void ast_sdp_options_set_postapply_cb(struct ast_sdp_options *options, ast_sdp_postapply_cb postapply_cb);
|
||||
ast_sdp_postapply_cb ast_sdp_options_get_postapply_cb(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options rtp_symmetric
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param rtp_symmetric
|
||||
*/
|
||||
void ast_sdp_options_set_rtp_symmetric(struct ast_sdp_options *options,
|
||||
unsigned int rtp_symmetric);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options rtp_symmetric
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns rtp_symmetric
|
||||
*/
|
||||
unsigned int ast_sdp_options_get_rtp_symmetric(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options rtp_ipv6
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param rtp_ipv6
|
||||
*/
|
||||
void ast_sdp_options_set_rtp_ipv6(struct ast_sdp_options *options,
|
||||
unsigned int rtp_ipv6);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options rtp_ipv6
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns rtp_ipv6
|
||||
*/
|
||||
unsigned int ast_sdp_options_get_rtp_ipv6(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options g726_non_standard
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param g726_non_standard
|
||||
*/
|
||||
void ast_sdp_options_set_g726_non_standard(struct ast_sdp_options *options,
|
||||
unsigned int g726_non_standard);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options g726_non_standard
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns g726_non_standard
|
||||
*/
|
||||
unsigned int ast_sdp_options_get_g726_non_standard(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options tos_audio
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param tos_audio
|
||||
*/
|
||||
void ast_sdp_options_set_tos_audio(struct ast_sdp_options *options,
|
||||
unsigned int tos_audio);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options tos_audio
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns tos_audio
|
||||
*/
|
||||
unsigned int ast_sdp_options_get_tos_audio(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options cos_audio
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param cos_audio
|
||||
*/
|
||||
void ast_sdp_options_set_cos_audio(struct ast_sdp_options *options,
|
||||
unsigned int cos_audio);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options cos_audio
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns cos_audio
|
||||
*/
|
||||
unsigned int ast_sdp_options_get_cos_audio(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options tos_video
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param tos_video
|
||||
*/
|
||||
void ast_sdp_options_set_tos_video(struct ast_sdp_options *options,
|
||||
unsigned int tos_video);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options tos_video
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns tos_video
|
||||
*/
|
||||
unsigned int ast_sdp_options_get_tos_video(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options cos_video
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param cos_video
|
||||
*/
|
||||
void ast_sdp_options_set_cos_video(struct ast_sdp_options *options,
|
||||
unsigned int cos_video);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options cos_video
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns cos_video
|
||||
*/
|
||||
unsigned int ast_sdp_options_get_cos_video(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options dtmf
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param dtmf
|
||||
*/
|
||||
void ast_sdp_options_set_dtmf(struct ast_sdp_options *options,
|
||||
enum ast_sdp_options_dtmf dtmf);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options dtmf
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns dtmf
|
||||
*/
|
||||
enum ast_sdp_options_dtmf ast_sdp_options_get_dtmf(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options ice
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param ice
|
||||
*/
|
||||
void ast_sdp_options_set_ice(struct ast_sdp_options *options,
|
||||
enum ast_sdp_options_ice ice);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options ice
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns ice
|
||||
*/
|
||||
enum ast_sdp_options_ice ast_sdp_options_get_ice(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options impl
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param impl
|
||||
*/
|
||||
void ast_sdp_options_set_impl(struct ast_sdp_options *options,
|
||||
enum ast_sdp_options_impl impl);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options impl
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns impl
|
||||
*/
|
||||
enum ast_sdp_options_impl ast_sdp_options_get_impl(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options encryption
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param encryption
|
||||
*/
|
||||
void ast_sdp_options_set_encryption(struct ast_sdp_options *options,
|
||||
enum ast_sdp_options_encryption encryption);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options encryption
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns encryption
|
||||
*/
|
||||
enum ast_sdp_options_encryption ast_sdp_options_get_encryption(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options RTCP MUX
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns Boolean indicating if RTCP MUX is enabled.
|
||||
*/
|
||||
unsigned int ast_sdp_options_get_rtcp_mux(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options RTCP MUX
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param value Boolean that indicates if RTCP MUX should be enabled.
|
||||
*/
|
||||
void ast_sdp_options_set_rtcp_mux(struct ast_sdp_options *options, unsigned int value);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options udptl_symmetric
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param udptl_symmetric
|
||||
*/
|
||||
void ast_sdp_options_set_udptl_symmetric(struct ast_sdp_options *options,
|
||||
unsigned int udptl_symmetric);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options udptl_symmetric
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns udptl_symmetric
|
||||
*/
|
||||
unsigned int ast_sdp_options_get_udptl_symmetric(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options udptl_error_correction
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param error_correction
|
||||
*/
|
||||
void ast_sdp_options_set_udptl_error_correction(struct ast_sdp_options *options,
|
||||
enum ast_t38_ec_modes error_correction);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options udptl_error_correction
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns udptl_error_correction
|
||||
*/
|
||||
enum ast_t38_ec_modes ast_sdp_options_get_udptl_error_correction(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options udptl_far_max_datagram
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param far_max_datagram
|
||||
*/
|
||||
void ast_sdp_options_set_udptl_far_max_datagram(struct ast_sdp_options *options,
|
||||
unsigned int far_max_datagram);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options udptl_far_max_datagram
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns udptl_far_max_datagram
|
||||
*/
|
||||
unsigned int ast_sdp_options_get_udptl_far_max_datagram(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set SDP Options max_streams
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param max_streams
|
||||
*/
|
||||
void ast_sdp_options_set_max_streams(struct ast_sdp_options *options,
|
||||
unsigned int max_streams);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options max_streams
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns max_streams
|
||||
*/
|
||||
unsigned int ast_sdp_options_get_max_streams(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Enable setting SSRC level attributes on SDPs
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param ssrc Boolean indicating if SSRC attributes should be included in generated SDPs
|
||||
*/
|
||||
void ast_sdp_options_set_ssrc(struct ast_sdp_options *options, unsigned int ssrc);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get SDP Options ssrc
|
||||
*
|
||||
* \param options SDP Options
|
||||
*
|
||||
* \returns Whether SSRC-level attributes will be added to our SDP.
|
||||
*/
|
||||
unsigned int ast_sdp_options_get_ssrc(const struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \brief Set the SDP options scheduler context used to create new streams of the type.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param type Media type the scheduler context is for.
|
||||
* \param sched Scheduler context to use for the specified media type.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
void ast_sdp_options_set_sched_type(struct ast_sdp_options *options,
|
||||
enum ast_media_type type, struct ast_sched_context *sched);
|
||||
|
||||
/*!
|
||||
* \brief Get the SDP options scheduler context used to create new streams of the type.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param type Media type the format cap represents.
|
||||
*
|
||||
* \return The stored scheduler context to create new streams of the type.
|
||||
*/
|
||||
struct ast_sched_context *ast_sdp_options_get_sched_type(const struct ast_sdp_options *options,
|
||||
enum ast_media_type type);
|
||||
|
||||
/*!
|
||||
* \brief Set all allowed stream types to create new streams.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param cap Format capabilities to set all allowed stream types at once.
|
||||
* Could be NULL to disable creating any new streams.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
void ast_sdp_options_set_format_caps(struct ast_sdp_options *options,
|
||||
struct ast_format_cap *cap);
|
||||
|
||||
/*!
|
||||
* \brief Set the SDP options format cap used to create new streams of the type.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param type Media type the format cap represents.
|
||||
* \param cap Format capabilities to use for the specified media type.
|
||||
* Could be NULL to disable creating new streams of type.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
void ast_sdp_options_set_format_cap_type(struct ast_sdp_options *options,
|
||||
enum ast_media_type type, struct ast_format_cap *cap);
|
||||
|
||||
/*!
|
||||
* \brief Get the SDP options format cap used to create new streams of the type.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \param options SDP Options
|
||||
* \param type Media type the format cap represents.
|
||||
*
|
||||
* \retval NULL if stream not allowed to be created.
|
||||
* \retval cap to use in negotiating the new stream.
|
||||
*
|
||||
* \note The returned cap does not have its own ao2 ref.
|
||||
*/
|
||||
struct ast_format_cap *ast_sdp_options_get_format_cap_type(const struct ast_sdp_options *options,
|
||||
enum ast_media_type type);
|
||||
|
||||
#endif /* _ASTERISK_SDP_OPTIONS_H */
|
|
@ -1,345 +0,0 @@
|
|||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2017, Digium, Inc.
|
||||
*
|
||||
* Mark Michelson <mmichelson@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_SDP_STATE_H
|
||||
#define _ASTERISK_SDP_STATE_H
|
||||
|
||||
#include "asterisk/stream.h"
|
||||
#include "asterisk/sdp_options.h"
|
||||
|
||||
struct ast_sdp_state;
|
||||
struct ast_sockaddr;
|
||||
struct ast_udptl;
|
||||
struct ast_control_t38_parameters;
|
||||
|
||||
/*!
|
||||
* \brief Allocate a new SDP state
|
||||
*
|
||||
* \details
|
||||
* SDP state keeps tabs on everything SDP-related for a media session.
|
||||
* Most SDP operations will require the state to be provided.
|
||||
* Ownership of the SDP options is taken on by the SDP state.
|
||||
* A good strategy is to call this during session creation.
|
||||
*
|
||||
* \param topology Initial stream topology to offer.
|
||||
* NULL if we are going to be the answerer. We can always
|
||||
* update the local topology later if it turns out we need
|
||||
* to be the offerer.
|
||||
* \param options SDP options for the duration of the session.
|
||||
*
|
||||
* \retval SDP state struct
|
||||
* \retval NULL on failure
|
||||
*/
|
||||
struct ast_sdp_state *ast_sdp_state_alloc(struct ast_stream_topology *topology,
|
||||
struct ast_sdp_options *options);
|
||||
|
||||
/*!
|
||||
* \brief Free the SDP state.
|
||||
*
|
||||
* A good strategy is to call this during session destruction
|
||||
*/
|
||||
void ast_sdp_state_free(struct ast_sdp_state *sdp_state);
|
||||
|
||||
/*!
|
||||
* \brief Get the associated RTP instance for a particular stream on the SDP state.
|
||||
*
|
||||
* Stream numbers correspond to the streams in the topology of the associated channel
|
||||
*/
|
||||
struct ast_rtp_instance *ast_sdp_state_get_rtp_instance(const struct ast_sdp_state *sdp_state,
|
||||
int stream_index);
|
||||
|
||||
/*!
|
||||
* \brief Get the associated UDPTL instance for a particular stream on the SDP state.
|
||||
*
|
||||
* Stream numbers correspond to the streams in the topology of the associated channel
|
||||
*/
|
||||
struct ast_udptl *ast_sdp_state_get_udptl_instance(const struct ast_sdp_state *sdp_state,
|
||||
int stream_index);
|
||||
|
||||
/*!
|
||||
* \brief Get the global connection address on the SDP state.
|
||||
*/
|
||||
const struct ast_sockaddr *ast_sdp_state_get_connection_address(const struct ast_sdp_state *sdp_state);
|
||||
|
||||
/*!
|
||||
* \brief Get the connection address for a particular stream.
|
||||
*
|
||||
* \param sdp_state
|
||||
* \param stream_index The particular stream to get the connection address of
|
||||
* \param address[out] A place to store the address in
|
||||
*
|
||||
* \retval 0 Success
|
||||
*
|
||||
* \note
|
||||
* Stream numbers correspond to the streams in the topology of the associated channel
|
||||
*/
|
||||
int ast_sdp_state_get_stream_connection_address(const struct ast_sdp_state *sdp_state,
|
||||
int stream_index, struct ast_sockaddr *address);
|
||||
|
||||
/*!
|
||||
* \brief Get the joint negotiated streams based on local and remote capabilities.
|
||||
*
|
||||
* If this is called prior to receiving a remote SDP, then this will just mirror
|
||||
* the local configured endpoint capabilities.
|
||||
*
|
||||
* \note Cannot return NULL. It is a BUG if it does.
|
||||
*/
|
||||
const struct ast_stream_topology *ast_sdp_state_get_joint_topology(
|
||||
const struct ast_sdp_state *sdp_state);
|
||||
|
||||
/*!
|
||||
* \brief Get the local topology
|
||||
*
|
||||
* \note Cannot return NULL. It is a BUG if it does.
|
||||
*/
|
||||
const struct ast_stream_topology *ast_sdp_state_get_local_topology(
|
||||
const struct ast_sdp_state *sdp_state);
|
||||
|
||||
/*!
|
||||
* \brief Get the sdp_state options
|
||||
*
|
||||
*/
|
||||
const struct ast_sdp_options *ast_sdp_state_get_options(
|
||||
const struct ast_sdp_state *sdp_state);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Get the local SDP.
|
||||
*
|
||||
* \param sdp_state
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \note
|
||||
* This function will return the last local SDP created if one were
|
||||
* previously requested for the current negotiation. Otherwise it
|
||||
* creates our SDP offer/answer depending on what role we are playing
|
||||
* in the current negotiation.
|
||||
*/
|
||||
const struct ast_sdp *ast_sdp_state_get_local_sdp(struct ast_sdp_state *sdp_state);
|
||||
|
||||
/*!
|
||||
* \brief Get the local SDP Implementation.
|
||||
*
|
||||
* \param sdp_state
|
||||
*
|
||||
* \retval non-NULL Success
|
||||
* \retval NULL Failure
|
||||
*
|
||||
* \note
|
||||
* This function calls ast_sdp_state_get_local_sdp then translates it into
|
||||
* the defined implementation.
|
||||
*
|
||||
* The return here is const. The use case for this is so that a channel can add
|
||||
* the SDP to an outgoing message. The API user should not attempt to modify the SDP.
|
||||
* SDP modification should only be done through the API.
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
const void *ast_sdp_state_get_local_sdp_impl(struct ast_sdp_state *sdp_state);
|
||||
|
||||
/*!
|
||||
* \brief Set the remote SDP
|
||||
*
|
||||
* \param sdp_state
|
||||
* \param sdp
|
||||
*
|
||||
* \note It is assumed that the passed in SDP has been checked for sanity
|
||||
* already. e.g., There are no syntax errors, a c= line is reachable for
|
||||
* each m= line, etc...
|
||||
*
|
||||
* \retval 0 Success
|
||||
* \retval non-0 Failure
|
||||
* Use ast_sdp_state_is_offer_rejected() to see if the SDP offer was rejected.
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_state_set_remote_sdp(struct ast_sdp_state *sdp_state, const struct ast_sdp *sdp);
|
||||
|
||||
/*!
|
||||
* \brief Set the remote SDP from an Implementation
|
||||
*
|
||||
* \param sdp_state
|
||||
* \param remote The implementation's representation of an SDP.
|
||||
*
|
||||
* \retval 0 Success
|
||||
* \retval non-0 Failure
|
||||
* Use ast_sdp_state_is_offer_rejected() to see if the SDP offer was rejected.
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_state_set_remote_sdp_from_impl(struct ast_sdp_state *sdp_state, const void *remote);
|
||||
|
||||
/*!
|
||||
* \brief Was the set remote offer rejected.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \param sdp_state
|
||||
*
|
||||
* \retval 0 if not rejected.
|
||||
* \retval non-zero if rejected.
|
||||
*/
|
||||
int ast_sdp_state_is_offer_rejected(struct ast_sdp_state *sdp_state);
|
||||
|
||||
/*!
|
||||
* \brief Are we the SDP offerer.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \param sdp_state
|
||||
*
|
||||
* \retval 0 if we are not the offerer.
|
||||
* \retval non-zero we are the offerer.
|
||||
*/
|
||||
int ast_sdp_state_is_offerer(struct ast_sdp_state *sdp_state);
|
||||
|
||||
/*!
|
||||
* \brief Are we the SDP answerer.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \param sdp_state
|
||||
*
|
||||
* \retval 0 if we are not the answerer.
|
||||
* \retval non-zero we are the answerer.
|
||||
*/
|
||||
int ast_sdp_state_is_answerer(struct ast_sdp_state *sdp_state);
|
||||
|
||||
/*!
|
||||
* \brief Restart the SDP offer/answer negotiations.
|
||||
*
|
||||
* \param sdp_state
|
||||
*
|
||||
* \retval 0 Success
|
||||
* \retval non-0 Failure
|
||||
*/
|
||||
int ast_sdp_state_restart_negotiations(struct ast_sdp_state *sdp_state);
|
||||
|
||||
/*!
|
||||
* \brief Update the local stream topology on the SDP state.
|
||||
*
|
||||
* \details
|
||||
* Basically we are saving off any topology updates until we create the
|
||||
* next SDP offer. Repeated updates merge with the previous updated
|
||||
* topology.
|
||||
*
|
||||
* \param sdp_state
|
||||
* \param topology The new stream topology.
|
||||
*
|
||||
* \retval 0 Success
|
||||
* \retval non-0 Failure
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_state_update_local_topology(struct ast_sdp_state *sdp_state, struct ast_stream_topology *topology);
|
||||
|
||||
/*!
|
||||
* \brief Set the local address (IP address) to use for connection addresses
|
||||
*
|
||||
* \param sdp_state
|
||||
* \param address The local address
|
||||
*
|
||||
* \note
|
||||
* Passing NULL as an address will unset the explicit local connection address.
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
void ast_sdp_state_set_local_address(struct ast_sdp_state *sdp_state, struct ast_sockaddr *address);
|
||||
|
||||
/*!
|
||||
* \brief Set the connection address (IP address and port) to use for a specific stream
|
||||
*
|
||||
* \param sdp_state
|
||||
* \param stream_index The stream to set the connection address for
|
||||
* \param address The connection address
|
||||
*
|
||||
* \retval 0 Success
|
||||
*
|
||||
* \note
|
||||
* Passing NULL as an address will unset the explicit local connection address.
|
||||
*
|
||||
* \since 15
|
||||
*/
|
||||
int ast_sdp_state_set_connection_address(struct ast_sdp_state *sdp_state, int stream_index,
|
||||
struct ast_sockaddr *address);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set the global locally held state.
|
||||
*
|
||||
* \param sdp_state
|
||||
* \param locally_held
|
||||
*/
|
||||
void ast_sdp_state_set_global_locally_held(struct ast_sdp_state *sdp_state, unsigned int locally_held);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get the global locally held state.
|
||||
*
|
||||
* \param sdp_state
|
||||
*
|
||||
* \returns locally_held
|
||||
*/
|
||||
unsigned int ast_sdp_state_get_global_locally_held(const struct ast_sdp_state *sdp_state);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set a stream to be held or unheld locally
|
||||
*
|
||||
* \param sdp_state
|
||||
* \param stream_index The stream to set the held value for
|
||||
* \param locally_held
|
||||
*/
|
||||
void ast_sdp_state_set_locally_held(struct ast_sdp_state *sdp_state,
|
||||
int stream_index, unsigned int locally_held);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get whether a stream is locally held or not
|
||||
*
|
||||
* \param sdp_state
|
||||
* \param stream_index The stream to get the held state for
|
||||
*
|
||||
* \returns locally_held
|
||||
*/
|
||||
unsigned int ast_sdp_state_get_locally_held(const struct ast_sdp_state *sdp_state,
|
||||
int stream_index);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Get whether a stream is remotely held or not
|
||||
*
|
||||
* \param sdp_state
|
||||
* \param stream_index The stream to get the held state for
|
||||
*
|
||||
* \returns remotely_held
|
||||
*/
|
||||
unsigned int ast_sdp_state_get_remotely_held(const struct ast_sdp_state *sdp_state,
|
||||
int stream_index);
|
||||
|
||||
/*!
|
||||
* \since 15.0.0
|
||||
* \brief Set the UDPTL session parameters
|
||||
*
|
||||
* \param sdp_state
|
||||
* \param stream_index The stream to set the UDPTL session parameters for
|
||||
* \param params
|
||||
*/
|
||||
void ast_sdp_state_set_t38_parameters(struct ast_sdp_state *sdp_state,
|
||||
int stream_index, struct ast_control_t38_parameters *params);
|
||||
|
||||
#endif /* _ASTERISK_SDP_STATE_H */
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2017, Digium, Inc.
|
||||
*
|
||||
* Mark Michelson <mmichelson@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_SDP_TRANSLATOR_H
|
||||
#define _ASTERISK_SDP_TRANSLATOR_H
|
||||
|
||||
#include "asterisk/sdp_options.h"
|
||||
|
||||
struct sdp;
|
||||
|
||||
/*!
|
||||
* \brief SDP translator operations
|
||||
*/
|
||||
struct ast_sdp_translator_ops {
|
||||
/*! The SDP representation on which this translator operates */
|
||||
enum ast_sdp_options_impl repr;
|
||||
/*! Allocate new translator private data for a translator */
|
||||
void *(*translator_new)(void);
|
||||
/*! Free translator private data */
|
||||
void (*translator_free)(void *translator_priv);
|
||||
/*! Convert the channel-native SDP into an internal Asterisk SDP */
|
||||
struct ast_sdp *(*to_sdp)(const void *repr_sdp, void *translator_priv);
|
||||
/*! Convert an internal Asterisk SDP into a channel-native SDP */
|
||||
const void *(*from_sdp)(const struct ast_sdp *sdp, void *translator_priv);
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief An SDP translator
|
||||
*
|
||||
* An SDP translator is responsible for converting between Asterisk's internal
|
||||
* representation of an SDP and the representation that is native to the channel
|
||||
* driver. Translators are allocated per-use.
|
||||
*/
|
||||
struct ast_sdp_translator {
|
||||
/*! The operations this translator uses */
|
||||
struct ast_sdp_translator_ops *ops;
|
||||
/*! Private data this translator uses */
|
||||
void *translator_priv;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Register an SDP translator
|
||||
* \param ops The SDP operations defined by this translator
|
||||
* \retval 0 Success
|
||||
* \retval -1 FAIL
|
||||
*/
|
||||
int ast_sdp_register_translator(struct ast_sdp_translator_ops *ops);
|
||||
|
||||
/*!
|
||||
* \brief Unregister an SDP translator
|
||||
*/
|
||||
void ast_sdp_unregister_translator(struct ast_sdp_translator_ops *ops);
|
||||
|
||||
/*!
|
||||
* \brief Allocate a new SDP translator
|
||||
* \param Representation corresponding to the translator_ops to use
|
||||
* \retval NULL FAIL
|
||||
* \retval non-NULL New SDP translator
|
||||
*/
|
||||
struct ast_sdp_translator *ast_sdp_translator_new(enum ast_sdp_options_impl repr);
|
||||
|
||||
/*!
|
||||
* \brief Free an SDP translator
|
||||
*/
|
||||
void ast_sdp_translator_free(struct ast_sdp_translator *translator);
|
||||
|
||||
/*!
|
||||
* \brief Translate a native SDP to internal Asterisk SDP
|
||||
*
|
||||
* \param translator The translator to use when translating
|
||||
* \param native_sdp The SDP from the channel driver
|
||||
* \retval NULL FAIL
|
||||
* \retval Non-NULL The translated SDP
|
||||
*/
|
||||
struct ast_sdp *ast_sdp_translator_to_sdp(struct ast_sdp_translator *translator, const void *native_sdp);
|
||||
|
||||
/*!
|
||||
* \brief Translate an internal Asterisk SDP to a native SDP
|
||||
*
|
||||
* \param translator The translator to use when translating
|
||||
* \param ast_sdp The Asterisk SDP to translate
|
||||
* \retval NULL FAIL
|
||||
* \retval non-NULL The translated SDP
|
||||
*/
|
||||
const void *ast_sdp_translator_from_sdp(struct ast_sdp_translator *translator,
|
||||
const struct ast_sdp *ast_sdp);
|
||||
|
||||
#endif /* _ASTERISK_SDP_TRANSLATOR_H */
|
950
main/sdp.c
950
main/sdp.c
|
@ -1,950 +0,0 @@
|
|||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2017, Digium, Inc.
|
||||
*
|
||||
* George Joseph <gjoseph@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
#include "asterisk.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/netsock2.h"
|
||||
#include "asterisk/codec.h"
|
||||
#include "asterisk/format.h"
|
||||
#include "asterisk/format_cap.h"
|
||||
#include "asterisk/format_cache.h"
|
||||
#include "asterisk/rtp_engine.h"
|
||||
#include "asterisk/sdp_state.h"
|
||||
#include "asterisk/sdp_options.h"
|
||||
#include "asterisk/sdp_translator.h"
|
||||
#include "asterisk/sdp.h"
|
||||
#include "asterisk/vector.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/stream.h"
|
||||
#include "sdp_private.h"
|
||||
|
||||
void ast_sdp_a_free(struct ast_sdp_a_line *a_line)
|
||||
{
|
||||
ast_free(a_line);
|
||||
}
|
||||
|
||||
void ast_sdp_a_lines_free(struct ast_sdp_a_lines *a_lines)
|
||||
{
|
||||
if (!a_lines) {
|
||||
return;
|
||||
}
|
||||
|
||||
AST_VECTOR_CALLBACK_VOID(a_lines, ast_sdp_a_free);
|
||||
AST_VECTOR_FREE(a_lines);
|
||||
ast_free(a_lines);
|
||||
}
|
||||
|
||||
void ast_sdp_c_free(struct ast_sdp_c_line *c_line)
|
||||
{
|
||||
ast_free(c_line);
|
||||
}
|
||||
|
||||
void ast_sdp_payload_free(struct ast_sdp_payload *payload)
|
||||
{
|
||||
ast_free(payload);
|
||||
}
|
||||
|
||||
void ast_sdp_payloads_free(struct ast_sdp_payloads *payloads)
|
||||
{
|
||||
if (!payloads) {
|
||||
return;
|
||||
}
|
||||
|
||||
AST_VECTOR_CALLBACK_VOID(payloads, ast_sdp_payload_free);
|
||||
AST_VECTOR_FREE(payloads);
|
||||
ast_free(payloads);
|
||||
}
|
||||
|
||||
void ast_sdp_m_free(struct ast_sdp_m_line *m_line)
|
||||
{
|
||||
if (!m_line) {
|
||||
return;
|
||||
}
|
||||
|
||||
ast_sdp_a_lines_free(m_line->a_lines);
|
||||
ast_sdp_payloads_free(m_line->payloads);
|
||||
ast_sdp_c_free(m_line->c_line);
|
||||
ast_free(m_line);
|
||||
}
|
||||
|
||||
void ast_sdp_m_lines_free(struct ast_sdp_m_lines *m_lines)
|
||||
{
|
||||
if (!m_lines) {
|
||||
return;
|
||||
}
|
||||
|
||||
AST_VECTOR_CALLBACK_VOID(m_lines, ast_sdp_m_free);
|
||||
AST_VECTOR_FREE(m_lines);
|
||||
ast_free(m_lines);
|
||||
}
|
||||
|
||||
void ast_sdp_o_free(struct ast_sdp_o_line *o_line)
|
||||
{
|
||||
ast_free(o_line);
|
||||
}
|
||||
|
||||
void ast_sdp_s_free(struct ast_sdp_s_line *s_line)
|
||||
{
|
||||
ast_free(s_line);
|
||||
}
|
||||
|
||||
void ast_sdp_t_free(struct ast_sdp_t_line *t_line)
|
||||
{
|
||||
ast_free(t_line);
|
||||
}
|
||||
|
||||
static void ast_sdp_dtor(void *vdoomed)
|
||||
{
|
||||
struct ast_sdp *sdp = vdoomed;
|
||||
|
||||
ast_sdp_o_free(sdp->o_line);
|
||||
ast_sdp_s_free(sdp->s_line);
|
||||
ast_sdp_c_free(sdp->c_line);
|
||||
ast_sdp_t_free(sdp->t_line);
|
||||
ast_sdp_a_lines_free(sdp->a_lines);
|
||||
ast_sdp_m_lines_free(sdp->m_lines);
|
||||
}
|
||||
|
||||
#define COPY_STR_AND_ADVANCE(p, dest, source) \
|
||||
({ \
|
||||
dest = p; \
|
||||
strcpy(dest, source); \
|
||||
p += (strlen(source) + 1); \
|
||||
})
|
||||
|
||||
struct ast_sdp_a_line *ast_sdp_a_alloc(const char *name, const char *value)
|
||||
{
|
||||
struct ast_sdp_a_line *a_line;
|
||||
size_t len;
|
||||
char *p;
|
||||
|
||||
ast_assert(!ast_strlen_zero(name));
|
||||
|
||||
if (ast_strlen_zero(value)) {
|
||||
value = "";
|
||||
}
|
||||
|
||||
len = sizeof(*a_line) + strlen(name) + strlen(value) + 2;
|
||||
a_line = ast_calloc(1, len);
|
||||
if (!a_line) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = ((char *)a_line) + sizeof(*a_line);
|
||||
|
||||
COPY_STR_AND_ADVANCE(p, a_line->name, name);
|
||||
COPY_STR_AND_ADVANCE(p, a_line->value, value);
|
||||
|
||||
return a_line;
|
||||
}
|
||||
|
||||
struct ast_sdp_c_line *ast_sdp_c_alloc(const char *address_type, const char *address)
|
||||
{
|
||||
struct ast_sdp_c_line *c_line;
|
||||
size_t len;
|
||||
char *p;
|
||||
|
||||
ast_assert(!ast_strlen_zero(address_type) && !ast_strlen_zero(address));
|
||||
|
||||
len = sizeof(*c_line) + strlen(address_type) + strlen(address) + 2;
|
||||
c_line = ast_calloc(1, len);
|
||||
if (!c_line) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = ((char *)c_line) + sizeof(*c_line);
|
||||
|
||||
COPY_STR_AND_ADVANCE(p, c_line->address_type, address_type);
|
||||
COPY_STR_AND_ADVANCE(p, c_line->address, address);
|
||||
|
||||
return c_line;
|
||||
}
|
||||
|
||||
struct ast_sdp_payload *ast_sdp_payload_alloc(const char *fmt)
|
||||
{
|
||||
struct ast_sdp_payload *payload;
|
||||
size_t len;
|
||||
|
||||
ast_assert(!ast_strlen_zero(fmt));
|
||||
|
||||
len = sizeof(*payload) + strlen(fmt) + 1;
|
||||
payload = ast_calloc(1, len);
|
||||
if (!payload) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
payload->fmt = ((char *)payload) + sizeof(*payload);
|
||||
strcpy(payload->fmt, fmt); /* Safe */
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
struct ast_sdp_m_line *ast_sdp_m_alloc(const char *type, uint16_t port,
|
||||
uint16_t port_count, const char *proto, struct ast_sdp_c_line *c_line)
|
||||
{
|
||||
struct ast_sdp_m_line *m_line;
|
||||
size_t len;
|
||||
char *p;
|
||||
|
||||
ast_assert(!ast_strlen_zero(type) && !ast_strlen_zero(proto));
|
||||
|
||||
len = sizeof(*m_line) + strlen(type) + strlen(proto) + 2;
|
||||
m_line = ast_calloc(1, len);
|
||||
if (!m_line) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_line->a_lines = ast_calloc(1, sizeof(*m_line->a_lines));
|
||||
if (!m_line->a_lines) {
|
||||
ast_sdp_m_free(m_line);
|
||||
return NULL;
|
||||
}
|
||||
if (AST_VECTOR_INIT(m_line->a_lines, 20)) {
|
||||
ast_sdp_m_free(m_line);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_line->payloads = ast_calloc(1, sizeof(*m_line->payloads));
|
||||
if (!m_line->payloads) {
|
||||
ast_sdp_m_free(m_line);
|
||||
return NULL;
|
||||
}
|
||||
if (AST_VECTOR_INIT(m_line->payloads, 20)) {
|
||||
ast_sdp_m_free(m_line);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = ((char *)m_line) + sizeof(*m_line);
|
||||
|
||||
COPY_STR_AND_ADVANCE(p, m_line->type, type);
|
||||
COPY_STR_AND_ADVANCE(p, m_line->proto, proto);
|
||||
m_line->port = port;
|
||||
m_line->port_count = port_count;
|
||||
m_line->c_line = c_line;
|
||||
|
||||
return m_line;
|
||||
}
|
||||
|
||||
struct ast_sdp_s_line *ast_sdp_s_alloc(const char *session_name)
|
||||
{
|
||||
struct ast_sdp_s_line *s_line;
|
||||
size_t len;
|
||||
|
||||
if (ast_strlen_zero(session_name)) {
|
||||
session_name = " ";
|
||||
}
|
||||
|
||||
len = sizeof(*s_line) + strlen(session_name) + 1;
|
||||
s_line = ast_calloc(1, len);
|
||||
if (!s_line) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s_line->session_name = ((char *)s_line) + sizeof(*s_line);
|
||||
strcpy(s_line->session_name, session_name); /* Safe */
|
||||
|
||||
return s_line;
|
||||
}
|
||||
|
||||
struct ast_sdp_t_line *ast_sdp_t_alloc(uint64_t start_time, uint64_t stop_time)
|
||||
{
|
||||
struct ast_sdp_t_line *t_line;
|
||||
|
||||
t_line = ast_calloc(1, sizeof(*t_line));
|
||||
if (!t_line) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
t_line->start_time = start_time;
|
||||
t_line->stop_time = stop_time;
|
||||
|
||||
return t_line;
|
||||
}
|
||||
|
||||
struct ast_sdp_o_line *ast_sdp_o_alloc(const char *username, uint64_t session_id,
|
||||
uint64_t session_version, const char *address_type, const char *address)
|
||||
{
|
||||
struct ast_sdp_o_line *o_line;
|
||||
size_t len;
|
||||
char *p;
|
||||
|
||||
ast_assert(!ast_strlen_zero(username) && !ast_strlen_zero(address_type)
|
||||
&& !ast_strlen_zero(address));
|
||||
|
||||
len = sizeof(*o_line) + strlen(username) + strlen(address_type) + strlen(address) + 3;
|
||||
o_line = ast_calloc(1, len);
|
||||
if (!o_line) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
o_line->session_id = session_id;
|
||||
o_line->session_version = session_version;
|
||||
|
||||
p = ((char *)o_line) + sizeof(*o_line);
|
||||
|
||||
COPY_STR_AND_ADVANCE(p, o_line->username, username);
|
||||
COPY_STR_AND_ADVANCE(p, o_line->address_type, address_type);
|
||||
COPY_STR_AND_ADVANCE(p, o_line->address, address);
|
||||
|
||||
return o_line;
|
||||
}
|
||||
|
||||
struct ast_sdp *ast_sdp_alloc(struct ast_sdp_o_line *o_line,
|
||||
struct ast_sdp_c_line *c_line, struct ast_sdp_s_line *s_line,
|
||||
struct ast_sdp_t_line *t_line)
|
||||
{
|
||||
struct ast_sdp *new_sdp;
|
||||
|
||||
new_sdp = ao2_alloc_options(sizeof(*new_sdp), ast_sdp_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
|
||||
if (!new_sdp) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_sdp->a_lines = ast_calloc(1, sizeof(*new_sdp->a_lines));
|
||||
if (!new_sdp->a_lines) {
|
||||
ao2_ref(new_sdp, -1);
|
||||
return NULL;
|
||||
}
|
||||
if (AST_VECTOR_INIT(new_sdp->a_lines, 20)) {
|
||||
ao2_ref(new_sdp, -1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_sdp->m_lines = ast_calloc(1, sizeof(*new_sdp->m_lines));
|
||||
if (!new_sdp->m_lines) {
|
||||
ao2_ref(new_sdp, -1);
|
||||
return NULL;
|
||||
}
|
||||
if (AST_VECTOR_INIT(new_sdp->m_lines, 20)) {
|
||||
ao2_ref(new_sdp, -1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_sdp->o_line = o_line;
|
||||
new_sdp->c_line = c_line;
|
||||
new_sdp->s_line = s_line;
|
||||
new_sdp->t_line = t_line;
|
||||
|
||||
return new_sdp;
|
||||
}
|
||||
|
||||
int ast_sdp_add_a(struct ast_sdp *sdp, struct ast_sdp_a_line *a_line)
|
||||
{
|
||||
ast_assert(sdp && a_line);
|
||||
|
||||
return AST_VECTOR_APPEND(sdp->a_lines, a_line);
|
||||
}
|
||||
|
||||
int ast_sdp_get_a_count(const struct ast_sdp *sdp)
|
||||
{
|
||||
ast_assert(sdp != NULL);
|
||||
|
||||
return AST_VECTOR_SIZE(sdp->a_lines);
|
||||
}
|
||||
|
||||
struct ast_sdp_a_line *ast_sdp_get_a(const struct ast_sdp *sdp, int index)
|
||||
{
|
||||
ast_assert(sdp != NULL);
|
||||
|
||||
return AST_VECTOR_GET(sdp->a_lines, index);
|
||||
}
|
||||
|
||||
int ast_sdp_add_m(struct ast_sdp *sdp, struct ast_sdp_m_line *m_line)
|
||||
{
|
||||
ast_assert(sdp && m_line);
|
||||
|
||||
return AST_VECTOR_APPEND(sdp->m_lines, m_line);
|
||||
}
|
||||
|
||||
int ast_sdp_get_m_count(const struct ast_sdp *sdp)
|
||||
{
|
||||
ast_assert(sdp != NULL);
|
||||
|
||||
return AST_VECTOR_SIZE(sdp->m_lines);
|
||||
}
|
||||
|
||||
struct ast_sdp_m_line *ast_sdp_get_m(const struct ast_sdp *sdp, int index)
|
||||
{
|
||||
ast_assert(sdp != NULL);
|
||||
|
||||
return AST_VECTOR_GET(sdp->m_lines, index);
|
||||
}
|
||||
|
||||
int ast_sdp_m_add_a(struct ast_sdp_m_line *m_line, struct ast_sdp_a_line *a_line)
|
||||
{
|
||||
ast_assert(m_line && a_line);
|
||||
|
||||
return AST_VECTOR_APPEND(m_line->a_lines, a_line);
|
||||
}
|
||||
|
||||
int ast_sdp_m_get_a_count(const struct ast_sdp_m_line *m_line)
|
||||
{
|
||||
ast_assert(m_line != NULL);
|
||||
|
||||
return AST_VECTOR_SIZE(m_line->a_lines);
|
||||
}
|
||||
|
||||
struct ast_sdp_a_line *ast_sdp_m_get_a(const struct ast_sdp_m_line *m_line, int index)
|
||||
{
|
||||
ast_assert(m_line != NULL);
|
||||
|
||||
return AST_VECTOR_GET(m_line->a_lines, index);
|
||||
}
|
||||
|
||||
int ast_sdp_m_add_payload(struct ast_sdp_m_line *m_line, struct ast_sdp_payload *payload)
|
||||
{
|
||||
ast_assert(m_line && payload);
|
||||
|
||||
return AST_VECTOR_APPEND(m_line->payloads, payload);
|
||||
}
|
||||
|
||||
int ast_sdp_m_get_payload_count(const struct ast_sdp_m_line *m_line)
|
||||
{
|
||||
ast_assert(m_line != NULL);
|
||||
|
||||
return AST_VECTOR_SIZE(m_line->payloads);
|
||||
}
|
||||
|
||||
struct ast_sdp_payload *ast_sdp_m_get_payload(const struct ast_sdp_m_line *m_line, int index)
|
||||
{
|
||||
ast_assert(m_line != NULL);
|
||||
|
||||
return AST_VECTOR_GET(m_line->payloads, index);
|
||||
}
|
||||
|
||||
static int sdp_m_add_fmtp(struct ast_sdp_m_line *m_line, const struct ast_format *format,
|
||||
int rtp_code)
|
||||
{
|
||||
struct ast_str *fmtp0 = ast_str_alloca(256);
|
||||
struct ast_sdp_a_line *a_line;
|
||||
char *tmp;
|
||||
|
||||
ast_format_generate_sdp_fmtp(format, rtp_code, &fmtp0);
|
||||
if (ast_str_strlen(fmtp0) == 0) {
|
||||
/* Format doesn't have fmtp attributes */
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp = ast_str_buffer(fmtp0) + ast_str_strlen(fmtp0) - 1;
|
||||
/* remove any carriage return line feeds */
|
||||
while (*tmp == '\r' || *tmp == '\n') --tmp;
|
||||
*++tmp = '\0';
|
||||
|
||||
/*
|
||||
* ast...generate gives us everything, just need value
|
||||
*
|
||||
* It can also give multiple fmtp attribute lines. (silk does)
|
||||
*/
|
||||
tmp = strchr(ast_str_buffer(fmtp0), ':');
|
||||
if (tmp && tmp[1] != '\0') {
|
||||
tmp++;
|
||||
} else {
|
||||
tmp = ast_str_buffer(fmtp0);
|
||||
}
|
||||
|
||||
a_line = ast_sdp_a_alloc("fmtp", tmp);
|
||||
if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sdp_m_add_rtpmap(struct ast_sdp_m_line *m_line,
|
||||
const struct ast_sdp_options *options, int rtp_code, int asterisk_format,
|
||||
const struct ast_format *format, int code)
|
||||
{
|
||||
char tmp[64];
|
||||
const char *enc_name;
|
||||
struct ast_sdp_payload *payload;
|
||||
struct ast_sdp_a_line *a_line;
|
||||
|
||||
snprintf(tmp, sizeof(tmp), "%d", rtp_code);
|
||||
payload = ast_sdp_payload_alloc(tmp);
|
||||
if (!payload || ast_sdp_m_add_payload(m_line, payload)) {
|
||||
ast_sdp_payload_free(payload);
|
||||
return -1;
|
||||
}
|
||||
|
||||
enc_name = ast_rtp_lookup_mime_subtype2(asterisk_format, format, code,
|
||||
options->g726_non_standard ? AST_RTP_OPT_G726_NONSTANDARD : 0);
|
||||
|
||||
snprintf(tmp, sizeof(tmp), "%d %s/%d%s%s", rtp_code, enc_name,
|
||||
ast_rtp_lookup_sample_rate2(asterisk_format, format, code),
|
||||
strcmp(enc_name, "opus") ? "" : "/", strcmp(enc_name, "opus") ? "" : "2");
|
||||
|
||||
a_line = ast_sdp_a_alloc("rtpmap", tmp);
|
||||
if (!a_line || ast_sdp_m_add_a(m_line, a_line)) {
|
||||
ast_sdp_a_free(a_line);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_sdp_m_add_format(struct ast_sdp_m_line *m_line, const struct ast_sdp_options *options,
|
||||
int rtp_code, int asterisk_format, const struct ast_format *format, int code)
|
||||
{
|
||||
return sdp_m_add_rtpmap(m_line, options, rtp_code, asterisk_format, format, code)
|
||||
|| sdp_m_add_fmtp(m_line, format, rtp_code) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int sdp_find_a_common(const struct ast_sdp_a_lines *a_lines, int start,
|
||||
const char *attr_name, int payload)
|
||||
{
|
||||
struct ast_sdp_a_line *a_line;
|
||||
int idx;
|
||||
|
||||
ast_assert(-1 <= start);
|
||||
|
||||
for (idx = start + 1; idx < AST_VECTOR_SIZE(a_lines); ++idx) {
|
||||
int a_line_payload;
|
||||
|
||||
a_line = AST_VECTOR_GET(a_lines, idx);
|
||||
if (strcmp(a_line->name, attr_name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (payload >= 0) {
|
||||
int sscanf_res;
|
||||
|
||||
sscanf_res = sscanf(a_line->value, "%30d", &a_line_payload);
|
||||
if (sscanf_res == 1 && payload == a_line_payload) {
|
||||
return idx;
|
||||
}
|
||||
} else {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ast_sdp_find_a_first(const struct ast_sdp *sdp, const char *attr_name, int payload)
|
||||
{
|
||||
return sdp_find_a_common(sdp->a_lines, -1, attr_name, payload);
|
||||
}
|
||||
|
||||
int ast_sdp_find_a_next(const struct ast_sdp *sdp, int last, const char *attr_name, int payload)
|
||||
{
|
||||
return sdp_find_a_common(sdp->a_lines, last, attr_name, payload);
|
||||
}
|
||||
|
||||
struct ast_sdp_a_line *ast_sdp_find_attribute(const struct ast_sdp *sdp,
|
||||
const char *attr_name, int payload)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = ast_sdp_find_a_first(sdp, attr_name, payload);
|
||||
if (idx < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return ast_sdp_get_a(sdp, idx);
|
||||
}
|
||||
|
||||
int ast_sdp_m_find_a_first(const struct ast_sdp_m_line *m_line, const char *attr_name,
|
||||
int payload)
|
||||
{
|
||||
return sdp_find_a_common(m_line->a_lines, -1, attr_name, payload);
|
||||
}
|
||||
|
||||
int ast_sdp_m_find_a_next(const struct ast_sdp_m_line *m_line, int last,
|
||||
const char *attr_name, int payload)
|
||||
{
|
||||
return sdp_find_a_common(m_line->a_lines, last, attr_name, payload);
|
||||
}
|
||||
|
||||
struct ast_sdp_a_line *ast_sdp_m_find_attribute(const struct ast_sdp_m_line *m_line,
|
||||
const char *attr_name, int payload)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = ast_sdp_m_find_a_first(m_line, attr_name, payload);
|
||||
if (idx < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return ast_sdp_m_get_a(m_line, idx);
|
||||
}
|
||||
|
||||
struct ast_sdp_rtpmap *ast_sdp_rtpmap_alloc(int payload, const char *encoding_name,
|
||||
int clock_rate, const char *encoding_parameters)
|
||||
{
|
||||
struct ast_sdp_rtpmap *rtpmap;
|
||||
char *buf_pos;
|
||||
|
||||
rtpmap = ast_calloc(1, sizeof(*rtpmap) + strlen(encoding_name) + strlen(encoding_parameters) + 2);
|
||||
if (!rtpmap) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rtpmap->payload = payload;
|
||||
rtpmap->clock_rate = clock_rate;
|
||||
|
||||
buf_pos = rtpmap->buf;
|
||||
COPY_STR_AND_ADVANCE(buf_pos, rtpmap->encoding_name, encoding_name);
|
||||
COPY_STR_AND_ADVANCE(buf_pos, rtpmap->encoding_parameters, encoding_parameters);
|
||||
|
||||
return rtpmap;
|
||||
}
|
||||
|
||||
void ast_sdp_rtpmap_free(struct ast_sdp_rtpmap *rtpmap)
|
||||
{
|
||||
ast_free(rtpmap);
|
||||
}
|
||||
|
||||
struct ast_sdp_rtpmap *ast_sdp_a_get_rtpmap(const struct ast_sdp_a_line *a_line)
|
||||
{
|
||||
char *value_copy;
|
||||
char *slash;
|
||||
int payload;
|
||||
char encoding_name[64];
|
||||
int clock_rate;
|
||||
char *encoding_parameters;
|
||||
struct ast_sdp_rtpmap *rtpmap;
|
||||
int clock_rate_len;
|
||||
|
||||
value_copy = ast_strip(ast_strdupa(a_line->value));
|
||||
|
||||
if (sscanf(value_copy, "%30d %63s", &payload, encoding_name) != 2) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
slash = strchr(encoding_name, '/');
|
||||
if (!slash) {
|
||||
return NULL;
|
||||
}
|
||||
*slash++ = '\0';
|
||||
if (ast_strlen_zero(encoding_name)) {
|
||||
return NULL;
|
||||
}
|
||||
if (sscanf(slash, "%30d%n", &clock_rate, &clock_rate_len) < 1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
slash += clock_rate_len;
|
||||
if (!ast_strlen_zero(slash)) {
|
||||
if (*slash == '/') {
|
||||
*slash++ = '\0';
|
||||
encoding_parameters = slash;
|
||||
if (ast_strlen_zero(encoding_parameters)) {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
encoding_parameters = "";
|
||||
}
|
||||
|
||||
rtpmap = ast_sdp_rtpmap_alloc(payload, encoding_name, clock_rate,
|
||||
encoding_parameters);
|
||||
|
||||
return rtpmap;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Turn an SDP attribute into an sdp_rtpmap structure
|
||||
*
|
||||
* \param m_line The media section where this attribute was found.
|
||||
* \param payload The RTP payload to find an rtpmap for
|
||||
* \param[out] rtpmap The rtpmap to fill in.
|
||||
* \return Zero if successful, otherwise less than zero
|
||||
*/
|
||||
static struct ast_sdp_rtpmap *sdp_payload_get_rtpmap(const struct ast_sdp_m_line *m_line, int payload)
|
||||
{
|
||||
struct ast_sdp_a_line *rtpmap_attr;
|
||||
|
||||
rtpmap_attr = ast_sdp_m_find_attribute(m_line, "rtpmap", payload);
|
||||
if (!rtpmap_attr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_sdp_a_get_rtpmap(rtpmap_attr);
|
||||
}
|
||||
|
||||
static void process_fmtp_value(const char *value, int payload, struct ast_rtp_codecs *codecs)
|
||||
{
|
||||
char *param;
|
||||
char *param_start;
|
||||
char *param_end;
|
||||
size_t len;
|
||||
struct ast_format *replace;
|
||||
struct ast_format *format;
|
||||
|
||||
/*
|
||||
* Extract the "a=fmtp:%d %s" attribute parameter string value which
|
||||
* starts after the colon.
|
||||
*/
|
||||
param_start = ast_skip_nonblanks(value);/* Skip payload type */
|
||||
param_start = ast_skip_blanks(param_start);
|
||||
param_end = ast_skip_nonblanks(param_start);
|
||||
if (param_end == param_start) {
|
||||
/* There is no parameter string */
|
||||
return;
|
||||
}
|
||||
len = param_end - param_start;
|
||||
param = ast_alloca(len + 1);
|
||||
memcpy(param, param_start, len);
|
||||
param[len] = '\0';
|
||||
|
||||
format = ast_rtp_codecs_get_payload_format(codecs, payload);
|
||||
if (!format) {
|
||||
return;
|
||||
}
|
||||
|
||||
replace = ast_format_parse_sdp_fmtp(format, param);
|
||||
if (replace) {
|
||||
ast_rtp_codecs_payload_replace_format(codecs, payload, replace);
|
||||
ao2_ref(replace, -1);
|
||||
}
|
||||
ao2_ref(format, -1);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Find and process all fmtp attribute lines for a given payload
|
||||
*
|
||||
* \param m_line The stream on which to search for the fmtp attributes
|
||||
* \param payload The specific fmtp attribute to search for
|
||||
* \param codecs The current RTP codecs that have been built up
|
||||
*/
|
||||
static void process_fmtp_lines(const struct ast_sdp_m_line *m_line, int payload,
|
||||
struct ast_rtp_codecs *codecs)
|
||||
{
|
||||
const struct ast_sdp_a_line *a_line;
|
||||
int idx;
|
||||
|
||||
idx = ast_sdp_m_find_a_first(m_line, "fmtp", payload);
|
||||
for (; 0 <= idx; idx = ast_sdp_m_find_a_next(m_line, idx, "fmtp", payload)) {
|
||||
a_line = ast_sdp_m_get_a(m_line, idx);
|
||||
ast_assert(a_line != NULL);
|
||||
|
||||
process_fmtp_value(a_line->value, payload, codecs);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Determine the RTP stream direction in the given a lines.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \param a_lines Attribute lines to search.
|
||||
*
|
||||
* \retval Stream direction on success.
|
||||
* \retval AST_STREAM_STATE_REMOVED on failure.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
static enum ast_stream_state get_a_line_direction(const struct ast_sdp_a_lines *a_lines)
|
||||
{
|
||||
if (a_lines) {
|
||||
enum ast_stream_state direction;
|
||||
int idx;
|
||||
const struct ast_sdp_a_line *a_line;
|
||||
|
||||
for (idx = 0; idx < AST_VECTOR_SIZE(a_lines); ++idx) {
|
||||
a_line = AST_VECTOR_GET(a_lines, idx);
|
||||
direction = ast_stream_str2state(a_line->name);
|
||||
if (direction != AST_STREAM_STATE_REMOVED) {
|
||||
return direction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return AST_STREAM_STATE_REMOVED;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Determine the RTP stream direction.
|
||||
* \since 15.0.0
|
||||
*
|
||||
* \param a_lines The SDP media global attributes
|
||||
* \param m_line The SDP media section to convert
|
||||
*
|
||||
* \return Stream direction
|
||||
*/
|
||||
static enum ast_stream_state get_stream_direction(const struct ast_sdp_a_lines *a_lines, const struct ast_sdp_m_line *m_line)
|
||||
{
|
||||
enum ast_stream_state direction;
|
||||
|
||||
direction = get_a_line_direction(m_line->a_lines);
|
||||
if (direction != AST_STREAM_STATE_REMOVED) {
|
||||
return direction;
|
||||
}
|
||||
direction = get_a_line_direction(a_lines);
|
||||
if (direction != AST_STREAM_STATE_REMOVED) {
|
||||
return direction;
|
||||
}
|
||||
return AST_STREAM_STATE_SENDRECV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Needed so we don't have an external function referenced as data.
|
||||
* The dynamic linker doesn't handle that very well.
|
||||
*/
|
||||
static void rtp_codecs_free(struct ast_rtp_codecs *codecs)
|
||||
{
|
||||
if (codecs) {
|
||||
ast_rtp_codecs_payloads_destroy(codecs);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Convert an SDP stream into an Asterisk stream
|
||||
*
|
||||
* Given an m-line from an SDP, convert it into an ast_stream structure.
|
||||
* This takes formats, as well as clock-rate and fmtp attributes into account.
|
||||
*
|
||||
* \param a_lines The SDP media global attributes
|
||||
* \param m_line The SDP media section to convert
|
||||
* \param g726_non_standard Non-zero if G.726 is non-standard
|
||||
*
|
||||
* \retval NULL An error occurred
|
||||
* \retval non-NULL The converted stream
|
||||
*/
|
||||
static struct ast_stream *get_stream_from_m(const struct ast_sdp_a_lines *a_lines, const struct ast_sdp_m_line *m_line, int g726_non_standard)
|
||||
{
|
||||
int i;
|
||||
int non_ast_fmts;
|
||||
struct ast_rtp_codecs *codecs;
|
||||
struct ast_format_cap *caps;
|
||||
struct ast_stream *stream;
|
||||
enum ast_rtp_options options;
|
||||
|
||||
caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
|
||||
if (!caps) {
|
||||
return NULL;
|
||||
}
|
||||
stream = ast_stream_alloc(m_line->type, ast_media_type_from_str(m_line->type));
|
||||
if (!stream) {
|
||||
ao2_ref(caps, -1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (ast_stream_get_type(stream)) {
|
||||
case AST_MEDIA_TYPE_AUDIO:
|
||||
case AST_MEDIA_TYPE_VIDEO:
|
||||
codecs = ast_calloc(1, sizeof(*codecs));
|
||||
if (!codecs || ast_rtp_codecs_payloads_initialize(codecs)) {
|
||||
rtp_codecs_free(codecs);
|
||||
ast_stream_free(stream);
|
||||
ao2_ref(caps, -1);
|
||||
ast_free(codecs);
|
||||
return NULL;
|
||||
}
|
||||
ast_stream_set_rtp_codecs(stream, codecs);
|
||||
|
||||
if (!m_line->port) {
|
||||
/* Stream is declined. There may not be any attributes. */
|
||||
ast_stream_set_state(stream, AST_STREAM_STATE_REMOVED);
|
||||
break;
|
||||
}
|
||||
|
||||
options = g726_non_standard ? AST_RTP_OPT_G726_NONSTANDARD : 0;
|
||||
for (i = 0; i < ast_sdp_m_get_payload_count(m_line); ++i) {
|
||||
struct ast_sdp_payload *payload_s;
|
||||
struct ast_sdp_rtpmap *rtpmap;
|
||||
int payload;
|
||||
|
||||
payload_s = ast_sdp_m_get_payload(m_line, i);
|
||||
sscanf(payload_s->fmt, "%30d", &payload);
|
||||
|
||||
rtpmap = sdp_payload_get_rtpmap(m_line, payload);
|
||||
if (!rtpmap) {
|
||||
/* No rtpmap attribute. Try static payload type format assignment */
|
||||
ast_rtp_codecs_payloads_set_m_type(codecs, NULL, payload);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ast_rtp_codecs_payloads_set_rtpmap_type_rate(codecs, NULL, payload,
|
||||
m_line->type, rtpmap->encoding_name, options, rtpmap->clock_rate)) {
|
||||
/* Successfully mapped the payload type to format */
|
||||
process_fmtp_lines(m_line, payload, codecs);
|
||||
}
|
||||
ast_sdp_rtpmap_free(rtpmap);
|
||||
}
|
||||
|
||||
ast_rtp_codecs_payload_formats(codecs, caps, &non_ast_fmts);
|
||||
|
||||
ast_stream_set_state(stream, get_stream_direction(a_lines, m_line));
|
||||
break;
|
||||
case AST_MEDIA_TYPE_IMAGE:
|
||||
if (!m_line->port) {
|
||||
/* Stream is declined. There may not be any attributes. */
|
||||
ast_stream_set_state(stream, AST_STREAM_STATE_REMOVED);
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < ast_sdp_m_get_payload_count(m_line); ++i) {
|
||||
struct ast_sdp_payload *payload;
|
||||
|
||||
/* As we don't carry T.38 over RTP we do our own format check */
|
||||
payload = ast_sdp_m_get_payload(m_line, i);
|
||||
if (!strcasecmp(payload->fmt, "t38")) {
|
||||
ast_format_cap_append(caps, ast_format_t38, 0);
|
||||
ast_stream_set_state(stream, AST_STREAM_STATE_SENDRECV);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AST_MEDIA_TYPE_UNKNOWN:
|
||||
case AST_MEDIA_TYPE_TEXT:
|
||||
case AST_MEDIA_TYPE_END:
|
||||
/* Consider these unsupported streams as declined */
|
||||
ast_stream_set_state(stream, AST_STREAM_STATE_REMOVED);
|
||||
break;
|
||||
}
|
||||
|
||||
ast_stream_set_formats(stream, caps);
|
||||
ao2_ref(caps, -1);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
struct ast_stream_topology *ast_get_topology_from_sdp(const struct ast_sdp *sdp, int g726_non_standard)
|
||||
{
|
||||
struct ast_stream_topology *topology;
|
||||
int i;
|
||||
|
||||
topology = ast_stream_topology_alloc();
|
||||
if (!topology) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ast_sdp_get_m_count(sdp); ++i) {
|
||||
struct ast_stream *stream;
|
||||
|
||||
stream = get_stream_from_m(sdp->a_lines, ast_sdp_get_m(sdp, i), g726_non_standard);
|
||||
if (!stream) {
|
||||
/*
|
||||
* The topology cannot match the SDP because
|
||||
* we failed to create a corresponding stream.
|
||||
*/
|
||||
ast_stream_topology_free(topology);
|
||||
return NULL;
|
||||
}
|
||||
if (ast_stream_topology_append_stream(topology, stream) < 0) {
|
||||
/* Failed to add stream to topology */
|
||||
ast_stream_free(stream);
|
||||
ast_stream_topology_free(topology);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return topology;
|
||||
}
|
|
@ -1,235 +0,0 @@
|
|||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2017, Digium, Inc.
|
||||
*
|
||||
* Mark Michelson <mmichelson@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/sdp_options.h"
|
||||
|
||||
#include "sdp_private.h"
|
||||
|
||||
#define DEFAULT_DTMF AST_SDP_DTMF_NONE
|
||||
#define DEFAULT_ICE AST_SDP_ICE_DISABLED
|
||||
#define DEFAULT_IMPL AST_SDP_IMPL_STRING
|
||||
#define DEFAULT_ENCRYPTION AST_SDP_ENCRYPTION_DISABLED
|
||||
#define DEFAULT_MAX_STREAMS 16 /* Set to match our PJPROJECT PJMEDIA_MAX_SDP_MEDIA. */
|
||||
|
||||
#define DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(field, assert_on_null) \
|
||||
void ast_sdp_options_set_##field(struct ast_sdp_options *options, const char *value) \
|
||||
{ \
|
||||
ast_assert(options != NULL); \
|
||||
if ((assert_on_null)) ast_assert(!ast_strlen_zero(value)); \
|
||||
if (!strcmp(value, options->field)) return; \
|
||||
ast_string_field_set(options, field, value); \
|
||||
} \
|
||||
const char *ast_sdp_options_get_##field(const struct ast_sdp_options *options) \
|
||||
{ \
|
||||
ast_assert(options != NULL); \
|
||||
return options->field; \
|
||||
} \
|
||||
|
||||
#define DEFINE_GETTERS_SETTERS_FOR(type, field) \
|
||||
void ast_sdp_options_set_##field(struct ast_sdp_options *options, type value) \
|
||||
{ \
|
||||
ast_assert(options != NULL); \
|
||||
options->field = value; \
|
||||
} \
|
||||
type ast_sdp_options_get_##field(const struct ast_sdp_options *options) \
|
||||
{ \
|
||||
ast_assert(options != NULL); \
|
||||
return options->field; \
|
||||
} \
|
||||
|
||||
DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(media_address, 0);
|
||||
DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(interface_address, 0);
|
||||
DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(sdpowner, 0);
|
||||
DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(sdpsession, 0);
|
||||
DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(rtp_engine, 0);
|
||||
|
||||
DEFINE_GETTERS_SETTERS_FOR(void *, state_context);
|
||||
DEFINE_GETTERS_SETTERS_FOR(ast_sdp_answerer_modify_cb, answerer_modify_cb);
|
||||
DEFINE_GETTERS_SETTERS_FOR(ast_sdp_offerer_modify_cb, offerer_modify_cb);
|
||||
DEFINE_GETTERS_SETTERS_FOR(ast_sdp_offerer_config_cb, offerer_config_cb);
|
||||
DEFINE_GETTERS_SETTERS_FOR(ast_sdp_preapply_cb, preapply_cb);
|
||||
DEFINE_GETTERS_SETTERS_FOR(ast_sdp_postapply_cb, postapply_cb);
|
||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, rtp_symmetric);
|
||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, udptl_symmetric);
|
||||
DEFINE_GETTERS_SETTERS_FOR(enum ast_t38_ec_modes, udptl_error_correction);
|
||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, udptl_far_max_datagram);
|
||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, rtp_ipv6);
|
||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, g726_non_standard);
|
||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, rtcp_mux);
|
||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, tos_audio);
|
||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, cos_audio);
|
||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, tos_video);
|
||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, cos_video);
|
||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, max_streams);
|
||||
DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_dtmf, dtmf);
|
||||
DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_ice, ice);
|
||||
DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_impl, impl);
|
||||
DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_encryption, encryption);
|
||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, ssrc);
|
||||
|
||||
struct ast_sched_context *ast_sdp_options_get_sched_type(const struct ast_sdp_options *options, enum ast_media_type type)
|
||||
{
|
||||
struct ast_sched_context *sched = NULL;
|
||||
|
||||
switch (type) {
|
||||
case AST_MEDIA_TYPE_AUDIO:
|
||||
case AST_MEDIA_TYPE_VIDEO:
|
||||
case AST_MEDIA_TYPE_IMAGE:
|
||||
case AST_MEDIA_TYPE_TEXT:
|
||||
sched = options->sched[type];
|
||||
break;
|
||||
case AST_MEDIA_TYPE_UNKNOWN:
|
||||
case AST_MEDIA_TYPE_END:
|
||||
break;
|
||||
}
|
||||
return sched;
|
||||
}
|
||||
|
||||
void ast_sdp_options_set_sched_type(struct ast_sdp_options *options, enum ast_media_type type, struct ast_sched_context *sched)
|
||||
{
|
||||
switch (type) {
|
||||
case AST_MEDIA_TYPE_AUDIO:
|
||||
case AST_MEDIA_TYPE_VIDEO:
|
||||
case AST_MEDIA_TYPE_IMAGE:
|
||||
case AST_MEDIA_TYPE_TEXT:
|
||||
options->sched[type] = sched;
|
||||
break;
|
||||
case AST_MEDIA_TYPE_UNKNOWN:
|
||||
case AST_MEDIA_TYPE_END:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct ast_format_cap *ast_sdp_options_get_format_cap_type(const struct ast_sdp_options *options,
|
||||
enum ast_media_type type)
|
||||
{
|
||||
struct ast_format_cap *cap = NULL;
|
||||
|
||||
switch (type) {
|
||||
case AST_MEDIA_TYPE_AUDIO:
|
||||
case AST_MEDIA_TYPE_VIDEO:
|
||||
case AST_MEDIA_TYPE_IMAGE:
|
||||
case AST_MEDIA_TYPE_TEXT:
|
||||
cap = options->caps[type];
|
||||
break;
|
||||
case AST_MEDIA_TYPE_UNKNOWN:
|
||||
case AST_MEDIA_TYPE_END:
|
||||
break;
|
||||
}
|
||||
return cap;
|
||||
}
|
||||
|
||||
void ast_sdp_options_set_format_cap_type(struct ast_sdp_options *options,
|
||||
enum ast_media_type type, struct ast_format_cap *cap)
|
||||
{
|
||||
switch (type) {
|
||||
case AST_MEDIA_TYPE_AUDIO:
|
||||
case AST_MEDIA_TYPE_VIDEO:
|
||||
case AST_MEDIA_TYPE_IMAGE:
|
||||
case AST_MEDIA_TYPE_TEXT:
|
||||
ao2_cleanup(options->caps[type]);
|
||||
options->caps[type] = NULL;
|
||||
if (cap && !ast_format_cap_empty(cap)) {
|
||||
ao2_ref(cap, +1);
|
||||
options->caps[type] = cap;
|
||||
}
|
||||
break;
|
||||
case AST_MEDIA_TYPE_UNKNOWN:
|
||||
case AST_MEDIA_TYPE_END:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ast_sdp_options_set_format_caps(struct ast_sdp_options *options,
|
||||
struct ast_format_cap *cap)
|
||||
{
|
||||
enum ast_media_type type;
|
||||
|
||||
for (type = AST_MEDIA_TYPE_UNKNOWN; type < AST_MEDIA_TYPE_END; ++type) {
|
||||
ao2_cleanup(options->caps[type]);
|
||||
options->caps[type] = NULL;
|
||||
}
|
||||
|
||||
if (!cap || ast_format_cap_empty(cap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (type = AST_MEDIA_TYPE_UNKNOWN + 1; type < AST_MEDIA_TYPE_END; ++type) {
|
||||
struct ast_format_cap *type_cap;
|
||||
|
||||
type_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
|
||||
if (!type_cap) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ast_format_cap_set_framing(type_cap, ast_format_cap_get_framing(cap));
|
||||
if (ast_format_cap_append_from_cap(type_cap, cap, type)
|
||||
|| ast_format_cap_empty(type_cap)) {
|
||||
ao2_ref(type_cap, -1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This takes the allocation reference */
|
||||
options->caps[type] = type_cap;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_defaults(struct ast_sdp_options *options)
|
||||
{
|
||||
options->dtmf = DEFAULT_DTMF;
|
||||
options->ice = DEFAULT_ICE;
|
||||
options->impl = DEFAULT_IMPL;
|
||||
options->encryption = DEFAULT_ENCRYPTION;
|
||||
options->max_streams = DEFAULT_MAX_STREAMS;
|
||||
}
|
||||
|
||||
struct ast_sdp_options *ast_sdp_options_alloc(void)
|
||||
{
|
||||
struct ast_sdp_options *options;
|
||||
|
||||
options = ast_calloc(1, sizeof(*options));
|
||||
if (!options) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ast_string_field_init(options, 256)) {
|
||||
ast_free(options);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
set_defaults(options);
|
||||
return options;
|
||||
}
|
||||
|
||||
void ast_sdp_options_free(struct ast_sdp_options *options)
|
||||
{
|
||||
enum ast_media_type type;
|
||||
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (type = AST_MEDIA_TYPE_UNKNOWN; type < AST_MEDIA_TYPE_END; ++type) {
|
||||
ao2_cleanup(options->caps[type]);
|
||||
}
|
||||
ast_string_field_free_memory(options);
|
||||
ast_free(options);
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2017, Digium, Inc.
|
||||
*
|
||||
* Mark Michelson <mmichelson@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef _MAIN_SDP_PRIVATE_H
|
||||
#define _MAIN_SDP_PRIVATE_H
|
||||
|
||||
#include "asterisk/stringfields.h"
|
||||
#include "asterisk/sdp_options.h"
|
||||
|
||||
struct ast_sdp_options {
|
||||
AST_DECLARE_STRING_FIELDS(
|
||||
/*! Media address to advertise in SDP session c= line */
|
||||
AST_STRING_FIELD(media_address);
|
||||
/*! Optional address of the interface media should use. */
|
||||
AST_STRING_FIELD(interface_address);
|
||||
/*! SDP origin username */
|
||||
AST_STRING_FIELD(sdpowner);
|
||||
/*! SDP session name */
|
||||
AST_STRING_FIELD(sdpsession);
|
||||
/*! RTP Engine Name */
|
||||
AST_STRING_FIELD(rtp_engine);
|
||||
);
|
||||
/*! Scheduler context for the media stream types (Mainly for RTP) */
|
||||
struct ast_sched_context *sched[AST_MEDIA_TYPE_END];
|
||||
/*! Capabilities to create new streams of the indexed media type. */
|
||||
struct ast_format_cap *caps[AST_MEDIA_TYPE_END];
|
||||
/*! User supplied context data pointer for the SDP state. */
|
||||
void *state_context;
|
||||
/*! Modify negotiated topology before create answer SDP callback. */
|
||||
ast_sdp_answerer_modify_cb answerer_modify_cb;
|
||||
/*! Modify proposed topology before create offer SDP callback. */
|
||||
ast_sdp_offerer_modify_cb offerer_modify_cb;
|
||||
/*! Configure proposed topology extra stream options before create offer SDP callback. */
|
||||
ast_sdp_offerer_config_cb offerer_config_cb;
|
||||
/*! Negotiated topology is about to be applied callback. */
|
||||
ast_sdp_preapply_cb preapply_cb;
|
||||
/*! Negotiated topology was just applied callback. */
|
||||
ast_sdp_postapply_cb postapply_cb;
|
||||
struct {
|
||||
unsigned int rtp_symmetric:1;
|
||||
unsigned int udptl_symmetric:1;
|
||||
unsigned int rtp_ipv6:1;
|
||||
unsigned int g726_non_standard:1;
|
||||
unsigned int rtcp_mux:1;
|
||||
unsigned int ssrc:1;
|
||||
};
|
||||
struct {
|
||||
unsigned int tos_audio;
|
||||
unsigned int cos_audio;
|
||||
unsigned int tos_video;
|
||||
unsigned int cos_video;
|
||||
unsigned int udptl_far_max_datagram;
|
||||
/*! Maximum number of streams to allow. */
|
||||
unsigned int max_streams;
|
||||
};
|
||||
enum ast_sdp_options_dtmf dtmf;
|
||||
enum ast_sdp_options_ice ice;
|
||||
enum ast_sdp_options_impl impl;
|
||||
enum ast_sdp_options_encryption encryption;
|
||||
enum ast_t38_ec_modes udptl_error_correction;
|
||||
};
|
||||
|
||||
#endif /* _MAIN_SDP_PRIVATE_H */
|
3411
main/sdp_state.c
3411
main/sdp_state.c
File diff suppressed because it is too large
Load Diff
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2017, Digium, Inc.
|
||||
*
|
||||
* Mark Michelson <mmichelson@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
#include "asterisk/sdp_options.h"
|
||||
#include "asterisk/sdp_translator.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/lock.h"
|
||||
|
||||
AST_RWLOCK_DEFINE_STATIC(registered_ops_lock);
|
||||
static struct ast_sdp_translator_ops *registered_ops[AST_SDP_IMPL_END];
|
||||
|
||||
int ast_sdp_register_translator(struct ast_sdp_translator_ops *ops)
|
||||
{
|
||||
SCOPED_WRLOCK(lock, ®istered_ops_lock);
|
||||
|
||||
if (ops->repr >= AST_SDP_IMPL_END) {
|
||||
ast_log(LOG_ERROR, "SDP translator has unrecognized representation\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (registered_ops[ops->repr] != NULL) {
|
||||
ast_log(LOG_ERROR, "SDP_translator with this representation already registered\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
registered_ops[ops->repr] = ops;
|
||||
ast_log(LOG_NOTICE, "Placed ops %p at slot %d\n", ops, ops->repr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ast_sdp_unregister_translator(struct ast_sdp_translator_ops *ops)
|
||||
{
|
||||
SCOPED_WRLOCK(lock, ®istered_ops_lock);
|
||||
|
||||
if (ops->repr >= AST_SDP_IMPL_END) {
|
||||
return;
|
||||
}
|
||||
|
||||
registered_ops[ops->repr] = NULL;
|
||||
}
|
||||
|
||||
struct ast_sdp_translator *ast_sdp_translator_new(enum ast_sdp_options_impl repr)
|
||||
{
|
||||
struct ast_sdp_translator *translator;
|
||||
SCOPED_RDLOCK(lock, ®istered_ops_lock);
|
||||
|
||||
if (registered_ops[repr] == NULL) {
|
||||
ast_log(LOG_NOTICE, "No registered SDP translator with representation %d\n", repr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
translator = ast_calloc(1, sizeof(*translator));
|
||||
if (!translator) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
translator->ops = registered_ops[repr];
|
||||
|
||||
translator->translator_priv = translator->ops->translator_new();
|
||||
if (!translator->translator_priv) {
|
||||
ast_free(translator);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return translator;
|
||||
}
|
||||
|
||||
void ast_sdp_translator_free(struct ast_sdp_translator *translator)
|
||||
{
|
||||
if (!translator) {
|
||||
return;
|
||||
}
|
||||
translator->ops->translator_free(translator->translator_priv);
|
||||
ast_free(translator);
|
||||
}
|
||||
|
||||
struct ast_sdp *ast_sdp_translator_to_sdp(struct ast_sdp_translator *translator,
|
||||
const void *native_sdp)
|
||||
{
|
||||
return translator->ops->to_sdp(native_sdp, translator->translator_priv);
|
||||
}
|
||||
|
||||
const void *ast_sdp_translator_from_sdp(struct ast_sdp_translator *translator,
|
||||
const struct ast_sdp *ast_sdp)
|
||||
{
|
||||
return translator->ops->from_sdp(ast_sdp, translator->translator_priv);
|
||||
}
|
|
@ -1,605 +0,0 @@
|
|||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2017, Digium, Inc.
|
||||
*
|
||||
* Mark Michelson <mmichelson@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
#include <pjlib.h>
|
||||
#include <pjmedia.h>
|
||||
|
||||
#include "asterisk/res_pjproject.h"
|
||||
#include "asterisk/sdp_translator.h"
|
||||
#include "asterisk/sdp_options.h"
|
||||
#include "asterisk/vector.h"
|
||||
#include "asterisk/netsock2.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/test.h"
|
||||
#include "asterisk/module.h"
|
||||
|
||||
#include "asterisk/sdp.h"
|
||||
|
||||
/*** MODULEINFO
|
||||
<depend>pjproject</depend>
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
/*
|
||||
* XXX TODO: The memory in the pool is held onto longer than necessary. It
|
||||
* is kept and grows for the duration of the associated chan_pjsip session.
|
||||
*
|
||||
* The translation API does not need to be so generic. The users will know
|
||||
* at compile time what the non-Asterisk SDP format they have or need. They
|
||||
* should simply call the specific translation functions. However, to make
|
||||
* this a loadable module we need to be able to keep it in memory when a
|
||||
* dependent module is loaded.
|
||||
*
|
||||
* To address both issues I propose this API:
|
||||
*
|
||||
* void ast_sdp_translate_pjmedia_ref(void) - Inc this module's user ref
|
||||
* void ast_sdp_translate_pjmedia_unref(void) - Dec this module's user ref.
|
||||
* The res_pjsip_session.c:ast_sip_session_alloc() can call the module ref
|
||||
* and the session's destructor can call the module unref.
|
||||
*
|
||||
* struct ast_sdp *ast_sdp_translate_pjmedia_from(const pjmedia_sdp_session *pjmedia_sdp);
|
||||
*
|
||||
* pjmedia_sdp_session *ast_sdp_translate_pjmedia_to(const struct ast_sdp *sdp, pj_pool_t *pool);
|
||||
* Passing in a memory pool allows the memory to be obtained from an
|
||||
* rdata memory pool that will be released when the message processing
|
||||
* is complete. This prevents memory from accumulating for the duration
|
||||
* of a call.
|
||||
*
|
||||
* int ast_sdp_translate_pjmedia_set_remote_sdp(struct ast_sdp_state *sdp_state, const pjmedia_sdp_session *remote);
|
||||
* const pjmedia_sdp_session *ast_sdp_translate_pjmedia_get_local_sdp(struct ast_sdp_state *sdp_state, pj_pool_t *pool);
|
||||
* These two functions just do the bookkeeping to translate and set or get
|
||||
* the requested SDP.
|
||||
*
|
||||
*
|
||||
* XXX TODO: This code doesn't handle allocation failures very well. i.e.,
|
||||
* It assumes they will never happen.
|
||||
*
|
||||
* XXX TODO: This code uses ast_alloca() inside loops. Doing so if the number
|
||||
* of times through the loop is unconstrained will blow the stack.
|
||||
* See dupa_pj_str() usage.
|
||||
*/
|
||||
|
||||
static pj_caching_pool sdp_caching_pool;
|
||||
|
||||
|
||||
static void *pjmedia_new(void)
|
||||
{
|
||||
pj_pool_t *pool;
|
||||
|
||||
pool = pj_pool_create(&sdp_caching_pool.factory, "pjmedia sdp translator", 1024, 1024, NULL);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
static void pjmedia_free(void *translator_priv)
|
||||
{
|
||||
pj_pool_t *pool = translator_priv;
|
||||
|
||||
pj_pool_release(pool);
|
||||
}
|
||||
|
||||
#define dupa_pj_str(pjstr) \
|
||||
({ \
|
||||
char *dest = ast_alloca(pjstr.slen + 1); \
|
||||
memcpy(dest, pjstr.ptr, pjstr.slen); \
|
||||
dest[pjstr.slen] = '\0'; \
|
||||
dest; \
|
||||
})
|
||||
|
||||
static struct ast_sdp_m_line *pjmedia_copy_m_line(struct pjmedia_sdp_media *pjmedia_m_line)
|
||||
{
|
||||
int i;
|
||||
|
||||
struct ast_sdp_c_line *c_line = pjmedia_m_line->conn ?
|
||||
ast_sdp_c_alloc(dupa_pj_str(pjmedia_m_line->conn->addr_type),
|
||||
dupa_pj_str(pjmedia_m_line->conn->addr)) : NULL;
|
||||
|
||||
struct ast_sdp_m_line *m_line = ast_sdp_m_alloc(dupa_pj_str(pjmedia_m_line->desc.media),
|
||||
pjmedia_m_line->desc.port, pjmedia_m_line->desc.port_count,
|
||||
dupa_pj_str(pjmedia_m_line->desc.transport), c_line);
|
||||
|
||||
for (i = 0; i < pjmedia_m_line->desc.fmt_count; ++i) {
|
||||
ast_sdp_m_add_payload(m_line,
|
||||
ast_sdp_payload_alloc(dupa_pj_str(pjmedia_m_line->desc.fmt[i])));
|
||||
}
|
||||
|
||||
for (i = 0; i < pjmedia_m_line->attr_count; ++i) {
|
||||
ast_sdp_m_add_a(m_line, ast_sdp_a_alloc(dupa_pj_str(pjmedia_m_line->attr[i]->name),
|
||||
dupa_pj_str(pjmedia_m_line->attr[i]->value)));
|
||||
}
|
||||
|
||||
return m_line;
|
||||
}
|
||||
|
||||
static void pjmedia_copy_a_lines(struct ast_sdp *new_sdp, const pjmedia_sdp_session *pjmedia_sdp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pjmedia_sdp->attr_count; ++i) {
|
||||
ast_sdp_add_a(new_sdp, ast_sdp_a_alloc(dupa_pj_str(pjmedia_sdp->attr[i]->name),
|
||||
dupa_pj_str(pjmedia_sdp->attr[i]->value)));
|
||||
}
|
||||
}
|
||||
|
||||
static void pjmedia_copy_m_lines(struct ast_sdp *new_sdp,
|
||||
const struct pjmedia_sdp_session *pjmedia_sdp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pjmedia_sdp->media_count; ++i) {
|
||||
ast_sdp_add_m(new_sdp, pjmedia_copy_m_line(pjmedia_sdp->media[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static struct ast_sdp *pjmedia_to_sdp(const void *in, void *translator_priv)
|
||||
{
|
||||
const struct pjmedia_sdp_session *pjmedia_sdp = in;
|
||||
|
||||
struct ast_sdp_o_line *o_line = ast_sdp_o_alloc(dupa_pj_str(pjmedia_sdp->origin.user),
|
||||
pjmedia_sdp->origin.id, pjmedia_sdp->origin.version,
|
||||
dupa_pj_str(pjmedia_sdp->origin.addr_type), dupa_pj_str(pjmedia_sdp->origin.addr));
|
||||
|
||||
struct ast_sdp_c_line *c_line = pjmedia_sdp->conn ?
|
||||
ast_sdp_c_alloc(dupa_pj_str(pjmedia_sdp->conn->addr_type),
|
||||
dupa_pj_str(pjmedia_sdp->conn->addr)) : NULL;
|
||||
|
||||
struct ast_sdp_s_line *s_line = ast_sdp_s_alloc(dupa_pj_str(pjmedia_sdp->name));
|
||||
|
||||
struct ast_sdp_t_line *t_line = ast_sdp_t_alloc(pjmedia_sdp->time.start,
|
||||
pjmedia_sdp->time.stop);
|
||||
|
||||
struct ast_sdp *new_sdp = ast_sdp_alloc(o_line, c_line, s_line, t_line);
|
||||
|
||||
pjmedia_copy_a_lines(new_sdp, pjmedia_sdp);
|
||||
pjmedia_copy_m_lines(new_sdp, pjmedia_sdp);
|
||||
|
||||
return new_sdp;
|
||||
}
|
||||
|
||||
static void copy_o_line_pjmedia(pj_pool_t *pool, pjmedia_sdp_session *pjmedia_sdp,
|
||||
struct ast_sdp_o_line *o_line)
|
||||
{
|
||||
pjmedia_sdp->origin.id = o_line->session_id;
|
||||
pjmedia_sdp->origin.version = o_line->session_version;
|
||||
pj_strdup2(pool, &pjmedia_sdp->origin.user, o_line->username);
|
||||
pj_strdup2(pool, &pjmedia_sdp->origin.addr_type, o_line->address_type);
|
||||
pj_strdup2(pool, &pjmedia_sdp->origin.addr, o_line->address);
|
||||
pj_strdup2(pool, &pjmedia_sdp->origin.net_type, "IN");
|
||||
}
|
||||
|
||||
static void copy_s_line_pjmedia(pj_pool_t *pool, pjmedia_sdp_session *pjmedia_sdp,
|
||||
struct ast_sdp_s_line *s_line)
|
||||
{
|
||||
pj_strdup2(pool, &pjmedia_sdp->name, s_line->session_name);
|
||||
}
|
||||
|
||||
static void copy_t_line_pjmedia(pj_pool_t *pool, pjmedia_sdp_session *pjmedia_sdp,
|
||||
struct ast_sdp_t_line *t_line)
|
||||
{
|
||||
pjmedia_sdp->time.start = t_line->start_time;
|
||||
pjmedia_sdp->time.stop = t_line->stop_time;
|
||||
}
|
||||
|
||||
static void copy_c_line_pjmedia(pj_pool_t *pool, pjmedia_sdp_conn **conn,
|
||||
struct ast_sdp_c_line *c_line)
|
||||
{
|
||||
pjmedia_sdp_conn *local_conn;
|
||||
local_conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn);
|
||||
pj_strdup2(pool, &local_conn->addr_type, c_line->address_type);
|
||||
pj_strdup2(pool, &local_conn->addr, c_line->address);
|
||||
pj_strdup2(pool, &local_conn->net_type, "IN");
|
||||
|
||||
*conn = local_conn;
|
||||
}
|
||||
|
||||
static void copy_a_lines_pjmedia(pj_pool_t *pool, pjmedia_sdp_session *pjmedia_sdp,
|
||||
const struct ast_sdp *sdp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ast_sdp_get_a_count(sdp); ++i) {
|
||||
pjmedia_sdp_attr *attr;
|
||||
pj_str_t value;
|
||||
struct ast_sdp_a_line *a_line;
|
||||
|
||||
a_line = ast_sdp_get_a(sdp, i);
|
||||
pj_strdup2(pool, &value, a_line->value);
|
||||
attr = pjmedia_sdp_attr_create(pool, a_line->name, &value);
|
||||
pjmedia_sdp_session_add_attr(pjmedia_sdp, attr);
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_a_lines_pjmedia_media(pj_pool_t *pool, pjmedia_sdp_media *media,
|
||||
struct ast_sdp_m_line *m_line)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ast_sdp_m_get_a_count(m_line); ++i) {
|
||||
pjmedia_sdp_attr *attr;
|
||||
pj_str_t value;
|
||||
struct ast_sdp_a_line *a_line;
|
||||
|
||||
a_line = ast_sdp_m_get_a(m_line, i);
|
||||
pj_strdup2(pool, &value, a_line->value);
|
||||
attr = pjmedia_sdp_attr_create(pool, a_line->name, &value);
|
||||
pjmedia_sdp_media_add_attr(media, attr);
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_m_line_pjmedia(pj_pool_t *pool, pjmedia_sdp_media *media,
|
||||
struct ast_sdp_m_line *m_line)
|
||||
{
|
||||
int i;
|
||||
|
||||
media->desc.port = m_line->port;
|
||||
media->desc.port_count = m_line->port_count;
|
||||
pj_strdup2(pool, &media->desc.transport, m_line->proto);
|
||||
pj_strdup2(pool, &media->desc.media, m_line->type);
|
||||
|
||||
for (i = 0; i < ast_sdp_m_get_payload_count(m_line); ++i) {
|
||||
pj_strdup2(pool, &media->desc.fmt[i], ast_sdp_m_get_payload(m_line, i)->fmt);
|
||||
++media->desc.fmt_count;
|
||||
}
|
||||
if (m_line->c_line && m_line->c_line->address) {
|
||||
copy_c_line_pjmedia(pool, &media->conn, m_line->c_line);
|
||||
}
|
||||
copy_a_lines_pjmedia_media(pool, media, m_line);
|
||||
}
|
||||
|
||||
static void copy_m_lines_pjmedia(pj_pool_t *pool, pjmedia_sdp_session *pjmedia_sdp,
|
||||
const struct ast_sdp *sdp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ast_sdp_get_m_count(sdp); ++i) {
|
||||
pjmedia_sdp_media *media;
|
||||
|
||||
media = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media);
|
||||
copy_m_line_pjmedia(pool, media, ast_sdp_get_m(sdp, i));
|
||||
pjmedia_sdp->media[pjmedia_sdp->media_count] = media;
|
||||
++pjmedia_sdp->media_count;
|
||||
}
|
||||
}
|
||||
|
||||
static const void *sdp_to_pjmedia(const struct ast_sdp *sdp, void *translator_priv)
|
||||
{
|
||||
pj_pool_t *pool = translator_priv;
|
||||
pjmedia_sdp_session *pjmedia_sdp;
|
||||
|
||||
pjmedia_sdp = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_session);
|
||||
copy_o_line_pjmedia(pool, pjmedia_sdp, sdp->o_line);
|
||||
copy_s_line_pjmedia(pool, pjmedia_sdp, sdp->s_line);
|
||||
copy_t_line_pjmedia(pool, pjmedia_sdp, sdp->t_line);
|
||||
copy_c_line_pjmedia(pool, &pjmedia_sdp->conn, sdp->c_line);
|
||||
copy_a_lines_pjmedia(pool, pjmedia_sdp, sdp);
|
||||
copy_m_lines_pjmedia(pool, pjmedia_sdp, sdp);
|
||||
return pjmedia_sdp;
|
||||
}
|
||||
|
||||
static struct ast_sdp_translator_ops pjmedia_translator = {
|
||||
.repr = AST_SDP_IMPL_PJMEDIA,
|
||||
.translator_new = pjmedia_new,
|
||||
.translator_free = pjmedia_free,
|
||||
.to_sdp = pjmedia_to_sdp,
|
||||
.from_sdp = sdp_to_pjmedia,
|
||||
};
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
|
||||
static int verify_s_line(struct ast_sdp_s_line *s_line, char *expected)
|
||||
{
|
||||
return strcmp(s_line->session_name, expected) == 0;
|
||||
}
|
||||
|
||||
static int verify_c_line(struct ast_sdp_c_line *c_line, char *family, char *addr)
|
||||
{
|
||||
return strcmp(c_line->address_type, family) == 0 && strcmp(c_line->address, addr) == 0;
|
||||
}
|
||||
|
||||
static int verify_t_line(struct ast_sdp_t_line *t_line, uint32_t start, uint32_t end)
|
||||
{
|
||||
return t_line->start_time == start && t_line->stop_time == end;
|
||||
}
|
||||
|
||||
static int verify_m_line(struct ast_sdp *sdp, int index, char *type, int port,
|
||||
int port_count, char *profile, ...)
|
||||
{
|
||||
struct ast_sdp_m_line *m_line;
|
||||
int res;
|
||||
va_list ap;
|
||||
int i;
|
||||
|
||||
m_line = ast_sdp_get_m(sdp, index);
|
||||
|
||||
res = strcmp(m_line->type, type) == 0;
|
||||
res |= m_line->port == port;
|
||||
res |= m_line->port_count == port_count;
|
||||
res |= strcmp(m_line->proto, profile) == 0;
|
||||
|
||||
va_start(ap, profile);
|
||||
for (i = 0; i < ast_sdp_m_get_payload_count(m_line); ++i) {
|
||||
char *payload;
|
||||
|
||||
payload = va_arg(ap, char *);
|
||||
if (!payload) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
res |= strcmp(ast_sdp_m_get_payload(m_line, i)->fmt, payload) == 0;
|
||||
}
|
||||
va_end(ap);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int verify_a_line(struct ast_sdp *sdp, int m_index, int a_index, char *name,
|
||||
char *value)
|
||||
{
|
||||
struct ast_sdp_m_line *m_line;
|
||||
struct ast_sdp_a_line *a_line;
|
||||
|
||||
m_line = ast_sdp_get_m(sdp, m_index);
|
||||
a_line = ast_sdp_m_get_a(m_line, a_index);
|
||||
|
||||
return strcmp(a_line->name, name) == 0 && strcmp(a_line->value, value) == 0;
|
||||
}
|
||||
|
||||
AST_TEST_DEFINE(pjmedia_to_sdp_test)
|
||||
{
|
||||
struct ast_sdp_translator *translator;
|
||||
pj_pool_t *pool;
|
||||
char *sdp_str =
|
||||
"v=0\r\n"
|
||||
"o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"
|
||||
"s= \r\n"
|
||||
"c=IN IP4 host.atlanta.example.com\r\n"
|
||||
"t=123 456\r\n"
|
||||
"m=audio 49170 RTP/AVP 0 8 97\r\n"
|
||||
"a=rtpmap:0 PCMU/8000\r\n"
|
||||
"a=rtpmap:8 PCMA/8000\r\n"
|
||||
"a=rtpmap:97 iLBC/8000\r\n"
|
||||
"a=sendrecv\r\n"
|
||||
"m=video 51372 RTP/AVP 31 32\r\n"
|
||||
"a=rtpmap:31 H261/90000\r\n"
|
||||
"a=rtpmap:32 MPV/90000\r\n";
|
||||
pjmedia_sdp_session *pjmedia_sdp;
|
||||
struct ast_sdp *sdp = NULL;
|
||||
pj_status_t status;
|
||||
enum ast_test_result_state res = AST_TEST_PASS;
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = "pjmedia_to_sdp";
|
||||
info->category = "/main/sdp/";
|
||||
info->summary = "PJMEDIA to SDP unit test";
|
||||
info->description =
|
||||
"Ensures PJMEDIA SDPs are translated correctly";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
pool = pj_pool_create(&sdp_caching_pool.factory, "pjmedia to sdp test", 1024, 1024, NULL);
|
||||
|
||||
translator = ast_sdp_translator_new(AST_SDP_IMPL_PJMEDIA);
|
||||
if (!translator) {
|
||||
ast_test_status_update(test, "Failed to create SDP translator\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
status = pjmedia_sdp_parse(pool, sdp_str, strlen(sdp_str), &pjmedia_sdp);
|
||||
if (status != PJ_SUCCESS) {
|
||||
ast_test_status_update(test, "Error parsing SDP\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
sdp = ast_sdp_translator_to_sdp(translator, pjmedia_sdp);
|
||||
|
||||
if (strcmp(sdp->o_line->username, "alice")) {
|
||||
ast_test_status_update(test, "Unexpected SDP user '%s'\n", sdp->o_line->username);
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
} else if (sdp->o_line->session_id != 2890844526UL) {
|
||||
ast_test_status_update(test, "Unexpected SDP id '%" PRId64 "lu'\n", sdp->o_line->session_id);
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
} else if (sdp->o_line->session_version != 2890844527UL) {
|
||||
ast_test_status_update(test, "Unexpected SDP version '%" PRId64 "'\n", sdp->o_line->session_version);
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
} else if (strcmp(sdp->o_line->address_type, "IP4")) {
|
||||
ast_test_status_update(test, "Unexpected address family '%s'\n", sdp->o_line->address_type);
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
} else if (strcmp(sdp->o_line->address, "host.atlanta.example.com")) {
|
||||
ast_test_status_update(test, "Unexpected address '%s'\n", sdp->o_line->address);
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!verify_s_line(sdp->s_line, " ")) {
|
||||
ast_test_status_update(test, "Bad s line\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
} else if (!verify_c_line(sdp->c_line, "IP4", "host.atlanta.example.com")) {
|
||||
ast_test_status_update(test, "Bad c line\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
} else if (!verify_t_line(sdp->t_line, 123, 456)) {
|
||||
ast_test_status_update(test, "Bad t line\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!verify_m_line(sdp, 0, "audio", 49170, 1, "RTP/AVP", "0", "8", "97", NULL)) {
|
||||
ast_test_status_update(test, "Bad m line 1\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
} else if (!verify_a_line(sdp, 0, 0, "rtpmap", "0 PCMU/8000")) {
|
||||
ast_test_status_update(test, "Bad a line 1\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
} else if (!verify_a_line(sdp, 0, 1, "rtpmap", "8 PCMA/8000")) {
|
||||
ast_test_status_update(test, "Bad a line 2\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
} else if (!verify_a_line(sdp, 0, 2, "rtpmap", "97 iLBC/8000")) {
|
||||
ast_test_status_update(test, "Bad a line 3\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
} else if (!verify_a_line(sdp, 0, 3, "sendrecv", "")) {
|
||||
ast_test_status_update(test, "Bad a line 3\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
} else if (!verify_m_line(sdp, 1, "video", 51372, 1, "RTP/AVP", "31", "32", NULL)) {
|
||||
ast_test_status_update(test, "Bad m line 2\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
} else if (!verify_a_line(sdp, 1, 0, "rtpmap", "31 H261/90000")) {
|
||||
ast_test_status_update(test, "Bad a line 4\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
} else if (!verify_a_line(sdp, 1, 1, "rtpmap", "32 MPV/90000")) {
|
||||
ast_test_status_update(test, "Bad a line 5\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
ao2_cleanup(sdp);
|
||||
ast_sdp_translator_free(translator);
|
||||
pj_pool_release(pool);
|
||||
return res;
|
||||
}
|
||||
|
||||
AST_TEST_DEFINE(sdp_to_pjmedia_test)
|
||||
{
|
||||
struct ast_sdp_translator *translator;
|
||||
char *sdp_str =
|
||||
"v=0\r\n"
|
||||
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
|
||||
"s= \r\n"
|
||||
"c=IN IP4 host.atlanta.example.com\r\n"
|
||||
"t=123 456\r\n"
|
||||
"m=audio 49170 RTP/AVP 0 8 97\r\n"
|
||||
"a=rtpmap:0 PCMU/8000\r\n"
|
||||
"a=rtpmap:8 PCMA/8000\r\n"
|
||||
"a=rtpmap:97 iLBC/8000\r\n"
|
||||
"a=sendrecv\r\n"
|
||||
"m=video 51372 RTP/AVP 31 32\r\n"
|
||||
"a=rtpmap:31 H261/90000\r\n"
|
||||
"a=rtpmap:32 MPV/90000\r\n\r\n";
|
||||
pj_pool_t *pool;
|
||||
pjmedia_sdp_session *pjmedia_sdp_orig;
|
||||
const pjmedia_sdp_session *pjmedia_sdp_dup;
|
||||
struct ast_sdp *sdp = NULL;
|
||||
pj_status_t status;
|
||||
enum ast_test_result_state res = AST_TEST_PASS;
|
||||
char buf[2048];
|
||||
char errbuf[256];
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = "sdp_to_pjmedia";
|
||||
info->category = "/main/sdp/";
|
||||
info->summary = "SDP to PJMEDIA unit test";
|
||||
info->description =
|
||||
"Ensures PJMEDIA SDPs are translated correctly";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
pool = pj_pool_create(&sdp_caching_pool.factory, "pjmedia to sdp test", 1024, 1024, NULL);
|
||||
|
||||
translator = ast_sdp_translator_new(AST_SDP_IMPL_PJMEDIA);
|
||||
if (!translator) {
|
||||
ast_test_status_update(test, "Failed to create SDP translator\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
status = pjmedia_sdp_parse(pool, sdp_str, strlen(sdp_str), &pjmedia_sdp_orig);
|
||||
if (status != PJ_SUCCESS) {
|
||||
ast_test_status_update(test, "Error parsing SDP\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
sdp = ast_sdp_translator_to_sdp(translator, pjmedia_sdp_orig);
|
||||
pjmedia_sdp_dup = ast_sdp_translator_from_sdp(translator, sdp);
|
||||
|
||||
if ((status = pjmedia_sdp_session_cmp(pjmedia_sdp_orig, pjmedia_sdp_dup, 0)) != PJ_SUCCESS) {
|
||||
ast_test_status_update(test, "SDPs aren't equal\n");
|
||||
pjmedia_sdp_print(pjmedia_sdp_orig, buf, sizeof(buf));
|
||||
ast_test_status_update(test, "Original SDP is %s\n", buf);
|
||||
pjmedia_sdp_print(pjmedia_sdp_dup, buf, sizeof(buf));
|
||||
ast_test_status_update(test, "New SDP is %s\n", buf);
|
||||
pjmedia_strerror(status, errbuf, sizeof(errbuf));
|
||||
ast_test_status_update(test, "PJMEDIA says %d: '%s'\n", status, errbuf);
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
ao2_cleanup(sdp);
|
||||
ast_sdp_translator_free(translator);
|
||||
pj_pool_release(pool);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* TEST_FRAMEWORK */
|
||||
|
||||
static int load_module(void)
|
||||
{
|
||||
if (ast_sdp_register_translator(&pjmedia_translator)) {
|
||||
return AST_MODULE_LOAD_DECLINE;
|
||||
}
|
||||
ast_pjproject_caching_pool_init(&sdp_caching_pool, NULL, 1024 * 1024);
|
||||
AST_TEST_REGISTER(pjmedia_to_sdp_test);
|
||||
AST_TEST_REGISTER(sdp_to_pjmedia_test);
|
||||
|
||||
return AST_MODULE_LOAD_SUCCESS;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
ast_sdp_unregister_translator(&pjmedia_translator);
|
||||
ast_pjproject_caching_pool_destroy(&sdp_caching_pool);
|
||||
AST_TEST_UNREGISTER(pjmedia_to_sdp_test);
|
||||
AST_TEST_UNREGISTER(sdp_to_pjmedia_test);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int reload_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJMEDIA SDP Translator",
|
||||
.support_level = AST_MODULE_SUPPORT_CORE,
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.reload = reload_module,
|
||||
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
|
||||
.requires = "res_pjproject",
|
||||
);
|
2105
tests/test_sdp.c
2105
tests/test_sdp.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue