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

Function perform_server_handshake

nodedb/src/control/server/native/handshake.rs:36–102  ·  view source on GitHub ↗

Negotiate the native protocol version with a newly-connected client. Reads a `HelloFrame`, validates it, picks a `proto_ver` in the overlap of `[client_proto_min, client_proto_max]` and `[PROTO_VERSION_MIN, PROTO_VERSION_MAX]`, then sends a `HelloAckFrame` with `limits` embedded. On any error, a `HelloErrorFrame` is written, the write side is shut down, and `Err` is returned so the caller can cl

(stream: &mut S, limits: &Limits)

Source from the content-addressed store, hash-verified

34/// On any error, a `HelloErrorFrame` is written, the write side is shut down,
35/// and `Err` is returned so the caller can close the connection.
36pub async fn perform_server_handshake<S>(stream: &mut S, limits: &Limits) -> crate::Result<u16>
37where
38 S: AsyncRead + AsyncWrite + Unpin,
39{
40 // ── 1. Read HelloFrame with timeout ─────────────────────────────────
41 let mut buf = [0u8; HelloFrame::WIRE_SIZE];
42 let read_result = tokio::time::timeout(HELLO_READ_TIMEOUT, stream.read_exact(&mut buf)).await;
43
44 let hello = match read_result {
45 Err(_timeout) => {
46 send_error(stream, HelloErrorCode::Malformed, "hello read timeout").await;
47 return Err(crate::Error::BadRequest {
48 detail: "hello frame read timed out".into(),
49 });
50 }
51 Ok(Err(io)) => {
52 // Don't bother sending an error frame on a connection-reset/EOF —
53 // the peer is already gone.
54 return Err(crate::Error::Io(io));
55 }
56 Ok(Ok(_)) => match HelloFrame::decode(&buf) {
57 Some(f) => f,
58 None => {
59 let msg = "bad hello frame: BadMagic";
60 send_error(stream, HelloErrorCode::BadMagic, msg).await;
61 return Err(crate::Error::BadRequest { detail: msg.into() });
62 }
63 },
64 };
65
66 debug!(
67 proto_min = hello.proto_min,
68 proto_max = hello.proto_max,
69 capabilities = hello.capabilities,
70 "hello received"
71 );
72
73 // ── 2. Negotiate version ─────────────────────────────────────────────
74 let proto_ver = match negotiate_version(hello.proto_min, hello.proto_max) {
75 Some(v) => v,
76 None => {
77 let msg = format!(
78 "client speaks [{}, {}], server speaks [{}, {}]",
79 hello.proto_min, hello.proto_max, PROTO_VERSION_MIN, PROTO_VERSION_MAX
80 );
81 send_error(stream, HelloErrorCode::VersionMismatch, &msg).await;
82 return Err(crate::Error::VersionCompat { detail: msg });
83 }
84 };
85
86 // ── 3. Send HelloAck ─────────────────────────────────────────────────
87 let ack = HelloAckFrame {
88 proto_version: proto_ver,
89 capabilities: hello.capabilities, // echo back what client offered (server supports all for v1)
90 server_version: format!("NodeDB/{}", crate::version::VERSION),
91 limits: limits.clone(),
92 };
93 let ack_bytes = ack.encode();

Callers 2

runMethod · 0.85
server_shake_with_limitsFunction · 0.85

Calls 7

send_errorFunction · 0.85
negotiate_versionFunction · 0.85
decodeFunction · 0.50
read_exactMethod · 0.45
cloneMethod · 0.45
encodeMethod · 0.45
flushMethod · 0.45

Tested by

no test coverage detected