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

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