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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 457a6f5 was 89e57cee, checked in by Jakub Jermar <jakub@…>, 15 years ago

Cleanup tpc.

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