diff --git a/.github/actions/nss/action.yml b/.github/actions/nss/action.yml index 55d75bf007..1bca72d3d2 100644 --- a/.github/actions/nss/action.yml +++ b/.github/actions/nss/action.yml @@ -87,14 +87,14 @@ runs: - name: Checkout NSS if: env.USE_SYSTEM_NSS == '0' - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: repository: nss-dev/nss path: nss - name: Checkout NSPR if: env.USE_SYSTEM_NSS == '0' - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: repository: nss-dev/nspr path: nspr @@ -111,7 +111,7 @@ runs: - name: Cache NSS id: cache if: env.USE_SYSTEM_NSS == '0' && runner.environment == 'github-hosted' - uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: path: dist key: nss-${{ runner.os }}-${{ inputs.type }}-${{ env.NSS_HEAD }}-${{ env.NSPR_HEAD }} @@ -120,7 +120,7 @@ runs: if: env.USE_SYSTEM_NSS == '0' shell: bash run: | - if [ "${{ runner.environment }}" != "github-hosted" ] || [ "${{ steps.cache.outputs.cache-hit }}" == "false" ]; then + if [ "${{ runner.environment }}" != "github-hosted" ] || [ "${{ steps.cache.outputs.cache-hit }}" == "" ]; then echo "Building NSS from source" echo "BUILD_NSS=1" >> "$GITHUB_ENV" else diff --git a/.github/actions/pr-comment-data-export/action.yml b/.github/actions/pr-comment-data-export/action.yml index be6f0182be..77bfd610ee 100644 --- a/.github/actions/pr-comment-data-export/action.yml +++ b/.github/actions/pr-comment-data-export/action.yml @@ -31,7 +31,7 @@ runs: echo "${{ inputs.log-url }}" > comment-data/log-url fi - if: github.event_name == 'pull_request' - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: ${{ inputs.name }} path: comment-data diff --git a/.github/actions/quic-interop-runner/action.yml b/.github/actions/quic-interop-runner/action.yml index 77278801fd..490ccd152e 100644 --- a/.github/actions/quic-interop-runner/action.yml +++ b/.github/actions/quic-interop-runner/action.yml @@ -24,7 +24,7 @@ runs: using: "composite" steps: - name: Checkout quic-interop/quic-interop-runner repository - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: repository: 'quic-interop/quic-interop-runner' path: 'quic-interop-runner' @@ -94,7 +94,7 @@ runs: exit $FAILED shell: bash - - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 if: always() id: upload-logs with: @@ -110,7 +110,7 @@ runs: mv result.json.tmp result.json shell: bash - - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 if: always() with: name: '${{ inputs.client }} vs. ${{ inputs.server }} results' diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index 1aeb9427d8..f23e252ca5 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -22,7 +22,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Download actionlint id: get_actionlint run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index a546a02645..fcece8bd42 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -27,10 +27,10 @@ jobs: steps: - name: Checkout neqo - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Checkout msquic - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: repository: microsoft/msquic ref: main @@ -70,7 +70,7 @@ jobs: - name: Download cached main-branch results id: criterion-cache - uses: actions/cache/restore@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 + uses: actions/cache/restore@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: path: ./target/criterion key: criterion-${{ runner.name }}-${{ github.sha }} @@ -231,14 +231,14 @@ jobs: - name: Cache main-branch results if: github.ref == 'refs/heads/main' - uses: actions/cache/save@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 + uses: actions/cache/save@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: path: ./target/criterion key: criterion-${{ runner.name }}-${{ github.sha }} - name: Export perf data id: export - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: ${{ github.event.repository.name }}-${{ github.sha }} path: | diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index d39d232892..1b9c2e8200 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -36,7 +36,7 @@ jobs: outputs: toolchains: ${{ steps.toolchains.outputs.toolchains }} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: sparse-checkout: Cargo.toml - id: toolchains @@ -61,7 +61,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - uses: ./.github/actions/rust with: @@ -122,7 +122,7 @@ jobs: - name: Save simulation seeds artifact if: env.DUMP_SIMULATION_SEEDS - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: simulation-seeds-${{ matrix.os }}-${{ matrix.rust-toolchain }}-${{ matrix.type }} path: ${{ env.DUMP_SIMULATION_SEEDS }} diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index c35fac4ea5..6bd7e3ccb3 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -31,7 +31,7 @@ jobs: shell: bash steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - uses: ./.github/actions/rust with: components: clippy diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index d3487b9655..38bb2dad1e 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -24,7 +24,7 @@ jobs: dependency-review: runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4 with: base-ref: ${{ github.event.pull_request.base.sha || 'main' }} diff --git a/.github/workflows/firefox.yml b/.github/workflows/firefox.yml index 8fd544b5f9..90cc485b93 100644 --- a/.github/workflows/firefox.yml +++ b/.github/workflows/firefox.yml @@ -35,7 +35,7 @@ jobs: steps: - name: Check out Neqo - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Maximize build space if: runner.os == 'Linux' @@ -54,7 +54,7 @@ jobs: df -h - name: Check out Firefox - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: repository: mozilla/gecko-dev path: mozilla-unified @@ -123,7 +123,7 @@ jobs: - name: Export binary id: upload - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: ${{ runner.os }}-${{ env.FIREFOX }}-${{ matrix.type }}.tgz path: ${{ env.FIREFOX }}.tar @@ -132,7 +132,7 @@ jobs: - run: echo "${{ steps.upload.outputs.artifact-url }}" >> artifact - name: Export artifact URL - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: artifact-${{ runner.os }}-${{ env.FIREFOX }}-${{ matrix.type }} path: artifact @@ -144,7 +144,7 @@ jobs: needs: firefox runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: diff --git a/.github/workflows/fuzz-bench.yml b/.github/workflows/fuzz-bench.yml index 4938fbe1c0..0749035b0f 100644 --- a/.github/workflows/fuzz-bench.yml +++ b/.github/workflows/fuzz-bench.yml @@ -20,7 +20,7 @@ jobs: fuzz-bench: runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - uses: ./.github/actions/rust with: version: nightly diff --git a/.github/workflows/machete.yml b/.github/workflows/machete.yml index 054f554c22..f72d9215e6 100644 --- a/.github/workflows/machete.yml +++ b/.github/workflows/machete.yml @@ -20,7 +20,7 @@ jobs: machete: runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install Rust uses: ./.github/actions/rust diff --git a/.github/workflows/mutants.yml b/.github/workflows/mutants.yml index e9fe3a9aff..bd318c1b75 100644 --- a/.github/workflows/mutants.yml +++ b/.github/workflows/mutants.yml @@ -20,7 +20,7 @@ jobs: if: github.event_name == 'pull_request' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 0 @@ -61,7 +61,7 @@ jobs: echo '```' } > "$GITHUB_STEP_SUMMARY" - - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: mutants.out path: mutants.out diff --git a/.github/workflows/pr-comment.yml b/.github/workflows/pr-comment.yml index b025325648..0ce5da9dc4 100644 --- a/.github/workflows/pr-comment.yml +++ b/.github/workflows/pr-comment.yml @@ -24,7 +24,7 @@ jobs: github.event.workflow_run.event == 'pull_request' && (github.event.workflow_run.conclusion == 'success' || github.event.workflow_run.conclusion == 'failure') steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - uses: ./.github/actions/pr-comment with: name: ${{ github.event.workflow_run.name }} diff --git a/.github/workflows/qns.yml b/.github/workflows/qns.yml index a918010c10..294382bea8 100644 --- a/.github/workflows/qns.yml +++ b/.github/workflows/qns.yml @@ -74,7 +74,7 @@ jobs: platforms: 'linux/amd64' outputs: type=docker,dest=/tmp/${{ env.LATEST }}.tar - - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: '${{ env.LATEST }} Docker image' path: /tmp/${{ env.LATEST }}.tar @@ -142,7 +142,7 @@ jobs: echo "client=$(echo "$PAIR" | cut -d% -f1)" >> "$GITHUB_OUTPUT" echo "server=$(echo "$PAIR" | cut -d% -f2)" >> "$GITHUB_OUTPUT" - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 # TODO: Replace once https://github.com/quic-interop/quic-interop-runner/pull/356 is merged. - uses: ./.github/actions/quic-interop-runner @@ -158,7 +158,7 @@ jobs: runs-on: ubuntu-latest if: always() steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: pattern: '*results' diff --git a/.github/workflows/rustfmt.yml b/.github/workflows/rustfmt.yml index d80900b59c..fd7710fea6 100644 --- a/.github/workflows/rustfmt.yml +++ b/.github/workflows/rustfmt.yml @@ -23,7 +23,7 @@ jobs: format: runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - uses: ./.github/actions/rust with: version: nightly diff --git a/.github/workflows/sanitize.yml b/.github/workflows/sanitize.yml index 71ca8ad2f2..4d6bef060a 100644 --- a/.github/workflows/sanitize.yml +++ b/.github/workflows/sanitize.yml @@ -40,7 +40,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - uses: ./.github/actions/rust with: version: nightly @@ -80,7 +80,7 @@ jobs: - name: Save simulation seeds artifact if: env.DUMP_SIMULATION_SEEDS - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: simulation-seeds-${{ matrix.os }}-sanitizer-${{ matrix.sanitizer }} path: ${{ env.DUMP_SIMULATION_SEEDS }} diff --git a/neqo-bin/src/client/mod.rs b/neqo-bin/src/client/mod.rs index 8bfac59703..ad5407e2cc 100644 --- a/neqo-bin/src/client/mod.rs +++ b/neqo-bin/src/client/mod.rs @@ -457,7 +457,7 @@ impl<'a, H: Handler> Runner<'a, H> { async fn process_multiple_input(&mut self) -> Res<()> { loop { - let dgrams = self.socket.recv(&self.local_addr)?; + let dgrams = self.socket.recv(self.local_addr)?; if dgrams.is_empty() { break; } diff --git a/neqo-bin/src/server/mod.rs b/neqo-bin/src/server/mod.rs index abf614f1f8..a6104daa5f 100644 --- a/neqo-bin/src/server/mod.rs +++ b/neqo-bin/src/server/mod.rs @@ -289,7 +289,7 @@ impl ServerRunner { match self.ready().await? { Ready::Socket(inx) => loop { let (host, socket) = self.sockets.get_mut(inx).unwrap(); - let dgrams = socket.recv(host)?; + let dgrams = socket.recv(*host)?; if dgrams.is_empty() { break; } diff --git a/neqo-bin/src/udp.rs b/neqo-bin/src/udp.rs index 148ff43175..bc14aadcf3 100644 --- a/neqo-bin/src/udp.rs +++ b/neqo-bin/src/udp.rs @@ -55,7 +55,7 @@ impl Socket { /// Receive a batch of [`Datagram`]s on the given [`Socket`], each set with /// the provided local address. - pub fn recv(&self, local_address: &SocketAddr) -> Result, io::Error> { + pub fn recv(&self, local_address: SocketAddr) -> Result, io::Error> { self.inner .try_io(tokio::io::Interest::READABLE, || { neqo_udp::recv_inner(local_address, &self.state, &self.inner) diff --git a/neqo-transport/src/connection/tests/ackrate.rs b/neqo-transport/src/connection/tests/ackrate.rs index f0a1d17cd9..c39b01895b 100644 --- a/neqo-transport/src/connection/tests/ackrate.rs +++ b/neqo-transport/src/connection/tests/ackrate.rs @@ -13,7 +13,7 @@ use super::{ ack_bytes, connect_rtt_idle, default_client, default_server, fill_cwnd, increase_cwnd, induce_persistent_congestion, new_client, new_server, send_something, DEFAULT_RTT, }; -use crate::stream_id::StreamType; +use crate::{connection::tests::assert_path_challenge_min_len, stream_id::StreamType}; /// With the default RTT here (100ms) and default ratio (4), endpoints won't send /// `ACK_FREQUENCY` as the ACK delay isn't different enough from the default. @@ -169,6 +169,7 @@ fn migrate_ack_delay() { let client1 = send_something(&mut client, now); assertions::assert_v4_path(&client1, true); // Contains PATH_CHALLENGE. + assert_path_challenge_min_len(&client, &client1, now); let client2 = send_something(&mut client, now); assertions::assert_v4_path(&client2, false); // Doesn't. Is dropped. now += DEFAULT_RTT / 2; diff --git a/neqo-transport/src/connection/tests/ecn.rs b/neqo-transport/src/connection/tests/ecn.rs index ca99282cf5..089c7e45fd 100644 --- a/neqo-transport/src/connection/tests/ecn.rs +++ b/neqo-transport/src/connection/tests/ecn.rs @@ -14,9 +14,10 @@ use test_fixture::{ use crate::{ connection::tests::{ - connect_force_idle, connect_force_idle_with_modifier, default_client, default_server, - handshake_with_modifier, migration::get_cid, new_client, new_server, send_and_receive, - send_something, send_something_with_modifier, send_with_modifier_and_receive, DEFAULT_RTT, + assert_path_challenge_min_len, connect_force_idle, connect_force_idle_with_modifier, + default_client, default_server, handshake_with_modifier, migration::get_cid, new_client, + new_server, send_and_receive, send_something, send_something_with_modifier, + send_with_modifier_and_receive, DEFAULT_RTT, }, ecn::ECN_TEST_COUNT, path::MAX_PATH_PROBES, @@ -120,6 +121,7 @@ fn migration_delay_to_ecn_blackhole() { // This should be a PATH_CHALLENGE. probes += 1; assert_eq!(client.stats().frame_tx.path_challenge, probes); + assert_path_challenge_min_len(&client, &d, now); if probes <= MAX_PATH_PROBES { // The first probes should be sent with ECN. assert_ecn_enabled(d.tos()); @@ -247,6 +249,7 @@ pub fn migration_with_modifiers( let probe = new_path_modifier(client.process_output(now).dgram().unwrap()); if let Some(probe) = probe { assert_v4_path(&probe, true); // Contains PATH_CHALLENGE. + assert_path_challenge_min_len(&client, &probe, now); assert_eq!(client.stats().frame_tx.path_challenge, 1); let probe_cid = ConnectionId::from(get_cid(&probe)); @@ -254,6 +257,7 @@ pub fn migration_with_modifiers( assert_v4_path(&resp, true); assert_eq!(server.stats().frame_tx.path_response, 1); assert_eq!(server.stats().frame_tx.path_challenge, 1); + assert_path_challenge_min_len(&server, &resp, now); // Data continues to be exchanged on the old path. let client_data = send_something_with_modifier(&mut client, now, orig_path_modifier); @@ -287,6 +291,10 @@ pub fn migration_with_modifiers( server.stats().frame_tx.path_challenge, if migrated { 2 } else { 0 } ); + if migrated { + assert_path_challenge_min_len(&server, &probe_old_server, now); + } + assert_eq!( server.stats().frame_tx.stream, if migrated { stream_before } else { 1 } diff --git a/neqo-transport/src/connection/tests/migration.rs b/neqo-transport/src/connection/tests/migration.rs index 0c978cc225..0b8e7623fa 100644 --- a/neqo-transport/src/connection/tests/migration.rs +++ b/neqo-transport/src/connection/tests/migration.rs @@ -25,7 +25,7 @@ use super::{ }; use crate::{ cid::LOCAL_ACTIVE_CID_LIMIT, - connection::tests::{send_something_paced, send_with_extra}, + connection::tests::{assert_path_challenge_min_len, send_something_paced, send_with_extra}, frame::FRAME_TYPE_NEW_CONNECTION_ID, packet::PacketBuilder, path::MAX_PATH_PROBES, @@ -255,10 +255,12 @@ fn path_forwarding_attack() { // The server now probes the new (primary) path. let new_probe = server.process_output(now).dgram().unwrap(); assert_eq!(server.stats().frame_tx.path_challenge, 1); + assert_path_challenge_min_len(&server, &new_probe, now); assert_v4_path(&new_probe, false); // Can't be padded. // The server also probes the old path. let old_probe = server.process_output(now).dgram().unwrap(); + assert_path_challenge_min_len(&server, &old_probe, now); assert_eq!(server.stats().frame_tx.path_challenge, 2); assert_v6_path(&old_probe, true); @@ -293,6 +295,7 @@ fn path_forwarding_attack() { let server_data1 = server.process(Some(&new_resp), now).dgram().unwrap(); assert_v4_path(&server_data1, true); assert_eq!(server.stats().frame_tx.path_challenge, 3); + assert_path_challenge_min_len(&server, &server_data1, now); // The client responds to this probe on the new path. client.process_input(&server_data1, now); @@ -332,6 +335,8 @@ fn migrate_immediate() { let client1 = send_something(&mut client, now); assert_v4_path(&client1, true); // Contains PATH_CHALLENGE. + assert_path_challenge_min_len(&client, &client1, now); + let client2 = send_something(&mut client, now); assert_v4_path(&client2, false); // Doesn't. @@ -389,6 +394,7 @@ fn migrate_immediate_fail() { let probe = client.process_output(now).dgram().unwrap(); assert_v4_path(&probe, true); // Contains PATH_CHALLENGE. + assert_path_challenge_min_len(&client, &probe, now); // -1 because first PATH_CHALLENGE already sent above for _ in 0..MAX_PATH_PROBES * 2 - 1 { @@ -399,6 +405,7 @@ fn migrate_immediate_fail() { let before = client.stats().frame_tx; let probe = client.process_output(now).dgram().unwrap(); assert_v4_path(&probe, true); // Contains PATH_CHALLENGE. + assert_path_challenge_min_len(&client, &probe, now); let after = client.stats().frame_tx; assert_eq!(after.path_challenge, before.path_challenge + 1); assert_eq!(after.padding, before.padding + 1); @@ -406,8 +413,9 @@ fn migrate_immediate_fail() { // This might be a PTO, which will result in sending a probe. if let Some(probe) = client.process_output(now).dgram() { - assert_v4_path(&probe, false); // Contains PATH_CHALLENGE. + assert_v4_path(&probe, false); // Contains PING. let after = client.stats().frame_tx; + assert_eq!(after.path_challenge, before.path_challenge + 1); assert_eq!(after.ping, before.ping + 1); assert_eq!(after.all(), before.all() + 3); } @@ -439,6 +447,7 @@ fn migrate_same() { let probe = client.process_output(now).dgram().unwrap(); assert_v6_path(&probe, true); // Contains PATH_CHALLENGE. assert_eq!(client.stats().frame_tx.path_challenge, 1); + assert_path_challenge_min_len(&client, &probe, now); let resp = server.process(Some(&probe), now).dgram().unwrap(); assert_v6_path(&resp, true); @@ -465,6 +474,7 @@ fn migrate_same_fail() { let probe = client.process_output(now).dgram().unwrap(); assert_v6_path(&probe, true); // Contains PATH_CHALLENGE. + assert_path_challenge_min_len(&client, &probe, now); // -1 because first PATH_CHALLENGE already sent above for _ in 0..MAX_PATH_PROBES * 2 - 1 { @@ -475,6 +485,7 @@ fn migrate_same_fail() { let before = client.stats().frame_tx; let probe = client.process_output(now).dgram().unwrap(); assert_v6_path(&probe, true); // Contains PATH_CHALLENGE. + assert_path_challenge_min_len(&client, &probe, now); let after = client.stats().frame_tx; assert_eq!(after.path_challenge, before.path_challenge + 1); assert_eq!(after.padding, before.padding + 1); @@ -482,8 +493,9 @@ fn migrate_same_fail() { // This might be a PTO, which will result in sending a probe. if let Some(probe) = client.process_output(now).dgram() { - assert_v6_path(&probe, false); // Contains PATH_CHALLENGE. + assert_v6_path(&probe, false); // Contains PING. let after = client.stats().frame_tx; + assert_eq!(after.path_challenge, before.path_challenge + 1); assert_eq!(after.ping, before.ping + 1); assert_eq!(after.all(), before.all() + 3); } @@ -521,11 +533,13 @@ fn migration(mut client: Connection) { let probe = client.process_output(now).dgram().unwrap(); assert_v4_path(&probe, true); // Contains PATH_CHALLENGE. + assert_path_challenge_min_len(&client, &probe, now); assert_eq!(client.stats().frame_tx.path_challenge, 1); let probe_cid = ConnectionId::from(get_cid(&probe)); let resp = server.process(Some(&probe), now).dgram().unwrap(); assert_v4_path(&resp, true); + assert_path_challenge_min_len(&server, &resp, now); assert_eq!(server.stats().frame_tx.path_response, 1); assert_eq!(server.stats().frame_tx.path_challenge, 1); @@ -552,6 +566,7 @@ fn migration(mut client: Connection) { let probe_old_server = send_something(&mut server, now); // This is just the double-check probe; no STREAM frames. assert_v6_path(&probe_old_server, true); + assert_path_challenge_min_len(&server, &probe_old_server, now); assert_eq!(server.stats().frame_tx.path_challenge, 2); assert_eq!(server.stats().frame_tx.stream, stream_before); @@ -668,6 +683,7 @@ fn preferred_address(hs_client: SocketAddr, hs_server: SocketAddr, preferred: So let probe = client.process(dgram.as_ref(), now()).dgram().unwrap(); assert_toward_spa(&probe, true); assert_eq!(client.stats().frame_tx.path_challenge, 1); + assert_path_challenge_min_len(&client, &probe, now()); assert_ne!(client.process_output(now()).callback(), Duration::new(0, 0)); // Data continues on the main path for the client. @@ -678,6 +694,7 @@ fn preferred_address(hs_client: SocketAddr, hs_server: SocketAddr, preferred: So let resp = server.process(Some(&probe), now()).dgram().unwrap(); assert_from_spa(&resp, true); assert_eq!(server.stats().frame_tx.path_challenge, 1); + assert_path_challenge_min_len(&server, &resp, now()); assert_eq!(server.stats().frame_tx.path_response, 1); // Data continues on the main path for the server. @@ -697,6 +714,7 @@ fn preferred_address(hs_client: SocketAddr, hs_server: SocketAddr, preferred: So let probe = server.process(Some(&data), now()).dgram().unwrap(); assert_orig_path(&probe, true); assert_eq!(server.stats().frame_tx.path_challenge, 2); + assert_path_challenge_min_len(&server, &probe, now()); // But data now goes on the new path. let data = send_something(&mut server, now()); @@ -1007,6 +1025,7 @@ fn retire_prior_to_migration_failure() { let probe = client.process_output(now()).dgram().unwrap(); assert_v4_path(&probe, true); assert_eq!(client.stats().frame_tx.path_challenge, 1); + assert_path_challenge_min_len(&client, &probe, now()); let probe_cid = ConnectionId::from(get_cid(&probe)); assert_ne!(original_cid, probe_cid); @@ -1018,6 +1037,7 @@ fn retire_prior_to_migration_failure() { assert_v4_path(&resp, true); assert_eq!(server.stats().frame_tx.path_response, 1); assert_eq!(server.stats().frame_tx.path_challenge, 1); + assert_path_challenge_min_len(&server, &resp, now()); // Have the client receive the NEW_CONNECTION_ID with Retire Prior To. client.process_input(&retire_all, now()); @@ -1060,6 +1080,7 @@ fn retire_prior_to_migration_success() { let probe = client.process_output(now()).dgram().unwrap(); assert_v4_path(&probe, true); assert_eq!(client.stats().frame_tx.path_challenge, 1); + assert_path_challenge_min_len(&client, &probe, now()); let probe_cid = ConnectionId::from(get_cid(&probe)); assert_ne!(original_cid, probe_cid); @@ -1071,6 +1092,7 @@ fn retire_prior_to_migration_success() { assert_v4_path(&resp, true); assert_eq!(server.stats().frame_tx.path_response, 1); assert_eq!(server.stats().frame_tx.path_challenge, 1); + assert_path_challenge_min_len(&server, &resp, now()); // Have the client receive the NEW_CONNECTION_ID with Retire Prior To second. // As this occurs in a very specific order, migration succeeds. diff --git a/neqo-transport/src/connection/tests/mod.rs b/neqo-transport/src/connection/tests/mod.rs index c2cf4db391..7aaced917a 100644 --- a/neqo-transport/src/connection/tests/mod.rs +++ b/neqo-transport/src/connection/tests/mod.rs @@ -30,7 +30,7 @@ use crate::{ stats::{FrameStats, Stats, MAX_PTO_COUNTS}, tparams::{DISABLE_MIGRATION, GREASE_QUIC_BIT}, ConnectionIdDecoder, ConnectionIdGenerator, ConnectionParameters, Error, StreamId, StreamType, - Version, + Version, MIN_INITIAL_PACKET_SIZE, }; // All the tests. @@ -669,6 +669,27 @@ fn assert_default_stats(stats: &Stats) { assert_eq!(stats.frame_tx, dflt_frames); } +fn assert_path_challenge_min_len(c: &Connection, d: &Datagram, now: Instant) { + let path = c.paths.find_path( + d.source(), + d.destination(), + c.conn_params.get_cc_algorithm(), + c.conn_params.pacing_enabled(), + now, + ); + if path.borrow().amplification_limit() < path.borrow().plpmtu() { + // If the amplification limit is less than the PLPMTU, then the path + // challenge will not have been padded. + return; + } + assert!( + d.len() >= MIN_INITIAL_PACKET_SIZE, + "{} < {}", + d.len(), + MIN_INITIAL_PACKET_SIZE + ); +} + #[test] fn create_client() { let client = default_client(); diff --git a/neqo-udp/src/lib.rs b/neqo-udp/src/lib.rs index 5f1fb3dbe6..dea2b26721 100644 --- a/neqo-udp/src/lib.rs +++ b/neqo-udp/src/lib.rs @@ -58,7 +58,7 @@ use std::os::fd::AsFd as SocketRef; use std::os::windows::io::AsSocket as SocketRef; pub fn recv_inner( - local_address: &SocketAddr, + local_address: SocketAddr, state: &UdpSocketState, socket: impl SocketRef, ) -> Result, io::Error> { @@ -99,7 +99,7 @@ pub fn recv_inner( ); Datagram::new( meta.addr, - *local_address, + local_address, meta.ecn.map(|n| IpTos::from(n as u8)).unwrap_or_default(), d, ) @@ -138,7 +138,7 @@ impl Socket { /// Receive a batch of [`Datagram`]s on the given [`Socket`], each /// set with the provided local address. - pub fn recv(&self, local_address: &SocketAddr) -> Result, io::Error> { + pub fn recv(&self, local_address: SocketAddr) -> Result, io::Error> { recv_inner(local_address, &self.state, &self.inner) } } @@ -170,7 +170,7 @@ mod tests { ); sender.send(&datagram)?; - let res = receiver.recv(&receiver_addr); + let res = receiver.recv(receiver_addr); assert_eq!(res.unwrap_err().kind(), std::io::ErrorKind::WouldBlock); Ok(()) @@ -192,7 +192,7 @@ mod tests { sender.send(&datagram)?; let received_datagram = receiver - .recv(&receiver_addr) + .recv(receiver_addr) .expect("receive to succeed") .into_iter() .next() @@ -238,7 +238,7 @@ mod tests { let mut num_received = 0; while num_received < max_gso_segments { receiver - .recv(&receiver_addr) + .recv(receiver_addr) .expect("receive to succeed") .into_iter() .for_each(|d| { diff --git a/qns/Dockerfile b/qns/Dockerfile index 97043d6366..60eeaa8e66 100644 --- a/qns/Dockerfile +++ b/qns/Dockerfile @@ -1,4 +1,4 @@ -FROM lukemathwalker/cargo-chef@sha256:f50231b8a01af14eda124040535193d60d9c86d413b02553d2809e5d881b9a90 AS chef +FROM lukemathwalker/cargo-chef@sha256:acfab68709ad444b7cc9106d7e90a2bce4a77ed63889712fb6686e0e6ecfe8aa AS chef WORKDIR /app @@ -33,7 +33,7 @@ RUN cargo chef cook --release --recipe-path recipe.json ADD . /neqo RUN set -eux; \ cd /neqo; \ - cargo build --release --bin neqo-client --bin neqo-server + CARGO_PROFILE_RELEASE_DEBUG=true cargo build --release --bin neqo-client --bin neqo-server # Copy only binaries to the final image to keep it small.