1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #6541 from brummer-simon/gnrc_tcp-cleanup

gnrc_tcp: cleanup
This commit is contained in:
Sebastian Meiling 2017-03-01 09:34:49 +01:00 committed by GitHub
commit f6022a283d
20 changed files with 648 additions and 744 deletions

View File

@ -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 */
/** @} */

View File

@ -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 */
/** @} */

View File

@ -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_ */
/** @} */

View File

@ -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 */
/** @} */

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -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.
*/
static int _fsm_call_recv(gnrc_tcp_tcb_t* tcb, void *buf, size_t nByte)
static int _fsm_call_recv(gnrc_tcp_tcb_t *tcb, void *buf, size_t len)
{
gnrc_pktsnip_t *out_pkt = NULL; /* Outgoing packet */
uint16_t seq_con = 0; /* Sequence number consumption (out_pkt) */
@ -330,14 +327,14 @@ static int _fsm_call_recv(gnrc_tcp_tcb_t* tcb, void *buf, size_t nByte)
}
/* Read up to the requesed amount of data */
size_t rcvd = ringbuffer_get(&(tcb->rcv_buf), buf, nByte);
size_t rcvd = ringbuffer_get(&(tcb->rcv_buf), buf, len);
/* If the buffer can store more than the GNRC_TCP_MSS: open Window to available buffersize */
if (ringbuffer_get_free(&tcb->rcv_buf) >= GNRC_TCP_MSS) {
tcb->rcv_wnd = ringbuffer_get_free(&(tcb->rcv_buf));
/* Send ACK to update window on reopening */
_pkt_build(tcb, &out_pkt, &seq_con, MSK_ACK, tcb->snd_nxt, tcb->rcv_nxt, 0, 0);
_pkt_build(tcb, &out_pkt, &seq_con, MSK_ACK, tcb->snd_nxt, tcb->rcv_nxt, NULL, 0);
_pkt_send(tcb, out_pkt, seq_con, false);
}
return rcvd;
@ -351,33 +348,31 @@ static int _fsm_call_recv(gnrc_tcp_tcb_t* tcb, void *buf, size_t nByte)
*
* @return zero on success.
*/
static int _fsm_call_close(gnrc_tcp_tcb_t* tcb, bool *notify_owner)
static int _fsm_call_close(gnrc_tcp_tcb_t *tcb, bool *notify_owner)
{
gnrc_pktsnip_t *out_pkt = NULL; /* Outgoing packet */
uint16_t seq_con = 0; /* Sequence number consumption (out_pkt) */
DEBUG("gnrc_tcp_fsm.c : _fsm_call_close()\n");
if (tcb->state == GNRC_TCP_FSM_STATE_SYN_RCVD
|| tcb->state == GNRC_TCP_FSM_STATE_ESTABLISHED
|| tcb->state == GNRC_TCP_FSM_STATE_CLOSE_WAIT
) {
if (tcb->state == FSM_STATE_SYN_RCVD || tcb->state == FSM_STATE_ESTABLISHED ||
tcb->state == FSM_STATE_CLOSE_WAIT) {
/* Send FIN packet */
_pkt_build(tcb, &out_pkt, &seq_con, MSK_FIN_ACK, tcb->snd_nxt, tcb->rcv_nxt, NULL, 0);
_pkt_setup_retransmit(tcb, out_pkt, false);
_pkt_send(tcb, out_pkt, seq_con, false);
}
switch (tcb->state) {
case GNRC_TCP_FSM_STATE_LISTEN:
_transition_to(tcb, GNRC_TCP_FSM_STATE_CLOSED, notify_owner);
case FSM_STATE_LISTEN:
_transition_to(tcb, FSM_STATE_CLOSED, notify_owner);
break;
case GNRC_TCP_FSM_STATE_SYN_RCVD:
case GNRC_TCP_FSM_STATE_ESTABLISHED:
_transition_to(tcb, GNRC_TCP_FSM_STATE_FIN_WAIT_1, notify_owner);
case FSM_STATE_SYN_RCVD:
case FSM_STATE_ESTABLISHED:
_transition_to(tcb, FSM_STATE_FIN_WAIT_1, notify_owner);
break;
case GNRC_TCP_FSM_STATE_CLOSE_WAIT:
_transition_to(tcb, GNRC_TCP_FSM_STATE_LAST_ACK, notify_owner);
case FSM_STATE_CLOSE_WAIT:
_transition_to(tcb, FSM_STATE_LAST_ACK, notify_owner);
break;
default:
@ -408,7 +403,7 @@ static int _fsm_call_abort(void)
* @return zero on success.
* @return -ENOMEM Can't allocate receive buffer.
*/
static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *notify_owner)
static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt, bool *notify_owner)
{
gnrc_pktsnip_t *out_pkt = NULL; /* Outgoing packet */
uint16_t seq_con = 0; /* Sequence number consumption (out_pkt) */
@ -448,7 +443,7 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
#endif
/* Handle state LISTEN */
if (tcb->state == GNRC_TCP_FSM_STATE_LISTEN) {
if (tcb->state == FSM_STATE_LISTEN) {
/* 1) Check RST: if set, return */
if (ctl & MSK_RST) {
return 0;
@ -465,7 +460,7 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
uint16_t dst = byteorder_ntohs(tcp_hdr->dst_port);
/* Check if SYN Request is handled by another connection */
lst = _list_gnrc_tcp_tcb_head;
lst = _list_tcb_head;
while (lst) {
/* Compare Portnumbers and Network Layer Adresses */
/* Note: Packets without ip-header were discarded earlier */
@ -475,9 +470,8 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
ipv6_addr_t *dst_addr = &((ipv6_hdr_t *)ip)->dst;
ipv6_addr_t *src_addr = &((ipv6_hdr_t *)ip)->src;
if (ipv6_addr_equal((ipv6_addr_t *)lst->local_addr, dst_addr)
&& ipv6_addr_equal((ipv6_addr_t *)lst->peer_addr, src_addr)
) {
if (ipv6_addr_equal((ipv6_addr_t *)lst->local_addr, dst_addr) &&
ipv6_addr_equal((ipv6_addr_t *)lst->peer_addr, src_addr)) {
break;
}
}
@ -516,12 +510,12 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
_pkt_build(tcb, &out_pkt, &seq_con, MSK_SYN_ACK, tcb->iss, tcb->rcv_nxt, NULL, 0);
_pkt_setup_retransmit(tcb, out_pkt, false);
_pkt_send(tcb, out_pkt, seq_con, false);
_transition_to(tcb, GNRC_TCP_FSM_STATE_SYN_RCVD, notify_owner);
_transition_to(tcb, FSM_STATE_SYN_RCVD, notify_owner);
}
return 0;
}
/* Handle state SYN_SENT */
else if (tcb->state == GNRC_TCP_FSM_STATE_SYN_SENT) {
else if (tcb->state == FSM_STATE_SYN_SENT) {
/* 1) Check ACK */
if (ctl & MSK_ACK) {
/* If ACK is not acceptable ...*/
@ -538,7 +532,7 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
if (ctl & MSK_RST) {
/* ... and ACK: Translate to CLOSED, if not return */
if (ctl & MSK_ACK) {
_transition_to(tcb, GNRC_TCP_FSM_STATE_CLOSED, notify_owner);
_transition_to(tcb, FSM_STATE_CLOSED, notify_owner);
}
return 0;
}
@ -563,18 +557,16 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
/* SYN has been ACKed, reply pure ACK, T: SYN_SENT -> ESTABLISHED */
if (tcb->snd_una > tcb->iss) {
_pkt_build(tcb, &out_pkt, &seq_con, MSK_ACK, tcb->snd_nxt, tcb->rcv_nxt,
NULL, 0);
_pkt_build(tcb, &out_pkt, &seq_con, MSK_ACK, tcb->snd_nxt, tcb->rcv_nxt, NULL, 0);
_pkt_send(tcb, out_pkt, seq_con, false);
_transition_to(tcb, GNRC_TCP_FSM_STATE_ESTABLISHED, notify_owner);
_transition_to(tcb, FSM_STATE_ESTABLISHED, notify_owner);
}
/* Simultaneous SYN received send SYN+ACK, T: SYN_SENT -> SYN_RCVD */
else {
_pkt_build(tcb, &out_pkt, &seq_con, MSK_SYN_ACK, tcb->iss, tcb->rcv_nxt,
NULL, 0);
_pkt_build(tcb, &out_pkt, &seq_con, MSK_SYN_ACK, tcb->iss, tcb->rcv_nxt, NULL, 0);
_pkt_setup_retransmit(tcb, out_pkt, false);
_pkt_send(tcb, out_pkt, seq_con, false);
_transition_to(tcb, GNRC_TCP_FSM_STATE_SYN_RCVD, notify_owner);
_transition_to(tcb, FSM_STATE_SYN_RCVD, notify_owner);
}
tcb->snd_wnd = seg_wnd;
tcb->snd_wl1 = seg_seq;
@ -590,8 +582,7 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
if (!_pkt_chk_seq_num(tcb, seg_seq, pay_len)) {
/* ... if invalid, and RST not set, reply with pure ACK, return */
if ((ctl & MSK_RST) != MSK_RST) {
_pkt_build(tcb, &out_pkt, &seq_con, MSK_ACK, tcb->snd_nxt, tcb->rcv_nxt,
NULL, 0);
_pkt_build(tcb, &out_pkt, &seq_con, MSK_ACK, tcb->snd_nxt, tcb->rcv_nxt, NULL, 0);
_pkt_send(tcb, out_pkt, seq_con, false);
}
return 0;
@ -599,16 +590,14 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
/* 2) Check RST: If RST is set ... */
if (ctl & MSK_RST) {
/* .. and State is SYN_RCVD and passive Open: SYN_RCVD -> LISTEN */
if (tcb->state == GNRC_TCP_FSM_STATE_SYN_RCVD
&& (tcb->status & GNRC_TCP_STATUS_PASSIVE)
) {
if (_transition_to(tcb, GNRC_TCP_FSM_STATE_LISTEN, notify_owner) == -ENOMEM) {
_transition_to(tcb, GNRC_TCP_FSM_STATE_CLOSED, notify_owner);
if (tcb->state == FSM_STATE_SYN_RCVD && (tcb->status & STATUS_PASSIVE)) {
if (_transition_to(tcb, FSM_STATE_LISTEN, notify_owner) == -ENOMEM) {
_transition_to(tcb, FSM_STATE_CLOSED, notify_owner);
return -ENOMEM;
}
}
else {
_transition_to(tcb, GNRC_TCP_FSM_STATE_CLOSED, notify_owner);
_transition_to(tcb, FSM_STATE_CLOSED, notify_owner);
}
return 0;
}
@ -617,7 +606,7 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
/* ... send RST, seq_no = snd_nxt, ack_no = rcv_nxt */
_pkt_build(tcb, &out_pkt, &seq_con, MSK_RST, tcb->snd_nxt, tcb->rcv_nxt, NULL, 0);
_pkt_send(tcb, out_pkt, seq_con, false);
_transition_to(tcb, GNRC_TCP_FSM_STATE_CLOSED, notify_owner);
_transition_to(tcb, FSM_STATE_CLOSED, notify_owner);
return 0;
}
/* 4) Check ACK */
@ -625,12 +614,12 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
return 0;
}
else {
if (tcb->state == GNRC_TCP_FSM_STATE_SYN_RCVD) {
if (tcb->state == FSM_STATE_SYN_RCVD) {
if (LSS_32_BIT(tcb->snd_una, seg_ack) && LEQ_32_BIT(seg_ack, tcb->snd_nxt)) {
tcb->snd_wnd = seg_wnd;
tcb->snd_wl1 = seg_seq;
tcb->snd_wl2 = seg_ack;
_transition_to(tcb, GNRC_TCP_FSM_STATE_ESTABLISHED, notify_owner);
_transition_to(tcb, FSM_STATE_ESTABLISHED, notify_owner);
}
else {
_pkt_build(tcb, &out_pkt, &seq_con, MSK_RST, seg_ack, 0, NULL, 0);
@ -638,13 +627,9 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
}
}
/* Acknowledgment processing */
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
|| tcb->state == GNRC_TCP_FSM_STATE_CLOSING
|| tcb->state == GNRC_TCP_FSM_STATE_LAST_ACK
) {
if (tcb->state == FSM_STATE_ESTABLISHED || tcb->state == FSM_STATE_FIN_WAIT_1 ||
tcb->state == FSM_STATE_FIN_WAIT_2 || tcb->state == FSM_STATE_CLOSE_WAIT ||
tcb->state == FSM_STATE_CLOSING || tcb->state == FSM_STATE_LAST_ACK) {
/* Sent data has been acknowledged */
if (LSS_32_BIT(tcb->snd_una, seg_ack) && LEQ_32_BIT(seg_ack, tcb->snd_nxt)) {
tcb->snd_una = seg_ack;
@ -659,9 +644,8 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
}
/* Update Window */
if (LEQ_32_BIT(tcb->snd_una, seg_ack) && LEQ_32_BIT(seg_ack, tcb->snd_nxt)) {
if (LSS_32_BIT(tcb->snd_wl1, seg_seq) || (tcb->snd_wl1 == seg_seq
&& LEQ_32_BIT(tcb->snd_wl2, seg_ack))
) {
if (LSS_32_BIT(tcb->snd_wl1, seg_seq) || (tcb->snd_wl1 == seg_seq &&
LEQ_32_BIT(tcb->snd_wl2, seg_ack))) {
tcb->snd_wnd = seg_wnd;
tcb->snd_wl1 = seg_seq;
tcb->snd_wl2 = seg_ack;
@ -672,27 +656,27 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
}
/* Additional processing */
/* Check additionaly if previous our sent FIN has been acknowledged */
if (tcb->state == GNRC_TCP_FSM_STATE_FIN_WAIT_1) {
if (tcb->state == FSM_STATE_FIN_WAIT_1) {
if (tcb->pkt_retransmit == NULL) {
_transition_to(tcb, GNRC_TCP_FSM_STATE_FIN_WAIT_2, notify_owner);
_transition_to(tcb, FSM_STATE_FIN_WAIT_2, notify_owner);
}
}
/* If retransmission queue is empty, acknowledge close operation */
if (tcb->state == GNRC_TCP_FSM_STATE_FIN_WAIT_2) {
if (tcb->state == FSM_STATE_FIN_WAIT_2) {
if (tcb->pkt_retransmit == NULL) {
/* Optional: Unblock user close operation */
}
}
/* If our FIN has been acknowledged: Translate to TIME_WAIT */
if (tcb->state == GNRC_TCP_FSM_STATE_CLOSING) {
if (tcb->state == FSM_STATE_CLOSING) {
if (tcb->pkt_retransmit == NULL) {
_transition_to(tcb, GNRC_TCP_FSM_STATE_TIME_WAIT, notify_owner);
_transition_to(tcb, FSM_STATE_TIME_WAIT, notify_owner);
}
}
/* If our FIN has been acknowledged: last ACK received, close connection */
if (tcb->state == GNRC_TCP_FSM_STATE_LAST_ACK) {
if (tcb->state == FSM_STATE_LAST_ACK) {
if (tcb->pkt_retransmit == NULL) {
_transition_to(tcb, GNRC_TCP_FSM_STATE_CLOSED, notify_owner);
_transition_to(tcb, FSM_STATE_CLOSED, notify_owner);
return 0;
}
}
@ -703,10 +687,8 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
/* 6) Process Payload, if existing */
if (pay_len > 0) {
/* Check if State is valid */
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
) {
if (tcb->state == FSM_STATE_ESTABLISHED || tcb->state == FSM_STATE_FIN_WAIT_1 ||
tcb->state == FSM_STATE_FIN_WAIT_2) {
/* Search for begin of payload "chain" */
LL_SEARCH_SCALAR(in_pkt, snp, type, GNRC_NETTYPE_UNDEF);
@ -733,10 +715,8 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
}
/* 7) Check FIN */
if (ctl & MSK_FIN) {
if (tcb->state == GNRC_TCP_FSM_STATE_CLOSED
|| tcb->state == GNRC_TCP_FSM_STATE_LISTEN
|| tcb->state == GNRC_TCP_FSM_STATE_SYN_SENT
) {
if (tcb->state == FSM_STATE_CLOSED || tcb->state == FSM_STATE_LISTEN ||
tcb->state == FSM_STATE_SYN_SENT) {
return 0;
}
/* Advance rcv_nxt over FIN bit. */
@ -744,23 +724,21 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
_pkt_build(tcb, &out_pkt, &seq_con, MSK_ACK, tcb->snd_nxt, tcb->rcv_nxt, NULL, 0);
_pkt_send(tcb, out_pkt, seq_con, false);
if (tcb->state == GNRC_TCP_FSM_STATE_SYN_RCVD
|| tcb->state == GNRC_TCP_FSM_STATE_ESTABLISHED
) {
_transition_to(tcb, GNRC_TCP_FSM_STATE_CLOSE_WAIT, notify_owner);
if (tcb->state == FSM_STATE_SYN_RCVD || tcb->state == FSM_STATE_ESTABLISHED) {
_transition_to(tcb, FSM_STATE_CLOSE_WAIT, notify_owner);
}
else if (tcb->state == GNRC_TCP_FSM_STATE_FIN_WAIT_1) {
else if (tcb->state == FSM_STATE_FIN_WAIT_1) {
if (tcb->pkt_retransmit == NULL) {
_transition_to(tcb, GNRC_TCP_FSM_STATE_TIME_WAIT, notify_owner);
_transition_to(tcb, FSM_STATE_TIME_WAIT, notify_owner);
}
else {
_transition_to(tcb, GNRC_TCP_FSM_STATE_CLOSING, notify_owner);
_transition_to(tcb, FSM_STATE_CLOSING, notify_owner);
}
}
else if (tcb->state == GNRC_TCP_FSM_STATE_FIN_WAIT_2) {
_transition_to(tcb, GNRC_TCP_FSM_STATE_TIME_WAIT, notify_owner);
else if (tcb->state == FSM_STATE_FIN_WAIT_2) {
_transition_to(tcb, FSM_STATE_TIME_WAIT, notify_owner);
}
else if (tcb->state == GNRC_TCP_FSM_STATE_TIME_WAIT) {
else if (tcb->state == FSM_STATE_TIME_WAIT) {
_restart_timewait_timer(tcb);
}
}
@ -776,10 +754,10 @@ static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *in_pkt, bool *noti
*
* @return zero on success.
*/
static int _fsm_timeout_timewait(gnrc_tcp_tcb_t* tcb, bool *notify_owner)
static int _fsm_timeout_timewait(gnrc_tcp_tcb_t *tcb, bool *notify_owner)
{
DEBUG("gnrc_tcp_fsm.c : _fsm_timeout_timewait()\n");
_transition_to(tcb, GNRC_TCP_FSM_STATE_CLOSED, notify_owner);
_transition_to(tcb, FSM_STATE_CLOSED, notify_owner);
return 0;
}
@ -790,10 +768,10 @@ static int _fsm_timeout_timewait(gnrc_tcp_tcb_t* tcb, bool *notify_owner)
*
* @return zero on success.
*/
static int _fsm_timeout_retransmit(gnrc_tcp_tcb_t* tcb)
static int _fsm_timeout_retransmit(gnrc_tcp_tcb_t *tcb)
{
DEBUG("gnrc_tcp_fsm.c : _fsm_timeout_retransmit()\n");
if(tcb->pkt_retransmit != NULL){
if (tcb->pkt_retransmit != NULL) {
_pkt_setup_retransmit(tcb, tcb->pkt_retransmit, true);
_pkt_send(tcb, tcb->pkt_retransmit, 0, true);
}
@ -811,24 +789,24 @@ static int _fsm_timeout_retransmit(gnrc_tcp_tcb_t* tcb)
*
* @return zero on success.
*/
static int _fsm_timeout_connection(gnrc_tcp_tcb_t* tcb, bool *notify_owner)
static int _fsm_timeout_connection(gnrc_tcp_tcb_t *tcb, bool *notify_owner)
{
DEBUG("gnrc_tcp_fsm.c : _fsm_timeout_connection()\n");
_transition_to(tcb, GNRC_TCP_FSM_STATE_CLOSED, notify_owner);
_transition_to(tcb, FSM_STATE_CLOSED, notify_owner);
return 0;
}
/**
* @brief FSM Handling Function for probe sending
*
* @param[in/out] tcb Specifies tcb to use fsm on.
* @param[in/out] tcb tcb of this connection
*
* @return zero on success.
*/
static int _fsm_send_probe(gnrc_tcp_tcb_t* tcb)
static int _fsm_send_probe(gnrc_tcp_tcb_t *tcb)
{
gnrc_pktsnip_t *out_pkt = NULL; /* Outgoing packet */
uint8_t probe_pay[] = { 1 }; /* Probe Payload */
uint8_t probe_pay[] = {1}; /* Probe Payload */
DEBUG("gnrc_tcp_fsm.c : _fsm_send_probe()\n");
/* The Probe sends a already acknowledged Sequence No. with a garbage byte */
@ -841,11 +819,11 @@ static int _fsm_send_probe(gnrc_tcp_tcb_t* tcb)
/**
* @brief FSM Handling Function for clearing the retransmit queue.
*
* @param[in/out] tcb Specifies tcb to use fsm on.
* @param[in/out] tcb tcb of this connection.
*
* @return zero on success.
*/
static int _fsm_clear_retransmit(gnrc_tcp_tcb_t* tcb)
static int _fsm_clear_retransmit(gnrc_tcp_tcb_t *tcb)
{
DEBUG("gnrc_tcp_fsm.c : _fsm_clear_retransmit()\n");
_clear_retransmit(tcb);
@ -859,60 +837,59 @@ static int _fsm_clear_retransmit(gnrc_tcp_tcb_t* tcb)
* @param[in] event current event that triggers fsm translation
* @param[in] in_pkt packet that triggered fsm event. Only in case of RCVD_PKT
* @param[in/out] buf buffer for send and receive functions
* @param[in] nByte number of bytes to send or receive atmost
* @param[in] len number of bytes to send or receive atmost
* @param[out] notify_owner non-negative if the tcb owner should be notified
*
* @return TODO zero on success
* @return Zero on success
* @return -ENOMEM Can't allocate receive buffer.
* @return -EADDRINUSE Given local port is already in use
* @return -EOPNOTSUPP If event is not implemented
*/
static int _fsm_unprotected(gnrc_tcp_tcb_t* tcb, gnrc_tcp_fsm_event_t event,
gnrc_pktsnip_t *in_pkt, void *buf, size_t nByte, bool *notify_owner)
static int _fsm_unprotected(gnrc_tcp_tcb_t *tcb, fsm_event_t event, gnrc_pktsnip_t *in_pkt,
void *buf, size_t len, bool *notify_owner)
{
int ret = 0; /* Return Value */
int ret = 0;
DEBUG("gnrc_tcp_fsm.c : _fsm_unprotected()\n");
switch (event) {
case GNRC_TCP_FSM_EVENT_CALL_OPEN :
case FSM_EVENT_CALL_OPEN :
ret = _fsm_call_open(tcb, notify_owner);
break;
case GNRC_TCP_FSM_EVENT_CALL_SEND :
ret = _fsm_call_send(tcb, buf, nByte);
case FSM_EVENT_CALL_SEND :
ret = _fsm_call_send(tcb, buf, len);
break;
case GNRC_TCP_FSM_EVENT_CALL_RECV :
ret = _fsm_call_recv(tcb, buf, nByte);
case FSM_EVENT_CALL_RECV :
ret = _fsm_call_recv(tcb, buf, len);
break;
case GNRC_TCP_FSM_EVENT_CALL_CLOSE :
case FSM_EVENT_CALL_CLOSE :
ret = _fsm_call_close(tcb, notify_owner);
break;
case GNRC_TCP_FSM_EVENT_CALL_ABORT :
case FSM_EVENT_CALL_ABORT :
ret = _fsm_call_abort();
break;
case GNRC_TCP_FSM_EVENT_RCVD_PKT :
case FSM_EVENT_RCVD_PKT :
ret = _fsm_rcvd_pkt(tcb, in_pkt, notify_owner);
break;
case GNRC_TCP_FSM_EVENT_TIMEOUT_TIMEWAIT :
case FSM_EVENT_TIMEOUT_TIMEWAIT :
ret = _fsm_timeout_timewait(tcb, notify_owner);
break;
case GNRC_TCP_FSM_EVENT_TIMEOUT_RETRANSMIT :
case FSM_EVENT_TIMEOUT_RETRANSMIT :
ret = _fsm_timeout_retransmit(tcb);
break;
case GNRC_TCP_FSM_EVENT_TIMEOUT_CONNECTION :
case FSM_EVENT_TIMEOUT_CONNECTION :
ret = _fsm_timeout_connection(tcb, notify_owner);
break;
case GNRC_TCP_FSM_EVENT_SEND_PROBE :
case FSM_EVENT_SEND_PROBE :
ret = _fsm_send_probe(tcb);
break;
case GNRC_TCP_FSM_EVENT_CLEAR_RETRANSMIT :
case FSM_EVENT_CLEAR_RETRANSMIT :
ret = _fsm_clear_retransmit(tcb);
break;
}
return ret;
}
int _fsm(gnrc_tcp_tcb_t* tcb, gnrc_tcp_fsm_event_t event, gnrc_pktsnip_t *in_pkt, void *buf,
size_t nByte)
int _fsm(gnrc_tcp_tcb_t *tcb, fsm_event_t event, gnrc_pktsnip_t *in_pkt, void *buf, size_t len)
{
msg_t msg;
int32_t result;
@ -921,7 +898,7 @@ int _fsm(gnrc_tcp_tcb_t* tcb, gnrc_tcp_fsm_event_t event, gnrc_pktsnip_t *in_pkt
/* Lock FSM */
mutex_lock(&(tcb->fsm_lock));
notify_owner = false;
result = _fsm_unprotected(tcb, event, in_pkt, buf, nByte, &notify_owner);
result = _fsm_unprotected(tcb, event, in_pkt, buf, len, &notify_owner);
/* Notify owner if something interesting happend */
if (notify_owner && tcb->owner != KERNEL_PID_UNDEF) {

View File

@ -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,29 +11,18 @@
* @{
*
* @file
* @brief GNRC's TCP option handling related functions
* @brief Implementation of internal/option.h
*
* @author Simon Brummer <brummer.simon@googlemail.com>
* @author Simon Brummer <simon.brummer@posteo.de>
* @}
*/
#include "assert.h"
#include "internal/common.h"
#include "internal/option.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
uint32_t _option_build_mss(uint16_t mss)
{
return (((uint32_t )TCP_OPTION_KIND_MSS) << 24) | (((uint32_t) TCP_OPTION_LENGTH_MSS) << 16) | mss;
}
uint16_t _option_build_offset_control(uint16_t nopts, uint16_t ctl)
{
assert(TCP_HDR_OFFSET_MIN <= nopts && nopts <= TCP_HDR_OFFSET_MAX);
return (nopts << 12) | ctl;
}
int _option_parse(gnrc_tcp_tcb_t* tcb, tcp_hdr_t *hdr)
int _option_parse(gnrc_tcp_tcb_t *tcb, tcp_hdr_t *hdr)
{
/* Extract Offset value. Return if no options are set */
uint8_t offset = GET_OFFSET(byteorder_ntohs(hdr->off_ctl));

View File

@ -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,29 +11,28 @@
* @{
*
* @file
* @brief GNRC's TCP paket related functions
* @brief Implementation of internal/pkt.h
*
* @author Simon Brummer <brummer.simon@googlemail.com>
* @author Simon Brummer <simon.brummer@posteo.de>
* @}
*/
#include <stdlib.h>
#include <string.h>
#include <utlist.h>
#include <errno.h>
#include "msg.h"
#include "byteorder.h"
#include "net/inet_csum.h"
#include "net/gnrc/pktbuf.h"
#include "net/gnrc/tcp.h"
#include "internal/pkt.h"
#include "internal/helper.h"
#include "internal/common.h"
#include "internal/option.h"
#include "internal/eventloop.h"
#include "internal/pkt.h"
#ifdef MODULE_GNRC_IPV6
#include "net/gnrc/ipv6.h"
#endif
#define ENABLE_DEBUG (0)
#include "debug.h"
/* Check if a sequence number, falls into the receive window */
#define INSIDE_WND(l_ed, seq_num, r_ed) (LEQ_32_BIT(l_ed, seq_num) && LSS_32_BIT(seq_num, r_ed))
/**
* @brief Calculates the maximum of two unsigned numbers
*
@ -92,7 +91,8 @@ int _pkt_build_reset_from_pkt(gnrc_pktsnip_t **out_pkt, gnrc_pktsnip_t *in_pkt)
/* Allocate new tcp header */
tcp_snp = gnrc_pktbuf_add(NULL, &tcp_hdr_out, TCP_HDR_OFFSET_MIN * 4, GNRC_NETTYPE_TCP);
if (tcp_snp == NULL) {
DEBUG("gnrc_tcp_pkt.c : _pkt_build_reset_from_pkt() : Can't alloc buffer for TCP Header\n.");
DEBUG("gnrc_tcp_pkt.c : _pkt_build_reset_from_pkt() :\
Can't alloc buffer for TCP Header\n.");
*(out_pkt) = NULL;
return -ENOMEM;
}
@ -102,7 +102,8 @@ int _pkt_build_reset_from_pkt(gnrc_pktsnip_t **out_pkt, gnrc_pktsnip_t *in_pkt)
#ifdef MODULE_GNRC_IPV6
ip6_snp = gnrc_ipv6_hdr_build(tcp_snp, &(ip6_hdr->dst), &(ip6_hdr->src));
if (ip6_snp == NULL) {
DEBUG("gnrc_tcp_pkt.c : _pkt_build_reset_from_pkt() : Can't alloc buffer for IPv6 Header.\n");
DEBUG("gnrc_tcp_pkt.c : _pkt_build_reset_from_pkt() :\
Can't alloc buffer for IPv6 Header.\n");
gnrc_pktbuf_release(tcp_snp);
*(out_pkt) = NULL;
return -ENOMEM;
@ -114,7 +115,7 @@ int _pkt_build_reset_from_pkt(gnrc_pktsnip_t **out_pkt, gnrc_pktsnip_t *in_pkt)
return 0;
}
int _pkt_build(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con,
int _pkt_build(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con,
const uint16_t ctl, const uint32_t seq_num, const uint32_t ack_num,
void *payload, const size_t payload_len)
{
@ -161,7 +162,7 @@ int _pkt_build(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con,
else {
/* Add options if existing */
if (TCP_HDR_OFFSET_MIN < offset) {
uint8_t* opt_ptr = (uint8_t *) tcp_snp->data + sizeof(tcp_hdr);
uint8_t *opt_ptr = (uint8_t *) tcp_snp->data + sizeof(tcp_hdr);
uint8_t opt_left = (offset - TCP_HDR_OFFSET_MIN) * sizeof(network_uint32_t);
/* Init options field with 'End Of List' - option (0) */
@ -180,7 +181,7 @@ int _pkt_build(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con,
/* Build network layer header */
#ifdef MODULE_GNRC_IPV6
gnrc_pktsnip_t* ip6_snp = gnrc_ipv6_hdr_build(tcp_snp, NULL, (ipv6_addr_t *) tcb->peer_addr);
gnrc_pktsnip_t *ip6_snp = gnrc_ipv6_hdr_build(tcp_snp, NULL, (ipv6_addr_t *) tcb->peer_addr);
if (ip6_snp == NULL) {
DEBUG("gnrc_tcp_pkt.c : _pkt_build() : Can't allocate buffer for IPv6 Header.\n");
gnrc_pktbuf_release(tcp_snp);
@ -190,7 +191,7 @@ int _pkt_build(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con,
else {
*(out_pkt) = ip6_snp;
}
#else
#else
DEBUG("gnrc_tcp_pkt.c : _pkt_build_reset_from_pkt() : Network Layer Module Missing\n");
#endif
@ -208,7 +209,7 @@ int _pkt_build(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con,
return 0;
}
int _pkt_send(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *out_pkt, const uint16_t seq_con,
int _pkt_send(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *out_pkt, const uint16_t seq_con,
const bool retransmit)
{
if (out_pkt == NULL) {
@ -227,11 +228,11 @@ int _pkt_send(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *out_pkt, const uint16_t seq_c
}
/* Pass packet down the network stack */
gnrc_netapi_send(_gnrc_tcp_pid, out_pkt);
gnrc_netapi_send(gnrc_tcp_pid, out_pkt);
return 0;
}
int _pkt_chk_seq_num(const gnrc_tcp_tcb_t* tcb, const uint32_t seq_num, const uint32_t seg_len)
int _pkt_chk_seq_num(const gnrc_tcp_tcb_t *tcb, const uint32_t seq_num, const uint32_t seg_len)
{
uint32_t l_edge = tcb->rcv_nxt;
uint32_t r_edge = tcb->rcv_nxt + tcb->rcv_wnd;
@ -240,7 +241,7 @@ int _pkt_chk_seq_num(const gnrc_tcp_tcb_t* tcb, const uint32_t seq_num, const ui
/* Possible case 1 */
/* Segment contains no payload and Receive window is closed and */
/* Sequence Number is next expected number */
if (seg_len == 0 && tcb->rcv_wnd == 0 && l_edge == seq_num ) {
if (seg_len == 0 && tcb->rcv_wnd == 0 && l_edge == seq_num) {
return 1;
}
@ -254,9 +255,8 @@ int _pkt_chk_seq_num(const gnrc_tcp_tcb_t* tcb, const uint32_t seq_num, const ui
/* Possible case 3 */
/* Segment contains Payload and Receive window is open and */
/* Sequence Number overlaps with receive window */
if (seg_len > 0 && tcb->rcv_wnd > 0
&& (INSIDE_WND(l_edge, seq_num, r_edge) || INSIDE_WND(l_edge, last_seq, r_edge))
) {
if (seg_len > 0 && tcb->rcv_wnd > 0 && (INSIDE_WND(l_edge, seq_num, r_edge) ||
INSIDE_WND(l_edge, last_seq, r_edge))) {
return 1;
}
@ -296,7 +296,7 @@ uint32_t _pkt_get_pay_len(gnrc_pktsnip_t *pkt)
return seg_len;
}
int _pkt_setup_retransmit(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *pkt, const bool retransmit)
int _pkt_setup_retransmit(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *pkt, const bool retransmit)
{
gnrc_pktsnip_t *snp = NULL;
uint32_t ctl = 0;
@ -331,7 +331,7 @@ int _pkt_setup_retransmit(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *pkt, const bool r
/* RTO Adjustment */
if (!retransmit) {
/* If this is the first transmission: rto is 1 sec (Lower Bound) */
if (tcb->srtt == GNRC_TCP_RTO_UNINITIALIZED || tcb->rtt_var == GNRC_TCP_RTO_UNINITIALIZED) {
if (tcb->srtt == RTO_UNINITIALIZED || tcb->rtt_var == RTO_UNINITIALIZED) {
tcb->rto = GNRC_TCP_RTO_LOWER_BOUND;
}
else {
@ -345,8 +345,8 @@ int _pkt_setup_retransmit(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *pkt, const bool r
/* If the transmission has been tried five times, we assume srtt and rtt_var are bogus */
/* New measurements must be taken */
if (tcb->retries >= 5) {
tcb->srtt = GNRC_TCP_RTO_UNINITIALIZED;
tcb->rtt_var = GNRC_TCP_RTO_UNINITIALIZED;
tcb->srtt = RTO_UNINITIALIZED;
tcb->rtt_var = RTO_UNINITIALIZED;
}
}
@ -360,12 +360,12 @@ int _pkt_setup_retransmit(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *pkt, const bool r
/* Setup retransmission timer, msg to TCP thread with ptr to tcb */
tcb->msg_tout.type = MSG_TYPE_RETRANSMISSION;
tcb->msg_tout.content.ptr = (void *)tcb;
xtimer_set_msg(&tcb->tim_tout, tcb->rto, &tcb->msg_tout, _gnrc_tcp_pid);
tcb->msg_tout.content.ptr = (void *) tcb;
xtimer_set_msg(&tcb->tim_tout, tcb->rto, &tcb->msg_tout, gnrc_tcp_pid);
return 0;
}
int _pkt_acknowledge(gnrc_tcp_tcb_t* tcb, const uint32_t ack)
int _pkt_acknowledge(gnrc_tcp_tcb_t *tcb, const uint32_t ack)
{
uint32_t seg = 0;
gnrc_pktsnip_t *snp = NULL;
@ -395,32 +395,29 @@ int _pkt_acknowledge(gnrc_tcp_tcb_t* tcb, const uint32_t ack)
/* Use sample only if ther was no timeroverflow and no retransmission (Karns Alogrithm) */
if (tcb->retries == 0 && rtt > 0) {
/* If this is the first sample taken */
if (tcb->srtt == GNRC_TCP_RTO_UNINITIALIZED
&& tcb->rtt_var == GNRC_TCP_RTO_UNINITIALIZED
) {
if (tcb->srtt == RTO_UNINITIALIZED && tcb->rtt_var == RTO_UNINITIALIZED) {
tcb->srtt = rtt;
tcb->rtt_var = (rtt >> 1);
}
/* If this is a subsequent sample */
else {
tcb->rtt_var = (tcb->rtt_var / GNRC_TCP_RTO_B_DIV) * (GNRC_TCP_RTO_B_DIV-1);
tcb->rtt_var += abs(tcb->srtt - rtt) / GNRC_TCP_RTO_B_DIV;
tcb->srtt = (tcb->srtt / GNRC_TCP_RTO_A_DIV) * (GNRC_TCP_RTO_A_DIV-1);
tcb->srtt += rtt / GNRC_TCP_RTO_A_DIV;
tcb->rtt_var = (tcb->rtt_var / GNRC_TCP_RTO_B_DIV) * (GNRC_TCP_RTO_B_DIV-1);
tcb->rtt_var += abs(tcb->srtt - rtt) / GNRC_TCP_RTO_B_DIV;
tcb->srtt = (tcb->srtt / GNRC_TCP_RTO_A_DIV) * (GNRC_TCP_RTO_A_DIV-1);
tcb->srtt += rtt / GNRC_TCP_RTO_A_DIV;
}
}
}
return 0;
}
uint16_t _pkt_calc_csum(const gnrc_pktsnip_t *hdr,
const gnrc_pktsnip_t *pseudo_hdr,
uint16_t _pkt_calc_csum(const gnrc_pktsnip_t *hdr, const gnrc_pktsnip_t *pseudo_hdr,
const gnrc_pktsnip_t *payload)
{
uint16_t csum = 0;
uint16_t len = (uint16_t) hdr->size;
if(pseudo_hdr == NULL) {
if (pseudo_hdr == NULL) {
return 0;
}
@ -432,9 +429,9 @@ uint16_t _pkt_calc_csum(const gnrc_pktsnip_t *hdr,
}
/* Process tcp-header, before checksum field(Byte 16 to 18) */
csum = inet_csum(csum, (uint8_t *)hdr->data, 16);
csum = inet_csum(csum, (uint8_t *) hdr->data, 16);
/* Process tcp-header, after checksum field */
csum = inet_csum(csum, ((uint8_t *)hdr->data) + 18, hdr->size - 18);
csum = inet_csum(csum, ((uint8_t *) hdr->data) + 18, hdr->size - 18);
/* Process Network layer Header */
switch (pseudo_hdr->type) {
@ -448,6 +445,3 @@ uint16_t _pkt_calc_csum(const gnrc_pktsnip_t *hdr,
}
return ~csum;
}
/* Cleanup, defines */
#undef INSIDE_WND

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Simon Brummer <brummer.simon@googlemail.com>
* 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
@ -7,12 +7,13 @@
*/
/**
* @ingroup net_gnrc
* @{
*
* @file
* @brief Implementation of tcp_internal/rcvbuf.h
* @brief Implementation of internal/rcvbuf.h
*
* @author Brummer Simon <brummer.simon@googlemail.com>
* @author Simon Brummer <simon.brummer@posteo.de>
*/
#include <errno.h>
#include "internal/rcvbuf.h"
@ -20,13 +21,13 @@
#define ENABLE_DEBUG (0)
#include "debug.h"
rcvbuf_t _static_buf; /**< Staticly allocated receive buffers */
rcvbuf_t _static_buf; /**< Staticly allocated receive buffers */
void _rcvbuf_init(void)
{
DEBUG("gnrc_tcp_rcvbuf.c : _rcvbuf_init() : Entry\n");
mutex_init(&(_static_buf.lock));
for (int i=0; i<GNRC_TCP_RCV_BUFFERS; i++) {
for (size_t i = 0; i < GNRC_TCP_RCV_BUFFERS; ++i) {
_static_buf.entries[i].used = 0;
}
}
@ -36,7 +37,7 @@ static void* _rcvbuf_alloc(void)
void *result = NULL;
DEBUG("gnrc_tcp_rcvbuf.c : _rcvbuf_alloc() : Entry\n");
mutex_lock(&(_static_buf.lock));
for (int i=0; i<GNRC_TCP_RCV_BUFFERS; i++) {
for (size_t i = 0; i < GNRC_TCP_RCV_BUFFERS; ++i) {
if (_static_buf.entries[i].used == 0) {
_static_buf.entries[i].used = 1;
result = (void *)(_static_buf.entries[i].buffer);
@ -51,7 +52,7 @@ static void _rcvbuf_free(void * const buf)
{
DEBUG("gnrc_tcp_rcvbuf.c : _rcvbuf_free() : Entry\n");
mutex_lock(&(_static_buf.lock));
for (int i=0; i<GNRC_TCP_RCV_BUFFERS; i++) {
for (size_t i = 0; i < GNRC_TCP_RCV_BUFFERS; ++i) {
if (_static_buf.entries[i].used == 1 && buf == _static_buf.entries[i].buffer) {
_static_buf.entries[i].used = 0;
}
@ -59,7 +60,7 @@ static void _rcvbuf_free(void * const buf)
mutex_unlock(&(_static_buf.lock));
}
int _rcvbuf_get_buffer(gnrc_tcp_tcb_t* tcb)
int _rcvbuf_get_buffer(gnrc_tcp_tcb_t *tcb)
{
if (tcb->rcv_buf_raw == NULL) {
tcb->rcv_buf_raw = _rcvbuf_alloc();
@ -74,7 +75,7 @@ int _rcvbuf_get_buffer(gnrc_tcp_tcb_t* tcb)
return 0;
}
void _rcvbuf_release_buffer(gnrc_tcp_tcb_t* tcb)
void _rcvbuf_release_buffer(gnrc_tcp_tcb_t *tcb)
{
if (tcb->rcv_buf_raw != NULL) {
_rcvbuf_free(tcb->rcv_buf_raw);

View File

@ -0,0 +1,137 @@
/*
* 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
* directory for more details.
*/
/**
* @defgroup net_gnrc_tcp TCP
* @ingroup net_gnrc
* @brief RIOT's tcp implementation for the gnrc stack
*
* @{
*
* @file
* @brief Internally used common defines, macros and variable declaration
*
* @author Simon Brummer <simon.brummer@posteo.de>
*/
#ifndef GNRC_TCP_INTERNAL_COMMON_H
#define GNRC_TCP_INTERNAL_COMMON_H
#include <stdint.h>
#include "kernel_types.h"
#include "thread.h"
#include "mutex.h"
#include "net/gnrc/netapi.h"
#include "net/gnrc/tcp/tcb.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Port unspecified.
*
* @note PORT 0 is unspecified (@see https://www.ietf.org/rfc/rfc1700.txt)
*/
#define PORT_UNSPEC (0)
/**
* @brief Status Flags for TCP
* @{
*/
#define STATUS_PASSIVE (1 << 0)
#define STATUS_ALLOW_ANY_ADDR (1 << 1)
/** @} */
/**
* @brief Defines for gnrc tcps "eventloop" thread
* @{
*/
#define TCP_EVENTLOOP_MSG_QUEUE_SIZE (8U)
#define TCP_EVENTLOOP_PRIO (THREAD_PRIORITY_MAIN - 2U)
#define TCP_EVENTLOOP_STACK_SIZE (THREAD_STACKSIZE_DEFAULT)
/** @} */
/**
* @brief Bitmasks for control bit handling
* @{
*/
#define MSK_FIN (0x0001)
#define MSK_SYN (0x0002)
#define MSK_RST (0x0004)
#define MSK_PSH (0x0008)
#define MSK_ACK (0x0010)
#define MSK_URG (0x0020)
#define MSK_FIN_ACK (0x0011)
#define MSK_SYN_ACK (0x0012)
#define MSK_RST_ACK (0x0014)
#define MSK_SYN_FIN_ACK (0x0013)
#define MSK_FIN_ACK_PSH (0x0019)
#define MSK_CTL (0x003F)
#define MSK_OFFSET (0xF000)
/** @} */
/**
* @brief Type field values for TCP internal Message Passing.
* @{
*/
#define MSG_TYPE_CONNECTION_TIMEOUT (GNRC_NETAPI_MSG_TYPE_ACK + 101)
#define MSG_TYPE_PROBE_TIMEOUT (GNRC_NETAPI_MSG_TYPE_ACK + 102)
#define MSG_TYPE_USER_SPEC_TIMEOUT (GNRC_NETAPI_MSG_TYPE_ACK + 103)
#define MSG_TYPE_RETRANSMISSION (GNRC_NETAPI_MSG_TYPE_ACK + 104)
#define MSG_TYPE_TIMEWAIT (GNRC_NETAPI_MSG_TYPE_ACK + 105)
#define MSG_TYPE_NOTIFY_USER (GNRC_NETAPI_MSG_TYPE_ACK + 106)
/** @} */
/**
* @brief Macro to mark is the time measurement is uninitialized
*/
#define RTO_UNINITIALIZED (-1)
/**
* @brief Overflow tolerant comparision operators for sequence and
acknowledgement number comparision
* @{
*/
#define LSS_32_BIT(x, y) (((int32_t) (x)) - ((int32_t) (y)) < 0)
#define LEQ_32_BIT(x, y) (((int32_t) (x)) - ((int32_t) (y)) <= 0)
#define GRT_32_BIT(x, y) (!LEQ_32_BIT(x, y))
#define GEQ_32_BIT(x, y) (!LSS_32_BOT(x, y))
/** @} */
/**
* @brief Check if a given sequence number, falls into the a receive window
*/
#define INSIDE_WND(l_ed, seq_num, r_ed) (LEQ_32_BIT(l_ed, seq_num) && LSS_32_BIT(seq_num, r_ed))
/**
* @brief Extract offset value from "offctl"-header field.
*/
#define GET_OFFSET( x ) (((x) & MSK_OFFSET) >> 12)
/**
* @brief PID of tcp event handling thread
*/
extern kernel_pid_t gnrc_tcp_pid;
/**
* @brief Head of linked tcb list.
*/
extern gnrc_tcp_tcb_t *_list_tcb_head;
/**
* @brief Mutex to protect linked list.
*/
extern mutex_t _list_tcb_lock;
#ifdef __cplusplus
}
#endif
#endif /* GNRC_TCP_INTERNAL_COMMON_H */
/** @} */

View File

@ -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,23 +14,18 @@
* @{
*
* @file
* @brief Definition for gnrc tcp event processing loop
* @brief TCP event loop delarations
*
* @author Simon Brummer <brummer.simon@googlemail.com>
* @author Simon Brummer <simon.brummer@posteo.de>
*/
#ifndef GNRC_TCP_INTERNAL_EVENTLOOP_H_
#define GNRC_TCP_INTERNAL_EVENTLOOP_H_
#ifndef GNRC_TCP_INTERNAL_EVENTLOOP_H
#define GNRC_TCP_INTERNAL_EVENTLOOP_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief PID of tcp event handling thread
*/
extern kernel_pid_t _gnrc_tcp_pid;
/**
* @brief TCP's mein processing thread.
*
@ -44,5 +39,5 @@ void *_event_loop(__attribute__((unused)) void *arg);
}
#endif
#endif /* GNRC_TCP_INTERNAL_EVENTLOOP_H_ */
#endif /* GNRC_TCP_INTERNAL_EVENTLOOP_H */
/** @} */

View File

@ -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,48 +14,74 @@
* @{
*
* @file
* @brief Definies function to manipulate a connections state
* @brief TCP finite state maschine declarations
*
* @author Simon Brummer <brummer.simon@googlemail.com>
* @author Simon Brummer <simon.brummer@posteo.de>
*/
#ifndef GNRC_TCP_INTERNAL_FSM_H_
#define GNRC_TCP_INTERNAL_FSM_H_
#ifndef GNRC_TCP_INTERNAL_FSM_H
#define GNRC_TCP_INTERNAL_FSM_H
#include <errno.h>
#include "net/gnrc/pktbuf.h"
#include <stdint.h>
#include "net/gnrc/pkt.h"
#include "net/gnrc/tcp/fsm.h"
#include "net/gnrc/tcp.h"
#include "net/gnrc/tcp/tcb.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief PID of tcp event handling thread
* @brief The TCP FSM States.
*/
extern kernel_pid_t _gnrc_tcp_pid;
typedef enum {
FSM_STATE_CLOSED,
FSM_STATE_LISTEN,
FSM_STATE_SYN_SENT,
FSM_STATE_SYN_RCVD,
FSM_STATE_ESTABLISHED,
FSM_STATE_CLOSE_WAIT,
FSM_STATE_LAST_ACK,
FSM_STATE_FIN_WAIT_1,
FSM_STATE_FIN_WAIT_2,
FSM_STATE_CLOSING,
FSM_STATE_TIME_WAIT
} fsm_state_t;
/**
* @brief Events that trigger translations in TCP FSM.
*/
typedef enum {
FSM_EVENT_CALL_OPEN, /* User function call: open */
FSM_EVENT_CALL_SEND, /* User function call: send */
FSM_EVENT_CALL_RECV, /* User function call: recv */
FSM_EVENT_CALL_CLOSE, /* User function call: close */
FSM_EVENT_CALL_ABORT, /* User function call: abort */
FSM_EVENT_RCVD_PKT, /* Paket received from peer */
FSM_EVENT_TIMEOUT_TIMEWAIT, /* Timeout: Timewait */
FSM_EVENT_TIMEOUT_RETRANSMIT, /* Timeout: Retransmit */
FSM_EVENT_TIMEOUT_CONNECTION, /* Timeout: Connection */
FSM_EVENT_SEND_PROBE, /* Send a Zero Window Probe */
FSM_EVENT_CLEAR_RETRANSMIT /* Clear Retransmission Mechanism */
} fsm_event_t;
/**
* @brief TCP finite state maschine
*
* @param[in,out] tcb specifies connection to use fsm on.
* @param[in] event current event that triggers fsm translation
* @param[in] in_pkt packet that triggered fsm event. Only in case of RCVD_PKT
* @param[in,out] buf buffer for send and receive functions
* @param[in] nByte number of bytes to send or receive atmost
* @param[in,out] tcb specifies connection to use fsm on.
* @param[in] event current event that triggers fsm translation
* @param[in] in_pkt packet that triggered fsm event. Only in case of RCVD_PKT
* @param[in,out] buf buffer for send and receive functions
* @param[in] len number of bytes to send or receive atmost
*
* @return Zero on success
* @return Positive Number, number of bytes sent from or copied into buf.
* @return -ENOSYS if event is not implemented
*/
int _fsm(gnrc_tcp_tcb_t* tcb, gnrc_tcp_fsm_event_t event, gnrc_pktsnip_t *in_pkt, void *buf,
size_t nByte);
int _fsm(gnrc_tcp_tcb_t *tcb, fsm_event_t event, gnrc_pktsnip_t *in_pkt, void *buf, size_t len);
#ifdef __cplusplus
}
#endif
#endif /* GNRC_TCP_INTERNAL_FSM_H_ */
#endif /* GNRC_TCP_INTERNAL_FSM_H */
/** @} */

View File

@ -1,79 +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 Helperfunctions and defines
*
* @author Simon Brummer <brummer.simon@googlemail.com>
*/
#ifndef GNRC_TCP_INTERNAL_HELPER_H_
#define GNRC_TCP_INTERNAL_HELPER_H_
#include "net/tcp.h"
#include "net/gnrc/netapi.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Bitmasks for control bit handling
* @{
*/
#define MSK_FIN 0x0001
#define MSK_SYN 0x0002
#define MSK_RST 0x0004
#define MSK_PSH 0x0008
#define MSK_ACK 0x0010
#define MSK_URG 0x0020
#define MSK_FIN_ACK 0x0011
#define MSK_SYN_ACK 0x0012
#define MSK_RST_ACK 0x0014
#define MSK_SYN_FIN_ACK 0x0013
#define MSK_FIN_ACK_PSH 0x0019
#define MSK_CTL 0x003F
#define MSK_OFFSET 0xF000
/** @} */
/**
* @brief Type field values for TCP internal Message Passing.
* @{
*/
#define MSG_TYPE_CONNECTION_TIMEOUT (GNRC_NETAPI_MSG_TYPE_ACK + 101)
#define MSG_TYPE_PROBE_TIMEOUT (GNRC_NETAPI_MSG_TYPE_ACK + 102)
#define MSG_TYPE_USER_SPEC_TIMEOUT (GNRC_NETAPI_MSG_TYPE_ACK + 103)
#define MSG_TYPE_RETRANSMISSION (GNRC_NETAPI_MSG_TYPE_ACK + 104)
#define MSG_TYPE_TIMEWAIT (GNRC_NETAPI_MSG_TYPE_ACK + 105)
#define MSG_TYPE_NOTIFY_USER (GNRC_NETAPI_MSG_TYPE_ACK + 106)
/** @} */
/**
* @brief Overflow tolerant comparision operators for sequence and
acknowledgement number comparision
* @{
*/
#define LSS_32_BIT(x, y) (((int32_t) (x)) - ((int32_t) (y)) < 0)
#define LEQ_32_BIT(x, y) (((int32_t) (x)) - ((int32_t) (y)) <= 0)
#define GRT_32_BIT(x, y) (!LEQ_32_BIT(x, y))
#define GEQ_32_BIT(x, y) (!LSS_32_BOT(x, y))
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* GNRC_TCP_INTERNAL_HELPER_H_ */
/** @} */

View File

@ -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,27 +14,23 @@
* @{
*
* @file
* @brief Defines and Macros for TCP option handling
* @brief TCP option handling declarations
*
* @author Simon Brummer <brummer.simon@googlemail.com>
* @author Simon Brummer <simon.brummer@posteo.de>
*/
#ifndef GNRC_TCP_INTERNAL_OPTION_H_
#define GNRC_TCP_INTERNAL_OPTION_H_
#ifndef GNRC_TCP_INTERNAL_OPTION_H
#define GNRC_TCP_INTERNAL_OPTION_H
#include "helper.h"
#include <stdint.h>
#include "assert.h"
#include "net/tcp.h"
#include "net/gnrc/tcp.h"
#include "net/gnrc/tcp/tcb.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Extract offset value from offet and ctl bit field.
*/
#define GET_OFFSET( x ) (((x) & MSK_OFFSET) >> 12)
/**
* @brief Helper Function to build the MSS Option
*
@ -42,7 +38,11 @@ extern "C" {
*
* @return Valid MSS Option.
*/
uint32_t _option_build_mss(uint16_t mss);
inline static uint32_t _option_build_mss(uint16_t mss)
{
return (((uint32_t) TCP_OPTION_KIND_MSS << 24) |
((uint32_t) TCP_OPTION_LENGTH_MSS << 16) | mss);
}
/**
* @brief Helper Function to build the combined option and control flag field
@ -52,7 +52,11 @@ uint32_t _option_build_mss(uint16_t mss);
*
* @return Valid option size and control field.
*/
uint16_t _option_build_offset_control(uint16_t nopts, uint16_t ctl);
inline static uint16_t _option_build_offset_control(uint16_t nopts, uint16_t ctl)
{
assert(TCP_HDR_OFFSET_MIN <= nopts && nopts <= TCP_HDR_OFFSET_MAX);
return (nopts << 12) | ctl;
}
/**
* @brief Parses options of a given tcp-header pktsnip.
@ -63,11 +67,11 @@ uint16_t _option_build_offset_control(uint16_t nopts, uint16_t ctl);
* @return Zero on success
* @return A negative value on error
*/
int _option_parse(gnrc_tcp_tcb_t* tcb, tcp_hdr_t *hdr);
int _option_parse(gnrc_tcp_tcb_t *tcb, tcp_hdr_t *hdr);
#ifdef __cplusplus
}
#endif
#endif /* GNRC_TCP_INTERNAL_OPTION_H_*/
#endif /* GNRC_TCP_INTERNAL_OPTION_H*/
/** @} */

View File

@ -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,15 +14,17 @@
* @{
*
* @file
* @brief Functions for TCP's paket handling
* @brief TCP paket handling declarations
*
* @author Simon Brummer <brummer.simon@googlemail.com>
* @author Simon Brummer <simon.brummer@posteo.de>
*/
#ifndef GNRC_TCP_INTERNAL_PKT_H_
#define GNRC_TCP_INTERNAL_PKT_H_
#ifndef GNRC_TCP_INTERNAL_PKT_H
#define GNRC_TCP_INTERNAL_PKT_H
#include "net/conn/tcp.h"
#include <stdint.h>
#include "net/gnrc/pkt.h"
#include "net/gnrc/tcp/tcb.h"
#ifdef __cplusplus
extern "C" {
@ -43,21 +45,21 @@ extern "C" {
int _pkt_build_reset_from_pkt(gnrc_pktsnip_t **out_pkt, gnrc_pktsnip_t *in_pkt);
/**
* @brief Build and allocate a tcp paket in paketbuffer, conn stores pointer to new paket.
* @brief Build and allocate a tcp paket, tcb stores pointer to new paket.
*
* @param[in,out] tcb This connections Transmission control block.
* @param[in,out] tcb This connections transmission control block.
* @param[out] out_pkt Pointer to paket to build
* @param[out] seq_con Number of Bytes, the packet will consume in sequence number spce
* @param[in] ctl control bits to set in pkt
* @param[in] seq_num sequence number to use in new paket
* @param[in] ack_num acknowledgment number to use in new paket
* @param[out] seq_con Number of Bytes, the packet will consume in sequence number space
* @param[in] ctl control bits to set in out_pkt
* @param[in] seq_num sequence number of the new paket
* @param[in] ack_num acknowledgment number of the new paket
* @param[in] payload pointer to payload buffer
* @param[in] payload_len payload size
*
* @return Zero on success.
* @return -ENOMEM if pktbuf is full.
*/
int _pkt_build(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con,
int _pkt_build(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con,
const uint16_t ctl, const uint32_t seq_num, const uint32_t ack_num,
void *payload, const size_t payload_len);
@ -72,7 +74,7 @@ int _pkt_build(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t **out_pkt, uint16_t *seq_con,
* @return Zero on success.
* @return -EINVAL if out_pkt was NULL
*/
int _pkt_send(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *out_pkt, const uint16_t seq_con,
int _pkt_send(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *out_pkt, const uint16_t seq_con,
const bool retransmit);
/**
@ -85,7 +87,7 @@ int _pkt_send(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *out_pkt, const uint16_t seq_c
* @return Zero if the sequence number is invalid
* @return Non-zero if the sequence number is acceptable
*/
int _pkt_chk_seq_num(const gnrc_tcp_tcb_t* tcb, const uint32_t seq_num, const uint32_t seg_len);
int _pkt_chk_seq_num(const gnrc_tcp_tcb_t *tcb, const uint32_t seq_num, const uint32_t seg_len);
/**
* @brief Extracts the length of a segment
@ -110,13 +112,13 @@ uint32_t _pkt_get_pay_len(gnrc_pktsnip_t *pkt);
*
* @param[in,out] tcb This connections Transmission control block.
* @param[in] pkt paket to add to the retransmission mechanism
* @param[in] retransmit is this a retransmission ?
* @param[in] retransmit Flag used to indicate that pkt is a retransmit.
*
* @return Zero on success
* @return -ENOMEM if the retransmission queue is full
* @return -EINVAL if pkt is null
*/
int _pkt_setup_retransmit(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *pkt, const bool retransmit);
int _pkt_setup_retransmit(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *pkt, const bool retransmit);
/**
* @brief Acknowledges and removes packet from the retransmission mechanism
@ -127,7 +129,7 @@ int _pkt_setup_retransmit(gnrc_tcp_tcb_t* tcb, gnrc_pktsnip_t *pkt, const bool r
* @return Zero on success
* @return -ENODATA if there is nothing to acknowledge
*/
int _pkt_acknowledge(gnrc_tcp_tcb_t* tcb, const uint32_t ack);
int _pkt_acknowledge(gnrc_tcp_tcb_t *tcb, const uint32_t ack);
/**
* @brief Calculates checksum over payload, tcp-header and network layer header
@ -146,5 +148,5 @@ uint16_t _pkt_calc_csum(const gnrc_pktsnip_t *hdr, const gnrc_pktsnip_t *pseudo_
}
#endif
#endif /* GNRC_TCP_INTERNAL_PKT_H_ */
#endif /* GNRC_TCP_INTERNAL_PKT_H */
/** @} */

View File

@ -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 Functions for allocating and freeing the receive buffer
* @brief Functions for allocating and freeing the receive buffer
*
* @author Simon Brummer <brummer.simon@googlemail.com>
* @}
* @author Simon Brummer <simon.brummer@posteo.de>
*/
#ifndef GNRC_TCP_INTERNAL_RCVBUF_H_
#define GNRC_TCP_INTERNAL_RCVBUF_H_
#ifndef GNRC_TCP_INTERNAL_RCVBUF_H
#define GNRC_TCP_INTERNAL_RCVBUF_H
#include <stdint.h>
#include "mutex.h"
#include "ringbuffer.h"
#include "net/gnrc/tcp/config.h"
#include "net/gnrc/tcp/tcb.h"
@ -64,18 +63,18 @@ void _rcvbuf_init(void);
* @return zero on success
* @return -ENOMEM If receive buffer is out of memory.
*/
int _rcvbuf_get_buffer(gnrc_tcp_tcb_t* tcb);
int _rcvbuf_get_buffer(gnrc_tcp_tcb_t *tcb);
/**
* @brief Free allocated receive buffer
*
* @param[in] tcb Transmission control block that buffer should be freed.
*/
void _rcvbuf_release_buffer(gnrc_tcp_tcb_t* tcb);
void _rcvbuf_release_buffer(gnrc_tcp_tcb_t *tcb);
#ifdef __cplusplus
}
#endif
#endif /* GNRC_TCP_INTERNAL_RCVBUF_H_ */
#endif /* GNRC_TCP_INTERNAL_RCVBUF_H */
/** @} */

View File

@ -1,14 +1,15 @@
/*
* 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
* directory for more details.
*/
#include <stdio.h>
#include <errno.h>
#include "thread.h"
#include "net/af.h"
#include "random.h"
#include "net/gnrc/ipv6.h"
#include "net/gnrc/tcp.h"
@ -17,7 +18,7 @@
/* Number of possible parallel connections */
#ifndef CONNS
#define CONNS 1
#define CONNS (1)
#endif
/* Amount of data to transmit */
@ -47,10 +48,9 @@ int main(void)
/* Start Connection Handling Threads */
for (int i = 0; i < CONNS; i += 1) {
thread_create((char *)stacks[i], sizeof(stacks[i]), THREAD_PRIORITY_MAIN, 0, cli_thread,
(void *)i, NULL);
thread_create((char *) stacks[i], sizeof(stacks[i]), THREAD_PRIORITY_MAIN, 0, cli_thread,
(void *) i, NULL);
}
return 0;
}
@ -112,8 +112,7 @@ void *cli_thread(void *arg)
return 0;
case -ETIMEDOUT:
printf("TID=%d : gnrc_tcp_open_active() : -ETIMEDOUT : retry after 10sec\n",
tid);
printf("TID=%d : gnrc_tcp_open_active() : -ETIMEDOUT : retry after 10sec\n", tid);
xtimer_sleep(10);
continue;
@ -123,7 +122,7 @@ void *cli_thread(void *arg)
}
/* Fill Buffer with a test pattern */
for (size_t i=0; i < sizeof(bufs[tid]); ++i){
for (size_t i = 0; i < sizeof(bufs[tid]); ++i){
bufs[tid][i] = TEST_PATERN_CLI;
}
@ -160,7 +159,7 @@ void *cli_thread(void *arg)
/* Receive Data, stop if errors were found */
for (size_t rcvd = 0; rcvd < sizeof(bufs[tid]) && ret >= 0; rcvd += ret) {
ret = gnrc_tcp_recv(&tcb, (void *)(bufs[tid] + rcvd), sizeof(bufs[tid]) - rcvd,
ret = gnrc_tcp_recv(&tcb, (void *) (bufs[tid] + rcvd), sizeof(bufs[tid]) - rcvd,
GNRC_TCP_CONNECTION_TIMEOUT_DURATION);
switch (ret) {
case -ENOTCONN:
@ -197,7 +196,7 @@ void *cli_thread(void *arg)
}
/* If there was no error: Check received pattern */
for (size_t i=0; i < sizeof(bufs[tid]); ++i) {
for (size_t i = 0; i < sizeof(bufs[tid]); ++i) {
if (bufs[tid][i] != TEST_PATERN_SRV) {
printf("TID=%d : Payload verfication failed\n", tid);
failed_payload_verifications += 1;
@ -210,7 +209,7 @@ void *cli_thread(void *arg)
/* Gather Data */
cycles += 1;
if(ret >= 0) {
if (ret >= 0) {
cycles_ok += 1;
}
printf("TID=%d : %"PRIi32" test cycles completed. %"PRIi32" ok, %"PRIi32" faulty",

View File

@ -1,10 +1,11 @@
/*
* 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
* directory for more details.
*/
#include <stdio.h>
#include <errno.h>
#include "thread.h"
@ -17,7 +18,7 @@
/* Number of possible parallel connections */
#ifndef CONNS
#define CONNS 1
#define CONNS (1)
#endif
/* Amount of data to transmit */
@ -54,15 +55,15 @@ int main(void)
/* Start Threads to handle each connection */
for (int i = 0; i < CONNS; i += 1) {
thread_create((char *)stacks[i], sizeof(stacks[i]), THREAD_PRIORITY_MAIN, 0, srv_thread,
(void *)i, NULL);
thread_create((char *) stacks[i], sizeof(stacks[i]), THREAD_PRIORITY_MAIN, 0, srv_thread,
(void *) i, NULL);
}
return 0;
}
void *srv_thread(void *arg)
{
int tid = (int)arg;
int tid = (int) arg;
uint32_t cycles = 0;
uint32_t cycles_ok = 0;
uint32_t failed_payload_verifications = 0;
@ -106,7 +107,7 @@ void *srv_thread(void *arg)
/* Receive Data, stop if errors were found */
for (size_t rcvd = 0; rcvd < sizeof(bufs[tid]) && ret >= 0; rcvd += ret) {
ret = gnrc_tcp_recv(&tcb, (void *)(bufs[tid] + rcvd), sizeof(bufs[tid]) - rcvd,
ret = gnrc_tcp_recv(&tcb, (void *) (bufs[tid] + rcvd), sizeof(bufs[tid]) - rcvd,
GNRC_TCP_CONNECTION_TIMEOUT_DURATION);
switch (ret) {
case -ENOTCONN:
@ -143,7 +144,7 @@ void *srv_thread(void *arg)
}
/* Check received pattern */
for (size_t i=0; i < sizeof(bufs[tid]); ++i) {
for (size_t i = 0; i < sizeof(bufs[tid]); ++i) {
if (bufs[tid][i] != TEST_PATERN_CLI) {
printf("TID=%d : Payload verfication failed\n", tid);
failed_payload_verifications += 1;
@ -152,7 +153,7 @@ void *srv_thread(void *arg)
}
/* Fill Buffer with a test pattern */
for (size_t i=0; i < sizeof(bufs[tid]); ++i) {
for (size_t i = 0; i < sizeof(bufs[tid]); ++i) {
bufs[tid][i] = TEST_PATERN_SRV;
}
@ -192,7 +193,7 @@ void *srv_thread(void *arg)
/* Gather Data */
cycles += 1;
if(ret >= 0) {
if (ret >= 0) {
cycles_ok += 1;
}
printf("TID=%d : %"PRIi32" test cycles completed. %"PRIi32" ok, %"PRIi32" faulty",