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 HeaderLengthtcp_header64 uint32 HeaderLength() const { return (uint32)header_length << 2; } Sequencetcp_header65 uint32 Sequence() const { return B_BENDIAN_TO_HOST_INT32(sequence); } Acknowledgetcp_header66 uint32 Acknowledge() const { return B_BENDIAN_TO_HOST_INT32(acknowledge); } AdvertisedWindowtcp_header67 uint16 AdvertisedWindow() const { return B_BENDIAN_TO_HOST_INT16(advertised_window); } Checksumtcp_header68 uint16 Checksum() const { return B_BENDIAN_TO_HOST_INT16(checksum); } UrgentOffsettcp_header69 uint16 UrgentOffset() const { return B_BENDIAN_TO_HOST_INT16(urgent_offset); } 70 } _PACKED; 71 72 class tcp_sequence { 73 public: tcp_sequence()74 inline tcp_sequence() {} tcp_sequence(uint32 sequence)75 inline tcp_sequence(uint32 sequence) 76 : fNumber(sequence) 77 { 78 } 79 Number()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 { tcp_segment_headertcp_segment_header238 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 AcknowledgeOnlytcp_segment_header264 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 AdvertisedWindowtcp_segment_header270 uint32 AdvertisedWindow(uint8 windowShift) const 271 { 272 return (uint32)advertised_window << windowShift; 273 } SetAdvertisedWindowtcp_segment_header274 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