INET Framework for OMNeT++/OMNEST
inet::tcp::TcpHeaderSerializer Class Reference

Converts between TcpHeader and binary (network byte order) Tcp header. More...

#include <TcpHeaderSerializer.h>

Inheritance diagram for inet::tcp::TcpHeaderSerializer:
inet::FieldsChunkSerializer inet::ChunkSerializer

Public Member Functions

 TcpHeaderSerializer ()
 
- Public Member Functions inherited from inet::FieldsChunkSerializer
virtual void serialize (MemoryOutputStream &stream, const Ptr< const Chunk > &chunk, b offset, b length) const override
 Serializes a chunk into a stream by writing the bytes representing the chunk at the end of the stream. More...
 
virtual const Ptr< Chunkdeserialize (MemoryInputStream &stream, const std::type_info &typeInfo) const override
 Deserializes a chunk from a stream by reading the bytes at the current position of the stream. More...
 

Protected Member Functions

virtual void serializeOption (MemoryOutputStream &stream, const TcpOption *option) const
 
virtual TcpOptiondeserializeOption (MemoryInputStream &stream) const
 
virtual void serialize (MemoryOutputStream &stream, const Ptr< const Chunk > &chunk) const override
 Serializes a chunk into a stream by writing all bytes representing the chunk at the end of the stream. More...
 
virtual const Ptr< Chunkdeserialize (MemoryInputStream &stream) const override
 Deserializes a chunk from a stream by reading the bytes at the current position of the stream. More...
 

Additional Inherited Members

- Static Public Attributes inherited from inet::ChunkSerializer
static b totalSerializedLength = b(0)
 
static b totalDeserializedLength = b(0)
 

Detailed Description

Converts between TcpHeader and binary (network byte order) Tcp header.

Constructor & Destructor Documentation

◆ TcpHeaderSerializer()

inet::tcp::TcpHeaderSerializer::TcpHeaderSerializer ( )
inline
31 : FieldsChunkSerializer() {}

Member Function Documentation

◆ deserialize()

const Ptr< Chunk > inet::tcp::TcpHeaderSerializer::deserialize ( MemoryInputStream stream) const
overrideprotectedvirtual

Deserializes a chunk from a stream by reading the bytes at the current position of the stream.

The current stream position is updated according to the length of the returned chunk.

Implements inet::FieldsChunkSerializer.

158 {
159  auto position = stream.getPosition();
160  uint8_t buffer[B(TCP_MIN_HEADER_LENGTH).get()];
161  stream.readBytes(buffer, TCP_MIN_HEADER_LENGTH);
162  auto tcpHeader = makeShared<TcpHeader>();
163  const struct tcphdr& tcp = *static_cast<const struct tcphdr *>((void *)&buffer);
164  ASSERT(B(sizeof(tcp)) == TCP_MIN_HEADER_LENGTH);
165 
166  // fill Tcp header structure
167  tcpHeader->setSrcPort(ntohs(tcp.th_sport));
168  tcpHeader->setDestPort(ntohs(tcp.th_dport));
169  tcpHeader->setSequenceNo(ntohl(tcp.th_seq));
170  tcpHeader->setAckNo(ntohl(tcp.th_ack));
171  B headerLength = B(tcp.th_offs * 4);
172 
173  // set flags
174  unsigned char flags = tcp.th_flags;
175  tcpHeader->setFinBit((flags & TH_FIN) == TH_FIN);
176  tcpHeader->setSynBit((flags & TH_SYN) == TH_SYN);
177  tcpHeader->setRstBit((flags & TH_RST) == TH_RST);
178  tcpHeader->setPshBit((flags & TH_PUSH) == TH_PUSH);
179  tcpHeader->setAckBit((flags & TH_ACK) == TH_ACK);
180  tcpHeader->setUrgBit((flags & TH_URG) == TH_URG);
181  tcpHeader->setEceBit((flags & TH_ECE) == TH_ECE);
182  tcpHeader->setCwrBit((flags & TH_CWR) == TH_CWR);
183 
184  tcpHeader->setWindow(ntohs(tcp.th_win));
185 
186  tcpHeader->setUrgentPointer(ntohs(tcp.th_urp));
187 
188  if (headerLength > TCP_MIN_HEADER_LENGTH) {
189  while (stream.getPosition() - position < headerLength) {
190  TcpOption *option = deserializeOption(stream);
191  tcpHeader->appendHeaderOption(option);
192  }
193  }
194  tcpHeader->setHeaderLength(headerLength);
195  tcpHeader->setCrc(ntohs(tcp.th_sum));
196  tcpHeader->setCrcMode(CRC_COMPUTED);
197  return tcpHeader;
198 }

