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 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 // Conceptually private, but used in global operators. 112 //private: 113 uint32 fNumber; 114 }; 115 116 117 // Global tcp_sequence Operators 118 119 120 inline bool 121 operator>(tcp_sequence a, tcp_sequence b) 122 { 123 return (int32)(a.fNumber - b.fNumber) > 0; 124 } 125 126 127 inline bool 128 operator>=(tcp_sequence a, tcp_sequence b) 129 { 130 return (int32)(a.fNumber - b.fNumber) >= 0; 131 } 132 133 134 inline bool 135 operator<(tcp_sequence a, tcp_sequence b) 136 { 137 return (int32)(a.fNumber - b.fNumber) < 0; 138 } 139 140 141 inline bool 142 operator<=(tcp_sequence a, tcp_sequence b) 143 { 144 return (int32)(a.fNumber - b.fNumber) <= 0; 145 } 146 147 148 inline tcp_sequence 149 operator+(tcp_sequence a, tcp_sequence b) 150 { 151 return a.fNumber + b.fNumber; 152 } 153 154 155 inline tcp_sequence 156 operator-(tcp_sequence a, tcp_sequence b) 157 { 158 return a.fNumber - b.fNumber; 159 } 160 161 162 inline bool 163 operator!=(tcp_sequence a, tcp_sequence b) 164 { 165 return a.fNumber != b.fNumber; 166 } 167 168 169 inline bool 170 operator==(tcp_sequence a, tcp_sequence b) 171 { 172 return a.fNumber == b.fNumber; 173 } 174 175 176 // TCP flag constants 177 #define TCP_FLAG_FINISH 0x01 178 #define TCP_FLAG_SYNCHRONIZE 0x02 179 #define TCP_FLAG_RESET 0x04 180 #define TCP_FLAG_PUSH 0x08 181 #define TCP_FLAG_ACKNOWLEDGE 0x10 182 #define TCP_FLAG_URGENT 0x20 183 #define TCP_FLAG_CONGESTION_NOTIFICATION_ECHO 0x40 184 #define TCP_FLAG_CONGESTION_WINDOW_REDUCED 0x80 185 186 #define TCP_CONNECTION_TIMEOUT 75000000 // 75 secs 187 #define TCP_DELAYED_ACKNOWLEDGE_TIMEOUT 100000 // 100 msecs 188 #define TCP_DEFAULT_MAX_SEGMENT_SIZE 536 189 #define TCP_MAX_WINDOW 65535 190 #define TCP_MAX_SEGMENT_LIFETIME 60000000 // 60 secs 191 192 struct tcp_sack { 193 uint32 left_edge; 194 uint32 right_edge; 195 } _PACKED; 196 197 struct tcp_option { 198 uint8 kind; 199 uint8 length; 200 union { 201 uint8 window_shift; 202 uint16 max_segment_size; 203 struct { 204 uint32 value; 205 uint32 reply; 206 } timestamp; 207 tcp_sack sack[0]; 208 }; 209 } _PACKED; 210 211 enum tcp_option_kind { 212 TCP_OPTION_END = 0, 213 TCP_OPTION_NOP = 1, 214 TCP_OPTION_MAX_SEGMENT_SIZE = 2, 215 TCP_OPTION_WINDOW_SHIFT = 3, 216 TCP_OPTION_SACK_PERMITTED = 4, 217 TCP_OPTION_SACK = 5, 218 TCP_OPTION_TIMESTAMP = 8, 219 }; 220 221 #define TCP_MAX_WINDOW_SHIFT 14 222 223 enum { 224 TCP_HAS_WINDOW_SCALE = 1 << 0, 225 TCP_HAS_TIMESTAMPS = 1 << 1, 226 TCP_SACK_PERMITTED = 1 << 2, 227 }; 228 229 struct tcp_segment_header { 230 tcp_segment_header(uint8 _flags) 231 : 232 flags(_flags), 233 window_shift(0), 234 max_segment_size(0), 235 sack_count(0), 236 options(0) 237 {} 238 239 uint32 sequence; 240 uint32 acknowledge; 241 uint16 advertised_window; 242 uint16 urgent_offset; 243 uint8 flags; 244 uint8 window_shift; 245 uint16 max_segment_size; 246 247 uint32 timestamp_value; 248 uint32 timestamp_reply; 249 250 tcp_sack *sacks; 251 int sack_count; 252 253 uint32 options; 254 255 bool AcknowledgeOnly() const 256 { 257 return (flags & (TCP_FLAG_SYNCHRONIZE | TCP_FLAG_FINISH | TCP_FLAG_RESET 258 | TCP_FLAG_URGENT | TCP_FLAG_ACKNOWLEDGE)) == TCP_FLAG_ACKNOWLEDGE; 259 } 260 }; 261 262 enum tcp_segment_action { 263 KEEP = 0x00, 264 DROP = 0x01, 265 RESET = 0x02, 266 ACKNOWLEDGE = 0x04, 267 IMMEDIATE_ACKNOWLEDGE = 0x08, 268 DELETE_ENDPOINT = 0x10, 269 }; 270 271 272 extern net_buffer_module_info* gBufferModule; 273 extern net_datalink_module_info* gDatalinkModule; 274 extern net_socket_module_info* gSocketModule; 275 extern net_stack_module_info* gStackModule; 276 277 278 EndpointManager* get_endpoint_manager(net_domain* domain); 279 void put_endpoint_manager(EndpointManager* manager); 280 281 status_t add_tcp_header(net_address_module_info* addressModule, 282 tcp_segment_header& segment, net_buffer* buffer); 283 size_t tcp_options_length(tcp_segment_header& segment); 284 285 const char* name_for_state(tcp_state state); 286 287 #endif // TCP_H 288