Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] option to disable upload #223

Merged
merged 3 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/librqbit/src/peer_connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{read_buf::ReadBuf, spawn_utils::BlockingSpawner, stream_connect::Str

pub trait PeerConnectionHandler {
fn on_connected(&self, _connection_time: Duration) {}
fn get_have_bytes(&self) -> u64;
fn should_send_bitfield(&self) -> bool;
fn serialize_bitfield_message_to_buf(&self, buf: &mut Vec<u8>) -> anyhow::Result<usize>;
fn on_handshake<B>(&self, handshake: Handshake<B>) -> anyhow::Result<()>;
fn on_extended_handshake(
Expand Down Expand Up @@ -268,7 +268,7 @@ impl<H: PeerConnectionHandler> PeerConnection<H> {
.keep_alive_interval
.unwrap_or_else(|| Duration::from_secs(120));

if self.handler.get_have_bytes() > 0 {
if self.handler.should_send_bitfield() {
let len = self
.handler
.serialize_bitfield_message_to_buf(&mut write_buf)?;
Expand Down
4 changes: 2 additions & 2 deletions crates/librqbit/src/peer_info_reader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ struct Handler {
}

impl PeerConnectionHandler for Handler {
fn get_have_bytes(&self) -> u64 {
0
fn should_send_bitfield(&self) -> bool {
false
}

fn serialize_bitfield_message_to_buf(&self, _buf: &mut Vec<u8>) -> anyhow::Result<usize> {
Expand Down
10 changes: 10 additions & 0 deletions crates/librqbit/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ pub struct Session {

pub(crate) stats: SessionStats,

disable_upload: bool,

// This is stored for all tasks to stop when session is dropped.
_cancellation_token_drop_guard: DropGuard,
}
Expand Down Expand Up @@ -410,6 +412,8 @@ pub struct SessionOptions {

// the root span to use. If not set will be None.
pub root_span: Option<Span>,

pub disable_upload: bool,
}

async fn create_tcp_listener(
Expand Down Expand Up @@ -485,6 +489,10 @@ impl Session {
let peer_id = opts.peer_id.unwrap_or_else(generate_peer_id);
let token = opts.cancellation_token.take().unwrap_or_default();

if opts.disable_upload {
warn!("uploading disabled");
}

let (tcp_listener, tcp_listen_port) =
if let Some(port_range) = opts.listen_port_range.clone() {
let (l, p) = create_tcp_listener(port_range)
Expand Down Expand Up @@ -618,6 +626,7 @@ impl Session {
concurrent_initialize_semaphore: Arc::new(tokio::sync::Semaphore::new(
opts.concurrent_init_limit.unwrap_or(3),
)),
disable_upload: opts.disable_upload,
});

if let Some(mut disk_write_rx) = disk_write_rx {
Expand Down Expand Up @@ -1141,6 +1150,7 @@ impl Session {
allow_overwrite: opts.overwrite,
output_folder,
disk_write_queue: self.disk_write_tx.clone(),
disable_upload: self.disable_upload,
},
connector: self.connector.clone(),
session: Arc::downgrade(self),
Expand Down
23 changes: 13 additions & 10 deletions crates/librqbit/src/torrent_state/live/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,14 +173,6 @@ impl TorrentStateLocked {
}
}

#[derive(Default)]
pub struct TorrentStateOptions {
#[allow(dead_code)]
pub peer_connect_timeout: Option<Duration>,
#[allow(dead_code)]
pub peer_read_write_timeout: Option<Duration>,
}

const FLUSH_BITV_EVERY_BYTES: u64 = 16 * 1024 * 1024;

pub struct TorrentStateLive {
Expand Down Expand Up @@ -929,11 +921,18 @@ impl<'a> PeerConnectionHandler for &'a PeerHandler {
Ok(())
}

fn get_have_bytes(&self) -> u64 {
self.state.get_approx_have_bytes()
fn should_send_bitfield(&self) -> bool {
if self.state.torrent().options.disable_upload {
return false;
}

self.state.get_approx_have_bytes() > 0
}

fn should_transmit_have(&self, id: ValidPieceIndex) -> bool {
if self.state.torrent.options.disable_upload {
return false;
}
let have = self
.state
.peers
Expand Down Expand Up @@ -1164,6 +1163,10 @@ impl PeerHandler {
}

fn on_download_request(&self, request: Request) -> anyhow::Result<()> {
if self.state.torrent().options.disable_upload {
anyhow::bail!("upload disabled, but peer requested a piece")
}

let piece_index = match self.state.lengths.validate_piece_index(request.index) {
Some(p) => p,
None => {
Expand Down
1 change: 1 addition & 0 deletions crates/librqbit/src/torrent_state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ pub(crate) struct ManagedTorrentOptions {
pub allow_overwrite: bool,
pub output_folder: PathBuf,
pub disk_write_queue: Option<DiskWorkQueueSender>,
pub disable_upload: bool,
}

/// Common information about torrent shared among all possible states.
Expand Down
9 changes: 9 additions & 0 deletions crates/rqbit/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,14 @@ struct Opts {
#[cfg(not(target_os = "windows"))]
#[arg(long, env = "RQBIT_UMASK", value_parser=parse_umask)]
umask: Option<libc::mode_t>,

/// Disable uploading entirely. If this is set, rqbit won't share piece availability
/// and will disconnect on download request.
///
/// Might be useful e.g. if rqbit upload consumes all your upload bandwidth and interferes
/// with your other Internet usage.
#[arg(long, env = "RQBIT_DISABLE_UPLOAD")]
disable_upload: bool,
}

#[derive(Parser)]
Expand Down Expand Up @@ -454,6 +462,7 @@ async fn async_main(opts: Opts, cancel: CancellationToken) -> anyhow::Result<()>
root_span: None,
fastresume: false,
cancellation_token: Some(cancel.clone()),
disable_upload: opts.disable_upload,
};

let stats_printer = |session: Arc<Session>| async move {
Expand Down
1 change: 1 addition & 0 deletions desktop/src-tauri/Cargo.lock

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

5 changes: 5 additions & 0 deletions desktop/src-tauri/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ pub struct RqbitDesktopConfigUpnp {
#[serde(default)]
pub struct RqbitDesktopConfig {
pub default_download_location: PathBuf,

#[serde(default)]
pub disable_upload: bool,

pub dht: RqbitDesktopConfigDht,
pub tcp_listen: RqbitDesktopConfigTcpListen,
pub upnp: RqbitDesktopConfigUpnp,
Expand All @@ -167,6 +171,7 @@ impl Default for RqbitDesktopConfig {
persistence: Default::default(),
peer_opts: Default::default(),
http_api: Default::default(),
disable_upload: false,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions desktop/src/configuration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ interface RqbitDesktopConfigUpnp {

export interface RqbitDesktopConfig {
default_download_location: PathLike;
disable_upload: boolean;
dht: RqbitDesktopConfigDht;
tcp_listen: RqbitDesktopConfigTcpListen;
upnp: RqbitDesktopConfigUpnp;
Expand Down
10 changes: 10 additions & 0 deletions desktop/src/configure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,16 @@ export const ConfigModal: React.FC<{
onChange={handleInputChange}
help="Where to download torrents by default. You can override this per torrent."
/>

<FormCheck
label="Disable upload"
name="disable_upload"
checked={config.disable_upload}
onChange={handleToggleChange}
help="Disable uploading entirely. If this is set, rqbit won't share piece availability and will disconnect on download request.

Might be useful e.g. if rqbit upload consumes all your upload bandwidth and interferes with your other Internet usage."
/>
</Tab>

<Tab name="DHT" currentTab={tab}>
Expand Down