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

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

Coding style fixes.

This changeset converts the entire TCP code into HelenOS cstyle and improves
its general legibility by adding vertical spacing and removing unnecessary
clutter. It also attempts to suppress too deep nesting of blocks by
functional-equivalent code restructuralization.

This changeset brings no change in functionality (hopefully), but it should make
it easier to understand and eventually fix TCP 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
45#include <ipc/ipc.h>
46#include <ipc/services.h>
47
48#include <net_err.h>
49#include <net_messages.h>
50#include <net_modules.h>
51#include <adt/dynamic_fifo.h>
52#include <packet/packet_client.h>
53#include <packet_remote.h>
54#include <net_checksum.h>
55#include <in.h>
56#include <in6.h>
57#include <inet.h>
58#include <ip_client.h>
59#include <ip_interface.h>
60#include <ip_protocols.h>
61#include <icmp_client.h>
62#include <icmp_interface.h>
63#include <net_interface.h>
64#include <socket_codes.h>
65#include <socket_errno.h>
66#include <tcp_codes.h>
67#include <socket_core.h>
68#include <socket_messages.h>
69#include <tl_common.h>
70#include <tl_messages.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, tcp_received_msg);
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;
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.