MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / handle_stream

Function handle_stream

nodedb-cluster/src/transport/server.rs:246–354  ·  view source on GitHub ↗
(
    handler: Arc<H>,
    auth: Arc<AuthContext>,
    identity_store: Arc<S>,
    peer_cert_der: Option<Vec<u8>>,
    conn: quinn::Connection,
    mut send: quinn::SendStream,
    mut recv: quinn::Re

Source from the content-addressed store, hash-verified

244/// module docstring for the rationale.
245#[allow(clippy::too_many_arguments)]
246async fn handle_stream<H: RaftRpcHandler, S: PeerIdentityStore>(
247 handler: Arc<H>,
248 auth: Arc<AuthContext>,
249 identity_store: Arc<S>,
250 peer_cert_der: Option<Vec<u8>>,
251 conn: quinn::Connection,
252 mut send: quinn::SendStream,
253 mut recv: quinn::RecvStream,
254 mut shutdown: watch::Receiver<bool>,
255) -> Result<()> {
256 let work = async {
257 // 1. Read one envelope.
258 let envelope = read_envelope(&mut recv).await?;
259 let (fields, inner_frame) = auth_envelope::parse_envelope(&envelope, &auth.mac_key)?;
260
261 // 2. Replay window — under the advertised from_node_id (MAC-verified).
262 // Self-addressed frames skip the window: when a node dispatches
263 // an RPC to itself over the transport, the shared `AuthContext`
264 // means one window is updated by both the server-side request
265 // accept (here) and the client-side response accept (in
266 // `send.rs::parse_inbound`). Skipping when `from == local`
267 // keeps the two flows from tripping on each other's entries —
268 // a self-addressed frame can't have been replayed by an
269 // external attacker by definition.
270 if fields.from_node_id != auth.local_node_id {
271 auth.peer_seq_in.accept(fields.from_node_id, fields.seq)?;
272 }
273
274 // 3b. Peer identity check — binds the MAC-verified node_id to the
275 // TLS certificate. Self-addressed frames skip the check by the
276 // same reasoning as the replay window above.
277 if fields.from_node_id != auth.local_node_id
278 && let Some(cert_der) = &peer_cert_der
279 {
280 let node_info = identity_store.get_node_info(fields.from_node_id);
281 match node_info {
282 Some(ref info) => match verify_peer_identity(info, cert_der) {
283 VerifyOutcome::Accepted { method } => {
284 debug!(
285 node_id = fields.from_node_id,
286 ?method,
287 "peer identity verified"
288 );
289 }
290 VerifyOutcome::BootstrapAccepted => {
291 warn!(
292 node_id = fields.from_node_id,
293 "peer identity not pinned — bootstrap window accepted"
294 );
295 }
296 VerifyOutcome::Rejected => {
297 warn!(
298 node_id = fields.from_node_id,
299 "peer identity mismatch — closing connection"
300 );
301 conn.close(IDENTITY_MISMATCH_QUIC_ERROR, b"peer identity mismatch");
302 return Err(ClusterError::Transport {
303 detail: format!(

Callers 1

handle_connectionFunction · 0.85

Calls 13

read_envelopeFunction · 0.85
verify_peer_identityFunction · 0.85
write_envelopeFunction · 0.85
acceptMethod · 0.80
closeMethod · 0.80
parse_envelopeFunction · 0.50
decodeFunction · 0.50
encodeFunction · 0.50
get_node_infoMethod · 0.45
handle_rpcMethod · 0.45
nextMethod · 0.45
lenMethod · 0.45

Tested by

no test coverage detected