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