From 1c599728348963771a9bf0803238267ef3ec6102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 29 Jan 2024 19:38:12 +0100 Subject: [PATCH 1/6] udp protocol: rename "write" and "from_bytes" methods --- crates/udp/src/common.rs | 2 +- crates/udp/src/workers/socket/mio.rs | 4 +-- .../src/workers/socket/uring/recv_helper.rs | 2 +- .../src/workers/socket/uring/send_buffers.rs | 2 +- crates/udp/tests/common/mod.rs | 4 +-- crates/udp/tests/invalid_connection_id.rs | 2 +- crates/udp_load_test/src/worker/mod.rs | 4 +-- crates/udp_protocol/src/request.rs | 8 +++--- crates/udp_protocol/src/response.rs | 26 +++++++++---------- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/crates/udp/src/common.rs b/crates/udp/src/common.rs index f803ea5..19f8b27 100644 --- a/crates/udp/src/common.rs +++ b/crates/udp/src/common.rs @@ -290,7 +290,7 @@ mod tests { let mut buf = Vec::new(); - response.write(&mut buf).unwrap(); + response.write_bytes(&mut buf).unwrap(); println!("Buffer len: {}", buf.len()); diff --git a/crates/udp/src/workers/socket/mio.rs b/crates/udp/src/workers/socket/mio.rs index 070e00b..38a1865 100644 --- a/crates/udp/src/workers/socket/mio.rs +++ b/crates/udp/src/workers/socket/mio.rs @@ -198,7 +198,7 @@ impl SocketWorker { } let src = CanonicalSocketAddr::new(src); - let request_parsable = match Request::from_bytes( + let request_parsable = match Request::parse_bytes( &self.buffer[..bytes_read], self.config.protocol.max_scrape_torrents, ) { @@ -431,7 +431,7 @@ impl SocketWorker { ) { let mut buffer = Cursor::new(&mut buffer[..]); - if let Err(err) = response.write(&mut buffer) { + if let Err(err) = response.write_bytes(&mut buffer) { ::log::error!("failed writing response to buffer: {:#}", err); return; diff --git a/crates/udp/src/workers/socket/uring/recv_helper.rs b/crates/udp/src/workers/socket/uring/recv_helper.rs index 4a485f6..0aef6d9 100644 --- a/crates/udp/src/workers/socket/uring/recv_helper.rs +++ b/crates/udp/src/workers/socket/uring/recv_helper.rs @@ -138,7 +138,7 @@ impl RecvHelper { let addr = CanonicalSocketAddr::new(addr); - let request = Request::from_bytes(msg.payload_data(), self.max_scrape_torrents) + let request = Request::parse_bytes(msg.payload_data(), self.max_scrape_torrents) .map_err(|err| Error::RequestParseError(err, addr))?; Ok((request, addr)) diff --git a/crates/udp/src/workers/socket/uring/send_buffers.rs b/crates/udp/src/workers/socket/uring/send_buffers.rs index 458d96f..902e251 100644 --- a/crates/udp/src/workers/socket/uring/send_buffers.rs +++ b/crates/udp/src/workers/socket/uring/send_buffers.rs @@ -196,7 +196,7 @@ impl SendBuffer { let mut cursor = Cursor::new(&mut self.bytes[..]); - match response.write(&mut cursor) { + match response.write_bytes(&mut cursor) { Ok(()) => { self.iovec.iov_len = cursor.position() as usize; diff --git a/crates/udp/tests/common/mod.rs b/crates/udp/tests/common/mod.rs index ee8e365..0656b73 100644 --- a/crates/udp/tests/common/mod.rs +++ b/crates/udp/tests/common/mod.rs @@ -104,7 +104,7 @@ pub fn request_and_response( let mut buffer = Cursor::new(&mut buffer[..]); request - .write(&mut buffer) + .write_bytes(&mut buffer) .with_context(|| "write request")?; let bytes_written = buffer.position() as usize; @@ -119,6 +119,6 @@ pub fn request_and_response( .recv_from(&mut buffer) .with_context(|| "recv response")?; - Response::from_bytes(&buffer[..bytes_read], true).with_context(|| "parse response") + Response::parse_bytes(&buffer[..bytes_read], true).with_context(|| "parse response") } } diff --git a/crates/udp/tests/invalid_connection_id.rs b/crates/udp/tests/invalid_connection_id.rs index 11579a3..7506854 100644 --- a/crates/udp/tests/invalid_connection_id.rs +++ b/crates/udp/tests/invalid_connection_id.rs @@ -77,7 +77,7 @@ fn no_response( let mut buffer = Cursor::new(&mut buffer[..]); request - .write(&mut buffer) + .write_bytes(&mut buffer) .with_context(|| "write request")?; let bytes_written = buffer.position() as usize; diff --git a/crates/udp_load_test/src/worker/mod.rs b/crates/udp_load_test/src/worker/mod.rs index b3be476..8c7c606 100644 --- a/crates/udp_load_test/src/worker/mod.rs +++ b/crates/udp_load_test/src/worker/mod.rs @@ -71,7 +71,7 @@ impl Worker { for _ in events.iter() { while let Ok(amt) = self.socket.recv(&mut self.buffer) { - match Response::from_bytes(&self.buffer[0..amt], self.addr.is_ipv4()) { + match Response::parse_bytes(&self.buffer[0..amt], self.addr.is_ipv4()) { Ok(response) => { if let Some(request) = self.process_response(response) { self.send_request(request); @@ -288,7 +288,7 @@ impl Worker { fn send_request(&mut self, request: Request) { let mut cursor = Cursor::new(self.buffer); - match request.write(&mut cursor) { + match request.write_bytes(&mut cursor) { Ok(()) => { let position = cursor.position() as usize; let inner = cursor.get_ref(); diff --git a/crates/udp_protocol/src/request.rs b/crates/udp_protocol/src/request.rs index cd2963e..8cdd10d 100644 --- a/crates/udp_protocol/src/request.rs +++ b/crates/udp_protocol/src/request.rs @@ -19,7 +19,7 @@ pub enum Request { } impl Request { - pub fn write(self, bytes: &mut impl Write) -> Result<(), io::Error> { + pub fn write_bytes(self, bytes: &mut impl Write) -> Result<(), io::Error> { match self { Request::Connect(r) => { bytes.write_i64::(PROTOCOL_IDENTIFIER)?; @@ -42,7 +42,7 @@ impl Request { Ok(()) } - pub fn from_bytes(bytes: &[u8], max_scrape_torrents: u8) -> Result { + pub fn parse_bytes(bytes: &[u8], max_scrape_torrents: u8) -> Result { let action = bytes .get(8..12) .map(|bytes| I32::from_bytes(bytes.try_into().unwrap())) @@ -323,8 +323,8 @@ mod tests { fn same_after_conversion(request: Request) -> bool { let mut buf = Vec::new(); - request.clone().write(&mut buf).unwrap(); - let r2 = Request::from_bytes(&buf[..], ::std::u8::MAX).unwrap(); + request.clone().write_bytes(&mut buf).unwrap(); + let r2 = Request::parse_bytes(&buf[..], ::std::u8::MAX).unwrap(); let success = request == r2; diff --git a/crates/udp_protocol/src/response.rs b/crates/udp_protocol/src/response.rs index 4e3353f..591abe7 100644 --- a/crates/udp_protocol/src/response.rs +++ b/crates/udp_protocol/src/response.rs @@ -18,18 +18,18 @@ pub enum Response { impl Response { #[inline] - pub fn write(&self, bytes: &mut impl Write) -> Result<(), io::Error> { + pub fn write_bytes(&self, bytes: &mut impl Write) -> Result<(), io::Error> { match self { - Response::Connect(r) => r.write(bytes), - Response::AnnounceIpv4(r) => r.write(bytes), - Response::AnnounceIpv6(r) => r.write(bytes), - Response::Scrape(r) => r.write(bytes), - Response::Error(r) => r.write(bytes), + Response::Connect(r) => r.write_bytes(bytes), + Response::AnnounceIpv4(r) => r.write_bytes(bytes), + Response::AnnounceIpv6(r) => r.write_bytes(bytes), + Response::Scrape(r) => r.write_bytes(bytes), + Response::Error(r) => r.write_bytes(bytes), } } #[inline] - pub fn from_bytes(mut bytes: &[u8], ipv4: bool) -> Result { + pub fn parse_bytes(mut bytes: &[u8], ipv4: bool) -> Result { let action = read_i32_ne(&mut bytes)?; match action.get() { @@ -137,7 +137,7 @@ pub struct ConnectResponse { impl ConnectResponse { #[inline] - pub fn write(&self, bytes: &mut impl Write) -> Result<(), io::Error> { + pub fn write_bytes(&self, bytes: &mut impl Write) -> Result<(), io::Error> { bytes.write_i32::(0)?; bytes.write_all(self.as_bytes())?; @@ -160,7 +160,7 @@ impl AnnounceResponse { } #[inline] - pub fn write(&self, bytes: &mut impl Write) -> Result<(), io::Error> { + pub fn write_bytes(&self, bytes: &mut impl Write) -> Result<(), io::Error> { bytes.write_i32::(1)?; bytes.write_all(self.fixed.as_bytes())?; bytes.write_all((*self.peers.as_slice()).as_bytes())?; @@ -186,7 +186,7 @@ pub struct ScrapeResponse { impl ScrapeResponse { #[inline] - pub fn write(&self, bytes: &mut impl Write) -> Result<(), io::Error> { + pub fn write_bytes(&self, bytes: &mut impl Write) -> Result<(), io::Error> { bytes.write_i32::(2)?; bytes.write_all(self.transaction_id.as_bytes())?; bytes.write_all((*self.torrent_stats.as_slice()).as_bytes())?; @@ -211,7 +211,7 @@ pub struct ErrorResponse { impl ErrorResponse { #[inline] - pub fn write(&self, bytes: &mut impl Write) -> Result<(), io::Error> { + pub fn write_bytes(&self, bytes: &mut impl Write) -> Result<(), io::Error> { bytes.write_i32::(3)?; bytes.write_all(self.transaction_id.as_bytes())?; bytes.write_all(self.message.as_bytes())?; @@ -304,8 +304,8 @@ mod tests { fn same_after_conversion(response: Response, ipv4: bool) -> bool { let mut buf = Vec::new(); - response.clone().write(&mut buf).unwrap(); - let r2 = Response::from_bytes(&buf[..], ipv4).unwrap(); + response.clone().write_bytes(&mut buf).unwrap(); + let r2 = Response::parse_bytes(&buf[..], ipv4).unwrap(); let success = response == r2; From 41efa151afd2a0f95fabc0107ca755f506b28ddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 29 Jan 2024 19:42:56 +0100 Subject: [PATCH 2/6] udp protocol: implement write_bytes for individual request types --- crates/udp_protocol/src/request.rs | 50 ++++++++++++++++++------------ 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/crates/udp_protocol/src/request.rs b/crates/udp_protocol/src/request.rs index 8cdd10d..ef0f5ac 100644 --- a/crates/udp_protocol/src/request.rs +++ b/crates/udp_protocol/src/request.rs @@ -19,27 +19,12 @@ pub enum Request { } impl Request { - pub fn write_bytes(self, bytes: &mut impl Write) -> Result<(), io::Error> { + pub fn write_bytes(&self, bytes: &mut impl Write) -> Result<(), io::Error> { match self { - Request::Connect(r) => { - bytes.write_i64::(PROTOCOL_IDENTIFIER)?; - bytes.write_i32::(0)?; - bytes.write_all(r.transaction_id.as_bytes())?; - } - - Request::Announce(r) => { - bytes.write_all(r.as_bytes())?; - } - - Request::Scrape(r) => { - bytes.write_all(r.connection_id.as_bytes())?; - bytes.write_i32::(2)?; - bytes.write_all(r.transaction_id.as_bytes())?; - bytes.write_all((*r.info_hashes.as_slice()).as_bytes())?; - } + Request::Connect(r) => r.write_bytes(bytes), + Request::Announce(r) => r.write_bytes(bytes), + Request::Scrape(r) => r.write_bytes(bytes), } - - Ok(()) } pub fn parse_bytes(bytes: &[u8], max_scrape_torrents: u8) -> Result { @@ -150,6 +135,16 @@ pub struct ConnectRequest { pub transaction_id: TransactionId, } +impl ConnectRequest { + pub fn write_bytes(&self, bytes: &mut impl Write) -> Result<(), io::Error> { + bytes.write_i64::(PROTOCOL_IDENTIFIER)?; + bytes.write_i32::(0)?; + bytes.write_all(self.transaction_id.as_bytes())?; + + Ok(()) + } +} + #[derive(PartialEq, Eq, Clone, Debug, AsBytes, FromBytes, FromZeroes)] #[repr(C, packed)] pub struct AnnounceRequest { @@ -170,6 +165,12 @@ pub struct AnnounceRequest { pub port: Port, } +impl AnnounceRequest { + pub fn write_bytes(&self, bytes: &mut impl Write) -> Result<(), io::Error> { + bytes.write_all(self.as_bytes()) + } +} + /// Note: Request::from_bytes only creates this struct with value 1 #[derive(PartialEq, Eq, Clone, Copy, Debug, AsBytes, FromBytes, FromZeroes)] #[repr(transparent)] @@ -223,6 +224,17 @@ pub struct ScrapeRequest { pub info_hashes: Vec, } +impl ScrapeRequest { + pub fn write_bytes(&self, bytes: &mut impl Write) -> Result<(), io::Error> { + bytes.write_all(self.connection_id.as_bytes())?; + bytes.write_i32::(2)?; + bytes.write_all(self.transaction_id.as_bytes())?; + bytes.write_all((*self.info_hashes.as_slice()).as_bytes())?; + + Ok(()) + } +} + #[derive(Debug)] pub enum RequestParseError { Sendable { From fee465d2056cba57b209fe9421b64d9a4e3c130b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 29 Jan 2024 19:45:15 +0100 Subject: [PATCH 3/6] udp protocol: derive Copy for multiple structs --- crates/udp_protocol/src/request.rs | 4 ++-- crates/udp_protocol/src/response.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/udp_protocol/src/request.rs b/crates/udp_protocol/src/request.rs index ef0f5ac..a60791b 100644 --- a/crates/udp_protocol/src/request.rs +++ b/crates/udp_protocol/src/request.rs @@ -130,7 +130,7 @@ impl From for Request { } } -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct ConnectRequest { pub transaction_id: TransactionId, } @@ -145,7 +145,7 @@ impl ConnectRequest { } } -#[derive(PartialEq, Eq, Clone, Debug, AsBytes, FromBytes, FromZeroes)] +#[derive(PartialEq, Eq, Clone, Copy, Debug, AsBytes, FromBytes, FromZeroes)] #[repr(C, packed)] pub struct AnnounceRequest { pub connection_id: ConnectionId, diff --git a/crates/udp_protocol/src/response.rs b/crates/udp_protocol/src/response.rs index 591abe7..98c5e6b 100644 --- a/crates/udp_protocol/src/response.rs +++ b/crates/udp_protocol/src/response.rs @@ -128,7 +128,7 @@ impl From for Response { } } -#[derive(PartialEq, Eq, Clone, Debug, AsBytes, FromBytes, FromZeroes)] +#[derive(PartialEq, Eq, Clone, Copy, Debug, AsBytes, FromBytes, FromZeroes)] #[repr(C, packed)] pub struct ConnectResponse { pub transaction_id: TransactionId, @@ -169,7 +169,7 @@ impl AnnounceResponse { } } -#[derive(PartialEq, Eq, Clone, Debug, AsBytes, FromBytes, FromZeroes)] +#[derive(PartialEq, Eq, Clone, Copy, Debug, AsBytes, FromBytes, FromZeroes)] #[repr(C, packed)] pub struct AnnounceResponseFixedData { pub transaction_id: TransactionId, From 3c906f48ee1687342b9b46910563019cbaed12a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 29 Jan 2024 19:49:05 +0100 Subject: [PATCH 4/6] ws protocol: make tungstenite integration optional feature --- crates/ws_protocol/Cargo.toml | 6 +++++- crates/ws_protocol/src/incoming/mod.rs | 1 + crates/ws_protocol/src/lib.rs | 2 ++ crates/ws_protocol/src/outgoing/mod.rs | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/ws_protocol/Cargo.toml b/crates/ws_protocol/Cargo.toml index 4ae72de..3c2dd4a 100644 --- a/crates/ws_protocol/Cargo.toml +++ b/crates/ws_protocol/Cargo.toml @@ -12,6 +12,10 @@ rust-version.workspace = true readme = "./README.md" +[features] +default = ["tungstenite"] +tungstenite = ["dep:tungstenite"] + [lib] name = "aquatic_ws_protocol" @@ -26,7 +30,7 @@ hashbrown = { version = "0.14", features = ["serde"] } serde = { version = "1", features = ["derive"] } serde_json = "1" simd-json = "0.13" -tungstenite = "0.21" +tungstenite = { version = "0.21", optional = true } [dev-dependencies] criterion = "0.5" diff --git a/crates/ws_protocol/src/incoming/mod.rs b/crates/ws_protocol/src/incoming/mod.rs index 1fe48a3..517a319 100644 --- a/crates/ws_protocol/src/incoming/mod.rs +++ b/crates/ws_protocol/src/incoming/mod.rs @@ -15,6 +15,7 @@ pub enum InMessage { ScrapeRequest(ScrapeRequest), } +#[cfg(feature = "tungstenite")] impl InMessage { #[inline] pub fn to_ws_message(&self) -> ::tungstenite::Message { diff --git a/crates/ws_protocol/src/lib.rs b/crates/ws_protocol/src/lib.rs index 2652e86..1c91b00 100644 --- a/crates/ws_protocol/src/lib.rs +++ b/crates/ws_protocol/src/lib.rs @@ -227,6 +227,7 @@ mod tests { } } + #[cfg(feature = "tungstenite")] #[quickcheck] fn quickcheck_serde_identity_in_message(in_message_1: InMessage) -> bool { let ws_message = in_message_1.to_ws_message(); @@ -246,6 +247,7 @@ mod tests { success } + #[cfg(feature = "tungstenite")] #[quickcheck] fn quickcheck_serde_identity_out_message(out_message_1: OutMessage) -> bool { let ws_message = out_message_1.to_ws_message(); diff --git a/crates/ws_protocol/src/outgoing/mod.rs b/crates/ws_protocol/src/outgoing/mod.rs index c2fbaab..151fb4b 100644 --- a/crates/ws_protocol/src/outgoing/mod.rs +++ b/crates/ws_protocol/src/outgoing/mod.rs @@ -23,6 +23,7 @@ pub enum OutMessage { ErrorResponse(ErrorResponse), } +#[cfg(feature = "tungstenite")] impl OutMessage { #[inline] pub fn to_ws_message(&self) -> tungstenite::Message { From 38de05a6c432228dabd9a1e8b9d3c1d54b20d022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 29 Jan 2024 19:52:41 +0100 Subject: [PATCH 5/6] http protocol: rename methods for writing to and parsing from bytes --- crates/http/src/workers/socket/connection.rs | 2 +- crates/http/src/workers/socket/request.rs | 2 +- crates/http_load_test/src/network.rs | 2 +- .../bench_announce_response_to_bytes.rs | 2 +- .../benches/bench_request_from_bytes.rs | 2 +- crates/http_protocol/src/request.rs | 28 +++++++++---------- crates/http_protocol/src/response.rs | 22 +++++++-------- 7 files changed, 30 insertions(+), 30 deletions(-) diff --git a/crates/http/src/workers/socket/connection.rs b/crates/http/src/workers/socket/connection.rs index 4ab82ab..a8cd846 100644 --- a/crates/http/src/workers/socket/connection.rs +++ b/crates/http/src/workers/socket/connection.rs @@ -389,7 +389,7 @@ where let mut position = RESPONSE_HEADER.len(); let body_len = response - .write(&mut &mut self.response_buffer[position..]) + .write_bytes(&mut &mut self.response_buffer[position..]) .map_err(ConnectionError::ResponseBufferWrite)?; position += body_len; diff --git a/crates/http/src/workers/socket/request.rs b/crates/http/src/workers/socket/request.rs index ec5f19f..f10950a 100644 --- a/crates/http/src/workers/socket/request.rs +++ b/crates/http/src/workers/socket/request.rs @@ -25,7 +25,7 @@ pub fn parse_request( match http_request.parse(buffer).with_context(|| "httparse")? { httparse::Status::Complete(_) => { let path = http_request.path.ok_or(anyhow::anyhow!("no http path"))?; - let request = Request::from_http_get_path(path)?; + let request = Request::parse_http_get_path(path)?; let opt_peer_ip = if config.network.runs_behind_reverse_proxy { let header_name = &config.network.reverse_proxy_ip_header_name; diff --git a/crates/http_load_test/src/network.rs b/crates/http_load_test/src/network.rs index 6c1ff12..f739a97 100644 --- a/crates/http_load_test/src/network.rs +++ b/crates/http_load_test/src/network.rs @@ -229,7 +229,7 @@ where } if let Some(body_start_index) = opt_body_start_index { - match Response::from_bytes(&interesting_bytes[body_start_index..]) { + match Response::parse_bytes(&interesting_bytes[body_start_index..]) { Ok(response) => { match response { Response::Announce(_) => { diff --git a/crates/http_protocol/benches/bench_announce_response_to_bytes.rs b/crates/http_protocol/benches/bench_announce_response_to_bytes.rs index b871cf0..146e168 100644 --- a/crates/http_protocol/benches/bench_announce_response_to_bytes.rs +++ b/crates/http_protocol/benches/bench_announce_response_to_bytes.rs @@ -33,7 +33,7 @@ pub fn bench(c: &mut Criterion) { b.iter(|| { buffer.set_position(0); - Response::write(black_box(&response), black_box(&mut buffer)).unwrap(); + Response::write_bytes(black_box(&response), black_box(&mut buffer)).unwrap(); }) }); } diff --git a/crates/http_protocol/benches/bench_request_from_bytes.rs b/crates/http_protocol/benches/bench_request_from_bytes.rs index c7d927f..b58c586 100644 --- a/crates/http_protocol/benches/bench_request_from_bytes.rs +++ b/crates/http_protocol/benches/bench_request_from_bytes.rs @@ -7,7 +7,7 @@ static INPUT: &[u8] = b"GET /announce?info_hash=%04%0bkV%3f%5cr%14%a6%b7%98%adC% pub fn bench(c: &mut Criterion) { c.bench_function("request-from-bytes", |b| { - b.iter(|| Request::from_bytes(black_box(INPUT))) + b.iter(|| Request::parse_bytes(black_box(INPUT))) }); } diff --git a/crates/http_protocol/src/request.rs b/crates/http_protocol/src/request.rs index 2fd175c..a462de7 100644 --- a/crates/http_protocol/src/request.rs +++ b/crates/http_protocol/src/request.rs @@ -21,7 +21,7 @@ pub struct AnnounceRequest { } impl AnnounceRequest { - fn write(&self, output: &mut W, url_suffix: &[u8]) -> ::std::io::Result<()> { + fn write_bytes(&self, output: &mut W, url_suffix: &[u8]) -> ::std::io::Result<()> { output.write_all(b"GET /announce")?; output.write_all(url_suffix)?; output.write_all(b"?info_hash=")?; @@ -67,7 +67,7 @@ impl AnnounceRequest { Ok(()) } - pub fn from_query_string(query_string: &str) -> anyhow::Result { + pub fn parse_query_string(query_string: &str) -> anyhow::Result { // -- Parse key-value pairs let mut opt_info_hash = None; @@ -173,7 +173,7 @@ pub struct ScrapeRequest { } impl ScrapeRequest { - fn write(&self, output: &mut W, url_suffix: &[u8]) -> ::std::io::Result<()> { + fn write_bytes(&self, output: &mut W, url_suffix: &[u8]) -> ::std::io::Result<()> { output.write_all(b"GET /scrape")?; output.write_all(url_suffix)?; output.write_all(b"?")?; @@ -196,7 +196,7 @@ impl ScrapeRequest { Ok(()) } - pub fn from_query_string(query_string: &str) -> anyhow::Result { + pub fn parse_query_string(query_string: &str) -> anyhow::Result { // -- Parse key-value pairs let mut info_hashes = Vec::new(); @@ -252,14 +252,14 @@ pub enum Request { impl Request { /// Parse Request from HTTP request bytes - pub fn from_bytes(bytes: &[u8]) -> anyhow::Result> { + pub fn parse_bytes(bytes: &[u8]) -> anyhow::Result> { let mut headers = [httparse::EMPTY_HEADER; 16]; let mut http_request = httparse::Request::new(&mut headers); match http_request.parse(bytes) { Ok(httparse::Status::Complete(_)) => { if let Some(path) = http_request.path { - Self::from_http_get_path(path).map(Some) + Self::parse_http_get_path(path).map(Some) } else { Err(anyhow::anyhow!("no http path")) } @@ -282,7 +282,7 @@ impl Request { /// UTF-8 string, meaning that non-ascii bytes are invalid characters. /// Therefore, these bytes must be converted to their equivalent multi-byte /// UTF-8 encodings. - pub fn from_http_get_path(path: &str) -> anyhow::Result { + pub fn parse_http_get_path(path: &str) -> anyhow::Result { ::log::debug!("request GET path: {}", path); let mut split_parts = path.splitn(2, '?'); @@ -291,11 +291,11 @@ impl Request { let query_string = split_parts.next().with_context(|| "no query string")?; if location == "/announce" { - Ok(Request::Announce(AnnounceRequest::from_query_string( + Ok(Request::Announce(AnnounceRequest::parse_query_string( query_string, )?)) } else if location == "/scrape" { - Ok(Request::Scrape(ScrapeRequest::from_query_string( + Ok(Request::Scrape(ScrapeRequest::parse_query_string( query_string, )?)) } else { @@ -305,8 +305,8 @@ impl Request { pub fn write(&self, output: &mut W, url_suffix: &[u8]) -> ::std::io::Result<()> { match self { - Self::Announce(r) => r.write(output, url_suffix), - Self::Scrape(r) => r.write(output, url_suffix), + Self::Announce(r) => r.write_bytes(output, url_suffix), + Self::Scrape(r) => r.write_bytes(output, url_suffix), } } } @@ -351,7 +351,7 @@ mod tests { bytes.extend_from_slice(ANNOUNCE_REQUEST_PATH.as_bytes()); bytes.extend_from_slice(b" HTTP/1.1\r\n\r\n"); - let parsed_request = Request::from_bytes(&bytes[..]).unwrap().unwrap(); + let parsed_request = Request::parse_bytes(&bytes[..]).unwrap().unwrap(); let reference_request = get_reference_announce_request(); assert_eq!(parsed_request, reference_request); @@ -365,7 +365,7 @@ mod tests { bytes.extend_from_slice(SCRAPE_REQUEST_PATH.as_bytes()); bytes.extend_from_slice(b" HTTP/1.1\r\n\r\n"); - let parsed_request = Request::from_bytes(&bytes[..]).unwrap().unwrap(); + let parsed_request = Request::parse_bytes(&bytes[..]).unwrap().unwrap(); let reference_request = Request::Scrape(ScrapeRequest { info_hashes: vec![InfoHash(REFERENCE_INFO_HASH)], }); @@ -432,7 +432,7 @@ mod tests { request.write(&mut bytes, &[]).unwrap(); - let parsed_request = Request::from_bytes(&bytes[..]).unwrap().unwrap(); + let parsed_request = Request::parse_bytes(&bytes[..]).unwrap().unwrap(); let success = request == parsed_request; diff --git a/crates/http_protocol/src/response.rs b/crates/http_protocol/src/response.rs index ed36b73..a3b0d17 100644 --- a/crates/http_protocol/src/response.rs +++ b/crates/http_protocol/src/response.rs @@ -61,7 +61,7 @@ pub struct AnnounceResponse { } impl AnnounceResponse { - pub fn write(&self, output: &mut W) -> ::std::io::Result { + pub fn write_bytes(&self, output: &mut W) -> ::std::io::Result { let mut bytes_written = 0usize; bytes_written += output.write(b"d8:completei")?; @@ -124,7 +124,7 @@ pub struct ScrapeResponse { } impl ScrapeResponse { - pub fn write(&self, output: &mut W) -> ::std::io::Result { + pub fn write_bytes(&self, output: &mut W) -> ::std::io::Result { let mut bytes_written = 0usize; bytes_written += output.write(b"d5:filesd")?; @@ -160,7 +160,7 @@ impl FailureResponse { } } - pub fn write(&self, output: &mut W) -> ::std::io::Result { + pub fn write_bytes(&self, output: &mut W) -> ::std::io::Result { let mut bytes_written = 0usize; let reason_bytes = self.failure_reason.as_bytes(); @@ -184,14 +184,14 @@ pub enum Response { } impl Response { - pub fn write(&self, output: &mut W) -> ::std::io::Result { + pub fn write_bytes(&self, output: &mut W) -> ::std::io::Result { match self { - Response::Announce(r) => r.write(output), - Response::Failure(r) => r.write(output), - Response::Scrape(r) => r.write(output), + Response::Announce(r) => r.write_bytes(output), + Response::Failure(r) => r.write_bytes(output), + Response::Scrape(r) => r.write_bytes(output), } } - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn parse_bytes(bytes: &[u8]) -> Result { ::serde_bencode::from_bytes(bytes) } } @@ -285,7 +285,7 @@ mod tests { let mut hand_written = Vec::new(); - response.write(&mut hand_written).unwrap(); + response.write_bytes(&mut hand_written).unwrap(); let success = hand_written == reference; @@ -303,7 +303,7 @@ mod tests { let mut hand_written = Vec::new(); - response.write(&mut hand_written).unwrap(); + response.write_bytes(&mut hand_written).unwrap(); let success = hand_written == reference; @@ -321,7 +321,7 @@ mod tests { let mut hand_written = Vec::new(); - response.write(&mut hand_written).unwrap(); + response.write_bytes(&mut hand_written).unwrap(); let success = hand_written == reference; From 239266ddab88a2a29fcb0e6aa33252427f1a560f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 29 Jan 2024 20:01:05 +0100 Subject: [PATCH 6/6] udp protocol: improve README --- crates/udp_protocol/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/udp_protocol/README.md b/crates/udp_protocol/README.md index 1b49ec7..19f32c4 100644 --- a/crates/udp_protocol/README.md +++ b/crates/udp_protocol/README.md @@ -1,4 +1,5 @@ # aquatic_udp_protocol: UDP BitTorrent tracker protocol -[UDP BitTorrent](https://www.bittorrent.org/beps/bep_0015.html) tracker -message parsing and serialization. \ No newline at end of file +UDP BitTorrent tracker message parsing and serialization. + +Implements [BEP 015](https://www.bittorrent.org/beps/bep_0015.html) ([more details](https://libtorrent.org/udp_tracker_protocol.html)).