rework message handling

This was previously broken and a free endpoint was requirted to dlcx *,
additionaly globally handling this is difficult due to different
response
codes, so just do it in the functions, they know best.

Change-Id: I8cbbe5936067ea1caa7935e8d14908ac5c4010bd
This commit is contained in:
Eric
2021-09-14 18:36:53 +02:00
committed by laforge
parent fbcf4a6f6c
commit ee6958c9a8

View File

@@ -97,10 +97,6 @@ struct mgcp_request {
/* function pointer to the request handler */ /* function pointer to the request handler */
struct msgb *(*handle_request)(struct mgcp_request_data *data); struct msgb *(*handle_request)(struct mgcp_request_data *data);
/* true if the request requires an endpoint, false if only a trunk
* is sufficient. (corner cases, e.g. wildcarded DLCX) */
bool require_endp;
/* a human readable name that describes the request */ /* a human readable name that describes the request */
char *debug_name; char *debug_name;
}; };
@@ -112,32 +108,34 @@ static struct msgb *handle_modify_con(struct mgcp_request_data *data);
static struct msgb *handle_rsip(struct mgcp_request_data *data); static struct msgb *handle_rsip(struct mgcp_request_data *data);
static struct msgb *handle_noti_req(struct mgcp_request_data *data); static struct msgb *handle_noti_req(struct mgcp_request_data *data);
static const struct mgcp_request mgcp_requests[] = { static const struct mgcp_request mgcp_requests[] = {
{ .name = "AUEP", { .name = "AUEP", .handle_request = handle_audit_endpoint, .debug_name = "AuditEndpoint" },
.handle_request = handle_audit_endpoint, {
.debug_name = "AuditEndpoint", .name = "CRCX",
.require_endp = true }, .handle_request = handle_create_con,
{ .name = "CRCX", .debug_name = "CreateConnection",
.handle_request = handle_create_con, },
.debug_name = "CreateConnection", {
.require_endp = true }, .name = "DLCX",
{ .name = "DLCX", .handle_request = handle_delete_con,
.handle_request = handle_delete_con, .debug_name = "DeleteConnection",
.debug_name = "DeleteConnection", },
.require_endp = false }, {
{ .name = "MDCX", .name = "MDCX",
.handle_request = handle_modify_con, .handle_request = handle_modify_con,
.debug_name = "ModifiyConnection", .debug_name = "ModifiyConnection",
.require_endp = true }, },
{ .name = "RQNT", {
.handle_request = handle_noti_req, .name = "RQNT",
.debug_name = "NotificationRequest", .handle_request = handle_noti_req,
.require_endp = true }, .debug_name = "NotificationRequest",
},
/* SPEC extension */ /* SPEC extension */
{ .name = "RSIP", {
.handle_request = handle_rsip, .name = "RSIP",
.debug_name = "ReSetInProgress", .handle_request = handle_rsip,
.require_endp = true }, .debug_name = "ReSetInProgress",
},
}; };
/* Initalize transcoder */ /* Initalize transcoder */
@@ -420,15 +418,6 @@ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
/* Find an appropriate handler for the current request and execute it */ /* Find an appropriate handler for the current request and execute it */
for (i = 0; i < ARRAY_SIZE(mgcp_requests); i++) { for (i = 0; i < ARRAY_SIZE(mgcp_requests); i++) {
if (strcmp(mgcp_requests[i].name, rq.name) == 0) { if (strcmp(mgcp_requests[i].name, rq.name) == 0) {
/* Check if the request requires and endpoint, if yes, check if we have it, otherwise don't
* execute the request handler. */
if (mgcp_requests[i].require_endp && !rq.endp) {
LOGP(DLMGCP, LOGL_ERROR,
"%s: the request handler \"%s\" requires an endpoint resource for \"%s\", which is not available -- abort\n",
rq.name, mgcp_requests[i].debug_name, pdata.epname);
return create_err_response(rq.trunk, NULL, -rq.mgcp_cause, rq.name, pdata.trans);
}
/* Execute request handler */ /* Execute request handler */
if (rq.endp) if (rq.endp)
LOGP(DLMGCP, LOGL_INFO, LOGP(DLMGCP, LOGL_INFO,
@@ -459,6 +448,11 @@ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
static struct msgb *handle_audit_endpoint(struct mgcp_request_data *rq) static struct msgb *handle_audit_endpoint(struct mgcp_request_data *rq)
{ {
LOGPENDP(rq->endp, DLMGCP, LOGL_NOTICE, "AUEP: auditing endpoint ...\n"); LOGPENDP(rq->endp, DLMGCP, LOGL_NOTICE, "AUEP: auditing endpoint ...\n");
if (!rq->endp || !mgcp_endp_avail(rq->endp)) {
LOGPENDP(rq->endp, DLMGCP, LOGL_ERROR, "AUEP: selected endpoint not available!\n");
return create_err_response(rq->trunk, NULL, 501, "AUEP", rq->pdata->trans);
}
return create_ok_response(rq->trunk, rq->endp, 200, "AUEP", rq->pdata->trans); return create_ok_response(rq->trunk, rq->endp, 200, "AUEP", rq->pdata->trans);
} }
@@ -853,6 +847,13 @@ static struct msgb *handle_create_con(struct mgcp_request_data *rq)
LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "CRCX: creating new connection ...\n"); LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "CRCX: creating new connection ...\n");
/* we must have a free ep */
if (!endp) {
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_AVAIL));
LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: no free endpoints available!\n");
return create_err_response(rq->trunk, NULL, 403, "CRCX", pdata->trans);
}
if (!mgcp_endp_avail(endp)) { if (!mgcp_endp_avail(endp)) {
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_AVAIL)); rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_AVAIL));
LOGPENDP(endp, DLMGCP, LOGL_ERROR, LOGPENDP(endp, DLMGCP, LOGL_ERROR,
@@ -1110,13 +1111,6 @@ static struct msgb *handle_modify_con(struct mgcp_request_data *rq)
LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "MDCX: modifying existing connection ...\n"); LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "MDCX: modifying existing connection ...\n");
if (!mgcp_endp_avail(endp)) {
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_AVAIL));
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
"MDCX: selected endpoint not available!\n");
return create_err_response(endp, NULL, 501, "MDCX", pdata->trans);
}
/* Prohibit wildcarded requests */ /* Prohibit wildcarded requests */
if (rq->wildcarded) { if (rq->wildcarded) {
LOGPENDP(endp, DLMGCP, LOGL_ERROR, LOGPENDP(endp, DLMGCP, LOGL_ERROR,
@@ -1125,6 +1119,11 @@ static struct msgb *handle_modify_con(struct mgcp_request_data *rq)
return create_err_response(rq->trunk, endp, 507, "MDCX", pdata->trans); return create_err_response(rq->trunk, endp, 507, "MDCX", pdata->trans);
} }
if (!endp || !mgcp_endp_avail(endp)) {
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_AVAIL));
LOGPENDP(endp, DLMGCP, LOGL_ERROR, "MDCX: selected endpoint not available!\n");
return create_err_response(rq->trunk, NULL, 501, "MDCX", pdata->trans);
}
if (llist_count(&endp->conns) <= 0) { if (llist_count(&endp->conns) <= 0) {
LOGPENDP(endp, DLMGCP, LOGL_ERROR, LOGPENDP(endp, DLMGCP, LOGL_ERROR,
"MDCX: endpoint is not holding a connection.\n"); "MDCX: endpoint is not holding a connection.\n");
@@ -1343,6 +1342,19 @@ static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
return create_err_response(endp, endp, 515, "DLCX", pdata->trans); return create_err_response(endp, endp, 515, "DLCX", pdata->trans);
} }
/* Handle wildcarded DLCX that refers to the whole trunk. This means
* that we walk over all endpoints on the trunk in order to drop all
* connections on the trunk. (see also RFC3435 Annex F.7) */
if (rq->wildcarded) {
int num_conns = 0;
for (i = 0; i < trunk->number_endpoints; i++) {
num_conns += llist_count(&trunk->endpoints[i]->conns);
mgcp_endp_release(trunk->endpoints[i]);
}
rate_ctr_add(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_SUCCESS), num_conns);
return create_ok_response(trunk, NULL, 200, "DLCX", pdata->trans);
}
for_each_line(line, pdata->save) { for_each_line(line, pdata->save) {
if (!mgcp_check_param(endp, trunk, line)) if (!mgcp_check_param(endp, trunk, line))
continue; continue;
@@ -1392,19 +1404,6 @@ static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
} }
} }
/* Handle wildcarded DLCX that refers to the whole trunk. This means
* that we walk over all endpoints on the trunk in order to drop all
* connections on the trunk. (see also RFC3435 Annex F.7) */
if (rq->wildcarded) {
int num_conns = 0;
for (i = 0; i < trunk->number_endpoints; i++) {
num_conns += llist_count(&trunk->endpoints[i]->conns);
mgcp_endp_release(trunk->endpoints[i]);
}
rate_ctr_add(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_SUCCESS), num_conns);
return create_ok_response(trunk, NULL, 200, "DLCX", pdata->trans);
}
/* The logic does not permit to go past this point without having the /* The logic does not permit to go past this point without having the
* the endp pointer populated. */ * the endp pointer populated. */
OSMO_ASSERT(endp); OSMO_ASSERT(endp);