aquatic_ws: convert ipv4-mapped ipv6 addresses to ipv4 (for state split)

This commit is contained in:
Joakim Frostegård 2020-08-01 00:08:18 +02:00
parent 4067e420c3
commit 809d16919d
4 changed files with 25 additions and 14 deletions

View file

@ -2,9 +2,6 @@
## General
* use ipv4-mapped address functions, but I should check that they really
work as they really work as they should. All announces over ipv4 should
go to ipv4 map, all over ipv6 to ipv6 map
* init logging in cli helper crate?
## aquatic_http_load_test
@ -30,13 +27,14 @@
write actually block here? And what action should be taken then?
## aquatic_ws
* test transfer again with crossbeam-channel
* test transfer again with changes made:
* crossbeam-channel
* ipv6/ipv4 mapping
* is 'key' sent in announce request? if so, maybe handle it like in
aquatic_http (including ip uniqueness part of peer map key)
* established connections do not get valid_until updated, I think?
* tests
* use enum as return type for handshake machine
* ipv4 and ipv6 state split: think about this more..
## aquatic_udp
* mio: set oneshot for epoll and kqueue? otherwise, stop reregistering?

View file

@ -1,4 +1,4 @@
use std::net::SocketAddr;
use std::net::{SocketAddr, IpAddr};
use std::sync::Arc;
use crossbeam_channel::{Sender, Receiver};
@ -18,7 +18,10 @@ pub struct ConnectionMeta {
/// Index of socket worker responsible for this connection. Required for
/// sending back response through correct channel to correct worker.
pub worker_index: usize,
pub peer_addr: SocketAddr,
/// Peer address as received from socket, meaning it wasn't converted to
/// an IPv4 address if it was a IPv4-mapped IPv6 address
pub naive_peer_addr: SocketAddr,
pub converted_peer_ip: IpAddr,
pub poll_token: Token,
}

View file

@ -93,7 +93,7 @@ pub fn handle_announce_requests(
let valid_until = ValidUntil::new(config.cleaning.max_peer_age);
for (request_sender_meta, request) in requests {
let torrent_data: &mut TorrentData = if request_sender_meta.peer_addr.is_ipv4(){
let torrent_data: &mut TorrentData = if request_sender_meta.converted_peer_ip.is_ipv4(){
torrent_maps.ipv4.entry(request.info_hash).or_default()
} else {
torrent_maps.ipv6.entry(request.info_hash).or_default()
@ -102,9 +102,11 @@ pub fn handle_announce_requests(
// If there is already a peer with this peer_id, check that socket
// addr is same as that of request sender. Otherwise, ignore request.
// Since peers have access to each others peer_id's, they could send
// requests using them, causing all sorts of issues.
// requests using them, causing all sorts of issues. Checking naive
// (non-converted) socket addresses is enough, since state is split
// on converted peer ip.
if let Some(previous_peer) = torrent_data.peers.get(&request.peer_id){
if request_sender_meta.peer_addr != previous_peer.connection_meta.peer_addr {
if request_sender_meta.naive_peer_addr != previous_peer.connection_meta.naive_peer_addr {
continue;
}
}
@ -177,7 +179,7 @@ pub fn handle_announce_requests(
// possible to write a new version of that function which isn't
// shared with aquatic_udp and goes about it differently
// though.
if request_sender_meta.peer_addr == offer_receiver.connection_meta.peer_addr {
if request_sender_meta.naive_peer_addr == offer_receiver.connection_meta.naive_peer_addr {
continue;
}
@ -244,7 +246,7 @@ pub fn handle_scrape_requests(
files: HashMap::with_capacity(num_to_take),
};
let torrent_map: &mut TorrentMap = if meta.peer_addr.is_ipv4(){
let torrent_map: &mut TorrentMap = if meta.converted_peer_ip.is_ipv4(){
&mut torrent_maps.ipv4
} else {
&mut torrent_maps.ipv6

View file

@ -9,6 +9,8 @@ use mio::{Events, Poll, Interest, Token};
use mio::net::TcpListener;
use tungstenite::protocol::WebSocketConfig;
use aquatic_common::convert_ipv4_mapped_ipv6;
use crate::common::*;
use crate::config::Config;
use crate::protocol::*;
@ -187,10 +189,16 @@ pub fn run_handshakes_and_read_messages(
match established_ws.ws.read_message(){
Ok(ws_message) => {
if let Some(in_message) = InMessage::from_ws_message(ws_message){
let naive_peer_addr = established_ws.peer_addr;
let converted_peer_ip = convert_ipv4_mapped_ipv6(
naive_peer_addr.ip()
);
let meta = ConnectionMeta {
worker_index: socket_worker_index,
poll_token,
peer_addr: established_ws.peer_addr
naive_peer_addr,
converted_peer_ip,
};
debug!("read message");
@ -249,7 +257,7 @@ pub fn send_out_messages(
.and_then(Connection::get_established_ws);
if let Some(established_ws) = opt_established_ws {
if established_ws.peer_addr != meta.peer_addr {
if established_ws.peer_addr != meta.naive_peer_addr {
info!("socket worker error: peer socket addrs didn't match");
continue;