allenap_libtftp/
packet.rs

1extern crate byteorder;
2
3use std::error;
4use std::fmt;
5use std::io;
6use std::result;
7
8use super::options::Options;
9use super::packetreader;
10use super::packetwriter;
11
12
13/// An error reading, parsing, or writing a packet.
14#[derive(Debug,PartialEq)]
15pub enum Error {
16    /// The operation is invalid / not recognised.
17    InvalidOpCode(u16),
18    /// The transfer mode is invalid / not recognised.
19    InvalidTransferMode(String),
20    /// The error code is invalid / not recognised.
21    InvalidErrorCode(u16),
22    /// The options are invalid / not recognised.
23    ///
24    /// Okay, perhaps *not recognised* is not appropriate here, because
25    /// the TFTP RFCs state that unrecognised options should be ignored.
26    /// Only recognised options are ackowledged in an `OACK` packet,
27    /// meaning that both sides know the options that the other side
28    /// understands and does not understand before the transfer begins.
29    InvalidOptions(String),
30    /// A packet could not be read / deserialised.
31    ReadError(packetreader::Error),
32    /// A packet could not be written / serialised.
33    WriteError(packetwriter::Error),
34}
35
36
37impl fmt::Display for Error {
38    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39        match *self {
40            Error::InvalidOpCode(opcode) =>
41                write!(f, "invalid operation: {}", opcode),
42            Error::InvalidTransferMode(ref txmode) =>
43                write!(f, "invalid transfer mode: {:?}", txmode),
44            Error::InvalidErrorCode(errcode) =>
45                write!(f, "invalid error code: {}", errcode),
46            Error::InvalidOptions(ref options) =>
47                write!(f, "invalid options: {:?}", options),
48            Error::ReadError(ref error) =>
49                write!(f, "packet could not be read: {:?}", error),
50            Error::WriteError(ref error) =>
51                write!(f, "packet could not be written: {:?}", error),
52        }
53    }
54}
55
56
57impl error::Error for Error {
58    fn description(&self) -> &str {
59        "tftp packet error"
60    }
61
62    fn cause(&self) -> Option<&error::Error> {
63        match *self {
64            Error::ReadError(ref error) => Some(error),
65            Error::WriteError(ref error) => Some(error),
66            _ => None,
67        }
68    }
69}
70
71
72impl From<packetreader::Error> for Error {
73    fn from(error: packetreader::Error) -> Error {
74        Error::ReadError(error)
75    }
76}
77
78
79impl From<packetwriter::Error> for Error {
80    fn from(error: packetwriter::Error) -> Error {
81        Error::WriteError(error)
82    }
83}
84
85
86impl From<Error> for io::Error {
87    fn from(error: Error) -> io::Error {
88        io::Error::new(io::ErrorKind::Other, error)
89    }
90}
91
92
93pub type Result<T> = result::Result<T, Error>;
94
95
96/// The operation code that begins every TFTP packet.
97#[derive(Debug)]
98pub enum OpCode {
99    /// Read request.
100    RRQ = 1,
101    /// Write request.
102    WRQ = 2,
103    /// Data.
104    DATA = 3,
105    /// Acknowledgment.
106    ACK = 4,
107    /// Error.
108    ERROR = 5,
109    /// Option Acknowledgment.
110    OACK = 6,
111}
112
113impl OpCode {
114    fn read(buffer: &mut packetreader::PacketReader) -> Result<Self> {
115        let code = buffer.take_u16()?;
116        match Self::from(code) {
117            Some(opcode) => Ok(opcode),
118            None => Err(Error::InvalidOpCode(code)),
119        }
120    }
121
122    pub fn write(self, writer: &mut packetwriter::PacketWriter) -> Result<()> {
123        writer.put_u16(self as u16)?;
124        Ok(())
125    }
126
127    fn from(opcode: u16) -> Option<Self> {
128        use self::OpCode::*;
129        match opcode {
130            1 => Some(RRQ),
131            2 => Some(WRQ),
132            3 => Some(DATA),
133            4 => Some(ACK),
134            5 => Some(ERROR),
135            6 => Some(OACK),
136            _ => None,
137        }
138    }
139}
140
141
142/// A filename as found in a `RRQ` or `WRQ` packet.
143///
144/// In TFTP, filenames are byte strings, transferred as NetASCII. There
145/// is no implicit or explicit encoding, like UTF-8, but this library
146/// makes a choice to parse and encode with UTF-8. This will be correct
147/// for 7-bit ASCII, which likely reflects the intentions of TFTP's
148/// creators, but may cause some incompatibility in real-world use,
149/// hence this choice may be revisited.
150///
151/// NetASCII is an anachronistic fly in the ointment that this library
152/// does not yet even attempt to support.
153#[derive(Debug)]
154pub struct Filename(pub String);
155
156impl Filename {
157    fn read(buffer: &mut packetreader::PacketReader) -> Result<Self> {
158        Ok(Filename(buffer.take_string()?))
159    }
160
161    pub fn write(self, writer: &mut packetwriter::PacketWriter) -> Result<()> {
162        writer.put_string(&self.0)?;
163        Ok(())
164    }
165}
166
167
168/// The transfer mode to use.
169#[derive(Debug)]
170pub enum TransferMode {
171    /// NetASCII is obsolete and potentially **harmful** to your data.
172    NetASCII,
173    /// Octet means transfer bytes unaltered.
174    Octet,
175}
176
177impl TransferMode {
178    fn read(buffer: &mut packetreader::PacketReader) -> Result<Self> {
179        let mode = buffer.take_string()?;
180        match TransferMode::parse(&mode.as_bytes()) {
181            Some(txmode) => Ok(txmode),
182            None => Err(Error::InvalidTransferMode(mode)),
183        }
184    }
185
186    pub fn write(self, writer: &mut packetwriter::PacketWriter) -> Result<()> {
187        writer.put_string(match self {
188            TransferMode::NetASCII => "netascii",
189            TransferMode::Octet => "octet",
190        })?;
191        Ok(())
192    }
193
194    fn parse(buffer: &[u8]) -> Option<Self> {
195        if buffer.eq_ignore_ascii_case("netascii".as_bytes()) {
196            Some(TransferMode::NetASCII)
197        }
198        else if buffer.eq_ignore_ascii_case("octet".as_bytes()) {
199            Some(TransferMode::Octet)
200        }
201        else {
202            None
203        }
204    }
205}
206
207
208/// The block number in a `DATA` or `ACK` packet.
209#[derive(Debug)]
210pub struct BlockNum(pub u16);
211
212impl BlockNum {
213    fn read(buffer: &mut packetreader::PacketReader) -> Result<Self> {
214        let blocknum = buffer.take_u16()?;
215        Ok(BlockNum(blocknum))
216    }
217
218    pub fn write(self, writer: &mut packetwriter::PacketWriter) -> Result<()> {
219        writer.put_u16(self.0)?;
220        Ok(())
221    }
222}
223
224
225/// The payload of a `DATA` packet.
226#[derive(Debug)]
227pub struct Data<'a>(pub &'a [u8]);
228
229impl<'a> Data<'a> {
230    fn read(buffer: &mut packetreader::PacketReader<'a>) -> Result<Self> {
231        let data = buffer.take_remaining()?;
232        Ok(Data(data))
233    }
234
235    pub fn write(self, writer: &mut packetwriter::PacketWriter) -> Result<()> {
236        writer.put_bytes(&self.0)?;
237        Ok(())
238    }
239}
240
241
242/// The code in an `ERROR` packet.
243///
244/// Unless specified otherwise, these codes are all defined in RFC-1350.
245#[derive(Debug)]
246pub enum ErrorCode {
247    /// Not defined, see error message (if any).
248    NotDefined = 0,
249    /// File not found.
250    FileNotFound = 1,
251    /// Access violation.
252    AccessViolation = 2,
253    /// Disk full or allocation exceeded.
254    DiskFull = 3,
255    /// Illegal TFTP operation.
256    IllegalOperation = 4,
257    /// Unknown transfer ID.
258    UnknownTransferId = 5,
259    /// File already exists.
260    FileAlreadyExists = 6,
261    /// No such user.
262    NoSuchUser = 7,
263    /// Options not acceptable. Defined in RFC-2347.
264    BadOptions = 8,
265}
266
267impl ErrorCode {
268    fn read(buffer: &mut packetreader::PacketReader) -> Result<Self> {
269        let code = buffer.take_u16()?;
270        match Self::from(code) {
271            Some(errorcode) => Ok(errorcode),
272            None => Err(Error::InvalidErrorCode(code)),
273        }
274    }
275
276    pub fn write(self, writer: &mut packetwriter::PacketWriter) -> Result<()> {
277        writer.put_u16(self as u16)?;
278        Ok(())
279    }
280
281    fn from(code: u16) -> Option<Self> {
282        use self::ErrorCode::*;
283        match code {
284            0 => Some(NotDefined),
285            1 => Some(FileNotFound),
286            2 => Some(AccessViolation),
287            3 => Some(DiskFull),
288            4 => Some(IllegalOperation),
289            5 => Some(UnknownTransferId),
290            6 => Some(FileAlreadyExists),
291            7 => Some(NoSuchUser),
292            8 => Some(BadOptions),
293            _ => None,
294        }
295    }
296}
297
298
299/// The message in an `ERROR` packet.
300#[derive(Debug)]
301pub struct ErrorMessage(pub String);
302
303impl ErrorMessage {
304    fn read(buffer: &mut packetreader::PacketReader) -> Result<Self> {
305        Ok(ErrorMessage(buffer.take_string()?))
306    }
307
308    pub fn write(self, writer: &mut packetwriter::PacketWriter) -> Result<()> {
309        writer.put_string(&self.0)?;
310        Ok(())
311    }
312}
313
314
315/// A packet of the Trivial File Transfer Protocol.
316#[derive(Debug)]
317pub enum Packet<'a> {
318    Read(Filename, TransferMode, Options),
319    Write(Filename, TransferMode, Options),
320    Data(BlockNum, Data<'a>),
321    Ack(BlockNum),
322    Error(ErrorCode, ErrorMessage),
323    OAck(Options),
324}
325
326impl<'a> Packet<'a> {
327    pub fn parse(buffer: &'a [u8]) -> Result<Self>
328        where Self: 'a
329    {
330        let mut buffer = packetreader::PacketReader::new(&buffer);
331        match OpCode::read(&mut buffer)? {
332            OpCode::RRQ => Ok(Packet::Read(
333                Filename::read(&mut buffer)?,
334                TransferMode::read(&mut buffer)?,
335                Options::read(&mut buffer)?,
336            )),
337            OpCode::WRQ => Ok(Packet::Write(
338                Filename::read(&mut buffer)?,
339                TransferMode::read(&mut buffer)?,
340                Options::read(&mut buffer)?,
341            )),
342            OpCode::DATA => Ok(Packet::Data(
343                BlockNum::read(&mut buffer)?,
344                Data::read(&mut buffer)?,
345            )),
346            OpCode::ACK => Ok(Packet::Ack(
347                BlockNum::read(&mut buffer)?,
348            )),
349            OpCode::ERROR => Ok(Packet::Error(
350                ErrorCode::read(&mut buffer)?,
351                ErrorMessage::read(&mut buffer)?,
352            )),
353            OpCode::OACK => Ok(Packet::OAck(
354                Options::read(&mut buffer)?,
355            )),
356        }
357    }
358
359    pub fn opcode(&self) -> OpCode {
360        match *self {
361            Packet::Read(..) => OpCode::RRQ,
362            Packet::Write(..) => OpCode::WRQ,
363            Packet::Data(..) => OpCode::DATA,
364            Packet::Ack(..) => OpCode::ACK,
365            Packet::Error(..) => OpCode::ERROR,
366            Packet::OAck(..) => OpCode::OACK,
367        }
368    }
369
370    pub fn write(self, mut buffer: &'a mut [u8]) -> Result<usize> {
371        let mut buffer = packetwriter::PacketWriter::new(&mut buffer);
372        self.opcode().write(&mut buffer)?;
373        match self {
374            Packet::Read(filename, mode, options) => {
375                filename.write(&mut buffer)?;
376                mode.write(&mut buffer)?;
377                options.write(&mut buffer)?;
378            },
379            Packet::Write(filename, mode, options) => {
380                filename.write(&mut buffer)?;
381                mode.write(&mut buffer)?;
382                options.write(&mut buffer)?;
383            },
384            Packet::Data(block, data) => {
385                block.write(&mut buffer)?;
386                data.write(&mut buffer)?;
387            },
388            Packet::Ack(block) => {
389                block.write(&mut buffer)?;
390            },
391            Packet::Error(code, message) => {
392                code.write(&mut buffer)?;
393                message.write(&mut buffer)?;
394            },
395            Packet::OAck(options) => {
396                options.write(&mut buffer)?;
397            },
398        };
399        Ok(buffer.pos())
400    }
401}