Changeset 899f1a9 in mainline
- Timestamp:
- 2011-12-11T20:27:56Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- c24c157d
- Parents:
- 4c67e52 (diff), 9c3bba0 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 29 added
- 1 deleted
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
boot/Makefile.common
r4c67e52 r899f1a9 174 174 $(USPACE_PATH)/app/nettest1/nettest1 \ 175 175 $(USPACE_PATH)/app/nettest2/nettest2 \ 176 $(USPACE_PATH)/app/nettest3/nettest3 \ 176 177 $(USPACE_PATH)/app/netecho/netecho \ 177 178 $(USPACE_PATH)/app/ping/ping \ -
uspace/Makefile
r4c67e52 r899f1a9 64 64 app/nettest1 \ 65 65 app/nettest2 \ 66 app/nettest3 \ 66 67 app/ping \ 67 68 app/websrv \ -
uspace/app/netecho/netecho.c
r4c67e52 r899f1a9 241 241 /* Accept a socket if a stream socket is used */ 242 242 addrlen = sizeof(address_buf); 243 if (verbose) 244 printf("accept()\n"); 243 245 socket_id = accept(listening_id, (void *) address_buf, &addrlen); 244 246 if (socket_id <= 0) { … … 258 260 259 261 /* Receive a message to echo */ 262 if (verbose) 263 printf("recvfrom()\n"); 260 264 rcv_size = recvfrom(socket_id, data, size, 0, address, 261 265 &addrlen); … … 297 301 298 302 /* Answer the request either with the static reply or the original data */ 299 rc = sendto(socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen); 300 if (rc != EOK) 301 socket_print_error(stderr, rc, "Socket send: ", "\n"); 303 if (type == SOCK_STREAM) { 304 if (verbose) 305 printf("send()\n"); 306 rc = send(socket_id, reply ? reply : data, reply ? reply_length : length, 0); 307 if (rc != EOK) 308 socket_print_error(stderr, rc, "Socket send: ", "\n"); 309 } else { 310 if (verbose) 311 printf("sendto()\n"); 312 rc = sendto(socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen); 313 if (rc != EOK) 314 socket_print_error(stderr, rc, "Socket send: ", "\n"); 315 } 302 316 } 303 317 -
uspace/app/websrv/websrv.c
r4c67e52 r899f1a9 1 1 /* 2 * Copyright (c) 201 0Jiri Svoboda2 * Copyright (c) 2011 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** 33 * @file (Less-than-skeleton)web server.33 * @file Skeletal web server. 34 34 */ 35 35 36 #include <bool.h> 37 #include <errno.h> 36 38 #include <stdio.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include <stdlib.h> 42 #include <fcntl.h> 37 43 38 44 #include <net/in.h> … … 44 50 #define PORT_NUMBER 8080 45 51 52 #define WEB_ROOT "/data/web" 53 46 54 /** Buffer for receiving the request. */ 47 55 #define BUFFER_SIZE 1024 48 static char buf[BUFFER_SIZE]; 56 static char rbuf[BUFFER_SIZE]; 57 static size_t rbuf_out, rbuf_in; 58 59 static char lbuf[BUFFER_SIZE + 1]; 60 static size_t lbuf_used; 61 62 static char fbuf[BUFFER_SIZE]; 49 63 50 64 /** Response to send to client. */ 51 static const char * response_msg =65 static const char *ok_msg = 52 66 "HTTP/1.0 200 OK\r\n" 53 "\r\n" 54 "<h1>Hello from HelenOS!</h1>\r\n"; 67 "\r\n"; 68 69 /** Receive one character (with buffering) */ 70 static int recv_char(int fd, char *c) 71 { 72 ssize_t rc; 73 74 if (rbuf_out == rbuf_in) { 75 rbuf_out = 0; 76 rbuf_in = 0; 77 78 rc = recv(fd, rbuf, BUFFER_SIZE, 0); 79 if (rc <= 0) { 80 printf("recv() failed (%zd)\n", rc); 81 return rc; 82 } 83 84 rbuf_in = rc; 85 } 86 87 *c = rbuf[rbuf_out++]; 88 return EOK; 89 } 90 91 /** Receive one line with length limit. */ 92 static int recv_line(int fd) 93 { 94 char c, prev; 95 int rc; 96 char *bp; 97 98 bp = lbuf; c = '\0'; 99 while (bp < lbuf + BUFFER_SIZE) { 100 prev = c; 101 rc = recv_char(fd, &c); 102 if (rc != EOK) 103 return rc; 104 105 *bp++ = c; 106 if (prev == '\r' && c == '\n') 107 break; 108 } 109 110 lbuf_used = bp - lbuf; 111 *bp = '\0'; 112 113 if (bp == lbuf + BUFFER_SIZE) 114 return ELIMIT; 115 116 return EOK; 117 } 118 119 static bool uri_is_valid(char *uri) 120 { 121 char *cp; 122 char c; 123 124 if (uri[0] != '/') 125 return false; 126 if (uri[1] == '.') 127 return false; 128 129 cp = uri + 1; 130 while (*cp != '\0') { 131 c = *cp++; 132 if (c == '/') 133 return false; 134 } 135 136 return true; 137 } 138 139 static int send_response(int conn_sd, const char *msg) 140 { 141 size_t response_size; 142 ssize_t rc; 143 144 response_size = str_size(msg); 145 146 /* Send a canned response. */ 147 printf("Send response...\n"); 148 rc = send(conn_sd, (void *) msg, response_size, 0); 149 if (rc < 0) { 150 printf("send() failed.\n"); 151 return rc; 152 } 153 154 return EOK; 155 } 156 157 static int uri_get(const char *uri, int conn_sd) 158 { 159 int rc; 160 char *fname; 161 int fd; 162 ssize_t nr; 163 164 if (str_cmp(uri, "/") == 0) 165 uri = "/index.htm"; 166 167 rc = asprintf(&fname, "%s%s", WEB_ROOT, uri); 168 if (rc < 0) 169 return ENOMEM; 170 171 fd = open(fname, O_RDONLY); 172 if (fd < 0) { 173 printf("File '%s' not found.\n", fname); 174 free(fname); 175 return ENOENT; 176 } 177 178 free(fname); 179 180 rc = send_response(conn_sd, ok_msg); 181 if (rc != EOK) 182 return rc; 183 184 while (true) { 185 nr = read(fd, fbuf, BUFFER_SIZE); 186 if (nr == 0) 187 break; 188 189 if (nr < 0) { 190 close(fd); 191 return EIO; 192 } 193 194 rc = send(conn_sd, fbuf, nr, 0); 195 if (rc < 0) { 196 printf("send() failed\n"); 197 close(fd); 198 return rc; 199 } 200 } 201 202 close(fd); 203 204 return EOK; 205 } 206 207 static int req_process(int conn_sd) 208 { 209 int rc; 210 char *uri, *end_uri; 211 212 rc = recv_line(conn_sd); 213 if (rc != EOK) { 214 printf("recv_line() failed\n"); 215 return rc; 216 } 217 218 printf("%s", lbuf); 219 220 if (str_lcmp(lbuf, "GET ", 4) != 0) { 221 printf("Invalid HTTP method.\n"); 222 return EINVAL; 223 } 224 225 uri = lbuf + 4; 226 end_uri = str_chr(uri, ' '); 227 if (end_uri == NULL) { 228 end_uri = lbuf + lbuf_used - 2; 229 assert(*end_uri == '\r'); 230 } 231 232 *end_uri = '\0'; 233 printf("Requested URI '%s'.\n", uri); 234 235 if (!uri_is_valid(uri)) { 236 printf("Invalid request URI.\n"); 237 return EINVAL; 238 } 239 240 return uri_get(uri, conn_sd); 241 } 55 242 56 243 int main(int argc, char *argv[]) … … 64 251 int rc; 65 252 66 size_t response_size;67 253 68 254 addr.sin_family = AF_INET; … … 94 280 return 1; 95 281 } 96 97 response_size = str_size(response_msg);98 282 99 283 printf("Listening for connections at port number %u.\n", PORT_NUMBER); … … 105 289 if (conn_sd < 0) { 106 290 printf("accept() failed.\n"); 107 return 1;291 continue; 108 292 } 109 293 … … 111 295 112 296 printf("Wait for client request\n"); 113 114 /* Really we should wait for a blank line. */ 115 rc = recv(conn_sd, buf, BUFFER_SIZE, 0); 116 if (rc < 0) { 117 printf("recv() failed\n"); 118 return 1; 119 } 120 121 /* Send a canned response. */ 122 printf("Send response...\n"); 123 rc = send(conn_sd, (void *) response_msg, response_size, 0); 124 if (rc < 0) { 125 printf("send() failed.\n"); 126 return 1; 127 } 297 rbuf_out = rbuf_in = 0; 298 299 rc = req_process(conn_sd); 300 if (rc != EOK) 301 printf("Error processing request.\n"); 128 302 129 303 rc = closesocket(conn_sd); -
uspace/drv/bus/isa/isa.dev
r4c67e52 r899f1a9 13 13 irq 1 14 14 io_range 060 10 15 15 16 ne2k: 17 match 100 isa/ne2k 18 irq 5 19 io_range 300 20 -
uspace/drv/nic/ne2k/dp8390.c
r4c67e52 r899f1a9 142 142 static void ne2k_upload(ne2k_t *ne2k, void *buf, size_t addr, size_t size) 143 143 { 144 size_t esize_ru = (size + 1) & ~1; 144 145 size_t esize = size & ~1; 145 146 146 pio_write_8(ne2k->port + DP_RBCR0, esize & 0xff);147 pio_write_8(ne2k->port + DP_RBCR1, (esize >> 8) & 0xff);147 pio_write_8(ne2k->port + DP_RBCR0, esize_ru & 0xff); 148 pio_write_8(ne2k->port + DP_RBCR1, (esize_ru >> 8) & 0xff); 148 149 pio_write_8(ne2k->port + DP_RSAR0, addr & 0xff); 149 150 pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff); -
uspace/lib/c/generic/fibril_synch.c
r4c67e52 r899f1a9 447 447 } 448 448 449 /** Timer fibril. 450 * 451 * @param arg Timer 452 */ 453 static int fibril_timer_func(void *arg) 454 { 455 fibril_timer_t *timer = (fibril_timer_t *) arg; 456 int rc; 457 458 fibril_mutex_lock(&timer->lock); 459 460 while (true) { 461 while (timer->state != fts_active && 462 timer->state != fts_cleanup) { 463 464 if (timer->state == fts_cleanup) 465 break; 466 467 fibril_condvar_wait(&timer->cv, &timer->lock); 468 } 469 470 if (timer->state == fts_cleanup) 471 break; 472 473 rc = fibril_condvar_wait_timeout(&timer->cv, &timer->lock, 474 timer->delay); 475 if (rc == ETIMEOUT) { 476 timer->state = fts_fired; 477 fibril_mutex_unlock(&timer->lock); 478 timer->fun(timer->arg); 479 fibril_mutex_lock(&timer->lock); 480 } 481 } 482 483 fibril_mutex_unlock(&timer->lock); 484 return 0; 485 } 486 487 /** Create new timer. 488 * 489 * @return New timer on success, @c NULL if out of memory. 490 */ 491 fibril_timer_t *fibril_timer_create(void) 492 { 493 fid_t fid; 494 fibril_timer_t *timer; 495 496 timer = calloc(1, sizeof(fibril_timer_t)); 497 if (timer == NULL) 498 return NULL; 499 500 fid = fibril_create(fibril_timer_func, (void *) timer); 501 if (fid == 0) { 502 free(timer); 503 return NULL; 504 } 505 506 fibril_mutex_initialize(&timer->lock); 507 fibril_condvar_initialize(&timer->cv); 508 509 timer->fibril = fid; 510 timer->state = fts_not_set; 511 512 fibril_add_ready(fid); 513 514 return timer; 515 } 516 517 /** Destroy timer. 518 * 519 * @param timer Timer, must not be active or accessed by other threads. 520 */ 521 void fibril_timer_destroy(fibril_timer_t *timer) 522 { 523 fibril_mutex_lock(&timer->lock); 524 assert(timer->state != fts_active); 525 timer->state = fts_cleanup; 526 fibril_condvar_broadcast(&timer->cv); 527 fibril_mutex_unlock(&timer->lock); 528 } 529 530 /** Set timer. 531 * 532 * Set timer to execute a callback function after the specified 533 * interval. 534 * 535 * @param timer Timer 536 * @param delay Delay in microseconds 537 * @param fun Callback function 538 * @param arg Argument for @a fun 539 */ 540 void fibril_timer_set(fibril_timer_t *timer, suseconds_t delay, 541 fibril_timer_fun_t fun, void *arg) 542 { 543 fibril_mutex_lock(&timer->lock); 544 timer->state = fts_active; 545 timer->delay = delay; 546 timer->fun = fun; 547 timer->arg = arg; 548 fibril_condvar_broadcast(&timer->cv); 549 fibril_mutex_unlock(&timer->lock); 550 } 551 552 /** Clear timer. 553 * 554 * Clears (cancels) timer and returns last state of the timer. 555 * This can be one of: 556 * - fts_not_set If the timer has not been set or has been cleared 557 * - fts_active Timer was set but did not fire 558 * - fts_fired Timer fired 559 * 560 * @param timer Timer 561 * @return Last timer state 562 */ 563 fibril_timer_state_t fibril_timer_clear(fibril_timer_t *timer) 564 { 565 fibril_timer_state_t old_state; 566 567 fibril_mutex_lock(&timer->lock); 568 old_state = timer->state; 569 timer->state = fts_not_set; 570 571 timer->delay = 0; 572 timer->fun = NULL; 573 timer->arg = NULL; 574 fibril_condvar_broadcast(&timer->cv); 575 fibril_mutex_unlock(&timer->lock); 576 577 return old_state; 578 } 579 449 580 /** @} 450 581 */ -
uspace/lib/c/include/bitops.h
r4c67e52 r899f1a9 40 40 /** Mask with bit @a n set. */ 41 41 #define BIT_V(type, n) \ 42 ((type)1 << ( (n) - 1))42 ((type)1 << (n)) 43 43 44 44 /** Mask with rightmost @a n bits set. */ 45 45 #define BIT_RRANGE(type, n) \ 46 (BIT_V(type, (n) + 1) - 1)46 (BIT_V(type, (n)) - 1) 47 47 48 48 /** Mask with bits @a hi .. @a lo set. @a hi >= @a lo. */ -
uspace/lib/c/include/errno.h
r4c67e52 r899f1a9 96 96 #define ENOTCONN (-10057) 97 97 98 #define ECONNREFUSED (-10058) 99 100 #define ECONNABORTED (-10059) 101 98 102 /** The requested operation was not performed. Try again later. */ 99 103 #define EAGAIN (-11002) -
uspace/lib/c/include/fibril_synch.h
r4c67e52 r899f1a9 107 107 fibril_condvar_t name = FIBRIL_CONDVAR_INITIALIZER(name) 108 108 109 typedef void (*fibril_timer_fun_t)(void *); 110 111 typedef enum { 112 /** Timer has not been set or has been cleared */ 113 fts_not_set, 114 /** Timer was set but did not fire yet */ 115 fts_active, 116 /** Timer has fired and has not been cleared since */ 117 fts_fired, 118 /** Timer is being destroyed */ 119 fts_cleanup 120 } fibril_timer_state_t; 121 122 /** Fibril timer. 123 * 124 * When a timer is set it executes a callback function (in a separate 125 * fibril) after a specified time interval. The timer can be cleared 126 * (canceled) before that. From the return value of fibril_timer_clear() 127 * one can tell whether the timer fired or not. 128 */ 129 typedef struct { 130 fibril_mutex_t lock; 131 fibril_condvar_t cv; 132 fid_t fibril; 133 fibril_timer_state_t state; 134 135 suseconds_t delay; 136 fibril_timer_fun_t fun; 137 void *arg; 138 } fibril_timer_t; 139 109 140 extern void fibril_mutex_initialize(fibril_mutex_t *); 110 141 extern void fibril_mutex_lock(fibril_mutex_t *); … … 129 160 extern void fibril_condvar_broadcast(fibril_condvar_t *); 130 161 162 extern fibril_timer_t *fibril_timer_create(void); 163 extern void fibril_timer_destroy(fibril_timer_t *); 164 extern void fibril_timer_set(fibril_timer_t *, suseconds_t, fibril_timer_fun_t, 165 void *); 166 extern fibril_timer_state_t fibril_timer_clear(fibril_timer_t *); 167 131 168 #endif 132 169 -
uspace/srv/fs/exfat/exfat_directory.c
r4c67e52 r899f1a9 92 92 int rc = EOK; 93 93 94 if (di->b) 94 if (di->b) { 95 95 rc = block_put(di->b); 96 di->b = NULL; 97 } 96 98 97 99 return rc; … … 285 287 for (i = 0; i < count; i++) { 286 288 rc = exfat_directory_get(di, &de); 287 if (rc != EOK) 288 return rc; 289 if (rc != EOK) { 290 free(array); 291 return rc; 292 } 289 293 array[i] = *de; 290 294 rc = exfat_directory_next(di); … … 312 316 for (i = 0; i < count; i++) { 313 317 rc = exfat_directory_get(di, &de); 314 if (rc != EOK) 315 return rc; 318 if (rc != EOK) { 319 free(array); 320 return rc; 321 } 316 322 *de = array[i]; 317 323 di->b->dirty = true; … … 424 430 425 431 di->b->dirty = true; 426 sname += chars;427 432 } 428 433 -
uspace/srv/net/tl/tcp/Makefile
r4c67e52 r899f1a9 1 1 # 2 # Copyright (c) 2005 Martin Decky 3 # Copyright (c) 2007 Jakub Jermar 2 # Copyright (c) 2011 Jiri Svoboda 4 3 # All rights reserved. 5 4 # … … 34 33 35 34 SOURCES = \ 36 tcp.c 35 conn.c \ 36 iqueue.c \ 37 ncsim.c \ 38 pdu.c \ 39 rqueue.c \ 40 segment.c \ 41 seq_no.c \ 42 sock.c \ 43 tcp.c \ 44 test.c \ 45 tqueue.c \ 46 ucall.c 37 47 38 48 include $(USPACE_PREFIX)/Makefile.common -
uspace/srv/net/tl/tcp/tcp.c
r4c67e52 r899f1a9 1 1 /* 2 * Copyright (c) 20 08 Lukas Mejdrech2 * Copyright (c) 2011 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 33 /** @file 34 * TCP module implementation. 35 * @see tcp.h 33 /** 34 * @file TCP (Transmission Control Protocol) network module 36 35 */ 37 36 38 #include <assert.h>39 37 #include <async.h> 40 #include < fibril_synch.h>41 #include < malloc.h>42 /* TODO remove stdio */ 38 #include <byteorder.h> 39 #include <errno.h> 40 #include <io/log.h> 43 41 #include <stdio.h> 44 #include <errno.h> 45 42 #include <task.h> 43 44 #include <icmp_remote.h> 45 #include <ip_client.h> 46 #include <ip_interface.h> 46 47 #include <ipc/services.h> 47 #include <ipc/net.h>48 48 #include <ipc/tl.h> 49 #include <ipc/socket.h> 50 51 #include <net/socket_codes.h> 52 #include <net/ip_protocols.h> 53 #include <net/in.h> 54 #include <net/in6.h> 55 #include <net/inet.h> 56 #include <net/modules.h> 57 58 #include <adt/dynamic_fifo.h> 49 #include <tl_common.h> 50 #include <tl_skel.h> 59 51 #include <packet_client.h> 60 52 #include <packet_remote.h> 61 #include <net_checksum.h> 62 #include <ip_client.h> 63 #include <ip_interface.h> 64 #include <icmp_client.h> 65 #include <icmp_remote.h> 66 #include <net_interface.h> 67 #include <socket_core.h> 68 #include <tl_common.h> 69 #include <tl_remote.h> 70 #include <tl_skel.h> 71 53 54 #include "ncsim.h" 55 #include "pdu.h" 56 #include "rqueue.h" 57 #include "sock.h" 58 #include "std.h" 72 59 #include "tcp.h" 73 #include "tcp_header.h" 74 75 /** TCP module name. */ 76 #define NAME "tcp" 77 78 /** The TCP window default value. */ 79 #define NET_DEFAULT_TCP_WINDOW 10240 80 81 /** Initial timeout for new connections. */ 82 #define NET_DEFAULT_TCP_INITIAL_TIMEOUT 3000000L 83 84 /** Default timeout for closing. */ 85 #define NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT 2000L 86 87 /** The initial outgoing sequence number. */ 88 #define TCP_INITIAL_SEQUENCE_NUMBER 2999 89 90 /** Maximum TCP fragment size. */ 91 #define MAX_TCP_FRAGMENT_SIZE 65535 92 93 /** Free ports pool start. */ 94 #define TCP_FREE_PORTS_START 1025 95 96 /** Free ports pool end. */ 97 #define TCP_FREE_PORTS_END 65535 98 99 /** Timeout for connection initialization, SYN sent. */ 100 #define TCP_SYN_SENT_TIMEOUT 1000000L 101 102 /** The maximum number of timeouts in a row before singaling connection lost. */ 103 #define TCP_MAX_TIMEOUTS 8 104 105 /** The number of acknowledgements before retransmit. */ 106 #define TCP_FAST_RETRANSMIT_COUNT 3 107 108 /** Returns a value indicating whether the value is in the interval respecting 109 * the possible overflow. 110 * 111 * The high end and/or the value may overflow, be lower than the low value. 112 * 113 * @param[in] lower The last value before the interval. 114 * @param[in] value The value to be checked. 115 * @param[in] higher_equal The last value in the interval. 116 */ 117 #define IS_IN_INTERVAL_OVERFLOW(lower, value, higher_equal) \ 118 ((((lower) < (value)) && (((value) <= (higher_equal)) || \ 119 ((higher_equal) < (lower)))) || (((value) <= (higher_equal)) && \ 120 ((higher_equal) < (lower)))) 121 122 /** Type definition of the TCP timeout. 123 * @see tcp_timeout 124 */ 125 typedef struct tcp_timeout tcp_timeout_t; 126 127 /** TCP reply timeout data. 128 * Used as a timeouting fibril argument. 129 * @see tcp_timeout() 130 */ 131 struct tcp_timeout { 132 /** TCP global data are going to be read only. */ 133 int globals_read_only; 134 135 /** Socket port. */ 136 int port; 137 138 /** Local sockets. */ 139 socket_cores_t *local_sockets; 140 141 /** Socket identifier. */ 142 int socket_id; 143 144 /** Socket state. */ 145 tcp_socket_state_t state; 146 147 /** Sent packet sequence number. */ 148 int sequence_number; 149 150 /** Timeout in microseconds. */ 151 suseconds_t timeout; 152 153 /** Port map key. */ 154 uint8_t *key; 155 156 /** Port map key length. */ 157 size_t key_length; 158 }; 159 160 static int tcp_release_and_return(packet_t *, int); 161 static void tcp_prepare_operation_header(socket_core_t *, tcp_socket_data_t *, 162 tcp_header_t *, int synchronize, int); 163 static int tcp_prepare_timeout(int (*)(void *), socket_core_t *, 164 tcp_socket_data_t *, size_t, tcp_socket_state_t, suseconds_t, int); 165 static void tcp_free_socket_data(socket_core_t *); 166 167 static int tcp_timeout(void *); 168 169 static int tcp_release_after_timeout(void *); 170 171 static int tcp_process_packet(nic_device_id_t, packet_t *, services_t); 172 static int tcp_connect_core(socket_core_t *, socket_cores_t *, 173 struct sockaddr *, socklen_t); 174 static int tcp_queue_prepare_packet(socket_core_t *, tcp_socket_data_t *, 175 packet_t *, size_t); 176 static int tcp_queue_packet(socket_core_t *, tcp_socket_data_t *, packet_t *, 177 size_t); 178 static packet_t *tcp_get_packets_to_send(socket_core_t *, tcp_socket_data_t *); 179 static void tcp_send_packets(nic_device_id_t, packet_t *); 180 181 static void tcp_process_acknowledgement(socket_core_t *, tcp_socket_data_t *, 182 tcp_header_t *); 183 static packet_t *tcp_send_prepare_packet(socket_core_t *, tcp_socket_data_t *, 184 packet_t *, size_t, size_t); 185 static packet_t *tcp_prepare_copy(socket_core_t *, tcp_socket_data_t *, 186 packet_t *, size_t, size_t); 187 /* static */ void tcp_retransmit_packet(socket_core_t *, tcp_socket_data_t *, 188 size_t); 189 static int tcp_create_notification_packet(packet_t **, socket_core_t *, 190 tcp_socket_data_t *, int, int); 191 static void tcp_refresh_socket_data(tcp_socket_data_t *); 192 193 static void tcp_initialize_socket_data(tcp_socket_data_t *); 194 195 static int tcp_process_listen(socket_core_t *, tcp_socket_data_t *, 196 tcp_header_t *, packet_t *, struct sockaddr *, struct sockaddr *, size_t); 197 static int tcp_process_syn_sent(socket_core_t *, tcp_socket_data_t *, 198 tcp_header_t *, packet_t *); 199 static int tcp_process_syn_received(socket_core_t *, tcp_socket_data_t *, 200 tcp_header_t *, packet_t *); 201 static int tcp_process_established(socket_core_t *, tcp_socket_data_t *, 202 tcp_header_t *, packet_t *, int, size_t); 203 static int tcp_queue_received_packet(socket_core_t *, tcp_socket_data_t *, 204 packet_t *, int, size_t); 205 static void tcp_queue_received_end_of_data(socket_core_t *socket); 206 207 static int tcp_received_msg(nic_device_id_t, packet_t *, services_t, services_t); 208 static int tcp_process_client_messages(async_sess_t *, ipc_callid_t, 209 ipc_call_t); 210 211 static int tcp_listen_message(socket_cores_t *, int, int); 212 static int tcp_connect_message(socket_cores_t *, int, struct sockaddr *, 213 socklen_t); 214 static int tcp_recvfrom_message(socket_cores_t *, int, int, size_t *); 215 static int tcp_send_message(socket_cores_t *, int, int, size_t *, int); 216 static int tcp_accept_message(socket_cores_t *, int, int, size_t *, size_t *); 217 static int tcp_close_message(socket_cores_t *, int); 218 219 /** TCP global data. */ 220 tcp_globals_t tcp_globals; 221 222 int tcp_received_msg(nic_device_id_t device_id, packet_t *packet, 223 services_t receiver, services_t error) 60 #include "test.h" 61 62 #define NAME "tcp" 63 64 async_sess_t *net_sess; 65 static async_sess_t *icmp_sess; 66 async_sess_t *ip_sess; 67 packet_dimensions_t pkt_dims; 68 69 static void tcp_received_pdu(tcp_pdu_t *pdu); 70 71 /* Pull up packets into a single memory block. */ 72 static int pq_pullup(packet_t *packet, void **data, size_t *dsize) 73 { 74 packet_t *npacket; 75 size_t tot_len; 76 int length; 77 78 npacket = packet; 79 tot_len = 0; 80 do { 81 length = packet_get_data_length(packet); 82 if (length <= 0) 83 return EINVAL; 84 85 tot_len += length; 86 } while ((npacket = pq_next(npacket)) != NULL); 87 88 uint8_t *buf; 89 uint8_t *dp; 90 91 buf = calloc(tot_len, 1); 92 if (buf == NULL) { 93 free(buf); 94 return ENOMEM; 95 } 96 97 npacket = packet; 98 dp = buf; 99 do { 100 length = packet_get_data_length(packet); 101 if (length <= 0) { 102 free(buf); 103 return EINVAL; 104 } 105 106 memcpy(dp, packet_get_data(packet), length); 107 dp += length; 108 } while ((npacket = pq_next(npacket)) != NULL); 109 110 *data = buf; 111 *dsize = tot_len; 112 return EOK; 113 } 114 115 /** Process packet received from network layer. */ 116 static int tcp_received_msg(nic_device_id_t device_id, packet_t *packet, 117 services_t error) 224 118 { 225 119 int rc; 226 227 if (receiver != SERVICE_TCP)228 return EREFUSED;229 230 fibril_rwlock_write_lock(&tcp_globals.lock);231 rc = tcp_process_packet(device_id, packet, error);232 if (rc != EOK)233 fibril_rwlock_write_unlock(&tcp_globals.lock);234 235 printf("receive %d \n", rc);236 237 return rc;238 }239 240 int tcp_process_packet(nic_device_id_t device_id, packet_t *packet, services_t error)241 {242 size_t length;243 120 size_t offset; 244 int result; 245 tcp_header_t *header; 246 socket_core_t *socket; 247 tcp_socket_data_t *socket_data; 248 packet_t *next_packet; 249 size_t total_length; 250 uint32_t checksum; 251 int fragments; 252 icmp_type_t type; 253 icmp_code_t code; 254 struct sockaddr *src; 255 struct sockaddr *dest; 256 size_t addrlen; 257 int rc; 121 int length; 122 struct sockaddr_in *src_addr; 123 struct sockaddr_in *dest_addr; 124 size_t addr_len; 125 126 log_msg(LVL_DEBUG, "tcp_received_msg()"); 258 127 259 128 switch (error) { … … 261 130 break; 262 131 case SERVICE_ICMP: 263 /* Process error */264 result = icmp_client_process_packet(packet, &type, &code, NULL,265 NULL);266 if (result < 0)267 return tcp_release_and_return(packet, result);268 269 length = (size_t) result;270 rc = packet_trim(packet, length, 0);271 if (rc != EOK)272 return tcp_release_and_return(packet, rc);273 break;274 132 default: 275 return tcp_release_and_return(packet, ENOTSUP); 276 } 277 278 /* TODO process received ipopts? */ 279 result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL); 280 if (result < 0) 281 return tcp_release_and_return(packet, result); 282 283 offset = (size_t) result; 284 133 log_msg(LVL_WARN, "Unsupported service number %u", 134 (unsigned)error); 135 pq_release_remote(net_sess, packet_get_id(packet)); 136 return ENOTSUP; 137 } 138 139 /* Process and trim off IP header */ 140 log_msg(LVL_DEBUG, "tcp_received_msg() - IP header"); 141 142 rc = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL); 143 if (rc < 0) { 144 log_msg(LVL_WARN, "ip_client_process_packet() failed"); 145 pq_release_remote(net_sess, packet_get_id(packet)); 146 return rc; 147 } 148 149 offset = (size_t)rc; 285 150 length = packet_get_data_length(packet); 286 if (length <= 0) 287 return tcp_release_and_return(packet, EINVAL); 288 289 if (length < TCP_HEADER_SIZE + offset) 290 return tcp_release_and_return(packet, NO_DATA); 291 292 /* Trim all but TCP header */ 151 152 if (length < 0 || (size_t)length < offset) { 153 log_msg(LVL_WARN, "length=%d, dropping.", length); 154 pq_release_remote(net_sess, packet_get_id(packet)); 155 return EINVAL; 156 } 157 158 addr_len = packet_get_addr(packet, (uint8_t **)&src_addr, 159 (uint8_t **)&dest_addr); 160 if (addr_len <= 0) { 161 log_msg(LVL_WARN, "Failed to get packet address."); 162 pq_release_remote(net_sess, packet_get_id(packet)); 163 return EINVAL; 164 } 165 166 if (addr_len != sizeof(struct sockaddr_in)) { 167 log_msg(LVL_WARN, "Unsupported address size %zu (!= %zu)", 168 addr_len, sizeof(struct sockaddr_in)); 169 pq_release_remote(net_sess, packet_get_id(packet)); 170 return EINVAL; 171 } 172 293 173 rc = packet_trim(packet, offset, 0); 294 if (rc != EOK) 295 return tcp_release_and_return(packet, rc); 296 297 /* Get tcp header */ 298 header = (tcp_header_t *) packet_get_data(packet); 299 if (!header) 300 return tcp_release_and_return(packet, NO_DATA); 301 302 #if 0 303 printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header), 304 ntohs(header->destination_port)); 305 #endif 306 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest); 307 if (result <= 0) 308 return tcp_release_and_return(packet, result); 309 310 addrlen = (size_t) result; 311 312 rc = tl_set_address_port(src, addrlen, ntohs(header->source_port)); 313 if (rc != EOK) 314 return tcp_release_and_return(packet, rc); 315 316 /* Find the destination socket */ 317 socket = socket_port_find(&tcp_globals.sockets, 318 ntohs(header->destination_port), (uint8_t *) src, addrlen); 319 if (!socket) { 320 /* Find the listening destination socket */ 321 socket = socket_port_find(&tcp_globals.sockets, 322 ntohs(header->destination_port), 323 (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0); 324 } 325 326 if (!socket) { 327 if (tl_prepare_icmp_packet(tcp_globals.net_sess, 328 tcp_globals.icmp_sess, packet, error) == EOK) { 329 icmp_destination_unreachable_msg(tcp_globals.icmp_sess, 330 ICMP_PORT_UNREACH, 0, packet); 331 } 332 return EADDRNOTAVAIL; 333 } 334 335 printf("socket id %d\n", socket->socket_id); 336 socket_data = (tcp_socket_data_t *) socket->specific_data; 337 assert(socket_data); 338 339 /* Some data received, clear the timeout counter */ 340 socket_data->timeout_count = 0; 341 342 /* Count the received packet fragments */ 343 next_packet = packet; 344 fragments = 0; 345 checksum = 0; 346 total_length = 0; 347 do { 348 fragments++; 349 length = packet_get_data_length(next_packet); 350 if (length <= 0) 351 return tcp_release_and_return(packet, NO_DATA); 352 353 total_length += length; 354 355 /* Add partial checksum if set */ 356 if (!error) { 357 checksum = compute_checksum(checksum, 358 packet_get_data(packet), 359 packet_get_data_length(packet)); 360 } 361 362 } while ((next_packet = pq_next(next_packet))); 363 364 fibril_rwlock_write_lock(socket_data->local_lock); 365 366 if (error) 367 goto has_error_service; 368 369 if (socket_data->state == TCP_SOCKET_LISTEN) { 370 if (socket_data->pseudo_header) { 371 free(socket_data->pseudo_header); 372 socket_data->pseudo_header = NULL; 373 socket_data->headerlen = 0; 374 } 375 376 rc = ip_client_get_pseudo_header(IPPROTO_TCP, src, addrlen, 377 dest, addrlen, total_length, &socket_data->pseudo_header, 378 &socket_data->headerlen); 379 if (rc != EOK) { 380 fibril_rwlock_write_unlock(socket_data->local_lock); 381 return tcp_release_and_return(packet, rc); 382 } 383 } else { 384 rc = ip_client_set_pseudo_header_data_length( 385 socket_data->pseudo_header, socket_data->headerlen, 386 total_length); 387 if (rc != EOK) { 388 fibril_rwlock_write_unlock(socket_data->local_lock); 389 return tcp_release_and_return(packet, rc); 390 } 391 } 392 393 checksum = compute_checksum(checksum, socket_data->pseudo_header, 394 socket_data->headerlen); 395 if (flip_checksum(compact_checksum(checksum)) != IP_CHECKSUM_ZERO) { 396 printf("checksum err %x -> %x\n", header->checksum, 397 flip_checksum(compact_checksum(checksum))); 398 fibril_rwlock_write_unlock(socket_data->local_lock); 399 400 rc = tl_prepare_icmp_packet(tcp_globals.net_sess, 401 tcp_globals.icmp_sess, packet, error); 402 if (rc == EOK) { 403 /* Checksum error ICMP */ 404 icmp_parameter_problem_msg(tcp_globals.icmp_sess, 405 ICMP_PARAM_POINTER, 406 ((size_t) ((void *) &header->checksum)) - 407 ((size_t) ((void *) header)), packet); 408 } 409 174 if (rc != EOK) { 175 log_msg(LVL_WARN, "Failed to trim packet."); 176 pq_release_remote(net_sess, packet_get_id(packet)); 177 return rc; 178 } 179 180 /* Pull up packets into a single memory block, pdu_raw. */ 181 log_msg(LVL_DEBUG, "tcp_received_msg() - pull up"); 182 uint8_t *pdu_raw; 183 size_t pdu_raw_size = 0; 184 185 pq_pullup(packet, (void **)&pdu_raw, &pdu_raw_size); 186 187 /* Split into header and payload. */ 188 189 log_msg(LVL_DEBUG, "tcp_received_msg() - split header/payload"); 190 191 tcp_pdu_t *pdu; 192 size_t hdr_size; 193 194 /* XXX Header options */ 195 hdr_size = sizeof(tcp_header_t); 196 197 if (pdu_raw_size < hdr_size) { 198 log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu", 199 pdu_raw_size, hdr_size); 200 pq_release_remote(net_sess, packet_get_id(packet)); 410 201 return EINVAL; 411 202 } 412 203 413 has_error_service: 414 fibril_rwlock_write_unlock(&tcp_globals.lock); 415 416 /* TODO error reporting/handling */ 417 switch (socket_data->state) { 418 case TCP_SOCKET_LISTEN: 419 rc = tcp_process_listen(socket, socket_data, header, packet, 420 src, dest, addrlen); 421 break; 422 case TCP_SOCKET_SYN_RECEIVED: 423 rc = tcp_process_syn_received(socket, socket_data, header, 424 packet); 425 break; 426 case TCP_SOCKET_SYN_SENT: 427 rc = tcp_process_syn_sent(socket, socket_data, header, packet); 428 break; 429 case TCP_SOCKET_FIN_WAIT_1: 430 /* ack changing the state to FIN_WAIT_2 gets processed later */ 431 case TCP_SOCKET_FIN_WAIT_2: 432 /* fin changing state to LAST_ACK gets processed later */ 433 case TCP_SOCKET_LAST_ACK: 434 /* ack releasing the socket get processed later */ 435 case TCP_SOCKET_CLOSING: 436 /* ack releasing the socket gets processed later */ 437 case TCP_SOCKET_ESTABLISHED: 438 rc = tcp_process_established(socket, socket_data, header, 439 packet, fragments, total_length); 440 break; 441 default: 442 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 443 } 444 445 if (rc != EOK) { 446 fibril_rwlock_write_unlock(socket_data->local_lock); 447 printf("process %d\n", rc); 448 } 204 log_msg(LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu", 205 pdu_raw_size, hdr_size); 206 pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size, 207 pdu_raw_size - hdr_size); 208 if (pdu == NULL) { 209 log_msg(LVL_WARN, "Failed creating PDU. Dropped."); 210 return ENOMEM; 211 } 212 213 free(pdu_raw); 214 215 pdu->src_addr.ipv4 = uint32_t_be2host(src_addr->sin_addr.s_addr); 216 pdu->dest_addr.ipv4 = uint32_t_be2host(dest_addr->sin_addr.s_addr); 217 log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x", 218 pdu->src_addr.ipv4, pdu->dest_addr.ipv4); 219 220 tcp_received_pdu(pdu); 221 tcp_pdu_delete(pdu); 449 222 450 223 return EOK; 451 224 } 452 225 453 int tcp_process_established(socket_core_t *socket, tcp_socket_data_t * 454 socket_data, tcp_header_t *header, packet_t *packet, int fragments, 455 size_t total_length) 456 { 457 packet_t *next_packet; 458 packet_t *tmp_packet; 459 uint32_t old_incoming; 460 size_t order; 461 uint32_t sequence_number; 462 size_t length; 463 size_t offset; 464 uint32_t new_sequence_number; 465 bool forced_ack; 466 int rc; 467 468 assert(socket); 469 assert(socket_data); 470 assert(socket->specific_data == socket_data); 471 assert(header); 472 assert(packet); 473 474 forced_ack = false; 475 476 new_sequence_number = ntohl(header->sequence_number); 477 old_incoming = socket_data->next_incoming; 478 479 if (GET_TCP_HEADER_FINALIZE(header)) { 480 socket_data->fin_incoming = new_sequence_number + 481 total_length - TCP_HEADER_LENGTH(header); 482 } 483 484 /* Trim begining if containing expected data */ 485 if (IS_IN_INTERVAL_OVERFLOW(new_sequence_number, 486 socket_data->next_incoming, new_sequence_number + total_length)) { 487 488 /* Get the acknowledged offset */ 489 if (socket_data->next_incoming < new_sequence_number) { 490 offset = new_sequence_number - 491 socket_data->next_incoming; 492 } else { 493 offset = socket_data->next_incoming - 494 new_sequence_number; 495 } 496 497 new_sequence_number += offset; 498 total_length -= offset; 499 length = packet_get_data_length(packet); 500 501 /* Trim the acknowledged data */ 502 while (length <= offset) { 503 /* Release the acknowledged packets */ 504 next_packet = pq_next(packet); 505 pq_release_remote(tcp_globals.net_sess, 506 packet_get_id(packet)); 507 packet = next_packet; 508 offset -= length; 509 length = packet_get_data_length(packet); 510 } 511 512 if (offset > 0) { 513 rc = packet_trim(packet, offset, 0); 514 if (rc != EOK) 515 return tcp_release_and_return(packet, rc); 516 } 517 518 assert(new_sequence_number == socket_data->next_incoming); 519 } 520 521 /* Release if overflowing the window */ 522 /* 523 if (IS_IN_INTERVAL_OVERFLOW(socket_data->next_incoming + 524 socket_data->window, new_sequence_number, new_sequence_number + 525 total_length)) { 526 return tcp_release_and_return(packet, EOVERFLOW); 527 } 528 529 // trim end if overflowing the window 530 if (IS_IN_INTERVAL_OVERFLOW(new_sequence_number, 531 socket_data->next_incoming + socket_data->window, 532 new_sequence_number + total_length)) { 533 // get the allowed data length 534 if (socket_data->next_incoming + socket_data->window < 535 new_sequence_number) { 536 offset = new_sequence_number - 537 socket_data->next_incoming + socket_data->window; 538 } else { 539 offset = socket_data->next_incoming + 540 socket_data->window - new_sequence_number; 541 } 542 next_packet = packet; 543 // trim the overflowing data 544 while (next_packet && (offset > 0)) { 545 length = packet_get_data_length(packet); 546 if (length <= offset) 547 next_packet = pq_next(next_packet); 548 else { 549 rc = packet_trim(next_packet, 0, 550 length - offset)); 551 if (rc != EOK) 552 return tcp_release_and_return(packet, 553 rc); 554 } 555 offset -= length; 556 total_length -= length - offset; 557 } 558 // release the overflowing packets 559 next_packet = pq_next(next_packet); 560 if (next_packet) { 561 tmp_packet = next_packet; 562 next_packet = pq_next(next_packet); 563 pq_insert_after(tmp_packet, next_packet); 564 pq_release_remote(tcp_globals.net_sess, 565 packet_get_id(tmp_packet)); 566 } 567 assert(new_sequence_number + total_length == 568 socket_data->next_incoming + socket_data->window); 569 } 570 */ 571 /* The expected one arrived? */ 572 if (new_sequence_number == socket_data->next_incoming) { 573 printf("expected\n"); 574 /* Process acknowledgement */ 575 tcp_process_acknowledgement(socket, socket_data, header); 576 577 /* Remove the header */ 578 total_length -= TCP_HEADER_LENGTH(header); 579 rc = packet_trim(packet, TCP_HEADER_LENGTH(header), 0); 580 if (rc != EOK) 581 return tcp_release_and_return(packet, rc); 582 583 if (total_length) { 584 rc = tcp_queue_received_packet(socket, socket_data, 585 packet, fragments, total_length); 586 if (rc != EOK) 587 return rc; 588 } else { 589 total_length = 1; 590 } 591 592 socket_data->next_incoming = old_incoming + total_length; 593 packet = socket_data->incoming; 594 while (packet) { 595 rc = pq_get_order(socket_data->incoming, &order, NULL); 596 if (rc != EOK) { 597 /* Remove the corrupted packet */ 598 next_packet = pq_detach(packet); 599 if (packet == socket_data->incoming) 600 socket_data->incoming = next_packet; 601 pq_release_remote(tcp_globals.net_sess, 602 packet_get_id(packet)); 603 packet = next_packet; 604 continue; 605 } 606 607 sequence_number = (uint32_t) order; 608 if (IS_IN_INTERVAL_OVERFLOW(sequence_number, 609 old_incoming, socket_data->next_incoming)) { 610 /* Move to the next */ 611 packet = pq_next(packet); 612 /* Coninual data? */ 613 } else if (IS_IN_INTERVAL_OVERFLOW(old_incoming, 614 sequence_number, socket_data->next_incoming)) { 615 /* Detach the packet */ 616 next_packet = pq_detach(packet); 617 if (packet == socket_data->incoming) 618 socket_data->incoming = next_packet; 619 /* Get data length */ 620 length = packet_get_data_length(packet); 621 new_sequence_number = sequence_number + length; 622 if (length <= 0) { 623 /* Remove the empty packet */ 624 pq_release_remote(tcp_globals.net_sess, 625 packet_get_id(packet)); 626 packet = next_packet; 627 continue; 628 } 629 /* Exactly following */ 630 if (sequence_number == 631 socket_data->next_incoming) { 632 /* Queue received data */ 633 rc = tcp_queue_received_packet(socket, 634 socket_data, packet, 1, 635 packet_get_data_length(packet)); 636 if (rc != EOK) 637 return rc; 638 socket_data->next_incoming = 639 new_sequence_number; 640 packet = next_packet; 641 continue; 642 /* At least partly following data? */ 643 } 644 if (IS_IN_INTERVAL_OVERFLOW(sequence_number, 645 socket_data->next_incoming, new_sequence_number)) { 646 if (socket_data->next_incoming < 647 new_sequence_number) { 648 length = new_sequence_number - 649 socket_data->next_incoming; 650 } else { 651 length = 652 socket_data->next_incoming - 653 new_sequence_number; 654 } 655 rc = packet_trim(packet,length, 0); 656 if (rc == EOK) { 657 /* Queue received data */ 658 rc = tcp_queue_received_packet( 659 socket, socket_data, packet, 660 1, packet_get_data_length( 661 packet)); 662 if (rc != EOK) 663 return rc; 664 socket_data->next_incoming = 665 new_sequence_number; 666 packet = next_packet; 667 continue; 668 } 669 } 670 /* Remove the duplicit or corrupted packet */ 671 pq_release_remote(tcp_globals.net_sess, 672 packet_get_id(packet)); 673 packet = next_packet; 674 continue; 675 } else { 676 break; 677 } 678 } 679 } else if (IS_IN_INTERVAL(socket_data->next_incoming, 680 new_sequence_number, 681 socket_data->next_incoming + socket_data->window)) { 682 printf("in window\n"); 683 /* Process acknowledgement */ 684 tcp_process_acknowledgement(socket, socket_data, header); 685 686 /* Remove the header */ 687 total_length -= TCP_HEADER_LENGTH(header); 688 rc = packet_trim(packet, TCP_HEADER_LENGTH(header), 0); 689 if (rc != EOK) 690 return tcp_release_and_return(packet, rc); 691 692 next_packet = pq_detach(packet); 693 length = packet_get_data_length(packet); 694 rc = pq_add(&socket_data->incoming, packet, new_sequence_number, 695 length); 696 if (rc != EOK) { 697 /* Remove the corrupted packets */ 698 pq_release_remote(tcp_globals.net_sess, 699 packet_get_id(packet)); 700 pq_release_remote(tcp_globals.net_sess, 701 packet_get_id(next_packet)); 702 } else { 703 while (next_packet) { 704 new_sequence_number += length; 705 tmp_packet = pq_detach(next_packet); 706 length = packet_get_data_length(next_packet); 707 708 rc = pq_set_order(next_packet, 709 new_sequence_number, length); 710 if (rc != EOK) { 711 pq_release_remote(tcp_globals.net_sess, 712 packet_get_id(next_packet)); 713 } 714 rc = pq_insert_after(packet, next_packet); 715 if (rc != EOK) { 716 pq_release_remote(tcp_globals.net_sess, 717 packet_get_id(next_packet)); 718 } 719 next_packet = tmp_packet; 720 } 721 } 722 } else { 723 printf("unexpected\n"); 724 /* Release duplicite or restricted */ 725 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 726 forced_ack = true; 727 } 728 729 /* If next in sequence is an incoming FIN */ 730 if (socket_data->next_incoming == socket_data->fin_incoming) { 731 /* Advance sequence number */ 732 socket_data->next_incoming += 1; 733 734 /* Handle FIN */ 735 switch (socket_data->state) { 736 case TCP_SOCKET_FIN_WAIT_1: 737 case TCP_SOCKET_FIN_WAIT_2: 738 case TCP_SOCKET_CLOSING: 739 socket_data->state = TCP_SOCKET_CLOSING; 740 break; 741 case TCP_SOCKET_ESTABLISHED: 742 /* Queue end-of-data marker on the socket. */ 743 tcp_queue_received_end_of_data(socket); 744 socket_data->state = TCP_SOCKET_CLOSE_WAIT; 745 break; 746 default: 747 socket_data->state = TCP_SOCKET_CLOSE_WAIT; 748 break; 749 } 750 } 751 752 packet = tcp_get_packets_to_send(socket, socket_data); 753 if (!packet && (socket_data->next_incoming != old_incoming || forced_ack)) { 754 /* Create the notification packet */ 755 rc = tcp_create_notification_packet(&packet, socket, 756 socket_data, 0, 0); 757 if (rc != EOK) 758 return rc; 759 rc = tcp_queue_prepare_packet(socket, socket_data, packet, 1); 760 if (rc != EOK) 761 return rc; 762 packet = tcp_send_prepare_packet(socket, socket_data, packet, 1, 763 socket_data->last_outgoing + 1); 764 } 765 766 fibril_rwlock_write_unlock(socket_data->local_lock); 767 768 /* Send the packet */ 769 tcp_send_packets(socket_data->device_id, packet); 770 771 return EOK; 772 } 773 774 int tcp_queue_received_packet(socket_core_t *socket, 775 tcp_socket_data_t *socket_data, packet_t *packet, int fragments, 776 size_t total_length) 777 { 778 packet_dimension_t *packet_dimension; 779 int rc; 780 781 assert(socket); 782 assert(socket_data); 783 assert(socket->specific_data == socket_data); 784 assert(packet); 785 assert(fragments >= 1); 786 assert(socket_data->window > total_length); 787 788 /* Queue the received packet */ 789 rc = dyn_fifo_push(&socket->received, packet_get_id(packet), 790 SOCKET_MAX_RECEIVED_SIZE); 791 if (rc != EOK) 792 return tcp_release_and_return(packet, rc); 793 rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess, 794 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension); 795 if (rc != EOK) 796 return tcp_release_and_return(packet, rc); 797 798 /* Decrease the window size */ 799 socket_data->window -= total_length; 800 801 /* Notify the destination socket */ 802 async_exch_t *exch = async_exchange_begin(socket->sess); 803 async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) socket->socket_id, 804 ((packet_dimension->content < socket_data->data_fragment_size) ? 805 packet_dimension->content : socket_data->data_fragment_size), 0, 0, 806 (sysarg_t) fragments); 807 async_exchange_end(exch); 808 809 return EOK; 810 } 811 812 /** Queue end-of-data marker on the socket. 813 * 814 * Next element in the sequence space is FIN. Queue end-of-data marker 815 * on the socket. 816 * 817 * @param socket Socket 818 */ 819 static void tcp_queue_received_end_of_data(socket_core_t *socket) 820 { 821 assert(socket != NULL); 822 823 /* Notify the destination socket */ 824 async_exch_t *exch = async_exchange_begin(socket->sess); 825 async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) socket->socket_id, 826 0, 0, 0, (sysarg_t) 0 /* 0 fragments == no more data */); 827 async_exchange_end(exch); 828 } 829 830 int tcp_process_syn_sent(socket_core_t *socket, tcp_socket_data_t * 831 socket_data, tcp_header_t *header, packet_t *packet) 832 { 833 packet_t *next_packet; 834 int rc; 835 836 assert(socket); 837 assert(socket_data); 838 assert(socket->specific_data == socket_data); 839 assert(header); 840 assert(packet); 841 842 if (!GET_TCP_HEADER_SYNCHRONIZE(header)) 843 return tcp_release_and_return(packet, EINVAL); 844 845 /* Process acknowledgement */ 846 tcp_process_acknowledgement(socket, socket_data, header); 847 848 socket_data->next_incoming = ntohl(header->sequence_number) + 1; 849 850 /* Release additional packets */ 851 next_packet = pq_detach(packet); 852 if (next_packet) { 853 pq_release_remote(tcp_globals.net_sess, 854 packet_get_id(next_packet)); 855 } 856 857 /* Trim if longer than the header */ 858 if (packet_get_data_length(packet) > sizeof(*header)) { 859 rc = packet_trim(packet, 0, 860 packet_get_data_length(packet) - sizeof(*header)); 861 if (rc != EOK) 862 return tcp_release_and_return(packet, rc); 863 } 864 865 tcp_prepare_operation_header(socket, socket_data, header, 0, 0); 866 fibril_mutex_lock(&socket_data->operation.mutex); 867 socket_data->operation.result = tcp_queue_packet(socket, socket_data, 868 packet, 1); 869 870 if (socket_data->operation.result == EOK) { 871 socket_data->state = TCP_SOCKET_ESTABLISHED; 872 packet = tcp_get_packets_to_send(socket, socket_data); 873 if (packet) { 874 fibril_rwlock_write_unlock( socket_data->local_lock); 875 /* Send the packet */ 876 tcp_send_packets(socket_data->device_id, packet); 877 /* Signal the result */ 878 fibril_condvar_signal( &socket_data->operation.condvar); 879 fibril_mutex_unlock( &socket_data->operation.mutex); 880 return EOK; 881 } 882 } 883 884 fibril_mutex_unlock(&socket_data->operation.mutex); 885 return tcp_release_and_return(packet, EINVAL); 886 } 887 888 int tcp_process_listen(socket_core_t *listening_socket, 889 tcp_socket_data_t *listening_socket_data, tcp_header_t *header, 890 packet_t *packet, struct sockaddr *src, struct sockaddr *dest, 891 size_t addrlen) 892 { 893 packet_t *next_packet; 894 socket_core_t *socket; 895 tcp_socket_data_t *socket_data; 896 int socket_id; 897 int listening_socket_id = listening_socket->socket_id; 898 int listening_port = listening_socket->port; 899 int rc; 900 901 assert(listening_socket); 902 assert(listening_socket_data); 903 assert(listening_socket->specific_data == listening_socket_data); 904 assert(header); 905 assert(packet); 906 907 if (!GET_TCP_HEADER_SYNCHRONIZE(header)) 908 return tcp_release_and_return(packet, EINVAL); 909 910 socket_data = (tcp_socket_data_t *) malloc(sizeof(*socket_data)); 911 if (!socket_data) 912 return tcp_release_and_return(packet, ENOMEM); 913 914 tcp_initialize_socket_data(socket_data); 915 socket_data->local_lock = listening_socket_data->local_lock; 916 socket_data->local_sockets = listening_socket_data->local_sockets; 917 socket_data->listening_socket_id = listening_socket->socket_id; 918 socket_data->next_incoming = ntohl(header->sequence_number); 919 socket_data->treshold = socket_data->next_incoming + 920 ntohs(header->window); 921 socket_data->addrlen = addrlen; 922 socket_data->addr = malloc(socket_data->addrlen); 923 if (!socket_data->addr) { 924 free(socket_data); 925 return tcp_release_and_return(packet, ENOMEM); 926 } 927 928 memcpy(socket_data->addr, src, socket_data->addrlen); 929 socket_data->dest_port = ntohs(header->source_port); 930 rc = tl_set_address_port(socket_data->addr, socket_data->addrlen, 931 socket_data->dest_port); 932 if (rc != EOK) { 933 free(socket_data->addr); 934 free(socket_data); 935 return tcp_release_and_return(packet, rc); 936 } 937 938 /* Create a socket */ 939 socket_id = -1; 940 rc = socket_create(socket_data->local_sockets, listening_socket->sess, 941 socket_data, &socket_id); 942 if (rc != EOK) { 943 free(socket_data->addr); 944 free(socket_data); 945 return tcp_release_and_return(packet, rc); 946 } 947 948 printf("new_sock %d\n", socket_id); 949 socket_data->pseudo_header = listening_socket_data->pseudo_header; 950 socket_data->headerlen = listening_socket_data->headerlen; 951 listening_socket_data->pseudo_header = NULL; 952 listening_socket_data->headerlen = 0; 953 954 fibril_rwlock_write_unlock(socket_data->local_lock); 955 fibril_rwlock_write_lock(&tcp_globals.lock); 956 957 /* Find the destination socket */ 958 listening_socket = socket_port_find(&tcp_globals.sockets, 959 listening_port, (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0); 960 if (!listening_socket || 961 (listening_socket->socket_id != listening_socket_id)) { 962 fibril_rwlock_write_unlock(&tcp_globals.lock); 963 /* A shadow may remain until app hangs up */ 964 return tcp_release_and_return(packet, EOK /*ENOTSOCK*/); 965 } 966 listening_socket_data = 967 (tcp_socket_data_t *) listening_socket->specific_data; 968 assert(listening_socket_data); 969 970 fibril_rwlock_write_lock(listening_socket_data->local_lock); 971 972 socket = socket_cores_find(listening_socket_data->local_sockets, 973 socket_id); 974 if (!socket) { 975 /* Where is the socket?!? */ 976 fibril_rwlock_write_unlock(&tcp_globals.lock); 977 return ENOTSOCK; 978 } 979 socket_data = (tcp_socket_data_t *) socket->specific_data; 980 assert(socket_data); 981 982 rc = socket_port_add(&tcp_globals.sockets, listening_port, socket, 983 (uint8_t *) socket_data->addr, socket_data->addrlen); 984 assert(socket == socket_port_find(&tcp_globals.sockets, listening_port, 985 (uint8_t *) socket_data->addr, socket_data->addrlen)); 986 987 // rc = socket_bind_free_port(&tcp_globals.sockets, socket, 988 // TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, 989 // tcp_globals.last_used_port); 990 // tcp_globals.last_used_port = socket->port; 991 fibril_rwlock_write_unlock(&tcp_globals.lock); 992 if (rc != EOK) { 993 socket_destroy(tcp_globals.net_sess, socket->socket_id, 994 socket_data->local_sockets, &tcp_globals.sockets, 995 tcp_free_socket_data); 996 return tcp_release_and_return(packet, rc); 997 } 998 999 socket_data->state = TCP_SOCKET_LISTEN; 1000 socket_data->next_incoming = ntohl(header->sequence_number) + 1; 1001 1002 /* Release additional packets */ 1003 next_packet = pq_detach(packet); 1004 if (next_packet) { 1005 pq_release_remote(tcp_globals.net_sess, 1006 packet_get_id(next_packet)); 1007 } 1008 1009 /* Trim if longer than the header */ 1010 if (packet_get_data_length(packet) > sizeof(*header)) { 1011 rc = packet_trim(packet, 0, 1012 packet_get_data_length(packet) - sizeof(*header)); 1013 if (rc != EOK) { 1014 socket_destroy(tcp_globals.net_sess, socket->socket_id, 1015 socket_data->local_sockets, &tcp_globals.sockets, 1016 tcp_free_socket_data); 1017 return tcp_release_and_return(packet, rc); 1018 } 1019 } 1020 1021 tcp_prepare_operation_header(socket, socket_data, header, 1, 0); 1022 1023 rc = tcp_queue_packet(socket, socket_data, packet, 1); 1024 if (rc != EOK) { 1025 socket_destroy(tcp_globals.net_sess, socket->socket_id, 1026 socket_data->local_sockets, &tcp_globals.sockets, 1027 tcp_free_socket_data); 1028 return rc; 1029 } 1030 1031 packet = tcp_get_packets_to_send(socket, socket_data); 1032 if (!packet) { 1033 socket_destroy(tcp_globals.net_sess, socket->socket_id, 1034 socket_data->local_sockets, &tcp_globals.sockets, 1035 tcp_free_socket_data); 1036 return EINVAL; 1037 } 1038 1039 socket_data->state = TCP_SOCKET_SYN_RECEIVED; 1040 fibril_rwlock_write_unlock(socket_data->local_lock); 1041 1042 /* Send the packet */ 1043 tcp_send_packets(socket_data->device_id, packet); 1044 1045 return EOK; 1046 } 1047 1048 int tcp_process_syn_received(socket_core_t *socket, 1049 tcp_socket_data_t *socket_data, tcp_header_t *header, packet_t *packet) 1050 { 1051 socket_core_t *listening_socket; 1052 tcp_socket_data_t *listening_socket_data; 1053 int rc; 1054 1055 assert(socket); 1056 assert(socket_data); 1057 assert(socket->specific_data == socket_data); 1058 assert(header); 1059 assert(packet); 1060 1061 if (!GET_TCP_HEADER_ACKNOWLEDGE(header)) 1062 return tcp_release_and_return(packet, EINVAL); 1063 1064 /* Process acknowledgement */ 1065 tcp_process_acknowledgement(socket, socket_data, header); 1066 1067 socket_data->next_incoming = ntohl(header->sequence_number); /* + 1; */ 1068 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1069 socket_data->state = TCP_SOCKET_ESTABLISHED; 1070 listening_socket = socket_cores_find(socket_data->local_sockets, 1071 socket_data->listening_socket_id); 1072 if (listening_socket) { 1073 listening_socket_data = 1074 (tcp_socket_data_t *) listening_socket->specific_data; 1075 assert(listening_socket_data); 1076 1077 /* Queue the received packet */ 1078 rc = dyn_fifo_push(&listening_socket->accepted, 1079 (-1 * socket->socket_id), listening_socket_data->backlog); 1080 if (rc == EOK) { 1081 /* Notify the destination socket */ 1082 async_exch_t *exch = async_exchange_begin(socket->sess); 1083 async_msg_5(exch, NET_SOCKET_ACCEPTED, 1084 (sysarg_t) listening_socket->socket_id, 1085 socket_data->data_fragment_size, TCP_HEADER_SIZE, 1086 0, (sysarg_t) socket->socket_id); 1087 async_exchange_end(exch); 1088 1089 fibril_rwlock_write_unlock(socket_data->local_lock); 1090 return EOK; 1091 } 1092 } 1093 /* Send FIN */ 1094 socket_data->state = TCP_SOCKET_FIN_WAIT_1; 1095 1096 /* Create the notification packet */ 1097 rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1); 1098 if (rc != EOK) 1099 return rc; 1100 1101 /* Send the packet */ 1102 rc = tcp_queue_packet(socket, socket_data, packet, 1); 1103 if (rc != EOK) 1104 return rc; 1105 1106 /* Flush packets */ 1107 packet = tcp_get_packets_to_send(socket, socket_data); 1108 fibril_rwlock_write_unlock(socket_data->local_lock); 1109 if (packet) { 1110 /* Send the packet */ 1111 tcp_send_packets(socket_data->device_id, packet); 1112 } 1113 1114 return EOK; 1115 } 1116 1117 void tcp_process_acknowledgement(socket_core_t *socket, 1118 tcp_socket_data_t *socket_data, tcp_header_t *header) 1119 { 1120 size_t number; 1121 size_t length; 1122 packet_t *packet; 1123 packet_t *next; 1124 packet_t *acknowledged = NULL; 1125 uint32_t old; 1126 1127 assert(socket); 1128 assert(socket_data); 1129 assert(socket->specific_data == socket_data); 1130 assert(header); 1131 1132 if (!GET_TCP_HEADER_ACKNOWLEDGE(header)) 1133 return; 1134 1135 number = ntohl(header->acknowledgement_number); 1136 1137 /* If more data acknowledged */ 1138 if (number != socket_data->expected) { 1139 old = socket_data->expected; 1140 if (IS_IN_INTERVAL_OVERFLOW(old, socket_data->fin_outgoing, 1141 number)) { 1142 switch (socket_data->state) { 1143 case TCP_SOCKET_FIN_WAIT_1: 1144 socket_data->state = TCP_SOCKET_FIN_WAIT_2; 1145 break; 1146 case TCP_SOCKET_LAST_ACK: 1147 case TCP_SOCKET_CLOSING: 1148 /* 1149 * FIN acknowledged - release the socket in 1150 * another fibril. 1151 */ 1152 tcp_prepare_timeout(tcp_release_after_timeout, 1153 socket, socket_data, 0, 1154 TCP_SOCKET_TIME_WAIT, 1155 NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT, true); 1156 break; 1157 default: 1158 break; 1159 } 1160 } 1161 1162 /* Update the treshold if higher than set */ 1163 if (number + ntohs(header->window) > 1164 socket_data->expected + socket_data->treshold) { 1165 socket_data->treshold = number + ntohs(header->window) - 1166 socket_data->expected; 1167 } 1168 1169 /* Set new expected sequence number */ 1170 socket_data->expected = number; 1171 socket_data->expected_count = 1; 1172 packet = socket_data->outgoing; 1173 while (pq_get_order(packet, &number, &length) == EOK) { 1174 if (IS_IN_INTERVAL_OVERFLOW((uint32_t) old, 1175 (uint32_t) (number + length), 1176 (uint32_t) socket_data->expected)) { 1177 next = pq_detach(packet); 1178 if (packet == socket_data->outgoing) 1179 socket_data->outgoing = next; 1180 1181 /* Add to acknowledged or release */ 1182 if (pq_add(&acknowledged, packet, 0, 0) != EOK) 1183 pq_release_remote(tcp_globals.net_sess, 1184 packet_get_id(packet)); 1185 packet = next; 1186 } else if (old < socket_data->expected) 1187 break; 1188 } 1189 1190 /* Release acknowledged */ 1191 if (acknowledged) { 1192 pq_release_remote(tcp_globals.net_sess, 1193 packet_get_id(acknowledged)); 1194 } 1195 return; 1196 /* If the same as the previous time */ 1197 } 1198 1199 if (number == socket_data->expected) { 1200 /* Increase the counter */ 1201 socket_data->expected_count++; 1202 if (socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT) { 1203 socket_data->expected_count = 1; 1204 /* TODO retransmit lock */ 1205 //tcp_retransmit_packet(socket, socket_data, number); 1206 } 1207 } 1208 } 1209 1210 /** Per-connection initialization 1211 * 1212 */ 1213 void tl_connection(void) 1214 { 1215 } 1216 1217 /** Processes the TCP message. 1218 * 1219 * @param[in] callid The message identifier. 1220 * @param[in] call The message parameters. 1221 * @param[out] answer The message answer parameters. 1222 * @param[out] answer_count The last parameter for the actual answer in the 1223 * answer parameter. 1224 * @return EOK on success. 1225 * @return ENOTSUP if the message is not known. 1226 * 1227 * @see tcp_interface.h 1228 * @see IS_NET_TCP_MESSAGE() 1229 */ 1230 int tl_message(ipc_callid_t callid, ipc_call_t *call, 1231 ipc_call_t *answer, size_t *answer_count) 1232 { 1233 assert(call); 1234 assert(answer); 1235 assert(answer_count); 1236 1237 *answer_count = 0; 1238 1239 async_sess_t *callback = 1240 async_callback_receive_start(EXCHANGE_SERIALIZE, call); 1241 if (callback) 1242 return tcp_process_client_messages(callback, callid, *call); 1243 1244 return ENOTSUP; 1245 } 1246 1247 void tcp_refresh_socket_data(tcp_socket_data_t *socket_data) 1248 { 1249 assert(socket_data); 1250 1251 bzero(socket_data, sizeof(*socket_data)); 1252 socket_data->state = TCP_SOCKET_INITIAL; 1253 socket_data->device_id = NIC_DEVICE_INVALID_ID; 1254 socket_data->window = NET_DEFAULT_TCP_WINDOW; 1255 socket_data->treshold = socket_data->window; 1256 socket_data->last_outgoing = TCP_INITIAL_SEQUENCE_NUMBER; 1257 socket_data->timeout = NET_DEFAULT_TCP_INITIAL_TIMEOUT; 1258 socket_data->acknowledged = socket_data->last_outgoing; 1259 socket_data->next_outgoing = socket_data->last_outgoing + 1; 1260 socket_data->expected = socket_data->next_outgoing; 1261 } 1262 1263 void tcp_initialize_socket_data(tcp_socket_data_t *socket_data) 1264 { 1265 assert(socket_data); 1266 1267 tcp_refresh_socket_data(socket_data); 1268 fibril_mutex_initialize(&socket_data->operation.mutex); 1269 fibril_condvar_initialize(&socket_data->operation.condvar); 1270 socket_data->data_fragment_size = MAX_TCP_FRAGMENT_SIZE; 1271 } 1272 1273 int tcp_process_client_messages(async_sess_t *sess, ipc_callid_t callid, 1274 ipc_call_t call) 1275 { 1276 int res; 1277 socket_cores_t local_sockets; 1278 struct sockaddr *addr; 1279 int socket_id; 1280 size_t addrlen; 1281 size_t size; 1282 fibril_rwlock_t lock; 1283 ipc_call_t answer; 1284 size_t answer_count; 1285 tcp_socket_data_t *socket_data; 1286 socket_core_t *socket; 1287 packet_dimension_t *packet_dimension; 1288 1289 /* 1290 * Accept the connection 1291 * - Answer the first IPC_M_CONNECT_ME_TO call. 1292 */ 1293 res = EOK; 1294 answer_count = 0; 1295 1296 socket_cores_initialize(&local_sockets); 1297 fibril_rwlock_initialize(&lock); 1298 1299 while (true) { 1300 1301 /* Answer the call */ 1302 answer_call(callid, res, &answer, answer_count); 1303 /* Refresh data */ 1304 refresh_answer(&answer, &answer_count); 1305 /* Get the next call */ 1306 callid = async_get_call(&call); 1307 1308 if (!IPC_GET_IMETHOD(call)) { 1309 res = EHANGUP; 1310 break; 1311 } 1312 1313 /* Process the call */ 1314 switch (IPC_GET_IMETHOD(call)) { 1315 case NET_SOCKET: 1316 socket_data = 1317 (tcp_socket_data_t *) malloc(sizeof(*socket_data)); 1318 if (!socket_data) { 1319 res = ENOMEM; 1320 break; 1321 } 1322 1323 tcp_initialize_socket_data(socket_data); 1324 socket_data->local_lock = &lock; 1325 socket_data->local_sockets = &local_sockets; 1326 fibril_rwlock_write_lock(&lock); 1327 socket_id = SOCKET_GET_SOCKET_ID(call); 1328 res = socket_create(&local_sockets, sess, 1329 socket_data, &socket_id); 1330 SOCKET_SET_SOCKET_ID(answer, socket_id); 1331 fibril_rwlock_write_unlock(&lock); 1332 if (res != EOK) { 1333 free(socket_data); 1334 break; 1335 } 1336 if (tl_get_ip_packet_dimension(tcp_globals.ip_sess, 1337 &tcp_globals.dimensions, NIC_DEVICE_INVALID_ID, 1338 &packet_dimension) == EOK) { 1339 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, 1340 ((packet_dimension->content < 1341 socket_data->data_fragment_size) ? 1342 packet_dimension->content : 1343 socket_data->data_fragment_size)); 1344 } 1345 // SOCKET_SET_DATA_FRAGMENT_SIZE(answer, MAX_TCP_FRAGMENT_SIZE); 1346 SOCKET_SET_HEADER_SIZE(answer, TCP_HEADER_SIZE); 1347 answer_count = 3; 1348 break; 1349 1350 case NET_SOCKET_BIND: 1351 res = async_data_write_accept((void **) &addr, false, 1352 0, 0, 0, &addrlen); 1353 if (res != EOK) 1354 break; 1355 fibril_rwlock_write_lock(&tcp_globals.lock); 1356 fibril_rwlock_write_lock(&lock); 1357 res = socket_bind(&local_sockets, &tcp_globals.sockets, 1358 SOCKET_GET_SOCKET_ID(call), addr, addrlen, 1359 TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, 1360 tcp_globals.last_used_port); 1361 if (res == EOK) { 1362 socket = socket_cores_find(&local_sockets, 1363 SOCKET_GET_SOCKET_ID(call)); 1364 if (socket) { 1365 socket_data = (tcp_socket_data_t *) 1366 socket->specific_data; 1367 assert(socket_data); 1368 socket_data->state = TCP_SOCKET_LISTEN; 1369 } 1370 } 1371 fibril_rwlock_write_unlock(&lock); 1372 fibril_rwlock_write_unlock(&tcp_globals.lock); 1373 free(addr); 1374 break; 1375 1376 case NET_SOCKET_LISTEN: 1377 fibril_rwlock_read_lock(&tcp_globals.lock); 1378 // fibril_rwlock_write_lock(&tcp_globals.lock); 1379 fibril_rwlock_write_lock(&lock); 1380 res = tcp_listen_message(&local_sockets, 1381 SOCKET_GET_SOCKET_ID(call), 1382 SOCKET_GET_BACKLOG(call)); 1383 fibril_rwlock_write_unlock(&lock); 1384 // fibril_rwlock_write_unlock(&tcp_globals.lock); 1385 fibril_rwlock_read_unlock(&tcp_globals.lock); 1386 break; 1387 1388 case NET_SOCKET_CONNECT: 1389 res = async_data_write_accept((void **) &addr, false, 1390 0, 0, 0, &addrlen); 1391 if (res != EOK) 1392 break; 1393 /* 1394 * The global lock may be released in the 1395 * tcp_connect_message() function. 1396 */ 1397 fibril_rwlock_write_lock(&tcp_globals.lock); 1398 fibril_rwlock_write_lock(&lock); 1399 res = tcp_connect_message(&local_sockets, 1400 SOCKET_GET_SOCKET_ID(call), addr, addrlen); 1401 if (res != EOK) { 1402 fibril_rwlock_write_unlock(&lock); 1403 fibril_rwlock_write_unlock(&tcp_globals.lock); 1404 free(addr); 1405 } 1406 break; 1407 1408 case NET_SOCKET_ACCEPT: 1409 fibril_rwlock_read_lock(&tcp_globals.lock); 1410 fibril_rwlock_write_lock(&lock); 1411 res = tcp_accept_message(&local_sockets, 1412 SOCKET_GET_SOCKET_ID(call), 1413 SOCKET_GET_NEW_SOCKET_ID(call), &size, &addrlen); 1414 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size); 1415 fibril_rwlock_write_unlock(&lock); 1416 fibril_rwlock_read_unlock(&tcp_globals.lock); 1417 if (res > 0) { 1418 SOCKET_SET_SOCKET_ID(answer, res); 1419 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen); 1420 answer_count = 3; 1421 } 1422 break; 1423 1424 case NET_SOCKET_SEND: 1425 fibril_rwlock_read_lock(&tcp_globals.lock); 1426 fibril_rwlock_write_lock(&lock); 1427 res = tcp_send_message(&local_sockets, 1428 SOCKET_GET_SOCKET_ID(call), 1429 SOCKET_GET_DATA_FRAGMENTS(call), &size, 1430 SOCKET_GET_FLAGS(call)); 1431 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size); 1432 if (res != EOK) { 1433 fibril_rwlock_write_unlock(&lock); 1434 fibril_rwlock_read_unlock(&tcp_globals.lock); 1435 } else { 1436 answer_count = 2; 1437 } 1438 break; 1439 1440 case NET_SOCKET_SENDTO: 1441 res = async_data_write_accept((void **) &addr, false, 1442 0, 0, 0, &addrlen); 1443 if (res != EOK) 1444 break; 1445 fibril_rwlock_read_lock(&tcp_globals.lock); 1446 fibril_rwlock_write_lock(&lock); 1447 res = tcp_send_message(&local_sockets, 1448 SOCKET_GET_SOCKET_ID(call), 1449 SOCKET_GET_DATA_FRAGMENTS(call), &size, 1450 SOCKET_GET_FLAGS(call)); 1451 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size); 1452 if (res != EOK) { 1453 fibril_rwlock_write_unlock(&lock); 1454 fibril_rwlock_read_unlock(&tcp_globals.lock); 1455 } else { 1456 answer_count = 2; 1457 } 1458 free(addr); 1459 break; 1460 1461 case NET_SOCKET_RECV: 1462 fibril_rwlock_read_lock(&tcp_globals.lock); 1463 fibril_rwlock_write_lock(&lock); 1464 res = tcp_recvfrom_message(&local_sockets, 1465 SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), 1466 NULL); 1467 fibril_rwlock_write_unlock(&lock); 1468 fibril_rwlock_read_unlock(&tcp_globals.lock); 1469 if (res > 0) { 1470 SOCKET_SET_READ_DATA_LENGTH(answer, res); 1471 answer_count = 1; 1472 res = EOK; 1473 } 1474 break; 1475 1476 case NET_SOCKET_RECVFROM: 1477 fibril_rwlock_read_lock(&tcp_globals.lock); 1478 fibril_rwlock_write_lock(&lock); 1479 res = tcp_recvfrom_message(&local_sockets, 1480 SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), 1481 &addrlen); 1482 fibril_rwlock_write_unlock(&lock); 1483 fibril_rwlock_read_unlock(&tcp_globals.lock); 1484 if (res > 0) { 1485 SOCKET_SET_READ_DATA_LENGTH(answer, res); 1486 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen); 1487 answer_count = 3; 1488 res = EOK; 1489 } 1490 break; 1491 1492 case NET_SOCKET_CLOSE: 1493 fibril_rwlock_write_lock(&tcp_globals.lock); 1494 fibril_rwlock_write_lock(&lock); 1495 res = tcp_close_message(&local_sockets, 1496 SOCKET_GET_SOCKET_ID(call)); 1497 if (res != EOK) { 1498 fibril_rwlock_write_unlock(&lock); 1499 fibril_rwlock_write_unlock(&tcp_globals.lock); 1500 } 1501 break; 1502 1503 case NET_SOCKET_GETSOCKOPT: 1504 case NET_SOCKET_SETSOCKOPT: 1505 default: 1506 res = ENOTSUP; 1507 break; 1508 } 1509 } 1510 1511 /* Release the application session */ 1512 async_hangup(sess); 1513 1514 printf("release\n"); 1515 /* Release all local sockets */ 1516 socket_cores_release(tcp_globals.net_sess, &local_sockets, 1517 &tcp_globals.sockets, tcp_free_socket_data); 1518 1519 return EOK; 1520 } 1521 1522 int tcp_timeout(void *data) 1523 { 1524 tcp_timeout_t *timeout = data; 1525 int keep_write_lock = false; 1526 socket_core_t *socket; 1527 tcp_socket_data_t *socket_data; 1528 1529 assert(timeout); 1530 1531 /* Sleep the given timeout */ 1532 async_usleep(timeout->timeout); 1533 /* Lock the globals */ 1534 if (timeout->globals_read_only) 1535 fibril_rwlock_read_lock(&tcp_globals.lock); 1536 else 1537 fibril_rwlock_write_lock(&tcp_globals.lock); 1538 1539 /* Find the pending operation socket */ 1540 socket = socket_port_find(&tcp_globals.sockets, timeout->port, 1541 timeout->key, timeout->key_length); 1542 if (!socket || (socket->socket_id != timeout->socket_id)) 1543 goto out; 1544 1545 socket_data = (tcp_socket_data_t *) socket->specific_data; 1546 assert(socket_data); 1547 if (socket_data->local_sockets != timeout->local_sockets) 1548 goto out; 1549 1550 fibril_rwlock_write_lock(socket_data->local_lock); 1551 if (timeout->sequence_number) { 1552 /* Increase the timeout counter */ 1553 socket_data->timeout_count++; 1554 if (socket_data->timeout_count == TCP_MAX_TIMEOUTS) { 1555 /* TODO release as connection lost */ 1556 //tcp_refresh_socket_data(socket_data); 1557 fibril_rwlock_write_unlock(socket_data->local_lock); 1558 } else { 1559 /* Retransmit */ 1560 // tcp_retransmit_packet(socket, 1561 // socket_data, timeout->sequence_number); 1562 fibril_rwlock_write_unlock(socket_data->local_lock); 1563 } 1564 } else { 1565 fibril_mutex_lock(&socket_data->operation.mutex); 1566 /* Set the timeout operation result if state not changed */ 1567 if (socket_data->state == timeout->state) { 1568 socket_data->operation.result = ETIMEOUT; 1569 1570 /* Notify the main fibril */ 1571 fibril_condvar_signal(&socket_data->operation.condvar); 1572 1573 /* Keep the global write lock */ 1574 keep_write_lock = true; 1575 } else { 1576 /* 1577 * Operation is ok, do nothing. 1578 * Unlocking from now on, so the unlocking 1579 * order does not matter. 1580 */ 1581 fibril_rwlock_write_unlock(socket_data->local_lock); 1582 } 1583 fibril_mutex_unlock(&socket_data->operation.mutex); 1584 } 1585 1586 out: 1587 /* Unlock only if no socket */ 1588 if (timeout->globals_read_only) 1589 fibril_rwlock_read_unlock(&tcp_globals.lock); 1590 else if (!keep_write_lock) 1591 /* Release if not desired */ 1592 fibril_rwlock_write_unlock(&tcp_globals.lock); 1593 1594 /* Release the timeout structure */ 1595 free(timeout); 1596 return EOK; 1597 } 1598 1599 int tcp_release_after_timeout(void *data) 1600 { 1601 tcp_timeout_t *timeout = data; 1602 socket_core_t *socket; 1603 tcp_socket_data_t *socket_data; 1604 fibril_rwlock_t *local_lock; 1605 1606 assert(timeout); 1607 1608 /* Sleep the given timeout */ 1609 async_usleep(timeout->timeout); 1610 1611 /* Lock the globals */ 1612 fibril_rwlock_write_lock(&tcp_globals.lock); 1613 1614 /* Find the pending operation socket */ 1615 socket = socket_port_find(&tcp_globals.sockets, timeout->port, 1616 timeout->key, timeout->key_length); 1617 1618 if (socket && (socket->socket_id == timeout->socket_id)) { 1619 socket_data = (tcp_socket_data_t *) socket->specific_data; 1620 assert(socket_data); 1621 if (socket_data->local_sockets == timeout->local_sockets) { 1622 local_lock = socket_data->local_lock; 1623 fibril_rwlock_write_lock(local_lock); 1624 socket_destroy(tcp_globals.net_sess, 1625 timeout->socket_id, timeout->local_sockets, 1626 &tcp_globals.sockets, tcp_free_socket_data); 1627 fibril_rwlock_write_unlock(local_lock); 1628 } 1629 } 1630 1631 /* Unlock the globals */ 1632 fibril_rwlock_write_unlock(&tcp_globals.lock); 1633 1634 /* Release the timeout structure */ 1635 free(timeout); 1636 1637 return EOK; 1638 } 1639 1640 void tcp_retransmit_packet(socket_core_t *socket, tcp_socket_data_t * 1641 socket_data, size_t sequence_number) 1642 { 1643 packet_t *packet; 1644 packet_t *copy; 1645 size_t data_length; 1646 1647 assert(socket); 1648 assert(socket_data); 1649 assert(socket->specific_data == socket_data); 1650 1651 /* Sent packet? */ 1652 packet = pq_find(socket_data->outgoing, sequence_number); 1653 if (packet) { 1654 pq_get_order(packet, NULL, &data_length); 1655 copy = tcp_prepare_copy(socket, socket_data, packet, 1656 data_length, sequence_number); 1657 fibril_rwlock_write_unlock(socket_data->local_lock); 1658 // printf("r send %d\n", packet_get_id(packet)); 1659 if (copy) 1660 tcp_send_packets(socket_data->device_id, copy); 1661 } else { 1662 fibril_rwlock_write_unlock(socket_data->local_lock); 1663 } 1664 } 1665 1666 int tcp_listen_message(socket_cores_t *local_sockets, int socket_id, 1667 int backlog) 1668 { 1669 socket_core_t *socket; 1670 tcp_socket_data_t *socket_data; 1671 1672 assert(local_sockets); 1673 1674 if (backlog < 0) 1675 return EINVAL; 1676 1677 /* Find the socket */ 1678 socket = socket_cores_find(local_sockets, socket_id); 1679 if (!socket) 1680 return ENOTSOCK; 1681 1682 /* Get the socket specific data */ 1683 socket_data = (tcp_socket_data_t *) socket->specific_data; 1684 assert(socket_data); 1685 1686 /* Set the backlog */ 1687 socket_data->backlog = backlog; 1688 1689 return EOK; 1690 } 1691 1692 int tcp_connect_message(socket_cores_t *local_sockets, int socket_id, 1693 struct sockaddr *addr, socklen_t addrlen) 1694 { 1695 socket_core_t *socket; 1696 int rc; 1697 1698 assert(local_sockets); 1699 assert(addr); 1700 assert(addrlen > 0); 1701 1702 /* Find the socket */ 1703 socket = socket_cores_find(local_sockets, socket_id); 1704 if (!socket) 1705 return ENOTSOCK; 1706 1707 rc = tcp_connect_core(socket, local_sockets, addr, addrlen); 1708 if (rc != EOK) { 1709 tcp_free_socket_data(socket); 1710 /* Unbind if bound */ 1711 if (socket->port > 0) { 1712 socket_ports_exclude(&tcp_globals.sockets, 1713 socket->port, free); 1714 socket->port = 0; 1715 } 1716 } 1717 return rc; 1718 } 1719 1720 int tcp_connect_core(socket_core_t *socket, socket_cores_t *local_sockets, 1721 struct sockaddr *addr, socklen_t addrlen) 1722 { 1723 tcp_socket_data_t *socket_data; 226 /** Receive packets from network layer. */ 227 static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg) 228 { 1724 229 packet_t *packet; 1725 230 int rc; 1726 231 1727 assert(socket); 1728 assert(addr); 1729 assert(addrlen > 0); 1730 1731 /* Get the socket specific data */ 1732 socket_data = (tcp_socket_data_t *) socket->specific_data; 1733 assert(socket_data); 1734 assert(socket->specific_data == socket_data); 1735 if ((socket_data->state != TCP_SOCKET_INITIAL) && 1736 ((socket_data->state != TCP_SOCKET_LISTEN) || 1737 (socket->port <= 0))) 1738 return EINVAL; 1739 1740 /* Get the destination port */ 1741 rc = tl_get_address_port(addr, addrlen, &socket_data->dest_port); 1742 if (rc != EOK) 1743 return rc; 1744 1745 if (socket->port <= 0) { 1746 /* Try to find a free port */ 1747 rc = socket_bind_free_port(&tcp_globals.sockets, socket, 1748 TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, 1749 tcp_globals.last_used_port); 1750 if (rc != EOK) 1751 return rc; 1752 /* Set the next port as the search starting port number */ 1753 tcp_globals.last_used_port = socket->port; 1754 } 1755 1756 rc = ip_get_route_req(tcp_globals.ip_sess, IPPROTO_TCP, 1757 addr, addrlen, &socket_data->device_id, 1758 &socket_data->pseudo_header, &socket_data->headerlen); 1759 if (rc != EOK) 1760 return rc; 1761 1762 /* Create the notification packet */ 1763 rc = tcp_create_notification_packet(&packet, socket, socket_data, 1, 0); 1764 if (rc != EOK) 1765 return rc; 1766 1767 /* Unlock the globals and wait for an operation */ 1768 fibril_rwlock_write_unlock(&tcp_globals.lock); 1769 1770 socket_data->addr = addr; 1771 socket_data->addrlen = addrlen; 1772 1773 /* Send the packet */ 1774 1775 if (((rc = tcp_queue_packet(socket, socket_data, packet, 1)) != EOK) || 1776 ((rc = tcp_prepare_timeout(tcp_timeout, socket, socket_data, 0, 1777 TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false)) != 1778 EOK)) { 1779 socket_data->addr = NULL; 1780 socket_data->addrlen = 0; 1781 fibril_rwlock_write_lock(&tcp_globals.lock); 1782 } else { 1783 packet = tcp_get_packets_to_send(socket, socket_data); 1784 if (packet) { 1785 fibril_mutex_lock(&socket_data->operation.mutex); 1786 fibril_rwlock_write_unlock(socket_data->local_lock); 1787 1788 socket_data->state = TCP_SOCKET_SYN_SENT; 1789 1790 /* Send the packet */ 1791 tcp_send_packets(socket_data->device_id, packet); 1792 1793 /* Wait for a reply */ 1794 fibril_condvar_wait(&socket_data->operation.condvar, 1795 &socket_data->operation.mutex); 1796 rc = socket_data->operation.result; 1797 if (rc != EOK) { 1798 socket_data->addr = NULL; 1799 socket_data->addrlen = 0; 1800 } 1801 } else { 1802 socket_data->addr = NULL; 1803 socket_data->addrlen = 0; 1804 rc = EINTR; 1805 } 1806 } 1807 1808 fibril_mutex_unlock(&socket_data->operation.mutex); 1809 return rc; 1810 } 1811 1812 int tcp_queue_prepare_packet(socket_core_t *socket, 1813 tcp_socket_data_t *socket_data, packet_t *packet, size_t data_length) 1814 { 1815 tcp_header_t *header; 1816 int rc; 1817 1818 assert(socket); 1819 assert(socket_data); 1820 assert(socket->specific_data == socket_data); 1821 1822 /* Get TCP header */ 1823 header = (tcp_header_t *) packet_get_data(packet); 1824 if (!header) 1825 return NO_DATA; 1826 1827 header->destination_port = htons(socket_data->dest_port); 1828 header->source_port = htons(socket->port); 1829 header->sequence_number = htonl(socket_data->next_outgoing); 1830 1831 rc = packet_set_addr(packet, NULL, (uint8_t *) socket_data->addr, 1832 socket_data->addrlen); 1833 if (rc != EOK) 1834 return tcp_release_and_return(packet, EINVAL); 1835 1836 /* Remember the outgoing FIN */ 1837 if (GET_TCP_HEADER_FINALIZE(header)) 1838 socket_data->fin_outgoing = socket_data->next_outgoing; 1839 1840 return EOK; 1841 } 1842 1843 int tcp_queue_packet(socket_core_t *socket, tcp_socket_data_t *socket_data, 1844 packet_t *packet, size_t data_length) 1845 { 1846 int rc; 1847 1848 assert(socket); 1849 assert(socket_data); 1850 assert(socket->specific_data == socket_data); 1851 1852 rc = tcp_queue_prepare_packet(socket, socket_data, packet, data_length); 1853 if (rc != EOK) 1854 return rc; 1855 1856 rc = pq_add(&socket_data->outgoing, packet, socket_data->next_outgoing, 1857 data_length); 1858 if (rc != EOK) 1859 return tcp_release_and_return(packet, rc); 1860 1861 socket_data->next_outgoing += data_length; 1862 return EOK; 1863 } 1864 1865 packet_t *tcp_get_packets_to_send(socket_core_t *socket, tcp_socket_data_t * 1866 socket_data) 1867 { 1868 packet_t *packet; 1869 packet_t *copy; 1870 packet_t *sending = NULL; 1871 packet_t *previous = NULL; 1872 size_t data_length; 1873 int rc; 1874 1875 assert(socket); 1876 assert(socket_data); 1877 assert(socket->specific_data == socket_data); 1878 1879 packet = pq_find(socket_data->outgoing, socket_data->last_outgoing + 1); 1880 while (packet) { 1881 pq_get_order(packet, NULL, &data_length); 1882 1883 /* 1884 * Send only if fits into the window, respecting the possible 1885 * overflow. 1886 */ 1887 if (!IS_IN_INTERVAL_OVERFLOW( 1888 (uint32_t) socket_data->last_outgoing, 1889 (uint32_t) (socket_data->last_outgoing + data_length), 1890 (uint32_t) (socket_data->expected + socket_data->treshold))) 1891 break; 1892 1893 copy = tcp_prepare_copy(socket, socket_data, packet, 1894 data_length, socket_data->last_outgoing + 1); 1895 if (!copy) 1896 return sending; 1897 1898 if (!sending) { 1899 sending = copy; 1900 } else { 1901 rc = pq_insert_after(previous, copy); 1902 if (rc != EOK) { 1903 pq_release_remote(tcp_globals.net_sess, 1904 packet_get_id(copy)); 1905 return sending; 1906 } 1907 } 1908 1909 previous = copy; 1910 packet = pq_next(packet); 1911 1912 /* Overflow occurred? */ 1913 if (!packet && 1914 (socket_data->last_outgoing > socket_data->next_outgoing)) { 1915 printf("gpts overflow\n"); 1916 /* Continue from the beginning */ 1917 packet = socket_data->outgoing; 1918 } 1919 socket_data->last_outgoing += data_length; 1920 } 1921 1922 return sending; 1923 } 1924 1925 packet_t *tcp_send_prepare_packet(socket_core_t *socket, tcp_socket_data_t * 1926 socket_data, packet_t *packet, size_t data_length, size_t sequence_number) 1927 { 1928 tcp_header_t *header; 1929 uint32_t checksum; 1930 int rc; 1931 1932 assert(socket); 1933 assert(socket_data); 1934 assert(socket->specific_data == socket_data); 1935 1936 /* Adjust the pseudo header */ 1937 rc = ip_client_set_pseudo_header_data_length(socket_data->pseudo_header, 1938 socket_data->headerlen, packet_get_data_length(packet)); 1939 if (rc != EOK) { 1940 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1941 return NULL; 1942 } 1943 1944 /* Get the header */ 1945 header = (tcp_header_t *) packet_get_data(packet); 1946 if (!header) { 1947 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1948 return NULL; 1949 } 1950 assert(ntohl(header->sequence_number) == sequence_number); 1951 1952 /* Adjust the header */ 1953 if (socket_data->next_incoming) { 1954 header->acknowledgement_number = 1955 htonl(socket_data->next_incoming); 1956 SET_TCP_HEADER_ACKNOWLEDGE(header, 1); 1957 } 1958 header->window = htons(socket_data->window); 1959 1960 /* Checksum */ 1961 header->checksum = 0; 1962 checksum = compute_checksum(0, socket_data->pseudo_header, 1963 socket_data->headerlen); 1964 checksum = compute_checksum(checksum, 1965 (uint8_t *) packet_get_data(packet), 1966 packet_get_data_length(packet)); 1967 header->checksum = htons(flip_checksum(compact_checksum(checksum))); 1968 1969 /* Prepare the packet */ 1970 rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0); 1971 if (rc != EOK) { 1972 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1973 return NULL; 1974 } 1975 1976 rc = tcp_prepare_timeout(tcp_timeout, socket, socket_data, 1977 sequence_number, socket_data->state, socket_data->timeout, true); 1978 if (rc != EOK) { 1979 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1980 return NULL; 1981 } 1982 1983 return packet; 1984 } 1985 1986 packet_t *tcp_prepare_copy(socket_core_t *socket, tcp_socket_data_t * 1987 socket_data, packet_t *packet, size_t data_length, size_t sequence_number) 1988 { 1989 packet_t *copy; 1990 1991 assert(socket); 1992 assert(socket_data); 1993 assert(socket->specific_data == socket_data); 1994 1995 /* Make a copy of the packet */ 1996 copy = packet_get_copy(tcp_globals.net_sess, packet); 1997 if (!copy) 1998 return NULL; 1999 2000 return tcp_send_prepare_packet(socket, socket_data, copy, data_length, 2001 sequence_number); 2002 } 2003 2004 void tcp_send_packets(nic_device_id_t device_id, packet_t *packet) 2005 { 2006 packet_t *next; 2007 2008 while (packet) { 2009 next = pq_detach(packet); 2010 ip_send_msg(tcp_globals.ip_sess, device_id, packet, 2011 SERVICE_TCP, 0); 2012 packet = next; 2013 } 2014 } 2015 2016 void tcp_prepare_operation_header(socket_core_t *socket, 2017 tcp_socket_data_t *socket_data, tcp_header_t *header, int synchronize, 2018 int finalize) 2019 { 2020 assert(socket); 2021 assert(socket_data); 2022 assert(socket->specific_data == socket_data); 2023 assert(header); 2024 2025 bzero(header, sizeof(*header)); 2026 header->source_port = htons(socket->port); 2027 header->source_port = htons(socket_data->dest_port); 2028 SET_TCP_HEADER_LENGTH(header, 2029 TCP_COMPUTE_HEADER_LENGTH(sizeof(*header))); 2030 SET_TCP_HEADER_SYNCHRONIZE(header, synchronize); 2031 SET_TCP_HEADER_FINALIZE(header, finalize); 2032 } 2033 2034 int tcp_prepare_timeout(int (*timeout_function)(void *tcp_timeout_t), 2035 socket_core_t *socket, tcp_socket_data_t *socket_data, 2036 size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout, 2037 int globals_read_only) 2038 { 2039 tcp_timeout_t *operation_timeout; 2040 fid_t fibril; 2041 2042 assert(socket); 2043 assert(socket_data); 2044 assert(socket->specific_data == socket_data); 2045 2046 /* Prepare the timeout with key bundle structure */ 2047 operation_timeout = malloc(sizeof(*operation_timeout) + 2048 socket->key_length + 1); 2049 if (!operation_timeout) 2050 return ENOMEM; 2051 2052 bzero(operation_timeout, sizeof(*operation_timeout)); 2053 operation_timeout->globals_read_only = globals_read_only; 2054 operation_timeout->port = socket->port; 2055 operation_timeout->local_sockets = socket_data->local_sockets; 2056 operation_timeout->socket_id = socket->socket_id; 2057 operation_timeout->timeout = timeout; 2058 operation_timeout->sequence_number = sequence_number; 2059 operation_timeout->state = state; 2060 2061 /* Copy the key */ 2062 operation_timeout->key = ((uint8_t *) operation_timeout) + 2063 sizeof(*operation_timeout); 2064 operation_timeout->key_length = socket->key_length; 2065 memcpy(operation_timeout->key, socket->key, socket->key_length); 2066 operation_timeout->key[operation_timeout->key_length] = '\0'; 2067 2068 /* Prepare the timeouting thread */ 2069 fibril = fibril_create(timeout_function, operation_timeout); 2070 if (!fibril) { 2071 free(operation_timeout); 2072 return ENOMEM; 2073 } 2074 2075 // fibril_mutex_lock(&socket_data->operation.mutex); 2076 /* Start the timeout fibril */ 2077 fibril_add_ready(fibril); 2078 //socket_data->state = state; 2079 return EOK; 2080 } 2081 2082 int tcp_recvfrom_message(socket_cores_t *local_sockets, int socket_id, 2083 int flags, size_t *addrlen) 2084 { 2085 socket_core_t *socket; 2086 tcp_socket_data_t *socket_data; 2087 int packet_id; 2088 packet_t *packet; 2089 size_t length; 2090 int rc; 2091 2092 assert(local_sockets); 2093 2094 /* Find the socket */ 2095 socket = socket_cores_find(local_sockets, socket_id); 2096 if (!socket) 2097 return ENOTSOCK; 2098 2099 /* Get the socket specific data */ 2100 if (!socket->specific_data) 2101 return NO_DATA; 2102 2103 socket_data = (tcp_socket_data_t *) socket->specific_data; 2104 2105 /* Check state */ 2106 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) && 2107 (socket_data->state != TCP_SOCKET_CLOSE_WAIT)) 2108 return ENOTCONN; 2109 2110 /* Send the source address if desired */ 2111 if (addrlen) { 2112 rc = data_reply(socket_data->addr, socket_data->addrlen); 2113 if (rc != EOK) 2114 return rc; 2115 *addrlen = socket_data->addrlen; 2116 } 2117 2118 /* Get the next received packet */ 2119 packet_id = dyn_fifo_value(&socket->received); 2120 if (packet_id < 0) 2121 return NO_DATA; 2122 2123 rc = packet_translate_remote(tcp_globals.net_sess, &packet, packet_id); 2124 if (rc != EOK) 2125 return rc; 2126 2127 /* Reply the packets */ 2128 rc = socket_reply_packets(packet, &length); 2129 if (rc != EOK) 2130 return rc; 2131 2132 /* Release the packet */ 2133 dyn_fifo_pop(&socket->received); 2134 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 2135 2136 /* Return the total length */ 2137 return (int) length; 2138 } 2139 2140 int tcp_send_message(socket_cores_t *local_sockets, int socket_id, 2141 int fragments, size_t *data_fragment_size, int flags) 2142 { 2143 socket_core_t *socket; 2144 tcp_socket_data_t *socket_data; 2145 packet_dimension_t *packet_dimension; 2146 packet_t *packet; 2147 size_t total_length; 2148 tcp_header_t *header; 2149 int index; 2150 int result; 2151 int rc; 2152 2153 assert(local_sockets); 2154 assert(data_fragment_size); 2155 2156 /* Find the socket */ 2157 socket = socket_cores_find(local_sockets, socket_id); 2158 if (!socket) 2159 return ENOTSOCK; 2160 2161 /* Get the socket specific data */ 2162 if (!socket->specific_data) 2163 return NO_DATA; 2164 2165 socket_data = (tcp_socket_data_t *) socket->specific_data; 2166 2167 /* Check state */ 2168 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) && 2169 (socket_data->state != TCP_SOCKET_CLOSE_WAIT)) 2170 return ENOTCONN; 2171 2172 rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess, 2173 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension); 2174 if (rc != EOK) 2175 return rc; 2176 2177 *data_fragment_size = 2178 ((packet_dimension->content < socket_data->data_fragment_size) ? 2179 packet_dimension->content : socket_data->data_fragment_size); 2180 2181 for (index = 0; index < fragments; index++) { 2182 /* Read the data fragment */ 2183 result = tl_socket_read_packet_data(tcp_globals.net_sess, 2184 &packet, TCP_HEADER_SIZE, packet_dimension, 2185 socket_data->addr, socket_data->addrlen); 2186 if (result < 0) 2187 return result; 2188 2189 total_length = (size_t) result; 2190 2191 /* Prefix the TCP header */ 2192 header = PACKET_PREFIX(packet, tcp_header_t); 2193 if (!header) 2194 return tcp_release_and_return(packet, ENOMEM); 2195 2196 tcp_prepare_operation_header(socket, socket_data, header, 0, 0); 2197 rc = tcp_queue_packet(socket, socket_data, packet, total_length); 2198 if (rc != EOK) 2199 return rc; 2200 } 2201 2202 /* Flush packets */ 2203 packet = tcp_get_packets_to_send(socket, socket_data); 2204 fibril_rwlock_write_unlock(socket_data->local_lock); 2205 fibril_rwlock_read_unlock(&tcp_globals.lock); 2206 2207 if (packet) { 2208 /* Send the packet */ 2209 tcp_send_packets(socket_data->device_id, packet); 2210 } 2211 2212 return EOK; 2213 } 2214 2215 int 2216 tcp_close_message(socket_cores_t *local_sockets, int socket_id) 2217 { 2218 socket_core_t *socket; 2219 tcp_socket_data_t *socket_data; 2220 packet_t *packet; 2221 int rc; 2222 2223 /* Find the socket */ 2224 socket = socket_cores_find(local_sockets, socket_id); 2225 if (!socket) 2226 return ENOTSOCK; 2227 2228 /* Get the socket specific data */ 2229 socket_data = (tcp_socket_data_t *) socket->specific_data; 2230 assert(socket_data); 2231 2232 /* Check state */ 2233 switch (socket_data->state) { 2234 case TCP_SOCKET_ESTABLISHED: 2235 socket_data->state = TCP_SOCKET_FIN_WAIT_1; 2236 break; 2237 2238 case TCP_SOCKET_CLOSE_WAIT: 2239 socket_data->state = TCP_SOCKET_LAST_ACK; 2240 break; 2241 2242 // case TCP_SOCKET_LISTEN: 2243 2244 default: 2245 /* Just destroy */ 2246 rc = socket_destroy(tcp_globals.net_sess, socket_id, 2247 local_sockets, &tcp_globals.sockets, 2248 tcp_free_socket_data); 2249 if (rc == EOK) { 2250 fibril_rwlock_write_unlock(socket_data->local_lock); 2251 fibril_rwlock_write_unlock(&tcp_globals.lock); 2252 } 2253 return rc; 2254 } 2255 2256 /* 2257 * Send FIN. 2258 * TODO should I wait to complete? 2259 */ 2260 2261 /* Create the notification packet */ 2262 rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1); 2263 if (rc != EOK) 2264 return rc; 2265 2266 /* Send the packet */ 2267 rc = tcp_queue_packet(socket, socket_data, packet, 1); 2268 if (rc != EOK) 2269 return rc; 2270 2271 /* Flush packets */ 2272 packet = tcp_get_packets_to_send(socket, socket_data); 2273 fibril_rwlock_write_unlock(socket_data->local_lock); 2274 fibril_rwlock_write_unlock(&tcp_globals.lock); 2275 2276 if (packet) { 2277 /* Send the packet */ 2278 tcp_send_packets(socket_data->device_id, packet); 2279 } 2280 2281 return EOK; 2282 } 2283 2284 int tcp_create_notification_packet(packet_t **packet, socket_core_t *socket, 2285 tcp_socket_data_t *socket_data, int synchronize, int finalize) 2286 { 2287 packet_dimension_t *packet_dimension; 2288 tcp_header_t *header; 2289 int rc; 2290 2291 assert(packet); 2292 2293 /* Get the device packet dimension */ 2294 rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess, 2295 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension); 2296 if (rc != EOK) 2297 return rc; 2298 2299 /* Get a new packet */ 2300 *packet = packet_get_4_remote(tcp_globals.net_sess, TCP_HEADER_SIZE, 2301 packet_dimension->addr_len, packet_dimension->prefix, 2302 packet_dimension->suffix); 2303 2304 if (!*packet) 2305 return ENOMEM; 2306 2307 /* Allocate space in the packet */ 2308 header = PACKET_SUFFIX(*packet, tcp_header_t); 2309 if (!header) 2310 tcp_release_and_return(*packet, ENOMEM); 2311 2312 tcp_prepare_operation_header(socket, socket_data, header, synchronize, 2313 finalize); 2314 2315 return EOK; 2316 } 2317 2318 int tcp_accept_message(socket_cores_t *local_sockets, int socket_id, 2319 int new_socket_id, size_t *data_fragment_size, size_t *addrlen) 2320 { 2321 socket_core_t *accepted; 2322 socket_core_t *socket; 2323 tcp_socket_data_t *socket_data; 2324 packet_dimension_t *packet_dimension; 2325 int rc; 2326 2327 assert(local_sockets); 2328 assert(data_fragment_size); 2329 assert(addrlen); 2330 2331 /* Find the socket */ 2332 socket = socket_cores_find(local_sockets, socket_id); 2333 if (!socket) 2334 return ENOTSOCK; 2335 2336 /* Get the socket specific data */ 2337 socket_data = (tcp_socket_data_t *) socket->specific_data; 2338 assert(socket_data); 2339 2340 /* Check state */ 2341 if (socket_data->state != TCP_SOCKET_LISTEN) 2342 return EINVAL; 2343 2344 do { 2345 socket_id = dyn_fifo_value(&socket->accepted); 2346 if (socket_id < 0) 2347 return ENOTSOCK; 2348 socket_id *= -1; 2349 2350 accepted = socket_cores_find(local_sockets, socket_id); 2351 if (!accepted) 2352 return ENOTSOCK; 2353 2354 /* Get the socket specific data */ 2355 socket_data = (tcp_socket_data_t *) accepted->specific_data; 2356 assert(socket_data); 2357 /* TODO can it be in another state? */ 2358 if (socket_data->state == TCP_SOCKET_ESTABLISHED) { 2359 rc = data_reply(socket_data->addr, 2360 socket_data->addrlen); 2361 if (rc != EOK) 2362 return rc; 2363 rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess, 2364 &tcp_globals.dimensions, socket_data->device_id, 2365 &packet_dimension); 2366 if (rc != EOK) 2367 return rc; 2368 *addrlen = socket_data->addrlen; 2369 2370 *data_fragment_size = 2371 ((packet_dimension->content < 2372 socket_data->data_fragment_size) ? 2373 packet_dimension->content : 2374 socket_data->data_fragment_size); 2375 2376 if (new_socket_id > 0) { 2377 rc = socket_cores_update(local_sockets, 2378 accepted->socket_id, new_socket_id); 2379 if (rc != EOK) 2380 return rc; 2381 accepted->socket_id = new_socket_id; 2382 } 2383 } 2384 dyn_fifo_pop(&socket->accepted); 2385 } while (socket_data->state != TCP_SOCKET_ESTABLISHED); 2386 2387 printf("ret accept %d\n", accepted->socket_id); 2388 return accepted->socket_id; 2389 } 2390 2391 void tcp_free_socket_data(socket_core_t *socket) 2392 { 2393 tcp_socket_data_t *socket_data; 2394 2395 assert(socket); 2396 2397 printf("destroy_socket %d\n", socket->socket_id); 2398 2399 /* Get the socket specific data */ 2400 socket_data = (tcp_socket_data_t *) socket->specific_data; 2401 assert(socket_data); 2402 2403 /* Free the pseudo header */ 2404 if (socket_data->pseudo_header) { 2405 if (socket_data->headerlen) { 2406 printf("d pseudo\n"); 2407 free(socket_data->pseudo_header); 2408 socket_data->headerlen = 0; 2409 } 2410 socket_data->pseudo_header = NULL; 2411 } 2412 2413 socket_data->headerlen = 0; 2414 2415 /* Free the address */ 2416 if (socket_data->addr) { 2417 if (socket_data->addrlen) { 2418 printf("d addr\n"); 2419 free(socket_data->addr); 2420 socket_data->addrlen = 0; 2421 } 2422 socket_data->addr = NULL; 2423 } 2424 socket_data->addrlen = 0; 2425 } 2426 2427 /** Releases the packet and returns the result. 2428 * 2429 * @param[in] packet The packet queue to be released. 2430 * @param[in] result The result to be returned. 2431 * @return The result parameter. 2432 */ 2433 int tcp_release_and_return(packet_t *packet, int result) 2434 { 2435 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 2436 return result; 2437 } 2438 2439 /** Process IPC messages from the IP module 2440 * 2441 * @param[in] iid Message identifier. 2442 * @param[in,out] icall Message parameters. 2443 * @param[in] arg Local argument. 2444 * 2445 */ 2446 static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg) 2447 { 2448 packet_t *packet; 2449 int rc; 2450 232 log_msg(LVL_DEBUG, "tcp_receiver()"); 233 2451 234 while (true) { 2452 235 switch (IPC_GET_IMETHOD(*icall)) { 2453 236 case NET_TL_RECEIVED: 2454 rc = packet_translate_remote(tcp_globals.net_sess, &packet, 237 log_msg(LVL_DEBUG, "method = NET_TL_RECEIVED"); 238 rc = packet_translate_remote(net_sess, &packet, 2455 239 IPC_GET_PACKET(*icall)); 2456 if (rc == EOK) 2457 rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet, 2458 SERVICE_TCP, IPC_GET_ERROR(*icall)); 2459 2460 async_answer_0(iid, (sysarg_t) rc); 240 if (rc != EOK) { 241 log_msg(LVL_DEBUG, "Error %d translating packet.", rc); 242 async_answer_0(iid, (sysarg_t)rc); 243 break; 244 } 245 rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet, 246 IPC_GET_ERROR(*icall)); 247 async_answer_0(iid, (sysarg_t)rc); 2461 248 break; 2462 249 default: 2463 async_answer_0(iid, (sysarg_t) ENOTSUP); 250 log_msg(LVL_DEBUG, "method = %u", 251 (unsigned)IPC_GET_IMETHOD(*icall)); 252 async_answer_0(iid, ENOTSUP); 253 break; 2464 254 } 2465 255 2466 256 iid = async_get_call(icall); 2467 257 } 2468 258 } 2469 259 2470 /** Initialize the TCP module. 2471 * 2472 * @param[in] sess Network module session. 2473 * 2474 * @return EOK on success. 2475 * @return ENOMEM if there is not enough memory left. 2476 * 260 /** Transmit PDU over network layer. */ 261 void tcp_transmit_pdu(tcp_pdu_t *pdu) 262 { 263 struct sockaddr_in dest; 264 nic_device_id_t dev_id; 265 void *phdr; 266 size_t phdr_len; 267 packet_dimension_t *pkt_dim; 268 int rc; 269 packet_t *packet; 270 void *pkt_data; 271 size_t pdu_size; 272 273 dest.sin_family = AF_INET; 274 dest.sin_port = 0; /* not needed */ 275 dest.sin_addr.s_addr = host2uint32_t_be(pdu->dest_addr.ipv4); 276 277 /* Find route. Obtained pseudo-header is not used. */ 278 rc = ip_get_route_req(ip_sess, IPPROTO_TCP, (struct sockaddr *)&dest, 279 sizeof(dest), &dev_id, &phdr, &phdr_len); 280 if (rc != EOK) { 281 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to find route."); 282 return; 283 } 284 285 rc = tl_get_ip_packet_dimension(ip_sess, &pkt_dims, dev_id, &pkt_dim); 286 if (rc != EOK) { 287 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get dimension."); 288 return; 289 } 290 291 pdu_size = pdu->header_size + pdu->text_size; 292 293 packet = packet_get_4_remote(net_sess, pdu_size, pkt_dim->addr_len, 294 pkt_dim->prefix, pkt_dim->suffix); 295 if (!packet) { 296 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get packet."); 297 return; 298 } 299 300 pkt_data = packet_suffix(packet, pdu_size); 301 if (!pkt_data) { 302 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get pkt_data ptr."); 303 pq_release_remote(net_sess, packet_get_id(packet)); 304 return; 305 } 306 307 rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0); 308 if (rc != EOK) { 309 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to prepare IP packet part."); 310 pq_release_remote(net_sess, packet_get_id(packet)); 311 return; 312 } 313 314 rc = packet_set_addr(packet, NULL, (uint8_t *)&dest, sizeof(dest)); 315 if (rc != EOK) { 316 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to set packet address."); 317 pq_release_remote(net_sess, packet_get_id(packet)); 318 return; 319 } 320 321 /* Copy PDU data to packet */ 322 memcpy(pkt_data, pdu->header, pdu->header_size); 323 memcpy((uint8_t *)pkt_data + pdu->header_size, pdu->text, 324 pdu->text_size); 325 326 /* Transmit packet. XXX Transfers packet ownership to IP? */ 327 ip_send_msg(ip_sess, dev_id, packet, SERVICE_TCP, 0); 328 } 329 330 /** Process received PDU. */ 331 static void tcp_received_pdu(tcp_pdu_t *pdu) 332 { 333 tcp_segment_t *dseg; 334 tcp_sockpair_t rident; 335 336 log_msg(LVL_DEBUG, "tcp_received_pdu()"); 337 338 if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) { 339 log_msg(LVL_WARN, "Not enough memory. PDU dropped."); 340 return; 341 } 342 343 /* Insert decoded segment into rqueue */ 344 tcp_rqueue_insert_seg(&rident, dseg); 345 } 346 347 /* Called from libnet */ 348 void tl_connection(void) 349 { 350 log_msg(LVL_DEBUG, "tl_connection()"); 351 } 352 353 /* Called from libnet */ 354 int tl_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 355 size_t *answer_count) 356 { 357 async_sess_t *callback; 358 359 log_msg(LVL_DEBUG, "tl_message()"); 360 361 *answer_count = 0; 362 callback = async_callback_receive_start(EXCHANGE_SERIALIZE, call); 363 if (callback) 364 return tcp_sock_connection(callback, callid, *call); 365 366 return ENOTSUP; 367 } 368 369 /* Called from libnet */ 370 int tl_initialize(async_sess_t *sess) 371 { 372 int rc; 373 374 net_sess = sess; 375 icmp_sess = icmp_connect_module(); 376 377 log_msg(LVL_DEBUG, "tl_initialize()"); 378 379 tcp_sock_init(); 380 381 ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP, SERVICE_TCP, 382 tcp_receiver); 383 if (ip_sess == NULL) 384 return ENOENT; 385 386 rc = packet_dimensions_initialize(&pkt_dims); 387 if (rc != EOK) 388 return rc; 389 390 return EOK; 391 } 392 393 int main(int argc, char **argv) 394 { 395 int rc; 396 397 printf(NAME ": TCP (Transmission Control Protocol) network module\n"); 398 399 rc = log_init(NAME, LVL_ERROR); 400 if (rc != EOK) { 401 printf(NAME ": Failed to initialize log.\n"); 402 return 1; 403 } 404 405 // printf(NAME ": Accepting connections\n"); 406 // task_retval(0); 407 408 tcp_rqueue_init(); 409 tcp_rqueue_thread_start(); 410 411 tcp_ncsim_init(); 412 tcp_ncsim_thread_start(); 413 414 if (0) tcp_test(); 415 /* 416 async_manager(); 417 */ 418 tl_module_start(SERVICE_TCP); 419 420 /* Not reached */ 421 return 0; 422 } 423 424 /** 425 * @} 2477 426 */ 2478 int tl_initialize(async_sess_t *sess)2479 {2480 fibril_rwlock_initialize(&tcp_globals.lock);2481 fibril_rwlock_write_lock(&tcp_globals.lock);2482 2483 tcp_globals.net_sess = sess;2484 2485 tcp_globals.icmp_sess = icmp_connect_module();2486 tcp_globals.ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP,2487 SERVICE_TCP, tcp_receiver);2488 if (tcp_globals.ip_sess == NULL) {2489 fibril_rwlock_write_unlock(&tcp_globals.lock);2490 return ENOENT;2491 }2492 2493 int rc = socket_ports_initialize(&tcp_globals.sockets);2494 if (rc != EOK)2495 goto out;2496 2497 rc = packet_dimensions_initialize(&tcp_globals.dimensions);2498 if (rc != EOK) {2499 socket_ports_destroy(&tcp_globals.sockets, free);2500 goto out;2501 }2502 2503 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;2504 2505 out:2506 fibril_rwlock_write_unlock(&tcp_globals.lock);2507 return rc;2508 }2509 2510 int main(int argc, char *argv[])2511 {2512 return tl_module_start(SERVICE_TCP);2513 }2514 2515 /** @}2516 */ -
uspace/srv/net/tl/tcp/tcp.h
r4c67e52 r899f1a9 1 1 /* 2 * Copyright (c) 20 08 Lukas Mejdrech2 * Copyright (c) 2011 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 30 30 * @{ 31 31 */ 32 33 /** @file 34 * TCP module. 32 /** @file TCP (Transmission Control Protocol) network module 35 33 */ 36 34 37 #ifndef NET_TCP_H_38 #define NET_TCP_H_35 #ifndef TCP_H 36 #define TCP_H 39 37 40 38 #include <async.h> 41 #include <fibril_synch.h> 42 #include <net/packet.h> 43 #include <net/device.h> 44 #include <socket_core.h> 45 #include <tl_common.h> 39 #include <packet_remote.h> 40 #include "tcp_type.h" 46 41 47 /** Type definition of the TCP global data. 48 * @see tcp_globals 49 */ 50 typedef struct tcp_globals tcp_globals_t; 51 52 /** Type definition of the TCP socket specific data. 53 * @see tcp_socket_data 54 */ 55 typedef struct tcp_socket_data tcp_socket_data_t; 56 57 /** Type definition of the TCP operation data. 58 * @see tcp_operation 59 */ 60 typedef struct tcp_operation tcp_operation_t; 61 62 /** TCP socket state type definition. 63 * @see tcp_socket_state 64 */ 65 typedef enum tcp_socket_state tcp_socket_state_t; 66 67 /** TCP socket state. */ 68 enum tcp_socket_state { 69 /** Initial. 70 * 71 * Not connected or bound. 72 */ 73 TCP_SOCKET_INITIAL, 74 75 /** Listening. 76 * 77 * Awaiting a connection request from another TCP layer. 78 * When SYN is received a new bound socket in the 79 * TCP_SOCKET_SYN_RECEIVED state should be created. 80 */ 81 TCP_SOCKET_LISTEN, 82 83 /** Connecting issued. 84 * 85 * A SYN has been sent, and TCP is awaiting the response SYN. 86 * Should continue to the TCP_SOCKET_ESTABLISHED state. 87 */ 88 TCP_SOCKET_SYN_SENT, 89 90 /** Connecting received. 91 * 92 * A SYN has been received, a SYN has been sent, and TCP is awaiting an 93 * ACK. Should continue to the TCP_SOCKET_ESTABLISHED state. 94 */ 95 TCP_SOCKET_SYN_RECEIVED, 96 97 /** Connected. 98 * 99 * The three-way handshake has been completed. 100 */ 101 TCP_SOCKET_ESTABLISHED, 102 103 /** Closing started. 104 * 105 * The local application has issued a CLOSE. 106 * TCP has sent a FIN, and is awaiting an ACK or a FIN. 107 * Should continue to the TCP_SOCKET_FIN_WAIT_2 state when an ACK is 108 * received. 109 * Should continue to the TCP_SOCKET_CLOSING state when a FIN is 110 * received. 111 */ 112 TCP_SOCKET_FIN_WAIT_1, 113 114 /** Closing confirmed. 115 * 116 * A FIN has been sent, and an ACK received. 117 * TCP is awaiting a~FIN from the remote TCP layer. 118 * Should continue to the TCP_SOCKET_CLOSING state. 119 */ 120 TCP_SOCKET_FIN_WAIT_2, 121 122 /** Closing. 123 * 124 * A FIN has been sent, a FIN has been received, and an ACK has been 125 * sent. 126 * TCP is awaiting an ACK for the FIN that was sent. 127 * Should continue to the TCP_SOCKET_TIME_WAIT state. 128 */ 129 TCP_SOCKET_CLOSING, 130 131 /** Closing received. 132 * 133 * TCP has received a FIN, and has sent an ACK. 134 * It is awaiting a close request from the local application before 135 * sending a FIN. 136 * Should continue to the TCP_SOCKET_SOCKET_LAST_ACK state. 137 */ 138 TCP_SOCKET_CLOSE_WAIT, 139 140 /** 141 * A FIN has been received, and an ACK and a FIN have been sent. 142 * TCP is awaiting an ACK. 143 * Should continue to the TCP_SOCKET_TIME_WAIT state. 144 */ 145 TCP_SOCKET_LAST_ACK, 146 147 /** Closing finished. 148 * 149 * FINs have been received and ACK’d, and TCP is waiting two MSLs to 150 * remove the connection from the table. 151 */ 152 TCP_SOCKET_TIME_WAIT, 153 154 /** Closed. 155 * 156 * Imaginary, this indicates that a connection has been removed from 157 * the connection table. 158 */ 159 TCP_SOCKET_CLOSED 160 }; 161 162 /** TCP operation data. */ 163 struct tcp_operation { 164 /** Operation result. */ 165 int result; 166 /** Safety lock. */ 167 fibril_mutex_t mutex; 168 /** Operation result signaling. */ 169 fibril_condvar_t condvar; 170 }; 171 172 /** TCP socket specific data. */ 173 struct tcp_socket_data { 174 /** TCP socket state. */ 175 tcp_socket_state_t state; 176 177 /** 178 * Data fragment size. 179 * Sending optimalization. 180 */ 181 size_t data_fragment_size; 182 183 /** Device identifier. */ 184 nic_device_id_t device_id; 185 186 /** 187 * Listening backlog. 188 * The maximal number of connected but not yet accepted sockets. 189 */ 190 int backlog; 191 192 /** 193 * Parent listening socket identifier. 194 * Set if this socket is an accepted one. 195 */ 196 int listening_socket_id; 197 198 /** Treshold size in bytes. */ 199 size_t treshold; 200 /** Window size in bytes. */ 201 size_t window; 202 /** Acknowledgement timeout. */ 203 suseconds_t timeout; 204 /** Last acknowledged byte. */ 205 uint32_t acknowledged; 206 /** Next incoming sequence number. */ 207 uint32_t next_incoming; 208 /** Incoming FIN. */ 209 uint32_t fin_incoming; 210 /** Next outgoing sequence number. */ 211 uint32_t next_outgoing; 212 /** Last outgoing sequence number. */ 213 uint32_t last_outgoing; 214 /** Outgoing FIN. */ 215 uint32_t fin_outgoing; 216 217 /** 218 * Expected sequence number by the remote host. 219 * The sequence number the other host expects. 220 * The notification is sent only upon a packet reecival. 221 */ 222 uint32_t expected; 223 224 /** 225 * Expected sequence number counter. 226 * Counts the number of received notifications for the same sequence 227 * number. 228 */ 229 int expected_count; 230 231 /** Incoming packet queue. 232 * 233 * Packets are buffered until received in the right order. 234 * The packets are excluded after successfully read. 235 * Packets are sorted by their starting byte. 236 * Packets metric is set as their data length. 237 */ 238 packet_t *incoming; 239 240 /** Outgoing packet queue. 241 * 242 * Packets are buffered until acknowledged by the remote host in the 243 * right order. 244 * The packets are excluded after acknowledged. 245 * Packets are sorted by their starting byte. 246 * Packets metric is set as their data length. 247 */ 248 packet_t *outgoing; 249 250 /** IP pseudo header. */ 251 void *pseudo_header; 252 /** IP pseudo header length. */ 253 size_t headerlen; 254 /** Remote host address. */ 255 struct sockaddr *addr; 256 /** Remote host address length. */ 257 socklen_t addrlen; 258 /** Remote host port. */ 259 uint16_t dest_port; 260 /** Parent local sockets. */ 261 socket_cores_t *local_sockets; 262 263 /** Local sockets safety lock. 264 * 265 * May be locked for writing while holding the global lock for reading 266 * when changing the local sockets only. 267 * The global lock may be locked only before locking the local lock. 268 * The global lock may be locked more weakly than the local lock. 269 * The global lock may be released before releasing the local lock. 270 * @see tcp_globals:lock 271 */ 272 fibril_rwlock_t *local_lock; 273 274 /** Pending operation data. */ 275 tcp_operation_t operation; 276 277 /** 278 * Timeouts in a row counter. 279 * If TCP_MAX_TIMEOUTS is reached, the connection is lost. 280 */ 281 int timeout_count; 282 }; 283 284 /** TCP global data. */ 285 struct tcp_globals { 286 /** Networking module session. */ 287 async_sess_t *net_sess; 288 /** IP module session. */ 289 async_sess_t *ip_sess; 290 /** ICMP module session. */ 291 async_sess_t *icmp_sess; 292 /** Last used free port. */ 293 int last_used_port; 294 /** Active sockets. */ 295 socket_ports_t sockets; 296 /** Device packet dimensions. */ 297 packet_dimensions_t dimensions; 298 299 /** 300 * Safety lock. 301 * Write lock is used only for adding or removing socket ports. 302 */ 303 fibril_rwlock_t lock; 304 }; 42 extern async_sess_t *net_sess; 43 extern async_sess_t *ip_sess; 44 extern void tcp_transmit_pdu(tcp_pdu_t *); 305 45 306 46 #endif
Note:
See TracChangeset
for help on using the changeset viewer.