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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 849ed54 was 849ed54, checked in by Martin Decky <martin@…>, 15 years ago

Networking work:
Split the networking stack into end-user library (libsocket) and two helper libraries (libnet and libnetif).
Don't use over-the-hand compiling and linking, but rather separation of conserns.
There might be still some issues and the non-modular networking architecture is currently broken, but this will be fixed soon.

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