mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2025-04-16 08:43:17 +00:00
tcp: introduce ext_args per pcb
This introduces the concept of ext (external/extended) arguments per tcp_pcb (also for listening pcbs) to store more data than just one "void *arg" per pcb. The "arg" is for use to applications, whereas the ext_args may be used by frameworks and leave "arg" untouched. In addition to a void pointer, callbacks are added to help frameworks migrate arguments from listen pcb to connection pcb and to free args when the pcb is freed. Signed-off-by: goldsimon <goldsimon@gmx.de>
This commit is contained in:
parent
ebe782ba16
commit
0e85582bc0
@ -2136,7 +2136,8 @@ PREDEFINED = __DOXYGEN__=1 \
|
|||||||
SO_REUSE=1 \
|
SO_REUSE=1 \
|
||||||
SO_REUSE_RXTOALL=1 \
|
SO_REUSE_RXTOALL=1 \
|
||||||
LWIP_HAVE_SLIPIF=1 \
|
LWIP_HAVE_SLIPIF=1 \
|
||||||
LWIP_6LOWPAN=1
|
LWIP_6LOWPAN=1 \
|
||||||
|
LWIP_TCP_PCB_NUM_EXT_ARGS=1
|
||||||
|
|
||||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||||
# tag can be used to specify a list of macro names that should be expanded. The
|
# tag can be used to specify a list of macro names that should be expanded. The
|
||||||
|
169
src/core/tcp.c
169
src/core/tcp.c
@ -8,7 +8,7 @@
|
|||||||
* Transmission Control Protocol for IP\n
|
* Transmission Control Protocol for IP\n
|
||||||
* @see @ref api
|
* @see @ref api
|
||||||
*
|
*
|
||||||
* Common functions for the TCP implementation, such as functinos
|
* Common functions for the TCP implementation, such as functions
|
||||||
* for manipulating the data structures and the TCP timer functions. TCP functions
|
* for manipulating the data structures and the TCP timer functions. TCP functions
|
||||||
* related to input and output is found in tcp_in.c and tcp_out.c respectively.\n
|
* related to input and output is found in tcp_in.c and tcp_out.c respectively.\n
|
||||||
*
|
*
|
||||||
@ -190,6 +190,9 @@ static u8_t tcp_timer_ctr;
|
|||||||
static u16_t tcp_new_port(void);
|
static u16_t tcp_new_port(void);
|
||||||
|
|
||||||
static err_t tcp_close_shutdown_fin(struct tcp_pcb *pcb);
|
static err_t tcp_close_shutdown_fin(struct tcp_pcb *pcb);
|
||||||
|
#if LWIP_TCP_PCB_NUM_EXT_ARGS
|
||||||
|
static void tcp_ext_arg_invoke_callbacks_destroyed(struct tcp_pcb_ext_args *ext_args);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize this module.
|
* Initialize this module.
|
||||||
@ -207,6 +210,9 @@ void
|
|||||||
tcp_free(struct tcp_pcb *pcb)
|
tcp_free(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
LWIP_ASSERT("tcp_free: LISTEN", pcb->state != LISTEN);
|
LWIP_ASSERT("tcp_free: LISTEN", pcb->state != LISTEN);
|
||||||
|
#if LWIP_TCP_PCB_NUM_EXT_ARGS
|
||||||
|
tcp_ext_arg_invoke_callbacks_destroyed(pcb->ext_args);
|
||||||
|
#endif
|
||||||
memp_free(MEMP_TCP_PCB, pcb);
|
memp_free(MEMP_TCP_PCB, pcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,6 +221,9 @@ static void
|
|||||||
tcp_free_listen(struct tcp_pcb *pcb)
|
tcp_free_listen(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
LWIP_ASSERT("tcp_free_listen: !LISTEN", pcb->state != LISTEN);
|
LWIP_ASSERT("tcp_free_listen: !LISTEN", pcb->state != LISTEN);
|
||||||
|
#if LWIP_TCP_PCB_NUM_EXT_ARGS
|
||||||
|
tcp_ext_arg_invoke_callbacks_destroyed(pcb->ext_args);
|
||||||
|
#endif
|
||||||
memp_free(MEMP_TCP_PCB_LISTEN, pcb);
|
memp_free(MEMP_TCP_PCB_LISTEN, pcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -866,6 +875,10 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
|
|||||||
if (pcb->local_port != 0) {
|
if (pcb->local_port != 0) {
|
||||||
TCP_RMV(&tcp_bound_pcbs, pcb);
|
TCP_RMV(&tcp_bound_pcbs, pcb);
|
||||||
}
|
}
|
||||||
|
#if LWIP_TCP_PCB_NUM_EXT_ARGS
|
||||||
|
/* copy over ext_args to listening pcb */
|
||||||
|
memcpy(&lpcb->ext_args, &pcb->ext_args, sizeof(pcb->ext_args));
|
||||||
|
#endif
|
||||||
tcp_free(pcb);
|
tcp_free(pcb);
|
||||||
#if LWIP_CALLBACK_API
|
#if LWIP_CALLBACK_API
|
||||||
lpcb->accept = tcp_accept_null;
|
lpcb->accept = tcp_accept_null;
|
||||||
@ -2460,4 +2473,158 @@ tcp_pcbs_sane(void)
|
|||||||
}
|
}
|
||||||
#endif /* TCP_DEBUG */
|
#endif /* TCP_DEBUG */
|
||||||
|
|
||||||
|
#if LWIP_TCP_PCB_NUM_EXT_ARGS
|
||||||
|
/**
|
||||||
|
* @defgroup tcp_raw_extargs ext arguments
|
||||||
|
* @ingroup tcp_raw
|
||||||
|
* Additional data storage per tcp pcb\n
|
||||||
|
* @see @ref tcp_raw
|
||||||
|
*
|
||||||
|
* When LWIP_TCP_PCB_NUM_EXT_ARGS is > 0, every tcp pcb (including listen pcb)
|
||||||
|
* includes a number of additional argument entries in an array.
|
||||||
|
*
|
||||||
|
* To support memory management, in addition to a 'void *', callbacks can be
|
||||||
|
* provided to manage transition from listening pcbs to connections and to
|
||||||
|
* deallocate memory when a pcb is deallocated (see struct @ref tcp_ext_arg_callbacks).
|
||||||
|
*
|
||||||
|
* After allocating this index, use @ref tcp_ext_arg_set and @ref tcp_ext_arg_get
|
||||||
|
* to store and load arguments from this index for a given pcb.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static u8_t tcp_ext_arg_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup tcp_raw_extargs
|
||||||
|
* Allocate an index to store data in ext_args member of struct tcp_pcb.
|
||||||
|
* Returned value is an index in mentioned array.
|
||||||
|
* The index is *global* over all pcbs!
|
||||||
|
*
|
||||||
|
* When @ref LWIP_TCP_PCB_NUM_EXT_ARGS is > 0, every tcp pcb (including listen pcb)
|
||||||
|
* includes a number of additional argument entries in an array.
|
||||||
|
*
|
||||||
|
* To support memory management, in addition to a 'void *', callbacks can be
|
||||||
|
* provided to manage transition from listening pcbs to connections and to
|
||||||
|
* deallocate memory when a pcb is deallocated (see struct @ref tcp_ext_arg_callbacks).
|
||||||
|
*
|
||||||
|
* After allocating this index, use @ref tcp_ext_arg_set and @ref tcp_ext_arg_get
|
||||||
|
* to store and load arguments from this index for a given pcb.
|
||||||
|
*
|
||||||
|
* @return a unique index into struct tcp_pcb.ext_args
|
||||||
|
*/
|
||||||
|
u8_t
|
||||||
|
tcp_ext_arg_alloc_id(void)
|
||||||
|
{
|
||||||
|
u8_t result = tcp_ext_arg_id;
|
||||||
|
tcp_ext_arg_id++;
|
||||||
|
|
||||||
|
LWIP_ASSERT_CORE_LOCKED();
|
||||||
|
|
||||||
|
#if LWIP_TCP_PCB_NUM_EXT_ARGS >= 255
|
||||||
|
#error LWIP_TCP_PCB_NUM_EXT_ARGS
|
||||||
|
#endif
|
||||||
|
LWIP_ASSERT("Increase LWIP_TCP_PCB_NUM_EXT_ARGS in lwipopts.h", result < LWIP_TCP_PCB_NUM_EXT_ARGS);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup tcp_raw_extargs
|
||||||
|
* Set callbacks for a given index of ext_args on the specified pcb.
|
||||||
|
*
|
||||||
|
* @param pcb tcp_pcb for which to set the callback
|
||||||
|
* @param id ext_args index to set (allocated via @ref tcp_ext_arg_alloc_id)
|
||||||
|
* @param callbacks callback table (const since it is referenced, not copied!)
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
tcp_ext_arg_set_callbacks(struct tcp_pcb *pcb, uint8_t id, const struct tcp_ext_arg_callbacks * const callbacks)
|
||||||
|
{
|
||||||
|
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
||||||
|
LWIP_ASSERT("id < LWIP_TCP_PCB_NUM_EXT_ARGS", id < LWIP_TCP_PCB_NUM_EXT_ARGS);
|
||||||
|
LWIP_ASSERT("callbacks != NULL", callbacks != NULL);
|
||||||
|
|
||||||
|
LWIP_ASSERT_CORE_LOCKED();
|
||||||
|
|
||||||
|
pcb->ext_args[id].callbacks = callbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup tcp_raw_extargs
|
||||||
|
* Set data for a given index of ext_args on the specified pcb.
|
||||||
|
*
|
||||||
|
* @param pcb tcp_pcb for which to set the data
|
||||||
|
* @param id ext_args index to set (allocated via @ref tcp_ext_arg_alloc_id)
|
||||||
|
* @param arg data pointer to set
|
||||||
|
*/
|
||||||
|
void tcp_ext_arg_set(struct tcp_pcb *pcb, uint8_t id, void *arg)
|
||||||
|
{
|
||||||
|
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
||||||
|
LWIP_ASSERT("id < LWIP_TCP_PCB_NUM_EXT_ARGS", id < LWIP_TCP_PCB_NUM_EXT_ARGS);
|
||||||
|
|
||||||
|
LWIP_ASSERT_CORE_LOCKED();
|
||||||
|
|
||||||
|
pcb->ext_args[id].data = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup tcp_raw_extargs
|
||||||
|
* Set data for a given index of ext_args on the specified pcb.
|
||||||
|
*
|
||||||
|
* @param pcb tcp_pcb for which to set the data
|
||||||
|
* @param id ext_args index to set (allocated via @ref tcp_ext_arg_alloc_id)
|
||||||
|
* @return data pointer at the given index
|
||||||
|
*/
|
||||||
|
void *tcp_ext_arg_get(const struct tcp_pcb *pcb, uint8_t id)
|
||||||
|
{
|
||||||
|
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
||||||
|
LWIP_ASSERT("id < LWIP_TCP_PCB_NUM_EXT_ARGS", id < LWIP_TCP_PCB_NUM_EXT_ARGS);
|
||||||
|
|
||||||
|
LWIP_ASSERT_CORE_LOCKED();
|
||||||
|
|
||||||
|
return pcb->ext_args[id].data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This function calls the "destroy" callback for all ext_args once a pcb is
|
||||||
|
* freed.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
tcp_ext_arg_invoke_callbacks_destroyed(struct tcp_pcb_ext_args *ext_args)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
LWIP_ASSERT("ext_args != NULL", ext_args != NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < LWIP_TCP_PCB_NUM_EXT_ARGS; i++) {
|
||||||
|
if (ext_args[i].callbacks != NULL) {
|
||||||
|
if (ext_args[i].callbacks->destroy != NULL) {
|
||||||
|
ext_args[i].callbacks->destroy((u8_t)i, ext_args[i].data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This function calls the "passive_open" callback for all ext_args if a connection
|
||||||
|
* is in the process of being accepted. This is called just after the SYN is
|
||||||
|
* received and before a SYN/ACK is sent, to allow to modify the very first
|
||||||
|
* segment sent even on passive open. Naturally, the "accepted" callback of the
|
||||||
|
* pcb has not been called yet!
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
tcp_ext_arg_invoke_callbacks_passive_open(struct tcp_pcb_listen *lpcb, struct tcp_pcb *cpcb)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
LWIP_ASSERT("lpcb != NULL", lpcb != NULL);
|
||||||
|
LWIP_ASSERT("cpcb != NULL", cpcb != NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < LWIP_TCP_PCB_NUM_EXT_ARGS; i++) {
|
||||||
|
if (lpcb->ext_args[i].callbacks != NULL) {
|
||||||
|
if (lpcb->ext_args[i].callbacks->passive_open != NULL) {
|
||||||
|
err_t err = lpcb->ext_args[i].callbacks->passive_open((u8_t)i, lpcb, cpcb);
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
#endif /* LWIP_TCP_PCB_NUM_EXT_ARGS */
|
||||||
|
|
||||||
#endif /* LWIP_TCP */
|
#endif /* LWIP_TCP */
|
||||||
|
@ -680,6 +680,13 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
|||||||
|
|
||||||
MIB2_STATS_INC(mib2.tcppassiveopens);
|
MIB2_STATS_INC(mib2.tcppassiveopens);
|
||||||
|
|
||||||
|
#if LWIP_TCP_PCB_NUM_EXT_ARGS
|
||||||
|
if (tcp_ext_arg_invoke_callbacks_passive_open(pcb, npcb) != ERR_OK) {
|
||||||
|
tcp_abandon(npcb, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Send a SYN|ACK together with the MSS option. */
|
/* Send a SYN|ACK together with the MSS option. */
|
||||||
rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
|
rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
|
||||||
if (rc != ERR_OK) {
|
if (rc != ERR_OK) {
|
||||||
|
@ -1465,6 +1465,15 @@
|
|||||||
#define TCP_RCV_SCALE 0
|
#define TCP_RCV_SCALE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_TCP_PCB_NUM_EXT_ARGS:
|
||||||
|
* When this is > 0, every tcp pcb (including listen pcb) includes a number of
|
||||||
|
* additional argument entries in an array (see tcp_ext_arg_alloc_id)
|
||||||
|
*/
|
||||||
|
#if !defined LWIP_TCP_PCB_NUM_EXT_ARGS || defined __DOXYGEN__
|
||||||
|
#define LWIP_TCP_PCB_NUM_EXT_ARGS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/** LWIP_ALTCP==1: enable the altcp API
|
/** LWIP_ALTCP==1: enable the altcp API
|
||||||
* altcp is an abstraction layer that prevents applications linking against the
|
* altcp is an abstraction layer that prevents applications linking against the
|
||||||
* tcp.h functions but provides the same functionality. It is used to e.g. add
|
* tcp.h functions but provides the same functionality. It is used to e.g. add
|
||||||
|
@ -508,6 +508,10 @@ void tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_a
|
|||||||
void tcp_free_ooseq(struct tcp_pcb *pcb);
|
void tcp_free_ooseq(struct tcp_pcb *pcb);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LWIP_TCP_PCB_NUM_EXT_ARGS
|
||||||
|
err_t tcp_ext_arg_invoke_callbacks_passive_open(struct tcp_pcb_listen *lpcb, struct tcp_pcb *cpcb);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,6 +56,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct tcp_pcb;
|
struct tcp_pcb;
|
||||||
|
struct tcp_pcb_listen;
|
||||||
|
|
||||||
/** Function prototype for tcp accept callback functions. Called when a new
|
/** Function prototype for tcp accept callback functions. Called when a new
|
||||||
* connection can be accepted on a listening pcb.
|
* connection can be accepted on a listening pcb.
|
||||||
@ -163,6 +164,45 @@ struct tcp_sack_range {
|
|||||||
};
|
};
|
||||||
#endif /* LWIP_TCP_SACK_OUT */
|
#endif /* LWIP_TCP_SACK_OUT */
|
||||||
|
|
||||||
|
/** Function prototype for deallocation of arguments. Called *just before* the
|
||||||
|
* pcb is freed, so don't expect to be able to do anything with this pcb!
|
||||||
|
*
|
||||||
|
* @param id ext arg id (allocated via @ref tcp_ext_arg_alloc_id)
|
||||||
|
* @param data pointer to the data (set via @ref tcp_ext_arg_set before)
|
||||||
|
*/
|
||||||
|
typedef void (*tcp_extarg_callback_pcb_destroyed_fn)(u8_t id, void *data);
|
||||||
|
|
||||||
|
/** Function prototype to transition arguments from a listening pcb to an accepted pcb
|
||||||
|
*
|
||||||
|
* @param id ext arg id (allocated via @ref tcp_ext_arg_alloc_id)
|
||||||
|
* @param lpcb the listening pcb accepting a connection
|
||||||
|
* @param cpcb the newly allocated connection pcb
|
||||||
|
* @param ERR_OK if OK, any error if connection should be dropped
|
||||||
|
*/
|
||||||
|
typedef err_t (*tcp_extarg_callback_passive_open_fn)(u8_t id, struct tcp_pcb_listen *lpcb, struct tcp_pcb *cpcb);
|
||||||
|
|
||||||
|
/** A table of callback functions that is invoked for ext arguments */
|
||||||
|
struct tcp_ext_arg_callbacks {
|
||||||
|
/** @ref tcp_extarg_callback_pcb_destroyed_fn */
|
||||||
|
tcp_extarg_callback_pcb_destroyed_fn destroy;
|
||||||
|
/** @ref tcp_extarg_callback_passive_open_fn */
|
||||||
|
tcp_extarg_callback_passive_open_fn passive_open;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LWIP_TCP_PCB_NUM_EXT_ARG_ID_INVALID 0xFF
|
||||||
|
|
||||||
|
#if LWIP_TCP_PCB_NUM_EXT_ARGS
|
||||||
|
/* This is the structure for ext args in tcp pcbs (used as array) */
|
||||||
|
struct tcp_pcb_ext_args {
|
||||||
|
const struct tcp_ext_arg_callbacks *callbacks;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
/* This is a helper define to prevent zero size arrays if disabled */
|
||||||
|
#define TCP_PCB_EXTARGS struct tcp_pcb_ext_args ext_args[LWIP_TCP_PCB_NUM_EXT_ARGS];
|
||||||
|
#else
|
||||||
|
#define TCP_PCB_EXTARGS
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef u16_t tcpflags_t;
|
typedef u16_t tcpflags_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -171,6 +211,7 @@ typedef u16_t tcpflags_t;
|
|||||||
#define TCP_PCB_COMMON(type) \
|
#define TCP_PCB_COMMON(type) \
|
||||||
type *next; /* for the linked list */ \
|
type *next; /* for the linked list */ \
|
||||||
void *callback_arg; \
|
void *callback_arg; \
|
||||||
|
TCP_PCB_EXTARGS \
|
||||||
enum tcp_state state; /* TCP state */ \
|
enum tcp_state state; /* TCP state */ \
|
||||||
u8_t prio; \
|
u8_t prio; \
|
||||||
/* ports are in host byte order */ \
|
/* ports are in host byte order */ \
|
||||||
@ -442,6 +483,13 @@ err_t tcp_tcp_get_tcp_addrinfo(struct tcp_pcb *pcb, int local, ip_add
|
|||||||
/* for compatibility with older implementation */
|
/* for compatibility with older implementation */
|
||||||
#define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6)
|
#define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6)
|
||||||
|
|
||||||
|
#if LWIP_TCP_PCB_NUM_EXT_ARGS
|
||||||
|
u8_t tcp_ext_arg_alloc_id(void);
|
||||||
|
void tcp_ext_arg_set_callbacks(struct tcp_pcb *pcb, uint8_t id, const struct tcp_ext_arg_callbacks * const callbacks);
|
||||||
|
void tcp_ext_arg_set(struct tcp_pcb *pcb, uint8_t id, void *arg);
|
||||||
|
void *tcp_ext_arg_get(const struct tcp_pcb *pcb, uint8_t id);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user