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

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

Move net_modules.[ch] to the standard library. Note that this functionality is
not directly related to networking so the next step regarding these two files
would be to somehow merge its functionality with what we already have in lib c.

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