# `ExWapp.Message.Handler.Call`
[🔗](https://github.com/elchemista/ex_wapp/blob/v0.1.5/lib/ex_wapp/message/handler/call.ex#L1)

Turns inbound `<call>` stanzas into call-log records and live call events.

WhatsApp delivers call signalling as a `<call>` stanza with one child naming
the phase: `offer`/`offer_notice` (ringing), `accept` (a device answered),
`terminate` (ended, with a `reason` attribute), or `reject`. Each phase is
merged into the persistent call log (`ExWapp.Call`) and forwarded to the
session worker as `{:call_event, %ExWapp.Call{}}` so subscribers can react
in real time. VoIP negotiation children (`preaccept`, `transport`,
`relaylatency`, ...) carry no log-worthy information and are skipped.

Outcome semantics for `terminate`:
- a call with a known accept (or a positive `duration` attribute) ends `:connected`
- an unanswered outgoing call ends `:cancelled`
- any other unanswered call ends `:missed` — WhatsApp uses `reason="timeout"`
  for a ring-out, but a caller hang-up is still a missed call for the callee

The raw terminate reason is preserved in `end_reason`. Duration comes from
the stanza's `duration` attribute when present, otherwise from the delta
between the observed accept and terminate timestamps.

# `handle_call_node`

```elixir
@spec handle_call_node(ExWapp.Binary.Node.t(), pid() | term(), map()) :: {:ok, map()}
```

Handles one inbound `<call>` stanza.

Always returns `{:ok, state}`: call stanzas never produce outbound actions
here (the transport ACK is already handled at the connection boundary).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
