tftpd/
packet.rs

1use std::error::Error;
2use std::str::FromStr;
3use std::fmt;
4
5use crate::{Convert, TransferOption, OptionType};
6
7/// Packet `enum` represents the valid TFTP packet types.
8///
9/// This `enum` has function implementaions for serializing [`Packet`]s into
10///  [`Vec<u8>`]s and deserializing [`u8`] slices to [`Packet`]s.
11///
12/// # Example
13/// ```rust
14/// use tftpd::Packet;
15///
16/// let packet = Packet::Data { block_num: 15, data: vec![0x01, 0x02, 0x03] };
17///
18/// assert_eq!(packet.serialize().unwrap(), vec![0x00, 0x03, 0x00, 0x0F, 0x01, 0x02, 0x03]);
19/// assert_eq!(Packet::deserialize(&[0x00, 0x03, 0x00, 0x0F, 0x01, 0x02, 0x03]).unwrap(), packet);
20/// ```
21#[derive(Debug, PartialEq)]
22pub enum Packet {
23    /// Read Request `struct`
24    Rrq {
25        /// Name of the requested file
26        filename: String,
27        /// Transfer mode
28        mode: String,
29        /// Transfer options
30        options: Vec<TransferOption>,
31    },
32    /// Write Request `struct`
33    Wrq {
34        /// Name of the requested file
35        filename: String,
36        /// Transfer mode
37        mode: String,
38        /// Transfer options
39        options: Vec<TransferOption>,
40    },
41    /// Data `struct`
42    Data {
43        /// Block number
44        block_num: u16,
45        /// Data
46        data: Vec<u8>,
47    },
48    /// Acknowledgement `tuple` with block number
49    Ack(u16),
50    /// Error `struct`
51    Error {
52        /// Error code
53        code: ErrorCode,
54        /// Error message
55        msg: String,
56    },
57    /// Option acknowledgement `tuple` with transfer options
58    Oack(Vec<TransferOption>),
59}
60
61impl Packet {
62    /// Deserializes a [`u8`] slice into a [`Packet`].
63    pub fn deserialize(buf: &[u8]) -> Result<Packet, Box<dyn Error>> {
64        if buf.len() < 2 {
65            return Err("Buffer too short to serialize".into());
66        }
67        let opcode = Opcode::from_u16(Convert::to_u16(&buf[0..=1])?)?;
68
69        match opcode {
70            Opcode::Rrq | Opcode::Wrq => parse_rq(buf, opcode),
71            Opcode::Data => parse_data(buf),
72            Opcode::Ack => parse_ack(buf),
73            Opcode::Oack => parse_oack(buf),
74            Opcode::Error => parse_error(buf),
75        }
76    }
77
78    /// Serializes a [`Packet`] into a [`Vec<u8>`].
79    pub fn serialize(&self) -> Result<Vec<u8>, &'static str> {
80        match self {
81            Packet::Rrq {
82                filename,
83                mode,
84                options,
85            } => Ok(serialize_rrq(filename, mode, options)),
86            Packet::Wrq {
87                filename,
88                mode,
89                options,
90            } => Ok(serialize_wrq(filename, mode, options)),
91            Packet::Data { block_num, data } => Ok(serialize_data(block_num, data)),
92            Packet::Ack(block_num) => Ok(serialize_ack(block_num)),
93            Packet::Error { code, msg } => Ok(serialize_error(code, msg)),
94            Packet::Oack(options) => Ok(serialize_oack(options)),
95        }
96    }
97}
98
99/// Opcode `enum` represents the opcodes used in the TFTP definition.
100///
101/// This `enum` has function implementations for converting [`u16`]s to
102/// [`Opcode`]s and [`Opcode`]s to [`u8`] arrays.
103///
104/// # Example
105///
106/// ```rust
107/// use tftpd::Opcode;
108///
109/// assert_eq!(Opcode::from_u16(3).unwrap(), Opcode::Data);
110/// assert_eq!(Opcode::Ack.as_bytes(), [0x00, 0x04]);
111/// ```
112#[repr(u16)]
113#[derive(Debug, PartialEq)]
114pub enum Opcode {
115    /// Read request opcode
116    Rrq = 0x0001,
117    /// Write request opcode
118    Wrq = 0x0002,
119    /// Data opcode
120    Data = 0x0003,
121    /// Acknowledgement opcode
122    Ack = 0x0004,
123    /// Error opcode
124    Error = 0x0005,
125    /// Option acknowledgement opcode
126    Oack = 0x0006,
127}
128
129impl Opcode {
130    /// Converts a [`u16`] to an [`Opcode`].
131    pub fn from_u16(val: u16) -> Result<Opcode, &'static str> {
132        match val {
133            0x0001 => Ok(Opcode::Rrq),
134            0x0002 => Ok(Opcode::Wrq),
135            0x0003 => Ok(Opcode::Data),
136            0x0004 => Ok(Opcode::Ack),
137            0x0005 => Ok(Opcode::Error),
138            0x0006 => Ok(Opcode::Oack),
139            _ => Err("Invalid opcode"),
140        }
141    }
142
143    /// Converts a [`u16`] to a [`u8`] array with 2 elements.
144    pub const fn as_bytes(self) -> [u8; 2] {
145        (self as u16).to_be_bytes()
146    }
147}
148
149/// ErrorCode `enum` represents the error codes used in the TFTP definition.
150///
151/// This `enum` has function implementations for converting [`u16`]s to
152/// [`ErrorCode`]s and [`ErrorCode`]s to [`u8`] arrays.
153///
154/// # Example
155///
156/// ```rust
157/// use tftpd::ErrorCode;
158///
159/// assert_eq!(ErrorCode::from_u16(3).unwrap(), ErrorCode::DiskFull);
160/// assert_eq!(ErrorCode::FileExists.as_bytes(), [0x00, 0x06]);
161/// ```
162#[repr(u16)]
163#[derive(Clone, Copy, PartialEq, Debug)]
164pub enum ErrorCode {
165    /// Not Defined error code
166    NotDefined = 0,
167    /// File not found error code
168    FileNotFound = 1,
169    /// Access violation error code
170    AccessViolation = 2,
171    /// Disk full error code
172    DiskFull = 3,
173    /// Illegal operation error code
174    IllegalOperation = 4,
175    /// Unknown ID error code
176    UnknownId = 5,
177    /// File exists error code
178    FileExists = 6,
179    /// No such user error code
180    NoSuchUser = 7,
181    /// Refused option error code
182    RefusedOption = 8,
183}
184
185impl ErrorCode {
186    /// Converts a [`u16`] to an [`ErrorCode`].
187    pub fn from_u16(code: u16) -> Result<ErrorCode, &'static str> {
188        match code {
189            0 => Ok(ErrorCode::NotDefined),
190            1 => Ok(ErrorCode::FileNotFound),
191            2 => Ok(ErrorCode::AccessViolation),
192            3 => Ok(ErrorCode::DiskFull),
193            4 => Ok(ErrorCode::IllegalOperation),
194            5 => Ok(ErrorCode::UnknownId),
195            6 => Ok(ErrorCode::FileExists),
196            7 => Ok(ErrorCode::NoSuchUser),
197            8 => Ok(ErrorCode::RefusedOption),
198            _ => Err("Invalid error code"),
199        }
200    }
201
202    /// Converts an [`ErrorCode`] to a [`u8`] array with 2 elements.
203    pub fn as_bytes(self) -> [u8; 2] {
204        (self as u16).to_be_bytes()
205    }
206}
207
208impl fmt::Display for ErrorCode {
209    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210        match self {
211            ErrorCode::NotDefined => write!(f, "Not Defined"),
212            ErrorCode::FileNotFound => write!(f, "File Not Found"),
213            ErrorCode::AccessViolation => write!(f, "Access Violation"),
214            ErrorCode::DiskFull => write!(f, "Disk Full"),
215            ErrorCode::IllegalOperation => write!(f, "Illegal Operation"),
216            ErrorCode::UnknownId => write!(f, "Unknown ID"),
217            ErrorCode::FileExists => write!(f, "File Exists"),
218            ErrorCode::NoSuchUser => write!(f, "No Such User"),
219            ErrorCode::RefusedOption => write!(f, "Refused option"),
220        }
221    }
222}
223
224fn parse_rq(buf: &[u8], opcode: Opcode) -> Result<Packet, Box<dyn Error>> {
225    let mut options = vec![];
226    let filename: String;
227    let mode: String;
228    let mut zero_index: usize;
229
230    (filename, zero_index) = Convert::to_string(buf, 2)?;
231    (mode, zero_index) = Convert::to_string(buf, zero_index + 1)?;
232
233    let mut value: String;
234    let mut option;
235    while zero_index < buf.len() - 1 {
236        (option, zero_index) = Convert::to_string(buf, zero_index + 1)?;
237        (value, zero_index) = Convert::to_string(buf, zero_index + 1)?;
238
239        if let Ok(option) = OptionType::from_str(option.to_lowercase().as_str()) {
240            options.push(TransferOption {
241                option,
242                value: value.parse()?,
243            });
244        }
245    }
246
247    match opcode {
248        Opcode::Rrq => Ok(Packet::Rrq {
249            filename,
250            mode,
251            options,
252        }),
253        Opcode::Wrq => Ok(Packet::Wrq {
254            filename,
255            mode,
256            options,
257        }),
258        _ => Err("Non request opcode".into()),
259    }
260}
261
262fn parse_data(buf: &[u8]) -> Result<Packet, Box<dyn Error>> {
263    Ok(Packet::Data {
264        block_num: Convert::to_u16(&buf[2..])?,
265        data: buf[4..].to_vec(),
266    })
267}
268
269fn parse_ack(buf: &[u8]) -> Result<Packet, Box<dyn Error>> {
270    Ok(Packet::Ack(Convert::to_u16(&buf[2..])?))
271}
272
273fn parse_oack(buf: &[u8]) -> Result<Packet, Box<dyn Error>> {
274    let mut options = vec![];
275    let mut value: String;
276    let mut option;
277    let mut zero_index = 1usize;
278
279    while zero_index < buf.len() - 1 {
280        (option, zero_index) = Convert::to_string(buf, zero_index + 1)?;
281        (value, zero_index) = Convert::to_string(buf, zero_index + 1)?;
282        if let Ok(option) = OptionType::from_str(option.to_lowercase().as_str()) {
283            options.push(TransferOption {
284                option,
285                value: value.parse()?,
286            });
287        }
288    }
289
290    Ok(Packet::Oack(options))
291}
292
293fn parse_error(buf: &[u8]) -> Result<Packet, Box<dyn Error>> {
294    let code = ErrorCode::from_u16(Convert::to_u16(&buf[2..])?)?;
295    if let Ok((msg, _)) = Convert::to_string(buf, 4) {
296        Ok(Packet::Error { code, msg })
297    } else {
298        Ok(Packet::Error {
299            code,
300            msg: "(no message)".to_string(),
301        })
302    }
303}
304
305fn serialize_rrq(filename: &String, mode: &String, options: &Vec<TransferOption>) -> Vec<u8> {
306    let mut buf = [
307        &Opcode::Rrq.as_bytes(),
308        filename.as_bytes(),
309        &[0x00],
310        mode.as_bytes(),
311        &[0x00],
312    ]
313    .concat();
314
315    for option in options {
316        buf = [buf, option.as_bytes()].concat();
317    }
318    buf
319}
320
321fn serialize_wrq(filename: &String, mode: &String, options: &Vec<TransferOption>) -> Vec<u8> {
322    let mut buf = [
323        &Opcode::Wrq.as_bytes(),
324        filename.as_bytes(),
325        &[0x00],
326        mode.as_bytes(),
327        &[0x00],
328    ]
329    .concat();
330
331    for option in options {
332        buf = [buf, option.as_bytes()].concat();
333    }
334    buf
335}
336
337fn serialize_data(block_num: &u16, data: &Vec<u8>) -> Vec<u8> {
338    [
339        &Opcode::Data.as_bytes(),
340        &block_num.to_be_bytes(),
341        data.as_slice(),
342    ]
343    .concat()
344}
345
346fn serialize_ack(block_num: &u16) -> Vec<u8> {
347    [Opcode::Ack.as_bytes(), block_num.to_be_bytes()].concat()
348}
349
350fn serialize_error(code: &ErrorCode, msg: &String) -> Vec<u8> {
351    [
352        &Opcode::Error.as_bytes()[..],
353        &code.as_bytes()[..],
354        msg.as_bytes(),
355        &[0x00],
356    ]
357    .concat()
358}
359
360fn serialize_oack(options: &Vec<TransferOption>) -> Vec<u8> {
361    let mut buf = Opcode::Oack.as_bytes().to_vec();
362
363    for option in options {
364        buf = [buf, option.as_bytes()].concat();
365    }
366
367    buf
368}
369
370#[cfg(test)]
371mod tests {
372    use super::*;
373
374    #[test]
375    fn parses_read_request() {
376        let buf = [
377            &Opcode::Rrq.as_bytes()[..],
378            ("test.png".as_bytes()),
379            &[0x00],
380            ("octet".as_bytes()),
381            &[0x00],
382        ]
383        .concat();
384
385        if let Ok(Packet::Rrq {
386            filename,
387            mode,
388            options,
389        }) = parse_rq(&buf, Opcode::Rrq)
390        {
391            assert_eq!(filename, "test.png");
392            assert_eq!(mode, "octet");
393            assert_eq!(options.len(), 0);
394        } else {
395            panic!("cannot parse read request")
396        }
397    }
398
399    #[test]
400    fn parses_read_request_with_options() {
401        let buf = [
402            &Opcode::Rrq.as_bytes()[..],
403            ("test.png".as_bytes()),
404            &[0x00],
405            ("octet".as_bytes()),
406            &[0x00],
407            (OptionType::TransferSize.as_str().as_bytes()),
408            &[0x00],
409            ("0".as_bytes()),
410            &[0x00],
411            (OptionType::Timeout.as_str().as_bytes()),
412            &[0x00],
413            ("5".as_bytes()),
414            &[0x00],
415            (OptionType::WindowSize.as_str().as_bytes()),
416            &[0x00],
417            ("4".as_bytes()),
418            &[0x00],
419        ]
420        .concat();
421
422        if let Ok(Packet::Rrq {
423            filename,
424            mode,
425            options,
426        }) = parse_rq(&buf, Opcode::Rrq)
427        {
428            assert_eq!(filename, "test.png");
429            assert_eq!(mode, "octet");
430            assert_eq!(options.len(), 3);
431            assert_eq!(
432                options[0],
433                TransferOption {
434                    option: OptionType::TransferSize,
435                    value: 0
436                }
437            );
438            assert_eq!(
439                options[1],
440                TransferOption {
441                    option: OptionType::Timeout,
442                    value: 5
443                }
444            );
445            assert_eq!(
446                options[2],
447                TransferOption {
448                    option: OptionType::WindowSize,
449                    value: 4
450                }
451            );
452        } else {
453            panic!("cannot parse read request with options")
454        }
455    }
456
457    #[test]
458    fn parses_write_request() {
459        let buf = [
460            &Opcode::Wrq.as_bytes()[..],
461            ("test.png".as_bytes()),
462            &[0x00],
463            ("octet".as_bytes()),
464            &[0x00],
465        ]
466        .concat();
467
468        if let Ok(Packet::Wrq {
469            filename,
470            mode,
471            options,
472        }) = parse_rq(&buf, Opcode::Wrq)
473        {
474            assert_eq!(filename, "test.png");
475            assert_eq!(mode, "octet");
476            assert_eq!(options.len(), 0);
477        } else {
478            panic!("cannot parse write request")
479        }
480    }
481
482    #[test]
483    fn parses_write_request_with_options() {
484        let buf = [
485            &Opcode::Wrq.as_bytes()[..],
486            ("test.png".as_bytes()),
487            &[0x00],
488            ("octet".as_bytes()),
489            &[0x00],
490            (OptionType::TransferSize.as_str().as_bytes()),
491            &[0x00],
492            ("12341234".as_bytes()),
493            &[0x00],
494            (OptionType::BlockSize.as_str().as_bytes()),
495            &[0x00],
496            ("1024".as_bytes()),
497            &[0x00],
498        ]
499        .concat();
500
501        if let Ok(Packet::Wrq {
502            filename,
503            mode,
504            options,
505        }) = parse_rq(&buf, Opcode::Wrq)
506        {
507            assert_eq!(filename, "test.png");
508            assert_eq!(mode, "octet");
509            assert_eq!(options.len(), 2);
510            assert_eq!(
511                options[0],
512                TransferOption {
513                    option: OptionType::TransferSize,
514                    value: 12341234
515                }
516            );
517            assert_eq!(
518                options[1],
519                TransferOption {
520                    option: OptionType::BlockSize,
521                    value: 1024
522                }
523            );
524        } else {
525            panic!("cannot parse write request with options")
526        }
527    }
528
529    #[test]
530    fn parses_data() {
531        let buf = [
532            &Opcode::Data.as_bytes()[..],
533            &5u16.to_be_bytes(),
534            &[
535                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
536            ],
537        ]
538        .concat();
539
540        if let Ok(Packet::Data { block_num, data }) = parse_data(&buf) {
541            assert_eq!(block_num, 5);
542            assert_eq!(
543                data,
544                [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C]
545            );
546        } else {
547            panic!("cannot parse data")
548        }
549    }
550
551    #[test]
552    fn parses_ack() {
553        let buf = [&Opcode::Ack.as_bytes()[..], &12u16.to_be_bytes()].concat();
554
555        if let Ok(Packet::Ack(block_num)) = parse_ack(&buf) {
556            assert_eq!(block_num, 12);
557        } else {
558            panic!("cannot parse ack")
559        }
560    }
561
562    #[test]
563    fn parses_oack() {
564        let buf = [
565            &Opcode::Oack.as_bytes()[..],
566            (OptionType::TransferSize.as_str().as_bytes()),
567            &[0x00],
568            ("0".as_bytes()),
569            &[0x00],
570            (OptionType::Timeout.as_str().as_bytes()),
571            &[0x00],
572            ("5".as_bytes()),
573            &[0x00],
574            (OptionType::WindowSize.as_str().as_bytes()),
575            &[0x00],
576            ("4".as_bytes()),
577            &[0x00],
578        ]
579        .concat();
580
581        if let Ok(Packet::Oack(options)) = parse_oack(&buf) {
582            assert_eq!(options.len(), 3);
583            assert_eq!(
584                options[0],
585                TransferOption {
586                    option: OptionType::TransferSize,
587                    value: 0
588                }
589            );
590            assert_eq!(
591                options[1],
592                TransferOption {
593                    option: OptionType::Timeout,
594                    value: 5
595                }
596            );
597            assert_eq!(
598                options[2],
599                TransferOption {
600                    option: OptionType::WindowSize,
601                    value: 4
602                }
603            );
604        } else {
605            panic!("cannot parse read request with options")
606        }
607    }
608
609    #[test]
610    fn parses_error() {
611        let buf = [
612            &Opcode::Error.as_bytes()[..],
613            &ErrorCode::FileExists.as_bytes(),
614            "file already exists".as_bytes(),
615            &[0x00],
616        ]
617        .concat();
618
619        if let Ok(Packet::Error { code, msg }) = parse_error(&buf) {
620            assert_eq!(code, ErrorCode::FileExists);
621            assert_eq!(msg, "file already exists");
622        } else {
623            panic!("cannot parse error")
624        }
625    }
626
627    #[test]
628    fn parses_error_without_message() {
629        let buf = [
630            &Opcode::Error.as_bytes()[..],
631            &ErrorCode::FileExists.as_bytes(),
632            &[0x00],
633        ]
634        .concat();
635
636        if let Ok(Packet::Error { code, msg }) = parse_error(&buf) {
637            assert_eq!(code, ErrorCode::FileExists);
638            assert_eq!(msg, "");
639        } else {
640            panic!("cannot parse error")
641        }
642    }
643
644    #[test]
645    fn serializes_rrq() {
646        let serialized_data = vec![
647            0x00, 0x01, 0x74, 0x65, 0x73, 0x74, 0x00, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x00,
648        ];
649
650        assert_eq!(
651            serialize_rrq(&"test".into(), &"octet".into(), &vec![]),
652            serialized_data
653        )
654    }
655
656    #[test]
657    fn serializes_rrq_with_options() {
658        let serialized_data = vec![
659            0x00, 0x01, 0x74, 0x65, 0x73, 0x74, 0x00, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x00, 0x62,
660            0x6c, 0x6b, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x31, 0x34, 0x36, 0x38, 0x00, 0x77, 0x69,
661            0x6e, 0x64, 0x6f, 0x77, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x31, 0x00, 0x74, 0x69, 0x6d,
662            0x65, 0x6f, 0x75, 0x74, 0x00, 0x35, 0x00,
663        ];
664
665        assert_eq!(
666            serialize_rrq(
667                &"test".into(),
668                &"octet".into(),
669                &vec![
670                    TransferOption {
671                        option: OptionType::BlockSize,
672                        value: 1468,
673                    },
674                    TransferOption {
675                        option: OptionType::WindowSize,
676                        value: 1,
677                    },
678                    TransferOption {
679                        option: OptionType::Timeout,
680                        value: 5,
681                    }
682                ]
683            ),
684            serialized_data
685        )
686    }
687
688    #[test]
689    fn serializes_wrq() {
690        let serialized_data = vec![
691            0x00, 0x02, 0x74, 0x65, 0x73, 0x74, 0x00, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x00,
692        ];
693
694        assert_eq!(
695            serialize_wrq(&"test".into(), &"octet".into(), &vec![]),
696            serialized_data
697        )
698    }
699
700    #[test]
701    fn serializes_wrq_with_options() {
702        let serialized_data = vec![
703            0x00, 0x02, 0x74, 0x65, 0x73, 0x74, 0x00, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x00, 0x62,
704            0x6c, 0x6b, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x31, 0x34, 0x36, 0x38, 0x00, 0x77, 0x69,
705            0x6e, 0x64, 0x6f, 0x77, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x31, 0x00, 0x74, 0x69, 0x6d,
706            0x65, 0x6f, 0x75, 0x74, 0x00, 0x35, 0x00,
707        ];
708
709        assert_eq!(
710            serialize_wrq(
711                &"test".into(),
712                &"octet".into(),
713                &vec![
714                    TransferOption {
715                        option: OptionType::BlockSize,
716                        value: 1468,
717                    },
718                    TransferOption {
719                        option: OptionType::WindowSize,
720                        value: 1,
721                    },
722                    TransferOption {
723                        option: OptionType::Timeout,
724                        value: 5,
725                    }
726                ]
727            ),
728            serialized_data
729        )
730    }
731
732    #[test]
733    fn serializes_data() {
734        let serialized_data = vec![0x00, 0x03, 0x00, 0x10, 0x01, 0x02, 0x03, 0x04];
735
736        assert_eq!(
737            serialize_data(&16, &vec![0x01, 0x02, 0x03, 0x04]),
738            serialized_data
739        );
740    }
741
742    #[test]
743    fn serializes_ack() {
744        let serialized_ack = vec![0x00, 0x04, 0x04, 0xD2];
745
746        assert_eq!(serialize_ack(&1234), serialized_ack);
747    }
748
749    #[test]
750    fn serializes_error() {
751        let serialized_error = vec![
752            0x00, 0x05, 0x00, 0x04, 0x69, 0x6C, 0x6C, 0x65, 0x67, 0x61, 0x6C, 0x20, 0x6F, 0x70,
753            0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00,
754        ];
755
756        assert_eq!(
757            serialize_error(
758                &ErrorCode::IllegalOperation,
759                &"illegal operation".to_string()
760            ),
761            serialized_error
762        );
763    }
764
765    #[test]
766    fn serializes_oack() {
767        let serialized_oack = vec![
768            0x00, 0x06, 0x62, 0x6C, 0x6B, 0x73, 0x69, 0x7A, 0x65, 0x00, 0x31, 0x34, 0x33, 0x32,
769            0x00,
770        ];
771
772        assert_eq!(
773            serialize_oack(&vec![TransferOption {
774                option: OptionType::BlockSize,
775                value: 1432
776            }]),
777            serialized_oack
778        );
779    }
780}