commit
a2cbf16cdd
15 changed files with 856 additions and 1077 deletions
972
Cargo.lock
generated
972
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "librqbit-bencode"
|
||||
version = "3.0.1"
|
||||
version = "3.0.2"
|
||||
edition = "2021"
|
||||
description = "Bencode serialization and deserialization using Serde"
|
||||
license = "Apache-2.0"
|
||||
|
|
@ -16,8 +16,8 @@ sha1-ring = ["sha1w/sha1-ring"]
|
|||
|
||||
[dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
buffers = { path = "../buffers", package = "librqbit-buffers", version = "4" }
|
||||
buffers = { path = "../buffers", package = "librqbit-buffers", version = "4.2" }
|
||||
clone_to_owned = { path = "../clone_to_owned", package = "librqbit-clone-to-owned", version = "3" }
|
||||
anyhow = "1"
|
||||
sha1w = { path = "../sha1w", default-features = false, optional = true, package = "librqbit-sha1-wrapper", version = "4" }
|
||||
sha1w = { path = "../sha1w", default-features = false, optional = true, package = "librqbit-sha1-wrapper", version = "4.1" }
|
||||
bytes = "1.7.1"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "librqbit-buffers"
|
||||
version = "4.1.0"
|
||||
version = "4.2.0"
|
||||
edition = "2021"
|
||||
description = "Utils to work with &[u8] and Vec<u8> in librqbit source code."
|
||||
license = "Apache-2.0"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "librqbit-dht"
|
||||
version = "5.1.0"
|
||||
version = "5.2.0"
|
||||
edition = "2021"
|
||||
description = "DHT implementation, used in rqbit torrent client."
|
||||
license = "Apache-2.0"
|
||||
|
|
@ -32,7 +32,7 @@ rand = "0.8"
|
|||
indexmap = "2"
|
||||
dashmap = { version = "6", features = ["serde"] }
|
||||
clone_to_owned = { path = "../clone_to_owned", package = "librqbit-clone-to-owned", version = "3" }
|
||||
librqbit-core = { path = "../librqbit_core", default-features = false, version = "4" }
|
||||
librqbit-core = { path = "../librqbit_core", default-features = false, version = "4.1" }
|
||||
chrono = { version = "0.4.31", features = ["serde"] }
|
||||
tokio-util = "0.7.10"
|
||||
bytes = "1.7.1"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "librqbit"
|
||||
version = "7.1.0-beta.1"
|
||||
version = "8.0.0"
|
||||
authors = ["Igor Katson <igor.katson@gmail.com>"]
|
||||
edition = "2021"
|
||||
description = "The main library used by rqbit torrent client. The binary is just a small wrapper on top of it."
|
||||
|
|
@ -34,26 +34,30 @@ rust-tls = [
|
|||
storage_middleware = ["lru"]
|
||||
storage_examples = []
|
||||
tracing-subscriber-utils = ["tracing-subscriber"]
|
||||
postgres = ["sqlx"]
|
||||
postgres = ["sqlx", "home"]
|
||||
async-bt = ["async-backtrace"]
|
||||
watch = ["notify"]
|
||||
disable-upload = []
|
||||
|
||||
[dependencies]
|
||||
sqlx = { version = "0.8.2", features = [
|
||||
# sqlx and home are pinned so that we can compile on older Rusts
|
||||
sqlx = { version = "=0.8.2", features = [
|
||||
"runtime-tokio",
|
||||
"macros",
|
||||
"postgres",
|
||||
], optional = true }
|
||||
], default-features = false, optional = true }
|
||||
home = { version = "=0.5.5", optional = true }
|
||||
|
||||
bencode = { path = "../bencode", default-features = false, package = "librqbit-bencode", version = "3" }
|
||||
tracker_comms = { path = "../tracker_comms", default-features = false, package = "librqbit-tracker-comms", version = "2" }
|
||||
buffers = { path = "../buffers", package = "librqbit-buffers", version = "4.1" }
|
||||
librqbit-core = { path = "../librqbit_core", default-features = false, version = "4" }
|
||||
tracker_comms = { path = "../tracker_comms", default-features = false, package = "librqbit-tracker-comms", version = "2.1" }
|
||||
buffers = { path = "../buffers", package = "librqbit-buffers", version = "4.2" }
|
||||
librqbit-core = { path = "../librqbit_core", default-features = false, version = "4.1" }
|
||||
clone_to_owned = { path = "../clone_to_owned", package = "librqbit-clone-to-owned", version = "3" }
|
||||
peer_binary_protocol = { path = "../peer_binary_protocol", default-features = false, package = "librqbit-peer-protocol", version = "4.1" }
|
||||
sha1w = { path = "../sha1w", default-features = false, package = "librqbit-sha1-wrapper", version = "4" }
|
||||
dht = { path = "../dht", package = "librqbit-dht", version = "5.1.0" }
|
||||
librqbit-upnp = { path = "../upnp", version = "0.1.1" }
|
||||
upnp-serve = { path = "../upnp-serve", package = "librqbit-upnp-serve", default-features = false, version = "0.1.0", optional = true }
|
||||
sha1w = { path = "../sha1w", default-features = false, package = "librqbit-sha1-wrapper", version = "4.1" }
|
||||
dht = { path = "../dht", package = "librqbit-dht", version = "5.2.0" }
|
||||
librqbit-upnp = { path = "../upnp", version = "1" }
|
||||
upnp-serve = { path = "../upnp-serve", package = "librqbit-upnp-serve", default-features = false, version = "1", optional = true }
|
||||
|
||||
tokio = { version = "1", features = [
|
||||
"macros",
|
||||
|
|
@ -61,16 +65,16 @@ tokio = { version = "1", features = [
|
|||
"fs",
|
||||
"io-util",
|
||||
] }
|
||||
governor = "0.7"
|
||||
governor = "0.8"
|
||||
console-subscriber = { version = "0.4", optional = true }
|
||||
axum = { version = "0.7", optional = true }
|
||||
tower-http = { version = "0.5", features = ["cors", "trace"], optional = true }
|
||||
axum = { version = "0.8", optional = true }
|
||||
tower-http = { version = "0.6", features = ["cors", "trace"], optional = true }
|
||||
tokio-stream = "0.1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
serde_urlencoded = "0.7"
|
||||
anyhow = "1"
|
||||
itertools = "0.13"
|
||||
itertools = "0.14"
|
||||
http = "1"
|
||||
regex = "1"
|
||||
reqwest = { version = "0.12", default-features = false, features = [
|
||||
|
|
@ -109,7 +113,7 @@ mime_guess = { version = "2.0.5", default-features = false }
|
|||
tokio-socks = "0.5.2"
|
||||
async-trait = "0.1.81"
|
||||
async-backtrace = { version = "0.2", optional = true }
|
||||
notify = { version = "6.1.1", optional = true }
|
||||
notify = { version = "7", optional = true }
|
||||
walkdir = "2.5.0"
|
||||
arc-swap = "1.7.1"
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use serde::{Deserialize, Serialize};
|
|||
use std::io::SeekFrom;
|
||||
use std::net::SocketAddr;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::io::AsyncSeekExt;
|
||||
use tokio::net::TcpListener;
|
||||
|
|
@ -94,7 +95,6 @@ mod timeout {
|
|||
|
||||
pub struct Timeout<const DEFAULT_MS: usize, const MAX_MS: usize>(pub Duration);
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<S, const DEFAULT_MS: usize, const MAX_MS: usize> axum::extract::FromRequestParts<S>
|
||||
for Timeout<DEFAULT_MS, MAX_MS>
|
||||
where
|
||||
|
|
@ -456,12 +456,20 @@ impl HttpApi {
|
|||
state.api_peer_stats(idx, filter).map(axum::Json)
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct StreamPathParams {
|
||||
id: TorrentIdOrHash,
|
||||
file_id: usize,
|
||||
#[serde(rename = "filename")]
|
||||
_filename: Option<Arc<str>>,
|
||||
}
|
||||
|
||||
async fn torrent_stream_file(
|
||||
State(state): State<ApiState>,
|
||||
Path((idx, file_id)): Path<(TorrentIdOrHash, usize)>,
|
||||
Path(StreamPathParams { id, file_id, .. }): Path<StreamPathParams>,
|
||||
headers: http::HeaderMap,
|
||||
) -> Result<impl IntoResponse> {
|
||||
let mut stream = state.api_stream(idx, file_id)?;
|
||||
let mut stream = state.api_stream(id, file_id)?;
|
||||
let mut status = StatusCode::OK;
|
||||
let mut output_headers = HeaderMap::new();
|
||||
output_headers.insert("Accept-Ranges", HeaderValue::from_static("bytes"));
|
||||
|
|
@ -489,7 +497,7 @@ impl HttpApi {
|
|||
);
|
||||
}
|
||||
|
||||
if let Ok(mime) = state.torrent_file_mime_type(idx, file_id) {
|
||||
if let Ok(mime) = state.torrent_file_mime_type(id, file_id) {
|
||||
output_headers.insert(
|
||||
http::header::CONTENT_TYPE,
|
||||
HeaderValue::from_str(mime).context("bug - invalid MIME")?,
|
||||
|
|
@ -497,7 +505,7 @@ impl HttpApi {
|
|||
}
|
||||
|
||||
let range_header = headers.get(http::header::RANGE);
|
||||
trace!(torrent_id=%idx, file_id=file_id, range=?range_header, "request for HTTP stream");
|
||||
trace!(torrent_id=%id, file_id=file_id, range=?range_header, "request for HTTP stream");
|
||||
|
||||
if let Some(range) = range_header {
|
||||
let offset: Option<u64> = range
|
||||
|
|
@ -619,17 +627,17 @@ impl HttpApi {
|
|||
.route("/dht/table", get(dht_table))
|
||||
.route("/stats", get(session_stats))
|
||||
.route("/torrents", get(torrents_list))
|
||||
.route("/torrents/:id", get(torrent_details))
|
||||
.route("/torrents/:id/haves", get(torrent_haves))
|
||||
.route("/torrents/:id/stats", get(torrent_stats_v0))
|
||||
.route("/torrents/:id/stats/v1", get(torrent_stats_v1))
|
||||
.route("/torrents/:id/peer_stats", get(peer_stats))
|
||||
.route("/torrents/:id/stream/:file_id", get(torrent_stream_file))
|
||||
.route("/torrents/:id/playlist", get(torrent_playlist))
|
||||
.route("/torrents/{id}", get(torrent_details))
|
||||
.route("/torrents/{id}/haves", get(torrent_haves))
|
||||
.route("/torrents/{id}/stats", get(torrent_stats_v0))
|
||||
.route("/torrents/{id}/stats/v1", get(torrent_stats_v1))
|
||||
.route("/torrents/{id}/peer_stats", get(peer_stats))
|
||||
.route("/torrents/{id}/playlist", get(torrent_playlist))
|
||||
.route("/torrents/playlist", get(global_playlist))
|
||||
.route("/torrents/resolve_magnet", post(resolve_magnet))
|
||||
.route("/torrents/{id}/stream/{file_id}", get(torrent_stream_file))
|
||||
.route(
|
||||
"/torrents/:id/stream/:file_id/*filename",
|
||||
"/torrents/{id}/stream/{file_id}/{*filename}",
|
||||
get(torrent_stream_file),
|
||||
);
|
||||
|
||||
|
|
@ -637,12 +645,12 @@ impl HttpApi {
|
|||
app = app
|
||||
.route("/torrents", post(torrents_post))
|
||||
.route("/torrents/limits", post(update_session_ratelimits))
|
||||
.route("/torrents/:id/pause", post(torrent_action_pause))
|
||||
.route("/torrents/:id/start", post(torrent_action_start))
|
||||
.route("/torrents/:id/forget", post(torrent_action_forget))
|
||||
.route("/torrents/:id/delete", post(torrent_action_delete))
|
||||
.route("/torrents/{id}/pause", post(torrent_action_pause))
|
||||
.route("/torrents/{id}/start", post(torrent_action_start))
|
||||
.route("/torrents/{id}/forget", post(torrent_action_forget))
|
||||
.route("/torrents/{id}/delete", post(torrent_action_delete))
|
||||
.route(
|
||||
"/torrents/:id/update_only_files",
|
||||
"/torrents/{id}/update_only_files",
|
||||
post(torrent_action_update_only_files),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,16 +15,14 @@ use tracing::{error, error_span, info, Instrument};
|
|||
use crate::{
|
||||
create_torrent,
|
||||
tests::test_util::{
|
||||
create_default_random_dir_with_torrents, setup_test_logging, spawn_debug_server,
|
||||
wait_until_i_am_the_last_task, DropChecks, TestPeerMetadata,
|
||||
create_default_random_dir_with_torrents, setup_test_logging, wait_until_i_am_the_last_task,
|
||||
DropChecks, TestPeerMetadata,
|
||||
},
|
||||
AddTorrentOptions, AddTorrentResponse, Session, SessionOptions, SessionPersistenceConfig,
|
||||
};
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 64)]
|
||||
async fn test_e2e_download() {
|
||||
let dbg_srv = spawn_debug_server();
|
||||
|
||||
let timeout = std::env::var("E2E_TIMEOUT")
|
||||
.ok()
|
||||
.and_then(|v| v.parse().ok())
|
||||
|
|
@ -39,8 +37,6 @@ async fn test_e2e_download() {
|
|||
.context("test_e2e_download timed out")
|
||||
.unwrap();
|
||||
|
||||
dbg_srv.abort();
|
||||
|
||||
// Wait to ensure everything is dropped.
|
||||
wait_until_i_am_the_last_task().await.unwrap();
|
||||
|
||||
|
|
|
|||
823
crates/librqbit/webui/package-lock.json
generated
823
crates/librqbit/webui/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "librqbit-core"
|
||||
version = "4.0.1"
|
||||
version = "4.1.0"
|
||||
edition = "2021"
|
||||
description = "Important utilities used throughout librqbit useful for working with torrents."
|
||||
license = "Apache-2.0"
|
||||
|
|
@ -23,10 +23,10 @@ url = { version = "2", default-features = false }
|
|||
uuid = { version = "1", features = ["v4"] }
|
||||
parking_lot = "0.12"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
buffers = { path = "../buffers", package = "librqbit-buffers", version = "4" }
|
||||
buffers = { path = "../buffers", package = "librqbit-buffers", version = "4.2" }
|
||||
bencode = { path = "../bencode", default-features = false, package = "librqbit-bencode", version = "3.0.1" }
|
||||
clone_to_owned = { path = "../clone_to_owned", package = "librqbit-clone-to-owned", version = "3" }
|
||||
itertools = "0.13"
|
||||
itertools = "0.14"
|
||||
directories = "5"
|
||||
tokio-util = "0.7.10"
|
||||
data-encoding = "2.6.0"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "librqbit-peer-protocol"
|
||||
version = "4.1.0"
|
||||
version = "4.2.0"
|
||||
edition = "2021"
|
||||
description = "Protocol for working with torrent peers. Used in rqbit torrent client."
|
||||
license = "Apache-2.0"
|
||||
|
|
@ -13,11 +13,11 @@ readme = "README.md"
|
|||
serde = { version = "1", features = ["derive"] }
|
||||
bincode = "1"
|
||||
byteorder = "1"
|
||||
buffers = { path = "../buffers", package = "librqbit-buffers", version = "4.1" }
|
||||
buffers = { path = "../buffers", package = "librqbit-buffers", version = "4.2" }
|
||||
bencode = { path = "../bencode", default-features = false, package = "librqbit-bencode", version = "3" }
|
||||
clone_to_owned = { path = "../clone_to_owned", package = "librqbit-clone-to-owned", version = "3" }
|
||||
librqbit-core = { path = "../librqbit_core", default-features = false, version = "4" }
|
||||
librqbit-core = { path = "../librqbit_core", default-features = false, version = "4.1" }
|
||||
bitvec = "1"
|
||||
anyhow = "1"
|
||||
bytes = "1.7.1"
|
||||
itertools = "0.13"
|
||||
itertools = "0.14"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "rqbit"
|
||||
version = "7.1.0-beta.1"
|
||||
version = "8.0.0"
|
||||
authors = ["Igor Katson <igor.katson@gmail.com>"]
|
||||
edition = "2021"
|
||||
description = "A bittorrent command line client and server."
|
||||
|
|
@ -24,7 +24,7 @@ postgres = ["librqbit/postgres"]
|
|||
disable-upload = ["librqbit/disable-upload"]
|
||||
|
||||
[dependencies]
|
||||
librqbit = { version = "7.1.0-beta.0", path = "../librqbit", default-features = false, features = [
|
||||
librqbit = { version = "8.0.0", path = "../librqbit", default-features = false, features = [
|
||||
"http-api",
|
||||
"tracing-subscriber-utils",
|
||||
"upnp-serve-adapter",
|
||||
|
|
@ -46,7 +46,7 @@ serde_json = "1"
|
|||
size_format = "1"
|
||||
bytes = "1.5.0"
|
||||
openssl = { version = "0.10", features = ["vendored"], optional = true }
|
||||
upnp-serve = { path = "../upnp-serve", default-features = false, version = "0.1.0", package = "librqbit-upnp-serve" }
|
||||
upnp-serve = { path = "../upnp-serve", default-features = false, version = "1", package = "librqbit-upnp-serve" }
|
||||
libc = "0.2.158"
|
||||
signal-hook = "0.3.17"
|
||||
tokio-util = "0.7.11"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "librqbit-sha1-wrapper"
|
||||
version = "4.0.0"
|
||||
version = "4.1.0"
|
||||
edition = "2018"
|
||||
description = "Common interface around various sha1 implementations used in rqbit torrent client."
|
||||
license = "Apache-2.0"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "librqbit-tracker-comms"
|
||||
version = "2.0.0"
|
||||
version = "2.1.0"
|
||||
edition = "2018"
|
||||
description = "Common interface around various sha1 implementations used in rqbit torrent client."
|
||||
license = "Apache-2.0"
|
||||
|
|
@ -15,8 +15,8 @@ tokio = "1"
|
|||
anyhow = "1"
|
||||
futures = "0.3"
|
||||
async-stream = "0.3.5"
|
||||
buffers = { path = "../buffers", package = "librqbit-buffers", version = "4" }
|
||||
librqbit-core = { path = "../librqbit_core", default-features = false, version = "4" }
|
||||
buffers = { path = "../buffers", package = "librqbit-buffers", version = "4.2" }
|
||||
librqbit-core = { path = "../librqbit_core", default-features = false, version = "4.1" }
|
||||
byteorder = "1.5"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
urlencoding = "2"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "librqbit-upnp-serve"
|
||||
version = "0.1.0"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
description = "Simple UPnP MediaServer implementation"
|
||||
license = "Apache-2.0"
|
||||
|
|
@ -18,7 +18,7 @@ sha1-ring = ["librqbit-sha1-wrapper/sha1-ring", "librqbit-core/sha1-ring"]
|
|||
|
||||
[dependencies]
|
||||
anyhow = "1.0.86"
|
||||
axum = { version = "0.7", features = ["tokio"] }
|
||||
axum = { version = "0.8", features = ["tokio"] }
|
||||
tokio = { version = "1.39.3", features = ["full"] }
|
||||
tracing = "0.1.40"
|
||||
bstr = "1.10.0"
|
||||
|
|
@ -26,10 +26,10 @@ serde = { version = "1", features = ["derive"] }
|
|||
http = "1.1.0"
|
||||
httparse = "1.9.4"
|
||||
uuid = { version = "1.10.0", features = ["v4"] }
|
||||
librqbit-upnp = { version = "0.1", path = "../upnp", default-features = false }
|
||||
librqbit-upnp = { version = "1", path = "../upnp", default-features = false }
|
||||
gethostname = "0.5.0"
|
||||
librqbit-sha1-wrapper = { path = "../sha1w", version = "4", default-features = false }
|
||||
librqbit-core = { version = "4", path = "../librqbit_core", default-features = false }
|
||||
librqbit-core = { version = "4.1", path = "../librqbit_core", default-features = false }
|
||||
mime_guess = "2.0.5"
|
||||
url = { version = "2", default-features = false }
|
||||
parking_lot = "0.12.3"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "librqbit-upnp"
|
||||
version = "0.1.1"
|
||||
version = "1.0.0"
|
||||
authors = ["Igor Katson <igor.katson@gmail.com>"]
|
||||
edition = "2021"
|
||||
description = "Library used by rqbit torrent client to lease port forwards on the router."
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue