1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use addr::ToSingleSocketAddr;

use std::io::{self, Cursor};

use std::net::SocketAddr;

use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};

/**
 * Maximum transmission unit of a gaffer payload
 *
 * Derived from ethernet_mtu - ipv6_header_size - udp_header_size - gaffer_header_size
 *       1452 = 1500         - 40               - 8               - 8
 *
 * This is not strictly guaranteed -- there may be less room in an ethernet frame than this due to
 * variability in ipv6 header size.
 */
pub const GAFFER_MTU: usize = 1452; /* bytes */

/// TODO: consider slice
pub type GafferPayload = Vec<u8>;

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct GafferPacket {
  pub addr: SocketAddr,
  pub payload: GafferPayload
}

impl GafferPacket {
  pub fn dummy_packet() -> GafferPacket {
    GafferPacket::new("0.0.0.0:7878", GafferPayload::new())
  }

  pub fn new<A: ToSingleSocketAddr>(addr: A, payload: GafferPayload) -> GafferPacket {
    let first_addr = addr.to_single_socket_addr().unwrap();
    GafferPacket { addr: first_addr, payload: payload }
  }
}


#[derive(Clone, PartialEq, Eq, Debug)]
pub struct CompleteGafferPacket {
  pub seq: u16,
  pub ack_seq: u16,
  pub ack_field: u32,
  pub payload: GafferPayload
}

impl CompleteGafferPacket {
  pub fn serialized(&self) -> Vec<u8> {
    let mut wtr = Vec::new();
    wtr.write_u16::<BigEndian>(self.seq).unwrap();
    wtr.write_u16::<BigEndian>(self.ack_seq).unwrap();
    wtr.write_u32::<BigEndian>(self.ack_field).unwrap();
    wtr.append(&mut self.payload.clone());
    wtr
  }

  pub fn deserialize(mut bytes: Vec<u8>) -> io::Result<CompleteGafferPacket> {
    let payload = bytes.split_off(8);
    let mut rdr = Cursor::new(bytes);

    let seq = try!(rdr.read_u16::<BigEndian>());
    let ack_seq = try!(rdr.read_u16::<BigEndian>());
    let ack_field = try!(rdr.read_u32::<BigEndian>());

    Ok(CompleteGafferPacket {
      seq: seq,
      ack_seq: ack_seq,
      ack_field: ack_field,
      payload: payload
    })
  }
}