parent
bd7dfe0b2d
commit
058c276133
|
@ -96,3 +96,6 @@ int sdp_audio_codecs_to_gsm0808_channel_type(struct gsm0808_channel_type *ct, co
|
|||
enum mgcp_codecs sdp_audio_codec_to_mgcp_codec(const struct osmo_sdp_codec *codec);
|
||||
|
||||
char *sdp_codec_to_str(const struct osmo_sdp_codec *codec);
|
||||
char *sdp_msg_to_str(const struct osmo_sdp_msg *msg, bool summarize);
|
||||
|
||||
void sdp_msg_replace(void *ctx, struct osmo_sdp_msg **var, struct osmo_sdp_msg *new_msg);
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
#include <osmocom/sdp/sdp_msg.h>
|
||||
#include <osmocom/msc/csd_bs.h>
|
||||
|
||||
void sdp_codecs_set_csd(void *ctx, struct osmo_sdp_codec_list *codecs);
|
||||
void sdp_codecs_set_csd(void *ctx, struct osmo_sdp_codec_list **codecs);
|
||||
|
|
|
@ -131,13 +131,14 @@ struct gsm_trans {
|
|||
bool mncc_initiated; /* Whether an MNCC Release is necessary on failure */
|
||||
struct osmo_lcls *lcls;
|
||||
/* SDP as last received from the remote call leg. */
|
||||
struct osmo_sdp_msg remote;
|
||||
struct osmo_sdp_msg *remote;
|
||||
/* Track codec/CSD choices from BSS and remote call leg */
|
||||
struct codec_filter codecs;
|
||||
struct codec_filter *codec_filter;
|
||||
struct csd_filter csd;
|
||||
/* Resulting choice from codecs/bearer services and the
|
||||
* local RTP address to be sent to the remote call leg. */
|
||||
struct osmo_sdp_msg local;
|
||||
struct osmo_sdp_msg *local;
|
||||
struct csd_bs_list local_bearer_services;
|
||||
} cc;
|
||||
struct {
|
||||
struct gsm411_smc_inst smc_inst;
|
||||
|
|
|
@ -437,19 +437,19 @@ int bearer_cap_set_radio(struct gsm_mncc_bearer_cap *bearer_cap)
|
|||
/* Try to convert the SDP audio codec name to Speech Versions to append to Bearer Capabilities.
|
||||
* Return the number of Speech Version entries added (some may add more than one, others may be unknown/unapplicable and
|
||||
* return 0). */
|
||||
int sdp_audio_codec_add_to_bearer_cap(struct gsm_mncc_bearer_cap *bearer_cap, const struct sdp_audio_codec *codec)
|
||||
int sdp_audio_codec_add_to_bearer_cap(struct gsm_mncc_bearer_cap *bearer_cap, const struct osmo_sdp_codec *codec)
|
||||
{
|
||||
const struct codec_mapping *m;
|
||||
int added = 0;
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, "sdp_audio_codec_add_to_bearer_cap(%s)\n", sdp_audio_codec_to_str(codec));
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, "sdp_audio_codec_add_to_bearer_cap(%s)\n", sdp_codec_to_str(codec));
|
||||
codec_mapping_foreach(m) {
|
||||
int i;
|
||||
if (osmo_sdp_codec_cmp(&m->sdp, codec, &osmo_sdp_codec_cmp_equivalent))
|
||||
continue;
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, " %s speech_ver_count %d\n", sdp_audio_codec_to_str(&m->sdp),
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, " %s speech_ver_count %d\n", sdp_codec_to_str(&m->sdp),
|
||||
m->speech_ver_count);
|
||||
for (i = 0; i < m->speech_ver_count; i++) {
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, " - add %s (enum gsm48_bcap_speech_ver)%d\n", sdp_audio_codec_to_str(&m->sdp),
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, " - add %s (enum gsm48_bcap_speech_ver)%d\n", sdp_codec_to_str(&m->sdp),
|
||||
m->speech_ver[i]);
|
||||
added += bearer_cap_add_speech_ver(bearer_cap, m->speech_ver[i]);
|
||||
}
|
||||
|
@ -513,14 +513,14 @@ void sdp_audio_codecs_from_bearer_cap(struct osmo_sdp_codec_list *codecs, const
|
|||
/* Append an entry for the given sdp_audio_codec to the gsm0808_speech_codec_list.
|
||||
* Return 0 if an entry was added, -ENOENT when there is no mapping to gsm0808_speech_codec for the given
|
||||
* sdp_audio_codec, and -ENOSPC when scl is full and nothing could be added. */
|
||||
int sdp_audio_codec_to_speech_codec_list(struct gsm0808_speech_codec_list *scl, const struct sdp_audio_codec *codec)
|
||||
int sdp_audio_codec_to_speech_codec_list(struct gsm0808_speech_codec_list *scl, const struct osmo_sdp_codec *codec)
|
||||
{
|
||||
const struct codec_mapping *m;
|
||||
int added = 0;
|
||||
int i;
|
||||
|
||||
codec_mapping_foreach (m) {
|
||||
if (sdp_audio_codec_cmp(&m->sdp, codec, true, false))
|
||||
if (osmo_sdp_codec_cmp(&m->sdp, codec, &osmo_sdp_codec_cmp_equivalent))
|
||||
continue;
|
||||
if (!m->has_gsm0808_speech_codec)
|
||||
continue;
|
||||
|
@ -555,20 +555,20 @@ int sdp_audio_codec_to_speech_codec_list(struct gsm0808_speech_codec_list *scl,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void sdp_audio_codecs_to_speech_codec_list(struct gsm0808_speech_codec_list *scl, const struct sdp_audio_codecs *ac)
|
||||
void sdp_audio_codecs_to_speech_codec_list(struct gsm0808_speech_codec_list *scl, const struct osmo_sdp_codec_list *ac)
|
||||
{
|
||||
const struct sdp_audio_codec *codec;
|
||||
const struct osmo_sdp_codec *codec;
|
||||
|
||||
*scl = (struct gsm0808_speech_codec_list){};
|
||||
|
||||
sdp_audio_codecs_foreach(codec, ac) {
|
||||
osmo_sdp_codec_list_foreach(codec, ac) {
|
||||
int rc = sdp_audio_codec_to_speech_codec_list(scl, codec);
|
||||
if (rc == -ENOSPC)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sdp_audio_codecs_from_speech_codec_list(struct sdp_audio_codecs *ac, const struct gsm0808_speech_codec_list *cl)
|
||||
void sdp_audio_codecs_from_speech_codec_list(struct osmo_sdp_codec_list *ac, const struct gsm0808_speech_codec_list *cl)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < cl->len; i++) {
|
||||
|
@ -583,9 +583,9 @@ void sdp_audio_codecs_from_speech_codec_list(struct sdp_audio_codecs *ac, const
|
|||
}
|
||||
}
|
||||
|
||||
int sdp_audio_codecs_to_gsm0808_channel_type(struct gsm0808_channel_type *ct, const struct sdp_audio_codecs *ac)
|
||||
int sdp_audio_codecs_to_gsm0808_channel_type(struct gsm0808_channel_type *ct, const struct osmo_sdp_codec_list *ac)
|
||||
{
|
||||
const struct sdp_audio_codec *codec;
|
||||
const struct osmo_sdp_codec *codec;
|
||||
bool fr_present = false;
|
||||
int first_fr_idx = -1;
|
||||
bool hr_present = false;
|
||||
|
@ -597,19 +597,19 @@ int sdp_audio_codecs_to_gsm0808_channel_type(struct gsm0808_channel_type *ct, co
|
|||
};
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, "sdp_audio_codecs_to_gsm0808_channel_type()\n");
|
||||
|
||||
sdp_audio_codecs_foreach(codec, ac) {
|
||||
osmo_sdp_codec_list_foreach(codec, ac) {
|
||||
const struct codec_mapping *m;
|
||||
int i;
|
||||
bool dup;
|
||||
idx++;
|
||||
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, "- codec = %s\n", sdp_audio_codec_to_str(codec));
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, "- codec = %s\n", sdp_codec_to_str(codec));
|
||||
|
||||
codec_mapping_foreach(m) {
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, " (m=%s %s)\n", sdp_audio_codec_to_str(&m->sdp),
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, " (m=%s %s)\n", sdp_codec_to_str(&m->sdp),
|
||||
gsm0808_permitted_speech_name(m->perm_speech));
|
||||
|
||||
if (sdp_audio_codec_cmp(codec, &m->sdp, true, false))
|
||||
if (osmo_sdp_codec_cmp(codec, &m->sdp, &osmo_sdp_codec_cmp_equivalent))
|
||||
continue;
|
||||
|
||||
switch (m->perm_speech) {
|
||||
|
@ -668,11 +668,11 @@ int sdp_audio_codecs_to_gsm0808_channel_type(struct gsm0808_channel_type *ct, co
|
|||
return 0;
|
||||
}
|
||||
|
||||
enum mgcp_codecs sdp_audio_codec_to_mgcp_codec(const struct sdp_audio_codec *codec)
|
||||
enum mgcp_codecs sdp_audio_codec_to_mgcp_codec(const struct osmo_sdp_codec *codec)
|
||||
{
|
||||
const struct codec_mapping *m;
|
||||
codec_mapping_foreach(m) {
|
||||
if (!sdp_audio_codec_cmp(&m->sdp, codec, true, false))
|
||||
if (!osmo_sdp_codec_cmp(&m->sdp, codec, &osmo_sdp_codec_cmp_equivalent))
|
||||
return m->mgcp;
|
||||
}
|
||||
return NO_MGCP_CODEC;
|
||||
|
@ -682,3 +682,21 @@ char *sdp_codec_to_str(const struct osmo_sdp_codec *codec)
|
|||
{
|
||||
return osmo_sdp_codec_to_str_c(OTC_SELECT, codec);
|
||||
}
|
||||
|
||||
char *sdp_msg_to_str(const struct osmo_sdp_msg *msg, bool summarize)
|
||||
{
|
||||
return osmo_sdp_msg_to_str_c(OTC_SELECT, msg, summarize);
|
||||
}
|
||||
|
||||
void sdp_msg_replace(void *ctx, struct osmo_sdp_msg **var, struct osmo_sdp_msg *new_msg)
|
||||
{
|
||||
struct osmo_sdp_msg *msg = *var;
|
||||
if (msg)
|
||||
talloc_free(msg);
|
||||
msg = new_msg;
|
||||
if (msg)
|
||||
talloc_steal(ctx, msg);
|
||||
else
|
||||
msg = osmo_sdp_msg_alloc(ctx);
|
||||
*var = msg;
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ int csd_filter_run(struct csd_filter *filter, struct osmo_sdp_msg *sdp_result, s
|
|||
csd_bs_list_add_bs(r, a);
|
||||
}
|
||||
|
||||
sdp_codecs_set_csd(sdp_result, &result->codecs);
|
||||
sdp_codecs_set_csd(sdp_result, &sdp_result->codecs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ int csd_filter_to_str_buf(char *buf, size_t buflen, const struct csd_filter *fil
|
|||
const struct osmo_sdp_msg *result, const struct osmo_sdp_msg *remote)
|
||||
{
|
||||
struct osmo_strbuf sb = { .buf = buf, .len = buflen };
|
||||
OSMO_STRBUF_APPEND(sb, sdp_msg_to_str_buf, result);
|
||||
OSMO_STRBUF_APPEND(sb, osmo_sdp_msg_to_str_buf, result, false);
|
||||
OSMO_STRBUF_PRINTF(sb, " (from:");
|
||||
|
||||
if (filter->assignment) {
|
||||
|
@ -115,9 +115,9 @@ int csd_filter_to_str_buf(char *buf, size_t buflen, const struct csd_filter *fil
|
|||
OSMO_STRBUF_APPEND(sb, csd_bs_to_str_buf, filter->assignment);
|
||||
}
|
||||
|
||||
if (remote->bearer_services.count || osmo_sockaddr_str_is_nonzero(&remote->rtp)) {
|
||||
if (!osmo_sdp_codec_list_is_empty(remote->codecs) || osmo_sockaddr_str_is_nonzero(&remote->rtp)) {
|
||||
OSMO_STRBUF_PRINTF(sb, " remote=");
|
||||
OSMO_STRBUF_APPEND(sb, sdp_msg_to_str_buf, remote);
|
||||
OSMO_STRBUF_APPEND(sb, osmo_sdp_msg_to_str_buf, remote, true);
|
||||
}
|
||||
|
||||
if (filter->ms.count) {
|
||||
|
|
|
@ -240,7 +240,7 @@ static void _log_mncc_rx_tx(const char *file, int line,
|
|||
struct gsm_trans *trans, const char *rx_tx, const union mncc_msg *mncc)
|
||||
{
|
||||
const char *sdp = NULL;
|
||||
struct osmo_sdp_msg sdp_msg = {};
|
||||
struct osmo_sdp_msg *sdp_msg = NULL;
|
||||
struct osmo_sockaddr addr = {};
|
||||
|
||||
if (!log_check_level(DMNCC, LOGL_DEBUG))
|
||||
|
@ -271,19 +271,20 @@ static void _log_mncc_rx_tx(const char *file, int line,
|
|||
}
|
||||
|
||||
if (sdp && sdp[0]) {
|
||||
int rc = sdp_msg_from_sdp_str(&sdp_msg, sdp);
|
||||
if (rc != 0) {
|
||||
LOG_TRANS_CAT_SRC(trans, DMNCC, LOGL_ERROR, file, line, "%s %s: invalid SDP message (trying anyway)\n",
|
||||
struct osmo_sdp_err err;
|
||||
sdp_msg = osmo_sdp_msg_decode(OTC_SELECT, sdp, &err);
|
||||
if (err.rc != 0) {
|
||||
LOG_TRANS_CAT_SRC(trans, DMNCC, LOGL_ERROR, file, line,
|
||||
"%s %s: invalid SDP message (trying anyway): %s\n",
|
||||
rx_tx,
|
||||
get_mncc_name(mncc->msg_type));
|
||||
LOG_TRANS_CAT_SRC(trans, DMNCC, LOGL_DEBUG, file, line, "erratic SDP: %s\n",
|
||||
osmo_quote_cstr_c(OTC_SELECT, sdp, -1));
|
||||
get_mncc_name(mncc->msg_type),
|
||||
osmo_quote_cstr_c(OTC_SELECT, err.src_str, err.src_str_len));
|
||||
return;
|
||||
}
|
||||
LOG_TRANS_CAT_SRC(trans, DMNCC, LOGL_DEBUG, file, line, "%s %s (RTP=%s)\n",
|
||||
rx_tx,
|
||||
get_mncc_name(mncc->msg_type),
|
||||
sdp_msg_to_str(&sdp_msg));
|
||||
sdp_msg_to_str(sdp_msg, false));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -754,10 +755,10 @@ void gsm48_cc_rx_setup_cn_local_rtp_port_known(struct gsm_trans *trans)
|
|||
trans_free(trans);
|
||||
return;
|
||||
}
|
||||
trans->cc.local.rtp = *rtp_cn_local;
|
||||
trans->cc.local->rtp = *rtp_cn_local;
|
||||
|
||||
sdp = trans->cc.local.audio_codecs.count ? &trans->cc.local : NULL;
|
||||
rc = sdp_msg_to_sdp_str_buf(setup.sdp, sizeof(setup.sdp), sdp);
|
||||
sdp = osmo_sdp_codec_list_is_empty(trans->cc.local->codecs) ? NULL : trans->cc.local;
|
||||
rc = osmo_sdp_msg_encode_buf(setup.sdp, sizeof(setup.sdp), sdp);
|
||||
if (rc >= sizeof(setup.sdp)) {
|
||||
LOG_TRANS(trans, LOGL_ERROR, "MNCC_SETUP_IND: SDP too long (%d > %zu bytes)\n", rc, sizeof(setup.sdp));
|
||||
trans_free(trans);
|
||||
|
@ -768,14 +769,22 @@ void gsm48_cc_rx_setup_cn_local_rtp_port_known(struct gsm_trans *trans)
|
|||
mncc_recvmsg(trans->net, trans, MNCC_SETUP_IND, &setup);
|
||||
}
|
||||
|
||||
static bool codecs_match(const struct sdp_audio_codec *a, const struct sdp_audio_codec *b)
|
||||
static bool codecs_match(const struct osmo_sdp_codec *a, const struct osmo_sdp_codec *b)
|
||||
{
|
||||
if (!sdp_audio_codec_cmp(a, b, true, false))
|
||||
if (!osmo_sdp_codec_cmp(a, b, &osmo_sdp_codec_cmp_equivalent))
|
||||
return true;
|
||||
|
||||
/* Codecs are not identical. But will the MGW be able to transcode? */
|
||||
if (!strcmp("AMR", a->subtype_name) && !strcmp("AMR", b->subtype_name)) {
|
||||
/* TODO: compare matching mode-set. */
|
||||
if (!strcmp("AMR", a->encoding_name) && !strcmp("AMR", b->encoding_name)) {
|
||||
/* MGW is expected to even out octet-align=0 vs 1 mismatches, so do not compare AMR octet-align. */
|
||||
|
||||
/* FIXME: compare matching mode-set.
|
||||
* So far regarding any and all mode-sets as equivalent.
|
||||
* Instead, a well-guided 'false' here may help to switch the BSS to an FR channel if the remote side
|
||||
* cannot do any HR rates. */
|
||||
|
||||
/* TODO: any other important AMR fmtp parameters? So far we've only ever seen 'octet-align' and
|
||||
* 'mode-set' in practice. So far regard all of them as not important for codec matching. */
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -784,43 +793,48 @@ static bool codecs_match(const struct sdp_audio_codec *a, const struct sdp_audio
|
|||
static void rx_mncc_sdp(struct gsm_trans *trans, uint32_t mncc_msg_type, const char *sdp,
|
||||
const struct gsm_mncc_bearer_cap *bcap)
|
||||
{
|
||||
struct codec_filter *codecs = &trans->cc.codecs;
|
||||
struct codec_filter *codecs = trans->cc.codec_filter;
|
||||
struct call_leg *cl = trans->msc_a ? trans->msc_a->cc.call_leg : NULL;
|
||||
struct rtp_stream *rtp_cn = cl ? cl->rtp[RTP_TO_CN] : NULL;
|
||||
|
||||
if (sdp[0]) {
|
||||
int rc = sdp_msg_from_sdp_str(&trans->cc.remote, sdp);
|
||||
if (rc)
|
||||
LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR, "rx %s: Failed to parse SDP: %d. Trying anyway.\n",
|
||||
get_mncc_name(mncc_msg_type), rc);
|
||||
struct osmo_sdp_err err;
|
||||
struct osmo_sdp_msg *msg = osmo_sdp_msg_decode(OTC_SELECT, sdp, &err);
|
||||
if (err.rc)
|
||||
LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR,
|
||||
"rx %s: Failed to parse SDP, trying anyway: %d at %s\n",
|
||||
get_mncc_name(mncc_msg_type), err.rc,
|
||||
osmo_quote_cstr_c(OTC_SELECT, err.src_str, err.src_str_len));
|
||||
else if (msg)
|
||||
sdp_msg_replace(trans, &trans->cc.remote, msg);
|
||||
}
|
||||
|
||||
/* if there is no SDP information or we failed to parse it, try using the Bearer Cap from MNCC, if any. */
|
||||
if (!trans->cc.remote.audio_codecs.count && bcap) {
|
||||
trans->cc.remote = (struct osmo_sdp_msg){};
|
||||
if (bcap && (!trans->cc.remote || osmo_sdp_codec_list_is_empty(trans->cc.remote->codecs))) {
|
||||
sdp_msg_replace(trans, &trans->cc.remote, NULL);
|
||||
trans_cc_set_remote_from_bc(trans, bcap);
|
||||
LOG_TRANS_CAT(trans, DMNCC, LOGL_DEBUG, "rx %s Bearer Cap: remote=%s\n",
|
||||
get_mncc_name(mncc_msg_type), sdp_msg_to_str(&trans->cc.remote));
|
||||
get_mncc_name(mncc_msg_type), sdp_msg_to_str(trans->cc.remote, false));
|
||||
}
|
||||
|
||||
if (!trans->cc.remote.audio_codecs.count)
|
||||
if (!trans->cc.remote || osmo_sdp_codec_list_is_empty(trans->cc.remote->codecs))
|
||||
LOG_TRANS(trans, LOGL_INFO,
|
||||
"Got no information of remote audio codecs: neither SDP nor Bearer Capability. Trying anyway.\n");
|
||||
|
||||
trans_cc_filter_run(trans);
|
||||
if (rtp_cn) {
|
||||
rtp_stream_set_remote_addr_and_codecs(rtp_cn, &trans->cc.remote);
|
||||
rtp_stream_set_remote_addr_and_codecs(rtp_cn, trans->cc.remote);
|
||||
rtp_stream_commit(rtp_cn);
|
||||
}
|
||||
|
||||
/* See if we need to switch codecs to maintain TFO: has the remote side changed the codecs information? If we
|
||||
* have already assigned a specific codec here, but the remote call leg has now chosen a different codec, we
|
||||
* need to re-assign this call leg to match the remote leg. */
|
||||
if (!sdp_audio_codec_is_set(&codecs->assignment)) {
|
||||
if (!osmo_sdp_codec_is_set(codecs->assignment)) {
|
||||
/* Voice channel assignment has not completed. Do not interfere. */
|
||||
return;
|
||||
}
|
||||
if (!trans->cc.remote.audio_codecs.count) {
|
||||
if (!trans->cc.remote || osmo_sdp_codec_list_is_empty(trans->cc.remote->codecs)) {
|
||||
/* Don't know remote codecs, nothing to do. */
|
||||
return;
|
||||
}
|
||||
|
@ -833,13 +847,13 @@ static void rx_mncc_sdp(struct gsm_trans *trans, uint32_t mncc_msg_type, const c
|
|||
* single codec in the SDP; but at least MO *must* send all possible codecs along, to give MT a chance to find a
|
||||
* good match. Maybe MO should offer all supported codecs, but MT should limit to a single pick -- but what do
|
||||
* other SDP peers do, say via SIP? */
|
||||
if (codecs_match(&trans->cc.remote.audio_codecs.codec[0], &codecs->assignment))
|
||||
if (codecs_match(osmo_sdp_codec_list_first(trans->cc.remote->codecs), codecs->assignment))
|
||||
return;
|
||||
|
||||
/* We've already completed Assignment of a voice channel (some time ago), and now the remote side has changed
|
||||
* to a mismatching codec (list). Try to re-assign this side to a matching codec. */
|
||||
LOG_TRANS(trans, LOGL_INFO, "Remote call leg mismatches assigned codec: %s\n",
|
||||
codec_filter_to_str(&trans->cc.codecs, &trans->cc.local, &trans->cc.remote));
|
||||
codec_filter_to_str(trans->cc.codec_filter, trans->cc.local, trans->cc.remote));
|
||||
msc_a_tx_assignment_cmd(trans->msc_a);
|
||||
}
|
||||
|
||||
|
@ -908,14 +922,14 @@ static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
|
|||
case GSM48_BCAP_ITCAP_FAX_G3:
|
||||
case GSM48_BCAP_ITCAP_UNR_DIG_INF:
|
||||
if (setup->fields & MNCC_F_BEARER_CAP) {
|
||||
trans->cc.remote = (struct osmo_sdp_msg){};
|
||||
sdp_msg_replace(trans, &trans->cc.remote, NULL);
|
||||
trans_cc_set_remote_from_bc(trans, &setup->bearer_cap);
|
||||
LOG_TRANS_CAT(trans, DMNCC, LOGL_DEBUG, "rx %s Bearer Cap: remote=%s\n",
|
||||
get_mncc_name(setup->msg_type), sdp_msg_to_str(&trans->cc.remote));
|
||||
get_mncc_name(setup->msg_type), sdp_msg_to_str(trans->cc.remote, false));
|
||||
} else {
|
||||
LOG_TRANS(trans, LOGL_INFO,
|
||||
"Got no information of remote Bearer Capability. Trying anyway.\n");
|
||||
sdp_audio_codecs_set_csd(trans, &trans->cc.codecs.ms);
|
||||
sdp_codecs_set_csd(trans->cc.codec_filter, &trans->cc.codec_filter->ms);
|
||||
}
|
||||
trans_cc_filter_run(trans);
|
||||
break;
|
||||
|
@ -933,7 +947,7 @@ static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
|
|||
bearer_cap = (struct gsm_mncc_bearer_cap){
|
||||
.speech_ver = { -1 },
|
||||
};
|
||||
sdp_audio_codecs_to_bearer_cap(&bearer_cap, &trans->cc.local.audio_codecs);
|
||||
sdp_audio_codecs_to_bearer_cap(&bearer_cap, trans->cc.local->codecs);
|
||||
rc = bearer_cap_set_radio(&bearer_cap);
|
||||
if (rc) {
|
||||
LOG_TRANS(trans, LOGL_ERROR, "Error composing Bearer Capability for CC Setup\n");
|
||||
|
@ -947,7 +961,7 @@ static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
|
|||
if (bearer_cap.speech_ver[0] == -1) {
|
||||
LOG_TRANS(trans, LOGL_ERROR, "%s: no codec match possible: %s\n",
|
||||
get_mncc_name(setup->msg_type),
|
||||
codec_filter_to_str(&trans->cc.codecs, &trans->cc.local, &trans->cc.remote));
|
||||
codec_filter_to_str(trans->cc.codec_filter, trans->cc.local, trans->cc.remote));
|
||||
|
||||
/* incompatible codecs */
|
||||
rc = mncc_release_ind(trans->net, trans, trans->callref,
|
||||
|
@ -962,7 +976,7 @@ static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
|
|||
case GSM48_BCAP_ITCAP_3k1_AUDIO:
|
||||
case GSM48_BCAP_ITCAP_FAX_G3:
|
||||
case GSM48_BCAP_ITCAP_UNR_DIG_INF:
|
||||
if (csd_bs_list_to_bearer_cap(&bearer_cap, &trans->cc.local.bearer_services) == 0) {
|
||||
if (csd_bs_list_to_bearer_cap(&bearer_cap, &trans->cc.local_bearer_services) == 0) {
|
||||
LOG_TRANS(trans, LOGL_ERROR, "Error composing Bearer Capability for CC Setup\n");
|
||||
|
||||
/* incompatible codecs */
|
||||
|
@ -1109,7 +1123,7 @@ static int gsm48_cc_mt_rtp_port_and_codec_known(struct gsm_trans *trans)
|
|||
trans_free(trans);
|
||||
return -EINVAL;
|
||||
}
|
||||
trans->cc.local.rtp = *rtp_cn_local;
|
||||
trans->cc.local->rtp = *rtp_cn_local;
|
||||
|
||||
trans_cc_filter_run(trans);
|
||||
|
||||
|
@ -2165,7 +2179,7 @@ int gsm48_tch_rtp_create(struct gsm_trans *trans)
|
|||
struct osmo_sockaddr_str *rtp_cn_local;
|
||||
struct rtp_stream *rtp_cn = cl ? cl->rtp[RTP_TO_CN] : NULL;
|
||||
int mncc_payload_msg_type;
|
||||
struct sdp_audio_codec *codec;
|
||||
struct osmo_sdp_codec *codec;
|
||||
const struct codec_mapping *m;
|
||||
struct sdp_audio_codecs *codecs;
|
||||
|
||||
|
|
|
@ -797,7 +797,7 @@ DEFUN_ATTR(cfg_codecs_clear, cfg_codecs_clear_cmd,
|
|||
CMD_ATTR_IMMEDIATE)
|
||||
{
|
||||
struct ran_infra *dst = vty->index;
|
||||
dst->codecs = (struct sdp_audio_codecs){};
|
||||
osmo_sdp_codec_list_free_items(dst->codecs);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -816,18 +816,22 @@ DEFUN_ATTR(cfg_codecs_entry, cfg_codecs_entry_cmd,
|
|||
struct ran_infra *dst = vty->index;
|
||||
const char *add_del = argv[0];
|
||||
const char *codec_str = argv[1];
|
||||
struct sdp_audio_codec c;
|
||||
struct sdp_audio_codec *exists;
|
||||
struct osmo_sdp_codec *c;
|
||||
struct osmo_sdp_codec *i;
|
||||
struct osmo_sdp_codec *exists;
|
||||
const struct codec_mapping *m;
|
||||
bool ok;
|
||||
|
||||
if (sdp_audio_codec_from_str(&c, codec_str))
|
||||
c = osmo_sdp_codec_alloc(OTC_SELECT);
|
||||
if (osmo_sdp_codec_from_str(c, codec_str, -1)) {
|
||||
vty_out(vty, "%% Error: cannot parse codec string '%s'%s", codec_str, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
/* make sure this is a known codec */
|
||||
ok = false;
|
||||
codec_mapping_foreach (m) {
|
||||
if (sdp_audio_codec_cmp(&m->sdp, &c, true, false))
|
||||
if (osmo_sdp_codec_cmp(&m->sdp, c, &osmo_sdp_codec_cmp_equivalent))
|
||||
continue;
|
||||
ok = true;
|
||||
break;
|
||||
|
@ -838,39 +842,42 @@ DEFUN_ATTR(cfg_codecs_entry, cfg_codecs_entry_cmd,
|
|||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
exists = sdp_audio_codecs_by_descr(&dst->codecs, &c);
|
||||
exists = NULL;
|
||||
osmo_sdp_codec_list_foreach (i, dst->codecs) {
|
||||
if (osmo_sdp_codec_cmp(i, c, &osmo_sdp_codec_cmp_equivalent))
|
||||
continue;
|
||||
exists = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcmp("add", add_del)) {
|
||||
if (exists) {
|
||||
vty_out(vty, "%% Codec already present in the list: %s%s", sdp_audio_codec_to_str(exists),
|
||||
vty_out(vty, "%% Codec already present in the list: %s%s", sdp_codec_to_str(exists),
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (!sdp_audio_codecs_add_copy(&dst->codecs, &c, false, false)) {
|
||||
vty_out(vty, "%% Error: failed to add codec '%s' -- too many entries?%s", codec_str, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
osmo_sdp_codec_list_add(dst->codecs, c, NULL, false);
|
||||
} else {
|
||||
/* "del" */
|
||||
if (!exists) {
|
||||
vty_out(vty, "%% Codec not present in the list: %s%s", codec_str, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
sdp_audio_codecs_remove(&dst->codecs, exists);
|
||||
|
||||
osmo_sdp_codec_list_remove_entry(exists);
|
||||
talloc_free(exists);
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void config_write_codecs_for_rat(struct vty *vty, enum osmo_rat_type rat)
|
||||
{
|
||||
const struct sdp_audio_codec *c;
|
||||
char buf[128];
|
||||
const struct osmo_sdp_codec *c;
|
||||
vty_out(vty, "codecs %s%s", rat == OSMO_RAT_GERAN_A ? "a" : "iu", VTY_NEWLINE);
|
||||
vty_out(vty, " clear%s", VTY_NEWLINE);
|
||||
sdp_audio_codecs_foreach (c, &msc_ran_infra[rat].codecs) {
|
||||
sdp_audio_codec_to_str_buf(buf, sizeof(buf), c);
|
||||
vty_out(vty, " %s%s", buf, VTY_NEWLINE);
|
||||
osmo_sdp_codec_list_foreach (c, msc_ran_infra[rat].codecs) {
|
||||
vty_out(vty, " %s%s", sdp_codec_to_str(c), VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -899,7 +906,7 @@ DEFUN(show_codecs, show_codecs_cmd,
|
|||
const struct codec_mapping *m;
|
||||
vty_out(vty, "Supported codecs are:%s", VTY_NEWLINE);
|
||||
codec_mapping_foreach (m)
|
||||
vty_out(vty, " %s%s", sdp_audio_codec_to_str(&m->sdp), VTY_NEWLINE);
|
||||
vty_out(vty, " %s%s", sdp_codec_to_str(&m->sdp), VTY_NEWLINE);
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -29,8 +29,11 @@ static const struct osmo_sdp_codec codec_csd = {
|
|||
.rate = 8000,
|
||||
};
|
||||
|
||||
void sdp_codecs_set_csd(void *ctx, struct osmo_sdp_codec_list *codecs)
|
||||
void sdp_codecs_set_csd(void *ctx, struct osmo_sdp_codec_list **codecs)
|
||||
{
|
||||
osmo_sdp_codec_list_free(codecs);
|
||||
osmo_sdp_codec_list_add(ctx, &codec_csd);
|
||||
if (*codecs)
|
||||
osmo_sdp_codec_list_free_items(*codecs);
|
||||
else
|
||||
*codecs = osmo_sdp_codec_list_alloc(ctx);
|
||||
osmo_sdp_codec_list_add(*codecs, &codec_csd);
|
||||
}
|
||||
|
|
|
@ -225,6 +225,11 @@ struct gsm_trans *trans_alloc(struct gsm_network *net,
|
|||
};
|
||||
if (vsub)
|
||||
vlr_subscr_get(vsub, trans_vsub_use(type));
|
||||
if (type == TRANS_CC) {
|
||||
trans->cc.codec_filter = talloc_zero(trans, struct codec_filter);
|
||||
trans->cc.remote = osmo_sdp_codec_alloc(trans);
|
||||
trans->cc.local = osmo_sdp_codec_alloc(trans);
|
||||
}
|
||||
llist_add_tail(&trans->entry, &net->trans_list);
|
||||
|
||||
LOG_TRANS(trans, LOGL_DEBUG, "New transaction\n");
|
||||
|
|
Loading…
Reference in New Issue