diff options
Diffstat (limited to 'openbsc/src/osmo-bsc_nat')
-rw-r--r-- | openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c | 96 |
1 files changed, 75 insertions, 21 deletions
diff --git a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c index 15c4767b8..606ac92df 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c +++ b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c @@ -50,6 +50,8 @@ #include <openbsc/ipaccess.h> #include <openbsc/mgcp.h> #include <openbsc/mgcp_internal.h> +#include <openbsc/osmux.h> + #include <osmocom/ctrl/control_cmd.h> #include <osmocom/sccp/sccp.h> @@ -262,13 +264,12 @@ static void bsc_mgcp_send_mdcx(struct bsc_connection *bsc, int port, struct mgcp int len; len = snprintf(buf, sizeof(buf), - "MDCX 23 %x@mgw MGCP 1.0%s\r\n" + "MDCX 23 %x@mgw MGCP 1.0\r\n" "Z: noanswer\r\n" "\r\n" "c=IN IP4 %s\r\n" "m=audio %d RTP/AVP 255\r\n", - port, bsc->cfg->osmux ? "\nX-Osmux: on" : "", - bsc->nat->mgcp_cfg->source_addr, + port, bsc->nat->mgcp_cfg->source_addr, endp->bts_end.local_port); if (len < 0) { LOGP(DMGCP, LOGL_ERROR, "snprintf for MDCX failed.\n"); @@ -505,6 +506,7 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int struct nat_sccp_connection *sccp; struct mgcp_endpoint *mgcp_endp; struct msgb *bsc_msg; + int osmux_cid = -1; nat = tcfg->cfg->data; bsc_endp = &nat->bsc_endpoints[endpoint]; @@ -541,11 +543,15 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int } } + /* Allocate a Osmux circuit ID */ + if (state == MGCP_ENDP_CRCX && + nat->mgcp_cfg->osmux && sccp->bsc->cfg->osmux) + osmux_cid = osmux_get_cid(); + /* we need to generate a new and patched message */ bsc_msg = bsc_mgcp_rewrite((char *) nat->mgcp_msg, nat->mgcp_length, sccp->bsc_endp, nat->mgcp_cfg->source_addr, - mgcp_endp->bts_end.local_port, - nat->mgcp_cfg->osmux ? sccp->bsc->cfg->osmux : 0, + mgcp_endp->bts_end.local_port, osmux_cid, &mgcp_endp->net_end.payload_type); if (!bsc_msg) { LOGP(DMGCP, LOGL_ERROR, "Failed to patch the msg.\n"); @@ -560,14 +566,14 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int /* we need to update some bits */ if (state == MGCP_ENDP_CRCX) { struct sockaddr_in sock; - struct mgcp_endpoint *endp = &nat->mgcp_cfg->trunk.endpoints[endpoint]; - if (nat->mgcp_cfg->osmux ? sccp->bsc->cfg->osmux : 0) { - if (osmux_enable_endpoint(endp, OSMUX_ROLE_BSC_NAT) < 0) { - LOGP(DMGCP, LOGL_ERROR, - "Could not activate osmux in endpoint %d\n", - ENDPOINT_NUMBER(endp)); - } + /* Annotate the allocated Osmux CID until the bsc confirms that + * it agrees to use Osmux for this voice flow. + */ + if (osmux_cid >= 0 && + mgcp_endp->osmux.state != OSMUX_STATE_ENABLED) { + mgcp_endp->osmux.state = OSMUX_STATE_ACTIVATING; + mgcp_endp->osmux.cid = osmux_cid; } socklen_t len = sizeof(sock); @@ -586,6 +592,11 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int /* we will free the endpoint now and send a DLCX to the BSC */ msgb_free(bsc_msg); bsc_mgcp_dlcx(sccp); + + /* libmgcp clears the MGCP endpoint for us */ + if (mgcp_endp->osmux.state == OSMUX_STATE_ENABLED) + osmux_put_cid(mgcp_endp->osmux.cid); + return MGCP_POLICY_CONT; } else { bsc_write(sccp->bsc, bsc_msg, IPAC_PROTO_MGCP_OLD); @@ -624,6 +635,42 @@ static void free_chan_downstream(struct mgcp_endpoint *endp, struct bsc_endpoint mgcp_release_endp(endp); } +static void bsc_mgcp_osmux_confirm(struct mgcp_endpoint *endp, const char *str) +{ + unsigned int osmux_cid; + char *res; + + res = strstr(str, "X-Osmux: "); + if (!res) { + LOGP(DMGCP, LOGL_INFO, + "BSC doesn't want to use Osmux, failing back to RTP\n"); + goto err; + } + + if (sscanf(res, "X-Osmux: %u", &osmux_cid) != 1) { + LOGP(DMGCP, LOGL_ERROR, "Failed to parse Osmux CID '%s'\n", + str); + goto err; + } + + if (endp->osmux.cid != osmux_cid) { + LOGP(DMGCP, LOGL_INFO, + "BSC sent us wrong CID %u, we expected %u", + osmux_cid, endp->osmux.cid); + goto err; + } + + LOGP(DMGCP, LOGL_NOTICE, "bsc accepted to use Osmux (cid=%u)\n", + osmux_cid); + return; +err: + LOGP(DMGCP, LOGL_NOTICE, "bsc didn't accept to use Osmux (cid=%u)\n", + osmux_cid); + osmux_put_cid(endp->osmux.cid); + endp->osmux.cid = -1; + endp->osmux.state = OSMUX_STATE_DISABLED; +} + /* * We have received a msg from the BSC. We will see if we know * this transaction and if it belongs to the BSC. Then we will @@ -685,6 +732,9 @@ void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg) return; } + if (endp->osmux.state == OSMUX_STATE_ACTIVATING) + bsc_mgcp_osmux_confirm(endp, (const char *) msg->l2h); + /* free some stuff */ talloc_free(bsc_endp->transaction_id); bsc_endp->transaction_id = NULL; @@ -697,8 +747,7 @@ void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg) */ output = bsc_mgcp_rewrite((char * ) msg->l2h, msgb_l2len(msg), -1, bsc->nat->mgcp_cfg->source_addr, - endp->net_end.local_port, - bsc->nat->mgcp_cfg->osmux ? bsc_endp->bsc->cfg->osmux : 0, + endp->net_end.local_port, -1, &endp->bts_end.payload_type); if (!output) { LOGP(DMGCP, LOGL_ERROR, "Failed to rewrite MGCP msg.\n"); @@ -738,11 +787,12 @@ uint32_t bsc_mgcp_extract_ci(const char *str) * Create a new MGCPCommand based on the input and endpoint from a message */ static void patch_mgcp(struct msgb *output, const char *op, const char *tok, - int endp, int len, int cr, int osmux) + int endp, int len, int cr, int osmux_cid) { int slen; int ret; char buf[40]; + char osmux_extension[strlen("X-Osmux: 255")]; buf[0] = buf[39] = '\0'; ret = sscanf(tok, "%*s %s", buf); @@ -752,15 +802,19 @@ static void patch_mgcp(struct msgb *output, const char *op, const char *tok, return; } + if (osmux_cid >= 0) + sprintf(osmux_extension, "\nX-Osmux: %u", osmux_cid); + else + osmux_extension[0] = '\0'; + slen = sprintf((char *) output->l3h, "%s %s %x@mgw MGCP 1.0%s%s", - op, buf, endp, osmux ? "\nX-Osmux: on" : "", - cr ? "\r\n" : "\n"); + op, buf, endp, osmux_extension, cr ? "\r\n" : "\n"); output->l3h = msgb_put(output, slen); } /* we need to replace some strings... */ struct msgb *bsc_mgcp_rewrite(char *input, int length, int endpoint, - const char *ip, int port, int osmux, + const char *ip, int port, int osmux_cid, int *payload_type) { static const char crcx_str[] = "CRCX "; @@ -799,11 +853,11 @@ struct msgb *bsc_mgcp_rewrite(char *input, int length, int endpoint, cr = len > 0 && token[len - 1] == '\r'; if (strncmp(crcx_str, token, (sizeof crcx_str) - 1) == 0) { - patch_mgcp(output, "CRCX", token, endpoint, len, cr, osmux); + patch_mgcp(output, "CRCX", token, endpoint, len, cr, osmux_cid); } else if (strncmp(dlcx_str, token, (sizeof dlcx_str) - 1) == 0) { - patch_mgcp(output, "DLCX", token, endpoint, len, cr, 0); + patch_mgcp(output, "DLCX", token, endpoint, len, cr, -1); } else if (strncmp(mdcx_str, token, (sizeof mdcx_str) - 1) == 0) { - patch_mgcp(output, "MDCX", token, endpoint, len, cr, osmux); + patch_mgcp(output, "MDCX", token, endpoint, len, cr, -1); } else if (strncmp(ip_str, token, (sizeof ip_str) - 1) == 0) { output->l3h = msgb_put(output, strlen(ip_str)); memcpy(output->l3h, ip_str, strlen(ip_str)); |