clear pending requests on MGCP failure

If an MGCP operation on one conn of an endpoint fails, no longer carry out
other pending requests for that endpoint. Only allow pending DLCX to be sent.

If the caller schedules two CRCX at the same time, the first CRCX is sent with
a wildcarded endpoint name like "rtpbridge/*@mgw". Only when the OK for that
returns an allocated endpoint, will the second CRCX be sent, using that actual
allocated endpoint name. But, if the first CRCX fails, then we should not send
another wildcard CRCX, but rather assume both as failed.

Since a failed MGCP message means that the endpoint becomes unusable /
undefined and typically deallocates directly, we can actually discard all other
pending requests except for DLCX.

Change-Id: Icb1d485224bb486b84eff6329f0bd95932e63246
This commit is contained in:
Neels Hofmeyr 2019-10-01 19:44:10 +02:00
parent 8c69e29820
commit cc0b97e197
1 changed files with 20 additions and 0 deletions

View File

@ -357,6 +357,8 @@ static void on_failure(struct osmo_mgcpc_ep_ci *ci)
struct osmo_fsm_inst *notify = ci->notify;
uint32_t notify_failure = ci->notify_failure;
void *notify_data = ci->notify_data;
struct osmo_mgcpc_ep *ep = ci->ep;
int i;
if (!ci->occupied)
return;
@ -365,6 +367,24 @@ static void on_failure(struct osmo_mgcpc_ep_ci *ci)
.ep = ci->ep,
};
/* An MGCP failure typically means the endpoint becomes unusable, cancel all pending request (except DLCX).
* Particularly, if two CRCX were scheduled and the first fails, we must no longer dispatch the second CRCX. */
for (i = 0; i < ARRAY_SIZE(ep->ci); i++) {
struct osmo_mgcpc_ep_ci *other_ci = &ep->ci[i];
if (other_ci == ci)
continue;
if (!other_ci->occupied)
continue;
if (!other_ci->pending)
continue;
if (other_ci->sent)
continue;
if (other_ci->verb == MGCP_VERB_DLCX)
continue;
/* Just clear the pending request, don't fire more events than below. */
other_ci->pending = false;
}
/* If this check has terminated the FSM instance, don't fire any more events to prevent use-after-free problems.
* The endpoint FSM does dispatch a term event to its parent, and everything should be cleaned like that. */
if (!osmo_mgcpc_ep_fsm_check_state_chg_after_response(ci->ep->fi))