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
RevLine 
[21580dd]1/*
2 * Copyright (c) 2008 Lukas Mejdrech
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup tcp
30 * @{
31 */
32
33/** @file
34 * TCP module implementation.
35 * @see tcp.h
36 */
37
38#include <assert.h>
39#include <async.h>
40#include <fibril_synch.h>
41#include <malloc.h>
42//TODO remove stdio
43#include <stdio.h>
44
45#include <ipc/ipc.h>
46#include <ipc/services.h>
47
[849ed54]48#include <net_err.h>
49#include <net_messages.h>
50#include <net_modules.h>
51#include <adt/dynamic_fifo.h>
52#include <packet/packet_client.h>
[14f1db0]53#include <packet_remote.h>
[849ed54]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>
[14f1db0]71#include <tl_local.h>
72#include <tl_interface.h>
[21580dd]73
74#include "tcp.h"
75#include "tcp_header.h"
76#include "tcp_module.h"
77
[849ed54]78/** TCP module name.
79 */
80#define NAME "TCP protocol"
81
[21580dd]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 */
[aadf01e]128#define IS_IN_INTERVAL_OVERFLOW(lower, value, higher_equal) ((((lower) < (value)) && (((value) <= (higher_equal)) || ((higher_equal) < (lower)))) || (((value) <= (higher_equal)) && ((higher_equal) < (lower))))
[21580dd]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 */
[aadf01e]147 int globals_read_only;
[21580dd]148 /** Socket port.
149 */
[aadf01e]150 int port;
[21580dd]151 /** Local sockets.
152 */
[aadf01e]153 socket_cores_ref local_sockets;
[21580dd]154 /** Socket identifier.
155 */
[aadf01e]156 int socket_id;
[21580dd]157 /** Socket state.
158 */
[aadf01e]159 tcp_socket_state_t state;
[21580dd]160 /** Sent packet sequence number.
161 */
[aadf01e]162 int sequence_number;
[21580dd]163 /** Timeout in microseconds.
164 */
[aadf01e]165 suseconds_t timeout;
[21580dd]166 /** Port map key.
167 */
[aadf01e]168 char * key;
[21580dd]169 /** Port map key length.
170 */
[aadf01e]171 size_t key_length;
[21580dd]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 */
[aadf01e]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);
[21580dd]213
214/** TCP global data.
215 */
216tcp_globals_t tcp_globals;
217
[aadf01e]218int tcp_initialize(async_client_conn_t client_connection){
[21580dd]219 ERROR_DECLARE;
220
[aadf01e]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){
[21580dd]227 return tcp_globals.ip_phone;
228 }
[aadf01e]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);
[21580dd]232 return ERROR_CODE;
233 }
234 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
[aadf01e]235 fibril_rwlock_write_unlock(&tcp_globals.lock);
[21580dd]236 return EOK;
237}
238
[aadf01e]239int tcp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
[21580dd]240 ERROR_DECLARE;
241
[aadf01e]242 if(receiver != SERVICE_TCP){
243 return EREFUSED;
[21580dd]244 }
[aadf01e]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);
[21580dd]250
251 return ERROR_CODE;
252}
253
[aadf01e]254int tcp_process_packet(device_id_t device_id, packet_t packet, services_t error){
[21580dd]255 ERROR_DECLARE;
256
[aadf01e]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){
[21580dd]276 case SERVICE_ICMP:
277 // process error
[aadf01e]278 result = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
279 if(result < 0){
280 return tcp_release_and_return(packet, result);
[21580dd]281 }
[aadf01e]282 length = (size_t) result;
283 if(ERROR_OCCURRED(packet_trim(packet, length, 0))){
284 return tcp_release_and_return(packet, ERROR_CODE);
[21580dd]285 }
286 break;
287 default:
[aadf01e]288 return tcp_release_and_return(packet, ENOTSUP);
[21580dd]289 }
290 }
291
292 // TODO process received ipopts?
[aadf01e]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);
[21580dd]297 }
[aadf01e]298 offset = (size_t) result;
[21580dd]299
[aadf01e]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);
[21580dd]304 }
[aadf01e]305 if(length < TCP_HEADER_SIZE + offset){
306 return tcp_release_and_return(packet, NO_DATA);
[21580dd]307 }
308
309 // trim all but TCP header
[aadf01e]310 if(ERROR_OCCURRED(packet_trim(packet, offset, 0))){
311 return tcp_release_and_return(packet, ERROR_CODE);
[21580dd]312 }
313
314 // get tcp header
[aadf01e]315 header = (tcp_header_ref) packet_get_data(packet);
316 if(! header){
317 return tcp_release_and_return(packet, NO_DATA);
[21580dd]318 }
[aadf01e]319// printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header), ntohs(header->destination_port));
[21580dd]320
[aadf01e]321 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
322 if(result <= 0){
323 return tcp_release_and_return(packet, result);
[21580dd]324 }
[aadf01e]325 addrlen = (size_t) result;
[21580dd]326
[aadf01e]327 if(ERROR_OCCURRED(tl_set_address_port(src, addrlen, ntohs(header->source_port)))){
328 return tcp_release_and_return(packet, ERROR_CODE);
[21580dd]329 }
330
331 // find the destination socket
[aadf01e]332 socket = socket_port_find(&tcp_globals.sockets, ntohs(header->destination_port), (const char *) src, addrlen);
333 if(! socket){
[21580dd]334// printf("listening?\n");
335 // find the listening destination socket
[aadf01e]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);
[21580dd]340 }
341 return EADDRNOTAVAIL;
342 }
343 }
[aadf01e]344 printf("socket id %d\n", socket->socket_id);
345 socket_data = (tcp_socket_data_ref) socket->specific_data;
346 assert(socket_data);
[21580dd]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;
[aadf01e]358 length = packet_get_data_length(next_packet);
359 if(length <= 0){
360 return tcp_release_and_return(packet, NO_DATA);
[21580dd]361 }
362 total_length += length;
363 // add partial checksum if set
[aadf01e]364 if(! error){
365 checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet));
[21580dd]366 }
[aadf01e]367 }while((next_packet = pq_next(next_packet)));
368// printf("fragments %d of %d bytes\n", fragments, total_length);
[21580dd]369
370// printf("lock?\n");
[aadf01e]371 fibril_rwlock_write_lock(socket_data->local_lock);
[21580dd]372// printf("locked\n");
[aadf01e]373 if(! error){
374 if(socket_data->state == TCP_SOCKET_LISTEN){
375 if(socket_data->pseudo_header){
376 free(socket_data->pseudo_header);
[21580dd]377 socket_data->pseudo_header = NULL;
378 socket_data->headerlen = 0;
379 }
[aadf01e]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);
[21580dd]383 }
[aadf01e]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);
[21580dd]387 }
[aadf01e]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))){
[21580dd]393 // checksum error ICMP
[aadf01e]394 icmp_parameter_problem_msg(tcp_globals.icmp_phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->checksum)) - ((size_t) ((void *) header)), packet);
[21580dd]395 }
396 return EINVAL;
397 }
398 }
399
[aadf01e]400 fibril_rwlock_read_unlock(&tcp_globals.lock);
[21580dd]401
402 // TODO error reporting/handling
[aadf01e]403// printf("st %d\n", socket_data->state);
404 switch(socket_data->state){
[21580dd]405 case TCP_SOCKET_LISTEN:
[aadf01e]406 ERROR_CODE = tcp_process_listen(socket, socket_data, header, packet, src, dest, addrlen);
[21580dd]407 break;
408 case TCP_SOCKET_SYN_RECEIVED:
[aadf01e]409 ERROR_CODE = tcp_process_syn_received(socket, socket_data, header, packet);
[21580dd]410 break;
411 case TCP_SOCKET_SYN_SENT:
[aadf01e]412 ERROR_CODE = tcp_process_syn_sent(socket, socket_data, header, packet);
[21580dd]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:
[aadf01e]423 ERROR_CODE = tcp_process_established(socket, socket_data, header, packet, fragments, total_length);
[21580dd]424 break;
425 default:
[14f1db0]426 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]427 }
428
[aadf01e]429 if(ERROR_CODE != EOK){
430 printf("process %d\n", ERROR_CODE);
431 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]432 }
433 return EOK;
434}
435
[aadf01e]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){
[21580dd]437 ERROR_DECLARE;
438
[aadf01e]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);
[21580dd]455 old_incoming = socket_data->next_incoming;
456
[aadf01e]457 if(header->finalize){
[21580dd]458 socket_data->fin_incoming = new_sequence_number;
459 }
460
[aadf01e]461// printf("pe %d < %d <= %d\n", new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length);
[21580dd]462 // trim begining if containing expected data
[aadf01e]463 if(IS_IN_INTERVAL_OVERFLOW(new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length)){
[21580dd]464 // get the acknowledged offset
[aadf01e]465 if(socket_data->next_incoming < new_sequence_number){
[21580dd]466 offset = new_sequence_number - socket_data->next_incoming;
467 }else{
468 offset = socket_data->next_incoming - new_sequence_number;
469 }
[aadf01e]470// printf("offset %d\n", offset);
[21580dd]471 new_sequence_number += offset;
472 total_length -= offset;
[aadf01e]473 length = packet_get_data_length(packet);
[21580dd]474 // trim the acknowledged data
[aadf01e]475 while(length <= offset){
[21580dd]476 // release the acknowledged packets
[aadf01e]477 next_packet = pq_next(packet);
[14f1db0]478 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]479 packet = next_packet;
480 offset -= length;
[aadf01e]481 length = packet_get_data_length(packet);
[21580dd]482 }
[aadf01e]483 if((offset > 0)
484 && (ERROR_OCCURRED(packet_trim(packet, offset, 0)))){
485 return tcp_release_and_return(packet, ERROR_CODE);
[21580dd]486 }
[aadf01e]487 assert(new_sequence_number == socket_data->next_incoming);
[21580dd]488 }
489
490 // release if overflowing the window
[aadf01e]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);
[21580dd]493// }
494
495/*
496 // trim end if overflowing the window
[aadf01e]497 if(IS_IN_INTERVAL_OVERFLOW(new_sequence_number, socket_data->next_incoming + socket_data->window, new_sequence_number + total_length)){
[21580dd]498 // get the allowed data length
[aadf01e]499 if(socket_data->next_incoming + socket_data->window < new_sequence_number){
[21580dd]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
[aadf01e]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);
[21580dd]512 }
513 offset -= length;
514 total_length -= length - offset;
515 }
516 // release the overflowing packets
[aadf01e]517 next_packet = pq_next(next_packet);
518 if(next_packet){
[21580dd]519 tmp_packet = next_packet;
[aadf01e]520 next_packet = pq_next(next_packet);
521 pq_insert_after(tmp_packet, next_packet);
[14f1db0]522 pq_release_remote(tcp_globals.net_phone, packet_get_id(tmp_packet));
[21580dd]523 }
[aadf01e]524 assert(new_sequence_number + total_length == socket_data->next_incoming + socket_data->window);
[21580dd]525 }
526*/
527 // the expected one arrived?
[aadf01e]528 if(new_sequence_number == socket_data->next_incoming){
[21580dd]529 printf("expected\n");
530 // process acknowledgement
[aadf01e]531 tcp_process_acknowledgement(socket, socket_data, header);
[21580dd]532
533 // remove the header
[aadf01e]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);
[21580dd]537 }
538
[aadf01e]539 if(total_length){
540 ERROR_PROPAGATE(tcp_queue_received_packet(socket, socket_data, packet, fragments, total_length));
[21580dd]541 }else{
542 total_length = 1;
543 }
544 socket_data->next_incoming = old_incoming + total_length;
545 packet = socket_data->incoming;
[aadf01e]546 while(packet){
547 if(ERROR_OCCURRED(pq_get_order(socket_data->incoming, &order, NULL))){
[21580dd]548 // remove the corrupted packet
[aadf01e]549 next_packet = pq_detach(packet);
550 if(packet == socket_data->incoming){
[21580dd]551 socket_data->incoming = next_packet;
552 }
[14f1db0]553 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]554 packet = next_packet;
555 continue;
556 }
[aadf01e]557 sequence_number = (uint32_t) order;
558 if(IS_IN_INTERVAL_OVERFLOW(sequence_number, old_incoming, socket_data->next_incoming)){
[21580dd]559 // move to the next
[aadf01e]560 packet = pq_next(packet);
[21580dd]561 // coninual data?
[aadf01e]562 }else if(IS_IN_INTERVAL_OVERFLOW(old_incoming, sequence_number, socket_data->next_incoming)){
[21580dd]563 // detach the packet
[aadf01e]564 next_packet = pq_detach(packet);
565 if(packet == socket_data->incoming){
[21580dd]566 socket_data->incoming = next_packet;
567 }
568 // get data length
[aadf01e]569 length = packet_get_data_length(packet);
[21580dd]570 new_sequence_number = sequence_number + length;
[aadf01e]571 if(length <= 0){
[21580dd]572 // remove the empty packet
[14f1db0]573 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]574 packet = next_packet;
575 continue;
576 }
577 // exactly following
[aadf01e]578 if(sequence_number == socket_data->next_incoming){
[21580dd]579 // queue received data
[aadf01e]580 ERROR_PROPAGATE(tcp_queue_received_packet(socket, socket_data, packet, 1, packet_get_data_length(packet)));
[21580dd]581 socket_data->next_incoming = new_sequence_number;
582 packet = next_packet;
583 continue;
584 // at least partly following data?
[aadf01e]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){
[21580dd]587 length = new_sequence_number - socket_data->next_incoming;
588 }else{
589 length = socket_data->next_incoming - new_sequence_number;
590 }
[aadf01e]591 if(! ERROR_OCCURRED(packet_trim(packet, length, 0))){
[21580dd]592 // queue received data
[aadf01e]593 ERROR_PROPAGATE(tcp_queue_received_packet(socket, socket_data, packet, 1, packet_get_data_length(packet)));
[21580dd]594 socket_data->next_incoming = new_sequence_number;
595 packet = next_packet;
596 continue;
597 }
598 }
599 // remove the duplicit or corrupted packet
[14f1db0]600 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]601 packet = next_packet;
602 continue;
603 }else{
604 break;
605 }
606 }
[aadf01e]607 }else if(IS_IN_INTERVAL(socket_data->next_incoming, new_sequence_number, socket_data->next_incoming + socket_data->window)){
[21580dd]608 printf("in window\n");
609 // process acknowledgement
[aadf01e]610 tcp_process_acknowledgement(socket, socket_data, header);
[21580dd]611
612 // remove the header
[aadf01e]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);
[21580dd]616 }
617
[aadf01e]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))){
[21580dd]621 // remove the corrupted packets
[14f1db0]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));
[21580dd]624 }else{
[aadf01e]625 while(next_packet){
[21580dd]626 new_sequence_number += length;
[aadf01e]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))){
[14f1db0]631 pq_release_remote(tcp_globals.net_phone, packet_get_id(next_packet));
[21580dd]632 }
633 next_packet = tmp_packet;
634 }
635 }
636 }else{
637 printf("unexpected\n");
638 // release duplicite or restricted
[14f1db0]639 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]640 }
641
642 // change state according to the acknowledging incoming fin
[aadf01e]643 if(IS_IN_INTERVAL_OVERFLOW(old_incoming, socket_data->fin_incoming, socket_data->next_incoming)){
644 switch(socket_data->state){
[21580dd]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
[aadf01e]657 packet = tcp_get_packets_to_send(socket, socket_data);
658 if(! packet){
[21580dd]659 // create the notification packet
[aadf01e]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);
[21580dd]663 }
[aadf01e]664 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]665 // send the packet
[aadf01e]666 tcp_send_packets(socket_data->device_id, packet);
[21580dd]667 return EOK;
668}
669
[aadf01e]670int tcp_queue_received_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, int fragments, size_t total_length){
[21580dd]671 ERROR_DECLARE;
672
[aadf01e]673 packet_dimension_ref packet_dimension;
[ede63e4]674
[aadf01e]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);
[21580dd]681
682 // queue the received packet
[aadf01e]683 if(ERROR_OCCURRED(dyn_fifo_push(&socket->received, packet_get_id(packet), SOCKET_MAX_RECEIVED_SIZE))
[14f1db0]684 || ERROR_OCCURRED(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension))){
[aadf01e]685 return tcp_release_and_return(packet, ERROR_CODE);
[21580dd]686 }
687
688 // decrease the window size
689 socket_data->window -= total_length;
690
691 // notify the destination socket
[aadf01e]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);
[21580dd]693 return EOK;
694}
695
[aadf01e]696int tcp_process_syn_sent(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet){
[21580dd]697 ERROR_DECLARE;
698
[aadf01e]699 packet_t next_packet;
[21580dd]700
[aadf01e]701 assert(socket);
702 assert(socket_data);
703 assert(socket->specific_data == socket_data);
704 assert(header);
705 assert(packet);
[21580dd]706
[aadf01e]707 if(header->synchronize){
[21580dd]708 // process acknowledgement
[aadf01e]709 tcp_process_acknowledgement(socket, socket_data, header);
[21580dd]710
[aadf01e]711 socket_data->next_incoming = ntohl(header->sequence_number) + 1;
[21580dd]712 // release additional packets
[aadf01e]713 next_packet = pq_detach(packet);
714 if(next_packet){
[14f1db0]715 pq_release_remote(tcp_globals.net_phone, packet_get_id(next_packet));
[21580dd]716 }
717 // trim if longer than the header
[aadf01e]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);
[21580dd]721 }
[aadf01e]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){
[21580dd]726 socket_data->state = TCP_SOCKET_ESTABLISHED;
[aadf01e]727 packet = tcp_get_packets_to_send(socket, socket_data);
728 if(packet){
729 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]730 // send the packet
[aadf01e]731 tcp_send_packets(socket_data->device_id, packet);
[21580dd]732 // signal the result
[aadf01e]733 fibril_condvar_signal(&socket_data->operation.condvar);
734 fibril_mutex_unlock(&socket_data->operation.mutex);
[21580dd]735 return EOK;
736 }
737 }
[aadf01e]738 fibril_mutex_unlock(&socket_data->operation.mutex);
[21580dd]739 }
[aadf01e]740 return tcp_release_and_return(packet, EINVAL);
[21580dd]741}
742
[aadf01e]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){
[21580dd]744 ERROR_DECLARE;
745
[aadf01e]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);
[21580dd]764 }else{
[aadf01e]765 tcp_initialize_socket_data(socket_data);
[21580dd]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
[aadf01e]770 socket_data->next_incoming = ntohl(header->sequence_number);
771 socket_data->treshold = socket_data->next_incoming + ntohs(header->window);
[21580dd]772
773 socket_data->addrlen = addrlen;
[aadf01e]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);
[21580dd]778 }
[aadf01e]779 memcpy(socket_data->addr, src, socket_data->addrlen);
[21580dd]780
[aadf01e]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);
[14f1db0]785 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]786 return ERROR_CODE;
787 }
788
[aadf01e]789// printf("addr %p\n", socket_data->addr, socket_data->addrlen);
[21580dd]790 // create a socket
[ede63e4]791 socket_id = -1;
[aadf01e]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);
[21580dd]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
[aadf01e]804 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]805// printf("list lg\n");
[aadf01e]806 fibril_rwlock_write_lock(&tcp_globals.lock);
[21580dd]807// printf("list locked\n");
808 // find the destination socket
[aadf01e]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);
[21580dd]812 // a shadow may remain until app hangs up
[aadf01e]813 return tcp_release_and_return(packet, EOK/*ENOTSOCK*/);
[21580dd]814 }
[aadf01e]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);
[21580dd]818
819// printf("list ll\n");
[aadf01e]820 fibril_rwlock_write_lock(listening_socket_data->local_lock);
[21580dd]821// printf("list locked\n");
822
[aadf01e]823 socket = socket_cores_find(listening_socket_data->local_sockets, socket_id);
824 if(! socket){
[21580dd]825 // where is the socket?!?
[aadf01e]826 fibril_rwlock_write_unlock(&tcp_globals.lock);
[21580dd]827 return ENOTSOCK;
828 }
[aadf01e]829 socket_data = (tcp_socket_data_ref) socket->specific_data;
830 assert(socket_data);
[21580dd]831
832// uint8_t * data = socket_data->addr;
[aadf01e]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]);
[21580dd]834
[aadf01e]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);
[21580dd]838 //tcp_globals.last_used_port = socket->port;
[aadf01e]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);
[21580dd]844 }
845
846 socket_data->state = TCP_SOCKET_LISTEN;
[aadf01e]847 socket_data->next_incoming = ntohl(header->sequence_number) + 1;
[21580dd]848 // release additional packets
[aadf01e]849 next_packet = pq_detach(packet);
850 if(next_packet){
[14f1db0]851 pq_release_remote(tcp_globals.net_phone, packet_get_id(next_packet));
[21580dd]852 }
853 // trim if longer than the header
[aadf01e]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);
[21580dd]858 }
[aadf01e]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);
[21580dd]862 return ERROR_CODE;
863 }
[aadf01e]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);
[21580dd]868 return EINVAL;
869 }else{
870 socket_data->state = TCP_SOCKET_SYN_RECEIVED;
871// printf("unlock\n");
[aadf01e]872 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]873 // send the packet
[aadf01e]874 tcp_send_packets(socket_data->device_id, packet);
[21580dd]875 return EOK;
876 }
877 }
878 }
[aadf01e]879 return tcp_release_and_return(packet, EINVAL);
[21580dd]880}
881
[aadf01e]882int tcp_process_syn_received(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet){
[21580dd]883 ERROR_DECLARE;
884
[aadf01e]885 socket_core_ref listening_socket;
886 tcp_socket_data_ref listening_socket_data;
[21580dd]887
[aadf01e]888 assert(socket);
889 assert(socket_data);
890 assert(socket->specific_data == socket_data);
891 assert(header);
892 assert(packet);
[21580dd]893
894 printf("syn_rec\n");
[aadf01e]895 if(header->acknowledge){
[21580dd]896 // process acknowledgement
[aadf01e]897 tcp_process_acknowledgement(socket, socket_data, header);
[21580dd]898
[aadf01e]899 socket_data->next_incoming = ntohl(header->sequence_number);// + 1;
[14f1db0]900 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]901 socket_data->state = TCP_SOCKET_ESTABLISHED;
[aadf01e]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);
[21580dd]906
907 // queue the received packet
[aadf01e]908 if(! ERROR_OCCURRED(dyn_fifo_push(&listening_socket->accepted, (-1 * socket->socket_id), listening_socket_data->backlog))){
[21580dd]909 // notify the destination socket
[aadf01e]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);
[21580dd]912 return EOK;
913 }
914 }
915 // send FIN
916 socket_data->state = TCP_SOCKET_FIN_WAIT_1;
917
918 // create the notification packet
[aadf01e]919 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 0, 1));
[21580dd]920
921 // send the packet
[aadf01e]922 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 1));
[21580dd]923
924 // flush packets
[aadf01e]925 packet = tcp_get_packets_to_send(socket, socket_data);
926 fibril_rwlock_write_unlock(socket_data->local_lock);
927 if(packet){
[21580dd]928 // send the packet
[aadf01e]929 tcp_send_packets(socket_data->device_id, packet);
[21580dd]930 }
931 return EOK;
932 }else{
[aadf01e]933 return tcp_release_and_return(packet, EINVAL);
[21580dd]934 }
935 return EINVAL;
936}
937
[aadf01e]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);
[21580dd]953 // if more data acknowledged
[aadf01e]954 if(number != socket_data->expected){
[21580dd]955 old = socket_data->expected;
[aadf01e]956 if(IS_IN_INTERVAL_OVERFLOW(old, socket_data->fin_outgoing, number)){
957 switch(socket_data->state){
[21580dd]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
[aadf01e]964 tcp_prepare_timeout(tcp_release_after_timeout, socket, socket_data, 0, TCP_SOCKET_TIME_WAIT, NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT, true);
[21580dd]965 break;
966 default:
967 break;
968 }
969 }
970 // update the treshold if higher than set
[aadf01e]971 if(number + ntohs(header->window) > socket_data->expected + socket_data->treshold){
972 socket_data->treshold = number + ntohs(header->window) - socket_data->expected;
[21580dd]973 }
974 // set new expected sequence number
975 socket_data->expected = number;
976 socket_data->expected_count = 1;
977 packet = socket_data->outgoing;
[aadf01e]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){
[21580dd]982 socket_data->outgoing = next;
983 }
984 // add to acknowledged or release
[aadf01e]985 if(pq_add(&acknowledged, packet, 0, 0) != EOK){
[14f1db0]986 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]987 }
988 packet = next;
[aadf01e]989 }else if(old < socket_data->expected){
[21580dd]990 break;
991 }
992 }
993 // release acknowledged
[aadf01e]994 if(acknowledged){
[14f1db0]995 pq_release_remote(tcp_globals.net_phone, packet_get_id(acknowledged));
[21580dd]996 }
997 return;
998 // if the same as the previous time
[aadf01e]999 }else if(number == socket_data->expected){
[21580dd]1000 // increase the counter
1001 ++ socket_data->expected_count;
[aadf01e]1002 if(socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT){
[21580dd]1003 socket_data->expected_count = 1;
1004 // TODO retransmit lock
[aadf01e]1005 //tcp_retransmit_packet(socket, socket_data, number);
[21580dd]1006 }
1007 }
1008 }
1009}
1010
[14f1db0]1011int tcp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
[21580dd]1012 ERROR_DECLARE;
1013
[aadf01e]1014 packet_t packet;
[21580dd]1015
[aadf01e]1016 assert(call);
1017 assert(answer);
1018 assert(answer_count);
[21580dd]1019
[aadf01e]1020 *answer_count = 0;
1021 switch(IPC_GET_METHOD(*call)){
[21580dd]1022 case NET_TL_RECEIVED:
[aadf01e]1023 //fibril_rwlock_read_lock(&tcp_globals.lock);
[14f1db0]1024 if(! ERROR_OCCURRED(packet_translate_remote(tcp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
[aadf01e]1025 ERROR_CODE = tcp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_TCP, IPC_GET_ERROR(call));
[21580dd]1026 }
[aadf01e]1027 //fibril_rwlock_read_unlock(&tcp_globals.lock);
[21580dd]1028 return ERROR_CODE;
1029 case IPC_M_CONNECT_TO_ME:
[aadf01e]1030 return tcp_process_client_messages(callid, * call);
[21580dd]1031 }
1032 return ENOTSUP;
1033}
1034
[aadf01e]1035void tcp_refresh_socket_data(tcp_socket_data_ref socket_data){
1036 assert(socket_data);
[21580dd]1037
[aadf01e]1038 bzero(socket_data, sizeof(*socket_data));
[21580dd]1039 socket_data->state = TCP_SOCKET_INITIAL;
[ede63e4]1040 socket_data->device_id = DEVICE_INVALID_ID;
[21580dd]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
[aadf01e]1050void tcp_initialize_socket_data(tcp_socket_data_ref socket_data){
1051 assert(socket_data);
[21580dd]1052
[aadf01e]1053 tcp_refresh_socket_data(socket_data);
1054 fibril_mutex_initialize(&socket_data->operation.mutex);
1055 fibril_condvar_initialize(&socket_data->operation.condvar);
[ede63e4]1056 socket_data->data_fragment_size = MAX_TCP_FRAGMENT_SIZE;
[21580dd]1057}
1058
[aadf01e]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;
[6092b56e]1065 int socket_id;
[aadf01e]1066 size_t addrlen;
[e417b96]1067 size_t size;
[aadf01e]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;
[21580dd]1074
1075 /*
1076 * Accept the connection
1077 * - Answer the first IPC_M_CONNECT_ME_TO call.
1078 */
[2e99277]1079 res = EOK;
1080 answer_count = 0;
[21580dd]1081
[aadf01e]1082 socket_cores_initialize(&local_sockets);
1083 fibril_rwlock_initialize(&lock);
[21580dd]1084
[aadf01e]1085 while(keep_on_going){
[2e99277]1086
1087 // answer the call
[aadf01e]1088 answer_call(callid, res, &answer, answer_count);
[2e99277]1089
[21580dd]1090 // refresh data
[aadf01e]1091 refresh_answer(&answer, &answer_count);
[21580dd]1092
[2e99277]1093 // get the next call
[aadf01e]1094 callid = async_get_call(&call);
[21580dd]1095
[2e99277]1096 // process the call
[aadf01e]1097 switch(IPC_GET_METHOD(call)){
[21580dd]1098 case IPC_M_PHONE_HUNGUP:
1099 keep_on_going = false;
[2e99277]1100 res = EHANGUP;
[21580dd]1101 break;
1102 case NET_SOCKET:
[aadf01e]1103 socket_data = (tcp_socket_data_ref) malloc(sizeof(*socket_data));
1104 if(! socket_data){
[21580dd]1105 res = ENOMEM;
1106 }else{
[aadf01e]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);
[6092b56e]1111 socket_id = SOCKET_GET_SOCKET_ID(call);
1112 res = socket_create(&local_sockets, app_phone, socket_data, &socket_id);
[e417b96]1113 SOCKET_SET_SOCKET_ID(answer, socket_id);
[aadf01e]1114 fibril_rwlock_write_unlock(&lock);
1115 if(res == EOK){
[14f1db0]1116 if (tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, DEVICE_INVALID_ID, &packet_dimension) == EOK){
[e417b96]1117 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, ((packet_dimension->content < socket_data->data_fragment_size) ? packet_dimension->content : socket_data->data_fragment_size));
[ede63e4]1118 }
[e417b96]1119// SOCKET_SET_DATA_FRAGMENT_SIZE(answer, MAX_TCP_FRAGMENT_SIZE);
1120 SOCKET_SET_HEADER_SIZE(answer, TCP_HEADER_SIZE);
[21580dd]1121 answer_count = 3;
1122 }else{
[aadf01e]1123 free(socket_data);
[21580dd]1124 }
1125 }
1126 break;
1127 case NET_SOCKET_BIND:
[aadf01e]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);
[21580dd]1138 socket_data->state = TCP_SOCKET_LISTEN;
1139 }
1140 }
[aadf01e]1141 fibril_rwlock_write_unlock(&lock);
1142 fibril_rwlock_write_unlock(&tcp_globals.lock);
1143 free(addr);
[21580dd]1144 }
1145 break;
1146 case NET_SOCKET_LISTEN:
[aadf01e]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);
[21580dd]1154 break;
1155 case NET_SOCKET_CONNECT:
[aadf01e]1156 res = data_receive((void **) &addr, &addrlen);
1157 if(res == EOK){
[ede63e4]1158 // the global lock may be released in the tcp_connect_message() function
[aadf01e]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);
[21580dd]1166 }
1167 }
1168 break;
1169 case NET_SOCKET_ACCEPT:
[aadf01e]1170 fibril_rwlock_read_lock(&tcp_globals.lock);
1171 fibril_rwlock_write_lock(&lock);
[e417b96]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);
[aadf01e]1174 fibril_rwlock_write_unlock(&lock);
1175 fibril_rwlock_read_unlock(&tcp_globals.lock);
1176 if(res > 0){
[e417b96]1177 SOCKET_SET_SOCKET_ID(answer, res);
1178 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
[ede63e4]1179 answer_count = 3;
[21580dd]1180 }
1181 break;
1182 case NET_SOCKET_SEND:
[aadf01e]1183 fibril_rwlock_read_lock(&tcp_globals.lock);
1184 fibril_rwlock_write_lock(&lock);
[e417b96]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);
[aadf01e]1187 if(res != EOK){
1188 fibril_rwlock_write_unlock(&lock);
1189 fibril_rwlock_read_unlock(&tcp_globals.lock);
[ede63e4]1190 }else{
1191 answer_count = 2;
[21580dd]1192 }
1193 break;
1194 case NET_SOCKET_SENDTO:
[aadf01e]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);
[e417b96]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);
[aadf01e]1201 if(res != EOK){
1202 fibril_rwlock_write_unlock(&lock);
1203 fibril_rwlock_read_unlock(&tcp_globals.lock);
[ede63e4]1204 }else{
1205 answer_count = 2;
[21580dd]1206 }
[aadf01e]1207 free(addr);
[21580dd]1208 }
1209 break;
1210 case NET_SOCKET_RECV:
[aadf01e]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){
[e417b96]1217 SOCKET_SET_READ_DATA_LENGTH(answer, res);
[21580dd]1218 answer_count = 1;
1219 res = EOK;
1220 }
1221 break;
1222 case NET_SOCKET_RECVFROM:
[aadf01e]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){
[e417b96]1229 SOCKET_SET_READ_DATA_LENGTH(answer, res);
1230 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
[ede63e4]1231 answer_count = 3;
[21580dd]1232 res = EOK;
1233 }
1234 break;
1235 case NET_SOCKET_CLOSE:
[aadf01e]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);
[21580dd]1242 }
1243 break;
1244 case NET_SOCKET_GETSOCKOPT:
1245 case NET_SOCKET_SETSOCKOPT:
1246 default:
1247 res = ENOTSUP;
1248 break;
1249 }
1250 }
1251
[a8a13d0]1252 // release the application phone
1253 ipc_hangup(app_phone);
1254
[21580dd]1255 printf("release\n");
1256 // release all local sockets
[aadf01e]1257 socket_cores_release(tcp_globals.net_phone, &local_sockets, &tcp_globals.sockets, tcp_free_socket_data);
[21580dd]1258
1259 return EOK;
1260}
1261
[aadf01e]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;
[21580dd]1267
[aadf01e]1268 assert(timeout);
[21580dd]1269
1270 // sleep the given timeout
[aadf01e]1271 async_usleep(timeout->timeout);
[21580dd]1272 // lock the globals
[aadf01e]1273 if(timeout->globals_read_only){
1274 fibril_rwlock_read_lock(&tcp_globals.lock);
[21580dd]1275 }else{
[aadf01e]1276 fibril_rwlock_write_lock(&tcp_globals.lock);
[21580dd]1277 }
1278 // find the pending operation socket
[aadf01e]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){
[21580dd]1286 // increase the timeout counter;
1287 ++ socket_data->timeout_count;
[aadf01e]1288 if(socket_data->timeout_count == TCP_MAX_TIMEOUTS){
[21580dd]1289 // TODO release as connection lost
[aadf01e]1290 //tcp_refresh_socket_data(socket_data);
[a8a13d0]1291 fibril_rwlock_write_unlock(socket_data->local_lock);
[2e99277]1292 }else{
1293 // retransmit
[a8a13d0]1294// tcp_retransmit_packet(socket, socket_data, timeout->sequence_number);
1295 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]1296 }
1297 }else{
[aadf01e]1298 fibril_mutex_lock(&socket_data->operation.mutex);
[21580dd]1299 // set the timeout operation result if state not changed
[aadf01e]1300 if(socket_data->state == timeout->state){
[21580dd]1301 socket_data->operation.result = ETIMEOUT;
1302 // notify the main fibril
[aadf01e]1303 fibril_condvar_signal(&socket_data->operation.condvar);
[21580dd]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...
[aadf01e]1309 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]1310 }
[aadf01e]1311 fibril_mutex_unlock(&socket_data->operation.mutex);
[21580dd]1312 }
1313 }
1314 }
1315 // unlock only if no socket
[aadf01e]1316 if(timeout->globals_read_only){
1317 fibril_rwlock_read_unlock(&tcp_globals.lock);
1318 }else if(! keep_write_lock){
[21580dd]1319 // release if not desired
[aadf01e]1320 fibril_rwlock_write_unlock(&tcp_globals.lock);
[21580dd]1321 }
1322 // release the timeout structure
[aadf01e]1323 free(timeout);
[21580dd]1324 return EOK;
1325}
1326
[aadf01e]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;
[21580dd]1332
[aadf01e]1333 assert(timeout);
[21580dd]1334
1335 // sleep the given timeout
[aadf01e]1336 async_usleep(timeout->timeout);
[21580dd]1337 // lock the globals
[aadf01e]1338 fibril_rwlock_write_lock(&tcp_globals.lock);
[21580dd]1339 // find the pending operation socket
[aadf01e]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){
[21580dd]1345 local_lock = socket_data->local_lock;
[aadf01e]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);
[21580dd]1349 }
1350 }
1351 // unlock the globals
[aadf01e]1352 fibril_rwlock_write_unlock(&tcp_globals.lock);
[21580dd]1353 // release the timeout structure
[aadf01e]1354 free(timeout);
[21580dd]1355 return EOK;
1356}
1357
[aadf01e]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;
[21580dd]1362
[aadf01e]1363 assert(socket);
1364 assert(socket_data);
1365 assert(socket->specific_data == socket_data);
[21580dd]1366
1367 // sent packet?
[aadf01e]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);
[21580dd]1377 }
1378 }else{
[aadf01e]1379 fibril_rwlock_write_unlock(socket_data->local_lock);
[21580dd]1380 }
1381}
1382
[aadf01e]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;
[21580dd]1386
[aadf01e]1387 assert(local_sockets);
[21580dd]1388
[aadf01e]1389 if(backlog < 0){
1390 return EINVAL;
1391 }
[21580dd]1392 // find the socket
[aadf01e]1393 socket = socket_cores_find(local_sockets, socket_id);
1394 if(! socket){
1395 return ENOTSOCK;
1396 }
[21580dd]1397 // get the socket specific data
[aadf01e]1398 socket_data = (tcp_socket_data_ref) socket->specific_data;
1399 assert(socket_data);
[21580dd]1400 // set the backlog
1401 socket_data->backlog = backlog;
1402 return EOK;
1403}
1404
[aadf01e]1405int tcp_connect_message(socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen){
[21580dd]1406 ERROR_DECLARE;
1407
[aadf01e]1408 socket_core_ref socket;
[21580dd]1409
[aadf01e]1410 assert(local_sockets);
1411 assert(addr);
1412 assert(addrlen > 0);
[21580dd]1413
1414 // find the socket
[aadf01e]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);
[21580dd]1421 // unbind if bound
[aadf01e]1422 if(socket->port > 0){
1423 socket_ports_exclude(&tcp_globals.sockets, socket->port);
[21580dd]1424 socket->port = 0;
1425 }
1426 }
1427 return ERROR_CODE;
1428}
1429
[aadf01e]1430int tcp_connect_core(socket_core_ref socket, socket_cores_ref local_sockets, struct sockaddr * addr, socklen_t addrlen){
[21580dd]1431 ERROR_DECLARE;
1432
[aadf01e]1433 tcp_socket_data_ref socket_data;
1434 packet_t packet;
[21580dd]1435
[aadf01e]1436 assert(socket);
1437 assert(addr);
1438 assert(addrlen > 0);
[21580dd]1439
1440 // get the socket specific data
[aadf01e]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))){
[21580dd]1446 return EINVAL;
1447 }
1448 // get the destination port
[aadf01e]1449 ERROR_PROPAGATE(tl_get_address_port(addr, addrlen, &socket_data->dest_port));
1450 if(socket->port <= 0){
[21580dd]1451 // try to find a free port
[aadf01e]1452 ERROR_PROPAGATE(socket_bind_free_port(&tcp_globals.sockets, socket, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port));
[21580dd]1453 // set the next port as the search starting port number
1454 tcp_globals.last_used_port = socket->port;
1455 }
[aadf01e]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));
[21580dd]1457
1458 // create the notification packet
[aadf01e]1459 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 1, 0));
[21580dd]1460
1461 // unlock the globals and wait for an operation
[aadf01e]1462 fibril_rwlock_write_unlock(&tcp_globals.lock);
[21580dd]1463
1464 socket_data->addr = addr;
1465 socket_data->addrlen = addrlen;
1466 // send the packet
[aadf01e]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))){
[21580dd]1469 socket_data->addr = NULL;
1470 socket_data->addrlen = 0;
[aadf01e]1471 fibril_rwlock_write_lock(&tcp_globals.lock);
[21580dd]1472 }else{
[aadf01e]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);
[21580dd]1477 // send the packet
[aadf01e]1478 printf("connecting %d\n", packet_get_id(packet));
1479 tcp_send_packets(socket_data->device_id, packet);
[21580dd]1480 // wait for a reply
[aadf01e]1481 fibril_condvar_wait(&socket_data->operation.condvar, &socket_data->operation.mutex);
[21580dd]1482 ERROR_CODE = socket_data->operation.result;
[aadf01e]1483 if(ERROR_CODE != EOK){
[21580dd]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
[aadf01e]1494 fibril_mutex_unlock(&socket_data->operation.mutex);
[21580dd]1495
1496 // return the result
1497 return ERROR_CODE;
1498}
1499
[aadf01e]1500int tcp_queue_prepare_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length){
[21580dd]1501 ERROR_DECLARE;
1502
[aadf01e]1503 tcp_header_ref header;
[21580dd]1504
[aadf01e]1505 assert(socket);
1506 assert(socket_data);
1507 assert(socket->specific_data == socket_data);
[21580dd]1508
1509 // get tcp header
[aadf01e]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);
[21580dd]1519 }
1520 // remember the outgoing FIN
[aadf01e]1521 if(header->finalize){
[21580dd]1522 socket_data->fin_outgoing = socket_data->next_outgoing;
1523 }
1524 return EOK;
1525}
1526
[aadf01e]1527int tcp_queue_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length){
[21580dd]1528 ERROR_DECLARE;
1529
[aadf01e]1530 assert(socket);
1531 assert(socket_data);
1532 assert(socket->specific_data == socket_data);
[21580dd]1533
[aadf01e]1534 ERROR_PROPAGATE(tcp_queue_prepare_packet(socket, socket_data, packet, data_length));
[21580dd]1535
[aadf01e]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);
[21580dd]1538 }
1539 socket_data->next_outgoing += data_length;
1540 return EOK;
1541}
1542
[aadf01e]1543packet_t tcp_get_packets_to_send(socket_core_ref socket, tcp_socket_data_ref socket_data){
[21580dd]1544 ERROR_DECLARE;
1545
[aadf01e]1546 packet_t packet;
1547 packet_t copy;
1548 packet_t sending = NULL;
1549 packet_t previous = NULL;
1550 size_t data_length;
[21580dd]1551
[aadf01e]1552 assert(socket);
1553 assert(socket_data);
1554 assert(socket->specific_data == socket_data);
[21580dd]1555
[aadf01e]1556 packet = pq_find(socket_data->outgoing, socket_data->last_outgoing + 1);
1557 while(packet){
1558 pq_get_order(packet, NULL, &data_length);
[21580dd]1559 // send only if fits into the window
1560 // respecting the possible overflow
[aadf01e]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){
[21580dd]1564 return sending;
1565 }
[aadf01e]1566 if(! sending){
[21580dd]1567 sending = copy;
1568 }else{
[aadf01e]1569 if(ERROR_OCCURRED(pq_insert_after(previous, copy))){
[14f1db0]1570 pq_release_remote(tcp_globals.net_phone, packet_get_id(copy));
[21580dd]1571 return sending;
1572 }
1573 }
1574 previous = copy;
[aadf01e]1575 packet = pq_next(packet);
[21580dd]1576 // overflow occurred ?
[aadf01e]1577 if((! packet) && (socket_data->last_outgoing > socket_data->next_outgoing)){
[21580dd]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
[aadf01e]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){
[21580dd]1591 ERROR_DECLARE;
1592
[aadf01e]1593 tcp_header_ref header;
1594 uint32_t checksum;
[21580dd]1595
[aadf01e]1596 assert(socket);
1597 assert(socket_data);
1598 assert(socket->specific_data == socket_data);
[21580dd]1599
1600 // adjust the pseudo header
[aadf01e]1601 if(ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(socket_data->pseudo_header, socket_data->headerlen, packet_get_data_length(packet)))){
[14f1db0]1602 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]1603 return NULL;
1604 }
1605
1606 // get the header
[aadf01e]1607 header = (tcp_header_ref) packet_get_data(packet);
1608 if(! header){
[14f1db0]1609 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]1610 return NULL;
1611 }
[aadf01e]1612 assert(ntohl(header->sequence_number) == sequence_number);
[21580dd]1613
1614 // adjust the header
[aadf01e]1615 if(socket_data->next_incoming){
1616 header->acknowledgement_number = htonl(socket_data->next_incoming);
[21580dd]1617 header->acknowledge = 1;
1618 }
[aadf01e]1619 header->window = htons(socket_data->window);
[21580dd]1620
1621 // checksum
1622 header->checksum = 0;
[aadf01e]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)));
[21580dd]1626 // prepare the packet
[aadf01e]1627 if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0))
[21580dd]1628 // prepare the timeout
[aadf01e]1629 || ERROR_OCCURRED(tcp_prepare_timeout(tcp_timeout, socket, socket_data, sequence_number, socket_data->state, socket_data->timeout, true))){
[14f1db0]1630 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]1631 return NULL;
1632 }
1633 return packet;
1634}
1635
[aadf01e]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;
[21580dd]1638
[aadf01e]1639 assert(socket);
1640 assert(socket_data);
1641 assert(socket->specific_data == socket_data);
[21580dd]1642
1643 // make a copy of the packet
[aadf01e]1644 copy = packet_get_copy(tcp_globals.net_phone, packet);
1645 if(! copy){
1646 return NULL;
1647 }
[21580dd]1648
[aadf01e]1649 return tcp_send_prepare_packet(socket, socket_data, copy, data_length, sequence_number);
[21580dd]1650}
1651
[aadf01e]1652void tcp_send_packets(device_id_t device_id, packet_t packet){
1653 packet_t next;
[21580dd]1654
[aadf01e]1655 while(packet){
1656 next = pq_detach(packet);
1657 ip_send_msg(tcp_globals.ip_phone, device_id, packet, SERVICE_TCP, 0);
[21580dd]1658 packet = next;
1659 }
1660}
1661
[aadf01e]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);
[21580dd]1667
[aadf01e]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));
[21580dd]1672 header->synchronize = synchronize;
1673 header->finalize = finalize;
1674}
1675
[aadf01e]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;
[21580dd]1679
[aadf01e]1680 assert(socket);
1681 assert(socket_data);
1682 assert(socket->specific_data == socket_data);
[21580dd]1683
1684 // prepare the timeout with key bundle structure
[aadf01e]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));
[21580dd]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
[aadf01e]1699 operation_timeout->key = ((char *) operation_timeout) + sizeof(*operation_timeout);
[21580dd]1700 operation_timeout->key_length = socket->key_length;
[aadf01e]1701 memcpy(operation_timeout->key, socket->key, socket->key_length);
1702 operation_timeout->key[operation_timeout->key_length] = '\0';
[21580dd]1703
1704 // prepare the timeouting thread
[aadf01e]1705 fibril = fibril_create(timeout_function, operation_timeout);
1706 if(! fibril){
1707 free(operation_timeout);
[21580dd]1708 return EPARTY;
1709 }
[aadf01e]1710// fibril_mutex_lock(&socket_data->operation.mutex);
[21580dd]1711 // start the timeouting fibril
[aadf01e]1712 fibril_add_ready(fibril);
[21580dd]1713 //socket_data->state = state;
1714 return EOK;
1715}
1716
[aadf01e]1717int tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){
[21580dd]1718 ERROR_DECLARE;
1719
[aadf01e]1720 socket_core_ref socket;
1721 tcp_socket_data_ref socket_data;
1722 int packet_id;
1723 packet_t packet;
1724 size_t length;
[21580dd]1725
[aadf01e]1726 assert(local_sockets);
[21580dd]1727
1728 // find the socket
[aadf01e]1729 socket = socket_cores_find(local_sockets, socket_id);
1730 if(! socket){
1731 return ENOTSOCK;
1732 }
[21580dd]1733 // get the socket specific data
[aadf01e]1734 if(! socket->specific_data){
1735 return NO_DATA;
1736 }
1737 socket_data = (tcp_socket_data_ref) socket->specific_data;
[21580dd]1738
1739 // check state
[aadf01e]1740 if((socket_data->state != TCP_SOCKET_ESTABLISHED) && (socket_data->state != TCP_SOCKET_CLOSE_WAIT)){
[21580dd]1741 return ENOTCONN;
1742 }
1743
1744 // send the source address if desired
[aadf01e]1745 if(addrlen){
1746 ERROR_PROPAGATE(data_reply(socket_data->addr, socket_data->addrlen));
1747 *addrlen = socket_data->addrlen;
[21580dd]1748 }
1749
1750 // get the next received packet
[aadf01e]1751 packet_id = dyn_fifo_value(&socket->received);
1752 if(packet_id < 0){
1753 return NO_DATA;
1754 }
[14f1db0]1755 ERROR_PROPAGATE(packet_translate_remote(tcp_globals.net_phone, &packet, packet_id));
[21580dd]1756
1757 // reply the packets
[aadf01e]1758 ERROR_PROPAGATE(socket_reply_packets(packet, &length));
[21580dd]1759
1760 // release the packet
[aadf01e]1761 dyn_fifo_pop(&socket->received);
[14f1db0]1762 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]1763 // return the total length
[aadf01e]1764 return (int) length;
[21580dd]1765}
1766
[aadf01e]1767int tcp_send_message(socket_cores_ref local_sockets, int socket_id, int fragments, size_t * data_fragment_size, int flags){
[21580dd]1768 ERROR_DECLARE;
1769
[aadf01e]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;
[21580dd]1778
[aadf01e]1779 assert(local_sockets);
1780 assert(data_fragment_size);
[21580dd]1781
1782 // find the socket
[aadf01e]1783 socket = socket_cores_find(local_sockets, socket_id);
1784 if(! socket){
1785 return ENOTSOCK;
1786 }
[21580dd]1787 // get the socket specific data
[aadf01e]1788 if(! socket->specific_data){
1789 return NO_DATA;
1790 }
1791 socket_data = (tcp_socket_data_ref) socket->specific_data;
[21580dd]1792
1793 // check state
[aadf01e]1794 if((socket_data->state != TCP_SOCKET_ESTABLISHED) && (socket_data->state != TCP_SOCKET_CLOSE_WAIT)){
[21580dd]1795 return ENOTCONN;
1796 }
1797
[aadf01e]1798 ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
[21580dd]1799
[aadf01e]1800 *data_fragment_size = ((packet_dimension->content < socket_data->data_fragment_size) ? packet_dimension->content : socket_data->data_fragment_size);
[21580dd]1801
[aadf01e]1802 for(index = 0; index < fragments; ++ index){
[21580dd]1803 // read the data fragment
[aadf01e]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;
[21580dd]1809 // prefix the tcp header
[aadf01e]1810 header = PACKET_PREFIX(packet, tcp_header_t);
1811 if(! header){
1812 return tcp_release_and_return(packet, ENOMEM);
[21580dd]1813 }
[aadf01e]1814 tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
1815 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 0));
[21580dd]1816 }
1817
1818 // flush packets
[aadf01e]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){
[21580dd]1823 // send the packet
[aadf01e]1824 tcp_send_packets(socket_data->device_id, packet);
[21580dd]1825 }
1826
1827 return EOK;
1828}
1829
[aadf01e]1830int tcp_close_message(socket_cores_ref local_sockets, int socket_id){
[21580dd]1831 ERROR_DECLARE;
1832
[aadf01e]1833 socket_core_ref socket;
1834 tcp_socket_data_ref socket_data;
1835 packet_t packet;
[21580dd]1836
1837 // find the socket
[aadf01e]1838 socket = socket_cores_find(local_sockets, socket_id);
1839 if(! socket){
1840 return ENOTSOCK;
1841 }
[21580dd]1842 // get the socket specific data
[aadf01e]1843 socket_data = (tcp_socket_data_ref) socket->specific_data;
1844 assert(socket_data);
[21580dd]1845
1846 // check state
[aadf01e]1847 switch(socket_data->state){
[21580dd]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
[aadf01e]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);
[21580dd]1860 }
1861 return ERROR_CODE;
1862 }
1863 // send FIN
1864 // TODO should I wait to complete?
1865
1866 // create the notification packet
[aadf01e]1867 ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 0, 1));
[21580dd]1868
1869 // send the packet
[aadf01e]1870 ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 1));
[21580dd]1871
1872 // flush packets
[aadf01e]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){
[21580dd]1877 // send the packet
[aadf01e]1878 tcp_send_packets(socket_data->device_id, packet);
[21580dd]1879 }
1880 return EOK;
1881}
1882
[aadf01e]1883int tcp_create_notification_packet(packet_t * packet, socket_core_ref socket, tcp_socket_data_ref socket_data, int synchronize, int finalize){
[21580dd]1884 ERROR_DECLARE;
1885
[aadf01e]1886 packet_dimension_ref packet_dimension;
1887 tcp_header_ref header;
[21580dd]1888
[aadf01e]1889 assert(packet);
[21580dd]1890
1891 // get the device packet dimension
[aadf01e]1892 ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
[21580dd]1893 // get a new packet
[14f1db0]1894 *packet = packet_get_4_remote(tcp_globals.net_phone, TCP_HEADER_SIZE, packet_dimension->addr_len, packet_dimension->prefix, packet_dimension->suffix);
[aadf01e]1895 if(! * packet){
1896 return ENOMEM;
1897 }
[21580dd]1898 // allocate space in the packet
[aadf01e]1899 header = PACKET_SUFFIX(*packet, tcp_header_t);
1900 if(! header){
1901 tcp_release_and_return(*packet, ENOMEM);
[21580dd]1902 }
1903
[aadf01e]1904 tcp_prepare_operation_header(socket, socket_data, header, synchronize, finalize);
[21580dd]1905 return EOK;
1906}
1907
[aadf01e]1908int tcp_accept_message(socket_cores_ref local_sockets, int socket_id, int new_socket_id, size_t * data_fragment_size, size_t * addrlen){
[21580dd]1909 ERROR_DECLARE;
1910
[aadf01e]1911 socket_core_ref accepted;
1912 socket_core_ref socket;
1913 tcp_socket_data_ref socket_data;
1914 packet_dimension_ref packet_dimension;
[21580dd]1915
[aadf01e]1916 assert(local_sockets);
1917 assert(data_fragment_size);
1918 assert(addrlen);
[21580dd]1919
1920 // find the socket
[aadf01e]1921 socket = socket_cores_find(local_sockets, socket_id);
1922 if(! socket){
1923 return ENOTSOCK;
1924 }
[21580dd]1925 // get the socket specific data
[aadf01e]1926 socket_data = (tcp_socket_data_ref) socket->specific_data;
1927 assert(socket_data);
[21580dd]1928
1929 // check state
[aadf01e]1930 if(socket_data->state != TCP_SOCKET_LISTEN){
[21580dd]1931 return EINVAL;
1932 }
1933
1934 do{
[aadf01e]1935 socket_id = dyn_fifo_value(&socket->accepted);
1936 if(socket_id < 0){
1937 return ENOTSOCK;
1938 }
[d510c0fe]1939 socket_id *= -1;
[21580dd]1940
[aadf01e]1941 accepted = socket_cores_find(local_sockets, socket_id);
1942 if(! accepted){
1943 return ENOTSOCK;
1944 }
[21580dd]1945 // get the socket specific data
[aadf01e]1946 socket_data = (tcp_socket_data_ref) accepted->specific_data;
1947 assert(socket_data);
[ede63e4]1948 // TODO can it be in another state?
[aadf01e]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));
[ede63e4]1956 accepted->socket_id = new_socket_id;
1957 }
[21580dd]1958 }
[aadf01e]1959 dyn_fifo_pop(&socket->accepted);
1960 }while(socket_data->state != TCP_SOCKET_ESTABLISHED);
1961 printf("ret accept %d\n", accepted->socket_id);
[21580dd]1962 return accepted->socket_id;
1963}
1964
[aadf01e]1965void tcp_free_socket_data(socket_core_ref socket){
1966 tcp_socket_data_ref socket_data;
[21580dd]1967
[aadf01e]1968 assert(socket);
[21580dd]1969
[aadf01e]1970 printf("destroy_socket %d\n", socket->socket_id);
[21580dd]1971
1972 // get the socket specific data
[aadf01e]1973 socket_data = (tcp_socket_data_ref) socket->specific_data;
1974 assert(socket_data);
[21580dd]1975 //free the pseudo header
[aadf01e]1976 if(socket_data->pseudo_header){
1977 if(socket_data->headerlen){
[21580dd]1978 printf("d pseudo\n");
[aadf01e]1979 free(socket_data->pseudo_header);
[21580dd]1980 socket_data->headerlen = 0;
1981 }
1982 socket_data->pseudo_header = NULL;
1983 }
1984 socket_data->headerlen = 0;
1985 // free the address
[aadf01e]1986 if(socket_data->addr){
1987 if(socket_data->addrlen){
[21580dd]1988 printf("d addr\n");
[aadf01e]1989 free(socket_data->addr);
[21580dd]1990 socket_data->addrlen = 0;
1991 }
1992 socket_data->addr = NULL;
1993 }
1994 socket_data->addrlen = 0;
1995}
1996
[aadf01e]1997int tcp_release_and_return(packet_t packet, int result){
[14f1db0]1998 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
[21580dd]1999 return result;
2000}
2001
[849ed54]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 */
[14f1db0]2028 int res = tl_module_message_standalone(callid, &call, &answer,
2029 &answer_count);
[849ed54]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 */
[14f1db0]2054 if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection)))
[849ed54]2055 return ERROR_CODE;
2056
2057 return EOK;
2058}
2059
[21580dd]2060/** @}
2061 */
Note: See TracBrowser for help on using the repository browser.