Skip to main content

negotiate_downstream

Function negotiate_downstream 

Source
pub fn negotiate_downstream(
    params: &JsonObject,
    upstream: &Leg,
    config: &DownstreamConfig,
) -> Result<Downstream, DownstreamError>
Expand description

Settles the downstream leg of a handshake.

Re-exported beside the rest so the two halves of a bridge’s negotiation are reachable together: this needs an upstream Agreement, which is what the client half of the connection produced. Settles the downstream leg against an already-negotiated upstream.

Reads the client’s offer with the same code a server uses, so a bridge and a server cannot disagree about what a client is allowed to say, then reconciles the two legs through Agreement::between.

The two things returned are not two views of one value. The Agreement is what the bridge may forward; the body is the wire form of it. A caller that forwarded against the downstream Leg alone would be forwarding features it had just told the client it does not have.

Takes the upstream as a Leg rather than an Agreement because that is all it is: the upstream negotiated with the server when the bridge connected, and the client that will supply the other leg has not arrived yet. Accepting an Agreement would have asked the caller to invent a downstream leg they do not have, and every invented leg is one more place the served profile can disagree with the advertised one.

§Errors

DownstreamError::Malformed for an initialize that is not an offer, and DownstreamError::NoHandshake if there is no revision with a handshake to answer with.

§Examples

use protocol_droid::application::bridge::{negotiate_downstream, DownstreamConfig};
use protocol_droid::domain::ir::JsonObject;
use protocol_droid::domain::{FeatureProfile, Leg, ProtocolVersion, TransportKind};

let config = DownstreamConfig::new("bridge", "0.1.0", TransportKind::Stdio)?;
let params = JsonObject::new(
    r#"{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe"}}"#,
)?;

let downstream = negotiate_downstream(&params, &upstream, &config)?;

// The advertisement is the agreement, never the client's own leg.
assert_eq!(downstream.served(), downstream.agreement().served());