INET Framework for OMNeT++/OMNEST
inet::serializer::TCPSerializer Class Reference

Converts between TCPSegment and binary (network byte order) TCP header. More...

#include <TCPSerializer.h>

Inheritance diagram for inet::serializer::TCPSerializer:
inet::serializer::SerializerBase

Public Member Functions

 TCPSerializer (const char *name=nullptr)
 
tcp::TCPSegmentdeserialize (const unsigned char *srcbuf, unsigned int bufsize, bool withBytes)
 Puts a packet sniffed from the wire into a TCPSegment. More...
 
- Public Member Functions inherited from inet::serializer::SerializerBase
 SerializerBase (const char *name=nullptr)
 
void serializePacket (const cPacket *pkt, Buffer &b, Context &context)
 
cPacket * deserializePacket (const Buffer &b, Context &context)
 

Protected Member Functions

virtual void serialize (const cPacket *pkt, Buffer &b, Context &context) override
 Serializes a cPacket for transmission on the wire. More...
 
virtual cPacket * deserialize (const Buffer &b, Context &context) override
 Puts a packet sniffed from the wire into an EtherFrame. More...
 
void serializeOption (const tcp::TCPOption *option, Buffer &b, Context &c)
 
tcp::TCPOptiondeserializeOption (Buffer &b, Context &c)
 

Additional Inherited Members

- Static Public Member Functions inherited from inet::serializer::SerializerBase
static SerializerBaselookupSerializer (const cPacket *pkt, Context &context, ProtocolGroup group, int id)
 
static void lookupAndSerialize (const cPacket *pkt, Buffer &b, Context &context, ProtocolGroup group, int id, unsigned int maxLength=(unsigned int)(-1))
 
static SerializerBaselookupDeserializer (Context &context, ProtocolGroup group, int id)
 
static cPacket * lookupAndDeserialize (const Buffer &b, Context &context, ProtocolGroup group, int id, unsigned int maxLength=(unsigned int)(-1))
 

Detailed Description

Converts between TCPSegment and binary (network byte order) TCP header.

Constructor & Destructor Documentation

inet::serializer::TCPSerializer::TCPSerializer ( const char *  name = nullptr)
inline
47 : SerializerBase(name) {}
SerializerBase(const char *name=nullptr)
Definition: SerializerBase.h:84

Member Function Documentation

cPacket * inet::TCPSerializer::deserialize ( const Buffer b,
Context context 
)
overrideprotectedvirtual

Puts a packet sniffed from the wire into an EtherFrame.

Implements inet::serializer::SerializerBase.

Referenced by inet::tcp::TCP_NSC_VirtualDataSendQueue::createSegmentWithBytes(), inet::tcp::TcpLwipVirtualDataSendQueue::createSegmentWithBytes(), inet::tcp::TCP_NSC_ByteStreamSendQueue::createSegmentWithBytes(), inet::tcp::TcpLwipByteStreamSendQueue::createSegmentWithBytes(), inet::tcp::TcpLwipMsgBasedSendQueue::createSegmentWithBytes(), inet::tcp::TCP_lwIP::ip_output(), and inet::tcp::TCP_NSC::sendToIP().

