From c0571506fe3254b4c9caa21b121f15d13e1dc293 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 | 4 +- examples/rpl_udp/demo.h | 2 +- examples/rpl_udp/main.c | 2 +- examples/rpl_udp/rpl.c | 4 +- examples/rpl_udp/udp.c | 18 +- pkg/libcoap/0001-Add-RIOT-Makefile.patch | 2 +- pkg/oonf_api/0001-add-RIOT-support.patch | 4 +- sys/Makefile | 17 +- sys/Makefile.include | 13 +- sys/auto_init/auto_init.c | 19 +- sys/net/include/{destiny.h => socket_base.h} | 27 +- sys/net/include/{destiny => socket_base}/in.h | 8 +- .../include/{destiny => socket_base}/socket.h | 40 +- .../include/{destiny => socket_base}/types.h | 12 +- sys/net/include/tcp.h | 42 + sys/net/include/udp.h | 42 + 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/socket_base/Makefile | 1 + .../{destiny => socket_base}/msg_help.c | 2 - .../{destiny => socket_base}/msg_help.h | 0 sys/net/transport_layer/socket_base/socket.c | 376 ++++ .../{destiny => socket_base}/socket.h | 63 +- sys/net/transport_layer/tcp/Makefile | 1 + .../{destiny/socket.c => tcp/tcp.c} | 1707 +++++++++-------- .../transport_layer/{destiny => tcp}/tcp.h | 14 +- .../transport_layer/{destiny => tcp}/tcp_hc.c | 4 +- .../transport_layer/{destiny => tcp}/tcp_hc.h | 2 +- .../{destiny => tcp}/tcp_timer.c | 7 +- .../{destiny => tcp}/tcp_timer.h | 0 sys/net/transport_layer/udp/Makefile | 1 + sys/net/transport_layer/udp/udp.c | 224 +++ .../transport_layer/{destiny => udp}/udp.h | 14 +- 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, 1773 insertions(+), 1548 deletions(-) rename sys/net/include/{destiny.h => socket_base.h} (65%) rename sys/net/include/{destiny => socket_base}/in.h (98%) rename sys/net/include/{destiny => socket_base}/socket.h (91%) 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 create mode 100644 sys/net/transport_layer/socket_base/Makefile rename sys/net/transport_layer/{destiny => socket_base}/msg_help.c (97%) rename sys/net/transport_layer/{destiny => socket_base}/msg_help.h (100%) create mode 100644 sys/net/transport_layer/socket_base/socket.c rename sys/net/transport_layer/{destiny => socket_base}/socket.h (50%) create mode 100644 sys/net/transport_layer/tcp/Makefile rename sys/net/transport_layer/{destiny/socket.c => tcp/tcp.c} (68%) rename sys/net/transport_layer/{destiny => tcp}/tcp.h (91%) 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 (98%) 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 rename sys/net/transport_layer/{destiny => udp}/udp.h (51%) diff --git a/Makefile.dep b/Makefile.dep index 7455a419b709d..38474f128668c 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 b0414da39db3e..2f9c7da734a02 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 d1713e3282bc3..ef0f5055fa9b5 100644 --- a/examples/rpl_udp/Makefile +++ b/examples/rpl_udp/Makefile @@ -48,11 +48,11 @@ 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 += pnet +USEMODULE += udp include $(RIOTBASE)/Makefile.include diff --git a/examples/rpl_udp/demo.h b/examples/rpl_udp/demo.h index 90eb39a379996..f7adb894eb110 100644 --- a/examples/rpl_udp/demo.h +++ b/examples/rpl_udp/demo.h @@ -10,7 +10,7 @@ /* RPL shell command handlers */ /** - * @brief Shell command to initializes RPL and Destiny + * @brief Shell command to initializes RPL and the transport layer */ void rpl_udp_init(int argc, char **argv); diff --git a/examples/rpl_udp/main.c b/examples/rpl_udp/main.c index 11342b1b719a7..d02a5721c72ba 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 "demo.h" diff --git a/examples/rpl_udp/rpl.c b/examples/rpl_udp/rpl.c index a8c6ce9629edf..329fdc89191a3 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_dodag.h" #include "demo.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 6f68d9dcf14c0..eda3f13a9e276 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" @@ -61,7 +61,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 = transport_layer_socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); memset(&sa, 0, sizeof(sa)); @@ -70,13 +70,13 @@ static void *init_udp_server(void *arg) fromlen = sizeof(sa); - if (-1 == destiny_socket_bind(sock, &sa, sizeof(sa))) { + if (-1 == transport_layer_socket_bind(sock, &sa, sizeof(sa))) { printf("Error bind failed!\n"); - destiny_socket_close(sock); + transport_layer_socket_close(sock); } while (1) { - recsize = destiny_socket_recvfrom(sock, (void *)buffer_main, UDP_BUFFER_SIZE, 0, + recsize = transport_layer_socket_recvfrom(sock, (void *)buffer_main, UDP_BUFFER_SIZE, 0, &sa, &fromlen); if (recsize < 0) { @@ -86,7 +86,7 @@ static void *init_udp_server(void *arg) printf("UDP packet received, payload: %s\n", buffer_main); } - destiny_socket_close(sock); + transport_layer_socket_close(sock); return NULL; } @@ -111,7 +111,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 = transport_layer_socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (-1 == sock) { printf("Error Creating Socket!"); @@ -126,7 +126,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 = transport_layer_socket_sendto(sock, (char *)text, strlen(text) + 1, 0, &sa, sizeof(sa)); @@ -139,5 +139,5 @@ void udp_send(int argc, char **argv) &ipaddr)); } - destiny_socket_close(sock); + transport_layer_socket_close(sock); } diff --git a/pkg/libcoap/0001-Add-RIOT-Makefile.patch b/pkg/libcoap/0001-Add-RIOT-Makefile.patch index 2a32d4f1c3666..4a07e32afe964 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 7a297c9e8a90c..adf0943b6c43f 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 d7c973ac1b7f8..35f0a32110152 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -43,8 +43,21 @@ 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))) + DIRS += net/transport_layer/socket_base + DIRS += net/transport_layer/tcp + DIRS += net/transport_layer/udp +endif +ifneq (,$(filter socket_base,$(USEMODULE))) + DIRS += net/transport_layer/socket_base +endif +ifneq (,$(filter udp,$(USEMODULE))) + DIRS += net/transport_layer/socket_base + DIRS += net/transport_layer/udp +endif +ifneq (,$(filter tcp,$(USEMODULE))) + DIRS += net/transport_layer/socket_base + 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 2073b310a78c2..c1eea42127f9a 100644 --- a/sys/Makefile.include +++ b/sys/Makefile.include @@ -1,4 +1,15 @@ -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/transport_layer/socket_base + USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include +endif +ifneq (,$(filter udp,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/transport_layer/socket_base 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 7dd76ebbd1028..f8a3c1c4bcd7a 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 c468d0d008222..465570af3df26 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 98% rename from sys/net/include/destiny/in.h rename to sys/net/include/socket_base/in.h index 5184d674aa3f1..bead233afa674 100644 --- a/sys/net/include/destiny/in.h +++ b/sys/net/include/socket_base/in.h @@ -1,5 +1,5 @@ /** - * 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 +18,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 +141,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 91% rename from sys/net/include/destiny/socket.h rename to sys/net/include/socket_base/socket.h index 853b9b22b18e1..1a49823ec6ec5 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 @@ * Public License. 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 transport_layer_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 transport_layer_socket_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 transport_layer_socket_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 transport_layer_socket_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 transport_layer_socket_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 transport_layer_socket_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 transport_layer_socket_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 transport_layer_socket_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 transport_layer_socket_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 transport_layer_socket_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 transport_layer_socket_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 1b168e09205cb..56cf6fe183126 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 @@ * Public License. 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 0000000000000..93e73da320f9f --- /dev/null +++ b/sys/net/include/tcp.h @@ -0,0 +1,42 @@ +/** + * tcp.h - Wraps all API types, constants and functions of the tcp implementation. + * + * Copyright (C) 2013 INRIA. + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. 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 0000000000000..00833c40c8eb3 --- /dev/null +++ b/sys/net/include/udp.h @@ -0,0 +1,42 @@ +/** + * udp.h - Wraps all API types, constants and functions of the tcp implementation. + * + * Copyright (C) 2013 INRIA. + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. 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 c8bb0a36f9fe9..100dee2e21021 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 21eb90d244ff6..0000000000000 --- 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. 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 */ - 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); - - /* 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(); - - 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.c b/sys/net/transport_layer/destiny/tcp.c deleted file mode 100644 index d8aafce4ffac0..0000000000000 --- 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. 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; - uint8_t target_pid; - - 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 1e975a5003a07..0000000000000 --- 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. 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/socket_base/Makefile b/sys/net/transport_layer/socket_base/Makefile new file mode 100644 index 0000000000000..48422e909a47d --- /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 97% rename from sys/net/transport_layer/destiny/msg_help.c rename to sys/net/transport_layer/socket_base/msg_help.c index 69cdad4868f63..85e93cac0db6c 100644 --- a/sys/net/transport_layer/destiny/msg_help.c +++ b/sys/net/transport_layer/socket_base/msg_help.c @@ -17,8 +17,6 @@ #include "thread.h" -#include "tcp_timer.h" - #include "msg_help.h" void block_continue_thread(void) diff --git a/sys/net/transport_layer/destiny/msg_help.h b/sys/net/transport_layer/socket_base/msg_help.h similarity index 100% rename from sys/net/transport_layer/destiny/msg_help.h rename to sys/net/transport_layer/socket_base/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 0000000000000..10df02f98b8f8 --- /dev/null +++ b/sys/net/transport_layer/socket_base/socket.c @@ -0,0 +1,376 @@ +/** + * socket API + * + * Copyright (C) 2013 INRIA. + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. 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 sockets[MAX_SOCKETS]; + +void 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 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"); +} + +int exists_socket(int socket) +{ + if (sockets[socket - 1].socket_id == 0) { + return false; + } + else { + return true; + } +} + +socket_internal_t *get_socket(int s) +{ + if (exists_socket(s)) { + return &(sockets[s - 1]); + } + else { + return NULL; + } +} + +void transport_layer_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)); + } + } +} + +void close_socket(socket_internal_t *current_socket) +{ + memset(current_socket, 0, sizeof(socket_internal_t)); +} + +bool __attribute__((weak)) is_tcp_socket(int s) +{ + (void) s; + + return false; +} + +bool __attribute__((weak)) is_udp_socket(int s) +{ + (void) s; + + return false; +} + +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; +} + +int transport_layer_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; +#ifdef MODULE_TCP + current_socket->tcp_control.state = 0; +#endif + return sockets[i - 1].socket_id; + } +} + +int __attribute__((weak)) transport_layer_socket_connect(int socket, sockaddr6_t *addr, uint32_t addrlen) +{ + (void) socket; + (void) addr; + (void) addrlen; + + return -1; +} + +int32_t __attribute__((weak)) transport_layer_socket_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)) transport_layer_socket_recv(int s, void *buf, uint32_t len, int flags) +{ + (void) s; + (void) buf; + (void) len; + (void) flags; + + return -1; +} + +int32_t __attribute__((weak)) transport_layer_socket_recvfrom_udp(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 transport_layer_socket_recvfrom(int s, void *buf, uint32_t len, int flags, + sockaddr6_t *from, uint32_t *fromlen) +{ + (void) flags; + + if (is_udp_socket(s)) { + return transport_layer_socket_recvfrom_udp(s, buf, len, flags, from, fromlen); + } + else if (is_tcp_socket(s)) { + return transport_layer_socket_recv(s, buf, len, flags); + } + else { + printf("Socket Type not supported!\n"); + return -1; + } +} + +int __attribute__((weak)) transport_layer_socket_tcp_teardown(socket_internal_t *current_socket) +{ + (void) current_socket; + + return -1; +} + +int32_t __attribute__((weak)) transport_layer_socket_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 transport_layer_socket_close(int s) +{ + socket_internal_t *current_socket = get_socket(s); + + if (current_socket != NULL) { + if (is_tcp_socket(s)) { + return transport_layer_socket_tcp_teardown(current_socket); + } + else if (is_udp_socket(s)) { + close_socket(current_socket); + return 0; + } + + return -1; + } + else { + return -1; + } +} + +int __attribute__((weak)) bind_tcp_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid) +{ + (void) s; + (void) name; + (void) namelen; + (void) pid; + + return -1; +} + +int __attribute__((weak)) bind_udp_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid) +{ + (void) s; + (void) name; + (void) namelen; + (void) pid; + + return -1; +} + +int transport_layer_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 __attribute__((weak)) transport_layer_socket_listen(int s, int backlog) +{ + (void) s; + (void) backlog; + + return -1; +} + +int __attribute__((weak)) transport_layer_socket_accept(int s, sockaddr6_t *addr, uint32_t *addrlen) +{ + (void) s; + (void) addr; + (void) addrlen; + + return -1; +} diff --git a/sys/net/transport_layer/destiny/socket.h b/sys/net/transport_layer/socket_base/socket.h similarity index 50% rename from sys/net/transport_layer/destiny/socket.h rename to sys/net/transport_layer/socket_base/socket.h index 90e715c445105..83f27c7b5c13f 100644 --- a/sys/net/transport_layer/destiny/socket.h +++ b/sys/net/transport_layer/socket_base/socket.h @@ -1,12 +1,17 @@ -#ifndef _DESTINY_SOCKET -#define _DESTINY_SOCKET +#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 +19,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,12 +55,15 @@ 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; @@ -63,33 +72,35 @@ typedef struct { uint8_t socket_id; 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]; -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); - -#endif /* _DESTINY_SOCKET */ +bool is_udp_socket(int s); +int exists_socket(int socket); +uint16_t get_free_source_port(uint8_t protocol); +int transport_layer_socket_tcp_teardown(socket_internal_t *current_socket); +int transport_layer_socket(int domain, int type, int protocol); +int transport_layer_socket_connect(int socket, sockaddr6_t *addr, socklen_t addrlen); +int32_t transport_layer_socket_recv(int s, void *buf, uint32_t len, int flags); +int32_t transport_layer_socket_recvfrom(int s, void *buf, uint32_t len, int flags, + sockaddr6_t *from, socklen_t *fromlen); +int32_t transport_layer_socket_send(int s, const void *buf, uint32_t len, int flags); +int32_t transport_layer_socket_sendto(int s, const void *buf, uint32_t len, int flags, + sockaddr6_t *to, socklen_t tolen); +int transport_layer_socket_close(int s); +int transport_layer_socket_bind(int s, sockaddr6_t *addr, int addrlen); +int transport_layer_socket_listen(int s, int backlog); +int transport_layer_socket_accept(int s, sockaddr6_t *addr, socklen_t *addrlen); +void transport_layer_socket_print_sockets(void); + +#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 0000000000000..48422e909a47d --- /dev/null +++ b/sys/net/transport_layer/tcp/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/transport_layer/destiny/socket.c b/sys/net/transport_layer/tcp/tcp.c similarity index 68% rename from sys/net/transport_layer/destiny/socket.c rename to sys/net/transport_layer/tcp/tcp.c index 8cb68e65310d6..2ddc73cc7751a 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 @@ * Public License. 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) -{ - 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 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, uint8_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, uint8_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) +uint16_t tcp_csum(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header) { - sockaddr->sin6_family = sin6_family; - sockaddr->sin6_port = sin6_port; - sockaddr->sin6_flowinfo = sin6_flowinfo; - memcpy(&sockaddr->sin6_addr, sin6_addr, 16); -} + uint16_t sum; + uint16_t len = NTOHS(ipv6_header->length); -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,213 +306,628 @@ 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 = 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; - 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])); + for (i = 1; i < MAX_SOCKETS + 1; i++) { + current_socket = get_socket(i); - /* Check if socket exists */ - current_int_tcp_socket = get_socket(socket); + if (!current_socket) { + continue; + } - if (current_int_tcp_socket == NULL) { - return -1; + /* 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; + } + } } - current_tcp_socket = ¤t_int_tcp_socket->socket_values; + return NULL; +} - current_int_tcp_socket->recv_pid = thread_getpid(); +socket_internal_t *new_tcp_queued_socket(ipv6_hdr_t *ipv6_header, + tcp_hdr_t *tcp_header) +{ + int queued_socket_id; - /* 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); + queued_socket_id = transport_layer_socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); + socket_internal_t *current_queued_socket = get_socket(queued_socket_id); - /* Foreign address information */ - set_socket_address(¤t_tcp_socket->foreign_address, addr->sin6_family, - addr->sin6_port, addr->sin6_flowinfo, &addr->sin6_addr); + /* Foreign address */ + set_socket_address(¤t_queued_socket->socket_values.foreign_address, + AF_INET6, tcp_header->src_port, ipv6_header->flowlabel, + &ipv6_header->srcaddr); - /* Fill lcoal TCP socket information */ - srand(addr->sin6_port); + /* Local address */ + set_socket_address(¤t_queued_socket->socket_values.local_address, + AF_INET6, tcp_header->dst_port, 0, + &ipv6_header->destaddr); - current_tcp_socket->tcp_control.rcv_irs = 0; + /* 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_tcp_socket->tcp_control.send_iss = global_sequence_counter; + current_queued_socket->socket_values.tcp_control.send_iss = + global_sequence_counter; mutex_unlock(&global_sequence_counter_mutex); - current_tcp_socket->tcp_control.state = TCP_SYN_SENT; + 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 = 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; +} + +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; + uint8_t target_pid; + + 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 - /* 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); + update_tcp_hc_context(true, new_socket, tcp_header); +#endif + /* notify socket function transport_layer_socket_accept(..) that a new + * connection request has arrived. No need to wait for an answer + * because the server transport_layer_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!"); + } +} - current_tcp_socket->tcp_control.tcp_context.hc_type = FULL_HEADER; +void handle_tcp_syn_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, + socket_internal_t *tcp_socket) +{ + (void) ipv6_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)); + 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 - 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); + if (current_tcp_socket->tcp_control.state == TCP_FIN_WAIT_1) { + current_tcp_socket->tcp_control.state = TCP_CLOSING; - /* 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; + send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_FIN_ACK, 0); + } + else { + current_tcp_socket->tcp_control.state = TCP_LAST_ACK; - msg_from_server.type = TCP_RETRY; + 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); - while (msg_from_server.type == TCP_RETRY) { /* Send packet */ - send_tcp(current_int_tcp_socket, current_tcp_packet, temp_ipv6_header, - TCP_SYN, 0); + // 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); + } +} - /* wait for SYN ACK or RETRY */ - msg_receive(&msg_from_server); +void *tcp_packet_handler(void *arg) +{ + (void) arg; - if (msg_from_server.type == TCP_TIMEOUT) { + 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 - /* 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)); + 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 - return -1; - } + 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 - 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)); + 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); } -#endif + msg_reply(&m_recv_ip, &m_send_ip); } +} - /* Read packet content */ - tcp_hdr_t *tcp_header = ((tcp_hdr_t *)(msg_from_server.content.ptr)); +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); +} - /* Check for consistency */ - if (tcp_header->ack_nr != current_tcp_socket->tcp_control.send_nxt) { - printf("TCP packets not consistent!\n"); +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; + } +} - /* 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)); +int bind_tcp_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid) +{ + int i; + + socket_internal_t *sock = get_socket(s); + + if (!sock) { + 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; + } + } + + (void) namelen; + sock->socket_values.local_address = *name; + sock->socket_values.tcp_control.rto = TCP_INITIAL_ACK_TIMEOUT; + sock->recv_pid = pid; + + return 0; +} + +void calculate_rto(tcp_cb_t *tcp_control, timex_t current_time) +{ + double rtt = (double) timex_uint64(timex_sub(current_time, tcp_control->last_packet_time)); + double srtt = tcp_control->srtt; + double rttvar = tcp_control->rttvar; + double rto = tcp_control->rto; + + if ((srtt == 0) && (rttvar == 0) && (rto == TCP_INITIAL_ACK_TIMEOUT)) { + /* First calculation */ + srtt = rtt; + rttvar = 0.5 * rtt; + rto = rtt + (((4 * rttvar) < TCP_TIMER_RESOLUTION) ? + (TCP_TIMER_RESOLUTION) : (4 * rttvar)); } else { - current_tcp_socket->tcp_control.mss = DESTINY_SOCKET_STATIC_MSS; + /* every other calculation */ + srtt = (1 - TCP_ALPHA) * srtt + TCP_ALPHA * rtt; + rttvar = (1 - TCP_BETA) * rttvar + TCP_BETA * abs(srtt - rtt); + rto = srtt + (((4 * rttvar) < TCP_TIMER_RESOLUTION) ? + (TCP_TIMER_RESOLUTION) : (4 * rttvar)); } - 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); + if (rto < SECOND) { + rto = SECOND; + } - msg_from_server.type = UNDEFINED; + tcp_control->srtt = srtt; + tcp_control->rttvar = rttvar; + tcp_control->rto = rto; +} - /* Remember current time */ - vtimer_now(&now); - current_tcp_socket->tcp_control.last_packet_time = now; - current_tcp_socket->tcp_control.no_of_retries = 0; +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_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)); + 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; - while (msg_from_server.type != TCP_RETRY) { + 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_int_tcp_socket, current_tcp_packet, temp_ipv6_header, - TCP_ACK, 0); + send_tcp(current_queued_int_socket, syn_ack_packet, temp_ipv6_header, + TCP_SYN_ACK, 0); - msg_receive(&msg_from_server); -#ifdef TCP_HC + /* wait for ACK from Client */ + msg_receive(&msg_recv_client_ack); - 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 */ + 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 - } - current_tcp_socket->tcp_control.state = TCP_ESTABLISHED; + /* Update connection status information */ + current_queued_socket->tcp_control.state = TCP_ESTABLISHED; - current_int_tcp_socket->recv_pid = 255; + /* Set status of internal socket back to TCP_LISTEN */ + server_socket->socket_values.tcp_control.state = TCP_LISTEN; - destiny_socket_print_sockets(); - return 0; -} + /* 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); -void calculate_rto(tcp_cb_t *tcp_control, timex_t current_time) -{ - double rtt = (double) timex_uint64(timex_sub(current_time, tcp_control->last_packet_time)); - double srtt = tcp_control->srtt; - double rttvar = tcp_control->rttvar; - double rto = tcp_control->rto; + /* Reset PID to an unlikely value */ + current_queued_int_socket->recv_pid = 255; - if ((srtt == 0) && (rttvar == 0) && (rto == TCP_INITIAL_ACK_TIMEOUT)) { - /* First calculation */ - srtt = rtt; - rttvar = 0.5 * rtt; - rto = rtt + (((4 * rttvar) < TCP_TIMER_RESOLUTION) ? - (TCP_TIMER_RESOLUTION) : (4 * rttvar)); - } - else { - /* every other calculation */ - srtt = (1 - TCP_ALPHA) * srtt + TCP_ALPHA * rtt; - rttvar = (1 - TCP_BETA) * rttvar + TCP_BETA * abs(srtt - rtt); - rto = srtt + (((4 * rttvar) < TCP_TIMER_RESOLUTION) ? - (TCP_TIMER_RESOLUTION) : (4 * rttvar)); - } + /* Waiting for Clients ACK waiting period to time out */ + vtimer_usleep(TCP_SYN_INITIAL_TIMEOUT / 2); - if (rto < SECOND) { - rto = SECOND; - } + transport_layer_socket_print_sockets(); - tcp_control->srtt = srtt; - tcp_control->rttvar = rttvar; - tcp_control->rto = rto; + return current_queued_int_socket->socket_id; } -int32_t destiny_socket_send(int s, const void *buf, uint32_t len, int flags) +int32_t transport_layer_socket_send(int s, const void *buf, uint32_t len, int flags) { (void) flags; @@ -888,287 +1102,278 @@ 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) +int transport_layer_socket_accept(int s, sockaddr6_t *addr, uint32_t *addrlen) { - 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; + (void) addr; + (void) addrlen; + + socket_internal_t *server_socket = get_socket(s); + + if (is_tcp_socket(s) && (server_socket->socket_values.tcp_control.state == TCP_LISTEN)) { + socket_internal_t *current_queued_socket = + get_waiting_connection_socket(s, NULL, NULL); + + if (current_queued_socket != NULL) { + return handle_new_tcp_connection(current_queued_socket, + server_socket, thread_getpid()); + } + else { + /* No waiting connections, waiting for message from TCP Layer */ + msg_t msg_recv_client_syn; + msg_recv_client_syn.type = UNDEFINED; + + while (msg_recv_client_syn.type != TCP_SYN) { + msg_receive(&msg_recv_client_syn); + } + + current_queued_socket = get_waiting_connection_socket(s, NULL, NULL); + + return handle_new_tcp_connection(current_queued_socket, + server_socket, thread_getpid()); + } } 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; + return -1; } } -int32_t destiny_socket_recv(int s, void *buf, uint32_t len, int flags) +int transport_layer_socket_connect(int socket, sockaddr6_t *addr, uint32_t addrlen) { - (void) flags; + (void) addrlen; /* Variables */ - uint8_t read_bytes; - msg_t m_recv, m_send; + 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])); /* Check if socket exists */ - if (!is_tcp_socket(s)) { - printf("INFO: NO TCP SOCKET!\n"); + current_int_tcp_socket = get_socket(socket); + + if (current_int_tcp_socket == NULL) { return -1; } - current_int_tcp_socket = get_socket(s); + current_tcp_socket = ¤t_int_tcp_socket->socket_values; - /* 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); + /* 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); - 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; - } + /* Foreign address information */ + set_socket_address(¤t_tcp_socket->foreign_address, addr->sin6_family, + addr->sin6_port, addr->sin6_flowinfo, &addr->sin6_addr); - /* 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; - } + /* Fill lcoal TCP socket information */ + srand(addr->sin6_port); - /* Received Last ACK (connection closed) or no data to read yet */ - return -1; -} + 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; -int32_t destiny_socket_recvfrom(int s, void *buf, uint32_t len, int flags, - sockaddr6_t *from, uint32_t *fromlen) -{ - (void) flags; +#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); - 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(); + current_tcp_socket->tcp_control.tcp_context.hc_type = FULL_HEADER; - msg_receive(&m_recv); + /* 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 - 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); + 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); - 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); + /* 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_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; - } -} + msg_from_server.type = TCP_RETRY; -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; + while (msg_from_server.type == TCP_RETRY) { + /* Send packet */ + send_tcp(current_int_tcp_socket, current_tcp_packet, temp_ipv6_header, + TCP_SYN, 0); - if (isUDPSocket(s) && - (get_socket(s)->socket_values.foreign_address.sin6_port == 0)) { - uint8_t send_buffer[BUFFER_SIZE]; + /* wait for SYN ACK or RETRY */ + msg_receive(&msg_from_server); - 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]; + 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; + } - memcpy(&(temp_ipv6_header->destaddr), &to->sin6_addr, 16); - ipv6_net_if_get_best_src_addr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr)); +#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)); + } - current_udp_packet->src_port = get_free_source_port(IPPROTO_UDP); - current_udp_packet->dst_port = to->sin6_port; - current_udp_packet->checksum = 0; +#endif + } - memcpy(payload, buf, len); - current_udp_packet->length = HTONS(UDP_HDR_LEN + len); - temp_ipv6_header->length = UDP_HDR_LEN + len; + /* Read packet content */ + tcp_hdr_t *tcp_header = ((tcp_hdr_t *)(msg_from_server.content.ptr)); - current_udp_packet->checksum = ~ipv6_csum(temp_ipv6_header, - (uint8_t *) current_udp_packet, - UDP_HDR_LEN + len, - IPPROTO_UDP); + /* Check for consistency */ + if (tcp_header->ack_nr != current_tcp_socket->tcp_control.send_nxt) { + printf("TCP packets not consistent!\n"); + } - return ipv6_sendto(&to->sin6_addr, IPPROTO_UDP, - (uint8_t *)(current_udp_packet), - NTOHS(current_udp_packet->length)); + /* 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 { - return -1; + current_tcp_socket->tcp_control.mss = TRANSPORT_LAYER_SOCKET_STATIC_MSS; } -} -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; - } + 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); - /* Check for TCP_ESTABLISHED STATE */ - if (current_socket->socket_values.tcp_control.state != TCP_ESTABLISHED) { - close_socket(current_socket); - return 0; - } + msg_from_server.type = UNDEFINED; - current_socket->send_pid = thread_getpid(); + /* Remember current time */ + vtimer_now(&now); + current_tcp_socket->tcp_control.last_packet_time = now; + current_tcp_socket->tcp_control.no_of_retries = 0; - /* 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; + 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 - send_tcp(current_socket, current_tcp_packet, temp_ipv6_header, - TCP_FIN_ACK, 0); - msg_receive(&m_recv); - close_socket(current_socket); - return 1; + 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 (isUDPSocket(s)) { - close_socket(current_socket); - return 0; + 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 */ } - return -1; +#endif + } + + current_tcp_socket->tcp_control.state = TCP_ESTABLISHED; + + current_int_tcp_socket->recv_pid = 255; + + transport_layer_socket_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 { - return -1; + 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; } } -int destiny_socket_bind(int s, sockaddr6_t *addr, int addrlen) +int32_t transport_layer_socket_recv(int s, void *buf, uint32_t len, int flags) { - 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; - } + (void) flags; - /* 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; - } + /* Variables */ + uint8_t read_bytes; + msg_t m_recv, m_send; + socket_internal_t *current_int_tcp_socket; - break; - } + /* Check if socket exists */ + if (!is_tcp_socket(s)) { + printf("INFO: NO TCP SOCKET!\n"); + return -1; + } - case (SOCK_SEQPACKET): { - /* not provided */ - return -1; - break; - } + current_int_tcp_socket = get_socket(s); - case (SOCK_RAW): { - /* not provided */ - return -1; - break; - } + /* Setting Thread PID */ + current_int_tcp_socket->recv_pid = thread_getpid(); - default: { - return -1; - break; - } - } + if (current_int_tcp_socket->tcp_input_buffer_end > 0) { + return read_from_socket(current_int_tcp_socket, buf, len); + } - break; - } + msg_receive(&m_recv); - case (PF_UNIX): { - /* Not provided */ - return -1; - break; - } - } + 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; } - else { - printf("SOCKET DOES NOT EXIST!\n"); + + /* 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 destiny_socket_listen(int s, int backlog) +int transport_layer_socket_listen(int s, int backlog) { (void) backlog; @@ -1182,203 +1387,61 @@ int destiny_socket_listen(int s, int backlog) } } -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, uint8_t pid) +int transport_layer_socket_tcp_teardown(socket_internal_t *current_socket) { - (void) pid; - - msg_t msg_recv_client_ack, msg_send_client_ack; - socket_t *current_queued_socket = ¤t_queued_int_socket->socket_values; + /* 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 *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)); + tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); - /* Check for consistency */ - if (tcp_header->ack_nr != current_queued_socket->tcp_control.send_nxt) { - printf("TCP packets not consistent!\n"); + /* Check for TCP_ESTABLISHED STATE */ + if (current_socket->socket_values.tcp_control.state != TCP_ESTABLISHED) { + close_socket(current_socket); + return 0; } - /* 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); + 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 - /* Copy TCP context information into new socket */ - memset(&server_socket->socket_values.tcp_control.tcp_context, 0, - sizeof(tcp_hc_context_t)); + current_socket->socket_values.tcp_control.tcp_context.hc_type = + COMPRESSED_HEADER; #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); - - destiny_socket_print_sockets(); - - return current_queued_int_socket->socket_id; + send_tcp(current_socket, current_tcp_packet, temp_ipv6_header, + TCP_FIN_ACK, 0); + msg_receive(&m_recv); + close_socket(current_socket); + return 1; } -int destiny_socket_accept(int s, sockaddr6_t *addr, uint32_t *addrlen) +int tcp_init_transport_layer(void) { - (void) addr; - (void) addrlen; - - socket_internal_t *server_socket = get_socket(s); - - if (is_tcp_socket(s) && (server_socket->socket_values.tcp_control.state == TCP_LISTEN)) { - socket_internal_t *current_queued_socket = - get_waiting_connection_socket(s, NULL, NULL); - - if (current_queued_socket != NULL) { - return handle_new_tcp_connection(current_queued_socket, - server_socket, thread_getpid()); - } - else { - /* No waiting connections, waiting for message from TCP Layer */ - msg_t msg_recv_client_syn; - msg_recv_client_syn.type = UNDEFINED; - - while (msg_recv_client_syn.type != TCP_SYN) { - msg_receive(&msg_recv_client_syn); - } + 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(); - current_queued_socket = get_waiting_connection_socket(s, NULL, NULL); + int tcp_thread_pid = thread_create(tcp_stack_buffer, TCP_STACK_SIZE, + PRIORITY_MAIN, CREATE_STACKTEST, tcp_packet_handler, NULL, "tcp_packet_handler"); - return handle_new_tcp_connection(current_queued_socket, - server_socket, thread_getpid()); - } - } - else { + if (tcp_thread_pid < 0) { return -1; } -} - -socket_internal_t *new_tcp_queued_socket(ipv6_hdr_t *ipv6_header, - tcp_hdr_t *tcp_header) -{ - int queued_socket_id; - - queued_socket_id = destiny_socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); - socket_internal_t *current_queued_socket = 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); + ipv6_register_next_header_handler(IPV6_PROTO_NUM_TCP, tcp_thread_pid); - /* 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 = DESTINY_SOCKET_STATIC_MSS; + if (thread_create(tcp_timer_stack, TCP_TIMER_STACKSIZE, PRIORITY_MAIN + 1, + CREATE_STACKTEST, tcp_general_timer, NULL, "tcp_general_timer") < 0) { + return -1; } - 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, - tcp_header->window); - - return current_queued_socket; + return 0; } diff --git a/sys/net/transport_layer/destiny/tcp.h b/sys/net/transport_layer/tcp/tcp.h similarity index 91% rename from sys/net/transport_layer/destiny/tcp.h rename to sys/net/transport_layer/tcp/tcp.h index f2ebe7646938d..123e06fc343db 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 @@ * Public License. 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,9 @@ 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 bind_tcp_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid); +bool is_tcp_socket(int s); /** * @} 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 c4ca3c4bc35d8..51cff5d92cea8 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 @@ * Public License. See the file LICENSE in the top level directory for more * details. * - * @ingroup destiny + * @ingroup transport_layer * @{ * @file tcp_hc.c * @brief TCP HC 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 3d89f680252a7..feeb3eba99346 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 98% rename from sys/net/transport_layer/destiny/tcp_timer.c rename to sys/net/transport_layer/tcp/tcp_timer.c index 6b52ebac8aaea..848791cb9fae7 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 @@ * Public License. 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) 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 0000000000000..48422e909a47d --- /dev/null +++ b/sys/net/transport_layer/udp/Makefile @@ -0,0 +1 @@ +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 0000000000000..4308aef19378a --- /dev/null +++ b/sys/net/transport_layer/udp/udp.c @@ -0,0 +1,224 @@ +/** + * UDP implementation + * + * Copyright (C) 2013 INRIA. + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. 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 (is_udp_socket(i) && + (get_socket(i)->socket_values.local_address.sin6_port == + udp_header->dst_port)) { + return 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 is_udp_socket(int 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; + } +} + +int bind_udp_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid) +{ + int i; + + if (!exists_socket(s)) { + return -1; + } + + for (i = 1; i < MAX_SOCKETS + 1; i++) { + if (is_udp_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; + return 0; +} + +int32_t transport_layer_socket_recvfrom_udp(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; + 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 transport_layer_socket_sendto(int s, const void *buf, uint32_t len, int flags, + sockaddr6_t *to, uint32_t tolen) +{ + (void) flags; + (void) tolen; + + if (is_udp_socket(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 udp_init_transport_layer(void) +{ + printf("Initializing transport layer protocol: udp\n"); + /* SOCKETS */ + memset(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/destiny/udp.h b/sys/net/transport_layer/udp/udp.h similarity index 51% rename from sys/net/transport_layer/destiny/udp.h rename to sys/net/transport_layer/udp/udp.h index 46e544458dd09..7e160e9bf21f5 100644 --- a/sys/net/transport_layer/destiny/udp.h +++ b/sys/net/transport_layer/udp/udp.h @@ -1,5 +1,5 @@ /** - * Destiny TCP header + * UDP header * * Copyright (C) 2013 INRIA. * @@ -7,7 +7,7 @@ * Public License. See the file LICENSE in the top level directory for more * details. * - * @ingroup destiny + * @ingroup transport_layer * @{ * @file * @brief UDP data structs and prototypes @@ -19,13 +19,17 @@ #define UDP_H_ #include "ipv6.h" -#include "destiny/types.h" +#include "socket_base/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 *); +bool is_udp_socket(int s); +int bind_udp_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid); +int32_t transport_layer_socket_recvfrom_udp(int s, void *buf, uint32_t len, int flags, + sockaddr6_t *from, uint32_t *fromlen); +int32_t transport_layer_socket_sendto(int s, const void *buf, uint32_t len, int flags, + sockaddr6_t *to, uint32_t tolen); /** * @} diff --git a/sys/posix/pnet/include/netinet/in.h b/sys/posix/pnet/include/netinet/in.h index 401253cd54092..79a62b724a605 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 a71761e806b90..2b11171270bd0 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 ae778c79c146d..5bfba2ee38eea 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)transport_layer_socket_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)transport_layer_socket_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 = transport_layer_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); + transport_layer_socket_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(transport_layer_socket_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); + transport_layer_socket_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(transport_layer_socket_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(transport_layer_socket_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(transport_layer_socket_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(transport_layer_socket_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(transport_layer_socket_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(transport_layer_socket_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(transport_layer_socket_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; }