Skip to main content

forward_request_streams

Function forward_request_streams 

Source
async fn forward_request_streams(
    source: &Transport,
    dest: &Transport,
    side: ProxySide,
    ctx: &ForwardCtx,
) -> Result<(), ProxyError>
Expand description

Forward bidirectional request streams, on the drafts where that is what a bidirectional stream is — see control_plane_is_unidirectional.

One accept loop per direction, because on these drafts either endpoint opens request streams: a subscriber opens one to SUBSCRIBE and a publisher opens one to PUBLISH, so a proxy that only accepted the client’s would drop every request the relay ever made. Each accepted stream is paired with one opened on the far side and forwarded by two pipes, one per direction.

§Why the control pipe and not the data pipe

Because a request stream carries the same framing the control stream does. Draft-17 Section 9 (draft-18 and draft-19 Section 10): “Every message on a control or request stream is formatted as follows”, and the figure beneath it gives Message Type, Message Length and Message Payload. So the messages on a request stream are decodable, and a hook that asked for Interest::CONTROL is shown them at Site::Control exactly as it is shown the control stream’s. Handing them to the object framer instead would produce a bypass and a stream of nothing.

§What an injection cannot reach

This registers each direction under a fresh per-stream channel, which is the one the registry hands a reset_stream to. The two channels an injection is routed to belong to the session’s control legs and go to the two unidirectional control streams, so a request stream’s pipe can never be handed an Inject — which is the whole point of separating them.

§One conservatism, stated

Both pipes run with the control stream’s end-of-stream rules, under which a hook’s ResetStream is refused as a session-level protocol violation. On a request stream that is stricter than the draft: draft-17 Section 3.3.1 says a request MAY be cancelled by either endpoint and that implementations SHOULD do it by resetting the stream. Refusing is the conservative direction — nothing is destroyed that the draft would have kept — and it is what this crate’s published capability table says happens, so it is left alone here rather than changed silently.