engine: keep the reg-event subscription alive and act on a terminated binding
The reg-event subscription is the network's own account of our binding (TS 24.229 5.1.1.3), and the daemon opened a new dialog for it at every refresh and reconnect and otherwise never looked back: a refused SUBSCRIBE was forgotten, an unanswered one had no timeout, an ended subscription got nothing until the next refresh's new dialog, and a NOTIFY was logged whatever it said. O2 UK, 2026-09-24: a fresh registration's SUBSCRIBE got 500, a NOTIFY arrived all the same and showed our contact active, the flow died eight seconds after the 200 and no connect over the SA succeeded after that; the 500 was logged and nothing was done about it. Keep the subscription alive: retry a refused or unanswered SUBSCRIBE on a backoff, renew one the S-CSCF ends with deactivated, timeout, giveup or probation (RFC 6665 4.1.3; after any other reason, or none, the next refresh subscribes anew), and subscribe anew ahead of the lifetime the S-CSCF granted. A refresh or a reconnect opens no dialog while imsd holds one for the registration or has a retry scheduled. Read the reginfo for our own contact and act on its state: a NOTIFY that terminates our binding schedules a fresh registration — at once for deactivated or expired, after the network's retry-after (up to an hour) for probation, on imsd's own refusal schedule (21 min, growing to 60) for rejected or unregistered (RFC 3680). A hold already running stands, and a REGISTER wait a call kept open that still gets its 200 after such a NOTIFY leaves that registration standing. The parser is in Imsd:Sip and pinned by tests/Sip with the O2 document shapes; the policy is RegRecovery's (OnBindingTerminated, added here with its tests in tests/Engine). Tested on the dev phone (KPN) in builds of this series; not every path has run there.
This commit is contained in:
parent
142adf057c
commit
db848c6490
6 changed files with 412 additions and 38 deletions
30
README.md
30
README.md
|
|
@ -282,7 +282,7 @@ PCSCF=2001:db8::105
|
|||
| `RTP_PORT` | `50004` | local RTP port advertised in SDP |
|
||||
| `PRECOND` | `0` | `1` offers SDP QoS preconditions |
|
||||
| `CODECS` | *(empty — defaults)* | comma-separated codec preference list over `AMR-WB`, `AMR` (or `AMR-NB`), `PCMA`, `PCMU`: restricts and orders both the codecs offered on an outgoing call and those accepted from an inbound offer (default: offer AMR-WB + AMR, accept all four in that order). A bench knob — a network whose gateway transcodes every caller up to AMR-WB otherwise never lets the narrowband path run |
|
||||
| `DUMP_SIP` | `0` | `1` writes raw REGISTER-200/SUBSCRIBE-200 dumps, the last refused REGISTER or SUBSCRIBE final (`imsd-register-fail.raw`, `imsd-subscribe-fail.raw`), the last inbound INVITE (`imsd-invite-in.raw`) and the last outgoing INVITE (`imsd-invite-out.raw`), mode 0600, for debugging — they contain your IMSI/MSISDN and addresses. A refused REGISTER, and a refused SUBSCRIBE final the run loop reads, are logged with the status line and any Retry-After / Warning / Reason / Server headers |
|
||||
| `DUMP_SIP` | `0` | `1` writes raw REGISTER-200/SUBSCRIBE-200 dumps, the last refused REGISTER or SUBSCRIBE final (`imsd-register-fail.raw`, `imsd-subscribe-fail.raw`), the last inbound INVITE (`imsd-invite-in.raw`) and the last outgoing INVITE (`imsd-invite-out.raw`), mode 0600, for debugging — they contain your IMSI/MSISDN and addresses. A refused REGISTER or SUBSCRIBE is logged with its status line and any Retry-After / Warning / Reason / Server headers |
|
||||
| `DUMP_DIR`, `OUT_DIR` | state dir | where dumps / per-call media stats land |
|
||||
| `IMSD_MEDIA` | *(auto)* | path to `imsd-media` (default: next to `imsd`, else `/usr/libexec/imsd-media`) |
|
||||
|
||||
|
|
@ -301,7 +301,8 @@ schedule (21 min, growing to 60), a silent one 30 s → 10 min, and a
|
|||
network `Retry-After` is honoured, up to an hour (the schedule's longest wait): a longer
|
||||
one is cut to it and the refusal heard again then. While a fresh registration is deferred, the existing SA is
|
||||
still retried on the reconnect backoff, unless the old registration is known gone: a `403` once a
|
||||
fresh registration is due, or an attempt that got past the SA setup. A `Dial`
|
||||
fresh registration is due, an attempt that got past the SA setup, or a binding
|
||||
the network terminated (reg-event). A `Dial`
|
||||
that reaches imsd while it is unregistered brings the next recovery step
|
||||
forward (the reconnect, or the fresh attempt once it is due), never a wait
|
||||
the network imposed (a `Retry-After`, or the schedule after a
|
||||
|
|
@ -313,11 +314,30 @@ restart of imsd: they are kept in
|
|||
`/run/imsd.holds` for the address they were set on, with the schedule's place
|
||||
(a restart does not start it over at 21 min), and waited out at the next
|
||||
start, before the resume (a refresh's `Retry-After`) or before the fresh
|
||||
registration (a fresh attempt's schedule or `Retry-After`); a reboot or
|
||||
another address starts clean.
|
||||
registration (a fresh attempt's schedule or `Retry-After`, a terminated
|
||||
binding's wait); a reboot or another address starts clean.
|
||||
The journal says which (`…; next: fresh registration in N s`, `registering
|
||||
fresh (recovery attempt N)`, `fresh registration deferred/refused/failed:
|
||||
…`, `bring-up deferred: …`).
|
||||
…`, `bring-up deferred: …`). The reg-event subscription — the network's own
|
||||
view of the binding, one live dialog per registration, subscribed anew ahead of
|
||||
the lifetime the S-CSCF granted — is retried when refused or unanswered
|
||||
(60 s doubling to 10 min, a `Retry-After` honoured up to an hour: a registration refresh
|
||||
neither brings a scheduled retry forward nor starts its back-off over) and renewed when the S-CSCF ends
|
||||
it for a reason that allows renewal (RFC 6665; after `noresource`,
|
||||
`rejected` or any other reason the renewal does not cover the next
|
||||
registration refresh subscribes anew); an earlier
|
||||
subscription's NOTIFY is still read for the binding's state, but its end is
|
||||
not ours to renew (KPN closes a registration's previous subscription with
|
||||
`noresource` when a new one replaces it); a NOTIFY that terminates the binding triggers a fresh
|
||||
registration (at once, or after the network's `retry-after`, up to an hour; after the
|
||||
call, when one is up; one exception: a REGISTER wait that still gets its 200
|
||||
after such a NOTIFY, a call having kept the flow, leaves that registration
|
||||
standing); after
|
||||
`rejected` and `unregistered` it waits on the refusal schedule (21 min,
|
||||
growing to 60), a wait no `Dial` cuts short — the binding is gone, so
|
||||
nothing is retried meanwhile. One termination counts once, however many
|
||||
NOTIFYs report it (a repeated `probation` report may extend its hold from
|
||||
its own `retry-after`).
|
||||
|
||||
### imsd-media (per-call, set through imsd's environment)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue