Sponge
CS144's user-space TCP library
tcp_header.cc
Go to the documentation of this file.
1 #include "tcp_header.hh"
2 
3 #include <sstream>
4 
5 using namespace std;
6 
18  sport = p.u16(); // source port
19  dport = p.u16(); // destination port
20  seqno = WrappingInt32{p.u32()}; // sequence number
21  ackno = WrappingInt32{p.u32()}; // ack number
22  doff = p.u8() >> 4; // data offset
23 
24  const uint8_t fl_b = p.u8(); // byte including flags
25  urg = static_cast<bool>(fl_b & 0b0010'0000); // binary literals and ' digit separator since C++14!!!
26  ack = static_cast<bool>(fl_b & 0b0001'0000);
27  psh = static_cast<bool>(fl_b & 0b0000'1000);
28  rst = static_cast<bool>(fl_b & 0b0000'0100);
29  syn = static_cast<bool>(fl_b & 0b0000'0010);
30  fin = static_cast<bool>(fl_b & 0b0000'0001);
31 
32  win = p.u16(); // window size
33  cksum = p.u16(); // checksum
34  uptr = p.u16(); // urgent pointer
35 
36  if (doff < 5) {
37  return ParseResult::HeaderTooShort;
38  }
39 
40  // skip any options or anything extra in the header
41  p.remove_prefix(doff * 4 - TCPHeader::LENGTH);
42 
43  if (p.error()) {
44  return p.get_error();
45  }
46 
47  return ParseResult::NoError;
48 }
49 
51 string TCPHeader::serialize() const {
52  // sanity check
53  if (doff < 5) {
54  throw runtime_error("TCP header too short");
55  }
56 
57  string ret;
58  ret.reserve(4 * doff);
59 
60  NetUnparser::u16(ret, sport); // source port
61  NetUnparser::u16(ret, dport); // destination port
62  NetUnparser::u32(ret, seqno.raw_value()); // sequence number
63  NetUnparser::u32(ret, ackno.raw_value()); // ack number
64  NetUnparser::u8(ret, doff << 4); // data offset
65 
66  const uint8_t fl_b = (urg ? 0b0010'0000 : 0) | (ack ? 0b0001'0000 : 0) | (psh ? 0b0000'1000 : 0) |
67  (rst ? 0b0000'0100 : 0) | (syn ? 0b0000'0010 : 0) | (fin ? 0b0000'0001 : 0);
68  NetUnparser::u8(ret, fl_b); // flags
69  NetUnparser::u16(ret, win); // window size
70 
71  NetUnparser::u16(ret, cksum); // checksum
72 
73  NetUnparser::u16(ret, uptr); // urgent pointer
74 
75  ret.resize(4 * doff); // expand header to advertised size
76 
77  return ret;
78 }
79 
81 string TCPHeader::to_string() const {
82  stringstream ss{};
83  ss << hex << boolalpha << "TCP source port: " << +sport << '\n'
84  << "TCP dest port: " << +dport << '\n'
85  << "TCP seqno: " << seqno << '\n'
86  << "TCP ackno: " << ackno << '\n'
87  << "TCP doff: " << +doff << '\n'
88  << "Flags: urg: " << urg << " ack: " << ack << " psh: " << psh << " rst: " << rst << " syn: " << syn
89  << " fin: " << fin << '\n'
90  << "TCP winsize: " << +win << '\n'
91  << "TCP cksum: " << +cksum << '\n'
92  << "TCP uptr: " << +uptr << '\n';
93  return ss.str();
94 }
95 
96 string TCPHeader::summary() const {
97  stringstream ss{};
98  ss << "Header(flags=" << (syn ? "S" : "") << (ack ? "A" : "") << (rst ? "R" : "") << (fin ? "F" : "")
99  << ",seqno=" << seqno << ",ack=" << ackno << ",win=" << win << ")";
100  return ss.str();
101 }
102 
103 bool TCPHeader::operator==(const TCPHeader &other) const {
104  // TODO(aozdemir) more complete check (right now we omit cksum, src, dst
105  return seqno == other.seqno && ackno == other.ackno && doff == other.doff && urg == other.urg && ack == other.ack &&
106  psh == other.psh && rst == other.rst && syn == other.syn && fin == other.fin && win == other.win &&
107  uptr == other.uptr;
108 }
NetParser::u16
uint16_t u16()
Parse a 16-bit integer in network byte order from the data stream.
Definition: parser.cc:64
WrappingInt32
A 32-bit integer, expressed relative to an arbitrary initial sequence number (ISN)
Definition: wrapping_integers.hh:9
tcp_header.hh
ParseResult
ParseResult
The result of parsing or unparsing an IP datagram, TCP segment, Ethernet frame, or ARP message.
Definition: parser.hh:12
std::uint8_t
NetParser
Definition: parser.hh:25
NetParser::u8
uint8_t u8()
Parse an 8-bit integer in network byte order from the data stream.
Definition: parser.cc:66
std
NetParser::u32
uint32_t u32()
Parse a 32-bit integer in network byte order from the data stream.
Definition: parser.cc:62
TCPHeader::parse
ParseResult parse(NetParser &p)
Parse the TCP fields from the provided NetParser.
Definition: tcp_header.cc:17