pespin has uploaded this change for review.

View Change

mgw: MDCX: Split mgcp header pars parsing into a previous step

Do most of the initial parsing and verification in a prior step, filling
in a "parsed" struct which simplifies logic coming after for different
message types.
This commit only modifies stuff enough to work for MDCX.
Further work (commits) will follow for DLCX.

Change-Id: I6ecb41fc2cc737c3a161b6bc98bd08ae01909655
---
M include/osmocom/mgcp/mgcp_protocol.h
M src/libosmo-mgcp/mgcp_msg.c
M src/libosmo-mgcp/mgcp_protocol.c
3 files changed, 45 insertions(+), 90 deletions(-)

git pull ssh://gerrit.osmocom.org:29418/osmo-mgw refs/changes/39/39239/1
diff --git a/include/osmocom/mgcp/mgcp_protocol.h b/include/osmocom/mgcp/mgcp_protocol.h
index 633f3e9..ffe7ae0 100644
--- a/include/osmocom/mgcp/mgcp_protocol.h
+++ b/include/osmocom/mgcp/mgcp_protocol.h
@@ -9,6 +9,7 @@
struct mgcp_parse_hdr_pars {
const char *local_options;
const char *callid;
+ const char *connid;
enum mgcp_connection_mode mode;
int remote_osmux_cid;
bool have_sdp;
@@ -21,6 +22,7 @@
*hpars = (struct mgcp_parse_hdr_pars){
.local_options = NULL,
.callid = NULL,
+ .connid = NULL,
.mode = MGCP_CONN_NONE,
.remote_osmux_cid = MGCP_PARSE_HDR_PARS_OSMUX_CID_UNSET,
.have_sdp = false,
diff --git a/src/libosmo-mgcp/mgcp_msg.c b/src/libosmo-mgcp/mgcp_msg.c
index 493c473..577914f 100644
--- a/src/libosmo-mgcp/mgcp_msg.c
+++ b/src/libosmo-mgcp/mgcp_msg.c
@@ -189,10 +189,8 @@
hp->callid = (const char *)line + 3;
break;
case 'I':
- /* It is illegal to send a connection identifier
- * together with a CRCX, the MGW will assign the
- * connection identifier by itself on CRCX */
- return 523;
+ hp->connid = (const char *)line + 3;
+ break;
case 'M':
hp->mode = mgcp_parse_conn_mode((const char *)line + 3);
break;
diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c
index d592cc9..3751bc1 100644
--- a/src/libosmo-mgcp/mgcp_protocol.c
+++ b/src/libosmo-mgcp/mgcp_protocol.c
@@ -716,19 +716,6 @@
return 0;
}

-/*! Initializes osmux socket if not yet initialized. Parses Osmux CID from MGCP line.
- * \param[in] endp Endpoint willing to initialize osmux
- * \param[in] line Line X-Osmux from MGCP header msg to parse
- * \returns OSMUX CID, -1 for wildcard, -2 on parse error, -3 on osmux initalize error
- */
-static int mgcp_osmux_setup(struct mgcp_endpoint *endp, const char *line)
-{
- if (mgcp_trunk_osmux_init_if_needed(endp->trunk) < 0)
- return -3;
-
- return mgcp_parse_osmux_cid(line);
-}
-
/* Process codec information contained in CRCX/MDCX */
static int handle_codec_info(struct mgcp_conn_rtp *conn,
struct mgcp_request_data *rq, int have_sdp, bool crcx)
@@ -843,9 +830,6 @@
switch (rc) {
case 0:
break; /* all good, continue below */
- case 523:
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_BAD_ACTION));
- return create_err_response(rq->trunk, NULL, rc, "CRCX", pdata->trans);
case 539:
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_UNHANDLED_PARAM));
return create_err_response(rq->trunk, NULL, 539, "CRCX", pdata->trans);
@@ -868,6 +852,15 @@
return create_err_response(endp, endp, 517, "CRCX", pdata->trans);
}

