From 710c7e6cf684f28aed15c024a613a19015f015df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cenk=20G=C3=BCndo=C4=9Fan?= Date: Thu, 31 Jul 2014 17:53:46 +0200 Subject: [PATCH] transport_layer: Splitting UDP and TCP Currently, the tcp and udp implementations are bound to each other in a module called *destiny*. Thus, when using only one of them then the other one gets also compiled into the binary and initialized, which results in unnecessary RAM usage and workload for the CPU. The approach in this PR defines a common module named *socket_base*, which contains functions used by the posix layer. Compiled by it's own, those functions return negative error codes, to symbolize upper layers that they are not supported. When also including the modules *udp* or *tcp* respectively, functions from *socket_base* get overwritten with the correct functionality. Defining *udp* or *tcp* in a Makefile also includes *socket_base*. Defining *pnet* in a Makefile also includes *socket_base*. --- Makefile.dep | 17 +- Makefile.pseudomodules | 1 + examples/rpl_udp/Makefile | 3 +- examples/rpl_udp/main.c | 2 +- examples/rpl_udp/rpl.c | 4 +- examples/rpl_udp/udp.c | 20 +- pkg/libcoap/0001-Add-RIOT-Makefile.patch | 2 +- pkg/oonf_api/0001-add-RIOT-support.patch | 4 +- sys/Makefile | 14 +- sys/Makefile.include | 11 +- sys/auto_init/auto_init.c | 19 +- sys/net/include/{destiny.h => socket_base.h} | 27 +- sys/net/include/{destiny => socket_base}/in.h | 16 +- .../include/{destiny => socket_base}/socket.h | 40 +- .../include/{destiny => socket_base}/types.h | 12 +- sys/net/include/tcp.h | 40 + sys/net/include/udp.h | 40 + sys/net/network_layer/sixlowpan/lowpan.c | 2 +- .../transport_layer/{destiny => }/Makefile | 0 sys/net/transport_layer/destiny/destiny.c | 81 - sys/net/transport_layer/destiny/tcp.c | 412 ---- sys/net/transport_layer/destiny/udp.c | 84 - sys/net/transport_layer/destiny/udp.h | 34 - sys/net/transport_layer/socket_base/Makefile | 1 + .../{destiny => socket_base}/msg_help.c | 12 +- .../{destiny => socket_base}/msg_help.h | 10 +- sys/net/transport_layer/socket_base/socket.c | 436 ++++ .../{destiny => socket_base}/socket.h | 66 +- sys/net/transport_layer/tcp/Makefile | 2 + .../{destiny/socket.c => tcp/tcp.c} | 1848 +++++++++-------- .../transport_layer/{destiny => tcp}/tcp.h | 21 +- .../transport_layer/{destiny => tcp}/tcp_hc.c | 6 +- .../transport_layer/{destiny => tcp}/tcp_hc.h | 2 +- .../{destiny => tcp}/tcp_timer.c | 21 +- .../{destiny => tcp}/tcp_timer.h | 0 sys/net/transport_layer/udp/Makefile | 2 + sys/net/transport_layer/udp/udp.c | 223 ++ sys/net/transport_layer/udp/udp.h | 38 + sys/posix/pnet/include/netinet/in.h | 2 +- sys/posix/pnet/include/sys/socket.h | 6 +- sys/posix/pnet/sys_socket.c | 44 +- 41 files changed, 1954 insertions(+), 1671 deletions(-) rename sys/net/include/{destiny.h => socket_base.h} (65%) rename sys/net/include/{destiny => socket_base}/in.h (95%) rename sys/net/include/{destiny => socket_base}/socket.h (92%) rename sys/net/include/{destiny => socket_base}/types.h (91%) create mode 100644 sys/net/include/tcp.h create mode 100644 sys/net/include/udp.h rename sys/net/transport_layer/{destiny => }/Makefile (100%) delete mode 100644 sys/net/transport_layer/destiny/destiny.c delete mode 100644 sys/net/transport_layer/destiny/tcp.c delete mode 100644 sys/net/transport_layer/destiny/udp.c delete mode 100644 sys/net/transport_layer/destiny/udp.h create mode 100644 sys/net/transport_layer/socket_base/Makefile rename sys/net/transport_layer/{destiny => socket_base}/msg_help.c (72%) rename sys/net/transport_layer/{destiny => socket_base}/msg_help.h (75%) create mode 100644 sys/net/transport_layer/socket_base/socket.c rename sys/net/transport_layer/{destiny => socket_base}/socket.h (51%) create mode 100644 sys/net/transport_layer/tcp/Makefile rename sys/net/transport_layer/{destiny/socket.c => tcp/tcp.c} (64%) rename sys/net/transport_layer/{destiny => tcp}/tcp.h (83%) rename sys/net/transport_layer/{destiny => tcp}/tcp_hc.c (99%) rename sys/net/transport_layer/{destiny => tcp}/tcp_hc.h (96%) rename sys/net/transport_layer/{destiny => tcp}/tcp_timer.c (86%) rename sys/net/transport_layer/{destiny => tcp}/tcp_timer.h (100%) create mode 100644 sys/net/transport_layer/udp/Makefile create mode 100644 sys/net/transport_layer/udp/udp.c create mode 100644 sys/net/transport_layer/udp/udp.h diff --git a/Makefile.dep b/Makefile.dep index c076697928..db9b2d0910 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -4,11 +4,24 @@ endif ifneq (,$(filter pnet,$(USEMODULE))) USEMODULE += posix - USEMODULE += destiny + USEMODULE += socket_base USEMODULE += net_help endif -ifneq (,$(filter destiny,$(USEMODULE))) +ifneq (,$(filter transport_layer,$(USEMODULE))) + USEMODULE += tcp + USEMODULE += udp +endif + +ifneq (,$(filter udp,$(USEMODULE))) + USEMODULE += socket_base +endif + +ifneq (,$(filter tcp,$(USEMODULE))) + USEMODULE += socket_base +endif + +ifneq (,$(filter socket_base,$(USEMODULE))) USEMODULE += sixlowpan USEMODULE += net_help USEMODULE += vtimer diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules index b0414da39d..2f9c7da734 100644 --- a/Makefile.pseudomodules +++ b/Makefile.pseudomodules @@ -1 +1,2 @@ PSEUDOMODULES += defaulttransceiver +PSEUDOMODULES += transport_layer diff --git a/examples/rpl_udp/Makefile b/examples/rpl_udp/Makefile index 700a312014..7a671d719c 100644 --- a/examples/rpl_udp/Makefile +++ b/examples/rpl_udp/Makefile @@ -54,11 +54,10 @@ BOARD_BLACKLIST := arduino-due mbed_lpc1768 msb-430 pttu udoo qemu-i386 stm32f0d USEMODULE += shell USEMODULE += shell_commands -USEMODULE += posix USEMODULE += ps USEMODULE += vtimer USEMODULE += defaulttransceiver USEMODULE += rpl -USEMODULE += destiny +USEMODULE += udp include $(RIOTBASE)/Makefile.include diff --git a/examples/rpl_udp/main.c b/examples/rpl_udp/main.c index 43fea6e422..38f93d9048 100644 --- a/examples/rpl_udp/main.c +++ b/examples/rpl_udp/main.c @@ -25,7 +25,7 @@ #include "shell.h" #include "shell_commands.h" #include "board_uart0.h" -#include "destiny.h" +#include "udp.h" #include "rpl_udp.h" diff --git a/examples/rpl_udp/rpl.c b/examples/rpl_udp/rpl.c index 9e1f6aec8e..40b848bda5 100644 --- a/examples/rpl_udp/rpl.c +++ b/examples/rpl_udp/rpl.c @@ -24,7 +24,7 @@ #include "thread.h" #include "net_if.h" #include "sixlowpan.h" -#include "destiny.h" +#include "udp.h" #include "rpl.h" #include "rpl/rpl_dodag.h" #include "rpl_udp.h" @@ -122,7 +122,7 @@ void rpl_udp_init(int argc, char **argv) msg_send_receive(&m, &m, transceiver_pid); printf("Channel set to %u\n", RADIO_CHANNEL); - puts("Destiny initialized"); + puts("Transport Layer initialized"); /* start transceiver watchdog */ } diff --git a/examples/rpl_udp/udp.c b/examples/rpl_udp/udp.c index 3332d17caa..f493fd3e4b 100644 --- a/examples/rpl_udp/udp.c +++ b/examples/rpl_udp/udp.c @@ -26,7 +26,7 @@ #include "thread.h" -#include "destiny/socket.h" +#include "socket_base/socket.h" #include "net_help.h" @@ -63,7 +63,7 @@ static void *init_udp_server(void *arg) char buffer_main[UDP_BUFFER_SIZE]; int32_t recsize; uint32_t fromlen; - int sock = destiny_socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); + int sock = socket_base_socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); memset(&sa, 0, sizeof(sa)); @@ -72,14 +72,14 @@ static void *init_udp_server(void *arg) fromlen = sizeof(sa); - if (-1 == destiny_socket_bind(sock, &sa, sizeof(sa))) { + if (-1 == socket_base_bind(sock, &sa, sizeof(sa))) { printf("Error bind failed!\n"); - destiny_socket_close(sock); + socket_base_close(sock); + return NULL; } while (1) { - recsize = destiny_socket_recvfrom(sock, (void *)buffer_main, UDP_BUFFER_SIZE, 0, - &sa, &fromlen); + recsize = socket_base_recvfrom(sock, (void *)buffer_main, UDP_BUFFER_SIZE, 0, &sa, &fromlen); if (recsize < 0) { printf("ERROR: recsize < 0!\n"); @@ -88,7 +88,7 @@ static void *init_udp_server(void *arg) printf("UDP packet received, payload: %s\n", buffer_main); } - destiny_socket_close(sock); + socket_base_close(sock); return NULL; } @@ -113,7 +113,7 @@ void udp_send(int argc, char **argv) strncpy(text, argv[2], sizeof(text)); text[sizeof(text) - 1] = 0; - sock = destiny_socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); + sock = socket_base_socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (-1 == sock) { printf("Error Creating Socket!"); @@ -133,7 +133,7 @@ void udp_send(int argc, char **argv) memcpy(&sa.sin6_addr, &ipaddr, 16); sa.sin6_port = HTONS(SERVER_PORT); - bytes_sent = destiny_socket_sendto(sock, (char *)text, + bytes_sent = socket_base_sendto(sock, (char *)text, strlen(text) + 1, 0, &sa, sizeof(sa)); @@ -146,5 +146,5 @@ void udp_send(int argc, char **argv) &ipaddr)); } - destiny_socket_close(sock); + socket_base_close(sock); } diff --git a/pkg/libcoap/0001-Add-RIOT-Makefile.patch b/pkg/libcoap/0001-Add-RIOT-Makefile.patch index 2a32d4f1c3..4a07e32afe 100644 --- a/pkg/libcoap/0001-Add-RIOT-Makefile.patch +++ b/pkg/libcoap/0001-Add-RIOT-Makefile.patch @@ -15,7 +15,7 @@ index 0000000..f90baa1 +++ b/Makefile @@ -0,0 +1,5 @@ +MODULE:=$(shell basename $(CURDIR)) -+INCLUDES += -I$(RIOTBASE) -I$(RIOTBASE)/sys/include -I$(RIOTBASE)/core/include -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/drivers/cc110x_ng/include -I$(RIOTBASE)/cpu/arm_common/include -I$(RIOTBASE)/sys/net/destiny/include -I$(RIOTBASE)/sys/net/sixlowpan/include/ -I$(RIOTBASE)/sys/net/ieee802154/include -I$(RIOTBASE)/sys/net/net_help -I$(RIOTBASE)/sys/posix/include -I$(RIOTBASE)/sys/posix/pnet/include ++INCLUDES += -I$(RIOTBASE) -I$(RIOTBASE)/sys/include -I$(RIOTBASE)/core/include -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/drivers/cc110x_ng/include -I$(RIOTBASE)/cpu/arm_common/include -I$(RIOTBASE)/sys/net/transport_layer/include -I$(RIOTBASE)/sys/net/sixlowpan/include/ -I$(RIOTBASE)/sys/net/ieee802154/include -I$(RIOTBASE)/sys/net/net_help -I$(RIOTBASE)/sys/posix/include -I$(RIOTBASE)/sys/posix/pnet/include +CFLAGS += -DWITH_POSIX + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/oonf_api/0001-add-RIOT-support.patch b/pkg/oonf_api/0001-add-RIOT-support.patch index 7a297c9e8a..adf0943b6c 100644 --- a/pkg/oonf_api/0001-add-RIOT-support.patch +++ b/pkg/oonf_api/0001-add-RIOT-support.patch @@ -359,7 +359,7 @@ index 78fd5b4..cfba7a9 100644 #endif +#ifdef RIOT -+#include "destiny/socket.h" ++#include "transport_layer/socket.h" +#define INET_ADDRSTRLEN (16) +#define INET6_ADDRSTRLEN (48) +#endif @@ -466,7 +466,7 @@ index 4b3e04d..6b52f72 100644 #include #include +#ifdef RIOT -+#include "destiny/socket.h" ++#include "transport_layer/socket.h" +#include "inet_ntop.h" +#else #include diff --git a/sys/Makefile b/sys/Makefile index 56549c73b7..ee4a219984 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -46,8 +46,18 @@ endif ifneq (,$(filter net_if,$(USEMODULE))) DIRS += net/link_layer/net_if endif -ifneq (,$(filter destiny,$(USEMODULE))) - DIRS += net/transport_layer/destiny +ifneq (,$(filter transport_layer,$(USEMODULE))) + USEMODULE += udp + USEMODULE += tcp +endif +ifneq (,$(filter socket_base,$(USEMODULE))) + DIRS += net/transport_layer/socket_base +endif +ifneq (,$(filter udp,$(USEMODULE))) + DIRS += net/transport_layer/udp +endif +ifneq (,$(filter tcp,$(USEMODULE))) + DIRS += net/transport_layer/tcp endif ifneq (,$(filter net_help,$(USEMODULE))) DIRS += net/crosslayer/net_help diff --git a/sys/Makefile.include b/sys/Makefile.include index 2073b310a7..171a53d537 100644 --- a/sys/Makefile.include +++ b/sys/Makefile.include @@ -1,4 +1,13 @@ -ifneq (,$(filter destiny,$(USEMODULE))) +ifneq (,$(filter transport_layer,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include +endif +ifneq (,$(filter socket_base,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include +endif +ifneq (,$(filter tcp,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include +endif +ifneq (,$(filter udp,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include endif ifneq (,$(filter net_help,$(USEMODULE))) diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 00631a1ca1..df6ad1340a 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -55,8 +55,12 @@ #include "sixlowpan.h" #endif -#ifdef MODULE_DESTINY -#include "destiny.h" +#ifdef MODULE_UDP +#include "udp.h" +#endif + +#ifdef MODULE_TCP +#include "tcp.h" #endif #ifdef MODULE_NET_IF @@ -180,8 +184,13 @@ void auto_init(void) extern void profiling_init(void); profiling_init(); #endif -#ifdef MODULE_DESTINY - DEBUG("Auto init transport layer [destiny] module.\n"); - destiny_init_transport_layer(); +#ifdef MODULE_UDP + DEBUG("Auto init transport layer module: [udp].\n"); + udp_init_transport_layer(); +#endif + +#ifdef MODULE_TCP + DEBUG("Auto init transport layer module: [tcp].\n"); + tcp_init_transport_layer(); #endif } diff --git a/sys/net/include/destiny.h b/sys/net/include/socket_base.h similarity index 65% rename from sys/net/include/destiny.h rename to sys/net/include/socket_base.h index 1d0aa9c524..6ca0d5ef7c 100644 --- a/sys/net/include/destiny.h +++ b/sys/net/include/socket_base.h @@ -1,5 +1,5 @@ /** - * destiny.h - Wraps all API types, constants and functions of the transport + * socket_base.h - Wraps all API types, constants and functions of the transport * layer implementation. * * Copyright (C) 2013 INRIA. @@ -10,9 +10,9 @@ */ /** - * @defgroup destiny DESTiny - Transport layer implementation + * @defgroup socket_base Transport layer implementation * @ingroup net - * @brief DESTiny module implements the transport layer. This includes + * @brief This module implements the transport layer. This includes * 6LoWPAN UDP header compression and (experimental) 6LoWPAN TCP header * compression. * @see @@ -25,23 +25,16 @@ * * @{ * @file - * @brief destiny functions + * @brief transport_layer functions * @author Oliver Gesch * @author Martin Lenders */ -#ifndef DESTINY_H -#define DESTINY_H +#ifndef SOCKET_BASE_H +#define SOCKET_BASE_H -#include "destiny/in.h" -#include "destiny/socket.h" -#include "destiny/types.h" +#include "socket_base/in.h" +#include "socket_base/socket.h" +#include "socket_base/types.h" -/** - * Initializes transport layer. - * - * @return 0 on success, other else. - */ -int destiny_init_transport_layer(void); - -#endif /* DESTINY_H */ +#endif /* SOCKET_BASE_H */ diff --git a/sys/net/include/destiny/in.h b/sys/net/include/socket_base/in.h similarity index 95% rename from sys/net/include/destiny/in.h rename to sys/net/include/socket_base/in.h index 6e42f932f7..a819a5ab76 100644 --- a/sys/net/include/destiny/in.h +++ b/sys/net/include/socket_base/in.h @@ -1,5 +1,13 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + /** - * destiny/in.h - Constants defined by the internet system, per RFC 790, + * socket_base/in.h - Constants defined by the internet system, per RFC 790, * September 1981, and numerous additions, inspired by * netinet/in.h definitions. * @{ @@ -18,8 +26,8 @@ * @author Martin Lenders */ -#ifndef DESTINY_IN_H -#define DESTINY_IN_H +#ifndef SOCKET_BASE_IN_H +#define SOCKET_BASE_IN_H /* * Protocols (RFC 1700) TODO: may be deleted due to some double definition @@ -141,4 +149,4 @@ #define IN_LOOPBACKNET (127) ///< official! -#endif /* DESTINY_IN_H */ +#endif /* SOCKET_BASE_IN_H */ diff --git a/sys/net/include/destiny/socket.h b/sys/net/include/socket_base/socket.h similarity index 92% rename from sys/net/include/destiny/socket.h rename to sys/net/include/socket_base/socket.h index 9706d38080..f67df8cf3c 100644 --- a/sys/net/include/destiny/socket.h +++ b/sys/net/include/socket_base/socket.h @@ -1,5 +1,5 @@ /** - * destiny/socket.h - Destiny socket API + * socket_base/socket.h - Transport Layer socket API * * Copyright (C) 2013 INRIA. * @@ -7,7 +7,7 @@ * General Public License v2.1. See the file LICENSE in the top level * directory for more details. * - * @ingroup destiny + * @ingroup socket_base * @{ * @file * @brief Header for BSD socket API @@ -19,14 +19,14 @@ */ -#ifndef DESTINY_SOCKET_H -#define DESTINY_SOCKET_H +#ifndef SOCKET_BASE_SOCKET_H +#define SOCKET_BASE_SOCKET_H #include #include "ipv6.h" -#include "destiny/in.h" +#include "socket_base/in.h" typedef uint8_t sa_family_t; ///< POSIX compatible type for address family. typedef uint32_t socklen_t; ///< POSIX compatible type for address length. @@ -159,17 +159,17 @@ typedef uint32_t socklen_t; ///< POSIX compatible type for address length. #define PF_MAX AF_MAX ///< maximum of protocol families ///< @see AF_MAX -#define DESTINY_SOCKET_STATIC_MSS 48 ///< Static TCP maxmimum segment size. +#define TRANSPORT_LAYER_SOCKET_STATIC_MSS 48 ///< Static TCP maxmimum segment size. /** * Static TCP flow control window for window size 1. */ -#define DESTINY_SOCKET_STATIC_WINDOW 1 * DESTINY_SOCKET_STATIC_MSS +#define TRANSPORT_LAYER_SOCKET_STATIC_WINDOW 1 * TRANSPORT_LAYER_SOCKET_STATIC_MSS /** * Maximum size of TCP buffer. */ -#define DESTINY_SOCKET_MAX_TCP_BUFFER 1 * DESTINY_SOCKET_STATIC_WINDOW +#define TRANSPORT_LAYER_SOCKET_MAX_TCP_BUFFER 1 * TRANSPORT_LAYER_SOCKET_STATIC_WINDOW /** * Socket address type for IPv6 communication. @@ -194,7 +194,7 @@ typedef struct __attribute__((packed)) { * imply IPPROTO_TCP, etc.) * @return Socket ID on success, -1 otherwise. */ -int destiny_socket(int domain, int type, int protocol); +int socket_base_socket(int domain, int type, int protocol); /** * Connects socket *socket* with a foreign host with IPv6 address *addr* @@ -208,7 +208,7 @@ int destiny_socket(int domain, int type, int protocol); * * @return 0 on success, -1 otherwise */ -int destiny_socket_connect(int socket, sockaddr6_t *addr, +int socket_base_connect(int socket, sockaddr6_t *addr, socklen_t addrlen); /** @@ -223,7 +223,7 @@ int destiny_socket_connect(int socket, sockaddr6_t *addr, * * @return Number of received bytes, -1 on error. */ -int32_t destiny_socket_recv(int s, void *buf, uint32_t len, int flags); +int32_t socket_base_recv(int s, void *buf, uint32_t len, int flags); /** * Receives data through socket *s* and saves it in buffer *buf*. The address @@ -240,7 +240,7 @@ int32_t destiny_socket_recv(int s, void *buf, uint32_t len, int flags); * * @return Number of received bytes, -1 on error. */ -int32_t destiny_socket_recvfrom(int s, void *buf, uint32_t len, int flags, +int32_t socket_base_recvfrom(int s, void *buf, uint32_t len, int flags, sockaddr6_t *from, socklen_t *fromlen); /** @@ -255,7 +255,7 @@ int32_t destiny_socket_recvfrom(int s, void *buf, uint32_t len, int flags, * * @return Number of send bytes, -1 on error. */ -int32_t destiny_socket_send(int s, const void *buf, uint32_t len, int flags); +int32_t socket_base_send(int s, const void *buf, uint32_t len, int flags); /** * Sends data *buf* through socket *s* to foreign host with IPv6 address *addr*. @@ -271,7 +271,7 @@ int32_t destiny_socket_send(int s, const void *buf, uint32_t len, int flags); * * @return Number of send bytes, -1 on error. */ -int32_t destiny_socket_sendto(int s, const void *buf, uint32_t len, int flags, +int32_t socket_base_sendto(int s, const void *buf, uint32_t len, int flags, sockaddr6_t *to, socklen_t tolen); /** @@ -281,7 +281,7 @@ int32_t destiny_socket_sendto(int s, const void *buf, uint32_t len, int flags, * * @return 0 on success, -1 otherwise. */ -int destiny_socket_close(int s); +int socket_base_close(int s); /** * Assigns an IPv6 address *addr* to the socket *s*. Roughly identical to @@ -293,7 +293,7 @@ int destiny_socket_close(int s); * * @return 0 on success, -1 otherwise. */ -int destiny_socket_bind(int s, sockaddr6_t *addr, int addrlen); +int socket_base_bind(int s, sockaddr6_t *addr, int addrlen); /** * Marks socket *s* as an passive socket, that listens for incoming messages. @@ -304,7 +304,7 @@ int destiny_socket_bind(int s, sockaddr6_t *addr, int addrlen); * * @return 0 on success, -1 otherwise. */ -int destiny_socket_listen(int s, int backlog); +int socket_base_listen(int s, int backlog); /** * Blocks the current thread and waits for incoming communication on the listening @@ -318,16 +318,16 @@ int destiny_socket_listen(int s, int backlog); * * @return New socket ID for communication. -1 on error. */ -int destiny_socket_accept(int s, sockaddr6_t *addr, socklen_t *addrlen); +int socket_base_accept(int s, sockaddr6_t *addr, socklen_t *addrlen); /** * Outputs a list of all open sockets to stdout. Information includes its * creation parameters, local and foreign address and ports, it's ID and the * PIDs of the send and receive thread. */ -void destiny_socket_print_sockets(void); +void socket_base_print_sockets(void); /** * @} */ -#endif /* DESTINY_SOCKET_H */ +#endif /* SOCKET_BASE_SOCKET_H */ diff --git a/sys/net/include/destiny/types.h b/sys/net/include/socket_base/types.h similarity index 91% rename from sys/net/include/destiny/types.h rename to sys/net/include/socket_base/types.h index 7db002d848..6c45603aa1 100644 --- a/sys/net/include/destiny/types.h +++ b/sys/net/include/socket_base/types.h @@ -1,5 +1,5 @@ /** - * Destiny types header + * Transport Layer types header * * Copyright (C) 2013 INRIA. * @@ -7,15 +7,15 @@ * General Public License v2.1. See the file LICENSE in the top level * directory for more details. * - * @ingroup destiny + * @ingroup transport_layer * @{ * @file - * @brief Destiny types + * @brief Transport Layer types * @author Oliver Gesch * @author Martin Lenders */ -#ifndef DESTINY_TYPES_H_ -#define DESTINY_TYPES_H_ +#ifndef SOCKET_BASE_TYPES_H_ +#define SOCKET_BASE_TYPES_H_ #include /** @@ -73,4 +73,4 @@ typedef struct __attribute__((packed)) { * @} */ -#endif /* DESTINY_TYPES_H_ */ +#endif /* SOCKET_BASE_TYPES_H_ */ diff --git a/sys/net/include/tcp.h b/sys/net/include/tcp.h new file mode 100644 index 0000000000..6f9f9f7650 --- /dev/null +++ b/sys/net/include/tcp.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2013, 2014 INRIA. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup tcp TCP implementation + * @ingroup net + * @brief This module implements the TCP transport layer protocol. + * This includes an (experimental) 6LoWPAN TCP header ompression. + * @see + * RFC draft-aayadi-6lowpan-tcphc-01 - TCP header compression for + * 6LoWPAN + * + * @{ + * @file + * @brief tcp functions + * @author Oliver Gesch + * @author Martin Lenders + * @author Cenk Gündoğan + */ + +#ifndef TCP_H +#define TCP_H + +#include "socket_base/in.h" +#include "socket_base/socket.h" +#include "socket_base/types.h" + +/** + * Initializes tcp. + * + * @return 0 on success, other else. + */ +int tcp_init_transport_layer(void); + +#endif /* TCP_H */ diff --git a/sys/net/include/udp.h b/sys/net/include/udp.h new file mode 100644 index 0000000000..7268394050 --- /dev/null +++ b/sys/net/include/udp.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2013, 2014 INRIA. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup tcp UDP implementation + * @ingroup net + * @brief This module implements the transport layer protocol UDP. + * This includes 6LoWPAN UDP header compression. + * @see + * RFC 6282 - Compression Format for IPv6 Datagrams over + * IEEE 802.15.4-Based Networks - UDP Header Compression + * + * @{ + * @file + * @brief udp functions + * @author Oliver Gesch + * @author Martin Lenders + * @author Cenk Gündoğan + */ + +#ifndef UDP_H +#define UDP_H + +#include "socket_base/in.h" +#include "socket_base/socket.h" +#include "socket_base/types.h" + +/** + * Initializes udp. + * + * @return 0 on success, other else. + */ +int udp_init_transport_layer(void); + +#endif /* UDP_H */ diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index 8fd7bf74bd..faf835532c 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -43,7 +43,7 @@ #include "icmp.h" #include "ieee802154_frame.h" -#include "destiny/in.h" +#include "socket_base/in.h" #include "net_help.h" #define ENABLE_DEBUG (0) diff --git a/sys/net/transport_layer/destiny/Makefile b/sys/net/transport_layer/Makefile similarity index 100% rename from sys/net/transport_layer/destiny/Makefile rename to sys/net/transport_layer/Makefile diff --git a/sys/net/transport_layer/destiny/destiny.c b/sys/net/transport_layer/destiny/destiny.c deleted file mode 100644 index 847aa1ea6f..0000000000 --- a/sys/net/transport_layer/destiny/destiny.c +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Destiny transport layer implementation - * - * Copyright (C) 2013 INRIA. - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * @ingroup destiny - * @{ - * @file destiny.c - * @brief transpor layer functions - * @author Oliver Gesch - * @} - */ - -#include -#include -#include - -#include "thread.h" - -#include "destiny.h" -#include "vtimer.h" - -#include "socket.h" -#include "tcp.h" -#include "tcp_timer.h" -#include "udp.h" - -char tcp_stack_buffer[TCP_STACK_SIZE]; -char udp_stack_buffer[UDP_STACK_SIZE]; - -char tcp_timer_stack[TCP_TIMER_STACKSIZE]; - -int destiny_init_transport_layer(void) -{ - printf("Initializing transport layer packages. Size of socket_type: %u\n", - (unsigned int) sizeof(socket_internal_t)); - /* SOCKETS */ - memset(sockets, 0, MAX_SOCKETS * sizeof(socket_internal_t)); - - /* UDP */ - kernel_pid_t udp_thread_pid = thread_create(udp_stack_buffer, UDP_STACK_SIZE, - PRIORITY_MAIN, CREATE_STACKTEST, - udp_packet_handler, NULL, "udp_packet_handler"); - - if (udp_thread_pid == KERNEL_PID_UNDEF) { - return -1; - } - - ipv6_register_next_header_handler(IPV6_PROTO_NUM_UDP, udp_thread_pid); - - /* TCP */ - timex_t now; - vtimer_now(&now); - srand(timex_uint64(now)); -#ifdef TCP_HC - printf("TCP_HC enabled!\n"); - global_context_counter = rand(); -#endif - global_sequence_counter = rand(); - - kernel_pid_t tcp_thread_pid = thread_create(tcp_stack_buffer, TCP_STACK_SIZE, - PRIORITY_MAIN, CREATE_STACKTEST, - tcp_packet_handler, NULL, "tcp_packet_handler"); - - if (tcp_thread_pid == KERNEL_PID_UNDEF) { - return -1; - } - - ipv6_register_next_header_handler(IPV6_PROTO_NUM_TCP, tcp_thread_pid); - - if (thread_create(tcp_timer_stack, TCP_TIMER_STACKSIZE, PRIORITY_MAIN + 1, - CREATE_STACKTEST, tcp_general_timer, NULL, "tcp_general_timer") < 0) { - return -1; - } - - return 0; -} diff --git a/sys/net/transport_layer/destiny/tcp.c b/sys/net/transport_layer/destiny/tcp.c deleted file mode 100644 index e28ba3edbe..0000000000 --- a/sys/net/transport_layer/destiny/tcp.c +++ /dev/null @@ -1,412 +0,0 @@ -/** - * Destiny TCP implementation - * - * Copyright (C) 2013 INRIA. - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * @ingroup destiny - * @{ - * @file tcp.c - * @brief TCP implementation - * @author Oliver Gesch - * @} - */ - -#include -#include -#include -#include - -#include "sixlowpan.h" -#include "thread.h" -#include "vtimer.h" - -#include "destiny/in.h" - -#include "net_help.h" - -#include "msg_help.h" -#include "socket.h" -#include "tcp_hc.h" -#include "tcp_timer.h" - -#include "tcp.h" - -#ifdef TCP_HC -mutex_t global_context_counter_mutex; -uint8_t global_context_counter; -#endif - -mutex_t global_sequence_counter_mutex; -uint32_t global_sequence_counter; - -void printTCPHeader(tcp_hdr_t *tcp_header) -{ - printf("\nBEGIN: TCP HEADER\n"); - printf("ack_nr: %" PRIu32 "\n", tcp_header->ack_nr); - printf("checksum: %i\n", tcp_header->checksum); - printf("data_offset: %i\n", tcp_header->data_offset); - printf("dst_port: %i\n", tcp_header->dst_port); - printf("reserved_flags: %i\n", tcp_header->reserved_flags); - printf("seq_nr: %" PRIu32 "\n", tcp_header->seq_nr); - printf("src_port: %i\n", tcp_header->src_port); - printf("urg_pointer: %i\n", tcp_header->urg_pointer); - printf("window: %i\n", tcp_header->window); - printf("END: TCP HEADER\n"); -} - -void printArrayRange_tcp(uint8_t *udp_header, uint16_t len) -{ - int i = 0; - printf("-------------MEMORY-------------\n"); - - for (i = 0; i < len; i++) { - printf("%#x ", *(udp_header + i)); - } - - printf("-------------MEMORY-------------\n"); -} - -uint16_t tcp_csum(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header) -{ - uint16_t sum; - uint16_t len = NTOHS(ipv6_header->length); - - sum = len + IPPROTO_TCP; - sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t)); - sum = csum(sum, (uint8_t *)tcp_header, len); - return (sum == 0) ? 0xffff : HTONS(sum); -} - -uint8_t handle_payload(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, - socket_internal_t *tcp_socket, uint8_t *payload) -{ - (void) tcp_header; - - msg_t m_send_tcp, m_recv_tcp; - uint8_t tcp_payload_len = NTOHS(ipv6_header->length) - TCP_HDR_LEN; - uint8_t acknowledged_bytes = 0; - - if (tcp_payload_len > tcp_socket->socket_values.tcp_control.rcv_wnd) { - mutex_lock(&tcp_socket->tcp_buffer_mutex); - memcpy(tcp_socket->tcp_input_buffer, payload, - tcp_socket->socket_values.tcp_control.rcv_wnd); - acknowledged_bytes = tcp_socket->socket_values.tcp_control.rcv_wnd; - tcp_socket->socket_values.tcp_control.rcv_wnd = 0; - tcp_socket->tcp_input_buffer_end = tcp_socket->tcp_input_buffer_end + - tcp_socket->socket_values.tcp_control.rcv_wnd; - mutex_unlock(&tcp_socket->tcp_buffer_mutex); - } - else { - mutex_lock(&tcp_socket->tcp_buffer_mutex); - memcpy(tcp_socket->tcp_input_buffer, payload, tcp_payload_len); - tcp_socket->socket_values.tcp_control.rcv_wnd = - tcp_socket->socket_values.tcp_control.rcv_wnd - tcp_payload_len; - acknowledged_bytes = tcp_payload_len; - tcp_socket->tcp_input_buffer_end = tcp_socket->tcp_input_buffer_end + - tcp_payload_len; - mutex_unlock(&tcp_socket->tcp_buffer_mutex); - } - - if (thread_getstatus(tcp_socket->recv_pid) == STATUS_RECEIVE_BLOCKED) { - net_msg_send_recv(&m_send_tcp, &m_recv_tcp, tcp_socket->recv_pid, UNDEFINED); - } - - return acknowledged_bytes; -} - -void handle_tcp_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, - socket_internal_t *tcp_socket) -{ - msg_t m_recv_tcp, m_send_tcp; - kernel_pid_t target_pid = KERNEL_PID_UNDEF; - - if (tcp_socket->socket_values.tcp_control.state == TCP_LAST_ACK) { - target_pid = tcp_socket->recv_pid; - close_socket(tcp_socket); - msg_send(&m_send_tcp, target_pid, 0); - return; - } - else if (tcp_socket->socket_values.tcp_control.state == TCP_CLOSING) { - msg_send(&m_send_tcp, tcp_socket->recv_pid, 0); - msg_send(&m_send_tcp, tcp_socket->send_pid, 0); - return; - } - else if (get_waiting_connection_socket(tcp_socket->socket_id, ipv6_header, - tcp_header) != NULL) { - m_send_tcp.content.ptr = (char *)tcp_header; - net_msg_send_recv(&m_send_tcp, &m_recv_tcp, tcp_socket->recv_pid, TCP_ACK); - return; - } - else if (tcp_socket->socket_values.tcp_control.state == TCP_ESTABLISHED) { - if (check_tcp_consistency(&tcp_socket->socket_values, tcp_header, 0) == PACKET_OK) { - m_send_tcp.content.ptr = (char *)tcp_header; - net_msg_send(&m_send_tcp, tcp_socket->send_pid, 0, TCP_ACK); - return; - } - } - - printf("NO WAY OF HANDLING THIS ACK!\n"); -} - -void handle_tcp_rst_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, - socket_internal_t *tcp_socket) -{ - (void) ipv6_header; - (void) tcp_header; - (void) tcp_socket; - - /* TODO: Reset connection */ -} - -void handle_tcp_syn_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, - socket_internal_t *tcp_socket) -{ - msg_t m_send_tcp; - - if (tcp_socket->socket_values.tcp_control.state == TCP_LISTEN) { - socket_internal_t *new_socket = new_tcp_queued_socket(ipv6_header, - tcp_header); - - if (new_socket != NULL) { -#ifdef TCP_HC - update_tcp_hc_context(true, new_socket, tcp_header); -#endif - /* notify socket function destiny_socket_accept(..) that a new - * connection request has arrived. No need to wait for an answer - * because the server destiny_socket_accept() function isnt reading - * from anything other than the queued sockets */ - net_msg_send(&m_send_tcp, tcp_socket->recv_pid, 0, TCP_SYN); - } - else { - printf("Dropped TCP SYN Message because an error occured while "\ - "requesting a new queued socket!\n"); - } - } - else { - printf("Dropped TCP SYN Message because socket was not in state TCP_LISTEN!"); - } -} - -void handle_tcp_syn_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, - socket_internal_t *tcp_socket) -{ - (void) ipv6_header; - - msg_t m_send_tcp; - - if (tcp_socket->socket_values.tcp_control.state == TCP_SYN_SENT) { - m_send_tcp.content.ptr = (char *) tcp_header; - net_msg_send(&m_send_tcp, tcp_socket->recv_pid, 0, TCP_SYN_ACK); - } - else { - printf("Socket not in state TCP_SYN_SENT, dropping SYN-ACK-packet!"); - } -} - -void handle_tcp_fin_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, - socket_internal_t *tcp_socket) -{ - (void) ipv6_header; - - msg_t m_send; - socket_t *current_tcp_socket = &tcp_socket->socket_values; - uint8_t send_buffer[BUFFER_SIZE]; - ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); - tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); - - set_tcp_cb(¤t_tcp_socket->tcp_control, tcp_header->seq_nr + 1, - current_tcp_socket->tcp_control.send_wnd, tcp_header->ack_nr + 1, - tcp_header->ack_nr, tcp_header->window); - -#ifdef TCP_HC - current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; -#endif - - if (current_tcp_socket->tcp_control.state == TCP_FIN_WAIT_1) { - current_tcp_socket->tcp_control.state = TCP_CLOSING; - - send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_FIN_ACK, 0); - } - else { - current_tcp_socket->tcp_control.state = TCP_LAST_ACK; - - send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_FIN_ACK, 0); - } - - net_msg_send(&m_send, tcp_socket->recv_pid, 0, CLOSE_CONN); -} - -void handle_tcp_fin_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, - socket_internal_t *tcp_socket) -{ - (void) ipv6_header; - - msg_t m_send; - socket_t *current_tcp_socket = &tcp_socket->socket_values; - uint8_t send_buffer[BUFFER_SIZE]; - ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); - tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); - - current_tcp_socket->tcp_control.state = TCP_CLOSED; - - set_tcp_cb(¤t_tcp_socket->tcp_control, tcp_header->seq_nr + 1, - current_tcp_socket->tcp_control.send_wnd, tcp_header->ack_nr, - tcp_header->ack_nr, tcp_header->window); - -#ifdef TCP_HC - current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; -#endif - - send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_ACK, 0); - - msg_send(&m_send, tcp_socket->send_pid, 0); - msg_send(&m_send, tcp_socket->recv_pid, 0); -} - -void handle_tcp_no_flags_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, - socket_internal_t *tcp_socket, uint8_t *payload, uint8_t tcp_payload_len) -{ - uint8_t read_bytes = 0; - socket_t *current_tcp_socket = &tcp_socket->socket_values; - uint8_t send_buffer[BUFFER_SIZE]; - ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); - tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); - - if (check_tcp_consistency(current_tcp_socket, tcp_header, tcp_payload_len) == PACKET_OK) { - read_bytes = handle_payload(ipv6_header, tcp_header, tcp_socket, payload); - - /* Refresh TCP status values */ - current_tcp_socket->tcp_control.state = TCP_ESTABLISHED; - - set_tcp_cb(¤t_tcp_socket->tcp_control, - tcp_header->seq_nr + read_bytes, - current_tcp_socket->tcp_control.rcv_wnd, - current_tcp_socket->tcp_control.send_nxt, - current_tcp_socket->tcp_control.send_una, - current_tcp_socket->tcp_control.send_wnd); - - /* Send packet */ - // block_continue_thread(); -#ifdef TCP_HC - current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; -#endif - send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_ACK, 0); - } - /* ACK packet probably got lost */ - else { - // block_continue_thread(); -#ifdef TCP_HC - current_tcp_socket->tcp_control.tcp_context.hc_type = FULL_HEADER; -#endif - send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_ACK, 0); - } -} - -void *tcp_packet_handler(void *arg) -{ - (void) arg; - - msg_t m_recv_ip, m_send_ip; - ipv6_hdr_t *ipv6_header; - tcp_hdr_t *tcp_header; - uint8_t *payload; - socket_internal_t *tcp_socket = NULL; - uint16_t chksum; - - while (1) { - msg_receive(&m_recv_ip); - - ipv6_header = ((ipv6_hdr_t *)m_recv_ip.content.ptr); - tcp_header = ((tcp_hdr_t *)(m_recv_ip.content.ptr + IPV6_HDR_LEN)); -#ifdef TCP_HC - tcp_socket = decompress_tcp_packet(ipv6_header); -#else - switch_tcp_packet_byte_order(tcp_header); - tcp_socket = get_tcp_socket(ipv6_header, tcp_header); -#endif - chksum = tcp_csum(ipv6_header, tcp_header); - - payload = (uint8_t *)(m_recv_ip.content.ptr + IPV6_HDR_LEN + tcp_header->data_offset * 4); - - if ((chksum == 0xffff) && (tcp_socket != NULL)) { -#ifdef TCP_HC - update_tcp_hc_context(true, tcp_socket, tcp_header); -#endif - /* Remove reserved bits from tcp flags field */ - uint8_t tcp_flags = tcp_header->reserved_flags; - - switch (tcp_flags) { - case TCP_ACK: { - /* only ACK Bit set */ - uint8_t tcp_payload_len = NTOHS(ipv6_header->length) - TCP_HDR_LEN; - uint8_t state = tcp_socket->socket_values.tcp_control.state; - - if ((tcp_payload_len > 0) && (state == TCP_ESTABLISHED)) { - /* handle data segments only when the connection was established successfully */ - handle_tcp_no_flags_packet(ipv6_header, tcp_header, tcp_socket, payload, tcp_payload_len); - } - else if (tcp_payload_len == 0 - && (state == TCP_ESTABLISHED || state == TCP_SYN_RCVD - || state == TCP_CLOSING || state == TCP_LAST_ACK)) { - /* no payload, acknowledging data only */ - handle_tcp_ack_packet(ipv6_header, tcp_header, tcp_socket); - } - break; - } - - case TCP_RST: { - printf("RST Bit set!\n"); - /* only RST Bit set */ - handle_tcp_rst_packet(ipv6_header, tcp_header, tcp_socket); - break; - } - - case TCP_SYN: { - /* only SYN Bit set, look for matching, listening socket - * and request new queued socket */ - printf("SYN Bit set!\n"); - handle_tcp_syn_packet(ipv6_header, tcp_header, tcp_socket); - break; - } - - case TCP_SYN_ACK: { - /* only SYN and ACK Bit set, complete three way handshake - * when socket in state TCP_SYN_SENT */ - handle_tcp_syn_ack_packet(ipv6_header, tcp_header, tcp_socket); - break; - } - - case TCP_FIN_ACK: { - if (tcp_socket->socket_values.tcp_control.state == TCP_ESTABLISHED) { - /* this is the first FIN */ - printf("FIN ACK Bit set!\n"); - handle_tcp_fin_packet(ipv6_header, tcp_header, tcp_socket); - } - else { - /* this is the response to FIN */ - handle_tcp_fin_ack_packet(ipv6_header, tcp_header, tcp_socket); - } - break; - } - - default: { - printf("Unable to process the incoming segment!\n"); - } - } - } - else { - printf("Wrong checksum (%x) or no corresponding socket found!\n", - chksum); - printArrayRange(((uint8_t *)ipv6_header), IPV6_HDR_LEN + - NTOHS(ipv6_header->length), "Incoming"); - print_tcp_status(INC_PACKET, ipv6_header, tcp_header, - &tcp_socket->socket_values); - } - - msg_reply(&m_recv_ip, &m_send_ip); - } -} diff --git a/sys/net/transport_layer/destiny/udp.c b/sys/net/transport_layer/destiny/udp.c deleted file mode 100644 index a995c9729f..0000000000 --- a/sys/net/transport_layer/destiny/udp.c +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Destiny UDP implementation - * - * Copyright (C) 2013 INRIA. - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * @ingroup destiny - * @{ - * @file udp.c - * @brief UDP implementation - * @author Oliver Gesch - * @} - */ - -#include -#include - -#include "ipv6.h" -#include "msg.h" -#include "sixlowpan.h" -#include "thread.h" - -#include "destiny/in.h" - -#include "net_help.h" - -#include "msg_help.h" -#include "socket.h" - -#include "udp.h" - -msg_t udp_msg_queue[UDP_PKT_RECV_BUF_SIZE]; - -uint16_t udp_csum(ipv6_hdr_t *ipv6_header, udp_hdr_t *udp_header) -{ - uint16_t sum; - uint16_t len = NTOHS(udp_header->length); - - sum = len + IPPROTO_UDP; - sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t)); - sum = csum(sum, (uint8_t *)udp_header, len); - return (sum == 0) ? 0xffff : HTONS(sum); -} - -void *udp_packet_handler(void *arg) -{ - (void) arg; - - msg_t m_recv_ip, m_send_ip, m_recv_udp, m_send_udp; - ipv6_hdr_t *ipv6_header; - udp_hdr_t *udp_header; - socket_internal_t *udp_socket = NULL; - uint16_t chksum; - - msg_init_queue(udp_msg_queue, UDP_PKT_RECV_BUF_SIZE); - - while (1) { - msg_receive(&m_recv_ip); - ipv6_header = ((ipv6_hdr_t *)m_recv_ip.content.ptr); - udp_header = ((udp_hdr_t *)(m_recv_ip.content.ptr + IPV6_HDR_LEN)); - - chksum = ipv6_csum(ipv6_header, (uint8_t*) udp_header, NTOHS(udp_header->length), IPPROTO_UDP); - - if (chksum == 0xffff) { - udp_socket = get_udp_socket(udp_header); - - if (udp_socket != NULL) { - m_send_udp.content.ptr = (char *)ipv6_header; - msg_send_receive(&m_send_udp, &m_recv_udp, udp_socket->recv_pid); - } - else { - printf("Dropped UDP Message because no thread ID was found for delivery!\n"); - } - } - else { - printf("Wrong checksum (%x)!\n", chksum); - } - - msg_reply(&m_recv_ip, &m_send_ip); - } -} diff --git a/sys/net/transport_layer/destiny/udp.h b/sys/net/transport_layer/destiny/udp.h deleted file mode 100644 index 15774e1ae3..0000000000 --- a/sys/net/transport_layer/destiny/udp.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Destiny TCP header - * - * Copyright (C) 2013 INRIA. - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * @ingroup destiny - * @{ - * @file - * @brief UDP data structs and prototypes - * @author Oliver Gesch - */ - - -#ifndef UDP_H_ -#define UDP_H_ - -#include "ipv6.h" -#include "destiny/types.h" - -#define UDP_STACK_SIZE KERNEL_CONF_STACKSIZE_MAIN -#define UDP_PKT_RECV_BUF_SIZE (64) - -uint16_t udp_csum(ipv6_hdr_t *ipv6_header, udp_hdr_t *udp_header); -void *udp_packet_handler(void *); - -/** - * @} - */ - -#endif /* UDP_H_ */ diff --git a/sys/net/transport_layer/socket_base/Makefile b/sys/net/transport_layer/socket_base/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/sys/net/transport_layer/socket_base/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/transport_layer/destiny/msg_help.c b/sys/net/transport_layer/socket_base/msg_help.c similarity index 72% rename from sys/net/transport_layer/destiny/msg_help.c rename to sys/net/transport_layer/socket_base/msg_help.c index a0fd418497..1dbe1e4ed3 100644 --- a/sys/net/transport_layer/destiny/msg_help.c +++ b/sys/net/transport_layer/socket_base/msg_help.c @@ -17,11 +17,9 @@ #include "thread.h" -#include "tcp_timer.h" - #include "msg_help.h" -void block_continue_thread(void) +void socket_base_block_continue_thread(void) { // msg_t recv_m; // recv_m.type = TCP_NOT_DEFINED; @@ -31,24 +29,24 @@ void block_continue_thread(void) // } } -int net_msg_receive(msg_t *m) +int socket_base_net_msg_receive(msg_t *m) { return msg_receive(m); } -int net_msg_reply(msg_t *m, msg_t *reply, uint16_t message) +int socket_base_net_msg_reply(msg_t *m, msg_t *reply, uint16_t message) { reply->type = message; return msg_reply(m, reply); } -int net_msg_send(msg_t *m, kernel_pid_t pid, bool block, uint16_t message) +int socket_base_net_msg_send(msg_t *m, kernel_pid_t pid, bool block, uint16_t message) { m->type = message; return msg_send(m, pid, block); } -int net_msg_send_recv(msg_t *m, msg_t *reply, kernel_pid_t pid, uint16_t message) +int socket_base_net_msg_send_recv(msg_t *m, msg_t *reply, kernel_pid_t pid, uint16_t message) { m->type = message; return msg_send_receive(m, reply, pid);; diff --git a/sys/net/transport_layer/destiny/msg_help.h b/sys/net/transport_layer/socket_base/msg_help.h similarity index 75% rename from sys/net/transport_layer/destiny/msg_help.h rename to sys/net/transport_layer/socket_base/msg_help.h index 2f43c619ea..7b9c27cc68 100644 --- a/sys/net/transport_layer/destiny/msg_help.h +++ b/sys/net/transport_layer/socket_base/msg_help.h @@ -34,11 +34,11 @@ #define RETURNNOW 4000 -void block_continue_thread(void); -int net_msg_receive(msg_t *m); -int net_msg_reply(msg_t *m, msg_t *reply, uint16_t message); -int net_msg_send(msg_t *m, kernel_pid_t pid, bool block, uint16_t message); -int net_msg_send_recv(msg_t *m, msg_t *reply, kernel_pid_t pid, uint16_t message); +void socket_base_block_continue_thread(void); +int socket_base_net_msg_receive(msg_t *m); +int socket_base_net_msg_reply(msg_t *m, msg_t *reply, uint16_t message); +int socket_base_net_msg_send(msg_t *m, kernel_pid_t pid, bool block, uint16_t message); +int socket_base_net_msg_send_recv(msg_t *m, msg_t *reply, kernel_pid_t pid, uint16_t message); #endif /* MSG_HELP_H_ */ /** diff --git a/sys/net/transport_layer/socket_base/socket.c b/sys/net/transport_layer/socket_base/socket.c new file mode 100644 index 0000000000..d8cffa5b79 --- /dev/null +++ b/sys/net/transport_layer/socket_base/socket.c @@ -0,0 +1,436 @@ +/* + * Copyright (C) 2013, 2014 INRIA. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup socket_base + * @{ + * @file socket.c + * @brief functions for BSD socket API, methods return default values and + * will be overwritten by appropriate transport layer protocols. + * @author Oliver Gesch + * @author Cenk Gündoğan + * @} + */ + +#include +#include +#include +#include + +#include "hwtimer.h" +#include "ipv6.h" +#include "thread.h" +#include "vtimer.h" + +#include "net_help.h" + +#include "msg_help.h" + +#include "socket.h" + +#define EPHEMERAL_PORTS 49152 + +socket_internal_t socket_base_sockets[MAX_SOCKETS]; + +int __attribute__((weak)) tcp_connect(int socket, sockaddr6_t *addr, uint32_t addrlen) +{ + (void) socket; + (void) addr; + (void) addrlen; + + return -1; +} + +int __attribute__((weak)) tcp_listen(int s, int backlog) +{ + (void) s; + (void) backlog; + + return -1; +} + +int __attribute__((weak)) tcp_accept(int s, sockaddr6_t *addr, uint32_t *addrlen) +{ + (void) s; + (void) addr; + (void) addrlen; + + return -1; +} + +int32_t __attribute__((weak)) tcp_send(int s, const void *buf, uint32_t len, int flags) +{ + (void) s; + (void) buf; + (void) len; + (void) flags; + + return -1; +} + +int32_t __attribute__((weak)) tcp_recv(int s, void *buf, uint32_t len, int flags) +{ + (void) s; + (void) buf; + (void) len; + (void) flags; + + return -1; +} + +int32_t __attribute__((weak)) udp_recvfrom(int s, void *buf, uint32_t len, int flags, + sockaddr6_t *from, uint32_t *fromlen) +{ + (void) s; + (void) buf; + (void) len; + (void) flags; + (void) from; + (void) fromlen; + + return -1; +} + +int32_t __attribute__((weak)) udp_sendto(int s, const void *buf, uint32_t len, int flags, + sockaddr6_t *to, uint32_t tolen) +{ + (void) s; + (void) buf; + (void) len; + (void) flags; + (void) to; + (void) tolen; + + return -1; +} + +int __attribute__((weak)) tcp_bind_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid) +{ + (void) s; + (void) name; + (void) namelen; + (void) pid; + + return -1; +} + +int __attribute__((weak)) udp_bind_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid) +{ + (void) s; + (void) name; + (void) namelen; + (void) pid; + + return -1; +} + +bool __attribute__((weak)) tcp_socket_compliancy(int s) +{ + (void) s; + + return false; +} + +bool __attribute__((weak)) udp_socket_compliancy(int s) +{ + (void) s; + + return false; +} + +int __attribute__((weak)) tcp_teardown(socket_internal_t *current_socket) +{ + (void) current_socket; + + return -1; +} + +void socket_base_print_socket(socket_t *current_socket) +{ + char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("Domain: %i, Type: %i, Protocol: %i \n", + current_socket->domain, + current_socket->type, + current_socket->protocol); + printf("Local address: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + ¤t_socket->local_address.sin6_addr)); + printf("Foreign address: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + ¤t_socket->foreign_address.sin6_addr)); + printf("Local Port: %u, Foreign Port: %u\n", + NTOHS(current_socket->local_address.sin6_port), + NTOHS(current_socket->foreign_address.sin6_port)); +} + +void socket_base_print_internal_socket(socket_internal_t *current_socket_internal) +{ + socket_t *current_socket = ¤t_socket_internal->socket_values; + printf("\n--------------------------\n"); + printf("ID: %i, RECV PID: %i SEND PID: %i\n", + current_socket_internal->socket_id, current_socket_internal->recv_pid, + current_socket_internal->send_pid); + socket_base_print_socket(current_socket); + printf("\n--------------------------\n"); +} + +int socket_base_exists_socket(int socket) +{ + if (socket_base_sockets[socket - 1].socket_id == 0) { + return false; + } + else { + return true; + } +} + +socket_internal_t *socket_base_get_socket(int s) +{ + if (socket_base_exists_socket(s)) { + return &(socket_base_sockets[s - 1]); + } + else { + return NULL; + } +} + +void socket_base_print_sockets(void) +{ + int i; + printf("\n--- Socket list: ---\n"); + + for (i = 1; i < MAX_SOCKETS + 1; i++) { + if (socket_base_get_socket(i) != NULL) { + socket_base_print_internal_socket(socket_base_get_socket(i)); + } + } +} + +int socket_base_close(int s) +{ + socket_internal_t *current_socket = socket_base_get_socket(s); + + if (udp_socket_compliancy(s)) { + memset(current_socket, 0, sizeof(socket_internal_t)); + return 0; + } + else if (tcp_socket_compliancy(s)) { + return tcp_teardown(current_socket); + } + + printf("Socket Type not supported!\n"); + return -1; +} + +uint16_t socket_base_get_free_source_port(uint8_t protocol) +{ + int i; + uint16_t biggest_port = EPHEMERAL_PORTS - 1; + + /* Remember biggest ephemeral port number used so far and add 1 */ + for (i = 0; i < MAX_SOCKETS; i++) { + if ((socket_base_sockets[i].socket_values.protocol == protocol) && + (socket_base_sockets[i].socket_values.local_address.sin6_port > biggest_port)) { + biggest_port = socket_base_sockets[i].socket_values.local_address.sin6_port; + } + } + + return biggest_port + 1; +} + +int socket_base_socket(int domain, int type, int protocol) +{ + int i = 1; + + while (socket_base_get_socket(i) != NULL) { + i++; + } + + if (i > MAX_SOCKETS + 1) { + return -1; + } + else { + socket_t *current_socket = &socket_base_sockets[i - 1].socket_values; + socket_base_sockets[i - 1].socket_id = i; + current_socket->domain = domain; + current_socket->type = type; + current_socket->protocol = protocol; +#ifdef MODULE_TCP + current_socket->tcp_control.state = 0; +#endif + return socket_base_sockets[i - 1].socket_id; + } +} + +int socket_base_connect(int socket, sockaddr6_t *addr, uint32_t addrlen) +{ + if (tcp_socket_compliancy(socket)) { + return tcp_connect(socket, addr, addrlen); + } + else { + printf("Socket Type not supported!\n"); + } + + return -1; +} + +int socket_base_accept(int s, sockaddr6_t *addr, uint32_t *addrlen) +{ + if (tcp_socket_compliancy(s)) { + return tcp_accept(s, addr, addrlen); + } + + printf("Socket Type not supported!\n"); + return -1; +} + +int socket_base_listen(int s, int backlog) +{ + if (tcp_socket_compliancy(s)) { + return tcp_listen(s, backlog); + } + + printf("Socket Type not supported!\n"); + return -1; +} + +int32_t socket_base_recv(int s, void *buf, uint32_t len, int flags) +{ + if (tcp_socket_compliancy(s)) { + return tcp_recv(s, buf, len, flags); + } + + printf("Socket Type not supported!\n"); + return -1; +} + +int32_t socket_base_recvfrom(int s, void *buf, uint32_t len, int flags, + sockaddr6_t *from, uint32_t *fromlen) +{ + if (udp_socket_compliancy(s)) { + return udp_recvfrom(s, buf, len, flags, from, fromlen); + } + else if (tcp_socket_compliancy(s)) { + return tcp_recv(s, buf, len, flags); + } + + printf("Socket Type not supported!\n"); + return -1; +} + +int32_t socket_base_sendto(int s, const void *buf, uint32_t len, int flags, + sockaddr6_t *to, uint32_t tolen) +{ + if (udp_socket_compliancy(s)) { + return udp_sendto(s, buf, len, flags, to, tolen); + } + else if (tcp_socket_compliancy(s)) { + return tcp_send(s, buf, len, flags); + } + else { + printf("Socket Type not supported!\n"); + return -1; + } + + return -1; +} + +int32_t socket_base_send(int s, const void *buf, uint32_t len, int flags) +{ + if (tcp_socket_compliancy(s)) { + return tcp_send(s, buf, len, flags); + } + else { + printf("Socket Type not supported!\n"); + return -1; + } + + return -1; +} + +int socket_base_bind(int s, sockaddr6_t *addr, int addrlen) +{ + if (socket_base_exists_socket(s)) { + socket_t *current_socket = &socket_base_get_socket(s)->socket_values; + + switch (current_socket->domain) { + case (PF_INET): { + /* Not provided */ + return -1; + break; + } + + case (PF_INET6): { + switch (current_socket->type) { + /* TCP */ + case (SOCK_STREAM): { + if ((current_socket->protocol == 0) || + (current_socket->protocol == IPPROTO_TCP)) { + return tcp_bind_socket(s, addr, addrlen, + thread_getpid()); + break; + } + else { + return -1; + break; + } + + break; + } + + /* UDP */ + case (SOCK_DGRAM): { + if ((current_socket->protocol == 0) || + (current_socket->protocol == IPPROTO_UDP)) { + return udp_bind_socket(s, addr, addrlen, + thread_getpid()); + break; + } + else { + return -1; + break; + } + + break; + } + + case (SOCK_SEQPACKET): { + /* not provided */ + return -1; + break; + } + + case (SOCK_RAW): { + /* not provided */ + return -1; + break; + } + + default: { + return -1; + break; + } + } + + break; + } + + case (PF_UNIX): { + /* Not provided */ + return -1; + break; + } + } + } + else { + printf("SOCKET DOES NOT EXIST!\n"); + return -1; + } + + return -1; +} diff --git a/sys/net/transport_layer/destiny/socket.h b/sys/net/transport_layer/socket_base/socket.h similarity index 51% rename from sys/net/transport_layer/destiny/socket.h rename to sys/net/transport_layer/socket_base/socket.h index 1da09c04af..0887069925 100644 --- a/sys/net/transport_layer/destiny/socket.h +++ b/sys/net/transport_layer/socket_base/socket.h @@ -1,12 +1,25 @@ -#ifndef _DESTINY_SOCKET -#define _DESTINY_SOCKET +/* + * Copyright (C) 2014 Freie Universität Berlin. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#ifndef _SOCKET_BASE_SOCKET +#define _SOCKET_BASE_SOCKET #include "cpu.h" -#include "destiny/socket.h" +#include "socket_base/socket.h" -#include "tcp.h" +#ifdef MODULE_UDP #include "udp.h" +#endif + +#ifdef MODULE_TCP +#include "tcp.h" +#endif #define MAX_SOCKETS 5 // #define MAX_QUEUED_SOCKETS 2 @@ -14,6 +27,7 @@ #define INC_PACKET 0 #define OUT_PACKET 1 +#ifdef MODULE_TCP typedef struct __attribute__((packed)) { uint16_t context_id; uint32_t seq_rcv; // Last received packet values @@ -49,47 +63,37 @@ typedef struct __attribute__((packed)) { tcp_hc_context_t tcp_context; #endif } tcp_cb_t; +#endif -typedef struct __attribute__((packed)) { +typedef struct { uint8_t domain; uint8_t type; uint8_t protocol; +#ifdef MODULE_TCP tcp_cb_t tcp_control; +#endif sockaddr6_t local_address; sockaddr6_t foreign_address; } socket_t; typedef struct { uint8_t socket_id; - kernel_pid_t recv_pid; - kernel_pid_t send_pid; + uint8_t recv_pid; + uint8_t send_pid; + socket_t socket_values; +#ifdef MODULE_TCP uint8_t tcp_input_buffer_end; mutex_t tcp_buffer_mutex; - socket_t socket_values; - uint8_t tcp_input_buffer[DESTINY_SOCKET_MAX_TCP_BUFFER]; + uint8_t tcp_input_buffer[TRANSPORT_LAYER_SOCKET_MAX_TCP_BUFFER]; +#endif } socket_internal_t; -extern socket_internal_t sockets[MAX_SOCKETS]; +extern socket_internal_t socket_base_sockets[MAX_SOCKETS]; -socket_internal_t *get_waiting_connection_socket(int socket, - ipv6_hdr_t *ipv6_header, - tcp_hdr_t *tcp_header); -void close_socket(socket_internal_t *current_socket); -socket_internal_t *get_socket(int s); -socket_internal_t *get_udp_socket(udp_hdr_t *udp_header); -socket_internal_t *get_tcp_socket(ipv6_hdr_t *ipv6_header, - tcp_hdr_t *tcp_header); -socket_internal_t *new_tcp_queued_socket(ipv6_hdr_t *ipv6_header, - tcp_hdr_t *tcp_header); -void print_tcp_status(int in_or_out, ipv6_hdr_t *ipv6_header, - tcp_hdr_t *tcp_header, socket_t *tcp_socket); -void set_tcp_cb(tcp_cb_t *tcp_control, uint32_t rcv_nxt, uint16_t rcv_wnd, - uint32_t send_nxt, uint32_t send_una, uint16_t send_wnd); -int check_tcp_consistency(socket_t *current_tcp_socket, tcp_hdr_t *tcp_header, uint8_t tcp_payload_len); -void switch_tcp_packet_byte_order(tcp_hdr_t *current_tcp_packet); -int send_tcp(socket_internal_t *current_socket, tcp_hdr_t *current_tcp_packet, - ipv6_hdr_t *temp_ipv6_header, uint8_t flags, - uint8_t payload_length); -bool is_tcp_socket(int s); +socket_internal_t *socket_base_get_socket(int s); +uint16_t socket_base_get_free_source_port(uint8_t protocol); +int socket_base_exists_socket(int socket); +int socket_base_socket(int domain, int type, int protocol); +void socket_base_print_sockets(void); -#endif /* _DESTINY_SOCKET */ +#endif /* _SOCKET_BASE_SOCKET */ diff --git a/sys/net/transport_layer/tcp/Makefile b/sys/net/transport_layer/tcp/Makefile new file mode 100644 index 0000000000..8978e06912 --- /dev/null +++ b/sys/net/transport_layer/tcp/Makefile @@ -0,0 +1,2 @@ +INCLUDES += -I $(RIOTBASE)/sys/net/transport_layer/socket_base +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/transport_layer/destiny/socket.c b/sys/net/transport_layer/tcp/tcp.c similarity index 64% rename from sys/net/transport_layer/destiny/socket.c rename to sys/net/transport_layer/tcp/tcp.c index 090d68a953..f9a65bd5a2 100644 --- a/sys/net/transport_layer/destiny/socket.c +++ b/sys/net/transport_layer/tcp/tcp.c @@ -1,5 +1,5 @@ /** - * Destiny socket API + * TCP implementation * * Copyright (C) 2013 INRIA. * @@ -7,11 +7,12 @@ * General Public License v2.1. See the file LICENSE in the top level * directory for more details. * - * @ingroup destiny + * @ingroup tcp * @{ - * @file socket.c - * @brief functions for BSD socket API + * @file tcp.c + * @brief TCP implementation * @author Oliver Gesch + * @author Cenk Gündoğan * @} */ @@ -20,42 +21,66 @@ #include #include -#include "hwtimer.h" -#include "ipv6.h" +#include "sixlowpan.h" #include "thread.h" #include "vtimer.h" +#include "socket_base/in.h" + #include "net_help.h" #include "msg_help.h" -#include "tcp.h" +#include "socket.h" #include "tcp_hc.h" #include "tcp_timer.h" -#include "udp.h" -#include "socket.h" +#include "tcp.h" -#define EPHEMERAL_PORTS 49152 +#ifdef TCP_HC +mutex_t global_context_counter_mutex; +uint8_t global_context_counter; +#endif -socket_internal_t sockets[MAX_SOCKETS]; +mutex_t global_sequence_counter_mutex; +uint32_t global_sequence_counter; -void print_socket(socket_t *current_socket); -void print_internal_socket(socket_internal_t *current_socket_internal); -void printf_tcp_context(tcp_hc_context_t *current_tcp_context); -int exists_socket(int socket); -void set_socket_address(sockaddr6_t *sockaddr, sa_family_t sin6_family, - uint16_t sin6_port, uint32_t sin6_flowinfo, - ipv6_addr_t *sin6_addr); -void set_tcp_packet(tcp_hdr_t *tcp_hdr, uint16_t src_port, uint16_t dst_port, - uint32_t seq_nr, uint32_t ack_nr, - uint8_t data_offset, uint8_t reserved_flags, - uint16_t window, uint16_t checksum, uint16_t urg_pointer); +char tcp_stack_buffer[TCP_STACK_SIZE]; +char tcp_timer_stack[TCP_TIMER_STACKSIZE]; -void printf_tcp_context(tcp_hc_context_t *current_tcp_context) +void set_socket_address(sockaddr6_t *sockaddr, uint8_t sin6_family, + uint16_t sin6_port, uint32_t sin6_flowinfo, ipv6_addr_t *sin6_addr) { - printf("Context: %u\n", current_tcp_context->context_id); - printf("Rcv Seq: %" PRIu32 " Rcv Ack: %" PRIu32 ", Rcv Wnd: %u\n", current_tcp_context->seq_rcv, current_tcp_context->ack_rcv, current_tcp_context->wnd_rcv); - printf("Snd Seq: %" PRIu32 " Snd Ack: %" PRIu32 ", Snd Wnd: %u\n", current_tcp_context->seq_snd, current_tcp_context->ack_snd, current_tcp_context->wnd_snd); + sockaddr->sin6_family = sin6_family; + sockaddr->sin6_port = sin6_port; + sockaddr->sin6_flowinfo = sin6_flowinfo; + memcpy(&sockaddr->sin6_addr, sin6_addr, 16); +} + +void printTCPHeader(tcp_hdr_t *tcp_header) +{ + printf("\nBEGIN: TCP HEADER\n"); + printf("ack_nr: %" PRIu32 "\n", tcp_header->ack_nr); + printf("checksum: %i\n", tcp_header->checksum); + printf("data_offset: %i\n", tcp_header->data_offset); + printf("dst_port: %i\n", tcp_header->dst_port); + printf("reserved_flags: %i\n", tcp_header->reserved_flags); + printf("seq_nr: %" PRIu32 "\n", tcp_header->seq_nr); + printf("src_port: %i\n", tcp_header->src_port); + printf("urg_pointer: %i\n", tcp_header->urg_pointer); + printf("window: %i\n", tcp_header->window); + printf("END: TCP HEADER\n"); +} + +void printArrayRange_tcp(uint8_t *udp_header, uint16_t len) +{ + int i = 0; + printf("-------------MEMORY-------------\n"); + + for (i = 0; i < len; i++) { + printf("%#x ", *(udp_header + i)); + } + + printf("-------------MEMORY-------------\n"); } void print_tcp_flags(tcp_hdr_t *tcp_header) @@ -142,269 +167,15 @@ void print_tcp_status(int in_or_out, ipv6_hdr_t *ipv6_header, #endif } -void print_socket(socket_t *current_socket) +uint16_t tcp_csum(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header) { - char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("Domain: %i, Type: %i, Protocol: %i \n", - current_socket->domain, - current_socket->type, - current_socket->protocol); - printf("Local address: %s\n", - ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, - ¤t_socket->local_address.sin6_addr)); - printf("Foreign address: %s\n", - ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, - ¤t_socket->foreign_address.sin6_addr)); - printf("Local Port: %u, Foreign Port: %u\n", - NTOHS(current_socket->local_address.sin6_port), - NTOHS(current_socket->foreign_address.sin6_port)); -} + uint16_t sum; + uint16_t len = NTOHS(ipv6_header->length); -void print_internal_socket(socket_internal_t *current_socket_internal) -{ - socket_t *current_socket = ¤t_socket_internal->socket_values; - printf("\n--------------------------\n"); - printf("ID: %i, RECV PID: %i SEND PID: %i\n", - current_socket_internal->socket_id, current_socket_internal->recv_pid, - current_socket_internal->send_pid); - print_socket(current_socket); - printf("\n--------------------------\n"); -} - -socket_internal_t *get_socket(int s) -{ - if (exists_socket(s)) { - return &(sockets[s - 1]); - } - else { - return NULL; - } -} - -void destiny_socket_print_sockets(void) -{ - int i; - printf("\n--- Socket list: ---\n"); - - for (i = 1; i < MAX_SOCKETS + 1; i++) { - if (get_socket(i) != NULL) { - print_internal_socket(get_socket(i)); - } - } -} - -int exists_socket(int socket) -{ - if (sockets[socket - 1].socket_id == 0) { - return false; - } - else { - return true; - } -} - -void close_socket(socket_internal_t *current_socket) -{ - memset(current_socket, 0, sizeof(socket_internal_t)); -} - -bool isUDPSocket(uint8_t s) -{ - if ((exists_socket(s)) && - (get_socket(s)->socket_values.domain == PF_INET6) && - (get_socket(s)->socket_values.type == SOCK_DGRAM) && - ((get_socket(s)->socket_values.protocol == IPPROTO_UDP) || - (get_socket(s)->socket_values.protocol == 0))) { - return true; - } - else { - return false; - } -} - -bool is_tcp_socket(int s) -{ - if ((exists_socket(s)) && - (get_socket(s)->socket_values.domain == PF_INET6) && - (get_socket(s)->socket_values.type == SOCK_STREAM) && - ((get_socket(s)->socket_values.protocol == IPPROTO_TCP) || - (get_socket(s)->socket_values.protocol == 0))) { - return true; - } - else { - return false; - } -} - -int bind_udp_socket(int s, sockaddr6_t *name, int namelen, kernel_pid_t pid) -{ - int i; - - if (!exists_socket(s)) { - return -1; - } - - for (i = 1; i < MAX_SOCKETS + 1; i++) { - if (isUDPSocket(i) && - (get_socket(i)->socket_values.local_address.sin6_port == name->sin6_port)) { - return -1; - } - } - - memcpy(&get_socket(s)->socket_values.local_address, name, namelen); - get_socket(s)->recv_pid = pid; - return 0; -} - -int bind_tcp_socket(int s, sockaddr6_t *name, int namelen, kernel_pid_t pid) -{ - int i; - - if (!exists_socket(s)) { - return -1; - } - - for (i = 1; i < MAX_SOCKETS + 1; i++) { - if (is_tcp_socket(i) && - (get_socket(i)->socket_values.local_address.sin6_port == name->sin6_port)) { - return -1; - } - } - - memcpy(&get_socket(s)->socket_values.local_address, name, namelen); - get_socket(s)->recv_pid = pid; - get_socket(s)->socket_values.tcp_control.rto = TCP_INITIAL_ACK_TIMEOUT; - return 0; -} - -int destiny_socket(int domain, int type, int protocol) -{ - int i = 1; - - while (get_socket(i) != NULL) { - i++; - } - - if (i > MAX_SOCKETS + 1) { - return -1; - } - else { - socket_t *current_socket = &sockets[i - 1].socket_values; - sockets[i - 1].socket_id = i; - current_socket->domain = domain; - current_socket->type = type; - current_socket->protocol = protocol; - current_socket->tcp_control.state = TCP_CLOSED; - return sockets[i - 1].socket_id; - } -} - -socket_internal_t *get_udp_socket(udp_hdr_t *udp_header) -{ - uint8_t i = 1; - - while (i < MAX_SOCKETS + 1) { - if (isUDPSocket(i) && - (get_socket(i)->socket_values.local_address.sin6_port == - udp_header->dst_port)) { - return get_socket(i); - } - - i++; - } - - return NULL; -} - -bool is_four_touple(socket_internal_t *current_socket, ipv6_hdr_t *ipv6_header, - tcp_hdr_t *tcp_header) -{ - return (ipv6_addr_is_equal(¤t_socket->socket_values.local_address.sin6_addr, - &ipv6_header->destaddr) && - (current_socket->socket_values.local_address.sin6_port == tcp_header->dst_port) && - ipv6_addr_is_equal(¤t_socket->socket_values.foreign_address.sin6_addr, - &ipv6_header->srcaddr) && - (current_socket->socket_values.foreign_address.sin6_port == tcp_header->src_port)); -} - -socket_internal_t *get_tcp_socket(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header) -{ - uint8_t i = 1; - socket_internal_t *current_socket = NULL; - socket_internal_t *listening_socket = NULL; - uint8_t compare[16]; - memset(compare, 0, 16); - - while (i < MAX_SOCKETS + 1) { - current_socket = get_socket(i); - - /* Check for matching 4 touple, TCP_ESTABLISHED connection */ - if (is_tcp_socket(i) && is_four_touple(current_socket, ipv6_header, - tcp_header)) { - return current_socket; - } - /* Sockets in TCP_LISTEN and TCP_SYN_RCVD state should only be tested on local TCP values */ - else if (is_tcp_socket(i) && - ((current_socket->socket_values.tcp_control.state == TCP_LISTEN) || - (current_socket->socket_values.tcp_control.state == TCP_SYN_RCVD)) && - (current_socket->socket_values.local_address.sin6_addr.uint8[15] == - ipv6_header->destaddr.uint8[15]) && - (current_socket->socket_values.local_address.sin6_port == - tcp_header->dst_port) && - (current_socket->socket_values.foreign_address.sin6_addr.uint8[15] == - 0x00) && - (current_socket->socket_values.foreign_address.sin6_port == 0)) { - listening_socket = current_socket; - } - - i++; - } - - /* Return either NULL if nothing was matched or the listening 2 touple socket */ - return listening_socket; -} - -uint16_t get_free_source_port(uint8_t protocol) -{ - int i; - uint16_t biggest_port = EPHEMERAL_PORTS - 1; - - /* Remember biggest ephemeral port number used so far and add 1 */ - for (i = 0; i < MAX_SOCKETS; i++) { - if ((sockets[i].socket_values.protocol == protocol) && - (sockets[i].socket_values.local_address.sin6_port > biggest_port)) { - biggest_port = sockets[i].socket_values.local_address.sin6_port; - } - } - - return biggest_port + 1; -} - -void set_socket_address(sockaddr6_t *sockaddr, uint8_t sin6_family, - uint16_t sin6_port, uint32_t sin6_flowinfo, ipv6_addr_t *sin6_addr) -{ - sockaddr->sin6_family = sin6_family; - sockaddr->sin6_port = sin6_port; - sockaddr->sin6_flowinfo = sin6_flowinfo; - memcpy(&sockaddr->sin6_addr, sin6_addr, 16); -} - -void set_tcp_packet(tcp_hdr_t *tcp_hdr, uint16_t src_port, uint16_t dst_port, - uint32_t seq_nr, uint32_t ack_nr, uint8_t data_offset, - uint8_t reserved_flags, uint16_t window, uint16_t checksum, - uint16_t urg_pointer) -{ - tcp_hdr->ack_nr = ack_nr; - tcp_hdr->checksum = checksum; - tcp_hdr->data_offset = data_offset; - tcp_hdr->dst_port = dst_port; - tcp_hdr->reserved_flags = reserved_flags; - tcp_hdr->reserved = 0; - tcp_hdr->flag_ns = 0; - tcp_hdr->seq_nr = seq_nr; - tcp_hdr->src_port = src_port; - tcp_hdr->urg_pointer = urg_pointer; - tcp_hdr->window = window; + sum = len + IPPROTO_TCP; + sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t)); + sum = csum(sum, (uint8_t *)tcp_header, len); + return (sum == 0) ? 0xffff : HTONS(sum); } /* Check for consistent ACK and SEQ number */ @@ -428,6 +199,16 @@ int check_tcp_consistency(socket_t *current_tcp_socket, tcp_hdr_t *tcp_header, u return PACKET_OK; } +void set_tcp_cb(tcp_cb_t *tcp_control, uint32_t rcv_nxt, uint16_t rcv_wnd, + uint32_t send_nxt, uint32_t send_una, uint16_t send_wnd) +{ + tcp_control->rcv_nxt = rcv_nxt; + tcp_control->rcv_wnd = rcv_wnd; + tcp_control->send_nxt = send_nxt; + tcp_control->send_una = send_una; + tcp_control->send_wnd = send_wnd; +} + void switch_tcp_packet_byte_order(tcp_hdr_t *current_tcp_packet) { if (current_tcp_packet->data_offset * 4 > TCP_HDR_LEN) { @@ -451,6 +232,24 @@ void switch_tcp_packet_byte_order(tcp_hdr_t *current_tcp_packet) current_tcp_packet->urg_pointer = HTONS(current_tcp_packet->urg_pointer); } +void set_tcp_packet(tcp_hdr_t *tcp_hdr, uint16_t src_port, uint16_t dst_port, + uint32_t seq_nr, uint32_t ack_nr, uint8_t data_offset, + uint8_t reserved_flags, uint16_t window, uint16_t checksum, + uint16_t urg_pointer) +{ + tcp_hdr->ack_nr = ack_nr; + tcp_hdr->checksum = checksum; + tcp_hdr->data_offset = data_offset; + tcp_hdr->dst_port = dst_port; + tcp_hdr->reserved_flags = reserved_flags; + tcp_hdr->reserved = 0; + tcp_hdr->flag_ns = 0; + tcp_hdr->seq_nr = seq_nr; + tcp_hdr->src_port = src_port; + tcp_hdr->urg_pointer = urg_pointer; + tcp_hdr->window = window; +} + int send_tcp(socket_internal_t *current_socket, tcp_hdr_t *current_tcp_packet, ipv6_hdr_t *temp_ipv6_header, uint8_t flags, uint8_t payload_length) { @@ -463,7 +262,7 @@ int send_tcp(socket_internal_t *current_socket, tcp_hdr_t *current_tcp_packet, current_mss_option.kind = TCP_MSS_OPTION; current_mss_option.len = sizeof(tcp_mss_option_t); - current_mss_option.mss = DESTINY_SOCKET_STATIC_MSS; + current_mss_option.mss = TRANSPORT_LAYER_SOCKET_STATIC_MSS; memcpy(((uint8_t *)current_tcp_packet) + TCP_HDR_LEN, ¤t_mss_option, sizeof(tcp_mss_option_t)); } @@ -507,178 +306,505 @@ int send_tcp(socket_internal_t *current_socket, tcp_hdr_t *current_tcp_packet, #endif } -void set_tcp_cb(tcp_cb_t *tcp_control, uint32_t rcv_nxt, uint16_t rcv_wnd, - uint32_t send_nxt, uint32_t send_una, uint16_t send_wnd) +bool is_four_touple(socket_internal_t *current_socket, ipv6_hdr_t *ipv6_header, + tcp_hdr_t *tcp_header) { - tcp_control->rcv_nxt = rcv_nxt; - tcp_control->rcv_wnd = rcv_wnd; - tcp_control->send_nxt = send_nxt; - tcp_control->send_una = send_una; - tcp_control->send_wnd = send_wnd; + return (ipv6_addr_is_equal(¤t_socket->socket_values.local_address.sin6_addr, + &ipv6_header->destaddr) && + (current_socket->socket_values.local_address.sin6_port == tcp_header->dst_port) && + ipv6_addr_is_equal(¤t_socket->socket_values.foreign_address.sin6_addr, + &ipv6_header->srcaddr) && + (current_socket->socket_values.foreign_address.sin6_port == tcp_header->src_port)); } -int destiny_socket_connect(int socket, sockaddr6_t *addr, uint32_t addrlen) +socket_internal_t *get_waiting_connection_socket(int socket, + ipv6_hdr_t *ipv6_header, + tcp_hdr_t *tcp_header) { - (void) addrlen; + int i; + socket_internal_t *current_socket, *listening_socket = socket_base_get_socket(socket); - /* Variables */ - ipv6_addr_t src_addr; - socket_internal_t *current_int_tcp_socket; - socket_t *current_tcp_socket; - msg_t msg_from_server; + for (i = 1; i < MAX_SOCKETS + 1; i++) { + current_socket = socket_base_get_socket(i); + + if (!current_socket) { + continue; + } + + /* Connection establishment ACK, Check for 4 touple and state */ + if ((ipv6_header != NULL) && (tcp_header != NULL)) { + if (is_four_touple(current_socket, ipv6_header, tcp_header) && + (current_socket->socket_values.tcp_control.state == TCP_SYN_RCVD)) { + return current_socket; + } + } + /* Connection establishment SYN ACK, check only for port and state */ + else { + if ((current_socket->socket_values.tcp_control.state == TCP_SYN_RCVD) && + (current_socket->socket_values.local_address.sin6_port == + listening_socket->socket_values.local_address.sin6_port)) { + return current_socket; + } + } + } + + return NULL; +} + +socket_internal_t *new_tcp_queued_socket(ipv6_hdr_t *ipv6_header, + tcp_hdr_t *tcp_header) +{ + int queued_socket_id; + + queued_socket_id = socket_base_socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); + socket_internal_t *current_queued_socket = socket_base_get_socket(queued_socket_id); + + /* Foreign address */ + set_socket_address(¤t_queued_socket->socket_values.foreign_address, + AF_INET6, tcp_header->src_port, ipv6_header->flowlabel, + &ipv6_header->srcaddr); + + /* Local address */ + set_socket_address(¤t_queued_socket->socket_values.local_address, + AF_INET6, tcp_header->dst_port, 0, + &ipv6_header->destaddr); + + /* Foreign TCP information */ + if ((tcp_header->data_offset * 4 > TCP_HDR_LEN) && + (*(((uint8_t *)tcp_header) + TCP_HDR_LEN) == TCP_MSS_OPTION)) { + current_queued_socket->socket_values.tcp_control.mss = + *((uint16_t *)(((uint8_t *)tcp_header) + TCP_HDR_LEN + 2)); + } + else { + current_queued_socket->socket_values.tcp_control.mss = TRANSPORT_LAYER_SOCKET_STATIC_MSS; + } + + current_queued_socket->socket_values.tcp_control.rcv_irs = + tcp_header->seq_nr; + mutex_lock(&global_sequence_counter_mutex); + current_queued_socket->socket_values.tcp_control.send_iss = + global_sequence_counter; + mutex_unlock(&global_sequence_counter_mutex); + current_queued_socket->socket_values.tcp_control.state = TCP_SYN_RCVD; + set_tcp_cb(¤t_queued_socket->socket_values.tcp_control, + tcp_header->seq_nr + 1, TRANSPORT_LAYER_SOCKET_STATIC_WINDOW, + current_queued_socket->socket_values.tcp_control.send_iss + 1, + current_queued_socket->socket_values.tcp_control.send_iss, + tcp_header->window); + + return current_queued_socket; +} + +socket_internal_t *get_tcp_socket(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header) +{ + uint8_t i = 1; + socket_internal_t *current_socket = NULL; + socket_internal_t *listening_socket = NULL; + uint8_t compare[16]; + memset(compare, 0, 16); + + while (i < MAX_SOCKETS + 1) { + current_socket = socket_base_get_socket(i); + + /* Check for matching 4 touple, TCP_ESTABLISHED connection */ + if (tcp_socket_compliancy(i) && is_four_touple(current_socket, ipv6_header, + tcp_header)) { + return current_socket; + } + /* Sockets in TCP_LISTEN and TCP_SYN_RCVD state should only be tested on local TCP values */ + else if (tcp_socket_compliancy(i) && + ((current_socket->socket_values.tcp_control.state == TCP_LISTEN) || + (current_socket->socket_values.tcp_control.state == TCP_SYN_RCVD)) && + (current_socket->socket_values.local_address.sin6_addr.uint8[15] == + ipv6_header->destaddr.uint8[15]) && + (current_socket->socket_values.local_address.sin6_port == + tcp_header->dst_port) && + (current_socket->socket_values.foreign_address.sin6_addr.uint8[15] == + 0x00) && + (current_socket->socket_values.foreign_address.sin6_port == 0)) { + listening_socket = current_socket; + } + + i++; + } + + /* Return either NULL if nothing was matched or the listening 2 touple socket */ + return listening_socket; +} + +uint8_t handle_payload(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, + socket_internal_t *tcp_socket, uint8_t *payload) +{ + (void) tcp_header; + + msg_t m_send_tcp, m_recv_tcp; + uint8_t tcp_payload_len = NTOHS(ipv6_header->length) - TCP_HDR_LEN; + uint8_t acknowledged_bytes = 0; + + if (tcp_payload_len > tcp_socket->socket_values.tcp_control.rcv_wnd) { + mutex_lock(&tcp_socket->tcp_buffer_mutex); + memcpy(tcp_socket->tcp_input_buffer, payload, + tcp_socket->socket_values.tcp_control.rcv_wnd); + acknowledged_bytes = tcp_socket->socket_values.tcp_control.rcv_wnd; + tcp_socket->socket_values.tcp_control.rcv_wnd = 0; + tcp_socket->tcp_input_buffer_end = tcp_socket->tcp_input_buffer_end + + tcp_socket->socket_values.tcp_control.rcv_wnd; + mutex_unlock(&tcp_socket->tcp_buffer_mutex); + } + else { + mutex_lock(&tcp_socket->tcp_buffer_mutex); + memcpy(tcp_socket->tcp_input_buffer, payload, tcp_payload_len); + tcp_socket->socket_values.tcp_control.rcv_wnd = + tcp_socket->socket_values.tcp_control.rcv_wnd - tcp_payload_len; + acknowledged_bytes = tcp_payload_len; + tcp_socket->tcp_input_buffer_end = tcp_socket->tcp_input_buffer_end + + tcp_payload_len; + mutex_unlock(&tcp_socket->tcp_buffer_mutex); + } + + if (thread_getstatus(tcp_socket->recv_pid) == STATUS_RECEIVE_BLOCKED) { + socket_base_net_msg_send_recv(&m_send_tcp, &m_recv_tcp, tcp_socket->recv_pid, UNDEFINED); + } + + return acknowledged_bytes; +} + +void handle_tcp_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, + socket_internal_t *tcp_socket) +{ + msg_t m_recv_tcp, m_send_tcp; + uint8_t target_pid; + + if (tcp_socket->socket_values.tcp_control.state == TCP_LAST_ACK) { + target_pid = tcp_socket->recv_pid; + memset(tcp_socket, 0, sizeof(socket_internal_t)); + msg_send(&m_send_tcp, target_pid, 0); + return; + } + else if (tcp_socket->socket_values.tcp_control.state == TCP_CLOSING) { + msg_send(&m_send_tcp, tcp_socket->recv_pid, 0); + msg_send(&m_send_tcp, tcp_socket->send_pid, 0); + return; + } + else if (get_waiting_connection_socket(tcp_socket->socket_id, ipv6_header, + tcp_header) != NULL) { + m_send_tcp.content.ptr = (char *)tcp_header; + socket_base_net_msg_send_recv(&m_send_tcp, &m_recv_tcp, tcp_socket->recv_pid, TCP_ACK); + return; + } + else if (tcp_socket->socket_values.tcp_control.state == TCP_ESTABLISHED) { + if (check_tcp_consistency(&tcp_socket->socket_values, tcp_header, 0) == PACKET_OK) { + m_send_tcp.content.ptr = (char *)tcp_header; + socket_base_net_msg_send(&m_send_tcp, tcp_socket->send_pid, 0, TCP_ACK); + return; + } + } + + printf("NO WAY OF HANDLING THIS ACK!\n"); +} + +void handle_tcp_rst_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, + socket_internal_t *tcp_socket) +{ + (void) ipv6_header; + (void) tcp_header; + (void) tcp_socket; + + /* TODO: Reset connection */ +} + +void handle_tcp_syn_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, + socket_internal_t *tcp_socket) +{ + msg_t m_send_tcp; + + if (tcp_socket->socket_values.tcp_control.state == TCP_LISTEN) { + socket_internal_t *new_socket = new_tcp_queued_socket(ipv6_header, + tcp_header); + + if (new_socket != NULL) { +#ifdef TCP_HC + update_tcp_hc_context(true, new_socket, tcp_header); +#endif + /* notify socket function tcp_accept(..) that a new + * connection request has arrived. No need to wait for an answer + * because the server tcp_accept() function isnt reading + * from anything other than the queued sockets */ + socket_base_net_msg_send(&m_send_tcp, tcp_socket->recv_pid, 0, TCP_SYN); + } + else { + printf("Dropped TCP SYN Message because an error occured while "\ + "requesting a new queued socket!\n"); + } + } + else { + printf("Dropped TCP SYN Message because socket was not in state TCP_LISTEN!"); + } +} + +void handle_tcp_syn_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, + socket_internal_t *tcp_socket) +{ + (void) ipv6_header; + + msg_t m_send_tcp; + + if (tcp_socket->socket_values.tcp_control.state == TCP_SYN_SENT) { + m_send_tcp.content.ptr = (char *) tcp_header; + socket_base_net_msg_send(&m_send_tcp, tcp_socket->recv_pid, 0, TCP_SYN_ACK); + } + else { + printf("Socket not in state TCP_SYN_SENT, dropping SYN-ACK-packet!"); + } +} + +void handle_tcp_fin_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, + socket_internal_t *tcp_socket) +{ + (void) ipv6_header; + + msg_t m_send; + socket_t *current_tcp_socket = &tcp_socket->socket_values; uint8_t send_buffer[BUFFER_SIZE]; ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); - /* Check if socket exists */ - current_int_tcp_socket = get_socket(socket); + set_tcp_cb(¤t_tcp_socket->tcp_control, tcp_header->seq_nr + 1, + current_tcp_socket->tcp_control.send_wnd, tcp_header->ack_nr + 1, + tcp_header->ack_nr, tcp_header->window); - if (current_int_tcp_socket == NULL) { +#ifdef TCP_HC + current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; +#endif + + if (current_tcp_socket->tcp_control.state == TCP_FIN_WAIT_1) { + current_tcp_socket->tcp_control.state = TCP_CLOSING; + + send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_FIN_ACK, 0); + } + else { + current_tcp_socket->tcp_control.state = TCP_LAST_ACK; + + send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_FIN_ACK, 0); + } + + socket_base_net_msg_send(&m_send, tcp_socket->recv_pid, 0, CLOSE_CONN); +} + +void handle_tcp_fin_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, + socket_internal_t *tcp_socket) +{ + (void) ipv6_header; + + msg_t m_send; + socket_t *current_tcp_socket = &tcp_socket->socket_values; + uint8_t send_buffer[BUFFER_SIZE]; + ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); + tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); + + current_tcp_socket->tcp_control.state = TCP_CLOSED; + + set_tcp_cb(¤t_tcp_socket->tcp_control, tcp_header->seq_nr + 1, + current_tcp_socket->tcp_control.send_wnd, tcp_header->ack_nr, + tcp_header->ack_nr, tcp_header->window); + +#ifdef TCP_HC + current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; +#endif + + send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_ACK, 0); + + msg_send(&m_send, tcp_socket->send_pid, 0); + msg_send(&m_send, tcp_socket->recv_pid, 0); +} + +void handle_tcp_no_flags_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, + socket_internal_t *tcp_socket, uint8_t *payload, uint8_t tcp_payload_len) +{ + uint8_t read_bytes = 0; + socket_t *current_tcp_socket = &tcp_socket->socket_values; + uint8_t send_buffer[BUFFER_SIZE]; + ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); + tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); + + if (check_tcp_consistency(current_tcp_socket, tcp_header, tcp_payload_len) == PACKET_OK) { + read_bytes = handle_payload(ipv6_header, tcp_header, tcp_socket, payload); + + /* Refresh TCP status values */ + current_tcp_socket->tcp_control.state = TCP_ESTABLISHED; + + set_tcp_cb(¤t_tcp_socket->tcp_control, + tcp_header->seq_nr + read_bytes, + current_tcp_socket->tcp_control.rcv_wnd, + current_tcp_socket->tcp_control.send_nxt, + current_tcp_socket->tcp_control.send_una, + current_tcp_socket->tcp_control.send_wnd); + + /* Send packet */ + // block_continue_thread(); +#ifdef TCP_HC + current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; +#endif + send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_ACK, 0); + } + /* ACK packet probably got lost */ + else { + // block_continue_thread(); +#ifdef TCP_HC + current_tcp_socket->tcp_control.tcp_context.hc_type = FULL_HEADER; +#endif + send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_ACK, 0); + } +} + +void *tcp_packet_handler(void *arg) +{ + (void) arg; + + msg_t m_recv_ip, m_send_ip; + ipv6_hdr_t *ipv6_header; + tcp_hdr_t *tcp_header; + uint8_t *payload; + socket_internal_t *tcp_socket = NULL; + uint16_t chksum; + + while (1) { + msg_receive(&m_recv_ip); + + ipv6_header = ((ipv6_hdr_t *)m_recv_ip.content.ptr); + tcp_header = ((tcp_hdr_t *)(m_recv_ip.content.ptr + IPV6_HDR_LEN)); +#ifdef TCP_HC + tcp_socket = decompress_tcp_packet(ipv6_header); +#else + switch_tcp_packet_byte_order(tcp_header); + tcp_socket = get_tcp_socket(ipv6_header, tcp_header); +#endif + chksum = tcp_csum(ipv6_header, tcp_header); + + payload = (uint8_t *)(m_recv_ip.content.ptr + IPV6_HDR_LEN + tcp_header->data_offset * 4); + + if ((chksum == 0xffff) && (tcp_socket != NULL)) { +#ifdef TCP_HC + update_tcp_hc_context(true, tcp_socket, tcp_header); +#endif + /* Remove reserved bits from tcp flags field */ + uint8_t tcp_flags = tcp_header->reserved_flags; + + switch (tcp_flags) { + case TCP_ACK: { + /* only ACK Bit set */ + uint8_t tcp_payload_len = NTOHS(ipv6_header->length) - TCP_HDR_LEN; + uint8_t state = tcp_socket->socket_values.tcp_control.state; + + if ((tcp_payload_len > 0) && (state == TCP_ESTABLISHED)) { + /* handle data segments only when the connection was established successfully */ + handle_tcp_no_flags_packet(ipv6_header, tcp_header, tcp_socket, payload, tcp_payload_len); + } + else if (tcp_payload_len == 0 + && (state == TCP_ESTABLISHED || state == TCP_SYN_RCVD + || state == TCP_CLOSING || state == TCP_LAST_ACK)) { + /* no payload, acknowledging data only */ + handle_tcp_ack_packet(ipv6_header, tcp_header, tcp_socket); + } + break; + } + + case TCP_RST: { + printf("RST Bit set!\n"); + /* only RST Bit set */ + handle_tcp_rst_packet(ipv6_header, tcp_header, tcp_socket); + break; + } + + case TCP_SYN: { + /* only SYN Bit set, look for matching, listening socket + * and request new queued socket */ + printf("SYN Bit set!\n"); + handle_tcp_syn_packet(ipv6_header, tcp_header, tcp_socket); + break; + } + + case TCP_SYN_ACK: { + /* only SYN and ACK Bit set, complete three way handshake + * when socket in state TCP_SYN_SENT */ + handle_tcp_syn_ack_packet(ipv6_header, tcp_header, tcp_socket); + break; + } + + case TCP_FIN_ACK: { + if (tcp_socket->socket_values.tcp_control.state == TCP_ESTABLISHED) { + /* this is the first FIN */ + printf("FIN ACK Bit set!\n"); + handle_tcp_fin_packet(ipv6_header, tcp_header, tcp_socket); + } + else { + /* this is the response to FIN */ + handle_tcp_fin_ack_packet(ipv6_header, tcp_header, tcp_socket); + } + break; + } + + default: { + printf("Unable to process the incoming segment!\n"); + } + } + } + else { + printf("Wrong checksum (%x) or no corresponding socket found!\n", + chksum); + printArrayRange(((uint8_t *)ipv6_header), IPV6_HDR_LEN + + NTOHS(ipv6_header->length), "Incoming"); + print_tcp_status(INC_PACKET, ipv6_header, tcp_header, + &tcp_socket->socket_values); + } + + msg_reply(&m_recv_ip, &m_send_ip); + } +} + +void printf_tcp_context(tcp_hc_context_t *current_tcp_context) +{ + printf("Context: %u\n", current_tcp_context->context_id); + printf("Rcv Seq: %" PRIu32 " Rcv Ack: %" PRIu32 ", Rcv Wnd: %u\n", current_tcp_context->seq_rcv, current_tcp_context->ack_rcv, current_tcp_context->wnd_rcv); + printf("Snd Seq: %" PRIu32 " Snd Ack: %" PRIu32 ", Snd Wnd: %u\n", current_tcp_context->seq_snd, current_tcp_context->ack_snd, current_tcp_context->wnd_snd); +} + +bool tcp_socket_compliancy(int s) +{ + if ((socket_base_exists_socket(s)) && + (socket_base_get_socket(s)->socket_values.domain == PF_INET6) && + (socket_base_get_socket(s)->socket_values.type == SOCK_STREAM) && + ((socket_base_get_socket(s)->socket_values.protocol == IPPROTO_TCP) || + (socket_base_get_socket(s)->socket_values.protocol == 0))) { + return true; + } + else { + return false; + } +} + +int tcp_bind_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid) +{ + int i; + + socket_internal_t *sock = socket_base_get_socket(s); + + if (!sock) { return -1; } - current_tcp_socket = ¤t_int_tcp_socket->socket_values; - - current_int_tcp_socket->recv_pid = thread_getpid(); - - /* Local address information */ - ipv6_net_if_get_best_src_addr(&src_addr, &addr->sin6_addr); - set_socket_address(¤t_tcp_socket->local_address, PF_INET6, - HTONS(get_free_source_port(IPPROTO_TCP)), 0, &src_addr); - - /* Foreign address information */ - set_socket_address(¤t_tcp_socket->foreign_address, addr->sin6_family, - addr->sin6_port, addr->sin6_flowinfo, &addr->sin6_addr); - - /* Fill lcoal TCP socket information */ - srand(addr->sin6_port); - - current_tcp_socket->tcp_control.rcv_irs = 0; - mutex_lock(&global_sequence_counter_mutex); - current_tcp_socket->tcp_control.send_iss = global_sequence_counter; - mutex_unlock(&global_sequence_counter_mutex); - current_tcp_socket->tcp_control.state = TCP_SYN_SENT; - -#ifdef TCP_HC - /* Choosing random number Context ID */ - mutex_lock(&global_context_counter_mutex); - current_tcp_socket->tcp_control.tcp_context.context_id = global_context_counter; - mutex_unlock(&global_context_counter_mutex); - - current_tcp_socket->tcp_control.tcp_context.hc_type = FULL_HEADER; - - /* Remember TCP Context for possible TCP_RETRY */ - tcp_hc_context_t saved_tcp_context; - memcpy(&saved_tcp_context, ¤t_tcp_socket->tcp_control.tcp_context, - sizeof(tcp_hc_context_t)); -#endif - - set_tcp_cb(¤t_tcp_socket->tcp_control, 0, DESTINY_SOCKET_STATIC_WINDOW, - current_tcp_socket->tcp_control.send_iss + 1, - current_tcp_socket->tcp_control.send_iss, 0); - - /* Remember current time */ - timex_t now; - vtimer_now(&now); - current_tcp_socket->tcp_control.last_packet_time = now; - current_tcp_socket->tcp_control.no_of_retries = 0; - - msg_from_server.type = TCP_RETRY; - - while (msg_from_server.type == TCP_RETRY) { - /* Send packet */ - send_tcp(current_int_tcp_socket, current_tcp_packet, temp_ipv6_header, - TCP_SYN, 0); - - /* wait for SYN ACK or RETRY */ - msg_receive(&msg_from_server); - - if (msg_from_server.type == TCP_TIMEOUT) { -#ifdef TCP_HC - /* We did not send anything successful so restore last context */ - memcpy(¤t_tcp_socket->tcp_control.tcp_context, - &saved_tcp_context, sizeof(tcp_hc_context_t)); -#endif + for (i = 1; i < MAX_SOCKETS + 1; i++) { + if (tcp_socket_compliancy(i) && + (socket_base_get_socket(i)->socket_values.local_address.sin6_port == name->sin6_port)) { return -1; } - -#ifdef TCP_HC - else if (msg_from_server.type == TCP_RETRY) { - /* We retry sending a packet so set everything to last values again */ - memcpy(¤t_tcp_socket->tcp_control.tcp_context, - &saved_tcp_context, sizeof(tcp_hc_context_t)); - } - -#endif } - /* Read packet content */ - tcp_hdr_t *tcp_header = ((tcp_hdr_t *)(msg_from_server.content.ptr)); + (void) namelen; + sock->socket_values.local_address = *name; + sock->socket_values.tcp_control.rto = TCP_INITIAL_ACK_TIMEOUT; + sock->recv_pid = pid; - /* Check for consistency */ - if (tcp_header->ack_nr != current_tcp_socket->tcp_control.send_nxt) { - printf("TCP packets not consistent!\n"); - } - - /* Got SYN ACK from Server */ - /* Refresh foreign TCP socket information */ - if ((tcp_header->data_offset * 4 > TCP_HDR_LEN) && - (*(((uint8_t *)tcp_header) + TCP_HDR_LEN) == TCP_MSS_OPTION)) { - current_tcp_socket->tcp_control.mss = - *((uint16_t *)(((uint8_t *)tcp_header) + TCP_HDR_LEN + 2)); - } - else { - current_tcp_socket->tcp_control.mss = DESTINY_SOCKET_STATIC_MSS; - } - - current_tcp_socket->tcp_control.rcv_irs = tcp_header->seq_nr; - set_tcp_cb(¤t_tcp_socket->tcp_control, tcp_header->seq_nr + 1, - current_tcp_socket->tcp_control.rcv_wnd, - current_tcp_socket->tcp_control.send_una + 1, - tcp_header->ack_nr, - tcp_header->window); - - msg_from_server.type = UNDEFINED; - - /* Remember current time */ - vtimer_now(&now); - current_tcp_socket->tcp_control.last_packet_time = now; - current_tcp_socket->tcp_control.no_of_retries = 0; - -#ifdef TCP_HC - current_tcp_socket->tcp_control.tcp_context.hc_type = FULL_HEADER; - /* Remember TCP Context for possible TCP_RETRY */ - memcpy(&saved_tcp_context, ¤t_tcp_socket->tcp_control.tcp_context, - sizeof(tcp_hc_context_t)); -#endif - - while (msg_from_server.type != TCP_RETRY) { - /* Send packet */ - send_tcp(current_int_tcp_socket, current_tcp_packet, temp_ipv6_header, - TCP_ACK, 0); - - msg_receive(&msg_from_server); -#ifdef TCP_HC - - if (msg_from_server.type == TCP_SYN_ACK) { - /* TCP_SYN_ACK from server arrived again, copy old context and - * send TCP_ACK again */ - memcpy(¤t_tcp_socket->tcp_control.tcp_context, - &saved_tcp_context, sizeof(tcp_hc_context_t)); - } - else if (msg_from_server.type == TCP_RETRY) { - /* We waited for RTT, no TCP_SYN_ACK received, so we assume the - * TCP_ACK packet arrived safely */ - } - -#endif - } - - current_tcp_socket->tcp_control.state = TCP_ESTABLISHED; - - current_int_tcp_socket->recv_pid = KERNEL_PID_UNDEF; - - destiny_socket_print_sockets(); return 0; } @@ -713,7 +839,94 @@ void calculate_rto(tcp_cb_t *tcp_control, timex_t current_time) tcp_control->rto = rto; } -int32_t destiny_socket_send(int s, const void *buf, uint32_t len, int flags) +int handle_new_tcp_connection(socket_internal_t *current_queued_int_socket, + socket_internal_t *server_socket, uint8_t pid) +{ + (void) pid; + + msg_t msg_recv_client_ack, msg_send_client_ack; + socket_t *current_queued_socket = ¤t_queued_int_socket->socket_values; + uint8_t send_buffer[BUFFER_SIZE]; + ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); + tcp_hdr_t *syn_ack_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); + + current_queued_int_socket->recv_pid = thread_getpid(); +#ifdef TCP_HC + current_queued_int_socket->socket_values.tcp_control.tcp_context.hc_type = + FULL_HEADER; + memcpy(¤t_queued_int_socket->socket_values.tcp_control.tcp_context.context_id, + &server_socket->socket_values.tcp_control.tcp_context.context_id, + sizeof(server_socket->socket_values.tcp_control.tcp_context.context_id)); +#endif + /* Remember current time */ + timex_t now; + vtimer_now(&now); + current_queued_int_socket->socket_values.tcp_control.last_packet_time = now; + + current_queued_int_socket->socket_values.tcp_control.no_of_retries = 0; + + /* Set message type to Retry for while loop */ + msg_recv_client_ack.type = TCP_RETRY; + + while (msg_recv_client_ack.type == TCP_RETRY) { + /* Send packet */ + send_tcp(current_queued_int_socket, syn_ack_packet, temp_ipv6_header, + TCP_SYN_ACK, 0); + + /* wait for ACK from Client */ + msg_receive(&msg_recv_client_ack); + + if (msg_recv_client_ack.type == TCP_TIMEOUT) { + /* Set status of internal socket back to TCP_LISTEN */ + server_socket->socket_values.tcp_control.state = TCP_LISTEN; + memset(current_queued_int_socket, 0, sizeof(socket_internal_t)); + return -1; + } + } + + tcp_hdr_t *tcp_header; + + tcp_header = ((tcp_hdr_t *)(msg_recv_client_ack.content.ptr)); + + /* Check for consistency */ + if (tcp_header->ack_nr != current_queued_socket->tcp_control.send_nxt) { + printf("TCP packets not consistent!\n"); + } + + /* Got ack, connection established, refresh local and foreign tcp socket + * status */ + set_tcp_cb(¤t_queued_socket->tcp_control, tcp_header->seq_nr, + current_queued_socket->tcp_control.rcv_wnd, tcp_header->ack_nr, + tcp_header->ack_nr, tcp_header->window); + +#ifdef TCP_HC + /* Copy TCP context information into new socket */ + memset(&server_socket->socket_values.tcp_control.tcp_context, 0, + sizeof(tcp_hc_context_t)); +#endif + + /* Update connection status information */ + current_queued_socket->tcp_control.state = TCP_ESTABLISHED; + + /* Set status of internal socket back to TCP_LISTEN */ + server_socket->socket_values.tcp_control.state = TCP_LISTEN; + + /* send a reply to the TCP handler after processing every information from + * the TCP ACK packet */ + msg_reply(&msg_recv_client_ack, &msg_send_client_ack); + + /* Reset PID to an unlikely value */ + current_queued_int_socket->recv_pid = 255; + + /* Waiting for Clients ACK waiting period to time out */ + vtimer_usleep(TCP_SYN_INITIAL_TIMEOUT / 2); + + socket_base_print_sockets(); + + return current_queued_int_socket->socket_id; +} + +int32_t tcp_send(int s, const void *buf, uint32_t len, int flags) { (void) flags; @@ -729,11 +942,11 @@ int32_t destiny_socket_send(int s, const void *buf, uint32_t len, int flags) tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); /* Check if socket exists and is TCP socket */ - if (!is_tcp_socket(s)) { + if (!tcp_socket_compliancy(s)) { return -1; } - current_int_tcp_socket = get_socket(s); + current_int_tcp_socket = socket_base_get_socket(s); current_tcp_socket = ¤t_int_tcp_socket->socket_values; /* Check for TCP_ESTABLISHED STATE */ @@ -811,7 +1024,7 @@ int32_t destiny_socket_send(int s, const void *buf, uint32_t len, int flags) /* Remember current time */ vtimer_now(¤t_tcp_socket->tcp_control.last_packet_time); - net_msg_receive(&recv_msg); + socket_base_net_msg_receive(&recv_msg); switch (recv_msg.type) { case TCP_ACK: { @@ -888,430 +1101,14 @@ int32_t destiny_socket_send(int s, const void *buf, uint32_t len, int flags) return sent_bytes; } -uint8_t read_from_socket(socket_internal_t *current_int_tcp_socket, - void *buf, int len) -{ - if (len >= current_int_tcp_socket->tcp_input_buffer_end) { - mutex_lock(¤t_int_tcp_socket->tcp_buffer_mutex); - uint8_t read_bytes = current_int_tcp_socket->tcp_input_buffer_end; - memcpy(buf, current_int_tcp_socket->tcp_input_buffer, - current_int_tcp_socket->tcp_input_buffer_end); - current_int_tcp_socket->tcp_input_buffer_end = 0; - current_int_tcp_socket->socket_values.tcp_control.rcv_wnd += read_bytes; - mutex_unlock(¤t_int_tcp_socket->tcp_buffer_mutex); - return read_bytes; - } - else { - mutex_lock(¤t_int_tcp_socket->tcp_buffer_mutex); - memcpy(buf, current_int_tcp_socket->tcp_input_buffer, len); - memmove(current_int_tcp_socket->tcp_input_buffer, - (current_int_tcp_socket->tcp_input_buffer + len), - current_int_tcp_socket->tcp_input_buffer_end - len); - current_int_tcp_socket->tcp_input_buffer_end = - current_int_tcp_socket->tcp_input_buffer_end - len; - current_int_tcp_socket->socket_values.tcp_control.rcv_wnd += len; - mutex_unlock(¤t_int_tcp_socket->tcp_buffer_mutex); - return len; - } -} - -int32_t destiny_socket_recv(int s, void *buf, uint32_t len, int flags) -{ - (void) flags; - - /* Variables */ - uint8_t read_bytes; - msg_t m_recv, m_send; - socket_internal_t *current_int_tcp_socket; - - /* Check if socket exists */ - if (!is_tcp_socket(s)) { - printf("INFO: NO TCP SOCKET!\n"); - return -1; - } - - current_int_tcp_socket = get_socket(s); - - /* Setting Thread PID */ - current_int_tcp_socket->recv_pid = thread_getpid(); - - if (current_int_tcp_socket->tcp_input_buffer_end > 0) { - return read_from_socket(current_int_tcp_socket, buf, len); - } - - msg_receive(&m_recv); - - if ((exists_socket(s)) && (current_int_tcp_socket->tcp_input_buffer_end > 0)) { - read_bytes = read_from_socket(current_int_tcp_socket, buf, len); - net_msg_reply(&m_recv, &m_send, UNDEFINED); - return read_bytes; - } - - /* Received FIN */ - if (m_recv.type == CLOSE_CONN) { - /* Sent FIN_ACK, wait for ACK */ - msg_receive(&m_recv); - /* Received ACK, return with closed socket!*/ - return -1; - } - - /* Received Last ACK (connection closed) or no data to read yet */ - return -1; -} - -int32_t destiny_socket_recvfrom(int s, void *buf, uint32_t len, int flags, - sockaddr6_t *from, uint32_t *fromlen) -{ - (void) flags; - - if (isUDPSocket(s)) { - msg_t m_recv, m_send; - ipv6_hdr_t *ipv6_header; - udp_hdr_t *udp_header; - uint8_t *payload; - get_socket(s)->recv_pid = thread_getpid(); - - msg_receive(&m_recv); - - ipv6_header = ((ipv6_hdr_t *)m_recv.content.ptr); - udp_header = ((udp_hdr_t *)(m_recv.content.ptr + IPV6_HDR_LEN)); - payload = (uint8_t *)(m_recv.content.ptr + IPV6_HDR_LEN + UDP_HDR_LEN); - - memset(buf, 0, len); - memcpy(buf, payload, NTOHS(udp_header->length) - UDP_HDR_LEN); - memcpy(&from->sin6_addr, &ipv6_header->srcaddr, 16); - from->sin6_family = AF_INET6; - from->sin6_flowinfo = 0; - from->sin6_port = NTOHS(udp_header->src_port); - *fromlen = sizeof(sockaddr6_t); - - msg_reply(&m_recv, &m_send); - return NTOHS(udp_header->length) - UDP_HDR_LEN; - } - else if (is_tcp_socket(s)) { - return destiny_socket_recv(s, buf, len, flags); - } - else { - printf("Socket Type not supported!\n"); - return -1; - } -} - -int32_t destiny_socket_sendto(int s, const void *buf, uint32_t len, int flags, - sockaddr6_t *to, uint32_t tolen) -{ - (void) flags; - (void) tolen; - - if (isUDPSocket(s) && - (get_socket(s)->socket_values.foreign_address.sin6_port == 0)) { - uint8_t send_buffer[BUFFER_SIZE]; - - ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); - udp_hdr_t *current_udp_packet = ((udp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); - uint8_t *payload = &send_buffer[IPV6_HDR_LEN + UDP_HDR_LEN]; - - memcpy(&(temp_ipv6_header->destaddr), &to->sin6_addr, 16); - ipv6_net_if_get_best_src_addr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr)); - - current_udp_packet->src_port = get_free_source_port(IPPROTO_UDP); - current_udp_packet->dst_port = to->sin6_port; - current_udp_packet->checksum = 0; - - memcpy(payload, buf, len); - current_udp_packet->length = HTONS(UDP_HDR_LEN + len); - temp_ipv6_header->length = UDP_HDR_LEN + len; - - current_udp_packet->checksum = ~ipv6_csum(temp_ipv6_header, - (uint8_t *) current_udp_packet, - UDP_HDR_LEN + len, - IPPROTO_UDP); - - return ipv6_sendto(&to->sin6_addr, IPPROTO_UDP, - (uint8_t *)(current_udp_packet), - NTOHS(current_udp_packet->length)); - } - else { - return -1; - } -} - -int destiny_socket_close(int s) -{ - socket_internal_t *current_socket = get_socket(s); - - if (current_socket != NULL) { - if (is_tcp_socket(s)) { - /* Variables */ - msg_t m_recv; - uint8_t send_buffer[BUFFER_SIZE]; - ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); - tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); - - /* Check if socket exists and is TCP socket */ - if (!is_tcp_socket(s)) { - return -1; - } - - /* Check for TCP_ESTABLISHED STATE */ - if (current_socket->socket_values.tcp_control.state != TCP_ESTABLISHED) { - close_socket(current_socket); - return 0; - } - - current_socket->send_pid = thread_getpid(); - - /* Refresh local TCP socket information */ - current_socket->socket_values.tcp_control.state = TCP_FIN_WAIT_1; -#ifdef TCP_HC - current_socket->socket_values.tcp_control.tcp_context.hc_type = - COMPRESSED_HEADER; -#endif - - send_tcp(current_socket, current_tcp_packet, temp_ipv6_header, - TCP_FIN_ACK, 0); - msg_receive(&m_recv); - close_socket(current_socket); - return 1; - } - else if (isUDPSocket(s)) { - close_socket(current_socket); - return 0; - } - - return -1; - } - else { - return -1; - } -} - -int destiny_socket_bind(int s, sockaddr6_t *addr, int addrlen) -{ - if (exists_socket(s)) { - socket_t *current_socket = &get_socket(s)->socket_values; - - switch (current_socket->domain) { - case (PF_INET): { - /* Not provided */ - return -1; - break; - } - - case (PF_INET6): { - switch (current_socket->type) { - /* TCP */ - case (SOCK_STREAM): { - if ((current_socket->protocol == 0) || - (current_socket->protocol == IPPROTO_TCP)) { - return bind_tcp_socket(s, addr, addrlen, - thread_getpid()); - break; - } - else { - return -1; - break; - } - - break; - } - - /* UDP */ - case (SOCK_DGRAM): { - if ((current_socket->protocol == 0) || - (current_socket->protocol == IPPROTO_UDP)) { - return bind_udp_socket(s, addr, addrlen, - thread_getpid()); - break; - } - else { - return -1; - break; - } - - break; - } - - case (SOCK_SEQPACKET): { - /* not provided */ - return -1; - break; - } - - case (SOCK_RAW): { - /* not provided */ - return -1; - break; - } - - default: { - return -1; - break; - } - } - - break; - } - - case (PF_UNIX): { - /* Not provided */ - return -1; - break; - } - } - } - else { - printf("SOCKET DOES NOT EXIST!\n"); - return -1; - } - - return -1; -} - -int destiny_socket_listen(int s, int backlog) -{ - (void) backlog; - - if (is_tcp_socket(s) && get_socket(s)->socket_values.tcp_control.state == TCP_CLOSED) { - socket_internal_t *current_socket = get_socket(s); - current_socket->socket_values.tcp_control.state = TCP_LISTEN; - return 0; - } - else { - return -1; - } -} - -socket_internal_t *get_waiting_connection_socket(int socket, - ipv6_hdr_t *ipv6_header, - tcp_hdr_t *tcp_header) -{ - int i; - socket_internal_t *current_socket, *listening_socket = get_socket(socket); - - for (i = 1; i < MAX_SOCKETS + 1; i++) { - current_socket = get_socket(i); - - if (!current_socket) { - continue; - } - - /* Connection establishment ACK, Check for 4 touple and state */ - if ((ipv6_header != NULL) && (tcp_header != NULL)) { - if (is_four_touple(current_socket, ipv6_header, tcp_header) && - (current_socket->socket_values.tcp_control.state == TCP_SYN_RCVD)) { - return current_socket; - } - } - /* Connection establishment SYN ACK, check only for port and state */ - else { - if ((current_socket->socket_values.tcp_control.state == TCP_SYN_RCVD) && - (current_socket->socket_values.local_address.sin6_port == - listening_socket->socket_values.local_address.sin6_port)) { - return current_socket; - } - } - } - - return NULL; -} - -int handle_new_tcp_connection(socket_internal_t *current_queued_int_socket, - socket_internal_t *server_socket, kernel_pid_t pid) -{ - (void) pid; - - msg_t msg_recv_client_ack, msg_send_client_ack; - socket_t *current_queued_socket = ¤t_queued_int_socket->socket_values; - uint8_t send_buffer[BUFFER_SIZE]; - ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); - tcp_hdr_t *syn_ack_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); - - current_queued_int_socket->recv_pid = thread_getpid(); -#ifdef TCP_HC - current_queued_int_socket->socket_values.tcp_control.tcp_context.hc_type = - FULL_HEADER; - memcpy(¤t_queued_int_socket->socket_values.tcp_control.tcp_context.context_id, - &server_socket->socket_values.tcp_control.tcp_context.context_id, - sizeof(server_socket->socket_values.tcp_control.tcp_context.context_id)); -#endif - /* Remember current time */ - timex_t now; - vtimer_now(&now); - current_queued_int_socket->socket_values.tcp_control.last_packet_time = now; - - current_queued_int_socket->socket_values.tcp_control.no_of_retries = 0; - - /* Set message type to Retry for while loop */ - msg_recv_client_ack.type = TCP_RETRY; - - while (msg_recv_client_ack.type == TCP_RETRY) { - /* Send packet */ - send_tcp(current_queued_int_socket, syn_ack_packet, temp_ipv6_header, - TCP_SYN_ACK, 0); - - /* wait for ACK from Client */ - msg_receive(&msg_recv_client_ack); - - if (msg_recv_client_ack.type == TCP_TIMEOUT) { - /* Set status of internal socket back to TCP_LISTEN */ - server_socket->socket_values.tcp_control.state = TCP_LISTEN; - - close_socket(current_queued_int_socket); - return -1; - } - } - - tcp_hdr_t *tcp_header; - - tcp_header = ((tcp_hdr_t *)(msg_recv_client_ack.content.ptr)); - - /* Check for consistency */ - if (tcp_header->ack_nr != current_queued_socket->tcp_control.send_nxt) { - printf("TCP packets not consistent!\n"); - } - - /* Got ack, connection established, refresh local and foreign tcp socket - * status */ - set_tcp_cb(¤t_queued_socket->tcp_control, tcp_header->seq_nr, - current_queued_socket->tcp_control.rcv_wnd, tcp_header->ack_nr, - tcp_header->ack_nr, tcp_header->window); - -#ifdef TCP_HC - /* Copy TCP context information into new socket */ - memset(&server_socket->socket_values.tcp_control.tcp_context, 0, - sizeof(tcp_hc_context_t)); -#endif - - /* Update connection status information */ - current_queued_socket->tcp_control.state = TCP_ESTABLISHED; - - /* Set status of internal socket back to TCP_LISTEN */ - server_socket->socket_values.tcp_control.state = TCP_LISTEN; - - /* send a reply to the TCP handler after processing every information from - * the TCP ACK packet */ - msg_reply(&msg_recv_client_ack, &msg_send_client_ack); - - /* Reset PID to an invalid value */ - current_queued_int_socket->recv_pid = KERNEL_PID_UNDEF; - - /* Waiting for Clients ACK waiting period to time out */ - vtimer_usleep(TCP_SYN_INITIAL_TIMEOUT / 2); - - destiny_socket_print_sockets(); - - return current_queued_int_socket->socket_id; -} - -int destiny_socket_accept(int s, sockaddr6_t *addr, uint32_t *addrlen) +int tcp_accept(int s, sockaddr6_t *addr, uint32_t *addrlen) { (void) addr; (void) addrlen; - socket_internal_t *server_socket = get_socket(s); + socket_internal_t *server_socket = socket_base_get_socket(s); - if (is_tcp_socket(s) && (server_socket->socket_values.tcp_control.state == TCP_LISTEN)) { + if (tcp_socket_compliancy(s) && (server_socket->socket_values.tcp_control.state == TCP_LISTEN)) { socket_internal_t *current_queued_socket = get_waiting_connection_socket(s, NULL, NULL); @@ -1339,46 +1136,311 @@ int destiny_socket_accept(int s, sockaddr6_t *addr, uint32_t *addrlen) } } -socket_internal_t *new_tcp_queued_socket(ipv6_hdr_t *ipv6_header, - tcp_hdr_t *tcp_header) +int tcp_connect(int socket, sockaddr6_t *addr, uint32_t addrlen) { - int queued_socket_id; + (void) addrlen; - queued_socket_id = destiny_socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); - socket_internal_t *current_queued_socket = get_socket(queued_socket_id); + /* Variables */ + ipv6_addr_t src_addr; + socket_internal_t *current_int_tcp_socket; + socket_t *current_tcp_socket; + msg_t msg_from_server; + uint8_t send_buffer[BUFFER_SIZE]; + ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); + tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); - /* Foreign address */ - set_socket_address(¤t_queued_socket->socket_values.foreign_address, - AF_INET6, tcp_header->src_port, ipv6_header->flowlabel, - &ipv6_header->srcaddr); + /* Check if socket exists */ + current_int_tcp_socket = socket_base_get_socket(socket); - /* Local address */ - set_socket_address(¤t_queued_socket->socket_values.local_address, - AF_INET6, tcp_header->dst_port, 0, - &ipv6_header->destaddr); + if (current_int_tcp_socket == NULL) { + return -1; + } - /* Foreign TCP information */ + current_tcp_socket = ¤t_int_tcp_socket->socket_values; + + current_int_tcp_socket->recv_pid = thread_getpid(); + + /* Local address information */ + ipv6_net_if_get_best_src_addr(&src_addr, &addr->sin6_addr); + set_socket_address(¤t_tcp_socket->local_address, PF_INET6, + HTONS(socket_base_get_free_source_port(IPPROTO_TCP)), 0, &src_addr); + + /* Foreign address information */ + set_socket_address(¤t_tcp_socket->foreign_address, addr->sin6_family, + addr->sin6_port, addr->sin6_flowinfo, &addr->sin6_addr); + + /* Fill lcoal TCP socket information */ + srand(addr->sin6_port); + + current_tcp_socket->tcp_control.rcv_irs = 0; + mutex_lock(&global_sequence_counter_mutex); + current_tcp_socket->tcp_control.send_iss = global_sequence_counter; + mutex_unlock(&global_sequence_counter_mutex); + current_tcp_socket->tcp_control.state = TCP_SYN_SENT; + +#ifdef TCP_HC + /* Choosing random number Context ID */ + mutex_lock(&global_context_counter_mutex); + current_tcp_socket->tcp_control.tcp_context.context_id = global_context_counter; + mutex_unlock(&global_context_counter_mutex); + + current_tcp_socket->tcp_control.tcp_context.hc_type = FULL_HEADER; + + /* Remember TCP Context for possible TCP_RETRY */ + tcp_hc_context_t saved_tcp_context; + memcpy(&saved_tcp_context, ¤t_tcp_socket->tcp_control.tcp_context, + sizeof(tcp_hc_context_t)); +#endif + + set_tcp_cb(¤t_tcp_socket->tcp_control, 0, TRANSPORT_LAYER_SOCKET_STATIC_WINDOW, + current_tcp_socket->tcp_control.send_iss + 1, + current_tcp_socket->tcp_control.send_iss, 0); + + /* Remember current time */ + timex_t now; + vtimer_now(&now); + current_tcp_socket->tcp_control.last_packet_time = now; + current_tcp_socket->tcp_control.no_of_retries = 0; + + msg_from_server.type = TCP_RETRY; + + while (msg_from_server.type == TCP_RETRY) { + /* Send packet */ + send_tcp(current_int_tcp_socket, current_tcp_packet, temp_ipv6_header, + TCP_SYN, 0); + + /* wait for SYN ACK or RETRY */ + msg_receive(&msg_from_server); + + if (msg_from_server.type == TCP_TIMEOUT) { +#ifdef TCP_HC + /* We did not send anything successful so restore last context */ + memcpy(¤t_tcp_socket->tcp_control.tcp_context, + &saved_tcp_context, sizeof(tcp_hc_context_t)); +#endif + return -1; + } + +#ifdef TCP_HC + else if (msg_from_server.type == TCP_RETRY) { + /* We retry sending a packet so set everything to last values again */ + memcpy(¤t_tcp_socket->tcp_control.tcp_context, + &saved_tcp_context, sizeof(tcp_hc_context_t)); + } + +#endif + } + + /* Read packet content */ + tcp_hdr_t *tcp_header = ((tcp_hdr_t *)(msg_from_server.content.ptr)); + + /* Check for consistency */ + if (tcp_header->ack_nr != current_tcp_socket->tcp_control.send_nxt) { + printf("TCP packets not consistent!\n"); + } + + /* Got SYN ACK from Server */ + /* Refresh foreign TCP socket information */ if ((tcp_header->data_offset * 4 > TCP_HDR_LEN) && (*(((uint8_t *)tcp_header) + TCP_HDR_LEN) == TCP_MSS_OPTION)) { - current_queued_socket->socket_values.tcp_control.mss = + current_tcp_socket->tcp_control.mss = *((uint16_t *)(((uint8_t *)tcp_header) + TCP_HDR_LEN + 2)); } else { - current_queued_socket->socket_values.tcp_control.mss = DESTINY_SOCKET_STATIC_MSS; + current_tcp_socket->tcp_control.mss = TRANSPORT_LAYER_SOCKET_STATIC_MSS; } - current_queued_socket->socket_values.tcp_control.rcv_irs = - tcp_header->seq_nr; - mutex_lock(&global_sequence_counter_mutex); - current_queued_socket->socket_values.tcp_control.send_iss = - global_sequence_counter; - mutex_unlock(&global_sequence_counter_mutex); - current_queued_socket->socket_values.tcp_control.state = TCP_SYN_RCVD; - set_tcp_cb(¤t_queued_socket->socket_values.tcp_control, - tcp_header->seq_nr + 1, DESTINY_SOCKET_STATIC_WINDOW, - current_queued_socket->socket_values.tcp_control.send_iss + 1, - current_queued_socket->socket_values.tcp_control.send_iss, + current_tcp_socket->tcp_control.rcv_irs = tcp_header->seq_nr; + set_tcp_cb(¤t_tcp_socket->tcp_control, tcp_header->seq_nr + 1, + current_tcp_socket->tcp_control.rcv_wnd, + current_tcp_socket->tcp_control.send_una + 1, + tcp_header->ack_nr, tcp_header->window); - return current_queued_socket; + msg_from_server.type = UNDEFINED; + + /* Remember current time */ + vtimer_now(&now); + current_tcp_socket->tcp_control.last_packet_time = now; + current_tcp_socket->tcp_control.no_of_retries = 0; + +#ifdef TCP_HC + current_tcp_socket->tcp_control.tcp_context.hc_type = FULL_HEADER; + /* Remember TCP Context for possible TCP_RETRY */ + memcpy(&saved_tcp_context, ¤t_tcp_socket->tcp_control.tcp_context, + sizeof(tcp_hc_context_t)); +#endif + + while (msg_from_server.type != TCP_RETRY) { + /* Send packet */ + send_tcp(current_int_tcp_socket, current_tcp_packet, temp_ipv6_header, + TCP_ACK, 0); + + msg_receive(&msg_from_server); +#ifdef TCP_HC + + if (msg_from_server.type == TCP_SYN_ACK) { + /* TCP_SYN_ACK from server arrived again, copy old context and + * send TCP_ACK again */ + memcpy(¤t_tcp_socket->tcp_control.tcp_context, + &saved_tcp_context, sizeof(tcp_hc_context_t)); + } + else if (msg_from_server.type == TCP_RETRY) { + /* We waited for RTT, no TCP_SYN_ACK received, so we assume the + * TCP_ACK packet arrived safely */ + } + +#endif + } + + current_tcp_socket->tcp_control.state = TCP_ESTABLISHED; + + current_int_tcp_socket->recv_pid = 255; + + socket_base_print_sockets(); + return 0; +} + +uint8_t read_from_socket(socket_internal_t *current_int_tcp_socket, + void *buf, int len) +{ + if (len >= current_int_tcp_socket->tcp_input_buffer_end) { + mutex_lock(¤t_int_tcp_socket->tcp_buffer_mutex); + uint8_t read_bytes = current_int_tcp_socket->tcp_input_buffer_end; + memcpy(buf, current_int_tcp_socket->tcp_input_buffer, + current_int_tcp_socket->tcp_input_buffer_end); + current_int_tcp_socket->tcp_input_buffer_end = 0; + current_int_tcp_socket->socket_values.tcp_control.rcv_wnd += read_bytes; + mutex_unlock(¤t_int_tcp_socket->tcp_buffer_mutex); + return read_bytes; + } + else { + mutex_lock(¤t_int_tcp_socket->tcp_buffer_mutex); + memcpy(buf, current_int_tcp_socket->tcp_input_buffer, len); + memmove(current_int_tcp_socket->tcp_input_buffer, + (current_int_tcp_socket->tcp_input_buffer + len), + current_int_tcp_socket->tcp_input_buffer_end - len); + current_int_tcp_socket->tcp_input_buffer_end = + current_int_tcp_socket->tcp_input_buffer_end - len; + current_int_tcp_socket->socket_values.tcp_control.rcv_wnd += len; + mutex_unlock(¤t_int_tcp_socket->tcp_buffer_mutex); + return len; + } +} + +int32_t tcp_recv(int s, void *buf, uint32_t len, int flags) +{ + (void) flags; + + /* Variables */ + uint8_t read_bytes; + msg_t m_recv, m_send; + socket_internal_t *current_int_tcp_socket; + + /* Check if socket exists */ + if (!tcp_socket_compliancy(s)) { + printf("INFO: NO TCP SOCKET!\n"); + return -1; + } + + current_int_tcp_socket = socket_base_get_socket(s); + + /* Setting Thread PID */ + current_int_tcp_socket->recv_pid = thread_getpid(); + + if (current_int_tcp_socket->tcp_input_buffer_end > 0) { + return read_from_socket(current_int_tcp_socket, buf, len); + } + + msg_receive(&m_recv); + + if ((socket_base_exists_socket(s)) && (current_int_tcp_socket->tcp_input_buffer_end > 0)) { + read_bytes = read_from_socket(current_int_tcp_socket, buf, len); + socket_base_net_msg_reply(&m_recv, &m_send, UNDEFINED); + return read_bytes; + } + + /* Received FIN */ + if (m_recv.type == CLOSE_CONN) { + /* Sent FIN_ACK, wait for ACK */ + msg_receive(&m_recv); + /* Received ACK, return with closed socket!*/ + return -1; + } + + /* Received Last ACK (connection closed) or no data to read yet */ + return -1; +} + +int tcp_listen(int s, int backlog) +{ + (void) backlog; + + if (tcp_socket_compliancy(s) && socket_base_get_socket(s)->socket_values.tcp_control.state == TCP_CLOSED) { + socket_internal_t *current_socket = socket_base_get_socket(s); + current_socket->socket_values.tcp_control.state = TCP_LISTEN; + return 0; + } + else { + return -1; + } +} + +int tcp_teardown(socket_internal_t *current_socket) +{ + /* Variables */ + msg_t m_recv; + uint8_t send_buffer[BUFFER_SIZE]; + ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); + tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); + + /* Check for TCP_ESTABLISHED STATE */ + if (current_socket->socket_values.tcp_control.state != TCP_ESTABLISHED) { + memset(current_socket, 0, sizeof(socket_internal_t)); + return 0; + } + + current_socket->send_pid = thread_getpid(); + + /* Refresh local TCP socket information */ + current_socket->socket_values.tcp_control.state = TCP_FIN_WAIT_1; +#ifdef TCP_HC + current_socket->socket_values.tcp_control.tcp_context.hc_type = + COMPRESSED_HEADER; +#endif + + send_tcp(current_socket, current_tcp_packet, temp_ipv6_header, + TCP_FIN_ACK, 0); + msg_receive(&m_recv); + memset(current_socket, 0, sizeof(socket_internal_t)); + return 1; +} + +int tcp_init_transport_layer(void) +{ + printf("Initializing transport layer protocol: tcp\n"); + timex_t now; + vtimer_now(&now); + srand(timex_uint64(now)); +#ifdef TCP_HC + printf("TCP_HC enabled!\n"); + global_context_counter = rand(); +#endif + global_sequence_counter = rand(); + + int tcp_thread_pid = thread_create(tcp_stack_buffer, TCP_STACK_SIZE, + PRIORITY_MAIN, CREATE_STACKTEST, tcp_packet_handler, NULL, "tcp_packet_handler"); + + if (tcp_thread_pid < 0) { + return -1; + } + + ipv6_register_next_header_handler(IPV6_PROTO_NUM_TCP, tcp_thread_pid); + + if (thread_create(tcp_timer_stack, TCP_TIMER_STACKSIZE, PRIORITY_MAIN + 1, + CREATE_STACKTEST, tcp_general_timer, NULL, "tcp_general_timer") < 0) { + return -1; + } + + return 0; } diff --git a/sys/net/transport_layer/destiny/tcp.h b/sys/net/transport_layer/tcp/tcp.h similarity index 83% rename from sys/net/transport_layer/destiny/tcp.h rename to sys/net/transport_layer/tcp/tcp.h index 85e0496d14..9138d750a0 100644 --- a/sys/net/transport_layer/destiny/tcp.h +++ b/sys/net/transport_layer/tcp/tcp.h @@ -1,5 +1,5 @@ /** - * Destiny TCP header + * TCP header * * Copyright (C) 2013 INRIA. * @@ -7,7 +7,7 @@ * General Public License v2.1. See the file LICENSE in the top level * directory for more details. * - * @ingroup destiny + * @ingroup transport_layer * @{ * @file * @brief TCP data structs and prototypes @@ -18,7 +18,8 @@ #define TCP_H_ #include "ipv6.h" -#include "destiny/types.h" +#include "socket_base/types.h" +#include "socket.h" #define TCP_EOO_OPTION (0x00) /* End of option list */ #define TCP_NOP_OPTION (0x01) /* No operation */ @@ -96,10 +97,16 @@ extern uint8_t global_context_counter; extern mutex_t global_sequence_counter_mutex; extern uint32_t global_sequence_counter; -void *tcp_packet_handler(void *); -uint16_t tcp_csum(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header); -void printTCPHeader(tcp_hdr_t *tcp_header); -void printArrayRange_tcp(uint8_t *udp_header, uint16_t len); +/* methods usde by socket_base */ +int tcp_bind_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid); +bool tcp_socket_compliancy(int s); +int32_t tcp_send(int s, const void *buf, uint32_t len, int flags); +int tcp_accept(int s, sockaddr6_t *addr, socklen_t *addrlen); +int tcp_connect(int socket, sockaddr6_t *addr, uint32_t addrlen); +int tcp_listen(int s, int backlog); +int32_t tcp_recv(int s, void *buf, uint32_t len, int flags); +bool tcp_socket_compliancy(int s); +int tcp_teardown(socket_internal_t *current_socket); /** * @} diff --git a/sys/net/transport_layer/destiny/tcp_hc.c b/sys/net/transport_layer/tcp/tcp_hc.c similarity index 99% rename from sys/net/transport_layer/destiny/tcp_hc.c rename to sys/net/transport_layer/tcp/tcp_hc.c index 0f05714f15..14684239c3 100644 --- a/sys/net/transport_layer/destiny/tcp_hc.c +++ b/sys/net/transport_layer/tcp/tcp_hc.c @@ -1,5 +1,5 @@ /** - * Destiny TCP header compression + * TCP header compression * * Copyright (C) 2013 INRIA. * @@ -7,7 +7,7 @@ * General Public License v2.1. See the file LICENSE in the top level * directory for more details. * - * @ingroup destiny + * @ingroup transport_layer * @{ * @file tcp_hc.c * @brief TCP HC @@ -37,7 +37,7 @@ socket_internal_t *get_tcp_socket_by_context(ipv6_hdr_t *current_ipv6_header, socket_internal_t *temp_socket; for (int i = 1; i < MAX_SOCKETS + 1; i++) { - temp_socket = get_socket(i); + temp_socket = socket_base_get_socket(i); if ((temp_socket != NULL) && ipv6_addr_is_equal(&temp_socket->socket_values.foreign_address.sin6_addr, diff --git a/sys/net/transport_layer/destiny/tcp_hc.h b/sys/net/transport_layer/tcp/tcp_hc.h similarity index 96% rename from sys/net/transport_layer/destiny/tcp_hc.h rename to sys/net/transport_layer/tcp/tcp_hc.h index df9e2fa344..685874426d 100644 --- a/sys/net/transport_layer/destiny/tcp_hc.h +++ b/sys/net/transport_layer/tcp/tcp_hc.h @@ -16,7 +16,7 @@ #include "sixlowpan.h" -#include "destiny/socket.h" +#include "socket_base/socket.h" #include "tcp.h" diff --git a/sys/net/transport_layer/destiny/tcp_timer.c b/sys/net/transport_layer/tcp/tcp_timer.c similarity index 86% rename from sys/net/transport_layer/destiny/tcp_timer.c rename to sys/net/transport_layer/tcp/tcp_timer.c index 615e591e41..f5d63a7fd0 100644 --- a/sys/net/transport_layer/destiny/tcp_timer.c +++ b/sys/net/transport_layer/tcp/tcp_timer.c @@ -1,5 +1,5 @@ /** - * Destiny TCP timer implementation + * TCP timer implementation * * Copyright (C) 2013 INRIA. * @@ -7,7 +7,7 @@ * General Public License v2.1. See the file LICENSE in the top level * directory for more details. * - * @ingroup destiny + * @ingroup transport_layer * @{ * @file tcp_timer.c * @brief TCP timer @@ -23,11 +23,10 @@ #include "thread.h" #include "vtimer.h" -#include "destiny.h" - #include "msg_help.h" #include "socket.h" +#include "tcp.h" #include "tcp_timer.h" void handle_synchro_timeout(socket_internal_t *current_socket) @@ -41,7 +40,7 @@ void handle_synchro_timeout(socket_internal_t *current_socket) if ((current_socket->socket_values.tcp_control.no_of_retries == 0) && (timex_uint64(timex_sub(now, current_socket->socket_values.tcp_control.last_packet_time)) > TCP_SYN_INITIAL_TIMEOUT)) { current_socket->socket_values.tcp_control.no_of_retries++; - net_msg_send(&send, current_socket->recv_pid, 0, TCP_RETRY); + socket_base_net_msg_send(&send, current_socket->recv_pid, 0, TCP_RETRY); } else if ((current_socket->socket_values.tcp_control.no_of_retries > 0) && (timex_uint64(timex_sub(now, current_socket->socket_values.tcp_control.last_packet_time)) > @@ -51,10 +50,10 @@ void handle_synchro_timeout(socket_internal_t *current_socket) if (current_socket->socket_values.tcp_control.no_of_retries > TCP_MAX_SYN_RETRIES) { - net_msg_send(&send, current_socket->recv_pid, 0, TCP_TIMEOUT); + socket_base_net_msg_send(&send, current_socket->recv_pid, 0, TCP_TIMEOUT); } else { - net_msg_send(&send, current_socket->recv_pid, 0, TCP_RETRY); + socket_base_net_msg_send(&send, current_socket->recv_pid, 0, TCP_RETRY); } } } @@ -83,12 +82,12 @@ void handle_established(socket_internal_t *current_socket) vtimer_now(&now); if (current_timeout > TCP_ACK_MAX_TIMEOUT) { - net_msg_send(&send, current_socket->send_pid, 0, TCP_TIMEOUT); + socket_base_net_msg_send(&send, current_socket->send_pid, 0, TCP_TIMEOUT); } else if (timex_uint64(timex_sub(now, current_socket->socket_values.tcp_control.last_packet_time)) > current_timeout) { current_socket->socket_values.tcp_control.no_of_retries++; - net_msg_send(&send, current_socket->send_pid, 0, TCP_RETRY); + socket_base_net_msg_send(&send, current_socket->send_pid, 0, TCP_RETRY); } } } @@ -99,9 +98,9 @@ void check_sockets(void) uint8_t i = 1; while (i < MAX_SOCKETS + 1) { - current_socket = get_socket(i); + current_socket = socket_base_get_socket(i); - if (is_tcp_socket(i)) { + if (tcp_socket_compliancy(i)) { switch (current_socket->socket_values.tcp_control.state) { case TCP_ESTABLISHED: { handle_established(current_socket); diff --git a/sys/net/transport_layer/destiny/tcp_timer.h b/sys/net/transport_layer/tcp/tcp_timer.h similarity index 100% rename from sys/net/transport_layer/destiny/tcp_timer.h rename to sys/net/transport_layer/tcp/tcp_timer.h diff --git a/sys/net/transport_layer/udp/Makefile b/sys/net/transport_layer/udp/Makefile new file mode 100644 index 0000000000..8978e06912 --- /dev/null +++ b/sys/net/transport_layer/udp/Makefile @@ -0,0 +1,2 @@ +INCLUDES += -I $(RIOTBASE)/sys/net/transport_layer/socket_base +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/transport_layer/udp/udp.c b/sys/net/transport_layer/udp/udp.c new file mode 100644 index 0000000000..2d39738a66 --- /dev/null +++ b/sys/net/transport_layer/udp/udp.c @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2013, 2014 INRIA. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup udp + * @{ + * @file udp.c + * @brief UDP implementation + * @author Oliver Gesch + * @author Cenk Gündoğan + * @} + */ + +#include +#include + +#include "ipv6.h" +#include "msg.h" +#include "sixlowpan.h" +#include "thread.h" + +#include "socket_base/in.h" + +#include "net_help.h" + +#include "msg_help.h" +#include "socket.h" + +#include "udp.h" + +msg_t udp_msg_queue[UDP_PKT_RECV_BUF_SIZE]; + +char udp_stack_buffer[UDP_STACK_SIZE]; + +uint16_t udp_csum(ipv6_hdr_t *ipv6_header, udp_hdr_t *udp_header) +{ + uint16_t sum; + uint16_t len = NTOHS(udp_header->length); + + sum = len + IPPROTO_UDP; + sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t)); + sum = csum(sum, (uint8_t *)udp_header, len); + return (sum == 0) ? 0xffff : HTONS(sum); +} + +socket_internal_t *get_udp_socket(udp_hdr_t *udp_header) +{ + uint8_t i = 1; + + while (i < MAX_SOCKETS + 1) { + if (udp_socket_compliancy(i) && + (socket_base_get_socket(i)->socket_values.local_address.sin6_port == + udp_header->dst_port)) { + return socket_base_get_socket(i); + } + + i++; + } + + return NULL; +} + +void *udp_packet_handler(void *arg) +{ + (void) arg; + + msg_t m_recv_ip, m_send_ip, m_recv_udp, m_send_udp; + ipv6_hdr_t *ipv6_header; + udp_hdr_t *udp_header; + socket_internal_t *udp_socket = NULL; + uint16_t chksum; + + msg_init_queue(udp_msg_queue, UDP_PKT_RECV_BUF_SIZE); + + while (1) { + msg_receive(&m_recv_ip); + ipv6_header = ((ipv6_hdr_t *)m_recv_ip.content.ptr); + udp_header = ((udp_hdr_t *)(m_recv_ip.content.ptr + IPV6_HDR_LEN)); + + chksum = ipv6_csum(ipv6_header, (uint8_t*) udp_header, NTOHS(udp_header->length), IPPROTO_UDP); + + if (chksum == 0xffff) { + udp_socket = get_udp_socket(udp_header); + + if (udp_socket != NULL) { + m_send_udp.content.ptr = (char *)ipv6_header; + msg_send_receive(&m_send_udp, &m_recv_udp, udp_socket->recv_pid); + } + else { + printf("Dropped UDP Message because no thread ID was found for delivery!\n"); + } + } + else { + printf("Wrong checksum (%x)!\n", chksum); + } + + msg_reply(&m_recv_ip, &m_send_ip); + } +} + +bool udp_socket_compliancy(int s) +{ + if ((socket_base_exists_socket(s)) && + (socket_base_get_socket(s)->socket_values.domain == PF_INET6) && + (socket_base_get_socket(s)->socket_values.type == SOCK_DGRAM) && + ((socket_base_get_socket(s)->socket_values.protocol == IPPROTO_UDP) || + (socket_base_get_socket(s)->socket_values.protocol == 0))) { + return true; + } + else { + return false; + } +} + +int udp_bind_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid) +{ + int i; + + if (!socket_base_exists_socket(s)) { + return -1; + } + + for (i = 1; i < MAX_SOCKETS + 1; i++) { + if (udp_socket_compliancy(i) && + (socket_base_get_socket(i)->socket_values.local_address.sin6_port == name->sin6_port)) { + return -1; + } + } + + memcpy(&socket_base_get_socket(s)->socket_values.local_address, name, namelen); + socket_base_get_socket(s)->recv_pid = pid; + return 0; +} + +int32_t udp_recvfrom(int s, void *buf, uint32_t len, int flags, sockaddr6_t *from, uint32_t *fromlen) +{ + (void) flags; + + msg_t m_recv, m_send; + ipv6_hdr_t *ipv6_header; + udp_hdr_t *udp_header; + uint8_t *payload; + socket_base_get_socket(s)->recv_pid = thread_getpid(); + + msg_receive(&m_recv); + + ipv6_header = ((ipv6_hdr_t *)m_recv.content.ptr); + udp_header = ((udp_hdr_t *)(m_recv.content.ptr + IPV6_HDR_LEN)); + payload = (uint8_t *)(m_recv.content.ptr + IPV6_HDR_LEN + UDP_HDR_LEN); + + memset(buf, 0, len); + memcpy(buf, payload, NTOHS(udp_header->length) - UDP_HDR_LEN); + memcpy(&from->sin6_addr, &ipv6_header->srcaddr, 16); + from->sin6_family = AF_INET6; + from->sin6_flowinfo = 0; + from->sin6_port = NTOHS(udp_header->src_port); + *fromlen = sizeof(sockaddr6_t); + + msg_reply(&m_recv, &m_send); + return NTOHS(udp_header->length) - UDP_HDR_LEN; +} + +int32_t udp_sendto(int s, const void *buf, uint32_t len, int flags, + sockaddr6_t *to, uint32_t tolen) +{ + (void) flags; + (void) tolen; + + if (udp_socket_compliancy(s) && + (socket_base_get_socket(s)->socket_values.foreign_address.sin6_port == 0)) { + uint8_t send_buffer[BUFFER_SIZE]; + + ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); + udp_hdr_t *current_udp_packet = ((udp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); + uint8_t *payload = &send_buffer[IPV6_HDR_LEN + UDP_HDR_LEN]; + + memcpy(&(temp_ipv6_header->destaddr), &to->sin6_addr, 16); + ipv6_net_if_get_best_src_addr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr)); + + current_udp_packet->src_port = socket_base_get_free_source_port(IPPROTO_UDP); + current_udp_packet->dst_port = to->sin6_port; + current_udp_packet->checksum = 0; + + memcpy(payload, buf, len); + current_udp_packet->length = HTONS(UDP_HDR_LEN + len); + temp_ipv6_header->length = UDP_HDR_LEN + len; + + current_udp_packet->checksum = ~ipv6_csum(temp_ipv6_header, + (uint8_t *) current_udp_packet, + UDP_HDR_LEN + len, + IPPROTO_UDP); + + return ipv6_sendto(&to->sin6_addr, IPPROTO_UDP, + (uint8_t *)(current_udp_packet), + NTOHS(current_udp_packet->length)); + } + else { + return -1; + } +} + +int udp_init_transport_layer(void) +{ + printf("Initializing transport layer protocol: udp\n"); + /* SOCKETS */ + memset(socket_base_sockets, 0, MAX_SOCKETS * sizeof(socket_internal_t)); + + int udp_thread_pid = thread_create(udp_stack_buffer, UDP_STACK_SIZE, PRIORITY_MAIN, + CREATE_STACKTEST, udp_packet_handler, NULL, "udp_packet_handler"); + + if (udp_thread_pid < 0) { + return -1; + } + + ipv6_register_next_header_handler(IPV6_PROTO_NUM_UDP, udp_thread_pid); + + return 0; +} diff --git a/sys/net/transport_layer/udp/udp.h b/sys/net/transport_layer/udp/udp.h new file mode 100644 index 0000000000..5c66b850c7 --- /dev/null +++ b/sys/net/transport_layer/udp/udp.h @@ -0,0 +1,38 @@ +/** + * UDP header + * + * Copyright (C) 2013 INRIA. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + * + * @ingroup transport_layer + * @{ + * @file + * @brief UDP data structs and prototypes + * @author Oliver Gesch + */ + + +#ifndef UDP_H_ +#define UDP_H_ + +#include "ipv6.h" +#include "socket_base/types.h" + +#define UDP_STACK_SIZE KERNEL_CONF_STACKSIZE_MAIN +#define UDP_PKT_RECV_BUF_SIZE (64) + +int udp_bind_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid); +int32_t udp_recvfrom(int s, void *buf, uint32_t len, int flags, sockaddr6_t *from, uint32_t *fromlen); +int32_t udp_sendto(int s, const void *buf, uint32_t len, int flags, sockaddr6_t *to, uint32_t tolen); +bool udp_socket_compliancy(int s); +int32_t udp_recvfrom(int s, void *buf, uint32_t len, int flags, sockaddr6_t *from, uint32_t *fromlen); +int32_t udp_sendto(int s, const void *buf, uint32_t len, int flags, sockaddr6_t *to, socklen_t tolen); + +/** + * @} + */ + +#endif /* UDP_H_ */ diff --git a/sys/posix/pnet/include/netinet/in.h b/sys/posix/pnet/include/netinet/in.h index 3f7e460d2f..586444e53d 100644 --- a/sys/posix/pnet/include/netinet/in.h +++ b/sys/posix/pnet/include/netinet/in.h @@ -27,7 +27,7 @@ #include #include #include "ipv6.h" -#include "destiny/socket.h" +#include "socket_base/socket.h" /** * IPv4 socket address type. diff --git a/sys/posix/pnet/include/sys/socket.h b/sys/posix/pnet/include/sys/socket.h index e1f88bfca2..6edc36a78a 100644 --- a/sys/posix/pnet/include/sys/socket.h +++ b/sys/posix/pnet/include/sys/socket.h @@ -36,7 +36,7 @@ #include "cpu.h" -#include "destiny/socket.h" +#include "socket_base/socket.h" /** * @brief Used to define the socket address. @@ -449,10 +449,10 @@ int setsockopt(int socket, int level, int option_name, const void *option_value, * * @param[in] domain Specifies the communications domain in which a socket * is to be created. Valid values are prefixed with ``AF_` - * and defined in @ref destiny/socket.h. + * and defined in @ref transport_layer/socket.h. * @param[in] type Specifies the type of socket to be created. Valued * values are prefixed with ``SOCK_`` and defined in - * @ref destiny/socket.h. + * @ref transport_layer/socket.h. * @param[in] protocol Specifies a particular protocol to be used with the * socket. Specifying a protocol of 0 causes socket() to * use an unspecified default protocol appropriate for diff --git a/sys/posix/pnet/sys_socket.c b/sys/posix/pnet/sys_socket.c index 769640bcfd..7aa0083692 100644 --- a/sys/posix/pnet/sys_socket.c +++ b/sys/posix/pnet/sys_socket.c @@ -14,24 +14,24 @@ */ #include -#include "destiny/socket.h" +#include "socket_base/socket.h" #include "fd.h" #include "sys/socket.h" int flagless_send(int fd, const void *buf, size_t len) { - return (int)destiny_socket_send(fd, buf, (uint32_t)len, 0); + return (int)socket_base_send(fd, buf, (uint32_t)len, 0); } int flagless_recv(int fd, void *buf, size_t len) { - return (int)destiny_socket_recv(fd, buf, (uint32_t)len, 0); + return (int)socket_base_recv(fd, buf, (uint32_t)len, 0); } int socket(int domain, int type, int protocol) { - int internal_socket = destiny_socket(domain, type, protocol); + int internal_socket = socket_base_socket(domain, type, protocol); if (internal_socket < 0) { errno = ENFILE; @@ -39,7 +39,7 @@ int socket(int domain, int type, int protocol) } return fd_new(internal_socket, flagless_recv, flagless_send, - destiny_socket_close); + socket_base_close); } @@ -51,27 +51,27 @@ int socket(int domain, int type, int protocol) int accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len) { - int res = sock_func_wrapper(destiny_socket_accept, socket, + int res = sock_func_wrapper(socket_base_accept, socket, (sockaddr6_t *)address, (socklen_t *)address_len); if (res < 0) { - // destiny needs more granular error handling + // transport_layer needs more granular error handling errno = EOPNOTSUPP; return -1; } return fd_new(res, flagless_recv, flagless_send, - destiny_socket_close); + socket_base_close); } int bind(int socket, const struct sockaddr *address, socklen_t address_len) { - int res = sock_func_wrapper(destiny_socket_bind, socket, + int res = sock_func_wrapper(socket_base_bind, socket, (sockaddr6_t *)address, address_len); if (res < 0) { - // destiny needs more granular error handling + // transport_layer needs more granular error handling errno = EOPNOTSUPP; return -1; } @@ -81,11 +81,11 @@ int bind(int socket, const struct sockaddr *address, socklen_t address_len) int connect(int socket, const struct sockaddr *address, socklen_t address_len) { - int res = sock_func_wrapper(destiny_socket_connect, socket, + int res = sock_func_wrapper(socket_base_connect, socket, (sockaddr6_t *)address, address_len); if (res < 0) { - // destiny needs more granular error handling + // transport_layer needs more granular error handling errno = ECONNREFUSED; return -1; } @@ -108,10 +108,10 @@ int getsockopt(int socket, int level, int option_name, int listen(int socket, int backlog) { - int res = sock_func_wrapper(destiny_socket_listen, socket, backlog); + int res = sock_func_wrapper(socket_base_listen, socket, backlog); if (res < 0) { - // destiny needs more granular error handling + // transport_layer needs more granular error handling errno = ECONNREFUSED; return -1; } @@ -121,11 +121,11 @@ int listen(int socket, int backlog) ssize_t recv(int socket, void *buffer, size_t length, int flags) { - int32_t res = sock_func_wrapper(destiny_socket_recv, socket, buffer, + int32_t res = sock_func_wrapper(socket_base_recv, socket, buffer, (uint32_t) length, flags); if (res < 0) { - // destiny needs more granular error handling + // transport_layer needs more granular error handling errno = ENOTCONN; return -1; } @@ -137,13 +137,13 @@ ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags, struct sockaddr *restrict address, socklen_t *restrict address_len) { - int32_t res = sock_func_wrapper(destiny_socket_recvfrom, socket, buffer, + int32_t res = sock_func_wrapper(socket_base_recvfrom, socket, buffer, (uint32_t) length, flags, (sockaddr6_t *)address, (socklen_t *)address_len); if (res < 0) { - // destiny needs more granular error handling + // transport_layer needs more granular error handling errno = ENOTCONN; return -1; } @@ -153,11 +153,11 @@ ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags, ssize_t send(int socket, const void *buffer, size_t length, int flags) { - int32_t res = sock_func_wrapper(destiny_socket_send, socket, buffer, + int32_t res = sock_func_wrapper(socket_base_send, socket, buffer, (uint32_t) length, flags); if (res < 0) { - // destiny needs more granular error handling + // transport_layer needs more granular error handling errno = ENOTCONN; return -1; } @@ -168,13 +168,13 @@ ssize_t send(int socket, const void *buffer, size_t length, int flags) ssize_t sendto(int socket, const void *message, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len) { - int32_t res = sock_func_wrapper(destiny_socket_sendto, socket, message, + int32_t res = sock_func_wrapper(socket_base_sendto, socket, message, (uint32_t) length, flags, (sockaddr6_t *)dest_addr, (socklen_t)dest_len); if (res < 0) { - // destiny needs more granular error handling + // transport_layer needs more granular error handling errno = ENOTCONN; return -1; }