source: mainline/uspace/srv/net/tl/tcp/tcp.c@ 3be62bc

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3be62bc was a8a13d0, checked in by Lukas Mejdrech <lukasmejdrech@…>, 15 years ago
  • udp and tcp application phones cleanup fix, * tcp retransmit disabled
  • Property mode set to 100644
File size: 67.1 KB
Line 
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 */
125#define IS_IN_INTERVAL_OVERFLOW(lower, value, higher_equal) ((((lower) < (value)) && (((value) <= (higher_equal)) || ((higher_equal) < (lower)))) || (((value) <= (higher_equal)) && ((higher_equal) < (lower))))
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 */
144 int globals_read_only;
145 /** Socket port.
146 */
147 int port;
148 /** Local sockets.
149 */
150 socket_cores_ref local_sockets;
151 /** Socket identifier.
152 */
153 int socket_id;
154 /** Socket state.
155 */
156 tcp_socket_state_t state;
157 /** Sent packet sequence number.
158 */
159 int sequence_number;
160 /** Timeout in microseconds.
161 */
162 suseconds_t timeout;
163 /** Port map key.
164 */
165 char * key;
166 /** Port map key length.
167 */
168 size_t key_length;
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 */
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);
210
211/** TCP global data.
212 */
213tcp_globals_t tcp_globals;
214
215int tcp_initialize(async_client_conn_t client_connection){
216 ERROR_DECLARE;
217
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){
224 return tcp_globals.ip_phone;
225 }
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);
229 return ERROR_CODE;
230 }
231 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
232 fibril_rwlock_write_unlock(&tcp_globals.lock);
233 return EOK;
234}
235
236int tcp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
237 ERROR_DECLARE;
238
239 if(receiver != SERVICE_TCP){
240 return EREFUSED;
241 }
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);
247
248 return ERROR_CODE;
249}
250
251int tcp_process_packet(device_id_t device_id, packet_t packet, services_t error){
252 ERROR_DECLARE;
253
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){
273 case SERVICE_ICMP:
274 // process error
275 result = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
276 if(result < 0){
277 return tcp_release_and_return(packet, result);
278 }
279 length = (size_t) result;
280 if(ERROR_OCCURRED(packet_trim(packet, length, 0))){
281 return tcp_release_and_return(packet, ERROR_CODE);
282 }
283 break;
284 default:
285 return tcp_release_and_return(packet, ENOTSUP);
286 }
287 }
288
289 // TODO process received ipopts?
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);
294 }
295 offset = (size_t) result;
296
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);
301 }
302 if(length < TCP_HEADER_SIZE + offset){
303 return tcp_release_and_return(packet, NO_DATA);
304 }
305
306 // trim all but TCP header
307 if(ERROR_OCCURRED(packet_trim(packet, offset, 0))){
308 return tcp_release_and_return(packet, ERROR_CODE);
309 }
310
311 // get tcp header
312 header = (tcp_header_ref) packet_get_data(packet);
313 if(! header){
314 return tcp_release_and_return(packet, NO_DATA);
315 }
316// printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header), ntohs(header->destination_port));
317
318 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
319 if(result <= 0){
320 return tcp_release_and_return(packet, result);
321 }
322 addrlen = (size_t) result;
323
324 if(ERROR_OCCURRED(tl_set_address_port(src, addrlen, ntohs(header->source_port)))){
325 return tcp_release_and_return(packet, ERROR_CODE);
326 }
327
328 // find the destination socket
329 socket = socket_port_find(&tcp_globals.sockets, ntohs(header->destination_port), (const char *) src, addrlen);
330 if(! socket){
331// printf("listening?\n");
332 // find the listening destination socket
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);
337 }
338 return EADDRNOTAVAIL;
339 }
340 }
341 printf("socket id %d\n", socket->socket_id);
342 socket_data = (tcp_socket_data_ref) socket->specific_data;
343 assert(socket_data);
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;
355 length = packet_get_data_length(next_packet);
356 if(length <= 0){
357 return tcp_release_and_return(packet, NO_DATA);
358 }
359 total_length += length;
360 // add partial checksum if set
361 if(! error){
362 checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet));
363 }
364 }while((next_packet = pq_next(next_packet)));
365// printf("fragments %d of %d bytes\n", fragments, total_length);
366
367// printf("lock?\n");
368 fibril_rwlock_write_lock(socket_data->local_lock);
369// printf("locked\n");
370 if(! error){
371 if(socket_data->state == TCP_SOCKET_LISTEN){
372 if(socket_data->pseudo_header){
373 free(socket_data->pseudo_header);
374 socket_data->pseudo_header = NULL;
375 socket_data->headerlen = 0;
376 }
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);
380 }
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);
384 }
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))){
390 // checksum error ICMP
391 icmp_parameter_problem_msg(tcp_globals.icmp_phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->checksum)) - ((size_t) ((void *) header)), packet);
392 }
393 return EINVAL;
394 }
395 }
396
397 fibril_rwlock_read_unlock(&tcp_globals.lock);
398
399 // TODO error reporting/handling
400// printf("st %d\n", socket_data->state);
401 switch(socket_data->state){
402 case TCP_SOCKET_LISTEN:
403 ERROR_CODE = tcp_process_listen(socket, socket_data, header, packet, src, dest, addrlen);
404 break;
405 case TCP_SOCKET_SYN_RECEIVED:
406 ERROR_CODE = tcp_process_syn_received(socket, socket_data, header, packet);
407 break;
408 case TCP_SOCKET_SYN_SENT:
409 ERROR_CODE = tcp_process_syn_sent(socket, socket_data, header, packet);
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:
420 ERROR_CODE = tcp_process_established(socket, socket_data, header, packet, fragments, total_length);
421 break;
422 default:
423 pq_release(tcp_globals.net_phone, packet_get_id(packet));
424 }
425
426 if(ERROR_CODE != EOK){
427 printf("process %d\n", ERROR_CODE);
428 fibril_rwlock_write_unlock(socket_data->local_lock);
429 }
430 return EOK;
431}
432
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){
434 ERROR_DECLARE;
435
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);
452 old_incoming = socket_data->next_incoming;
453
454 if(header->finalize){
455 socket_data->fin_incoming = new_sequence_number;
456 }
457
458// printf("pe %d < %d <= %d\n", new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length);
459 // trim begining if containing expected data
460 if(IS_IN_INTERVAL_OVERFLOW(new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length)){
461 // get the acknowledged offset
462 if(socket_data->next_incoming < new_sequence_number){
463 offset = new_sequence_number - socket_data->next_incoming;
464 }else{
465 offset = socket_data->next_incoming - new_sequence_number;
466 }
467// printf("offset %d\n", offset);
468 new_sequence_number += offset;
469 total_length -= offset;
470 length = packet_get_data_length(packet);
471 // trim the acknowledged data
472 while(length <= offset){
473 // release the acknowledged packets
474 next_packet = pq_next(packet);
475 pq_release(tcp_globals.net_phone, packet_get_id(packet));
476 packet = next_packet;
477 offset -= length;
478 length = packet_get_data_length(packet);
479 }
480 if((offset > 0)
481 && (ERROR_OCCURRED(packet_trim(packet, offset, 0)))){
482 return tcp_release_and_return(packet, ERROR_CODE);
483 }
484 assert(new_sequence_number == socket_data->next_incoming);
485 }
486
487 // release if overflowing the window
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);
490// }
491
492/*
493 // trim end if overflowing the window
494 if(IS_IN_INTERVAL_OVERFLOW(new_sequence_number, socket_data->next_incoming + socket_data->window, new_sequence_number + total_length)){
495 // get the allowed data length
496 if(socket_data->next_incoming + socket_data->window < new_sequence_number){
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
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);
509 }
510 offset -= length;
511 total_length -= length - offset;
512 }
513 // release the overflowing packets
514 next_packet = pq_next(next_packet);
515 if(next_packet){
516 tmp_packet = next_packet;
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));
520 }
521 assert(new_sequence_number + total_length == socket_data->next_incoming + socket_data->window);
522 }
523*/
524 // the expected one arrived?
525 if(new_sequence_number == socket_data->next_incoming){
526 printf("expected\n");
527 // process acknowledgement
528 tcp_process_acknowledgement(socket, socket_data, header);
529
530 // remove the header
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);
534 }
535
536 if(total_length){
537 ERROR_PROPAGATE(tcp_queue_received_packet(socket, socket_data, packet, fragments, total_length));
538 }else{
539 total_length = 1;
540 }
541 socket_data->next_incoming = old_incoming + total_length;
542 packet = socket_data->incoming;
543 while(packet){
544 if(ERROR_OCCURRED(pq_get_order(socket_data->incoming, &order, NULL))){
545 // remove the corrupted packet
546 next_packet = pq_detach(packet);
547 if(packet == socket_data->incoming){
548 socket_data->incoming = next_packet;
549 }
550 pq_release(tcp_globals.net_phone, packet_get_id(packet));
551 packet = next_packet;
552 continue;
553 }
554 sequence_number = (uint32_t) order;
555 if(IS_IN_INTERVAL_OVERFLOW(sequence_number, old_incoming, socket_data->next_incoming)){
556 // move to the next
557 packet = pq_next(packet);
558 // coninual data?
559 }else if(IS_IN_INTERVAL_OVERFLOW(old_incoming, sequence_number, socket_data->next_incoming)){
560 // detach the packet
561 next_packet = pq_detach(packet);
562 if(packet == socket_data->incoming){
563 socket_data->incoming = next_packet;
564 }
565 // get data length
566 length = packet_get_data_length(packet);
567 new_sequence_number = sequence_number + length;
568 if(length <= 0){
569 // remove the empty packet
570 pq_release(tcp_globals.net_phone, packet_get_id(packet));
571 packet = next_packet;
572 continue;
573 }
574 // exactly following
575 if(sequence_number == socket_data->next_incoming){
576 // queue received data
577 ERROR_PROPAGATE(tcp_queue_received_packet(socket, socket_data, packet, 1, packet_get_data_length(packet)));
578 socket_data->next_incoming = new_sequence_number;
579 packet = next_packet;
580 continue;
581 // at least partly following data?
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){
584 length = new_sequence_number - socket_data->next_incoming;
585 }else{
586 length = socket_data->next_incoming - new_sequence_number;
587 }
588 if(! ERROR_OCCURRED(packet_trim(packet, length, 0))){
589 // queue received data
590 ERROR_PROPAGATE(tcp_queue_received_packet(socket, socket_data, packet, 1, packet_get_data_length(packet)));
591 socket_data->next_incoming = new_sequence_number;
592 packet = next_packet;
593 continue;
594 }
595 }
596 // remove the duplicit or corrupted packet
597 pq_release(tcp_globals.net_phone, packet_get_id(packet));
598 packet = next_packet;
599 continue;
600 }else{
601 break;
602 }
603 }
604 }else if(IS_IN_INTERVAL(socket_data->next_incoming, new_sequence_number, socket_data->next_incoming + socket_data->window)){
605 printf("in window\n");
606 // process acknowledgement
607 tcp_process_acknowledgement(socket, socket_data, header);
608
609 // remove the header
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);
613 }
614
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))){
618 // remove the corrupted packets
619 pq_release(tcp_globals.net_phone, packet_get_id(packet));
620 pq_release(tcp_globals.net_phone, packet_get_id(next_packet));
621 }else{
622 while(next_packet){
623 new_sequence_number += length;
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));
629 }
630 next_packet = tmp_packet;
631 }
632 }
633 }else{
634 printf("unexpected\n");
635 // release duplicite or restricted
636 pq_release(tcp_globals.net_phone, packet_get_id(packet));
637 }
638
639 // change state according to the acknowledging incoming fin
640 if(IS_IN_INTERVAL_OVERFLOW(old_incoming, socket_data->fin_incoming, socket_data->next_incoming)){
641 switch(socket_data->state){
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
654 packet = tcp_get_packets_to_send(socket, socket_data);
655 if(! packet){
656 // create the notification packet
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);
660 }
661 fibril_rwlock_write_unlock(socket_data->local_lock);
662 // send the packet
663 tcp_send_packets(socket_data->device_id, packet);
664 return EOK;
665}
666
667int tcp_queue_received_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, int fragments, size_t total_length){
668 ERROR_DECLARE;
669
670 packet_dimension_ref packet_dimension;
671
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);
678
679 // queue the received packet
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);
683 }
684
685 // decrease the window size
686 socket_data->window -= total_length;
687
688 // notify the destination socket
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);
690 return EOK;
691}
692
693int tcp_process_syn_sent(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet){
694 ERROR_DECLARE;
695
696 packet_t next_packet;
697
698 assert(socket);
699 assert(socket_data);
700 assert(socket->specific_data == socket_data);
701 assert(header);
702 assert(packet);
703
704 if(header->synchronize){
705 // process acknowledgement
706 tcp_process_acknowledgement(socket, socket_data, header);
707
708 socket_data->next_incoming = ntohl(header->sequence_number) + 1;
709 // release additional packets
710 next_packet = pq_detach(packet);
711 if(next_packet){
712 pq_release(tcp_globals.net_phone, packet_get_id(next_packet));
713 }
714 // trim if longer than the header
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);
718 }
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){
723 socket_data->state = TCP_SOCKET_ESTABLISHED;
724 packet = tcp_get_packets_to_send(socket, socket_data);
725 if(packet){
726 fibril_rwlock_write_unlock(socket_data->local_lock);
727 // send the packet
728 tcp_send_packets(socket_data->device_id, packet);
729 // signal the result
730 fibril_condvar_signal(&socket_data->operation.condvar);
731 fibril_mutex_unlock(&socket_data->operation.mutex);
732 return EOK;
733 }
734 }
735 fibril_mutex_unlock(&socket_data->operation.mutex);
736 }
737 return tcp_release_and_return(packet, EINVAL);
738}
739
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){
741 ERROR_DECLARE;
742
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);
761 }else{
762 tcp_initialize_socket_data(socket_data);
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
767 socket_data->next_incoming = ntohl(header->sequence_number);
768 socket_data->treshold = socket_data->next_incoming + ntohs(header->window);
769
770 socket_data->addrlen = addrlen;
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);
775 }
776 memcpy(socket_data->addr, src, socket_data->addrlen);
777
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));
783 return ERROR_CODE;
784 }
785
786// printf("addr %p\n", socket_data->addr, socket_data->addrlen);
787 // create a socket
788 socket_id = -1;
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);
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
801 fibril_rwlock_write_unlock(socket_data->local_lock);
802// printf("list lg\n");
803 fibril_rwlock_write_lock(&tcp_globals.lock);
804// printf("list locked\n");
805 // find the destination socket
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);
809 // a shadow may remain until app hangs up
810 return tcp_release_and_return(packet, EOK/*ENOTSOCK*/);
811 }
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);
815
816// printf("list ll\n");
817 fibril_rwlock_write_lock(listening_socket_data->local_lock);
818// printf("list locked\n");
819
820 socket = socket_cores_find(listening_socket_data->local_sockets, socket_id);
821 if(! socket){
822 // where is the socket?!?
823 fibril_rwlock_write_unlock(&tcp_globals.lock);
824 return ENOTSOCK;
825 }
826 socket_data = (tcp_socket_data_ref) socket->specific_data;
827 assert(socket_data);
828
829// uint8_t * data = socket_data->addr;
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]);
831
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);
835 //tcp_globals.last_used_port = socket->port;
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);
841 }
842
843 socket_data->state = TCP_SOCKET_LISTEN;
844 socket_data->next_incoming = ntohl(header->sequence_number) + 1;
845 // release additional packets
846 next_packet = pq_detach(packet);
847 if(next_packet){
848 pq_release(tcp_globals.net_phone, packet_get_id(next_packet));
849 }
850 // trim if longer than the header
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);
855 }
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);
859 return ERROR_CODE;
860 }
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);
865 return EINVAL;
866 }else{
867 socket_data->state = TCP_SOCKET_SYN_RECEIVED;
868// printf("unlock\n");
869 fibril_rwlock_write_unlock(socket_data->local_lock);
870 // send the packet
871 tcp_send_packets(socket_data->device_id, packet);
872 return EOK;
873 }
874 }
875 }
876 return tcp_release_and_return(packet, EINVAL);
877}
878
879int tcp_process_syn_received(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet){
880 ERROR_DECLARE;
881
882 socket_core_ref listening_socket;
883 tcp_socket_data_ref listening_socket_data;
884
885 assert(socket);
886 assert(socket_data);
887 assert(socket->specific_data == socket_data);
888 assert(header);
889 assert(packet);
890
891 printf("syn_rec\n");
892 if(header->acknowledge){
893 // process acknowledgement
894 tcp_process_acknowledgement(socket, socket_data, header);
895
896 socket_data->next_incoming = ntohl(header->sequence_number);// + 1;
897 pq_release(tcp_globals.net_phone, packet_get_id(packet));
898 socket_data->state = TCP_SOCKET_ESTABLISHED;
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);
903
904 // queue the received packet
905 if(! ERROR_OCCURRED(dyn_fifo_push(&listening_socket->accepted, (-1 * socket->socket_id), listening_socket_data->backlog))){
906 // notify the destination socket
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);
909 return EOK;
910 }
911 }
912 // send FIN
913 socket_data->state = TCP_SOCKET_FIN_WAIT_1;
914
915 // create the notification packet
916 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 0, 1));
917
918 // send the packet
919 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 1));
920
921 // flush packets
922 packet = tcp_get_packets_to_send(socket, socket_data);
923 fibril_rwlock_write_unlock(socket_data->local_lock);
924 if(packet){
925 // send the packet
926 tcp_send_packets(socket_data->device_id, packet);
927 }
928 return EOK;
929 }else{
930 return tcp_release_and_return(packet, EINVAL);
931 }
932 return EINVAL;
933}
934
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);
950 // if more data acknowledged
951 if(number != socket_data->expected){
952 old = socket_data->expected;
953 if(IS_IN_INTERVAL_OVERFLOW(old, socket_data->fin_outgoing, number)){
954 switch(socket_data->state){
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
961 tcp_prepare_timeout(tcp_release_after_timeout, socket, socket_data, 0, TCP_SOCKET_TIME_WAIT, NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT, true);
962 break;
963 default:
964 break;
965 }
966 }
967 // update the treshold if higher than set
968 if(number + ntohs(header->window) > socket_data->expected + socket_data->treshold){
969 socket_data->treshold = number + ntohs(header->window) - socket_data->expected;
970 }
971 // set new expected sequence number
972 socket_data->expected = number;
973 socket_data->expected_count = 1;
974 packet = socket_data->outgoing;
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){
979 socket_data->outgoing = next;
980 }
981 // add to acknowledged or release
982 if(pq_add(&acknowledged, packet, 0, 0) != EOK){
983 pq_release(tcp_globals.net_phone, packet_get_id(packet));
984 }
985 packet = next;
986 }else if(old < socket_data->expected){
987 break;
988 }
989 }
990 // release acknowledged
991 if(acknowledged){
992 pq_release(tcp_globals.net_phone, packet_get_id(acknowledged));
993 }
994 return;
995 // if the same as the previous time
996 }else if(number == socket_data->expected){
997 // increase the counter
998 ++ socket_data->expected_count;
999 if(socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT){
1000 socket_data->expected_count = 1;
1001 // TODO retransmit lock
1002 //tcp_retransmit_packet(socket, socket_data, number);
1003 }
1004 }
1005 }
1006}
1007
1008int tcp_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
1009 ERROR_DECLARE;
1010
1011 packet_t packet;
1012
1013 assert(call);
1014 assert(answer);
1015 assert(answer_count);
1016
1017 *answer_count = 0;
1018 switch(IPC_GET_METHOD(*call)){
1019 case NET_TL_RECEIVED:
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));
1023 }
1024 //fibril_rwlock_read_unlock(&tcp_globals.lock);
1025 return ERROR_CODE;
1026 case IPC_M_CONNECT_TO_ME:
1027 return tcp_process_client_messages(callid, * call);
1028 }
1029 return ENOTSUP;
1030}
1031
1032void tcp_refresh_socket_data(tcp_socket_data_ref socket_data){
1033 assert(socket_data);
1034
1035 bzero(socket_data, sizeof(*socket_data));
1036 socket_data->state = TCP_SOCKET_INITIAL;
1037 socket_data->device_id = DEVICE_INVALID_ID;
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
1047void tcp_initialize_socket_data(tcp_socket_data_ref socket_data){
1048 assert(socket_data);
1049
1050 tcp_refresh_socket_data(socket_data);
1051 fibril_mutex_initialize(&socket_data->operation.mutex);
1052 fibril_condvar_initialize(&socket_data->operation.condvar);
1053 socket_data->data_fragment_size = MAX_TCP_FRAGMENT_SIZE;
1054}
1055
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;
1069
1070 /*
1071 * Accept the connection
1072 * - Answer the first IPC_M_CONNECT_ME_TO call.
1073 */
1074 res = EOK;
1075 answer_count = 0;
1076
1077 socket_cores_initialize(&local_sockets);
1078 fibril_rwlock_initialize(&lock);
1079
1080 while(keep_on_going){
1081
1082 // answer the call
1083 answer_call(callid, res, &answer, answer_count);
1084
1085 // refresh data
1086 refresh_answer(&answer, &answer_count);
1087
1088 // get the next call
1089 callid = async_get_call(&call);
1090
1091 // process the call
1092 switch(IPC_GET_METHOD(call)){
1093 case IPC_M_PHONE_HUNGUP:
1094 keep_on_going = false;
1095 res = EHANGUP;
1096 break;
1097 case NET_SOCKET:
1098 socket_data = (tcp_socket_data_ref) malloc(sizeof(*socket_data));
1099 if(! socket_data){
1100 res = ENOMEM;
1101 }else{
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);
1112 }
1113// *SOCKET_SET_DATA_FRAGMENT_SIZE(answer) = MAX_TCP_FRAGMENT_SIZE;
1114 *SOCKET_SET_HEADER_SIZE(answer) = TCP_HEADER_SIZE;
1115 answer_count = 3;
1116 }else{
1117 free(socket_data);
1118 }
1119 }
1120 break;
1121 case NET_SOCKET_BIND:
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);
1132 socket_data->state = TCP_SOCKET_LISTEN;
1133 }
1134 }
1135 fibril_rwlock_write_unlock(&lock);
1136 fibril_rwlock_write_unlock(&tcp_globals.lock);
1137 free(addr);
1138 }
1139 break;
1140 case NET_SOCKET_LISTEN:
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);
1148 break;
1149 case NET_SOCKET_CONNECT:
1150 res = data_receive((void **) &addr, &addrlen);
1151 if(res == EOK){
1152 // the global lock may be released in the tcp_connect_message() function
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);
1160 }
1161 }
1162 break;
1163 case NET_SOCKET_ACCEPT:
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;
1172 answer_count = 3;
1173 }
1174 break;
1175 case NET_SOCKET_SEND:
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);
1182 }else{
1183 answer_count = 2;
1184 }
1185 break;
1186 case NET_SOCKET_SENDTO:
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);
1195 }else{
1196 answer_count = 2;
1197 }
1198 free(addr);
1199 }
1200 break;
1201 case NET_SOCKET_RECV:
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;
1209 answer_count = 1;
1210 res = EOK;
1211 }
1212 break;
1213 case NET_SOCKET_RECVFROM:
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;
1222 answer_count = 3;
1223 res = EOK;
1224 }
1225 break;
1226 case NET_SOCKET_CLOSE:
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);
1233 }
1234 break;
1235 case NET_SOCKET_GETSOCKOPT:
1236 case NET_SOCKET_SETSOCKOPT:
1237 default:
1238 res = ENOTSUP;
1239 break;
1240 }
1241 }
1242
1243 // release the application phone
1244 ipc_hangup(app_phone);
1245
1246 printf("release\n");
1247 // release all local sockets
1248 socket_cores_release(tcp_globals.net_phone, &local_sockets, &tcp_globals.sockets, tcp_free_socket_data);
1249
1250 return EOK;
1251}
1252
1253int tcp_timeout(void * data){
1254 tcp_timeout_ref timeout = data;
1255 int keep_write_lock = false;
1256 socket_core_ref socket;
1257 tcp_socket_data_ref socket_data;
1258
1259 assert(timeout);
1260
1261 // sleep the given timeout
1262 async_usleep(timeout->timeout);
1263 // lock the globals
1264 if(timeout->globals_read_only){
1265 fibril_rwlock_read_lock(&tcp_globals.lock);
1266 }else{
1267 fibril_rwlock_write_lock(&tcp_globals.lock);
1268 }
1269 // find the pending operation socket
1270 socket = socket_port_find(&tcp_globals.sockets, timeout->port, timeout->key, timeout->key_length);
1271 if(socket && (socket->socket_id == timeout->socket_id)){
1272 socket_data = (tcp_socket_data_ref) socket->specific_data;
1273 assert(socket_data);
1274 if(socket_data->local_sockets == timeout->local_sockets){
1275 fibril_rwlock_write_lock(socket_data->local_lock);
1276 if(timeout->sequence_number){
1277 // increase the timeout counter;
1278 ++ socket_data->timeout_count;
1279 if(socket_data->timeout_count == TCP_MAX_TIMEOUTS){
1280 // TODO release as connection lost
1281 //tcp_refresh_socket_data(socket_data);
1282 fibril_rwlock_write_unlock(socket_data->local_lock);
1283 }else{
1284 // retransmit
1285// tcp_retransmit_packet(socket, socket_data, timeout->sequence_number);
1286 fibril_rwlock_write_unlock(socket_data->local_lock);
1287 }
1288 }else{
1289 fibril_mutex_lock(&socket_data->operation.mutex);
1290 // set the timeout operation result if state not changed
1291 if(socket_data->state == timeout->state){
1292 socket_data->operation.result = ETIMEOUT;
1293 // notify the main fibril
1294 fibril_condvar_signal(&socket_data->operation.condvar);
1295 // keep the global write lock
1296 keep_write_lock = true;
1297 }else{
1298 // operation is ok, do nothing
1299 // unlocking from now on, so the unlock order does not matter...
1300 fibril_rwlock_write_unlock(socket_data->local_lock);
1301 }
1302 fibril_mutex_unlock(&socket_data->operation.mutex);
1303 }
1304 }
1305 }
1306 // unlock only if no socket
1307 if(timeout->globals_read_only){
1308 fibril_rwlock_read_unlock(&tcp_globals.lock);
1309 }else if(! keep_write_lock){
1310 // release if not desired
1311 fibril_rwlock_write_unlock(&tcp_globals.lock);
1312 }
1313 // release the timeout structure
1314 free(timeout);
1315 return EOK;
1316}
1317
1318int tcp_release_after_timeout(void * data){
1319 tcp_timeout_ref timeout = data;
1320 socket_core_ref socket;
1321 tcp_socket_data_ref socket_data;
1322 fibril_rwlock_t * local_lock;
1323
1324 assert(timeout);
1325
1326 // sleep the given timeout
1327 async_usleep(timeout->timeout);
1328 // lock the globals
1329 fibril_rwlock_write_lock(&tcp_globals.lock);
1330 // find the pending operation socket
1331 socket = socket_port_find(&tcp_globals.sockets, timeout->port, timeout->key, timeout->key_length);
1332 if(socket && (socket->socket_id == timeout->socket_id)){
1333 socket_data = (tcp_socket_data_ref) socket->specific_data;
1334 assert(socket_data);
1335 if(socket_data->local_sockets == timeout->local_sockets){
1336 local_lock = socket_data->local_lock;
1337 fibril_rwlock_write_lock(local_lock);
1338 socket_destroy(tcp_globals.net_phone, timeout->socket_id, timeout->local_sockets, &tcp_globals.sockets, tcp_free_socket_data);
1339 fibril_rwlock_write_unlock(local_lock);
1340 }
1341 }
1342 // unlock the globals
1343 fibril_rwlock_write_unlock(&tcp_globals.lock);
1344 // release the timeout structure
1345 free(timeout);
1346 return EOK;
1347}
1348
1349void tcp_retransmit_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number){
1350 packet_t packet;
1351 packet_t copy;
1352 size_t data_length;
1353
1354 assert(socket);
1355 assert(socket_data);
1356 assert(socket->specific_data == socket_data);
1357
1358 // sent packet?
1359 packet = pq_find(socket_data->outgoing, sequence_number);
1360 printf("retransmit %d\n", packet_get_id(packet));
1361 if(packet){
1362 pq_get_order(packet, NULL, &data_length);
1363 copy = tcp_prepare_copy(socket, socket_data, packet, data_length, sequence_number);
1364 fibril_rwlock_write_unlock(socket_data->local_lock);
1365// printf("r send %d\n", packet_get_id(packet));
1366 if(copy){
1367 tcp_send_packets(socket_data->device_id, copy);
1368 }
1369 }else{
1370 fibril_rwlock_write_unlock(socket_data->local_lock);
1371 }
1372}
1373
1374int tcp_listen_message(socket_cores_ref local_sockets, int socket_id, int backlog){
1375 socket_core_ref socket;
1376 tcp_socket_data_ref socket_data;
1377
1378 assert(local_sockets);
1379
1380 if(backlog < 0){
1381 return EINVAL;
1382 }
1383 // find the socket
1384 socket = socket_cores_find(local_sockets, socket_id);
1385 if(! socket){
1386 return ENOTSOCK;
1387 }
1388 // get the socket specific data
1389 socket_data = (tcp_socket_data_ref) socket->specific_data;
1390 assert(socket_data);
1391 // set the backlog
1392 socket_data->backlog = backlog;
1393 return EOK;
1394}
1395
1396int tcp_connect_message(socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen){
1397 ERROR_DECLARE;
1398
1399 socket_core_ref socket;
1400
1401 assert(local_sockets);
1402 assert(addr);
1403 assert(addrlen > 0);
1404
1405 // find the socket
1406 socket = socket_cores_find(local_sockets, socket_id);
1407 if(! socket){
1408 return ENOTSOCK;
1409 }
1410 if(ERROR_OCCURRED(tcp_connect_core(socket, local_sockets, addr, addrlen))){
1411 tcp_free_socket_data(socket);
1412 // unbind if bound
1413 if(socket->port > 0){
1414 socket_ports_exclude(&tcp_globals.sockets, socket->port);
1415 socket->port = 0;
1416 }
1417 }
1418 return ERROR_CODE;
1419}
1420
1421int tcp_connect_core(socket_core_ref socket, socket_cores_ref local_sockets, struct sockaddr * addr, socklen_t addrlen){
1422 ERROR_DECLARE;
1423
1424 tcp_socket_data_ref socket_data;
1425 packet_t packet;
1426
1427 assert(socket);
1428 assert(addr);
1429 assert(addrlen > 0);
1430
1431 // get the socket specific data
1432 socket_data = (tcp_socket_data_ref) socket->specific_data;
1433 assert(socket_data);
1434 assert(socket->specific_data == socket_data);
1435 if((socket_data->state != TCP_SOCKET_INITIAL)
1436 && ((socket_data->state != TCP_SOCKET_LISTEN) || (socket->port <= 0))){
1437 return EINVAL;
1438 }
1439 // get the destination port
1440 ERROR_PROPAGATE(tl_get_address_port(addr, addrlen, &socket_data->dest_port));
1441 if(socket->port <= 0){
1442 // try to find a free port
1443 ERROR_PROPAGATE(socket_bind_free_port(&tcp_globals.sockets, socket, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port));
1444 // set the next port as the search starting port number
1445 tcp_globals.last_used_port = socket->port;
1446 }
1447 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));
1448
1449 // create the notification packet
1450 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 1, 0));
1451
1452 // unlock the globals and wait for an operation
1453 fibril_rwlock_write_unlock(&tcp_globals.lock);
1454
1455 socket_data->addr = addr;
1456 socket_data->addrlen = addrlen;
1457 // send the packet
1458 if(ERROR_OCCURRED(tcp_queue_packet(socket, socket_data, packet, 1))
1459 || ERROR_OCCURRED(tcp_prepare_timeout(tcp_timeout, socket, socket_data, 0, TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false))){
1460 socket_data->addr = NULL;
1461 socket_data->addrlen = 0;
1462 fibril_rwlock_write_lock(&tcp_globals.lock);
1463 }else{
1464 packet = tcp_get_packets_to_send(socket, socket_data);
1465 if(packet){
1466 fibril_mutex_lock(&socket_data->operation.mutex);
1467 fibril_rwlock_write_unlock(socket_data->local_lock);
1468 // send the packet
1469 printf("connecting %d\n", packet_get_id(packet));
1470 tcp_send_packets(socket_data->device_id, packet);
1471 // wait for a reply
1472 fibril_condvar_wait(&socket_data->operation.condvar, &socket_data->operation.mutex);
1473 ERROR_CODE = socket_data->operation.result;
1474 if(ERROR_CODE != EOK){
1475 socket_data->addr = NULL;
1476 socket_data->addrlen = 0;
1477 }
1478 }else{
1479 socket_data->addr = NULL;
1480 socket_data->addrlen = 0;
1481 ERROR_CODE = EINTR;
1482 }
1483 }
1484
1485 fibril_mutex_unlock(&socket_data->operation.mutex);
1486
1487 // return the result
1488 return ERROR_CODE;
1489}
1490
1491int tcp_queue_prepare_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length){
1492 ERROR_DECLARE;
1493
1494 tcp_header_ref header;
1495
1496 assert(socket);
1497 assert(socket_data);
1498 assert(socket->specific_data == socket_data);
1499
1500 // get tcp header
1501 header = (tcp_header_ref) packet_get_data(packet);
1502 if(! header){
1503 return NO_DATA;
1504 }
1505 header->destination_port = htons(socket_data->dest_port);
1506 header->source_port = htons(socket->port);
1507 header->sequence_number = htonl(socket_data->next_outgoing);
1508 if(ERROR_OCCURRED(packet_set_addr(packet, NULL, (uint8_t *) socket_data->addr, socket_data->addrlen))){
1509 return tcp_release_and_return(packet, EINVAL);
1510 }
1511 // remember the outgoing FIN
1512 if(header->finalize){
1513 socket_data->fin_outgoing = socket_data->next_outgoing;
1514 }
1515 return EOK;
1516}
1517
1518int tcp_queue_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length){
1519 ERROR_DECLARE;
1520
1521 assert(socket);
1522 assert(socket_data);
1523 assert(socket->specific_data == socket_data);
1524
1525 ERROR_PROPAGATE(tcp_queue_prepare_packet(socket, socket_data, packet, data_length));
1526
1527 if(ERROR_OCCURRED(pq_add(&socket_data->outgoing, packet, socket_data->next_outgoing, data_length))){
1528 return tcp_release_and_return(packet, ERROR_CODE);
1529 }
1530 socket_data->next_outgoing += data_length;
1531 return EOK;
1532}
1533
1534packet_t tcp_get_packets_to_send(socket_core_ref socket, tcp_socket_data_ref socket_data){
1535 ERROR_DECLARE;
1536
1537 packet_t packet;
1538 packet_t copy;
1539 packet_t sending = NULL;
1540 packet_t previous = NULL;
1541 size_t data_length;
1542
1543 assert(socket);
1544 assert(socket_data);
1545 assert(socket->specific_data == socket_data);
1546
1547 packet = pq_find(socket_data->outgoing, socket_data->last_outgoing + 1);
1548 while(packet){
1549 pq_get_order(packet, NULL, &data_length);
1550 // send only if fits into the window
1551 // respecting the possible overflow
1552 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))){
1553 copy = tcp_prepare_copy(socket, socket_data, packet, data_length, socket_data->last_outgoing + 1);
1554 if(! copy){
1555 return sending;
1556 }
1557 if(! sending){
1558 sending = copy;
1559 }else{
1560 if(ERROR_OCCURRED(pq_insert_after(previous, copy))){
1561 pq_release(tcp_globals.net_phone, packet_get_id(copy));
1562 return sending;
1563 }
1564 }
1565 previous = copy;
1566 packet = pq_next(packet);
1567 // overflow occurred ?
1568 if((! packet) && (socket_data->last_outgoing > socket_data->next_outgoing)){
1569 printf("gpts overflow\n");
1570 // continue from the beginning
1571 packet = socket_data->outgoing;
1572 }
1573 socket_data->last_outgoing += data_length;
1574 }else{
1575 break;
1576 }
1577 }
1578 return sending;
1579}
1580
1581packet_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){
1582 ERROR_DECLARE;
1583
1584 tcp_header_ref header;
1585 uint32_t checksum;
1586
1587 assert(socket);
1588 assert(socket_data);
1589 assert(socket->specific_data == socket_data);
1590
1591 // adjust the pseudo header
1592 if(ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(socket_data->pseudo_header, socket_data->headerlen, packet_get_data_length(packet)))){
1593 pq_release(tcp_globals.net_phone, packet_get_id(packet));
1594 return NULL;
1595 }
1596
1597 // get the header
1598 header = (tcp_header_ref) packet_get_data(packet);
1599 if(! header){
1600 pq_release(tcp_globals.net_phone, packet_get_id(packet));
1601 return NULL;
1602 }
1603 assert(ntohl(header->sequence_number) == sequence_number);
1604
1605 // adjust the header
1606 if(socket_data->next_incoming){
1607 header->acknowledgement_number = htonl(socket_data->next_incoming);
1608 header->acknowledge = 1;
1609 }
1610 header->window = htons(socket_data->window);
1611
1612 // checksum
1613 header->checksum = 0;
1614 checksum = compute_checksum(0, socket_data->pseudo_header, socket_data->headerlen);
1615 checksum = compute_checksum(checksum, (uint8_t *) packet_get_data(packet), packet_get_data_length(packet));
1616 header->checksum = htons(flip_checksum(compact_checksum(checksum)));
1617 // prepare the packet
1618 if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0))
1619 // prepare the timeout
1620 || ERROR_OCCURRED(tcp_prepare_timeout(tcp_timeout, socket, socket_data, sequence_number, socket_data->state, socket_data->timeout, true))){
1621 pq_release(tcp_globals.net_phone, packet_get_id(packet));
1622 return NULL;
1623 }
1624 return packet;
1625}
1626
1627packet_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){
1628 packet_t copy;
1629
1630 assert(socket);
1631 assert(socket_data);
1632 assert(socket->specific_data == socket_data);
1633
1634 // make a copy of the packet
1635 copy = packet_get_copy(tcp_globals.net_phone, packet);
1636 if(! copy){
1637 return NULL;
1638 }
1639
1640 return tcp_send_prepare_packet(socket, socket_data, copy, data_length, sequence_number);
1641}
1642
1643void tcp_send_packets(device_id_t device_id, packet_t packet){
1644 packet_t next;
1645
1646 while(packet){
1647 next = pq_detach(packet);
1648 ip_send_msg(tcp_globals.ip_phone, device_id, packet, SERVICE_TCP, 0);
1649 packet = next;
1650 }
1651}
1652
1653void tcp_prepare_operation_header(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize, int finalize){
1654 assert(socket);
1655 assert(socket_data);
1656 assert(socket->specific_data == socket_data);
1657 assert(header);
1658
1659 bzero(header, sizeof(*header));
1660 header->source_port = htons(socket->port);
1661 header->source_port = htons(socket_data->dest_port);
1662 header->header_length = TCP_COMPUTE_HEADER_LENGTH(sizeof(*header));
1663 header->synchronize = synchronize;
1664 header->finalize = finalize;
1665}
1666
1667int 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){
1668 tcp_timeout_ref operation_timeout;
1669 fid_t fibril;
1670
1671 assert(socket);
1672 assert(socket_data);
1673 assert(socket->specific_data == socket_data);
1674
1675 // prepare the timeout with key bundle structure
1676 operation_timeout = malloc(sizeof(*operation_timeout) + socket->key_length + 1);
1677 if(! operation_timeout){
1678 return ENOMEM;
1679 }
1680 bzero(operation_timeout, sizeof(*operation_timeout));
1681 operation_timeout->globals_read_only = globals_read_only;
1682 operation_timeout->port = socket->port;
1683 operation_timeout->local_sockets = socket_data->local_sockets;
1684 operation_timeout->socket_id = socket->socket_id;
1685 operation_timeout->timeout = timeout;
1686 operation_timeout->sequence_number = sequence_number;
1687 operation_timeout->state = state;
1688
1689 // copy the key
1690 operation_timeout->key = ((char *) operation_timeout) + sizeof(*operation_timeout);
1691 operation_timeout->key_length = socket->key_length;
1692 memcpy(operation_timeout->key, socket->key, socket->key_length);
1693 operation_timeout->key[operation_timeout->key_length] = '\0';
1694
1695 // prepare the timeouting thread
1696 fibril = fibril_create(timeout_function, operation_timeout);
1697 if(! fibril){
1698 free(operation_timeout);
1699 return EPARTY;
1700 }
1701// fibril_mutex_lock(&socket_data->operation.mutex);
1702 // start the timeouting fibril
1703 fibril_add_ready(fibril);
1704 //socket_data->state = state;
1705 return EOK;
1706}
1707
1708int tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){
1709 ERROR_DECLARE;
1710
1711 socket_core_ref socket;
1712 tcp_socket_data_ref socket_data;
1713 int packet_id;
1714 packet_t packet;
1715 size_t length;
1716
1717 assert(local_sockets);
1718
1719 // find the socket
1720 socket = socket_cores_find(local_sockets, socket_id);
1721 if(! socket){
1722 return ENOTSOCK;
1723 }
1724 // get the socket specific data
1725 if(! socket->specific_data){
1726 return NO_DATA;
1727 }
1728 socket_data = (tcp_socket_data_ref) socket->specific_data;
1729
1730 // check state
1731 if((socket_data->state != TCP_SOCKET_ESTABLISHED) && (socket_data->state != TCP_SOCKET_CLOSE_WAIT)){
1732 return ENOTCONN;
1733 }
1734
1735 // send the source address if desired
1736 if(addrlen){
1737 ERROR_PROPAGATE(data_reply(socket_data->addr, socket_data->addrlen));
1738 *addrlen = socket_data->addrlen;
1739 }
1740
1741 // get the next received packet
1742 packet_id = dyn_fifo_value(&socket->received);
1743 if(packet_id < 0){
1744 return NO_DATA;
1745 }
1746 ERROR_PROPAGATE(packet_translate(tcp_globals.net_phone, &packet, packet_id));
1747
1748 // reply the packets
1749 ERROR_PROPAGATE(socket_reply_packets(packet, &length));
1750
1751 // release the packet
1752 dyn_fifo_pop(&socket->received);
1753 pq_release(tcp_globals.net_phone, packet_get_id(packet));
1754 // return the total length
1755 return (int) length;
1756}
1757
1758int tcp_send_message(socket_cores_ref local_sockets, int socket_id, int fragments, size_t * data_fragment_size, int flags){
1759 ERROR_DECLARE;
1760
1761 socket_core_ref socket;
1762 tcp_socket_data_ref socket_data;
1763 packet_dimension_ref packet_dimension;
1764 packet_t packet;
1765 size_t total_length;
1766 tcp_header_ref header;
1767 int index;
1768 int result;
1769
1770 assert(local_sockets);
1771 assert(data_fragment_size);
1772
1773 // find the socket
1774 socket = socket_cores_find(local_sockets, socket_id);
1775 if(! socket){
1776 return ENOTSOCK;
1777 }
1778 // get the socket specific data
1779 if(! socket->specific_data){
1780 return NO_DATA;
1781 }
1782 socket_data = (tcp_socket_data_ref) socket->specific_data;
1783
1784 // check state
1785 if((socket_data->state != TCP_SOCKET_ESTABLISHED) && (socket_data->state != TCP_SOCKET_CLOSE_WAIT)){
1786 return ENOTCONN;
1787 }
1788
1789 ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
1790
1791 *data_fragment_size = ((packet_dimension->content < socket_data->data_fragment_size) ? packet_dimension->content : socket_data->data_fragment_size);
1792
1793 for(index = 0; index < fragments; ++ index){
1794 // read the data fragment
1795 result = tl_socket_read_packet_data(tcp_globals.net_phone, &packet, TCP_HEADER_SIZE, packet_dimension, socket_data->addr, socket_data->addrlen);
1796 if(result < 0){
1797 return result;
1798 }
1799 total_length = (size_t) result;
1800 // prefix the tcp header
1801 header = PACKET_PREFIX(packet, tcp_header_t);
1802 if(! header){
1803 return tcp_release_and_return(packet, ENOMEM);
1804 }
1805 tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
1806 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 0));
1807 }
1808
1809 // flush packets
1810 packet = tcp_get_packets_to_send(socket, socket_data);
1811 fibril_rwlock_write_unlock(socket_data->local_lock);
1812 fibril_rwlock_read_unlock(&tcp_globals.lock);
1813 if(packet){
1814 // send the packet
1815 tcp_send_packets(socket_data->device_id, packet);
1816 }
1817
1818 return EOK;
1819}
1820
1821int tcp_close_message(socket_cores_ref local_sockets, int socket_id){
1822 ERROR_DECLARE;
1823
1824 socket_core_ref socket;
1825 tcp_socket_data_ref socket_data;
1826 packet_t packet;
1827
1828 // find the socket
1829 socket = socket_cores_find(local_sockets, socket_id);
1830 if(! socket){
1831 return ENOTSOCK;
1832 }
1833 // get the socket specific data
1834 socket_data = (tcp_socket_data_ref) socket->specific_data;
1835 assert(socket_data);
1836
1837 // check state
1838 switch(socket_data->state){
1839 case TCP_SOCKET_ESTABLISHED:
1840 socket_data->state = TCP_SOCKET_FIN_WAIT_1;
1841 break;
1842 case TCP_SOCKET_CLOSE_WAIT:
1843 socket_data->state = TCP_SOCKET_LAST_ACK;
1844 break;
1845// case TCP_SOCKET_LISTEN:
1846 default:
1847 // just destroy
1848 if(! ERROR_OCCURRED(socket_destroy(tcp_globals.net_phone, socket_id, local_sockets, &tcp_globals.sockets, tcp_free_socket_data))){
1849 fibril_rwlock_write_unlock(socket_data->local_lock);
1850 fibril_rwlock_write_unlock(&tcp_globals.lock);
1851 }
1852 return ERROR_CODE;
1853 }
1854 // send FIN
1855 // TODO should I wait to complete?
1856
1857 // create the notification packet
1858 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 0, 1));
1859
1860 // send the packet
1861 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 1));
1862
1863 // flush packets
1864 packet = tcp_get_packets_to_send(socket, socket_data);
1865 fibril_rwlock_write_unlock(socket_data->local_lock);
1866 fibril_rwlock_write_unlock(&tcp_globals.lock);
1867 if(packet){
1868 // send the packet
1869 tcp_send_packets(socket_data->device_id, packet);
1870 }
1871 return EOK;
1872}
1873
1874int tcp_create_notification_packet(packet_t * packet, socket_core_ref socket, tcp_socket_data_ref socket_data, int synchronize, int finalize){
1875 ERROR_DECLARE;
1876
1877 packet_dimension_ref packet_dimension;
1878 tcp_header_ref header;
1879
1880 assert(packet);
1881
1882 // get the device packet dimension
1883 ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
1884 // get a new packet
1885 *packet = packet_get_4(tcp_globals.net_phone, TCP_HEADER_SIZE, packet_dimension->addr_len, packet_dimension->prefix, packet_dimension->suffix);
1886 if(! * packet){
1887 return ENOMEM;
1888 }
1889 // allocate space in the packet
1890 header = PACKET_SUFFIX(*packet, tcp_header_t);
1891 if(! header){
1892 tcp_release_and_return(*packet, ENOMEM);
1893 }
1894
1895 tcp_prepare_operation_header(socket, socket_data, header, synchronize, finalize);
1896 return EOK;
1897}
1898
1899int tcp_accept_message(socket_cores_ref local_sockets, int socket_id, int new_socket_id, size_t * data_fragment_size, size_t * addrlen){
1900 ERROR_DECLARE;
1901
1902 socket_core_ref accepted;
1903 socket_core_ref socket;
1904 tcp_socket_data_ref socket_data;
1905 packet_dimension_ref packet_dimension;
1906
1907 assert(local_sockets);
1908 assert(data_fragment_size);
1909 assert(addrlen);
1910
1911 // find the socket
1912 socket = socket_cores_find(local_sockets, socket_id);
1913 if(! socket){
1914 return ENOTSOCK;
1915 }
1916 // get the socket specific data
1917 socket_data = (tcp_socket_data_ref) socket->specific_data;
1918 assert(socket_data);
1919
1920 // check state
1921 if(socket_data->state != TCP_SOCKET_LISTEN){
1922 return EINVAL;
1923 }
1924
1925 do{
1926 socket_id = dyn_fifo_value(&socket->accepted);
1927 if(socket_id < 0){
1928 return ENOTSOCK;
1929 }
1930 socket_id *= -1;
1931
1932 accepted = socket_cores_find(local_sockets, socket_id);
1933 if(! accepted){
1934 return ENOTSOCK;
1935 }
1936 // get the socket specific data
1937 socket_data = (tcp_socket_data_ref) accepted->specific_data;
1938 assert(socket_data);
1939 // TODO can it be in another state?
1940 if(socket_data->state == TCP_SOCKET_ESTABLISHED){
1941 ERROR_PROPAGATE(data_reply(socket_data->addr, socket_data->addrlen));
1942 ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
1943 *addrlen = socket_data->addrlen;
1944 *data_fragment_size = ((packet_dimension->content < socket_data->data_fragment_size) ? packet_dimension->content : socket_data->data_fragment_size);
1945 if(new_socket_id > 0){
1946 ERROR_PROPAGATE(socket_cores_update(local_sockets, accepted->socket_id, new_socket_id));
1947 accepted->socket_id = new_socket_id;
1948 }
1949 }
1950 dyn_fifo_pop(&socket->accepted);
1951 }while(socket_data->state != TCP_SOCKET_ESTABLISHED);
1952 printf("ret accept %d\n", accepted->socket_id);
1953 return accepted->socket_id;
1954}
1955
1956void tcp_free_socket_data(socket_core_ref socket){
1957 tcp_socket_data_ref socket_data;
1958
1959 assert(socket);
1960
1961 printf("destroy_socket %d\n", socket->socket_id);
1962
1963 // get the socket specific data
1964 socket_data = (tcp_socket_data_ref) socket->specific_data;
1965 assert(socket_data);
1966 //free the pseudo header
1967 if(socket_data->pseudo_header){
1968 if(socket_data->headerlen){
1969 printf("d pseudo\n");
1970 free(socket_data->pseudo_header);
1971 socket_data->headerlen = 0;
1972 }
1973 socket_data->pseudo_header = NULL;
1974 }
1975 socket_data->headerlen = 0;
1976 // free the address
1977 if(socket_data->addr){
1978 if(socket_data->addrlen){
1979 printf("d addr\n");
1980 free(socket_data->addr);
1981 socket_data->addrlen = 0;
1982 }
1983 socket_data->addr = NULL;
1984 }
1985 socket_data->addrlen = 0;
1986}
1987
1988int tcp_release_and_return(packet_t packet, int result){
1989 pq_release(tcp_globals.net_phone, packet_get_id(packet));
1990 return result;
1991}
1992
1993/** @}
1994 */
Note: See TracBrowser for help on using the repository browser.