+ /* It is illegal to send a connection identifier
+ * together with a CRCX, the MGW will assign the
+ * connection identifier by itself on CRCX */
+ if (hpars->connid) {
+ LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: 'I: %s' not expected!\n", hpars->connid);
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_BAD_ACTION));
+ return create_err_response(endp, endp, 523, "CRCX", pdata->trans);
+ }
+
/* If osmux is disabled, just skip setting it up */
if (trunk->cfg->osmux.usage == OSMUX_USAGE_OFF)
hpars->remote_osmux_cid = MGCP_PARSE_HDR_PARS_OSMUX_CID_UNSET;
@@ -1046,17 +1039,12 @@
struct mgcp_parse_data *pdata = rq->pdata;
struct mgcp_trunk *trunk = rq->trunk;
struct mgcp_endpoint *endp = rq->endp;
+ struct mgcp_parse_hdr_pars *hpars = &pdata->hpars;
struct rate_ctr_group *rate_ctrs;
char new_local_addr[INET6_ADDRSTRLEN];
int error_code = 500;
- int have_sdp = 0;
- char *line;
- const char *local_options = NULL;
- enum mgcp_connection_mode mode = MGCP_CONN_NONE;
struct mgcp_conn *conn = NULL;
struct mgcp_conn_rtp *conn_rtp = NULL;
- const char *conn_id = NULL;
- int remote_osmux_cid = -2;
int rc;

LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "MDCX: modifying existing connection ...\n");
@@ -1089,64 +1077,33 @@
return create_err_response(endp, endp, 400, "MDCX", pdata->trans);
}

- for_each_line(line, pdata->save) {
- if (!mgcp_check_param(line))
- continue;
-
- switch (toupper(line[0])) {
- case 'C':
- if (mgcp_verify_call_id(endp, line + 3) != 0) {
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_INVALID_CALLID));
- error_code = 516;
- goto error3;
- }
- break;
- case 'I':
- conn_id = (const char *)line + 3;
- if ((error_code = mgcp_verify_ci(endp, conn_id))) {
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_INVALID_CONNID));
- goto error3;
- }
- break;
- case 'L':
- local_options = (const char *)line + 3;
- break;
- case 'M':
- mode = mgcp_parse_conn_mode((const char *)line + 3);
- break;
- case 'X':
- if (strncasecmp("Osmux: ", line + 2, strlen("Osmux: ")) == 0) {
- /* If osmux is disabled, just skip setting it up */
- if (endp->trunk->cfg->osmux.usage == OSMUX_USAGE_OFF)
- break;
- remote_osmux_cid = mgcp_osmux_setup(endp, line);
- break;
- }
- /* Ignore unknown X-headers */
- break;
- case '\0':
- have_sdp = 1;
- goto mgcp_header_done;
- break;
- default:
- LOGPENDP(endp, DLMGCP, LOGL_NOTICE,
- "MDCX: Unhandled MGCP option: '%c'/%d\n",
- line[0], line[0]);
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_UNHANDLED_PARAM));
- return create_err_response(rq->trunk, NULL, 539, "MDCX", pdata->trans);
- break;
- }
+ rc = mgcp_parse_hdr_pars(pdata);
+ switch (rc) {
+ case 0:
+ break; /* all good, continue below */
+ case 539:
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_UNHANDLED_PARAM));
+ return create_err_response(rq->trunk, NULL, 539, "MDCX", pdata->trans);
+ default:
+ return create_err_response(rq->trunk, NULL, rc, "MDCX", pdata->trans);
}

-mgcp_header_done:
- if (!conn_id) {
+ if (hpars->callid && mgcp_verify_call_id(endp, hpars->callid) < 0) {
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_INVALID_CALLID));
+ return create_err_response(endp, endp, 516, "MDCX", pdata->trans);
+ }
+
+ if (!hpars->connid) {
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
"MDCX: insufficient parameters, missing ci (connectionIdentifier)\n");
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_NO_CONNID));
return create_err_response(endp, endp, 515, "MDCX", pdata->trans);
+ } else if ((error_code = mgcp_verify_ci(endp, hpars->connid)) != 0) {
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_INVALID_CONNID));
+ return create_err_response(endp, endp, error_code, "MDCX", pdata->trans);
}

