xref: /haiku/src/add-ons/kernel/network/protocols/tcp/tcp.h (revision 1294543de9ac0eff000eaea1b18368c36435d08e)
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 <util/khash.h>
20 
21 #include <ByteOrder.h>
22 
23 #include <sys/socket.h>
24 
25 
26 class EndpointManager;
27 
28 enum tcp_state {
29 	// establishing a connection
30 	CLOSED,
31 	LISTEN,
32 	SYNCHRONIZE_SENT,
33 	SYNCHRONIZE_RECEIVED,
34 	ESTABLISHED,
35 
36 	// peer closes the connection
37 	FINISH_RECEIVED,				// close-wait
38 	WAIT_FOR_FINISH_ACKNOWLEDGE,	// last-ack
39 
40 	// we close the connection
41 	FINISH_SENT,					// fin-wait-1
42 	FINISH_ACKNOWLEDGED,			// fin-wait-2
43 	CLOSING,
44 	TIME_WAIT
45 };
46 
47 struct tcp_header {
48 	uint16 source_port;
49 	uint16 destination_port;
50 	uint32 sequence;
51 	uint32 acknowledge;
52 	struct {
53 #if B_HOST_IS_LENDIAN == 1
54 		uint8 reserved : 4;
55 		uint8 header_length : 4;
56 #else
57 		uint8 header_length : 4;
58 		uint8 reserved : 4;
59 #endif
60 	};
61 	uint8  flags;
62 	uint16 advertised_window;
63 	uint16 checksum;
64 	uint16 urgent_offset;
65 
66 	uint32 HeaderLength() const { return (uint32)header_length << 2; }
67 	uint32 Sequence() const { return ntohl(sequence); }
68 	uint32 Acknowledge() const { return ntohl(acknowledge); }
69 	uint16 AdvertisedWindow() const { return ntohs(advertised_window); }
70 	uint16 Checksum() const { return ntohs(checksum); }
71 	uint16 UrgentOffset() const { return ntohs(urgent_offset); }
72 } _PACKED;
73 
74 class tcp_sequence {
75 public:
76 	inline tcp_sequence() {}
77 	inline tcp_sequence(uint32 sequence)
78 		: fNumber(sequence)
79 	{
80 	}
81 
82 	inline uint32 Number() const
83 	{
84 		return fNumber;
85 	}
86 
87 	inline tcp_sequence& operator=(tcp_sequence sequence)
88 	{
89 		fNumber = sequence.fNumber;
90 		return *this;
91 	}
92 
93 	inline tcp_sequence& operator+=(tcp_sequence sequence)
94 	{
95 		fNumber += sequence.fNumber;
96 		return *this;
97 	}
98 
99 	inline tcp_sequence& operator++()
100 	{
101 		fNumber++;
102 		return *this;
103 	}
104 
105 	inline tcp_sequence operator++(int _)
106 	{
107 		fNumber++;
108 		return fNumber - 1;
109 	}
110 
111 private:
112 	uint32	fNumber;
113 };
114 
115 
116 // Global tcp_sequence Operators
117 
118 
119 inline bool
120 operator>(tcp_sequence a, tcp_sequence b)
121 {
122 	return (int32)(a.Number() - b.Number()) > 0;
123 }
124 
125 
126 inline bool
127 operator>=(tcp_sequence a, tcp_sequence b)
128 {
129 	return (int32)(a.Number() - b.Number()) >= 0;
130 }
131 
132 
133 inline bool
134 operator<(tcp_sequence a, tcp_sequence b)
135 {
136 	return (int32)(a.Number() - b.Number()) < 0;
137 }
138 
139 
140 inline bool
141 operator<=(tcp_sequence a, tcp_sequence b)
142 {
143 	return (int32)(a.Number() - b.Number()) <= 0;
144 }
145 
146 
147 inline tcp_sequence
148 operator+(tcp_sequence a, tcp_sequence b)
149 {
150 	return a.Number() + b.Number();
151 }
152 
153 
154 inline tcp_sequence
155 operator-(tcp_sequence a, tcp_sequence b)
156 {
157 	return a.Number() - b.Number();
158 }
159 
160 
161 inline bool
162 operator!=(tcp_sequence a, tcp_sequence b)
163 {
164 	return a.Number() != b.Number();
165 }
166 
167 
168 inline bool
169 operator==(tcp_sequence a, tcp_sequence b)
170 {
171 	return a.Number() == b.Number();
172 }
173 
174 
175 // TCP flag constants
176 #define TCP_FLAG_FINISH					0x01
177 #define TCP_FLAG_SYNCHRONIZE			0x02
178 #define TCP_FLAG_RESET					0x04
179 #define TCP_FLAG_PUSH					0x08
180 #define TCP_FLAG_ACKNOWLEDGE			0x10
181 #define TCP_FLAG_URGENT					0x20
182 #define TCP_FLAG_CONGESTION_NOTIFICATION_ECHO	0x40
183 #define TCP_FLAG_CONGESTION_WINDOW_REDUCED		0x80
184 
185 #define TCP_CONNECTION_TIMEOUT			75000000	// 75 secs
186 #define TCP_DELAYED_ACKNOWLEDGE_TIMEOUT	100000		// 100 msecs
187 #define TCP_DEFAULT_MAX_SEGMENT_SIZE	536
188 #define TCP_MAX_WINDOW					65535
189 #define TCP_MAX_SEGMENT_LIFETIME		60000000	// 60 secs
190 
191 struct tcp_sack {
192 	uint32 left_edge;
193 	uint32 right_edge;
194 } _PACKED;
195 
196 struct tcp_option {
197 	uint8	kind;
198 	uint8	length;
199 	union {
200 		uint8		window_shift;
201 		uint16		max_segment_size;
202 		struct {
203 			uint32	value;
204 			uint32	reply;
205 		}			timestamp;
206 		tcp_sack	sack[0];
207 	};
208 } _PACKED;
209 
210 enum tcp_option_kind {
211 	TCP_OPTION_END				= 0,
212 	TCP_OPTION_NOP				= 1,
213 	TCP_OPTION_MAX_SEGMENT_SIZE	= 2,
214 	TCP_OPTION_WINDOW_SHIFT		= 3,
215 	TCP_OPTION_SACK_PERMITTED	= 4,
216 	TCP_OPTION_SACK				= 5,
217 	TCP_OPTION_TIMESTAMP		= 8,
218 };
219 
220 #define TCP_MAX_WINDOW_SHIFT	14
221 
222 enum {
223 	TCP_HAS_WINDOW_SCALE	= 1 << 0,
224 	TCP_HAS_TIMESTAMPS		= 1 << 1,
225 	TCP_SACK_PERMITTED		= 1 << 2,
226 };
227 
228 struct tcp_segment_header {
229 	tcp_segment_header(uint8 _flags)
230 		:
231 		flags(_flags),
232 		window_shift(0),
233 		max_segment_size(0),
234 		sack_count(0),
235 		options(0)
236 	{}
237 
238 	uint32	sequence;
239 	uint32	acknowledge;
240 	uint16	advertised_window;
241 	uint16	urgent_offset;
242 	uint8	flags;
243 	uint8	window_shift;
244 	uint16	max_segment_size;
245 
246 	uint32	timestamp_value;
247 	uint32	timestamp_reply;
248 
249 	tcp_sack	*sacks;
250 	int			sack_count;
251 
252 	uint32	options;
253 
254 	bool AcknowledgeOnly() const
255 	{
256 		return (flags & (TCP_FLAG_SYNCHRONIZE | TCP_FLAG_FINISH | TCP_FLAG_RESET
257 			| TCP_FLAG_URGENT | TCP_FLAG_ACKNOWLEDGE)) == TCP_FLAG_ACKNOWLEDGE;
258 	}
259 };
260 
261 enum tcp_segment_action {
262 	KEEP			= 0x00,
263 	DROP			= 0x01,
264 	RESET			= 0x02,
265 	ACKNOWLEDGE		= 0x04,
266 	IMMEDIATE_ACKNOWLEDGE = 0x08,
267 	DELETE_ENDPOINT	= 0x10,
268 };
269 
270 
271 extern net_buffer_module_info* gBufferModule;
272 extern net_datalink_module_info* gDatalinkModule;
273 extern net_socket_module_info* gSocketModule;
274 extern net_stack_module_info* gStackModule;
275 
276 
277 EndpointManager* get_endpoint_manager(net_domain* domain);
278 void put_endpoint_manager(EndpointManager* manager);
279 
280 status_t add_tcp_header(net_address_module_info* addressModule,
281 	tcp_segment_header& segment, net_buffer* buffer);
282 size_t tcp_options_length(tcp_segment_header& segment);
283 
284 const char* name_for_state(tcp_state state);
285 
286 #endif	// TCP_H
287