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

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

networking overhaul:

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