Skip to content

Commit

Permalink
Merge #202: Axum HTTP tracker: announce request in listed mode
Browse files Browse the repository at this point in the history
cd14c6b feat(http): [#200] announce request in listed mode (Jose Celano)
ea24973 refactor(http): [#200] move function to Tracker (Jose Celano)

Pull request description:

  For the new Auxm HTTP tracker implementation.

Top commit has no ACKs.

Tree-SHA512: 37bd2c98c8ab1a016e9fb1945b032c4811496e36a7d73c78645663a0a62c048d8dc3e954e4c4297faacb2f7d164f3a9cc13a0e76a0f1c75f75d654c4320eac8f
  • Loading branch information
josecelano committed Mar 1, 2023
2 parents d5e52ec + cd14c6b commit fa5d14a
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 22 deletions.
10 changes: 8 additions & 2 deletions src/http/axum_implementation/handlers/announce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub async fn handle_without_key(
) -> Response {
debug!("http announce request: {:#?}", announce_request);

if tracker.is_private() {
if tracker.requires_authentication() {
return responses::error::Error::from(auth::Error::MissingAuthKey {
location: Location::caller(),
})
Expand All @@ -47,6 +47,7 @@ pub async fn handle_with_key(
) -> Response {
debug!("http announce request: {:#?}", announce_request);

// todo: extract to Axum extractor. Duplicate code in `scrape` handler.
let Ok(key_id) = key_id_param.value().parse::<KeyId>() else {
return responses::error::Error::from(
auth::Error::InvalidKeyFormat {
Expand All @@ -55,7 +56,7 @@ pub async fn handle_with_key(
.into_response()
};

match auth::authenticate(&key_id, &tracker).await {
match tracker.authenticate(&key_id).await {
Ok(_) => (),
Err(error) => return responses::error::Error::from(error).into_response(),
}
Expand All @@ -64,6 +65,11 @@ pub async fn handle_with_key(
}

async fn handle(tracker: &Arc<Tracker>, announce_request: &Announce, remote_client_ip: &RemoteClientIp) -> Response {
match tracker.authorize(&announce_request.info_hash).await {
Ok(_) => (),
Err(error) => return responses::error::Error::from(error).into_response(),
}

let peer_ip = match peer_ip::resolve(tracker.config.on_reverse_proxy, remote_client_ip) {
Ok(peer_ip) => peer_ip,
Err(err) => return err,
Expand Down
15 changes: 1 addition & 14 deletions src/http/axum_implementation/handlers/auth.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use std::panic::Location;
use std::sync::Arc;

use serde::Deserialize;
use thiserror::Error;

use crate::http::axum_implementation::responses;
use crate::tracker::auth::{self, KeyId};
use crate::tracker::Tracker;
use crate::tracker::auth;

#[derive(Deserialize)]
pub struct KeyIdParam(String);
Expand All @@ -26,17 +24,6 @@ pub enum Error {
InvalidKeyFormat { location: &'static Location<'static> },
}

/// # Errors
///
/// Will return an error if the the authentication key cannot be verified.
pub async fn authenticate(key_id: &KeyId, tracker: &Arc<Tracker>) -> Result<(), auth::Error> {
if tracker.is_private() {
tracker.verify_auth_key(key_id).await
} else {
Ok(())
}
}

impl From<Error> for responses::error::Error {
fn from(err: Error) -> Self {
responses::error::Error {
Expand Down
11 changes: 11 additions & 0 deletions src/http/axum_implementation/handlers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
use super::responses;
use crate::tracker::error::Error;

pub mod announce;
pub mod auth;
pub mod scrape;
pub mod status;

impl From<Error> for responses::error::Error {
fn from(err: Error) -> Self {
responses::error::Error {
failure_reason: format!("Tracker error: {err}"),
}
}
}
5 changes: 3 additions & 2 deletions src/http/axum_implementation/handlers/scrape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub async fn handle_without_key(
) -> Response {
debug!("http scrape request: {:#?}", &scrape_request);

if tracker.is_private() {
if tracker.requires_authentication() {
return handle_fake_scrape(&tracker, &scrape_request, &remote_client_ip).await;
}

Expand All @@ -39,6 +39,7 @@ pub async fn handle_with_key(
) -> Response {
debug!("http scrape request: {:#?}", &scrape_request);

// todo: extract to Axum extractor. Duplicate code in `announce` handler.
let Ok(key_id) = key_id_param.value().parse::<KeyId>() else {
return responses::error::Error::from(
auth::Error::InvalidKeyFormat {
Expand All @@ -47,7 +48,7 @@ pub async fn handle_with_key(
.into_response()
};

match auth::authenticate(&key_id, &tracker).await {
match tracker.authenticate(&key_id).await {
Ok(_) => (),
Err(_) => return handle_fake_scrape(&tracker, &scrape_request, &remote_client_ip).await,
}
Expand Down
36 changes: 36 additions & 0 deletions src/tracker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ impl Tracker {
self.mode == mode::Mode::Listed || self.mode == mode::Mode::PrivateListed
}

pub fn requires_authentication(&self) -> bool {
self.is_private()
}

/// It handles an announce request.
///
/// BEP 03: [The `BitTorrent` Protocol Specification](https://www.bittorrent.org/beps/bep_0003.html).
Expand Down Expand Up @@ -334,6 +338,38 @@ impl Tracker {
Ok(())
}

/// # Errors
///
/// Will return an error if the the authentication key cannot be verified.
pub async fn authenticate(&self, key_id: &KeyId) -> Result<(), auth::Error> {
if self.is_private() {
self.verify_auth_key(key_id).await
} else {
Ok(())
}
}

/// The only authorization process is the whitelist.
///
/// # Errors
///
/// Will return an error if the tracker is running in `listed` mode
/// and the infohash is not whitelisted.
pub async fn authorize(&self, info_hash: &InfoHash) -> Result<(), Error> {
if !self.is_whitelisted() {
return Ok(());
}

if self.is_info_hash_whitelisted(info_hash).await {
return Ok(());
}

return Err(Error::TorrentNotWhitelisted {
info_hash: *info_hash,
location: Location::caller(),
});
}

/// Loading the torrents from database into memory
///
/// # Errors
Expand Down
6 changes: 2 additions & 4 deletions tests/http_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2403,8 +2403,7 @@ mod axum_http_tracker_server {
use crate::http::requests::announce::QueryBuilder;
use crate::http::server::start_whitelisted_http_tracker;

//#[tokio::test]
#[allow(dead_code)]
#[tokio::test]
async fn should_fail_if_the_torrent_is_not_in_the_whitelist() {
let http_tracker_server = start_whitelisted_http_tracker(Version::Axum).await;

Expand All @@ -2417,8 +2416,7 @@ mod axum_http_tracker_server {
assert_torrent_not_in_whitelist_error_response(response).await;
}

//#[tokio::test]
#[allow(dead_code)]
#[tokio::test]
async fn should_allow_announcing_a_whitelisted_torrent() {
let http_tracker_server = start_whitelisted_http_tracker(Version::Axum).await;

Expand Down

0 comments on commit fa5d14a

Please sign in to comment.