289 {
290  struct tcphdr tcp;
291  memset(&tcp, 0, sizeof(tcp));
292  ASSERT(sizeof(tcp) == TCP_HEADER_OCTETS);
293  b.readNBytes(TCP_HEADER_OCTETS, &tcp);
294 
295  TCPSegment *tcpseg = new TCPSegment("parsed-tcp");
296 
297  // fill TCP header structure
298  tcpseg->setSrcPort(ntohs(tcp.th_sport));
299  tcpseg->setDestPort(ntohs(tcp.th_dport));
300  tcpseg->setSequenceNo(ntohl(tcp.th_seq));
301  tcpseg->setAckNo(ntohl(tcp.th_ack));
302  unsigned short hdrLength = tcp.th_offs * 4;
303  tcpseg->setHeaderLength(hdrLength);
304 
305  // set flags
306  unsigned char flags = tcp.th_flags;
307  tcpseg->setFinBit((flags & TH_FIN) == TH_FIN);
308  tcpseg->setSynBit((flags & TH_SYN) == TH_SYN);
309  tcpseg->setRstBit((flags & TH_RST) == TH_RST);
310  tcpseg->setPshBit((flags & TH_PUSH) == TH_PUSH);
311  tcpseg->setAckBit((flags & TH_ACK) == TH_ACK);
312  tcpseg->setUrgBit((flags & TH_URG) == TH_URG);
313 
314  tcpseg->setWindow(ntohs(tcp.th_win));
315 
316  tcpseg->setUrgentPointer(ntohs(tcp.th_urp));
317 
318  if (hdrLength > TCP_HEADER_OCTETS) { // options present?
319  unsigned short optionBytes = hdrLength - TCP_HEADER_OCTETS; // TCP_HEADER_OCTETS = 20
320  Buffer sb(b, optionBytes);
321 
322  while (sb.getRemainingSize()) {
323  TCPOption *option = deserializeOption(sb, c);
324  tcpseg->addHeaderOption(option);
325  }
326  if (sb.hasError())
327  b.setError();
328  } // if options present
329  b.seek(hdrLength);
330  tcpseg->setByteLength(b._getBufSize());
331  unsigned int payloadLength = b.getRemainingSize();
332  tcpseg->setPayloadLength(payloadLength);
333  tcpseg->getByteArray().setDataFromBuffer(b.accessNBytes(payloadLength), payloadLength);
334 
335  if (b.hasError())
336  tcpseg->setBitError(true);
337  // Checksum: modeled by cPacket::hasBitError()
338  if (tcp.th_sum != 0 && c.l3AddressesPtr && c.l3AddressesLength && TCPIPchecksum::checksum(IP_PROT_TCP, b._getBuf(), b._getBufSize(), c.l3AddressesPtr, c.l3AddressesLength))
339  tcpseg->setBitError(true);
340  return tcpseg;
341 }
#define TH_ACK
Definition: tcphdr.h:30
u16_t ntohs(u16_t n)
#define TH_PUSH
Definition: tcphdr.h:29
#define TH_URG
Definition: tcphdr.h:31
static uint16_t checksum(const void *addr, unsigned int count)
Definition: TCPIPchecksum.h:44
u32_t ntohl(u32_t n)
#define TH_RST
Definition: tcphdr.h:28
tcp::TCPOption * deserializeOption(Buffer &b, Context &c)
Definition: TCPSerializer.cc:197
const value< double, compose< units::m, pow< units::s,-1 > > > c(299792458)
#define TH_FIN
Definition: tcphdr.h:26
#define TCP_HEADER_OCTETS
Definition: TCPSegment_m.h:50
#define TH_SYN
Definition: tcphdr.h:27
Definition: IPProtocolId_m.h:80
value< double, units::m > b
Definition: Units.h:1054
TCPSegment * inet::TCPSerializer::deserialize ( const unsigned char *  srcbuf,
unsigned int  bufsize,
bool  withBytes 
)

Puts a packet sniffed from the wire into a TCPSegment.

282 {
283  Buffer b(const_cast<unsigned char *>(buf), bufsize);
284  Context c;
285  return check_and_cast_nullable<TCPSegment *>(deserialize(b, c));
286 }
virtual cPacket * deserialize(const Buffer &b, Context &context) override
Puts a packet sniffed from the wire into an EtherFrame.
Definition: TCPSerializer.cc:288
const value< double, compose< units::m, pow< units::s,-1 > > > c(299792458)
value< double, units::m > b
Definition: Units.h:1054
TCPOption * inet::TCPSerializer::deserializeOption ( Buffer b,
Context c 
)
protected
198 {
199  unsigned char kind = b.readByte();
200  unsigned char length = 0;
201 
202  switch (kind) {
203  case TCPOPTION_END_OF_OPTION_LIST: // EOL
204  return new TCPOptionEnd();
205 
206  case TCPOPTION_NO_OPERATION: // NOP
207  return new TCPOptionNop();
208 
210  length = b.readByte();
211  if (length == 4) {
212  auto *option = new TCPOptionMaxSegmentSize();
213  option->setLength(length);
214  option->setMaxSegmentSize(b.readUint16());
215  return option;
216  }
217  break;
218 
220  length = b.readByte();
221  if (length == 3) {
222  auto *option = new TCPOptionWindowScale();
223  option->setLength(length);
224  option->setWindowScale(b.readByte());
225  return option;
226  }
227  break;
228 
230  length = b.readByte();
231  if (length == 2) {
232  auto *option = new TCPOptionSackPermitted();
233  option->setLength(length);
234  return option;
235  }
236  break;
237 
238  case TCPOPTION_SACK:
239  length = b.readByte();
240  if (length > 2 && (length % 8) == 2) {
241  auto *option = new TCPOptionSack();
242  option->setLength(length);
243  option->setSackItemArraySize(length / 8);
244  unsigned int count = 0;
245  for (unsigned int i = 2; i < length; i += 8) {
246  SackItem si;
247  si.setStart(b.readUint32());
248  si.setEnd(b.readUint32());
249  option->setSackItem(count++, si);
250  }
251  return option;
252  }
253  break;
254 
255  case TCPOPTION_TIMESTAMP:
256  length = b.readByte();
257  if (length == 10) {
258  auto *option = new TCPOptionTimestamp();
259  option->setLength(length);
260  option->setSenderTimestamp(b.readUint32());
261  option->setEchoedTimestamp(b.readUint32());
262  return option;
263  }
264  break;
265 
266  default:
267  length = b.readByte();
268  break;
269  } // switch
270 
271  auto *option = new TCPOptionUnknown();
272  option->setKind(kind);
273  option->setLength(length);
274  if (length > 2)
275  option->setBytesArraySize(length - 2);
276  for (unsigned int i = 2; i < length; i++)
277  option->setBytes(i-2, b.readByte());
278  return option;
279 }
Definition: TCPSegment_m.h:114
Definition: TCPSegment_m.h:112
int count(const std::vector< T > &v, const T &a)
Definition: stlutils.h:58
Definition: TCPSegment_m.h:117
Definition: TCPSegment_m.h:118
Definition: TCPSegment_m.h:113
Definition: TCPSegment_m.h:116
value< double, units::m > b
Definition: Units.h:1054
Definition: TCPSegment_m.h:115
void inet::TCPSerializer::serialize ( const cPacket *  pkt,
Buffer b,
Context context 
)
overrideprotectedvirtual

