VFS LwIP: state tracking fixes
Better track the state of TCP connections and PCB pointers. Allow received data that has queued to be read under any conditions. Ref #2335
This commit is contained in:
parent
67d88526b9
commit
ffd688642a
|
@ -1050,7 +1050,8 @@ class Lwip::Tcp_socket_dir final :
|
||||||
destroy(alloc, p);
|
destroy(alloc, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state != CLOSED && _pcb != NULL) {
|
if (_pcb != NULL) {
|
||||||
|
tcp_arg(_pcb, NULL);
|
||||||
tcp_close(_pcb);
|
tcp_close(_pcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1095,8 +1096,13 @@ class Lwip::Tcp_socket_dir final :
|
||||||
void error()
|
void error()
|
||||||
{
|
{
|
||||||
state = CLOSED;
|
state = CLOSED;
|
||||||
|
|
||||||
/* the PCB is expired now */
|
/* the PCB is expired now */
|
||||||
_pcb = NULL;
|
if (_pcb) {
|
||||||
|
tcp_arg(_pcb, NULL);
|
||||||
|
tcp_close(_pcb);
|
||||||
|
_pcb = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* churn the application */
|
/* churn the application */
|
||||||
handle_io(~0U);
|
handle_io(~0U);
|
||||||
|
@ -1113,11 +1119,12 @@ class Lwip::Tcp_socket_dir final :
|
||||||
if (_recv_pbuf)
|
if (_recv_pbuf)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tcp_close(_pcb);
|
if (_pcb) {
|
||||||
tcp_arg(_pcb, NULL);
|
tcp_arg(_pcb, NULL);
|
||||||
state = CLOSED;
|
tcp_close(_pcb);
|
||||||
/* lwIP may reuse the PCB memory for the next connection */
|
state = CLOSED;
|
||||||
_pcb = NULL;
|
_pcb = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************
|
/**************************
|
||||||
|
@ -1174,15 +1181,19 @@ class Lwip::Tcp_socket_dir final :
|
||||||
char *dst, file_size count,
|
char *dst, file_size count,
|
||||||
file_size &out_count) override
|
file_size &out_count) override
|
||||||
{
|
{
|
||||||
if (_pcb == NULL)
|
|
||||||
return Read_result::READ_OK;
|
|
||||||
|
|
||||||
switch(handle.kind) {
|
switch(handle.kind) {
|
||||||
|
|
||||||
case Lwip_file_handle::DATA:
|
case Lwip_file_handle::DATA:
|
||||||
if (state == READY || state == CLOSING) {
|
{
|
||||||
if (_recv_pbuf == nullptr) {
|
if (_recv_pbuf == nullptr) {
|
||||||
return Read_result::READ_QUEUED;
|
/*
|
||||||
|
* queue the read if the PCB is active and
|
||||||
|
* there is nothing to read, otherwise return
|
||||||
|
* zero to indicate the connection is closed
|
||||||
|
*/
|
||||||
|
return (state == READY)
|
||||||
|
? Read_result::READ_QUEUED
|
||||||
|
: Read_result::READ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16_t const ucount = count;
|
u16_t const ucount = count;
|
||||||
|
@ -1205,15 +1216,14 @@ class Lwip::Tcp_socket_dir final :
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ACK the remote */
|
/* ACK the remote */
|
||||||
tcp_recved(_pcb, n);
|
if (_pcb)
|
||||||
|
tcp_recved(_pcb, n);
|
||||||
|
|
||||||
if (state == CLOSING)
|
if (state == CLOSING)
|
||||||
shutdown();
|
shutdown();
|
||||||
|
|
||||||
out_count = n;
|
out_count = n;
|
||||||
return Read_result::READ_OK;
|
return Read_result::READ_OK;
|
||||||
} else if (state == CLOSED) {
|
|
||||||
return Read_result::READ_OK;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1443,12 +1453,15 @@ namespace Lwip {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
static
|
static
|
||||||
void udp_recv_callback(void *arg, struct udp_pcb*, struct pbuf *p, const ip_addr_t *addr, u16_t port)
|
void udp_recv_callback(void *arg, struct udp_pcb*, struct pbuf *buf, const ip_addr_t *addr, u16_t port)
|
||||||
{
|
{
|
||||||
if (!arg) return;
|
if (arg) {
|
||||||
|
Lwip::Udp_socket_dir *socket_dir =
|
||||||
Lwip::Udp_socket_dir *socket_dir = static_cast<Lwip::Udp_socket_dir *>(arg);
|
static_cast<Lwip::Udp_socket_dir *>(arg);
|
||||||
socket_dir->queue(addr, port, p);
|
socket_dir->queue(addr, port, buf);
|
||||||
|
} else {
|
||||||
|
pbuf_free(buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1456,8 +1469,8 @@ static
|
||||||
err_t tcp_connect_callback(void *arg, struct tcp_pcb *pcb, err_t)
|
err_t tcp_connect_callback(void *arg, struct tcp_pcb *pcb, err_t)
|
||||||
{
|
{
|
||||||
if (!arg) {
|
if (!arg) {
|
||||||
tcp_close(pcb);
|
tcp_abort(pcb);
|
||||||
return ERR_ARG;
|
return ERR_ABRT;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lwip::Tcp_socket_dir *socket_dir = static_cast<Lwip::Tcp_socket_dir *>(arg);
|
Lwip::Tcp_socket_dir *socket_dir = static_cast<Lwip::Tcp_socket_dir *>(arg);
|
||||||
|
@ -1474,8 +1487,8 @@ static
|
||||||
err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err)
|
err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||||
{
|
{
|
||||||
if (!arg) {
|
if (!arg) {
|
||||||
tcp_close(newpcb);
|
tcp_abort(newpcb);
|
||||||
return ERR_OK;
|
return ERR_ABRT;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lwip::Tcp_socket_dir *socket_dir = static_cast<Lwip::Tcp_socket_dir *>(arg);
|
Lwip::Tcp_socket_dir *socket_dir = static_cast<Lwip::Tcp_socket_dir *>(arg);
|
||||||
|
@ -1485,9 +1498,12 @@ err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
err_t tcp_recv_callback(void *arg, struct tcp_pcb*, struct pbuf *p, err_t)
|
err_t tcp_recv_callback(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t)
|
||||||
{
|
{
|
||||||
if (!arg) return ERR_ARG;
|
if (!arg) {
|
||||||
|
tcp_abort(pcb);
|
||||||
|
return ERR_ABRT;
|
||||||
|
}
|
||||||
|
|
||||||
Lwip::Tcp_socket_dir *socket_dir = static_cast<Lwip::Tcp_socket_dir *>(arg);
|
Lwip::Tcp_socket_dir *socket_dir = static_cast<Lwip::Tcp_socket_dir *>(arg);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
|
@ -1501,8 +1517,13 @@ err_t tcp_recv_callback(void *arg, struct tcp_pcb*, struct pbuf *p, err_t)
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
err_t tcp_delayed_recv_callback(void *arg, struct tcp_pcb*, struct pbuf *buf, err_t)
|
err_t tcp_delayed_recv_callback(void *arg, struct tcp_pcb *pcb, struct pbuf *buf, err_t)
|
||||||
{
|
{
|
||||||
|
if (!arg) {
|
||||||
|
tcp_abort(pcb);
|
||||||
|
return ERR_ABRT;
|
||||||
|
}
|
||||||
|
|
||||||
Lwip::Tcp_socket_dir::Pcb_pending *pending =
|
Lwip::Tcp_socket_dir::Pcb_pending *pending =
|
||||||
static_cast<Lwip::Tcp_socket_dir::Pcb_pending *>(arg);
|
static_cast<Lwip::Tcp_socket_dir::Pcb_pending *>(arg);
|
||||||
|
|
||||||
|
@ -1516,11 +1537,17 @@ err_t tcp_delayed_recv_callback(void *arg, struct tcp_pcb*, struct pbuf *buf, er
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
|
* This would be the ACK callback, we could defer sync completion
|
||||||
|
* until then, but performance is expected to be unacceptable.
|
||||||
|
*
|
||||||
static
|
static
|
||||||
err_t tcp_sent_callback(void *arg, struct tcp_pcb*, u16_t len)
|
err_t tcp_sent_callback(void *arg, struct tcp_pcb*, u16_t len)
|
||||||
{
|
{
|
||||||
if (!arg) return ERR_ARG;
|
if (!arg) {
|
||||||
|
tcp_abort(pcb);
|
||||||
|
return ERR_ABRT;
|
||||||
|
}
|
||||||
|
|
||||||
Lwip::Tcp_socket_dir *socket_dir = static_cast<Lwip::Tcp_socket_dir *>(arg);
|
Lwip::Tcp_socket_dir *socket_dir = static_cast<Lwip::Tcp_socket_dir *>(arg);
|
||||||
socket_dir->pending_ack -= len;
|
socket_dir->pending_ack -= len;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user