xref: /haiku/src/add-ons/kernel/network/protocols/tcp/tcp.h (revision e221c09e508ffc3c62738140c9b6fc4fa211662a)
1 /*
2  * Copyright 2006-2008, 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,
38 	WAIT_FOR_FINISH_ACKNOWLEDGE,
39 
40 	// we close the connection
41 	FINISH_SENT,
42 	FINISH_ACKNOWLEDGED,
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 					tcp_sequence() {}
77 					tcp_sequence(uint32 sequence) : fNumber(sequence) {}
78 
79 					operator uint32() const { return fNumber; }
80 
81 			void	operator=(uint32 sequence) { fNumber = sequence; }
82 			bool	operator>(uint32 sequence) const
83 						{ return (int32)(fNumber - sequence) > 0; }
84 			bool	operator>=(uint32 sequence) const
85 						{ return (int32)(fNumber - sequence) >= 0; }
86 			bool	operator<(uint32 sequence) const
87 						{ return (int32)(fNumber - sequence) < 0; }
88 			bool	operator<=(uint32 sequence) const
89 						{ return (int32)(fNumber - sequence) <= 0; }
90 
91 			uint32&	operator+=(uint32 sequence) { return fNumber += sequence; }
92 			uint32&	operator++() { return ++fNumber; }
93 			uint32	operator++(int _) { return fNumber++; }
94 
95 private:
96 	uint32	fNumber;
97 };
98 
99 // TCP flag constants
100 #define TCP_FLAG_FINISH					0x01
101 #define TCP_FLAG_SYNCHRONIZE			0x02
102 #define TCP_FLAG_RESET					0x04
103 #define TCP_FLAG_PUSH					0x08
104 #define TCP_FLAG_ACKNOWLEDGE			0x10
105 #define TCP_FLAG_URGENT					0x20
106 #define TCP_FLAG_CONGESTION_NOTIFICATION_ECHO	0x40
107 #define TCP_FLAG_CONGESTION_WINDOW_REDUCED		0x80
108 
109 #define TCP_CONNECTION_TIMEOUT			75000000	// 75 secs
110 #define TCP_DELAYED_ACKNOWLEDGE_TIMEOUT	100000		// 100 msecs
111 #define TCP_DEFAULT_MAX_SEGMENT_SIZE	536
112 #define TCP_MAX_WINDOW					65535
113 #define TCP_MAX_SEGMENT_LIFETIME		60000000	// 60 secs
114 
115 struct tcp_sack {
116 	uint32 left_edge;
117 	uint32 right_edge;
118 } _PACKED;
119 
120 struct tcp_option {
121 	uint8	kind;
122 	uint8	length;
123 	union {
124 		uint8		window_shift;
125 		uint16		max_segment_size;
126 		struct {
127 			uint32	value;
128 			uint32	reply;
129 		}			timestamp;
130 		tcp_sack	sack[0];
131 	};
132 } _PACKED;
133 
134 enum tcp_option_kind {
135 	TCP_OPTION_END				= 0,
136 	TCP_OPTION_NOP				= 1,
137 	TCP_OPTION_MAX_SEGMENT_SIZE	= 2,
138 	TCP_OPTION_WINDOW_SHIFT		= 3,
139 	TCP_OPTION_SACK_PERMITTED	= 4,
140 	TCP_OPTION_SACK				= 5,
141 	TCP_OPTION_TIMESTAMP		= 8,
142 };
143 
144 #define TCP_MAX_WINDOW_SHIFT	14
145 
146 enum {
147 	TCP_HAS_WINDOW_SCALE	= 1 << 0,
148 	TCP_HAS_TIMESTAMPS		= 1 << 1,
149 	TCP_SACK_PERMITTED		= 1 << 2,
150 };
151 
152 struct tcp_segment_header {
153 	tcp_segment_header(uint8 _flags)
154 		:
155 		flags(_flags),
156 		window_shift(0),
157 		max_segment_size(0),
158 		sack_count(0),
159 		options(0)
160 	{}
161 
162 	uint32	sequence;
163 	uint32	acknowledge;
164 	uint16	advertised_window;
165 	uint16	urgent_offset;
166 	uint8	flags;
167 	uint8	window_shift;
168 	uint16	max_segment_size;
169 
170 	uint32	timestamp_value;
171 	uint32	timestamp_reply;
172 
173 	tcp_sack	*sacks;
174 	int			sack_count;
175 
176 	uint32	options;
177 
178 	bool AcknowledgeOnly() const
179 	{
180 		return (flags & (TCP_FLAG_SYNCHRONIZE | TCP_FLAG_FINISH | TCP_FLAG_RESET
181 			| TCP_FLAG_URGENT | TCP_FLAG_ACKNOWLEDGE)) == TCP_FLAG_ACKNOWLEDGE;
182 	}
183 };
184 
185 enum tcp_segment_action {
186 	KEEP			= 0x00,
187 	DROP			= 0x01,
188 	RESET			= 0x02,
189 	ACKNOWLEDGE		= 0x04,
190 	IMMEDIATE_ACKNOWLEDGE = 0x08,
191 	DELETE_ENDPOINT	= 0x10,
192 };
193 
194 
195 extern net_buffer_module_info* gBufferModule;
196 extern net_datalink_module_info* gDatalinkModule;
197 extern net_socket_module_info* gSocketModule;
198 extern net_stack_module_info* gStackModule;
199 
200 
201 EndpointManager* get_endpoint_manager(net_domain* domain);
202 void put_endpoint_manager(EndpointManager* manager);
203 
204 status_t add_tcp_header(net_address_module_info* addressModule,
205 	tcp_segment_header& segment, net_buffer* buffer);
206 size_t tcp_options_length(tcp_segment_header& segment);
207 
208 const char* name_for_state(tcp_state state);
209 
210 #endif	// TCP_H
211