diff --git a/.github/actions/test-transfer/Dockerfile b/.github/actions/test-file-transfers/Dockerfile similarity index 100% rename from .github/actions/test-transfer/Dockerfile rename to .github/actions/test-file-transfers/Dockerfile diff --git a/.github/actions/test-transfer/action.yml b/.github/actions/test-file-transfers/action.yml similarity index 81% rename from .github/actions/test-transfer/action.yml rename to .github/actions/test-file-transfers/action.yml index c04e4e8..67c1026 100644 --- a/.github/actions/test-transfer/action.yml +++ b/.github/actions/test-file-transfers/action.yml @@ -1,5 +1,5 @@ -name: 'test-transfer' -description: 'test aquatic file transfer' +name: 'test-file-transfers' +description: 'test aquatic file transfers' outputs: # http_ipv4: # description: 'HTTP IPv4 status' diff --git a/.github/actions/test-transfer/entrypoint.sh b/.github/actions/test-file-transfers/entrypoint.sh similarity index 100% rename from .github/actions/test-transfer/entrypoint.sh rename to .github/actions/test-file-transfers/entrypoint.sh diff --git a/.github/workflows/cargo-build-and-test.yml b/.github/workflows/ci.yml similarity index 57% rename from .github/workflows/cargo-build-and-test.yml rename to .github/workflows/ci.yml index 658625b..d12ff7b 100644 --- a/.github/workflows/cargo-build-and-test.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: 'cargo: build and test' +name: CI on: push: @@ -10,9 +10,9 @@ env: CARGO_TERM_COLOR: always jobs: - build-test-linux: + build-linux: runs-on: ubuntu-latest - timeout-minutes: 25 + timeout-minutes: 20 steps: - uses: actions/checkout@v3 - name: Install latest stable Rust @@ -30,9 +30,6 @@ jobs: cargo build --verbose -p aquatic_udp --features "cpu-pinning" cargo build --verbose -p aquatic_http cargo build --verbose -p aquatic_ws - - name: Run tests - run: cargo test --verbose --workspace --profile "test-fast" - build-macos: runs-on: macos-latest @@ -49,3 +46,35 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Build run: cargo build --verbose -p aquatic_udp + + test: + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v3 + - name: Install latest stable Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - name: Install dependencies + run: sudo apt-get update -y && sudo apt-get install libhwloc-dev -y + - name: Setup Rust dependency caching + uses: Swatinem/rust-cache@v2 + - name: Run tests + run: cargo test --verbose --workspace --profile "test-fast" + + test-file-transfers: + runs-on: ubuntu-latest + name: "Test BitTorrent file transfers over UDP, TLS and WSS" + timeout-minutes: 20 + container: + image: rust:1-bullseye + options: --ulimit memlock=524288:524288 + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Test file transfers + uses: ./.github/actions/test-file-transfers + id: test_file_transfers diff --git a/.github/workflows/test-transfer.yml b/.github/workflows/test-transfer.yml deleted file mode 100644 index c1ae76b..0000000 --- a/.github/workflows/test-transfer.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: "Test UDP, TLS and WSS file transfer" - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - test-transfer-http: - runs-on: ubuntu-latest - name: "Test BitTorrent file transfer over UDP, TLS and WSS" - timeout-minutes: 20 - container: - image: rust:1-bullseye - options: --ulimit memlock=524288:524288 - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Test file transfers - uses: ./.github/actions/test-transfer - id: test_transfer diff --git a/Cargo.lock b/Cargo.lock index 9718825..c580828 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,7 +107,7 @@ dependencies = [ "futures-lite", "futures-rustls", "glommio", - "itoa 1.0.3", + "itoa 1.0.4", "libc", "log", "memchr", @@ -182,7 +182,7 @@ dependencies = [ "criterion", "hex", "httparse", - "itoa 1.0.3", + "itoa 1.0.4", "log", "memchr", "quickcheck", @@ -462,7 +462,7 @@ dependencies = [ "http", "http-body", "hyper", - "itoa 1.0.3", + "itoa 1.0.4", "matchit", "memchr", "mime", @@ -665,13 +665,13 @@ dependencies = [ [[package]] name = "console" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89eab4d20ce20cea182308bca13088fecea9c05f6776cf287205d41a0ed3c847" +checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c" dependencies = [ "encode_unicode", + "lazy_static", "libc", - "once_cell", "terminal_size", "winapi 0.3.9", ] @@ -800,15 +800,14 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" +checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", "memoffset 0.6.5", - "once_cell", "scopeguard", ] @@ -824,12 +823,11 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" dependencies = [ "cfg-if", - "once_cell", ] [[package]] @@ -1409,7 +1407,7 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.3", + "itoa 1.0.4", ] [[package]] @@ -1470,7 +1468,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.3", + "itoa 1.0.4", "pin-project-lite", "socket2 0.4.7", "tokio", @@ -1557,9 +1555,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "js-sys" @@ -1591,9 +1589,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.133" +version = "0.2.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" +checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" [[package]] name = "libm" @@ -2114,9 +2112,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.44" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58" +checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" dependencies = [ "unicode-ident", ] @@ -2418,11 +2416,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "41feea4228a6f1cd09ec7a3593a682276702cd67b5273544757dae23c096f074" dependencies = [ - "itoa 1.0.3", + "itoa 1.0.4", "ryu", "serde", ] @@ -2528,9 +2526,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "smartstring" @@ -2635,7 +2633,7 @@ dependencies = [ "hashlink", "hex", "indexmap", - "itoa 1.0.3", + "itoa 1.0.4", "libc", "log", "memchr", @@ -2713,9 +2711,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e" +checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1" dependencies = [ "proc-macro2", "quote", @@ -2761,18 +2759,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a99cb8c4b9a8ef0e7907cd3b617cc8dc04d571c4e73c8ae403d80ac160bb122" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a891860d3c8d66fec8e73ddb3765f90082374dbaaa833407b904a94f1a7eb43" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", @@ -2781,11 +2779,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b" +checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c" dependencies = [ - "itoa 1.0.3", + "itoa 1.0.4", "libc", "num_threads", "time-macros", @@ -2824,9 +2822,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.21.1" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0020c875007ad96677dcc890298f4b942882c5d4eb7cc8f439fc3bf813dc9c95" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ "autocfg", "bytes", @@ -2834,7 +2832,6 @@ dependencies = [ "memchr", "mio", "num_cpus", - "once_cell", "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", @@ -2934,9 +2931,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "log", @@ -2947,9 +2944,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", @@ -2958,9 +2955,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", ] @@ -3004,9 +3001,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" @@ -3078,7 +3075,7 @@ checksum = "c0a635407649b66e125e4d2ffd208153210179f8c7c8b71c030aa2ad3eeb4c8f" dependencies = [ "float-cmp", "halfbrown", - "itoa 1.0.3", + "itoa 1.0.4", "ryu", ] @@ -3197,9 +3194,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.4" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf" +checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" dependencies = [ "webpki", ] diff --git a/README.md b/README.md index 2f9420a..2e867d6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # aquatic: high-performance open BitTorrent tracker -[![CargoBuildAndTest](https://github.com/greatest-ape/aquatic/actions/workflows/cargo-build-and-test.yml/badge.svg)](https://github.com/greatest-ape/aquatic/actions/workflows/cargo-build-and-test.yml) [![Test HTTP, UDP and WSS file transfer](https://github.com/greatest-ape/aquatic/actions/workflows/test-transfer.yml/badge.svg)](https://github.com/greatest-ape/aquatic/actions/workflows/test-transfer.yml) +[![CI](https://github.com/greatest-ape/aquatic/actions/workflows/ci.yml/badge.svg)](https://github.com/greatest-ape/aquatic/actions/workflows/ci.yml) High-performance open BitTorrent tracker, consisting of sub-implementations for different protocols: diff --git a/aquatic_ws/src/workers/socket.rs b/aquatic_ws/src/workers/socket.rs index 0d7f09b..5d730a1 100644 --- a/aquatic_ws/src/workers/socket.rs +++ b/aquatic_ws/src/workers/socket.rs @@ -24,7 +24,8 @@ use glommio::net::{TcpListener, TcpStream}; use glommio::task::JoinHandle; use glommio::timer::{sleep, timeout, TimerActionRepeat}; use glommio::{enclose, prelude::*}; -use hashbrown::{HashMap, HashSet}; +use hashbrown::hash_map::Entry; +use hashbrown::HashMap; use slab::Slab; use crate::config::Config; @@ -45,8 +46,7 @@ struct ConnectionReference { out_message_sender: Rc>, /// Updated after sending message to peer valid_until: ValidUntil, - peer_id: Option, - announced_info_hashes: HashSet, + announced_info_hashes: HashMap, ip_version: IpVersion, } @@ -145,7 +145,6 @@ pub async fn run_socket_worker( server_start_instant, config.cleaning.max_connection_idle, ), - peer_id: None, announced_info_hashes: Default::default(), ip_version, }); @@ -180,26 +179,24 @@ pub async fn run_socket_worker( // Tell swarm workers to remove peer if let Some(reference) = opt_reference { - if let Some(peer_id) = reference.peer_id { - for info_hash in reference.announced_info_hashes { - let message = SwarmControlMessage::ConnectionClosed { - info_hash, - peer_id, - ip_version: reference.ip_version, - }; + for (info_hash, peer_id) in reference.announced_info_hashes { + let message = SwarmControlMessage::ConnectionClosed { + info_hash, + peer_id, + ip_version: reference.ip_version, + }; - let consumer_index = - calculate_in_message_consumer_index(&config, info_hash); + let consumer_index = + calculate_in_message_consumer_index(&config, info_hash); - // Only fails when receiver is closed - control_message_senders - .send_to( - consumer_index, - message - ) - .await - .unwrap(); - } + // Only fails when receiver is closed + control_message_senders + .send_to( + consumer_index, + message + ) + .await + .unwrap(); } } }), tq_regular) @@ -499,26 +496,31 @@ impl ConnectionReader { })?; // Store peer id / check if stored peer id matches - match &mut connection_reference.peer_id { - Some(peer_id) if *peer_id != announce_request.peer_id => { - self.send_error_response( - "Only one peer id can be used per connection".into(), - Some(ErrorResponseAction::Announce), - Some(info_hash), - ) - .await?; - return Err(anyhow::anyhow!("Peer used more than one PeerId")); + match connection_reference + .announced_info_hashes + .entry(announce_request.info_hash) + { + Entry::Occupied(entry) => { + if *entry.get() != announce_request.peer_id { + // Drop Rc borrow before awaiting + drop(connection_slab); + + self.send_error_response( + "Only one peer id can be used per torrent".into(), + Some(ErrorResponseAction::Announce), + Some(info_hash), + ) + .await?; + + return Err(anyhow::anyhow!( + "Peer used more than one PeerId for a single torrent" + )); + } } - Some(_) => (), - opt_peer_id @ None => { - *opt_peer_id = Some(announce_request.peer_id); + Entry::Vacant(entry) => { + entry.insert(announce_request.peer_id); } } - - // Remember info hash for later - connection_reference - .announced_info_hashes - .insert(announce_request.info_hash); } let in_message = InMessage::AnnounceRequest(announce_request);