sdp: refactoring sdp parser/generator
move SDP generator function write_response_sdp() from mgcp_protocol.c to mgcp_sdp.c and use msgb_printf() instead of snprintf() move prototypes for mgcp_parse_sdp_data() and mgcp_set_audio_info() to mgcp_sdp.h change parameter list of mgcp_parse_sdp_data() so that it takes the rtp conn directly, rather than struct mgcp_rtp_end. add doxygen comments to all public functions Change-Id: I9f88c93872ff913bc211f560b26901267f577324
This commit is contained in:
parent
1e0b9f872c
commit
8970c497bc
|
@ -4,4 +4,5 @@ noinst_HEADERS = \
|
|||
mgcp_conn.h \
|
||||
mgcp_stat.h \
|
||||
mgcp_ep.h \
|
||||
mgcp_sdp.h \
|
||||
$(NULL)
|
||||
|
|
|
@ -317,9 +317,6 @@ enum {
|
|||
#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
|
||||
|
||||
#define PTYPE_UNDEFINED (-1)
|
||||
int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p);
|
||||
int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
|
||||
int payload_type, const char *audio_name);
|
||||
|
||||
/*! get the ip-address where the mgw application is bound on.
|
||||
* \param[in] endp mgcp endpoint, that holds a copy of the VTY parameters
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* SDP generation and parsing
|
||||
*
|
||||
* (C) 2009-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2014 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <osmocom/mgcp/mgcp_sdp.h>
|
||||
|
||||
int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
|
||||
struct mgcp_conn_rtp *conn,
|
||||
struct mgcp_parse_data *p);
|
||||
|
||||
int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
|
||||
int payload_type, const char *audio_name);
|
||||
|
||||
int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
|
||||
const struct mgcp_conn_rtp *conn, struct msgb *sdp,
|
||||
const char *addr);
|
|
@ -39,6 +39,7 @@
|
|||
#include <osmocom/mgcp/mgcp_stat.h>
|
||||
#include <osmocom/mgcp/mgcp_msg.h>
|
||||
#include <osmocom/mgcp/mgcp_ep.h>
|
||||
#include <osmocom/mgcp/mgcp_sdp.h>
|
||||
|
||||
struct mgcp_request {
|
||||
char *name;
|
||||
|
@ -191,80 +192,6 @@ static struct msgb *create_err_response(struct mgcp_endpoint *endp,
|
|||
return create_resp(endp, code, " FAIL", msg, trans, NULL, NULL);
|
||||
}
|
||||
|
||||
static int write_response_sdp(struct mgcp_endpoint *endp,
|
||||
struct mgcp_conn_rtp *conn,
|
||||
char *sdp_record, size_t size, const char *addr)
|
||||
{
|
||||
const char *fmtp_extra;
|
||||
const char *audio_name;
|
||||
int payload_type;
|
||||
int len;
|
||||
int nchars;
|
||||
|
||||
if (!conn)
|
||||
return -1;
|
||||
|
||||
endp->cfg->get_net_downlink_format_cb(endp, &payload_type,
|
||||
&audio_name, &fmtp_extra, conn);
|
||||
|
||||
len = snprintf(sdp_record, size,
|
||||
"v=0\r\n"
|
||||
"o=- %u 23 IN IP4 %s\r\n"
|
||||
"s=-\r\n"
|
||||
"c=IN IP4 %s\r\n"
|
||||
"t=0 0\r\n", conn->conn->id, addr, addr);
|
||||
|
||||
if (len < 0 || len >= size)
|
||||
goto buffer_too_small;
|
||||
|
||||
if (payload_type >= 0) {
|
||||
nchars = snprintf(sdp_record + len, size - len,
|
||||
"m=audio %d RTP/AVP %d\r\n",
|
||||
conn->end.local_port, payload_type);
|
||||
if (nchars < 0 || nchars >= size - len)
|
||||
goto buffer_too_small;
|
||||
|
||||
len += nchars;
|
||||
|
||||
if (audio_name && endp->tcfg->audio_send_name) {
|
||||
nchars = snprintf(sdp_record + len, size - len,
|
||||
"a=rtpmap:%d %s\r\n",
|
||||
payload_type, audio_name);
|
||||
|
||||
if (nchars < 0 || nchars >= size - len)
|
||||
goto buffer_too_small;
|
||||
|
||||
len += nchars;
|
||||
}
|
||||
|
||||
if (fmtp_extra) {
|
||||
nchars = snprintf(sdp_record + len, size - len,
|
||||
"%s\r\n", fmtp_extra);
|
||||
|
||||
if (nchars < 0 || nchars >= size - len)
|
||||
goto buffer_too_small;
|
||||
|
||||
len += nchars;
|
||||
}
|
||||
}
|
||||
if (conn->end.packet_duration_ms > 0 && endp->tcfg->audio_send_ptime) {
|
||||
nchars = snprintf(sdp_record + len, size - len,
|
||||
"a=ptime:%u\r\n",
|
||||
conn->end.packet_duration_ms);
|
||||
if (nchars < 0 || nchars >= size - len)
|
||||
goto buffer_too_small;
|
||||
|
||||
len += nchars;
|
||||
}
|
||||
|
||||
return len;
|
||||
|
||||
buffer_too_small:
|
||||
LOGP(DLMGCP, LOGL_ERROR, "SDP buffer too small: %zu (needed %d)\n",
|
||||
size, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Format MGCP response string (with SDP attached) */
|
||||
static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
|
||||
struct mgcp_conn_rtp *conn,
|
||||
|
@ -272,11 +199,15 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
|
|||
const char *trans_id)
|
||||
{
|
||||
const char *addr = endp->cfg->local_ip;
|
||||
char sdp_record[4096];
|
||||
int len;
|
||||
int nchars;
|
||||
struct msgb *sdp;
|
||||
int rc;
|
||||
struct msgb *result;
|
||||
char osmux_extension[strlen("\nX-Osmux: 255") + 1];
|
||||
|
||||
sdp = msgb_alloc_headroom(4096, 128, "sdp record");
|
||||
if (!sdp)
|
||||
return NULL;
|
||||
|
||||
if (!addr)
|
||||
addr = mgcp_net_src_addr(endp);
|
||||
|
||||
|
@ -287,21 +218,19 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
|
|||
osmux_extension[0] = '\0';
|
||||
}
|
||||
|
||||
len = snprintf(sdp_record, sizeof(sdp_record),
|
||||
"I: %u%s\n\n", conn->conn->id, osmux_extension);
|
||||
if (len < 0)
|
||||
return NULL;
|
||||
rc = msgb_printf(sdp, "I: %u%s\n\n", conn->conn->id, osmux_extension);
|
||||
if (rc < 0)
|
||||
goto error;
|
||||
|
||||
nchars = write_response_sdp(endp, conn, sdp_record + len,
|
||||
sizeof(sdp_record) - len - 1, addr);
|
||||
if (nchars < 0)
|
||||
return NULL;
|
||||
|
||||
len += nchars;
|
||||
|
||||
sdp_record[sizeof(sdp_record) - 1] = '\0';
|
||||
|
||||
return create_resp(endp, 200, " OK", msg, trans_id, NULL, sdp_record);
|
||||
rc = mgcp_write_response_sdp(endp, conn, sdp, addr);
|
||||
if (rc < 0)
|
||||
goto error;
|
||||
result = create_resp(endp, 200, " OK", msg, trans_id, NULL, (char*) sdp->data);
|
||||
msgb_free(sdp);
|
||||
return result;
|
||||
error:
|
||||
msgb_free(sdp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Send out dummy packet to keep the connection open, if the connection is an
|
||||
|
@ -689,7 +618,7 @@ mgcp_header_done:
|
|||
|
||||
/* set up RTP media parameters */
|
||||
if (have_sdp)
|
||||
mgcp_parse_sdp_data(endp, &conn->end, p);
|
||||
mgcp_parse_sdp_data(endp, conn, p);
|
||||
else if (endp->local_options.codec)
|
||||
mgcp_set_audio_info(p->cfg, &conn->end.codec,
|
||||
PTYPE_UNDEFINED, endp->local_options.codec);
|
||||
|
@ -836,7 +765,7 @@ mgcp_header_done:
|
|||
conn->conn->mode = conn->conn->mode_orig;
|
||||
|
||||
if (have_sdp)
|
||||
mgcp_parse_sdp_data(endp, &conn->end, p);
|
||||
mgcp_parse_sdp_data(endp, conn, p);
|
||||
|
||||
set_local_cx_options(endp->tcfg->endpoints, &endp->local_options,
|
||||
local_options);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/mgcp/mgcp.h>
|
||||
#include <osmocom/mgcp/mgcp_internal.h>
|
||||
#include <osmocom/mgcp/mgcp_msg.h>
|
||||
|
@ -38,6 +39,12 @@ struct sdp_rtp_map {
|
|||
int channels;
|
||||
};
|
||||
|
||||
/*! Set codec configuration depending on payload type and codec name.
|
||||
* \param[in] ctx talloc context.
|
||||
* \param[out] codec configuration (caller provided memory).
|
||||
* \param[in] payload_type codec type id (e.g. 3 for GSM, -1 when undefined).
|
||||
* \param[in] audio_name audio codec name (e.g. "GSM/8000/1").
|
||||
* \returns 0 on success, -1 on failure. */
|
||||
int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
|
||||
int payload_type, const char *audio_name)
|
||||
{
|
||||
|
@ -107,7 +114,7 @@ int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void codecs_initialize(void *ctx, struct sdp_rtp_map *codecs, int used)
|
||||
static void codecs_initialize(void *ctx, struct sdp_rtp_map *codecs, int used)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -137,7 +144,8 @@ void codecs_initialize(void *ctx, struct sdp_rtp_map *codecs, int used)
|
|||
}
|
||||
}
|
||||
|
||||
void codecs_update(void *ctx, struct sdp_rtp_map *codecs, int used, int payload, char *audio_name)
|
||||
static void codecs_update(void *ctx, struct sdp_rtp_map *codecs, int used,
|
||||
int payload, const char *audio_name)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -163,7 +171,9 @@ void codecs_update(void *ctx, struct sdp_rtp_map *codecs, int used, int payload,
|
|||
LOGP(DLMGCP, LOGL_ERROR, "Unconfigured PT(%d) with %s\n", payload, audio_name);
|
||||
}
|
||||
|
||||
int is_codec_compatible(struct mgcp_endpoint *endp, struct sdp_rtp_map *codec)
|
||||
/* Check if the codec matches what is set up in the trunk config */
|
||||
static int is_codec_compatible(const struct mgcp_endpoint *endp,
|
||||
const struct sdp_rtp_map *codec)
|
||||
{
|
||||
char *bts_codec;
|
||||
char audio_codec[64];
|
||||
|
@ -182,7 +192,17 @@ int is_codec_compatible(struct mgcp_endpoint *endp, struct sdp_rtp_map *codec)
|
|||
return strcasecmp(audio_codec, codec->codec_name) == 0;
|
||||
}
|
||||
|
||||
int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
|
||||
/*! Analyze SDP input string.
|
||||
* \param[in] endp trunk endpoint.
|
||||
* \param[out] conn associated rtp connection.
|
||||
* \param[out] caller provided memory to store the parsing results.
|
||||
* \returns 0 on success, -1 on failure.
|
||||
*
|
||||
* Note: In conn (conn->end) the function returns the packet duration,
|
||||
* the rtp port and the rtcp port */
|
||||
int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
|
||||
struct mgcp_conn_rtp *conn,
|
||||
struct mgcp_parse_data *p)
|
||||
{
|
||||
struct sdp_rtp_map codecs[10];
|
||||
int codecs_used = 0;
|
||||
|
@ -191,7 +211,13 @@ int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, st
|
|||
int i;
|
||||
int codecs_assigned = 0;
|
||||
void *tmp_ctx = talloc_new(NULL);
|
||||
struct mgcp_rtp_end *rtp;
|
||||
|
||||
OSMO_ASSERT(endp);
|
||||
OSMO_ASSERT(conn);
|
||||
OSMO_ASSERT(p);
|
||||
|
||||
rtp = &conn->end;
|
||||
memset(&codecs, 0, sizeof(codecs));
|
||||
|
||||
for_each_line(line, p->save) {
|
||||
|
@ -304,3 +330,73 @@ int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, st
|
|||
return codecs_assigned > 0;
|
||||
}
|
||||
|
||||
/*! Generate SDP response string.
|
||||
* \param[in] endp trunk endpoint.
|
||||
* \param[in] conn associated rtp connection.
|
||||
* \param[out] sdp msg buffer to append resulting SDP string data.
|
||||
* \param[in] addr IPV4 address string (e.g. 192.168.100.1).
|
||||
* \returns 0 on success, -1 on failure. */
|
||||
int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
|
||||
const struct mgcp_conn_rtp *conn, struct msgb *sdp,
|
||||
const char *addr)
|
||||
{
|
||||
const char *fmtp_extra;
|
||||
const char *audio_name;
|
||||
int payload_type;
|
||||
int rc;
|
||||
|
||||
OSMO_ASSERT(endp);
|
||||
OSMO_ASSERT(conn);
|
||||
OSMO_ASSERT(sdp);
|
||||
OSMO_ASSERT(addr);
|
||||
|
||||
/* FIXME: constify endp and conn args in get_net_donwlink_format_cb() */
|
||||
endp->cfg->get_net_downlink_format_cb((struct mgcp_endpoint *)endp,
|
||||
&payload_type, &audio_name,
|
||||
&fmtp_extra,
|
||||
(struct mgcp_conn_rtp *)conn);
|
||||
|
||||
rc = msgb_printf(sdp,
|
||||
"v=0\r\n"
|
||||
"o=- %u 23 IN IP4 %s\r\n"
|
||||
"s=-\r\n"
|
||||
"c=IN IP4 %s\r\n"
|
||||
"t=0 0\r\n", conn->conn->id, addr, addr);
|
||||
|
||||
if (rc < 0)
|
||||
goto buffer_too_small;
|
||||
|
||||
if (payload_type >= 0) {
|
||||
rc = msgb_printf(sdp, "m=audio %d RTP/AVP %d\r\n",
|
||||
conn->end.local_port, payload_type);
|
||||
if (rc < 0)
|
||||
goto buffer_too_small;
|
||||
|
||||
if (audio_name && endp->tcfg->audio_send_name) {
|
||||
rc = msgb_printf(sdp, "a=rtpmap:%d %s\r\n",
|
||||
payload_type, audio_name);
|
||||
|
||||
if (rc < 0)
|
||||
goto buffer_too_small;
|
||||
}
|
||||
|
||||
if (fmtp_extra) {
|
||||
rc = msgb_printf(sdp, "%s\r\n", fmtp_extra);
|
||||
|
||||
if (rc < 0)
|
||||
goto buffer_too_small;
|
||||
}
|
||||
}
|
||||
if (conn->end.packet_duration_ms > 0 && endp->tcfg->audio_send_ptime) {
|
||||
rc = msgb_printf(sdp, "a=ptime:%u\r\n",
|
||||
conn->end.packet_duration_ms);
|
||||
if (rc < 0)
|
||||
goto buffer_too_small;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
buffer_too_small:
|
||||
LOGP(DLMGCP, LOGL_ERROR, "SDP messagebuffer too small\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue