xref: /haiku/src/add-ons/kernel/network/protocols/tcp/tcp.h (revision 35f57d15ffc68ce74fbb4408c939173f080ee4cc)
1 /*
2  * Copyright 2006, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Andrew Galante, haiku.galante@gmail.com
7  */
8 #ifndef TCP_H
9 #define TCP_H
10 
11 
12 #include <net_buffer.h>
13 #include <net_datalink.h>
14 #include <net_socket.h>
15 #include <net_stack.h>
16 
17 #include <util/khash.h>
18 
19 #include <ByteOrder.h>
20 
21 #include <sys/socket.h>
22 
23 
24 class EndpointManager;
25 
26 typedef enum {
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,
36 	WAIT_FOR_FINISH_ACKNOWLEDGE,
37 
38 	// we close the connection
39 	FINISH_SENT,
40 	FINISH_ACKNOWLEDGED,
41 	CLOSING,
42 	TIME_WAIT
43 } tcp_state;
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 ntohl(sequence); }
66 	uint32 Acknowledge() const { return ntohl(acknowledge); }
67 	uint16 AdvertisedWindow() const { return ntohs(advertised_window); }
68 	uint16 Checksum() const { return ntohs(checksum); }
69 	uint16 UrgentOffset() const { return ntohs(urgent_offset); }
70 } _PACKED;
71 
72 class tcp_sequence {
73 	public:
74 		tcp_sequence() {}
75 		tcp_sequence(uint32 sequence) : number(sequence) {}
76 
77 		operator uint32() const { return number; }
78 
79 		void operator=(uint32 sequence) { number = sequence; }
80 		bool operator>(uint32 sequence) const { return (int32)(number - sequence) > 0; }
81 		bool operator>=(uint32 sequence) const { return (int32)(number - sequence) >= 0; }
82 		bool operator<(uint32 sequence) const { return (int32)(number - sequence) < 0; }
83 		bool operator<=(uint32 sequence) const { return (int32)(number - sequence) <= 0; }
84 
85 		uint32& operator+=(uint32 sequence) { return number += sequence; }
86 		uint32& operator++() { return ++number; }
87 		uint32 operator++(int _) { return number++; }
88 
89 	private:
90 		uint32 number;
91 };
92 
93 // TCP flag constants
94 #define TCP_FLAG_FINISH					0x01
95 #define TCP_FLAG_SYNCHRONIZE			0x02
96 #define TCP_FLAG_RESET					0x04
97 #define TCP_FLAG_PUSH					0x08
98 #define TCP_FLAG_ACKNOWLEDGE			0x10
99 #define TCP_FLAG_URGENT					0x20
100 #define TCP_FLAG_CONGESTION_NOTIFICATION_ECHO	0x40
101 #define TCP_FLAG_CONGESTION_WINDOW_REDUCED		0x80
102 
103 #define TCP_CONNECTION_TIMEOUT			75000000	// 75 secs
104 #define TCP_DELAYED_ACKNOWLEDGE_TIMEOUT	100000		// 100 msecs
105 #define TCP_DEFAULT_MAX_SEGMENT_SIZE	536
106 #define TCP_MAX_WINDOW					65535
107 #define TCP_MAX_SEGMENT_LIFETIME		60000000	// 60 secs
108 
109 struct tcp_sack {
110 	uint32 left_edge;
111 	uint32 right_edge;
112 } _PACKED;
113 
114 struct tcp_option {
115 	uint8	kind;
116 	uint8	length;
117 	union {
118 		uint8	window_shift;
119 		uint16	max_segment_size;
120 		struct {
121 			uint32 timestamp_value;
122 			uint32 timestamp_reply;
123 		} timestamp;
124 		tcp_sack sack[0];
125 	};
126 } _PACKED;
127 
128 enum tcp_option_kind {
129 	TCP_OPTION_END				= 0,
130 	TCP_OPTION_NOP				= 1,
131 	TCP_OPTION_MAX_SEGMENT_SIZE	= 2,
132 	TCP_OPTION_WINDOW_SHIFT		= 3,
133 	TCP_OPTION_SACK_PERMITTED	= 4,
134 	TCP_OPTION_SACK				= 5,
135 	TCP_OPTION_TIMESTAMP		= 8,
136 };
137 
138 #define TCP_MAX_WINDOW_SHIFT	14
139 
140 enum {
141 	TCP_HAS_WINDOW_SCALE	= 1 << 0,
142 	TCP_HAS_TIMESTAMPS		= 1 << 1,
143 	TCP_SACK_PERMITTED		= 1 << 2,
144 };
145 
146 struct tcp_segment_header {
147 	tcp_segment_header(uint8 _flags)
148 		:
149 		flags(_flags),
150 		window_shift(0),
151 		max_segment_size(0),
152 		sack_count(0),
153 		options(0)
154 	{}
155 
156 	uint32	sequence;
157 	uint32	acknowledge;
158 	uint16	advertised_window;
159 	uint16	urgent_offset;
160 	uint8	flags;
161 	uint8	window_shift;
162 	uint16	max_segment_size;
163 
164 	uint32	timestamp_value;
165 	uint32	timestamp_reply;
166 
167 	tcp_sack	*sacks;
168 	int			sack_count;
169 
170 	uint32	options;
171 
172 	bool AcknowledgeOnly() const
173 	{
174 		return (flags & (TCP_FLAG_SYNCHRONIZE | TCP_FLAG_FINISH | TCP_FLAG_RESET
175 			| TCP_FLAG_URGENT | TCP_FLAG_ACKNOWLEDGE)) == TCP_FLAG_ACKNOWLEDGE;
176 	}
177 };
178 
179 enum tcp_segment_action {
180 	KEEP		= 0x00,
181 	DROP		= 0x01,
182 	RESET		= 0x02,
183 	ACKNOWLEDGE	= 0x04,
184 	IMMEDIATE_ACKNOWLEDGE = 0x08,
185 };
186 
187 
188 extern net_buffer_module_info *gBufferModule;
189 extern net_datalink_module_info *gDatalinkModule;
190 extern net_socket_module_info *gSocketModule;
191 extern net_stack_module_info *gStackModule;
192 
193 
194 status_t add_tcp_header(net_address_module_info *addressModule,
195 	tcp_segment_header &segment, net_buffer *buffer);
196 size_t tcp_options_length(tcp_segment_header &segment);
197 
198 const char *name_for_state(tcp_state state);
199 
200 EndpointManager *create_endpoint_manager(net_domain *domain);
201 void return_endpoint_manager(EndpointManager *);
202 
203 #endif	// TCP_H
204