From a9da0dc4f2cc2096a4715cdd81fb4aea4d5c665a Mon Sep 17 00:00:00 2001 From: Simon Brummer Date: Mon, 6 Mar 2017 08:47:06 +0100 Subject: [PATCH] gnrc_tcp: cleanup: various minor changes --- sys/include/net/gnrc/tcp.h | 189 ++++---- sys/include/net/gnrc/tcp/config.h | 22 +- sys/include/net/gnrc/tcp/tcb.h | 54 +-- sys/include/net/tcp.h | 28 +- sys/net/gnrc/transport_layer/tcp/gnrc_tcp.c | 203 ++++---- .../transport_layer/tcp/gnrc_tcp_eventloop.c | 89 ++-- .../gnrc/transport_layer/tcp/gnrc_tcp_fsm.c | 437 ++++++++---------- .../transport_layer/tcp/gnrc_tcp_option.c | 6 +- .../gnrc/transport_layer/tcp/gnrc_tcp_pkt.c | 66 +-- .../transport_layer/tcp/gnrc_tcp_rcvbuf.c | 23 +- .../transport_layer/tcp/internal/common.h | 32 +- .../transport_layer/tcp/internal/eventloop.h | 10 +- .../gnrc/transport_layer/tcp/internal/fsm.h | 34 +- .../transport_layer/tcp/internal/option.h | 28 +- .../gnrc/transport_layer/tcp/internal/pkt.h | 116 ++--- .../transport_layer/tcp/internal/rcvbuf.h | 33 +- tests/gnrc_tcp_client/Makefile | 4 +- tests/gnrc_tcp_client/README.md | 32 ++ tests/gnrc_tcp_client/main.c | 28 +- tests/gnrc_tcp_server/Makefile | 11 +- tests/gnrc_tcp_server/README.md | 33 ++ tests/gnrc_tcp_server/main.c | 46 +- 22 files changed, 786 insertions(+), 738 deletions(-) create mode 100644 tests/gnrc_tcp_client/README.md create mode 100644 tests/gnrc_tcp_server/README.md diff --git a/sys/include/net/gnrc/tcp.h b/sys/include/net/gnrc/tcp.h index e12a35ebb..cc0e85df3 100644 --- a/sys/include/net/gnrc/tcp.h +++ b/sys/include/net/gnrc/tcp.h @@ -9,7 +9,7 @@ /** * @defgroup net_gnrc_tcp TCP * @ingroup net_gnrc - * @brief RIOT's tcp implementation for the gnrc stack + * @brief RIOT's TCP implementation for the GNRC network stack. * * @{ * @@ -35,20 +35,20 @@ extern "C" { #endif /** - * @brief Initialize and start TCP + * @brief Initialize TCP * - * @return PID of TCP thread on success - * @return -1 if thread is already running. - * @return -EINVAL, if priority is greater than or equal SCHED_PRIO_LEVELS - * @return -EOVERFLOW, if there are too many threads running. + * @returns PID of TCP thread on success + * -1 if TCB is already running. + * -EINVAL, if priority is greater than or equal SCHED_PRIO_LEVELS + * -EOVERFLOW, if there are too many threads running. */ int gnrc_tcp_init(void); /** - * @brief Initialize Transmission Control Block (tcb) - * @pre tcb must not be NULL. + * @brief Initialize Transmission Control Block (TCB) + * @pre @p tcb must not be NULL. * - * @param[in,out] tcb Transmission that should be initialized. + * @param[in,out] tcb TCB that should be initialized. */ void gnrc_tcp_tcb_init(gnrc_tcp_tcb_t *tcb); @@ -56,29 +56,28 @@ void gnrc_tcp_tcb_init(gnrc_tcp_tcb_t *tcb); * @brief Opens a connection actively. * * @pre gnrc_tcp_tcb_init() must have been successfully called. - * @pre tcb must not be NULL - * @pre target_addr must not be NULL. - * @pre target_port must not be 0. + * @pre @p tcb must not be NULL + * @pre @p target_addr must not be NULL. + * @pre @p target_port must not be 0. * * @note Blocks until a connection has been established or an error occured. * - * @param[in,out] tcb This connections Transmission control block. - * @param[in] address_family Address Family of @p target_addr. - * @param[in] target_addr Pointer to target address. - * @param[in] target_port Targets port number. - * @param[in] local_port If zero or GNRC_TCP_PORT_UNSPEC, the connections - * source port is randomly chosen. If local_port is non-zero - * the local_port is used as source port. + * @param[in,out] tcb TCB holding the connection information. + * @param[in] address_family Address family of @p target_addr. + * @param[in] target_addr Pointer to target address. + * @param[in] target_port Target port number. + * @param[in] local_port If zero or GNRC_TCP_PORT_UNSPEC, the connections + * source port is randomly chosen. If local_port is non-zero + * the local_port is used as source port. * - * @return Zero on success. - * @return -EAFNOSUPPORT if @p address_family is not supported. - * @return -EINVAL if @p address_family is not the same the address_family use by the tcb. - * @return -EISCONN if transmission control block is already in use. - * @return -ENOMEM if the receive buffer for the tcb could not be allocated. - * Increase "GNRC_TCP_RCV_BUFFERS". - * @return -EADDRINUSE if @p local_port is already used by another connection. - * @return -ETIMEDOUT if the connection could not be opened. - * @return -ECONNREFUSED if the connection was resetted by the peer. + * @returns Zero on success. + * -EAFNOSUPPORT if @p address_family is not supported. + * -EINVAL if @p address_family is not the same the address_family use by the TCB. + * -EISCONN if TCB is already in use. + * -ENOMEM if the receive buffer for the TCB could not be allocated. + * -EADDRINUSE if @p local_port is already used by another connection. + * -ETIMEDOUT if the connection could not be opened. + * -ECONNREFUSED if the connection was resetted by the peer. */ int gnrc_tcp_open_active(gnrc_tcp_tcb_t *tcb, const uint8_t address_family, const uint8_t *target_addr, const uint16_t target_port, @@ -88,120 +87,120 @@ int gnrc_tcp_open_active(gnrc_tcp_tcb_t *tcb, const uint8_t address_family, * @brief Opens a connection passively, by waiting for an incomming request. * * @pre gnrc_tcp_tcb_init() must have been successfully called. - * @pre tcb must not be NULL. + * @pre @p tcb must not be NULL. * @pre if local_addr is not NULL, local_addr must be assigned to a network interface. * @pre if local_port is not zero. * * @note Blocks until a connection has been established (incomming connection request * to @p local_port) or an error occured. * - * @param[in,out] tcb This connections Transmission control block. - * @param[in] address_family Address Family of @p local_addr. - * If local_addr == NULL, address_family is ignored. - * @param[in] local_addr If not NULL the connection is bound to the address @p local_addr. - * If NULL a connection request to every local ip address is valid. - * @param[in] local_port Portnumber that should used for incomming connection requests. - * - * @return Zero on success - * @return -EAFNOSUPPORT if local_addr != NULL and @p address_family is not supported. - * @return -EINVAL if @p address_family is not the same the address_family use by the tcb. - * @return -EISCONN if transmission control block is already in use. - * @return -ENOMEM if the receive buffer for the tcb could not be allocated. - * Increase "GNRC_TCP_RCV_BUFFERS". + * @param[in,out] tcb TCB holding the connection information. + * @param[in] address_family Address family of @p local_addr. + * If local_addr == NULL, address_family is ignored. + * @param[in] local_addr If not NULL the connection is bound to @p local_addr. + * If NULL a connection request to all local ip + * addresses is valied. + * @param[in] local_port Port number to listen on. + * + * @returns Zero on success. + * -EAFNOSUPPORT if local_addr != NULL and @p address_family is not supported. + * -EINVAL if @p address_family is not the same the address_family used in TCB. + * -EISCONN if TCB is already in use. + * -ENOMEM if the receive buffer for the TCB could not be allocated. + * Hint: Increase "GNRC_TCP_RCV_BUFFERS". */ int gnrc_tcp_open_passive(gnrc_tcp_tcb_t *tcb, const uint8_t address_family, const uint8_t *local_addr, const uint16_t local_port); /** - * @brief Transmit Data to Peer. + * @brief Transmit data to connected peer. * * @pre gnrc_tcp_tcb_init() must have been successfully called. - * @pre tcb must not be NULL. - * @pre data must not be NULL. + * @pre @p tcb must not be NULL. + * @pre @p data must not be NULL. * * @note Blocks until up to @p len bytes were transmitted or an error occured. * - * @param[in,out] tcb This connections Transmission control block. - * @param[in] data Pointer to the data that should be transmitted. - * @param[in] len Number of bytes that should be transmitted. - * @param[in] user_timeout_duration_us If not zero and there were not data transmitted - * successfully, the function call returns after - * user_timeout_duration_us. If zero not timeout will be - * triggered. - * - * @return On success, the number of successfully transmitted bytes. - * @return -ENOTCONN if connection is not established. - * @return -ECONNRESET if connection was resetted by the peer. - * @return -ECONNABORTED if the connection was aborted. - * @return -ETIMEDOUT if @p user_timeout_duration_us expired. + * @param[in,out] tcb TCB holding the connection information. + * @param[in] data Pointer to the data that should be transmitted. + * @param[in] len Number of bytes that should be transmitted. + * @param[in] user_timeout_duration_us If not zero and there was not data transmitted + * the function returns after user_timeout_duration_us. + * If zero, no timeout will be triggered. + * + * @returns The number of successfully transmitted bytes. + * -ENOTCONN if connection is not established. + * -ECONNRESET if connection was resetted by the peer. + * -ECONNABORTED if the connection was aborted. + * -ETIMEDOUT if @p user_timeout_duration_us expired. */ ssize_t gnrc_tcp_send(gnrc_tcp_tcb_t *tcb, const void *data, const size_t len, const uint32_t user_timeout_duration_us); /** - * @brief Receive Data from the Peer. + * @brief Receive Data from the peer. * * @pre gnrc_tcp_tcb_init() must have been successfully called. - * @pre tcb must not be NULL. - * @pre data must not be NULL. + * @pre @p tcb must not be NULL. + * @pre @p data must not be NULL. * * @note Function blocks if user_timeout_duration_us is not zero. * - * @param[in,out] tcb This connections Transmission control block. - * @param[out] data Pointer to the buffer where the received data - * should be copied into. - * @param[in] max_len Maximum amount to bytes that should be reeived. - * Should not exceed size of @p data. - * @param[in] user_timeout_duration_us Timeout for receive in microseconds. If zero and no data - * is available, the function returns immediately. If not - * zero the function block until data is available or - * user_timeout_duration_us microseconds have passed. - * - * @return On success, the number of bytes read into @p data. - * @return -ENOTCONN if connection is not established. - * @return -EAGAIN if user_timeout_duration_us is zero and no data is available. - * @return -ECONNRESET if connection was resetted by the peer. - * @return -ECONNABORTED if the connection was aborted. - * @return -ETIMEDOUT if @p user_timeout_duration_us expired. + * @param[in,out] tcb TCB holding the connection information. + * @param[out] data Pointer to the buffer where the received data + * should be copied into. + * @param[in] max_len Maximum amount to bytes that should be read + * into @p data. + * @param[in] user_timeout_duration_us Timeout for receive in microseconds. + * If zero and no data is available, the function + * returns immediately. If not zero the function + * blocks until data is available or + * @p user_timeout_duration_us microseconds passed. + * + * @returns The number of bytes read into @p data. + * -ENOTCONN if connection is not established. + * -EAGAIN if user_timeout_duration_us is zero and no data is available. + * -ECONNRESET if connection was resetted by the peer. + * -ECONNABORTED if the connection was aborted. + * -ETIMEDOUT if @p user_timeout_duration_us expired. */ ssize_t gnrc_tcp_recv(gnrc_tcp_tcb_t *tcb, void *data, const size_t max_len, const uint32_t user_timeout_duration_us); /** - * @brief Close a tcp connection. + * @brief Close a TCP connection. * * @pre gnrc_tcp_tcb_init() must have been successfully called. - * @pre tcb must not be NULL. + * @pre @p tcb must not be NULL. * - * @param[in,out] tcb This connections Transmission control block. + * @param[in,out] tcb TCB holding the connection information. * - * @return Zero on success. + * @returns Zero on success. */ int gnrc_tcp_close(gnrc_tcp_tcb_t *tcb); /** - * @brief Set checksum calculated from tcp and network-layer header in tcp-header. + * @brief Calculate and set checksum in TCP header. * - * @param[in] hdr gnrc_pktsnip that contains tcp header. - * @param[in] pseudo_hdr gnrc_pktsnip that contains networklayer header. + * @param[in] hdr Gnrc_pktsnip that contains TCP header. + * @param[in] pseudo_hdr Gnrc_pktsnip that contains network layer header. * - * @return zero on succeed. - * @return -EFAULT if hdr or pseudo_hdr were NULL - * @return -EBADMSG if hdr is not of type GNRC_NETTYPE_TCP - * @return -ENOENT if pseudo_hdr protocol is unsupported. + * @returns Zero on succeed. + * -EFAULT if @p hdr or pseudo_hdr were NULL + * -EBADMSG if @p hdr is not of type GNRC_NETTYPE_TCP + * -ENOENT if @p pseudo_hdr protocol is unsupported. */ int gnrc_tcp_calc_csum(const gnrc_pktsnip_t *hdr, const gnrc_pktsnip_t *pseudo_hdr); /** - * @brief Adds a tcp header to a given payload. Be carefull, leads to huge headers. - * Allocates all option bytes + * @brief Adds a TCP header to a given payload. * - * @param[in] payload payload that follows the tcp header - * @param[in] src Source port in host byte order - * @param[in] dst Destination port in host byte order + * @param[in] payload Payload that follows the TCP header. + * @param[in] src Source port number. + * @param[in] dst Destination port number. * - * @return NULL, if paket buffer is full - * @return Not NULL on success + * @returns Not NULL on success. + * NULL if TCP header was not allocated. */ gnrc_pktsnip_t *gnrc_tcp_hdr_build(gnrc_pktsnip_t *payload, uint16_t src, uint16_t dst); diff --git a/sys/include/net/gnrc/tcp/config.h b/sys/include/net/gnrc/tcp/config.h index 9088c8368..427798f33 100644 --- a/sys/include/net/gnrc/tcp/config.h +++ b/sys/include/net/gnrc/tcp/config.h @@ -9,7 +9,7 @@ /** * @defgroup net_gnrc_tcp TCP * @ingroup net_gnrc - * @brief RIOT's tcp implementation for the gnrc stack + * @brief RIOT's TCP implementation for the GNRC network stack. * * @{ * @@ -29,25 +29,25 @@ extern "C" { #endif /** - * @brief Timeout Duration for user calls. Default 2 minutes + * @brief Timeout duration for user calls. Default is 2 minutes. */ #ifndef GNRC_TCP_CONNECTION_TIMEOUT_DURATION #define GNRC_TCP_CONNECTION_TIMEOUT_DURATION (120U * US_PER_SEC) #endif /** - * @brief Maximum Segment Lifetime. Default 30 secounds + * @brief Maximum segment lifetime (MSL). Default is 30 seconds. */ #ifndef GNRC_TCP_MSL #define GNRC_TCP_MSL (30U * US_PER_SEC) #endif /** - * @brief Maximum Segement Size + * @brief Maximum Segement Size (MSS). */ #ifndef GNRC_TCP_MSS #ifdef MODULE_GNRC_IPV6 -#define GNRC_TCP_MSS (1220U) /**< If IPv6 is used. Get MSS = 1280 - IPv6-Hdr - TCP-Hdr = 1220 */ +#define GNRC_TCP_MSS (1220U) /**< If IPv6 is used. Get MSS = 1280 - IPv6 Hdr - TCP Hdr = 1220 */ #else #define GNRC_TCP_MSS (576U) /**< Default MSS */ #endif @@ -61,7 +61,7 @@ extern "C" { #endif /** - * @brief Default Window Size + * @brief Default receive window size */ #ifndef GNRC_TCP_DEFAULT_WINDOW #define GNRC_TCP_DEFAULT_WINDOW (GNRC_TCP_MSS * GNRC_TCP_MSS_MULTIPLICATOR) @@ -75,21 +75,21 @@ extern "C" { #endif /** - * @brief Default Receive Buffer Size + * @brief Default receive buffer size */ #ifndef GNRC_TCP_RCV_BUF_SIZE #define GNRC_TCP_RCV_BUF_SIZE (GNRC_TCP_DEFAULT_WINDOW) #endif /** - * @brief Lower Bound for RTO = 1 sec (see RFC 6298) + * @brief Lower bound for RTO = 1 sec (see RFC 6298) */ #ifndef GNRC_TCP_RTO_LOWER_BOUND #define GNRC_TCP_RTO_LOWER_BOUND (1U * US_PER_SEC) #endif /** - * @brief Upper Bound for RTO = 60 sec (see RFC 6298) + * @brief Upper bound for RTO = 60 sec (see RFC 6298) */ #ifndef GNRC_TCP_RTO_UPPER_BOUND #define GNRC_TCP_RTO_UPPER_BOUND (60U * US_PER_SEC) @@ -124,14 +124,14 @@ extern "C" { #endif /** - * @brief Lower Bound for the duration between probes + * @brief Lower bound for the duration between probes */ #ifndef GNRC_TCP_PROBE_LOWER_BOUND #define GNRC_TCP_PROBE_LOWER_BOUND (1U * US_PER_SEC) #endif /** - * @brief Upper Bound for the duration between probes + * @brief Upper bound for the duration between probes */ #ifndef GNRC_TCP_PROBE_UPPER_BOUND #define GNRC_TCP_PROBE_UPPER_BOUND (60U * US_PER_SEC) diff --git a/sys/include/net/gnrc/tcp/tcb.h b/sys/include/net/gnrc/tcp/tcb.h index bb3faf672..134b2146e 100644 --- a/sys/include/net/gnrc/tcp/tcb.h +++ b/sys/include/net/gnrc/tcp/tcb.h @@ -9,12 +9,12 @@ /** * @defgroup net_gnrc_tcp TCP * @ingroup net_gnrc - * @brief RIOT's tcp implementation for the gnrc stack + * @brief RIOT's TCP implementation for the GNRC network stack. * * @{ * * @file - * @brief GNRC TCP transmission control block + * @brief GNRC TCP transmission control block (TCB) * * @author Simon Brummer */ @@ -40,48 +40,48 @@ extern "C" { #endif /** - * @brief Size of the tcbs internal message queue + * @brief Size of the TCB message queue */ #define GNRC_TCP_TCB_MSG_QUEUE_SIZE (8U) /** - * @brief transmission control block of gnrc_tcp + * @brief Transmission control block of GNRC TCP. */ typedef struct _transmission_control_block { - uint8_t address_family; /**< Address Family of local_addr and peer_addr */ + uint8_t address_family; /**< Address Family of local_addr / peer_addr */ #ifdef MODULE_GNRC_IPV6 - uint8_t local_addr[sizeof(ipv6_addr_t)]; /**< local IP address */ - uint8_t peer_addr[sizeof(ipv6_addr_t)]; /**< peer IP address */ + uint8_t local_addr[sizeof(ipv6_addr_t)]; /**< Local IP address */ + uint8_t peer_addr[sizeof(ipv6_addr_t)]; /**< Peer IP address */ #endif - uint16_t local_port; /**< local connections port number */ - uint16_t peer_port; /**< port connections port number */ + uint16_t local_port; /**< Local connections port number */ + uint16_t peer_port; /**< Peer connections port number */ uint8_t state; /**< Connections state */ uint8_t status; /**< A connections status flags */ - uint32_t snd_una; /**< Send Unacknowledged */ - uint32_t snd_nxt; /**< Send Next */ - uint16_t snd_wnd; /**< Send Window */ - uint32_t snd_wl1; /**< SeqNo. Last Windowupdate */ - uint32_t snd_wl2; /**< AckNo. Last Windowupdate */ - uint32_t rcv_nxt; /**< Receive Next */ - uint16_t rcv_wnd; /**< Receive Window */ - uint32_t iss; /**< Initial Sequence Number */ - uint32_t irs; /**< Initial Received Sequence Number */ + uint32_t snd_una; /**< Send unacknowledged */ + uint32_t snd_nxt; /**< Send next */ + uint16_t snd_wnd; /**< Send window */ + uint32_t snd_wl1; /**< SeqNo. from last window update */ + uint32_t snd_wl2; /**< AckNo. from last window update */ + uint32_t rcv_nxt; /**< Receive next */ + uint16_t rcv_wnd; /**< Receive window */ + uint32_t iss; /**< Initial sequence sumber */ + uint32_t irs; /**< Initial received sequence number */ uint16_t mss; /**< The peers MSS */ uint32_t rtt_start; /**< Timer value for rtt estimation */ - int32_t rtt_var; /**< Round Trip Time variance */ - int32_t srtt; /**< Smoothed Round Trip Time */ - int32_t rto; /**< Retransmission Timeout Duration */ - uint8_t retries; /**< Number of Retransmissions */ + int32_t rtt_var; /**< Round trip time variance */ + int32_t srtt; /**< Smoothed round trip time */ + int32_t rto; /**< Retransmission timeout duration */ + uint8_t retries; /**< Number of retransmissions */ xtimer_t tim_tout; /**< Timer struct for timeouts */ msg_t msg_tout; /**< Message, sent on timeouts */ - gnrc_pktsnip_t *pkt_retransmit; /**< Pointer to Packet in "retransmit queue" */ + gnrc_pktsnip_t *pkt_retransmit; /**< Pointer to packet in "retransmit queue" */ kernel_pid_t owner; /**< PID of this connection handling thread */ - msg_t msg_queue[GNRC_TCP_TCB_MSG_QUEUE_SIZE]; /**< Tcb's message queue */ + msg_t msg_queue[GNRC_TCP_TCB_MSG_QUEUE_SIZE]; /**< TCB message queue */ uint8_t *rcv_buf_raw; /**< Pointer to the receive buffer */ - ringbuffer_t rcv_buf; /**< Receive Buffer data structure */ + ringbuffer_t rcv_buf; /**< Receive buffer data structure */ mutex_t fsm_lock; /**< Mutex for FSM access synchronization */ - mutex_t function_lock; /**< Mutex for Function call synchronization */ - struct _transmission_control_block *next; /**< Pointer next TCP connection */ + mutex_t function_lock; /**< Mutex for function call synchronization */ + struct _transmission_control_block *next; /**< Pointer next TCB */ } gnrc_tcp_tcb_t; #ifdef __cplusplus diff --git a/sys/include/net/tcp.h b/sys/include/net/tcp.h index 9ef4258c6..c206fd9f3 100644 --- a/sys/include/net/tcp.h +++ b/sys/include/net/tcp.h @@ -29,7 +29,7 @@ extern "C" { #endif /** - * @brief TCP offset value boundries + * @brief TCP offset value boundries. * @{ */ #define TCP_HDR_OFFSET_MIN (0x05) @@ -37,7 +37,7 @@ extern "C" { /** @} */ /** - * @brief TCP Option "Kind" field defines + * @brief TCP Option "Kind"-field defines. * @{ */ #define TCP_OPTION_KIND_EOL (0x00) /**< "End of List"-Option */ @@ -46,7 +46,7 @@ extern "C" { /** @} */ /** - * @brief TCP Option Length Field Values + * @brief TCP option "length"-field values. * @{ */ #define TCP_OPTION_LENGTH_MSS (0x04) /**< MSS Option Size always 4 */ @@ -56,29 +56,29 @@ extern "C" { * @brief TCP header definition */ typedef struct __attribute__((packed)) { - network_uint16_t src_port; /**< source port, in network byte order */ - network_uint16_t dst_port; /**< destination port, in network byte order */ - network_uint32_t seq_num; /**< sequence number, in network byte order */ + network_uint16_t src_port; /**< Source port, in network byte order */ + network_uint16_t dst_port; /**< Destination port, in network byte order */ + network_uint32_t seq_num; /**< Dequence number, in network byte order */ network_uint32_t ack_num; /**< Acknowledgement number, in network byte order */ network_uint16_t off_ctl; /**< Data Offset and control Bits in network byte order */ - network_uint16_t window; /**< window, in network byte order */ - network_uint16_t checksum; /**< checksum, in network byte order */ - network_uint16_t urgent_ptr; /**< urgent pointer, in network byte order */ + network_uint16_t window; /**< Window, in network byte order */ + network_uint16_t checksum; /**< Checksum, in network byte order */ + network_uint16_t urgent_ptr; /**< Urgent pointer, in network byte order */ } tcp_hdr_t; /** - * @brief TCP Option Field Helper Structure + * @brief TCP option field helper structure */ typedef struct __attribute__((packed)) { - uint8_t kind; /**< TCP options Kind field */ - uint8_t length; /**< TCP options Length field */ - uint8_t value[]; /**< Pointer to TCP options Value field */ + uint8_t kind; /**< TCP options "Kind" field */ + uint8_t length; /**< TCP options "Length" field */ + uint8_t value[]; /**< TCP options "Value" field */ } tcp_hdr_opt_t; /** * @brief Print the given TCP header to STDOUT * - * @param[in] hdr TCP header to print + * @param[in] hdr TCP header to print */ void tcp_hdr_print(tcp_hdr_t *hdr); diff --git a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp.c b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp.c index b8c7fbb73..821dfac2c 100644 --- a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp.c +++ b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp.c @@ -36,7 +36,7 @@ #include "debug.h" /** - * @brief Allocate memory for TCP thread's stack + * @brief Allocate memory for GNRC TCP thread stack. */ #if ENABLE_DEBUG static char _stack[TCP_EVENTLOOP_STACK_SIZE + THREAD_EXTRA_STACKSIZE_PRINTF]; @@ -45,47 +45,46 @@ static char _stack[TCP_EVENTLOOP_STACK_SIZE]; #endif /** - * @brief TCPs eventloop pid, declared externally + * @brief TCPs eventloop pid, declared externally. */ kernel_pid_t gnrc_tcp_pid = KERNEL_PID_UNDEF; /** - * @brief Head of liked list of active connections + * @brief Head of liked TCB list. */ gnrc_tcp_tcb_t *_list_tcb_head; /** - * @brief Mutex to protect the connection list + * @brief Mutex for TCB list synchronization. */ mutex_t _list_tcb_lock; /** - * @brief Establishes a new TCP connection + * @brief Establishes a new TCP connection. * - * @param[in/out] tcb This connections Transmission control block. - * @param[in] target_addr Target Address to connect to, if this is a active connection. - * @param[in] target_port Target Port to connect to, if this is a active connection. - * @param[in] local_addr Local Address to bind on, if this is a passive connection. - * @param[in] local_port Local Port to bind on, if this is a passive connection. - * @param[in] passive Flag to indicate if this is a active or passive open. + * @param[in,out] tcb TCB holding the connection information. + * @param[in] target_addr Target address to connect to, if this is a active connection. + * @param[in] target_port Target port to connect to, if this is a active connection. + * @param[in] local_addr Local address to bind on, if this is a passive connection. + * @param[in] local_port Local port to bind on, if this is a passive connection. + * @param[in] passive Flag to indicate if this is a active or passive open. * - * @return 0 on success. - * @return -EISCONN if transmission control block is already in use. - * @return -ENOMEM if the receive buffer for the tcb could not be allocated. - * Increase "GNRC_TCP_RCV_BUFFERS". - * @return -EADDRINUSE if @p local_port is already used by another connection. Only active mode. - * @return -ETIMEDOUT if the connection could not be opened. Only active mode. - * @return -ECONNREFUSED if the connection was resetted by the peer. + * @returns Zero on success. + * -EISCONN if TCB is already connected. + * -ENOMEM if the receive buffer for the TCB could not be allocated. + * -EADDRINUSE if @p local_port is already in use. + * -ETIMEDOUT if the connection opening timed out. + * -ECONNREFUSED if the connection was resetted by the peer. */ static int _gnrc_tcp_open(gnrc_tcp_tcb_t *tcb, const uint8_t *target_addr, uint16_t target_port, const uint8_t *local_addr, uint16_t local_port, uint8_t passive) { - msg_t msg; /* Message for incomming Messages */ - msg_t connection_timeout_msg; /* Connection Timeout Message */ - xtimer_t connection_timeout_timer; /* Connection Timeout Timer */ - int8_t ret = 0; /* Return Value */ + msg_t msg; /* Message for incomming messages */ + msg_t connection_timeout_msg; /* Connection timeout message */ + xtimer_t connection_timeout_timer; /* Connection timeout timer */ + int8_t ret = 0; /* Return value */ - /* Lock the tcb for this function call */ + /* Lock the TCB for this function call */ mutex_lock(&(tcb->function_lock)); /* Connection is already connected: Return -EISCONN */ @@ -100,48 +99,40 @@ static int _gnrc_tcp_open(gnrc_tcp_tcb_t *tcb, const uint8_t *target_addr, uint1 /* Setup passive connection */ if (passive) { - /* Set Status Flags */ + /* Mark connection as passive opend */ tcb->status |= STATUS_PASSIVE; if (local_addr == NULL) { tcb->status |= STATUS_ALLOW_ANY_ADDR; } - /* If local address is specified: Copy it into tcb */ - else { - switch (tcb->address_family) { #ifdef MODULE_GNRC_IPV6 - case AF_INET6: - memcpy(tcb->local_addr, local_addr, sizeof(ipv6_addr_t)); - break; -#endif - } + /* If local address is specified: Copy it into TCB */ + else if (tcb->address_family == AF_INET6) { + memcpy(tcb->local_addr, local_addr, sizeof(ipv6_addr_t)); } - /* Assign Port to listen on, to tcb */ +#endif + /* Set port number to listen on */ tcb->local_port = local_port; } /* Setup active connection */ else { - /* Copy Target Address and Port into tcb structure */ - if (target_addr != NULL) { - switch (tcb->address_family) { + /* Copy target address and port number into TCB */ #ifdef MODULE_GNRC_IPV6 - case AF_INET6: - memcpy(tcb->peer_addr, target_addr, sizeof(ipv6_addr_t)); - break; - #endif - } + if ((target_addr != NULL) && (tcb->address_family == AF_INET6)) { + memcpy(tcb->peer_addr, target_addr, sizeof(ipv6_addr_t)); } - /* Copy Port Information, verfication happens in fsm */ + #endif + /* Assign port numbers, verfication happens in fsm */ tcb->local_port = local_port; tcb->peer_port = target_port; - /* Setup Timeout: If connection could not be established before */ + /* Setup timeout: If connection could not be established before */ /* the timer expired, the connection attempt failed */ connection_timeout_msg.type = MSG_TYPE_CONNECTION_TIMEOUT; xtimer_set_msg(&connection_timeout_timer, GNRC_TCP_CONNECTION_TIMEOUT_DURATION, &connection_timeout_msg, tcb->owner); } - /* Call FSM with Event: CALL_OPEN */ + /* Call FSM with event: CALL_OPEN */ ret = _fsm(tcb, FSM_EVENT_CALL_OPEN, NULL, NULL, 0); if (ret == -ENOMEM) { DEBUG("gnrc_tcp.c : gnrc_tcp_connect() : Out of receive buffers.\n"); @@ -180,7 +171,7 @@ static int _gnrc_tcp_open(gnrc_tcp_tcb_t *tcb, const uint8_t *target_addr, uint1 return ret; } -/* External GNRC_TCP API */ +/* External GNRC TCP API */ int gnrc_tcp_init(void) { /* Guard: Check if thread is already running */ @@ -188,26 +179,25 @@ int gnrc_tcp_init(void) return -1; } - /* Initialize Mutex for linked-list synchronization */ + /* Initialize mutex for TCB list synchronization */ mutex_init(&(_list_tcb_lock)); - /* Initialize Linked-List for connection storage */ + /* Initialize TCB list */ _list_tcb_head = NULL; /* Initialize receive buffers */ _rcvbuf_init(); - /* Start TCP processing loop */ + /* Start TCP processing thread */ return thread_create(_stack, sizeof(_stack), TCP_EVENTLOOP_PRIO, 0, _event_loop, NULL, "gnrc_tcp"); } void gnrc_tcp_tcb_init(gnrc_tcp_tcb_t *tcb) { + memset(tcb, 0, sizeof(gnrc_tcp_tcb_t)); #ifdef MODULE_GNRC_IPV6 tcb->address_family = AF_INET6; - ipv6_addr_set_unspecified((ipv6_addr_t *) tcb->local_addr); - ipv6_addr_set_unspecified((ipv6_addr_t *) tcb->peer_addr); #else tcb->address_family = AF_UNSPEC; DEBUG("gnrc_tcp.c : gnrc_tcp_tcb_init() : Address unspec, add netlayer module to makefile\n"); @@ -215,28 +205,12 @@ void gnrc_tcp_tcb_init(gnrc_tcp_tcb_t *tcb) tcb->local_port = PORT_UNSPEC; tcb->peer_port = PORT_UNSPEC; tcb->state = FSM_STATE_CLOSED; - tcb->status = 0; - tcb->snd_una = 0; - tcb->snd_nxt = 0; - tcb->snd_wnd = 0; - tcb->snd_wl1 = 0; - tcb->snd_wl2 = 0; - tcb->rcv_nxt = 0; - tcb->rcv_wnd = 0; - tcb->iss = 0; - tcb->irs = 0; - tcb->mss = 0; - tcb->rtt_start = 0; tcb->rtt_var = RTO_UNINITIALIZED; tcb->srtt = RTO_UNINITIALIZED; tcb->rto = RTO_UNINITIALIZED; - tcb->retries = 0; - tcb->pkt_retransmit = NULL; tcb->owner = KERNEL_PID_UNDEF; - tcb->rcv_buf_raw = NULL; mutex_init(&(tcb->fsm_lock)); mutex_init(&(tcb->function_lock)); - tcb->next = NULL; } int gnrc_tcp_open_active(gnrc_tcp_tcb_t *tcb, const uint8_t address_family, @@ -247,19 +221,20 @@ int gnrc_tcp_open_active(gnrc_tcp_tcb_t *tcb, const uint8_t address_family, assert(target_addr != NULL); assert(target_port != PORT_UNSPEC); - /* Check AF-Family Support from target_addr */ - switch (address_family) { + /* Check if AF-Family of target_addr is supported */ #ifdef MODULE_GNRC_IPV6 - case AF_INET6: - break; -#endif - default: - return -EAFNOSUPPORT; + if (address_family != AF_INET6) { + return -EAFNOSUPPORT; } - /* Check if AF-Family for Target Address matches internally used AF-Family */ +#else + return -EAFNOSUPPORT; +#endif + + /* Check if AF-Family for target address matches internally used AF-Family */ if (tcb->address_family != address_family) { return -EINVAL; } + /* Proceed with connection opening */ return _gnrc_tcp_open(tcb, target_addr, target_port, NULL, local_port, 0); } @@ -271,19 +246,19 @@ int gnrc_tcp_open_passive(gnrc_tcp_tcb_t *tcb, const uint8_t address_family, /* Check AF-Family support if local address was supplied */ if (local_addr != NULL) { - switch (address_family) { #ifdef MODULE_GNRC_IPV6 - case AF_INET6: - break; -#endif - default: - return -EAFNOSUPPORT; + if (address_family != AF_INET6) { + return -EAFNOSUPPORT; } +#else + return -EAFNOSUPPORT; +#endif /* Check if AF-Family matches internally used AF-Family */ if (tcb->address_family != address_family) { return -EINVAL; } } + /* Proceed with connection opening */ return _gnrc_tcp_open(tcb, NULL, 0, local_addr, local_port, 1); } @@ -293,18 +268,18 @@ ssize_t gnrc_tcp_send(gnrc_tcp_tcb_t *tcb, const void *data, const size_t len, assert(tcb != NULL); assert(data != NULL); - msg_t msg; /* Message for incomming Messages */ - msg_t connection_timeout_msg; /* Connection Timeout Message */ - msg_t probe_timeout_msg; /* Probe Timeout Message */ - msg_t user_timeout_msg; /* User Specified Timeout Message */ - xtimer_t connection_timeout_timer; /* Connection Timeout Timer */ - xtimer_t probe_timeout_timer; /* Probe Timeout Timer */ - xtimer_t user_timeout_timer; /* User Specified Timeout Timer */ - uint32_t probe_timeout_duration_us = 0; /* Probe Timeout Duration in microseconds */ - ssize_t ret = 0; /* Return Value */ + msg_t msg; /* Message for incomming messages */ + msg_t connection_timeout_msg; /* Connection timeout message */ + msg_t probe_timeout_msg; /* Probe timeout message */ + msg_t user_timeout_msg; /* User specified timeout message */ + xtimer_t connection_timeout_timer; /* Connection timeout timer */ + xtimer_t probe_timeout_timer; /* Probe timeout timer */ + xtimer_t user_timeout_timer; /* User specified timeout timer */ + uint32_t probe_timeout_duration_us = 0; /* Probe timeout duration in microseconds */ + ssize_t ret = 0; /* Return value */ bool probing = false; /* True if this connection is probing */ - /* Lock the tcb for this function call */ + /* Lock the TCB for this function call */ mutex_lock(&(tcb->function_lock)); /* Check if connection is in a valid state */ @@ -313,16 +288,16 @@ ssize_t gnrc_tcp_send(gnrc_tcp_tcb_t *tcb, const void *data, const size_t len, return -ENOTCONN; } - /* Re-init message queue, take ownership. FSM can send Messages to this thread now */ + /* Re-init message queue, take ownership. FSM can send messages to this thread now */ msg_init_queue(tcb->msg_queue, GNRC_TCP_TCB_MSG_QUEUE_SIZE); tcb->owner = thread_getpid(); - /* Setup Connection Timeout */ + /* Setup connection timeout */ connection_timeout_msg.type = MSG_TYPE_CONNECTION_TIMEOUT; xtimer_set_msg(&connection_timeout_timer, GNRC_TCP_CONNECTION_TIMEOUT_DURATION, &connection_timeout_msg, tcb->owner); - /* Setup User specified timeout if timeout_us is greater than zero */ + /* Setup user specified timeout if timeout_us is greater than zero */ if (timeout_duration_us > 0) { user_timeout_msg.type = MSG_TYPE_USER_SPEC_TIMEOUT; xtimer_set_msg(&user_timeout_timer, timeout_duration_us, &user_timeout_msg, tcb->owner); @@ -343,13 +318,13 @@ ssize_t gnrc_tcp_send(gnrc_tcp_tcb_t *tcb, const void *data, const size_t len, probing = true; probe_timeout_duration_us = tcb->rto; } - /* Initialize Probe Timer */ + /* Initialize probe timer */ probe_timeout_msg.type = MSG_TYPE_PROBE_TIMEOUT; xtimer_set_msg(&probe_timeout_timer, probe_timeout_duration_us, &probe_timeout_msg, tcb->owner); } - /* Try to send data in case there nothing has been sent and we are not probing */ + /* Try to send data if nothing has been sent and we are not probing */ if (ret == 0 && !probing) { ret = _fsm(tcb, FSM_EVENT_CALL_SEND, NULL, (void *) data, len); } @@ -371,7 +346,7 @@ ssize_t gnrc_tcp_send(gnrc_tcp_tcb_t *tcb, const void *data, const size_t len, case MSG_TYPE_PROBE_TIMEOUT: DEBUG("gnrc_tcp.c : gnrc_tcp_send() : PROBE_TIMEOUT\n"); - /* Send Probe */ + /* Send probe */ _fsm(tcb, FSM_EVENT_SEND_PROBE, NULL, NULL, 0); probe_timeout_duration_us += probe_timeout_duration_us; @@ -386,7 +361,7 @@ ssize_t gnrc_tcp_send(gnrc_tcp_tcb_t *tcb, const void *data, const size_t len, case MSG_TYPE_NOTIFY_USER: DEBUG("gnrc_tcp.c : gnrc_tcp_send() : NOTIFY_USER\n"); - /* Connection is alive: Reset Connection Timeout */ + /* Connection is alive: Reset connection timeout */ xtimer_set_msg(&connection_timeout_timer, GNRC_TCP_CONNECTION_TIMEOUT_DURATION, &connection_timeout_msg, tcb->owner); @@ -417,14 +392,14 @@ ssize_t gnrc_tcp_recv(gnrc_tcp_tcb_t *tcb, void *data, const size_t max_len, assert(tcb != NULL); assert(data != NULL); - msg_t msg; /* Message for incomming Messages */ - msg_t connection_timeout_msg; /* Connection Timeout Message */ - msg_t user_timeout_msg; /* User Specified Timeout Message */ - xtimer_t connection_timeout_timer; /* Connection Timeout Timer */ - xtimer_t user_timeout_timer; /* User Specified Timeout Timer */ - ssize_t ret = 0; /* Return Value */ + msg_t msg; /* Message for incomming messages */ + msg_t connection_timeout_msg; /* Connection timeout message */ + msg_t user_timeout_msg; /* User specified timeout message */ + xtimer_t connection_timeout_timer; /* Connection timeout timer */ + xtimer_t user_timeout_timer; /* User specified timeout timer */ + ssize_t ret = 0; /* Return value */ - /* Lock the tcb for this function call */ + /* Lock the TCB for this function call */ mutex_lock(&(tcb->function_lock)); /* Check if connection is in a valid state */ @@ -448,16 +423,16 @@ ssize_t gnrc_tcp_recv(gnrc_tcp_tcb_t *tcb, void *data, const size_t max_len, msg_init_queue(tcb->msg_queue, GNRC_TCP_TCB_MSG_QUEUE_SIZE); tcb->owner = thread_getpid(); - /* Setup Connection Timeout */ + /* Setup connection timeout */ connection_timeout_msg.type = MSG_TYPE_CONNECTION_TIMEOUT; xtimer_set_msg(&connection_timeout_timer, GNRC_TCP_CONNECTION_TIMEOUT_DURATION, &connection_timeout_msg, tcb->owner); - /* Setup User Specified Timeout */ + /* Setup user specified timeout */ user_timeout_msg.type = MSG_TYPE_USER_SPEC_TIMEOUT; xtimer_set_msg(&user_timeout_timer, timeout_duration_us, &user_timeout_msg, tcb->owner); - /* Processing Loop */ + /* Processing loop */ while (ret == 0) { /* Check if the connections state is closed. If so, a reset was received */ if (tcb->state == FSM_STATE_CLOSED) { @@ -506,11 +481,11 @@ int gnrc_tcp_close(gnrc_tcp_tcb_t *tcb) { assert(tcb != NULL); - msg_t msg; /* Message for incomming Messages */ - msg_t connection_timeout_msg; /* Connection Timeout Message */ - xtimer_t connection_timeout_timer; /* Connection Timeout Timer */ + msg_t msg; /* Message for incomming messages */ + msg_t connection_timeout_msg; /* Connection timeout message */ + xtimer_t connection_timeout_timer; /* Connection timeout timer */ - /* Lock the tcb for this function call */ + /* Lock the TCB for this function call */ mutex_lock(&(tcb->function_lock)); /* Start connection teardown if the connection was not closed before */ @@ -519,7 +494,7 @@ int gnrc_tcp_close(gnrc_tcp_tcb_t *tcb) msg_init_queue(tcb->msg_queue, GNRC_TCP_TCB_MSG_QUEUE_SIZE); tcb->owner = thread_getpid(); - /* Setup Connection Timeout */ + /* Setup connection timeout */ connection_timeout_msg.type = MSG_TYPE_CONNECTION_TIMEOUT; xtimer_set_msg(&connection_timeout_timer, GNRC_TCP_CONNECTION_TIMEOUT_DURATION, &connection_timeout_msg, tcb->owner); @@ -577,7 +552,7 @@ gnrc_pktsnip_t *gnrc_tcp_hdr_build(gnrc_pktsnip_t *payload, uint16_t src, uint16 gnrc_pktsnip_t *res; tcp_hdr_t *hdr; - /* allocate header */ + /* Allocate header */ res = gnrc_pktbuf_add(payload, NULL, sizeof(tcp_hdr_t), GNRC_NETTYPE_TCP); if (res == NULL) { DEBUG("tcp: No space left in packet buffer\n"); @@ -588,7 +563,7 @@ gnrc_pktsnip_t *gnrc_tcp_hdr_build(gnrc_pktsnip_t *payload, uint16_t src, uint16 /* Clear Header */ memset(hdr, 0, sizeof(tcp_hdr_t)); - /* Initialize Header with sane Defaults */ + /* Initialize header with sane defaults */ hdr->src_port = byteorder_htons(src); hdr->dst_port = byteorder_htons(dst); hdr->checksum = byteorder_htons(0); diff --git a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_eventloop.c b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_eventloop.c index c3f44d779..da38da139 100644 --- a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_eventloop.c +++ b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_eventloop.c @@ -33,21 +33,23 @@ #define ENABLE_DEBUG (0) #include "debug.h" +static msg_t _eventloop_msg_queue[TCP_EVENTLOOP_MSG_QUEUE_SIZE]; + /** - * @brief send function, pass paket down the network stack + * @brief Send function, pass paket down the network stack. * - * @param[in] pkt paket to pass down the network stack + * @param[in] pkt Paket to send. * - * @return zero on success - * @return negative value on error - * @return -EBADMSG if tcp header is missing + * @returns Zero on success. + * Negative value on error. + * @returns -EBADMSG if TCP header is missing in @p pkt. */ static int _send(gnrc_pktsnip_t *pkt) { - /* NOTE: Sending Direction: pkt = nw, nw->next = tcp, tcp->next = payload */ + /* NOTE: In sending direction: pkt = nw, nw->next = tcp, tcp->next = payload */ gnrc_pktsnip_t *tcp; - /* Search for tcp header */ + /* Search for TCP header */ LL_SEARCH_SCALAR(pkt, tcp, type, GNRC_NETTYPE_TCP); if (tcp == NULL) { DEBUG("gnrc_tcp_eventloop : _send() : tcp header missing.\n"); @@ -55,7 +57,7 @@ static int _send(gnrc_pktsnip_t *pkt) return -EBADMSG; } - /* Dispatch to network layer */ + /* Dispatch packet to network layer */ if (!gnrc_netapi_dispatch_send(pkt->type, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) { DEBUG("gnrc_tcp_eventloop : _send() : network layer not found\n"); gnrc_pktbuf_release(pkt); @@ -64,21 +66,21 @@ static int _send(gnrc_pktsnip_t *pkt) } /** - * @brief recv function, receive packet from network layer. + * @brief Receive function, receive packet from network layer. * - * @param[in] pkt incomming paket to process + * @param[in] pkt Incomming paket. * - * @return zero on success - * @return negative value on error - * @return -EACCES if not able to get write access to packet - * @return -ERANGE if segment offset is less than 5 - * @return -ENOMSG if paket can't be marked - * @return -EINVAL if checksum was invalid - * @return -ENOTCONN if no module is interested in this context + * @returns Zero on success. + * Negative value on error. + * -EACCES if write access to packet was not aquired. + * -ERANGE if segment offset value is less than 5. + * -ENOMSG if paket couldn't be marked. + * -EINVAL if checksum was invalid. + * -ENOTCONN if no TCB is interested in @p pkt. */ static int _receive(gnrc_pktsnip_t *pkt) { - /* NOTE: Receiving direction: pkt = payload, payload->next = tcp, tcp->next = nw */ + /* NOTE: In receiving direction: pkt = payload, payload->next = tcp, tcp->next = nw */ uint16_t ctl = 0; uint16_t src = 0; uint16_t dst = 0; @@ -89,7 +91,7 @@ static int _receive(gnrc_pktsnip_t *pkt) gnrc_tcp_tcb_t *tcb = NULL; tcp_hdr_t *hdr; - /* Get write access to the TCP Header */ + /* Get write access to the TCP header */ gnrc_pktsnip_t *tcp = gnrc_pktbuf_start_write(pkt); if (tcp == NULL) { DEBUG("gnrc_tcp_eventloop.c : _receive() : can't write to packet\n"); @@ -99,7 +101,7 @@ static int _receive(gnrc_pktsnip_t *pkt) pkt = tcp; #ifdef MODULE_GNRC_IPV6 - /* Get IP Header, discard packet if doesn't contain an ip header */ + /* Get IPv6 header, discard packet if doesn't contain an ip header */ LL_SEARCH_SCALAR(pkt, ip, type, GNRC_NETTYPE_IPV6); if (ip == NULL) { DEBUG("gnrc_tcp_eventloop.c : _receive() : pkt contains no IP Header\n"); @@ -108,7 +110,7 @@ static int _receive(gnrc_pktsnip_t *pkt) } #endif - /* Get TCP Header */ + /* Get TCP header */ LL_SEARCH_SCALAR(pkt, tcp, type, GNRC_NETTYPE_TCP); if (tcp == NULL) { DEBUG("gnrc_tcp_eventloop.c : _receive() : pkt contains no TCP Header\n"); @@ -123,17 +125,17 @@ static int _receive(gnrc_pktsnip_t *pkt) dst = byteorder_ntohs(hdr->dst_port); syn = ((ctl & MSK_SYN_ACK) == MSK_SYN); - /* Validate Offset */ + /* Validate offset */ if (GET_OFFSET(ctl) < TCP_HDR_OFFSET_MIN) { DEBUG("gnrc_tcp_eventloop.c : _receive() : unexpected Offset Value\n"); gnrc_pktbuf_release(pkt); return -ERANGE; } - /* Calculate tcp header size */ + /* Calculate TCP header size */ hdr_size = GET_OFFSET(ctl) * 4; - /* Mark TCP-Header, if it contains any payload */ + /* Mark TCP header if it contains any payload */ if ((pkt->type == GNRC_NETTYPE_TCP) && (pkt->size != hdr_size)) { tcp = gnrc_pktbuf_mark(pkt, hdr_size, GNRC_NETTYPE_TCP); if (tcp == NULL) { @@ -144,24 +146,24 @@ static int _receive(gnrc_pktsnip_t *pkt) pkt->type = GNRC_NETTYPE_UNDEF; } - /* Validate Checksum */ + /* Validate checksum */ if (byteorder_ntohs(hdr->checksum) != _pkt_calc_csum(tcp, ip, pkt)) { DEBUG("gnrc_tcp_eventloop.c : _receive() : Invalid checksum\n"); gnrc_pktbuf_release(pkt); return -EINVAL; } - /* Find tcb to de-multiplex this packet to */ + /* Find TCB to for this packet */ mutex_lock(&_list_tcb_lock); tcb = _list_tcb_head; while (tcb) { #ifdef MODULE_GNRC_IPV6 - /* Check if current tcb is fitting for the incomming packet */ + /* Check if current TCB is fitting for the incomming packet */ if (ip->type == GNRC_NETTYPE_IPV6 && tcb->address_family == AF_INET6) { /* If SYN is set, a connection is listening on that port ... */ ipv6_addr_t *tmp_addr = NULL; if (syn && tcb->local_port == dst && tcb->state == FSM_STATE_LISTEN) { - /* ... and local addr is unspec or preconfigured */ + /* ... and local addr is unspec or pre configured */ tmp_addr = &((ipv6_hdr_t *)ip->data)->dst; if (ipv6_addr_equal((ipv6_addr_t *) tcb->local_addr, (ipv6_addr_t *) tmp_addr) || ipv6_addr_is_unspecified((ipv6_addr_t *) tcb->local_addr)) { @@ -171,7 +173,7 @@ static int _receive(gnrc_pktsnip_t *pkt) /* If SYN is not set and the ports match ... */ if (!syn && tcb->local_port == dst && tcb->peer_port == src) { - /* .. and the IP-Addresses match */ + /* .. and the IPv6 addresses match */ tmp_addr = &((ipv6_hdr_t * )ip->data)->src; if (ipv6_addr_equal((ipv6_addr_t *) tcb->peer_addr, (ipv6_addr_t *) tmp_addr)) { break; @@ -179,7 +181,7 @@ static int _receive(gnrc_pktsnip_t *pkt) } } #else - /* Supress compiler warnings if TCP is build without IP-Layer */ + /* Supress compiler warnings if TCP is build without network layer */ (void) syn; (void) src; (void) dst; @@ -188,13 +190,13 @@ static int _receive(gnrc_pktsnip_t *pkt) } mutex_unlock(&_list_tcb_lock); - /* Call FSM with event RCVD_PKT if a fitting connection was found */ + /* Call FSM with event RCVD_PKT if a fitting TCB was found */ if (tcb != NULL) { _fsm(tcb, FSM_EVENT_RCVD_PKT, pkt, NULL, 0); } - /* No fitting connection has been found. Respond with reset */ + /* No fitting TCB has been found. Respond with reset */ else { - DEBUG("gnrc_tcp_eventloop.c : _receive() : Can't find fitting connection\n"); + DEBUG("gnrc_tcp_eventloop.c : _receive() : Can't find fitting tcb\n"); if ((ctl & MSK_RST) != MSK_RST) { _pkt_build_reset_from_pkt(&reset, pkt); gnrc_netapi_send(gnrc_tcp_pid, reset); @@ -209,7 +211,6 @@ void *_event_loop(__attribute__((unused)) void *arg) { msg_t msg; msg_t reply; - msg_t msg_queue[TCP_EVENTLOOP_MSG_QUEUE_SIZE]; /* Store pid */ gnrc_tcp_pid = thread_getpid(); @@ -218,44 +219,44 @@ void *_event_loop(__attribute__((unused)) void *arg) reply.type = GNRC_NETAPI_MSG_TYPE_ACK; reply.content.value = (uint32_t)-ENOTSUP; - /* Init message queue*/ - msg_init_queue(msg_queue, TCP_EVENTLOOP_MSG_QUEUE_SIZE); + /* Init message queue */ + msg_init_queue(_eventloop_msg_queue, TCP_EVENTLOOP_MSG_QUEUE_SIZE); - /* Register GNRC_tcp in netreg */ + /* Register GNRC TCPs handling thread in netreg */ gnrc_netreg_entry_t entry; gnrc_netreg_entry_init_pid(&entry, GNRC_NETREG_DEMUX_CTX_ALL, gnrc_tcp_pid); gnrc_netreg_register(GNRC_NETTYPE_TCP, &entry); - /* dispatch NETAPI Messages */ + /* dispatch NETAPI messages */ while (1) { msg_receive(&msg); switch (msg.type) { - /* Pass Message up the network stack */ + /* Pass message up the network stack */ case GNRC_NETAPI_MSG_TYPE_RCV: DEBUG("gnrc_tcp_eventloop.c : _event_loop() : GNRC_NETAPI_MSG_TYPE_RCV\n"); _receive((gnrc_pktsnip_t *)msg.content.ptr); break; - /* Pass Message down the network stack */ + /* Pass message down the network stack */ case GNRC_NETAPI_MSG_TYPE_SND: DEBUG("gnrc_tcp_eventloop.c : _event_loop() : GNRC_NETAPI_MSG_TYPE_SND\n"); _send((gnrc_pktsnip_t *)msg.content.ptr); break; - /* Option Set and Get Messages*/ + /* Reply to option set and set messages*/ case GNRC_NETAPI_MSG_TYPE_SET: case GNRC_NETAPI_MSG_TYPE_GET: msg_reply(&msg, &reply); break; - /* Retransmission Timer expired -> Call FSM with retransmission event */ + /* Retransmission timer expired: Call FSM with retransmission event */ case MSG_TYPE_RETRANSMISSION: DEBUG("gnrc_tcp_eventloop.c : _event_loop() : MSG_TYPE_RETRANSMISSION\n"); _fsm((gnrc_tcp_tcb_t *)msg.content.ptr, FSM_EVENT_TIMEOUT_RETRANSMIT, NULL, NULL, 0); break; - /* Time Wait Timer expired -> Call FSM with timewait event */ + /* Timewait timer expired: Call FSM with timewait event */ case MSG_TYPE_TIMEWAIT: DEBUG("gnrc_tcp_eventloop.c : _event_loop() : MSG_TYPE_TIMEWAIT\n"); _fsm((gnrc_tcp_tcb_t *)msg.content.ptr, FSM_EVENT_TIMEOUT_TIMEWAIT, @@ -266,6 +267,6 @@ void *_event_loop(__attribute__((unused)) void *arg) DEBUG("gnrc_tcp_eventloop.c : _event_loop() : received expected message\n"); } } - /* never reached */ + /* Never reached */ return NULL; } diff --git a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_fsm.c b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_fsm.c index 0dd29b305..f9323a7a3 100644 --- a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_fsm.c +++ b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_fsm.c @@ -33,20 +33,20 @@ #include "debug.h" /** - * @brief Checks if a given portnumber is currently used by a tcb as local_port. + * @brief Checks if a given port number is currently used by a TCB as local_port. * - * @param[in] portnumber Portnumber that should be checked + * @note Must be called from a context where the TCB list is locked. * - * @note Must be called from a context where the tcb list ist locked. + * @param[in] port_number Port number that should be checked. * - * @return Zero if @p portnumber is currently not used. - * @return 1 if @p portnumber is used by an tcb. + * @returns Zero if @p port_number is currently not used. + * 1 if @p port_number is used by an active connection. */ -static int _is_local_port_in_use(const uint16_t portnumber) +static int _is_local_port_in_use(const uint16_t port_number) { gnrc_tcp_tcb_t *iter = NULL; LL_FOREACH(_list_tcb_head, iter) { - if (iter->local_port == portnumber) { + if (iter->local_port == port_number) { return 1; } } @@ -54,9 +54,9 @@ static int _is_local_port_in_use(const uint16_t portnumber) } /** - * @brief Generate random unused local port above the well-known ports (> 1024) + * @brief Generate random unused local port above the well-known ports (> 1024). * - * @return The generated port number + * @returns Generated port number. */ static uint16_t _get_random_local_port(void) { @@ -71,11 +71,11 @@ static uint16_t _get_random_local_port(void) } /** - * @brief clears retransmit queue + * @brief Clears retransmit queue. * - * @param[in/out] tcb tcb containing the retransmit queue. + * @param[in,out] tcb TCB holding the retransmit queue. * - * @return zero on success + * @return Zero on success. */ static int _clear_retransmit(gnrc_tcp_tcb_t *tcb) { @@ -88,11 +88,11 @@ static int _clear_retransmit(gnrc_tcp_tcb_t *tcb) } /** - * @brief restarts time wait timer + * @brief Restarts timewait timer. * - * @param[in/out] tcb tcb containing the timer structure to use. + * @param[in,out] tcb TCB holding the timer struct to reset. * - * @return Zero on success + * @return Zero on success. */ static int _restart_timewait_timer(gnrc_tcp_tcb_t *tcb) { @@ -104,102 +104,94 @@ static int _restart_timewait_timer(gnrc_tcp_tcb_t *tcb) } /** - * @brief translates fsm into another state + * @brief Transition from current FSM state into another state. * - * @param[in/out] tcb tcb, that specifies connection - * @param[in] state state to translate in - * @param[out] notify_owner non-negative if the tcb owner should be notified + * @param[in,out] tcb TCB holding the FSM state. + * @param[in] state State to transition in. * - * @return zero on success + * @return Zero on success. */ -static int _transition_to(gnrc_tcp_tcb_t *tcb, fsm_state_t state, bool *notify_owner) +static int _transition_to(gnrc_tcp_tcb_t *tcb, fsm_state_t state) { gnrc_tcp_tcb_t *iter = NULL; - uint8_t found = 0; switch (state) { case FSM_STATE_CLOSED: - /* Free Packets in Retransmit queue */ + /* Clear retransmit queue */ _clear_retransmit(tcb); - /* Remove from Connection from active connections */ + /* Remove connection from active connections */ mutex_lock(&_list_tcb_lock); LL_FOREACH(_list_tcb_head, iter) { if (iter == tcb) { - found = 1; + break; } } - if (found) { + if (iter != NULL) { LL_DELETE(_list_tcb_head, iter); } mutex_unlock(&_list_tcb_lock); - /* Free potencially allocated Receive Buffer */ + /* Free potencially allocated receive buffer */ _rcvbuf_release_buffer(tcb); - *notify_owner = true; + tcb->status |= STATUS_NOTIFY_USER; break; case FSM_STATE_LISTEN: - /* Clear Adress Info */ - switch (tcb->address_family) { + /* Clear address info */ #ifdef MODULE_GNRC_IPV6 - case AF_INET6: - if (tcb->status & STATUS_ALLOW_ANY_ADDR) { - ipv6_addr_set_unspecified((ipv6_addr_t *) tcb->local_addr); - } - ipv6_addr_set_unspecified((ipv6_addr_t *) tcb->peer_addr); - break; -#endif - default: - DEBUG("gnrc_tcp_fsm.c : _transition_to() : Undefined Addresses\n"); - break; + if (tcb->address_family == AF_INET6) { + if (tcb->status & STATUS_ALLOW_ANY_ADDR) { + ipv6_addr_set_unspecified((ipv6_addr_t *) tcb->local_addr); + } + ipv6_addr_set_unspecified((ipv6_addr_t *) tcb->peer_addr); } +#endif tcb->peer_port = PORT_UNSPEC; - /* Allocate rcv Buffer */ + /* Allocate receive buffer */ if (_rcvbuf_get_buffer(tcb) == -ENOMEM) { return -ENOMEM; } - /* Add to Connection to active connections (if not already active) */ + /* Add connection to active connections (if not already active) */ mutex_lock(&_list_tcb_lock); LL_FOREACH(_list_tcb_head, iter) { if (iter == tcb) { - found = 1; + break; } } - if (!found) { + if (iter == NULL) { LL_APPEND(_list_tcb_head, tcb); } mutex_unlock(&_list_tcb_lock); break; case FSM_STATE_SYN_SENT: - /* Allocate rcv Buffer */ + /* Allocate rceveive buffer */ if (_rcvbuf_get_buffer(tcb) == -ENOMEM) { return -ENOMEM; } - /* Add to Connections to active connection (if not already active) */ + /* Add connection to active connections (if not already active) */ mutex_lock(&_list_tcb_lock); LL_FOREACH(_list_tcb_head, iter) { if (iter == tcb) { - found = 1; + break; } } - /* If not already active: Apped tcb but check portnumber first */ - if (!found) { - /* Check if Port Number is not in use */ + /* If connection is not already active: Check port number, append TCB */ + if (iter == NULL) { + /* Check if port number was specified */ if (tcb->local_port != PORT_UNSPEC) { - - /* If Portnumber is used: return error and release buffer */ + /* Check if given port number is use: return error and release buffer */ if (_is_local_port_in_use(tcb->local_port)) { mutex_unlock(&_list_tcb_lock); _rcvbuf_release_buffer(tcb); return -EADDRINUSE; } } - /* Pick Random Port */ + /* Pick random port */ else { tcb->local_port = _get_random_local_port(); } @@ -209,11 +201,8 @@ static int _transition_to(gnrc_tcp_tcb_t *tcb, fsm_state_t state, bool *notify_o break; case FSM_STATE_ESTABLISHED: - *notify_owner = true; - break; - case FSM_STATE_CLOSE_WAIT: - *notify_owner = true; + tcb->status |= STATUS_NOTIFY_USER; break; case FSM_STATE_TIME_WAIT: @@ -228,41 +217,40 @@ static int _transition_to(gnrc_tcp_tcb_t *tcb, fsm_state_t state, bool *notify_o } /** - * @brief FSM Handling Function for active and passive open + * @brief FSM handling function for opening a TCP connection. * - * @param[in/out] tcb Specifies tcb to use fsm on. - * @param[out] notify_owner non-negative if the tcb owner should be notified + * @param[in,out] tcb TCB holding the connection information. * - * @return zero on success - * @return -ENOMEM Can't allocate receive buffer. - * @return -EADDRINUSE Given local port is already in use + * @returns Zero on success. + * -ENOMEM if receive buffer could not be allocated. + * -EADDRINUSE if given local port number is already in use. */ -static int _fsm_call_open(gnrc_tcp_tcb_t *tcb, bool *notify_owner) +static int _fsm_call_open(gnrc_tcp_tcb_t *tcb) { gnrc_pktsnip_t *out_pkt = NULL; /* Outgoing packet */ - uint16_t seq_con = 0; /* Sequence number consumption (out_pkt) */ + uint16_t seq_con = 0; /* Sequence number consumption of outgoing packet */ int ret = 0; /* Return value */ DEBUG("gnrc_tcp_fsm.c : _fsm_call_open()\n"); tcb->rcv_wnd = GNRC_TCP_DEFAULT_WINDOW; if (tcb->status & STATUS_PASSIVE) { - /* Passive Open, T: CLOSED -> LISTEN */ - if (_transition_to(tcb, FSM_STATE_LISTEN, notify_owner) == -ENOMEM) { - _transition_to(tcb, FSM_STATE_CLOSED, notify_owner); + /* Passive open, T: CLOSED -> LISTEN */ + if (_transition_to(tcb, FSM_STATE_LISTEN) == -ENOMEM) { + _transition_to(tcb, FSM_STATE_CLOSED); return -ENOMEM; } } else { - /* Active Open, init tcb values, send SYN, T: CLOSED -> SYN_SENT */ + /* Active Open, set TCB values, send SYN, T: CLOSED -> SYN_SENT */ tcb->iss = random_uint32(); tcb->snd_nxt = tcb->iss; tcb->snd_una = tcb->iss; - /* Translate to SYN_SENT */ - ret = _transition_to(tcb, FSM_STATE_SYN_SENT, notify_owner); + /* Transition FSM to SYN_SENT */ + ret = _transition_to(tcb, FSM_STATE_SYN_SENT); if (ret < 0) { - _transition_to(tcb, FSM_STATE_CLOSED, notify_owner); + _transition_to(tcb, FSM_STATE_CLOSED); return ret; } @@ -275,13 +263,13 @@ static int _fsm_call_open(gnrc_tcp_tcb_t *tcb, bool *notify_owner) } /** - * @brief FSM Handling Function for sending data. + * @brief FSM Handling function for sending data. * - * @param[in/out] tcb Specifies tcb to use fsm on. - * @param[in/out] buf Buffer containing data to send. - * @param[in] len Maximum Number of Bytes to send. + * @param[in,out] tcb TCB holding the connection information. + * @param[in,out] buf Buffer containing data to send. + * @param[in] len Maximum Number of Bytes to send from @p buf. * - * @return number of bytes that was sent. + * @returns Number of successfully transmitted bytes. */ static int _fsm_call_send(gnrc_tcp_tcb_t *tcb, void *buf, size_t len) { @@ -291,7 +279,7 @@ static int _fsm_call_send(gnrc_tcp_tcb_t *tcb, void *buf, size_t len) DEBUG("gnrc_tcp_fsm.c : _fsm_call_send()\n"); size_t payload = (tcb->snd_una + tcb->snd_wnd) - tcb->snd_nxt; - /* We are allowed to send further bytes if window is open */ + /* Check if window is open and all packets were transmitted */ if (payload > 0 && tcb->snd_wnd > 0 && tcb->pkt_retransmit == NULL) { /* Calculate segment size */ payload = (payload < GNRC_TCP_MSS) ? payload : GNRC_TCP_MSS; @@ -308,32 +296,32 @@ static int _fsm_call_send(gnrc_tcp_tcb_t *tcb, void *buf, size_t len) } /** - * @brief FSM Handling Function for receiving data. + * @brief FSM handling function for receiving data. * - * @param[in/out] tcb Specifies tcb to use fsm on. - * @param[in/out] buf buffer to store received data into. - * @param[in] len Maximum Number of Bytes to receive. + * @param[in,out] tcb TCB holding the connection information. + * @param[in,out] buf Buffer to store received data into. + * @param[in] len Maximum number of bytes to receive. * - * @return number of bytes that was received. + * @returns Number of successfully received bytes. */ static int _fsm_call_recv(gnrc_tcp_tcb_t *tcb, void *buf, size_t len) { gnrc_pktsnip_t *out_pkt = NULL; /* Outgoing packet */ - uint16_t seq_con = 0; /* Sequence number consumption (out_pkt) */ + uint16_t seq_con = 0; /* Sequence number consumption of outgoing packet */ DEBUG("gnrc_tcp_fsm.c : _fsm_call_recv()\n"); if (ringbuffer_empty(&tcb->rcv_buf)) { return 0; } - /* Read up to the requesed amount of data */ + /* Read data into 'buf' up to 'len' bytes from receive buffer */ size_t rcvd = ringbuffer_get(&(tcb->rcv_buf), buf, len); - /* If the buffer can store more than the GNRC_TCP_MSS: open Window to available buffersize */ + /* If receive buffer can store more than GNRC_TCP_MSS: open window to available buffer size */ if (ringbuffer_get_free(&tcb->rcv_buf) >= GNRC_TCP_MSS) { tcb->rcv_wnd = ringbuffer_get_free(&(tcb->rcv_buf)); - /* Send ACK to update window on reopening */ + /* Send ACK to anounce window update */ _pkt_build(tcb, &out_pkt, &seq_con, MSK_ACK, tcb->snd_nxt, tcb->rcv_nxt, NULL, 0); _pkt_send(tcb, out_pkt, seq_con, false); } @@ -341,17 +329,16 @@ static int _fsm_call_recv(gnrc_tcp_tcb_t *tcb, void *buf, size_t len) } /** - * @brief FSM Handling Function for initiating a teardown. + * @brief FSM handling function for starting connection teardown sequence. * - * @param[in/out] tcb Specifies tcb to use fsm on. - * @param[out] notify_owner non-negative if the tcb owner should be notified + * @param[in,out] tcb TCB holding the connection information. * - * @return zero on success. + * @returns Zero on success. */ -static int _fsm_call_close(gnrc_tcp_tcb_t *tcb, bool *notify_owner) +static int _fsm_call_close(gnrc_tcp_tcb_t *tcb) { gnrc_pktsnip_t *out_pkt = NULL; /* Outgoing packet */ - uint16_t seq_con = 0; /* Sequence number consumption (out_pkt) */ + uint16_t seq_con = 0; /* Sequence number consumption of outgoing packet */ DEBUG("gnrc_tcp_fsm.c : _fsm_call_close()\n"); if (tcb->state == FSM_STATE_SYN_RCVD || tcb->state == FSM_STATE_ESTABLISHED || @@ -361,30 +348,23 @@ static int _fsm_call_close(gnrc_tcp_tcb_t *tcb, bool *notify_owner) _pkt_setup_retransmit(tcb, out_pkt, false); _pkt_send(tcb, out_pkt, seq_con, false); } - switch (tcb->state) { - case FSM_STATE_LISTEN: - _transition_to(tcb, FSM_STATE_CLOSED, notify_owner); - break; - - case FSM_STATE_SYN_RCVD: - case FSM_STATE_ESTABLISHED: - _transition_to(tcb, FSM_STATE_FIN_WAIT_1, notify_owner); - break; - case FSM_STATE_CLOSE_WAIT: - _transition_to(tcb, FSM_STATE_LAST_ACK, notify_owner); - break; - - default: - break; + if (tcb->state == FSM_STATE_LISTEN) { + _transition_to(tcb, FSM_STATE_CLOSED); + } + else if (tcb->state == FSM_STATE_SYN_RCVD || tcb->state == FSM_STATE_ESTABLISHED) { + _transition_to(tcb, FSM_STATE_FIN_WAIT_1); + } + else if (tcb->state == FSM_STATE_CLOSE_WAIT) { + _transition_to(tcb, FSM_STATE_LAST_ACK); } return 0; } /** - * @brief FSM Handling Function for forcefull teardown + * @brief FSM handling function for forcefull connection teardown sequence. * - * @return -EOPNOTSUPP, because function is currently not implemented + * @returns -EOPNOTSUPP. Currently not implemented. */ static int _fsm_call_abort(void) { @@ -394,34 +374,33 @@ static int _fsm_call_abort(void) } /** - * @brief FSM Handling Function for processing of a received packet + * @brief FSM handling function for processing of an incomming TCP packet. * - * @param[in/out] tcb Specifies tcb to use fsm on. - * @param[in] in_pkt Packet that should be processed. - * @param[out] notify_owner non-negative if the tcb owner should be notified + * @param[in,out] tcb TCB holding the connection information. + * @param[in] in_pkt Incomming packet. * - * @return zero on success. - * @return -ENOMEM Can't allocate receive buffer. + * @returns Zero on success. + * -ENOMEM if receive buffer could not be allocated. */ -static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *notify_owner) +static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt) { gnrc_pktsnip_t *out_pkt = NULL; /* Outgoing packet */ - uint16_t seq_con = 0; /* Sequence number consumption (out_pkt) */ - gnrc_pktsnip_t *snp = NULL; /* Temporary Packet Snip */ - gnrc_tcp_tcb_t *lst = NULL; /* Temporary tcb pointer */ - uint16_t ctl = 0; /* Received control bits */ - uint32_t seg_seq = 0; /* Received sequence number */ - uint32_t seg_ack = 0; /* Received acknowledgment number */ - uint32_t seg_len = 0; /* Segment length */ - uint32_t pay_len = 0; /* Payload length */ - uint32_t seg_wnd = 0; /* Segment window */ + uint16_t seq_con = 0; /* Sequence number consumption of outgoing packet */ + gnrc_pktsnip_t *snp = NULL; /* Temporary packet snip */ + gnrc_tcp_tcb_t *lst = NULL; /* Temporary pointer to TCB */ + uint16_t ctl = 0; /* Control bits of the incomming packet */ + uint32_t seg_seq = 0; /* Sequence number of the incomming packet*/ + uint32_t seg_ack = 0; /* Acknowledgment number of the incomming packet */ + uint32_t seg_wnd = 0; /* Receive window of the incomming packet */ + uint32_t seg_len = 0; /* Segment length of the incomming packet */ + uint32_t pay_len = 0; /* Payload length of the incomming packet */ DEBUG("gnrc_tcp_fsm.c : _fsm_rcvd_pkt()\n"); - /* Search TCP header. */ + /* Search for TCP header. */ LL_SEARCH_SCALAR(in_pkt, snp, type, GNRC_NETTYPE_TCP); tcp_hdr_t *tcp_hdr = (tcp_hdr_t *) snp->data; - /* Verify packet options, return if they were faulty */ + /* Parse packet options, return if they are malformed */ if (_option_parse(tcb, tcp_hdr) < 0) { return 0; } @@ -432,11 +411,11 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti seg_ack = byteorder_ntohl(tcp_hdr->ack_num); seg_wnd = byteorder_ntohs(tcp_hdr->window); - /* Extract IPv6-Header */ + /* Extract network layer header */ #ifdef MODULE_GNRC_IPV6 LL_SEARCH_SCALAR(in_pkt, snp, type, GNRC_NETTYPE_IPV6); if (snp == NULL) { - DEBUG("gnrc_tcp_fsm.c : _fsm_rcvd_pkt() : incomming packet had no ip header\n"); + DEBUG("gnrc_tcp_fsm.c : _fsm_rcvd_pkt() : incomming packet had no IPv6 header\n"); return 0; } void *ip = snp->data; @@ -444,26 +423,25 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti /* Handle state LISTEN */ if (tcb->state == FSM_STATE_LISTEN) { - /* 1) Check RST: if set, return */ + /* 1) Check RST: if RST is set: return */ if (ctl & MSK_RST) { return 0; } - /* 2) Check ACK: if set, send reset with seq_no = ack_no, return */ + /* 2) Check ACK: if ACK is set: send RST with seq_no = ack_no and return */ if (ctl & MSK_ACK) { _pkt_build_reset_from_pkt(&out_pkt, in_pkt); _pkt_send(tcb, out_pkt, 0, false); return 0; } - /* 3) Check SYN: Setup incoming connection*/ + /* 3) Check SYN: if SYN is set prepare for incomming connection */ if (ctl & MSK_SYN) { uint16_t src = byteorder_ntohs(tcp_hdr->src_port); uint16_t dst = byteorder_ntohs(tcp_hdr->dst_port); - /* Check if SYN Request is handled by another connection */ + /* Check if SYN request is handled by another connection */ lst = _list_tcb_head; while (lst) { - /* Compare Portnumbers and Network Layer Adresses */ - /* Note: Packets without ip-header were discarded earlier */ + /* Compare port numbers and network layer adresses */ if (lst->local_port == dst && lst->peer_port == src) { #ifdef MODULE_GNRC_IPV6 if (snp->type == GNRC_NETTYPE_IPV6 && lst->address_family == AF_INET6) { @@ -485,15 +463,14 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti return 0; } - /* SYN Request is valid, fill connection struct with connection information */ - /* Note: Packets without ipv6-header were discarded earlier */ + /* SYN request is valid, fill TCB with connection information */ #ifdef MODULE_GNRC_IPV6 if (snp->type == GNRC_NETTYPE_IPV6 && tcb->address_family == AF_INET6) { memcpy(tcb->local_addr, &((ipv6_hdr_t *)ip)->dst, sizeof(ipv6_addr_t)); memcpy(tcb->peer_addr, &((ipv6_hdr_t *)ip)->src, sizeof(ipv6_addr_t)); } #else - DEBUG("gnrc_tcp_fsm.c : _fsm_rcvd_pkt() : Received Address was not stored\n"); + DEBUG("gnrc_tcp_fsm.c : _fsm_rcvd_pkt() : Received address was not stored\n"); return 0; #endif @@ -510,7 +487,7 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti _pkt_build(tcb, &out_pkt, &seq_con, MSK_SYN_ACK, tcb->iss, tcb->rcv_nxt, NULL, 0); _pkt_setup_retransmit(tcb, out_pkt, false); _pkt_send(tcb, out_pkt, seq_con, false); - _transition_to(tcb, FSM_STATE_SYN_RCVD, notify_owner); + _transition_to(tcb, FSM_STATE_SYN_RCVD); } return 0; } @@ -520,7 +497,7 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti if (ctl & MSK_ACK) { /* If ACK is not acceptable ...*/ if (seg_ack <= tcb->iss || seg_ack > tcb->snd_nxt) { - /* ... send Reset if RST is not set else return */ + /* ... send reset, if RST is not set else return */ if ((ctl & MSK_RST) != MSK_RST) { _pkt_build(tcb, &out_pkt, &seq_con, MSK_RST, seg_ack, 0, NULL, 0); _pkt_send(tcb, out_pkt, seq_con, false); @@ -532,7 +509,7 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti if (ctl & MSK_RST) { /* ... and ACK: Translate to CLOSED, if not return */ if (ctl & MSK_ACK) { - _transition_to(tcb, FSM_STATE_CLOSED, notify_owner); + _transition_to(tcb, FSM_STATE_CLOSED); } return 0; } @@ -544,29 +521,28 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti tcb->snd_una = seg_ack; _pkt_acknowledge(tcb, seg_ack); } - /* Set the local address accordingly */ - /* Note: Packets without ipv6-header were discarded earlier */ + /* Set local network layer address accordingly */ #ifdef MODULE_GNRC_IPV6 if (snp->type == GNRC_NETTYPE_IPV6 && tcb->address_family == AF_INET6) { memcpy(tcb->local_addr, &((ipv6_hdr_t *)ip)->dst, sizeof(ipv6_addr_t)); } #else - DEBUG("gnrc_tcp_fsm.c : _fsm_rcvd_pkt() : Received Address was not stored\n"); + DEBUG("gnrc_tcp_fsm.c : _fsm_rcvd_pkt() : Received address was not stored\n"); return 0; #endif - /* SYN has been ACKed, reply pure ACK, T: SYN_SENT -> ESTABLISHED */ + /* SYN has been ACKed. Send ACK, T: SYN_SENT -> ESTABLISHED */ if (tcb->snd_una > tcb->iss) { _pkt_build(tcb, &out_pkt, &seq_con, MSK_ACK, tcb->snd_nxt, tcb->rcv_nxt, NULL, 0); _pkt_send(tcb, out_pkt, seq_con, false); - _transition_to(tcb, FSM_STATE_ESTABLISHED, notify_owner); + _transition_to(tcb, FSM_STATE_ESTABLISHED); } - /* Simultaneous SYN received send SYN+ACK, T: SYN_SENT -> SYN_RCVD */ + /* Simultaneous SYN received. Send SYN+ACK, T: SYN_SENT -> SYN_RCVD */ else { _pkt_build(tcb, &out_pkt, &seq_con, MSK_SYN_ACK, tcb->iss, tcb->rcv_nxt, NULL, 0); _pkt_setup_retransmit(tcb, out_pkt, false); _pkt_send(tcb, out_pkt, seq_con, false); - _transition_to(tcb, FSM_STATE_SYN_RCVD, notify_owner); + _transition_to(tcb, FSM_STATE_SYN_RCVD); } tcb->snd_wnd = seg_wnd; tcb->snd_wl1 = seg_seq; @@ -578,8 +554,8 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti else { seg_len = _pkt_get_seg_len(in_pkt); pay_len = _pkt_get_pay_len(in_pkt); - /* 1) Verify Sequence Number ... */ - if (!_pkt_chk_seq_num(tcb, seg_seq, pay_len)) { + /* 1) Verify sequence number ... */ + if (_pkt_chk_seq_num(tcb, seg_seq, pay_len)) { /* ... if invalid, and RST not set, reply with pure ACK, return */ if ((ctl & MSK_RST) != MSK_RST) { _pkt_build(tcb, &out_pkt, &seq_con, MSK_ACK, tcb->snd_nxt, tcb->rcv_nxt, NULL, 0); @@ -589,15 +565,15 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti } /* 2) Check RST: If RST is set ... */ if (ctl & MSK_RST) { - /* .. and State is SYN_RCVD and passive Open: SYN_RCVD -> LISTEN */ + /* .. and state is SYN_RCVD and the connection is passive: SYN_RCVD -> LISTEN */ if (tcb->state == FSM_STATE_SYN_RCVD && (tcb->status & STATUS_PASSIVE)) { - if (_transition_to(tcb, FSM_STATE_LISTEN, notify_owner) == -ENOMEM) { - _transition_to(tcb, FSM_STATE_CLOSED, notify_owner); + if (_transition_to(tcb, FSM_STATE_LISTEN) == -ENOMEM) { + _transition_to(tcb, FSM_STATE_CLOSED); return -ENOMEM; } } else { - _transition_to(tcb, FSM_STATE_CLOSED, notify_owner); + _transition_to(tcb, FSM_STATE_CLOSED); } return 0; } @@ -606,7 +582,7 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti /* ... send RST, seq_no = snd_nxt, ack_no = rcv_nxt */ _pkt_build(tcb, &out_pkt, &seq_con, MSK_RST, tcb->snd_nxt, tcb->rcv_nxt, NULL, 0); _pkt_send(tcb, out_pkt, seq_con, false); - _transition_to(tcb, FSM_STATE_CLOSED, notify_owner); + _transition_to(tcb, FSM_STATE_CLOSED); return 0; } /* 4) Check ACK */ @@ -619,7 +595,7 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti tcb->snd_wnd = seg_wnd; tcb->snd_wl1 = seg_seq; tcb->snd_wl2 = seg_ack; - _transition_to(tcb, FSM_STATE_ESTABLISHED, notify_owner); + _transition_to(tcb, FSM_STATE_ESTABLISHED); } else { _pkt_build(tcb, &out_pkt, &seq_con, MSK_RST, seg_ack, 0, NULL, 0); @@ -630,7 +606,7 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti if (tcb->state == FSM_STATE_ESTABLISHED || tcb->state == FSM_STATE_FIN_WAIT_1 || tcb->state == FSM_STATE_FIN_WAIT_2 || tcb->state == FSM_STATE_CLOSE_WAIT || tcb->state == FSM_STATE_CLOSING || tcb->state == FSM_STATE_LAST_ACK) { - /* Sent data has been acknowledged */ + /* Acknowledge previously sent data */ if (LSS_32_BIT(tcb->snd_una, seg_ack) && LEQ_32_BIT(seg_ack, tcb->snd_nxt)) { tcb->snd_una = seg_ack; _pkt_acknowledge(tcb, seg_ack); @@ -642,7 +618,7 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti _pkt_send(tcb, out_pkt, seq_con, false); return 0; } - /* Update Window */ + /* Update receive window */ if (LEQ_32_BIT(tcb->snd_una, seg_ack) && LEQ_32_BIT(seg_ack, tcb->snd_nxt)) { if (LSS_32_BIT(tcb->snd_wl1, seg_seq) || (tcb->snd_wl1 == seg_seq && LEQ_32_BIT(tcb->snd_wl2, seg_ack))) { @@ -650,15 +626,15 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti tcb->snd_wl1 = seg_seq; tcb->snd_wl2 = seg_ack; - /* Signal User after Window Update */ - *notify_owner = true; + /* Signal user after window update */ + tcb->status |= STATUS_NOTIFY_USER; } } /* Additional processing */ - /* Check additionaly if previous our sent FIN has been acknowledged */ + /* Check additionaly if previously sent FIN was acknowledged */ if (tcb->state == FSM_STATE_FIN_WAIT_1) { if (tcb->pkt_retransmit == NULL) { - _transition_to(tcb, FSM_STATE_FIN_WAIT_2, notify_owner); + _transition_to(tcb, FSM_STATE_FIN_WAIT_2); } } /* If retransmission queue is empty, acknowledge close operation */ @@ -667,45 +643,46 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti /* Optional: Unblock user close operation */ } } - /* If our FIN has been acknowledged: Translate to TIME_WAIT */ + /* If our FIN has been acknowledged: Transition to TIME_WAIT */ if (tcb->state == FSM_STATE_CLOSING) { if (tcb->pkt_retransmit == NULL) { - _transition_to(tcb, FSM_STATE_TIME_WAIT, notify_owner); + _transition_to(tcb, FSM_STATE_TIME_WAIT); } } - /* If our FIN has been acknowledged: last ACK received, close connection */ + /* If our FIN was acknowledged and status is LAST_ACK: close connection */ if (tcb->state == FSM_STATE_LAST_ACK) { if (tcb->pkt_retransmit == NULL) { - _transition_to(tcb, FSM_STATE_CLOSED, notify_owner); + _transition_to(tcb, FSM_STATE_CLOSED); return 0; } } } } /* 5) Check URG */ - /* NOTE: Add Urgent Pointer Processing here ... */ - /* 6) Process Payload, if existing */ + /* NOTE: Add urgent pointer processing here ... */ + + /* 6) Process payload, if existing */ if (pay_len > 0) { - /* Check if State is valid */ + /* Check if state is valid for payload receiving */ if (tcb->state == FSM_STATE_ESTABLISHED || tcb->state == FSM_STATE_FIN_WAIT_1 || tcb->state == FSM_STATE_FIN_WAIT_2) { - /* Search for begin of payload "chain" */ + /* Search for begin of payload */ LL_SEARCH_SCALAR(in_pkt, snp, type, GNRC_NETTYPE_UNDEF); - /* Add only Data that is expected, to be received */ + /* Accept only data that is expected, to be received */ if (tcb->rcv_nxt == seg_seq) { - /* Copy contents in to buffer */ + /* Copy contents into receive buffer */ while (snp && snp->type == GNRC_NETTYPE_UNDEF) { tcb->rcv_nxt += ringbuffer_add(&(tcb->rcv_buf), snp->data, snp->size); snp = snp->next; } - /* Shrink Receive Window */ + /* Shrink receive window */ tcb->rcv_wnd = ringbuffer_get_free(&(tcb->rcv_buf)); - /* Notify Owner because new data is available */ - *notify_owner = true; + /* Notify owner because new data is available */ + tcb->status |= STATUS_NOTIFY_USER; } - /* Send pure ACK, if FIN doesn't this already */ - /* NOTE: this is the place to add piggybagging in the future */ + /* Send ACK, if FIN processing sends ACK already */ + /* NOTE: this is the place to add payload piggybagging in the future */ if (!(ctl & MSK_FIN)) { _pkt_build(tcb, &out_pkt, &seq_con, MSK_ACK, tcb->snd_nxt, tcb->rcv_nxt, NULL, 0); @@ -719,24 +696,24 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti tcb->state == FSM_STATE_SYN_SENT) { return 0; } - /* Advance rcv_nxt over FIN bit. */ + /* Advance rcv_nxt over FIN bit */ tcb->rcv_nxt = seg_seq + seg_len; _pkt_build(tcb, &out_pkt, &seq_con, MSK_ACK, tcb->snd_nxt, tcb->rcv_nxt, NULL, 0); _pkt_send(tcb, out_pkt, seq_con, false); if (tcb->state == FSM_STATE_SYN_RCVD || tcb->state == FSM_STATE_ESTABLISHED) { - _transition_to(tcb, FSM_STATE_CLOSE_WAIT, notify_owner); + _transition_to(tcb, FSM_STATE_CLOSE_WAIT); } else if (tcb->state == FSM_STATE_FIN_WAIT_1) { if (tcb->pkt_retransmit == NULL) { - _transition_to(tcb, FSM_STATE_TIME_WAIT, notify_owner); + _transition_to(tcb, FSM_STATE_TIME_WAIT); } else { - _transition_to(tcb, FSM_STATE_CLOSING, notify_owner); + _transition_to(tcb, FSM_STATE_CLOSING); } } else if (tcb->state == FSM_STATE_FIN_WAIT_2) { - _transition_to(tcb, FSM_STATE_TIME_WAIT, notify_owner); + _transition_to(tcb, FSM_STATE_TIME_WAIT); } else if (tcb->state == FSM_STATE_TIME_WAIT) { _restart_timewait_timer(tcb); @@ -747,26 +724,25 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *noti } /** - * @brief FSM Handling Function for timewait timeout handling + * @brief FSM handling function for timewait timeout handling. * - * @param[in/out] tcb Specifies tcb to use fsm on. - * @param[out] notify_owner non-negative if the tcb owner should be notified + * @param[in,out] tcb TCB holding the connection information. * - * @return zero on success. + * @returns Zero on success. */ -static int _fsm_timeout_timewait(gnrc_tcp_tcb_t *tcb, bool *notify_owner) +static int _fsm_timeout_timewait(gnrc_tcp_tcb_t *tcb) { DEBUG("gnrc_tcp_fsm.c : _fsm_timeout_timewait()\n"); - _transition_to(tcb, FSM_STATE_CLOSED, notify_owner); + _transition_to(tcb, FSM_STATE_CLOSED); return 0; } /** - * @brief FSM Handling Function for retransmissions + * @brief FSM handling function for retransmissions. * - * @param[in/out] tcb Specifies tcb to use fsm on. + * @param[in,out] tcb TCB holding the connection information. * - * @return zero on success. + * @returns Zero on success. */ static int _fsm_timeout_retransmit(gnrc_tcp_tcb_t *tcb) { @@ -782,34 +758,33 @@ static int _fsm_timeout_retransmit(gnrc_tcp_tcb_t *tcb) } /** - * @brief FSM Handling Function for connection timeout handling + * @brief FSM handling function for connection timeout handling. * - * @param[in/out] tcb Specifies tcb to use fsm on. - * @param[out] notify_owner non-negative if the tcb owner should be notified + * @param[in,out] tcb TCB holding the connection information. * - * @return zero on success. + * @returns Zero on success. */ -static int _fsm_timeout_connection(gnrc_tcp_tcb_t *tcb, bool *notify_owner) +static int _fsm_timeout_connection(gnrc_tcp_tcb_t *tcb) { DEBUG("gnrc_tcp_fsm.c : _fsm_timeout_connection()\n"); - _transition_to(tcb, FSM_STATE_CLOSED, notify_owner); + _transition_to(tcb, FSM_STATE_CLOSED); return 0; } /** - * @brief FSM Handling Function for probe sending + * @brief FSM handling function for probe sending. * - * @param[in/out] tcb tcb of this connection + * @param[in,out] tcb TCB holding the connection information. * - * @return zero on success. + * @returns Zero on success. */ static int _fsm_send_probe(gnrc_tcp_tcb_t *tcb) { gnrc_pktsnip_t *out_pkt = NULL; /* Outgoing packet */ - uint8_t probe_pay[] = {1}; /* Probe Payload */ + uint8_t probe_pay[] = {1}; /* Probe payload */ DEBUG("gnrc_tcp_fsm.c : _fsm_send_probe()\n"); - /* The Probe sends a already acknowledged Sequence No. with a garbage byte */ + /* The probe sends a already acknowledged sequence no. with a garbage byte. */ _pkt_build(tcb, &out_pkt, NULL, MSK_ACK, tcb->snd_una - 1, tcb->rcv_nxt, probe_pay, sizeof(probe_pay)); _pkt_send(tcb, out_pkt, 0, false); @@ -819,9 +794,9 @@ static int _fsm_send_probe(gnrc_tcp_tcb_t *tcb) /** * @brief FSM Handling Function for clearing the retransmit queue. * - * @param[in/out] tcb tcb of this connection. + * @param[in,out] tcb TCB holding the connection information. * - * @return zero on success. + * @returns Zero on success. */ static int _fsm_clear_retransmit(gnrc_tcp_tcb_t *tcb) { @@ -831,29 +806,28 @@ static int _fsm_clear_retransmit(gnrc_tcp_tcb_t *tcb) } /** - * @brief real fsm: needs to be protected from the outside - * - * @param[in/out] tcb Specifies tcb to use fsm on. - * @param[in] event current event that triggers fsm translation - * @param[in] in_pkt packet that triggered fsm event. Only in case of RCVD_PKT - * @param[in/out] buf buffer for send and receive functions - * @param[in] len number of bytes to send or receive atmost - * @param[out] notify_owner non-negative if the tcb owner should be notified - * - * @return Zero on success - * @return -ENOMEM Can't allocate receive buffer. - * @return -EADDRINUSE Given local port is already in use - * @return -EOPNOTSUPP If event is not implemented + * @brief FSM function (not synchronized). + * + * @param[in,out] tcb TCB holding the connection information. + * @param[in] event Current event that triggers fsm translation. + * @param[in] in_pkt Packet that triggered fsm event. Only in case of RCVD_PKT. + * @param[in,out] buf Buffer for send and receive functions. + * @param[in] len Number of bytes to send or receive in @p buf. + * + * @returns Zero on success. + * -ENOMEM if receive buffer could not be allocated. + * -EADDRINUSE if given local port number in @p tcb is already in use. + * -EOPNOTSUPP if event is not implemented. */ static int _fsm_unprotected(gnrc_tcp_tcb_t *tcb, fsm_event_t event, gnrc_pktsnip_t *in_pkt, - void *buf, size_t len, bool *notify_owner) + void *buf, size_t len) { int ret = 0; DEBUG("gnrc_tcp_fsm.c : _fsm_unprotected()\n"); switch (event) { case FSM_EVENT_CALL_OPEN : - ret = _fsm_call_open(tcb, notify_owner); + ret = _fsm_call_open(tcb); break; case FSM_EVENT_CALL_SEND : ret = _fsm_call_send(tcb, buf, len); @@ -862,22 +836,22 @@ static int _fsm_unprotected(gnrc_tcp_tcb_t *tcb, fsm_event_t event, gnrc_pktsnip ret = _fsm_call_recv(tcb, buf, len); break; case FSM_EVENT_CALL_CLOSE : - ret = _fsm_call_close(tcb, notify_owner); + ret = _fsm_call_close(tcb); break; case FSM_EVENT_CALL_ABORT : ret = _fsm_call_abort(); break; case FSM_EVENT_RCVD_PKT : - ret = _fsm_rcvd_pkt(tcb, in_pkt, notify_owner); + ret = _fsm_rcvd_pkt(tcb, in_pkt); break; case FSM_EVENT_TIMEOUT_TIMEWAIT : - ret = _fsm_timeout_timewait(tcb, notify_owner); + ret = _fsm_timeout_timewait(tcb); break; case FSM_EVENT_TIMEOUT_RETRANSMIT : ret = _fsm_timeout_retransmit(tcb); break; case FSM_EVENT_TIMEOUT_CONNECTION : - ret = _fsm_timeout_connection(tcb, notify_owner); + ret = _fsm_timeout_connection(tcb); break; case FSM_EVENT_SEND_PROBE : ret = _fsm_send_probe(tcb); @@ -891,17 +865,16 @@ static int _fsm_unprotected(gnrc_tcp_tcb_t *tcb, fsm_event_t event, gnrc_pktsnip int _fsm(gnrc_tcp_tcb_t *tcb, fsm_event_t event, gnrc_pktsnip_t *in_pkt, void *buf, size_t len) { - msg_t msg; - int32_t result; - bool notify_owner; - /* Lock FSM */ mutex_lock(&(tcb->fsm_lock)); - notify_owner = false; - result = _fsm_unprotected(tcb, event, in_pkt, buf, len, ¬ify_owner); - /* Notify owner if something interesting happend */ - if (notify_owner && tcb->owner != KERNEL_PID_UNDEF) { + /* Call FSM */ + tcb->status &= ~(STATUS_NOTIFY_USER); + int32_t result = _fsm_unprotected(tcb, event, in_pkt, buf, len); + + /* Notify blocked thread if something interesting happend */ + if ((tcb->status & STATUS_NOTIFY_USER) && (tcb->owner != KERNEL_PID_UNDEF)) { + msg_t msg; msg.type = MSG_TYPE_NOTIFY_USER; msg_send(&msg, tcb->owner); } diff --git a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_option.c b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_option.c index 9ed5063ac..e484c81b5 100644 --- a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_option.c +++ b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_option.c @@ -24,17 +24,17 @@ int _option_parse(gnrc_tcp_tcb_t *tcb, tcp_hdr_t *hdr) { - /* Extract Offset value. Return if no options are set */ + /* Extract offset value. Return if no options are set */ uint8_t offset = GET_OFFSET(byteorder_ntohs(hdr->off_ctl)); if (offset <= TCP_HDR_OFFSET_MIN) { return 0; } - /* Get Pointer to option field and field-size */ + /* Get pointer to option field and field size */ uint8_t *opt_ptr = (uint8_t *) hdr + sizeof(tcp_hdr_t); uint8_t opt_left = (offset - TCP_HDR_OFFSET_MIN) * 4; - /* Parse Options via tcp_hdr_opt_t */ + /* Parse options via tcp_hdr_opt_t */ while (opt_left > 0) { tcp_hdr_opt_t *option = (tcp_hdr_opt_t *) opt_ptr; diff --git a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_pkt.c b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_pkt.c index 60ed68fc9..d3857ea30 100644 --- a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_pkt.c +++ b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_pkt.c @@ -34,12 +34,12 @@ #include "debug.h" /** - * @brief Calculates the maximum of two unsigned numbers + * @brief Calculates the maximum of two unsigned numbers. * - * @param [in] x First comparrison value - * @param [in] y Second comparrison value + * @param[in] x First comparrison value. + * @param[in] y Second comparrison value. * - * @return x if x is larger than y, if not y is returned. + * @returns X if x is larger than y, if not y is returned. */ static inline uint32_t _max(const uint32_t x, const uint32_t y) { @@ -60,7 +60,7 @@ int _pkt_build_reset_from_pkt(gnrc_pktsnip_t **out_pkt, gnrc_pktsnip_t *in_pkt) ipv6_hdr_t *ip6_hdr = (ipv6_hdr_t *)ip6_snp->data; #endif - /* Setup Header information */ + /* Setup header information */ tcp_hdr_out.src_port = tcp_hdr_in->dst_port; tcp_hdr_out.dst_port = tcp_hdr_in->src_port; tcp_hdr_out.checksum = byteorder_htons(0); @@ -88,7 +88,7 @@ int _pkt_build_reset_from_pkt(gnrc_pktsnip_t **out_pkt, gnrc_pktsnip_t *in_pkt) tcp_hdr_out.ack_num = byteorder_htonl(seq_no + tmp + _pkt_get_pay_len(in_pkt)); } - /* Allocate new tcp header */ + /* Allocate new TCB header */ tcp_snp = gnrc_pktbuf_add(NULL, &tcp_hdr_out, TCP_HDR_OFFSET_MIN * 4, GNRC_NETTYPE_TCP); if (tcp_snp == NULL) { DEBUG("gnrc_tcp_pkt.c : _pkt_build_reset_from_pkt() :\ @@ -134,7 +134,7 @@ int _pkt_build(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con, } } - /* fill tcp-header */ + /* Fill TCP header */ tcp_hdr.src_port = byteorder_htons(tcb->local_port); tcp_hdr.dst_port = byteorder_htons(tcb->peer_port); tcp_hdr.checksum = byteorder_htons(0); @@ -151,7 +151,7 @@ int _pkt_build(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con, /* Set offset and control bit accordingly */ tcp_hdr.off_ctl = byteorder_htons(_option_build_offset_control(offset, ctl)); - /* allocate tcp header: size = offset * 4 bytes */ + /* Allocate TCP header: size = offset * 4 bytes */ tcp_snp = gnrc_pktbuf_add(pay_snp, &tcp_hdr, offset * 4, GNRC_NETTYPE_TCP); if (tcp_snp == NULL) { DEBUG("gnrc_tcp_pkt.c : _pkt_build() : Can't allocate buffer for TCP Header\n."); @@ -174,7 +174,7 @@ int _pkt_build(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con, memcpy(opt_ptr, &mss_option, sizeof(mss_option)); } /* Increase opt_ptr and decrease opt_ptr, if other options are added */ - /* NOTE: Add Additional Options here */ + /* NOTE: Add additional options here */ } *(out_pkt) = tcp_snp; } @@ -195,7 +195,7 @@ int _pkt_build(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con, DEBUG("gnrc_tcp_pkt.c : _pkt_build_reset_from_pkt() : Network Layer Module Missing\n"); #endif - /* Calculate Sequence Space Number Consumption for this packet */ + /* Calculate sequence space number consumption for this packet */ if (seq_con != NULL) { *seq_con = 0; if (ctl & MSK_SYN) { @@ -238,30 +238,30 @@ int _pkt_chk_seq_num(const gnrc_tcp_tcb_t *tcb, const uint32_t seq_num, const ui uint32_t r_edge = tcb->rcv_nxt + tcb->rcv_wnd; uint32_t last_seq = seq_num + seg_len - 1; - /* Possible case 1 */ - /* Segment contains no payload and Receive window is closed and */ - /* Sequence Number is next expected number */ + /* Possible case 1: */ + /* Segment contains no payload and receive window is closed and */ + /* sequence number is next expected number */ if (seg_len == 0 && tcb->rcv_wnd == 0 && l_edge == seq_num) { - return 1; + return 0; } - /* Possible case 2 */ - /* Segment contains no payload and Receive window is open and */ - /* Sequence number falls inside the receive window */ + /* Possible case 2: */ + /* Segment contains no payload and receive window is open and */ + /* sequence number falls inside the receive window */ if (seg_len == 0 && tcb->rcv_wnd > 0 && INSIDE_WND(l_edge, seq_num, r_edge)) { - return 1; + return 0; } - /* Possible case 3 */ - /* Segment contains Payload and Receive window is open and */ - /* Sequence Number overlaps with receive window */ + /* Possible case 3: */ + /* Segment contains payload and receive window is open and */ + /* sequence number overlaps with receive window */ if (seg_len > 0 && tcb->rcv_wnd > 0 && (INSIDE_WND(l_edge, seq_num, r_edge) || INSIDE_WND(l_edge, last_seq, r_edge))) { - return 1; + return 0; } /* Everthing else is not acceptable */ - return 0; + return -1; } uint32_t _pkt_get_seg_len(gnrc_pktsnip_t *pkt) @@ -328,7 +328,7 @@ int _pkt_setup_retransmit(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *pkt, const bool r tcb->pkt_retransmit = pkt; gnrc_pktbuf_hold(pkt, 1); - /* RTO Adjustment */ + /* RTO adjustment */ if (!retransmit) { /* If this is the first transmission: rto is 1 sec (Lower Bound) */ if (tcb->srtt == RTO_UNINITIALIZED || tcb->rtt_var == RTO_UNINITIALIZED) { @@ -343,14 +343,14 @@ int _pkt_setup_retransmit(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *pkt, const bool r tcb->rto *= 2; /* If the transmission has been tried five times, we assume srtt and rtt_var are bogus */ - /* New measurements must be taken */ + /* New measurements must be taken the next time something is sent. */ if (tcb->retries >= 5) { tcb->srtt = RTO_UNINITIALIZED; tcb->rtt_var = RTO_UNINITIALIZED; } } - /* Perform Boundrychecks on current RTO before usage */ + /* Perform boundry checks on current RTO before usage */ if (tcb->rto < (int32_t) GNRC_TCP_RTO_LOWER_BOUND) { tcb->rto = GNRC_TCP_RTO_LOWER_BOUND; } @@ -358,7 +358,7 @@ int _pkt_setup_retransmit(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *pkt, const bool r tcb->rto = GNRC_TCP_RTO_UPPER_BOUND; } - /* Setup retransmission timer, msg to TCP thread with ptr to tcb */ + /* Setup retransmission timer, msg to TCP thread with ptr to TCB */ tcb->msg_tout.type = MSG_TYPE_RETRANSMISSION; tcb->msg_tout.content.ptr = (void *) tcb; xtimer_set_msg(&tcb->tim_tout, tcb->rto, &tcb->msg_tout, gnrc_tcp_pid); @@ -371,7 +371,7 @@ int _pkt_acknowledge(gnrc_tcp_tcb_t *tcb, const uint32_t ack) gnrc_pktsnip_t *snp = NULL; tcp_hdr_t *hdr; - /* Retransmission Queue is empty. Nothing to ACK there */ + /* Retransmission queue is empty. Nothing to ACK there */ if (tcb->pkt_retransmit == NULL) { DEBUG("gnrc_tcp_pkt.c : _pkt_acknowledge() : There is no packet to ack\n"); return -ENODATA; @@ -389,10 +389,10 @@ int _pkt_acknowledge(gnrc_tcp_tcb_t *tcb, const uint32_t ack) gnrc_pktbuf_release(tcb->pkt_retransmit); tcb->pkt_retransmit = NULL; - /* Measure Round Trip Time */ + /* Measure round trip time */ int32_t rtt = xtimer_now().ticks32 - tcb->rtt_start; - /* Use sample only if ther was no timeroverflow and no retransmission (Karns Alogrithm) */ + /* Use time only if ther was no timer overflow and no retransmission (Karns Alogrithm) */ if (tcb->retries == 0 && rtt > 0) { /* If this is the first sample taken */ if (tcb->srtt == RTO_UNINITIALIZED && tcb->rtt_var == RTO_UNINITIALIZED) { @@ -428,12 +428,12 @@ uint16_t _pkt_calc_csum(const gnrc_pktsnip_t *hdr, const gnrc_pktsnip_t *pseudo_ payload = payload->next; } - /* Process tcp-header, before checksum field(Byte 16 to 18) */ + /* Process TCP header, before checksum field(Byte 16 to 18) */ csum = inet_csum(csum, (uint8_t *) hdr->data, 16); - /* Process tcp-header, after checksum field */ + /* Process TCP header, after checksum field */ csum = inet_csum(csum, ((uint8_t *) hdr->data) + 18, hdr->size - 18); - /* Process Network layer Header */ + /* Process network layer header */ switch (pseudo_hdr->type) { #ifdef MODULE_GNRC_IPV6 case GNRC_NETTYPE_IPV6: diff --git a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_rcvbuf.c b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_rcvbuf.c index f8f595497..8058f4687 100644 --- a/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_rcvbuf.c +++ b/sys/net/gnrc/transport_layer/tcp/gnrc_tcp_rcvbuf.c @@ -21,17 +21,29 @@ #define ENABLE_DEBUG (0) #include "debug.h" -rcvbuf_t _static_buf; /**< Staticly allocated receive buffers */ +/** + * @brief Internal struct holding receive buffers. + */ +rcvbuf_t _static_buf; +/** + * @brief Initializes all receive buffers. + */ void _rcvbuf_init(void) { - DEBUG("gnrc_tcp_rcvbuf.c : _rcvbuf_init() : Entry\n"); + DEBUG("gnrc_tcp_rcvbuf.c : _rcvbuf_init() : entry\n"); mutex_init(&(_static_buf.lock)); for (size_t i = 0; i < GNRC_TCP_RCV_BUFFERS; ++i) { _static_buf.entries[i].used = 0; } } +/** + * @brief Allocate receive buffer. + * + * @returns Not NULL if a receive buffer was allocated. + * NULL if allocation failed. + */ static void* _rcvbuf_alloc(void) { void *result = NULL; @@ -48,12 +60,17 @@ static void* _rcvbuf_alloc(void) return result; } +/** + * @brief Release allocated receive buffer. + * + * @param[in] buf Pointer to buffer that should be released. + */ static void _rcvbuf_free(void * const buf) { DEBUG("gnrc_tcp_rcvbuf.c : _rcvbuf_free() : Entry\n"); mutex_lock(&(_static_buf.lock)); for (size_t i = 0; i < GNRC_TCP_RCV_BUFFERS; ++i) { - if (_static_buf.entries[i].used == 1 && buf == _static_buf.entries[i].buffer) { + if ((_static_buf.entries[i].used == 1) && (buf == _static_buf.entries[i].buffer)) { _static_buf.entries[i].used = 0; } } diff --git a/sys/net/gnrc/transport_layer/tcp/internal/common.h b/sys/net/gnrc/transport_layer/tcp/internal/common.h index 8d7f98f93..0fa7f256c 100644 --- a/sys/net/gnrc/transport_layer/tcp/internal/common.h +++ b/sys/net/gnrc/transport_layer/tcp/internal/common.h @@ -9,12 +9,12 @@ /** * @defgroup net_gnrc_tcp TCP * @ingroup net_gnrc - * @brief RIOT's tcp implementation for the gnrc stack + * @brief RIOT's TCP implementation for the GNRC network stack. * * @{ * * @file - * @brief Internally used common defines, macros and variable declaration + * @brief Internally used defines, macros and variable declarations. * * @author Simon Brummer */ @@ -23,6 +23,7 @@ #define GNRC_TCP_INTERNAL_COMMON_H #include +#include "assert.h" #include "kernel_types.h" #include "thread.h" #include "mutex.h" @@ -34,22 +35,23 @@ extern "C" { #endif /** - * @brief Port unspecified. + * @brief Port number unspecified. * - * @note PORT 0 is unspecified (@see https://www.ietf.org/rfc/rfc1700.txt) + * @see https://www.ietf.org/rfc/rfc1700.txt */ #define PORT_UNSPEC (0) /** - * @brief Status Flags for TCP + * @brief TCB status flags * @{ */ #define STATUS_PASSIVE (1 << 0) #define STATUS_ALLOW_ANY_ADDR (1 << 1) +#define STATUS_NOTIFY_USER (1 << 2) /** @} */ /** - * @brief Defines for gnrc tcps "eventloop" thread + * @brief Defines for "eventloop" thread settings. * @{ */ #define TCP_EVENTLOOP_MSG_QUEUE_SIZE (8U) @@ -58,7 +60,7 @@ extern "C" { /** @} */ /** - * @brief Bitmasks for control bit handling + * @brief Bitmasks for control bit field handling. * @{ */ #define MSK_FIN (0x0001) @@ -77,7 +79,7 @@ extern "C" { /** @} */ /** - * @brief Type field values for TCP internal Message Passing. + * @brief Message types for GNRC TCPs internal message passing. * @{ */ #define MSG_TYPE_CONNECTION_TIMEOUT (GNRC_NETAPI_MSG_TYPE_ACK + 101) @@ -89,13 +91,13 @@ extern "C" { /** @} */ /** - * @brief Macro to mark is the time measurement is uninitialized + * @brief Define for marking that time measurement is uninitialized. */ #define RTO_UNINITIALIZED (-1) /** * @brief Overflow tolerant comparision operators for sequence and - acknowledgement number comparision + acknowledgement number comparison. * @{ */ #define LSS_32_BIT(x, y) (((int32_t) (x)) - ((int32_t) (y)) < 0) @@ -105,27 +107,27 @@ extern "C" { /** @} */ /** - * @brief Check if a given sequence number, falls into the a receive window + * @brief Check if a given sequence number falls into receive window. */ #define INSIDE_WND(l_ed, seq_num, r_ed) (LEQ_32_BIT(l_ed, seq_num) && LSS_32_BIT(seq_num, r_ed)) /** - * @brief Extract offset value from "offctl"-header field. + * @brief Extract offset value from "offctl" field in TCP header. */ #define GET_OFFSET( x ) (((x) & MSK_OFFSET) >> 12) /** - * @brief PID of tcp event handling thread + * @brief PID of GNRC TCP event handling thread */ extern kernel_pid_t gnrc_tcp_pid; /** - * @brief Head of linked tcb list. + * @brief Head of linked TCB list. */ extern gnrc_tcp_tcb_t *_list_tcb_head; /** - * @brief Mutex to protect linked list. + * @brief Mutex to protect TCB list. */ extern mutex_t _list_tcb_lock; diff --git a/sys/net/gnrc/transport_layer/tcp/internal/eventloop.h b/sys/net/gnrc/transport_layer/tcp/internal/eventloop.h index febe85c53..cbded225c 100644 --- a/sys/net/gnrc/transport_layer/tcp/internal/eventloop.h +++ b/sys/net/gnrc/transport_layer/tcp/internal/eventloop.h @@ -9,12 +9,12 @@ /** * @defgroup net_gnrc_tcp TCP * @ingroup net_gnrc - * @brief RIOT's tcp implementation for the gnrc stack + * @brief RIOT's TCP implementation for the GNRC network stack. * * @{ * * @file - * @brief TCP event loop delarations + * @brief TCP event loop delarations. * * @author Simon Brummer */ @@ -27,11 +27,11 @@ extern "C" { #endif /** - * @brief TCP's mein processing thread. + * @brief GNRC TCPs main processing thread. * - * @param[in] arg arguments, unused + * @param[in] arg Thread arguments (unused). * - * @return Never returns, its an endless loop + * @returns Never, its an endless loop */ void *_event_loop(__attribute__((unused)) void *arg); diff --git a/sys/net/gnrc/transport_layer/tcp/internal/fsm.h b/sys/net/gnrc/transport_layer/tcp/internal/fsm.h index bb2622f42..b70189e92 100644 --- a/sys/net/gnrc/transport_layer/tcp/internal/fsm.h +++ b/sys/net/gnrc/transport_layer/tcp/internal/fsm.h @@ -9,12 +9,12 @@ /** * @defgroup net_gnrc_tcp TCP * @ingroup net_gnrc - * @brief RIOT's tcp implementation for the gnrc stack + * @brief RIOT's TCP implementation for the GNRC network stack. * * @{ * * @file - * @brief TCP finite state maschine declarations + * @brief TCP finite state maschine declarations. * * @author Simon Brummer */ @@ -31,7 +31,7 @@ extern "C" { #endif /** - * @brief The TCP FSM States. + * @brief The TCP FSM states. */ typedef enum { FSM_STATE_CLOSED, @@ -48,7 +48,7 @@ typedef enum { } fsm_state_t; /** - * @brief Events that trigger translations in TCP FSM. + * @brief Events that trigger transitions in TCP FSM. */ typedef enum { FSM_EVENT_CALL_OPEN, /* User function call: open */ @@ -57,25 +57,25 @@ typedef enum { FSM_EVENT_CALL_CLOSE, /* User function call: close */ FSM_EVENT_CALL_ABORT, /* User function call: abort */ FSM_EVENT_RCVD_PKT, /* Paket received from peer */ - FSM_EVENT_TIMEOUT_TIMEWAIT, /* Timeout: Timewait */ - FSM_EVENT_TIMEOUT_RETRANSMIT, /* Timeout: Retransmit */ - FSM_EVENT_TIMEOUT_CONNECTION, /* Timeout: Connection */ - FSM_EVENT_SEND_PROBE, /* Send a Zero Window Probe */ - FSM_EVENT_CLEAR_RETRANSMIT /* Clear Retransmission Mechanism */ + FSM_EVENT_TIMEOUT_TIMEWAIT, /* Timeout: timewait */ + FSM_EVENT_TIMEOUT_RETRANSMIT, /* Timeout: retransmit */ + FSM_EVENT_TIMEOUT_CONNECTION, /* Timeout: connection */ + FSM_EVENT_SEND_PROBE, /* Send zero window probe */ + FSM_EVENT_CLEAR_RETRANSMIT /* Clear retransmission mechanism */ } fsm_event_t; /** * @brief TCP finite state maschine * - * @param[in,out] tcb specifies connection to use fsm on. - * @param[in] event current event that triggers fsm translation - * @param[in] in_pkt packet that triggered fsm event. Only in case of RCVD_PKT - * @param[in,out] buf buffer for send and receive functions - * @param[in] len number of bytes to send or receive atmost + * @param[in,out] tcb TCB holding the connection information. + * @param[in] event Current event that triggers FSM transition. + * @param[in] in_pkt Incomming packet. Only not NULL in case of event RCVD_PKT. + * @param[in,out] buf Buffer for send and receive functions. + * @param[in] len Number of bytes to send or receive. * - * @return Zero on success - * @return Positive Number, number of bytes sent from or copied into buf. - * @return -ENOSYS if event is not implemented + * @returns Zero on success + * Positive Number, number of bytes sent from or copied into @p buf. + * -ENOSYS if event is not implemented */ int _fsm(gnrc_tcp_tcb_t *tcb, fsm_event_t event, gnrc_pktsnip_t *in_pkt, void *buf, size_t len); diff --git a/sys/net/gnrc/transport_layer/tcp/internal/option.h b/sys/net/gnrc/transport_layer/tcp/internal/option.h index 2706854c0..34bda4b8b 100644 --- a/sys/net/gnrc/transport_layer/tcp/internal/option.h +++ b/sys/net/gnrc/transport_layer/tcp/internal/option.h @@ -9,12 +9,12 @@ /** * @defgroup net_gnrc_tcp TCP * @ingroup net_gnrc - * @brief RIOT's tcp implementation for the gnrc stack + * @brief RIOT's TCP implementation for the GNRC network stack. * * @{ * * @file - * @brief TCP option handling declarations + * @brief TCP option handling declarations. * * @author Simon Brummer */ @@ -32,11 +32,11 @@ extern "C" { #endif /** - * @brief Helper Function to build the MSS Option + * @brief Helper function to build the MSS option. * - * @param[in] mss tcp header to be checked + * @param[in] mss MSS value that should be set. * - * @return Valid MSS Option. + * @returns MSS option value. */ inline static uint32_t _option_build_mss(uint16_t mss) { @@ -45,12 +45,12 @@ inline static uint32_t _option_build_mss(uint16_t mss) } /** - * @brief Helper Function to build the combined option and control flag field + * @brief Helper function to build the combined option and control flag field. * - * @param[in] nopts Number of Options - * @param[in] ctl Control Flags + * @param[in] nopts Number of options. + * @param[in] ctl Control flag field. * - * @return Valid option size and control field. + * @returns Bitfield with encoded control bits and number of options. */ inline static uint16_t _option_build_offset_control(uint16_t nopts, uint16_t ctl) { @@ -59,13 +59,13 @@ inline static uint16_t _option_build_offset_control(uint16_t nopts, uint16_t ctl } /** - * @brief Parses options of a given tcp-header pktsnip. + * @brief Parses options of a given TCP header. * - * @param[out] tcb transmission control block to memorize options. - * @param[in] hdr tcp header to be checked + * @param[in,out] tcb TCB holding the connection information. + * @param[in] hdr TCP header to be parsed. * - * @return Zero on success - * @return A negative value on error + * @returns Zero on success. + * Negative value on error. */ int _option_parse(gnrc_tcp_tcb_t *tcb, tcp_hdr_t *hdr); diff --git a/sys/net/gnrc/transport_layer/tcp/internal/pkt.h b/sys/net/gnrc/transport_layer/tcp/internal/pkt.h index 4cc76eb44..a2f50fa7a 100644 --- a/sys/net/gnrc/transport_layer/tcp/internal/pkt.h +++ b/sys/net/gnrc/transport_layer/tcp/internal/pkt.h @@ -9,12 +9,12 @@ /** * @defgroup net_gnrc_tcp TCP * @ingroup net_gnrc - * @brief RIOT's tcp implementation for the gnrc stack + * @brief RIOT's TCP implementation for the GNRC network stack. * * @{ * * @file - * @brief TCP paket handling declarations + * @brief TCP paket handling declarations. * * @author Simon Brummer */ @@ -33,113 +33,113 @@ extern "C" { /** * @brief Build a reset packet from an incomming packet. * - * This function builds a reset from an incomming packet - * for cases where the connection has not been established + * @note This function builds a reset from an incomming packet + * in cases where the connection has not been established. * - * @param[out] out_pkt outgoing reset packet - * @param[in] in_pkt incomming packet + * @param[out] out_pkt Outgoing reset packet + * @param[in] in_pkt Incomming packet * - * @return Zero on success - * @return -ENOMEM if pktbuf is full. + * @returns Zero on success + * -ENOMEM if pktbuf is full. */ int _pkt_build_reset_from_pkt(gnrc_pktsnip_t **out_pkt, gnrc_pktsnip_t *in_pkt); /** - * @brief Build and allocate a tcp paket, tcb stores pointer to new paket. - * - * @param[in,out] tcb This connections transmission control block. - * @param[out] out_pkt Pointer to paket to build - * @param[out] seq_con Number of Bytes, the packet will consume in sequence number space - * @param[in] ctl control bits to set in out_pkt - * @param[in] seq_num sequence number of the new paket - * @param[in] ack_num acknowledgment number of the new paket - * @param[in] payload pointer to payload buffer - * @param[in] payload_len payload size - * - * @return Zero on success. - * @return -ENOMEM if pktbuf is full. + * @brief Build and allocate a TCB paket, TCB stores pointer to new paket. + * + * @param[in,out] tcb TCB holding the connection information. + * @param[out] out_pkt Pointer to paket to build. + * @param[out] seq_con Sequence number consumption of built packet. + * @param[in] ctl Control bits to set in @p out_pkt. + * @param[in] seq_num Sequence number of the new packet. + * @param[in] ack_num Acknowledgment number of the new packet. + * @param[in] payload Pointer to payload buffer. + * @param[in] payload_len Payload size. + * + * @returns Zero on success. + * -ENOMEM if pktbuf is full. */ int _pkt_build(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con, const uint16_t ctl, const uint32_t seq_num, const uint32_t ack_num, void *payload, const size_t payload_len); /** - * @brief Sends a packet to the peer + * @brief Sends packet to peer. * - * @param[in,out] tcb This connections Transmission control block. - * @param[in] out_pkt pointer to paket to send - * @param[in] seq_con sequence number consumption of the paket to send - * @param[in] retransmit is this a retransmission ? + * @param[in,out] tcb TCB holding the connection information. + * @param[in] out_pkt Pointer to paket to send. + * @param[in] seq_con Sequence number consumption of the packet to send. + * @param[in] retransmit Flag so mark that packet this is a retransmission. * - * @return Zero on success. - * @return -EINVAL if out_pkt was NULL + * @returns Zero on success. + * -EINVAL if out_pkt was NULL. */ int _pkt_send(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *out_pkt, const uint16_t seq_con, const bool retransmit); /** - * @brief Checks sequence number + * @brief Verify sequence number. * - * @param[in,out] tcb This connections Transmission control block. - * @param[in] seq_num sequence number from the segment - * @param[in] seg_len length of a segments payload + * @param[in,out] tcb TCB holding the connection information. + * @param[in] seq_num Sequence number from the segment. + * @param[in] seg_len Length of a segments payload. * - * @return Zero if the sequence number is invalid - * @return Non-zero if the sequence number is acceptable + * @returns Zero if the sequence number is acceptable. + * Negative value if the sequence number is not acceptable. */ int _pkt_chk_seq_num(const gnrc_tcp_tcb_t *tcb, const uint32_t seq_num, const uint32_t seg_len); /** - * @brief Extracts the length of a segment + * @brief Extracts the length of a segment. * - * @param[in] pkt Packet to calculate payload length + * @param[in] pkt Packet to calculate the segments length. * - * @return number consumption in sequence number space + * @returns Segments length in bytes (== sequence number consumption). */ uint32_t _pkt_get_seg_len(gnrc_pktsnip_t *pkt); /** - * @brief Calculates a segments payload length + * @brief Calculates a packets payload length. * - * @param[in] pkt Packet to calculate payload length + * @param[in] pkt Packet to calculate payload length. * - * @return the segments payload length in bytes + * @returns The packets payload length in bytes. */ uint32_t _pkt_get_pay_len(gnrc_pktsnip_t *pkt); /** - * @brief Adds a paket to the retransmission mechanism + * @brief Adds a packet to the retransmission mechanism. * - * @param[in,out] tcb This connections Transmission control block. - * @param[in] pkt paket to add to the retransmission mechanism - * @param[in] retransmit Flag used to indicate that pkt is a retransmit. + * @param[in,out] tcb TCB holding the connection information. + * @param[in] pkt Packet to add to the retransmission mechanism. + * @param[in] retransmit Flag used to indicate that @p pkt is a retransmit. * - * @return Zero on success - * @return -ENOMEM if the retransmission queue is full - * @return -EINVAL if pkt is null + * @returns Zero on success. + * -ENOMEM if the retransmission queue is full. + * -EINVAL if pkt is null. */ int _pkt_setup_retransmit(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *pkt, const bool retransmit); /** - * @brief Acknowledges and removes packet from the retransmission mechanism + * @brief Acknowledges and removes packet from the retransmission mechanism. * - * @param[in,out] tcb This connections Transmission control block. - * @param[in] ack Acknowldegment number used to acknowledge packets + * @param[in,out] tcb TCB holding the connection information. + * @param[in] ack Acknowldegment number used to acknowledge packets. * - * @return Zero on success - * @return -ENODATA if there is nothing to acknowledge + * @returns Zero on success. + * -ENODATA if there is nothing to acknowledge. */ int _pkt_acknowledge(gnrc_tcp_tcb_t *tcb, const uint32_t ack); /** - * @brief Calculates checksum over payload, tcp-header and network layer header + * @brief Calculates checksum over payload, TCP header and network layer header. * - * @param[in] hdr gnrc_pktsnip_t to tcp-header - * @param[in] pseudo_hdr gnrc_pktsnip_t to network layer header - * @param[in] payload gnrc_pktsnip_t to payload + * @param[in] hdr Gnrc_pktsnip_t to TCP header. + * @param[in] pseudo_hdr Gnrc_pktsnip_t to network layer header. + * @param[in] payload Gnrc_pktsnip_t to payload. * - * @return non zero checksum if given network layer is supported - * @return zero if given network layer is not supported + * @returns Non-zero checksum if given network layer is supported. + * Zero if given network layer is not supported. */ uint16_t _pkt_calc_csum(const gnrc_pktsnip_t *hdr, const gnrc_pktsnip_t *pseudo_hdr, const gnrc_pktsnip_t *payload); diff --git a/sys/net/gnrc/transport_layer/tcp/internal/rcvbuf.h b/sys/net/gnrc/transport_layer/tcp/internal/rcvbuf.h index b47d673c2..c3b349bca 100644 --- a/sys/net/gnrc/transport_layer/tcp/internal/rcvbuf.h +++ b/sys/net/gnrc/transport_layer/tcp/internal/rcvbuf.h @@ -9,12 +9,12 @@ /** * @defgroup net_gnrc_tcp TCP * @ingroup net_gnrc - * @brief RIOT's tcp implementation for the gnrc stack + * @brief RIOT's TCP implementation for the GNRC network stack. * * @{ * * @file - * @brief Functions for allocating and freeing the receive buffer + * @brief Functions for allocating and freeing the receive buffer. * * @author Simon Brummer */ @@ -32,43 +32,40 @@ extern "C" { #endif /** - * @brief Struct for a single connections receive buffer - * @internal + * @brief Receive buffer entry. */ typedef struct rcvbuf_entry { - uint8_t used; /**< Is entry currently in use */ - uint8_t buffer[GNRC_TCP_RCV_BUF_SIZE]; /**< Raw Buffer Data */ + uint8_t used; /**< Flag: Is buffer in use? */ + uint8_t buffer[GNRC_TCP_RCV_BUF_SIZE]; /**< Receive buffer storage */ } rcvbuf_entry_t; /** - * @brief Stuct holding receive buffers - * @internal + * @brief Stuct holding receive buffers. */ typedef struct rcvbuf { - mutex_t lock; /**< Lock for synchronization */ - rcvbuf_entry_t entries[GNRC_TCP_RCV_BUFFERS]; /**< Number of receive buffers */ + mutex_t lock; /**< Lock for allocation synchronization */ + rcvbuf_entry_t entries[GNRC_TCP_RCV_BUFFERS]; /**< Maintained receive buffers */ } rcvbuf_t; /** - * @brief Initializes global receive Buffer - * @internal + * @brief Initializes global receive buffer. */ void _rcvbuf_init(void); /** - * @brief Initializes and assigns receive Buffer to tcb. + * @brief Allocate receive buffer and assign it to TCB. * - * @param[in] tcb Transmission control block that should hold the buffer. + * @param[in,out] tcb TCB that aquires receive buffer. * - * @return zero on success - * @return -ENOMEM If receive buffer is out of memory. + * @returns Zero on success. + * -ENOMEM if all receive buffers are currently used. */ int _rcvbuf_get_buffer(gnrc_tcp_tcb_t *tcb); /** - * @brief Free allocated receive buffer + * @brief Release allocated receive buffer. * - * @param[in] tcb Transmission control block that buffer should be freed. + * @param[in,out] tcb TCB holding the receive buffer that should be released. */ void _rcvbuf_release_buffer(gnrc_tcp_tcb_t *tcb); diff --git a/tests/gnrc_tcp_client/Makefile b/tests/gnrc_tcp_client/Makefile index 47b574984..cb9a4e81f 100644 --- a/tests/gnrc_tcp_client/Makefile +++ b/tests/gnrc_tcp_client/Makefile @@ -6,9 +6,9 @@ include ../Makefile.tests_common BOARD ?= native PORT ?= tap1 -TCP_TARGET_ADDR ?= fe80::5c38:e9ff:fe76:6195 +TCP_TARGET_ADDR ?= fe80::affe TCP_TARGET_PORT ?= 80 -TCP_TEST_CYCLES ?= 10 +TCP_TEST_CYCLES ?= 3 # Mark Boards with insufficient memory BOARD_INSUFFICIENT_MEMORY := airfy-beacon arduino-duemilanove arduino-mega2560 \ diff --git a/tests/gnrc_tcp_client/README.md b/tests/gnrc_tcp_client/README.md new file mode 100644 index 000000000..83e0ce85a --- /dev/null +++ b/tests/gnrc_tcp_client/README.md @@ -0,0 +1,32 @@ +Test description +========== +This test starts a client using GNRC TCP. The test is intended to +work with gnrc_tcp_server. + +On startup the client tries to connect to a server waiting +for an incoming connection request. The target address and port number +can be user specified during the test build. After successful +connection establishment, the clients sends 2048 byte containing a test pattern (0xF0) +to the peer. After successful transmission, the client expects to receive 2048 byte + with a test pattern (0xA7) from the peer. After successful verification, the connection + termination sequence is initiated. + +The test sequence above runs a configurable amount of times. + +Usage (native) +========== + +Build and run test: +make clean all term + +Build and run test, user specified target address: +make clean all term TCP_TARGET_ADDR= + +Build and run test, user specified target port: +make clean all term TCP_TARGET_PORT= + +Build and run test, user specified amount of test cycles: +make clean all term TCP_TEST_CYLES= + +Build and run test, fully specified: +make clean all term TCP_TARGET_ADDR= TCP_TARGET_PORT= TCP_TEST_CYLES= diff --git a/tests/gnrc_tcp_client/main.c b/tests/gnrc_tcp_client/main.c index 77df29331..3d0dba905 100644 --- a/tests/gnrc_tcp_client/main.c +++ b/tests/gnrc_tcp_client/main.c @@ -26,12 +26,12 @@ #define NBYTE (2048) #endif -/* Test Pattern used by Client Application */ +/* Test pattern used by client application */ #ifndef TEST_PATERN_CLI #define TEST_PATERN_CLI (0xF0) #endif -/* Test Pattern used by Server Application */ +/* Test pattern used by server application */ #ifndef TEST_PATERN_SRV #define TEST_PATERN_SRV (0xA7) #endif @@ -46,7 +46,7 @@ int main(void) printf("\nStarting Client Threads. TARGET_ADDR=%s, TARGET_PORT=%d, ", TARGET_ADDR, TARGET_PORT); printf("CONNS=%d, NBYTE=%d, CYCLES=%d\n\n", CONNS, NBYTE, CYCLES ); - /* Start Connection Handling Threads */ + /* Start connection handling threads */ for (int i = 0; i < CONNS; i += 1) { thread_create((char *) stacks[i], sizeof(stacks[i]), THREAD_PRIORITY_MAIN, 0, cli_thread, (void *) i, NULL); @@ -56,29 +56,29 @@ int main(void) void *cli_thread(void *arg) { - /* Test Program variables */ + /* Test program variables */ int tid = (int) arg; uint32_t cycles = 0; uint32_t cycles_ok = 0; uint32_t failed_payload_verifications = 0; - /* Transmission Control Block */ + /* Transmission control block */ gnrc_tcp_tcb_t tcb; - /* Target Peer Address Information */ + /* Target peer address information */ ipv6_addr_t target_addr; uint16_t target_port; - /* Initialize Target Information */ + /* Initialize target information */ ipv6_addr_from_str(&target_addr, TARGET_ADDR); target_port = TARGET_PORT; printf("Client running: TID=%d\n", tid); while (cycles < CYCLES) { - /* Initialize tcb struct */ + /* Initialize TCB */ gnrc_tcp_tcb_init(&tcb); - /* Connect to Peer */ + /* Connect to peer */ int ret = gnrc_tcp_open_active(&tcb, AF_INET6, (uint8_t *) &target_addr, target_port, 0); switch (ret) { case 0: @@ -121,12 +121,12 @@ void *cli_thread(void *arg) return 0; } - /* Fill Buffer with a test pattern */ + /* Fill buffer with a test pattern */ for (size_t i = 0; i < sizeof(bufs[tid]); ++i){ bufs[tid][i] = TEST_PATERN_CLI; } - /* Send Data, stop if errors were found */ + /* Send data, stop if errors were found */ for (size_t sent = 0; sent < sizeof(bufs[tid]) && ret >= 0; sent += ret) { ret = gnrc_tcp_send(&tcb, bufs[tid] + sent, sizeof(bufs[tid]) - sent, 0); switch (ret) { @@ -157,7 +157,7 @@ void *cli_thread(void *arg) } } - /* Receive Data, stop if errors were found */ + /* Receive data, stop if errors were found */ for (size_t rcvd = 0; rcvd < sizeof(bufs[tid]) && ret >= 0; rcvd += ret) { ret = gnrc_tcp_recv(&tcb, (void *) (bufs[tid] + rcvd), sizeof(bufs[tid]) - rcvd, GNRC_TCP_CONNECTION_TIMEOUT_DURATION); @@ -204,10 +204,10 @@ void *cli_thread(void *arg) } } - /* Close Connection */ + /* Close connection */ gnrc_tcp_close(&tcb); - /* Gather Data */ + /* Gather data */ cycles += 1; if (ret >= 0) { cycles_ok += 1; diff --git a/tests/gnrc_tcp_server/Makefile b/tests/gnrc_tcp_server/Makefile index be7484f22..4398c288a 100644 --- a/tests/gnrc_tcp_server/Makefile +++ b/tests/gnrc_tcp_server/Makefile @@ -6,7 +6,9 @@ include ../Makefile.tests_common BOARD ?= native PORT ?= tap0 +TCP_LOCAL_ADDR ?= fe80::affe TCP_LOCAL_PORT ?= 80 +TCP_TEST_CYCLES ?= 3 # Mark Boards with insufficient memory BOARD_INSUFFICIENT_MEMORY := airfy-beacon arduino-duemilanove arduino-mega2560 \ @@ -17,8 +19,13 @@ BOARD_INSUFFICIENT_MEMORY := airfy-beacon arduino-duemilanove arduino-mega2560 \ pca10000 pca10005 sb-430 sb-430h stm32f0discovery telosb \ weio wsn430-v1_3b wsn430-v1_4 yunjia-nrf51822 z1 -# Specify local Port to open +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../.. + +# Local Address, Local Port and number of Test Cycles +CFLAGS += -DLOCAL_ADDR=\"$(TCP_LOCAL_ADDR)\" CFLAGS += -DLOCAL_PORT=$(TCP_LOCAL_PORT) +CFLAGS += -DCYCLES=$(TCP_TEST_CYCLES) # Comment this out to disable code in RIOT that does safety checking # which is not needed in a production environment but helps in the @@ -31,7 +38,7 @@ USEMODULE += auto_init_gnrc_netif USEMODULE += gnrc_ipv6_default USEMODULE += gnrc_tcp -# include this for printing IP addresses +# include this for IP address manipulation USEMODULE += shell_commands include $(RIOTBASE)/Makefile.include diff --git a/tests/gnrc_tcp_server/README.md b/tests/gnrc_tcp_server/README.md new file mode 100644 index 000000000..fd9615c78 --- /dev/null +++ b/tests/gnrc_tcp_server/README.md @@ -0,0 +1,33 @@ +Test description +========== +This test starts a server using GNRC TCP. The test is intended to +work with gnrc_tcp_client. + +On startup the server assigns a given IP-Address to its network +interface and opens a given port number waiting for a client +to connect to this port. As soon as a client connects the server +expects to receive 2048 byte containing a sequence of a test pattern (0xF0). + +After successful verification, the server sends 2048 byte with a test +pattern (0xA7) to the peer. After successful transmission the connection +termination sequence is initiated. + +The test sequence above runs a configurable amount of times. + +Usage (native) +========== + +Build and run test: +make clean all term + +Build and run test, user specified local address: +make clean all term TCP_LOCAL_ADDR= + +Build and run test, user specified local port: +make clean all term TCP_LOCAL_PORT= + +Build and run test, user specified amount of test cycles: +make clean all term TCP_TEST_CYLES= + +Build and run test, fully specified: +make clean all term TCP_LOCAL_ADDR= TCP_LOCAL_PORT= TCP_TEST_CYLES= diff --git a/tests/gnrc_tcp_server/main.c b/tests/gnrc_tcp_server/main.c index c938cafc9..32415c656 100644 --- a/tests/gnrc_tcp_server/main.c +++ b/tests/gnrc_tcp_server/main.c @@ -26,12 +26,12 @@ #define NBYTE (2048) #endif -/* Test Pattern used by Client Application */ +/* Test pattern used by client application */ #ifndef TEST_PATERN_CLI #define TEST_PATERN_CLI (0xF0) #endif -/* Test Pattern used by Server Application */ +/* Test pattern used by server application */ #ifndef TEST_PATERN_SRV #define TEST_PATERN_SRV (0xA7) #endif @@ -39,21 +39,32 @@ uint8_t bufs[CONNS][NBYTE]; uint8_t stacks[CONNS][THREAD_STACKSIZE_DEFAULT + THREAD_EXTRA_STACKSIZE_PRINTF]; -/* ifconfig shell command */ +/* "ifconfig" shell command */ extern int _netif_config(int argc, char **argv); -/* Server Thread */ +/* Server thread */ void *srv_thread(void *arg); int main(void) { + /* Get PID of the a network interface */ + kernel_pid_t ifs[GNRC_NETIF_NUMOF]; + size_t numof = gnrc_netif_get(ifs); + if (10 <= numof) { + printf("No valid network interface found\n"); + return -1; + } + + /* Set pre-configured IP address */ + char if_pid[] = {ifs[0] + '0', '\0'}; + char *cmd[] = {"ifconfig", if_pid, "add", "unicast", LOCAL_ADDR}; + _netif_config(5, cmd); - /* Print all configured addresses of the server */ - printf("\nStarting server: LOCAL_PORT=%d, CONNS=%d, NBYTE=%d\n\n", LOCAL_PORT, CONNS, NBYTE); - printf("Printing Servers Network Configuration:\n"); - _netif_config(0, NULL); + /* Test configuration */ + printf("\nStarting server: LOCAL_ADDR=%s, LOCAL_PORT=%d, ", LOCAL_ADDR, LOCAL_PORT); + printf("CONNS=%d, NBYTE=%d, CYCLES=%d\n\n", CONNS, NBYTE, CYCLES); - /* Start Threads to handle each connection */ + /* Start Threads to handle connections */ for (int i = 0; i < CONNS; i += 1) { thread_create((char *) stacks[i], sizeof(stacks[i]), THREAD_PRIORITY_MAIN, 0, srv_thread, (void *) i, NULL); @@ -73,11 +84,11 @@ void *srv_thread(void *arg) /* Connection handling code */ printf("Server running: TID=%d\n", tid); - while (1) { - /* Initialize tcb struct */ + while (cycles < CYCLES) { + /* Initialize TCB struct */ gnrc_tcp_tcb_init(&tcb); - /* Connect to Peer */ + /* Connect to peer */ int ret = gnrc_tcp_open_passive(&tcb, AF_INET6, NULL, LOCAL_PORT); switch (ret) { case 0: @@ -105,7 +116,7 @@ void *srv_thread(void *arg) return 0; } - /* Receive Data, stop if errors were found */ + /* Receive data, stop if errors were found */ for (size_t rcvd = 0; rcvd < sizeof(bufs[tid]) && ret >= 0; rcvd += ret) { ret = gnrc_tcp_recv(&tcb, (void *) (bufs[tid] + rcvd), sizeof(bufs[tid]) - rcvd, GNRC_TCP_CONNECTION_TIMEOUT_DURATION); @@ -152,12 +163,12 @@ void *srv_thread(void *arg) } } - /* Fill Buffer with a test pattern */ + /* Fill buffer with a test pattern */ for (size_t i = 0; i < sizeof(bufs[tid]); ++i) { bufs[tid][i] = TEST_PATERN_SRV; } - /* Send Data, stop if errors were found */ + /* Send data, stop if errors were found */ for (size_t sent = 0; sent < sizeof(bufs[tid]) && ret >= 0; sent += ret) { ret = gnrc_tcp_send(&tcb, bufs[tid] + sent, sizeof(bufs[tid]) - sent, 0); switch (ret) { @@ -188,10 +199,10 @@ void *srv_thread(void *arg) } } - /* Close Connection */ + /* Close connection */ gnrc_tcp_close(&tcb); - /* Gather Data */ + /* Gather data */ cycles += 1; if (ret >= 0) { cycles_ok += 1; @@ -200,5 +211,6 @@ void *srv_thread(void *arg) tid, cycles, cycles_ok, cycles - cycles_ok); printf(", %"PRIi32" failed payload verifications\n", failed_payload_verifications); } + printf("server thread terminating: TID=%d\n", tid); return 0; }