NetBurner 3.1
tcp_internal.h
1 #ifndef __TCP_INTERNAL_H
2 #define __TCP_INTERNAL_H
3 
4 // NB Definitions
5 #include <predef.h>
6 
7 // NB Libs
8 #include <iointernal.h>
9 #include <ip.h>
10 #include <netinterface.h>
11 #include <nettypes.h>
12 #include <tcp.h>
13 
14 #ifdef IPV6
15 #include <ipv6/ipv6_frames.h>
16 #include <ipv6/ipv6_interface.h>
17 #endif
18 
19 #define TCP_FIN (1)
20 #define TCP_SYN (2)
21 #define TCP_RST (4)
22 #define TCP_PSH (8)
23 #define TCP_ACK (16)
24 #define TCP_URG (32)
25 
26 /* States are defined in tcp.h */
27 
28 // The following are set into gpflags;
29 #define NEED_TOACK (1)
30 #define TCP_WANTS_TO_CLOSE (2)
31 #define TCP_FIN_SENT (4)
32 #define TCP_ZERO_PROBING (8)
33 #define TCP_USER_CLOSED (16) /* Set only once the user has requested that the socket be closed */
34 #define TCP_INLISTENLIST (32) /* We are currently stored on a Listening socket list */
35 #define TCP_INLISTENCNT (64) /* We are currently counted on a Listening socket list */
36 #define TCP_SAW_SACK (128)
37 
38 #define DEFAULT_MAX_OUTSTANDING_ACK_BUFFERS (10)
39 
40 // Forward declarations
41 struct socket_struct;
42 typedef socket_struct SOCKET;
43 typedef SOCKET *PSOCKET;
44 extern socket_struct sockets[TCP_SOCKET_STRUCTS];
45 
46 class TcpCarrierPacket;
47 
48 #ifdef _DEBUG
49 void DumpTcpPacket(TcpCarrierPacket &ptpkt, uint16_t len);
50 #endif /* ifdef _DEBUG */
51 
52 #define MAXTICKS (0xFFFFFFFF)
53 #define TCPTOTAL_HEADER_SIZE (20 + 20)
54 #ifdef IPV6
55 #define TCPTOTAL_V6_HEADER_SIZE (sizeof(IP6FRAME) + sizeof(TCPPKT))
56 #endif
57 
58 #define DT_STATE_CHANGE 1
59 #define DT_SEND 2
60 #define DT_DISCARD 3
61 #define DT_RX 4
62 #define DT_CLOSE 5
63 #define DT_MAXRETRY_CLOSE 6
64 #define DT_RETRANSMIT 7
65 #define DT_EXTDOCLOSE 8
66 #define DT_GOTFIN 9
67 #define DT_SAVEDATA 10
68 #define DT_ReadCall 11
69 #define DT_ReadFail1 12
70 #define DT_ReadFail2 13
71 #define DT_ReadError 14
72 #define DT_ReadFail4 15
73 #define DT_SAVEZERO 16
74 #define DT_ERRORTIMO 17
75 #define DT_NULLRT 18
76 #define DT_RXDUP 19
77 
78 int GetProperInterfaceForDestination(const IPADDR &dst);
79 BOOL IsLocal(const IPADDR &ip, int ifc);
80 void RemoveFromUserCloseList(PSOCKET ps);
81 
82 #ifdef _DEBUG
83 #define TCP_DEBUG
84 #endif
85 
86 //#define TCP_DEBUG
87 
88 #ifdef TCP_DEBUG
89 static uint16_t dbFlag __attribute__((unused)); // Only used by a macro
90 void DebugTraceFunc(socket_struct *ss, TcpCarrierPacket *ptpkt, uint16_t why, int line);
91 void RawDumpTcpDebug(PSOCKET psfilter);
92 
93 #define DebugTrace(ss, t, why) \
94  if (dbFlag) DebugTraceFunc(ss, t, why, __LINE__);
95 
96 #else
97 #define DebugTrace(w, x, y) ((void)0)
98 #endif
99 
100 #define MAXMAXPEND 8
101 
102 #ifdef IPV6
103 struct IP6FRAME; // Forward
104 class IPv6Interface;
105 #endif
106 
107 class TcpCarrierPacket
108 {
109  PoolPtr pp;
110  PTCPPKT pTcp;
111 #ifdef IPV6
112  union {
113  IP6FRAME *pIp6;
114  PIPPKT pIp4;
115  };
116  bool bIsV6;
117 #else
118  PIPPKT pIp4;
119 #endif
120  puint8_t pData;
121  uint16_t nDataLen;
122 
123  public:
124 #ifdef IPV6
125  TcpCarrierPacket(bool bIsV6 = false);
126  TcpCarrierPacket(IPv6FrameProcessingStruct &p6proc);
127  void InitIPv6Carrier(IPv6FrameProcessingStruct &p6proc);
128  void InitBlank(PoolPtr pp, bool bIsV6 = false);
129 #else
130  TcpCarrierPacket();
131  void InitBlank(PoolPtr pp);
132 #endif
133  TcpCarrierPacket(PoolPtr pp);
134 
135  inline void Free()
136  {
137  pIp4 = NULL;
138  pTcp = NULL;
139  if (pp) FreeBuffer(pp);
140  pp = NULL;
141  };
142  inline PoolPtr Detach()
143  {
144  pIp4 = NULL;
145  pTcp = NULL;
146  PoolPtr rv = pp;
147  pp = NULL;
148  return rv;
149  };
150 
151  // buffer access functions
152  inline uint8_t Get_pp_flag()
153  {
154  if (pp) return pp->bBufferFlag;
155  return 0;
156  };
157  inline uint8_t GetInterface()
158  {
159  if (pp) return pp->bInterfaceNumber;
160  return 0;
161  };
162  inline MACADR GetMacSource() { return GetEframe(pp)->src_addr; };
163 
164  // tcp access functions
165  inline uint8_t GetFlags() { return pTcp->flags; };
166  inline uint16_t GetDestPort()
167  {
168  if (pTcp) return pTcp->dstPort;
169  return 0;
170  };
171  inline uint16_t GetSourcePort()
172  {
173  if (pTcp) return pTcp->srcPort;
174  return 0;
175  };
176  inline uint16_t GetWindow()
177  {
178  if (pTcp) return pTcp->window;
179  return 0;
180  };
181  inline uint32_t GetSeq()
182  {
183  if (pTcp) return pTcp->SeqNumber;
184  return 0;
185  };
186  inline uint32_t GetAck()
187  {
188  if (pTcp) return pTcp->AckNumber;
189  return 0;
190  };
191  inline uint8_t GetHeaderLen()
192  {
193  if (pTcp) return pTcp->header_len;
194  return 0;
195  };
196 
197  inline PTCPPKT GetpTcp() { return pTcp; };
198  inline PoolPtr GetPP() { return pp; };
199 
200  uint16_t GetTcpDataLen() { return nDataLen; };
201  puint8_t GetTcpData() { return pData; };
202  void SetDataLen(uint16_t len) { nDataLen = len; };
203 
204  void SetOutBoundSize(uint16_t data_len);
205 
206  bool IsSourceIP(const IPADDR &ip);
207  uint32_t GetSourceIpHash();
208  uint32_t GetDestinationIpHash();
209  IPADDR GetDestinationIP();
210  IPADDR GetSourceIP();
211 
212  uint16_t GetDefMss(const IPADDR &ip);
213 
214  // Returns true if this sourc ip should loop back to us.
215  bool SourceShouldLoopBack();
216 #ifdef IPV6
217  inline bool IsV6() { return bIsV6; };
218  friend void TcpSendwSum6(PSOCKET ps, const IPADDR &IPto, TcpCarrierPacket &pkt, BOOL keep, uint32_t data_sum);
219  friend void TcpSendwSumFrom6(const IPADDR &IPto, const IPADDR &IPfrom, TcpCarrierPacket &pkt, BOOL keep, uint32_t data_sum);
220  friend void SumTCPV6(IPv6FrameProcessingStruct &p6proc, TcpCarrierPacket &pkt, uint32_t data_csum);
221 #else
222  inline bool IsV6() { return false; };
223 #endif
224  bool Valid() { return (pTcp != 0); };
225 
226  friend void TcpSendwSum4(PSOCKET ps, IPADDR4 to, TcpCarrierPacket &pkt, BOOL keep, uint32_t data_sum);
227 };
228 
229 struct socket_struct : public TimeOutElement
230 {
231  PSOCKET m_pNextActive; // Used for the active list of sockets.
232  PSOCKET m_pPrevActive;
233  PSOCKET m_pListening;
234 
235  volatile uint32_t next_retransmit; // The next retransmit time we have to wake up for
236 
237  // The next three define his window for his reception / my transmission ..
238  //
239  // | | |
240  // data that is long gone | Data waiting to be acked | data I can send | data in the future....
241  // | | |
242  uint32_t sent_and_acked; //------------A
243  uint32_t send_not_acked; //---------------------------------------A
244  uint32_t his_window; //---------------------------------------------------------A
245  uint32_t my_last_window; // Uses for SWS avoidance
246  uint32_t last_seq_I_rxed; // The last sequence I recieved from him....
247  uint32_t close_time;
248  uint32_t lastRxTime;
249 
250  long tick_RTTVAR; // The RTO in ticks. See Stevens IP... Volume 1 pg 300
251  long tick_SRTT; // Also reused to report errors on close
252  long sock_err;
253  uint32_t RTO; /* The actual RTO time out */
254 
255  fifo_buffer_storage TxBuffer; // The buffer for transmit.
256  fifo_buffer_storage RxBuffer; // The buffer for received data
257 
258  PoolPtr buffers_tobe_acked_head; // Buffers that have been sent, and not ACKED
259  PoolPtr buffers_tobe_acked_tail;
260 
261  volatile PoolPtr buffers_out_of_order;
262 
263  OS_SEM m_OsSemaphore; // This is used for all blocking calls.
264 
265  IPADDR my_if_ip;
266  IPADDR his_ip;
267 #ifdef IPV6
268  IPV6_DEST *his_dest;
269 #endif
270 
271  int options; // Socket options
272 
273  uint16_t his_port; // The port he is from
274  uint16_t my_port; // The port he is aimed at
275  uint16_t mss; // His reported max segment size.
276  uint16_t largest_window_iveseen;
277 
278  uint16_t TimeBackPointer;
279  volatile uint8_t state; // The RFC state
280  volatile uint8_t gpflags; // General purpose flags...
281  uint8_t dup_Ack; // Also listining_sockets
282  uint8_t cur_listen;
283  uint8_t nPendingCalls;
284  uint8_t max_listining_sockets;
285  uint8_t outstanding_acks; // Number of things on the tobe_acked list
286  uint8_t max_buffers_out_of_order;
287  volatile uint8_t cur_buffers_out_of_order;
288  void *ExtraData;
289 
290  MACADR mac_shortcut;
291  int Intf_shortcut;
292  bool checksumOffload;
293 #ifdef IPV6
294  IPv6Interface *m_Ip6IfShortCut;
295 #endif
296 
297  uint8_t MAX_OUTSTANDING_ACK_BUFFERS;
298  tcp_notify_handler *pReadNotify;
299  tcp_notify_handler *pWriteNotify;
300  BOOL bLoopBack;
301 
302  // Process packets, checksup is ok when this is called
303  void process(TcpCarrierPacket &tpkt);
304 
305  // Process the options portions of the packet
306  void processoptions(TcpCarrierPacket &tpkt);
307 
308  // We received a segment with data and it is ok to process it.
309  void ProcessDataSegment(TcpCarrierPacket &tpkt, uint16_t data_len, puint8_t data);
310 
311  void TestOutofOrder();
312 
313  // Send ACK SYN FIN etc ...
314  void SendState(uint16_t flags, PoolPtr pp = NULL);
315  void SendState(uint16_t flags, TcpCarrierPacket &tpkt);
316 
317  // Save received data
318  void SaveData(puint8_t data, uint16_t len, BOOL push);
319 
320  // Set the time tick when we want the timer function to call ProcessTimer
321  // If the passed in value is grater than the current value, nothing is done!
322  void SetTimer(uint32_t timeout);
323 
324  void KillTimer(); // Stop timing
325 
326  // Called when the timer is ready to be processed
327  // void ProcessTimer();
328  virtual void TimeElementEvent();
329 
330  // Move things from the tobe set to to be acked and send them out.
331  void DoRawSend();
332 
333  // PRocess the ACKs in received packets.
334  void ProcessAck(TcpCarrierPacket &ptpkt);
335 
336  // Calculate the RTO time
337  void CalcRTO(uint32_t txtime);
338 
339  // Retransmit if necessary.
340  void DoRetransmit(BOOL count);
341 
342  // Setup the timer for retransmit if apropos
343  void SetUpNextRetransmit();
344 
345  // Close the socket
346  int DoClose(int why);
347 
348  // Process received RST
349  void ProcessRST(void);
350 
351  // process received FIN.
352  void ProcessFIN(TcpCarrierPacket &ptpkt, uint16_t data_len);
353 
354  // Reset and free everything
355  void DoCleanup(void);
356 
357  void CleanUpDeletedListener();
358 
359  void SetState(int news);
360 
361  void ClearPending(int why);
362 
363  // Get the window to advertise to avoid SWS....
364  uint16_t MyAdvertisedWindow(void);
365 
366  void OpenWindow(void);
367 
368  void CreateInitOutBoundPacket(TcpCarrierPacket &ptpkt, uint16_t flags, PoolPtr pp);
369 
370  inline int GetMyFd() { return ((this - sockets) + TCP_SOCKET_OFFSET); };
371 
372 #ifdef TCP_NOCOPY_TX
373  // Calc the address for the tcp payload for the given PoolBuffer
374  uint8_t *GetTCPPayload(PoolPtr pp);
375 #endif
376 
377 #ifdef SPEED_TCP
378  int SockSubmitTcpBuffer4Tx(uint32_t csum32bit, uint16_t length, puint8_t pBuffer);
379 
380  tcp_data_handler *pDataHandle;
381 #endif
382 
383  void init(uint16_t pos)
384  {
385  state = TCP_STATE_CLOSED;
386  m_pNextActive = NULL;
387  m_pPrevActive = NULL;
388  dup_Ack = 0;
389  cur_listen = 0;
390  TimeBackPointer = pos + 1;
391  nPendingCalls = 0;
392  options = 0;
393  bLoopBack = FALSE;
394  TxBuffer.Init(TCP_BUFFER_SEGMENTS, 0);
395  RxBuffer.Init(TCP_BUFFER_SEGMENTS, 0);
396  buffers_tobe_acked_head = NULL;
397  buffers_tobe_acked_tail = NULL;
398  outstanding_acks = 0;
399  mac_shortcut = ENET_ZERO;
400  Intf_shortcut = -1;
401  MAX_OUTSTANDING_ACK_BUFFERS = DEFAULT_MAX_OUTSTANDING_ACK_BUFFERS;
402  pReadNotify = NULL;
403 #ifdef SPEED_TCP
404  pDataHandle = NULL;
405 #endif
406  };
407 
408  uint32_t GetFirstSeq();
409  bool PacketMatchesSocket(TcpCarrierPacket &tpkt);
410 
411  int CoreConnect(IPADDR addr, uint16_t localport, uint16_t remoteport, IPADDR ipa);
412 
413  void ShowSocketInfo();
414  static void ShowSocketsInfo(bool includeClosed);
415 } __attribute__((packed));
416 
417 PSOCKET GetTcpSocket(TcpCarrierPacket &pkt);
418 
419 class HashSocketList
420 {
421  public:
422  HashSocketList();
423  void Init(void) const;
424  PSOCKET findsocket(TcpCarrierPacket &pkt) const;
425  void AddSocket(PSOCKET ps) const;
426  void RemoveSocket(PSOCKET ps) const;
427 };
428 
429 /*
430 The system accumulates a lot of sockets in TIME_WAIT and FIN_WAIT_2 states.
431 This list keeps them without using up the Socket list resources
432 This short list only gets sockets that have nothing left to Ack. */
433 
434 #define SocketHashSize 37
435 
436 struct ShortSocket;
437 class ShortSocketList
438 {
439  uint16_t m_slist[SocketHashSize];
440  ShortSocket *findsocket(TcpCarrierPacket &pkt) const;
441  ShortSocket *GetFreeShort();
442  void FreeShort(ShortSocket *pShort) const;
443 
444  public:
445  ShortSocketList();
446  void Init(void);
447  void AddSocket(PSOCKET ps);
448  int process(TcpCarrierPacket &pkt) const; /* Returns true if the socket was handled */
449  void processTimeEvent();
450 };
451 
452 extern OS_CRIT TCP_critical_section FAST_TCP_VAR;
453 extern OS_SEM TCP_TimerSemaphore FAST_TCP_VAR;
454 
455 extern PSOCKET free_list_head;
456 extern PSOCKET user_closed_list_head;
457 extern PSOCKET listen_list_head;
458 
459 extern HashSocketList active_list;
460 extern ShortSocketList semiactive_list;
461 
462 int GetInterfaceNumberFromMyAddr(IPADDR ip);
463 
464 #ifdef IPV6
465 struct IPv6FrameProcessingStruct; // Forward
466 bool process_tcp6(IPv6FrameProcessingStruct &p6proc);
467 void TcpSendwSum6(PSOCKET ps, const IPADDR &IPto, TcpCarrierPacket &pkt, BOOL keep, uint32_t data_sum);
468 void RetransmitV6Packet(PoolPtr pp, PSOCKET ps);
469 #endif
470 
471 #endif // __TCP_INTERNAL_H
void init()
System initialization. Normally called at the beginning of all applications.
Definition: init.cpp:22
Used to hold and manipulate IPv4 and IPv6 addresses in dual stack mode.
Definition: ipv6_addr.h:28
Semaphores are used to control access to shared resource critical section, or to communicate between ...
Definition: nbrtos.h:318
#define TCP_STATE_CLOSED
Socket Closed.
Definition: tcp.h:25
NetBurner File Descriptor Library API.
An OS_CRIT object is used to establish critical sections of code that can only be run by one task at ...
Definition: nbrtos.h:893
#define NULL
Definition: nm_bsp.h:76
NetBurner TCP API.