source: mainline/uspace/srv/net/tl/tcp/tcp.c@ 71b00dcc

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 71b00dcc was aadf01e, checked in by Lukas Mejdrech <lukasmejdrech@…>, 15 years ago

Coding style (no functional change)

  • Property mode set to 100644
File size: 67.0 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;
1062 size_t addrlen;
1063 fibril_rwlock_t lock;
1064 ipc_call_t answer;
1065 int answer_count;
1066 tcp_socket_data_ref socket_data;
1067 socket_core_ref socket;
1068 packet_dimension_ref packet_dimension;
[21580dd]1069
1070 /*
1071 * Accept the connection
1072 * - Answer the first IPC_M_CONNECT_ME_TO call.
1073 */
[2e99277]1074 res = EOK;
1075 answer_count = 0;
[21580dd]1076
[aadf01e]1077 socket_cores_initialize(&local_sockets);
1078 fibril_rwlock_initialize(&lock);
[21580dd]1079
[aadf01e]1080 while(keep_on_going){
[2e99277]1081
1082 // answer the call
[aadf01e]1083 answer_call(callid, res, &answer, answer_count);
[2e99277]1084
[21580dd]1085 // refresh data
[aadf01e]1086 refresh_answer(&answer, &answer_count);
[21580dd]1087
[2e99277]1088 // get the next call
[aadf01e]1089 callid = async_get_call(&call);
[21580dd]1090
[2e99277]1091 // process the call
[aadf01e]1092 switch(IPC_GET_METHOD(call)){
[21580dd]1093 case IPC_M_PHONE_HUNGUP:
1094 keep_on_going = false;
[2e99277]1095 res = EHANGUP;
[21580dd]1096 break;
1097 case NET_SOCKET:
[aadf01e]1098 socket_data = (tcp_socket_data_ref) malloc(sizeof(*socket_data));
1099 if(! socket_data){
[21580dd]1100 res = ENOMEM;
1101 }else{
[aadf01e]1102 tcp_initialize_socket_data(socket_data);
1103 socket_data->local_lock = &lock;
1104 socket_data->local_sockets = &local_sockets;
1105 fibril_rwlock_write_lock(&lock);
1106 *SOCKET_SET_SOCKET_ID(answer) = SOCKET_GET_SOCKET_ID(call);
1107 res = socket_create(&local_sockets, app_phone, socket_data, SOCKET_SET_SOCKET_ID(answer));
1108 fibril_rwlock_write_unlock(&lock);
1109 if(res == EOK){
1110 if(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, DEVICE_INVALID_ID, &packet_dimension) == EOK){
1111 *SOCKET_SET_DATA_FRAGMENT_SIZE(answer) = ((packet_dimension->content < socket_data->data_fragment_size) ? packet_dimension->content : socket_data->data_fragment_size);
[ede63e4]1112 }
[aadf01e]1113// *SOCKET_SET_DATA_FRAGMENT_SIZE(answer) = MAX_TCP_FRAGMENT_SIZE;
1114 *SOCKET_SET_HEADER_SIZE(answer) = TCP_HEADER_SIZE;
[21580dd]1115 answer_count = 3;
1116 }else{
[aadf01e]1117 free(socket_data);
[21580dd]1118 }
1119 }
1120 break;
1121 case NET_SOCKET_BIND:
[aadf01e]1122 res = data_receive((void **) &addr, &addrlen);
1123 if(res == EOK){
1124 fibril_rwlock_write_lock(&tcp_globals.lock);
1125 fibril_rwlock_write_lock(&lock);
1126 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);
1127 if(res == EOK){
1128 socket = socket_cores_find(&local_sockets, SOCKET_GET_SOCKET_ID(call));
1129 if(socket){
1130 socket_data = (tcp_socket_data_ref) socket->specific_data;
1131 assert(socket_data);
[21580dd]1132 socket_data->state = TCP_SOCKET_LISTEN;
1133 }
1134 }
[aadf01e]1135 fibril_rwlock_write_unlock(&lock);
1136 fibril_rwlock_write_unlock(&tcp_globals.lock);
1137 free(addr);
[21580dd]1138 }
1139 break;
1140 case NET_SOCKET_LISTEN:
[aadf01e]1141 fibril_rwlock_read_lock(&tcp_globals.lock);
1142// fibril_rwlock_write_lock(&tcp_globals.lock);
1143 fibril_rwlock_write_lock(&lock);
1144 res = tcp_listen_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_BACKLOG(call));
1145 fibril_rwlock_write_unlock(&lock);
1146// fibril_rwlock_write_unlock(&tcp_globals.lock);
1147 fibril_rwlock_read_unlock(&tcp_globals.lock);
[21580dd]1148 break;
1149 case NET_SOCKET_CONNECT:
[aadf01e]1150 res = data_receive((void **) &addr, &addrlen);
1151 if(res == EOK){
[ede63e4]1152 // the global lock may be released in the tcp_connect_message() function
[aadf01e]1153 fibril_rwlock_write_lock(&tcp_globals.lock);
1154 fibril_rwlock_write_lock(&lock);
1155 res = tcp_connect_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), addr, addrlen);
1156 if(res != EOK){
1157 fibril_rwlock_write_unlock(&lock);
1158 fibril_rwlock_write_unlock(&tcp_globals.lock);
1159 free(addr);
[21580dd]1160 }
1161 }
1162 break;
1163 case NET_SOCKET_ACCEPT:
[aadf01e]1164 fibril_rwlock_read_lock(&tcp_globals.lock);
1165 fibril_rwlock_write_lock(&lock);
1166 res = tcp_accept_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_NEW_SOCKET_ID(call), SOCKET_SET_DATA_FRAGMENT_SIZE(answer), &addrlen);
1167 fibril_rwlock_write_unlock(&lock);
1168 fibril_rwlock_read_unlock(&tcp_globals.lock);
1169 if(res > 0){
1170 *SOCKET_SET_SOCKET_ID(answer) = res;
1171 *SOCKET_SET_ADDRESS_LENGTH(answer) = addrlen;
[ede63e4]1172 answer_count = 3;
[21580dd]1173 }
1174 break;
1175 case NET_SOCKET_SEND:
[aadf01e]1176 fibril_rwlock_read_lock(&tcp_globals.lock);
1177 fibril_rwlock_write_lock(&lock);
1178 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));
1179 if(res != EOK){
1180 fibril_rwlock_write_unlock(&lock);
1181 fibril_rwlock_read_unlock(&tcp_globals.lock);
[ede63e4]1182 }else{
1183 answer_count = 2;
[21580dd]1184 }
1185 break;
1186 case NET_SOCKET_SENDTO:
[aadf01e]1187 res = data_receive((void **) &addr, &addrlen);
1188 if(res == EOK){
1189 fibril_rwlock_read_lock(&tcp_globals.lock);
1190 fibril_rwlock_write_lock(&lock);
1191 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));
1192 if(res != EOK){
1193 fibril_rwlock_write_unlock(&lock);
1194 fibril_rwlock_read_unlock(&tcp_globals.lock);
[ede63e4]1195 }else{
1196 answer_count = 2;
[21580dd]1197 }
[aadf01e]1198 free(addr);
[21580dd]1199 }
1200 break;
1201 case NET_SOCKET_RECV:
[aadf01e]1202 fibril_rwlock_read_lock(&tcp_globals.lock);
1203 fibril_rwlock_write_lock(&lock);
1204 res = tcp_recvfrom_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), NULL);
1205 fibril_rwlock_write_unlock(&lock);
1206 fibril_rwlock_read_unlock(&tcp_globals.lock);
1207 if(res > 0){
1208 *SOCKET_SET_READ_DATA_LENGTH(answer) = res;
[21580dd]1209 answer_count = 1;
1210 res = EOK;
1211 }
1212 break;
1213 case NET_SOCKET_RECVFROM:
[aadf01e]1214 fibril_rwlock_read_lock(&tcp_globals.lock);
1215 fibril_rwlock_write_lock(&lock);
1216 res = tcp_recvfrom_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), &addrlen);
1217 fibril_rwlock_write_unlock(&lock);
1218 fibril_rwlock_read_unlock(&tcp_globals.lock);
1219 if(res > 0){
1220 *SOCKET_SET_READ_DATA_LENGTH(answer) = res;
1221 *SOCKET_SET_ADDRESS_LENGTH(answer) = addrlen;
[ede63e4]1222 answer_count = 3;
[21580dd]1223 res = EOK;
1224 }
1225 break;
1226 case NET_SOCKET_CLOSE:
[aadf01e]1227 fibril_rwlock_write_lock(&tcp_globals.lock);
1228 fibril_rwlock_write_lock(&lock);
1229 res = tcp_close_message(&local_sockets, SOCKET_GET_SOCKET_ID(call));
1230 if(res != EOK){
1231 fibril_rwlock_write_unlock(&lock);
1232 fibril_rwlock_write_unlock(&tcp_globals.lock);
[21580dd]1233 }
1234 break;
1235 case NET_SOCKET_GETSOCKOPT:
1236 case NET_SOCKET_SETSOCKOPT:
1237 default:
1238 res = ENOTSUP;
1239 break;
1240 }
1241 }
1242
1243 printf("release\n");
1244 // release all local sockets
[aadf01e]1245 socket_cores_release(tcp_globals.net_phone, &local_sockets, &tcp_globals.sockets, tcp_free_socket_data);
[21580dd]1246
1247 return EOK;
1248}
1249
[aadf01e]1250int tcp_timeout(void * data){
1251 tcp_timeout_ref timeout = data;
1252 int keep_write_lock = false;
1253 socket_core_ref socket;
1254 tcp_socket_data_ref socket_data;
[21580dd]1255
[aadf01e]1256 assert(timeout);
[21580dd]1257
1258 // sleep the given timeout
[aadf01e]1259 async_usleep(timeout->timeout);
[21580dd]1260 // lock the globals
[aadf01e]1261 if(timeout->globals_read_only){
1262 fibril_rwlock_read_lock(&tcp_globals.lock);
[21580dd]1263 }else{
[aadf01e]1264 fibril_rwlock_write_lock(&tcp_globals.lock);
[21580dd]1265 }
1266 // find the pending operation socket
[aadf01e]1267 socket = socket_port_find(&tcp_globals.sockets, timeout->port, timeout->key, timeout->key_length);
1268 if(socket && (socket->socket_id == timeout->socket_id)){
1269 socket_data = (tcp_socket_data_ref) socket->specific_data;
1270 assert(socket_data);
1271 if(socket_data->local_sockets == timeout->local_sockets){
1272 fibril_rwlock_write_lock(socket_data->local_lock);
1273 if(timeout->sequence_number){
[21580dd]1274 // increase the timeout counter;
1275 ++ socket_data->timeout_count;
[aadf01e]1276 if(socket_data->timeout_count == TCP_MAX_TIMEOUTS){
[21580dd]1277 // TODO release as connection lost
[aadf01e]1278 //tcp_refresh_socket_data(socket_data);
[2e99277]1279 }else{
1280 // retransmit
[aadf01e]1281 tcp_retransmit_packet(socket, socket_data, timeout->sequence_number);
[21580dd]1282 }
[aadf01e]1283 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]1284 }else{
[aadf01e]1285 fibril_mutex_lock(&socket_data->operation.mutex);
[21580dd]1286 // set the timeout operation result if state not changed
[aadf01e]1287 if(socket_data->state == timeout->state){
[21580dd]1288 socket_data->operation.result = ETIMEOUT;
1289 // notify the main fibril
[aadf01e]1290 fibril_condvar_signal(&socket_data->operation.condvar);
[21580dd]1291 // keep the global write lock
1292 keep_write_lock = true;
1293 }else{
1294 // operation is ok, do nothing
1295 // unlocking from now on, so the unlock order does not matter...
[aadf01e]1296 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]1297 }
[aadf01e]1298 fibril_mutex_unlock(&socket_data->operation.mutex);
[21580dd]1299 }
1300 }
1301 }
1302 // unlock only if no socket
[aadf01e]1303 if(timeout->globals_read_only){
1304 fibril_rwlock_read_unlock(&tcp_globals.lock);
1305 }else if(! keep_write_lock){
[21580dd]1306 // release if not desired
[aadf01e]1307 fibril_rwlock_write_unlock(&tcp_globals.lock);
[21580dd]1308 }
1309 // release the timeout structure
[aadf01e]1310 free(timeout);
[21580dd]1311 return EOK;
1312}
1313
[aadf01e]1314int tcp_release_after_timeout(void * data){
1315 tcp_timeout_ref timeout = data;
1316 socket_core_ref socket;
1317 tcp_socket_data_ref socket_data;
1318 fibril_rwlock_t * local_lock;
[21580dd]1319
[aadf01e]1320 assert(timeout);
[21580dd]1321
1322 // sleep the given timeout
[aadf01e]1323 async_usleep(timeout->timeout);
[21580dd]1324 // lock the globals
[aadf01e]1325 fibril_rwlock_write_lock(&tcp_globals.lock);
[21580dd]1326 // find the pending operation socket
[aadf01e]1327 socket = socket_port_find(&tcp_globals.sockets, timeout->port, timeout->key, timeout->key_length);
1328 if(socket && (socket->socket_id == timeout->socket_id)){
1329 socket_data = (tcp_socket_data_ref) socket->specific_data;
1330 assert(socket_data);
1331 if(socket_data->local_sockets == timeout->local_sockets){
[21580dd]1332 local_lock = socket_data->local_lock;
[aadf01e]1333 fibril_rwlock_write_lock(local_lock);
1334 socket_destroy(tcp_globals.net_phone, timeout->socket_id, timeout->local_sockets, &tcp_globals.sockets, tcp_free_socket_data);
1335 fibril_rwlock_write_unlock(local_lock);
[21580dd]1336 }
1337 }
1338 // unlock the globals
[aadf01e]1339 fibril_rwlock_write_unlock(&tcp_globals.lock);
[21580dd]1340 // release the timeout structure
[aadf01e]1341 free(timeout);
[21580dd]1342 return EOK;
1343}
1344
[aadf01e]1345void tcp_retransmit_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number){
1346 packet_t packet;
1347 packet_t copy;
1348 size_t data_length;
[21580dd]1349
[aadf01e]1350 assert(socket);
1351 assert(socket_data);
1352 assert(socket->specific_data == socket_data);
[21580dd]1353
1354 // sent packet?
[aadf01e]1355 packet = pq_find(socket_data->outgoing, sequence_number);
1356 printf("retransmit %d\n", packet_get_id(packet));
1357 if(packet){
1358 pq_get_order(packet, NULL, &data_length);
1359 copy = tcp_prepare_copy(socket, socket_data, packet, data_length, sequence_number);
1360 fibril_rwlock_write_unlock(socket_data->local_lock);
1361// printf("r send %d\n", packet_get_id(packet));
1362 if(copy){
1363 tcp_send_packets(socket_data->device_id, copy);
[21580dd]1364 }
1365 }else{
[aadf01e]1366 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]1367 }
1368}
1369
[aadf01e]1370int tcp_listen_message(socket_cores_ref local_sockets, int socket_id, int backlog){
1371 socket_core_ref socket;
1372 tcp_socket_data_ref socket_data;
[21580dd]1373
[aadf01e]1374 assert(local_sockets);
[21580dd]1375
[aadf01e]1376 if(backlog < 0){
1377 return EINVAL;
1378 }
[21580dd]1379 // find the socket
[aadf01e]1380 socket = socket_cores_find(local_sockets, socket_id);
1381 if(! socket){
1382 return ENOTSOCK;
1383 }
[21580dd]1384 // get the socket specific data
[aadf01e]1385 socket_data = (tcp_socket_data_ref) socket->specific_data;
1386 assert(socket_data);
[21580dd]1387 // set the backlog
1388 socket_data->backlog = backlog;
1389 return EOK;
1390}
1391
[aadf01e]1392int tcp_connect_message(socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen){
[21580dd]1393 ERROR_DECLARE;
1394
[aadf01e]1395 socket_core_ref socket;
[21580dd]1396
[aadf01e]1397 assert(local_sockets);
1398 assert(addr);
1399 assert(addrlen > 0);
[21580dd]1400
1401 // find the socket
[aadf01e]1402 socket = socket_cores_find(local_sockets, socket_id);
1403 if(! socket){
1404 return ENOTSOCK;
1405 }
1406 if(ERROR_OCCURRED(tcp_connect_core(socket, local_sockets, addr, addrlen))){
1407 tcp_free_socket_data(socket);
[21580dd]1408 // unbind if bound
[aadf01e]1409 if(socket->port > 0){
1410 socket_ports_exclude(&tcp_globals.sockets, socket->port);
[21580dd]1411 socket->port = 0;
1412 }
1413 }
1414 return ERROR_CODE;
1415}
1416
[aadf01e]1417int tcp_connect_core(socket_core_ref socket, socket_cores_ref local_sockets, struct sockaddr * addr, socklen_t addrlen){
[21580dd]1418 ERROR_DECLARE;
1419
[aadf01e]1420 tcp_socket_data_ref socket_data;
1421 packet_t packet;
[21580dd]1422
[aadf01e]1423 assert(socket);
1424 assert(addr);
1425 assert(addrlen > 0);
[21580dd]1426
1427 // get the socket specific data
[aadf01e]1428 socket_data = (tcp_socket_data_ref) socket->specific_data;
1429 assert(socket_data);
1430 assert(socket->specific_data == socket_data);
1431 if((socket_data->state != TCP_SOCKET_INITIAL)
1432 && ((socket_data->state != TCP_SOCKET_LISTEN) || (socket->port <= 0))){
[21580dd]1433 return EINVAL;
1434 }
1435 // get the destination port
[aadf01e]1436 ERROR_PROPAGATE(tl_get_address_port(addr, addrlen, &socket_data->dest_port));
1437 if(socket->port <= 0){
[21580dd]1438 // try to find a free port
[aadf01e]1439 ERROR_PROPAGATE(socket_bind_free_port(&tcp_globals.sockets, socket, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port));
[21580dd]1440 // set the next port as the search starting port number
1441 tcp_globals.last_used_port = socket->port;
1442 }
[aadf01e]1443 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]1444
1445 // create the notification packet
[aadf01e]1446 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 1, 0));
[21580dd]1447
1448 // unlock the globals and wait for an operation
[aadf01e]1449 fibril_rwlock_write_unlock(&tcp_globals.lock);
[21580dd]1450
1451 socket_data->addr = addr;
1452 socket_data->addrlen = addrlen;
1453 // send the packet
[aadf01e]1454 if(ERROR_OCCURRED(tcp_queue_packet(socket, socket_data, packet, 1))
1455 || ERROR_OCCURRED(tcp_prepare_timeout(tcp_timeout, socket, socket_data, 0, TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false))){
[21580dd]1456 socket_data->addr = NULL;
1457 socket_data->addrlen = 0;
[aadf01e]1458 fibril_rwlock_write_lock(&tcp_globals.lock);
[21580dd]1459 }else{
[aadf01e]1460 packet = tcp_get_packets_to_send(socket, socket_data);
1461 if(packet){
1462 fibril_mutex_lock(&socket_data->operation.mutex);
1463 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]1464 // send the packet
[aadf01e]1465 printf("connecting %d\n", packet_get_id(packet));
1466 tcp_send_packets(socket_data->device_id, packet);
[21580dd]1467 // wait for a reply
[aadf01e]1468 fibril_condvar_wait(&socket_data->operation.condvar, &socket_data->operation.mutex);
[21580dd]1469 ERROR_CODE = socket_data->operation.result;
[aadf01e]1470 if(ERROR_CODE != EOK){
[21580dd]1471 socket_data->addr = NULL;
1472 socket_data->addrlen = 0;
1473 }
1474 }else{
1475 socket_data->addr = NULL;
1476 socket_data->addrlen = 0;
1477 ERROR_CODE = EINTR;
1478 }
1479 }
1480
[aadf01e]1481 fibril_mutex_unlock(&socket_data->operation.mutex);
[21580dd]1482
1483 // return the result
1484 return ERROR_CODE;
1485}
1486
[aadf01e]1487int tcp_queue_prepare_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length){
[21580dd]1488 ERROR_DECLARE;
1489
[aadf01e]1490 tcp_header_ref header;
[21580dd]1491
[aadf01e]1492 assert(socket);
1493 assert(socket_data);
1494 assert(socket->specific_data == socket_data);
[21580dd]1495
1496 // get tcp header
[aadf01e]1497 header = (tcp_header_ref) packet_get_data(packet);
1498 if(! header){
1499 return NO_DATA;
1500 }
1501 header->destination_port = htons(socket_data->dest_port);
1502 header->source_port = htons(socket->port);
1503 header->sequence_number = htonl(socket_data->next_outgoing);
1504 if(ERROR_OCCURRED(packet_set_addr(packet, NULL, (uint8_t *) socket_data->addr, socket_data->addrlen))){
1505 return tcp_release_and_return(packet, EINVAL);
[21580dd]1506 }
1507 // remember the outgoing FIN
[aadf01e]1508 if(header->finalize){
[21580dd]1509 socket_data->fin_outgoing = socket_data->next_outgoing;
1510 }
1511 return EOK;
1512}
1513
[aadf01e]1514int tcp_queue_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length){
[21580dd]1515 ERROR_DECLARE;
1516
[aadf01e]1517 assert(socket);
1518 assert(socket_data);
1519 assert(socket->specific_data == socket_data);
[21580dd]1520
[aadf01e]1521 ERROR_PROPAGATE(tcp_queue_prepare_packet(socket, socket_data, packet, data_length));
[21580dd]1522
[aadf01e]1523 if(ERROR_OCCURRED(pq_add(&socket_data->outgoing, packet, socket_data->next_outgoing, data_length))){
1524 return tcp_release_and_return(packet, ERROR_CODE);
[21580dd]1525 }
1526 socket_data->next_outgoing += data_length;
1527 return EOK;
1528}
1529
[aadf01e]1530packet_t tcp_get_packets_to_send(socket_core_ref socket, tcp_socket_data_ref socket_data){
[21580dd]1531 ERROR_DECLARE;
1532
[aadf01e]1533 packet_t packet;
1534 packet_t copy;
1535 packet_t sending = NULL;
1536 packet_t previous = NULL;
1537 size_t data_length;
[21580dd]1538
[aadf01e]1539 assert(socket);
1540 assert(socket_data);
1541 assert(socket->specific_data == socket_data);
[21580dd]1542
[aadf01e]1543 packet = pq_find(socket_data->outgoing, socket_data->last_outgoing + 1);
1544 while(packet){
1545 pq_get_order(packet, NULL, &data_length);
[21580dd]1546 // send only if fits into the window
1547 // respecting the possible overflow
[aadf01e]1548 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))){
1549 copy = tcp_prepare_copy(socket, socket_data, packet, data_length, socket_data->last_outgoing + 1);
1550 if(! copy){
[21580dd]1551 return sending;
1552 }
[aadf01e]1553 if(! sending){
[21580dd]1554 sending = copy;
1555 }else{
[aadf01e]1556 if(ERROR_OCCURRED(pq_insert_after(previous, copy))){
1557 pq_release(tcp_globals.net_phone, packet_get_id(copy));
[21580dd]1558 return sending;
1559 }
1560 }
1561 previous = copy;
[aadf01e]1562 packet = pq_next(packet);
[21580dd]1563 // overflow occurred ?
[aadf01e]1564 if((! packet) && (socket_data->last_outgoing > socket_data->next_outgoing)){
[21580dd]1565 printf("gpts overflow\n");
1566 // continue from the beginning
1567 packet = socket_data->outgoing;
1568 }
1569 socket_data->last_outgoing += data_length;
1570 }else{
1571 break;
1572 }
1573 }
1574 return sending;
1575}
1576
[aadf01e]1577packet_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]1578 ERROR_DECLARE;
1579
[aadf01e]1580 tcp_header_ref header;
1581 uint32_t checksum;
[21580dd]1582
[aadf01e]1583 assert(socket);
1584 assert(socket_data);
1585 assert(socket->specific_data == socket_data);
[21580dd]1586
1587 // adjust the pseudo header
[aadf01e]1588 if(ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(socket_data->pseudo_header, socket_data->headerlen, packet_get_data_length(packet)))){
1589 pq_release(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]1590 return NULL;
1591 }
1592
1593 // get the header
[aadf01e]1594 header = (tcp_header_ref) packet_get_data(packet);
1595 if(! header){
1596 pq_release(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]1597 return NULL;
1598 }
[aadf01e]1599 assert(ntohl(header->sequence_number) == sequence_number);
[21580dd]1600
1601 // adjust the header
[aadf01e]1602 if(socket_data->next_incoming){
1603 header->acknowledgement_number = htonl(socket_data->next_incoming);
[21580dd]1604 header->acknowledge = 1;
1605 }
[aadf01e]1606 header->window = htons(socket_data->window);
[21580dd]1607
1608 // checksum
1609 header->checksum = 0;
[aadf01e]1610 checksum = compute_checksum(0, socket_data->pseudo_header, socket_data->headerlen);
1611 checksum = compute_checksum(checksum, (uint8_t *) packet_get_data(packet), packet_get_data_length(packet));
1612 header->checksum = htons(flip_checksum(compact_checksum(checksum)));
[21580dd]1613 // prepare the packet
[aadf01e]1614 if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0))
[21580dd]1615 // prepare the timeout
[aadf01e]1616 || ERROR_OCCURRED(tcp_prepare_timeout(tcp_timeout, socket, socket_data, sequence_number, socket_data->state, socket_data->timeout, true))){
1617 pq_release(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]1618 return NULL;
1619 }
1620 return packet;
1621}
1622
[aadf01e]1623packet_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){
1624 packet_t copy;
[21580dd]1625
[aadf01e]1626 assert(socket);
1627 assert(socket_data);
1628 assert(socket->specific_data == socket_data);
[21580dd]1629
1630 // make a copy of the packet
[aadf01e]1631 copy = packet_get_copy(tcp_globals.net_phone, packet);
1632 if(! copy){
1633 return NULL;
1634 }
[21580dd]1635
[aadf01e]1636 return tcp_send_prepare_packet(socket, socket_data, copy, data_length, sequence_number);
[21580dd]1637}
1638
[aadf01e]1639void tcp_send_packets(device_id_t device_id, packet_t packet){
1640 packet_t next;
[21580dd]1641
[aadf01e]1642 while(packet){
1643 next = pq_detach(packet);
1644 ip_send_msg(tcp_globals.ip_phone, device_id, packet, SERVICE_TCP, 0);
[21580dd]1645 packet = next;
1646 }
1647}
1648
[aadf01e]1649void tcp_prepare_operation_header(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize, int finalize){
1650 assert(socket);
1651 assert(socket_data);
1652 assert(socket->specific_data == socket_data);
1653 assert(header);
[21580dd]1654
[aadf01e]1655 bzero(header, sizeof(*header));
1656 header->source_port = htons(socket->port);
1657 header->source_port = htons(socket_data->dest_port);
1658 header->header_length = TCP_COMPUTE_HEADER_LENGTH(sizeof(*header));
[21580dd]1659 header->synchronize = synchronize;
1660 header->finalize = finalize;
1661}
1662
[aadf01e]1663int 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){
1664 tcp_timeout_ref operation_timeout;
1665 fid_t fibril;
[21580dd]1666
[aadf01e]1667 assert(socket);
1668 assert(socket_data);
1669 assert(socket->specific_data == socket_data);
[21580dd]1670
1671 // prepare the timeout with key bundle structure
[aadf01e]1672 operation_timeout = malloc(sizeof(*operation_timeout) + socket->key_length + 1);
1673 if(! operation_timeout){
1674 return ENOMEM;
1675 }
1676 bzero(operation_timeout, sizeof(*operation_timeout));
[21580dd]1677 operation_timeout->globals_read_only = globals_read_only;
1678 operation_timeout->port = socket->port;
1679 operation_timeout->local_sockets = socket_data->local_sockets;
1680 operation_timeout->socket_id = socket->socket_id;
1681 operation_timeout->timeout = timeout;
1682 operation_timeout->sequence_number = sequence_number;
1683 operation_timeout->state = state;
1684
1685 // copy the key
[aadf01e]1686 operation_timeout->key = ((char *) operation_timeout) + sizeof(*operation_timeout);
[21580dd]1687 operation_timeout->key_length = socket->key_length;
[aadf01e]1688 memcpy(operation_timeout->key, socket->key, socket->key_length);
1689 operation_timeout->key[operation_timeout->key_length] = '\0';
[21580dd]1690
1691 // prepare the timeouting thread
[aadf01e]1692 fibril = fibril_create(timeout_function, operation_timeout);
1693 if(! fibril){
1694 free(operation_timeout);
[21580dd]1695 return EPARTY;
1696 }
[aadf01e]1697// fibril_mutex_lock(&socket_data->operation.mutex);
[21580dd]1698 // start the timeouting fibril
[aadf01e]1699 fibril_add_ready(fibril);
[21580dd]1700 //socket_data->state = state;
1701 return EOK;
1702}
1703
[aadf01e]1704int tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){
[21580dd]1705 ERROR_DECLARE;
1706
[aadf01e]1707 socket_core_ref socket;
1708 tcp_socket_data_ref socket_data;
1709 int packet_id;
1710 packet_t packet;
1711 size_t length;
[21580dd]1712
[aadf01e]1713 assert(local_sockets);
[21580dd]1714
1715 // find the socket
[aadf01e]1716 socket = socket_cores_find(local_sockets, socket_id);
1717 if(! socket){
1718 return ENOTSOCK;
1719 }
[21580dd]1720 // get the socket specific data
[aadf01e]1721 if(! socket->specific_data){
1722 return NO_DATA;
1723 }
1724 socket_data = (tcp_socket_data_ref) socket->specific_data;
[21580dd]1725
1726 // check state
[aadf01e]1727 if((socket_data->state != TCP_SOCKET_ESTABLISHED) && (socket_data->state != TCP_SOCKET_CLOSE_WAIT)){
[21580dd]1728 return ENOTCONN;
1729 }
1730
1731 // send the source address if desired
[aadf01e]1732 if(addrlen){
1733 ERROR_PROPAGATE(data_reply(socket_data->addr, socket_data->addrlen));
1734 *addrlen = socket_data->addrlen;
[21580dd]1735 }
1736
1737 // get the next received packet
[aadf01e]1738 packet_id = dyn_fifo_value(&socket->received);
1739 if(packet_id < 0){
1740 return NO_DATA;
1741 }
1742 ERROR_PROPAGATE(packet_translate(tcp_globals.net_phone, &packet, packet_id));
[21580dd]1743
1744 // reply the packets
[aadf01e]1745 ERROR_PROPAGATE(socket_reply_packets(packet, &length));
[21580dd]1746
1747 // release the packet
[aadf01e]1748 dyn_fifo_pop(&socket->received);
1749 pq_release(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]1750 // return the total length
[aadf01e]1751 return (int) length;
[21580dd]1752}
1753
[aadf01e]1754int tcp_send_message(socket_cores_ref local_sockets, int socket_id, int fragments, size_t * data_fragment_size, int flags){
[21580dd]1755 ERROR_DECLARE;
1756
[aadf01e]1757 socket_core_ref socket;
1758 tcp_socket_data_ref socket_data;
1759 packet_dimension_ref packet_dimension;
1760 packet_t packet;
1761 size_t total_length;
1762 tcp_header_ref header;
1763 int index;
1764 int result;
[21580dd]1765
[aadf01e]1766 assert(local_sockets);
1767 assert(data_fragment_size);
[21580dd]1768
1769 // find the socket
[aadf01e]1770 socket = socket_cores_find(local_sockets, socket_id);
1771 if(! socket){
1772 return ENOTSOCK;
1773 }
[21580dd]1774 // get the socket specific data
[aadf01e]1775 if(! socket->specific_data){
1776 return NO_DATA;
1777 }
1778 socket_data = (tcp_socket_data_ref) socket->specific_data;
[21580dd]1779
1780 // check state
[aadf01e]1781 if((socket_data->state != TCP_SOCKET_ESTABLISHED) && (socket_data->state != TCP_SOCKET_CLOSE_WAIT)){
[21580dd]1782 return ENOTCONN;
1783 }
1784
[aadf01e]1785 ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
[21580dd]1786
[aadf01e]1787 *data_fragment_size = ((packet_dimension->content < socket_data->data_fragment_size) ? packet_dimension->content : socket_data->data_fragment_size);
[21580dd]1788
[aadf01e]1789 for(index = 0; index < fragments; ++ index){
[21580dd]1790 // read the data fragment
[aadf01e]1791 result = tl_socket_read_packet_data(tcp_globals.net_phone, &packet, TCP_HEADER_SIZE, packet_dimension, socket_data->addr, socket_data->addrlen);
1792 if(result < 0){
1793 return result;
1794 }
1795 total_length = (size_t) result;
[21580dd]1796 // prefix the tcp header
[aadf01e]1797 header = PACKET_PREFIX(packet, tcp_header_t);
1798 if(! header){
1799 return tcp_release_and_return(packet, ENOMEM);
[21580dd]1800 }
[aadf01e]1801 tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
1802 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 0));
[21580dd]1803 }
1804
1805 // flush packets
[aadf01e]1806 packet = tcp_get_packets_to_send(socket, socket_data);
1807 fibril_rwlock_write_unlock(socket_data->local_lock);
1808 fibril_rwlock_read_unlock(&tcp_globals.lock);
1809 if(packet){
[21580dd]1810 // send the packet
[aadf01e]1811 tcp_send_packets(socket_data->device_id, packet);
[21580dd]1812 }
1813
1814 return EOK;
1815}
1816
[aadf01e]1817int tcp_close_message(socket_cores_ref local_sockets, int socket_id){
[21580dd]1818 ERROR_DECLARE;
1819
[aadf01e]1820 socket_core_ref socket;
1821 tcp_socket_data_ref socket_data;
1822 packet_t packet;
[21580dd]1823
1824 // find the socket
[aadf01e]1825 socket = socket_cores_find(local_sockets, socket_id);
1826 if(! socket){
1827 return ENOTSOCK;
1828 }
[21580dd]1829 // get the socket specific data
[aadf01e]1830 socket_data = (tcp_socket_data_ref) socket->specific_data;
1831 assert(socket_data);
[21580dd]1832
1833 // check state
[aadf01e]1834 switch(socket_data->state){
[21580dd]1835 case TCP_SOCKET_ESTABLISHED:
1836 socket_data->state = TCP_SOCKET_FIN_WAIT_1;
1837 break;
1838 case TCP_SOCKET_CLOSE_WAIT:
1839 socket_data->state = TCP_SOCKET_LAST_ACK;
1840 break;
1841// case TCP_SOCKET_LISTEN:
1842 default:
1843 // just destroy
[aadf01e]1844 if(! ERROR_OCCURRED(socket_destroy(tcp_globals.net_phone, socket_id, local_sockets, &tcp_globals.sockets, tcp_free_socket_data))){
1845 fibril_rwlock_write_unlock(socket_data->local_lock);
1846 fibril_rwlock_write_unlock(&tcp_globals.lock);
[21580dd]1847 }
1848 return ERROR_CODE;
1849 }
1850 // send FIN
1851 // TODO should I wait to complete?
1852
1853 // create the notification packet
[aadf01e]1854 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 0, 1));
[21580dd]1855
1856 // send the packet
[aadf01e]1857 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 1));
[21580dd]1858
1859 // flush packets
[aadf01e]1860 packet = tcp_get_packets_to_send(socket, socket_data);
1861 fibril_rwlock_write_unlock(socket_data->local_lock);
1862 fibril_rwlock_write_unlock(&tcp_globals.lock);
1863 if(packet){
[21580dd]1864 // send the packet
[aadf01e]1865 tcp_send_packets(socket_data->device_id, packet);
[21580dd]1866 }
1867 return EOK;
1868}
1869
[aadf01e]1870int tcp_create_notification_packet(packet_t * packet, socket_core_ref socket, tcp_socket_data_ref socket_data, int synchronize, int finalize){
[21580dd]1871 ERROR_DECLARE;
1872
[aadf01e]1873 packet_dimension_ref packet_dimension;
1874 tcp_header_ref header;
[21580dd]1875
[aadf01e]1876 assert(packet);
[21580dd]1877
1878 // get the device packet dimension
[aadf01e]1879 ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
[21580dd]1880 // get a new packet
[aadf01e]1881 *packet = packet_get_4(tcp_globals.net_phone, TCP_HEADER_SIZE, packet_dimension->addr_len, packet_dimension->prefix, packet_dimension->suffix);
1882 if(! * packet){
1883 return ENOMEM;
1884 }
[21580dd]1885 // allocate space in the packet
[aadf01e]1886 header = PACKET_SUFFIX(*packet, tcp_header_t);
1887 if(! header){
1888 tcp_release_and_return(*packet, ENOMEM);
[21580dd]1889 }
1890
[aadf01e]1891 tcp_prepare_operation_header(socket, socket_data, header, synchronize, finalize);
[21580dd]1892 return EOK;
1893}
1894
[aadf01e]1895int tcp_accept_message(socket_cores_ref local_sockets, int socket_id, int new_socket_id, size_t * data_fragment_size, size_t * addrlen){
[21580dd]1896 ERROR_DECLARE;
1897
[aadf01e]1898 socket_core_ref accepted;
1899 socket_core_ref socket;
1900 tcp_socket_data_ref socket_data;
1901 packet_dimension_ref packet_dimension;
[21580dd]1902
[aadf01e]1903 assert(local_sockets);
1904 assert(data_fragment_size);
1905 assert(addrlen);
[21580dd]1906
1907 // find the socket
[aadf01e]1908 socket = socket_cores_find(local_sockets, socket_id);
1909 if(! socket){
1910 return ENOTSOCK;
1911 }
[21580dd]1912 // get the socket specific data
[aadf01e]1913 socket_data = (tcp_socket_data_ref) socket->specific_data;
1914 assert(socket_data);
[21580dd]1915
1916 // check state
[aadf01e]1917 if(socket_data->state != TCP_SOCKET_LISTEN){
[21580dd]1918 return EINVAL;
1919 }
1920
1921 do{
[aadf01e]1922 socket_id = dyn_fifo_value(&socket->accepted);
1923 if(socket_id < 0){
1924 return ENOTSOCK;
1925 }
[d510c0fe]1926 socket_id *= -1;
[21580dd]1927
[aadf01e]1928 accepted = socket_cores_find(local_sockets, socket_id);
1929 if(! accepted){
1930 return ENOTSOCK;
1931 }
[21580dd]1932 // get the socket specific data
[aadf01e]1933 socket_data = (tcp_socket_data_ref) accepted->specific_data;
1934 assert(socket_data);
[ede63e4]1935 // TODO can it be in another state?
[aadf01e]1936 if(socket_data->state == TCP_SOCKET_ESTABLISHED){
1937 ERROR_PROPAGATE(data_reply(socket_data->addr, socket_data->addrlen));
1938 ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
1939 *addrlen = socket_data->addrlen;
1940 *data_fragment_size = ((packet_dimension->content < socket_data->data_fragment_size) ? packet_dimension->content : socket_data->data_fragment_size);
1941 if(new_socket_id > 0){
1942 ERROR_PROPAGATE(socket_cores_update(local_sockets, accepted->socket_id, new_socket_id));
[ede63e4]1943 accepted->socket_id = new_socket_id;
1944 }
[21580dd]1945 }
[aadf01e]1946 dyn_fifo_pop(&socket->accepted);
1947 }while(socket_data->state != TCP_SOCKET_ESTABLISHED);
1948 printf("ret accept %d\n", accepted->socket_id);
[21580dd]1949 return accepted->socket_id;
1950}
1951
[aadf01e]1952void tcp_free_socket_data(socket_core_ref socket){
1953 tcp_socket_data_ref socket_data;
[21580dd]1954
[aadf01e]1955 assert(socket);
[21580dd]1956
[aadf01e]1957 printf("destroy_socket %d\n", socket->socket_id);
[21580dd]1958
1959 // get the socket specific data
[aadf01e]1960 socket_data = (tcp_socket_data_ref) socket->specific_data;
1961 assert(socket_data);
[21580dd]1962 //free the pseudo header
[aadf01e]1963 if(socket_data->pseudo_header){
1964 if(socket_data->headerlen){
[21580dd]1965 printf("d pseudo\n");
[aadf01e]1966 free(socket_data->pseudo_header);
[21580dd]1967 socket_data->headerlen = 0;
1968 }
1969 socket_data->pseudo_header = NULL;
1970 }
1971 socket_data->headerlen = 0;
1972 // free the address
[aadf01e]1973 if(socket_data->addr){
1974 if(socket_data->addrlen){
[21580dd]1975 printf("d addr\n");
[aadf01e]1976 free(socket_data->addr);
[21580dd]1977 socket_data->addrlen = 0;
1978 }
1979 socket_data->addr = NULL;
1980 }
1981 socket_data->addrlen = 0;
1982}
1983
[aadf01e]1984int tcp_release_and_return(packet_t packet, int result){
1985 pq_release(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]1986 return result;
1987}
1988
1989/** @}
1990 */
Note: See TracBrowser for help on using the repository browser.