aquatic/aquatic_udp/src/workers/socket/responses.rs
2022-04-16 00:15:33 +02:00

104 lines
3.3 KiB
Rust

use std::io::Cursor;
use std::sync::atomic::Ordering;
use std::vec::Drain;
use crossbeam_channel::Receiver;
use mio::net::UdpSocket;
use aquatic_common::CanonicalSocketAddr;
use aquatic_udp_protocol::*;
use crate::common::*;
use crate::config::Config;
use super::common::PendingScrapeResponseSlab;
pub fn send_responses(
state: &State,
config: &Config,
socket: &mut UdpSocket,
buffer: &mut [u8],
response_receiver: &Receiver<(ConnectedResponse, CanonicalSocketAddr)>,
pending_scrape_responses: &mut PendingScrapeResponseSlab,
local_responses: Drain<(Response, CanonicalSocketAddr)>,
) {
for (response, addr) in local_responses {
send_response(state, config, socket, buffer, response, addr);
}
for (response, addr) in response_receiver.try_iter() {
let opt_response = match response {
ConnectedResponse::Scrape(r) => pending_scrape_responses
.add_and_get_finished(r)
.map(Response::Scrape),
ConnectedResponse::AnnounceIpv4(r) => Some(Response::AnnounceIpv4(r)),
ConnectedResponse::AnnounceIpv6(r) => Some(Response::AnnounceIpv6(r)),
};
if let Some(response) = opt_response {
send_response(state, config, socket, buffer, response, addr);
}
}
}
fn send_response(
state: &State,
config: &Config,
socket: &mut UdpSocket,
buffer: &mut [u8],
response: Response,
addr: CanonicalSocketAddr,
) {
let mut cursor = Cursor::new(buffer);
let canonical_addr_is_ipv4 = addr.is_ipv4();
let addr = if config.network.address.is_ipv4() {
addr.get_ipv4()
.expect("found peer ipv6 address while running bound to ipv4 address")
} else {
addr.get_ipv6_mapped()
};
match response.write(&mut cursor) {
Ok(()) => {
let amt = cursor.position() as usize;
match socket.send_to(&cursor.get_ref()[..amt], addr) {
Ok(amt) if config.statistics.active() => {
let stats = if canonical_addr_is_ipv4 {
&state.statistics_ipv4
} else {
&state.statistics_ipv6
};
stats.bytes_sent.fetch_add(amt, Ordering::Relaxed);
match response {
Response::Connect(_) => {
stats.responses_sent_connect.fetch_add(1, Ordering::Relaxed);
}
Response::AnnounceIpv4(_) | Response::AnnounceIpv6(_) => {
stats
.responses_sent_announce
.fetch_add(1, Ordering::Relaxed);
}
Response::Scrape(_) => {
stats.responses_sent_scrape.fetch_add(1, Ordering::Relaxed);
}
Response::Error(_) => {
stats.responses_sent_error.fetch_add(1, Ordering::Relaxed);
}
}
}
Ok(_) => {}
Err(err) => {
::log::warn!("send_to error: {:#}", err);
}
}
}
Err(err) => {
::log::error!("Response::write error: {:?}", err);
}
}
}