From aeadf261e54d4e3987797b5818a8356441512568 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 14 Aug 2015 15:43:06 +0200 Subject: mgcp: Allow to enforce that the codecs need to match We have a lot of legacy that I am afraid to break. We have everything in place to make a good codec selection (e.g. if we can avoid transcoding, pick the one with best quality or the lowest speed). Right now I have a specific case where from all options I want to pick GSM. Guard the codec compat check behind the disallow transcoding option to make sure to not break legacy application. --- openbsc/include/openbsc/mgcp_internal.h | 2 +- openbsc/src/libmgcp/mgcp_protocol.c | 4 +-- openbsc/src/libmgcp/mgcp_sdp.c | 25 +++++++++++++- openbsc/tests/mgcp/mgcp_test.c | 59 +++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 4 deletions(-) diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index 763d83b0d..485a12409 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -317,6 +317,6 @@ enum { #define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1 #define PTYPE_UNDEFINED (-1) -int mgcp_parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p); +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); diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c index 5f3eb3a6b..40ea7916a 100644 --- a/openbsc/src/libmgcp/mgcp_protocol.c +++ b/openbsc/src/libmgcp/mgcp_protocol.c @@ -828,7 +828,7 @@ mgcp_header_done: endp->bts_end.fmtp_extra = talloc_strdup(tcfg->endpoints, tcfg->audio_fmtp_extra); if (have_sdp) - mgcp_parse_sdp_data(&endp->net_end, p); + mgcp_parse_sdp_data(endp, &endp->net_end, p); else if (endp->local_options.codec) mgcp_set_audio_info(p->cfg, &endp->net_end.codec, PTYPE_UNDEFINED, endp->local_options.codec); @@ -931,7 +931,7 @@ static struct msgb *handle_modify_con(struct mgcp_parse_data *p) case '\0': /* SDP file begins */ have_sdp = 1; - mgcp_parse_sdp_data(&endp->net_end, p); + mgcp_parse_sdp_data(endp, &endp->net_end, p); /* This will exhaust p->save, so the loop will * terminate next time. */ diff --git a/openbsc/src/libmgcp/mgcp_sdp.c b/openbsc/src/libmgcp/mgcp_sdp.c index dc8708934..33837b9af 100644 --- a/openbsc/src/libmgcp/mgcp_sdp.c +++ b/openbsc/src/libmgcp/mgcp_sdp.c @@ -154,8 +154,23 @@ void codecs_update(void *ctx, struct sdp_rtp_map *codecs, int used, int payload, LOGP(DMGCP, LOGL_ERROR, "Unconfigured PT(%d) with %s\n", payload, audio_name); } +int is_codec_compatible(struct mgcp_endpoint *endp, struct sdp_rtp_map *codec) +{ + char *bts_codec; + char audio_codec[64]; + + /* + * GSM, GSM/8000 and GSM/8000/1 should all be compatible.. let's go + * by name first. + */ + bts_codec = endp->tcfg->audio_name; + if (sscanf(bts_codec, "%63[^/]/%*d/%*d", audio_codec) < 1) + return 0; + + return strcasecmp(audio_codec, codec->codec_name) == 0; +} -int mgcp_parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p) +int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p) { struct sdp_rtp_map codecs[10]; int codecs_used = 0; @@ -243,6 +258,14 @@ int mgcp_parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p) for (i = 0; i < codecs_used && codecs_assigned < 2; ++i) { struct mgcp_rtp_codec *codec = codecs_assigned == 0 ? &rtp->codec : &rtp->alt_codec; + + if (endp->tcfg->no_audio_transcoding && + !is_codec_compatible(endp, &codecs[i])) { + LOGP(DMGCP, LOGL_NOTICE, "Skipping codec %s\n", + codecs[i].codec_name); + continue; + } + mgcp_set_audio_info(p->cfg, codec, codecs[i].payload_type, codecs[i].map_line); diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c index 0f0e06ccf..d5018591b 100644 --- a/openbsc/tests/mgcp/mgcp_test.c +++ b/openbsc/tests/mgcp/mgcp_test.c @@ -340,6 +340,31 @@ static void test_strline(void) "a=rtpmap:101 FOO/8000\r\n" \ "a=ptime:40\r\n" +#define CRCX_MULT_GSM_EXACT \ + "CRCX 259260421 5@mgw MGCP 1.0\r\n" \ + "C: 1355c6041e\r\n" \ + "I: 3\r\n" \ + "L: p:20, a:GSM, nt:IN\r\n" \ + "M: recvonly\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "o=- 1439038275 1439038275 IN IP4 192.168.181.247\r\n" \ + "s=-\r\nc=IN IP4 192.168.181.247\r\n" \ + "t=0 0\r\nm=audio 29084 RTP/AVP 0 8 3 18 4 96 97 101\r\n" \ + "a=rtpmap:0 PCMU/8000\r\n" \ + "a=rtpmap:8 PCMA/8000\r\n" \ + "a=rtpmap:3 gsm/8000\r\n" \ + "a=rtpmap:18 G729/8000\r\n" \ + "a=fmtp:18 annexb=no\r\n" \ + "a=rtpmap:4 G723/8000\r\n" \ + "a=rtpmap:96 iLBC/8000\r\n" \ + "a=fmtp:96 mode=20\r\n" \ + "a=rtpmap:97 iLBC/8000\r\n" \ + "a=fmtp:97 mode=30\r\n" \ + "a=rtpmap:101 telephone-event/8000\r\n" \ + "a=fmtp:101 0-15\r\n" \ + "a=recvonly\r\n" + struct mgcp_test { const char *name; const char *req; @@ -1011,6 +1036,40 @@ static void test_multilple_codec(void) OSMO_ASSERT(endp->net_end.codec.payload_type == 18); OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1); + /* Allocate 5@mgw at select GSM.. */ + last_endpoint = -1; + inp = create_msg(CRCX_MULT_GSM_EXACT); + talloc_free(cfg->trunk.audio_name); + cfg->trunk.audio_name = "GSM/8000"; + cfg->trunk.no_audio_transcoding = 1; + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 5); + endp = &cfg->trunk.endpoints[last_endpoint]; + OSMO_ASSERT(endp->net_end.codec.payload_type == 3); + OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1); + + /* Check what happens without that flag */ + + /* Free the previous endpoint and the data ... */ + mgcp_release_endp(endp); + talloc_free(endp->last_response); + talloc_free(endp->last_trans); + endp->last_response = endp->last_trans = NULL; + + last_endpoint = -1; + inp = create_msg(CRCX_MULT_GSM_EXACT); + cfg->trunk.no_audio_transcoding = 0; + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 5); + endp = &cfg->trunk.endpoints[last_endpoint]; + OSMO_ASSERT(endp->net_end.codec.payload_type == 0); + OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 8); talloc_free(cfg); } -- cgit v1.2.3