Skip to content

Commit

Permalink
UPNP server integrated into rqbit.
Browse files Browse the repository at this point in the history
How to use: #208
  • Loading branch information
ikatson committed Aug 23, 2024
1 parent e8bd7ca commit 9e7b656
Show file tree
Hide file tree
Showing 34 changed files with 2,420 additions and 234 deletions.
132 changes: 71 additions & 61 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ members = [
"crates/peer_binary_protocol",
"crates/dht",
"crates/upnp",
"crates/tracker_comms",
"crates/tracker_comms", "crates/upnp-serve",
]

[profile.dev]
Expand Down
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ devserver:
echo -n '' > /tmp/rqbit-log && CORS_ALLOW_REGEXP=".*" \
cargo run -- \
--log-file /tmp/rqbit-log \
--log-file-rust-log=debug,librqbit=trace \
--log-file-rust-log=debug,librqbit=trace,upnp_serve=trace \
--http-api-listen-addr 0.0.0.0:3030 \
--upnp-server-hostname 192.168.0.112 \
--upnp-server-friendly-name rqbit-dev \
server start /tmp/scratch/

@PHONY: devserver
Expand Down
4 changes: 3 additions & 1 deletion crates/librqbit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ readme = "README.md"
[features]
default = ["default-tls"]
http-api = ["axum", "tower-http"]
upnp-serve-adapter = ["upnp-serve"]
webui = []
timed_existence = []
default-tls = ["reqwest/default-tls"]
Expand All @@ -38,6 +39,7 @@ peer_binary_protocol = { path = "../peer_binary_protocol", package = "librqbit-p
sha1w = { path = "../sha1w", default-features = false, package = "librqbit-sha1-wrapper", version = "3.0.0" }
dht = { path = "../dht", package = "librqbit-dht", version = "5.1.0" }
librqbit-upnp = { path = "../upnp", version = "0.1.1" }
upnp-serve = { path = "../upnp-serve", version = "0.1.0", optional = true }

tokio = { version = "1", features = [
"macros",
Expand Down Expand Up @@ -80,7 +82,7 @@ backoff = "0.4.0"
dashmap = "5.5.3"
base64 = "0.21.5"
serde_with = "3.4.0"
tokio-util = "0.7.10"
tokio-util = { version = "0.7.10", features = ["io"] }
bytes = "1.5.0"
rlimit = "0.10.1"
async-stream = "0.3.5"
Expand Down
44 changes: 30 additions & 14 deletions crates/librqbit/src/http_api.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use anyhow::Context;
use axum::body::Bytes;
use axum::extract::{Path, Query, State};
use axum::extract::{ConnectInfo, Path, Query, Request, State};
use axum::response::IntoResponse;
use axum::routing::{get, post};
use bencode::AsDisplay;
Expand All @@ -16,7 +16,8 @@ use std::net::SocketAddr;
use std::str::FromStr;
use std::time::Duration;
use tokio::io::AsyncSeekExt;
use tracing::{debug, info, trace};
use tokio::net::TcpListener;
use tracing::{debug, error_span, trace};

use axum::Router;

Expand Down Expand Up @@ -52,7 +53,11 @@ impl HttpApi {
/// Run the HTTP server forever on the given address.
/// If read_only is passed, no state-modifying methods will be exposed.
#[inline(never)]
pub fn make_http_api_and_run(self, addr: SocketAddr) -> BoxFuture<'static, anyhow::Result<()>> {
pub fn make_http_api_and_run(
self,
listener: TcpListener,
upnp_router: Option<Router>,
) -> BoxFuture<'static, anyhow::Result<()>> {
let state = self.inner;

async fn api_root() -> impl IntoResponse {
Expand Down Expand Up @@ -558,22 +563,33 @@ impl HttpApi {
.allow_headers(AllowHeaders::any())
};

let app = app
.layer(cors_layer)
.layer(tower_http::trace::TraceLayer::new_for_http())
.with_state(state)
.into_make_service();
let mut app = app.with_state(state);

info!(%addr, "starting HTTP server");
if let Some(upnp_router) = upnp_router {
app = app.nest("/upnp", upnp_router);
}

use tokio::net::TcpListener;
let app = app
.layer(cors_layer)
.layer(
tower_http::trace::TraceLayer::new_for_http().make_span_with(|req: &Request| {
let method = req.method();
let uri = req.uri();
if let Some(ConnectInfo(addr)) =
req.extensions().get::<ConnectInfo<SocketAddr>>()
{
error_span!("request", %method, %uri, %addr)
} else {
error_span!("request", %method, %uri)
}
}),
)
.into_make_service_with_connect_info::<SocketAddr>();

async move {
let listener = TcpListener::bind(&addr)
axum::serve(listener, app)
.await
.with_context(|| format!("error binding to {addr}"))?;
axum::serve(listener, app).await?;
Ok(())
.context("error running HTTP API")
}
.boxed()
}
Expand Down
2 changes: 2 additions & 0 deletions crates/librqbit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ mod torrent_state;
#[cfg(feature = "tracing-subscriber-utils")]
pub mod tracing_subscriber_config_utils;
mod type_aliases;
#[cfg(all(feature = "http-api", feature = "upnp-serve-adapter"))]
pub mod upnp_server_adapter;

pub use api::Api;
pub use api_error::ApiError;
Expand Down
Loading

0 comments on commit 9e7b656

Please sign in to comment.