vimpunk / cratetorrent Goto Github PK
View Code? Open in Web Editor NEWA BitTorrent V1 engine library for Rust (and currently Linux)
A BitTorrent V1 engine library for Rust (and currently Linux)
Sometimes occurs when running tests/test_multi_connection_download.sh --size $(( 50 * 1024 * 1024 ))
.
[2020-11-14T19:20:55Z DEBUG cratetorrent::disk::io] Piece 761 intersects files: 0..1
[2020-11-14T19:20:55Z DEBUG cratetorrent::torrent] Disk write result Ok(BatchWrite { blocks: [BlockInfo { piece_index: 760, offset: 0, len: 16384 }, BlockInfo { piece_index: 760, offset: 16384, len: 16384 }, BlockInfo { piece_index: 760, offset: 32768, len: 16384 }, BlockInfo { piece_index: 760, offset: 49152, len: 16384 }], is_piece_valid: Some(true) })
[2020-11-14T19:20:55Z DEBUG cratetorrent::disk::io] Disk received command
[2020-11-14T19:20:55Z TRACE cratetorrent::disk::io] Saving torrent 0 block BlockInfo { piece_index: 761, offset: 16384, len: 16384 } to disk
[2020-11-14T19:20:55Z TRACE cratetorrent::disk::io] Saving block BlockInfo { piece_index: 761, offset: 16384, len: 16384 } to disk
[2020-11-14T19:20:55Z DEBUG cratetorrent::disk::io] Disk received command
[2020-11-14T19:20:55Z INFO cratetorrent::torrent] Finished piece 760 download, valid: true, left: 38
[2020-11-14T19:20:55Z TRACE cratetorrent::disk::io] Saving torrent 0 block BlockInfo { piece_index: 761, offset: 32768, len: 16384 } to disk
[2020-11-14T19:20:55Z TRACE cratetorrent::disk::io] Saving block BlockInfo { piece_index: 761, offset: 32768, len: 16384 } to disk
[2020-11-14T19:20:55Z DEBUG cratetorrent::disk::io] Disk received command
[2020-11-14T19:20:55Z TRACE cratetorrent::disk::io] Saving torrent 0 block BlockInfo { piece_index: 761, offset: 49152, len: 16384 } to disk
[2020-11-14T19:20:55Z TRACE cratetorrent::disk::io] Saving block BlockInfo { piece_index: 761, offset: 49152, len: 16384 } to disk
[2020-11-14T19:20:55Z DEBUG cratetorrent::disk::io] Piece 761 is complete (65536 bytes), flushing 4 block(s) to disk
[2020-11-14T19:20:55Z DEBUG cratetorrent::disk::io] Piece hash: f1a938c768f7efbcc26b33a112bbf3ec381aa40b
[2020-11-14T19:20:55Z DEBUG cratetorrent::disk::io] Piece 761 is valid
[2020-11-14T19:20:55Z DEBUG cratetorrent::disk::io] Disk received command
[2020-11-14T19:20:55Z DEBUG cratetorrent::torrent] Disk write result Ok(BatchWrite { blocks: [BlockInfo { piece_index: 761, offset: 0, len: 16384 }, BlockInfo { piece_index: 761, offset: 16384, len: 16384 }, BlockInfo { piece_index: 761, offset: 32768, len: 16384 }, BlockInfo { piece_index: 761, offset: 49152, len: 16384 }], is_piece_valid: Some(true) })
[2020-11-14T19:20:55Z INFO cratetorrent::torrent] Finished piece 761 download, valid: true, left: 38
[2020-11-14T19:20:55Z TRACE cratetorrent::disk::io] Saving torrent 0 block BlockInfo { piece_index: 762, offset: 0, len: 16384 } to disk
[2020-11-14T19:20:55Z TRACE cratetorrent::disk::io] Saving block BlockInfo { piece_index: 762, offset: 0, len: 16384 } to disk
[2020-11-14T19:20:55Z TRACE cratetorrent::disk::io] Creating piece 762 write buffer
[2020-11-14T19:20:55Z DEBUG cratetorrent::disk::io] Piece 762 expected hash 6292ef9ee99381ddd8fb524c64daa61047bbe88b
[2020-11-14T19:20:55Z DEBUG cratetorrent::disk::io] Piece 762 is 65536 bytes long
[2020-11-14T19:20:55Z TRACE cratetorrent::storage_info] Returning files intersecting piece 762
[2020-11-14T19:20:55Z DEBUG cratetorrent::disk::io] Piece 762 intersects files: 0..1
[2020-11-14T19:20:55Z DEBUG cratetorrent::disk::io] Disk received command
[2020-11-14T19:20:55Z TRACE cratetorrent::disk::io] Saving torrent 0 block BlockInfo { piece_index: 762, offset: 16384, len: 16384 } to disk
[2020-11-14T19:20:55Z TRACE cratetorrent::disk::io] Saving block BlockInfo { piece_index: 762, offset: 16384, len: 16384 } to disk
[2020-11-14T19:20:55Z DEBUG cratetorrent::disk::io] Disk received command
[2020-11-14T19:20:55Z TRACE cratetorrent::disk::io] Saving torrent 0 block BlockInfo { piece_index: 762, offset: 32768, len: 16384 } to disk
[2020-11-14T19:20:55Z TRACE cratetorrent::disk::io] Saving block BlockInfo { piece_index: 762, offset: 32768, len: 16384 } to disk
[2020-11-14T19:20:55Z WARN cratetorrent::peer] [Peer 172.17.0.2:51413] timeout after 14935 ms (timeouts: 13)
[2020-11-14T19:20:55Z TRACE cratetorrent::peer] Making requests to peer 172.17.0.2:51413
[2020-11-14T19:20:55Z DEBUG cratetorrent::peer] Session 172.17.0.2:51413 starting new piece download
[2020-11-14T19:20:55Z TRACE cratetorrent::piece_picker] Picking next piece
[2020-11-14T19:20:55Z TRACE cratetorrent::piece_picker] Could not pick piece
[2020-11-14T19:20:55Z DEBUG cratetorrent::peer] Could not pick more pieces from peer 172.17.0.2:51413
[2020-11-14T19:20:55Z INFO cratetorrent::peer] [Peer 172.17.0.2:51413] download rate: 34311 b/s (peak: 780141 b/s, total: 4128768 b) queue: 1, rtt: 616 ms (~0 s)
[2020-11-14T19:20:55Z WARN cratetorrent::peer] [Peer 172.17.0.3:51413] timeout after 14951 ms (timeouts: 1)
[2020-11-14T19:20:55Z TRACE cratetorrent::download] Canceling request for piece 762 block BlockInfo { piece_index: 762, offset: 49152, len: 16384 }
[2020-11-14T19:20:55Z TRACE cratetorrent::download] Canceling request for piece 763 block BlockInfo { piece_index: 763, offset: 0, len: 16384 }
< snip>
[2020-11-14T19:20:55Z TRACE cratetorrent::download] Canceling request for piece 799 block BlockInfo { piece_index: 799, offset: 49152, len: 16384 }
[2020-11-14T19:20:55Z TRACE cratetorrent::peer] Making requests to peer 172.17.0.3:51413
[2020-11-14T19:20:55Z DEBUG cratetorrent::peer] Peer 172.17.0.3:51413 trying to continue download 784
[2020-11-14T19:20:55Z TRACE cratetorrent::download] Picking 1 block(s) in piece 784 (length: 65536, blocks: 4)
[2020-11-14T19:20:55Z DEBUG cratetorrent::download] Picked 1 block(s) for piece 784: [BlockInfo { piece_index: 784, offset: 0, len: 16384 }]
[2020-11-14T19:20:55Z DEBUG cratetorrent::peer] Peer 172.17.0.3:51413 trying to continue download 791
[2020-11-14T19:20:55Z INFO cratetorrent::peer] Requesting 1 block(s) from peer 172.17.0.3:51413 (0 pending)
[2020-11-14T19:20:55Z INFO cratetorrent::peer] [Peer 172.17.0.3:51413] download rate: 2593852 b/s (peak: 2593852 b/s, total: 45858816 b) queue: 1, rtt: 14627 ms (~14 s)
[2020-11-14T19:20:55Z TRACE cratetorrent::peer::codec] Decoder has 16371 byte(s) remaining
[2020-11-14T19:20:55Z TRACE cratetorrent::peer::codec] Read buffer is 16371 bytes long but message is 16393 bytes long
[2020-11-14T19:20:55Z TRACE cratetorrent::peer::codec] Decoder has 16397 byte(s) remaining
[2020-11-14T19:20:55Z DEBUG cratetorrent::peer] Received message 172.17.0.3:51413 from peer Some(Block)
[2020-11-14T19:20:55Z INFO cratetorrent::peer] Received block from peer 172.17.0.3:51413: BlockInfo { piece_index: 784, offset: 0, len: 16384 }
[2020-11-14T19:20:55Z TRACE cratetorrent::download] Received piece 784 block BlockInfo { piece_index: 784, offset: 0, len: 16384 }
thread 'tokio-runtime-worker' panicked at 'supplied instant is later than self', library/std/src/time.rs:271:48
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
[2020-11-14T19:20:56Z DEBUG cratetorrent::torrent] Torrent running for 26s
Technically here we should reject bitfield messages where the overhang part contains non-zero bits.
Originally posted by @mandreyel in #34
We should deterministically generate the test environment (test files, torrent files, Transmission seed dir structure and config files, etc), rather than saving them in git.
This will be important once we test downloads with larger files in which case we won't want to blow up the git repo in size, and it would also help to avoid bugs where a required test file was forgotten to be added.
The problem is that as far as I can tell it is not possible to generate a metainfo in an automated way. Maybe with docker exec.
Some module level docs would be nice.
Originally posted by @mandreyel in #34
Currently the disk
module has tests to tests its high-level API, but it would be ideal to test each component of disk::io
too for higher coverage.
Unit and integration tests.
Currently unsure how to do this with the container based approach. Maybe it's possible to block container links for a short time?
As for unit tests, PeerSession
is not currently structured in such a way as to allow for easy unit testing of its logic. That is probably a larger issue, not related to only this.
The periodic (1s) torrent tick needs to do the following:
Currently the torrent doesn't do much with the peer sessions it has. This is partly because there is no existing infrastructure for a peer to report its state to its torrent.
This is crucial for a few reasons: if torrent requests peers from its tracker, the peers returned are not guaranteed to be seeds, so the torrent may end up in a situation where it is stuck. Therefore it needs to periodically check (in its "torrent tick") whether we need to disconnect idle peers and request new ones to drive forward the download.
We can start at 1.0.0-alpha.1 (https://codeblog.jonskeet.uk/2019/10/20/why-i-dont-start-versions-at-0-x-any-more/).
Currently the disk::io::Piece::write
method takes a path and reopens the file with each write. We should open file once and keep around its handle and use it for writing all its pieces.
Currently cratetorrent unchokes a new peer unconditionally. This needs to change as upload slots need to be capped. Otherwise cratetorrent might take up most of host's upload bandwidth.
Currently it's enforced that all blocks be 4 KiB, but this may not be the case for the last block in the torrent if it's total download length is not a multiple of 4 KiB.
TODO: expand list
This issue tracks potential ways to speed up downloads.
Currently these are stored in two places but they are very much related. So when we get a block, we find its corresponding request entry in the request queue and then find the corresponding piece.
Maybe:
downloads: HashMap<PieceIndex, Download>,
struct Download {
piece: PieceDownload,
requests: Vec<BlockInfo>,
}
This would protect the client against getting DoS-ed.
Only (non-positional) scatter-gather IO is supported in the std lib via the Write::write_vectored
trait interface, but this is not good enough for our use case as we'll need to perform 2 syscalls for every write: seek
and writev
.
It looks like github actions are free? If so, we should set up one to run unit tests and a few integration tests (not all to save time as we'd presumably capped).
Because there is no real reason to do so: cratetorrent doesn't have much config files so there is nothing to contain as with transmission, and everything else is configurable (listen address, download directory, as of this writing).
However, there are downsides to maintaining the dockerfile (e.g. openssl seems to break from time to time).
Currently we check after every block, which is needlessly expensive.
We can use https://github.com/fdehau/tui-rs, it's incredible.
Place limit on in-memory write buffer to not cause OOM. This should be configurable.
We currently notify torrent that this occurred (so that after n
failures it may stop torrent and further propagate failures to user), but we should also not erase the piece write buffer and retry writing later.
Currently not an issue but we shouldn't pull all of tokio in anyway.
instead of allocating a new vector every time
Record round trip type, downloaded bytes per second, etc.
The goal is simply to exchange a handshake and process a few messages from the peer. The focus is not a full download, as saving the file is part of the next milestone.
PeerSession
struct that holds peer related information and peer protocol methodsCurrently PeerSession::run
just returns with an Ok(()).
Although currently there is no real 'engine' entity, we still want to communicate two things:
These can be used to more cleanly implement stopping the torrent than how it is currently done.
Later of course this will expand to many more types of commands engine can send to torrent, and events torrent can send to engine.
It is a bit puzzling why this is happening. There are sometimes peers that keep sending not requested blocks.
It is not yet clear whether this is some mismanagement in cratetorrent or due to malicious peers. Probably the former.
Right now we necessitate peer sending us a bitfield as we only support downloading from seeds. However, once we support seeding, our peer may not have any pieces in which case it won't send a bitfield, and this would cause us to be stuck in the piece availability exchange state.
While this simplifies the logic a great deal, it uses up more resources without much need.
Instead of looping over all blocks every time the function is called.
For now, until seeding is supported.
engine
Use cratetorrent for seeding and downloading as we already have test infrastructure to easily set up and verify cratetorrent downloads. As a next step we could have leech tests for e.g. transmission to ensure compatibility, but probably not before alpha release.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.