xref: /haiku/src/add-ons/kernel/network/protocols/tcp/tcp.h (revision 084e24d0bf3808808e2bf58d4d65f493bd2b8f49)
1 /*
2  * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Axel Dörfler, axeld@pinc-software.de
7  *		Andrew Galante, haiku.galante@gmail.com
8  *		Hugo Santos, hugosantos@gmail.com
9  */
10 #ifndef TCP_H
11 #define TCP_H
12 
13 
14 #include <net_buffer.h>
15 #include <net_datalink.h>
16 #include <net_socket.h>
17 #include <net_stack.h>
18 
19 #include <ByteOrder.h>
20 
21 #include <sys/socket.h>
22 
23 
24 class EndpointManager;
25 
26 enum tcp_state {
27 	// establishing a connection
28 	CLOSED,
29 	LISTEN,
30 	SYNCHRONIZE_SENT,
31 	SYNCHRONIZE_RECEIVED,
32 	ESTABLISHED,
33 
34 	// peer closes the connection
35 	FINISH_RECEIVED,				// close-wait
36 	WAIT_FOR_FINISH_ACKNOWLEDGE,	// last-ack
37 
38 	// we close the connection
39 	FINISH_SENT,					// fin-wait-1
40 	FINISH_ACKNOWLEDGED,			// fin-wait-2
41 	CLOSING,
42 	TIME_WAIT
43 };
44 
45 struct tcp_header {
46 	uint16	source_port;
47 	uint16	destination_port;
48 	uint32	sequence;
49 	uint32	acknowledge;
50 	struct {
51 #if B_HOST_IS_LENDIAN == 1
52 		uint8	reserved : 4;
53 		uint8	header_length : 4;
54 #else
55 		uint8	header_length : 4;
56 		uint8	reserved : 4;
57 #endif
58 	};
59 	uint8	flags;
60 	uint16	advertised_window;
61 	uint16	checksum;
62 	uint16	urgent_offset;
63 
64 	uint32	HeaderLength() const { return (uint32)header_length << 2; }
65 	uint32	Sequence() const { return B_BENDIAN_TO_HOST_INT32(sequence); }
66 	uint32	Acknowledge() const { return B_BENDIAN_TO_HOST_INT32(acknowledge); }
67 	uint16	AdvertisedWindow() const { return B_BENDIAN_TO_HOST_INT16(advertised_window); }
68 	uint16	Checksum() const { return B_BENDIAN_TO_HOST_INT16(checksum); }
69 	uint16	UrgentOffset() const { return B_BENDIAN_TO_HOST_INT16(urgent_offset); }
70 } _PACKED;
71 
72 class tcp_sequence {
73 public:
74 	inline tcp_sequence() {}
75 	inline tcp_sequence(uint32 sequence)
76 		: fNumber(sequence)
77 	{
78 	}
79 
80 	inline uint32 Number() const
81 	{
82 		return fNumber;
83 	}
84 
85 	inline tcp_sequence& operator=(tcp_sequence sequence)
86 	{
87 		fNumber = sequence.fNumber;
88 		return *this;
89 	}
90 
91 	inline tcp_sequence& operator+=(tcp_sequence sequence)
92 	{
93 		fNumber += sequence.fNumber;
94 		return *this;
95 	}
96 
97 	inline tcp_sequence& operator++()
98 	{
99 		fNumber++;
100 		return *this;
101 	}
102 
103 	inline tcp_sequence operator++(int _)
104 	{
105 		fNumber++;
106 		return fNumber - 1;
107 	}
108 
109 private:
110 	uint32	fNumber;
111 };
112 
113 
114 // Global tcp_sequence Operators
115 
116 
117 inline bool
118 operator>(tcp_sequence a, tcp_sequence b)
119 {
120 	return (int32)(a.Number() - b.Number()) > 0;
121 }
122 
123 
124 inline bool
125 operator>=(tcp_sequence a, tcp_sequence b)
126 {
127 	return (int32)(a.Number() - b.Number()) >= 0;
128 }
129 
130 
131 inline bool
132 operator<(tcp_sequence a, tcp_sequence b)
133 {
134 	return (int32)(a.Number() - b.Number()) < 0;
135 }
136 
137 
138 inline bool
139 operator<=(tcp_sequence a, tcp_sequence b)
140 {
141 	return (int32)(a.Number() - b.Number()) <= 0;
142 }
143 
144 
145 inline tcp_sequence
146 operator+(tcp_sequence a, tcp_sequence b)
147 {
148 	return a.Number() + b.Number();
149 }
150 
151 
152 inline tcp_sequence
153 operator-(tcp_sequence a, tcp_sequence b)
154 {
155 	return a.Number() - b.Number();
156 }
157 
158 
159 inline bool
160 operator!=(tcp_sequence a, tcp_sequence b)
161 {
162 	return a.Number() != b.Number();
163 }
164 
165 
166 inline bool
167 operator==(tcp_sequence a, tcp_sequence b)
168 {
169 	return a.Number() == b.Number();
170 }
171 
172 
173 // TCP flag constants
174 #define TCP_FLAG_FINISH					0x01
175 #define TCP_FLAG_SYNCHRONIZE			0x02
176 #define TCP_FLAG_RESET					0x04
177 #define TCP_FLAG_PUSH					0x08
178 #define TCP_FLAG_ACKNOWLEDGE			0x10
179 #define TCP_FLAG_URGENT					0x20
180 #define TCP_FLAG_CONGESTION_NOTIFICATION_ECHO	0x40
181 #define TCP_FLAG_CONGESTION_WINDOW_REDUCED		0x80
182 
183 #define TCP_CONNECTION_TIMEOUT			75000000	// 75 secs
184 #define TCP_DELAYED_ACKNOWLEDGE_TIMEOUT	100000		// 100 msecs
185 #define TCP_DEFAULT_MAX_SEGMENT_SIZE	536
186 #define TCP_MAX_WINDOW					65535
187 #define TCP_MAX_SEGMENT_LIFETIME		60000000	// 60 secs
188 #define TCP_PERSIST_TIMEOUT				1000000		// 1 sec
189 
190 // Initial estimate for packet round trip time (RTT)
191 #define TCP_INITIAL_RTT					2000000		// 2 secs
192 // Minimum retransmit timeout (consider delayed ack)
193 #define TCP_MIN_RETRANSMIT_TIMEOUT		200000		// 200 msecs
194 // Maximum retransmit timeout (per RFC6298)
195 #define TCP_MAX_RETRANSMIT_TIMEOUT		60000000	// 60 secs
196 // New value for timeout in case of lost SYN (RFC 6298)
197 #define TCP_SYN_RETRANSMIT_TIMEOUT 		3000000		// 3 secs
198 
199 struct tcp_sack {
200 	uint32 left_edge;
201 	uint32 right_edge;
202 } _PACKED;
203 
204 struct tcp_option {
205 	uint8	kind;
206 	uint8	length;
207 	union {
208 		uint8		window_shift;
209 		uint16		max_segment_size;
210 		struct {
211 			uint32	value;
212 			uint32	reply;
213 		}			timestamp;
214 		tcp_sack	sack[0];
215 	};
216 } _PACKED;
217 
218 enum tcp_option_kind {
219 	TCP_OPTION_END				= 0,
220 	TCP_OPTION_NOP				= 1,
221 	TCP_OPTION_MAX_SEGMENT_SIZE	= 2,
222 	TCP_OPTION_WINDOW_SHIFT		= 3,
223 	TCP_OPTION_SACK_PERMITTED	= 4,
224 	TCP_OPTION_SACK				= 5,
225 	TCP_OPTION_TIMESTAMP		= 8,
226 };
227 
228 #define TCP_MAX_WINDOW_SHIFT	14
229 
230 enum {
231 	TCP_HAS_WINDOW_SCALE	= 1 << 0,
232 	TCP_HAS_TIMESTAMPS		= 1 << 1,
233 	TCP_SACK_PERMITTED		= 1 << 2,
234 	TCP_HAS_SACK			= 1 << 3,
235 };
236 
237 struct tcp_segment_header {
238 	tcp_segment_header(uint8 _flags)
239 		:
240 		flags(_flags),
241 		window_shift(0),
242 		max_segment_size(0),
243 		sackCount(0),
244 		options(0)
245 	{}
246 
247 	uint32	sequence;
248 	uint32	acknowledge;
249 	uint16	advertised_window;
250 	uint16	urgent_offset;
251 	uint8	flags;
252 	uint8	window_shift;
253 	uint16	max_segment_size;
254 
255 	uint32	timestamp_value;
256 	uint32	timestamp_reply;
257 
258 #define MAX_SACK_BLKS 4
259 	tcp_sack	sacks[MAX_SACK_BLKS];
260 	int			sackCount;
261 
262 	uint32	options;
263 
264 	bool AcknowledgeOnly() const
265 	{
266 		return (flags & (TCP_FLAG_SYNCHRONIZE | TCP_FLAG_FINISH | TCP_FLAG_RESET
267 			| TCP_FLAG_URGENT | TCP_FLAG_ACKNOWLEDGE)) == TCP_FLAG_ACKNOWLEDGE;
268 	}
269 
270 	uint32 AdvertisedWindow(uint8 windowShift) const
271 	{
272 		return (uint32)advertised_window << windowShift;
273 	}
274 	void SetAdvertisedWindow(size_t availableBytes, uint8 windowShift)
275 	{
276 		availableBytes >>= windowShift;
277 		advertised_window = min_c(TCP_MAX_WINDOW, availableBytes);
278 	}
279 };
280 
281 enum tcp_segment_action {
282 	KEEP					= 0,
283 	DROP					= (1 << 0),
284 	RESET					= (1 << 1),
285 	ACKNOWLEDGE				= (1 << 2),
286 	IMMEDIATE_ACKNOWLEDGE	= (1 << 3),
287 	SEND_QUEUED				= (1 << 4),
288 	DELETED_ENDPOINT		= (1 << 5),
289 };
290 
291 
292 extern net_buffer_module_info* gBufferModule;
293 extern net_datalink_module_info* gDatalinkModule;
294 extern net_socket_module_info* gSocketModule;
295 extern net_stack_module_info* gStackModule;
296 
297 
298 EndpointManager* get_endpoint_manager(net_domain* domain);
299 void put_endpoint_manager(EndpointManager* manager);
300 
301 status_t add_tcp_header(net_address_module_info* addressModule,
302 	tcp_segment_header& segment, net_buffer* buffer);
303 size_t tcp_options_length(tcp_segment_header& segment);
304 
305 const char* name_for_state(tcp_state state);
306 
307 #endif	// TCP_H
308