aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/osmo-bsc_nat
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/osmo-bsc_nat')
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c96
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));