From 058c2761338e43afc5aac4abeeab8b70580c3d5f Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Sun, 25 Feb 2024 06:24:01 +0100 Subject: wip Change-Id: I00a410e0c01a527d7bbd978da91649f4fdf6775c --- include/osmocom/msc/codec_mapping.h | 3 ++ include/osmocom/msc/sdp_msg.h | 2 +- include/osmocom/msc/transaction.h | 7 +-- src/libmsc/codec_mapping.c | 54 +++++++++++++++-------- src/libmsc/csd_filter.c | 8 ++-- src/libmsc/gsm_04_08_cc.c | 88 +++++++++++++++++++++---------------- src/libmsc/msc_vty.c | 43 ++++++++++-------- src/libmsc/sdp_msg.c | 9 ++-- src/libmsc/transaction.c | 5 +++ 9 files changed, 135 insertions(+), 84 deletions(-) diff --git a/include/osmocom/msc/codec_mapping.h b/include/osmocom/msc/codec_mapping.h index 7781dfce2..7f5e33982 100644 --- a/include/osmocom/msc/codec_mapping.h +++ b/include/osmocom/msc/codec_mapping.h @@ -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); diff --git a/include/osmocom/msc/sdp_msg.h b/include/osmocom/msc/sdp_msg.h index 4a42ab9d8..475191164 100644 --- a/include/osmocom/msc/sdp_msg.h +++ b/include/osmocom/msc/sdp_msg.h @@ -3,4 +3,4 @@ #include #include -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); diff --git a/include/osmocom/msc/transaction.h b/include/osmocom/msc/transaction.h index 33e435a5d..24845d997 100644 --- a/include/osmocom/msc/transaction.h +++ b/include/osmocom/msc/transaction.h @@ -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; diff --git a/src/libmsc/codec_mapping.c b/src/libmsc/codec_mapping.c index d47d74a4e..82e479768 100644 --- a/src/libmsc/codec_mapping.c +++ b/src/libmsc/codec_mapping.c @@ -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; +} diff --git a/src/libmsc/csd_filter.c b/src/libmsc/csd_filter.c index d1dcda927..a6ce9fdc2 100644 --- a/src/libmsc/csd_filter.c +++ b/src/libmsc/csd_filter.c @@ -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) { diff --git a/src/libmsc/gsm_04_08_cc.c b/src/libmsc/gsm_04_08_cc.c index 49a583f3d..96ab99817 100644 --- a/src/libmsc/gsm_04_08_cc.c +++ b/src/libmsc/gsm_04_08_cc.c @@ -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; diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c index bc03d897a..75561d5b4 100644 --- a/src/libmsc/msc_vty.c +++ b/src/libmsc/msc_vty.c @@ -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; } diff --git a/src/libmsc/sdp_msg.c b/src/libmsc/sdp_msg.c index c9b5c16c0..0d88fe89a 100644 --- a/src/libmsc/sdp_msg.c +++ b/src/libmsc/sdp_msg.c @@ -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); } diff --git a/src/libmsc/transaction.c b/src/libmsc/transaction.c index 7ae4c7d92..4fe816bbf 100644 --- a/src/libmsc/transaction.c +++ b/src/libmsc/transaction.c @@ -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"); -- cgit v1.2.3