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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c9f0975 was 0743493a, checked in by Jakub Jermar <jakub@…>, 14 years ago

tcp: Remove bit fields and use defines and bitwise ops instead.

  • Property mode set to 100644
File size: 69.2 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#include <errno.h>
45
46#include <ipc/services.h>
47#include <ipc/net.h>
48#include <ipc/tl.h>
49#include <ipc/socket.h>
50
51#include <net/socket_codes.h>
52#include <net/ip_protocols.h>
53#include <net/in.h>
54#include <net/in6.h>
55#include <net/inet.h>
56#include <net/modules.h>
57
58#include <adt/dynamic_fifo.h>
59#include <packet_client.h>
60#include <packet_remote.h>
61#include <net_checksum.h>
62#include <ip_client.h>
63#include <ip_interface.h>
64#include <icmp_client.h>
65#include <icmp_remote.h>
66#include <net_interface.h>
67#include <socket_core.h>
68#include <tl_common.h>
69#include <tl_remote.h>
70#include <tl_skel.h>
71
72#include "tcp.h"
73#include "tcp_header.h"
74
75/** TCP module name. */
76#define NAME "tcp"
77
78/** The TCP window default value. */
79#define NET_DEFAULT_TCP_WINDOW 10240
80
81/** Initial timeout for new connections. */
82#define NET_DEFAULT_TCP_INITIAL_TIMEOUT 3000000L
83
84/** Default timeout for closing. */
85#define NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT 2000L
86
87/** The initial outgoing sequence number. */
88#define TCP_INITIAL_SEQUENCE_NUMBER 2999
89
90/** Maximum TCP fragment size. */
91#define MAX_TCP_FRAGMENT_SIZE 65535
92
93/** Free ports pool start. */
94#define TCP_FREE_PORTS_START 1025
95
96/** Free ports pool end. */
97#define TCP_FREE_PORTS_END 65535
98
99/** Timeout for connection initialization, SYN sent. */
100#define TCP_SYN_SENT_TIMEOUT 1000000L
101
102/** The maximum number of timeouts in a row before singaling connection lost. */
103#define TCP_MAX_TIMEOUTS 8
104
105/** The number of acknowledgements before retransmit. */
106#define TCP_FAST_RETRANSMIT_COUNT 3
107
108/** Returns a value indicating whether the value is in the interval respecting
109 * the possible overflow.
110 *
111 * The high end and/or the value may overflow, be lower than the low value.
112 *
113 * @param[in] lower The last value before the interval.
114 * @param[in] value The value to be checked.
115 * @param[in] higher_equal The last value in the interval.
116 */
117#define IS_IN_INTERVAL_OVERFLOW(lower, value, higher_equal) \
118 ((((lower) < (value)) && (((value) <= (higher_equal)) || \
119 ((higher_equal) < (lower)))) || (((value) <= (higher_equal)) && \
120 ((higher_equal) < (lower))))
121
122/** Type definition of the TCP timeout.
123 * @see tcp_timeout
124 */
125typedef struct tcp_timeout tcp_timeout_t;
126
127/** TCP reply timeout data.
128 * Used as a timeouting fibril argument.
129 * @see tcp_timeout()
130 */
131struct tcp_timeout {
132 /** TCP global data are going to be read only. */
133 int globals_read_only;
134
135 /** Socket port. */
136 int port;
137
138 /** Local sockets. */
139 socket_cores_t *local_sockets;
140
141 /** Socket identifier. */
142 int socket_id;
143
144 /** Socket state. */
145 tcp_socket_state_t state;
146
147 /** Sent packet sequence number. */
148 int sequence_number;
149
150 /** Timeout in microseconds. */
151 suseconds_t timeout;
152
153 /** Port map key. */
154 uint8_t *key;
155
156 /** Port map key length. */
157 size_t key_length;
158};
159
160static int tcp_release_and_return(packet_t *, int);
161static void tcp_prepare_operation_header(socket_core_t *, tcp_socket_data_t *,
162 tcp_header_t *, int synchronize, int);
163static int tcp_prepare_timeout(int (*)(void *), socket_core_t *,
164 tcp_socket_data_t *, size_t, tcp_socket_state_t, suseconds_t, int);
165static void tcp_free_socket_data(socket_core_t *);
166
167static int tcp_timeout(void *);
168
169static int tcp_release_after_timeout(void *);
170
171static int tcp_process_packet(device_id_t, packet_t *, services_t);
172static int tcp_connect_core(socket_core_t *, socket_cores_t *,
173 struct sockaddr *, socklen_t);
174static int tcp_queue_prepare_packet(socket_core_t *, tcp_socket_data_t *,
175 packet_t *, size_t);
176static int tcp_queue_packet(socket_core_t *, tcp_socket_data_t *, packet_t *,
177 size_t);
178static packet_t *tcp_get_packets_to_send(socket_core_t *, tcp_socket_data_t *);
179static void tcp_send_packets(device_id_t, packet_t *);
180
181static void tcp_process_acknowledgement(socket_core_t *, tcp_socket_data_t *,
182 tcp_header_t *);
183static packet_t *tcp_send_prepare_packet(socket_core_t *, tcp_socket_data_t *,
184 packet_t *, size_t, size_t);
185static packet_t *tcp_prepare_copy(socket_core_t *, tcp_socket_data_t *,
186 packet_t *, size_t, size_t);
187/* static */ void tcp_retransmit_packet(socket_core_t *, tcp_socket_data_t *,
188 size_t);
189static int tcp_create_notification_packet(packet_t **, socket_core_t *,
190 tcp_socket_data_t *, int, int);
191static void tcp_refresh_socket_data(tcp_socket_data_t *);
192
193static void tcp_initialize_socket_data(tcp_socket_data_t *);
194
195static int tcp_process_listen(socket_core_t *, tcp_socket_data_t *,
196 tcp_header_t *, packet_t *, struct sockaddr *, struct sockaddr *, size_t);
197static int tcp_process_syn_sent(socket_core_t *, tcp_socket_data_t *,
198 tcp_header_t *, packet_t *);
199static int tcp_process_syn_received(socket_core_t *, tcp_socket_data_t *,
200 tcp_header_t *, packet_t *);
201static int tcp_process_established(socket_core_t *, tcp_socket_data_t *,
202 tcp_header_t *, packet_t *, int, size_t);
203static int tcp_queue_received_packet(socket_core_t *, tcp_socket_data_t *,
204 packet_t *, int, size_t);
205static void tcp_queue_received_end_of_data(socket_core_t *socket);
206
207static int tcp_received_msg(device_id_t, packet_t *, services_t, services_t);
208static int tcp_process_client_messages(ipc_callid_t, ipc_call_t);
209
210static int tcp_listen_message(socket_cores_t *, int, int);
211static int tcp_connect_message(socket_cores_t *, int, struct sockaddr *,
212 socklen_t);
213static int tcp_recvfrom_message(socket_cores_t *, int, int, size_t *);
214static int tcp_send_message(socket_cores_t *, int, int, size_t *, int);
215static int tcp_accept_message(socket_cores_t *, int, int, size_t *, size_t *);
216static int tcp_close_message(socket_cores_t *, int);
217
218/** TCP global data. */
219tcp_globals_t tcp_globals;
220
221int tcp_received_msg(device_id_t device_id, packet_t *packet,
222 services_t receiver, services_t error)
223{
224 int rc;
225
226 if (receiver != SERVICE_TCP)
227 return EREFUSED;
228
229 fibril_rwlock_write_lock(&tcp_globals.lock);
230 rc = tcp_process_packet(device_id, packet, error);
231 if (rc != EOK)
232 fibril_rwlock_write_unlock(&tcp_globals.lock);
233
234 printf("receive %d \n", rc);
235
236 return rc;
237}
238
239int tcp_process_packet(device_id_t device_id, packet_t *packet, services_t error)
240{
241 size_t length;
242 size_t offset;
243 int result;
244 tcp_header_t *header;
245 socket_core_t *socket;
246 tcp_socket_data_t *socket_data;
247 packet_t *next_packet;
248 size_t total_length;
249 uint32_t checksum;
250 int fragments;
251 icmp_type_t type;
252 icmp_code_t code;
253 struct sockaddr *src;
254 struct sockaddr *dest;
255 size_t addrlen;
256 int rc;
257
258 switch (error) {
259 case SERVICE_NONE:
260 break;
261 case SERVICE_ICMP:
262 /* Process error */
263 result = icmp_client_process_packet(packet, &type, &code, NULL,
264 NULL);
265 if (result < 0)
266 return tcp_release_and_return(packet, result);
267
268 length = (size_t) result;
269 rc = packet_trim(packet, length, 0);
270 if (rc != EOK)
271 return tcp_release_and_return(packet, rc);
272 break;
273 default:
274 return tcp_release_and_return(packet, ENOTSUP);
275 }
276
277 /* TODO process received ipopts? */
278 result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
279 if (result < 0)
280 return tcp_release_and_return(packet, result);
281
282 offset = (size_t) result;
283
284 length = packet_get_data_length(packet);
285 if (length <= 0)
286 return tcp_release_and_return(packet, EINVAL);
287
288 if (length < TCP_HEADER_SIZE + offset)
289 return tcp_release_and_return(packet, NO_DATA);
290
291 /* Trim all but TCP header */
292 rc = packet_trim(packet, offset, 0);
293 if (rc != EOK)
294 return tcp_release_and_return(packet, rc);
295
296 /* Get tcp header */
297 header = (tcp_header_t *) packet_get_data(packet);
298 if (!header)
299 return tcp_release_and_return(packet, NO_DATA);
300
301#if 0
302 printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header),
303 ntohs(header->destination_port));
304#endif
305 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
306 if (result <= 0)
307 return tcp_release_and_return(packet, result);
308
309 addrlen = (size_t) result;
310
311 rc = tl_set_address_port(src, addrlen, ntohs(header->source_port));
312 if (rc != EOK)
313 return tcp_release_and_return(packet, rc);
314
315 /* Find the destination socket */
316 socket = socket_port_find(&tcp_globals.sockets,
317 ntohs(header->destination_port), (uint8_t *) src, addrlen);
318 if (!socket) {
319 /* Find the listening destination socket */
320 socket = socket_port_find(&tcp_globals.sockets,
321 ntohs(header->destination_port),
322 (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
323 }
324
325 if (!socket) {
326 if (tl_prepare_icmp_packet(tcp_globals.net_phone,
327 tcp_globals.icmp_phone, packet, error) == EOK) {
328 icmp_destination_unreachable_msg(tcp_globals.icmp_phone,
329 ICMP_PORT_UNREACH, 0, packet);
330 }
331 return EADDRNOTAVAIL;
332 }
333
334 printf("socket id %d\n", socket->socket_id);
335 socket_data = (tcp_socket_data_t *) socket->specific_data;
336 assert(socket_data);
337
338 /* Some data received, clear the timeout counter */
339 socket_data->timeout_count = 0;
340
341 /* Count the received packet fragments */
342 next_packet = packet;
343 fragments = 0;
344 checksum = 0;
345 total_length = 0;
346 do {
347 fragments++;
348 length = packet_get_data_length(next_packet);
349 if (length <= 0)
350 return tcp_release_and_return(packet, NO_DATA);
351
352 total_length += length;
353
354 /* Add partial checksum if set */
355 if (!error) {
356 checksum = compute_checksum(checksum,
357 packet_get_data(packet),
358 packet_get_data_length(packet));
359 }
360
361 } while ((next_packet = pq_next(next_packet)));
362
363 fibril_rwlock_write_lock(socket_data->local_lock);
364
365 if (error)
366 goto has_error_service;
367
368 if (socket_data->state == TCP_SOCKET_LISTEN) {
369 if (socket_data->pseudo_header) {
370 free(socket_data->pseudo_header);
371 socket_data->pseudo_header = NULL;
372 socket_data->headerlen = 0;
373 }
374
375 rc = ip_client_get_pseudo_header(IPPROTO_TCP, src, addrlen,
376 dest, addrlen, total_length, &socket_data->pseudo_header,
377 &socket_data->headerlen);
378 if (rc != EOK) {
379 fibril_rwlock_write_unlock(socket_data->local_lock);
380 return tcp_release_and_return(packet, rc);
381 }
382 } else {
383 rc = ip_client_set_pseudo_header_data_length(
384 socket_data->pseudo_header, socket_data->headerlen,
385 total_length);
386 if (rc != EOK) {
387 fibril_rwlock_write_unlock(socket_data->local_lock);
388 return tcp_release_and_return(packet, rc);
389 }
390 }
391
392 checksum = compute_checksum(checksum, socket_data->pseudo_header,
393 socket_data->headerlen);
394 if (flip_checksum(compact_checksum(checksum)) != IP_CHECKSUM_ZERO) {
395 printf("checksum err %x -> %x\n", header->checksum,
396 flip_checksum(compact_checksum(checksum)));
397 fibril_rwlock_write_unlock(socket_data->local_lock);
398
399 rc = tl_prepare_icmp_packet(tcp_globals.net_phone,
400 tcp_globals.icmp_phone, packet, error);
401 if (rc == EOK) {
402 /* Checksum error ICMP */
403 icmp_parameter_problem_msg(tcp_globals.icmp_phone,
404 ICMP_PARAM_POINTER,
405 ((size_t) ((void *) &header->checksum)) -
406 ((size_t) ((void *) header)), packet);
407 }
408
409 return EINVAL;
410 }
411
412has_error_service:
413 fibril_rwlock_write_unlock(&tcp_globals.lock);
414
415 /* TODO error reporting/handling */
416 switch (socket_data->state) {
417 case TCP_SOCKET_LISTEN:
418 rc = tcp_process_listen(socket, socket_data, header, packet,
419 src, dest, addrlen);
420 break;
421 case TCP_SOCKET_SYN_RECEIVED:
422 rc = tcp_process_syn_received(socket, socket_data, header,
423 packet);
424 break;
425 case TCP_SOCKET_SYN_SENT:
426 rc = tcp_process_syn_sent(socket, socket_data, header, packet);
427 break;
428 case TCP_SOCKET_FIN_WAIT_1:
429 /* ack changing the state to FIN_WAIT_2 gets processed later */
430 case TCP_SOCKET_FIN_WAIT_2:
431 /* fin changing state to LAST_ACK gets processed later */
432 case TCP_SOCKET_LAST_ACK:
433 /* ack releasing the socket get processed later */
434 case TCP_SOCKET_CLOSING:
435 /* ack releasing the socket gets processed later */
436 case TCP_SOCKET_ESTABLISHED:
437 rc = tcp_process_established(socket, socket_data, header,
438 packet, fragments, total_length);
439 break;
440 default:
441 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
442 }
443
444 if (rc != EOK) {
445 fibril_rwlock_write_unlock(socket_data->local_lock);
446 printf("process %d\n", rc);
447 }
448
449 return EOK;
450}
451
452int tcp_process_established(socket_core_t *socket, tcp_socket_data_t *
453 socket_data, tcp_header_t *header, packet_t *packet, int fragments,
454 size_t total_length)
455{
456 packet_t *next_packet;
457 packet_t *tmp_packet;
458 uint32_t old_incoming;
459 size_t order;
460 uint32_t sequence_number;
461 size_t length;
462 size_t offset;
463 uint32_t new_sequence_number;
464 bool forced_ack;
465 int rc;
466
467 assert(socket);
468 assert(socket_data);
469 assert(socket->specific_data == socket_data);
470 assert(header);
471 assert(packet);
472
473 forced_ack = false;
474
475 new_sequence_number = ntohl(header->sequence_number);
476 old_incoming = socket_data->next_incoming;
477
478 if (GET_TCP_HEADER_FINALIZE(header)) {
479 socket_data->fin_incoming = new_sequence_number +
480 total_length - TCP_HEADER_LENGTH(header);
481 }
482
483 /* Trim begining if containing expected data */
484 if (IS_IN_INTERVAL_OVERFLOW(new_sequence_number,
485 socket_data->next_incoming, new_sequence_number + total_length)) {
486
487 /* Get the acknowledged offset */
488 if (socket_data->next_incoming < new_sequence_number) {
489 offset = new_sequence_number -
490 socket_data->next_incoming;
491 } else {
492 offset = socket_data->next_incoming -
493 new_sequence_number;
494 }
495
496 new_sequence_number += offset;
497 total_length -= offset;
498 length = packet_get_data_length(packet);
499
500 /* Trim the acknowledged data */
501 while (length <= offset) {
502 /* Release the acknowledged packets */
503 next_packet = pq_next(packet);
504 pq_release_remote(tcp_globals.net_phone,
505 packet_get_id(packet));
506 packet = next_packet;
507 offset -= length;
508 length = packet_get_data_length(packet);
509 }
510
511 if (offset > 0) {
512 rc = packet_trim(packet, offset, 0);
513 if (rc != EOK)
514 return tcp_release_and_return(packet, rc);
515 }
516
517 assert(new_sequence_number == socket_data->next_incoming);
518 }
519
520 /* Release if overflowing the window */
521/*
522 if (IS_IN_INTERVAL_OVERFLOW(socket_data->next_incoming +
523 socket_data->window, new_sequence_number, new_sequence_number +
524 total_length)) {
525 return tcp_release_and_return(packet, EOVERFLOW);
526 }
527
528 // trim end if overflowing the window
529 if (IS_IN_INTERVAL_OVERFLOW(new_sequence_number,
530 socket_data->next_incoming + socket_data->window,
531 new_sequence_number + total_length)) {
532 // get the allowed data length
533 if (socket_data->next_incoming + socket_data->window <
534 new_sequence_number) {
535 offset = new_sequence_number -
536 socket_data->next_incoming + socket_data->window;
537 } else {
538 offset = socket_data->next_incoming +
539 socket_data->window - new_sequence_number;
540 }
541 next_packet = packet;
542 // trim the overflowing data
543 while (next_packet && (offset > 0)) {
544 length = packet_get_data_length(packet);
545 if (length <= offset)
546 next_packet = pq_next(next_packet);
547 else {
548 rc = packet_trim(next_packet, 0,
549 length - offset));
550 if (rc != EOK)
551 return tcp_release_and_return(packet,
552 rc);
553 }
554 offset -= length;
555 total_length -= length - offset;
556 }
557 // release the overflowing packets
558 next_packet = pq_next(next_packet);
559 if (next_packet) {
560 tmp_packet = next_packet;
561 next_packet = pq_next(next_packet);
562 pq_insert_after(tmp_packet, next_packet);
563 pq_release_remote(tcp_globals.net_phone,
564 packet_get_id(tmp_packet));
565 }
566 assert(new_sequence_number + total_length ==
567 socket_data->next_incoming + socket_data->window);
568 }
569*/
570 /* The expected one arrived? */
571 if (new_sequence_number == socket_data->next_incoming) {
572 printf("expected\n");
573 /* Process acknowledgement */
574 tcp_process_acknowledgement(socket, socket_data, header);
575
576 /* Remove the header */
577 total_length -= TCP_HEADER_LENGTH(header);
578 rc = packet_trim(packet, TCP_HEADER_LENGTH(header), 0);
579 if (rc != EOK)
580 return tcp_release_and_return(packet, rc);
581
582 if (total_length) {
583 rc = tcp_queue_received_packet(socket, socket_data,
584 packet, fragments, total_length);
585 if (rc != EOK)
586 return rc;
587 } else {
588 total_length = 1;
589 }
590
591 socket_data->next_incoming = old_incoming + total_length;
592 packet = socket_data->incoming;
593 while (packet) {
594 rc = pq_get_order(socket_data->incoming, &order, NULL);
595 if (rc != EOK) {
596 /* Remove the corrupted packet */
597 next_packet = pq_detach(packet);
598 if (packet == socket_data->incoming)
599 socket_data->incoming = next_packet;
600 pq_release_remote(tcp_globals.net_phone,
601 packet_get_id(packet));
602 packet = next_packet;
603 continue;
604 }
605
606 sequence_number = (uint32_t) order;
607 if (IS_IN_INTERVAL_OVERFLOW(sequence_number,
608 old_incoming, socket_data->next_incoming)) {
609 /* Move to the next */
610 packet = pq_next(packet);
611 /* Coninual data? */
612 } else if (IS_IN_INTERVAL_OVERFLOW(old_incoming,
613 sequence_number, socket_data->next_incoming)) {
614 /* Detach the packet */
615 next_packet = pq_detach(packet);
616 if (packet == socket_data->incoming)
617 socket_data->incoming = next_packet;
618 /* Get data length */
619 length = packet_get_data_length(packet);
620 new_sequence_number = sequence_number + length;
621 if (length <= 0) {
622 /* Remove the empty packet */
623 pq_release_remote(tcp_globals.net_phone,
624 packet_get_id(packet));
625 packet = next_packet;
626 continue;
627 }
628 /* Exactly following */
629 if (sequence_number ==
630 socket_data->next_incoming) {
631 /* Queue received data */
632 rc = tcp_queue_received_packet(socket,
633 socket_data, packet, 1,
634 packet_get_data_length(packet));
635 if (rc != EOK)
636 return rc;
637 socket_data->next_incoming =
638 new_sequence_number;
639 packet = next_packet;
640 continue;
641 /* At least partly following data? */
642 }
643 if (IS_IN_INTERVAL_OVERFLOW(sequence_number,
644 socket_data->next_incoming, new_sequence_number)) {
645 if (socket_data->next_incoming <
646 new_sequence_number) {
647 length = new_sequence_number -
648 socket_data->next_incoming;
649 } else {
650 length =
651 socket_data->next_incoming -
652 new_sequence_number;
653 }
654 rc = packet_trim(packet,length, 0);
655 if (rc == EOK) {
656 /* Queue received data */
657 rc = tcp_queue_received_packet(
658 socket, socket_data, packet,
659 1, packet_get_data_length(
660 packet));
661 if (rc != EOK)
662 return rc;
663 socket_data->next_incoming =
664 new_sequence_number;
665 packet = next_packet;
666 continue;
667 }
668 }
669 /* Remove the duplicit or corrupted packet */
670 pq_release_remote(tcp_globals.net_phone,
671 packet_get_id(packet));
672 packet = next_packet;
673 continue;
674 } else {
675 break;
676 }
677 }
678 } else if (IS_IN_INTERVAL(socket_data->next_incoming,
679 new_sequence_number,
680 socket_data->next_incoming + socket_data->window)) {
681 printf("in window\n");
682 /* Process acknowledgement */
683 tcp_process_acknowledgement(socket, socket_data, header);
684
685 /* Remove the header */
686 total_length -= TCP_HEADER_LENGTH(header);
687 rc = packet_trim(packet, TCP_HEADER_LENGTH(header), 0);
688 if (rc != EOK)
689 return tcp_release_and_return(packet, rc);
690
691 next_packet = pq_detach(packet);
692 length = packet_get_data_length(packet);
693 rc = pq_add(&socket_data->incoming, packet, new_sequence_number,
694 length);
695 if (rc != EOK) {
696 /* Remove the corrupted packets */
697 pq_release_remote(tcp_globals.net_phone,
698 packet_get_id(packet));
699 pq_release_remote(tcp_globals.net_phone,
700 packet_get_id(next_packet));
701 } else {
702 while (next_packet) {
703 new_sequence_number += length;
704 tmp_packet = pq_detach(next_packet);
705 length = packet_get_data_length(next_packet);
706
707 rc = pq_set_order(next_packet,
708 new_sequence_number, length);
709 if (rc != EOK) {
710 pq_release_remote(tcp_globals.net_phone,
711 packet_get_id(next_packet));
712 }
713 rc = pq_insert_after(packet, next_packet);
714 if (rc != EOK) {
715 pq_release_remote(tcp_globals.net_phone,
716 packet_get_id(next_packet));
717 }
718 next_packet = tmp_packet;
719 }
720 }
721 } else {
722 printf("unexpected\n");
723 /* Release duplicite or restricted */
724 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
725 forced_ack = true;
726 }
727
728 /* If next in sequence is an incoming FIN */
729 if (socket_data->next_incoming == socket_data->fin_incoming) {
730 /* Advance sequence number */
731 socket_data->next_incoming += 1;
732
733 /* Handle FIN */
734 switch (socket_data->state) {
735 case TCP_SOCKET_FIN_WAIT_1:
736 case TCP_SOCKET_FIN_WAIT_2:
737 case TCP_SOCKET_CLOSING:
738 socket_data->state = TCP_SOCKET_CLOSING;
739 break;
740 case TCP_SOCKET_ESTABLISHED:
741 /* Queue end-of-data marker on the socket. */
742 tcp_queue_received_end_of_data(socket);
743 socket_data->state = TCP_SOCKET_CLOSE_WAIT;
744 break;
745 default:
746 socket_data->state = TCP_SOCKET_CLOSE_WAIT;
747 break;
748 }
749 }
750
751 packet = tcp_get_packets_to_send(socket, socket_data);
752 if (!packet && (socket_data->next_incoming != old_incoming || forced_ack)) {
753 /* Create the notification packet */
754 rc = tcp_create_notification_packet(&packet, socket,
755 socket_data, 0, 0);
756 if (rc != EOK)
757 return rc;
758 rc = tcp_queue_prepare_packet(socket, socket_data, packet, 1);
759 if (rc != EOK)
760 return rc;
761 packet = tcp_send_prepare_packet(socket, socket_data, packet, 1,
762 socket_data->last_outgoing + 1);
763 }
764
765 fibril_rwlock_write_unlock(socket_data->local_lock);
766
767 /* Send the packet */
768 tcp_send_packets(socket_data->device_id, packet);
769
770 return EOK;
771}
772
773int tcp_queue_received_packet(socket_core_t *socket,
774 tcp_socket_data_t *socket_data, packet_t *packet, int fragments,
775 size_t total_length)
776{
777 packet_dimension_t *packet_dimension;
778 int rc;
779
780 assert(socket);
781 assert(socket_data);
782 assert(socket->specific_data == socket_data);
783 assert(packet);
784 assert(fragments >= 1);
785 assert(socket_data->window > total_length);
786
787 /* Queue the received packet */
788 rc = dyn_fifo_push(&socket->received, packet_get_id(packet),
789 SOCKET_MAX_RECEIVED_SIZE);
790 if (rc != EOK)
791 return tcp_release_and_return(packet, rc);
792 rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
793 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
794 if (rc != EOK)
795 return tcp_release_and_return(packet, rc);
796
797 /* Decrease the window size */
798 socket_data->window -= total_length;
799
800 /* Notify the destination socket */
801 async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
802 (sysarg_t) socket->socket_id,
803 ((packet_dimension->content < socket_data->data_fragment_size) ?
804 packet_dimension->content : socket_data->data_fragment_size), 0, 0,
805 (sysarg_t) fragments);
806
807 return EOK;
808}
809
810/** Queue end-of-data marker on the socket.
811 *
812 * Next element in the sequence space is FIN. Queue end-of-data marker
813 * on the socket.
814 *
815 * @param socket Socket
816 */
817static void tcp_queue_received_end_of_data(socket_core_t *socket)
818{
819 assert(socket != NULL);
820
821 /* Notify the destination socket */
822 async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
823 (sysarg_t) socket->socket_id,
824 0, 0, 0,
825 (sysarg_t) 0 /* 0 fragments == no more data */);
826}
827
828int tcp_process_syn_sent(socket_core_t *socket, tcp_socket_data_t *
829 socket_data, tcp_header_t *header, packet_t *packet)
830{
831 packet_t *next_packet;
832 int rc;
833
834 assert(socket);
835 assert(socket_data);
836 assert(socket->specific_data == socket_data);
837 assert(header);
838 assert(packet);
839
840 if (!GET_TCP_HEADER_SYNCHRONIZE(header))
841 return tcp_release_and_return(packet, EINVAL);
842
843 /* Process acknowledgement */
844 tcp_process_acknowledgement(socket, socket_data, header);
845
846 socket_data->next_incoming = ntohl(header->sequence_number) + 1;
847
848 /* Release additional packets */
849 next_packet = pq_detach(packet);
850 if (next_packet) {
851 pq_release_remote(tcp_globals.net_phone,
852 packet_get_id(next_packet));
853 }
854
855 /* Trim if longer than the header */
856 if (packet_get_data_length(packet) > sizeof(*header)) {
857 rc = packet_trim(packet, 0,
858 packet_get_data_length(packet) - sizeof(*header));
859 if (rc != EOK)
860 return tcp_release_and_return(packet, rc);
861 }
862
863 tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
864 fibril_mutex_lock(&socket_data->operation.mutex);
865 socket_data->operation.result = tcp_queue_packet(socket, socket_data,
866 packet, 1);
867
868 if (socket_data->operation.result == EOK) {
869 socket_data->state = TCP_SOCKET_ESTABLISHED;
870 packet = tcp_get_packets_to_send(socket, socket_data);
871 if (packet) {
872 fibril_rwlock_write_unlock( socket_data->local_lock);
873 /* Send the packet */
874 tcp_send_packets(socket_data->device_id, packet);
875 /* Signal the result */
876 fibril_condvar_signal( &socket_data->operation.condvar);
877 fibril_mutex_unlock( &socket_data->operation.mutex);
878 return EOK;
879 }
880 }
881
882 fibril_mutex_unlock(&socket_data->operation.mutex);
883 return tcp_release_and_return(packet, EINVAL);
884}
885
886int tcp_process_listen(socket_core_t *listening_socket,
887 tcp_socket_data_t *listening_socket_data, tcp_header_t *header,
888 packet_t *packet, struct sockaddr *src, struct sockaddr *dest,
889 size_t addrlen)
890{
891 packet_t *next_packet;
892 socket_core_t *socket;
893 tcp_socket_data_t *socket_data;
894 int socket_id;
895 int listening_socket_id = listening_socket->socket_id;
896 int listening_port = listening_socket->port;
897 int rc;
898
899 assert(listening_socket);
900 assert(listening_socket_data);
901 assert(listening_socket->specific_data == listening_socket_data);
902 assert(header);
903 assert(packet);
904
905 if (!GET_TCP_HEADER_SYNCHRONIZE(header))
906 return tcp_release_and_return(packet, EINVAL);
907
908 socket_data = (tcp_socket_data_t *) malloc(sizeof(*socket_data));
909 if (!socket_data)
910 return tcp_release_and_return(packet, ENOMEM);
911
912 tcp_initialize_socket_data(socket_data);
913 socket_data->local_lock = listening_socket_data->local_lock;
914 socket_data->local_sockets = listening_socket_data->local_sockets;
915 socket_data->listening_socket_id = listening_socket->socket_id;
916 socket_data->next_incoming = ntohl(header->sequence_number);
917 socket_data->treshold = socket_data->next_incoming +
918 ntohs(header->window);
919 socket_data->addrlen = addrlen;
920 socket_data->addr = malloc(socket_data->addrlen);
921 if (!socket_data->addr) {
922 free(socket_data);
923 return tcp_release_and_return(packet, ENOMEM);
924 }
925
926 memcpy(socket_data->addr, src, socket_data->addrlen);
927 socket_data->dest_port = ntohs(header->source_port);
928 rc = tl_set_address_port(socket_data->addr, socket_data->addrlen,
929 socket_data->dest_port);
930 if (rc != EOK) {
931 free(socket_data->addr);
932 free(socket_data);
933 return tcp_release_and_return(packet, rc);
934 }
935
936 /* Create a socket */
937 socket_id = -1;
938 rc = socket_create(socket_data->local_sockets, listening_socket->phone,
939 socket_data, &socket_id);
940 if (rc != EOK) {
941 free(socket_data->addr);
942 free(socket_data);
943 return tcp_release_and_return(packet, rc);
944 }
945
946 printf("new_sock %d\n", socket_id);
947 socket_data->pseudo_header = listening_socket_data->pseudo_header;
948 socket_data->headerlen = listening_socket_data->headerlen;
949 listening_socket_data->pseudo_header = NULL;
950 listening_socket_data->headerlen = 0;
951
952 fibril_rwlock_write_unlock(socket_data->local_lock);
953 fibril_rwlock_write_lock(&tcp_globals.lock);
954
955 /* Find the destination socket */
956 listening_socket = socket_port_find(&tcp_globals.sockets,
957 listening_port, (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
958 if (!listening_socket ||
959 (listening_socket->socket_id != listening_socket_id)) {
960 fibril_rwlock_write_unlock(&tcp_globals.lock);
961 /* A shadow may remain until app hangs up */
962 return tcp_release_and_return(packet, EOK /*ENOTSOCK*/);
963 }
964 listening_socket_data =
965 (tcp_socket_data_t *) listening_socket->specific_data;
966 assert(listening_socket_data);
967
968 fibril_rwlock_write_lock(listening_socket_data->local_lock);
969
970 socket = socket_cores_find(listening_socket_data->local_sockets,
971 socket_id);
972 if (!socket) {
973 /* Where is the socket?!? */
974 fibril_rwlock_write_unlock(&tcp_globals.lock);
975 return ENOTSOCK;
976 }
977 socket_data = (tcp_socket_data_t *) socket->specific_data;
978 assert(socket_data);
979
980 rc = socket_port_add(&tcp_globals.sockets, listening_port, socket,
981 (uint8_t *) socket_data->addr, socket_data->addrlen);
982 assert(socket == socket_port_find(&tcp_globals.sockets, listening_port,
983 (uint8_t *) socket_data->addr, socket_data->addrlen));
984
985// rc = socket_bind_free_port(&tcp_globals.sockets, socket,
986// TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
987// tcp_globals.last_used_port);
988// tcp_globals.last_used_port = socket->port;
989 fibril_rwlock_write_unlock(&tcp_globals.lock);
990 if (rc != EOK) {
991 socket_destroy(tcp_globals.net_phone, socket->socket_id,
992 socket_data->local_sockets, &tcp_globals.sockets,
993 tcp_free_socket_data);
994 return tcp_release_and_return(packet, rc);
995 }
996
997 socket_data->state = TCP_SOCKET_LISTEN;
998 socket_data->next_incoming = ntohl(header->sequence_number) + 1;
999
1000 /* Release additional packets */
1001 next_packet = pq_detach(packet);
1002 if (next_packet) {
1003 pq_release_remote(tcp_globals.net_phone,
1004 packet_get_id(next_packet));
1005 }
1006
1007 /* Trim if longer than the header */
1008 if (packet_get_data_length(packet) > sizeof(*header)) {
1009 rc = packet_trim(packet, 0,
1010 packet_get_data_length(packet) - sizeof(*header));
1011 if (rc != EOK) {
1012 socket_destroy(tcp_globals.net_phone, socket->socket_id,
1013 socket_data->local_sockets, &tcp_globals.sockets,
1014 tcp_free_socket_data);
1015 return tcp_release_and_return(packet, rc);
1016 }
1017 }
1018
1019 tcp_prepare_operation_header(socket, socket_data, header, 1, 0);
1020
1021 rc = tcp_queue_packet(socket, socket_data, packet, 1);
1022 if (rc != EOK) {
1023 socket_destroy(tcp_globals.net_phone, socket->socket_id,
1024 socket_data->local_sockets, &tcp_globals.sockets,
1025 tcp_free_socket_data);
1026 return rc;
1027 }
1028
1029 packet = tcp_get_packets_to_send(socket, socket_data);
1030 if (!packet) {
1031 socket_destroy(tcp_globals.net_phone, socket->socket_id,
1032 socket_data->local_sockets, &tcp_globals.sockets,
1033 tcp_free_socket_data);
1034 return EINVAL;
1035 }
1036
1037 socket_data->state = TCP_SOCKET_SYN_RECEIVED;
1038 fibril_rwlock_write_unlock(socket_data->local_lock);
1039
1040 /* Send the packet */
1041 tcp_send_packets(socket_data->device_id, packet);
1042
1043 return EOK;
1044}
1045
1046int tcp_process_syn_received(socket_core_t *socket,
1047 tcp_socket_data_t *socket_data, tcp_header_t *header, packet_t *packet)
1048{
1049 socket_core_t *listening_socket;
1050 tcp_socket_data_t *listening_socket_data;
1051 int rc;
1052
1053 assert(socket);
1054 assert(socket_data);
1055 assert(socket->specific_data == socket_data);
1056 assert(header);
1057 assert(packet);
1058
1059 if (!GET_TCP_HEADER_ACKNOWLEDGE(header))
1060 return tcp_release_and_return(packet, EINVAL);
1061
1062 /* Process acknowledgement */
1063 tcp_process_acknowledgement(socket, socket_data, header);
1064
1065 socket_data->next_incoming = ntohl(header->sequence_number); /* + 1; */
1066 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
1067 socket_data->state = TCP_SOCKET_ESTABLISHED;
1068 listening_socket = socket_cores_find(socket_data->local_sockets,
1069 socket_data->listening_socket_id);
1070 if (listening_socket) {
1071 listening_socket_data =
1072 (tcp_socket_data_t *) listening_socket->specific_data;
1073 assert(listening_socket_data);
1074
1075 /* Queue the received packet */
1076 rc = dyn_fifo_push(&listening_socket->accepted,
1077 (-1 * socket->socket_id), listening_socket_data->backlog);
1078 if (rc == EOK) {
1079 /* Notify the destination socket */
1080 async_msg_5(socket->phone, NET_SOCKET_ACCEPTED,
1081 (sysarg_t) listening_socket->socket_id,
1082 socket_data->data_fragment_size, TCP_HEADER_SIZE,
1083 0, (sysarg_t) socket->socket_id);
1084
1085 fibril_rwlock_write_unlock(socket_data->local_lock);
1086 return EOK;
1087 }
1088 }
1089 /* Send FIN */
1090 socket_data->state = TCP_SOCKET_FIN_WAIT_1;
1091
1092 /* Create the notification packet */
1093 rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1);
1094 if (rc != EOK)
1095 return rc;
1096
1097 /* Send the packet */
1098 rc = tcp_queue_packet(socket, socket_data, packet, 1);
1099 if (rc != EOK)
1100 return rc;
1101
1102 /* Flush packets */
1103 packet = tcp_get_packets_to_send(socket, socket_data);
1104 fibril_rwlock_write_unlock(socket_data->local_lock);
1105 if (packet) {
1106 /* Send the packet */
1107 tcp_send_packets(socket_data->device_id, packet);
1108 }
1109
1110 return EOK;
1111}
1112
1113void tcp_process_acknowledgement(socket_core_t *socket,
1114 tcp_socket_data_t *socket_data, tcp_header_t *header)
1115{
1116 size_t number;
1117 size_t length;
1118 packet_t *packet;
1119 packet_t *next;
1120 packet_t *acknowledged = NULL;
1121 uint32_t old;
1122
1123 assert(socket);
1124 assert(socket_data);
1125 assert(socket->specific_data == socket_data);
1126 assert(header);
1127
1128 if (!GET_TCP_HEADER_ACKNOWLEDGE(header))
1129 return;
1130
1131 number = ntohl(header->acknowledgement_number);
1132
1133 /* If more data acknowledged */
1134 if (number != socket_data->expected) {
1135 old = socket_data->expected;
1136 if (IS_IN_INTERVAL_OVERFLOW(old, socket_data->fin_outgoing,
1137 number)) {
1138 switch (socket_data->state) {
1139 case TCP_SOCKET_FIN_WAIT_1:
1140 socket_data->state = TCP_SOCKET_FIN_WAIT_2;
1141 break;
1142 case TCP_SOCKET_LAST_ACK:
1143 case TCP_SOCKET_CLOSING:
1144 /*
1145 * FIN acknowledged - release the socket in
1146 * another fibril.
1147 */
1148 tcp_prepare_timeout(tcp_release_after_timeout,
1149 socket, socket_data, 0,
1150 TCP_SOCKET_TIME_WAIT,
1151 NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT, true);
1152 break;
1153 default:
1154 break;
1155 }
1156 }
1157
1158 /* Update the treshold if higher than set */
1159 if (number + ntohs(header->window) >
1160 socket_data->expected + socket_data->treshold) {
1161 socket_data->treshold = number + ntohs(header->window) -
1162 socket_data->expected;
1163 }
1164
1165 /* Set new expected sequence number */
1166 socket_data->expected = number;
1167 socket_data->expected_count = 1;
1168 packet = socket_data->outgoing;
1169 while (pq_get_order(packet, &number, &length) == EOK) {
1170 if (IS_IN_INTERVAL_OVERFLOW((uint32_t) old,
1171 (uint32_t) (number + length),
1172 (uint32_t) socket_data->expected)) {
1173 next = pq_detach(packet);
1174 if (packet == socket_data->outgoing)
1175 socket_data->outgoing = next;
1176
1177 /* Add to acknowledged or release */
1178 if (pq_add(&acknowledged, packet, 0, 0) != EOK)
1179 pq_release_remote(tcp_globals.net_phone,
1180 packet_get_id(packet));
1181 packet = next;
1182 } else if (old < socket_data->expected)
1183 break;
1184 }
1185
1186 /* Release acknowledged */
1187 if (acknowledged) {
1188 pq_release_remote(tcp_globals.net_phone,
1189 packet_get_id(acknowledged));
1190 }
1191 return;
1192 /* If the same as the previous time */
1193 }
1194
1195 if (number == socket_data->expected) {
1196 /* Increase the counter */
1197 socket_data->expected_count++;
1198 if (socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT) {
1199 socket_data->expected_count = 1;
1200 /* TODO retransmit lock */
1201 //tcp_retransmit_packet(socket, socket_data, number);
1202 }
1203 }
1204}
1205
1206/** Per-connection initialization
1207 *
1208 */
1209void tl_connection(void)
1210{
1211}
1212
1213/** Processes the TCP message.
1214 *
1215 * @param[in] callid The message identifier.
1216 * @param[in] call The message parameters.
1217 * @param[out] answer The message answer parameters.
1218 * @param[out] answer_count The last parameter for the actual answer in the
1219 * answer parameter.
1220 * @return EOK on success.
1221 * @return ENOTSUP if the message is not known.
1222 *
1223 * @see tcp_interface.h
1224 * @see IS_NET_TCP_MESSAGE()
1225 */
1226int tl_message(ipc_callid_t callid, ipc_call_t *call,
1227 ipc_call_t *answer, size_t *answer_count)
1228{
1229 assert(call);
1230 assert(answer);
1231 assert(answer_count);
1232
1233 *answer_count = 0;
1234 switch (IPC_GET_IMETHOD(*call)) {
1235 case IPC_M_CONNECT_TO_ME:
1236 return tcp_process_client_messages(callid, *call);
1237 }
1238
1239 return ENOTSUP;
1240}
1241
1242void tcp_refresh_socket_data(tcp_socket_data_t *socket_data)
1243{
1244 assert(socket_data);
1245
1246 bzero(socket_data, sizeof(*socket_data));
1247 socket_data->state = TCP_SOCKET_INITIAL;
1248 socket_data->device_id = DEVICE_INVALID_ID;
1249 socket_data->window = NET_DEFAULT_TCP_WINDOW;
1250 socket_data->treshold = socket_data->window;
1251 socket_data->last_outgoing = TCP_INITIAL_SEQUENCE_NUMBER;
1252 socket_data->timeout = NET_DEFAULT_TCP_INITIAL_TIMEOUT;
1253 socket_data->acknowledged = socket_data->last_outgoing;
1254 socket_data->next_outgoing = socket_data->last_outgoing + 1;
1255 socket_data->expected = socket_data->next_outgoing;
1256}
1257
1258void tcp_initialize_socket_data(tcp_socket_data_t *socket_data)
1259{
1260 assert(socket_data);
1261
1262 tcp_refresh_socket_data(socket_data);
1263 fibril_mutex_initialize(&socket_data->operation.mutex);
1264 fibril_condvar_initialize(&socket_data->operation.condvar);
1265 socket_data->data_fragment_size = MAX_TCP_FRAGMENT_SIZE;
1266}
1267
1268int tcp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
1269{
1270 int res;
1271 bool keep_on_going = true;
1272 socket_cores_t local_sockets;
1273 int app_phone = IPC_GET_PHONE(call);
1274 struct sockaddr *addr;
1275 int socket_id;
1276 size_t addrlen;
1277 size_t size;
1278 fibril_rwlock_t lock;
1279 ipc_call_t answer;
1280 size_t answer_count;
1281 tcp_socket_data_t *socket_data;
1282 socket_core_t *socket;
1283 packet_dimension_t *packet_dimension;
1284
1285 /*
1286 * Accept the connection
1287 * - Answer the first IPC_M_CONNECT_ME_TO call.
1288 */
1289 res = EOK;
1290 answer_count = 0;
1291
1292 socket_cores_initialize(&local_sockets);
1293 fibril_rwlock_initialize(&lock);
1294
1295 while (keep_on_going) {
1296
1297 /* Answer the call */
1298 answer_call(callid, res, &answer, answer_count);
1299 /* Refresh data */
1300 refresh_answer(&answer, &answer_count);
1301 /* Get the next call */
1302 callid = async_get_call(&call);
1303
1304 /* Process the call */
1305 switch (IPC_GET_IMETHOD(call)) {
1306 case IPC_M_PHONE_HUNGUP:
1307 keep_on_going = false;
1308 res = EHANGUP;
1309 break;
1310
1311 case NET_SOCKET:
1312 socket_data =
1313 (tcp_socket_data_t *) malloc(sizeof(*socket_data));
1314 if (!socket_data) {
1315 res = ENOMEM;
1316 break;
1317 }
1318
1319 tcp_initialize_socket_data(socket_data);
1320 socket_data->local_lock = &lock;
1321 socket_data->local_sockets = &local_sockets;
1322 fibril_rwlock_write_lock(&lock);
1323 socket_id = SOCKET_GET_SOCKET_ID(call);
1324 res = socket_create(&local_sockets, app_phone,
1325 socket_data, &socket_id);
1326 SOCKET_SET_SOCKET_ID(answer, socket_id);
1327 fibril_rwlock_write_unlock(&lock);
1328 if (res != EOK) {
1329 free(socket_data);
1330 break;
1331 }
1332 if (tl_get_ip_packet_dimension(tcp_globals.ip_phone,
1333 &tcp_globals.dimensions, DEVICE_INVALID_ID,
1334 &packet_dimension) == EOK) {
1335 SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
1336 ((packet_dimension->content <
1337 socket_data->data_fragment_size) ?
1338 packet_dimension->content :
1339 socket_data->data_fragment_size));
1340 }
1341// SOCKET_SET_DATA_FRAGMENT_SIZE(answer, MAX_TCP_FRAGMENT_SIZE);
1342 SOCKET_SET_HEADER_SIZE(answer, TCP_HEADER_SIZE);
1343 answer_count = 3;
1344 break;
1345
1346 case NET_SOCKET_BIND:
1347 res = async_data_write_accept((void **) &addr, false,
1348 0, 0, 0, &addrlen);
1349 if (res != EOK)
1350 break;
1351 fibril_rwlock_write_lock(&tcp_globals.lock);
1352 fibril_rwlock_write_lock(&lock);
1353 res = socket_bind(&local_sockets, &tcp_globals.sockets,
1354 SOCKET_GET_SOCKET_ID(call), addr, addrlen,
1355 TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
1356 tcp_globals.last_used_port);
1357 if (res == EOK) {
1358 socket = socket_cores_find(&local_sockets,
1359 SOCKET_GET_SOCKET_ID(call));
1360 if (socket) {
1361 socket_data = (tcp_socket_data_t *)
1362 socket->specific_data;
1363 assert(socket_data);
1364 socket_data->state = TCP_SOCKET_LISTEN;
1365 }
1366 }
1367 fibril_rwlock_write_unlock(&lock);
1368 fibril_rwlock_write_unlock(&tcp_globals.lock);
1369 free(addr);
1370 break;
1371
1372 case NET_SOCKET_LISTEN:
1373 fibril_rwlock_read_lock(&tcp_globals.lock);
1374// fibril_rwlock_write_lock(&tcp_globals.lock);
1375 fibril_rwlock_write_lock(&lock);
1376 res = tcp_listen_message(&local_sockets,
1377 SOCKET_GET_SOCKET_ID(call),
1378 SOCKET_GET_BACKLOG(call));
1379 fibril_rwlock_write_unlock(&lock);
1380// fibril_rwlock_write_unlock(&tcp_globals.lock);
1381 fibril_rwlock_read_unlock(&tcp_globals.lock);
1382 break;
1383
1384 case NET_SOCKET_CONNECT:
1385 res = async_data_write_accept((void **) &addr, false,
1386 0, 0, 0, &addrlen);
1387 if (res != EOK)
1388 break;
1389 /*
1390 * The global lock may be released in the
1391 * tcp_connect_message() function.
1392 */
1393 fibril_rwlock_write_lock(&tcp_globals.lock);
1394 fibril_rwlock_write_lock(&lock);
1395 res = tcp_connect_message(&local_sockets,
1396 SOCKET_GET_SOCKET_ID(call), addr, addrlen);
1397 if (res != EOK) {
1398 fibril_rwlock_write_unlock(&lock);
1399 fibril_rwlock_write_unlock(&tcp_globals.lock);
1400 free(addr);
1401 }
1402 break;
1403
1404 case NET_SOCKET_ACCEPT:
1405 fibril_rwlock_read_lock(&tcp_globals.lock);
1406 fibril_rwlock_write_lock(&lock);
1407 res = tcp_accept_message(&local_sockets,
1408 SOCKET_GET_SOCKET_ID(call),
1409 SOCKET_GET_NEW_SOCKET_ID(call), &size, &addrlen);
1410 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
1411 fibril_rwlock_write_unlock(&lock);
1412 fibril_rwlock_read_unlock(&tcp_globals.lock);
1413 if (res > 0) {
1414 SOCKET_SET_SOCKET_ID(answer, res);
1415 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
1416 answer_count = 3;
1417 }
1418 break;
1419
1420 case NET_SOCKET_SEND:
1421 fibril_rwlock_read_lock(&tcp_globals.lock);
1422 fibril_rwlock_write_lock(&lock);
1423 res = tcp_send_message(&local_sockets,
1424 SOCKET_GET_SOCKET_ID(call),
1425 SOCKET_GET_DATA_FRAGMENTS(call), &size,
1426 SOCKET_GET_FLAGS(call));
1427 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
1428 if (res != EOK) {
1429 fibril_rwlock_write_unlock(&lock);
1430 fibril_rwlock_read_unlock(&tcp_globals.lock);
1431 } else {
1432 answer_count = 2;
1433 }
1434 break;
1435
1436 case NET_SOCKET_SENDTO:
1437 res = async_data_write_accept((void **) &addr, false,
1438 0, 0, 0, &addrlen);
1439 if (res != EOK)
1440 break;
1441 fibril_rwlock_read_lock(&tcp_globals.lock);
1442 fibril_rwlock_write_lock(&lock);
1443 res = tcp_send_message(&local_sockets,
1444 SOCKET_GET_SOCKET_ID(call),
1445 SOCKET_GET_DATA_FRAGMENTS(call), &size,
1446 SOCKET_GET_FLAGS(call));
1447 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
1448 if (res != EOK) {
1449 fibril_rwlock_write_unlock(&lock);
1450 fibril_rwlock_read_unlock(&tcp_globals.lock);
1451 } else {
1452 answer_count = 2;
1453 }
1454 free(addr);
1455 break;
1456
1457 case NET_SOCKET_RECV:
1458 fibril_rwlock_read_lock(&tcp_globals.lock);
1459 fibril_rwlock_write_lock(&lock);
1460 res = tcp_recvfrom_message(&local_sockets,
1461 SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
1462 NULL);
1463 fibril_rwlock_write_unlock(&lock);
1464 fibril_rwlock_read_unlock(&tcp_globals.lock);
1465 if (res > 0) {
1466 SOCKET_SET_READ_DATA_LENGTH(answer, res);
1467 answer_count = 1;
1468 res = EOK;
1469 }
1470 break;
1471
1472 case NET_SOCKET_RECVFROM:
1473 fibril_rwlock_read_lock(&tcp_globals.lock);
1474 fibril_rwlock_write_lock(&lock);
1475 res = tcp_recvfrom_message(&local_sockets,
1476 SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
1477 &addrlen);
1478 fibril_rwlock_write_unlock(&lock);
1479 fibril_rwlock_read_unlock(&tcp_globals.lock);
1480 if (res > 0) {
1481 SOCKET_SET_READ_DATA_LENGTH(answer, res);
1482 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
1483 answer_count = 3;
1484 res = EOK;
1485 }
1486 break;
1487
1488 case NET_SOCKET_CLOSE:
1489 fibril_rwlock_write_lock(&tcp_globals.lock);
1490 fibril_rwlock_write_lock(&lock);
1491 res = tcp_close_message(&local_sockets,
1492 SOCKET_GET_SOCKET_ID(call));
1493 if (res != EOK) {
1494 fibril_rwlock_write_unlock(&lock);
1495 fibril_rwlock_write_unlock(&tcp_globals.lock);
1496 }
1497 break;
1498
1499 case NET_SOCKET_GETSOCKOPT:
1500 case NET_SOCKET_SETSOCKOPT:
1501 default:
1502 res = ENOTSUP;
1503 break;
1504 }
1505 }
1506
1507 /* Release the application phone */
1508 async_hangup(app_phone);
1509
1510 printf("release\n");
1511 /* Release all local sockets */
1512 socket_cores_release(tcp_globals.net_phone, &local_sockets,
1513 &tcp_globals.sockets, tcp_free_socket_data);
1514
1515 return EOK;
1516}
1517
1518int tcp_timeout(void *data)
1519{
1520 tcp_timeout_t *timeout = data;
1521 int keep_write_lock = false;
1522 socket_core_t *socket;
1523 tcp_socket_data_t *socket_data;
1524
1525 assert(timeout);
1526
1527 /* Sleep the given timeout */
1528 async_usleep(timeout->timeout);
1529 /* Lock the globals */
1530 if (timeout->globals_read_only)
1531 fibril_rwlock_read_lock(&tcp_globals.lock);
1532 else
1533 fibril_rwlock_write_lock(&tcp_globals.lock);
1534
1535 /* Find the pending operation socket */
1536 socket = socket_port_find(&tcp_globals.sockets, timeout->port,
1537 timeout->key, timeout->key_length);
1538 if (!socket || (socket->socket_id != timeout->socket_id))
1539 goto out;
1540
1541 socket_data = (tcp_socket_data_t *) socket->specific_data;
1542 assert(socket_data);
1543 if (socket_data->local_sockets != timeout->local_sockets)
1544 goto out;
1545
1546 fibril_rwlock_write_lock(socket_data->local_lock);
1547 if (timeout->sequence_number) {
1548 /* Increase the timeout counter */
1549 socket_data->timeout_count++;
1550 if (socket_data->timeout_count == TCP_MAX_TIMEOUTS) {
1551 /* TODO release as connection lost */
1552 //tcp_refresh_socket_data(socket_data);
1553 fibril_rwlock_write_unlock(socket_data->local_lock);
1554 } else {
1555 /* Retransmit */
1556// tcp_retransmit_packet(socket,
1557// socket_data, timeout->sequence_number);
1558 fibril_rwlock_write_unlock(socket_data->local_lock);
1559 }
1560 } else {
1561 fibril_mutex_lock(&socket_data->operation.mutex);
1562 /* Set the timeout operation result if state not changed */
1563 if (socket_data->state == timeout->state) {
1564 socket_data->operation.result = ETIMEOUT;
1565
1566 /* Notify the main fibril */
1567 fibril_condvar_signal(&socket_data->operation.condvar);
1568
1569 /* Keep the global write lock */
1570 keep_write_lock = true;
1571 } else {
1572 /*
1573 * Operation is ok, do nothing.
1574 * Unlocking from now on, so the unlocking
1575 * order does not matter.
1576 */
1577 fibril_rwlock_write_unlock(socket_data->local_lock);
1578 }
1579 fibril_mutex_unlock(&socket_data->operation.mutex);
1580 }
1581
1582out:
1583 /* Unlock only if no socket */
1584 if (timeout->globals_read_only)
1585 fibril_rwlock_read_unlock(&tcp_globals.lock);
1586 else if (!keep_write_lock)
1587 /* Release if not desired */
1588 fibril_rwlock_write_unlock(&tcp_globals.lock);
1589
1590 /* Release the timeout structure */
1591 free(timeout);
1592 return EOK;
1593}
1594
1595int tcp_release_after_timeout(void *data)
1596{
1597 tcp_timeout_t *timeout = data;
1598 socket_core_t *socket;
1599 tcp_socket_data_t *socket_data;
1600 fibril_rwlock_t *local_lock;
1601
1602 assert(timeout);
1603
1604 /* Sleep the given timeout */
1605 async_usleep(timeout->timeout);
1606
1607 /* Lock the globals */
1608 fibril_rwlock_write_lock(&tcp_globals.lock);
1609
1610 /* Find the pending operation socket */
1611 socket = socket_port_find(&tcp_globals.sockets, timeout->port,
1612 timeout->key, timeout->key_length);
1613
1614 if (socket && (socket->socket_id == timeout->socket_id)) {
1615 socket_data = (tcp_socket_data_t *) socket->specific_data;
1616 assert(socket_data);
1617 if (socket_data->local_sockets == timeout->local_sockets) {
1618 local_lock = socket_data->local_lock;
1619 fibril_rwlock_write_lock(local_lock);
1620 socket_destroy(tcp_globals.net_phone,
1621 timeout->socket_id, timeout->local_sockets,
1622 &tcp_globals.sockets, tcp_free_socket_data);
1623 fibril_rwlock_write_unlock(local_lock);
1624 }
1625 }
1626
1627 /* Unlock the globals */
1628 fibril_rwlock_write_unlock(&tcp_globals.lock);
1629
1630 /* Release the timeout structure */
1631 free(timeout);
1632
1633 return EOK;
1634}
1635
1636void tcp_retransmit_packet(socket_core_t *socket, tcp_socket_data_t *
1637 socket_data, size_t sequence_number)
1638{
1639 packet_t *packet;
1640 packet_t *copy;
1641 size_t data_length;
1642
1643 assert(socket);
1644 assert(socket_data);
1645 assert(socket->specific_data == socket_data);
1646
1647 /* Sent packet? */
1648 packet = pq_find(socket_data->outgoing, sequence_number);
1649 printf("retransmit %d\n", packet_get_id(packet));
1650 if (packet) {
1651 pq_get_order(packet, NULL, &data_length);
1652 copy = tcp_prepare_copy(socket, socket_data, packet,
1653 data_length, sequence_number);
1654 fibril_rwlock_write_unlock(socket_data->local_lock);
1655// printf("r send %d\n", packet_get_id(packet));
1656 if (copy)
1657 tcp_send_packets(socket_data->device_id, copy);
1658 } else {
1659 fibril_rwlock_write_unlock(socket_data->local_lock);
1660 }
1661}
1662
1663int tcp_listen_message(socket_cores_t *local_sockets, int socket_id,
1664 int backlog)
1665{
1666 socket_core_t *socket;
1667 tcp_socket_data_t *socket_data;
1668
1669 assert(local_sockets);
1670
1671 if (backlog < 0)
1672 return EINVAL;
1673
1674 /* Find the socket */
1675 socket = socket_cores_find(local_sockets, socket_id);
1676 if (!socket)
1677 return ENOTSOCK;
1678
1679 /* Get the socket specific data */
1680 socket_data = (tcp_socket_data_t *) socket->specific_data;
1681 assert(socket_data);
1682
1683 /* Set the backlog */
1684 socket_data->backlog = backlog;
1685
1686 return EOK;
1687}
1688
1689int tcp_connect_message(socket_cores_t *local_sockets, int socket_id,
1690 struct sockaddr *addr, socklen_t addrlen)
1691{
1692 socket_core_t *socket;
1693 int rc;
1694
1695 assert(local_sockets);
1696 assert(addr);
1697 assert(addrlen > 0);
1698
1699 /* Find the socket */
1700 socket = socket_cores_find(local_sockets, socket_id);
1701 if (!socket)
1702 return ENOTSOCK;
1703
1704 rc = tcp_connect_core(socket, local_sockets, addr, addrlen);
1705 if (rc != EOK) {
1706 tcp_free_socket_data(socket);
1707 /* Unbind if bound */
1708 if (socket->port > 0) {
1709 socket_ports_exclude(&tcp_globals.sockets,
1710 socket->port, free);
1711 socket->port = 0;
1712 }
1713 }
1714 return rc;
1715}
1716
1717int tcp_connect_core(socket_core_t *socket, socket_cores_t *local_sockets,
1718 struct sockaddr *addr, socklen_t addrlen)
1719{
1720 tcp_socket_data_t *socket_data;
1721 packet_t *packet;
1722 int rc;
1723
1724 assert(socket);
1725 assert(addr);
1726 assert(addrlen > 0);
1727
1728 /* Get the socket specific data */
1729 socket_data = (tcp_socket_data_t *) socket->specific_data;
1730 assert(socket_data);
1731 assert(socket->specific_data == socket_data);
1732 if ((socket_data->state != TCP_SOCKET_INITIAL) &&
1733 ((socket_data->state != TCP_SOCKET_LISTEN) ||
1734 (socket->port <= 0)))
1735 return EINVAL;
1736
1737 /* Get the destination port */
1738 rc = tl_get_address_port(addr, addrlen, &socket_data->dest_port);
1739 if (rc != EOK)
1740 return rc;
1741
1742 if (socket->port <= 0) {
1743 /* Try to find a free port */
1744 rc = socket_bind_free_port(&tcp_globals.sockets, socket,
1745 TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
1746 tcp_globals.last_used_port);
1747 if (rc != EOK)
1748 return rc;
1749 /* Set the next port as the search starting port number */
1750 tcp_globals.last_used_port = socket->port;
1751 }
1752
1753 rc = ip_get_route_req(tcp_globals.ip_phone, IPPROTO_TCP,
1754 addr, addrlen, &socket_data->device_id,
1755 &socket_data->pseudo_header, &socket_data->headerlen);
1756 if (rc != EOK)
1757 return rc;
1758
1759 /* Create the notification packet */
1760 rc = tcp_create_notification_packet(&packet, socket, socket_data, 1, 0);
1761 if (rc != EOK)
1762 return rc;
1763
1764 /* Unlock the globals and wait for an operation */
1765 fibril_rwlock_write_unlock(&tcp_globals.lock);
1766
1767 socket_data->addr = addr;
1768 socket_data->addrlen = addrlen;
1769
1770 /* Send the packet */
1771
1772 if (((rc = tcp_queue_packet(socket, socket_data, packet, 1)) != EOK) ||
1773 ((rc = tcp_prepare_timeout(tcp_timeout, socket, socket_data, 0,
1774 TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false)) !=
1775 EOK)) {
1776 socket_data->addr = NULL;
1777 socket_data->addrlen = 0;
1778 fibril_rwlock_write_lock(&tcp_globals.lock);
1779 } else {
1780 packet = tcp_get_packets_to_send(socket, socket_data);
1781 if (packet) {
1782 fibril_mutex_lock(&socket_data->operation.mutex);
1783 fibril_rwlock_write_unlock(socket_data->local_lock);
1784
1785 socket_data->state = TCP_SOCKET_SYN_SENT;
1786
1787 /* Send the packet */
1788 printf("connecting %d\n", packet_get_id(packet));
1789 tcp_send_packets(socket_data->device_id, packet);
1790
1791 /* Wait for a reply */
1792 fibril_condvar_wait(&socket_data->operation.condvar,
1793 &socket_data->operation.mutex);
1794 rc = socket_data->operation.result;
1795 if (rc != EOK) {
1796 socket_data->addr = NULL;
1797 socket_data->addrlen = 0;
1798 }
1799 } else {
1800 socket_data->addr = NULL;
1801 socket_data->addrlen = 0;
1802 rc = EINTR;
1803 }
1804 }
1805
1806 fibril_mutex_unlock(&socket_data->operation.mutex);
1807 return rc;
1808}
1809
1810int tcp_queue_prepare_packet(socket_core_t *socket,
1811 tcp_socket_data_t *socket_data, packet_t *packet, size_t data_length)
1812{
1813 tcp_header_t *header;
1814 int rc;
1815
1816 assert(socket);
1817 assert(socket_data);
1818 assert(socket->specific_data == socket_data);
1819
1820 /* Get TCP header */
1821 header = (tcp_header_t *) packet_get_data(packet);
1822 if (!header)
1823 return NO_DATA;
1824
1825 header->destination_port = htons(socket_data->dest_port);
1826 header->source_port = htons(socket->port);
1827 header->sequence_number = htonl(socket_data->next_outgoing);
1828
1829 rc = packet_set_addr(packet, NULL, (uint8_t *) socket_data->addr,
1830 socket_data->addrlen);
1831 if (rc != EOK)
1832 return tcp_release_and_return(packet, EINVAL);
1833
1834 /* Remember the outgoing FIN */
1835 if (GET_TCP_HEADER_FINALIZE(header))
1836 socket_data->fin_outgoing = socket_data->next_outgoing;
1837
1838 return EOK;
1839}
1840
1841int tcp_queue_packet(socket_core_t *socket, tcp_socket_data_t *socket_data,
1842 packet_t *packet, size_t data_length)
1843{
1844 int rc;
1845
1846 assert(socket);
1847 assert(socket_data);
1848 assert(socket->specific_data == socket_data);
1849
1850 rc = tcp_queue_prepare_packet(socket, socket_data, packet, data_length);
1851 if (rc != EOK)
1852 return rc;
1853
1854 rc = pq_add(&socket_data->outgoing, packet, socket_data->next_outgoing,
1855 data_length);
1856 if (rc != EOK)
1857 return tcp_release_and_return(packet, rc);
1858
1859 socket_data->next_outgoing += data_length;
1860 return EOK;
1861}
1862
1863packet_t *tcp_get_packets_to_send(socket_core_t *socket, tcp_socket_data_t *
1864 socket_data)
1865{
1866 packet_t *packet;
1867 packet_t *copy;
1868 packet_t *sending = NULL;
1869 packet_t *previous = NULL;
1870 size_t data_length;
1871 int rc;
1872
1873 assert(socket);
1874 assert(socket_data);
1875 assert(socket->specific_data == socket_data);
1876
1877 packet = pq_find(socket_data->outgoing, socket_data->last_outgoing + 1);
1878 while (packet) {
1879 pq_get_order(packet, NULL, &data_length);
1880
1881 /*
1882 * Send only if fits into the window, respecting the possible
1883 * overflow.
1884 */
1885 if (!IS_IN_INTERVAL_OVERFLOW(
1886 (uint32_t) socket_data->last_outgoing,
1887 (uint32_t) (socket_data->last_outgoing + data_length),
1888 (uint32_t) (socket_data->expected + socket_data->treshold)))
1889 break;
1890
1891 copy = tcp_prepare_copy(socket, socket_data, packet,
1892 data_length, socket_data->last_outgoing + 1);
1893 if (!copy)
1894 return sending;
1895
1896 if (!sending) {
1897 sending = copy;
1898 } else {
1899 rc = pq_insert_after(previous, copy);
1900 if (rc != EOK) {
1901 pq_release_remote(tcp_globals.net_phone,
1902 packet_get_id(copy));
1903 return sending;
1904 }
1905 }
1906
1907 previous = copy;
1908 packet = pq_next(packet);
1909
1910 /* Overflow occurred? */
1911 if (!packet &&
1912 (socket_data->last_outgoing > socket_data->next_outgoing)) {
1913 printf("gpts overflow\n");
1914 /* Continue from the beginning */
1915 packet = socket_data->outgoing;
1916 }
1917 socket_data->last_outgoing += data_length;
1918 }
1919
1920 return sending;
1921}
1922
1923packet_t *tcp_send_prepare_packet(socket_core_t *socket, tcp_socket_data_t *
1924 socket_data, packet_t *packet, size_t data_length, size_t sequence_number)
1925{
1926 tcp_header_t *header;
1927 uint32_t checksum;
1928 int rc;
1929
1930 assert(socket);
1931 assert(socket_data);
1932 assert(socket->specific_data == socket_data);
1933
1934 /* Adjust the pseudo header */
1935 rc = ip_client_set_pseudo_header_data_length(socket_data->pseudo_header,
1936 socket_data->headerlen, packet_get_data_length(packet));
1937 if (rc != EOK) {
1938 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
1939 return NULL;
1940 }
1941
1942 /* Get the header */
1943 header = (tcp_header_t *) packet_get_data(packet);
1944 if (!header) {
1945 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
1946 return NULL;
1947 }
1948 assert(ntohl(header->sequence_number) == sequence_number);
1949
1950 /* Adjust the header */
1951 if (socket_data->next_incoming) {
1952 header->acknowledgement_number =
1953 htonl(socket_data->next_incoming);
1954 SET_TCP_HEADER_ACKNOWLEDGE(header, 1);
1955 }
1956 header->window = htons(socket_data->window);
1957
1958 /* Checksum */
1959 header->checksum = 0;
1960 checksum = compute_checksum(0, socket_data->pseudo_header,
1961 socket_data->headerlen);
1962 checksum = compute_checksum(checksum,
1963 (uint8_t *) packet_get_data(packet),
1964 packet_get_data_length(packet));
1965 header->checksum = htons(flip_checksum(compact_checksum(checksum)));
1966
1967 /* Prepare the packet */
1968 rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0);
1969 if (rc != EOK) {
1970 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
1971 return NULL;
1972 }
1973
1974 rc = tcp_prepare_timeout(tcp_timeout, socket, socket_data,
1975 sequence_number, socket_data->state, socket_data->timeout, true);
1976 if (rc != EOK) {
1977 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
1978 return NULL;
1979 }
1980
1981 return packet;
1982}
1983
1984packet_t *tcp_prepare_copy(socket_core_t *socket, tcp_socket_data_t *
1985 socket_data, packet_t *packet, size_t data_length, size_t sequence_number)
1986{
1987 packet_t *copy;
1988
1989 assert(socket);
1990 assert(socket_data);
1991 assert(socket->specific_data == socket_data);
1992
1993 /* Make a copy of the packet */
1994 copy = packet_get_copy(tcp_globals.net_phone, packet);
1995 if (!copy)
1996 return NULL;
1997
1998 return tcp_send_prepare_packet(socket, socket_data, copy, data_length,
1999 sequence_number);
2000}
2001
2002void tcp_send_packets(device_id_t device_id, packet_t *packet)
2003{
2004 packet_t *next;
2005
2006 while (packet) {
2007 next = pq_detach(packet);
2008 ip_send_msg(tcp_globals.ip_phone, device_id, packet,
2009 SERVICE_TCP, 0);
2010 packet = next;
2011 }
2012}
2013
2014void tcp_prepare_operation_header(socket_core_t *socket,
2015 tcp_socket_data_t *socket_data, tcp_header_t *header, int synchronize,
2016 int finalize)
2017{
2018 assert(socket);
2019 assert(socket_data);
2020 assert(socket->specific_data == socket_data);
2021 assert(header);
2022
2023 bzero(header, sizeof(*header));
2024 header->source_port = htons(socket->port);
2025 header->source_port = htons(socket_data->dest_port);
2026 SET_TCP_HEADER_LENGTH(header,
2027 TCP_COMPUTE_HEADER_LENGTH(sizeof(*header)));
2028 SET_TCP_HEADER_SYNCHRONIZE(header, synchronize);
2029 SET_TCP_HEADER_FINALIZE(header, finalize);
2030}
2031
2032int tcp_prepare_timeout(int (*timeout_function)(void *tcp_timeout_t),
2033 socket_core_t *socket, tcp_socket_data_t *socket_data,
2034 size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout,
2035 int globals_read_only)
2036{
2037 tcp_timeout_t *operation_timeout;
2038 fid_t fibril;
2039
2040 assert(socket);
2041 assert(socket_data);
2042 assert(socket->specific_data == socket_data);
2043
2044 /* Prepare the timeout with key bundle structure */
2045 operation_timeout = malloc(sizeof(*operation_timeout) +
2046 socket->key_length + 1);
2047 if (!operation_timeout)
2048 return ENOMEM;
2049
2050 bzero(operation_timeout, sizeof(*operation_timeout));
2051 operation_timeout->globals_read_only = globals_read_only;
2052 operation_timeout->port = socket->port;
2053 operation_timeout->local_sockets = socket_data->local_sockets;
2054 operation_timeout->socket_id = socket->socket_id;
2055 operation_timeout->timeout = timeout;
2056 operation_timeout->sequence_number = sequence_number;
2057 operation_timeout->state = state;
2058
2059 /* Copy the key */
2060 operation_timeout->key = ((uint8_t *) operation_timeout) +
2061 sizeof(*operation_timeout);
2062 operation_timeout->key_length = socket->key_length;
2063 memcpy(operation_timeout->key, socket->key, socket->key_length);
2064 operation_timeout->key[operation_timeout->key_length] = '\0';
2065
2066 /* Prepare the timeouting thread */
2067 fibril = fibril_create(timeout_function, operation_timeout);
2068 if (!fibril) {
2069 free(operation_timeout);
2070 return ENOMEM;
2071 }
2072
2073// fibril_mutex_lock(&socket_data->operation.mutex);
2074 /* Start the timeout fibril */
2075 fibril_add_ready(fibril);
2076 //socket_data->state = state;
2077 return EOK;
2078}
2079
2080int tcp_recvfrom_message(socket_cores_t *local_sockets, int socket_id,
2081 int flags, size_t *addrlen)
2082{
2083 socket_core_t *socket;
2084 tcp_socket_data_t *socket_data;
2085 int packet_id;
2086 packet_t *packet;
2087 size_t length;
2088 int rc;
2089
2090 assert(local_sockets);
2091
2092 /* Find the socket */
2093 socket = socket_cores_find(local_sockets, socket_id);
2094 if (!socket)
2095 return ENOTSOCK;
2096
2097 /* Get the socket specific data */
2098 if (!socket->specific_data)
2099 return NO_DATA;
2100
2101 socket_data = (tcp_socket_data_t *) socket->specific_data;
2102
2103 /* Check state */
2104 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) &&
2105 (socket_data->state != TCP_SOCKET_CLOSE_WAIT))
2106 return ENOTCONN;
2107
2108 /* Send the source address if desired */
2109 if (addrlen) {
2110 rc = data_reply(socket_data->addr, socket_data->addrlen);
2111 if (rc != EOK)
2112 return rc;
2113 *addrlen = socket_data->addrlen;
2114 }
2115
2116 /* Get the next received packet */
2117 packet_id = dyn_fifo_value(&socket->received);
2118 if (packet_id < 0)
2119 return NO_DATA;
2120
2121 rc = packet_translate_remote(tcp_globals.net_phone, &packet, packet_id);
2122 if (rc != EOK)
2123 return rc;
2124
2125 /* Reply the packets */
2126 rc = socket_reply_packets(packet, &length);
2127 if (rc != EOK)
2128 return rc;
2129
2130 /* Release the packet */
2131 dyn_fifo_pop(&socket->received);
2132 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
2133
2134 /* Return the total length */
2135 return (int) length;
2136}
2137
2138int tcp_send_message(socket_cores_t *local_sockets, int socket_id,
2139 int fragments, size_t *data_fragment_size, int flags)
2140{
2141 socket_core_t *socket;
2142 tcp_socket_data_t *socket_data;
2143 packet_dimension_t *packet_dimension;
2144 packet_t *packet;
2145 size_t total_length;
2146 tcp_header_t *header;
2147 int index;
2148 int result;
2149 int rc;
2150
2151 assert(local_sockets);
2152 assert(data_fragment_size);
2153
2154 /* Find the socket */
2155 socket = socket_cores_find(local_sockets, socket_id);
2156 if (!socket)
2157 return ENOTSOCK;
2158
2159 /* Get the socket specific data */
2160 if (!socket->specific_data)
2161 return NO_DATA;
2162
2163 socket_data = (tcp_socket_data_t *) socket->specific_data;
2164
2165 /* Check state */
2166 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) &&
2167 (socket_data->state != TCP_SOCKET_CLOSE_WAIT))
2168 return ENOTCONN;
2169
2170 rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
2171 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
2172 if (rc != EOK)
2173 return rc;
2174
2175 *data_fragment_size =
2176 ((packet_dimension->content < socket_data->data_fragment_size) ?
2177 packet_dimension->content : socket_data->data_fragment_size);
2178
2179 for (index = 0; index < fragments; index++) {
2180 /* Read the data fragment */
2181 result = tl_socket_read_packet_data(tcp_globals.net_phone,
2182 &packet, TCP_HEADER_SIZE, packet_dimension,
2183 socket_data->addr, socket_data->addrlen);
2184 if (result < 0)
2185 return result;
2186
2187 total_length = (size_t) result;
2188
2189 /* Prefix the TCP header */
2190 header = PACKET_PREFIX(packet, tcp_header_t);
2191 if (!header)
2192 return tcp_release_and_return(packet, ENOMEM);
2193
2194 tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
2195 rc = tcp_queue_packet(socket, socket_data, packet, total_length);
2196 if (rc != EOK)
2197 return rc;
2198 }
2199
2200 /* Flush packets */
2201 packet = tcp_get_packets_to_send(socket, socket_data);
2202 fibril_rwlock_write_unlock(socket_data->local_lock);
2203 fibril_rwlock_read_unlock(&tcp_globals.lock);
2204
2205 if (packet) {
2206 /* Send the packet */
2207 tcp_send_packets(socket_data->device_id, packet);
2208 }
2209
2210 return EOK;
2211}
2212
2213int
2214tcp_close_message(socket_cores_t *local_sockets, int socket_id)
2215{
2216 socket_core_t *socket;
2217 tcp_socket_data_t *socket_data;
2218 packet_t *packet;
2219 int rc;
2220
2221 /* Find the socket */
2222 socket = socket_cores_find(local_sockets, socket_id);
2223 if (!socket)
2224 return ENOTSOCK;
2225
2226 /* Get the socket specific data */
2227 socket_data = (tcp_socket_data_t *) socket->specific_data;
2228 assert(socket_data);
2229
2230 /* Check state */
2231 switch (socket_data->state) {
2232 case TCP_SOCKET_ESTABLISHED:
2233 socket_data->state = TCP_SOCKET_FIN_WAIT_1;
2234 break;
2235
2236 case TCP_SOCKET_CLOSE_WAIT:
2237 socket_data->state = TCP_SOCKET_LAST_ACK;
2238 break;
2239
2240// case TCP_SOCKET_LISTEN:
2241
2242 default:
2243 /* Just destroy */
2244 rc = socket_destroy(tcp_globals.net_phone, socket_id,
2245 local_sockets, &tcp_globals.sockets,
2246 tcp_free_socket_data);
2247 if (rc == EOK) {
2248 fibril_rwlock_write_unlock(socket_data->local_lock);
2249 fibril_rwlock_write_unlock(&tcp_globals.lock);
2250 }
2251 return rc;
2252 }
2253
2254 /*
2255 * Send FIN.
2256 * TODO should I wait to complete?
2257 */
2258
2259 /* Create the notification packet */
2260 rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1);
2261 if (rc != EOK)
2262 return rc;
2263
2264 /* Send the packet */
2265 rc = tcp_queue_packet(socket, socket_data, packet, 1);
2266 if (rc != EOK)
2267 return rc;
2268
2269 /* Flush packets */
2270 packet = tcp_get_packets_to_send(socket, socket_data);
2271 fibril_rwlock_write_unlock(socket_data->local_lock);
2272 fibril_rwlock_write_unlock(&tcp_globals.lock);
2273
2274 if (packet) {
2275 /* Send the packet */
2276 tcp_send_packets(socket_data->device_id, packet);
2277 }
2278
2279 return EOK;
2280}
2281
2282int tcp_create_notification_packet(packet_t **packet, socket_core_t *socket,
2283 tcp_socket_data_t *socket_data, int synchronize, int finalize)
2284{
2285 packet_dimension_t *packet_dimension;
2286 tcp_header_t *header;
2287 int rc;
2288
2289 assert(packet);
2290
2291 /* Get the device packet dimension */
2292 rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
2293 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
2294 if (rc != EOK)
2295 return rc;
2296
2297 /* Get a new packet */
2298 *packet = packet_get_4_remote(tcp_globals.net_phone, TCP_HEADER_SIZE,
2299 packet_dimension->addr_len, packet_dimension->prefix,
2300 packet_dimension->suffix);
2301
2302 if (!*packet)
2303 return ENOMEM;
2304
2305 /* Allocate space in the packet */
2306 header = PACKET_SUFFIX(*packet, tcp_header_t);
2307 if (!header)
2308 tcp_release_and_return(*packet, ENOMEM);
2309
2310 tcp_prepare_operation_header(socket, socket_data, header, synchronize,
2311 finalize);
2312
2313 return EOK;
2314}
2315
2316int tcp_accept_message(socket_cores_t *local_sockets, int socket_id,
2317 int new_socket_id, size_t *data_fragment_size, size_t *addrlen)
2318{
2319 socket_core_t *accepted;
2320 socket_core_t *socket;
2321 tcp_socket_data_t *socket_data;
2322 packet_dimension_t *packet_dimension;
2323 int rc;
2324
2325 assert(local_sockets);
2326 assert(data_fragment_size);
2327 assert(addrlen);
2328
2329 /* Find the socket */
2330 socket = socket_cores_find(local_sockets, socket_id);
2331 if (!socket)
2332 return ENOTSOCK;
2333
2334 /* Get the socket specific data */
2335 socket_data = (tcp_socket_data_t *) socket->specific_data;
2336 assert(socket_data);
2337
2338 /* Check state */
2339 if (socket_data->state != TCP_SOCKET_LISTEN)
2340 return EINVAL;
2341
2342 do {
2343 socket_id = dyn_fifo_value(&socket->accepted);
2344 if (socket_id < 0)
2345 return ENOTSOCK;
2346 socket_id *= -1;
2347
2348 accepted = socket_cores_find(local_sockets, socket_id);
2349 if (!accepted)
2350 return ENOTSOCK;
2351
2352 /* Get the socket specific data */
2353 socket_data = (tcp_socket_data_t *) accepted->specific_data;
2354 assert(socket_data);
2355 /* TODO can it be in another state? */
2356 if (socket_data->state == TCP_SOCKET_ESTABLISHED) {
2357 rc = data_reply(socket_data->addr,
2358 socket_data->addrlen);
2359 if (rc != EOK)
2360 return rc;
2361 rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
2362 &tcp_globals.dimensions, socket_data->device_id,
2363 &packet_dimension);
2364 if (rc != EOK)
2365 return rc;
2366 *addrlen = socket_data->addrlen;
2367
2368 *data_fragment_size =
2369 ((packet_dimension->content <
2370 socket_data->data_fragment_size) ?
2371 packet_dimension->content :
2372 socket_data->data_fragment_size);
2373
2374 if (new_socket_id > 0) {
2375 rc = socket_cores_update(local_sockets,
2376 accepted->socket_id, new_socket_id);
2377 if (rc != EOK)
2378 return rc;
2379 accepted->socket_id = new_socket_id;
2380 }
2381 }
2382 dyn_fifo_pop(&socket->accepted);
2383 } while (socket_data->state != TCP_SOCKET_ESTABLISHED);
2384
2385 printf("ret accept %d\n", accepted->socket_id);
2386 return accepted->socket_id;
2387}
2388
2389void tcp_free_socket_data(socket_core_t *socket)
2390{
2391 tcp_socket_data_t *socket_data;
2392
2393 assert(socket);
2394
2395 printf("destroy_socket %d\n", socket->socket_id);
2396
2397 /* Get the socket specific data */
2398 socket_data = (tcp_socket_data_t *) socket->specific_data;
2399 assert(socket_data);
2400
2401 /* Free the pseudo header */
2402 if (socket_data->pseudo_header) {
2403 if (socket_data->headerlen) {
2404 printf("d pseudo\n");
2405 free(socket_data->pseudo_header);
2406 socket_data->headerlen = 0;
2407 }
2408 socket_data->pseudo_header = NULL;
2409 }
2410
2411 socket_data->headerlen = 0;
2412
2413 /* Free the address */
2414 if (socket_data->addr) {
2415 if (socket_data->addrlen) {
2416 printf("d addr\n");
2417 free(socket_data->addr);
2418 socket_data->addrlen = 0;
2419 }
2420 socket_data->addr = NULL;
2421 }
2422 socket_data->addrlen = 0;
2423}
2424
2425/** Releases the packet and returns the result.
2426 *
2427 * @param[in] packet The packet queue to be released.
2428 * @param[in] result The result to be returned.
2429 * @return The result parameter.
2430 */
2431int tcp_release_and_return(packet_t *packet, int result)
2432{
2433 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
2434 return result;
2435}
2436
2437/** Process IPC messages from the IP module
2438 *
2439 * @param[in] iid Message identifier.
2440 * @param[in,out] icall Message parameters.
2441 *
2442 */
2443static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall)
2444{
2445 packet_t *packet;
2446 int rc;
2447
2448 while (true) {
2449 switch (IPC_GET_IMETHOD(*icall)) {
2450 case NET_TL_RECEIVED:
2451 rc = packet_translate_remote(tcp_globals.net_phone, &packet,
2452 IPC_GET_PACKET(*icall));
2453 if (rc == EOK)
2454 rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet,
2455 SERVICE_TCP, IPC_GET_ERROR(*icall));
2456
2457 async_answer_0(iid, (sysarg_t) rc);
2458 break;
2459 default:
2460 async_answer_0(iid, (sysarg_t) ENOTSUP);
2461 }
2462
2463 iid = async_get_call(icall);
2464 }
2465}
2466
2467/** Initialize the TCP module.
2468 *
2469 * @param[in] net_phone Network module phone.
2470 *
2471 * @return EOK on success.
2472 * @return ENOMEM if there is not enough memory left.
2473 *
2474 */
2475int tl_initialize(int net_phone)
2476{
2477 fibril_rwlock_initialize(&tcp_globals.lock);
2478 fibril_rwlock_write_lock(&tcp_globals.lock);
2479
2480 tcp_globals.net_phone = net_phone;
2481
2482 tcp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
2483 tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
2484 SERVICE_TCP, tcp_receiver);
2485 if (tcp_globals.ip_phone < 0) {
2486 fibril_rwlock_write_unlock(&tcp_globals.lock);
2487 return tcp_globals.ip_phone;
2488 }
2489
2490 int rc = socket_ports_initialize(&tcp_globals.sockets);
2491 if (rc != EOK)
2492 goto out;
2493
2494 rc = packet_dimensions_initialize(&tcp_globals.dimensions);
2495 if (rc != EOK) {
2496 socket_ports_destroy(&tcp_globals.sockets, free);
2497 goto out;
2498 }
2499
2500 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
2501
2502out:
2503 fibril_rwlock_write_unlock(&tcp_globals.lock);
2504 return rc;
2505}
2506
2507int main(int argc, char *argv[])
2508{
2509 return tl_module_start(SERVICE_TCP);
2510}
2511
2512/** @}
2513 */
Note: See TracBrowser for help on using the repository browser.