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