summaryrefslogtreecommitdiff
path: root/main/sdp.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/sdp.c')
-rw-r--r--main/sdp.c950
1 files changed, 0 insertions, 950 deletions
diff --git a/main/sdp.c b/main/sdp.c
deleted file mode 100644
index e5c8803d5..000000000
--- a/main/sdp.c
+++ /dev/null
@@ -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;
-}