Serializes a cPacket for transmission on the wire.

Returns the length of data written into buffer.

Implements inet::serializer::SerializerBase.

130 {
131  ASSERT(b.getPos() == 0);
132  const TCPSegment *tcpseg = check_and_cast<const TCPSegment *>(pkt);
133  struct tcphdr tcp; // = (struct tcphdr *)(b.accessNBytes(sizeof(struct tcphdr)))
134 
135  int writtenbytes = tcpseg->getByteLength();
136 
137  // fill TCP header structure
138  tcp.th_sum = 0;
139  tcp.th_sport = htons(tcpseg->getSrcPort());
140  tcp.th_dport = htons(tcpseg->getDestPort());
141  tcp.th_seq = htonl(tcpseg->getSequenceNo());
142  tcp.th_ack = htonl(tcpseg->getAckNo());
143  tcp.th_offs = TCP_HEADER_OCTETS / 4;
144  tcp.th_x2 = 0; // unused
145 
146  // set flags
147  unsigned char flags = 0;
148  if (tcpseg->getFinBit())
149  flags |= TH_FIN;
150  if (tcpseg->getSynBit())
151  flags |= TH_SYN;
152  if (tcpseg->getRstBit())
153  flags |= TH_RST;
154  if (tcpseg->getPshBit())
155  flags |= TH_PUSH;
156  if (tcpseg->getAckBit())
157  flags |= TH_ACK;
158  if (tcpseg->getUrgBit())
159  flags |= TH_URG;
160  tcp.th_flags = (TH_FLAGS & flags);
161  tcp.th_win = htons(tcpseg->getWindow());
162  tcp.th_urp = htons(tcpseg->getUrgentPointer());
163  if (tcpseg->getHeaderLength() % 4 != 0)
164  throw cRuntimeError("invalid TCP header length=%u: must be dividable by 4", tcpseg->getHeaderLength());
165  tcp.th_offs = tcpseg->getHeaderLength() / 4;
166  b.writeNBytes(TCP_HEADER_OCTETS, &tcp);
167  unsigned short numOptions = tcpseg->getHeaderOptionArraySize();
168  unsigned int optionsLength = 0;
169  if (numOptions > 0) { // options present?
170  for (unsigned short i = 0; i < numOptions; i++) {
171  const TCPOption *option = tcpseg->getHeaderOption(i);
172  serializeOption(option, b, c);
173  optionsLength += option->getLength();
174  } // for
175  //padding:
176  optionsLength %= 4;
177  if (optionsLength)
178  b.fillNBytes(4 - optionsLength, 0);
179  } // if options present
180 
181  // write data
182  if (tcpseg->getByteLength() > tcpseg->getHeaderLength()) { // data present? FIXME TODO: || tcpseg->getEncapsulatedPacket()!=nullptr
183  unsigned int dataLength = tcpseg->getByteLength() - tcpseg->getHeaderLength();
184 
185  if (tcpseg->getByteArray().getDataArraySize() > 0) {
186  ASSERT(tcpseg->getByteArray().getDataArraySize() == dataLength);
187  tcpseg->getByteArray().copyDataToBuffer(b.accessNBytes(0), b.getRemainingSize());
188  b.accessNBytes(dataLength);
189  }
190  else
191  b.fillNBytes(dataLength, 't'); // fill data part with 't'
192  }
193  writtenbytes = b.getPos();
194  b.writeUint16To(16, TCPIPchecksum::checksum(IP_PROT_TCP, b._getBuf(), writtenbytes, c.l3AddressesPtr, c.l3AddressesLength));
195 }
#define TH_ACK
Definition: tcphdr.h:30
void serializeOption(const tcp::TCPOption *option, Buffer &b, Context &c)
Definition: TCPSerializer.cc:54
#define TH_PUSH
Definition: tcphdr.h:29
#define TH_URG
Definition: tcphdr.h:31
static uint16_t checksum(const void *addr, unsigned int count)
Definition: TCPIPchecksum.h:44
#define TH_RST
Definition: tcphdr.h:28
u16_t htons(u16_t n)
const value< double, compose< units::m, pow< units::s,-1 > > > c(299792458)
#define TH_FIN
Definition: tcphdr.h:26
u32_t htonl(u32_t n)
#define TCP_HEADER_OCTETS
Definition: TCPSegment_m.h:50
#define TH_SYN
Definition: tcphdr.h:27
#define TH_FLAGS
Definition: tcphdr.h:32
Definition: IPProtocolId_m.h:80
value< double, units::m > b
Definition: Units.h:1054
void inet::TCPSerializer::serializeOption ( const tcp::TCPOption option,
Buffer b,
Context c 
)
protected
55 {
56  unsigned short kind = option->getKind();
57  unsigned short length = option->getLength(); // length >= 1
58 
59  b.writeByte(kind);
60  if (length > 1)
61  b.writeByte(length);
62 
63  auto *opt = dynamic_cast<const TCPOptionUnknown *>(option);
64  if (opt) {
65  unsigned int datalen = opt->getBytesArraySize();
66  ASSERT(length == 2 + datalen);
67  for (unsigned int i = 0; i < datalen; i++)
68  b.writeByte(opt->getBytes(i));
69  return;
70  }
71 
72  switch (kind) {
73  case TCPOPTION_END_OF_OPTION_LIST: // EOL
74  check_and_cast<const TCPOptionEnd *>(option);
75  ASSERT(length == 1);
76  break;
77 
78  case TCPOPTION_NO_OPERATION: // NOP
79  check_and_cast<const TCPOptionNop *>(option);
80  ASSERT(length == 1);
81  break;
82 
84  auto *opt = check_and_cast<const TCPOptionMaxSegmentSize *>(option);
85  ASSERT(length == 4);
86  b.writeUint16(opt->getMaxSegmentSize());
87  break;
88  }
89 
91  auto *opt = check_and_cast<const TCPOptionWindowScale *>(option);
92  ASSERT(length == 3);
93  b.writeByte(opt->getWindowScale());
94  break;
95  }
96 
98  auto *opt = check_and_cast<const TCPOptionSackPermitted *>(option); (void)opt; // UNUSED
99  ASSERT(length == 2);
100  break;
101  }
102 
103  case TCPOPTION_SACK: {
104  auto *opt = check_and_cast<const TCPOptionSack *>(option);
105  ASSERT(length == 2 + opt->getSackItemArraySize() * 8);
106  for (unsigned int i = 0; i < opt->getSackItemArraySize(); i++) {
107  SackItem si = opt->getSackItem(i);
108  b.writeUint32(si.getStart());
109  b.writeUint32(si.getEnd());
110  }
111  break;
112  }
113 
114  case TCPOPTION_TIMESTAMP: {
115  auto *opt = check_and_cast<const TCPOptionTimestamp *>(option);
116  ASSERT(length == 10);
117  b.writeUint32(opt->getSenderTimestamp());
118  b.writeUint32(opt->getEchoedTimestamp());
119  break;
120  }
121 
122  default: {
123  throw cRuntimeError("Unknown TCPOption kind=%d (not in a TCPOptionUnknown option)", kind);
124  break;
125  }
126  } // switch
127 }
Definition: TCPSegment_m.h:114
Definition: TCPSegment_m.h:112
Definition: TCPSegment_m.h:117
Definition: TCPSegment_m.h:118
Definition: TCPSegment_m.h:113
Definition: TCPSegment_m.h:116
value< double, units::m > b
Definition: Units.h:1054
Definition: TCPSegment_m.h:115

The documentation for this class was generated from the following files: