Merge pull request #6541 from brummer-simon/gnrc_tcp-cleanup
gnrc_tcp: cleanup
This commit is contained in:
commit
f6022a283d
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Simon Brummer
|
||||
* Copyright (C) 2015-2017 Simon Brummer
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
|
@ -14,17 +14,16 @@
|
|||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief TCP interface definition
|
||||
* @brief GNRC TCP API
|
||||
*
|
||||
* @author Simon Brummer <simon.brummer@haw-hamburg.de>
|
||||
* @author Simon Brummer <simon.brummer@posteo.de>
|
||||
*/
|
||||
|
||||
#ifndef GNRC_TCP_H_
|
||||
#define GNRC_TCP_H_
|
||||
#ifndef GNRC_TCP_H
|
||||
#define GNRC_TCP_H
|
||||
|
||||
#include "net/tcp.h"
|
||||
#include "net/gnrc/netapi.h"
|
||||
#include "net/gnrc/nettype.h"
|
||||
#include <stdint.h>
|
||||
#include "net/gnrc/pkt.h"
|
||||
#include "net/gnrc/tcp/tcb.h"
|
||||
|
||||
#ifdef MODULE_GNRC_IPV6
|
||||
|
@ -35,23 +34,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Port unspecified.
|
||||
*
|
||||
* @note PORT 0 is reserved, according to rfc 1700(https://www.ietf.org/rfc/rfc1700.txt)
|
||||
*/
|
||||
#define GNRC_TCP_PORT_UNSPEC 0
|
||||
|
||||
/**
|
||||
* @brief Head of conn linked list.
|
||||
*/
|
||||
extern gnrc_tcp_tcb_t *_list_gnrc_tcp_tcb_head;
|
||||
|
||||
/**
|
||||
* @brief Mutex to protect linked list.
|
||||
*/
|
||||
extern mutex_t _list_gnrc_tcp_tcb_lock;
|
||||
|
||||
/**
|
||||
* @brief Initialize and start TCP
|
||||
*
|
||||
|
@ -68,7 +50,7 @@ int gnrc_tcp_init(void);
|
|||
*
|
||||
* @param[in,out] tcb Transmission that should be initialized.
|
||||
*/
|
||||
void gnrc_tcp_tcb_init(gnrc_tcp_tcb_t* tcb);
|
||||
void gnrc_tcp_tcb_init(gnrc_tcp_tcb_t *tcb);
|
||||
|
||||
/**
|
||||
* @brief Opens a connection actively.
|
||||
|
@ -85,7 +67,7 @@ void gnrc_tcp_tcb_init(gnrc_tcp_tcb_t* tcb);
|
|||
* @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 choosen. If local_port is non-zero
|
||||
* source port is randomly chosen. If local_port is non-zero
|
||||
* the local_port is used as source port.
|
||||
*
|
||||
* @return Zero on success.
|
||||
|
@ -116,7 +98,7 @@ int gnrc_tcp_open_active(gnrc_tcp_tcb_t *tcb, const uint8_t address_family,
|
|||
* @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 in @p local_addr.
|
||||
* @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.
|
||||
*
|
||||
|
@ -200,8 +182,8 @@ int gnrc_tcp_close(gnrc_tcp_tcb_t *tcb);
|
|||
/**
|
||||
* @brief Set checksum calculated from tcp and network-layer header in tcp-header.
|
||||
*
|
||||
* @param[in] hdr ng_pktsnip that contains tcp header.
|
||||
* @param[in] pseudo_hdr ng_pktsnip that contains networklayer header.
|
||||
* @param[in] hdr gnrc_pktsnip that contains tcp header.
|
||||
* @param[in] pseudo_hdr gnrc_pktsnip that contains networklayer header.
|
||||
*
|
||||
* @return zero on succeed.
|
||||
* @return -EFAULT if hdr or pseudo_hdr were NULL
|
||||
|
@ -227,5 +209,5 @@ gnrc_pktsnip_t *gnrc_tcp_hdr_build(gnrc_pktsnip_t *payload, uint16_t src, uint16
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* GNRC_TCP_H_ */
|
||||
#endif /* GNRC_TCP_H */
|
||||
/** @} */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Simon Brummer
|
||||
* Copyright (C) 2015-2017 Simon Brummer
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
|
@ -14,13 +14,13 @@
|
|||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief TCP configuration, includes buffersizes, timeout durations
|
||||
* @brief GNRC TCP configuration
|
||||
*
|
||||
* @author Simon Brummer <simon.brummer@haw-hamburg.de>
|
||||
* @author Simon Brummer <simon.brummer@posteo.de>
|
||||
*/
|
||||
|
||||
#ifndef GNRC_TCP_CONFIG_H_
|
||||
#define GNRC_TCP_CONFIG_H_
|
||||
#ifndef GNRC_TCP_CONFIG_H
|
||||
#define GNRC_TCP_CONFIG_H
|
||||
|
||||
#include "timex.h"
|
||||
|
||||
|
@ -28,48 +28,18 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Status Flags for TCP
|
||||
* @{
|
||||
*/
|
||||
#define GNRC_TCP_STATUS_PASSIVE (1 << 0)
|
||||
#define GNRC_TCP_STATUS_ACCEPTED (1 << 1)
|
||||
#define GNRC_TCP_STATUS_ALLOW_ANY_ADDR (1 << 2)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Timeout Duration for user calls. Default 2 minutes
|
||||
*/
|
||||
#ifndef GNRC_TCP_CONNECTION_TIMEOUT_DURATION
|
||||
#define GNRC_TCP_CONNECTION_TIMEOUT_DURATION (120 * US_PER_SEC)
|
||||
#define GNRC_TCP_CONNECTION_TIMEOUT_DURATION (120U * US_PER_SEC)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Maximum Segment Lifetime. Default 30 secounds
|
||||
*/
|
||||
#ifndef GNRC_TCP_MSL
|
||||
#define GNRC_TCP_MSL (30 * US_PER_SEC)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Message queue size for the TCP handling thread
|
||||
*/
|
||||
#ifndef GNRC_TCP_MSG_QUEUE_SIZE
|
||||
#define GNRC_TCP_MSG_QUEUE_SIZE (8U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Priority of the tcp handling thread, must be lower than the applications prio.
|
||||
*/
|
||||
#ifndef GNRC_TCP_PRIO
|
||||
#define GNRC_TCP_PRIO (THREAD_PRIORITY_MAIN - 2U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default stack size for the TCP handling thread
|
||||
*/
|
||||
#ifndef GNRC_TCP_STACK_SIZE
|
||||
#define GNRC_TCP_STACK_SIZE (THREAD_STACKSIZE_DEFAULT)
|
||||
#define GNRC_TCP_MSL (30U * US_PER_SEC)
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -101,7 +71,7 @@ extern "C" {
|
|||
* @brief Number of preallocated receive buffers
|
||||
*/
|
||||
#ifndef GNRC_TCP_RCV_BUFFERS
|
||||
#define GNRC_TCP_RCV_BUFFERS 1
|
||||
#define GNRC_TCP_RCV_BUFFERS (1U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -115,21 +85,21 @@ extern "C" {
|
|||
* @brief Lower Bound for RTO = 1 sec (see RFC 6298)
|
||||
*/
|
||||
#ifndef GNRC_TCP_RTO_LOWER_BOUND
|
||||
#define GNRC_TCP_RTO_LOWER_BOUND (1 * US_PER_SEC)
|
||||
#define GNRC_TCP_RTO_LOWER_BOUND (1U * US_PER_SEC)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Upper Bound for RTO = 60 sec (see RFC 6298)
|
||||
*/
|
||||
#ifndef GNRC_TCP_RTO_UPPER_BOUND
|
||||
#define GNRC_TCP_RTO_UPPER_BOUND (60 * US_PER_SEC)
|
||||
#define GNRC_TCP_RTO_UPPER_BOUND (60U * US_PER_SEC)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Assumes clock granularity for TCP of 10 ms (see RFC 6298)
|
||||
*/
|
||||
#ifndef GNRC_TCP_RTO_GRANULARITY
|
||||
#define GNRC_TCP_RTO_GRANULARITY (10 * MS_PER_SEC)
|
||||
#define GNRC_TCP_RTO_GRANULARITY (10U * MS_PER_SEC)
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -153,30 +123,23 @@ extern "C" {
|
|||
#define GNRC_TCP_RTO_K (4U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Macro to mark is the time measurement is uninitialized
|
||||
*/
|
||||
#ifndef GNRC_TCP_RTO_UNINITIALIZED
|
||||
#define GNRC_TCP_RTO_UNINITIALIZED (-1)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Lower Bound for the duration between probes
|
||||
*/
|
||||
#ifndef GNRC_TCP_PROBE_LOWER_BOUND
|
||||
#define GNRC_TCP_PROBE_LOWER_BOUND (1 * US_PER_SEC)
|
||||
#define GNRC_TCP_PROBE_LOWER_BOUND (1U * US_PER_SEC)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Upper Bound for the duration between probes
|
||||
*/
|
||||
#ifndef GNRC_TCP_PROBE_UPPER_BOUND
|
||||
#define GNRC_TCP_PROBE_UPPER_BOUND (60 * US_PER_SEC)
|
||||
#define GNRC_TCP_PROBE_UPPER_BOUND (60U * US_PER_SEC)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GNRC_TCP_CONFIG_H_ */
|
||||
#endif /* GNRC_TCP_CONFIG_H */
|
||||
/** @} */
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Simon Brummer
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup net_gnrc_tcp TCP
|
||||
* @ingroup net_gnrc
|
||||
* @brief RIOT's tcp implementation for the gnrc stack
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Definies states and events for TCP finite state maschine
|
||||
*
|
||||
* @author Simon Brummer <brummer.simon@googlemail.com>
|
||||
*/
|
||||
|
||||
#ifndef GNRC_TCP_FSM_H_
|
||||
#define GNRC_TCP_FSM_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The TCP FSM States.
|
||||
*/
|
||||
typedef enum {
|
||||
GNRC_TCP_FSM_STATE_CLOSED,
|
||||
GNRC_TCP_FSM_STATE_LISTEN,
|
||||
GNRC_TCP_FSM_STATE_SYN_SENT,
|
||||
GNRC_TCP_FSM_STATE_SYN_RCVD,
|
||||
GNRC_TCP_FSM_STATE_ESTABLISHED,
|
||||
GNRC_TCP_FSM_STATE_CLOSE_WAIT,
|
||||
GNRC_TCP_FSM_STATE_LAST_ACK,
|
||||
GNRC_TCP_FSM_STATE_FIN_WAIT_1,
|
||||
GNRC_TCP_FSM_STATE_FIN_WAIT_2,
|
||||
GNRC_TCP_FSM_STATE_CLOSING,
|
||||
GNRC_TCP_FSM_STATE_TIME_WAIT
|
||||
} gnrc_tcp_fsm_state_t;
|
||||
|
||||
/**
|
||||
* @brief Events that trigger translations in TCP FSM.
|
||||
*/
|
||||
typedef enum {
|
||||
GNRC_TCP_FSM_EVENT_CALL_OPEN, /* User function call: open */
|
||||
GNRC_TCP_FSM_EVENT_CALL_SEND, /* User function call: send */
|
||||
GNRC_TCP_FSM_EVENT_CALL_RECV, /* User function call: recv */
|
||||
GNRC_TCP_FSM_EVENT_CALL_CLOSE, /* User function call: close */
|
||||
GNRC_TCP_FSM_EVENT_CALL_ABORT, /* User function call: abort */
|
||||
GNRC_TCP_FSM_EVENT_RCVD_PKT, /* Paket received from peer */
|
||||
GNRC_TCP_FSM_EVENT_TIMEOUT_TIMEWAIT, /* Timeout: Timewait */
|
||||
GNRC_TCP_FSM_EVENT_TIMEOUT_RETRANSMIT, /* Timeout: Retransmit */
|
||||
GNRC_TCP_FSM_EVENT_TIMEOUT_CONNECTION, /* Timeout: Connection */
|
||||
GNRC_TCP_FSM_EVENT_SEND_PROBE, /* Send a Zero Window Probe */
|
||||
GNRC_TCP_FSM_EVENT_CLEAR_RETRANSMIT /* Clear Retransmission Mechanism */
|
||||
} gnrc_tcp_fsm_event_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GNRC_TCP_FSM_H_ */
|
||||
/** @} */
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Simon Brummer
|
||||
* Copyright (C) 2015-2017 Simon Brummer
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
|
@ -14,21 +14,21 @@
|
|||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Transmission Control Block definition
|
||||
* @brief GNRC TCP transmission control block
|
||||
*
|
||||
* @author Simon Brummer <simon.brummer@haw-hamburg.de>
|
||||
* @author Simon Brummer <simon.brummer@posteo.de>
|
||||
*/
|
||||
|
||||
#ifndef GNRC_TCP_TCB_H_
|
||||
#define GNRC_TCP_TCB_H_
|
||||
#ifndef GNRC_TCP_TCB_H
|
||||
#define GNRC_TCP_TCB_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <ringbuffer.h>
|
||||
#include <xtimer.h>
|
||||
#include <mutex.h>
|
||||
#include <msg.h>
|
||||
#include "net/gnrc.h"
|
||||
#include "fsm.h"
|
||||
#include "kernel_types.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "xtimer.h"
|
||||
#include "mutex.h"
|
||||
#include "msg.h"
|
||||
#include "net/gnrc/pkt.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef MODULE_GNRC_IPV6
|
||||
|
@ -39,48 +39,53 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Size of the tcbs internal message queue
|
||||
*/
|
||||
#define GNRC_TCP_TCB_MSG_QUEUE_SIZE (8U)
|
||||
|
||||
/**
|
||||
* @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 and 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 */
|
||||
gnrc_tcp_fsm_state_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 */
|
||||
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 */
|
||||
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" */
|
||||
kernel_pid_t owner; /**< PID of this connection handling thread */
|
||||
msg_t msg_queue[GNRC_TCP_MSG_QUEUE_SIZE]; /**< Message queue used for asynchronious operation */
|
||||
uint8_t *rcv_buf_raw; /**< Pointer to the receive buffer */
|
||||
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 */
|
||||
uint16_t local_port; /**< local connections port number */
|
||||
uint16_t peer_port; /**< port 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 */
|
||||
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 */
|
||||
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" */
|
||||
kernel_pid_t owner; /**< PID of this connection handling thread */
|
||||
msg_t msg_queue[GNRC_TCP_TCB_MSG_QUEUE_SIZE]; /**< Tcb's message queue */
|
||||
uint8_t *rcv_buf_raw; /**< Pointer to the receive buffer */
|
||||
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 */
|
||||
} gnrc_tcp_tcb_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* GNRC_TCP_TCB_H_ */
|
||||
#endif /* GNRC_TCP_TCB_H */
|
||||
/** @} */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Simon Brummer
|
||||
* Copyright (C) 2015-2017 Simon Brummer
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
|
@ -14,9 +14,9 @@
|
|||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief TCP header and helper functions
|
||||
* @brief TCP header and helper functions
|
||||
*
|
||||
* @author Simon Brummer <brummer.simon@googlemail.com>
|
||||
* @author Simon Brummer <simon.brummer@posteo.de>
|
||||
*/
|
||||
|
||||
#ifndef TCP_H
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Simon Brummer
|
||||
* Copyright (C) 2015-2017 Simon Brummer
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
|
@ -11,34 +11,20 @@
|
|||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief GNRC's TCP implementation
|
||||
* @brief GNRC TCP API implementation
|
||||
*
|
||||
* @author Simon Brummer <brummer.simon@googlemail.com>
|
||||
* @author Simon Brummer <simon.brummer@posteo.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <utlist.h>
|
||||
#include "msg.h"
|
||||
#include "assert.h"
|
||||
#include "thread.h"
|
||||
#include "byteorder.h"
|
||||
#include "random.h"
|
||||
#include "xtimer.h"
|
||||
#include "mutex.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "net/af.h"
|
||||
#include "net/gnrc/nettype.h"
|
||||
#include "net/gnrc/netapi.h"
|
||||
#include "net/gnrc/netreg.h"
|
||||
#include "net/gnrc/pktbuf.h"
|
||||
#include "net/gnrc/tcp.h"
|
||||
|
||||
#include "internal/common.h"
|
||||
#include "internal/fsm.h"
|
||||
#include "internal/pkt.h"
|
||||
#include "internal/option.h"
|
||||
#include "internal/helper.h"
|
||||
#include "internal/eventloop.h"
|
||||
#include "internal/rcvbuf.h"
|
||||
|
||||
|
@ -53,25 +39,25 @@
|
|||
* @brief Allocate memory for TCP thread's stack
|
||||
*/
|
||||
#if ENABLE_DEBUG
|
||||
static char _stack[GNRC_TCP_STACK_SIZE + THREAD_EXTRA_STACKSIZE_PRINTF];
|
||||
static char _stack[TCP_EVENTLOOP_STACK_SIZE + THREAD_EXTRA_STACKSIZE_PRINTF];
|
||||
#else
|
||||
static char _stack[GNRC_TCP_STACK_SIZE];
|
||||
static char _stack[TCP_EVENTLOOP_STACK_SIZE];
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief TCPs eventloop pid, declared externally
|
||||
*/
|
||||
kernel_pid_t _gnrc_tcp_pid = KERNEL_PID_UNDEF;
|
||||
kernel_pid_t gnrc_tcp_pid = KERNEL_PID_UNDEF;
|
||||
|
||||
/**
|
||||
* @brief Head of liked list of active connections
|
||||
*/
|
||||
gnrc_tcp_tcb_t *_list_gnrc_tcp_tcb_head;
|
||||
gnrc_tcp_tcb_t *_list_tcb_head;
|
||||
|
||||
/**
|
||||
* @brief Mutex to protect the connection list
|
||||
*/
|
||||
mutex_t _list_gnrc_tcp_tcb_lock;
|
||||
mutex_t _list_tcb_lock;
|
||||
|
||||
/**
|
||||
* @brief Establishes a new TCP connection
|
||||
|
@ -83,7 +69,7 @@ mutex_t _list_gnrc_tcp_tcb_lock;
|
|||
* @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 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".
|
||||
|
@ -103,23 +89,23 @@ static int _gnrc_tcp_open(gnrc_tcp_tcb_t *tcb, const uint8_t *target_addr, uint1
|
|||
mutex_lock(&(tcb->function_lock));
|
||||
|
||||
/* Connection is already connected: Return -EISCONN */
|
||||
if (tcb->state != GNRC_TCP_FSM_STATE_CLOSED) {
|
||||
if (tcb->state != FSM_STATE_CLOSED) {
|
||||
mutex_unlock(&(tcb->function_lock));
|
||||
return -EISCONN;
|
||||
}
|
||||
|
||||
/* Setup connection (common parts) */
|
||||
msg_init_queue(tcb->msg_queue, GNRC_TCP_MSG_QUEUE_SIZE);
|
||||
msg_init_queue(tcb->msg_queue, GNRC_TCP_TCB_MSG_QUEUE_SIZE);
|
||||
tcb->owner = thread_getpid();
|
||||
|
||||
/* Setup passive connection */
|
||||
if (passive){
|
||||
if (passive) {
|
||||
/* Set Status Flags */
|
||||
tcb->status |= GNRC_TCP_STATUS_PASSIVE;
|
||||
tcb->status |= STATUS_PASSIVE;
|
||||
if (local_addr == NULL) {
|
||||
tcb->status |= GNRC_TCP_STATUS_ALLOW_ANY_ADDR;
|
||||
tcb->status |= STATUS_ALLOW_ANY_ADDR;
|
||||
}
|
||||
/* If local address is specified: Copy it into tcb: only connections to this addr are ok */
|
||||
/* If local address is specified: Copy it into tcb */
|
||||
else {
|
||||
switch (tcb->address_family) {
|
||||
#ifdef MODULE_GNRC_IPV6
|
||||
|
@ -133,14 +119,14 @@ static int _gnrc_tcp_open(gnrc_tcp_tcb_t *tcb, const uint8_t *target_addr, uint1
|
|||
tcb->local_port = local_port;
|
||||
}
|
||||
/* Setup active connection */
|
||||
else{
|
||||
else {
|
||||
/* Copy Target Address and Port into tcb structure */
|
||||
if (target_addr != NULL) {
|
||||
switch (tcb->address_family) {
|
||||
#ifdef MODULE_GNRC_IPV6
|
||||
case AF_INET6:
|
||||
memcpy(tcb->peer_addr, target_addr, sizeof(ipv6_addr_t));
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(tcb->peer_addr, target_addr, sizeof(ipv6_addr_t));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -156,23 +142,22 @@ static int _gnrc_tcp_open(gnrc_tcp_tcb_t *tcb, const uint8_t *target_addr, uint1
|
|||
}
|
||||
|
||||
/* Call FSM with Event: CALL_OPEN */
|
||||
ret = _fsm(tcb, GNRC_TCP_FSM_EVENT_CALL_OPEN, NULL, NULL, 0);
|
||||
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");
|
||||
} else if(ret == -EADDRINUSE) {
|
||||
}
|
||||
else if(ret == -EADDRINUSE) {
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_connect() : local_port is already in use.\n");
|
||||
}
|
||||
|
||||
/* Wait until a connection was established or closed */
|
||||
while (ret >= 0 && tcb->state != GNRC_TCP_FSM_STATE_CLOSED
|
||||
&& tcb->state != GNRC_TCP_FSM_STATE_ESTABLISHED
|
||||
&& tcb->state != GNRC_TCP_FSM_STATE_CLOSE_WAIT
|
||||
) {
|
||||
while (ret >= 0 && tcb->state != FSM_STATE_CLOSED && tcb->state != FSM_STATE_ESTABLISHED &&
|
||||
tcb->state != FSM_STATE_CLOSE_WAIT) {
|
||||
msg_receive(&msg);
|
||||
switch (msg.type) {
|
||||
case MSG_TYPE_CONNECTION_TIMEOUT:
|
||||
DEBUG("gnrc_tcp.c : _gnrc_tcp_open() : CONNECTION_TIMEOUT\n");
|
||||
_fsm(tcb, GNRC_TCP_FSM_EVENT_TIMEOUT_CONNECTION, NULL, NULL, 0);
|
||||
_fsm(tcb, FSM_EVENT_TIMEOUT_CONNECTION, NULL, NULL, 0);
|
||||
ret = -ETIMEDOUT;
|
||||
break;
|
||||
|
||||
|
@ -187,7 +172,7 @@ static int _gnrc_tcp_open(gnrc_tcp_tcb_t *tcb, const uint8_t *target_addr, uint1
|
|||
|
||||
/* Cleanup */
|
||||
xtimer_remove(&connection_timeout_timer);
|
||||
if (tcb->state == GNRC_TCP_FSM_STATE_CLOSED && ret == 0) {
|
||||
if (tcb->state == FSM_STATE_CLOSED && ret == 0) {
|
||||
ret = -ECONNREFUSED;
|
||||
}
|
||||
tcb->owner = KERNEL_PID_UNDEF;
|
||||
|
@ -199,24 +184,25 @@ static int _gnrc_tcp_open(gnrc_tcp_tcb_t *tcb, const uint8_t *target_addr, uint1
|
|||
int gnrc_tcp_init(void)
|
||||
{
|
||||
/* Guard: Check if thread is already running */
|
||||
if (_gnrc_tcp_pid != KERNEL_PID_UNDEF) {
|
||||
if (gnrc_tcp_pid != KERNEL_PID_UNDEF) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize Mutex for linked-list synchronization */
|
||||
mutex_init(&(_list_gnrc_tcp_tcb_lock));
|
||||
mutex_init(&(_list_tcb_lock));
|
||||
|
||||
/* Initialize Linked-List for connection storage */
|
||||
_list_gnrc_tcp_tcb_head = NULL;
|
||||
_list_tcb_head = NULL;
|
||||
|
||||
/* Initialize receive buffers */
|
||||
_rcvbuf_init();
|
||||
|
||||
/* Start TCP processing loop */
|
||||
return thread_create(_stack, sizeof(_stack), GNRC_TCP_PRIO, 0, _event_loop, NULL, "gnrc_tcp");
|
||||
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)
|
||||
void gnrc_tcp_tcb_init(gnrc_tcp_tcb_t *tcb)
|
||||
{
|
||||
#ifdef MODULE_GNRC_IPV6
|
||||
tcb->address_family = AF_INET6;
|
||||
|
@ -226,9 +212,9 @@ void gnrc_tcp_tcb_init(gnrc_tcp_tcb_t* tcb)
|
|||
tcb->address_family = AF_UNSPEC;
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_tcb_init() : Address unspec, add netlayer module to makefile\n");
|
||||
#endif
|
||||
tcb->local_port = GNRC_TCP_PORT_UNSPEC;
|
||||
tcb->peer_port = GNRC_TCP_PORT_UNSPEC;
|
||||
tcb->state = GNRC_TCP_FSM_STATE_CLOSED;
|
||||
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;
|
||||
|
@ -241,9 +227,9 @@ void gnrc_tcp_tcb_init(gnrc_tcp_tcb_t* tcb)
|
|||
tcb->irs = 0;
|
||||
tcb->mss = 0;
|
||||
tcb->rtt_start = 0;
|
||||
tcb->rtt_var = GNRC_TCP_RTO_UNINITIALIZED;
|
||||
tcb->srtt = GNRC_TCP_RTO_UNINITIALIZED;
|
||||
tcb->rto = GNRC_TCP_RTO_UNINITIALIZED;
|
||||
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;
|
||||
|
@ -259,7 +245,7 @@ int gnrc_tcp_open_active(gnrc_tcp_tcb_t *tcb, const uint8_t address_family,
|
|||
{
|
||||
assert(tcb != NULL);
|
||||
assert(target_addr != NULL);
|
||||
assert(target_port != GNRC_TCP_PORT_UNSPEC);
|
||||
assert(target_port != PORT_UNSPEC);
|
||||
|
||||
/* Check AF-Family Support from target_addr */
|
||||
switch (address_family) {
|
||||
|
@ -322,15 +308,13 @@ ssize_t gnrc_tcp_send(gnrc_tcp_tcb_t *tcb, const void *data, const size_t len,
|
|||
mutex_lock(&(tcb->function_lock));
|
||||
|
||||
/* Check if connection is in a valid state */
|
||||
if (tcb->state != GNRC_TCP_FSM_STATE_ESTABLISHED
|
||||
&& tcb->state != GNRC_TCP_FSM_STATE_CLOSE_WAIT
|
||||
) {
|
||||
mutex_unlock(&(tcb->function_lock));
|
||||
return -ENOTCONN;
|
||||
if (tcb->state != FSM_STATE_ESTABLISHED && tcb->state != FSM_STATE_CLOSE_WAIT) {
|
||||
mutex_unlock(&(tcb->function_lock));
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
/* Re-init message queue, take ownership. FSM can send Messages to this thread now */
|
||||
msg_init_queue(tcb->msg_queue, GNRC_TCP_MSG_QUEUE_SIZE);
|
||||
msg_init_queue(tcb->msg_queue, GNRC_TCP_TCB_MSG_QUEUE_SIZE);
|
||||
tcb->owner = thread_getpid();
|
||||
|
||||
/* Setup Connection Timeout */
|
||||
|
@ -347,9 +331,9 @@ ssize_t gnrc_tcp_send(gnrc_tcp_tcb_t *tcb, const void *data, const size_t len,
|
|||
/* Loop until something was sent and acked */
|
||||
while (ret == 0 || tcb->pkt_retransmit != NULL) {
|
||||
/* Check if the connections state is closed. If so, a reset was received */
|
||||
if (tcb->state == GNRC_TCP_FSM_STATE_CLOSED) {
|
||||
ret = -ECONNRESET;
|
||||
break;
|
||||
if (tcb->state == FSM_STATE_CLOSED) {
|
||||
ret = -ECONNRESET;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the send window is closed: Setup Probing */
|
||||
|
@ -367,7 +351,7 @@ ssize_t gnrc_tcp_send(gnrc_tcp_tcb_t *tcb, const void *data, const size_t len,
|
|||
|
||||
/* Try to send data in case there nothing has been sent and we are not probing */
|
||||
if (ret == 0 && !probing) {
|
||||
ret = _fsm(tcb, GNRC_TCP_FSM_EVENT_CALL_SEND, NULL, (void *) data, len);
|
||||
ret = _fsm(tcb, FSM_EVENT_CALL_SEND, NULL, (void *) data, len);
|
||||
}
|
||||
|
||||
/* Wait for responses */
|
||||
|
@ -375,20 +359,20 @@ ssize_t gnrc_tcp_send(gnrc_tcp_tcb_t *tcb, const void *data, const size_t len,
|
|||
switch (msg.type) {
|
||||
case MSG_TYPE_CONNECTION_TIMEOUT:
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_send() : CONNECTION_TIMEOUT\n");
|
||||
_fsm(tcb, GNRC_TCP_FSM_EVENT_TIMEOUT_CONNECTION, NULL, NULL, 0);
|
||||
_fsm(tcb, FSM_EVENT_TIMEOUT_CONNECTION, NULL, NULL, 0);
|
||||
ret = -ECONNABORTED;
|
||||
break;
|
||||
|
||||
case MSG_TYPE_USER_SPEC_TIMEOUT:
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_send() : USER_SPEC_TIMEOUT\n");
|
||||
_fsm(tcb, GNRC_TCP_FSM_EVENT_CLEAR_RETRANSMIT, NULL, NULL, 0);
|
||||
_fsm(tcb, FSM_EVENT_CLEAR_RETRANSMIT, NULL, NULL, 0);
|
||||
ret = -ETIMEDOUT;
|
||||
break;
|
||||
|
||||
case MSG_TYPE_PROBE_TIMEOUT:
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_send() : PROBE_TIMEOUT\n");
|
||||
/* Send Probe */
|
||||
_fsm(tcb, GNRC_TCP_FSM_EVENT_SEND_PROBE, NULL, NULL, 0);
|
||||
_fsm(tcb, FSM_EVENT_SEND_PROBE, NULL, NULL, 0);
|
||||
probe_timeout_duration_us += probe_timeout_duration_us;
|
||||
|
||||
/* Boundry check for time interval between probes */
|
||||
|
@ -444,19 +428,16 @@ ssize_t gnrc_tcp_recv(gnrc_tcp_tcb_t *tcb, void *data, const size_t max_len,
|
|||
mutex_lock(&(tcb->function_lock));
|
||||
|
||||
/* Check if connection is in a valid state */
|
||||
if (tcb->state != GNRC_TCP_FSM_STATE_ESTABLISHED
|
||||
&& tcb->state != GNRC_TCP_FSM_STATE_FIN_WAIT_1
|
||||
&& tcb->state != GNRC_TCP_FSM_STATE_FIN_WAIT_2
|
||||
&& tcb->state != GNRC_TCP_FSM_STATE_CLOSE_WAIT
|
||||
) {
|
||||
mutex_unlock(&(tcb->function_lock));
|
||||
return -ENOTCONN;
|
||||
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) {
|
||||
mutex_unlock(&(tcb->function_lock));
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
/* If this call is non-blocking (timeout_duration_us == 0): Try to read data and return */
|
||||
if (timeout_duration_us == 0) {
|
||||
ret = _fsm(tcb, GNRC_TCP_FSM_EVENT_CALL_RECV, NULL, data, max_len);
|
||||
if(ret == 0) {
|
||||
ret = _fsm(tcb, FSM_EVENT_CALL_RECV, NULL, data, max_len);
|
||||
if (ret == 0) {
|
||||
ret = -EAGAIN;
|
||||
}
|
||||
mutex_unlock(&(tcb->function_lock));
|
||||
|
@ -464,7 +445,7 @@ ssize_t gnrc_tcp_recv(gnrc_tcp_tcb_t *tcb, void *data, const size_t max_len,
|
|||
}
|
||||
|
||||
/* If this call is blocking, setup messages and timers */
|
||||
msg_init_queue(tcb->msg_queue, GNRC_TCP_MSG_QUEUE_SIZE);
|
||||
msg_init_queue(tcb->msg_queue, GNRC_TCP_TCB_MSG_QUEUE_SIZE);
|
||||
tcb->owner = thread_getpid();
|
||||
|
||||
/* Setup Connection Timeout */
|
||||
|
@ -479,36 +460,36 @@ ssize_t gnrc_tcp_recv(gnrc_tcp_tcb_t *tcb, void *data, const size_t max_len,
|
|||
/* Processing Loop */
|
||||
while (ret == 0) {
|
||||
/* Check if the connections state is closed. If so, a reset was received */
|
||||
if (tcb->state == GNRC_TCP_FSM_STATE_CLOSED) {
|
||||
ret = -ECONNRESET;
|
||||
break;
|
||||
if (tcb->state == FSM_STATE_CLOSED) {
|
||||
ret = -ECONNRESET;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try to read available data */
|
||||
ret = _fsm(tcb, GNRC_TCP_FSM_EVENT_CALL_RECV, NULL, data, max_len);
|
||||
ret = _fsm(tcb, FSM_EVENT_CALL_RECV, NULL, data, max_len);
|
||||
|
||||
/* If there was no data: Wait for next packet or until the timeout fires */
|
||||
if (ret <= 0) {
|
||||
msg_receive(&msg);
|
||||
switch (msg.type) {
|
||||
case MSG_TYPE_CONNECTION_TIMEOUT:
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_recv() : CONNECTION_TIMEOUT\n");
|
||||
_fsm(tcb, GNRC_TCP_FSM_EVENT_TIMEOUT_CONNECTION, NULL, NULL, 0);
|
||||
ret = -ECONNABORTED;
|
||||
break;
|
||||
case MSG_TYPE_CONNECTION_TIMEOUT:
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_recv() : CONNECTION_TIMEOUT\n");
|
||||
_fsm(tcb, FSM_EVENT_TIMEOUT_CONNECTION, NULL, NULL, 0);
|
||||
ret = -ECONNABORTED;
|
||||
break;
|
||||
|
||||
case MSG_TYPE_USER_SPEC_TIMEOUT:
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_send() : USER_SPEC_TIMEOUT\n");
|
||||
_fsm(tcb, GNRC_TCP_FSM_EVENT_CLEAR_RETRANSMIT, NULL, NULL, 0);
|
||||
ret = -ETIMEDOUT;
|
||||
break;
|
||||
case MSG_TYPE_USER_SPEC_TIMEOUT:
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_send() : USER_SPEC_TIMEOUT\n");
|
||||
_fsm(tcb, FSM_EVENT_CLEAR_RETRANSMIT, NULL, NULL, 0);
|
||||
ret = -ETIMEDOUT;
|
||||
break;
|
||||
|
||||
case MSG_TYPE_NOTIFY_USER:
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_recv() : NOTIFY_USER\n");
|
||||
break;
|
||||
case MSG_TYPE_NOTIFY_USER:
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_recv() : NOTIFY_USER\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_recv() : other message type\n");
|
||||
default:
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_recv() : other message type\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -533,9 +514,9 @@ int gnrc_tcp_close(gnrc_tcp_tcb_t *tcb)
|
|||
mutex_lock(&(tcb->function_lock));
|
||||
|
||||
/* Start connection teardown if the connection was not closed before */
|
||||
if (tcb->state != GNRC_TCP_FSM_STATE_CLOSED) {
|
||||
if (tcb->state != FSM_STATE_CLOSED) {
|
||||
/* Take ownership */
|
||||
msg_init_queue(tcb->msg_queue, GNRC_TCP_MSG_QUEUE_SIZE);
|
||||
msg_init_queue(tcb->msg_queue, GNRC_TCP_TCB_MSG_QUEUE_SIZE);
|
||||
tcb->owner = thread_getpid();
|
||||
|
||||
/* Setup Connection Timeout */
|
||||
|
@ -544,15 +525,15 @@ int gnrc_tcp_close(gnrc_tcp_tcb_t *tcb)
|
|||
&connection_timeout_msg, tcb->owner);
|
||||
|
||||
/* Start connection teardown sequence */
|
||||
_fsm(tcb, GNRC_TCP_FSM_EVENT_CALL_CLOSE, NULL, NULL, 0);
|
||||
_fsm(tcb, FSM_EVENT_CALL_CLOSE, NULL, NULL, 0);
|
||||
|
||||
/* Loop until the connection has been closed */
|
||||
while (tcb->state != GNRC_TCP_FSM_STATE_CLOSED) {
|
||||
while (tcb->state != FSM_STATE_CLOSED) {
|
||||
msg_receive(&msg);
|
||||
switch (msg.type) {
|
||||
case MSG_TYPE_CONNECTION_TIMEOUT:
|
||||
DEBUG("gnrc_tcp.c : gnrc_tcp_close() : CONNECTION_TIMEOUT\n");
|
||||
_fsm(tcb, GNRC_TCP_FSM_EVENT_TIMEOUT_CONNECTION, NULL, NULL, 0);
|
||||
_fsm(tcb, FSM_EVENT_TIMEOUT_CONNECTION, NULL, NULL, 0);
|
||||
break;
|
||||
|
||||
case MSG_TYPE_NOTIFY_USER:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Simon Brummer
|
||||
* Copyright (C) 2015-2017 Simon Brummer
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
|
@ -11,9 +11,9 @@
|
|||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief GNRC's TCP event processing loop
|
||||
* @brief Implementation of internal/eventloop.h
|
||||
*
|
||||
* @author Simon Brummer <brummer.simon@googlemail.com>
|
||||
* @author Simon Brummer <simon.brummer@posteo.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
@ -21,12 +21,9 @@
|
|||
#include <errno.h>
|
||||
#include "net/af.h"
|
||||
#include "net/tcp.h"
|
||||
#include "net/gnrc/pkt.h"
|
||||
#include "net/gnrc/tcp.h"
|
||||
#include "internal/common.h"
|
||||
#include "internal/pkt.h"
|
||||
#include "internal/fsm.h"
|
||||
#include "internal/helper.h"
|
||||
#include "internal/option.h"
|
||||
#include "internal/eventloop.h"
|
||||
|
||||
#ifdef MODULE_GNRC_IPV6
|
||||
|
@ -37,7 +34,7 @@
|
|||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* @brief send function, used to 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
|
||||
*
|
||||
|
@ -67,7 +64,7 @@ static int _send(gnrc_pktsnip_t *pkt)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief recv function, used to call fsm on packet reception
|
||||
* @brief recv function, receive packet from network layer.
|
||||
*
|
||||
* @param[in] pkt incomming paket to process
|
||||
*
|
||||
|
@ -114,9 +111,9 @@ static int _receive(gnrc_pktsnip_t *pkt)
|
|||
/* 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");
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return 0;
|
||||
DEBUG("gnrc_tcp_eventloop.c : _receive() : pkt contains no TCP Header\n");
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Extract control bits, src and dst ports and check if SYN is set (not SYN+ACK) */
|
||||
|
@ -155,21 +152,20 @@ static int _receive(gnrc_pktsnip_t *pkt)
|
|||
}
|
||||
|
||||
/* Find tcb to de-multiplex this packet to */
|
||||
mutex_lock(&_list_gnrc_tcp_tcb_lock);
|
||||
tcb = _list_gnrc_tcp_tcb_head;
|
||||
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 */
|
||||
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 == GNRC_TCP_FSM_STATE_LISTEN) {
|
||||
ipv6_addr_t *tmp_addr = NULL;
|
||||
if (syn && tcb->local_port == dst && tcb->state == FSM_STATE_LISTEN) {
|
||||
/* ... and local addr is unspec or preconfigured */
|
||||
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)
|
||||
) {
|
||||
break;
|
||||
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)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,18 +186,18 @@ static int _receive(gnrc_pktsnip_t *pkt)
|
|||
#endif
|
||||
tcb = tcb->next;
|
||||
}
|
||||
mutex_unlock(&_list_gnrc_tcp_tcb_lock);
|
||||
mutex_unlock(&_list_tcb_lock);
|
||||
|
||||
/* Call FSM with event RCVD_PKT if a fitting connection was found */
|
||||
if (tcb != NULL) {
|
||||
_fsm(tcb, GNRC_TCP_FSM_EVENT_RCVD_PKT, pkt, NULL, 0);
|
||||
_fsm(tcb, FSM_EVENT_RCVD_PKT, pkt, NULL, 0);
|
||||
}
|
||||
/* No fitting connection has been found. Respond with reset */
|
||||
else {
|
||||
DEBUG("gnrc_tcp_eventloop.c : _receive() : Can't find fitting connection\n");
|
||||
if ((ctl & MSK_RST) != MSK_RST) {
|
||||
_pkt_build_reset_from_pkt(&reset, pkt);
|
||||
gnrc_netapi_send(_gnrc_tcp_pid, reset);
|
||||
gnrc_netapi_send(gnrc_tcp_pid, reset);
|
||||
}
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
@ -213,21 +209,21 @@ void *_event_loop(__attribute__((unused)) void *arg)
|
|||
{
|
||||
msg_t msg;
|
||||
msg_t reply;
|
||||
msg_t msg_queue[GNRC_TCP_MSG_QUEUE_SIZE];
|
||||
msg_t msg_queue[TCP_EVENTLOOP_MSG_QUEUE_SIZE];
|
||||
|
||||
/* Store pid */
|
||||
_gnrc_tcp_pid = thread_getpid();
|
||||
gnrc_tcp_pid = thread_getpid();
|
||||
|
||||
/* Setup reply message */
|
||||
reply.type = GNRC_NETAPI_MSG_TYPE_ACK;
|
||||
reply.content.value = (uint32_t)-ENOTSUP;
|
||||
|
||||
/* Init message queue*/
|
||||
msg_init_queue(msg_queue, GNRC_TCP_MSG_QUEUE_SIZE);
|
||||
msg_init_queue(msg_queue, TCP_EVENTLOOP_MSG_QUEUE_SIZE);
|
||||
|
||||
/* Register GNRC_tcp in netreg */
|
||||
gnrc_netreg_entry_t entry;
|
||||
gnrc_netreg_entry_init_pid(&entry, GNRC_NETREG_DEMUX_CTX_ALL, _gnrc_tcp_pid);
|
||||
gnrc_netreg_entry_init_pid(&entry, GNRC_NETREG_DEMUX_CTX_ALL, gnrc_tcp_pid);
|
||||
gnrc_netreg_register(GNRC_NETTYPE_TCP, &entry);
|
||||
|
||||
/* dispatch NETAPI Messages */
|
||||
|
@ -255,14 +251,14 @@ void *_event_loop(__attribute__((unused)) void *arg)
|
|||
/* 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, GNRC_TCP_FSM_EVENT_TIMEOUT_RETRANSMIT,
|
||||
_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 */
|
||||
case MSG_TYPE_TIMEWAIT:
|
||||
DEBUG("gnrc_tcp_eventloop.c : _event_loop() : MSG_TYPE_TIMEWAIT\n");
|
||||
_fsm((gnrc_tcp_tcb_t *)msg.content.ptr, GNRC_TCP_FSM_EVENT_TIMEOUT_TIMEWAIT,
|
||||
_fsm((gnrc_tcp_tcb_t *)msg.content.ptr, FSM_EVENT_TIMEOUT_TIMEWAIT,
|
||||
NULL, NULL, 0);
|
||||
break;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Simon Brummer
|
||||
* Copyright (C) 2015-2017 Simon Brummer
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
|
@ -11,22 +11,19 @@
|
|||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief GNRC's TCP finite state maschine
|
||||
* @brief Implementation of internal/fsm.h
|
||||
*
|
||||
* @author Simon Brummer <brummer.simon@googlemail.com>
|
||||
* @author Simon Brummer <simon.brummer@posteo.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "msg.h"
|
||||
#include "random.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "net/af.h"
|
||||
|
||||
#include "internal/fsm.h"
|
||||
#include "internal/common.h"
|
||||
#include "internal/pkt.h"
|
||||
#include "internal/option.h"
|
||||
#include "internal/helper.h"
|
||||
#include "internal/rcvbuf.h"
|
||||
#include "internal/fsm.h"
|
||||
|
||||
#ifdef MODULE_GNRC_IPV6
|
||||
#include "net/gnrc/ipv6.h"
|
||||
|
@ -48,7 +45,7 @@
|
|||
static int _is_local_port_in_use(const uint16_t portnumber)
|
||||
{
|
||||
gnrc_tcp_tcb_t *iter = NULL;
|
||||
LL_FOREACH(_list_gnrc_tcp_tcb_head, iter) {
|
||||
LL_FOREACH(_list_tcb_head, iter) {
|
||||
if (iter->local_port == portnumber) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -57,7 +54,7 @@ static int _is_local_port_in_use(const uint16_t portnumber)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Generate random, currently 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
|
||||
*/
|
||||
|
@ -76,7 +73,7 @@ static uint16_t _get_random_local_port(void)
|
|||
/**
|
||||
* @brief clears retransmit queue
|
||||
*
|
||||
* @param[in/out] conn TCP Connection, where the retransmit should be cleared
|
||||
* @param[in/out] tcb tcb containing the retransmit queue.
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
|
@ -93,16 +90,16 @@ static int _clear_retransmit(gnrc_tcp_tcb_t *tcb)
|
|||
/**
|
||||
* @brief restarts time wait timer
|
||||
*
|
||||
* @param[in/out] conn TCP Connection, where the timewait_timer should be restarted
|
||||
* @param[in/out] tcb tcb containing the timer structure to use.
|
||||
*
|
||||
* @return Zero on success
|
||||
*/
|
||||
static int _restart_timewait_timer(gnrc_tcp_tcb_t* tcb)
|
||||
static int _restart_timewait_timer(gnrc_tcp_tcb_t *tcb)
|
||||
{
|
||||
xtimer_remove(&tcb->tim_tout);
|
||||
tcb->msg_tout.type = MSG_TYPE_TIMEWAIT;
|
||||
tcb->msg_tout.content.ptr = (void *)tcb;
|
||||
xtimer_set_msg(&tcb->tim_tout, 2 * GNRC_TCP_MSL, &tcb->msg_tout, _gnrc_tcp_pid);
|
||||
xtimer_set_msg(&tcb->tim_tout, 2 * GNRC_TCP_MSL, &tcb->msg_tout, gnrc_tcp_pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -115,49 +112,49 @@ static int _restart_timewait_timer(gnrc_tcp_tcb_t* tcb)
|
|||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
static int _transition_to(gnrc_tcp_tcb_t* tcb, gnrc_tcp_fsm_state_t state, bool *notify_owner)
|
||||
static int _transition_to(gnrc_tcp_tcb_t *tcb, fsm_state_t state, bool *notify_owner)
|
||||
{
|
||||
gnrc_tcp_tcb_t *iter = NULL;
|
||||
uint8_t found = 0;
|
||||
|
||||
switch (state) {
|
||||
case GNRC_TCP_FSM_STATE_CLOSED:
|
||||
case FSM_STATE_CLOSED:
|
||||
/* Free Packets in Retransmit queue */
|
||||
_clear_retransmit(tcb);
|
||||
|
||||
/* Remove from Connection from active connections */
|
||||
mutex_lock(&_list_gnrc_tcp_tcb_lock);
|
||||
LL_FOREACH(_list_gnrc_tcp_tcb_head, iter) {
|
||||
mutex_lock(&_list_tcb_lock);
|
||||
LL_FOREACH(_list_tcb_head, iter) {
|
||||
if (iter == tcb) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
LL_DELETE(_list_gnrc_tcp_tcb_head, iter);
|
||||
LL_DELETE(_list_tcb_head, iter);
|
||||
}
|
||||
mutex_unlock(&_list_gnrc_tcp_tcb_lock);
|
||||
mutex_unlock(&_list_tcb_lock);
|
||||
|
||||
/* Free potencially allocated Receive Buffer */
|
||||
_rcvbuf_release_buffer(tcb);
|
||||
*notify_owner = true;
|
||||
break;
|
||||
|
||||
case GNRC_TCP_FSM_STATE_LISTEN:
|
||||
case FSM_STATE_LISTEN:
|
||||
/* Clear Adress Info */
|
||||
switch (tcb->address_family) {
|
||||
#ifdef MODULE_GNRC_IPV6
|
||||
case AF_INET6:
|
||||
if (tcb->status & GNRC_TCP_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;
|
||||
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;
|
||||
default:
|
||||
DEBUG("gnrc_tcp_fsm.c : _transition_to() : Undefined Addresses\n");
|
||||
break;
|
||||
}
|
||||
tcb->peer_port = GNRC_TCP_PORT_UNSPEC;
|
||||
tcb->peer_port = PORT_UNSPEC;
|
||||
|
||||
/* Allocate rcv Buffer */
|
||||
if (_rcvbuf_get_buffer(tcb) == -ENOMEM) {
|
||||
|
@ -165,27 +162,27 @@ static int _transition_to(gnrc_tcp_tcb_t* tcb, gnrc_tcp_fsm_state_t state, bool
|
|||
}
|
||||
|
||||
/* Add to Connection to active connections (if not already active) */
|
||||
mutex_lock(&_list_gnrc_tcp_tcb_lock);
|
||||
LL_FOREACH(_list_gnrc_tcp_tcb_head, iter) {
|
||||
mutex_lock(&_list_tcb_lock);
|
||||
LL_FOREACH(_list_tcb_head, iter) {
|
||||
if (iter == tcb) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
LL_APPEND(_list_gnrc_tcp_tcb_head, tcb);
|
||||
LL_APPEND(_list_tcb_head, tcb);
|
||||
}
|
||||
mutex_unlock(&_list_gnrc_tcp_tcb_lock);
|
||||
mutex_unlock(&_list_tcb_lock);
|
||||
break;
|
||||
|
||||
case GNRC_TCP_FSM_STATE_SYN_SENT:
|
||||
case FSM_STATE_SYN_SENT:
|
||||
/* Allocate rcv Buffer */
|
||||
if (_rcvbuf_get_buffer(tcb) == -ENOMEM) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Add to Connections to active connection (if not already active) */
|
||||
mutex_lock(&_list_gnrc_tcp_tcb_lock);
|
||||
LL_FOREACH(_list_gnrc_tcp_tcb_head, iter) {
|
||||
mutex_lock(&_list_tcb_lock);
|
||||
LL_FOREACH(_list_tcb_head, iter) {
|
||||
if (iter == tcb) {
|
||||
found = 1;
|
||||
}
|
||||
|
@ -193,11 +190,11 @@ static int _transition_to(gnrc_tcp_tcb_t* tcb, gnrc_tcp_fsm_state_t state, bool
|
|||
/* If not already active: Apped tcb but check portnumber first */
|
||||
if (!found) {
|
||||
/* Check if Port Number is not in use */
|
||||
if (tcb->local_port != GNRC_TCP_PORT_UNSPEC ) {
|
||||
if (tcb->local_port != PORT_UNSPEC) {
|
||||
|
||||
/* If Portnumber is used: return error and release buffer */
|
||||
if (_is_local_port_in_use(tcb->local_port)) {
|
||||
mutex_unlock(&_list_gnrc_tcp_tcb_lock);
|
||||
mutex_unlock(&_list_tcb_lock);
|
||||
_rcvbuf_release_buffer(tcb);
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
|
@ -206,20 +203,20 @@ static int _transition_to(gnrc_tcp_tcb_t* tcb, gnrc_tcp_fsm_state_t state, bool
|
|||
else {
|
||||
tcb->local_port = _get_random_local_port();
|
||||
}
|
||||
LL_APPEND(_list_gnrc_tcp_tcb_head, tcb);
|
||||
LL_APPEND(_list_tcb_head, tcb);
|
||||
}
|
||||
mutex_unlock(&_list_gnrc_tcp_tcb_lock);
|
||||
mutex_unlock(&_list_tcb_lock);
|
||||
break;
|
||||
|
||||
case GNRC_TCP_FSM_STATE_ESTABLISHED:
|
||||
case FSM_STATE_ESTABLISHED:
|
||||
*notify_owner = true;
|
||||
break;
|
||||
|
||||
case GNRC_TCP_FSM_STATE_CLOSE_WAIT:
|
||||
case FSM_STATE_CLOSE_WAIT:
|
||||
*notify_owner = true;
|
||||
break;
|
||||
|
||||
case GNRC_TCP_FSM_STATE_TIME_WAIT:
|
||||
case FSM_STATE_TIME_WAIT:
|
||||
_restart_timewait_timer(tcb);
|
||||
break;
|
||||
|
||||
|
@ -240,7 +237,7 @@ static int _transition_to(gnrc_tcp_tcb_t* tcb, gnrc_tcp_fsm_state_t state, bool
|
|||
* @return -ENOMEM Can't allocate receive buffer.
|
||||
* @return -EADDRINUSE Given local port 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, bool *notify_owner)
|
||||
{
|
||||
gnrc_pktsnip_t *out_pkt = NULL; /* Outgoing packet */
|
||||
uint16_t seq_con = 0; /* Sequence number consumption (out_pkt) */
|
||||
|
@ -249,10 +246,10 @@ static int _fsm_call_open(gnrc_tcp_tcb_t* tcb, bool *notify_owner)
|
|||
DEBUG("gnrc_tcp_fsm.c : _fsm_call_open()\n");
|
||||
tcb->rcv_wnd = GNRC_TCP_DEFAULT_WINDOW;
|
||||
|
||||
if (tcb->status & GNRC_TCP_STATUS_PASSIVE) {
|
||||
if (tcb->status & STATUS_PASSIVE) {
|
||||
/* Passive Open, T: CLOSED -> LISTEN */
|
||||
if (_transition_to(tcb, GNRC_TCP_FSM_STATE_LISTEN, notify_owner) == -ENOMEM){
|
||||
_transition_to(tcb, GNRC_TCP_FSM_STATE_CLOSED, notify_owner);
|
||||
if (_transition_to(tcb, FSM_STATE_LISTEN, notify_owner) == -ENOMEM) {
|
||||
_transition_to(tcb, FSM_STATE_CLOSED, notify_owner);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
@ -263,9 +260,9 @@ static int _fsm_call_open(gnrc_tcp_tcb_t* tcb, bool *notify_owner)
|
|||
tcb->snd_una = tcb->iss;
|
||||
|
||||
/* Translate to SYN_SENT */
|
||||
ret = _transition_to(tcb, GNRC_TCP_FSM_STATE_SYN_SENT, notify_owner);
|
||||
if ( ret < 0) {
|
||||
_transition_to(tcb, GNRC_TCP_FSM_STATE_CLOSED, notify_owner);
|
||||
ret = _transition_to(tcb, FSM_STATE_SYN_SENT, notify_owner);
|
||||
if (ret < 0) {
|
||||
_transition_to(tcb, FSM_STATE_CLOSED, notify_owner);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -280,13 +277,13 @@ static int _fsm_call_open(gnrc_tcp_tcb_t* tcb, bool *notify_owner)
|
|||
/**
|
||||
* @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] nByte Maximum Number of Bytes to send.
|
||||
* @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.
|
||||
*
|
||||
* @return number of bytes that was sent.
|
||||
*/
|
||||
static int _fsm_call_send(gnrc_tcp_tcb_t* tcb, void *buf, size_t nByte)
|
||||
static int _fsm_call_send(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) */
|
||||
|
@ -297,9 +294,9 @@ static int _fsm_call_send(gnrc_tcp_tcb_t* tcb, void *buf, size_t nByte)
|
|||
/* We are allowed to send further bytes if window is open */
|
||||
if (payload > 0 && tcb->snd_wnd > 0 && tcb->pkt_retransmit == NULL) {
|
||||
/* Calculate segment size */
|
||||
payload = (payload < GNRC_TCP_MSS ? payload : GNRC_TCP_MSS);
|
||||
payload = (payload < GNRC_TCP_MSS) ? payload : GNRC_TCP_MSS;
|
||||
payload = (payload < tcb->mss) ? payload : tcb->mss;
|
||||
payload = (payload < nByte) ? payload : nByte;
|
||||
payload = (payload < len) ? payload : len;
|
||||
|
||||
/* Calculate payload size for this segment */
|
||||
_pkt_build(tcb, &out_pkt, &seq_con, MSK_ACK, tcb->snd_nxt, tcb->rcv_nxt, buf, payload);
|
||||
|
@ -313,13 +310,13 @@ static int _fsm_call_send(gnrc_tcp_tcb_t* tcb, void *buf, size_t nByte)
|
|||
/**
|
||||
* @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] nByte Maximum Number of Bytes to receive.
|
||||
* @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.
|
||||
*
|
||||
* @return number of bytes that was received.
|
||||
*/
|
||||