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

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

Cleanup tpc.

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