◆ deserializeOption()

TcpOption * inet::tcp::TcpHeaderSerializer::deserializeOption ( MemoryInputStream stream) const
protectedvirtual
201 {
202  TcpOptionNumbers kind = static_cast<TcpOptionNumbers>(stream.readByte());
203  unsigned char length = 0;
204 
205  switch (kind) {
206  case TCPOPTION_END_OF_OPTION_LIST: // EOL
207  return new TcpOptionEnd();
208 
209  case TCPOPTION_NO_OPERATION: // NOP
210  return new TcpOptionNop();
211 
213  length = stream.readByte();
214  if (length == 4) {
215  auto *option = new TcpOptionMaxSegmentSize();
216  option->setLength(length);
217  option->setMaxSegmentSize(stream.readUint16Be());
218  return option;
219  }
220  break;
221 
223  length = stream.readByte();
224  if (length == 3) {
225  auto *option = new TcpOptionWindowScale();
226  option->setLength(length);
227  option->setWindowScale(stream.readByte());
228  return option;
229  }
230  break;
231 
233  length = stream.readByte();
234  if (length == 2) {
235  auto *option = new TcpOptionSackPermitted();
236  option->setLength(length);
237  return option;
238  }
239  break;
240 
241  case TCPOPTION_SACK:
242  length = stream.readByte();
243  if (length > 2 && (length % 8) == 2) {
244  auto *option = new TcpOptionSack();
245  option->setLength(length);
246  option->setSackItemArraySize(length / 8);
247  unsigned int count = 0;
248  for (unsigned int i = 2; i < length; i += 8) {
249  SackItem si;
250  si.setStart(stream.readUint32Be());
251  si.setEnd(stream.readUint32Be());
252  option->setSackItem(count++, si);
253  }
254  return option;
255  }
256  break;
257 
258  case TCPOPTION_TIMESTAMP:
259  length = stream.readByte();
260  if (length == 10) {
261  auto *option = new TcpOptionTimestamp();
262  option->setLength(length);
263  option->setSenderTimestamp(stream.readUint32Be());
264  option->setEchoedTimestamp(stream.readUint32Be());
265  return option;
266  }
267  break;
268 
269  default:
270  length = stream.readByte();
271  break;
272  } // switch
273 
274  auto *option = new TcpOptionUnknown();
275  option->setKind(kind);
276  option->setLength(length);
277  if (length > 2)
278  option->setBytesArraySize(length - 2);
279  for (unsigned int i = 2; i < length; i++)
280  option->setBytes(i - 2, stream.readByte());
281  return option;
282 }

Referenced by deserialize().

◆ serialize()

void inet::tcp::TcpHeaderSerializer::serialize ( MemoryOutputStream stream,
const Ptr< const Chunk > &  chunk 
) const
overrideprotectedvirtual

Serializes a chunk into a stream by writing all bytes representing the chunk at the end of the stream.

Implements inet::FieldsChunkSerializer.

