Summary

  • SIP Outbound let a proxy deliver new requests over flows that a user agent had already opened. It did not require the server to invent a fresh inbound connection through a NAT or firewall.
  • Several registrations could represent different paths to the same user-agent instance. The service therefore had to distinguish an account, an instance and each replaceable flow rather than count every binding as another recipient.
  • A 430 response identified a failed flow and could justify trying the instance's other path. A different final response generally meant that the instance had answered and the same request had to stop.

The failure reached the caller first

Section 9.3 of RFC 5626 presents a deliberately awkward sequence. A phone has registered through two edge proxies. One edge crashes and restarts. Before the phone's own keepalive procedure detects the loss, a new INVITE arrives for it.

The restarted edge no longer has the flow named by the stored token. It returns 430 Flow Failed. The proxy responsible for the address of record removes the stale binding and selects another registration for the same account and user-agent instance, distinguished by another reg-id. The second edge receives the request and can route the new dialog. The phone repairs the first registration later.

This is a specification example, not a report of a carrier outage and not a measured recovery time. It does not promise that every existing dialog will migrate without interruption. The document leaves particular mid-dialog edge procedures outside its mandatory algorithm. Its narrower point is still consequential: the calling side can discover that one delivery path is dead before the phone finishes discovering the same failure locally.

That creates a legitimate reason to try another path. It does not create a second recipient. The alternate binding belongs to the same phone, and the rules must preserve that fact even while the two sides possess different knowledge of the failure.

Registration had never made the Contact reachable

The original SIP registration model associated an address of record, or AOR, with one or more Contacts. Under RFC 3261, a registrar accepted those bindings and a location service made them available to a proxy routing later requests. Registrar and proxy could be separate functions or parts of one system.

A response to REGISTER could return on the reliable connection that carried the request, provided the connection remained open. A later INVITE was not another response to that REGISTER. It was a new request in the reverse direction. A phone behind a NAT or firewall could open an outbound TCP or TLS connection without being able to accept a new connection initiated by the server. A formally stored Contact did not punch a durable hole through that boundary.

Outbound used a flow established by the user agent. For TCP, the flow was a connection. For UDP, it was a bidirectional datagram association identified by addresses, ports and transport protocol. Reducing the design to persistent TCP would miss both the UDP case and the deeper rule: delivery depended on a known association to the registered endpoint, not on the hope that an untested reverse connection could be opened later.

The distinction also mattered when a large message required a transport change. The document's operational discussion noted that a server could not simply replace UDP with a fresh inbound TCP connection that the phone had never established. The suitable Outbound flows had to exist first. This was not a claim that every large UDP request failed or that every deployment had to keep every transport open; it exposed the cost of treating a Contact as if it were a complete route.

Path remembered where the flow entered

The registrar was not necessarily the phone's first SIP hop. An edge proxy might forward REGISTER into the home domain, and a future request would need to return through that edge. RFC 3327 had introduced Path for this purpose. Intermediaries added themselves during registration; the resulting vector was stored with the binding and used as a preloaded Route for later requests through the home domain.

Path was not Record-Route applied to REGISTER. REGISTER still created no dialog. Nor was Path a universal route that any correspondent could impose. It operated within the routing and trust policies of the home domain, which made integrity protection and the relationship to an authenticated registration essential.

Outbound added the missing precision at the first edge. The edge inserted a protected flow token and the ob indication so that it could recover the particular association to the phone. The token was not a permanent name for the device or person. It was usable by the edge to find one flow.

That local scope mattered after restarts and resource reuse. A new connection assigned an old file-descriptor number did not become the old recipient's connection. Once the network established that a flow would no longer deliver—through a TCP close, for example, or an applicable UDP error—the bindings attached to it had to be invalidated. Recycled coordinates could not silently inherit old authority.

One identifier persisted; another marked the path

Multiple flows required two kinds of identity. An instance-id named the user-agent instance and persisted across a restart or network change. A reg-id distinguished that instance's simultaneous flow registrations. The meaningful binding key brought AOR, instance-id and reg-id together.

On restart, the phone deliberately reused its sequence of reg-id values. In many systems, avoiding a numeric collision sounds safer. Here the right collision was the cleanup mechanism: a new registration for the same logical path position replaced stale state rather than accumulating beside it as a fictional additional destination.

