embkernel
 All Classes Functions Variables Typedefs Groups Pages
NetTcp.cpp
1 //------------------------------------------------------------------------------
2 //This file is part of embKernel.
3 //See license.txt for the full license governing this code.
4 //------------------------------------------------------------------------------
5 
6 #include "NetTcp.hpp"
7 #include "Net.hpp"
8 #include "NetIp.hpp"
9 #include "LibEndian.hpp"
10 #include "NetTcpSocket.hpp"
11 #include "NetChecksum.hpp"
12 
13 LibLinkedList<NetTcpSocket> NetTcp::sSocketList;
14 RtosSemaphore NetTcp::sSema(1, 1);
15 
16 void NetTcp::processFrame(NetDefs::FRAME& frame, NetDefs::TCP_HEADER& header, int len) {
17 
18  // Check checksum
19  NetDefs::IP_PSEUDO_HEADER ipPseudoHeader;
20  ipPseudoHeader.srcAddr = frame.types.ip.ipHeader.srcAddr;
21  ipPseudoHeader.dstAddr = frame.types.ip.ipHeader.dstAddr;
22  ipPseudoHeader.zero = 0x0;
23  ipPseudoHeader.protocol = NetDefs::IP_PROTOCOL_TCP;
24  ipPseudoHeader.len = LibEndian::beToHw((uint16_t) len);
25 
26  uint32_t checkSum = NetChecksum::calcPartialChecksum((uint8_t*) &ipPseudoHeader, sizeof(ipPseudoHeader));
27 
28  checkSum += NetChecksum::calcPartialChecksum((uint8_t*) &header, len);
29 
30  checkSum = NetChecksum::finalizeCheckSum(checkSum);
31 
32  if (checkSum) {
33  Net::freeFrame(frame);
34  return;
35  }
36 
37  swapHeader(header);
38 
39  sSema.take(Rtos::TICK_INFINITE);
40 
41  NetTcpSocket* s = findMatchingSocket(header, frame.types.ip.ipHeader.srcAddr);
42 
43  if (!s) {
44  sSema.give(Rtos::TICK_INFINITE);
45  Net::freeFrame(frame);
46  return;
47  }
48 
49  if (!onSegmentReceived(frame, header, *s, len)) {
50  Net::freeFrame(frame);
51  }
52  sSema.give(Rtos::TICK_INFINITE);
53 }
54 
55 bool NetTcp::onSegmentReceived(NetDefs::FRAME& frame, NetDefs::TCP_HEADER& header, NetTcpSocket& s, int len) {
56 
57  //Acknowledge TX segments
58  if (header.flags.bits.ack) {
59  for (; s.mTxFirstSegment != 0;) {
60  uint32_t diff = header.ack - (s.mTxFirstSegment->hdr.seq + s.mTxFirstSegment->hdr.len);
61  if (diff < 0x80000000) {
62  NetTcpSocket::TX_SEGMENT* next = s.mTxFirstSegment->next;
63  Net::freeFrame((NetDefs::FRAME&) *s.mTxFirstSegment);
64  s.mTxFirstSegment = next;
65  }
66  else {
67  break;
68  }
69  }
70  }
71 
72  if (header.flags.bits.rst) {
73  switch (s.mState) {
74  case NetTcpSocket::STATE_LISTEN:
75  break;
76  case NetTcpSocket::STATE_SYN_SENT:
77  s.mState = NetTcpSocket::STATE_CLOSED;
78  s.mSemaEvent.give(0);
79  break;
80  case NetTcpSocket::STATE_SYN_RCVD:
81  s.mState = NetTcpSocket::STATE_LISTEN;
82  break;
83  case NetTcpSocket::STATE_EST: {
84  s.discardAllRxSegments();
85  s.discardAllTxSegments();
86  if (s.mIsAutoListenAndAccept) {
87  s.mState = NetTcpSocket::STATE_LISTEN;
88  }
89  else {
90  s.mState = NetTcpSocket::STATE_RESET;
91  NetTcpSocket::RX_SEGMENT* seg = 0;
92  s.mRxMsgBox.give(seg, 0);
93  }
94  break;
95  }
96  default:
97  s.discardAllTxSegments();
98  s.discardAllTxSegments();
99  if (s.mIsAutoListenAndAccept) {
100  s.mState = NetTcpSocket::STATE_LISTEN;
101  }
102  else {
103  s.mState = NetTcpSocket::STATE_RESET;
104  }
105  break;
106  }
107  return false;
108  }
109 
110  switch (s.mState) {
111  case NetTcpSocket::STATE_LISTEN:
112  if (header.flags.bits.syn) {
113  s.mRemoteMacAddr = frame.types.mac.macHeader.srcAddr;
114  s.mRemoteIpAddr = frame.types.ip.ipHeader.srcAddr;
115  s.mRemotePort = header.srcPort;
116  s.mSentCount = 1;
117  s.mRecvCount = header.seq + 1;
118 
119  s.mRetries = MAX_RETRIES_SYN_RCVD;
120  s.mTimer = TIMER_SYN_RCVD;
121  s.mState = NetTcpSocket::STATE_SYN_RCVD;
122  sendControlPacket(s, NetDefs::TCP_FLAG_SYN | NetDefs::TCP_FLAG_ACK);
123  s.mSentCount++;
124  }
125  return false;
126  case NetTcpSocket::STATE_SYN_SENT:
127  if (header.flags.bits.syn && header.flags.bits.ack && (header.ack == s.mSentCount)) {
128  s.mRecvCount = header.seq + 1;
129  sendControlPacket(s, NetDefs::TCP_FLAG_ACK);
130  s.mRetries = MAX_RETRIES_EST_KEEP_ALIVE;
131  s.mTimer = TIMER_EST_KEEP_ALIVE;
132  s.mState = NetTcpSocket::STATE_EST;
133  s.mSemaEvent.give(0);
134  }
135  return false;
136  case NetTcpSocket::STATE_SYN_RCVD:
137  if (header.flags.bits.ack) {
138  if (header.seq == s.mRecvCount) {
139  s.mRecvCount = header.seq;
140  s.mRetries = MAX_RETRIES_EST_KEEP_ALIVE;
141  s.mTimer = TIMER_EST_KEEP_ALIVE;
142  s.mState = NetTcpSocket::STATE_EST;
143  if (!s.mIsAutoListenAndAccept) {
144  s.mSemaEvent.give(0);
145  }
146  }
147  }
148  return false;
149  case NetTcpSocket::STATE_EST: {
150  if (header.seq != s.mRecvCount) {
151  //Did we miss a packet or an ack got lost?
152  //resend the current ack
153  sendControlPacket(s, NetDefs::TCP_FLAG_ACK);
154  }
155  else {
156  if (header.flags.bits.fin) {
157  s.discardAllTxSegments();
158  s.mRecvCount++;
159  s.mSentCount = header.ack;
160  sendControlPacket(s, NetDefs::TCP_FLAG_ACK);
161  if (s.mIsAutoListenAndAccept) {
162  sendControlPacket(s, NetDefs::TCP_FLAG_FIN | NetDefs::TCP_FLAG_ACK);
163  s.mState = NetTcpSocket::STATE_LAST_ACK;
164  s.mRetries = MAX_RETRIES_LAST_ACK;
165  s.mTimer = TIMER_LAST_ACK;
166  }
167  else {
168  s.mState = NetTcpSocket::STATE_CLOSE_WAIT;
169  NetTcpSocket::RX_SEGMENT* seg = 0;
170  s.mRxMsgBox.give(seg, 0);
171  }
172  }
173  else {
174  s.mRetries = MAX_RETRIES_EST_KEEP_ALIVE;
175  s.mTimer = TIMER_EST_KEEP_ALIVE;
176  }
177 
178  int optionLen = (((int) header.offset.val) << 2) - sizeof(NetDefs::TCP_HEADER);
179  int dataLen = len - (((int) header.offset.val) << 2);
180 
181  if (dataLen > 0) {
182  if (dataLen <= s.mWindowSize) {
183  NetTcpSocket::RX_SEGMENT* seg = (NetTcpSocket::RX_SEGMENT*) Net::resizeFrameLeft(frame,
184  (((uint8_t*) &header + sizeof(NetDefs::TCP_HEADER) + optionLen - (uint8_t*) &frame)) - sizeof(NetTcpSocket::RX_SEGMENT_HEADER));
185 
186  if (!seg) {
187  return false;
188  }
189  seg->hdr.dataLen = dataLen;
190  if (!s.mRxMsgBox.give(seg, 0)) {
191  Net::freeFrame((NetDefs::FRAME&) *seg);
192  }
193  else {
194  s.mWindowSize -= dataLen;
195  s.mRecvCount += dataLen;
196  sendControlPacket(s, NetDefs::TCP_FLAG_ACK);
197  }
198  return true;
199  }
200  }
201  }
202  return false;
203  }
204  case NetTcpSocket::STATE_FIN_WAIT_1:
205  if ((header.seq == s.mRecvCount)) {
206  s.mRecvCount += len - (((int) header.offset.val) << 2);
207 
208  if (header.flags.bits.fin && header.flags.bits.ack) {
209  s.mRecvCount++;
210  sendControlPacket(s, NetDefs::TCP_FLAG_ACK);
211  s.mSentCount++;
212  s.mTimer = TIMER_TIME_WAIT;
213  s.mState = NetTcpSocket::STATE_TIME_WAIT;
214  }
215  else if (header.flags.bits.ack) {
216  s.mRetries = MAX_RETRIES_FIN_WAIT_2;
217  s.mTimer = TIMER_FIN_WAIT_2;
218  s.mState = NetTcpSocket::STATE_FIN_WAIT_2;
219  }
220  else if (header.flags.bits.fin) {
221  s.mRecvCount++;
222  sendControlPacket(s, NetDefs::TCP_FLAG_ACK);
223  s.mSentCount++;
224  s.mRetries = MAX_RETRIES_CLOSING;
225  s.mTimer = TIMER_CLOSING;
226  s.mState = NetTcpSocket::STATE_CLOSING;
227  }
228  }
229  return false;
230  case NetTcpSocket::STATE_FIN_WAIT_2:
231  if (header.seq == s.mRecvCount) {
232  s.mRecvCount += len - (((int) header.offset.val) << 2);
233  if (header.flags.bits.fin) {
234  s.mRecvCount++;
235  sendControlPacket(s, NetDefs::TCP_FLAG_ACK);
236  s.mSentCount++;
237  s.mTimer = TIMER_TIME_WAIT;
238  s.mState = NetTcpSocket::STATE_TIME_WAIT;
239  }
240  }
241  return false;
242  case NetTcpSocket::STATE_CLOSING:
243  if (header.seq == s.mRecvCount) {
244  s.mRecvCount += len - (((int) header.offset.val) << 2);
245  if (header.flags.bits.ack) {
246  s.mTimer = TIMER_TIME_WAIT;
247  s.mState = NetTcpSocket::STATE_TIME_WAIT;
248  }
249  }
250  return false;
251  case NetTcpSocket::STATE_TIME_WAIT:
252  if (header.seq == s.mRecvCount) {
253  sendControlPacket(s, NetDefs::TCP_FLAG_ACK);
254  }
255  return false;
256  case NetTcpSocket::STATE_LAST_ACK:
257  if (header.seq == s.mRecvCount) {
258  if (header.flags.bits.ack) {
259  s.discardAllTxSegments();
260  s.discardAllRxSegments();
261  if (s.mIsAutoListenAndAccept) {
262  s.mState = NetTcpSocket::STATE_LISTEN;
263  }
264  else {
265  removeSocket(s);
266  s.mState = NetTcpSocket::STATE_CLOSED;
267  delete (&s);
268  }
269  }
270  }
271  return false;
272  default:
273  return false;
274  }
275 }
276 
277 void NetTcp::tick() { //Every 10ms
278  sSema.take(Rtos::TICK_INFINITE);
279 
280  for (NetTcpSocket* s = sSocketList.getFirst(); s != 0; s = s->getNext()) {
281  //Flush ready segments
282  for (NetTcpSocket::TX_SEGMENT* segment = s->mTxFirstSegment; segment != 0; segment = segment->next) {
283  if (segment->hdr.timeout-- <= 0) {
284  if (segment->hdr.retries > 0) {
285  flushSegment(*s, *segment);
286  s->mRetries = MAX_RETRIES_EST_KEEP_ALIVE;
287  s->mTimer = TIMER_EST_KEEP_ALIVE;
288  }
289  else {
290  //discard all tx segments
291  s->mSentCount = s->mTxFirstSegment->hdr.seq;
292  s->discardAllTxSegments();
293  sendControlPacket(*s, NetDefs::TCP_FLAG_PSH | NetDefs::TCP_FLAG_RST);
294  if (s->mIsAutoListenAndAccept) {
295  s->discardAllRxSegments();
296  s->mState = NetTcpSocket::STATE_LISTEN;
297  }
298  else {
299  s->mState = NetTcpSocket::STATE_CLOSE_WAIT;
300  }
301  }
302  }
303  }
304 
305  if (s->mTimer-- > 0) {
306  continue;
307  }
308 
309  switch (s->mState) {
310  case NetTcpSocket::STATE_SYN_SENT:
311  if (s->mRetries--) {
312  s->mSentCount--;
313  sendControlPacket(*s, NetDefs::TCP_FLAG_SYN);
314  s->mSentCount++;
315  s->mTimer = TIMER_SYN_RCVD;
316  }
317  else {
318  s->mState = NetTcpSocket::STATE_CLOSED;
319  s->mSemaEvent.give(0);
320  }
321  break;
322  case NetTcpSocket::STATE_SYN_RCVD:
323  if (s->mRetries--) {
324  s->mSentCount--;
325  sendControlPacket(*s, NetDefs::TCP_FLAG_SYN | NetDefs::TCP_FLAG_ACK);
326  s->mSentCount++;
327  s->mTimer = TIMER_SYN_RCVD;
328  }
329  else {
330  sendControlPacket(*s, NetDefs::TCP_FLAG_PSH | NetDefs::TCP_FLAG_RST);
331  s->mState = NetTcpSocket::STATE_LISTEN;
332  }
333  break;
334  case NetTcpSocket::STATE_EST:
335  if (s->mTxFirstSegment == 0) {
336  if (s->mRetries--) {
337  s->mSentCount--;
338  sendControlPacket(*s, NetDefs::TCP_FLAG_ACK);
339  s->mSentCount++;
340  s->mTimer = TIMER_EST_KEEP_ALIVE;
341  }
342  else {
343  sendControlPacket(*s, NetDefs::TCP_FLAG_PSH | NetDefs::TCP_FLAG_RST);
344  if (s->mIsAutoListenAndAccept) {
345  s->discardAllRxSegments();
346  s->discardAllTxSegments();
347  s->mState = NetTcpSocket::STATE_LISTEN;
348  }
349  else {
350  s->mState = NetTcpSocket::STATE_CLOSE_WAIT;
351  NetTcpSocket::RX_SEGMENT* seg = 0;
352  s->mRxMsgBox.give(seg, 0);
353  }
354  }
355  }
356  break;
357  case NetTcpSocket::STATE_LAST_ACK:
358  if (s->mRetries--) {
359  s->mSentCount--;
360  sendControlPacket(*s, NetDefs::TCP_FLAG_PSH | NetDefs::TCP_FLAG_FIN | NetDefs::TCP_FLAG_ACK);
361  s->mSentCount++;
362  s->mTimer = TIMER_LAST_ACK;
363  }
364  else {
365  // Send Reset
366  s->mSentCount--;
367  sendControlPacket(*s, NetDefs::TCP_FLAG_PSH | NetDefs::TCP_FLAG_RST);
368  if (s->mIsAutoListenAndAccept) {
369  s->discardAllRxSegments();
370  s->discardAllTxSegments();
371  s->mState = NetTcpSocket::STATE_LISTEN;
372  }
373  else {
374  s->mTimer = TIMER_TIME_WAIT;
375  s->mState = NetTcpSocket::STATE_TIME_WAIT;
376  }
377  }
378  break;
379  case NetTcpSocket::STATE_FIN_WAIT_1:
380  if (s->mRetries--) {
381  s->mSentCount--;
382  sendControlPacket(*s, NetDefs::TCP_FLAG_PSH | NetDefs::TCP_FLAG_FIN | NetDefs::TCP_FLAG_ACK);
383  s->mSentCount++;
384  s->mTimer = TIMER_FIN_WAIT_1;
385  }
386  else {
387  // Send Reset
388  s->mSentCount--;
389  sendControlPacket(*s, NetDefs::TCP_FLAG_PSH | NetDefs::TCP_FLAG_RST);
390  s->mTimer = TIMER_TIME_WAIT;
391  s->mState = NetTcpSocket::STATE_TIME_WAIT;
392  }
393  break;
394  case NetTcpSocket::STATE_FIN_WAIT_2:
395  sendControlPacket(*s, NetDefs::TCP_FLAG_PSH | NetDefs::TCP_FLAG_RST);
396  s->mTimer = TIMER_TIME_WAIT;
397  s->mState = NetTcpSocket::STATE_TIME_WAIT;
398  break;
399  case NetTcpSocket::STATE_CLOSING:
400  sendControlPacket(*s, NetDefs::TCP_FLAG_PSH | NetDefs::TCP_FLAG_RST);
401  s->mTimer = TIMER_TIME_WAIT;
402  s->mState = NetTcpSocket::STATE_TIME_WAIT;
403  break;
404  case NetTcpSocket::STATE_TIME_WAIT:
405  s->discardAllTxSegments();
406  removeSocket(*s);
407  s->mState = NetTcpSocket::STATE_CLOSED;
408  delete (s);
409  break;
410  default:
411  break;
412  }
413  }
414 
415  sSema.give(Rtos::TICK_INFINITE);
416 }
417 
418 void NetTcp::sendControlPacket(NetTcpSocket& s, uint8_t flags) {
419  NetDefs::FRAME* frame;
420  int len = sizeof(NetDefs::TCP_HEADER);
421 
422  if (flags & NetDefs::TCP_FLAG_SYN) {
423  len += sizeof(NetDefs::TCP_HEADER_OPTIONS);
424  }
425 
426  frame = Net::allocFrame(sizeof(NetDefs::MAC_HEADER) + sizeof(NetDefs::IP_HEADER) + len);
427 
428  if (frame == 0) {
429  return;
430  }
431 
432  putHeader(*frame, s, s.mSentCount, 0, 0, flags);
433  NetIp::flush(*frame, len, true);
434 }
435 
436 void NetTcp::putHeader(NetDefs::FRAME& frame, NetTcpSocket& s, uint32_t seq, uint32_t checkSum, int dataLen, uint8_t flags) {
437 
438  frame.types.tcp.tcpHeader.srcPort = s.mLocalPort;
439  frame.types.tcp.tcpHeader.dstPort = s.mRemotePort;
440  frame.types.tcp.tcpHeader.ack = s.mRecvCount;
441  frame.types.tcp.tcpHeader.seq = seq;
442  frame.types.tcp.tcpHeader.offset.zero = 0;
443  frame.types.tcp.tcpHeader.flags.value = flags;
444  frame.types.tcp.tcpHeader.window = s.mWindowSize;
445  frame.types.tcp.tcpHeader.checkSum = 0;
446  frame.types.tcp.tcpHeader.urgentPointer = 0;
447 
448  swapHeader(frame.types.tcp.tcpHeader);
449 
450  if (flags & NetDefs::TCP_FLAG_SYN) {
451  frame.types.tcp_with_options.tcpOptions.type = OPTIONS_MAX_SEG_SIZE;
452  frame.types.tcp_with_options.tcpOptions.len = 0x04;
453  frame.types.tcp_with_options.tcpOptions.maxSegLen = frame.types.tcp.tcpHeader.window;
454  frame.types.tcp.tcpHeader.offset.val = (sizeof(NetDefs::TCP_HEADER) + sizeof(NetDefs::TCP_HEADER_OPTIONS)) >> 2;
455  checkSum += NetChecksum::calcPartialChecksum((uint8_t*) &frame.types.tcp_with_options.tcpOptions, sizeof(NetDefs::TCP_HEADER_OPTIONS));
456  dataLen += sizeof(NetDefs::TCP_HEADER_OPTIONS);
457  }
458  else {
459  frame.types.tcp.tcpHeader.offset.val = sizeof(NetDefs::TCP_HEADER) >> 2;
460  }
461 
462  {
463  NetDefs::IP_PSEUDO_HEADER pseudoHeader;
464 
465  // Calculate IP pseudoheader checksum.
466  pseudoHeader.srcAddr.val = Net::sConfig.ipAddr.val;
467  pseudoHeader.dstAddr.val = s.mRemoteIpAddr.val;
468  pseudoHeader.zero = 0x0;
469  pseudoHeader.protocol = NetDefs::IP_PROTOCOL_TCP;
470  pseudoHeader.len = LibEndian::hwToBe((uint16_t) (sizeof(NetDefs::TCP_HEADER) + dataLen));
471 
472  checkSum += NetChecksum::calcPartialChecksum((uint8_t*) &pseudoHeader, sizeof(NetDefs::IP_PSEUDO_HEADER));
473  checkSum += NetChecksum::calcPartialChecksum((uint8_t*) &frame.types.tcp.tcpHeader, sizeof(NetDefs::TCP_HEADER));
474 
475  }
476 
477  frame.types.tcp.tcpHeader.checkSum = NetChecksum::finalizeCheckSum(checkSum);
478 
479  NetIp::putHeader(frame, s.mRemoteMacAddr, s.mRemoteIpAddr, sizeof(NetDefs::TCP_HEADER) + dataLen, NetDefs::IP_PROTOCOL_TCP);
480 }
481 
482 NetTcpSocket* NetTcp::findMatchingSocket(NetDefs::TCP_HEADER& header, NetDefs::IP_ADDR& remoteIpAddr) {
483  NetTcpSocket* result = 0;
484 
485  for (NetTcpSocket* s = sSocketList.getFirst(); s != 0; s = s->getNext()) {
486  if (s->mState > NetTcpSocket::STATE_CLOSED) {
487  if (s->mLocalPort == header.dstPort) {
488  if (s->mState == NetTcpSocket::STATE_LISTEN) {
489  result = s;
490  }
491  else if ((s->mRemotePort == header.srcPort) && (s->mRemoteIpAddr == remoteIpAddr)) {
492  return s;
493  }
494  }
495  }
496  }
497  if (!header.flags.bits.syn) {
498  return 0;
499  }
500  return result;
501 }
502 
503 void NetTcp::lock() {
504  sSema.take(Rtos::TICK_INFINITE);
505 }
506 
507 void NetTcp::unlock() {
508  sSema.give(Rtos::TICK_INFINITE);
509 }
510 
511 void NetTcp::addSocket(NetTcpSocket& socket) {
512  sSocketList.insert(socket);
513 }
514 
515 void NetTcp::removeSocket(NetTcpSocket& socket) {
516  sSocketList.remove(socket);
517 }
518 
519 void NetTcp::flushSegment(NetTcpSocket& s, NetTcpSocket::TX_SEGMENT& segment) {
520  if (!segment.hdr.flushed) {
521  //Calculate data checksum
522  segment.hdr.dataChecksum = NetChecksum::calcPartialChecksum(segment.frame.types.tcp.data, segment.hdr.len);
523  segment.hdr.flushed = true;
524  s.mSentCount += segment.hdr.len;
525  }
526  putHeader(segment.frame, s, segment.hdr.seq, segment.hdr.dataChecksum, segment.hdr.len, NetDefs::TCP_FLAG_PSH | NetDefs::TCP_FLAG_ACK);
527  NetIp::flush(segment.frame, sizeof(NetDefs::TCP_HEADER) + segment.hdr.len, false);
528  if (&segment == s.mTxCurrentSegment) {
529  s.mTxCurrentSegment = 0;
530  }
531  segment.hdr.timeout = TIMER_SEGMENT_RETRY;
532  segment.hdr.retries--;
533 }
534 
535 int NetTcp::getTcpSocketList(SOCKET_INFO* buffer, int count) {
536  sSema.take(Rtos::TICK_INFINITE);
537  int i = 0;
538  for (NetTcpSocket* s = sSocketList.getFirst(); s != 0 && i < count; s = s->getNext(), buffer++) {
539  buffer->remoteIpAddr = s->mRemoteIpAddr;
540  buffer->localPort = s->mLocalPort;
541  buffer->remotePort = s->mRemotePort;
542  buffer->state = s->mState;
543  i++;
544  }
545  sSema.give(Rtos::TICK_INFINITE);
546  return i;
547 }
548 
549 void NetTcp::swapHeader(NetDefs::TCP_HEADER& header) {
550  header.srcPort = LibEndian::hwToBe(header.srcPort);
551  header.dstPort = LibEndian::hwToBe(header.dstPort);
552  header.seq = LibEndian::hwToBe(header.seq);
553  header.ack = LibEndian::hwToBe(header.ack);
554  header.window = LibEndian::hwToBe(header.window);
555  header.checkSum = LibEndian::hwToBe(header.checkSum);
556  header.urgentPointer = LibEndian::hwToBe(header.urgentPointer);
557 }