25 {
26  const auto& tcpHeader = staticPtrCast<const TcpHeader>(chunk);
27  struct tcphdr tcp;
28 
29  // fill Tcp header structure
30  if (tcpHeader->getCrcMode() != CRC_COMPUTED)
31  throw cRuntimeError("Cannot serialize Tcp header without a properly computed CRC");
32  tcp.th_sum = htons(tcpHeader->getCrc());
33  tcp.th_sport = htons(tcpHeader->getSrcPort());
34  tcp.th_dport = htons(tcpHeader->getDestPort());
35  tcp.th_seq = htonl(tcpHeader->getSequenceNo());
36  tcp.th_ack = htonl(tcpHeader->getAckNo());
37  tcp.th_x2 = 0; // unused
38 
39  // set flags
40  uint8_t flags = 0;
41  if (tcpHeader->getFinBit())
42  flags |= TH_FIN;
43  if (tcpHeader->getSynBit())
44  flags |= TH_SYN;
45  if (tcpHeader->getRstBit())
46  flags |= TH_RST;
47  if (tcpHeader->getPshBit())
48  flags |= TH_PUSH;
49  if (tcpHeader->getAckBit())
50  flags |= TH_ACK;
51  if (tcpHeader->getUrgBit())
52  flags |= TH_URG;
53  if (tcpHeader->getEceBit())
54  flags |= TH_ECE;
55  if (tcpHeader->getCwrBit())
56  flags |= TH_CWR;
57 
58  tcp.th_flags = flags;
59  tcp.th_win = htons(tcpHeader->getWindow());
60  tcp.th_urp = htons(tcpHeader->getUrgentPointer());
61  if (B(tcpHeader->getHeaderLength()).get() % 4 != 0)
62  throw cRuntimeError("invalid Tcp header length=%s: must be dividable by 4 bytes", tcpHeader->getHeaderLength().str().c_str());
63  tcp.th_offs = B(tcpHeader->getHeaderLength()).get() / 4;
64 
65  stream.writeBytes((uint8_t *)&tcp, TCP_MIN_HEADER_LENGTH);
66 
67  unsigned short numOptions = tcpHeader->getHeaderOptionArraySize();
68  unsigned int optionsLength = 0;
69  if (numOptions > 0) {
70  for (unsigned short i = 0; i < numOptions; i++) {
71  const TcpOption *option = tcpHeader->getHeaderOption(i);
72  serializeOption(stream, option);
73  optionsLength += option->getLength();
74  }
75  if (optionsLength % 4 != 0)
76  stream.writeByteRepeatedly(0, 4 - optionsLength % 4);
77  }
78  ASSERT(tcpHeader->getHeaderLength() == TCP_MIN_HEADER_LENGTH + B(optionsLength));
79 }

◆ serializeOption()

void inet::tcp::TcpHeaderSerializer::serializeOption ( MemoryOutputStream stream,
const TcpOption option 
) const
protectedvirtual
82 {
83  TcpOptionNumbers kind = option->getKind();
84  unsigned short length = option->getLength(); // length >= 1
85 
86  stream.writeByte(kind);
87  if (length > 1)
88  stream.writeByte(length);
89 
90  auto *opt = dynamic_cast<const TcpOptionUnknown *>(option);
91  if (opt) {
92  unsigned int datalen = opt->getBytesArraySize();
93  ASSERT(length == 2 + datalen);
94  for (unsigned int i = 0; i < datalen; i++)
95  stream.writeByte(opt->getBytes(i));
96  return;
97  }
98 
99  switch (kind) {
100  case TCPOPTION_END_OF_OPTION_LIST: // EOL
101  check_and_cast<const TcpOptionEnd *>(option);
102  ASSERT(length == 1);
103  break;
104 
105  case TCPOPTION_NO_OPERATION: // NOP
106  check_and_cast<const TcpOptionNop *>(option);
107  ASSERT(length == 1);
108  break;
109 
111  auto *opt = check_and_cast<const TcpOptionMaxSegmentSize *>(option);
112  ASSERT(length == 4);
113  stream.writeUint16Be(opt->getMaxSegmentSize());
114  break;
115  }
116 
117  case TCPOPTION_WINDOW_SCALE: {
118  auto *opt = check_and_cast<const TcpOptionWindowScale *>(option);
119  ASSERT(length == 3);
120  stream.writeByte(opt->getWindowScale());
121  break;
122  }
123 
125  auto *opt = check_and_cast<const TcpOptionSackPermitted *>(option);
126  (void)opt; // UNUSED
127  ASSERT(length == 2);
128  break;
129  }
130 
131  case TCPOPTION_SACK: {
132  auto *opt = check_and_cast<const TcpOptionSack *>(option);
133  ASSERT(length == 2 + opt->getSackItemArraySize() * 8);
134  for (unsigned int i = 0; i < opt->getSackItemArraySize(); i++) {
135  SackItem si = opt->getSackItem(i);
136  stream.writeUint32Be(si.getStart());
137  stream.writeUint32Be(si.getEnd());
138  }
139  break;
140  }
141 
142  case TCPOPTION_TIMESTAMP: {
143  auto *opt = check_and_cast<const TcpOptionTimestamp *>(option);
144  ASSERT(length == 10);
145  stream.writeUint32Be(opt->getSenderTimestamp());
146  stream.writeUint32Be(opt->getEchoedTimestamp());
147  break;
148  }
149 
150  default: {
151  throw cRuntimeError("Unknown TCPOption kind=%d (not in a TCPOptionUnknown option)", kind);
152  break;
153  }
154  } // switch
155 }

Referenced by serialize().


The documentation for this class was generated from the following files:
TH_PUSH
#define TH_PUSH
Definition: tcphdr.h:20
TH_FIN
#define TH_FIN
Definition: tcphdr.h:17
ntohs
u16_t ntohs(u16_t n)
inet::count
int count(const std::vector< T > &v, const Tk &a)
Definition: stlutils.h:54
inet::CRC_COMPUTED
@ CRC_COMPUTED
Definition: CrcMode_m.h:59
TH_RST
#define TH_RST
Definition: tcphdr.h:19
inet::tcp::TCPOPTION_SACK_PERMITTED
@ TCPOPTION_SACK_PERMITTED
Definition: TcpHeader_m.h:119
htonl
u32_t htonl(u32_t n)
ntohl
u32_t ntohl(u32_t n)
TH_SYN
#define TH_SYN
Definition: tcphdr.h:18
htons
u16_t htons(u16_t n)
inet::units::units::B
intscale< b, 1, 8 > B
Definition: Units.h:1168
TH_ECE
#define TH_ECE
Definition: tcphdr.h:23
inet::tcp::TCPOPTION_WINDOW_SCALE
@ TCPOPTION_WINDOW_SCALE
Definition: TcpHeader_m.h:118
inet::tcp::TcpOptionNumbers
TcpOptionNumbers
Enum generated from inet/transportlayer/tcp_common/TcpHeader.msg:40 by opp_msgtool.
Definition: TcpHeader_m.h:114
kind
removed DscpReq kind
Definition: IUdp-gates.txt:12
TH_CWR
#define TH_CWR
Definition: tcphdr.h:24
inet::tcp::TCPOPTION_MAXIMUM_SEGMENT_SIZE
@ TCPOPTION_MAXIMUM_SEGMENT_SIZE
Definition: TcpHeader_m.h:117
inet::tcp::TCPOPTION_TIMESTAMP
@ TCPOPTION_TIMESTAMP
Definition: TcpHeader_m.h:121
inet::tcp::TcpHeaderSerializer::deserializeOption
virtual TcpOption * deserializeOption(MemoryInputStream &stream) const
Definition: TcpHeaderSerializer.cc:200
TH_URG
#define TH_URG
Definition: tcphdr.h:22
TH_ACK
#define TH_ACK
Definition: tcphdr.h:21
inet::tcp::TCPOPTION_END_OF_OPTION_LIST
@ TCPOPTION_END_OF_OPTION_LIST
Definition: TcpHeader_m.h:115
inet::tcp::TcpHeaderSerializer::serializeOption
virtual void serializeOption(MemoryOutputStream &stream, const TcpOption *option) const
Definition: TcpHeaderSerializer.cc:81
inet::tcp::TCPOPTION_SACK
@ TCPOPTION_SACK
Definition: TcpHeader_m.h:120
inet::tcp::TCP_MIN_HEADER_LENGTH
const B TCP_MIN_HEADER_LENGTH
Definition: TcpHeader_m.h:63
inet::tcp::TCPOPTION_NO_OPERATION
@ TCPOPTION_NO_OPERATION
Definition: TcpHeader_m.h:116