The Contact was still stored and still helped construct the target set. It did not become irrelevant. But Contact text alone no longer carried the identity of the binding. The proxy was forbidden to place more than one Contact for the same AOR and instance-id in its target set at once. Separate devices sharing an AOR remained possible, as did ordinary SIP forking where appropriate. The limit was narrower: alternative flows to one instance could not be counted as independent recipients in the same attempt.

Two rows in a registrar therefore did not prove two phones. They did not prove two people, two customers or two independent failure domains either. They recorded state whose cardinality had meaning only after the account, instance and flow relationships were read together.

A 430 response belonged to the path

When an edge could not find the requested flow, it was to answer with 430 Flow Failed. If another binding existed for the same AOR and instance-id with a different reg-id, the responsible proxy was to try it. This is the precise repair illustrated by the crash-and-restart sequence.

The code was not a verdict on the account, the person or the call's media. It was information between the edge and the authoritative proxy about a path. Endpoints were not intended to receive 430 and were to treat it as 400 if they did. A modified flow token called for a separate response, with 403 recommended. Collapsing these conditions into a generic “network error” would discard the reason controlled failover was safe in one case and inappropriate in another.

The same care prevents an exaggerated availability claim. The example saves a new request from one known stale path. It does not establish seamless survival for every dialog, guaranteed end-to-end delivery or a particular uptime percentage. A protocol can define the handoff of evidence without proving how faithfully every product uses it.

The other path could not overrule an answer

Outbound's least theatrical rule may be its most important. After a final response other than 408 or 430, a proxy must not forward the same request to another target representing the same AOR and instance-id. The instance has answered. A second registered path does not make that answer provisional.

The exceptions and scope belong in the explanation. This was not a ban on all future calls, all retries in all protocols or forking to genuinely distinct devices. It constrained the same request as it moved among alternate routes to the same instance. A failed flow could justify another delivery attempt; a final response usually could not.

Without that stop rule, redundancy would confuse recovery with persistence. A refusal, completion or other final decision might be treated as another reason to reach the same phone again. The service would have more paths but less respect for state. Resilience required knowledge of both kinds: what had failed, and what had already replied.

Keepalive and registration ran on separate clocks

A registration's lifetime and a flow's health were not interchangeable. A recoverable refresh error such as 503 did not necessarily require closing a reliable connection that continued to answer pings. Keeping the transport did not make the binding immortal; it preserved a resource while the registration procedure handled a different failure.

The inverse was possible on UDP. A STUN response could arrive while reporting a changed XOR-MAPPED-ADDRESS. In that case, receiving a reply showed that the old association had failed, because the mapped address or port was no longer the one registered. Explicit next-hop support was required for this use of STUN; a generic promise to “handle NAT” was not enough.

Keepalive operated to the next SIP hop. It did not confirm that the user received an INVITE, that an application acted on it or that audio media flowed. Flow-Timer expressed an expected keepalive interval with grace, not a lease guaranteeing delivery throughout the period. Short intervals improved detection at the cost of battery and server load; multiple flows reduced the exposure while adding their own state.

RFC 6223 later defined adjacent-hop, per-direction negotiation using the Via keep parameter. It explicitly did not define connection reuse. Keeping a neighboring path responsive and authorizing future reverse requests over it remained different operations.

Adjacent extensions kept their own boundaries

RFC 5923 dealt with TLS connection aliases between SIP neighbors able to initiate connections in both directions. Authentication and the accepting server's decision to reuse a channel remained central. An open TLS socket did not automatically authorize arbitrary reverse traffic; where connection direction was constrained, the document's applicability discussion pointed back to Outbound.

RFC 5627 solved another problem: how to give a third party a URI that selected a particular user-agent instance. In its blind-transfer example, calling the AOR could reach another device or voicemail when the intended target was the handset already involved. A GRUU supplied an externally usable, domain-mediated instance target. It was not the edge's flow token and did not prove that any one flow was still alive.

The browser scenario in RFC 7118 made the separations visible. A JavaScript SIP stack might not know a meaningful local transport address. When it had requested and received Outbound support, the scenario allowed a random name under .invalid in Via and Contact, while incoming signaling returned through the WebSocket proxy and existing flow. That was a conditional part of this scenario, not general permission to publish unusable Contacts. Server-certificate checks still applied, and media transport remained outside the document.

The IANA SIP parameters registry records the names, response codes and references involved. It does not measure adoption or certify implementations. The historical result is more exact than a universal claim of availability: the protocol acquired a way to preserve several return paths without multiplying the recipient or treating the recipient's answer as an obstacle to route around.