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