- conn = mgcp_endp_get_conn(endp, conn_id);
+ conn = mgcp_endp_get_conn(endp, hpars->connid);
if (!conn) {
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_CONN_NOT_FOUND));
return create_err_response(endp, endp, 400, "MDCX", pdata->trans);
@@ -1154,20 +1111,18 @@

mgcp_conn_watchdog_kick(conn);

- if (mode != MGCP_CONN_NONE) {
- if (mgcp_conn_set_mode(conn, mode) < 0) {
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_INVALID_MODE));
- error_code = 517;
- goto error3;
- }
- } else {
+ if (hpars->mode == MGCP_CONN_NONE) {
+ /* Reset conn mode in case it was tweaked through VTY: */
conn->mode = conn->mode_orig;
+ } else if (mgcp_conn_set_mode(conn, hpars->mode) < 0) {
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_INVALID_MODE));
+ return create_err_response(endp, endp, 517, "MDCX", pdata->trans);
}

/* Set local connection options, if present */
- if (local_options) {
+ if (hpars->local_options) {
rc = set_local_cx_options(trunk->endpoints,
- &endp->local_options, local_options);
+ &endp->local_options, hpars->local_options);
if (rc != 0) {
LOGPCONN(conn, DLMGCP, LOGL_ERROR,
"MDCX: invalid local connection options!\n");
@@ -1181,7 +1136,7 @@
OSMO_ASSERT(conn_rtp);

/* Handle codec information and decide for a suitable codec */
- rc = handle_codec_info(conn_rtp, rq, have_sdp, false);
+ rc = handle_codec_info(conn_rtp, rq, hpars->have_sdp, false);
mgcp_codecset_summary(&conn_rtp->end.cset, mgcp_conn_dump(conn));
if (rc) {
error_code = rc;
@@ -1195,22 +1150,22 @@

if (mgcp_conn_rtp_is_osmux(conn_rtp)) {
OSMO_ASSERT(conn_rtp->osmux.local_cid_allocated);
- if (remote_osmux_cid < -1) {
+ if (hpars->remote_osmux_cid < -1) {
LOGPCONN(conn, DLMGCP, LOGL_ERROR,
"MDCX: Failed to parse Osmux CID!\n");
goto error3;
- } else if (remote_osmux_cid == -1) {
+ } else if (hpars->remote_osmux_cid == -1) {
LOGPCONN(conn, DLMGCP, LOGL_ERROR,
"MDCX: wilcard in MDCX is not supported!\n");
goto error3;
} else if (conn_rtp->osmux.remote_cid_present &&
- remote_osmux_cid != conn_rtp->osmux.remote_cid) {
+ hpars->remote_osmux_cid != conn_rtp->osmux.remote_cid) {
LOGPCONN(conn, DLMGCP, LOGL_ERROR,
"MDCX: changing already allocated CID is not supported!\n");
goto error3;
} else {
conn_rtp->osmux.remote_cid_present = true;
- conn_rtp->osmux.remote_cid = remote_osmux_cid;
+ conn_rtp->osmux.remote_cid = hpars->remote_osmux_cid;
if (conn_osmux_event_rx_crcx_mdcx(conn_rtp) < 0) {
LOGPCONN(conn, DLMGCP, LOGL_ERROR,
"MDCX: Osmux handling failed!\n");

To view, visit change 39239. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: newchange
Gerrit-Project: osmo-mgw
Gerrit-Branch: master
Gerrit-Change-Id: I6ecb41fc2cc737c3a161b6bc98bd08ae01909655
Gerrit-Change-Number: 39239
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin@sysmocom.de>