Blame view

lufa-master/Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.h 11.6 KB
142ecdaf   rguillom   first commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  /*
               LUFA Library
       Copyright (C) Dean Camera, 2019.
  
    dean [at] fourwalledcubicle [dot] com
             www.lufa-lib.org
  */
  
  /*
    Copyright 2019  Dean Camera (dean [at] fourwalledcubicle [dot] com)
  
    Permission to use, copy, modify, distribute, and sell this
    software and its documentation for any purpose is hereby granted
    without fee, provided that the above copyright notice appear in
    all copies and that both that the copyright notice and this
    permission notice and warranty disclaimer appear in supporting
    documentation, and that the name of the author not be used in
    advertising or publicity pertaining to distribution of the
    software without specific, written prior permission.
  
    The author disclaims all warranties with regard to this
    software, including all implied warranties of merchantability
    and fitness.  In no event shall the author be liable for any
    special, indirect or consequential damages or any damages
    whatsoever resulting from loss of use, data or profits, whether
    in an action of contract, negligence or other tortious action,
    arising out of or in connection with the use or performance of
    this software.
  */
  
  /** \file
   *
   *  Header file for TCP.c.
   */
  
  #ifndef _TCP_H_
  #define _TCP_H_
  
  	/* Includes: */
  		#include <avr/io.h>
  		#include <stdbool.h>
  
  		#include "EthernetProtocols.h"
  		#include "Ethernet.h"
  		#include "ProtocolDecoders.h"
  
  	/* Macros: */
  		/** Maximum number of TCP ports which can be open at the one time. */
  		#define MAX_OPEN_TCP_PORTS              1
  
  		/** Maximum number of TCP connections which can be sustained at the one time. */
  		#define MAX_TCP_CONNECTIONS             3
  
  		/** TCP window size, giving the maximum number of bytes which can be buffered at the one time. */
  		#define TCP_WINDOW_SIZE                 512
  
  		/** Port number for HTTP transmissions. */
  		#define TCP_PORT_HTTP                   SwapEndian_16(80)
  
  		/** Data direction indicator for a TCP application buffer, indicating data from host-to-device. */
  		#define TCP_PACKETDIR_IN                false
  
  		/** Data direction indicator for a TCP application buffer, indicating data from device-to-host. */
  		#define TCP_PACKETDIR_OUT               true
  
  		/** Congestion Window Reduced TCP flag mask. */
  		#define TCP_FLAG_CWR                    (1 << 7)
  
  		/** Explicit Congestion Notification TCP flag mask. */
  		#define TCP_FLAG_ECE                    (1 << 6)
  
  		/** Urgent TCP flag mask. */
  		#define TCP_FLAG_URG                    (1 << 5)
  
  		/** Data Acknowledge TCP flag mask. */
  		#define TCP_FLAG_ACK                    (1 << 4)
  
  		/** Data Push TCP flag mask. */
  		#define TCP_FLAG_PSH                    (1 << 3)
  
  		/** Reset TCP flag mask. */
  		#define TCP_FLAG_RST                    (1 << 2)
  
  		/** Synchronize TCP flag mask. */
  		#define TCP_FLAG_SYN                    (1 << 1)
  
  		/** Connection Finalize TCP flag mask. */
  		#define TCP_FLAG_FIN                    (1 << 0)
  
  		/** Application macro: Determines if the given application buffer contains a packet received from the host
  		 *
  		 *  \param[in] Buffer  Application buffer to check
  		 *
  		 *  \return Boolean \c true if the buffer contains a packet from the host, \c false otherwise
  		 */
  		#define TCP_APP_HAS_RECEIVED_PACKET(Buffer)  (Buffer->Ready && (Buffer->Direction == TCP_PACKETDIR_IN))
  
  		/** Application macro: Indicates if the application buffer is currently locked by the application for device-to-host transfers.
  		 *
  		 *  \param[in] Buffer  Application buffer to check
  		 *
  		 *  \return Boolean \c true if the buffer has been captured by the application for device-to-host transmissions, \c false otherwise
  		 */
  		#define TCP_APP_HAVE_CAPTURED_BUFFER(Buffer) (!(Buffer->Ready) && Buffer->InUse && \
  		                                              (Buffer->Direction == TCP_PACKETDIR_OUT))
  
  		/** Application macro: Indicates if the application can lock the buffer for multiple continued device-to-host transmissions.
  		 *
  		 *  \param[in] Buffer  Application buffer to check
  		 *
  		 *  \return Boolean \c true if the buffer may be captured by the application for device-to-host transmissions, \c false otherwise
  		 */
  		#define TCP_APP_CAN_CAPTURE_BUFFER(Buffer)   Buffer->InUse
  
  		/** Application macro: Captures the application buffer, locking it for device-to-host transmissions only. This should be
  		 *  performed when the application needs to transmit several packets worth of data in succession with no interruptions from the host.
  		 *
  		 *  \pre The application must check that the buffer can be locked first using TCP_APP_CAN_CAPTURE_BUFFER().
  		 *
  		 *  \param[in] Buffer  Application buffer to lock
  		 */
  		#define TCP_APP_CAPTURE_BUFFER(Buffer)       do { Buffer->Direction = TCP_PACKETDIR_OUT; Buffer->InUse = true; } while (0)
  
  		/** Application macro: Releases a captured application buffer, allowing for host-to-device packets to be received.
  		 *
  		 *  \param[in] Buffer  Application buffer to release
  		 */
  		#define TCP_APP_RELEASE_BUFFER(Buffer)       do { Buffer->InUse = false; } while (0)
  
  		/** Application macro: Sends the contents of the given application buffer to the host.
  		 *
  		 *  \param[in] Buffer  Application buffer to send
  		 *  \param[in] Len     Length of data contained in the buffer
  		 */
  		#define TCP_APP_SEND_BUFFER(Buffer, Len)     do { Buffer->Direction = TCP_PACKETDIR_OUT; Buffer->Length = Len; Buffer->Ready = true; } while (0)
  
  		/** Application macro: Clears the application buffer, ready for a packet to be written to it.
  		 *
  		 *  \param[in] Buffer  Application buffer to clear
  		 */
  		#define TCP_APP_CLEAR_BUFFER(Buffer)         do { Buffer->Ready = false; Buffer->Length = 0; } while (0)
  
  		/** Application macro: Closes an open connection to a host.
  		 *
  		 *  \param[in] Connection  Open TCP connection to close
  		 */
  		#define TCP_APP_CLOSECONNECTION(Connection)  do { Connection->State = TCP_Connection_Closing;  } while (0)
  
  	/* Enums: */
  		/** Enum for possible TCP port states. */
  		enum TCP_PortStates_t
  		{
  			TCP_Port_Closed            = 0, /**< TCP port closed, no connections to a host may be made on this port. */
  			TCP_Port_Open              = 1, /**< TCP port open, connections to a host may be made on this port. */
  		};
  
  		/** Enum for possible TCP connection states. */
  		enum TCP_ConnectionStates_t
  		{
  			TCP_Connection_Listen      = 0, /**< Listening for a connection from a host */
  			TCP_Connection_SYNSent     = 1, /**< Unused */
  			TCP_Connection_SYNReceived = 2, /**< SYN received, waiting for ACK */
  			TCP_Connection_Established = 3, /**< Connection established in both directions */
  			TCP_Connection_FINWait1    = 4, /**< Closing, waiting for ACK */
  			TCP_Connection_FINWait2    = 5, /**< Closing, waiting for FIN ACK */
  			TCP_Connection_CloseWait   = 6, /**< Closing, waiting for ACK */
  			TCP_Connection_Closing     = 7, /**< Unused */
  			TCP_Connection_LastACK     = 8, /**< Unused */
  			TCP_Connection_TimeWait    = 9, /**< Unused */
  			TCP_Connection_Closed      = 10, /**< Connection closed in both directions */
  		};
  
  	/* Type Defines: */
  		/** Type define for a TCP connection buffer structure, including size, data and direction. */
  		typedef struct
  		{
  			uint16_t               Length; /**< Length of data in the TCP application buffer */
  			uint8_t                Data[TCP_WINDOW_SIZE]; /**< TCP application data buffer */
  			bool                   Direction; /**< Buffer transmission direction, either TCP_PACKETDIR_IN  or TCP_PACKETDIR_OUT */
  			bool                   Ready; /**< If data from host, indicates buffer ready to be read, otherwise indicates
  			                               *   buffer ready to be sent to the host
  			                               */
  			bool                   InUse; /**< Indicates if the buffer is locked to to the current direction, and cannot be changed */
  		} TCP_ConnectionBuffer_t;
  
  		/** Type define for a TCP connection information structure. */
  		typedef struct
  		{
  			uint32_t               SequenceNumberIn; /**< Current TCP sequence number for host-to-device */
  			uint32_t               SequenceNumberOut; /**< Current TCP sequence number for device-to-host */
  			TCP_ConnectionBuffer_t Buffer; /**< Connection application data buffer */
  		} TCP_ConnectionInfo_t;
  
  		/** Type define for a complete TCP connection state. */
  		typedef struct
  		{
  			uint16_t               Port; /**< Connection port number on the device */
  			uint16_t               RemotePort; /**< Connection port number on the host */
  			IP_Address_t           RemoteAddress; /**< Connection protocol IP address of the host */
  			TCP_ConnectionInfo_t   Info; /**< Connection information, including application buffer */
  			uint8_t                State; /**< Current connection state, a value from the \ref TCP_ConnectionStates_t enum */
  		} TCP_ConnectionState_t;
  
  		/** Type define for a TCP port state. */
  		typedef struct
  		{
  			uint16_t               Port; /**< TCP port number on the device */
  			uint8_t                State; /**< Current port state, a value from the \ref TCP_PortStates_t enum */
  			void                   (*ApplicationHandler) (TCP_ConnectionState_t* ConnectionState,
  			                                              TCP_ConnectionBuffer_t* Buffer); /**< Port application handler */
  		} TCP_PortState_t;
  
  		/** Type define for a TCP packet header. */
  		typedef struct
  		{
  			uint16_t               SourcePort; /**< Source port of the TCP packet */
  			uint16_t               DestinationPort; /**< Destination port of the TCP packet */
  
  			uint32_t               SequenceNumber; /**< Data sequence number of the packet */
  			uint32_t               AcknowledgmentNumber; /**< Data acknowledgment number of the packet */
  
  			unsigned               Reserved   : 4; /**< Reserved, must be all 0 */
  			unsigned               DataOffset : 4; /**< Offset of the data from the start of the header, in 4 byte chunks */
  			uint8_t                Flags; /**< TCP packet flags */
  			uint16_t               WindowSize; /**< Current data window size (bytes remaining in reception buffer) */
  
  			uint16_t               Checksum; /**< TCP checksum */
  			uint16_t               UrgentPointer; /**< Urgent data pointer */
  		} TCP_Header_t;
  
  	/* Function Prototypes: */
  		void                  TCP_Init(void);
  		void                  TCP_Task(void);
  		bool                  TCP_SetPortState(const uint16_t Port,
  		                                       const uint8_t State,
  		                                       void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*));
  		uint8_t               TCP_GetPortState(const uint16_t Port);
  		bool                  TCP_SetConnectionState(const uint16_t Port,
  		                                             const IP_Address_t* RemoteAddress,
  		                                             const uint16_t RemotePort,
  		                                             const uint8_t State);
  		uint8_t               TCP_GetConnectionState(const uint16_t Port,
  		                                             const IP_Address_t* RemoteAddress,
  		                                             const uint16_t RemotePort);
  		TCP_ConnectionInfo_t* TCP_GetConnectionInfo(const uint16_t Port,
  		                                            const IP_Address_t* RemoteAddress,
  		                                            const uint16_t RemotePort);
  		int16_t               TCP_ProcessTCPPacket(void* IPHeaderInStart,
  		                                           void* TCPHeaderInStart,
  		                                           void* TCPHeaderOutStart);
  
  		#if defined(INCLUDE_FROM_TCP_C)
  			static uint16_t TCP_Checksum16(void* TCPHeaderOutStart,
  			                               const IP_Address_t* SourceAddress,
  			                               const IP_Address_t* DestinationAddress,
  			                               uint16_t TCPOutSize);
  		#endif
  
  #endif