switch to zerocopy crate. Initial server query debug implementation

This commit is contained in:
soruh 2023-03-28 13:46:38 +02:00
parent eefb943292
commit 1340e87c15
6 changed files with 130 additions and 7 deletions

22
Cargo.lock generated
View File

@ -190,6 +190,7 @@ dependencies = [
"tracing", "tracing",
"tracing-error", "tracing-error",
"tracing-subscriber", "tracing-subscriber",
"zerocopy",
] ]
[[package]] [[package]]
@ -1338,3 +1339,24 @@ name = "windows_x86_64_msvc"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "zerocopy"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236"
dependencies = [
"byteorder",
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]

View File

@ -27,6 +27,7 @@ once_cell = "1.17.1"
eyre = "0.6.8" eyre = "0.6.8"
color-eyre = "0.6.2" color-eyre = "0.6.2"
tracing-error = "0.2.0" tracing-error = "0.2.0"
zerocopy = "0.6.1"
[features] [features]
default = ["debug_server", "tokio_console"] default = ["debug_server", "tokio_console"]

View File

@ -2,9 +2,21 @@ use std::net::SocketAddr;
use eyre::eyre; use eyre::eyre;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
use zerocopy::{AsBytes, FromBytes, LittleEndian, Unaligned};
use crate::packets::{Header, Packet, PacketKind}; use crate::packets::{Header, Packet, PacketKind};
type U16 = zerocopy::U16<LittleEndian>;
type U32 = zerocopy::U32<LittleEndian>;
#[derive(AsBytes)]
#[repr(C)]
struct DynIpUpdate {
number: U32,
pin: U16,
port: U16,
}
/// # Errors /// # Errors
/// - the dyn ip server returns a malformed response or is unreachable /// - the dyn ip server returns a malformed response or is unreachable
/// - the authentication fails /// - the authentication fails
@ -25,18 +37,21 @@ pub async fn dyn_ip_update(
data: Vec::new(), data: Vec::new(),
}; };
packet.data.clear(); packet.data.resize(packet.header.length as usize, 0);
packet.data.reserve(packet.header.length as usize);
packet.data.extend_from_slice(&number.to_le_bytes()); DynIpUpdate {
packet.data.extend_from_slice(&pin.to_le_bytes()); number: number.into(),
packet.data.extend_from_slice(&port.to_le_bytes()); pin: pin.into(),
port: port.into(),
}
.write_to(packet.data.as_mut_slice())
.unwrap();
let mut socket = tokio::net::TcpStream::connect(server).await?; let mut socket = tokio::net::TcpStream::connect(server).await?;
let (mut reader, mut writer) = socket.split(); let (mut reader, mut writer) = socket.split();
packet.send(&mut writer).await?; packet.send(&mut writer).await?;
packet.recv_into(&mut reader).await?; packet.recv_into(&mut reader).await?;
let result = match packet.kind() { let result = match packet.kind() {

View File

@ -15,6 +15,7 @@ use tracing::{info, instrument, trace};
use crate::{ use crate::{
auth::dyn_ip_update, auth::dyn_ip_update,
constants::{AUTH_TIMEOUT, CALL_ACK_TIMEOUT, CALL_TIMEOUT, PING_TIMEOUT, SEND_PING_INTERVAL}, constants::{AUTH_TIMEOUT, CALL_ACK_TIMEOUT, CALL_TIMEOUT, PING_TIMEOUT, SEND_PING_INTERVAL},
debug_server::peer_query,
packets::{Header, Packet, PacketKind, RemConnect, REJECT_OOP, REJECT_TIMEOUT}, packets::{Header, Packet, PacketKind, RemConnect, REJECT_OOP, REJECT_TIMEOUT},
ports::{PortHandler, PortStatus}, ports::{PortHandler, PortStatus},
Config, HandlerMetadata, Config, HandlerMetadata,
@ -328,6 +329,10 @@ pub async fn handler(
info!(%addr, number, port, "authenticated"); info!(%addr, number, port, "authenticated");
let res = peer_query(&config.dyn_ip_server, number).await;
dbg!(&res);
let Some(listener) = handler_metadata.listener.as_mut() else { let Some(listener) = handler_metadata.listener.as_mut() else {
unreachable!("client sucessfully authenticated but did not set handler_metadata.listener"); unreachable!("client sucessfully authenticated but did not set handler_metadata.listener");
}; };

View File

@ -7,6 +7,12 @@ use std::net::SocketAddr;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tracing::error; use tracing::error;
use zerocopy::{AsBytes, FromBytes, LittleEndian, Unaligned};
use eyre::eyre;
use tracing::{debug, instrument};
use crate::packets::{Header, Packet, PacketKind};
use crate::ports::PortHandler; use crate::ports::PortHandler;
use crate::spawn; use crate::spawn;
@ -41,3 +47,77 @@ pub async fn debug_server(addr: SocketAddr, port_handler: Arc<Mutex<PortHandler>
error!(%error, "debug server error"); error!(%error, "debug server error");
} }
} }
type U16 = zerocopy::U16<LittleEndian>;
type U32 = zerocopy::U32<LittleEndian>;
#[derive(AsBytes)]
#[repr(transparent)]
struct PeerQuery {
number: U32,
}
#[derive(FromBytes, Unaligned, Debug)]
#[repr(packed)]
struct PeerReply {
number: U32,
name: [u8; 40],
flags: U16,
kind: u8,
hostname: [u8; 40],
ipaddress: [u8; 4],
port: U16,
extension: u8,
pin: U16,
timestamp: U32,
}
#[instrument]
pub async fn peer_query(server: &SocketAddr, number: u32) -> eyre::Result<Option<String>> {
debug!(%number, "looking up");
let mut packet = Packet {
header: Header {
kind: 3, // Peer Query
length: 4,
},
data: Vec::new(),
};
packet.data.clear();
packet.data.resize(packet.header.length as usize, 0);
PeerQuery {
number: number.into(),
}
.write_to(packet.data.as_mut_slice())
.unwrap();
let mut socket = tokio::net::TcpStream::connect(server).await?;
let (mut reader, mut writer) = socket.split();
packet.send(&mut writer).await?;
packet.recv_into(&mut reader).await?;
dbg!(&packet);
if packet.kind().raw() == 5 {
// PeerReply
let reply = PeerReply::read_from(packet.data.as_slice());
dbg!(&reply);
Ok(reply.and_then(|x| {
let i = x
.name
.iter()
.enumerate()
.find_map(|(i, c)| (*c == 0).then_some(i))
.unwrap_or(x.name.len());
std::str::from_utf8(&x.name[..i]).ok().map(|x| x.to_owned())
}))
} else {
Ok(None)
}
}

View File

@ -465,7 +465,7 @@ impl PortHandler {
}; };
if let Some(port) = port { if let Some(port) = port {
info!(port, "allocated port"); info!(port, "allocated");
} }
port port