started to implement fullduplex sockets/netconns (note that this is highly unstable yet!)

This commit is contained in:
sg 2015-02-11 21:18:15 +01:00
parent 04b4971d8c
commit 7ff9825f55
3 changed files with 67 additions and 4 deletions

View File

@ -6,6 +6,10 @@ HISTORY
++ New features:
2015-02-11: Simon Goldschmidt
* api_msg.c, opt.h: started to implement fullduplex sockets/netconns
(note that this is highly unstable yet!)
2015-01-02: Simon Goldschmidt
* tcp.c: tcp_kill_prio(): prefer nearly-closed connections (waiting for the
last ACK only) over established connections when out of tcp pcbs

View File

@ -960,11 +960,34 @@ lwip_netconn_do_delconn(struct api_msg_msg *msg)
enum netconn_state state = msg->conn->state;
LWIP_ASSERT("netconn state error", /* this only happens for TCP netconns */
(state == NETCONN_NONE) || (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP));
if ((msg->conn->state != NETCONN_NONE) &&
#if LWIP_NETCONN_FULLDUPLEX
/* In full duplex mode, blocking write/connect is aborted with ERR_CLSD */
if (state != NETCONN_NONE) {
if ((state == NETCONN_WRITE) ||
((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) {
/* close requested, abort running write/connect */
sys_sem_t* op_completed_sem;
LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL);
op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg);
msg->conn->current_msg->err = ERR_CLSD;
msg->conn->current_msg = NULL;
msg->conn->write_offset = 0;
msg->conn->state = NETCONN_NONE;
msg->conn->flags &= ~NETCONN_FLAG_WRITE_DELAYED;
sys_sem_signal(op_completed_sem);
}
}
#else /* LWIP_NETCONN_FULLDUPLEX */
if (((msg->conn->state != NETCONN_NONE) &&
(msg->conn->state != NETCONN_LISTEN) &&
(msg->conn->state != NETCONN_CONNECT)) {
(msg->conn->state != NETCONN_CONNECT)) ||
(msg->conn->state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn)) {
/* This means either a blocking write or blocking connect is running
(nonblocking write returns and sets state to NONE) */
msg->err = ERR_INPROGRESS;
} else {
} else
#endif /* LWIP_NETCONN_FULLDUPLEX */
{
LWIP_ASSERT("blocking connect in progress",
(msg->conn->state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn));
msg->err = ERR_OK;
@ -1642,8 +1665,32 @@ lwip_netconn_do_close(struct api_msg_msg *msg)
if ((msg->conn->pcb.tcp != NULL) &&
(NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) &&
((msg->msg.sd.shut == NETCONN_SHUT_RDWR) || (state != NETCONN_LISTEN))) {
if ((state == NETCONN_CONNECT) || (state == NETCONN_WRITE)) {
/* Check if we are in a connected state */
if (state == NETCONN_CONNECT) {
/* TCP connect in progress: cannot shutdown */
msg->err = ERR_CONN;
} else if (state == NETCONN_WRITE) {
#if LWIP_NETCONN_FULLDUPLEX
if (msg->msg.sd.shut & NETCONN_SHUT_WR) {
/* close requested, abort running write */
sys_sem_t* op_completed_sem;
LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL);
op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg);
msg->conn->current_msg->err = ERR_CLSD;
msg->conn->current_msg = NULL;
msg->conn->write_offset = 0;
msg->conn->state = NETCONN_NONE;
msg->conn->flags &= ~NETCONN_FLAG_WRITE_DELAYED;
sys_sem_signal(op_completed_sem);
} else {
LWIP_ASSERT("msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD);
/* In this case, let the write continue and do not interfere with
conn->current_msg or conn->state! */
msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0);
}
#else /* LWIP_NETCONN_FULLDUPLEX */
msg->err = ERR_INPROGRESS;
#endif /* LWIP_NETCONN_FULLDUPLEX */
} else {
if (msg->msg.sd.shut & NETCONN_SHUT_RD) {
/* Drain and delete mboxes */

View File

@ -1497,6 +1497,18 @@
#define LWIP_NETCONN_SEM_PER_THREAD 0
#endif
/** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread,
* writing from a 2nd thread and closing from a 3rd thread at the same time.
* ATTENTION: This is currently really alpha! Some requirements:
* - LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from
* multiple threads at once
* - sys_mbox_free() has to unblock receive tasks waiting on recvmbox/acceptmbox
* and prevent a task pending on this during/after deletion
*/
#ifndef LWIP_NETCONN_FULLDUPLEX
#define LWIP_NETCONN_FULLDUPLEX 0
#endif
/*
------------------------------------
---------- Socket options ----------