aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
authorReiner Herrmann <reiner@reiner-h.de>2019-03-03 17:50:54 +0100
committerReiner Herrmann <reiner@reiner-h.de>2019-03-03 17:50:54 +0100
commit393ca44d250ddf20f343ad532ebdff8da1085927 (patch)
tree7efd7ea2c3076782a16b4a1da5fc4059fc804416 /src/lib.rs
parent150d6635b5ed86ecdd517942cb09be444a1b132e (diff)
Parse received errors and other minor error logging improvements
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs46
1 files changed, 43 insertions, 3 deletions
diff --git a/src/lib.rs b/src/lib.rs
index f9fc57e..2d5523a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -69,21 +69,60 @@ impl Tftp {
buf.push(0x00);
}
+ pub fn parse_error(&self, buf: &[u8]) -> std::io::Error {
+ let mut kind = std::io::ErrorKind::InvalidData;
+ let mut error = String::from("Invalid packet received");
+
+ if buf.len() < 5 {
+ return std::io::Error::new(kind, error);
+ }
+
+ let opcode = u16::from_be_bytes([buf[0], buf[1]]);
+ if opcode != Opcodes::ERROR as u16 {
+ return std::io::Error::new(kind, error);
+ }
+
+ let errorcode = u16::from_be_bytes([buf[2], buf[3]]);
+ error = match String::from_utf8(buf[4 ..].to_vec()) {
+ Ok(e) => e,
+ Err(_) => return std::io::Error::new(kind, error),
+ };
+
+ kind = match errorcode {
+ 1 => std::io::ErrorKind::NotFound,
+ 2 => std::io::ErrorKind::PermissionDenied,
+ 3 => std::io::ErrorKind::UnexpectedEof,
+ 4 => std::io::ErrorKind::InvalidData,
+ 5 => std::io::ErrorKind::InvalidInput,
+ 6 => std::io::ErrorKind::AlreadyExists,
+ 7 => std::io::ErrorKind::NotFound,
+ _ => std::io::ErrorKind::InvalidData,
+ };
+
+ return std::io::Error::new(kind, error);
+ }
+
fn wait_for_ack(&self, sock: &UdpSocket, expected_block: u16) -> Result<bool, io::Error> {
- let mut buf = [0; 4];
- match sock.recv(&mut buf) {
- Ok(_) => (),
+ let mut buf = [0; 512];
+ let len = match sock.recv(&mut buf) {
+ Ok(l) => l,
Err(ref error) if [io::ErrorKind::WouldBlock, io::ErrorKind::TimedOut].contains(&error.kind()) => {
return Ok(false);
}
Err(err) => return Err(err),
};
+ if len < 4 {
+ return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid data received"));
+ }
+
let opcode = u16::from_be_bytes([buf[0], buf[1]]);
let block_nr = u16::from_be_bytes([buf[2], buf[3]]);
if opcode == Opcodes::ACK as u16 && block_nr == expected_block {
return Ok(true)
+ } else if opcode == Opcodes::ERROR as u16 {
+ return Err(self.parse_error(&buf[4 ..]));
}
Ok(false)
@@ -312,6 +351,7 @@ impl Tftp {
let _opcode = match u16::from_be_bytes([buf[0], buf[1]]) {
opc if opc == Opcodes::DATA as u16 => (),
+ opc if opc == Opcodes::ERROR as u16 => return Err(self.parse_error(&buf[.. len])),
_ => return Err(io::Error::new(io::ErrorKind::Other, "unexpected opcode")),
};
if u16::from_be_bytes([buf[2], buf[3]]) != block_nr {