sockets: remove sock->lastoffset and free unused pbufs instead (using pbuf_free_header)

This commit is contained in:
goldsimon 2017-03-06 21:54:50 +01:00
parent 49414826af
commit 30be7b582e

View File

@ -200,14 +200,17 @@ static void sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t*
#define SELWAIT_T u8_t #define SELWAIT_T u8_t
#endif #endif
union lwip_sock_lastdata {
struct netbuf *netbuf;
struct pbuf *pbuf;
};
/** Contains all internal pointers and states used for a socket */ /** Contains all internal pointers and states used for a socket */
struct lwip_sock { struct lwip_sock {
/** sockets currently are built on netconns, each socket has one netconn */ /** sockets currently are built on netconns, each socket has one netconn */
struct netconn *conn; struct netconn *conn;
/** data that was left from the previous read */ /** data that was left from the previous read */
void *lastdata; union lwip_sock_lastdata lastdata;
/** offset in the data that was left from the previous read */
u16_t lastoffset;
/** number of times data was received, set by event_callback(), /** number of times data was received, set by event_callback(),
tested by the receive and select functions */ tested by the receive and select functions */
s16_t rcvevent; s16_t rcvevent;
@ -466,8 +469,7 @@ alloc_socket(struct netconn *newconn, int accepted)
/* The socket is not yet known to anyone, so no need to protect /* The socket is not yet known to anyone, so no need to protect
after having marked it as used. */ after having marked it as used. */
SYS_ARCH_UNPROTECT(lev); SYS_ARCH_UNPROTECT(lev);
sockets[i].lastdata = NULL; sockets[i].lastdata.pbuf = NULL;
sockets[i].lastoffset = 0;
sockets[i].rcvevent = 0; sockets[i].rcvevent = 0;
/* TCP sendbuf is empty, but the socket is not yet writable until connected /* TCP sendbuf is empty, but the socket is not yet writable until connected
* (unless it has been created by accept()). */ * (unless it has been created by accept()). */
@ -490,7 +492,7 @@ alloc_socket(struct netconn *newconn, int accepted)
static void static void
free_socket(struct lwip_sock *sock, int is_tcp) free_socket(struct lwip_sock *sock, int is_tcp)
{ {
void *lastdata; union lwip_sock_lastdata lastdata;
SYS_ARCH_DECL_PROTECT(lev); SYS_ARCH_DECL_PROTECT(lev);
/* Protect socket array */ /* Protect socket array */
@ -506,18 +508,17 @@ free_socket(struct lwip_sock *sock, int is_tcp)
#endif #endif
lastdata = sock->lastdata; lastdata = sock->lastdata;
sock->lastdata = NULL; sock->lastdata.pbuf = NULL;
sock->lastoffset = 0;
sock->err = 0; sock->err = 0;
sock->conn = NULL; sock->conn = NULL;
SYS_ARCH_UNPROTECT(lev); SYS_ARCH_UNPROTECT(lev);
/* don't use 'sock' after this line, as another task might have allocated it */ /* don't use 'sock' after this line, as another task might have allocated it */
if (lastdata != NULL) { if (lastdata.pbuf != NULL) {
if (is_tcp) { if (is_tcp) {
pbuf_free((struct pbuf *)lastdata); pbuf_free(lastdata.pbuf);
} else { } else {
netbuf_delete((struct netbuf *)lastdata); netbuf_delete(lastdata.netbuf);
} }
} }
} }
@ -688,7 +689,7 @@ lwip_close(int s)
if (sock->conn != NULL) { if (sock->conn != NULL) {
is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP; is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP;
} else { } else {
LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL); LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata.pbuf == NULL);
} }
#if LWIP_IGMP #if LWIP_IGMP
@ -834,10 +835,10 @@ lwip_recv_tcp(struct lwip_sock *sock, void *mem, size_t len, int flags)
err_t err; err_t err;
u16_t copylen; u16_t copylen;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recv_tcp: top while sock->lastdata=%p\n", sock->lastdata)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recv_tcp: top while sock->lastdata=%p\n", sock->lastdata.pbuf));
/* Check if there is data left from the last recv operation. */ /* Check if there is data left from the last recv operation. */
if (sock->lastdata) { if (sock->lastdata.pbuf) {
p = (struct pbuf *)sock->lastdata; p = sock->lastdata.pbuf;
} else { } else {
/* No data was left from the previous operation, so we try to get /* No data was left from the previous operation, so we try to get
some from the network. */ some from the network. */
@ -871,7 +872,7 @@ lwip_recv_tcp(struct lwip_sock *sock, void *mem, size_t len, int flags)
} }
} }
LWIP_ASSERT("p != NULL", p != NULL); LWIP_ASSERT("p != NULL", p != NULL);
sock->lastdata = p; sock->lastdata.pbuf = p;
} }
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recv_tcp: buflen=%"U16_F" len=%"SZT_F" off=%d\n", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recv_tcp: buflen=%"U16_F" len=%"SZT_F" off=%d\n",
@ -900,11 +901,10 @@ lwip_recv_tcp(struct lwip_sock *sock, void *mem, size_t len, int flags)
if (p->tot_len - copylen > 0) { if (p->tot_len - copylen > 0) {
/* If so, it should be saved in the sock structure for the next recv call. /* If so, it should be saved in the sock structure for the next recv call.
We store the pbuf but hide/free the consumed data: */ We store the pbuf but hide/free the consumed data: */
sock->lastdata = p; sock->lastdata.pbuf = pbuf_free_header(p, copylen);
sock->lastoffset += copylen; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recv_tcp: lastdata now pbuf=%p\n", sock->lastdata.pbuf));
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recv_tcp: lastdata now pbuf=%p\n", sock->lastdata));
} else { } else {
sock->lastdata = NULL; sock->lastdata.pbuf = NULL;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recv_tcp: deleting pbuf=%p\n", p)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recv_tcp: deleting pbuf=%p\n", p));
pbuf_free(p); pbuf_free(p);
} }
@ -986,7 +986,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom[UDP/RAW]: top sock->lastdata=%p\n", sock->lastdata)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom[UDP/RAW]: top sock->lastdata=%p\n", sock->lastdata));
/* Check if there is data left from the last recv operation. */ /* Check if there is data left from the last recv operation. */
buf = (struct netbuf *)sock->lastdata; buf = sock->lastdata.netbuf;
if (buf == NULL) { if (buf == NULL) {
/* No data was left from the previous operation, so we try to get /* No data was left from the previous operation, so we try to get
some from the network. */ some from the network. */
@ -1002,7 +1002,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
return -1; return -1;
} }
LWIP_ASSERT("buf != NULL", buf != NULL); LWIP_ASSERT("buf != NULL", buf != NULL);
sock->lastdata = buf; sock->lastdata.netbuf = buf;
} }
buflen = buf->p->tot_len; buflen = buf->p->tot_len;
@ -1032,7 +1032,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
/* If we don't peek the incoming message: zero lastdata pointer and free the netbuf */ /* If we don't peek the incoming message: zero lastdata pointer and free the netbuf */
if ((flags & MSG_PEEK) == 0) { if ((flags & MSG_PEEK) == 0) {
sock->lastdata = NULL; sock->lastdata.netbuf = NULL;
netbuf_delete(buf); netbuf_delete(buf);
} }
} }
@ -1450,7 +1450,7 @@ lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *excep
SYS_ARCH_PROTECT(lev); SYS_ARCH_PROTECT(lev);
sock = tryget_socket_unconn(i); sock = tryget_socket_unconn(i);
if (sock != NULL) { if (sock != NULL) {
void* lastdata = sock->lastdata; void* lastdata = sock->lastdata.pbuf;
s16_t rcvevent = sock->rcvevent; s16_t rcvevent = sock->rcvevent;
u16_t sendevent = sock->sendevent; u16_t sendevent = sock->sendevent;
u16_t errevent = sock->errevent; u16_t errevent = sock->errevent;
@ -2857,7 +2857,6 @@ lwip_ioctl(int s, long cmd, void *argp)
struct lwip_sock *sock = get_socket(s); struct lwip_sock *sock = get_socket(s);
u8_t val; u8_t val;
#if LWIP_SO_RCVBUF #if LWIP_SO_RCVBUF
u16_t buflen = 0;
int recv_avail; int recv_avail;
#endif /* LWIP_SO_RCVBUF */ #endif /* LWIP_SO_RCVBUF */
@ -2875,18 +2874,17 @@ lwip_ioctl(int s, long cmd, void *argp)
} }
#if LWIP_FIONREAD_LINUXMODE #if LWIP_FIONREAD_LINUXMODE
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
struct pbuf *p; struct netbuf *nb;
if (sock->lastdata) { if (sock->lastdata.netbuf) {
p = ((struct netbuf *)sock->lastdata)->p; nb = sock->lastdata.netbuf;
*((int*)argp) = p->tot_len - sock->lastoffset; *((int*)argp) = nb->p->tot_len;
} else { } else {
struct netbuf *rxbuf; struct netbuf *rxbuf;
err_t err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK); err_t err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK);
if (err != ERR_OK) { if (err != ERR_OK) {
*((int*)argp) = 0; *((int*)argp) = 0;
} else { } else {
sock->lastdata = rxbuf; sock->lastdata.netbuf = rxbuf;
sock->lastoffset = 0;
*((int*)argp) = rxbuf->p->tot_len; *((int*)argp) = rxbuf->p->tot_len;
} }
} }
@ -2901,19 +2899,16 @@ lwip_ioctl(int s, long cmd, void *argp)
if (recv_avail < 0) { if (recv_avail < 0) {
recv_avail = 0; recv_avail = 0;
} }
*((int*)argp) = recv_avail;
/* Check if there is data left from the last recv operation. /maq 041215 */ /* Check if there is data left from the last recv operation. /maq 041215 */
if (sock->lastdata) { if (sock->lastdata.netbuf) {
struct pbuf *p = (struct pbuf *)sock->lastdata;
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
p = ((struct netbuf *)p)->p; recv_avail += sock->lastdata.pbuf->tot_len;
} else {
recv_avail += sock->lastdata.netbuf->p->tot_len;
} }
buflen = p->tot_len;
buflen -= sock->lastoffset;
*((int*)argp) += buflen;
} }
*((int*)argp) = recv_avail;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
sock_set_errno(sock, 0); sock_set_errno(sock, 0);