Browse Source

Merge pull request #6742 from brummer-simon/gnrc_tcp-cleanup-minor_changes

gnrc_tcp: cleanup: minor changes
master
Sebastian Meiling 6 years ago committed by GitHub
parent
commit
9480488e92
  1. 189
      sys/include/net/gnrc/tcp.h
  2. 22
      sys/include/net/gnrc/tcp/config.h
  3. 54
      sys/include/net/gnrc/tcp/tcb.h
  4. 28
      sys/include/net/tcp.h
  5. 203
      sys/net/gnrc/transport_layer/tcp/gnrc_tcp.c
  6. 89
      sys/net/gnrc/transport_layer/tcp/gnrc_tcp_eventloop.c
  7. 437
      sys/net/gnrc/transport_layer/tcp/gnrc_tcp_fsm.c
  8. 6
      sys/net/gnrc/transport_layer/tcp/gnrc_tcp_option.c
  9. 66
      sys/net/gnrc/transport_layer/tcp/gnrc_tcp_pkt.c
  10. 23
      sys/net/gnrc/transport_layer/tcp/gnrc_tcp_rcvbuf.c
  11. 32
      sys/net/gnrc/transport_layer/tcp/internal/common.h
  12. 10
      sys/net/gnrc/transport_layer/tcp/internal/eventloop.h
  13. 34
      sys/net/gnrc/transport_layer/tcp/internal/fsm.h
  14. 28
      sys/net/gnrc/transport_layer/tcp/internal/option.h
  15. 116
      sys/net/gnrc/transport_layer/tcp/internal/pkt.h
  16. 33
      sys/net/gnrc/transport_layer/tcp/internal/rcvbuf.h
  17. 4
      tests/gnrc_tcp_client/Makefile
  18. 32
      tests/gnrc_tcp_client/README.md
  19. 28
      tests/gnrc_tcp_client/main.c
  20. 11
      tests/gnrc_tcp_server/Makefile
  21. 33
      tests/gnrc_tcp_server/README.md
  22. 46
      tests/gnrc_tcp_server/main.c

189
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);

22
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)

54
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 <simon.brummer@posteo.de>
*/
@ -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

28
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);

203
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);

89
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;
}

437
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)