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

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

Mark EPARTY for replacement by another error code.

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