From d3675473eddd12a30b59e5ab856d09b5c90676ca Mon Sep 17 00:00:00 2001 From: _ <> Date: Sat, 17 Jul 2021 22:27:05 +0000 Subject: [PATCH] :pencil: document the fixed-length control protocol that I need to replace soon --- prototypes/quic_demo/README.md | 70 +++++++++++++++++++ .../quic_demo/src/bin/quic_demo_client.rs | 18 ++++- .../src/bin/quic_demo_relay_server.rs | 2 +- 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/prototypes/quic_demo/README.md b/prototypes/quic_demo/README.md index 1302ca4..a20c4a6 100644 --- a/prototypes/quic_demo/README.md +++ b/prototypes/quic_demo/README.md @@ -22,6 +22,76 @@ The end-to-end testing above is the happy path. Try these sadder cases: - After Step 2, restart the relay server P3 - After Step 3, restart the relay server P3 +# Network protocol + +For the prototype, all control messages are fixed 4-byte messages at the +start of bidirectional streams. + +Unused bytes are always "0". + +## QUIC client connection + +When P2 or P4 connects to P3 over QUIC, it opens a bi stream and identifies +itself with a 4-byte request. The bytes are: + +1. Client type +2. Client ID +3. Unused +4. Unused + +The type is "2" or "4" to identify the client as a P2 or a P4. The IDs are +hard-coded as "42" and "43" for now. + +P3 responds with these 4 bytes: + +1. Status code +2. Unused +3. Unused +4. Unused + +The status code is always "20" to mean "OK". If authorization or authentication +had failed, it would be something else, and P3 would close the connection. + +## PTTH connection + +When P1 connects to P2's TCP listener, P2 opens a bi stream to P3 and sends +this request: + +1. "1" to mean "Open a PTTH connection" +2. Server ID, hard-coded as "43" for the only P4 server instance we have +3. Unused +4. Unused + +The first 4 bytes are interpreted by P3. If everything is okay, P3 responds +with: + +1. "20" to mean "OK". +2. Unused +3. Unused +4. Unused + +Then P3 opens a bi stream to P4 and begins relaying from P2 to P4. + +P2 reads that response and sends another request, which will be forwarded +to P4: + +1. "1" to mean "Open a PTTH connection" +2. Unused (Reserved for choosing port) +3. Unused +4. Unused + +P4 parses the last 4 bytes. If everything is okay, P4 (via P3) responds to P2 with: + +1. "20" to mean "OK". +2. Unused +3. Unused +4. Unused + +And then P4 begins relaying between P2 and P5. + +P2 reads the 4 byte response from P3 and the 4 byte response from P4. +If everything is okay, it completes the relaying from P1 to P5. + # Plan This is a TCP port forwarding system, like SSH has, but better. diff --git a/prototypes/quic_demo/src/bin/quic_demo_client.rs b/prototypes/quic_demo/src/bin/quic_demo_client.rs index aeb561f..3f5022b 100644 --- a/prototypes/quic_demo/src/bin/quic_demo_client.rs +++ b/prototypes/quic_demo/src/bin/quic_demo_client.rs @@ -42,12 +42,26 @@ async fn main () -> anyhow::Result <()> { let (mut relay_send, mut relay_recv) = connection.open_bi ().await?; - let req_buf = [1, 43, 0, 0, 1, 0, 0, 0]; + // Ask P3 if we can connect to P4 + + let req_buf = [1, 43, 0, 0]; relay_send.write_all (&req_buf).await?; - let mut resp_buf = [0; 8]; + let mut resp_buf = [0; 4]; relay_recv.read_exact (&mut resp_buf).await?; + debug! ("Status code from P3: {}", resp_buf [0]); + + // Ask P4 if we can connect to P5 + + let req_buf = [1, 0, 0, 0]; + relay_send.write_all (&req_buf).await?; + + let mut resp_buf = [0; 4]; + relay_recv.read_exact (&mut resp_buf).await?; + + debug! ("Status code from P4: {}", resp_buf [0]); + trace! ("Relaying bytes..."); let ptth_conn = PtthNewConnection { diff --git a/prototypes/quic_demo/src/bin/quic_demo_relay_server.rs b/prototypes/quic_demo/src/bin/quic_demo_relay_server.rs index 2f0445e..62be5d3 100644 --- a/prototypes/quic_demo/src/bin/quic_demo_relay_server.rs +++ b/prototypes/quic_demo/src/bin/quic_demo_relay_server.rs @@ -239,7 +239,7 @@ async fn handle_request_p2_to_p4 ( // TODO: Auth checks - let resp_buf = [0, 0, 0, 0]; + let resp_buf = [20, 0, 0, 0]; client_send.write_all (&resp_buf).await?; {