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

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

Move socket_messages.h to libc's ipc/socket.h

  • Property mode set to 100644
File size: 69.0 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
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>
[e98b1d5]44#include <errno.h>
[c5b59ce]45#include <err.h>
[21580dd]46
47#include <ipc/ipc.h>
48#include <ipc/services.h>
[88e127ee]49#include <ipc/socket.h>
[21580dd]50
[058edb6]51#include <net/socket_codes.h>
[fe5d3c1b]52#include <net/ip_protocols.h>
[e4554d4]53#include <net/in.h>
54#include <net/in6.h>
55#include <net/inet.h>
[058edb6]56
[849ed54]57#include <net_messages.h>
58#include <net_modules.h>
59#include <adt/dynamic_fifo.h>
60#include <packet/packet_client.h>
[14f1db0]61#include <packet_remote.h>
[849ed54]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>
[14f1db0]72#include <tl_local.h>
73#include <tl_interface.h>
[21580dd]74
75#include "tcp.h"
76#include "tcp_header.h"
77#include "tcp_module.h"
78
[7c8267b]79/** TCP module name. */
[849ed54]80#define NAME "TCP protocol"
81
[7c8267b]82/** The TCP window default value. */
83#define NET_DEFAULT_TCP_WINDOW 10240
[21580dd]84
[7c8267b]85/** Initial timeout for new connections. */
[21580dd]86#define NET_DEFAULT_TCP_INITIAL_TIMEOUT 3000000L
87
[7c8267b]88/** Default timeout for closing. */
89#define NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT 2000L
[21580dd]90
[7c8267b]91/** The initial outgoing sequence number. */
92#define TCP_INITIAL_SEQUENCE_NUMBER 2999
[21580dd]93
[7c8267b]94/** Maximum TCP fragment size. */
95#define MAX_TCP_FRAGMENT_SIZE 65535
[21580dd]96
[7c8267b]97/** Free ports pool start. */
98#define TCP_FREE_PORTS_START 1025
[21580dd]99
[7c8267b]100/** Free ports pool end. */
[21580dd]101#define TCP_FREE_PORTS_END 65535
102
[7c8267b]103/** Timeout for connection initialization, SYN sent. */
104#define TCP_SYN_SENT_TIMEOUT 1000000L
[21580dd]105
[7c8267b]106/** The maximum number of timeouts in a row before singaling connection lost. */
[21580dd]107#define TCP_MAX_TIMEOUTS 8
108
[7c8267b]109/** The number of acknowledgements before retransmit. */
[21580dd]110#define TCP_FAST_RETRANSMIT_COUNT 3
111
[7c8267b]112/** Returns a value indicating whether the value is in the interval respecting
113 * the possible overflow.
114 *
[21580dd]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 */
[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
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 */
[aadf01e]173int tcp_release_and_return(packet_t packet, int result);
174
[7c8267b]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);
[aadf01e]182void tcp_free_socket_data(socket_core_ref socket);
[7c8267b]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);
[aadf01e]198void tcp_send_packets(device_id_t device_id, packet_t packet);
[7c8267b]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);
[aadf01e]212void tcp_refresh_socket_data(tcp_socket_data_ref socket_data);
[7c8267b]213
[aadf01e]214void tcp_initialize_socket_data(tcp_socket_data_ref socket_data);
215
[7c8267b]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);
[aadf01e]233int tcp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
[7c8267b]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);
[aadf01e]245int tcp_close_message(socket_cores_ref local_sockets, int socket_id);
[21580dd]246
[7c8267b]247/** TCP global data. */
248tcp_globals_t tcp_globals;
[21580dd]249
[7c8267b]250int tcp_initialize(async_client_conn_t client_connection)
251{
[21580dd]252 ERROR_DECLARE;
253
[aadf01e]254 assert(client_connection);
[7c8267b]255
[aadf01e]256 fibril_rwlock_initialize(&tcp_globals.lock);
257 fibril_rwlock_write_lock(&tcp_globals.lock);
[7c8267b]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)
[21580dd]264 return tcp_globals.ip_phone;
[7c8267b]265
[aadf01e]266 ERROR_PROPAGATE(socket_ports_initialize(&tcp_globals.sockets));
[7c8267b]267 if (ERROR_OCCURRED(packet_dimensions_initialize(
268 &tcp_globals.dimensions))) {
[aadf01e]269 socket_ports_destroy(&tcp_globals.sockets);
[21580dd]270 return ERROR_CODE;
271 }
[7c8267b]272
[21580dd]273 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
[aadf01e]274 fibril_rwlock_write_unlock(&tcp_globals.lock);
[7c8267b]275
[21580dd]276 return EOK;
277}
278
[7c8267b]279int
280tcp_received_msg(device_id_t device_id, packet_t packet, services_t receiver,
281 services_t error)
282{
[21580dd]283 ERROR_DECLARE;
284
[7c8267b]285 if (receiver != SERVICE_TCP)
[aadf01e]286 return EREFUSED;
[7c8267b]287
[aadf01e]288 fibril_rwlock_write_lock(&tcp_globals.lock);
[7c8267b]289 if (ERROR_OCCURRED(tcp_process_packet(device_id, packet, error)))
[aadf01e]290 fibril_rwlock_write_unlock(&tcp_globals.lock);
[7c8267b]291
[aadf01e]292 printf("receive %d \n", ERROR_CODE);
[21580dd]293
294 return ERROR_CODE;
295}
296
[7c8267b]297int tcp_process_packet(device_id_t device_id, packet_t packet, services_t error)
298{
[21580dd]299 ERROR_DECLARE;
300
[aadf01e]301 size_t length;
302 size_t offset;
303 int result;
304 tcp_header_ref header;
[7c8267b]305 socket_core_ref socket;
[aadf01e]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;
[7c8267b]313 struct sockaddr *src;
314 struct sockaddr *dest;
[aadf01e]315 size_t addrlen;
316
[7c8267b]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);
[21580dd]335 }
336 }
337
338 // TODO process received ipopts?
[aadf01e]339 result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
[7c8267b]340 if (result < 0)
[aadf01e]341 return tcp_release_and_return(packet, result);
[7c8267b]342
[aadf01e]343 offset = (size_t) result;
[21580dd]344
[aadf01e]345 length = packet_get_data_length(packet);
[7c8267b]346 if (length <= 0)
[aadf01e]347 return tcp_release_and_return(packet, EINVAL);
[7c8267b]348
349 if (length < TCP_HEADER_SIZE + offset)
[aadf01e]350 return tcp_release_and_return(packet, NO_DATA);
[21580dd]351
352 // trim all but TCP header
[7c8267b]353 if (ERROR_OCCURRED(packet_trim(packet, offset, 0)))
[aadf01e]354 return tcp_release_and_return(packet, ERROR_CODE);
[21580dd]355
356 // get tcp header
[aadf01e]357 header = (tcp_header_ref) packet_get_data(packet);
[7c8267b]358 if (!header)
[aadf01e]359 return tcp_release_and_return(packet, NO_DATA);
[7c8267b]360
361// printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header),
362// ntohs(header->destination_port));
[21580dd]363
[aadf01e]364 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
[7c8267b]365 if (result <= 0)
[aadf01e]366 return tcp_release_and_return(packet, result);
[7c8267b]367
[aadf01e]368 addrlen = (size_t) result;
[21580dd]369
[7c8267b]370 if (ERROR_OCCURRED(tl_set_address_port(src, addrlen,
371 ntohs(header->source_port))))
[aadf01e]372 return tcp_release_and_return(packet, ERROR_CODE);
[7c8267b]373
[21580dd]374 // find the destination socket
[7c8267b]375 socket = socket_port_find(&tcp_globals.sockets,
376 ntohs(header->destination_port), (const char *) src, addrlen);
377 if (!socket) {
[21580dd]378 // find the listening destination socket
[7c8267b]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);
[21580dd]388 }
389 return EADDRNOTAVAIL;
390 }
391 }
[aadf01e]392 printf("socket id %d\n", socket->socket_id);
393 socket_data = (tcp_socket_data_ref) socket->specific_data;
394 assert(socket_data);
[21580dd]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;
[7c8267b]404 do {
405 ++fragments;
[aadf01e]406 length = packet_get_data_length(next_packet);
[7c8267b]407 if (length <= 0)
[aadf01e]408 return tcp_release_and_return(packet, NO_DATA);
[7c8267b]409
[21580dd]410 total_length += length;
[7c8267b]411
[21580dd]412 // add partial checksum if set
[7c8267b]413 if (!error) {
414 checksum = compute_checksum(checksum,
415 packet_get_data(packet),
416 packet_get_data_length(packet));
[21580dd]417 }
418
[7c8267b]419 } while ((next_packet = pq_next(next_packet)));
420
[aadf01e]421 fibril_rwlock_write_lock(socket_data->local_lock);
[7c8267b]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))) {
[aadf01e]437 fibril_rwlock_write_unlock(socket_data->local_lock);
438 return tcp_release_and_return(packet, ERROR_CODE);
[21580dd]439 }
[7c8267b]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);
[21580dd]462 }
[7c8267b]463
464 return EINVAL;
[21580dd]465 }
466
[7c8267b]467error:
[aadf01e]468 fibril_rwlock_read_unlock(&tcp_globals.lock);
[21580dd]469
470 // TODO error reporting/handling
[7c8267b]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));
[21580dd]498 }
499
[7c8267b]500 if (ERROR_CODE != EOK) {
[aadf01e]501 printf("process %d\n", ERROR_CODE);
502 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]503 }
[7c8267b]504
[21580dd]505 return EOK;
506}
507
[7c8267b]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{
[21580dd]513 ERROR_DECLARE;
514
[aadf01e]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);
[21580dd]531 old_incoming = socket_data->next_incoming;
532
[7c8267b]533 if (header->finalize)
[21580dd]534 socket_data->fin_incoming = new_sequence_number;
535
536 // trim begining if containing expected data
[7c8267b]537 if (IS_IN_INTERVAL_OVERFLOW(new_sequence_number,
538 socket_data->next_incoming, new_sequence_number + total_length)) {
539
[21580dd]540 // get the acknowledged offset
[7c8267b]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;
[21580dd]547 }
[7c8267b]548
[21580dd]549 new_sequence_number += offset;
550 total_length -= offset;
[aadf01e]551 length = packet_get_data_length(packet);
[21580dd]552 // trim the acknowledged data
[7c8267b]553 while (length <= offset) {
[21580dd]554 // release the acknowledged packets
[aadf01e]555 next_packet = pq_next(packet);
[7c8267b]556 pq_release_remote(tcp_globals.net_phone,
557 packet_get_id(packet));
[21580dd]558 packet = next_packet;
559 offset -= length;
[aadf01e]560 length = packet_get_data_length(packet);
[21580dd]561 }
[7c8267b]562
563 if ((offset > 0) && (ERROR_OCCURRED(packet_trim(packet,
564 offset, 0))))
[aadf01e]565 return tcp_release_and_return(packet, ERROR_CODE);
[7c8267b]566
[aadf01e]567 assert(new_sequence_number == socket_data->next_incoming);
[21580dd]568 }
569
570 // release if overflowing the window
571/*
[7c8267b]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
[21580dd]578 // trim end if overflowing the window
[7c8267b]579 if (IS_IN_INTERVAL_OVERFLOW(new_sequence_number,
580 socket_data->next_incoming + socket_data->window,
581 new_sequence_number + total_length)) {
[21580dd]582 // get the allowed data length
[7c8267b]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;
[21580dd]590 }
591 next_packet = packet;
592 // trim the overflowing data
[7c8267b]593 while (next_packet && (offset > 0)) {
[aadf01e]594 length = packet_get_data_length(packet);
[7c8267b]595 if (length <= offset)
[aadf01e]596 next_packet = pq_next(next_packet);
[7c8267b]597 else if (ERROR_OCCURRED(packet_trim(next_packet, 0,
598 length - offset)))
599 return tcp_release_and_return(packet,
600 ERROR_CODE);
[21580dd]601 offset -= length;
602 total_length -= length - offset;
603 }
604 // release the overflowing packets
[aadf01e]605 next_packet = pq_next(next_packet);
[7c8267b]606 if (next_packet) {
[21580dd]607 tmp_packet = next_packet;
[aadf01e]608 next_packet = pq_next(next_packet);
609 pq_insert_after(tmp_packet, next_packet);
[7c8267b]610 pq_release_remote(tcp_globals.net_phone,
611 packet_get_id(tmp_packet));
[21580dd]612 }
[7c8267b]613 assert(new_sequence_number + total_length ==
614 socket_data->next_incoming + socket_data->window);
[21580dd]615 }
616*/
617 // the expected one arrived?
[7c8267b]618 if (new_sequence_number == socket_data->next_incoming) {
[21580dd]619 printf("expected\n");
620 // process acknowledgement
[aadf01e]621 tcp_process_acknowledgement(socket, socket_data, header);
[21580dd]622
623 // remove the header
[aadf01e]624 total_length -= TCP_HEADER_LENGTH(header);
[7c8267b]625 if (ERROR_OCCURRED(packet_trim(packet,
626 TCP_HEADER_LENGTH(header), 0)))
[aadf01e]627 return tcp_release_and_return(packet, ERROR_CODE);
[21580dd]628
[7c8267b]629 if (total_length) {
630 ERROR_PROPAGATE(tcp_queue_received_packet(socket,
631 socket_data, packet, fragments, total_length));
632 } else {
[21580dd]633 total_length = 1;
634 }
[7c8267b]635
[21580dd]636 socket_data->next_incoming = old_incoming + total_length;
637 packet = socket_data->incoming;
[7c8267b]638 while (packet) {
639
640 if (ERROR_OCCURRED(pq_get_order(socket_data->incoming,
641 &order, NULL))) {
[21580dd]642 // remove the corrupted packet
[aadf01e]643 next_packet = pq_detach(packet);
[7c8267b]644 if (packet == socket_data->incoming)
[21580dd]645 socket_data->incoming = next_packet;
[7c8267b]646 pq_release_remote(tcp_globals.net_phone,
647 packet_get_id(packet));
[21580dd]648 packet = next_packet;
649 continue;
650 }
[7c8267b]651
[aadf01e]652 sequence_number = (uint32_t) order;
[7c8267b]653 if (IS_IN_INTERVAL_OVERFLOW(sequence_number,
654 old_incoming, socket_data->next_incoming)) {
[21580dd]655 // move to the next
[aadf01e]656 packet = pq_next(packet);
[7c8267b]657 // coninual data?
658 } else if (IS_IN_INTERVAL_OVERFLOW(old_incoming,
659 sequence_number, socket_data->next_incoming)) {
[21580dd]660 // detach the packet
[aadf01e]661 next_packet = pq_detach(packet);
[7c8267b]662 if (packet == socket_data->incoming)
[21580dd]663 socket_data->incoming = next_packet;
664 // get data length
[aadf01e]665 length = packet_get_data_length(packet);
[21580dd]666 new_sequence_number = sequence_number + length;
[7c8267b]667 if (length <= 0) {
[21580dd]668 // remove the empty packet
[7c8267b]669 pq_release_remote(tcp_globals.net_phone,
670 packet_get_id(packet));
[21580dd]671 packet = next_packet;
672 continue;
673 }
674 // exactly following
[7c8267b]675 if (sequence_number ==
676 socket_data->next_incoming) {
[21580dd]677 // queue received data
[7c8267b]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;
[21580dd]684 packet = next_packet;
685 continue;
[7c8267b]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;
[21580dd]698 }
[7c8267b]699 if (ERROR_NONE(packet_trim(packet,
700 length, 0))) {
[21580dd]701 // queue received data
[7c8267b]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;
[21580dd]709 packet = next_packet;
710 continue;
711 }
712 }
713 // remove the duplicit or corrupted packet
[7c8267b]714 pq_release_remote(tcp_globals.net_phone,
715 packet_get_id(packet));
[21580dd]716 packet = next_packet;
717 continue;
[7c8267b]718 } else {
[21580dd]719 break;
720 }
721 }
[7c8267b]722 } else if (IS_IN_INTERVAL(socket_data->next_incoming,
723 new_sequence_number,
724 socket_data->next_incoming + socket_data->window)) {
[21580dd]725 printf("in window\n");
726 // process acknowledgement
[aadf01e]727 tcp_process_acknowledgement(socket, socket_data, header);
[21580dd]728
729 // remove the header
[aadf01e]730 total_length -= TCP_HEADER_LENGTH(header);
[7c8267b]731 if (ERROR_OCCURRED(packet_trim(packet,
732 TCP_HEADER_LENGTH(header), 0)))
[aadf01e]733 return tcp_release_and_return(packet, ERROR_CODE);
[21580dd]734
[aadf01e]735 next_packet = pq_detach(packet);
736 length = packet_get_data_length(packet);
[7c8267b]737 if (ERROR_OCCURRED(pq_add(&socket_data->incoming, packet,
738 new_sequence_number, length))) {
[21580dd]739 // remove the corrupted packets
[7c8267b]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) {
[21580dd]746 new_sequence_number += length;
[aadf01e]747 tmp_packet = pq_detach(next_packet);
748 length = packet_get_data_length(next_packet);
[7c8267b]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));
[21580dd]755 }
756 next_packet = tmp_packet;
757 }
758 }
[7c8267b]759 } else {
[21580dd]760 printf("unexpected\n");
761 // release duplicite or restricted
[14f1db0]762 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]763 }
764
765 // change state according to the acknowledging incoming fin
[7c8267b]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;
[21580dd]774 //case TCP_ESTABLISHED:
[7c8267b]775 default:
776 socket_data->state = TCP_SOCKET_CLOSE_WAIT;
777 break;
[21580dd]778 }
779 }
780
[aadf01e]781 packet = tcp_get_packets_to_send(socket, socket_data);
[7c8267b]782 if (!packet) {
[21580dd]783 // create the notification packet
[7c8267b]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);
[21580dd]790 }
[7c8267b]791
[aadf01e]792 fibril_rwlock_write_unlock(socket_data->local_lock);
[7c8267b]793
[21580dd]794 // send the packet
[aadf01e]795 tcp_send_packets(socket_data->device_id, packet);
[7c8267b]796
[21580dd]797 return EOK;
798}
799
[7c8267b]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{
[21580dd]805 ERROR_DECLARE;
806
[aadf01e]807 packet_dimension_ref packet_dimension;
[ede63e4]808
[aadf01e]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);
[21580dd]815
816 // queue the received packet
[7c8267b]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))) {
[aadf01e]822 return tcp_release_and_return(packet, ERROR_CODE);
[21580dd]823 }
824
825 // decrease the window size
826 socket_data->window -= total_length;
827
828 // notify the destination socket
[7c8267b]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
[21580dd]835 return EOK;
836}
837
[7c8267b]838int
839tcp_process_syn_sent(socket_core_ref socket, tcp_socket_data_ref socket_data,
840 tcp_header_ref header, packet_t packet)
841{
[21580dd]842 ERROR_DECLARE;
843
[aadf01e]844 packet_t next_packet;
[21580dd]845
[aadf01e]846 assert(socket);
847 assert(socket_data);
848 assert(socket->specific_data == socket_data);
849 assert(header);
850 assert(packet);
[21580dd]851
[7c8267b]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;
[21580dd]886 }
887 }
[7c8267b]888 fibril_mutex_unlock(&socket_data->operation.mutex);
[aadf01e]889 return tcp_release_and_return(packet, EINVAL);
[21580dd]890}
891
[7c8267b]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{
[21580dd]898 ERROR_DECLARE;
899
[aadf01e]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
[7c8267b]913 if (!header->synchronize)
914 return tcp_release_and_return(packet, EINVAL);
[21580dd]915
[7c8267b]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 }
[21580dd]942
[7c8267b]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 }
[21580dd]951
[7c8267b]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;
[21580dd]957
[7c8267b]958 fibril_rwlock_write_unlock(socket_data->local_lock);
959 fibril_rwlock_write_lock(&tcp_globals.lock);
[21580dd]960
[7c8267b]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);
[21580dd]973
[7c8267b]974 fibril_rwlock_write_lock(listening_socket_data->local_lock);
[21580dd]975
[7c8267b]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);
[21580dd]985
[7c8267b]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));
[21580dd]990
[7c8267b]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 }
[21580dd]1002
[7c8267b]1003 socket_data->state = TCP_SOCKET_LISTEN;
1004 socket_data->next_incoming = ntohl(header->sequence_number) + 1;
[21580dd]1005
[7c8267b]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));
[21580dd]1011 }
[7c8267b]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;
[21580dd]1047}
1048
[7c8267b]1049int
1050tcp_process_syn_received(socket_core_ref socket,
1051 tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet)
1052{
[21580dd]1053 ERROR_DECLARE;
1054
[aadf01e]1055 socket_core_ref listening_socket;
1056 tcp_socket_data_ref listening_socket_data;
[21580dd]1057
[aadf01e]1058 assert(socket);
1059 assert(socket_data);
1060 assert(socket->specific_data == socket_data);
1061 assert(header);
1062 assert(packet);
[21580dd]1063
[7c8267b]1064 if (!header->acknowledge)
1065 return tcp_release_and_return(packet, EINVAL);
[21580dd]1066
[7c8267b]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;
[21580dd]1093 }
[7c8267b]1094 }
1095 // send FIN
1096 socket_data->state = TCP_SOCKET_FIN_WAIT_1;
[21580dd]1097
[7c8267b]1098 // create the notification packet
1099 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket,
1100 socket_data, 0, 1));
[21580dd]1101
[7c8267b]1102 // send the packet
1103 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 1));
[21580dd]1104
[7c8267b]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);
[21580dd]1111 }
[7c8267b]1112
1113 return EOK;
[21580dd]1114}
1115
[7c8267b]1116void
1117tcp_process_acknowledgement(socket_core_ref socket,
1118 tcp_socket_data_ref socket_data, tcp_header_ref header)
1119{
[aadf01e]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
[7c8267b]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;
[21580dd]1156 }
[7c8267b]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;
[21580dd]1190 // if the same as the previous time
[7c8267b]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);
[21580dd]1199 }
1200 }
1201}
1202
[7c8267b]1203int tcp_message_standalone(ipc_callid_t callid, ipc_call_t * call,
1204 ipc_call_t * answer, int *answer_count)
1205{
[21580dd]1206 ERROR_DECLARE;
1207
[aadf01e]1208 packet_t packet;
[21580dd]1209
[aadf01e]1210 assert(call);
1211 assert(answer);
1212 assert(answer_count);
[21580dd]1213
[aadf01e]1214 *answer_count = 0;
[7c8267b]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);
[21580dd]1228 }
[7c8267b]1229
[21580dd]1230 return ENOTSUP;
1231}
1232
[7c8267b]1233void tcp_refresh_socket_data(tcp_socket_data_ref socket_data)
1234{
[aadf01e]1235 assert(socket_data);
[21580dd]1236
[aadf01e]1237 bzero(socket_data, sizeof(*socket_data));
[21580dd]1238 socket_data->state = TCP_SOCKET_INITIAL;
[ede63e4]1239 socket_data->device_id = DEVICE_INVALID_ID;
[21580dd]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
[7c8267b]1249void tcp_initialize_socket_data(tcp_socket_data_ref socket_data)
1250{
[aadf01e]1251 assert(socket_data);
[21580dd]1252
[aadf01e]1253 tcp_refresh_socket_data(socket_data);
1254 fibril_mutex_initialize(&socket_data->operation.mutex);
1255 fibril_condvar_initialize(&socket_data->operation.condvar);
[ede63e4]1256 socket_data->data_fragment_size = MAX_TCP_FRAGMENT_SIZE;
[21580dd]1257}
1258
[7c8267b]1259int tcp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
1260{
[aadf01e]1261 int res;
1262 bool keep_on_going = true;
1263 socket_cores_t local_sockets;
1264 int app_phone = IPC_GET_PHONE(&call);
[7c8267b]1265 struct sockaddr *addr;
[6092b56e]1266 int socket_id;
[aadf01e]1267 size_t addrlen;
[e417b96]1268 size_t size;
[aadf01e]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;
[21580dd]1275
1276 /*
1277 * Accept the connection
1278 * - Answer the first IPC_M_CONNECT_ME_TO call.
1279 */
[2e99277]1280 res = EOK;
1281 answer_count = 0;
[21580dd]1282
[aadf01e]1283 socket_cores_initialize(&local_sockets);
1284 fibril_rwlock_initialize(&lock);
[21580dd]1285
[7c8267b]1286 while (keep_on_going) {
[2e99277]1287
1288 // answer the call
[aadf01e]1289 answer_call(callid, res, &answer, answer_count);
[21580dd]1290 // refresh data
[aadf01e]1291 refresh_answer(&answer, &answer_count);
[2e99277]1292 // get the next call
[aadf01e]1293 callid = async_get_call(&call);
[21580dd]1294
[2e99277]1295 // process the call
[7c8267b]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;
[21580dd]1307 break;
[7c8267b]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);
[21580dd]1321 break;
[7c8267b]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)
[21580dd]1340 break;
[7c8267b]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;
[21580dd]1355 }
[7c8267b]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)
[21580dd]1377 break;
[7c8267b]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) {
[aadf01e]1385 fibril_rwlock_write_unlock(&lock);
[7c8267b]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) {
[aadf01e]1416 fibril_rwlock_write_unlock(&lock);
1417 fibril_rwlock_read_unlock(&tcp_globals.lock);
[7c8267b]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)
[21580dd]1426 break;
[7c8267b]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) {
[aadf01e]1435 fibril_rwlock_write_unlock(&lock);
1436 fibril_rwlock_read_unlock(&tcp_globals.lock);
[7c8267b]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;
[21580dd]1490 }
1491 }
1492
[a8a13d0]1493 // release the application phone
1494 ipc_hangup(app_phone);
1495
[21580dd]1496 printf("release\n");
1497 // release all local sockets
[7c8267b]1498 socket_cores_release(tcp_globals.net_phone, &local_sockets,
1499 &tcp_globals.sockets, tcp_free_socket_data);
[21580dd]1500
1501 return EOK;
1502}
1503
[7c8267b]1504int tcp_timeout(void *data)
1505{
[aadf01e]1506 tcp_timeout_ref timeout = data;
1507 int keep_write_lock = false;
1508 socket_core_ref socket;
1509 tcp_socket_data_ref socket_data;
[21580dd]1510
[aadf01e]1511 assert(timeout);
[21580dd]1512
1513 // sleep the given timeout
[aadf01e]1514 async_usleep(timeout->timeout);
[21580dd]1515 // lock the globals
[7c8267b]1516 if (timeout->globals_read_only)
[aadf01e]1517 fibril_rwlock_read_lock(&tcp_globals.lock);
[7c8267b]1518 else
[aadf01e]1519 fibril_rwlock_write_lock(&tcp_globals.lock);
[7c8267b]1520
[21580dd]1521 // find the pending operation socket
[7c8267b]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);
[21580dd]1545 }
[7c8267b]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);
[21580dd]1563 }
[7c8267b]1564
1565out:
[21580dd]1566 // unlock only if no socket
[7c8267b]1567 if (timeout->globals_read_only)
[aadf01e]1568 fibril_rwlock_read_unlock(&tcp_globals.lock);
[7c8267b]1569 else if (!keep_write_lock)
[21580dd]1570 // release if not desired
[aadf01e]1571 fibril_rwlock_write_unlock(&tcp_globals.lock);
[7c8267b]1572
[21580dd]1573 // release the timeout structure
[aadf01e]1574 free(timeout);
[21580dd]1575 return EOK;
1576}
1577
[7c8267b]1578int tcp_release_after_timeout(void *data)
1579{
[aadf01e]1580 tcp_timeout_ref timeout = data;
1581 socket_core_ref socket;
1582 tcp_socket_data_ref socket_data;
[7c8267b]1583 fibril_rwlock_t *local_lock;
[21580dd]1584
[aadf01e]1585 assert(timeout);
[21580dd]1586
1587 // sleep the given timeout
[aadf01e]1588 async_usleep(timeout->timeout);
[21580dd]1589 // lock the globals
[aadf01e]1590 fibril_rwlock_write_lock(&tcp_globals.lock);
[21580dd]1591 // find the pending operation socket
[7c8267b]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)) {
[aadf01e]1595 socket_data = (tcp_socket_data_ref) socket->specific_data;
1596 assert(socket_data);
[7c8267b]1597 if (socket_data->local_sockets == timeout->local_sockets) {
[21580dd]1598 local_lock = socket_data->local_lock;
[aadf01e]1599 fibril_rwlock_write_lock(local_lock);
[7c8267b]1600 socket_destroy(tcp_globals.net_phone,
1601 timeout->socket_id, timeout->local_sockets,
1602 &tcp_globals.sockets, tcp_free_socket_data);
[aadf01e]1603 fibril_rwlock_write_unlock(local_lock);
[21580dd]1604 }
1605 }
1606 // unlock the globals
[aadf01e]1607 fibril_rwlock_write_unlock(&tcp_globals.lock);
[21580dd]1608 // release the timeout structure
[aadf01e]1609 free(timeout);
[21580dd]1610 return EOK;
1611}
1612
[7c8267b]1613void
1614tcp_retransmit_packet(socket_core_ref socket, tcp_socket_data_ref socket_data,
1615 size_t sequence_number)
1616{
[aadf01e]1617 packet_t packet;
1618 packet_t copy;
1619 size_t data_length;
[21580dd]1620
[aadf01e]1621 assert(socket);
1622 assert(socket_data);
1623 assert(socket->specific_data == socket_data);
[21580dd]1624
1625 // sent packet?
[aadf01e]1626 packet = pq_find(socket_data->outgoing, sequence_number);
1627 printf("retransmit %d\n", packet_get_id(packet));
[7c8267b]1628 if (packet) {
[aadf01e]1629 pq_get_order(packet, NULL, &data_length);
[7c8267b]1630 copy = tcp_prepare_copy(socket, socket_data, packet,
1631 data_length, sequence_number);
[aadf01e]1632 fibril_rwlock_write_unlock(socket_data->local_lock);
[7c8267b]1633// printf("r send %d\n", packet_get_id(packet));
1634 if (copy)
[aadf01e]1635 tcp_send_packets(socket_data->device_id, copy);
[7c8267b]1636 } else {
[aadf01e]1637 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]1638 }
1639}
1640
[7c8267b]1641int
1642tcp_listen_message(socket_cores_ref local_sockets, int socket_id, int backlog)
1643{
[aadf01e]1644 socket_core_ref socket;
1645 tcp_socket_data_ref socket_data;
[21580dd]1646
[aadf01e]1647 assert(local_sockets);
[21580dd]1648
[7c8267b]1649 if (backlog < 0)
[aadf01e]1650 return EINVAL;
[7c8267b]1651
[21580dd]1652 // find the socket
[aadf01e]1653 socket = socket_cores_find(local_sockets, socket_id);
[7c8267b]1654 if (!socket)
[aadf01e]1655 return ENOTSOCK;
[7c8267b]1656
[21580dd]1657 // get the socket specific data
[aadf01e]1658 socket_data = (tcp_socket_data_ref) socket->specific_data;
1659 assert(socket_data);
[21580dd]1660 // set the backlog
1661 socket_data->backlog = backlog;
[7c8267b]1662
[21580dd]1663 return EOK;
1664}
1665
[7c8267b]1666int
1667tcp_connect_message(socket_cores_ref local_sockets, int socket_id,
1668 struct sockaddr *addr, socklen_t addrlen)
1669{
[21580dd]1670 ERROR_DECLARE;
1671
[aadf01e]1672 socket_core_ref socket;
[21580dd]1673
[aadf01e]1674 assert(local_sockets);
1675 assert(addr);
1676 assert(addrlen > 0);
[21580dd]1677
1678 // find the socket
[aadf01e]1679 socket = socket_cores_find(local_sockets, socket_id);
[7c8267b]1680 if (!socket)
[aadf01e]1681 return ENOTSOCK;
[7c8267b]1682
1683 if (ERROR_OCCURRED(tcp_connect_core(socket, local_sockets, addr,
1684 addrlen))) {
[aadf01e]1685 tcp_free_socket_data(socket);
[21580dd]1686 // unbind if bound
[7c8267b]1687 if (socket->port > 0) {
1688 socket_ports_exclude(&tcp_globals.sockets,
1689 socket->port);
[21580dd]1690 socket->port = 0;
1691 }
1692 }
1693 return ERROR_CODE;
1694}
1695
[7c8267b]1696int
1697tcp_connect_core(socket_core_ref socket, socket_cores_ref local_sockets,
1698 struct sockaddr *addr, socklen_t addrlen)
1699{
[21580dd]1700 ERROR_DECLARE;
1701
[aadf01e]1702 tcp_socket_data_ref socket_data;
1703 packet_t packet;
[21580dd]1704
[aadf01e]1705 assert(socket);
1706 assert(addr);
1707 assert(addrlen > 0);
[21580dd]1708
1709 // get the socket specific data
[aadf01e]1710 socket_data = (tcp_socket_data_ref) socket->specific_data;
1711 assert(socket_data);
1712 assert(socket->specific_data == socket_data);
[7c8267b]1713 if ((socket_data->state != TCP_SOCKET_INITIAL) &&
1714 ((socket_data->state != TCP_SOCKET_LISTEN) ||
1715 (socket->port <= 0)))
[21580dd]1716 return EINVAL;
[7c8267b]1717
[21580dd]1718 // get the destination port
[7c8267b]1719 ERROR_PROPAGATE(tl_get_address_port(addr, addrlen,
1720 &socket_data->dest_port));
1721 if (socket->port <= 0) {
[21580dd]1722 // try to find a free port
[7c8267b]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));
[21580dd]1726 // set the next port as the search starting port number
1727 tcp_globals.last_used_port = socket->port;
1728 }
[7c8267b]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));
[21580dd]1733
1734 // create the notification packet
[7c8267b]1735 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket,
1736 socket_data, 1, 0));
[21580dd]1737
1738 // unlock the globals and wait for an operation
[aadf01e]1739 fibril_rwlock_write_unlock(&tcp_globals.lock);
[21580dd]1740
1741 socket_data->addr = addr;
1742 socket_data->addrlen = addrlen;
1743 // send the packet
[7c8267b]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
[21580dd]1748 socket_data->addr = NULL;
1749 socket_data->addrlen = 0;
[aadf01e]1750 fibril_rwlock_write_lock(&tcp_globals.lock);
[7c8267b]1751
1752 } else {
1753
[aadf01e]1754 packet = tcp_get_packets_to_send(socket, socket_data);
[7c8267b]1755 if (packet) {
[aadf01e]1756 fibril_mutex_lock(&socket_data->operation.mutex);
1757 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]1758 // send the packet
[aadf01e]1759 printf("connecting %d\n", packet_get_id(packet));
1760 tcp_send_packets(socket_data->device_id, packet);
[7c8267b]1761
[21580dd]1762 // wait for a reply
[7c8267b]1763 fibril_condvar_wait(&socket_data->operation.condvar,
1764 &socket_data->operation.mutex);
[21580dd]1765 ERROR_CODE = socket_data->operation.result;
[7c8267b]1766 if (ERROR_CODE != EOK) {
[21580dd]1767 socket_data->addr = NULL;
1768 socket_data->addrlen = 0;
1769 }
[7c8267b]1770 } else {
[21580dd]1771 socket_data->addr = NULL;
1772 socket_data->addrlen = 0;
1773 ERROR_CODE = EINTR;
1774 }
1775 }
1776
[aadf01e]1777 fibril_mutex_unlock(&socket_data->operation.mutex);
[21580dd]1778
1779 // return the result
1780 return ERROR_CODE;
1781}
1782
[7c8267b]1783int
1784tcp_queue_prepare_packet(socket_core_ref socket,
1785 tcp_socket_data_ref socket_data, packet_t packet, size_t data_length)
1786{
[21580dd]1787 ERROR_DECLARE;
1788
[aadf01e]1789 tcp_header_ref header;
[21580dd]1790
[aadf01e]1791 assert(socket);
1792 assert(socket_data);
1793 assert(socket->specific_data == socket_data);
[21580dd]1794
1795 // get tcp header
[aadf01e]1796 header = (tcp_header_ref) packet_get_data(packet);
[7c8267b]1797 if (!header)
[aadf01e]1798 return NO_DATA;
[7c8267b]1799
[aadf01e]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);
[7c8267b]1803
1804 if (ERROR_OCCURRED(packet_set_addr(packet, NULL,
1805 (uint8_t *) socket_data->addr, socket_data->addrlen)))
[aadf01e]1806 return tcp_release_and_return(packet, EINVAL);
[7c8267b]1807
[21580dd]1808 // remember the outgoing FIN
[7c8267b]1809 if (header->finalize)
[21580dd]1810 socket_data->fin_outgoing = socket_data->next_outgoing;
[7c8267b]1811
[21580dd]1812 return EOK;
1813}
1814
[7c8267b]1815int
1816tcp_queue_packet(socket_core_ref socket, tcp_socket_data_ref socket_data,
1817 packet_t packet, size_t data_length)
1818{
[21580dd]1819 ERROR_DECLARE;
1820
[aadf01e]1821 assert(socket);
1822 assert(socket_data);
1823 assert(socket->specific_data == socket_data);
[21580dd]1824
[7c8267b]1825 ERROR_PROPAGATE(tcp_queue_prepare_packet(socket, socket_data, packet,
1826 data_length));
[21580dd]1827
[7c8267b]1828 if (ERROR_OCCURRED(pq_add(&socket_data->outgoing, packet,
1829 socket_data->next_outgoing, data_length)))
[aadf01e]1830 return tcp_release_and_return(packet, ERROR_CODE);
[7c8267b]1831
[21580dd]1832 socket_data->next_outgoing += data_length;
1833 return EOK;
1834}
1835
[7c8267b]1836packet_t
1837tcp_get_packets_to_send(socket_core_ref socket, tcp_socket_data_ref socket_data)
1838{
[21580dd]1839 ERROR_DECLARE;
1840
[aadf01e]1841 packet_t packet;
1842 packet_t copy;
1843 packet_t sending = NULL;
1844 packet_t previous = NULL;
1845 size_t data_length;
[21580dd]1846
[aadf01e]1847 assert(socket);
1848 assert(socket_data);
1849 assert(socket->specific_data == socket_data);
[21580dd]1850
[aadf01e]1851 packet = pq_find(socket_data->outgoing, socket_data->last_outgoing + 1);
[7c8267b]1852 while (packet) {
[aadf01e]1853 pq_get_order(packet, NULL, &data_length);
[7c8267b]1854
[21580dd]1855 // send only if fits into the window
1856 // respecting the possible overflow
[7c8267b]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)))
[21580dd]1861 break;
[7c8267b]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;
[21580dd]1884 }
[7c8267b]1885 socket_data->last_outgoing += data_length;
[21580dd]1886 }
[7c8267b]1887
[21580dd]1888 return sending;
1889}
1890
[7c8267b]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{
[21580dd]1895 ERROR_DECLARE;
1896
[aadf01e]1897 tcp_header_ref header;
1898 uint32_t checksum;
[21580dd]1899
[aadf01e]1900 assert(socket);
1901 assert(socket_data);
1902 assert(socket->specific_data == socket_data);
[21580dd]1903
1904 // adjust the pseudo header
[7c8267b]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)))) {
[14f1db0]1908 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]1909 return NULL;
1910 }
1911
1912 // get the header
[aadf01e]1913 header = (tcp_header_ref) packet_get_data(packet);
[7c8267b]1914 if (!header) {
[14f1db0]1915 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]1916 return NULL;
1917 }
[aadf01e]1918 assert(ntohl(header->sequence_number) == sequence_number);
[21580dd]1919
1920 // adjust the header
[7c8267b]1921 if (socket_data->next_incoming) {
1922 header->acknowledgement_number =
1923 htonl(socket_data->next_incoming);
[21580dd]1924 header->acknowledge = 1;
1925 }
[aadf01e]1926 header->window = htons(socket_data->window);
[21580dd]1927
1928 // checksum
1929 header->checksum = 0;
[7c8267b]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));
[aadf01e]1934 header->checksum = htons(flip_checksum(compact_checksum(checksum)));
[7c8267b]1935
[21580dd]1936 // prepare the packet
[7c8267b]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))) {
[14f1db0]1941 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]1942 return NULL;
1943 }
[7c8267b]1944
[21580dd]1945 return packet;
1946}
1947
[7c8267b]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{
[aadf01e]1952 packet_t copy;
[21580dd]1953
[aadf01e]1954 assert(socket);
1955 assert(socket_data);
1956 assert(socket->specific_data == socket_data);
[21580dd]1957
1958 // make a copy of the packet
[aadf01e]1959 copy = packet_get_copy(tcp_globals.net_phone, packet);
[7c8267b]1960 if (!copy)
[aadf01e]1961 return NULL;
[21580dd]1962
[7c8267b]1963 return tcp_send_prepare_packet(socket, socket_data, copy, data_length,
1964 sequence_number);
[21580dd]1965}
1966
[7c8267b]1967void tcp_send_packets(device_id_t device_id, packet_t packet)
1968{
[aadf01e]1969 packet_t next;
[21580dd]1970
[7c8267b]1971 while (packet) {
[aadf01e]1972 next = pq_detach(packet);
[7c8267b]1973 ip_send_msg(tcp_globals.ip_phone, device_id, packet,
1974 SERVICE_TCP, 0);
[21580dd]1975 packet = next;
1976 }
1977}
1978
[7c8267b]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{
[aadf01e]1984 assert(socket);
1985 assert(socket_data);
1986 assert(socket->specific_data == socket_data);
1987 assert(header);
[21580dd]1988
[aadf01e]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));
[21580dd]1993 header->synchronize = synchronize;
1994 header->finalize = finalize;
1995}
1996
[7c8267b]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{
[aadf01e]2003 tcp_timeout_ref operation_timeout;
2004 fid_t fibril;
[21580dd]2005
[aadf01e]2006 assert(socket);
2007 assert(socket_data);
2008 assert(socket->specific_data == socket_data);
[21580dd]2009
2010 // prepare the timeout with key bundle structure
[7c8267b]2011 operation_timeout = malloc(sizeof(*operation_timeout) +
2012 socket->key_length + 1);
2013 if (!operation_timeout)
[aadf01e]2014 return ENOMEM;
[7c8267b]2015
[aadf01e]2016 bzero(operation_timeout, sizeof(*operation_timeout));
[21580dd]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
[7c8267b]2026 operation_timeout->key = ((char *) operation_timeout) +
2027 sizeof(*operation_timeout);
[21580dd]2028 operation_timeout->key_length = socket->key_length;
[aadf01e]2029 memcpy(operation_timeout->key, socket->key, socket->key_length);
2030 operation_timeout->key[operation_timeout->key_length] = '\0';
[21580dd]2031
2032 // prepare the timeouting thread
[aadf01e]2033 fibril = fibril_create(timeout_function, operation_timeout);
[7c8267b]2034 if (!fibril) {
[aadf01e]2035 free(operation_timeout);
[21580dd]2036 return EPARTY;
2037 }
[7c8267b]2038// fibril_mutex_lock(&socket_data->operation.mutex);
[21580dd]2039 // start the timeouting fibril
[aadf01e]2040 fibril_add_ready(fibril);
[21580dd]2041 //socket_data->state = state;
2042 return EOK;
2043}
2044
[7c8267b]2045int
2046tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags,
2047 size_t * addrlen)
2048{
[21580dd]2049 ERROR_DECLARE;
2050
[aadf01e]2051 socket_core_ref socket;
2052 tcp_socket_data_ref socket_data;
2053 int packet_id;
2054 packet_t packet;
2055 size_t length;
[21580dd]2056
[aadf01e]2057 assert(local_sockets);
[21580dd]2058
2059 // find the socket
[aadf01e]2060 socket = socket_cores_find(local_sockets, socket_id);
[7c8267b]2061 if (!socket)
[aadf01e]2062 return ENOTSOCK;
[7c8267b]2063
[21580dd]2064 // get the socket specific data
[7c8267b]2065 if (!socket->specific_data)
[aadf01e]2066 return NO_DATA;
[7c8267b]2067
[aadf01e]2068 socket_data = (tcp_socket_data_ref) socket->specific_data;
[21580dd]2069
2070 // check state
[7c8267b]2071 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) &&
2072 (socket_data->state != TCP_SOCKET_CLOSE_WAIT))
[21580dd]2073 return ENOTCONN;
2074
2075 // send the source address if desired
[7c8267b]2076 if (addrlen) {
2077 ERROR_PROPAGATE(data_reply(socket_data->addr,
2078 socket_data->addrlen));
[aadf01e]2079 *addrlen = socket_data->addrlen;
[21580dd]2080 }
2081
2082 // get the next received packet
[aadf01e]2083 packet_id = dyn_fifo_value(&socket->received);
[7c8267b]2084 if (packet_id < 0)
[aadf01e]2085 return NO_DATA;
[7c8267b]2086
2087 ERROR_PROPAGATE(packet_translate_remote(tcp_globals.net_phone, &packet,
2088 packet_id));
[21580dd]2089
2090 // reply the packets
[aadf01e]2091 ERROR_PROPAGATE(socket_reply_packets(packet, &length));
[21580dd]2092
2093 // release the packet
[aadf01e]2094 dyn_fifo_pop(&socket->received);
[14f1db0]2095 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]2096 // return the total length
[aadf01e]2097 return (int) length;
[21580dd]2098}
2099
[7c8267b]2100int
2101tcp_send_message(socket_cores_ref local_sockets, int socket_id, int fragments,
2102 size_t * data_fragment_size, int flags)
2103{
[21580dd]2104 ERROR_DECLARE;
2105
[aadf01e]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;
[21580dd]2114
[aadf01e]2115 assert(local_sockets);
2116 assert(data_fragment_size);
[21580dd]2117
2118 // find the socket
[aadf01e]2119 socket = socket_cores_find(local_sockets, socket_id);
[7c8267b]2120 if (!socket)
[aadf01e]2121 return ENOTSOCK;
[7c8267b]2122
[21580dd]2123 // get the socket specific data
[7c8267b]2124 if (!socket->specific_data)
[aadf01e]2125 return NO_DATA;
[7c8267b]2126
[aadf01e]2127 socket_data = (tcp_socket_data_ref) socket->specific_data;
[21580dd]2128
2129 // check state
[7c8267b]2130 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) &&
2131 (socket_data->state != TCP_SOCKET_CLOSE_WAIT))
[21580dd]2132 return ENOTCONN;
2133
[7c8267b]2134 ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone,
2135 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
[21580dd]2136
[7c8267b]2137 *data_fragment_size =
2138 ((packet_dimension->content < socket_data->data_fragment_size) ?
2139 packet_dimension->content : socket_data->data_fragment_size);
[21580dd]2140
[7c8267b]2141 for (index = 0; index < fragments; ++index) {
[21580dd]2142 // read the data fragment
[7c8267b]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)
[aadf01e]2147 return result;
[7c8267b]2148
[aadf01e]2149 total_length = (size_t) result;
[21580dd]2150 // prefix the tcp header
[aadf01e]2151 header = PACKET_PREFIX(packet, tcp_header_t);
[7c8267b]2152 if (!header)
[aadf01e]2153 return tcp_release_and_return(packet, ENOMEM);
[7c8267b]2154
[aadf01e]2155 tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
[7c8267b]2156 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet,
2157 0));
[21580dd]2158 }
2159
2160 // flush packets
[aadf01e]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);
[7c8267b]2164
2165 if (packet) {
[21580dd]2166 // send the packet
[aadf01e]2167 tcp_send_packets(socket_data->device_id, packet);
[21580dd]2168 }
2169
2170 return EOK;
2171}
2172
[7c8267b]2173int
2174tcp_close_message(socket_cores_ref local_sockets, int socket_id)
2175{
[21580dd]2176 ERROR_DECLARE;
2177
[aadf01e]2178 socket_core_ref socket;
2179 tcp_socket_data_ref socket_data;
2180 packet_t packet;
[21580dd]2181
2182 // find the socket
[aadf01e]2183 socket = socket_cores_find(local_sockets, socket_id);
[7c8267b]2184 if (!socket)
[aadf01e]2185 return ENOTSOCK;
[7c8267b]2186
[21580dd]2187 // get the socket specific data
[aadf01e]2188 socket_data = (tcp_socket_data_ref) socket->specific_data;
2189 assert(socket_data);
[21580dd]2190
2191 // check state
[7c8267b]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;
[21580dd]2212 }
[7c8267b]2213
[21580dd]2214 // send FIN
2215 // TODO should I wait to complete?
2216
2217 // create the notification packet
[7c8267b]2218 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket,
2219 socket_data, 0, 1));
[21580dd]2220
2221 // send the packet
[aadf01e]2222 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 1));
[21580dd]2223
2224 // flush packets
[aadf01e]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);
[7c8267b]2228
2229 if (packet) {
[21580dd]2230 // send the packet
[aadf01e]2231 tcp_send_packets(socket_data->device_id, packet);
[21580dd]2232 }
[7c8267b]2233
[21580dd]2234 return EOK;
2235}
2236
[7c8267b]2237int
2238tcp_create_notification_packet(packet_t * packet, socket_core_ref socket,
2239 tcp_socket_data_ref socket_data, int synchronize, int finalize)
2240{
[21580dd]2241 ERROR_DECLARE;
2242
[aadf01e]2243 packet_dimension_ref packet_dimension;
2244 tcp_header_ref header;
[21580dd]2245
[aadf01e]2246 assert(packet);
[21580dd]2247
2248 // get the device packet dimension
[7c8267b]2249 ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone,
2250 &tcp_globals.dimensions, socket_data->device_id,
2251 &packet_dimension));
2252
[21580dd]2253 // get a new packet
[7c8267b]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)
[aadf01e]2259 return ENOMEM;
[7c8267b]2260
[21580dd]2261 // allocate space in the packet
[aadf01e]2262 header = PACKET_SUFFIX(*packet, tcp_header_t);
[7c8267b]2263 if (!header)
[aadf01e]2264 tcp_release_and_return(*packet, ENOMEM);
[21580dd]2265
[7c8267b]2266 tcp_prepare_operation_header(socket, socket_data, header, synchronize,
2267 finalize);
2268
[21580dd]2269 return EOK;
2270}
2271
[7c8267b]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{
[21580dd]2276 ERROR_DECLARE;
2277
[aadf01e]2278 socket_core_ref accepted;
2279 socket_core_ref socket;
2280 tcp_socket_data_ref socket_data;
2281 packet_dimension_ref packet_dimension;
[21580dd]2282
[aadf01e]2283 assert(local_sockets);
2284 assert(data_fragment_size);
2285 assert(addrlen);
[21580dd]2286
2287 // find the socket
[aadf01e]2288 socket = socket_cores_find(local_sockets, socket_id);
[7c8267b]2289 if (!socket)
[aadf01e]2290 return ENOTSOCK;
[7c8267b]2291
[21580dd]2292 // get the socket specific data
[aadf01e]2293 socket_data = (tcp_socket_data_ref) socket->specific_data;
2294 assert(socket_data);
[21580dd]2295
2296 // check state
[7c8267b]2297 if (socket_data->state != TCP_SOCKET_LISTEN)
[21580dd]2298 return EINVAL;
2299
[7c8267b]2300 do {
[aadf01e]2301 socket_id = dyn_fifo_value(&socket->accepted);
[7c8267b]2302 if (socket_id < 0)
[aadf01e]2303 return ENOTSOCK;
[d510c0fe]2304 socket_id *= -1;
[21580dd]2305
[aadf01e]2306 accepted = socket_cores_find(local_sockets, socket_id);
[7c8267b]2307 if (!accepted)
[aadf01e]2308 return ENOTSOCK;
[7c8267b]2309
[21580dd]2310 // get the socket specific data
[aadf01e]2311 socket_data = (tcp_socket_data_ref) accepted->specific_data;
2312 assert(socket_data);
[ede63e4]2313 // TODO can it be in another state?
[7c8267b]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));
[aadf01e]2320 *addrlen = socket_data->addrlen;
[7c8267b]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));
[ede63e4]2332 accepted->socket_id = new_socket_id;
2333 }
[21580dd]2334 }
[aadf01e]2335 dyn_fifo_pop(&socket->accepted);
[7c8267b]2336 } while (socket_data->state != TCP_SOCKET_ESTABLISHED);
2337
[aadf01e]2338 printf("ret accept %d\n", accepted->socket_id);
[21580dd]2339 return accepted->socket_id;
2340}
2341
[7c8267b]2342void
2343tcp_free_socket_data(socket_core_ref socket)
2344{
[aadf01e]2345 tcp_socket_data_ref socket_data;
[21580dd]2346
[aadf01e]2347 assert(socket);
[21580dd]2348
[aadf01e]2349 printf("destroy_socket %d\n", socket->socket_id);
[21580dd]2350
2351 // get the socket specific data
[aadf01e]2352 socket_data = (tcp_socket_data_ref) socket->specific_data;
2353 assert(socket_data);
[21580dd]2354 //free the pseudo header
[7c8267b]2355 if (socket_data->pseudo_header) {
2356 if (socket_data->headerlen) {
[21580dd]2357 printf("d pseudo\n");
[aadf01e]2358 free(socket_data->pseudo_header);
[21580dd]2359 socket_data->headerlen = 0;
2360 }
2361 socket_data->pseudo_header = NULL;
2362 }
2363 socket_data->headerlen = 0;
2364 // free the address
[7c8267b]2365 if (socket_data->addr) {
2366 if (socket_data->addrlen) {
[21580dd]2367 printf("d addr\n");
[aadf01e]2368 free(socket_data->addr);
[21580dd]2369 socket_data->addrlen = 0;
2370 }
2371 socket_data->addr = NULL;
2372 }
2373 socket_data->addrlen = 0;
2374}
2375
[7c8267b]2376int tcp_release_and_return(packet_t packet, int result)
2377{
[14f1db0]2378 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]2379 return result;
2380}
2381
[849ed54]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);
[7c8267b]2395
2396 while (true) {
[849ed54]2397 ipc_call_t answer;
2398 int answer_count;
[7c8267b]2399
2400 /*
2401 Clear the answer structure
2402 */
[849ed54]2403 refresh_answer(&answer, &answer_count);
[7c8267b]2404
2405 /*
2406 Fetch the next message
2407 */
[849ed54]2408 ipc_call_t call;
2409 ipc_callid_t callid = async_get_call(&call);
[7c8267b]2410
2411 /*
2412 Process the message
2413 */
[14f1db0]2414 int res = tl_module_message_standalone(callid, &call, &answer,
2415 &answer_count);
[7c8267b]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))
[849ed54]2422 return;
[7c8267b]2423
2424 /*
2425 Answer the message
2426 */
[849ed54]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 */
[7c8267b]2440int
2441main(int argc, char *argv[])
[849ed54]2442{
2443 ERROR_DECLARE;
[7c8267b]2444
2445 /*
2446 Start the module
2447 */
[14f1db0]2448 if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection)))
[849ed54]2449 return ERROR_CODE;
[7c8267b]2450
[849ed54]2451 return EOK;
2452}
2453
[21580dd]2454/** @}
2455 */
Note: See TracBrowser for help on using the repository browser.