Failure handling in OpenSIPS
A failure route runs when a transaction receives a negative final reply, that is anything from 3xx upwards. It is the place to decide whether the call is really over or whether it should be tried somewhere else, because inside it the transaction can still be relayed to a new destination.
Failure routes need the tm module, since only a stateful transaction remembers enough to retry.
The route is armed on the request before it is relayed:
route {
if (!lookup("location")) {
send_reply("404", "Not Found");
exit;
}
# arm a failure route to be executed if the transaction fails with a non-2xx reply
t_on_failure("vm_redirect");
t_relay();
}
The block itself inspects the reply that caused the failure and either creates a new branch or answers the caller:
failure_route[vm_redirect] {
# redirect to the voicemail system when the callee cancelled or timed out
if (t_check_status("(487)|(408)")) {
$rd = "10.10.1.100";
t_relay();
} else {
# replace every other non-2xx reply from end users with a single code
t_reply("408", "Unavailable");
}
}
t_check_status() matches a regular expression against the status code of the winning reply, so
(487)|(408) catches a cancelled call and a request timeout while letting genuine rejections such
as 486 Busy Here fall through to the else.
Two details are easy to get wrong:
- The name passed to
t_on_failure()must match thefailure_route[...]label exactly, otherwise the block never runs and the original reply is simply forwarded. - Changing
$rdalone rewrites the destination host. The request URI user part, and anything else the new destination cares about, stays as it was.
A failure route is not triggered by a locally generated reply, only by one received from the network, and it is skipped entirely if the transaction was already answered with a 2xx.
See branch handling for the counterpart that runs on each outgoing branch, and reply handling for inspecting replies that are not failures.