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

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

Mark EPARTY for replacement by another error code.

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