source: mainline/uspace/srv/net/tl/tcp/tcp.c@ 76ca3f7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 76ca3f7 was 6092b56e, checked in by Jakub Jermar <jakub@…>, 15 years ago

Fix dangerous type casts.

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