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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3ac66f69 was 3ac66f69, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Set socket state to SYN_SENT when sending SYN packet during connect() (fixes connect() not responding to SYN,ACK).

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