Rev 4708 | Rev 4750 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4708 | Rev 4742 | ||
---|---|---|---|
Line 29... | Line 29... | ||
29 | /** @addtogroup tcp |
29 | /** @addtogroup tcp |
30 | * @{ |
30 | * @{ |
31 | */ |
31 | */ |
32 | 32 | ||
33 | /** @file |
33 | /** @file |
- | 34 | * TCP module implementation. |
|
- | 35 | * @see tcp.h |
|
34 | * \todo |
36 | * \todo |
35 | */ |
37 | */ |
36 | 38 | ||
- | 39 | #include <assert.h> |
|
37 | #include <async.h> |
40 | #include <async.h> |
- | 41 | #include <fibril_sync.h> |
|
- | 42 | #include <malloc.h> |
|
- | 43 | //TODO remove stdio |
|
38 | #include <stdio.h> |
44 | #include <stdio.h> |
39 | 45 | ||
40 | #include <ipc/ipc.h> |
46 | #include <ipc/ipc.h> |
41 | #include <ipc/services.h> |
47 | #include <ipc/services.h> |
42 | 48 | ||
43 | #include "../../err.h" |
49 | #include "../../err.h" |
44 | #include "../../messages.h" |
50 | #include "../../messages.h" |
45 | #include "../../modules.h" |
51 | #include "../../modules.h" |
- | 52 | ||
- | 53 | #include "../../structures/dynamic_fifo.h" |
|
46 | #include "../../structures/packet/packet_client.h" |
54 | #include "../../structures/packet/packet_client.h" |
47 | 55 | ||
- | 56 | #include "../../include/checksum.h" |
|
- | 57 | #include "../../include/in.h" |
|
- | 58 | #include "../../include/in6.h" |
|
- | 59 | #include "../../include/inet.h" |
|
48 | #include "../../include/ip_client.h" |
60 | #include "../../include/ip_client.h" |
49 | #include "../../include/ip_interface.h" |
61 | #include "../../include/ip_interface.h" |
50 | #include "../../include/ip_protocols.h" |
62 | #include "../../include/ip_protocols.h" |
- | 63 | #include "../../include/icmp_client.h" |
|
51 | #include "../../include/icmp_interface.h" |
64 | #include "../../include/icmp_interface.h" |
- | 65 | #include "../../include/net_interface.h" |
|
- | 66 | #include "../../include/socket_codes.h" |
|
- | 67 | #include "../../include/socket_errno.h" |
|
- | 68 | #include "../../include/tcp_codes.h" |
|
52 | 69 | ||
53 | #include "../../socket/socket_core.h" |
70 | #include "../../socket/socket_core.h" |
- | 71 | #include "../../socket/socket_messages.h" |
|
54 | 72 | ||
- | 73 | #include "../tl_common.h" |
|
55 | #include "../tl_messages.h" |
74 | #include "../tl_messages.h" |
56 | 75 | ||
57 | #include "tcp.h" |
76 | #include "tcp.h" |
- | 77 | #include "tcp_header.h" |
|
58 | #include "tcp_module.h" |
78 | #include "tcp_module.h" |
59 | 79 | ||
- | 80 | /** The TCP window default value. |
|
- | 81 | */ |
|
- | 82 | #define NET_DEFAULT_TCP_WINDOW 10240 |
|
- | 83 | ||
- | 84 | /** \todo |
|
- | 85 | */ |
|
- | 86 | #define NET_DEFAULT_TCP_INITIAL_TIMEOUT 3000000L |
|
- | 87 | ||
- | 88 | /** \todo |
|
- | 89 | */ |
|
- | 90 | #define NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT 2000L |
|
- | 91 | ||
- | 92 | /** The initial outgoing sequence number. |
|
- | 93 | */ |
|
- | 94 | #define TCP_INITIAL_SEQUENCE_NUMBER 2999 |
|
- | 95 | ||
- | 96 | /** Maximum TCP fragment size. |
|
- | 97 | */ |
|
- | 98 | #define MAX_TCP_FRAGMENT_SIZE 65535 |
|
- | 99 | ||
60 | /** Free ports pool start. |
100 | /** Free ports pool start. |
61 | */ |
101 | */ |
62 | #define TCP_FREE_PORTS_START 1025 |
102 | #define TCP_FREE_PORTS_START 1025 |
63 | 103 | ||
64 | /** Free ports pool end. |
104 | /** Free ports pool end. |
65 | */ |
105 | */ |
66 | #define TCP_FREE_PORTS_END 65535 |
106 | #define TCP_FREE_PORTS_END 65535 |
67 | 107 | ||
68 | /** TCP global data. |
108 | /** \todo |
69 | */ |
109 | */ |
- | 110 | #define TCP_SYN_SENT_TIMEOUT 1000000L |
|
- | 111 | ||
- | 112 | /** The maximum number of timeouts in a row before singaling connection lost. |
|
- | 113 | */ |
|
- | 114 | #define TCP_MAX_TIMEOUTS 8 |
|
- | 115 | ||
- | 116 | /** The number of acknowledgements before retransmit. |
|
- | 117 | */ |
|
- | 118 | #define TCP_FAST_RETRANSMIT_COUNT 3 |
|
- | 119 | ||
- | 120 | /** \todo |
|
- | 121 | */ |
|
- | 122 | #define IS_IN_INTERVAL_OVERFLOW( lower, value, higher_equal ) (((( lower ) < ( value )) && ((( value ) <= ( higher_equal )) || (( higher_equal ) < ( lower )))) || ((( value ) <= ( higher_equal )) && (( higher_equal ) < ( lower )))) |
|
- | 123 | ||
- | 124 | /** Type definition of the TCP timeout. |
|
- | 125 | * @see tcp_timeout |
|
- | 126 | */ |
|
- | 127 | typedef struct tcp_timeout tcp_timeout_t; |
|
- | 128 | ||
- | 129 | /** Type definition of the TCP timeout pointer. |
|
- | 130 | * @see tcp_timeout |
|
- | 131 | */ |
|
- | 132 | typedef tcp_timeout_t * tcp_timeout_ref; |
|
- | 133 | ||
- | 134 | /** TCP reply timeout data. |
|
- | 135 | * Used as a timeouting fibril argument. |
|
- | 136 | * @see tcp_timeout() |
|
- | 137 | */ |
|
- | 138 | struct tcp_timeout{ |
|
- | 139 | /** TCP global data are going to be read only. |
|
- | 140 | */ |
|
- | 141 | int globals_read_only; |
|
- | 142 | /** Socket port. |
|
- | 143 | */ |
|
- | 144 | int port; |
|
- | 145 | /** Local sockets. |
|
- | 146 | */ |
|
- | 147 | socket_cores_ref local_sockets; |
|
- | 148 | /** Socket identifier. |
|
- | 149 | */ |
|
- | 150 | int socket_id; |
|
- | 151 | /** Socket state. |
|
- | 152 | */ |
|
70 | tcp_globals_t tcp_globals; |
153 | tcp_socket_state_t state; |
- | 154 | /** Sent packet sequence number. |
|
- | 155 | */ |
|
- | 156 | int sequence_number; |
|
- | 157 | /** Timeout in microseconds. |
|
- | 158 | */ |
|
- | 159 | suseconds_t timeout; |
|
- | 160 | /** Port map key. |
|
- | 161 | */ |
|
- | 162 | char * key; |
|
- | 163 | /** Port map key length. |
|
- | 164 | */ |
|
- | 165 | size_t key_length; |
|
- | 166 | }; |
|
- | 167 | ||
- | 168 | /** Releases the packet and returns the result. |
|
- | 169 | * @param packet The packet queue to be released. Input parameter. |
|
- | 170 | * @param result The result to be returned. Input parameter. |
|
- | 171 | * @return The result parameter. |
|
- | 172 | */ |
|
- | 173 | int tcp_release_and_return( packet_t packet, int result ); |
|
- | 174 | ||
- | 175 | int tcp_get_packet_dimension( device_id_t device_id, packet_dimension_ref * packet_dimension ); |
|
- | 176 | void tcp_prepare_operation_header( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize, int finalize ); |
|
- | 177 | int tcp_prepare_timeout( int ( * timeout_function )( void * tcp_timeout_t ), socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout, int globals_read_only ); |
|
- | 178 | void tcp_free_socket_data( socket_core_ref socket ); |
|
- | 179 | int tcp_timeout( void * data ); |
|
- | 180 | int tcp_release_after_timeout( void * data ); |
|
- | 181 | int tcp_process_packet( device_id_t device_id, packet_t packet, services_t error ); |
|
- | 182 | int tcp_connect_core( socket_core_ref socket, socket_cores_ref local_sockets, struct sockaddr * addr, socklen_t addrlen ); |
|
- | 183 | int tcp_queue_prepare_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length ); |
|
- | 184 | int tcp_queue_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length ); |
|
- | 185 | packet_t tcp_get_packets_to_send( socket_core_ref socket, tcp_socket_data_ref socket_data ); |
|
- | 186 | void tcp_send_packets( device_id_t device_id, packet_t packet ); |
|
- | 187 | void tcp_process_acknowledgement( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header ); |
|
- | 188 | packet_t tcp_send_prepare_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number ); |
|
- | 189 | packet_t tcp_prepare_copy( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number ); |
|
- | 190 | void tcp_retransmit_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number ); |
|
- | 191 | int tcp_create_notification_packet( packet_t * packet, socket_core_ref socket, tcp_socket_data_ref socket_data, int synchronize, int finalize ); |
|
- | 192 | void tcp_refresh_socket_data( tcp_socket_data_ref socket_data ); |
|
- | 193 | void tcp_initialize_socket_data( tcp_socket_data_ref socket_data ); |
|
- | 194 | int tcp_process_listen( socket_core_ref listening_socket, tcp_socket_data_ref listening_socket_data, tcp_header_ref header, packet_t packet, struct sockaddr * src, struct sockaddr * dest, size_t addrlen ); |
|
- | 195 | int tcp_process_syn_sent( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet ); |
|
- | 196 | int tcp_process_syn_received( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet ); |
|
- | 197 | int tcp_process_established( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet, int fragments, size_t total_length ); |
|
- | 198 | int tcp_queue_received_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, int fragments, size_t total_length ); |
|
71 | 199 | ||
72 | int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ); |
200 | int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ); |
- | 201 | int tcp_process_client_messages( ipc_callid_t callid, ipc_call_t call ); |
|
- | 202 | int tcp_listen_message( socket_cores_ref local_sockets, int socket_id, int backlog ); |
|
- | 203 | int tcp_connect_message( socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen ); |
|
- | 204 | int tcp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen ); |
|
- | 205 | int tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t data_fragment_size, int flags ); |
|
- | 206 | int tcp_accept_message( socket_cores_ref local_sockets, int socket_id, size_t * addrlen ); |
|
- | 207 | int tcp_close_message( socket_cores_ref local_sockets, int socket_id ); |
|
- | 208 | ||
- | 209 | DEVICE_MAP_IMPLEMENT( packet_dimensions, packet_dimension_t ); |
|
- | 210 | ||
- | 211 | /** TCP global data. |
|
- | 212 | */ |
|
- | 213 | tcp_globals_t tcp_globals; |
|
73 | 214 | ||
74 | /** Initializes the module. |
215 | /** Initializes the module. |
75 | */ |
216 | */ |
76 | int tcp_initialize( async_client_conn_t client_connection ){ |
217 | int tcp_initialize( async_client_conn_t client_connection ){ |
77 | ERROR_DECLARE; |
218 | ERROR_DECLARE; |
78 | 219 | ||
- | 220 | assert( client_connection ); |
|
79 | fibril_rwlock_initialize( & tcp_globals.lock ); |
221 | fibril_rwlock_initialize( & tcp_globals.lock ); |
80 | fibril_rwlock_write_lock( & tcp_globals.lock ); |
222 | fibril_rwlock_write_lock( & tcp_globals.lock ); |
81 | tcp_globals.icmp_phone = icmp_connect_module( SERVICE_ICMP ); |
223 | tcp_globals.icmp_phone = icmp_connect_module( SERVICE_ICMP ); |
82 | if( tcp_globals.icmp_phone < 0 ){ |
224 | if( tcp_globals.icmp_phone < 0 ){ |
83 | return tcp_globals.icmp_phone; |
225 | return tcp_globals.icmp_phone; |
Line 85... | Line 227... | ||
85 | tcp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_TCP, SERVICE_TCP, client_connection, tcp_received_msg ); |
227 | tcp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_TCP, SERVICE_TCP, client_connection, tcp_received_msg ); |
86 | if( tcp_globals.ip_phone < 0 ){ |
228 | if( tcp_globals.ip_phone < 0 ){ |
87 | return tcp_globals.ip_phone; |
229 | return tcp_globals.ip_phone; |
88 | } |
230 | } |
89 | ERROR_PROPAGATE( socket_ports_initialize( & tcp_globals.sockets )); |
231 | ERROR_PROPAGATE( socket_ports_initialize( & tcp_globals.sockets )); |
- | 232 | if( ERROR_OCCURRED( packet_dimensions_initialize( & tcp_globals.dimensions ))){ |
|
- | 233 | socket_ports_destroy( & tcp_globals.sockets ); |
|
- | 234 | return ERROR_CODE; |
|
- | 235 | } |
|
90 | tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1; |
236 | tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1; |
91 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
237 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
92 | return EOK; |
238 | return EOK; |
93 | } |
239 | } |
94 | 240 | ||
95 | int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){ |
241 | int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){ |
96 | // TODO received |
242 | ERROR_DECLARE; |
- | 243 | ||
- | 244 | if( receiver != SERVICE_TCP ) return EREFUSED; |
|
- | 245 | fibril_rwlock_write_lock( & tcp_globals.lock ); |
|
- | 246 | if( ERROR_OCCURRED( tcp_process_packet( device_id, packet, error ))){ |
|
- | 247 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
|
- | 248 | } |
|
97 | // TODO remove debug dump: |
249 | printf( "receive %d \n", ERROR_CODE ); |
- | 250 | ||
- | 251 | return ERROR_CODE; |
|
- | 252 | } |
|
- | 253 | ||
- | 254 | int tcp_process_packet( device_id_t device_id, packet_t packet, services_t error ){ |
|
- | 255 | ERROR_DECLARE; |
|
- | 256 | ||
98 | uint8_t * data; |
257 | size_t length; |
- | 258 | size_t offset; |
|
- | 259 | int result; |
|
99 | data = packet_get_data( packet ); |
260 | tcp_header_ref header; |
100 | printf( "Receiving packet:\n\tid\t= %d\n\tlength\t= %d\n\tdata\t= %.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX\n\t\t%.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX\n", packet_get_id( packet ), packet_get_data_length( packet ), data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ], data[ 8 ], data[ 9 ], data[ 10 ], data[ 11 ], data[ 12 ], data[ 13 ], data[ 14 ], data[ 15 ], data[ 16 ], data[ 17 ], data[ 18 ], data[ 19 ], data[ 20 ], data[ 21 ], data[ 22 ], data[ 23 ], data[ 24 ], data[ 25 ], data[ 26 ], data[ 27 ], data[ 28 ], data[ 29 ], data[ 30 ], data[ 31 ], data[ 32 ], data[ 33 ], data[ 34 ], data[ 35 ], data[ 36 ], data[ 37 ], data[ 38 ], data[ 39 ], data[ 40 ], data[ 41 ], data[ 42 ], data[ 43 ], data[ 44 ], data[ 45 ], data[ 46 ], data[ 47 ], data[ 48 ], data[ 49 ], data[ 50 ], data[ 51 ], data[ 52 ], data[ 53 ], data[ 54 ], data[ 55 ], data[ 56 ], data[ 57 ], data[ 58 ], data[ 59 ] ); |
261 | socket_core_ref socket; |
101 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
262 | tcp_socket_data_ref socket_data; |
- | 263 | packet_t next_packet; |
|
- | 264 | size_t total_length; |
|
- | 265 | uint32_t checksum; |
|
- | 266 | int fragments; |
|
- | 267 | icmp_type_t type; |
|
- | 268 | icmp_code_t code; |
|
- | 269 | struct sockaddr * src; |
|
- | 270 | struct sockaddr * dest; |
|
- | 271 | size_t addrlen; |
|
102 | 272 | ||
- | 273 | printf( "p1 \n" ); |
|
- | 274 | if( error ){ |
|
- | 275 | switch( error ){ |
|
- | 276 | case SERVICE_ICMP: |
|
- | 277 | // process error |
|
- | 278 | result = icmp_client_process_packet( packet, & type, & code, NULL, NULL ); |
|
- | 279 | if( result < 0 ){ |
|
- | 280 | return tcp_release_and_return( packet, result ); |
|
- | 281 | } |
|
- | 282 | length = ( size_t ) result; |
|
- | 283 | if( ERROR_OCCURRED( packet_trim( packet, length, 0 ))){ |
|
- | 284 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 285 | } |
|
- | 286 | break; |
|
- | 287 | default: |
|
- | 288 | return tcp_release_and_return( packet, ENOTSUP ); |
|
- | 289 | } |
|
- | 290 | } |
|
- | 291 | ||
- | 292 | // TODO process received ipopts? |
|
- | 293 | result = ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL ); |
|
- | 294 | // printf("ip len %d\n", result ); |
|
- | 295 | if( result < 0 ){ |
|
- | 296 | return tcp_release_and_return( packet, result ); |
|
- | 297 | } |
|
- | 298 | offset = ( size_t ) result; |
|
- | 299 | ||
- | 300 | length = packet_get_data_length( packet ); |
|
- | 301 | // printf("packet len %d\n", length ); |
|
- | 302 | if( length <= 0 ){ |
|
- | 303 | return tcp_release_and_return( packet, EINVAL ); |
|
- | 304 | } |
|
- | 305 | if( length < sizeof( tcp_header_t ) + offset ){ |
|
- | 306 | return tcp_release_and_return( packet, NO_DATA ); |
|
- | 307 | } |
|
- | 308 | ||
- | 309 | // trim all but TCP header |
|
- | 310 | if( ERROR_OCCURRED( packet_trim( packet, offset, 0 ))){ |
|
- | 311 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 312 | } |
|
- | 313 | ||
- | 314 | // get tcp header |
|
- | 315 | header = ( tcp_header_ref ) packet_get_data( packet ); |
|
- | 316 | if( ! header ){ |
|
- | 317 | return tcp_release_and_return( packet, NO_DATA ); |
|
- | 318 | } |
|
- | 319 | // printf( "header len %d, port %d \n", TCP_HEADER_LENGTH( header ), ntohs( header->destination_port )); |
|
- | 320 | ||
- | 321 | result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest ); |
|
- | 322 | if( result <= 0 ){ |
|
- | 323 | return tcp_release_and_return( packet, result ); |
|
- | 324 | } |
|
- | 325 | addrlen = ( size_t ) result; |
|
- | 326 | ||
- | 327 | if( ERROR_OCCURRED( tl_set_address_port( src, addrlen, ntohs( header->source_port )))){ |
|
- | 328 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 329 | } |
|
- | 330 | ||
- | 331 | // find the destination socket |
|
- | 332 | socket = socket_port_find( & tcp_globals.sockets, ntohs( header->destination_port ), ( const char * ) src, addrlen ); |
|
- | 333 | if( ! socket ){ |
|
- | 334 | // printf("listening?\n"); |
|
- | 335 | // find the listening destination socket |
|
- | 336 | socket = socket_port_find( & tcp_globals.sockets, ntohs( header->destination_port ), SOCKET_MAP_KEY_LISTENING, 0 ); |
|
- | 337 | if( ! socket ){ |
|
- | 338 | if( tl_prepare_icmp_packet( tcp_globals.net_phone, tcp_globals.icmp_phone, packet, error ) == EOK ){ |
|
- | 339 | icmp_destination_unreachable_msg( tcp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet ); |
|
- | 340 | } |
|
- | 341 | return EADDRNOTAVAIL; |
|
- | 342 | } |
|
- | 343 | } |
|
- | 344 | printf("socket id %d\n", socket->socket_id ); |
|
- | 345 | socket_data = ( tcp_socket_data_ref ) socket->specific_data; |
|
- | 346 | assert( socket_data ); |
|
- | 347 | ||
- | 348 | // some data received, clear the timeout counter |
|
- | 349 | socket_data->timeout_count = 0; |
|
- | 350 | ||
- | 351 | // count the received packet fragments |
|
- | 352 | next_packet = packet; |
|
- | 353 | fragments = 0; |
|
- | 354 | checksum = 0; |
|
- | 355 | total_length = 0; |
|
- | 356 | do{ |
|
- | 357 | ++ fragments; |
|
- | 358 | length = packet_get_data_length( next_packet ); |
|
- | 359 | if( length <= 0 ){ |
|
- | 360 | return tcp_release_and_return( packet, NO_DATA ); |
|
- | 361 | } |
|
- | 362 | total_length += length; |
|
- | 363 | // add partial checksum if set |
|
- | 364 | if( ! error ){ |
|
- | 365 | checksum = compute_checksum( checksum, packet_get_data( packet ), packet_get_data_length( packet )); |
|
- | 366 | } |
|
- | 367 | }while(( next_packet = pq_next( next_packet ))); |
|
- | 368 | // printf( "fragments %d of %d bytes\n", fragments, total_length ); |
|
- | 369 | ||
- | 370 | // printf("lock?\n"); |
|
- | 371 | fibril_rwlock_write_lock( socket_data->local_lock ); |
|
- | 372 | // printf("locked\n"); |
|
- | 373 | if( ! error ){ |
|
- | 374 | if( socket_data->state == TCP_SOCKET_LISTEN ){ |
|
- | 375 | if( socket_data->pseudo_header ){ |
|
- | 376 | free( socket_data->pseudo_header ); |
|
- | 377 | socket_data->pseudo_header = NULL; |
|
- | 378 | socket_data->headerlen = 0; |
|
- | 379 | } |
|
- | 380 | if( ERROR_OCCURRED( ip_client_get_pseudo_header( IPPROTO_TCP, src, addrlen, dest, addrlen, total_length, & socket_data->pseudo_header, & socket_data->headerlen ))){ |
|
- | 381 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 382 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 383 | } |
|
- | 384 | }else if( ERROR_OCCURRED( ip_client_set_pseudo_header_data_length( socket_data->pseudo_header, socket_data->headerlen, total_length ))){ |
|
- | 385 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 386 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 387 | } |
|
- | 388 | checksum = compute_checksum( checksum, socket_data->pseudo_header, socket_data->headerlen ); |
|
- | 389 | if( flip_checksum( compact_checksum( checksum ))){ |
|
- | 390 | printf( "checksum err %x -> %x\n", header->checksum, flip_checksum( compact_checksum( checksum ))); |
|
- | 391 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 392 | if( ! ERROR_OCCURRED( tl_prepare_icmp_packet( tcp_globals.net_phone, tcp_globals.icmp_phone, packet, error ))){ |
|
- | 393 | // checksum error ICMP |
|
- | 394 | icmp_parameter_problem_msg( tcp_globals.icmp_phone, ICMP_PARAM_POINTER, (( size_t ) (( void * ) & header->checksum )) - (( size_t ) (( void * ) header )), packet ); |
|
- | 395 | } |
|
- | 396 | return EINVAL; |
|
- | 397 | } |
|
- | 398 | } |
|
- | 399 | ||
- | 400 | fibril_rwlock_read_unlock( & tcp_globals.lock ); |
|
- | 401 | ||
- | 402 | // TODO error reporting/handling |
|
- | 403 | // printf( "st %d\n", socket_data->state ); |
|
- | 404 | switch( socket_data->state ){ |
|
- | 405 | case TCP_SOCKET_LISTEN: |
|
- | 406 | ERROR_CODE = tcp_process_listen( socket, socket_data, header, packet, src, dest, addrlen ); |
|
- | 407 | break; |
|
- | 408 | case TCP_SOCKET_SYN_RECEIVED: |
|
- | 409 | ERROR_CODE = tcp_process_syn_received( socket, socket_data, header, packet ); |
|
- | 410 | break; |
|
- | 411 | case TCP_SOCKET_SYN_SENT: |
|
- | 412 | ERROR_CODE = tcp_process_syn_sent( socket, socket_data, header, packet ); |
|
- | 413 | break; |
|
- | 414 | case TCP_SOCKET_FIN_WAIT_1: |
|
- | 415 | // ack changing the state to FIN_WAIT_2 gets processed later |
|
- | 416 | case TCP_SOCKET_FIN_WAIT_2: |
|
- | 417 | // fin changing state to LAST_ACK gets processed later |
|
- | 418 | case TCP_SOCKET_LAST_ACK: |
|
- | 419 | // ack releasing the socket get processed later |
|
- | 420 | case TCP_SOCKET_CLOSING: |
|
- | 421 | // ack releasing the socket gets processed later |
|
- | 422 | case TCP_SOCKET_ESTABLISHED: |
|
- | 423 | ERROR_CODE = tcp_process_established( socket, socket_data, header, packet, fragments, total_length ); |
|
- | 424 | break; |
|
- | 425 | default: |
|
- | 426 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 427 | } |
|
- | 428 | ||
- | 429 | if( ERROR_CODE != EOK ){ |
|
- | 430 | printf( "process %d\n", ERROR_CODE ); |
|
- | 431 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 432 | } |
|
103 | return EOK; |
433 | return EOK; |
104 | } |
434 | } |
105 | 435 | ||
- | 436 | int tcp_process_established( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet, int fragments, size_t total_length ){ |
|
- | 437 | ERROR_DECLARE; |
|
- | 438 | ||
- | 439 | packet_t next_packet; |
|
- | 440 | packet_t tmp_packet; |
|
- | 441 | uint32_t old_incoming; |
|
- | 442 | size_t order; |
|
- | 443 | uint32_t sequence_number; |
|
- | 444 | size_t length; |
|
- | 445 | size_t offset; |
|
- | 446 | uint32_t new_sequence_number; |
|
- | 447 | ||
- | 448 | assert( socket ); |
|
- | 449 | assert( socket_data ); |
|
- | 450 | assert( socket->specific_data == socket_data ); |
|
- | 451 | assert( header ); |
|
- | 452 | assert( packet ); |
|
- | 453 | ||
- | 454 | new_sequence_number = ntohl( header->sequence_number ); |
|
- | 455 | old_incoming = socket_data->next_incoming; |
|
- | 456 | ||
- | 457 | if( header->finalize ){ |
|
- | 458 | socket_data->fin_incoming = new_sequence_number; |
|
- | 459 | } |
|
- | 460 | ||
- | 461 | // printf( "pe %d < %d <= %d\n", new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length ); |
|
- | 462 | // trim begining if containing expected data |
|
- | 463 | if( IS_IN_INTERVAL_OVERFLOW( new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length )){ |
|
- | 464 | // get the acknowledged offset |
|
- | 465 | if( socket_data->next_incoming < new_sequence_number ){ |
|
- | 466 | offset = new_sequence_number - socket_data->next_incoming; |
|
- | 467 | }else{ |
|
- | 468 | offset = socket_data->next_incoming - new_sequence_number; |
|
- | 469 | } |
|
- | 470 | // printf( "offset %d\n", offset ); |
|
- | 471 | new_sequence_number += offset; |
|
- | 472 | total_length -= offset; |
|
- | 473 | length = packet_get_data_length( packet ); |
|
- | 474 | // trim the acknowledged data |
|
- | 475 | while( length <= offset ){ |
|
- | 476 | // release the acknowledged packets |
|
- | 477 | next_packet = pq_next( packet ); |
|
- | 478 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 479 | packet = next_packet; |
|
- | 480 | offset -= length; |
|
- | 481 | length = packet_get_data_length( packet ); |
|
- | 482 | } |
|
- | 483 | if(( offset > 0 ) |
|
- | 484 | && ( ERROR_OCCURRED( packet_trim( packet, offset, 0 )))){ |
|
- | 485 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 486 | } |
|
- | 487 | assert( new_sequence_number == socket_data->next_incoming ); |
|
- | 488 | } |
|
- | 489 | ||
- | 490 | // release if overflowing the window |
|
- | 491 | // if( IS_IN_INTERVAL_OVERFLOW( socket_data->next_incoming + socket_data->window, new_sequence_number, new_sequence_number + total_length )){ |
|
- | 492 | // return tcp_release_and_return( packet, EOVERFLOW ); |
|
- | 493 | // } |
|
- | 494 | ||
- | 495 | /* |
|
- | 496 | // trim end if overflowing the window |
|
- | 497 | if( IS_IN_INTERVAL_OVERFLOW( new_sequence_number, socket_data->next_incoming + socket_data->window, new_sequence_number + total_length )){ |
|
- | 498 | // get the allowed data length |
|
- | 499 | if( socket_data->next_incoming + socket_data->window < new_sequence_number ){ |
|
- | 500 | offset = new_sequence_number - socket_data->next_incoming + socket_data->window; |
|
- | 501 | }else{ |
|
- | 502 | offset = socket_data->next_incoming + socket_data->window - new_sequence_number; |
|
- | 503 | } |
|
- | 504 | next_packet = packet; |
|
- | 505 | // trim the overflowing data |
|
- | 506 | while( next_packet && ( offset > 0 )){ |
|
- | 507 | length = packet_get_data_length( packet ); |
|
- | 508 | if( length <= offset ){ |
|
- | 509 | next_packet = pq_next( next_packet ); |
|
- | 510 | }else if( ERROR_OCCURRED( packet_trim( next_packet, 0, length - offset ))){ |
|
- | 511 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 512 | } |
|
- | 513 | offset -= length; |
|
- | 514 | total_length -= length - offset; |
|
- | 515 | } |
|
- | 516 | // release the overflowing packets |
|
- | 517 | next_packet = pq_next( next_packet ); |
|
- | 518 | if( next_packet ){ |
|
- | 519 | tmp_packet = next_packet; |
|
- | 520 | next_packet = pq_next( next_packet ); |
|
- | 521 | pq_insert_after( tmp_packet, next_packet ); |
|
- | 522 | pq_release( tcp_globals.net_phone, packet_get_id( tmp_packet )); |
|
- | 523 | } |
|
- | 524 | assert( new_sequence_number + total_length == socket_data->next_incoming + socket_data->window ); |
|
- | 525 | } |
|
- | 526 | */ |
|
- | 527 | // the expected one arrived? |
|
- | 528 | if( new_sequence_number == socket_data->next_incoming ){ |
|
- | 529 | printf("expected\n"); |
|
- | 530 | // process acknowledgement |
|
- | 531 | tcp_process_acknowledgement( socket, socket_data, header ); |
|
- | 532 | ||
- | 533 | // remove the header |
|
- | 534 | total_length -= TCP_HEADER_LENGTH( header ); |
|
- | 535 | if( ERROR_OCCURRED( packet_trim( packet, TCP_HEADER_LENGTH( header ), 0 ))){ |
|
- | 536 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 537 | } |
|
- | 538 | ||
- | 539 | if( total_length ){ |
|
- | 540 | ERROR_PROPAGATE( tcp_queue_received_packet( socket, socket_data, packet, fragments, total_length )); |
|
- | 541 | }else{ |
|
- | 542 | total_length = 1; |
|
- | 543 | } |
|
- | 544 | socket_data->next_incoming = old_incoming + total_length; |
|
- | 545 | packet = socket_data->incoming; |
|
- | 546 | while( packet ){ |
|
- | 547 | if( ERROR_OCCURRED( pq_get_order( socket_data->incoming, & order, NULL ))){ |
|
- | 548 | // remove the corrupted packet |
|
- | 549 | next_packet = pq_detach( packet ); |
|
- | 550 | if( packet == socket_data->incoming ){ |
|
- | 551 | socket_data->incoming = next_packet; |
|
- | 552 | } |
|
- | 553 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 554 | packet = next_packet; |
|
- | 555 | continue; |
|
- | 556 | } |
|
- | 557 | sequence_number = ( uint32_t ) order; |
|
- | 558 | if( IS_IN_INTERVAL_OVERFLOW( sequence_number, old_incoming, socket_data->next_incoming )){ |
|
- | 559 | // move to the next |
|
- | 560 | packet = pq_next( packet ); |
|
- | 561 | // coninual data? |
|
- | 562 | }else if( IS_IN_INTERVAL_OVERFLOW( old_incoming, sequence_number, socket_data->next_incoming )){ |
|
- | 563 | // detach the packet |
|
- | 564 | next_packet = pq_detach( packet ); |
|
- | 565 | if( packet == socket_data->incoming ){ |
|
- | 566 | socket_data->incoming = next_packet; |
|
- | 567 | } |
|
- | 568 | // get data length |
|
- | 569 | length = packet_get_data_length( packet ); |
|
- | 570 | new_sequence_number = sequence_number + length; |
|
- | 571 | if( length <= 0 ){ |
|
- | 572 | // remove the empty packet |
|
- | 573 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 574 | packet = next_packet; |
|
- | 575 | continue; |
|
- | 576 | } |
|
- | 577 | // exactly following |
|
- | 578 | if( sequence_number == socket_data->next_incoming ){ |
|
- | 579 | // queue received data |
|
- | 580 | ERROR_PROPAGATE( tcp_queue_received_packet( socket, socket_data, packet, 1, packet_get_data_length( packet ))); |
|
- | 581 | socket_data->next_incoming = new_sequence_number; |
|
- | 582 | packet = next_packet; |
|
- | 583 | continue; |
|
- | 584 | // at least partly following data? |
|
- | 585 | }else if( IS_IN_INTERVAL_OVERFLOW( sequence_number, socket_data->next_incoming, new_sequence_number )){ |
|
- | 586 | if( socket_data->next_incoming < new_sequence_number ){ |
|
- | 587 | length = new_sequence_number - socket_data->next_incoming; |
|
- | 588 | }else{ |
|
- | 589 | length = socket_data->next_incoming - new_sequence_number; |
|
- | 590 | } |
|
- | 591 | if( ! ERROR_OCCURRED( packet_trim( packet, length, 0 ))){ |
|
- | 592 | // queue received data |
|
- | 593 | ERROR_PROPAGATE( tcp_queue_received_packet( socket, socket_data, packet, 1, packet_get_data_length( packet ))); |
|
- | 594 | socket_data->next_incoming = new_sequence_number; |
|
- | 595 | packet = next_packet; |
|
- | 596 | continue; |
|
- | 597 | } |
|
- | 598 | } |
|
- | 599 | // remove the duplicit or corrupted packet |
|
- | 600 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 601 | packet = next_packet; |
|
- | 602 | continue; |
|
- | 603 | }else{ |
|
- | 604 | break; |
|
- | 605 | } |
|
- | 606 | } |
|
- | 607 | }else if( IS_IN_INTERVAL( socket_data->next_incoming, new_sequence_number, socket_data->next_incoming + socket_data->window )){ |
|
- | 608 | printf("in window\n"); |
|
- | 609 | // process acknowledgement |
|
- | 610 | tcp_process_acknowledgement( socket, socket_data, header ); |
|
- | 611 | ||
- | 612 | // remove the header |
|
- | 613 | total_length -= TCP_HEADER_LENGTH( header ); |
|
- | 614 | if( ERROR_OCCURRED( packet_trim( packet, TCP_HEADER_LENGTH( header ), 0 ))){ |
|
- | 615 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 616 | } |
|
- | 617 | ||
- | 618 | next_packet = pq_detach( packet ); |
|
- | 619 | length = packet_get_data_length( packet ); |
|
- | 620 | tmp_packet = pq_add( socket_data->incoming, packet, new_sequence_number, length ); |
|
- | 621 | if( ! tmp_packet ){ |
|
- | 622 | // remove the corrupted packets |
|
- | 623 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 624 | pq_release( tcp_globals.net_phone, packet_get_id( next_packet )); |
|
- | 625 | }else{ |
|
- | 626 | socket_data->incoming = tmp_packet; |
|
- | 627 | while( next_packet ){ |
|
- | 628 | new_sequence_number += length; |
|
- | 629 | tmp_packet = pq_detach( next_packet ); |
|
- | 630 | length = packet_get_data_length( next_packet ); |
|
- | 631 | if( ERROR_OCCURRED( pq_set_order( next_packet, new_sequence_number, length )) |
|
- | 632 | || ERROR_OCCURRED( pq_insert_after( packet, next_packet ))){ |
|
- | 633 | pq_release( tcp_globals.net_phone, packet_get_id( next_packet )); |
|
- | 634 | } |
|
- | 635 | next_packet = tmp_packet; |
|
- | 636 | } |
|
- | 637 | } |
|
- | 638 | }else{ |
|
- | 639 | printf("unexpected\n"); |
|
- | 640 | // release duplicite or restricted |
|
- | 641 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 642 | } |
|
- | 643 | ||
- | 644 | // change state according to the acknowledging incoming fin |
|
- | 645 | if( IS_IN_INTERVAL_OVERFLOW( old_incoming, socket_data->fin_incoming, socket_data->next_incoming )){ |
|
- | 646 | switch( socket_data->state ){ |
|
- | 647 | case TCP_SOCKET_FIN_WAIT_1: |
|
- | 648 | case TCP_SOCKET_FIN_WAIT_2: |
|
- | 649 | case TCP_SOCKET_CLOSING: |
|
- | 650 | socket_data->state = TCP_SOCKET_CLOSING; |
|
- | 651 | break; |
|
- | 652 | //case TCP_ESTABLISHED: |
|
- | 653 | default: |
|
- | 654 | socket_data->state = TCP_SOCKET_CLOSE_WAIT; |
|
- | 655 | break; |
|
- | 656 | } |
|
- | 657 | } |
|
- | 658 | ||
- | 659 | packet = tcp_get_packets_to_send( socket, socket_data ); |
|
- | 660 | if( ! packet ){ |
|
- | 661 | // create the notification packet |
|
- | 662 | ERROR_PROPAGATE( tcp_create_notification_packet( & packet, socket, socket_data, 0, 0 )); |
|
- | 663 | ERROR_PROPAGATE( tcp_queue_prepare_packet( socket, socket_data, packet, 1 )); |
|
- | 664 | packet = tcp_send_prepare_packet( socket, socket_data, packet, 1, socket_data->last_outgoing + 1 ); |
|
- | 665 | } |
|
- | 666 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 667 | // send the packet |
|
- | 668 | tcp_send_packets( socket_data->device_id, packet ); |
|
- | 669 | return EOK; |
|
- | 670 | } |
|
- | 671 | ||
- | 672 | int tcp_queue_received_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, int fragments, size_t total_length ){ |
|
- | 673 | ERROR_DECLARE; |
|
- | 674 | ||
- | 675 | assert( socket ); |
|
- | 676 | assert( socket_data ); |
|
- | 677 | assert( socket->specific_data == socket_data ); |
|
- | 678 | assert( packet ); |
|
- | 679 | assert( fragments >= 1 ); |
|
- | 680 | assert( socket_data->window > total_length ); |
|
- | 681 | ||
- | 682 | // queue the received packet |
|
- | 683 | if( ERROR_OCCURRED( dyn_fifo_push( & socket->received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){ |
|
- | 684 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 685 | } |
|
- | 686 | ||
- | 687 | // decrease the window size |
|
- | 688 | socket_data->window -= total_length; |
|
- | 689 | ||
- | 690 | // notify the destination socket |
|
- | 691 | async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, 0, 0, 0, ( ipcarg_t ) fragments ); |
|
- | 692 | return EOK; |
|
- | 693 | } |
|
- | 694 | ||
- | 695 | int tcp_process_syn_sent( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet ){ |
|
- | 696 | ERROR_DECLARE; |
|
- | 697 | ||
- | 698 | packet_t next_packet; |
|
- | 699 | ||
- | 700 | assert( socket ); |
|
- | 701 | assert( socket_data ); |
|
- | 702 | assert( socket->specific_data == socket_data ); |
|
- | 703 | assert( header ); |
|
- | 704 | assert( packet ); |
|
- | 705 | ||
- | 706 | if( header->synchronize ){ |
|
- | 707 | // process acknowledgement |
|
- | 708 | tcp_process_acknowledgement( socket, socket_data, header ); |
|
- | 709 | ||
- | 710 | socket_data->next_incoming = ntohl( header->sequence_number ) + 1; |
|
- | 711 | // release additional packets |
|
- | 712 | next_packet = pq_detach( packet ); |
|
- | 713 | if( next_packet ){ |
|
- | 714 | pq_release( tcp_globals.net_phone, packet_get_id( next_packet )); |
|
- | 715 | } |
|
- | 716 | // trim if longer than the header |
|
- | 717 | if(( packet_get_data_length( packet ) > sizeof( * header )) |
|
- | 718 | && ERROR_OCCURRED( packet_trim( packet, 0, packet_get_data_length( packet ) - sizeof( * header )))){ |
|
- | 719 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 720 | } |
|
- | 721 | tcp_prepare_operation_header( socket, socket_data, header, 0, 0 ); |
|
- | 722 | fibril_mutex_lock( & socket_data->operation.mutex ); |
|
- | 723 | socket_data->operation.result = tcp_queue_packet( socket, socket_data, packet, 1 ); |
|
- | 724 | if( socket_data->operation.result == EOK ){ |
|
- | 725 | socket_data->state = TCP_SOCKET_ESTABLISHED; |
|
- | 726 | packet = tcp_get_packets_to_send( socket, socket_data ); |
|
- | 727 | if( packet ){ |
|
- | 728 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 729 | // send the packet |
|
- | 730 | tcp_send_packets( socket_data->device_id, packet ); |
|
- | 731 | // signal the result |
|
- | 732 | fibril_condvar_signal( & socket_data->operation.condvar ); |
|
- | 733 | fibril_mutex_unlock( & socket_data->operation.mutex ); |
|
- | 734 | return EOK; |
|
- | 735 | } |
|
- | 736 | } |
|
- | 737 | fibril_mutex_unlock( & socket_data->operation.mutex ); |
|
- | 738 | } |
|
- | 739 | return tcp_release_and_return( packet, EINVAL ); |
|
- | 740 | } |
|
- | 741 | ||
- | 742 | int tcp_process_listen( socket_core_ref listening_socket, tcp_socket_data_ref listening_socket_data, tcp_header_ref header, packet_t packet, struct sockaddr * src, struct sockaddr * dest, size_t addrlen ){ |
|
- | 743 | ERROR_DECLARE; |
|
- | 744 | ||
- | 745 | packet_t next_packet; |
|
- | 746 | socket_core_ref socket; |
|
- | 747 | tcp_socket_data_ref socket_data; |
|
- | 748 | int socket_id; |
|
- | 749 | int listening_socket_id = listening_socket->socket_id; |
|
- | 750 | int listening_port = listening_socket->port; |
|
- | 751 | ||
- | 752 | assert( listening_socket ); |
|
- | 753 | assert( listening_socket_data ); |
|
- | 754 | assert( listening_socket->specific_data == listening_socket_data ); |
|
- | 755 | assert( header ); |
|
- | 756 | assert( packet ); |
|
- | 757 | ||
- | 758 | // printf( "syn %d\n", header->synchronize ); |
|
- | 759 | if( header->synchronize ){ |
|
- | 760 | socket_data = ( tcp_socket_data_ref ) malloc( sizeof( * socket_data )); |
|
- | 761 | if( ! socket_data ){ |
|
- | 762 | return tcp_release_and_return( packet, ENOMEM ); |
|
- | 763 | }else{ |
|
- | 764 | tcp_initialize_socket_data( socket_data ); |
|
- | 765 | socket_data->local_lock = listening_socket_data->local_lock; |
|
- | 766 | socket_data->local_sockets = listening_socket_data->local_sockets; |
|
- | 767 | socket_data->listening_socket_id = listening_socket->socket_id; |
|
- | 768 | ||
- | 769 | socket_data->next_incoming = ntohl( header->sequence_number ); |
|
- | 770 | socket_data->treshold = socket_data->next_incoming + ntohs( header->window ); |
|
- | 771 | ||
- | 772 | socket_data->addrlen = addrlen; |
|
- | 773 | socket_data->addr = malloc( socket_data->addrlen ); |
|
- | 774 | if( ! socket_data->addr ){ |
|
- | 775 | free( socket_data ); |
|
- | 776 | return tcp_release_and_return( packet, ENOMEM ); |
|
- | 777 | } |
|
- | 778 | memcpy( socket_data->addr, src, socket_data->addrlen ); |
|
- | 779 | ||
- | 780 | socket_data->dest_port = ntohs( header->source_port ); |
|
- | 781 | if( ERROR_OCCURRED( tl_set_address_port( socket_data->addr, socket_data->addrlen, socket_data->dest_port ))){ |
|
- | 782 | free( socket_data->addr ); |
|
- | 783 | free( socket_data ); |
|
- | 784 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 785 | return ERROR_CODE; |
|
- | 786 | } |
|
- | 787 | ||
- | 788 | // printf( "addr %p\n", socket_data->addr, socket_data->addrlen ); |
|
- | 789 | // create a socket |
|
- | 790 | if( ERROR_OCCURRED( socket_create( socket_data->local_sockets, listening_socket->phone, socket_data, & socket_id ))){ |
|
- | 791 | free( socket_data->addr ); |
|
- | 792 | free( socket_data ); |
|
- | 793 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 794 | } |
|
- | 795 | ||
- | 796 | printf("new_sock %d\n", socket_id); |
|
- | 797 | socket_data->pseudo_header = listening_socket_data->pseudo_header; |
|
- | 798 | socket_data->headerlen = listening_socket_data->headerlen; |
|
- | 799 | listening_socket_data->pseudo_header = NULL; |
|
- | 800 | listening_socket_data->headerlen = 0; |
|
- | 801 | ||
- | 802 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 803 | // printf("list lg\n"); |
|
- | 804 | fibril_rwlock_write_lock( & tcp_globals.lock ); |
|
- | 805 | // printf("list locked\n"); |
|
- | 806 | // find the destination socket |
|
- | 807 | listening_socket = socket_port_find( & tcp_globals.sockets, listening_port, SOCKET_MAP_KEY_LISTENING, 0 ); |
|
- | 808 | if(( ! listening_socket ) || ( listening_socket->socket_id != listening_socket_id )){ |
|
- | 809 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
|
- | 810 | // a shadow may remain until app hangs up |
|
- | 811 | return tcp_release_and_return( packet, EOK/*ENOTSOCK*/ ); |
|
- | 812 | } |
|
- | 813 | // printf("port %d\n", listening_socket->port ); |
|
- | 814 | listening_socket_data = ( tcp_socket_data_ref ) listening_socket->specific_data; |
|
- | 815 | assert( listening_socket_data ); |
|
- | 816 | ||
- | 817 | // printf("list ll\n"); |
|
- | 818 | fibril_rwlock_write_lock( listening_socket_data->local_lock ); |
|
- | 819 | // printf("list locked\n"); |
|
- | 820 | ||
- | 821 | socket = socket_cores_find( listening_socket_data->local_sockets, socket_id ); |
|
- | 822 | if( ! socket ){ |
|
- | 823 | // where is the socket?!? |
|
- | 824 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
|
- | 825 | return ENOTSOCK; |
|
- | 826 | } |
|
- | 827 | socket_data = ( tcp_socket_data_ref ) socket->specific_data; |
|
- | 828 | assert( socket_data ); |
|
- | 829 | ||
- | 830 | // uint8_t * data = socket_data->addr; |
|
- | 831 | // printf( "addr %d of %x %x %x %x-%x %x %x %x-%x %x %x %x-%x %x %x %x\n", socket_data->addrlen, data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ], data[ 8 ], data[ 9 ], data[ 10 ], data[ 11 ], data[ 12 ], data[ 13 ], data[ 14 ], data[ 15 ] ); |
|
- | 832 | ||
- | 833 | ERROR_CODE = socket_port_add( & tcp_globals.sockets, listening_port, socket, ( const char * ) socket_data->addr, socket_data->addrlen ); |
|
- | 834 | assert( socket == socket_port_find( & tcp_globals.sockets, listening_port, ( const char * ) socket_data->addr, socket_data->addrlen )); |
|
- | 835 | //ERROR_CODE = socket_bind_free_port( & tcp_globals.sockets, socket, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port ); |
|
- | 836 | //tcp_globals.last_used_port = socket->port; |
|
- | 837 | // printf("bound %d\n", socket->port ); |
|
- | 838 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
|
- | 839 | if( ERROR_CODE != EOK ){ |
|
- | 840 | socket_destroy( tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, & tcp_globals.sockets, tcp_free_socket_data ); |
|
- | 841 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 842 | } |
|
- | 843 | ||
- | 844 | socket_data->state = TCP_SOCKET_LISTEN; |
|
- | 845 | socket_data->next_incoming = ntohl( header->sequence_number ) + 1; |
|
- | 846 | // release additional packets |
|
- | 847 | next_packet = pq_detach( packet ); |
|
- | 848 | if( next_packet ){ |
|
- | 849 | pq_release( tcp_globals.net_phone, packet_get_id( next_packet )); |
|
- | 850 | } |
|
- | 851 | // trim if longer than the header |
|
- | 852 | if(( packet_get_data_length( packet ) > sizeof( * header )) |
|
- | 853 | && ERROR_OCCURRED( packet_trim( packet, 0, packet_get_data_length( packet ) - sizeof( * header )))){ |
|
- | 854 | socket_destroy( tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, & tcp_globals.sockets, tcp_free_socket_data ); |
|
- | 855 | return tcp_release_and_return( packet, ERROR_CODE ); |
|
- | 856 | } |
|
- | 857 | tcp_prepare_operation_header( socket, socket_data, header, 1, 0 ); |
|
- | 858 | if( ERROR_OCCURRED( tcp_queue_packet( socket, socket_data, packet, 1 ))){ |
|
- | 859 | socket_destroy( tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, & tcp_globals.sockets, tcp_free_socket_data ); |
|
- | 860 | return ERROR_CODE; |
|
- | 861 | } |
|
- | 862 | packet = tcp_get_packets_to_send( socket, socket_data ); |
|
- | 863 | // printf("send %d\n", packet_get_id( packet )); |
|
- | 864 | if( ! packet ){ |
|
- | 865 | socket_destroy( tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, & tcp_globals.sockets, tcp_free_socket_data ); |
|
- | 866 | return EINVAL; |
|
- | 867 | }else{ |
|
- | 868 | socket_data->state = TCP_SOCKET_SYN_RECEIVED; |
|
- | 869 | // printf("unlock\n"); |
|
- | 870 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 871 | // send the packet |
|
- | 872 | tcp_send_packets( socket_data->device_id, packet ); |
|
- | 873 | return EOK; |
|
- | 874 | } |
|
- | 875 | } |
|
- | 876 | } |
|
- | 877 | return tcp_release_and_return( packet, EINVAL ); |
|
- | 878 | } |
|
- | 879 | ||
- | 880 | int tcp_process_syn_received( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet ){ |
|
- | 881 | ERROR_DECLARE; |
|
- | 882 | ||
- | 883 | socket_core_ref listening_socket; |
|
- | 884 | tcp_socket_data_ref listening_socket_data; |
|
- | 885 | ||
- | 886 | assert( socket ); |
|
- | 887 | assert( socket_data ); |
|
- | 888 | assert( socket->specific_data == socket_data ); |
|
- | 889 | assert( header ); |
|
- | 890 | assert( packet ); |
|
- | 891 | ||
- | 892 | printf("syn_rec\n"); |
|
- | 893 | if( header->acknowledge ){ |
|
- | 894 | // process acknowledgement |
|
- | 895 | tcp_process_acknowledgement( socket, socket_data, header ); |
|
- | 896 | ||
- | 897 | socket_data->next_incoming = ntohl( header->sequence_number );// + 1; |
|
- | 898 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 899 | socket_data->state = TCP_SOCKET_ESTABLISHED; |
|
- | 900 | listening_socket = socket_cores_find( socket_data->local_sockets, socket_data->listening_socket_id ); |
|
- | 901 | if( listening_socket ){ |
|
- | 902 | listening_socket_data = ( tcp_socket_data_ref ) listening_socket->specific_data; |
|
- | 903 | assert( listening_socket_data ); |
|
- | 904 | ||
- | 905 | // queue the received packet |
|
- | 906 | if( ! ERROR_OCCURRED( dyn_fifo_push( & listening_socket->accepted, socket->socket_id, listening_socket_data->backlog ))){ |
|
- | 907 | // notify the destination socket |
|
- | 908 | async_msg_5( socket->phone, NET_SOCKET_ACCEPTED, ( ipcarg_t ) listening_socket->socket_id, 0, 0, 0, ( ipcarg_t ) socket->socket_id ); |
|
- | 909 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 910 | return EOK; |
|
- | 911 | } |
|
- | 912 | } |
|
- | 913 | // send FIN |
|
- | 914 | socket_data->state = TCP_SOCKET_FIN_WAIT_1; |
|
- | 915 | ||
- | 916 | // create the notification packet |
|
- | 917 | ERROR_PROPAGATE( tcp_create_notification_packet( & packet, socket, socket_data, 0, 1 )); |
|
- | 918 | ||
- | 919 | // send the packet |
|
- | 920 | ERROR_PROPAGATE( tcp_queue_packet( socket, socket_data, packet, 1 )); |
|
- | 921 | ||
- | 922 | // flush packets |
|
- | 923 | packet = tcp_get_packets_to_send( socket, socket_data ); |
|
- | 924 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 925 | if( packet ){ |
|
- | 926 | // send the packet |
|
- | 927 | tcp_send_packets( socket_data->device_id, packet ); |
|
- | 928 | } |
|
- | 929 | return EOK; |
|
- | 930 | }else{ |
|
- | 931 | return tcp_release_and_return( packet, EINVAL ); |
|
- | 932 | } |
|
- | 933 | return EINVAL; |
|
- | 934 | } |
|
- | 935 | ||
- | 936 | void tcp_process_acknowledgement( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header ){ |
|
- | 937 | size_t number; |
|
- | 938 | size_t length; |
|
- | 939 | packet_t packet; |
|
- | 940 | packet_t next; |
|
- | 941 | packet_t acknowledged = NULL; |
|
- | 942 | packet_t first; |
|
- | 943 | uint32_t old; |
|
- | 944 | ||
- | 945 | assert( socket ); |
|
- | 946 | assert( socket_data ); |
|
- | 947 | assert( socket->specific_data == socket_data ); |
|
- | 948 | assert( header ); |
|
- | 949 | ||
- | 950 | if( header->acknowledge ){ |
|
- | 951 | number = ntohl( header->acknowledgement_number ); |
|
- | 952 | // if more data acknowledged |
|
- | 953 | if( number != socket_data->expected ){ |
|
- | 954 | old = socket_data->expected; |
|
- | 955 | if( IS_IN_INTERVAL_OVERFLOW( old, socket_data->fin_outgoing, number )){ |
|
- | 956 | switch( socket_data->state ){ |
|
- | 957 | case TCP_SOCKET_FIN_WAIT_1: |
|
- | 958 | socket_data->state = TCP_SOCKET_FIN_WAIT_2; |
|
- | 959 | break; |
|
- | 960 | case TCP_SOCKET_LAST_ACK: |
|
- | 961 | case TCP_SOCKET_CLOSING: |
|
- | 962 | // fin acknowledged - release the socket in another fibril |
|
- | 963 | tcp_prepare_timeout( tcp_release_after_timeout, socket, socket_data, 0, TCP_SOCKET_TIME_WAIT, NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT, true ); |
|
- | 964 | break; |
|
- | 965 | default: |
|
- | 966 | break; |
|
- | 967 | } |
|
- | 968 | } |
|
- | 969 | // update the treshold if higher than set |
|
- | 970 | if( number + ntohs( header->window ) > socket_data->expected + socket_data->treshold ){ |
|
- | 971 | socket_data->treshold = number + ntohs( header->window ) - socket_data->expected; |
|
- | 972 | } |
|
- | 973 | // set new expected sequence number |
|
- | 974 | socket_data->expected = number; |
|
- | 975 | socket_data->expected_count = 1; |
|
- | 976 | packet = socket_data->outgoing; |
|
- | 977 | while( pq_get_order( packet, & number, & length ) == EOK ){ |
|
- | 978 | if( IS_IN_INTERVAL_OVERFLOW(( uint32_t ) old, ( uint32_t )( number + length ), ( uint32_t ) socket_data->expected )){ |
|
- | 979 | next = pq_detach( packet ); |
|
- | 980 | if( packet == socket_data->outgoing ){ |
|
- | 981 | socket_data->outgoing = next; |
|
- | 982 | } |
|
- | 983 | // add to acknowledged or release |
|
- | 984 | first = pq_add( acknowledged, packet, 0, 0 ); |
|
- | 985 | if( first ){ |
|
- | 986 | acknowledged = first; |
|
- | 987 | }else{ |
|
- | 988 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 989 | } |
|
- | 990 | packet = next; |
|
- | 991 | }else if( old < socket_data->expected ){ |
|
- | 992 | break; |
|
- | 993 | } |
|
- | 994 | } |
|
- | 995 | // release acknowledged |
|
- | 996 | if( acknowledged ){ |
|
- | 997 | pq_release( tcp_globals.net_phone, packet_get_id( acknowledged )); |
|
- | 998 | } |
|
- | 999 | return; |
|
- | 1000 | // if the same as the previous time |
|
- | 1001 | }else if( number == socket_data->expected ){ |
|
- | 1002 | // increase the counter |
|
- | 1003 | ++ socket_data->expected_count; |
|
- | 1004 | if( socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT ){ |
|
- | 1005 | socket_data->expected_count = 1; |
|
- | 1006 | // TODO retransmit lock |
|
- | 1007 | //tcp_retransmit_packet( socket, socket_data, number ); |
|
- | 1008 | } |
|
- | 1009 | } |
|
- | 1010 | } |
|
- | 1011 | } |
|
- | 1012 | ||
106 | int tcp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
1013 | int tcp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
107 | ERROR_DECLARE; |
1014 | ERROR_DECLARE; |
108 | 1015 | ||
109 | packet_t packet; |
1016 | packet_t packet; |
110 | 1017 | ||
- | 1018 | assert( call ); |
|
- | 1019 | assert( answer ); |
|
- | 1020 | assert( answer_count ); |
|
- | 1021 | ||
111 | * answer_count = 0; |
1022 | * answer_count = 0; |
112 | switch( IPC_GET_METHOD( * call )){ |
1023 | switch( IPC_GET_METHOD( * call )){ |
113 | case IPC_M_PHONE_HUNGUP: |
- | |
114 | return EOK; |
- | |
115 | case NET_TL_RECEIVED: |
1024 | case NET_TL_RECEIVED: |
- | 1025 | //fibril_rwlock_read_lock( & tcp_globals.lock ); |
|
116 | ERROR_PROPAGATE( packet_translate( tcp_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
1026 | if( ! ERROR_OCCURRED( packet_translate( tcp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){ |
117 | return tcp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_TCP, IPC_GET_ERROR( call )); |
1027 | ERROR_CODE = tcp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_TCP, IPC_GET_ERROR( call )); |
- | 1028 | } |
|
- | 1029 | //fibril_rwlock_read_unlock( & tcp_globals.lock ); |
|
- | 1030 | return ERROR_CODE; |
|
- | 1031 | case IPC_M_CONNECT_TO_ME: |
|
- | 1032 | return tcp_process_client_messages( callid, * call ); |
|
118 | } |
1033 | } |
119 | return ENOTSUP; |
1034 | return ENOTSUP; |
120 | } |
1035 | } |
121 | 1036 | ||
- | 1037 | void tcp_refresh_socket_data( tcp_socket_data_ref socket_data ){ |
|
- | 1038 | assert( socket_data ); |
|
- | 1039 | ||
- | 1040 | bzero( socket_data, sizeof( * socket_data )); |
|
- | 1041 | socket_data->state = TCP_SOCKET_INITIAL; |
|
- | 1042 | socket_data->device_id = -1; |
|
- | 1043 | socket_data->window = NET_DEFAULT_TCP_WINDOW; |
|
- | 1044 | socket_data->treshold = socket_data->window; |
|
- | 1045 | socket_data->last_outgoing = TCP_INITIAL_SEQUENCE_NUMBER; |
|
- | 1046 | socket_data->timeout = NET_DEFAULT_TCP_INITIAL_TIMEOUT; |
|
- | 1047 | socket_data->acknowledged = socket_data->last_outgoing; |
|
- | 1048 | socket_data->next_outgoing = socket_data->last_outgoing + 1; |
|
- | 1049 | socket_data->expected = socket_data->next_outgoing; |
|
- | 1050 | } |
|
- | 1051 | ||
- | 1052 | void tcp_initialize_socket_data( tcp_socket_data_ref socket_data ){ |
|
- | 1053 | assert( socket_data ); |
|
- | 1054 | ||
- | 1055 | tcp_refresh_socket_data( socket_data ); |
|
- | 1056 | fibril_mutex_initialize( & socket_data->operation.mutex ); |
|
- | 1057 | fibril_condvar_initialize( & socket_data->operation.condvar ); |
|
- | 1058 | } |
|
- | 1059 | ||
- | 1060 | int tcp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){ |
|
- | 1061 | int res; |
|
- | 1062 | bool keep_on_going = true; |
|
- | 1063 | socket_cores_t local_sockets; |
|
- | 1064 | int app_phone = IPC_GET_PHONE( & call ); |
|
- | 1065 | struct sockaddr * addr; |
|
- | 1066 | size_t addrlen; |
|
- | 1067 | fibril_rwlock_t lock; |
|
- | 1068 | ipc_call_t answer; |
|
- | 1069 | int answer_count; |
|
- | 1070 | tcp_socket_data_ref socket_data; |
|
- | 1071 | socket_core_ref socket; |
|
- | 1072 | ||
- | 1073 | /* |
|
- | 1074 | * Accept the connection |
|
- | 1075 | * - Answer the first IPC_M_CONNECT_ME_TO call. |
|
- | 1076 | */ |
|
- | 1077 | ipc_answer_0( callid, EOK ); |
|
- | 1078 | ||
- | 1079 | socket_cores_initialize( & local_sockets ); |
|
- | 1080 | fibril_rwlock_initialize( & lock ); |
|
- | 1081 | ||
- | 1082 | while( keep_on_going ){ |
|
- | 1083 | // refresh data |
|
- | 1084 | refresh_answer( & answer, & answer_count ); |
|
- | 1085 | ||
- | 1086 | callid = async_get_call( & call ); |
|
- | 1087 | // printf( "message %d\n", IPC_GET_METHOD( * call )); |
|
- | 1088 | ||
- | 1089 | switch( IPC_GET_METHOD( call )){ |
|
- | 1090 | case IPC_M_PHONE_HUNGUP: |
|
- | 1091 | keep_on_going = false; |
|
- | 1092 | res = EOK; |
|
- | 1093 | break; |
|
- | 1094 | case NET_SOCKET: |
|
- | 1095 | socket_data = ( tcp_socket_data_ref ) malloc( sizeof( * socket_data )); |
|
- | 1096 | if( ! socket_data ){ |
|
- | 1097 | res = ENOMEM; |
|
- | 1098 | }else{ |
|
- | 1099 | tcp_initialize_socket_data( socket_data ); |
|
- | 1100 | socket_data->local_lock = & lock; |
|
- | 1101 | socket_data->local_sockets = & local_sockets; |
|
- | 1102 | fibril_rwlock_write_lock( & lock ); |
|
- | 1103 | res = socket_create( & local_sockets, app_phone, socket_data, SOCKET_SET_SOCKET_ID( answer )); |
|
- | 1104 | fibril_rwlock_write_unlock( & lock ); |
|
- | 1105 | if( res == EOK ){ |
|
- | 1106 | * SOCKET_SET_HEADER_SIZE( answer ) = sizeof( tcp_header_t ); |
|
- | 1107 | * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_TCP_FRAGMENT_SIZE; |
|
- | 1108 | answer_count = 3; |
|
- | 1109 | }else{ |
|
- | 1110 | free( socket_data ); |
|
- | 1111 | } |
|
- | 1112 | } |
|
- | 1113 | break; |
|
- | 1114 | case NET_SOCKET_BIND: |
|
- | 1115 | res = data_receive(( void ** ) & addr, & addrlen ); |
|
- | 1116 | if( res == EOK ){ |
|
- | 1117 | fibril_rwlock_write_lock( & tcp_globals.lock ); |
|
- | 1118 | fibril_rwlock_write_lock( & lock ); |
|
- | 1119 | res = socket_bind( & local_sockets, & tcp_globals.sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port ); |
|
- | 1120 | if( res == EOK ){ |
|
- | 1121 | socket = socket_cores_find( & local_sockets, SOCKET_GET_SOCKET_ID( call )); |
|
- | 1122 | if( socket ){ |
|
- | 1123 | socket_data = ( tcp_socket_data_ref ) socket->specific_data; |
|
- | 1124 | assert( socket_data ); |
|
- | 1125 | socket_data->state = TCP_SOCKET_LISTEN; |
|
- | 1126 | } |
|
- | 1127 | } |
|
- | 1128 | fibril_rwlock_write_unlock( & lock ); |
|
- | 1129 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
|
- | 1130 | free( addr ); |
|
- | 1131 | } |
|
- | 1132 | break; |
|
- | 1133 | case NET_SOCKET_LISTEN: |
|
- | 1134 | fibril_rwlock_read_lock( & tcp_globals.lock ); |
|
- | 1135 | // fibril_rwlock_write_lock( & tcp_globals.lock ); |
|
- | 1136 | fibril_rwlock_write_lock( & lock ); |
|
- | 1137 | res = tcp_listen_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_BACKLOG( call )); |
|
- | 1138 | fibril_rwlock_write_unlock( & lock ); |
|
- | 1139 | // fibril_rwlock_write_unlock( & tcp_globals.lock ); |
|
- | 1140 | fibril_rwlock_read_unlock( & tcp_globals.lock ); |
|
- | 1141 | break; |
|
- | 1142 | case NET_SOCKET_CONNECT: |
|
- | 1143 | res = data_receive(( void ** ) & addr, & addrlen ); |
|
- | 1144 | if( res == EOK ){ |
|
- | 1145 | // the global lock may released in the tcp_connect_message() function |
|
- | 1146 | fibril_rwlock_write_lock( & tcp_globals.lock ); |
|
- | 1147 | fibril_rwlock_write_lock( & lock ); |
|
- | 1148 | res = tcp_connect_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen ); |
|
- | 1149 | if( res != EOK ){ |
|
- | 1150 | fibril_rwlock_write_unlock( & lock ); |
|
- | 1151 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
|
- | 1152 | free( addr ); |
|
- | 1153 | } |
|
- | 1154 | } |
|
- | 1155 | break; |
|
- | 1156 | case NET_SOCKET_ACCEPT: |
|
- | 1157 | fibril_rwlock_read_lock( & tcp_globals.lock ); |
|
- | 1158 | fibril_rwlock_write_lock( & lock ); |
|
- | 1159 | res = tcp_accept_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), & addrlen ); |
|
- | 1160 | fibril_rwlock_write_unlock( & lock ); |
|
- | 1161 | fibril_rwlock_read_unlock( & tcp_globals.lock ); |
|
- | 1162 | if( res > 0 ){ |
|
- | 1163 | * SOCKET_SET_SOCKET_ID( answer ) = res; |
|
- | 1164 | * SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen; |
|
- | 1165 | answer_count = 2; |
|
- | 1166 | } |
|
- | 1167 | break; |
|
- | 1168 | case NET_SOCKET_SEND: |
|
- | 1169 | fibril_rwlock_read_lock( & tcp_globals.lock ); |
|
- | 1170 | fibril_rwlock_write_lock( & lock ); |
|
- | 1171 | res = tcp_send_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_DATA_FRAGMENT_SIZE( call ), SOCKET_GET_FLAGS( call )); |
|
- | 1172 | if( res != EOK ){ |
|
- | 1173 | fibril_rwlock_write_unlock( & lock ); |
|
- | 1174 | fibril_rwlock_read_unlock( & tcp_globals.lock ); |
|
- | 1175 | } |
|
- | 1176 | break; |
|
- | 1177 | case NET_SOCKET_SENDTO: |
|
- | 1178 | res = data_receive(( void ** ) & addr, & addrlen ); |
|
- | 1179 | if( res == EOK ){ |
|
- | 1180 | fibril_rwlock_read_lock( & tcp_globals.lock ); |
|
- | 1181 | fibril_rwlock_write_lock( & lock ); |
|
- | 1182 | res = tcp_send_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_DATA_FRAGMENT_SIZE( call ), SOCKET_GET_FLAGS( call )); |
|
- | 1183 | if( res != EOK ){ |
|
- | 1184 | fibril_rwlock_write_unlock( & lock ); |
|
- | 1185 | fibril_rwlock_read_unlock( & tcp_globals.lock ); |
|
- | 1186 | } |
|
- | 1187 | free( addr ); |
|
- | 1188 | } |
|
- | 1189 | break; |
|
- | 1190 | case NET_SOCKET_RECV: |
|
- | 1191 | fibril_rwlock_read_lock( & tcp_globals.lock ); |
|
- | 1192 | fibril_rwlock_write_lock( & lock ); |
|
- | 1193 | res = tcp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ), NULL ); |
|
- | 1194 | fibril_rwlock_write_unlock( & lock ); |
|
- | 1195 | fibril_rwlock_read_unlock( & tcp_globals.lock ); |
|
- | 1196 | if( res > 0 ){ |
|
- | 1197 | * SOCKET_SET_READ_DATA_LENGTH( answer ) = res; |
|
- | 1198 | answer_count = 1; |
|
- | 1199 | res = EOK; |
|
- | 1200 | } |
|
- | 1201 | break; |
|
- | 1202 | case NET_SOCKET_RECVFROM: |
|
- | 1203 | fibril_rwlock_read_lock( & tcp_globals.lock ); |
|
- | 1204 | fibril_rwlock_write_lock( & lock ); |
|
- | 1205 | res = tcp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ), & addrlen ); |
|
- | 1206 | fibril_rwlock_write_unlock( & lock ); |
|
- | 1207 | fibril_rwlock_read_unlock( & tcp_globals.lock ); |
|
- | 1208 | if( res > 0 ){ |
|
- | 1209 | * SOCKET_SET_READ_DATA_LENGTH( answer ) = res; |
|
- | 1210 | * SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen; |
|
- | 1211 | answer_count = 2; |
|
- | 1212 | res = EOK; |
|
- | 1213 | } |
|
- | 1214 | break; |
|
- | 1215 | case NET_SOCKET_CLOSE: |
|
- | 1216 | fibril_rwlock_write_lock( & tcp_globals.lock ); |
|
- | 1217 | fibril_rwlock_write_lock( & lock ); |
|
- | 1218 | res = tcp_close_message( & local_sockets, SOCKET_GET_SOCKET_ID( call )); |
|
- | 1219 | if( res != EOK ){ |
|
- | 1220 | fibril_rwlock_write_unlock( & lock ); |
|
- | 1221 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
|
- | 1222 | } |
|
- | 1223 | break; |
|
- | 1224 | case NET_SOCKET_GETSOCKOPT: |
|
- | 1225 | case NET_SOCKET_SETSOCKOPT: |
|
- | 1226 | default: |
|
- | 1227 | res = ENOTSUP; |
|
- | 1228 | break; |
|
- | 1229 | } |
|
- | 1230 | ||
- | 1231 | // printf( "res = %d\n", res ); |
|
- | 1232 | ||
- | 1233 | answer_call( callid, res, & answer, answer_count ); |
|
- | 1234 | } |
|
- | 1235 | ||
- | 1236 | printf("release\n"); |
|
- | 1237 | // release all local sockets |
|
- | 1238 | socket_cores_release( tcp_globals.net_phone, & local_sockets, & tcp_globals.sockets, tcp_free_socket_data ); |
|
- | 1239 | ||
- | 1240 | return EOK; |
|
- | 1241 | } |
|
- | 1242 | ||
- | 1243 | int tcp_timeout( void * data ){ |
|
- | 1244 | tcp_timeout_ref timeout = data; |
|
- | 1245 | int keep_write_lock = false; |
|
- | 1246 | socket_core_ref socket; |
|
- | 1247 | tcp_socket_data_ref socket_data; |
|
- | 1248 | ||
- | 1249 | assert( timeout ); |
|
- | 1250 | ||
- | 1251 | // sleep the given timeout |
|
- | 1252 | async_usleep( timeout->timeout ); |
|
- | 1253 | // lock the globals |
|
- | 1254 | if( timeout->globals_read_only ){ |
|
- | 1255 | fibril_rwlock_read_lock( & tcp_globals.lock ); |
|
- | 1256 | }else{ |
|
- | 1257 | fibril_rwlock_write_lock( & tcp_globals.lock ); |
|
- | 1258 | } |
|
- | 1259 | // find the pending operation socket |
|
- | 1260 | socket = socket_port_find( & tcp_globals.sockets, timeout->port, timeout->key, timeout->key_length ); |
|
- | 1261 | if( socket && ( socket->socket_id == timeout->socket_id )){ |
|
- | 1262 | socket_data = ( tcp_socket_data_ref ) socket->specific_data; |
|
- | 1263 | assert( socket_data ); |
|
- | 1264 | if( socket_data->local_sockets == timeout->local_sockets ){ |
|
- | 1265 | fibril_rwlock_write_lock( socket_data->local_lock ); |
|
- | 1266 | if( timeout->sequence_number ){ |
|
- | 1267 | // increase the timeout counter; |
|
- | 1268 | ++ socket_data->timeout_count; |
|
- | 1269 | if( socket_data->timeout_count == TCP_MAX_TIMEOUTS ){ |
|
- | 1270 | // TODO release as connection lost |
|
- | 1271 | //tcp_refresh_socket_data( socket_data ); |
|
- | 1272 | } |
|
- | 1273 | // retransmit |
|
- | 1274 | // TODO enable retransmit |
|
- | 1275 | //tcp_retransmit_packet( socket, socket_data, timeout->sequence_number ); |
|
- | 1276 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 1277 | }else{ |
|
- | 1278 | fibril_mutex_lock( & socket_data->operation.mutex ); |
|
- | 1279 | // set the timeout operation result if state not changed |
|
- | 1280 | if( socket_data->state == timeout->state ){ |
|
- | 1281 | socket_data->operation.result = ETIMEOUT; |
|
- | 1282 | // notify the main fibril |
|
- | 1283 | fibril_condvar_signal( & socket_data->operation.condvar ); |
|
- | 1284 | // keep the global write lock |
|
- | 1285 | keep_write_lock = true; |
|
- | 1286 | }else{ |
|
- | 1287 | // operation is ok, do nothing |
|
- | 1288 | // unlocking from now on, so the unlock order does not matter... |
|
- | 1289 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 1290 | } |
|
- | 1291 | fibril_mutex_unlock( & socket_data->operation.mutex ); |
|
- | 1292 | } |
|
- | 1293 | } |
|
- | 1294 | } |
|
- | 1295 | // unlock only if no socket |
|
- | 1296 | if( timeout->globals_read_only ){ |
|
- | 1297 | fibril_rwlock_read_unlock( & tcp_globals.lock ); |
|
- | 1298 | }else if( ! keep_write_lock ){ |
|
- | 1299 | // release if not desired |
|
- | 1300 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
|
- | 1301 | } |
|
- | 1302 | // release the timeout structure |
|
- | 1303 | free( timeout ); |
|
- | 1304 | return EOK; |
|
- | 1305 | } |
|
- | 1306 | ||
- | 1307 | int tcp_release_after_timeout( void * data ){ |
|
- | 1308 | tcp_timeout_ref timeout = data; |
|
- | 1309 | socket_core_ref socket; |
|
- | 1310 | tcp_socket_data_ref socket_data; |
|
- | 1311 | fibril_rwlock_t * local_lock; |
|
- | 1312 | ||
- | 1313 | assert( timeout ); |
|
- | 1314 | ||
- | 1315 | // sleep the given timeout |
|
- | 1316 | async_usleep( timeout->timeout ); |
|
- | 1317 | // lock the globals |
|
- | 1318 | fibril_rwlock_write_lock( & tcp_globals.lock ); |
|
- | 1319 | // find the pending operation socket |
|
- | 1320 | socket = socket_port_find( & tcp_globals.sockets, timeout->port, timeout->key, timeout->key_length ); |
|
- | 1321 | if( socket && ( socket->socket_id == timeout->socket_id )){ |
|
- | 1322 | socket_data = ( tcp_socket_data_ref ) socket->specific_data; |
|
- | 1323 | assert( socket_data ); |
|
- | 1324 | if( socket_data->local_sockets == timeout->local_sockets ){ |
|
- | 1325 | local_lock = socket_data->local_lock; |
|
- | 1326 | fibril_rwlock_write_lock( local_lock ); |
|
- | 1327 | socket_destroy( tcp_globals.net_phone, timeout->socket_id, timeout->local_sockets, & tcp_globals.sockets, tcp_free_socket_data ); |
|
- | 1328 | fibril_rwlock_write_unlock( local_lock ); |
|
- | 1329 | } |
|
- | 1330 | } |
|
- | 1331 | // unlock the globals |
|
- | 1332 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
|
- | 1333 | // release the timeout structure |
|
- | 1334 | free( timeout ); |
|
- | 1335 | return EOK; |
|
- | 1336 | } |
|
- | 1337 | ||
- | 1338 | void tcp_retransmit_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number ){ |
|
- | 1339 | packet_t packet; |
|
- | 1340 | packet_t copy; |
|
- | 1341 | size_t data_length; |
|
- | 1342 | ||
- | 1343 | assert( socket ); |
|
- | 1344 | assert( socket_data ); |
|
- | 1345 | assert( socket->specific_data == socket_data ); |
|
- | 1346 | ||
- | 1347 | // sent packet? |
|
- | 1348 | packet = pq_find( socket_data->outgoing, sequence_number ); |
|
- | 1349 | printf("retransmit %d\n", packet_get_id( packet )); |
|
- | 1350 | if( packet ){ |
|
- | 1351 | pq_get_order( packet, NULL, & data_length ); |
|
- | 1352 | copy = tcp_prepare_copy( socket, socket_data, packet, data_length, sequence_number ); |
|
- | 1353 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 1354 | // printf( "r send %d\n", packet_get_id( packet )); |
|
- | 1355 | if( copy ){ |
|
- | 1356 | tcp_send_packets( socket_data->device_id, copy ); |
|
- | 1357 | } |
|
- | 1358 | }else{ |
|
- | 1359 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 1360 | } |
|
- | 1361 | } |
|
- | 1362 | ||
- | 1363 | int tcp_listen_message( socket_cores_ref local_sockets, int socket_id, int backlog ){ |
|
- | 1364 | socket_core_ref socket; |
|
- | 1365 | tcp_socket_data_ref socket_data; |
|
- | 1366 | ||
- | 1367 | assert( local_sockets ); |
|
- | 1368 | ||
- | 1369 | if( backlog < 0 ) return EINVAL; |
|
- | 1370 | // find the socket |
|
- | 1371 | socket = socket_cores_find( local_sockets, socket_id ); |
|
- | 1372 | if( ! socket ) return ENOTSOCK; |
|
- | 1373 | // get the socket specific data |
|
- | 1374 | socket_data = ( tcp_socket_data_ref ) socket->specific_data; |
|
- | 1375 | assert( socket_data ); |
|
- | 1376 | // set the backlog |
|
- | 1377 | socket_data->backlog = backlog; |
|
- | 1378 | return EOK; |
|
- | 1379 | } |
|
- | 1380 | ||
- | 1381 | int tcp_connect_message( socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen ){ |
|
- | 1382 | ERROR_DECLARE; |
|
- | 1383 | ||
- | 1384 | socket_core_ref socket; |
|
- | 1385 | ||
- | 1386 | assert( local_sockets ); |
|
- | 1387 | assert( addr ); |
|
- | 1388 | assert( addrlen > 0 ); |
|
- | 1389 | ||
- | 1390 | // find the socket |
|
- | 1391 | socket = socket_cores_find( local_sockets, socket_id ); |
|
- | 1392 | if( ! socket ) return ENOTSOCK; |
|
- | 1393 | if( ERROR_OCCURRED( tcp_connect_core( socket, local_sockets, addr, addrlen ))){ |
|
- | 1394 | tcp_free_socket_data( socket ); |
|
- | 1395 | // unbind if bound |
|
- | 1396 | if( socket->port > 0 ){ |
|
- | 1397 | socket_ports_exclude( & tcp_globals.sockets, socket->port ); |
|
- | 1398 | socket->port = 0; |
|
- | 1399 | } |
|
- | 1400 | } |
|
- | 1401 | return ERROR_CODE; |
|
- | 1402 | } |
|
- | 1403 | ||
- | 1404 | int tcp_connect_core( socket_core_ref socket, socket_cores_ref local_sockets, struct sockaddr * addr, socklen_t addrlen ){ |
|
- | 1405 | ERROR_DECLARE; |
|
- | 1406 | ||
- | 1407 | tcp_socket_data_ref socket_data; |
|
- | 1408 | packet_t packet; |
|
- | 1409 | ||
- | 1410 | assert( socket ); |
|
- | 1411 | assert( addr ); |
|
- | 1412 | assert( addrlen > 0 ); |
|
- | 1413 | ||
- | 1414 | // get the socket specific data |
|
- | 1415 | socket_data = ( tcp_socket_data_ref ) socket->specific_data; |
|
- | 1416 | assert( socket_data ); |
|
- | 1417 | assert( socket->specific_data == socket_data ); |
|
- | 1418 | if(( socket_data->state != TCP_SOCKET_INITIAL ) |
|
- | 1419 | && (( socket_data->state != TCP_SOCKET_LISTEN ) || ( socket->port <= 0 ))){ |
|
- | 1420 | return EINVAL; |
|
- | 1421 | } |
|
- | 1422 | // get the destination port |
|
- | 1423 | ERROR_PROPAGATE( tl_get_address_port( addr, addrlen, & socket_data->dest_port )); |
|
- | 1424 | if( socket->port <= 0 ){ |
|
- | 1425 | // try to find a free port |
|
- | 1426 | ERROR_PROPAGATE( socket_bind_free_port( & tcp_globals.sockets, socket, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port )); |
|
- | 1427 | // set the next port as the search starting port number |
|
- | 1428 | tcp_globals.last_used_port = socket->port; |
|
- | 1429 | } |
|
- | 1430 | ERROR_PROPAGATE( ip_get_route_req( tcp_globals.ip_phone, IPPROTO_TCP, addr, addrlen, & socket_data->device_id, & socket_data->pseudo_header, & socket_data->headerlen )); |
|
- | 1431 | ||
- | 1432 | // create the notification packet |
|
- | 1433 | ERROR_PROPAGATE( tcp_create_notification_packet( & packet, socket, socket_data, 1, 0 )); |
|
- | 1434 | ||
- | 1435 | // unlock the globals and wait for an operation |
|
- | 1436 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
|
- | 1437 | ||
- | 1438 | socket_data->addr = addr; |
|
- | 1439 | socket_data->addrlen = addrlen; |
|
- | 1440 | // send the packet |
|
- | 1441 | if( ERROR_OCCURRED( tcp_queue_packet( socket, socket_data, packet, 1 )) |
|
- | 1442 | || ERROR_OCCURRED( tcp_prepare_timeout( tcp_timeout, socket, socket_data, 0, TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false ))){ |
|
- | 1443 | socket_data->addr = NULL; |
|
- | 1444 | socket_data->addrlen = 0; |
|
- | 1445 | fibril_rwlock_write_lock( & tcp_globals.lock ); |
|
- | 1446 | }else{ |
|
- | 1447 | packet = tcp_get_packets_to_send( socket, socket_data ); |
|
- | 1448 | if( packet ){ |
|
- | 1449 | fibril_mutex_lock( & socket_data->operation.mutex ); |
|
- | 1450 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 1451 | // send the packet |
|
- | 1452 | printf( "connecting %d\n", packet_get_id( packet )); |
|
- | 1453 | tcp_send_packets( socket_data->device_id, packet ); |
|
- | 1454 | // wait for a reply |
|
- | 1455 | fibril_condvar_wait( & socket_data->operation.condvar, & socket_data->operation.mutex ); |
|
- | 1456 | ERROR_CODE = socket_data->operation.result; |
|
- | 1457 | if( ERROR_CODE != EOK ){ |
|
- | 1458 | socket_data->addr = NULL; |
|
- | 1459 | socket_data->addrlen = 0; |
|
- | 1460 | } |
|
- | 1461 | }else{ |
|
- | 1462 | socket_data->addr = NULL; |
|
- | 1463 | socket_data->addrlen = 0; |
|
- | 1464 | ERROR_CODE = EINTR; |
|
- | 1465 | } |
|
- | 1466 | } |
|
- | 1467 | ||
- | 1468 | fibril_mutex_unlock( & socket_data->operation.mutex ); |
|
- | 1469 | ||
- | 1470 | // return the result |
|
- | 1471 | return ERROR_CODE; |
|
- | 1472 | } |
|
- | 1473 | ||
- | 1474 | int tcp_queue_prepare_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length ){ |
|
- | 1475 | ERROR_DECLARE; |
|
- | 1476 | ||
- | 1477 | tcp_header_ref header; |
|
- | 1478 | ||
- | 1479 | assert( socket ); |
|
- | 1480 | assert( socket_data ); |
|
- | 1481 | assert( socket->specific_data == socket_data ); |
|
- | 1482 | ||
- | 1483 | // get tcp header |
|
- | 1484 | header = ( tcp_header_ref ) packet_get_data( packet ); |
|
- | 1485 | if( ! header ) return NO_DATA; |
|
- | 1486 | header->destination_port = htons( socket_data->dest_port ); |
|
- | 1487 | header->source_port = htons( socket->port ); |
|
- | 1488 | header->sequence_number = htonl( socket_data->next_outgoing ); |
|
- | 1489 | if( ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) socket_data->addr, socket_data->addrlen ))){ |
|
- | 1490 | return tcp_release_and_return( packet, EINVAL ); |
|
- | 1491 | } |
|
- | 1492 | // remember the outgoing FIN |
|
- | 1493 | if( header->finalize ){ |
|
- | 1494 | socket_data->fin_outgoing = socket_data->next_outgoing; |
|
- | 1495 | } |
|
- | 1496 | return EOK; |
|
- | 1497 | } |
|
- | 1498 | ||
- | 1499 | int tcp_queue_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length ){ |
|
- | 1500 | ERROR_DECLARE; |
|
- | 1501 | packet_t first; |
|
- | 1502 | ||
- | 1503 | assert( socket ); |
|
- | 1504 | assert( socket_data ); |
|
- | 1505 | assert( socket->specific_data == socket_data ); |
|
- | 1506 | ||
- | 1507 | ERROR_PROPAGATE( tcp_queue_prepare_packet( socket, socket_data, packet, data_length )); |
|
- | 1508 | ||
- | 1509 | first = pq_add( socket_data->outgoing, packet, socket_data->next_outgoing, data_length ); |
|
- | 1510 | if( ! first ){ |
|
- | 1511 | return tcp_release_and_return( packet, EINVAL ); |
|
- | 1512 | } |
|
- | 1513 | socket_data->outgoing = first; |
|
- | 1514 | socket_data->next_outgoing += data_length; |
|
- | 1515 | return EOK; |
|
- | 1516 | } |
|
- | 1517 | ||
- | 1518 | packet_t tcp_get_packets_to_send( socket_core_ref socket, tcp_socket_data_ref socket_data ){ |
|
- | 1519 | ERROR_DECLARE; |
|
- | 1520 | ||
- | 1521 | packet_t packet; |
|
- | 1522 | packet_t copy; |
|
- | 1523 | packet_t sending = NULL; |
|
- | 1524 | packet_t previous = NULL; |
|
- | 1525 | size_t data_length; |
|
- | 1526 | ||
- | 1527 | assert( socket ); |
|
- | 1528 | assert( socket_data ); |
|
- | 1529 | assert( socket->specific_data == socket_data ); |
|
- | 1530 | ||
- | 1531 | packet = pq_find( socket_data->outgoing, socket_data->last_outgoing + 1 ); |
|
- | 1532 | while( packet ){ |
|
- | 1533 | pq_get_order( packet, NULL, & data_length ); |
|
- | 1534 | // send only if fits into the window |
|
- | 1535 | // respecting the possible overflow |
|
- | 1536 | if( IS_IN_INTERVAL_OVERFLOW(( uint32_t ) socket_data->last_outgoing, ( uint32_t )( socket_data->last_outgoing + data_length ), ( uint32_t )( socket_data->expected + socket_data->treshold ))){ |
|
- | 1537 | copy = tcp_prepare_copy( socket, socket_data, packet, data_length, socket_data->last_outgoing + 1 ); |
|
- | 1538 | if( ! copy ){ |
|
- | 1539 | return sending; |
|
- | 1540 | } |
|
- | 1541 | if( ! sending ){ |
|
- | 1542 | sending = copy; |
|
- | 1543 | }else{ |
|
- | 1544 | if( ERROR_OCCURRED( pq_insert_after( previous, copy ))){ |
|
- | 1545 | pq_release( tcp_globals.net_phone, packet_get_id( copy )); |
|
- | 1546 | return sending; |
|
- | 1547 | } |
|
- | 1548 | } |
|
- | 1549 | previous = copy; |
|
- | 1550 | packet = pq_next( packet ); |
|
- | 1551 | // overflow occurred ? |
|
- | 1552 | if(( ! packet ) && ( socket_data->last_outgoing > socket_data->next_outgoing )){ |
|
- | 1553 | printf("gpts overflow\n"); |
|
- | 1554 | // continue from the beginning |
|
- | 1555 | packet = socket_data->outgoing; |
|
- | 1556 | } |
|
- | 1557 | socket_data->last_outgoing += data_length; |
|
- | 1558 | }else{ |
|
- | 1559 | break; |
|
- | 1560 | } |
|
- | 1561 | } |
|
- | 1562 | return sending; |
|
- | 1563 | } |
|
- | 1564 | ||
- | 1565 | packet_t tcp_send_prepare_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number ){ |
|
- | 1566 | ERROR_DECLARE; |
|
- | 1567 | ||
- | 1568 | tcp_header_ref header; |
|
- | 1569 | uint32_t checksum; |
|
- | 1570 | ||
- | 1571 | assert( socket ); |
|
- | 1572 | assert( socket_data ); |
|
- | 1573 | assert( socket->specific_data == socket_data ); |
|
- | 1574 | ||
- | 1575 | // adjust the pseudo header |
|
- | 1576 | if( ERROR_OCCURRED( ip_client_set_pseudo_header_data_length( socket_data->pseudo_header, socket_data->headerlen, packet_get_data_length( packet )))){ |
|
- | 1577 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 1578 | return NULL; |
|
- | 1579 | } |
|
- | 1580 | ||
- | 1581 | // get the header |
|
- | 1582 | header = ( tcp_header_ref ) packet_get_data( packet ); |
|
- | 1583 | if( ! header ){ |
|
- | 1584 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 1585 | return NULL; |
|
- | 1586 | } |
|
- | 1587 | assert( ntohl( header->sequence_number ) == sequence_number ); |
|
- | 1588 | ||
- | 1589 | // adjust the header |
|
- | 1590 | if( socket_data->next_incoming ){ |
|
- | 1591 | header->acknowledgement_number = htonl( socket_data->next_incoming ); |
|
- | 1592 | header->acknowledge = 1; |
|
- | 1593 | } |
|
- | 1594 | header->window = htons( socket_data->window ); |
|
- | 1595 | ||
- | 1596 | // checksum |
|
- | 1597 | header->checksum = 0; |
|
- | 1598 | checksum = compute_checksum( 0, socket_data->pseudo_header, socket_data->headerlen ); |
|
- | 1599 | checksum = compute_checksum( checksum, ( uint8_t * ) packet_get_data( packet ), packet_get_data_length( packet )); |
|
- | 1600 | header->checksum = htons( flip_checksum( compact_checksum( checksum ))); |
|
- | 1601 | // prepare the packet |
|
- | 1602 | if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_TCP, 0, 0, 0, 0 )) |
|
- | 1603 | // prepare the timeout |
|
- | 1604 | || ERROR_OCCURRED( tcp_prepare_timeout( tcp_timeout, socket, socket_data, sequence_number, socket_data->state, socket_data->timeout, true ))){ |
|
- | 1605 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 1606 | return NULL; |
|
- | 1607 | } |
|
- | 1608 | return packet; |
|
- | 1609 | } |
|
- | 1610 | ||
- | 1611 | packet_t tcp_prepare_copy( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number ){ |
|
- | 1612 | packet_t copy; |
|
- | 1613 | ||
- | 1614 | assert( socket ); |
|
- | 1615 | assert( socket_data ); |
|
- | 1616 | assert( socket->specific_data == socket_data ); |
|
- | 1617 | ||
- | 1618 | // make a copy of the packet |
|
- | 1619 | copy = packet_get_copy( tcp_globals.net_phone, packet ); |
|
- | 1620 | if( ! copy ) return NULL; |
|
- | 1621 | ||
- | 1622 | return tcp_send_prepare_packet( socket, socket_data, copy, data_length, sequence_number ); |
|
- | 1623 | } |
|
- | 1624 | ||
- | 1625 | void tcp_send_packets( device_id_t device_id, packet_t packet ){ |
|
- | 1626 | packet_t next; |
|
- | 1627 | ||
- | 1628 | while( packet ){ |
|
- | 1629 | next = pq_detach( packet ); |
|
- | 1630 | ip_send_msg( tcp_globals.ip_phone, device_id, packet, SERVICE_TCP, 0 ); |
|
- | 1631 | packet = next; |
|
- | 1632 | } |
|
- | 1633 | } |
|
- | 1634 | ||
- | 1635 | int tcp_get_packet_dimension( device_id_t device_id, packet_dimension_ref * packet_dimension ){ |
|
- | 1636 | ERROR_DECLARE; |
|
- | 1637 | ||
- | 1638 | assert( packet_dimension ); |
|
- | 1639 | ||
- | 1640 | * packet_dimension = packet_dimensions_find( & tcp_globals.dimensions, device_id ); |
|
- | 1641 | if( ! * packet_dimension ){ |
|
- | 1642 | // ask for and remember them if not found |
|
- | 1643 | * packet_dimension = malloc( sizeof( ** packet_dimension )); |
|
- | 1644 | if( ! * packet_dimension ) return ENOMEM; |
|
- | 1645 | if( ERROR_OCCURRED( ip_packet_size_req( tcp_globals.ip_phone, device_id, & ( ** packet_dimension ).addr_len, & ( ** packet_dimension ).prefix, & ( ** packet_dimension ).content, & ( ** packet_dimension ).suffix ))){ |
|
- | 1646 | free( * packet_dimension ); |
|
- | 1647 | return ERROR_CODE; |
|
- | 1648 | } |
|
- | 1649 | ERROR_CODE = packet_dimensions_add( & tcp_globals.dimensions, device_id, * packet_dimension ); |
|
- | 1650 | if( ERROR_CODE < 0 ){ |
|
- | 1651 | free( * packet_dimension ); |
|
- | 1652 | return ERROR_CODE; |
|
- | 1653 | } |
|
- | 1654 | } |
|
- | 1655 | return EOK; |
|
- | 1656 | } |
|
- | 1657 | ||
- | 1658 | void tcp_prepare_operation_header( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize, int finalize ){ |
|
- | 1659 | assert( socket ); |
|
- | 1660 | assert( socket_data ); |
|
- | 1661 | assert( socket->specific_data == socket_data ); |
|
- | 1662 | assert( header ); |
|
- | 1663 | ||
- | 1664 | bzero( header, sizeof( * header )); |
|
- | 1665 | header->source_port = htons( socket->port ); |
|
- | 1666 | header->source_port = htons( socket_data->dest_port ); |
|
- | 1667 | header->header_length = TCP_COMPUTE_HEADER_LENGTH( sizeof( * header )); |
|
- | 1668 | header->synchronize = synchronize; |
|
- | 1669 | header->finalize = finalize; |
|
- | 1670 | } |
|
- | 1671 | ||
- | 1672 | int tcp_prepare_timeout( int ( * timeout_function )( void * tcp_timeout_t ), socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout, int globals_read_only ){ |
|
- | 1673 | tcp_timeout_ref operation_timeout; |
|
- | 1674 | fid_t fibril; |
|
- | 1675 | ||
- | 1676 | assert( socket ); |
|
- | 1677 | assert( socket_data ); |
|
- | 1678 | assert( socket->specific_data == socket_data ); |
|
- | 1679 | ||
- | 1680 | // prepare the timeout with key bundle structure |
|
- | 1681 | operation_timeout = malloc( sizeof( * operation_timeout ) + socket->key_length + 1 ); |
|
- | 1682 | if( ! operation_timeout ) return ENOMEM; |
|
- | 1683 | bzero( operation_timeout, sizeof( * operation_timeout )); |
|
- | 1684 | operation_timeout->globals_read_only = globals_read_only; |
|
- | 1685 | operation_timeout->port = socket->port; |
|
- | 1686 | operation_timeout->local_sockets = socket_data->local_sockets; |
|
- | 1687 | operation_timeout->socket_id = socket->socket_id; |
|
- | 1688 | operation_timeout->timeout = timeout; |
|
- | 1689 | operation_timeout->sequence_number = sequence_number; |
|
- | 1690 | operation_timeout->state = state; |
|
- | 1691 | ||
- | 1692 | // copy the key |
|
- | 1693 | operation_timeout->key = (( char * ) operation_timeout ) + sizeof( * operation_timeout ); |
|
- | 1694 | operation_timeout->key_length = socket->key_length; |
|
- | 1695 | memcpy( operation_timeout->key, socket->key, socket->key_length ); |
|
- | 1696 | operation_timeout->key[ operation_timeout->key_length ] = '\0'; |
|
- | 1697 | ||
- | 1698 | // prepare the timeouting thread |
|
- | 1699 | fibril = fibril_create( timeout_function, operation_timeout ); |
|
- | 1700 | if( ! fibril ){ |
|
- | 1701 | free( operation_timeout ); |
|
- | 1702 | return EPARTY; |
|
- | 1703 | } |
|
- | 1704 | // fibril_mutex_lock( & socket_data->operation.mutex ); |
|
- | 1705 | // start the timeouting fibril |
|
- | 1706 | fibril_add_ready( fibril ); |
|
- | 1707 | //socket_data->state = state; |
|
- | 1708 | return EOK; |
|
- | 1709 | } |
|
- | 1710 | ||
- | 1711 | int tcp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen ){ |
|
- | 1712 | ERROR_DECLARE; |
|
- | 1713 | ||
- | 1714 | socket_core_ref socket; |
|
- | 1715 | tcp_socket_data_ref socket_data; |
|
- | 1716 | int packet_id; |
|
- | 1717 | packet_t packet; |
|
- | 1718 | size_t length; |
|
- | 1719 | ||
- | 1720 | assert( local_sockets ); |
|
- | 1721 | ||
- | 1722 | // find the socket |
|
- | 1723 | socket = socket_cores_find( local_sockets, socket_id ); |
|
- | 1724 | if( ! socket ) return ENOTSOCK; |
|
- | 1725 | // get the socket specific data |
|
- | 1726 | if( ! socket->specific_data ) return NO_DATA; |
|
- | 1727 | socket_data = ( tcp_socket_data_ref ) socket->specific_data; |
|
- | 1728 | ||
- | 1729 | // check state |
|
- | 1730 | if(( socket_data->state != TCP_SOCKET_ESTABLISHED ) && ( socket_data->state != TCP_SOCKET_CLOSE_WAIT )){ |
|
- | 1731 | return ENOTCONN; |
|
- | 1732 | } |
|
- | 1733 | ||
- | 1734 | // send the source address if desired |
|
- | 1735 | if( addrlen ){ |
|
- | 1736 | ERROR_PROPAGATE( data_reply( socket_data->addr, socket_data->addrlen )); |
|
- | 1737 | * addrlen = socket_data->addrlen; |
|
- | 1738 | } |
|
- | 1739 | ||
- | 1740 | // get the next received packet |
|
- | 1741 | packet_id = dyn_fifo_value( & socket->received ); |
|
- | 1742 | if( packet_id < 0 ) return NO_DATA; |
|
- | 1743 | ERROR_PROPAGATE( packet_translate( tcp_globals.net_phone, & packet, packet_id )); |
|
- | 1744 | ||
- | 1745 | // reply the packets |
|
- | 1746 | ERROR_PROPAGATE( socket_reply_packets( packet, & length )); |
|
- | 1747 | ||
- | 1748 | // release the packet |
|
- | 1749 | dyn_fifo_pop( & socket->received ); |
|
- | 1750 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 1751 | // return the total length |
|
- | 1752 | return ( int ) length; |
|
- | 1753 | } |
|
- | 1754 | ||
- | 1755 | int tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t data_fragment_size, int flags ){ |
|
- | 1756 | ERROR_DECLARE; |
|
- | 1757 | ||
- | 1758 | socket_core_ref socket; |
|
- | 1759 | tcp_socket_data_ref socket_data; |
|
- | 1760 | packet_dimension_ref packet_dimension; |
|
- | 1761 | packet_t packet; |
|
- | 1762 | size_t total_length; |
|
- | 1763 | tcp_header_ref header; |
|
- | 1764 | int index; |
|
- | 1765 | int result; |
|
- | 1766 | ||
- | 1767 | assert( local_sockets ); |
|
- | 1768 | ||
- | 1769 | // find the socket |
|
- | 1770 | socket = socket_cores_find( local_sockets, socket_id ); |
|
- | 1771 | if( ! socket ) return ENOTSOCK; |
|
- | 1772 | // get the socket specific data |
|
- | 1773 | if( ! socket->specific_data ) return NO_DATA; |
|
- | 1774 | socket_data = ( tcp_socket_data_ref ) socket->specific_data; |
|
- | 1775 | ||
- | 1776 | // check state |
|
- | 1777 | if(( socket_data->state != TCP_SOCKET_ESTABLISHED ) && ( socket_data->state != TCP_SOCKET_CLOSE_WAIT )){ |
|
- | 1778 | return ENOTCONN; |
|
- | 1779 | } |
|
- | 1780 | ||
- | 1781 | ERROR_PROPAGATE( tcp_get_packet_dimension( socket_data->device_id, & packet_dimension )); |
|
- | 1782 | ||
- | 1783 | // TODO return the device_id + data_fragment_size if different - the client should send it again |
|
- | 1784 | // ( two messages are better than ip fragmentation ) |
|
- | 1785 | ||
- | 1786 | for( index = 0; index < fragments; ++ index ){ |
|
- | 1787 | // read the data fragment |
|
- | 1788 | result = tl_socket_read_packet_data( tcp_globals.net_phone, & packet, sizeof( tcp_header_t ), packet_dimension, socket_data->addr, socket_data->addrlen ); |
|
- | 1789 | if( result < 0 ) return result; |
|
- | 1790 | total_length = ( size_t ) result; |
|
- | 1791 | // prefix the tcp header |
|
- | 1792 | header = PACKET_PREFIX( packet, tcp_header_t ); |
|
- | 1793 | if( ! header ){ |
|
- | 1794 | return tcp_release_and_return( packet, ENOMEM ); |
|
- | 1795 | } |
|
- | 1796 | tcp_prepare_operation_header( socket, socket_data, header, 0, 0 ); |
|
- | 1797 | ERROR_PROPAGATE( tcp_queue_packet( socket, socket_data, packet, 0 )); |
|
- | 1798 | } |
|
- | 1799 | ||
- | 1800 | // flush packets |
|
- | 1801 | packet = tcp_get_packets_to_send( socket, socket_data ); |
|
- | 1802 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 1803 | fibril_rwlock_read_unlock( & tcp_globals.lock ); |
|
- | 1804 | if( packet ){ |
|
- | 1805 | // send the packet |
|
- | 1806 | tcp_send_packets( socket_data->device_id, packet ); |
|
- | 1807 | } |
|
- | 1808 | ||
- | 1809 | return EOK; |
|
- | 1810 | } |
|
- | 1811 | ||
- | 1812 | int tcp_close_message( socket_cores_ref local_sockets, int socket_id ){ |
|
- | 1813 | ERROR_DECLARE; |
|
- | 1814 | ||
- | 1815 | socket_core_ref socket; |
|
- | 1816 | tcp_socket_data_ref socket_data; |
|
- | 1817 | packet_t packet; |
|
- | 1818 | ||
- | 1819 | // find the socket |
|
- | 1820 | socket = socket_cores_find( local_sockets, socket_id ); |
|
- | 1821 | if( ! socket ) return ENOTSOCK; |
|
- | 1822 | // get the socket specific data |
|
- | 1823 | socket_data = ( tcp_socket_data_ref ) socket->specific_data; |
|
- | 1824 | assert( socket_data ); |
|
- | 1825 | ||
- | 1826 | // check state |
|
- | 1827 | switch( socket_data->state ){ |
|
- | 1828 | case TCP_SOCKET_ESTABLISHED: |
|
- | 1829 | socket_data->state = TCP_SOCKET_FIN_WAIT_1; |
|
- | 1830 | break; |
|
- | 1831 | case TCP_SOCKET_CLOSE_WAIT: |
|
- | 1832 | socket_data->state = TCP_SOCKET_LAST_ACK; |
|
- | 1833 | break; |
|
- | 1834 | // case TCP_SOCKET_LISTEN: |
|
- | 1835 | default: |
|
- | 1836 | // just destroy |
|
- | 1837 | if( ! ERROR_OCCURRED( socket_destroy( tcp_globals.net_phone, socket_id, local_sockets, & tcp_globals.sockets, tcp_free_socket_data ))){ |
|
- | 1838 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 1839 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
|
- | 1840 | } |
|
- | 1841 | return ERROR_CODE; |
|
- | 1842 | } |
|
- | 1843 | // send FIN |
|
- | 1844 | // TODO should I wait to complete? |
|
- | 1845 | ||
- | 1846 | // create the notification packet |
|
- | 1847 | ERROR_PROPAGATE( tcp_create_notification_packet( & packet, socket, socket_data, 0, 1 )); |
|
- | 1848 | ||
- | 1849 | // send the packet |
|
- | 1850 | ERROR_PROPAGATE( tcp_queue_packet( socket, socket_data, packet, 1 )); |
|
- | 1851 | ||
- | 1852 | // flush packets |
|
- | 1853 | packet = tcp_get_packets_to_send( socket, socket_data ); |
|
- | 1854 | fibril_rwlock_write_unlock( socket_data->local_lock ); |
|
- | 1855 | fibril_rwlock_write_unlock( & tcp_globals.lock ); |
|
- | 1856 | if( packet ){ |
|
- | 1857 | // send the packet |
|
- | 1858 | tcp_send_packets( socket_data->device_id, packet ); |
|
- | 1859 | } |
|
- | 1860 | return EOK; |
|
- | 1861 | } |
|
- | 1862 | ||
- | 1863 | int tcp_create_notification_packet( packet_t * packet, socket_core_ref socket, tcp_socket_data_ref socket_data, int synchronize, int finalize ){ |
|
- | 1864 | ERROR_DECLARE; |
|
- | 1865 | ||
- | 1866 | packet_dimension_ref packet_dimension; |
|
- | 1867 | tcp_header_ref header; |
|
- | 1868 | ||
- | 1869 | assert( packet ); |
|
- | 1870 | ||
- | 1871 | // get the device packet dimension |
|
- | 1872 | ERROR_PROPAGATE( tcp_get_packet_dimension( socket_data->device_id, & packet_dimension )); |
|
- | 1873 | // get a new packet |
|
- | 1874 | * packet = packet_get_4( tcp_globals.net_phone, sizeof( tcp_header_t ), packet_dimension->addr_len, packet_dimension->prefix, packet_dimension->suffix ); |
|
- | 1875 | if( ! * packet ) return ENOMEM; |
|
- | 1876 | // allocate space in the packet |
|
- | 1877 | header = PACKET_SUFFIX( * packet, tcp_header_t ); |
|
- | 1878 | if( ! header ){ |
|
- | 1879 | tcp_release_and_return( * packet, ENOMEM ); |
|
- | 1880 | } |
|
- | 1881 | ||
- | 1882 | tcp_prepare_operation_header( socket, socket_data, header, synchronize, finalize ); |
|
- | 1883 | return EOK; |
|
- | 1884 | } |
|
- | 1885 | ||
- | 1886 | int tcp_accept_message( socket_cores_ref local_sockets, int socket_id, size_t * addrlen ){ |
|
- | 1887 | ERROR_DECLARE; |
|
- | 1888 | ||
- | 1889 | socket_core_ref accepted; |
|
- | 1890 | socket_core_ref socket; |
|
- | 1891 | tcp_socket_data_ref socket_data; |
|
- | 1892 | ||
- | 1893 | assert( local_sockets ); |
|
- | 1894 | assert( addrlen ); |
|
- | 1895 | ||
- | 1896 | // find the socket |
|
- | 1897 | socket = socket_cores_find( local_sockets, socket_id ); |
|
- | 1898 | if( ! socket ) return ENOTSOCK; |
|
- | 1899 | // get the socket specific data |
|
- | 1900 | socket_data = ( tcp_socket_data_ref ) socket->specific_data; |
|
- | 1901 | assert( socket_data ); |
|
- | 1902 | ||
- | 1903 | // check state |
|
- | 1904 | if( socket_data->state != TCP_SOCKET_LISTEN ){ |
|
- | 1905 | return EINVAL; |
|
- | 1906 | } |
|
- | 1907 | ||
- | 1908 | do{ |
|
- | 1909 | socket_id = dyn_fifo_value( & socket->accepted ); |
|
- | 1910 | if( socket_id < 0 ) return ENOTSOCK; |
|
- | 1911 | ||
- | 1912 | accepted = socket_cores_find( local_sockets, socket_id ); |
|
- | 1913 | if( ! accepted ) return ENOTSOCK; |
|
- | 1914 | // get the socket specific data |
|
- | 1915 | socket_data = ( tcp_socket_data_ref ) accepted->specific_data; |
|
- | 1916 | assert( socket_data ); |
|
- | 1917 | if( socket_data->state == TCP_SOCKET_ESTABLISHED ){ |
|
- | 1918 | ERROR_PROPAGATE( data_reply( socket_data->addr, socket_data->addrlen )); |
|
- | 1919 | * addrlen = socket_data->addrlen; |
|
- | 1920 | } |
|
- | 1921 | dyn_fifo_pop( & socket->accepted ); |
|
- | 1922 | }while( socket_data->state != TCP_SOCKET_ESTABLISHED ); |
|
- | 1923 | printf("ret accept %d\n", accepted->socket_id ); |
|
- | 1924 | return accepted->socket_id; |
|
- | 1925 | } |
|
- | 1926 | ||
- | 1927 | void tcp_free_socket_data( socket_core_ref socket ){ |
|
- | 1928 | tcp_socket_data_ref socket_data; |
|
- | 1929 | ||
- | 1930 | assert( socket ); |
|
- | 1931 | ||
- | 1932 | printf( "destroy_socket %d\n", socket->socket_id ); |
|
- | 1933 | ||
- | 1934 | // get the socket specific data |
|
- | 1935 | socket_data = ( tcp_socket_data_ref ) socket->specific_data; |
|
- | 1936 | assert( socket_data ); |
|
- | 1937 | //free the pseudo header |
|
- | 1938 | if( socket_data->pseudo_header ){ |
|
- | 1939 | if( socket_data->headerlen ){ |
|
- | 1940 | printf("d pseudo\n"); |
|
- | 1941 | free( socket_data->pseudo_header ); |
|
- | 1942 | socket_data->headerlen = 0; |
|
- | 1943 | } |
|
- | 1944 | socket_data->pseudo_header = NULL; |
|
- | 1945 | } |
|
- | 1946 | socket_data->headerlen = 0; |
|
- | 1947 | // free the address |
|
- | 1948 | if( socket_data->addr ){ |
|
- | 1949 | if( socket_data->addrlen ){ |
|
- | 1950 | printf("d addr\n"); |
|
- | 1951 | free( socket_data->addr ); |
|
- | 1952 | socket_data->addrlen = 0; |
|
- | 1953 | } |
|
- | 1954 | socket_data->addr = NULL; |
|
- | 1955 | } |
|
- | 1956 | socket_data->addrlen = 0; |
|
- | 1957 | } |
|
- | 1958 | ||
- | 1959 | int tcp_release_and_return( packet_t packet, int result ){ |
|
- | 1960 | pq_release( tcp_globals.net_phone, packet_get_id( packet )); |
|
- | 1961 | return result; |
|
- | 1962 | } |
|
- | 1963 | ||
122 | /** @} |
1964 | /** @} |
123 | */ |
1965 | */ |