Merge pull request #4 from greatest-ape/ws-file-transfer-ci

Add CI for WebTorrent file transfer, upgrade dependencies
This commit is contained in:
Joakim Frostegård 2021-08-17 12:36:03 +02:00 committed by GitHub
commit c2e47d6fab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 147 additions and 52 deletions

View file

@ -1,5 +1,5 @@
# Container image that runs your code
FROM rust:latest
FROM rust:bullseye
# Copies your code file from your action repository to the filesystem path `/` of the container
COPY entrypoint.sh /entrypoint.sh

View file

@ -1,5 +1,5 @@
name: 'test-transfer-http-udp'
description: 'test aquatic http and udp file transfer'
name: 'test-transfer'
description: 'test aquatic file transfer'
outputs:
http_ipv4:
description: 'HTTP IPv4 status'
@ -7,6 +7,8 @@ outputs:
description: 'HTTP IPv4 over TLS status'
udp_ipv4:
description: 'UDP IPv4 status'
wss_ipv4:
description: 'WSS IPv4 status'
runs:
using: 'docker'
image: 'Dockerfile'

View file

@ -1,10 +1,15 @@
#!/bin/bash
#
# Test that file transfers work with aquatic_http (with and without TLS)
# and aquatic_udp.
# aquatic_udp and experimentally aquatic_ws (with TLS).
#
# IPv6 is unfortunately disabled by default in Docker
# (see sysctl net.ipv6.conf.lo.disable_ipv6)
#
# When testing locally, use:
# 1. docker build -t aquatic ./path/to/Dockerfile
# 2. docker run aquatic
# 3. On failure, run `docker rmi aquatic -f` and go back to step 1
set -e
@ -17,9 +22,14 @@ else
fi
$SUDO apt-get update
$SUDO apt-get install -y cmake libssl-dev screen rtorrent mktorrent ssl-cert ca-certificates
$SUDO apt-get install -y cmake libssl-dev screen rtorrent mktorrent ssl-cert ca-certificates curl golang
rtorrent -h
git clone https://github.com/anacrolix/torrent.git gotorrent
cd gotorrent
git checkout 16176b762e4a840fc5dfe3b1dfd2d6fa853b68d7
go build -o $HOME/gotorrent ./cmd/torrent
cd ..
file $HOME/gotorrent
# Clone repository if necessary, go to repository directory
@ -70,6 +80,16 @@ echo "[network]
address = '127.0.0.1:3000'" > udp.toml
./target/debug/aquatic udp -c udp.toml > "$HOME/udp.log" 2>&1 &
echo "log_level = 'trace'
[network]
address = '127.0.0.1:3002'
use_tls = true
tls_pkcs12_path = './identity.pfx'
tls_pkcs12_password = 'p'
" > ws.toml
./target/debug/aquatic ws -c ws.toml > "$HOME/wss.log" 2>&1 &
# Setup directories
cd "$HOME"
@ -83,25 +103,37 @@ mkdir torrents
echo "http-test-ipv4" > seed/http-test-ipv4
echo "tls-test-ipv4" > seed/tls-test-ipv4
echo "udp-test-ipv4" > seed/udp-test-ipv4
echo "wss-test-ipv4" > seed/wss-test-ipv4
mktorrent -p -o "torrents/http-ipv4.torrent" -a "http://127.0.0.1:3000/announce" "seed/http-test-ipv4"
mktorrent -p -o "torrents/tls-ipv4.torrent" -a "https://example.com:3001/announce" "seed/tls-test-ipv4"
mktorrent -p -o "torrents/udp-ipv4.torrent" -a "udp://127.0.0.1:3000" "seed/udp-test-ipv4"
mktorrent -p -o "torrents/wss-ipv4.torrent" -a "wss://example.com:3002" "seed/wss-test-ipv4"
cp -r torrents torrents-seed
cp -r torrents torrents-leech
# Start seeding client
# Setup wss seeding client
echo "Starting seeding wss client"
cd seed
GOPPROF=http GODEBUG=x509ignoreCN=0 $HOME/gotorrent download --dht=false --tcppeers=false --utppeers=false --pex=false --stats --seed ../torrents/wss-ipv4.torrent > "$HOME/wss-seed.log" 2>&1 &
cd ..
# Start seeding rtorrent client
echo "directory.default.set = $HOME/seed
schedule2 = watch_directory,5,5,load.start=$HOME/torrents-seed/*.torrent" > ~/.rtorrent.rc
echo "Starting seeding client"
echo "Starting seeding rtorrent client"
screen -dmS rtorrent-seed rtorrent
sleep 10 # Give seeding rtorrent time to load its config file
# Give seeding clients time to load config files etc
# Start leeching client
echo "Waiting for a while"
sleep 30
# Start leeching clients
echo "directory.default.set = $HOME/leech
schedule2 = watch_directory,5,5,load.start=$HOME/torrents-leech/*.torrent" > ~/.rtorrent.rc
@ -109,35 +141,58 @@ schedule2 = watch_directory,5,5,load.start=$HOME/torrents-leech/*.torrent" > ~/.
echo "Starting leeching client.."
screen -dmS rtorrent-leech rtorrent
echo "Starting leeching wss client"
cd leech
GOPPROF=http GODEBUG=x509ignoreCN=0 $HOME/gotorrent download --dht=false --tcppeers=false --utppeers=false --pex=false --stats --addr ":43000" ../torrents/wss-ipv4.torrent > "$HOME/wss-leech.log" 2>&1 &
cd ..
# Check for completion
HTTP_IPv4="Failed"
TLS_IPv4="Failed"
UDP_IPv4="Failed"
WSS_IPv4="Failed"
i="0"
echo "Watching for finished files.."
while [ $i -lt 300 ]
while [ $i -lt 60 ]
do
if test -f "leech/http-test-ipv4"; then
if grep -q "http-test-ipv4" "leech/http-test-ipv4"; then
HTTP_IPv4="Ok"
if [ "$HTTP_IPv4" != "Ok" ]; then
HTTP_IPv4="Ok"
echo "HTTP_IPv4 is Ok"
fi
fi
fi
if test -f "leech/tls-test-ipv4"; then
if grep -q "tls-test-ipv4" "leech/tls-test-ipv4"; then
TLS_IPv4="Ok"
if [ "$TLS_IPv4" != "Ok" ]; then
TLS_IPv4="Ok"
echo "TLS_IPv4 is Ok"
fi
fi
fi
if test -f "leech/udp-test-ipv4"; then
if grep -q "udp-test-ipv4" "leech/udp-test-ipv4"; then
UDP_IPv4="Ok"
if [ "$UDP_IPv4" != "Ok" ]; then
UDP_IPv4="Ok"
echo "UDP_IPv4 is Ok"
fi
fi
fi
if test -f "leech/wss-test-ipv4"; then
if grep -q "wss-test-ipv4" "leech/wss-test-ipv4"; then
if [ "$WSS_IPv4" != "Ok" ]; then
WSS_IPv4="Ok"
echo "WSS_IPv4 is Ok"
fi
fi
fi
if [ "$HTTP_IPv4" = "Ok" ] && [ "$TLS_IPv4" = "Ok" ] && [ "$UDP_IPv4" = "Ok" ]; then
if [ "$HTTP_IPv4" = "Ok" ] && [ "$TLS_IPv4" = "Ok" ] && [ "$UDP_IPv4" = "Ok" ] && [ "$WSS_IPv4" = "Ok" ]; then
break
fi
@ -151,25 +206,51 @@ echo "Waited for $i seconds"
echo "::set-output name=http_ipv4::$HTTP_IPv4"
echo "::set-output name=http_tls_ipv4::$TLS_IPv4"
echo "::set-output name=udp_ipv4::$UDP_IPv4"
echo "::set-output name=wss_ipv4::$WSS_IPv4"
echo ""
echo "# --- HTTP log --- #"
cat "http.log"
sleep 1
echo ""
echo "# --- HTTP over TLS log --- #"
cat "tls.log"
sleep 1
echo ""
echo "# --- UDP log --- #"
cat "udp.log"
sleep 1
echo ""
echo "# --- WSS tracker log --- #"
cat "wss.log"
sleep 1
echo ""
echo "# --- WSS seed log --- #"
cat "wss-seed.log"
sleep 1
echo ""
echo "# --- WSS leech log --- #"
cat "wss-leech.log"
sleep 1
echo ""
echo "# --- Test results --- #"
echo "HTTP (IPv4): $HTTP_IPv4"
echo "HTTP over TLS (IPv4): $TLS_IPv4"
echo "UDP (IPv4): $UDP_IPv4"
echo "WSS (IPv4): $WSS_IPv4"
if [ "$HTTP_IPv4" != "Ok" ] || [ "$TLS_IPv4" != "Ok" ] || [ "$UDP_IPv4" != "Ok" ]; then
if [ "$HTTP_IPv4" != "Ok" ] || [ "$TLS_IPv4" != "Ok" ] || [ "$UDP_IPv4" != "Ok" ] || [ "$WSS_IPv4" != "Ok" ]; then
exit 1
fi

View file

@ -1,4 +1,4 @@
name: "Test HTTP and UDP file transfer"
name: "Test HTTP, UDP and WSS file transfer"
on:
push:
@ -9,10 +9,10 @@ on:
jobs:
test-transfer-http:
runs-on: ubuntu-latest
name: "Test BitTorrent file transfer over HTTP (with and without TLS) and UDP"
name: "Test BitTorrent file transfer over HTTP (with and without TLS), UDP and WSS"
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Test file transfers
uses: ./.github/actions/test-transfer-http-udp
id: test_transfer_udp_http
uses: ./.github/actions/test-transfer
id: test_transfer

19
Cargo.lock generated
View file

@ -337,9 +337,9 @@ dependencies = [
[[package]]
name = "bitflags"
version = "1.3.1"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2da1976d75adbe5fbc88130ecd119529cf1cc6a93ae1546d8696ee66f0d21af1"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
@ -792,15 +792,6 @@ dependencies = [
"regex",
]
[[package]]
name = "input_buffer"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413"
dependencies = [
"bytes",
]
[[package]]
name = "instant"
version = "0.1.10"
@ -1675,18 +1666,16 @@ dependencies = [
[[package]]
name = "tungstenite"
version = "0.13.0"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fe8dada8c1a3aeca77d6b51a4f1314e0f4b8e438b7b1b71e3ddaca8080e4093"
checksum = "983d40747bce878d2fb67d910dcb8bd3eca2b2358540c3cc1b98c027407a3ae3"
dependencies = [
"base64",
"byteorder",
"bytes",
"http",
"httparse",
"input_buffer",
"log",
"native-tls",
"rand",
"sha-1",
"thiserror",

View file

@ -17,10 +17,12 @@ Distributed under Apache 2.0 license (details in `LICENSE` file.)
## Technical overview of tracker design
One or more socket workers open sockets, read and parse requests from peers and
send them through channels to request workers. They in turn go through the
requests, update internal state as appropriate and generate responses, which
are sent back to the socket workers, which serialize them and send them to
peers. This design means little waiting for locks on internal state occurs,
send them through channels to request workers. The request workers go through
the requests, update shared internal tracker state as appropriate and generate
responses that are sent back to the socket workers. The responses are then
serialized and sent back to the peers.
This design means little waiting for locks on internal state occurs,
while network work can be efficiently distributed over multiple threads,
making use of SO_REUSEPORT setting.
@ -149,11 +151,7 @@ exceptions:
For information about running over TLS, please refer to the TLS subsection
of the `aquatic_http` section above.
`aquatic_ws` is experimental software. Connections are established
successfully when using `aquatic_ws_load_test`, but so far, I haven't been able
to implement CI for testing if aquatic_ws works as the tracker for a full
file transfer session between two real-world clients. One reason for this
is the general lack of high-quality WebTorrent clients.
`aquatic_ws` is experimental software.
## Load testing

View file

@ -34,7 +34,7 @@ privdrop = "0.5"
rand = { version = "0.8", features = ["small_rng"] }
serde = { version = "1", features = ["derive"] }
socket2 = { version = "0.4.1", features = ["all"] }
tungstenite = "0.13"
tungstenite = "0.15"
[dev-dependencies]
quickcheck = "1.0"

View file

@ -118,6 +118,8 @@ pub fn handle_announce_requests(
}
}
::log::trace!("received request from {:?}", request_sender_meta);
// Insert/update/remove peer who sent this request
{
let peer_status = PeerStatus::from_event_and_bytes_left(
@ -187,6 +189,10 @@ pub fn handle_announce_requests(
offer_receiver.connection_meta,
OutMessage::Offer(middleman_offer),
);
::log::trace!(
"sent middleman offer to {:?}",
offer_receiver.connection_meta
);
wake_socket_workers[offer_receiver.connection_meta.worker_index] = true;
}
}
@ -208,6 +214,10 @@ pub fn handle_announce_requests(
answer_receiver.connection_meta,
OutMessage::Answer(middleman_answer),
);
::log::trace!(
"sent middleman answer to {:?}",
answer_receiver.connection_meta
);
wake_socket_workers[answer_receiver.connection_meta.worker_index] = true;
}
}

View file

@ -9,7 +9,7 @@ use mio::{Poll, Token};
use native_tls::{MidHandshakeTlsStream, TlsAcceptor, TlsStream};
use tungstenite::handshake::{server::NoCallback, HandshakeError, MidHandshake};
use tungstenite::protocol::WebSocketConfig;
use tungstenite::server::ServerHandshake;
use tungstenite::ServerHandshake;
use tungstenite::WebSocket;
use crate::common::*;
@ -111,7 +111,7 @@ impl HandshakeMachine {
if let Some(tls_acceptor) = opt_tls_acceptor {
Self::handle_tls_handshake_result(tls_acceptor.accept(stream))
} else {
let handshake_result = ::tungstenite::server::accept_with_config(
let handshake_result = ::tungstenite::accept_with_config(
Stream::TcpStream(stream),
Some(ws_config),
);
@ -120,7 +120,7 @@ impl HandshakeMachine {
}
}
HandshakeMachine::TlsStream(stream) => {
let handshake_result = ::tungstenite::server::accept(Stream::TlsStream(stream));
let handshake_result = ::tungstenite::accept(Stream::TlsStream(stream));
Self::handle_ws_handshake_result(handshake_result)
}
@ -138,7 +138,14 @@ impl HandshakeMachine {
result: Result<TlsStream<TcpStream>, ::native_tls::HandshakeError<TcpStream>>,
) -> (Option<Either<EstablishedWs, Self>>, bool) {
match result {
Ok(stream) => (Some(Either::Right(Self::TlsStream(stream))), false),
Ok(stream) => {
::log::trace!(
"established tls handshake with peer with addr: {:?}",
stream.get_ref().peer_addr()
);
(Some(Either::Right(Self::TlsStream(stream))), false)
},
Err(native_tls::HandshakeError::WouldBlock(handshake)) => {
(Some(Either::Right(Self::TlsMidHandshake(handshake))), true)
}
@ -158,7 +165,15 @@ impl HandshakeMachine {
Ok(mut ws) => {
let peer_addr = ws.get_mut().get_peer_addr();
let established_ws = EstablishedWs { ws, peer_addr };
::log::trace!(
"established ws handshake with peer with addr: {:?}",
peer_addr
);
let established_ws = EstablishedWs {
ws,
peer_addr,
};
(Some(Either::Left(established_ws)), false)
}

View file

@ -21,7 +21,7 @@ rand_distr = "0.4"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
slab = "0.4"
tungstenite = "0.13"
tungstenite = "0.15"
[dev-dependencies]
quickcheck = "1.0"

View file

@ -22,7 +22,7 @@ hashbrown = { version = "0.11.2", features = ["serde"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
simd-json = { version = "0.4.7", features = ["allow-non-simd"] }
tungstenite = "0.13"
tungstenite = "0.15"
[dev-dependencies]
criterion = "0.3"