Name update

This commit is contained in:
Miles Ward
2026-05-21 02:13:08 -04:00
parent 91848e02e3
commit 115ba779da
37 changed files with 1387 additions and 589 deletions
+49 -15
View File
@@ -45,7 +45,12 @@ impl TftpServer {
clients: Arc<ClientRegistry>,
metrics: openpxe_core::Metrics,
) -> Self {
Self { bind, port, clients, metrics }
Self {
bind,
port,
clients,
metrics,
}
}
pub async fn run(self) -> anyhow::Result<()> {
@@ -86,7 +91,9 @@ async fn handle_rrq(
let Some(req) = parse_rrq(&packet) else {
return Ok(());
};
let Request { filename, options, .. } = req;
let Request {
filename, options, ..
} = req;
// Per-transfer ephemeral socket.
let sock = bind_udp(bind_ip, 0)?;
@@ -98,7 +105,9 @@ async fn handle_rrq(
&peer.ip().to_string(),
Some(peer.ip()),
None,
ClientEvent::TftpRead { file: filename.clone() },
ClientEvent::TftpRead {
file: filename.clone(),
},
);
return Ok(());
};
@@ -112,7 +121,9 @@ async fn handle_rrq(
&peer.ip().to_string(),
Some(peer.ip()),
None,
ClientEvent::TftpRead { file: filename.clone() },
ClientEvent::TftpRead {
file: filename.clone(),
},
);
// Negotiate options.
@@ -173,7 +184,9 @@ async fn handle_rrq(
// Send one window worth of DATA.
for _ in 0..window {
if offset >= total { break; }
if offset >= total {
break;
}
let end = (offset + blksize).min(total);
let chunk = &file_bytes[offset..end];
let pkt = encode_data(block_no, chunk);
@@ -255,20 +268,30 @@ struct Request {
}
fn parse_rrq(pkt: &[u8]) -> Option<Request> {
if pkt.len() < 4 { return None; }
if pkt.len() < 4 {
return None;
}
let op = u16::from_be_bytes([pkt[0], pkt[1]]);
if op != OP_RRQ { return None; }
if op != OP_RRQ {
return None;
}
let mut rest = &pkt[2..];
let filename = read_cstr(&mut rest)?;
let mode = read_cstr(&mut rest)?;
let mut options = Vec::new();
while !rest.is_empty() {
let Some(k) = read_cstr(&mut rest) else { break };
if k.is_empty() { break; }
if k.is_empty() {
break;
}
let v = read_cstr(&mut rest).unwrap_or_default();
options.push((k.to_ascii_lowercase(), v));
}
Some(Request { filename, mode, options })
Some(Request {
filename,
mode,
options,
})
}
fn read_cstr(buf: &mut &[u8]) -> Option<String> {
@@ -316,8 +339,12 @@ async fn recv_ack(sock: &UdpSocket, peer: SocketAddr) -> anyhow::Result<u16> {
let mut buf = [0u8; 32];
loop {
let (n, from) = sock.recv_from(&mut buf).await?;
if from.ip() != peer.ip() { continue; }
if n < 4 { continue; }
if from.ip() != peer.ip() {
continue;
}
if n < 4 {
continue;
}
let op = u16::from_be_bytes([buf[0], buf[1]]);
match op {
OP_ACK => return Ok(u16::from_be_bytes([buf[2], buf[3]])),
@@ -344,14 +371,19 @@ async fn wait_for_ack(
Ok(Ok(_)) => {}
Ok(Err(_)) | Err(_) => {
tries += 1;
if tries > 5 { return Ok(false); }
if tries > 5 {
return Ok(false);
}
}
}
}
}
fn bind_udp(bind: IpAddr, port: u16) -> anyhow::Result<UdpSocket> {
let domain = match bind { IpAddr::V4(_) => Domain::IPV4, IpAddr::V6(_) => Domain::IPV6 };
let domain = match bind {
IpAddr::V4(_) => Domain::IPV4,
IpAddr::V6(_) => Domain::IPV6,
};
let sock = Socket::new(domain, Type::DGRAM, Some(Protocol::UDP))?;
sock.set_reuse_address(true)?;
sock.set_nonblocking(true)?;
@@ -382,7 +414,9 @@ pub fn plan_window(
let mut o = offset;
let mut b = starting_block;
for _ in 0..window {
if o >= total { break; }
if o >= total {
break;
}
let end = (o + blksize).min(total);
out.push((b, end - o));
o = end;
@@ -453,7 +487,7 @@ mod tests {
assert_eq!(p, vec![(65534, 1024), (65535, 1024)]);
let p2 = plan_window(2048, 2048, 1024, 2, 0);
assert!(p2.is_empty()); // nothing past EOF
// And a cross-boundary case:
// And a cross-boundary case:
let p3 = plan_window(3072, 0, 1024, 3, 65535);
assert_eq!(p3, vec![(65535, 1024), (0, 1024), (1, 1024)]);
}