mirror of https://github.com/ikatson/rqbit
BREAKING: add uTP support to desktop
This commit is contained in:
parent
789cc26a36
commit
3d31175a0c
4
Makefile
4
Makefile
|
|
@ -14,11 +14,11 @@ webui-dev: webui-deps
|
||||||
export RQBIT_UPNP_SERVER_ENABLE ?= true
|
export RQBIT_UPNP_SERVER_ENABLE ?= true
|
||||||
export RQBIT_UPNP_SERVER_FRIENDLY_NAME ?= rqbit-dev
|
export RQBIT_UPNP_SERVER_FRIENDLY_NAME ?= rqbit-dev
|
||||||
export RQBIT_HTTP_API_LISTEN_ADDR ?= [::]:3030
|
export RQBIT_HTTP_API_LISTEN_ADDR ?= [::]:3030
|
||||||
|
export RQBIT_EXPERIMENTAL_UTP_LISTEN_ENABLE ?= true
|
||||||
export RQBIT_FASTRESUME = true
|
export RQBIT_FASTRESUME = true
|
||||||
|
|
||||||
# Don't expose devserver
|
# Don't expose devserver
|
||||||
export RQBIT_UPNP_PORT_FORWARD_DISABLE = true
|
export RQBIT_LISTEN_IP = 127.0.0.1
|
||||||
export RQBIT_TCP_LISTEN_DISABLE = true
|
|
||||||
|
|
||||||
CARGO_RUN_FLAGS ?=
|
CARGO_RUN_FLAGS ?=
|
||||||
RQBIT_OUTPUT_FOLDER ?= /tmp/scratch
|
RQBIT_OUTPUT_FOLDER ?= /tmp/scratch
|
||||||
|
|
|
||||||
|
|
@ -96,11 +96,14 @@ impl ListenerOptions {
|
||||||
if !self.mode.utp_enabled() {
|
if !self.mode.utp_enabled() {
|
||||||
return Ok::<_, anyhow::Error>(None);
|
return Ok::<_, anyhow::Error>(None);
|
||||||
}
|
}
|
||||||
Ok(Some(
|
let socket = UtpSocketUdp::new_udp_with_opts(self.listen_addr, utp_opts)
|
||||||
UtpSocketUdp::new_udp_with_opts(self.listen_addr, utp_opts)
|
.await
|
||||||
.await
|
.context("error starting uTP listener")?;
|
||||||
.context("error starting uTP listener")?,
|
info!(
|
||||||
))
|
"Listening on UDP {:?} for incoming uTP peer connections",
|
||||||
|
self.listen_addr
|
||||||
|
);
|
||||||
|
Ok(Some(socket))
|
||||||
};
|
};
|
||||||
|
|
||||||
let announce_port = if self.listen_addr.ip().is_loopback() {
|
let announce_port = if self.listen_addr.ip().is_loopback() {
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ pub enum WriterRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[serde_as]
|
#[serde_as]
|
||||||
#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
pub struct PeerConnectionOptions {
|
pub struct PeerConnectionOptions {
|
||||||
#[serde_as(as = "Option<serde_with::DurationSeconds>")]
|
#[serde_as(as = "Option<serde_with::DurationSeconds>")]
|
||||||
pub connect_timeout: Option<Duration>,
|
pub connect_timeout: Option<Duration>,
|
||||||
|
|
|
||||||
|
|
@ -700,6 +700,7 @@ impl Session {
|
||||||
}
|
}
|
||||||
if let Some(announce_port) = listen.announce_port {
|
if let Some(announce_port) = listen.announce_port {
|
||||||
if listen.enable_upnp_port_forwarding {
|
if listen.enable_upnp_port_forwarding {
|
||||||
|
info!(port = announce_port, "starting UPnP port forwarder");
|
||||||
session.spawn(
|
session.spawn(
|
||||||
error_span!(parent: session.rs(), "upnp_forward", port = announce_port),
|
error_span!(parent: session.rs(), "upnp_forward", port = announce_port),
|
||||||
Self::task_upnp_port_forwarder(announce_port),
|
Self::task_upnp_port_forwarder(announce_port),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
io,
|
io,
|
||||||
net::{Ipv4Addr, SocketAddr},
|
net::{IpAddr, SocketAddr},
|
||||||
num::NonZeroU32,
|
num::NonZeroU32,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
|
|
@ -133,6 +133,10 @@ struct Opts {
|
||||||
#[arg(long = "disable-tcp-listen", env = "RQBIT_TCP_LISTEN_DISABLE")]
|
#[arg(long = "disable-tcp-listen", env = "RQBIT_TCP_LISTEN_DISABLE")]
|
||||||
disable_tcp_listen: bool,
|
disable_tcp_listen: bool,
|
||||||
|
|
||||||
|
// Disable connecting over TCP. Only uTP will be used (if enabled).
|
||||||
|
#[arg(long = "disable-tcp-connect", env = "RQBIT_TCP_CONNECT_DISABLE")]
|
||||||
|
disable_tcp_connect: bool,
|
||||||
|
|
||||||
// Enable to listen and connect over uTP
|
// Enable to listen and connect over uTP
|
||||||
#[arg(
|
#[arg(
|
||||||
long = "experimental-enable-utp-listen",
|
long = "experimental-enable-utp-listen",
|
||||||
|
|
@ -148,15 +152,19 @@ struct Opts {
|
||||||
)]
|
)]
|
||||||
listen_port: u16,
|
listen_port: u16,
|
||||||
|
|
||||||
|
/// What's the IP to listen on. Default is to listen on all interfaces.
|
||||||
|
#[arg(long = "listen-ip", default_value = "0.0.0.0", env = "RQBIT_LISTEN_IP")]
|
||||||
|
listen_ip: IpAddr,
|
||||||
|
|
||||||
/// If set, will try to publish the chosen port through upnp on your router.
|
/// If set, will try to publish the chosen port through upnp on your router.
|
||||||
|
/// If the listen-ip is localhost, this will not be used.
|
||||||
#[arg(
|
#[arg(
|
||||||
long = "disable-upnp-port-forward",
|
long = "disable-upnp-port-forward",
|
||||||
env = "RQBIT_UPNP_PORT_FORWARD_DISABLE"
|
env = "RQBIT_UPNP_PORT_FORWARD_DISABLE"
|
||||||
)]
|
)]
|
||||||
disable_upnp_port_forward: bool,
|
disable_upnp_port_forward: bool,
|
||||||
|
|
||||||
/// If set, will run a UPNP Media server and stream all the torrents through it.
|
/// If set, will run a UPNP Media server on RQBIT_HTTP_API_LISTEN_ADDR.
|
||||||
/// Should be set to your hostname/IP as seen by your LAN neighbors.
|
|
||||||
#[arg(long = "enable-upnp-server", env = "RQBIT_UPNP_SERVER_ENABLE")]
|
#[arg(long = "enable-upnp-server", env = "RQBIT_UPNP_SERVER_ENABLE")]
|
||||||
enable_upnp_server: bool,
|
enable_upnp_server: bool,
|
||||||
|
|
||||||
|
|
@ -490,7 +498,7 @@ async fn async_main(opts: Opts, cancel: CancellationToken) -> anyhow::Result<()>
|
||||||
};
|
};
|
||||||
let listen = listen_mode.map(|mode| ListenerOptions {
|
let listen = listen_mode.map(|mode| ListenerOptions {
|
||||||
mode,
|
mode,
|
||||||
listen_addr: (Ipv4Addr::UNSPECIFIED, opts.listen_port).into(),
|
listen_addr: (opts.listen_ip, opts.listen_port).into(),
|
||||||
enable_upnp_port_forwarding: !opts.disable_upnp_port_forward,
|
enable_upnp_port_forwarding: !opts.disable_upnp_port_forward,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
@ -505,7 +513,7 @@ async fn async_main(opts: Opts, cancel: CancellationToken) -> anyhow::Result<()>
|
||||||
listen,
|
listen,
|
||||||
connect: Some(ConnectionOptions {
|
connect: Some(ConnectionOptions {
|
||||||
proxy_url: opts.socks_url,
|
proxy_url: opts.socks_url,
|
||||||
enable_tcp: true,
|
enable_tcp: !opts.disable_tcp_connect,
|
||||||
peer_opts: Some(PeerConnectionOptions {
|
peer_opts: Some(PeerConnectionOptions {
|
||||||
connect_timeout: Some(opts.peer_connect_timeout),
|
connect_timeout: Some(opts.peer_connect_timeout),
|
||||||
read_write_timeout: Some(opts.peer_read_write_timeout),
|
read_write_timeout: Some(opts.peer_read_write_timeout),
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
[package]
|
[package]
|
||||||
name = "rqbit-desktop"
|
name = "rqbit-desktop"
|
||||||
|
edition = "2024"
|
||||||
version = "8.1.0"
|
version = "8.1.0"
|
||||||
description = "rqbit torrent client"
|
description = "rqbit torrent client"
|
||||||
authors = ["you"]
|
authors = ["Igor Katson igor.katson@gmail.com"]
|
||||||
license = ""
|
license = ""
|
||||||
repository = ""
|
repository = ""
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@ use std::{
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use librqbit::{dht::PersistentDht, limits::LimitsConfig, ListenerMode, ListenerOptions};
|
use librqbit::{
|
||||||
|
dht::PersistentDht, limits::LimitsConfig, ConnectionOptions, ListenerMode, ListenerOptions,
|
||||||
|
PeerConnectionOptions,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::serde_as;
|
use serde_with::serde_as;
|
||||||
|
|
||||||
|
|
@ -26,39 +29,65 @@ impl Default for RqbitDesktopConfigDht {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
#[serde_as]
|
||||||
|
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct RqbitDesktopConfigListen {
|
pub struct RqbitDesktopConfigConnections {
|
||||||
pub enable_tcp: bool,
|
pub enable_tcp_listen: bool,
|
||||||
|
pub enable_tcp_outgoing: bool,
|
||||||
pub enable_utp: bool,
|
pub enable_utp: bool,
|
||||||
pub enable_upnp_port_forward: bool,
|
pub enable_upnp_port_forward: bool,
|
||||||
pub port: u16,
|
pub socks_proxy: String,
|
||||||
|
pub listen_port: u16,
|
||||||
|
|
||||||
|
#[serde_as(as = "serde_with::DurationSeconds")]
|
||||||
|
pub peer_connect_timeout: Duration,
|
||||||
|
#[serde_as(as = "serde_with::DurationSeconds")]
|
||||||
|
pub peer_read_write_timeout: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RqbitDesktopConfigListen {
|
impl RqbitDesktopConfigConnections {
|
||||||
pub fn as_listener_opts(&self) -> Option<ListenerOptions> {
|
pub fn as_listener_and_connect_opts(&self) -> (Option<ListenerOptions>, ConnectionOptions) {
|
||||||
let mode = match (self.enable_tcp, self.enable_utp) {
|
let mode = match (self.enable_tcp_listen, self.enable_utp) {
|
||||||
(true, true) => ListenerMode::TcpAndUtp,
|
(true, true) => Some(ListenerMode::TcpAndUtp),
|
||||||
(true, false) => ListenerMode::TcpOnly,
|
(true, false) => Some(ListenerMode::TcpOnly),
|
||||||
(false, true) => ListenerMode::UtpOnly,
|
(false, true) => Some(ListenerMode::UtpOnly),
|
||||||
(false, false) => return None,
|
(false, false) => None,
|
||||||
};
|
};
|
||||||
Some(ListenerOptions {
|
let listener_opts = mode.map(|mode| ListenerOptions {
|
||||||
mode,
|
mode,
|
||||||
listen_addr: (Ipv4Addr::UNSPECIFIED, self.port).into(),
|
listen_addr: (Ipv4Addr::UNSPECIFIED, self.listen_port).into(),
|
||||||
enable_upnp_port_forwarding: self.enable_upnp_port_forward,
|
enable_upnp_port_forwarding: self.enable_upnp_port_forward,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
});
|
||||||
|
let connect_opts = ConnectionOptions {
|
||||||
|
proxy_url: if self.socks_proxy.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.socks_proxy.clone())
|
||||||
|
},
|
||||||
|
enable_tcp: self.enable_tcp_outgoing,
|
||||||
|
peer_opts: Some(PeerConnectionOptions {
|
||||||
|
connect_timeout: Some(self.peer_connect_timeout),
|
||||||
|
read_write_timeout: Some(self.peer_read_write_timeout),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
(listener_opts, connect_opts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RqbitDesktopConfigListen {
|
impl Default for RqbitDesktopConfigConnections {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
enable_tcp: true,
|
enable_tcp_listen: true,
|
||||||
|
enable_tcp_outgoing: true,
|
||||||
enable_utp: false,
|
enable_utp: false,
|
||||||
enable_upnp_port_forward: true,
|
enable_upnp_port_forward: true,
|
||||||
port: 4240,
|
listen_port: 4240,
|
||||||
|
socks_proxy: String::new(),
|
||||||
|
peer_connect_timeout: Duration::from_secs(2),
|
||||||
|
peer_read_write_timeout: Duration::from_secs(10),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -104,26 +133,6 @@ impl Default for RqbitDesktopConfigPersistence {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[serde_as]
|
|
||||||
#[derive(Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
|
||||||
#[serde(default)]
|
|
||||||
pub struct RqbitDesktopConfigPeerOpts {
|
|
||||||
#[serde_as(as = "serde_with::DurationSeconds")]
|
|
||||||
pub connect_timeout: Duration,
|
|
||||||
|
|
||||||
#[serde_as(as = "serde_with::DurationSeconds")]
|
|
||||||
pub read_write_timeout: Duration,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for RqbitDesktopConfigPeerOpts {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
connect_timeout: Duration::from_secs(2),
|
|
||||||
read_write_timeout: Duration::from_secs(10),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[serde_as]
|
#[serde_as]
|
||||||
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|
@ -163,11 +172,9 @@ pub struct RqbitDesktopConfig {
|
||||||
pub disable_upload: bool,
|
pub disable_upload: bool,
|
||||||
|
|
||||||
pub dht: RqbitDesktopConfigDht,
|
pub dht: RqbitDesktopConfigDht,
|
||||||
#[serde(default)]
|
pub connections: RqbitDesktopConfigConnections,
|
||||||
pub listen: RqbitDesktopConfigListen,
|
|
||||||
pub upnp: RqbitDesktopConfigUpnp,
|
pub upnp: RqbitDesktopConfigUpnp,
|
||||||
pub persistence: RqbitDesktopConfigPersistence,
|
pub persistence: RqbitDesktopConfigPersistence,
|
||||||
pub peer_opts: RqbitDesktopConfigPeerOpts,
|
|
||||||
pub http_api: RqbitDesktopConfigHttpApi,
|
pub http_api: RqbitDesktopConfigHttpApi,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|
@ -185,10 +192,9 @@ impl Default for RqbitDesktopConfig {
|
||||||
Self {
|
Self {
|
||||||
default_download_location: download_folder,
|
default_download_location: download_folder,
|
||||||
dht: Default::default(),
|
dht: Default::default(),
|
||||||
listen: Default::default(),
|
connections: Default::default(),
|
||||||
upnp: Default::default(),
|
upnp: Default::default(),
|
||||||
persistence: Default::default(),
|
persistence: Default::default(),
|
||||||
peer_opts: Default::default(),
|
|
||||||
http_api: Default::default(),
|
http_api: Default::default(),
|
||||||
ratelimits: Default::default(),
|
ratelimits: Default::default(),
|
||||||
#[cfg(feature = "disable-upload")]
|
#[cfg(feature = "disable-upload")]
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,8 @@ async fn api_from_config(
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let (listen, connect) = config.connections.as_listener_and_connect_opts();
|
||||||
|
|
||||||
let session = Session::new_with_opts(
|
let session = Session::new_with_opts(
|
||||||
config.default_download_location.clone(),
|
config.default_download_location.clone(),
|
||||||
SessionOptions {
|
SessionOptions {
|
||||||
|
|
@ -94,16 +96,8 @@ async fn api_from_config(
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
persistence,
|
persistence,
|
||||||
connect: Some(librqbit::ConnectionOptions {
|
connect: Some(connect),
|
||||||
enable_tcp: true,
|
listen,
|
||||||
peer_opts: Some(PeerConnectionOptions {
|
|
||||||
connect_timeout: Some(config.peer_opts.connect_timeout),
|
|
||||||
read_write_timeout: Some(config.peer_opts.read_write_timeout),
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
listen: config.listen.as_listener_opts(),
|
|
||||||
fastresume: config.persistence.fastresume,
|
fastresume: config.persistence.fastresume,
|
||||||
ratelimits: config.ratelimits,
|
ratelimits: config.ratelimits,
|
||||||
#[cfg(feature = "disable-upload")]
|
#[cfg(feature = "disable-upload")]
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,15 @@ interface RqbitDesktopConfigDht {
|
||||||
persistence_filename: PathLike;
|
persistence_filename: PathLike;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RqbitDesktopConfigTcpListen {
|
interface RqbitDesktopConfigConnections {
|
||||||
disable: boolean;
|
enable_tcp_listen: boolean;
|
||||||
min_port: number;
|
enable_tcp_outgoing: boolean;
|
||||||
max_port: number;
|
enable_utp: boolean;
|
||||||
|
enable_upnp_port_forward: boolean;
|
||||||
|
socks_proxy: string;
|
||||||
|
listen_port: number;
|
||||||
|
peer_connect_timeout: Duration;
|
||||||
|
peer_read_write_timeout: Duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RqbitDesktopConfigPersistence {
|
interface RqbitDesktopConfigPersistence {
|
||||||
|
|
@ -20,11 +25,6 @@ interface RqbitDesktopConfigPersistence {
|
||||||
fastresume: boolean;
|
fastresume: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RqbitDesktopConfigPeerOpts {
|
|
||||||
connect_timeout: Duration;
|
|
||||||
read_write_timeout: Duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface RqbitDesktopConfigHttpApi {
|
interface RqbitDesktopConfigHttpApi {
|
||||||
disable: boolean;
|
disable: boolean;
|
||||||
listen_addr: SocketAddr;
|
listen_addr: SocketAddr;
|
||||||
|
|
@ -48,10 +48,9 @@ export interface RqbitDesktopConfig {
|
||||||
default_download_location: PathLike;
|
default_download_location: PathLike;
|
||||||
disable_upload?: boolean;
|
disable_upload?: boolean;
|
||||||
dht: RqbitDesktopConfigDht;
|
dht: RqbitDesktopConfigDht;
|
||||||
tcp_listen: RqbitDesktopConfigTcpListen;
|
connections: RqbitDesktopConfigConnections;
|
||||||
upnp: RqbitDesktopConfigUpnp;
|
upnp: RqbitDesktopConfigUpnp;
|
||||||
persistence: RqbitDesktopConfigPersistence;
|
persistence: RqbitDesktopConfigPersistence;
|
||||||
peer_opts: RqbitDesktopConfigPeerOpts;
|
|
||||||
http_api: RqbitDesktopConfigHttpApi;
|
http_api: RqbitDesktopConfigHttpApi;
|
||||||
ratelimits: LimitsConfig;
|
ratelimits: LimitsConfig;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,17 +58,15 @@ type TAB =
|
||||||
| "Home"
|
| "Home"
|
||||||
| "DHT"
|
| "DHT"
|
||||||
| "Session"
|
| "Session"
|
||||||
| "Peer options"
|
|
||||||
| "HTTP API"
|
| "HTTP API"
|
||||||
| "TCP Listen"
|
| "Connection"
|
||||||
| "UPnP Server";
|
| "UPnP Server";
|
||||||
|
|
||||||
const TABS: readonly TAB[] = [
|
const TABS: readonly TAB[] = [
|
||||||
"Home",
|
"Home",
|
||||||
"DHT",
|
"DHT",
|
||||||
"Session",
|
"Session",
|
||||||
"TCP Listen",
|
"Connection",
|
||||||
"Peer options",
|
|
||||||
"HTTP API",
|
"HTTP API",
|
||||||
"UPnP Server",
|
"UPnP Server",
|
||||||
] as const;
|
] as const;
|
||||||
|
|
@ -133,7 +131,7 @@ export const ConfigModal: React.FC<{
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleToggleChange: React.ChangeEventHandler<HTMLInputElement> = (
|
const handleToggleChange: React.ChangeEventHandler<HTMLInputElement> = (
|
||||||
e
|
e,
|
||||||
) => {
|
) => {
|
||||||
const name: string = e.target.name;
|
const name: string = e.target.name;
|
||||||
const [mainField, subField] = name.split(".", 2);
|
const [mainField, subField] = name.split(".", 2);
|
||||||
|
|
@ -169,7 +167,7 @@ export const ConfigModal: React.FC<{
|
||||||
text: "Error saving configuration",
|
text: "Error saving configuration",
|
||||||
details: e,
|
details: e,
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -257,42 +255,78 @@ Might be useful e.g. if rqbit upload consumes all your upload bandwidth and inte
|
||||||
</Fieldset>
|
</Fieldset>
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab name="TCP Listen" currentTab={tab}>
|
<Tab name="Connection" currentTab={tab}>
|
||||||
<Fieldset>
|
<Fieldset>
|
||||||
<FormCheck
|
<FormCheck
|
||||||
label="Listen on TCP"
|
label="Listen on TCP"
|
||||||
name="tcp_listen.disable"
|
name="connections.enable_tcp_listen"
|
||||||
checked={!config.tcp_listen.disable}
|
checked={config.connections.enable_tcp_listen}
|
||||||
onChange={handleToggleChange}
|
onChange={handleToggleChange}
|
||||||
help="Listen for torrent requests on TCP. Required for peers to be able to connect to you, mainly for uploading."
|
help="Listen for torrent requests on TCP. Required for peers to be able to connect to you, mainly for uploading."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormCheck
|
<FormCheck
|
||||||
label="Advertise TCP port over UPnP"
|
label="Listen on uTP (over UDP)"
|
||||||
name="tcp_listen.disable"
|
name="connections.enable_utp"
|
||||||
checked={!config.tcp_listen.disable}
|
checked={config.connections.enable_utp}
|
||||||
|
onChange={handleToggleChange}
|
||||||
|
help="Listen for torrent requests on uTP over UDP. Required for uTP support in general, both outgoing and incoming."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormCheck
|
||||||
|
label="Advertise port over UPnP"
|
||||||
|
name="connections.enable_upnp_port_forward"
|
||||||
|
checked={config.connections.enable_upnp_port_forward}
|
||||||
onChange={handleToggleChange}
|
onChange={handleToggleChange}
|
||||||
help="Advertise your port over UPnP to your router(s). This is required for peers to be able to connect to you from the internet. Will only work if your router has a static IP."
|
help="Advertise your port over UPnP to your router(s). This is required for peers to be able to connect to you from the internet. Will only work if your router has a static IP."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<FormCheck
|
||||||
|
label="[ADVANCED] Disable outgoing connections over TCP"
|
||||||
|
name="connections.enable_tcp_outgoing"
|
||||||
|
checked={!config.connections.enable_tcp_outgoing}
|
||||||
|
onChange={handleToggleChange}
|
||||||
|
help="WARNING: leave this unchecked unless you know what you are doing."
|
||||||
|
/>
|
||||||
|
|
||||||
<FormInput
|
<FormInput
|
||||||
inputType="number"
|
inputType="text"
|
||||||
label="Min port"
|
label="Socks proxy"
|
||||||
name="tcp_listen.min_port"
|
name="connections.socks_proxy"
|
||||||
value={config.tcp_listen.min_port}
|
value={config.connections.socks_proxy}
|
||||||
disabled={config.tcp_listen.disable}
|
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
help="The min port to try to listen on. First successful is taken."
|
help="Socks5 proxy for outgoing connections. Format: socks5://[username:password@]host:port"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormInput
|
<FormInput
|
||||||
inputType="number"
|
inputType="number"
|
||||||
label="Max port"
|
label="Port"
|
||||||
name="tcp_listen.max_port"
|
name="connections.listen_port"
|
||||||
value={config.tcp_listen.max_port}
|
value={config.connections.listen_port}
|
||||||
disabled={config.tcp_listen.disable}
|
disabled={
|
||||||
|
!config.connections.enable_tcp_listen &&
|
||||||
|
!config.connections.enable_utp
|
||||||
|
}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
help="The max port to try to listen on."
|
help="The port to listen on for both TCP and UDP (if enabled)."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormInput
|
||||||
|
label="Peer connect timeout (seconds)"
|
||||||
|
inputType="number"
|
||||||
|
name="connections.peer_connect_timeout"
|
||||||
|
value={config.connections.peer_connect_timeout}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
help="How much to wait for outgoing connections to connect. Default is low to prefer faster peers."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormInput
|
||||||
|
label="Peer read/write timeout (seconds)"
|
||||||
|
inputType="number"
|
||||||
|
name="connections.peer_read_write_timeout"
|
||||||
|
value={config.connections.peer_read_write_timeout}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
help="Peer socket read/write timeout."
|
||||||
/>
|
/>
|
||||||
</Fieldset>
|
</Fieldset>
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
@ -378,28 +412,6 @@ Might be useful e.g. if rqbit upload consumes all your upload bandwidth and inte
|
||||||
</Fieldset>
|
</Fieldset>
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab name="Peer options" currentTab={tab}>
|
|
||||||
<Fieldset>
|
|
||||||
<FormInput
|
|
||||||
label="Connect timeout (seconds)"
|
|
||||||
inputType="number"
|
|
||||||
name="peer_opts.connect_timeout"
|
|
||||||
value={config.peer_opts.connect_timeout}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
help="How much to wait for outgoing connections to connect. Default is low to prefer faster peers."
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormInput
|
|
||||||
label="Read/write timeout (seconds)"
|
|
||||||
inputType="number"
|
|
||||||
name="peer_opts.read_write_timeout"
|
|
||||||
value={config.peer_opts.read_write_timeout}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
help="Peer socket read/write timeout."
|
|
||||||
/>
|
|
||||||
</Fieldset>
|
|
||||||
</Tab>
|
|
||||||
|
|
||||||
<Tab name="HTTP API" currentTab={tab}>
|
<Tab name="HTTP API" currentTab={tab}>
|
||||||
<Fieldset>
|
<Fieldset>
|
||||||
<FormCheck
|
<FormCheck
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue