source: mainline/uspace/srv/net/tl/tcp/tcp.c@ 24ab58b3

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

more compact network startup messages (usually one line instead of multiple lines)
pass module name as an argument to nil_message() and friends
deeper cstyle changes (replace forward prototypes with proper extern declarations and static functions, change doxygen comments, stick more closely to the 80-column rule, no argument names in header files, spacing, comments, etc.)

  • Property mode set to 100644
File size: 68.5 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 <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>
70
71#include "tcp.h"
72#include "tcp_header.h"
73#include "tcp_module.h"
74
75/** TCP module name.
76 */
77#define NAME "TCP protocol"
78
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 */
125#define IS_IN_INTERVAL_OVERFLOW(lower, value, higher_equal) ((((lower) < (value)) && (((value) <= (higher_equal)) || ((higher_equal) < (lower)))) || (((value) <= (higher_equal)) && ((higher_equal) < (lower))))
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 */
144 int globals_read_only;
145 /** Socket port.
146 */
147 int port;
148 /** Local sockets.
149 */
150 socket_cores_ref local_sockets;
151 /** Socket identifier.
152 */
153 int socket_id;
154 /** Socket state.
155 */
156 tcp_socket_state_t state;
157 /** Sent packet sequence number.
158 */
159 int sequence_number;
160 /** Timeout in microseconds.
161 */
162 suseconds_t timeout;
163 /** Port map key.
164 */
165 char * key;
166 /** Port map key length.
167 */
168 size_t key_length;
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 */
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);
210
211/** TCP global data.
212 */
213tcp_globals_t tcp_globals;
214
215int tcp_initialize(async_client_conn_t client_connection){
216 ERROR_DECLARE;
217
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){
224 return tcp_globals.ip_phone;
225 }
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);
229 return ERROR_CODE;
230 }
231 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
232 fibril_rwlock_write_unlock(&tcp_globals.lock);
233 return EOK;
234}
235
236int tcp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
237 ERROR_DECLARE;
238
239 if(receiver != SERVICE_TCP){
240 return EREFUSED;
241 }
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);
247
248 return ERROR_CODE;
249}
250
251int tcp_process_packet(device_id_t device_id, packet_t packet, services_t error){
252 ERROR_DECLARE;
253
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){
273 case SERVICE_ICMP:
274 // process error
275 result = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
276 if(result < 0){
277 return tcp_release_and_return(packet, result);
278 }
279 length = (size_t) result;
280 if(ERROR_OCCURRED(packet_trim(packet, length, 0))){
281 return tcp_release_and_return(packet, ERROR_CODE);
282 }
283 break;
284 default:
285 return tcp_release_and_return(packet, ENOTSUP);
286 }
287 }
288
289 // TODO process received ipopts?
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);
294 }
295 offset = (size_t) result;
296
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);
301 }
302 if(length < TCP_HEADER_SIZE + offset){
303 return tcp_release_and_return(packet, NO_DATA);
304 }
305
306 // trim all but TCP header
307 if(ERROR_OCCURRED(packet_trim(packet, offset, 0))){
308 return tcp_release_and_return(packet, ERROR_CODE);
309 }
310
311 // get tcp header
312 header = (tcp_header_ref) packet_get_data(packet);
313 if(! header){
314 return tcp_release_and_return(packet, NO_DATA);
315 }
316// printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header), ntohs(header->destination_port));
317
318 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
319 if(result <= 0){
320 return tcp_release_and_return(packet, result);
321 }
322 addrlen = (size_t) result;
323
324 if(ERROR_OCCURRED(tl_set_address_port(src, addrlen, ntohs(header->source_port)))){
325 return tcp_release_and_return(packet, ERROR_CODE);
326 }
327
328 // find the destination socket
329 socket = socket_port_find(&tcp_globals.sockets, ntohs(header->destination_port), (const char *) src, addrlen);
330 if(! socket){
331// printf("listening?\n");
332 // find the listening destination socket
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);
337 }
338 return EADDRNOTAVAIL;
339 }
340 }
341 printf("socket id %d\n", socket->socket_id);
342 socket_data = (tcp_socket_data_ref) socket->specific_data;
343 assert(socket_data);
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;
355 length = packet_get_data_length(next_packet);
356 if(length <= 0){
357 return tcp_release_and_return(packet, NO_DATA);
358 }
359 total_length += length;
360 // add partial checksum if set
361 if(! error){
362 checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet));
363 }
364 }while((next_packet = pq_next(next_packet)));
365// printf("fragments %d of %d bytes\n", fragments, total_length);
366
367// printf("lock?\n");
368 fibril_rwlock_write_lock(socket_data->local_lock);
369// printf("locked\n");
370 if(! error){
371 if(socket_data->state == TCP_SOCKET_LISTEN){
372 if(socket_data->pseudo_header){
373 free(socket_data->pseudo_header);
374 socket_data->pseudo_header = NULL;
375 socket_data->headerlen = 0;
376 }
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);
380 }
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);
384 }
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))){
390 // checksum error ICMP
391 icmp_parameter_problem_msg(tcp_globals.icmp_phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->checksum)) - ((size_t) ((void *) header)), packet);
392 }
393 return EINVAL;
394 }
395 }
396
397 fibril_rwlock_read_unlock(&tcp_globals.lock);
398
399 // TODO error reporting/handling
400// printf("st %d\n", socket_data->state);
401 switch(socket_data->state){
402 case TCP_SOCKET_LISTEN:
403 ERROR_CODE = tcp_process_listen(socket, socket_data, header, packet, src, dest, addrlen);
404 break;
405 case TCP_SOCKET_SYN_RECEIVED:
406 ERROR_CODE = tcp_process_syn_received(socket, socket_data, header, packet);
407 break;
408 case TCP_SOCKET_SYN_SENT:
409 ERROR_CODE = tcp_process_syn_sent(socket, socket_data, header, packet);
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:
420 ERROR_CODE = tcp_process_established(socket, socket_data, header, packet, fragments, total_length);
421 break;
422 default:
423 pq_release(tcp_globals.net_phone, packet_get_id(packet));
424 }
425
426 if(ERROR_CODE != EOK){
427 printf("process %d\n", ERROR_CODE);
428 fibril_rwlock_write_unlock(socket_data->local_lock);
429 }
430 return EOK;
431}
432
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){
434 ERROR_DECLARE;
435
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);
452 old_incoming = socket_data->next_incoming;
453
454 if(header->finalize){
455 socket_data->fin_incoming = new_sequence_number;
456 }
457
458// printf("pe %d < %d <= %d\n", new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length);
459 // trim begining if containing expected data
460 if(IS_IN_INTERVAL_OVERFLOW(new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length)){
461 // get the acknowledged offset
462 if(socket_data->next_incoming < new_sequence_number){
463 offset = new_sequence_number - socket_data->next_incoming;
464 }else{
465 offset = socket_data->next_incoming - new_sequence_number;
466 }
467// printf("offset %d\n", offset);
468 new_sequence_number += offset;
469 total_length -= offset;
470 length = packet_get_data_length(packet);
471 // trim the acknowledged data
472 while(length <= offset){
473 // release the acknowledged packets
474 next_packet = pq_next(packet);
475 pq_release(tcp_globals.net_phone, packet_get_id(packet));
476 packet = next_packet;
477 offset -= length;
478 length = packet_get_data_length(packet);
479 }
480 if((offset > 0)
481 && (ERROR_OCCURRED(packet_trim(packet, offset, 0)))){
482 return tcp_release_and_return(packet, ERROR_CODE);
483 }
484 assert(new_sequence_number == socket_data->next_incoming);
485 }
486
487 // release if overflowing the window
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);
490// }
491
492/*
493 // trim end if overflowing the window
494 if(IS_IN_INTERVAL_OVERFLOW(new_sequence_number, socket_data->next_incoming + socket_data->window, new_sequence_number + total_length)){
495 // get the allowed data length
496 if(socket_data->next_incoming + socket_data->window < new_sequence_number){
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
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);
509 }
510 offset -= length;
511 total_length -= length - offset;
512 }
513 // release the overflowing packets
514 next_packet = pq_next(next_packet);
515 if(next_packet){
516 tmp_packet = next_packet;
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));
520 }
521 assert(new_sequence_number + total_length == socket_data->next_incoming + socket_data->window);
522 }
523*/
524 // the expected one arrived?
525 if(new_sequence_number == socket_data->next_incoming){
526 printf("expected\n");
527 // process acknowledgement
528 tcp_process_acknowledgement(socket, socket_data, header);
529
530 // remove the header
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);
534 }
535
536 if(total_length){
537 ERROR_PROPAGATE(tcp_queue_received_packet(socket, socket_data, packet, fragments, total_length));
538 }else{
539 total_length = 1;
540 }
541 socket_data->next_incoming = old_incoming + total_length;
542 packet = socket_data->incoming;
543 while(packet){
544 if(ERROR_OCCURRED(pq_get_order(socket_data->incoming, &order, NULL))){
545 // remove the corrupted packet
546 next_packet = pq_detach(packet);
547 if(packet == socket_data->incoming){
548 socket_data->incoming = next_packet;
549 }
550 pq_release(tcp_globals.net_phone, packet_get_id(packet));
551 packet = next_packet;
552 continue;
553 }
554 sequence_number = (uint32_t) order;
555 if(IS_IN_INTERVAL_OVERFLOW(sequence_number, old_incoming, socket_data->next_incoming)){
556 // move to the next
557 packet = pq_next(packet);
558 // coninual data?
559 }else if(IS_IN_INTERVAL_OVERFLOW(old_incoming, sequence_number, socket_data->next_incoming)){
560 // detach the packet
561 next_packet = pq_detach(packet);
562 if(packet == socket_data->incoming){
563 socket_data->incoming = next_packet;
564 }
565 // get data length
566 length = packet_get_data_length(packet);
567 new_sequence_number = sequence_number + length;
568 if(length <= 0){
569 // remove the empty packet
570 pq_release(tcp_globals.net_phone, packet_get_id(packet));
571 packet = next_packet;
572 continue;
573 }
574 // exactly following
575 if(sequence_number == socket_data->next_incoming){
576 // queue received data
577 ERROR_PROPAGATE(tcp_queue_received_packet(socket, socket_data, packet, 1, packet_get_data_length(packet)));
578 socket_data->next_incoming = new_sequence_number;
579 packet = next_packet;
580 continue;
581 // at least partly following data?
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){
584 length = new_sequence_number - socket_data->next_incoming;
585 }else{
586 length = socket_data->next_incoming - new_sequence_number;
587 }
588 if(! ERROR_OCCURRED(packet_trim(packet, length, 0))){
589 // queue received data
590 ERROR_PROPAGATE(tcp_queue_received_packet(socket, socket_data, packet, 1, packet_get_data_length(packet)));
591 socket_data->next_incoming = new_sequence_number;
592 packet = next_packet;
593 continue;
594 }
595 }
596 // remove the duplicit or corrupted packet
597 pq_release(tcp_globals.net_phone, packet_get_id(packet));
598 packet = next_packet;
599 continue;
600 }else{
601 break;
602 }
603 }
604 }else if(IS_IN_INTERVAL(socket_data->next_incoming, new_sequence_number, socket_data->next_incoming + socket_data->window)){
605 printf("in window\n");
606 // process acknowledgement
607 tcp_process_acknowledgement(socket, socket_data, header);
608
609 // remove the header
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);
613 }
614
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))){
618 // remove the corrupted packets
619 pq_release(tcp_globals.net_phone, packet_get_id(packet));
620 pq_release(tcp_globals.net_phone, packet_get_id(next_packet));
621 }else{
622 while(next_packet){
623 new_sequence_number += length;
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));
629 }
630 next_packet = tmp_packet;
631 }
632 }
633 }else{
634 printf("unexpected\n");
635 // release duplicite or restricted
636 pq_release(tcp_globals.net_phone, packet_get_id(packet));
637 }
638
639 // change state according to the acknowledging incoming fin
640 if(IS_IN_INTERVAL_OVERFLOW(old_incoming, socket_data->fin_incoming, socket_data->next_incoming)){
641 switch(socket_data->state){
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
654 packet = tcp_get_packets_to_send(socket, socket_data);
655 if(! packet){
656 // create the notification packet
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);
660 }
661 fibril_rwlock_write_unlock(socket_data->local_lock);
662 // send the packet
663 tcp_send_packets(socket_data->device_id, packet);
664 return EOK;
665}
666
667int tcp_queue_received_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, int fragments, size_t total_length){
668 ERROR_DECLARE;
669
670 packet_dimension_ref packet_dimension;
671
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);
678
679 // queue the received packet
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);
683 }
684
685 // decrease the window size
686 socket_data->window -= total_length;
687
688 // notify the destination socket
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);
690 return EOK;
691}
692
693int tcp_process_syn_sent(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet){
694 ERROR_DECLARE;
695
696 packet_t next_packet;
697
698 assert(socket);
699 assert(socket_data);
700 assert(socket->specific_data == socket_data);
701 assert(header);
702 assert(packet);
703
704 if(header->synchronize){
705 // process acknowledgement
706 tcp_process_acknowledgement(socket, socket_data, header);
707
708 socket_data->next_incoming = ntohl(header->sequence_number) + 1;
709 // release additional packets
710 next_packet = pq_detach(packet);
711 if(next_packet){
712 pq_release(tcp_globals.net_phone, packet_get_id(next_packet));
713 }
714 // trim if longer than the header
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);
718 }
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){
723 socket_data->state = TCP_SOCKET_ESTABLISHED;
724 packet = tcp_get_packets_to_send(socket, socket_data);
725 if(packet){
726 fibril_rwlock_write_unlock(socket_data->local_lock);
727 // send the packet
728 tcp_send_packets(socket_data->device_id, packet);
729 // signal the result
730 fibril_condvar_signal(&socket_data->operation.condvar);
731 fibril_mutex_unlock(&socket_data->operation.mutex);
732 return EOK;
733 }
734 }
735 fibril_mutex_unlock(&socket_data->operation.mutex);
736 }
737 return tcp_release_and_return(packet, EINVAL);
738}
739
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){
741 ERROR_DECLARE;
742
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);
761 }else{
762 tcp_initialize_socket_data(socket_data);
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
767 socket_data->next_incoming = ntohl(header->sequence_number);
768 socket_data->treshold = socket_data->next_incoming + ntohs(header->window);
769
770 socket_data->addrlen = addrlen;
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);
775 }
776 memcpy(socket_data->addr, src, socket_data->addrlen);
777
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));
783 return ERROR_CODE;
784 }
785
786// printf("addr %p\n", socket_data->addr, socket_data->addrlen);
787 // create a socket
788 socket_id = -1;
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);
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
801 fibril_rwlock_write_unlock(socket_data->local_lock);
802// printf("list lg\n");
803 fibril_rwlock_write_lock(&tcp_globals.lock);
804// printf("list locked\n");
805 // find the destination socket
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);
809 // a shadow may remain until app hangs up
810 return tcp_release_and_return(packet, EOK/*ENOTSOCK*/);
811 }
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);
815
816// printf("list ll\n");
817 fibril_rwlock_write_lock(listening_socket_data->local_lock);
818// printf("list locked\n");
819
820 socket = socket_cores_find(listening_socket_data->local_sockets, socket_id);
821 if(! socket){
822 // where is the socket?!?
823 fibril_rwlock_write_unlock(&tcp_globals.lock);
824 return ENOTSOCK;
825 }
826 socket_data = (tcp_socket_data_ref) socket->specific_data;
827 assert(socket_data);
828
829// uint8_t * data = socket_data->addr;
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]);
831
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);
835 //tcp_globals.last_used_port = socket->port;
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);
841 }
842
843 socket_data->state = TCP_SOCKET_LISTEN;
844 socket_data->next_incoming = ntohl(header->sequence_number) + 1;
845 // release additional packets
846 next_packet = pq_detach(packet);
847 if(next_packet){
848 pq_release(tcp_globals.net_phone, packet_get_id(next_packet));
849 }
850 // trim if longer than the header
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);
855 }
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);
859 return ERROR_CODE;
860 }
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);
865 return EINVAL;
866 }else{
867 socket_data->state = TCP_SOCKET_SYN_RECEIVED;
868// printf("unlock\n");
869 fibril_rwlock_write_unlock(socket_data->local_lock);
870 // send the packet
871 tcp_send_packets(socket_data->device_id, packet);
872 return EOK;
873 }
874 }
875 }
876 return tcp_release_and_return(packet, EINVAL);
877}
878
879int tcp_process_syn_received(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet){
880 ERROR_DECLARE;
881
882 socket_core_ref listening_socket;
883 tcp_socket_data_ref listening_socket_data;
884
885 assert(socket);
886 assert(socket_data);
887 assert(socket->specific_data == socket_data);
888 assert(header);
889 assert(packet);
890
891 printf("syn_rec\n");
892 if(header->acknowledge){
893 // process acknowledgement
894 tcp_process_acknowledgement(socket, socket_data, header);
895
896 socket_data->next_incoming = ntohl(header->sequence_number);// + 1;
897 pq_release(tcp_globals.net_phone, packet_get_id(packet));
898 socket_data->state = TCP_SOCKET_ESTABLISHED;
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);
903
904 // queue the received packet
905 if(! ERROR_OCCURRED(dyn_fifo_push(&listening_socket->accepted, (-1 * socket->socket_id), listening_socket_data->backlog))){
906 // notify the destination socket
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);
909 return EOK;
910 }
911 }
912 // send FIN
913 socket_data->state = TCP_SOCKET_FIN_WAIT_1;
914
915 // create the notification packet
916 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 0, 1));
917
918 // send the packet
919 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 1));
920
921 // flush packets
922 packet = tcp_get_packets_to_send(socket, socket_data);
923 fibril_rwlock_write_unlock(socket_data->local_lock);
924 if(packet){
925 // send the packet
926 tcp_send_packets(socket_data->device_id, packet);
927 }
928 return EOK;
929 }else{
930 return tcp_release_and_return(packet, EINVAL);
931 }
932 return EINVAL;
933}
934
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);
950 // if more data acknowledged
951 if(number != socket_data->expected){
952 old = socket_data->expected;
953 if(IS_IN_INTERVAL_OVERFLOW(old, socket_data->fin_outgoing, number)){
954 switch(socket_data->state){
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
961 tcp_prepare_timeout(tcp_release_after_timeout, socket, socket_data, 0, TCP_SOCKET_TIME_WAIT, NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT, true);
962 break;
963 default:
964 break;
965 }
966 }
967 // update the treshold if higher than set
968 if(number + ntohs(header->window) > socket_data->expected + socket_data->treshold){
969 socket_data->treshold = number + ntohs(header->window) - socket_data->expected;
970 }
971 // set new expected sequence number
972 socket_data->expected = number;
973 socket_data->expected_count = 1;
974 packet = socket_data->outgoing;
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){
979 socket_data->outgoing = next;
980 }
981 // add to acknowledged or release
982 if(pq_add(&acknowledged, packet, 0, 0) != EOK){
983 pq_release(tcp_globals.net_phone, packet_get_id(packet));
984 }
985 packet = next;
986 }else if(old < socket_data->expected){
987 break;
988 }
989 }
990 // release acknowledged
991 if(acknowledged){
992 pq_release(tcp_globals.net_phone, packet_get_id(acknowledged));
993 }
994 return;
995 // if the same as the previous time
996 }else if(number == socket_data->expected){
997 // increase the counter
998 ++ socket_data->expected_count;
999 if(socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT){
1000 socket_data->expected_count = 1;
1001 // TODO retransmit lock
1002 //tcp_retransmit_packet(socket, socket_data, number);
1003 }
1004 }
1005 }
1006}
1007
1008int tcp_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
1009 ERROR_DECLARE;
1010
1011 packet_t packet;
1012
1013 assert(call);
1014 assert(answer);
1015 assert(answer_count);
1016
1017 *answer_count = 0;
1018 switch(IPC_GET_METHOD(*call)){
1019 case NET_TL_RECEIVED:
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));
1023 }
1024 //fibril_rwlock_read_unlock(&tcp_globals.lock);
1025 return ERROR_CODE;
1026 case IPC_M_CONNECT_TO_ME:
1027 return tcp_process_client_messages(callid, * call);
1028 }
1029 return ENOTSUP;
1030}
1031
1032void tcp_refresh_socket_data(tcp_socket_data_ref socket_data){
1033 assert(socket_data);
1034
1035 bzero(socket_data, sizeof(*socket_data));
1036 socket_data->state = TCP_SOCKET_INITIAL;
1037 socket_data->device_id = DEVICE_INVALID_ID;
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
1047void tcp_initialize_socket_data(tcp_socket_data_ref socket_data){
1048 assert(socket_data);
1049
1050 tcp_refresh_socket_data(socket_data);
1051 fibril_mutex_initialize(&socket_data->operation.mutex);
1052 fibril_condvar_initialize(&socket_data->operation.condvar);
1053 socket_data->data_fragment_size = MAX_TCP_FRAGMENT_SIZE;
1054}
1055
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;
1062 int socket_id;
1063 size_t addrlen;
1064 size_t size;
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;
1071
1072 /*
1073 * Accept the connection
1074 * - Answer the first IPC_M_CONNECT_ME_TO call.
1075 */
1076 res = EOK;
1077 answer_count = 0;
1078
1079 socket_cores_initialize(&local_sockets);
1080 fibril_rwlock_initialize(&lock);
1081
1082 while(keep_on_going){
1083
1084 // answer the call
1085 answer_call(callid, res, &answer, answer_count);
1086
1087 // refresh data
1088 refresh_answer(&answer, &answer_count);
1089
1090 // get the next call
1091 callid = async_get_call(&call);
1092
1093 // process the call
1094 switch(IPC_GET_METHOD(call)){
1095 case IPC_M_PHONE_HUNGUP:
1096 keep_on_going = false;
1097 res = EHANGUP;
1098 break;
1099 case NET_SOCKET:
1100 socket_data = (tcp_socket_data_ref) malloc(sizeof(*socket_data));
1101 if(! socket_data){
1102 res = ENOMEM;
1103 }else{
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);
1108 socket_id = SOCKET_GET_SOCKET_ID(call);
1109 res = socket_create(&local_sockets, app_phone, socket_data, &socket_id);
1110 SOCKET_SET_SOCKET_ID(answer, socket_id);
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){
1114 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, ((packet_dimension->content < socket_data->data_fragment_size) ? packet_dimension->content : socket_data->data_fragment_size));
1115 }
1116// SOCKET_SET_DATA_FRAGMENT_SIZE(answer, MAX_TCP_FRAGMENT_SIZE);
1117 SOCKET_SET_HEADER_SIZE(answer, TCP_HEADER_SIZE);
1118 answer_count = 3;
1119 }else{
1120 free(socket_data);
1121 }
1122 }
1123 break;
1124 case NET_SOCKET_BIND:
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);
1135 socket_data->state = TCP_SOCKET_LISTEN;
1136 }
1137 }
1138 fibril_rwlock_write_unlock(&lock);
1139 fibril_rwlock_write_unlock(&tcp_globals.lock);
1140 free(addr);
1141 }
1142 break;
1143 case NET_SOCKET_LISTEN:
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);
1151 break;
1152 case NET_SOCKET_CONNECT:
1153 res = data_receive((void **) &addr, &addrlen);
1154 if(res == EOK){
1155 // the global lock may be released in the tcp_connect_message() function
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);
1163 }
1164 }
1165 break;
1166 case NET_SOCKET_ACCEPT:
1167 fibril_rwlock_read_lock(&tcp_globals.lock);
1168 fibril_rwlock_write_lock(&lock);
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);
1171 fibril_rwlock_write_unlock(&lock);
1172 fibril_rwlock_read_unlock(&tcp_globals.lock);
1173 if(res > 0){
1174 SOCKET_SET_SOCKET_ID(answer, res);
1175 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
1176 answer_count = 3;
1177 }
1178 break;
1179 case NET_SOCKET_SEND:
1180 fibril_rwlock_read_lock(&tcp_globals.lock);
1181 fibril_rwlock_write_lock(&lock);
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);
1184 if(res != EOK){
1185 fibril_rwlock_write_unlock(&lock);
1186 fibril_rwlock_read_unlock(&tcp_globals.lock);
1187 }else{
1188 answer_count = 2;
1189 }
1190 break;
1191 case NET_SOCKET_SENDTO:
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);
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);
1198 if(res != EOK){
1199 fibril_rwlock_write_unlock(&lock);
1200 fibril_rwlock_read_unlock(&tcp_globals.lock);
1201 }else{
1202 answer_count = 2;
1203 }
1204 free(addr);
1205 }
1206 break;
1207 case NET_SOCKET_RECV:
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){
1214 SOCKET_SET_READ_DATA_LENGTH(answer, res);
1215 answer_count = 1;
1216 res = EOK;
1217 }
1218 break;
1219 case NET_SOCKET_RECVFROM:
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){
1226 SOCKET_SET_READ_DATA_LENGTH(answer, res);
1227 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
1228 answer_count = 3;
1229 res = EOK;
1230 }
1231 break;
1232 case NET_SOCKET_CLOSE:
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);
1239 }
1240 break;
1241 case NET_SOCKET_GETSOCKOPT:
1242 case NET_SOCKET_SETSOCKOPT:
1243 default:
1244 res = ENOTSUP;
1245 break;
1246 }
1247 }
1248
1249 // release the application phone
1250 ipc_hangup(app_phone);
1251
1252 printf("release\n");
1253 // release all local sockets
1254 socket_cores_release(tcp_globals.net_phone, &local_sockets, &tcp_globals.sockets, tcp_free_socket_data);
1255
1256 return EOK;
1257}
1258
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;
1264
1265 assert(timeout);
1266
1267 // sleep the given timeout
1268 async_usleep(timeout->timeout);
1269 // lock the globals
1270 if(timeout->globals_read_only){
1271 fibril_rwlock_read_lock(&tcp_globals.lock);
1272 }else{
1273 fibril_rwlock_write_lock(&tcp_globals.lock);
1274 }
1275 // find the pending operation socket
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){
1283 // increase the timeout counter;
1284 ++ socket_data->timeout_count;
1285 if(socket_data->timeout_count == TCP_MAX_TIMEOUTS){
1286 // TODO release as connection lost
1287 //tcp_refresh_socket_data(socket_data);
1288 fibril_rwlock_write_unlock(socket_data->local_lock);
1289 }else{
1290 // retransmit
1291// tcp_retransmit_packet(socket, socket_data, timeout->sequence_number);
1292 fibril_rwlock_write_unlock(socket_data->local_lock);
1293 }
1294 }else{
1295 fibril_mutex_lock(&socket_data->operation.mutex);
1296 // set the timeout operation result if state not changed
1297 if(socket_data->state == timeout->state){
1298 socket_data->operation.result = ETIMEOUT;
1299 // notify the main fibril
1300 fibril_condvar_signal(&socket_data->operation.condvar);
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...
1306 fibril_rwlock_write_unlock(socket_data->local_lock);
1307 }
1308 fibril_mutex_unlock(&socket_data->operation.mutex);
1309 }
1310 }
1311 }
1312 // unlock only if no socket
1313 if(timeout->globals_read_only){
1314 fibril_rwlock_read_unlock(&tcp_globals.lock);
1315 }else if(! keep_write_lock){
1316 // release if not desired
1317 fibril_rwlock_write_unlock(&tcp_globals.lock);
1318 }
1319 // release the timeout structure
1320 free(timeout);
1321 return EOK;
1322}
1323
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;
1329
1330 assert(timeout);
1331
1332 // sleep the given timeout
1333 async_usleep(timeout->timeout);
1334 // lock the globals
1335 fibril_rwlock_write_lock(&tcp_globals.lock);
1336 // find the pending operation socket
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){
1342 local_lock = socket_data->local_lock;
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);
1346 }
1347 }
1348 // unlock the globals
1349 fibril_rwlock_write_unlock(&tcp_globals.lock);
1350 // release the timeout structure
1351 free(timeout);
1352 return EOK;
1353}
1354
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;
1359
1360 assert(socket);
1361 assert(socket_data);
1362 assert(socket->specific_data == socket_data);
1363
1364 // sent packet?
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);
1374 }
1375 }else{
1376 fibril_rwlock_write_unlock(socket_data->local_lock);
1377 }
1378}
1379
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;
1383
1384 assert(local_sockets);
1385
1386 if(backlog < 0){
1387 return EINVAL;
1388 }
1389 // find the socket
1390 socket = socket_cores_find(local_sockets, socket_id);
1391 if(! socket){
1392 return ENOTSOCK;
1393 }
1394 // get the socket specific data
1395 socket_data = (tcp_socket_data_ref) socket->specific_data;
1396 assert(socket_data);
1397 // set the backlog
1398 socket_data->backlog = backlog;
1399 return EOK;
1400}
1401
1402int tcp_connect_message(socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen){
1403 ERROR_DECLARE;
1404
1405 socket_core_ref socket;
1406
1407 assert(local_sockets);
1408 assert(addr);
1409 assert(addrlen > 0);
1410
1411 // find the socket
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);
1418 // unbind if bound
1419 if(socket->port > 0){
1420 socket_ports_exclude(&tcp_globals.sockets, socket->port);
1421 socket->port = 0;
1422 }
1423 }
1424 return ERROR_CODE;
1425}
1426
1427int tcp_connect_core(socket_core_ref socket, socket_cores_ref local_sockets, struct sockaddr * addr, socklen_t addrlen){
1428 ERROR_DECLARE;
1429
1430 tcp_socket_data_ref socket_data;
1431 packet_t packet;
1432
1433 assert(socket);
1434 assert(addr);
1435 assert(addrlen > 0);
1436
1437 // get the socket specific data
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))){
1443 return EINVAL;
1444 }
1445 // get the destination port
1446 ERROR_PROPAGATE(tl_get_address_port(addr, addrlen, &socket_data->dest_port));
1447 if(socket->port <= 0){
1448 // try to find a free port
1449 ERROR_PROPAGATE(socket_bind_free_port(&tcp_globals.sockets, socket, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port));
1450 // set the next port as the search starting port number
1451 tcp_globals.last_used_port = socket->port;
1452 }
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));
1454
1455 // create the notification packet
1456 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 1, 0));
1457
1458 // unlock the globals and wait for an operation
1459 fibril_rwlock_write_unlock(&tcp_globals.lock);
1460
1461 socket_data->addr = addr;
1462 socket_data->addrlen = addrlen;
1463 // send the packet
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))){
1466 socket_data->addr = NULL;
1467 socket_data->addrlen = 0;
1468 fibril_rwlock_write_lock(&tcp_globals.lock);
1469 }else{
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);
1474 // send the packet
1475 printf("connecting %d\n", packet_get_id(packet));
1476 tcp_send_packets(socket_data->device_id, packet);
1477 // wait for a reply
1478 fibril_condvar_wait(&socket_data->operation.condvar, &socket_data->operation.mutex);
1479 ERROR_CODE = socket_data->operation.result;
1480 if(ERROR_CODE != EOK){
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
1491 fibril_mutex_unlock(&socket_data->operation.mutex);
1492
1493 // return the result
1494 return ERROR_CODE;
1495}
1496
1497int tcp_queue_prepare_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length){
1498 ERROR_DECLARE;
1499
1500 tcp_header_ref header;
1501
1502 assert(socket);
1503 assert(socket_data);
1504 assert(socket->specific_data == socket_data);
1505
1506 // get tcp header
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);
1516 }
1517 // remember the outgoing FIN
1518 if(header->finalize){
1519 socket_data->fin_outgoing = socket_data->next_outgoing;
1520 }
1521 return EOK;
1522}
1523
1524int tcp_queue_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length){
1525 ERROR_DECLARE;
1526
1527 assert(socket);
1528 assert(socket_data);
1529 assert(socket->specific_data == socket_data);
1530
1531 ERROR_PROPAGATE(tcp_queue_prepare_packet(socket, socket_data, packet, data_length));
1532
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);
1535 }
1536 socket_data->next_outgoing += data_length;
1537 return EOK;
1538}
1539
1540packet_t tcp_get_packets_to_send(socket_core_ref socket, tcp_socket_data_ref socket_data){
1541 ERROR_DECLARE;
1542
1543 packet_t packet;
1544 packet_t copy;
1545 packet_t sending = NULL;
1546 packet_t previous = NULL;
1547 size_t data_length;
1548
1549 assert(socket);
1550 assert(socket_data);
1551 assert(socket->specific_data == socket_data);
1552
1553 packet = pq_find(socket_data->outgoing, socket_data->last_outgoing + 1);
1554 while(packet){
1555 pq_get_order(packet, NULL, &data_length);
1556 // send only if fits into the window
1557 // respecting the possible overflow
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){
1561 return sending;
1562 }
1563 if(! sending){
1564 sending = copy;
1565 }else{
1566 if(ERROR_OCCURRED(pq_insert_after(previous, copy))){
1567 pq_release(tcp_globals.net_phone, packet_get_id(copy));
1568 return sending;
1569 }
1570 }
1571 previous = copy;
1572 packet = pq_next(packet);
1573 // overflow occurred ?
1574 if((! packet) && (socket_data->last_outgoing > socket_data->next_outgoing)){
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
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){
1588 ERROR_DECLARE;
1589
1590 tcp_header_ref header;
1591 uint32_t checksum;
1592
1593 assert(socket);
1594 assert(socket_data);
1595 assert(socket->specific_data == socket_data);
1596
1597 // adjust the pseudo header
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));
1600 return NULL;
1601 }
1602
1603 // get the header
1604 header = (tcp_header_ref) packet_get_data(packet);
1605 if(! header){
1606 pq_release(tcp_globals.net_phone, packet_get_id(packet));
1607 return NULL;
1608 }
1609 assert(ntohl(header->sequence_number) == sequence_number);
1610
1611 // adjust the header
1612 if(socket_data->next_incoming){
1613 header->acknowledgement_number = htonl(socket_data->next_incoming);
1614 header->acknowledge = 1;
1615 }
1616 header->window = htons(socket_data->window);
1617
1618 // checksum
1619 header->checksum = 0;
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)));
1623 // prepare the packet
1624 if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0))
1625 // prepare the timeout
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));
1628 return NULL;
1629 }
1630 return packet;
1631}
1632
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;
1635
1636 assert(socket);
1637 assert(socket_data);
1638 assert(socket->specific_data == socket_data);
1639
1640 // make a copy of the packet
1641 copy = packet_get_copy(tcp_globals.net_phone, packet);
1642 if(! copy){
1643 return NULL;
1644 }
1645
1646 return tcp_send_prepare_packet(socket, socket_data, copy, data_length, sequence_number);
1647}
1648
1649void tcp_send_packets(device_id_t device_id, packet_t packet){
1650 packet_t next;
1651
1652 while(packet){
1653 next = pq_detach(packet);
1654 ip_send_msg(tcp_globals.ip_phone, device_id, packet, SERVICE_TCP, 0);
1655 packet = next;
1656 }
1657}
1658
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);
1664
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));
1669 header->synchronize = synchronize;
1670 header->finalize = finalize;
1671}
1672
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;
1676
1677 assert(socket);
1678 assert(socket_data);
1679 assert(socket->specific_data == socket_data);
1680
1681 // prepare the timeout with key bundle structure
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));
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
1696 operation_timeout->key = ((char *) operation_timeout) + sizeof(*operation_timeout);
1697 operation_timeout->key_length = socket->key_length;
1698 memcpy(operation_timeout->key, socket->key, socket->key_length);
1699 operation_timeout->key[operation_timeout->key_length] = '\0';
1700
1701 // prepare the timeouting thread
1702 fibril = fibril_create(timeout_function, operation_timeout);
1703 if(! fibril){
1704 free(operation_timeout);
1705 return EPARTY;
1706 }
1707// fibril_mutex_lock(&socket_data->operation.mutex);
1708 // start the timeouting fibril
1709 fibril_add_ready(fibril);
1710 //socket_data->state = state;
1711 return EOK;
1712}
1713
1714int tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){
1715 ERROR_DECLARE;
1716
1717 socket_core_ref socket;
1718 tcp_socket_data_ref socket_data;
1719 int packet_id;
1720 packet_t packet;
1721 size_t length;
1722
1723 assert(local_sockets);
1724
1725 // find the socket
1726 socket = socket_cores_find(local_sockets, socket_id);
1727 if(! socket){
1728 return ENOTSOCK;
1729 }
1730 // get the socket specific data
1731 if(! socket->specific_data){
1732 return NO_DATA;
1733 }
1734 socket_data = (tcp_socket_data_ref) socket->specific_data;
1735
1736 // check state
1737 if((socket_data->state != TCP_SOCKET_ESTABLISHED) && (socket_data->state != TCP_SOCKET_CLOSE_WAIT)){
1738 return ENOTCONN;
1739 }
1740
1741 // send the source address if desired
1742 if(addrlen){
1743 ERROR_PROPAGATE(data_reply(socket_data->addr, socket_data->addrlen));
1744 *addrlen = socket_data->addrlen;
1745 }
1746
1747 // get the next received packet
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));
1753
1754 // reply the packets
1755 ERROR_PROPAGATE(socket_reply_packets(packet, &length));
1756
1757 // release the packet
1758 dyn_fifo_pop(&socket->received);
1759 pq_release(tcp_globals.net_phone, packet_get_id(packet));
1760 // return the total length
1761 return (int) length;
1762}
1763
1764int tcp_send_message(socket_cores_ref local_sockets, int socket_id, int fragments, size_t * data_fragment_size, int flags){
1765 ERROR_DECLARE;
1766
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;
1775
1776 assert(local_sockets);
1777 assert(data_fragment_size);
1778
1779 // find the socket
1780 socket = socket_cores_find(local_sockets, socket_id);
1781 if(! socket){
1782 return ENOTSOCK;
1783 }
1784 // get the socket specific data
1785 if(! socket->specific_data){
1786 return NO_DATA;
1787 }
1788 socket_data = (tcp_socket_data_ref) socket->specific_data;
1789
1790 // check state
1791 if((socket_data->state != TCP_SOCKET_ESTABLISHED) && (socket_data->state != TCP_SOCKET_CLOSE_WAIT)){
1792 return ENOTCONN;
1793 }
1794
1795 ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
1796
1797 *data_fragment_size = ((packet_dimension->content < socket_data->data_fragment_size) ? packet_dimension->content : socket_data->data_fragment_size);
1798
1799 for(index = 0; index < fragments; ++ index){
1800 // read the data fragment
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;
1806 // prefix the tcp header
1807 header = PACKET_PREFIX(packet, tcp_header_t);
1808 if(! header){
1809 return tcp_release_and_return(packet, ENOMEM);
1810 }
1811 tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
1812 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 0));
1813 }
1814
1815 // flush packets
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){
1820 // send the packet
1821 tcp_send_packets(socket_data->device_id, packet);
1822 }
1823
1824 return EOK;
1825}
1826
1827int tcp_close_message(socket_cores_ref local_sockets, int socket_id){
1828 ERROR_DECLARE;
1829
1830 socket_core_ref socket;
1831 tcp_socket_data_ref socket_data;
1832 packet_t packet;
1833
1834 // find the socket
1835 socket = socket_cores_find(local_sockets, socket_id);
1836 if(! socket){
1837 return ENOTSOCK;
1838 }
1839 // get the socket specific data
1840 socket_data = (tcp_socket_data_ref) socket->specific_data;
1841 assert(socket_data);
1842
1843 // check state
1844 switch(socket_data->state){
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
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);
1857 }
1858 return ERROR_CODE;
1859 }
1860 // send FIN
1861 // TODO should I wait to complete?
1862
1863 // create the notification packet
1864 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 0, 1));
1865
1866 // send the packet
1867 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 1));
1868
1869 // flush packets
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){
1874 // send the packet
1875 tcp_send_packets(socket_data->device_id, packet);
1876 }
1877 return EOK;
1878}
1879
1880int tcp_create_notification_packet(packet_t * packet, socket_core_ref socket, tcp_socket_data_ref socket_data, int synchronize, int finalize){
1881 ERROR_DECLARE;
1882
1883 packet_dimension_ref packet_dimension;
1884 tcp_header_ref header;
1885
1886 assert(packet);
1887
1888 // get the device packet dimension
1889 ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
1890 // get a new packet
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 }
1895 // allocate space in the packet
1896 header = PACKET_SUFFIX(*packet, tcp_header_t);
1897 if(! header){
1898 tcp_release_and_return(*packet, ENOMEM);
1899 }
1900
1901 tcp_prepare_operation_header(socket, socket_data, header, synchronize, finalize);
1902 return EOK;
1903}
1904
1905int tcp_accept_message(socket_cores_ref local_sockets, int socket_id, int new_socket_id, size_t * data_fragment_size, size_t * addrlen){
1906 ERROR_DECLARE;
1907
1908 socket_core_ref accepted;
1909 socket_core_ref socket;
1910 tcp_socket_data_ref socket_data;
1911 packet_dimension_ref packet_dimension;
1912
1913 assert(local_sockets);
1914 assert(data_fragment_size);
1915 assert(addrlen);
1916
1917 // find the socket
1918 socket = socket_cores_find(local_sockets, socket_id);
1919 if(! socket){
1920 return ENOTSOCK;
1921 }
1922 // get the socket specific data
1923 socket_data = (tcp_socket_data_ref) socket->specific_data;
1924 assert(socket_data);
1925
1926 // check state
1927 if(socket_data->state != TCP_SOCKET_LISTEN){
1928 return EINVAL;
1929 }
1930
1931 do{
1932 socket_id = dyn_fifo_value(&socket->accepted);
1933 if(socket_id < 0){
1934 return ENOTSOCK;
1935 }
1936 socket_id *= -1;
1937
1938 accepted = socket_cores_find(local_sockets, socket_id);
1939 if(! accepted){
1940 return ENOTSOCK;
1941 }
1942 // get the socket specific data
1943 socket_data = (tcp_socket_data_ref) accepted->specific_data;
1944 assert(socket_data);
1945 // TODO can it be in another state?
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));
1953 accepted->socket_id = new_socket_id;
1954 }
1955 }
1956 dyn_fifo_pop(&socket->accepted);
1957 }while(socket_data->state != TCP_SOCKET_ESTABLISHED);
1958 printf("ret accept %d\n", accepted->socket_id);
1959 return accepted->socket_id;
1960}
1961
1962void tcp_free_socket_data(socket_core_ref socket){
1963 tcp_socket_data_ref socket_data;
1964
1965 assert(socket);
1966
1967 printf("destroy_socket %d\n", socket->socket_id);
1968
1969 // get the socket specific data
1970 socket_data = (tcp_socket_data_ref) socket->specific_data;
1971 assert(socket_data);
1972 //free the pseudo header
1973 if(socket_data->pseudo_header){
1974 if(socket_data->headerlen){
1975 printf("d pseudo\n");
1976 free(socket_data->pseudo_header);
1977 socket_data->headerlen = 0;
1978 }
1979 socket_data->pseudo_header = NULL;
1980 }
1981 socket_data->headerlen = 0;
1982 // free the address
1983 if(socket_data->addr){
1984 if(socket_data->addrlen){
1985 printf("d addr\n");
1986 free(socket_data->addr);
1987 socket_data->addrlen = 0;
1988 }
1989 socket_data->addr = NULL;
1990 }
1991 socket_data->addrlen = 0;
1992}
1993
1994int tcp_release_and_return(packet_t packet, int result){
1995 pq_release(tcp_globals.net_phone, packet_get_id(packet));
1996 return result;
1997}
1998
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 /* Start the module */
2054 if (ERROR_OCCURRED(tl_module_start(tl_client_connection)))
2055 return ERROR_CODE;
2056
2057 return EOK;
2058}
2059
2060#endif /* CONFIG_NETWORKING_modular */
2061
2062/** @}
2063 */
Note: See TracBrowser for help on using the repository browser.