This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 143d1322ea Added handling of MSG_WAITALL flag in TCP recv.
143d1322ea is described below
commit 143d1322eab11062da12fb0d5ebc246bea96a01f
Author: Fotis Panagiotopoulos <[email protected]>
AuthorDate: Tue Oct 11 20:40:56 2022 +0300
Added handling of MSG_WAITALL flag in TCP recv.
---
net/devif/devif.h | 1 +
net/tcp/tcp_recvfrom.c | 41 ++++++++++++++++++-----------------------
2 files changed, 19 insertions(+), 23 deletions(-)
diff --git a/net/devif/devif.h b/net/devif/devif.h
index e78f7b5b4e..4393e4be1a 100644
--- a/net/devif/devif.h
+++ b/net/devif/devif.h
@@ -188,6 +188,7 @@
#define TCP_ABORT (1 << 7)
#define TCP_CONNECTED (1 << 8)
#define TCP_TIMEDOUT (1 << 9)
+#define TCP_WAITALL (1 << 10)
/* Bits 10-11: Unused, available */
diff --git a/net/tcp/tcp_recvfrom.c b/net/tcp/tcp_recvfrom.c
index a32a7fef71..c217ea6596 100644
--- a/net/tcp/tcp_recvfrom.c
+++ b/net/tcp/tcp_recvfrom.c
@@ -412,7 +412,8 @@ static uint16_t tcp_recvhandler(FAR struct net_driver_s
*dev,
* next receive is performed.
*/
- if (pstate->ir_recvlen > 0)
+ if ((pstate->ir_recvlen > 0 && (flags & TCP_WAITALL) == 0) ||
+ pstate->ir_buflen == 0)
{
ninfo("TCP resume\n");
@@ -556,30 +557,20 @@ static void tcp_recvfrom_initialize(FAR struct tcp_conn_s
*conn,
static ssize_t tcp_recvfrom_result(int result, struct tcp_recvfrom_s *pstate)
{
- /* Check for a error/timeout detected by the event handler. Errors are
- * signaled by negative errno values for the rcv length
+ /* Check if any data were received. If so, then return their length and
+ * ignore any error codes.
*/
- if (pstate->ir_result < 0)
+ if (pstate->ir_recvlen > 0)
{
- /* This might return EAGAIN on a timeout or ENOTCONN on loss of
- * connection (TCP only)
- */
-
- return pstate->ir_result;
+ return pstate->ir_recvlen;
}
- /* If net_timedwait failed, then we were probably reawakened by a signal.
- * In this case, net_timedwait will have returned negated errno
- * appropriately.
+ /* If no data were received, return the error code instead. The event
+ * handler error is prioritized over any previous error.
*/
- if (result < 0)
- {
- return result;
- }
-
- return pstate->ir_recvlen;
+ return (pstate->ir_result <= 0) ? pstate->ir_result : result;
}
/****************************************************************************
@@ -698,15 +689,18 @@ ssize_t psock_tcp_recvfrom(FAR struct socket *psock, FAR
struct msghdr *msg,
/* We get here when we we decide that we need to setup the wait for
* incoming TCP/IP data. Just a few more conditions to check:
*
- * 1) Make sure thet there is buffer space to receive additional data
+ * 1) Make sure that there is buffer space to receive additional data
* (state.ir_buflen > 0). This could be zero, for example, we filled
* the user buffer with data from the read-ahead buffers. And
* 2) then we not want to wait if we already obtained some data from the
* read-ahead buffer. In that case, return now with what we have (don't
* want for more because there may be no timeout).
+ * 3) If however MSG_WAITALL flag is set, block here till all requested
+ * data are received (or there is a timeout / error).
*/
- if (state.ir_recvlen == 0 && state.ir_buflen > 0)
+ if (((flags & MSG_WAITALL) != 0 || state.ir_recvlen == 0) &&
+ state.ir_buflen > 0)
{
/* Set up the callback in the connection */
@@ -714,16 +708,17 @@ ssize_t psock_tcp_recvfrom(FAR struct socket *psock, FAR
struct msghdr *msg,
if (state.ir_cb)
{
state.ir_cb->flags = (TCP_NEWDATA | TCP_DISCONN_EVENTS);
+ state.ir_cb->flags |= (flags & MSG_WAITALL) ? TCP_WAITALL : 0;
state.ir_cb->priv = (FAR void *)&state;
state.ir_cb->event = tcp_recvhandler;
/* Wait for either the receive to complete or for an error/timeout
- * to occur. net_timedwait will also terminate if a signal isi
+ * to occur. net_timedwait will also terminate if a signal is
* received.
*/
ret = net_timedwait(&state.ir_sem,
- _SO_TIMEOUT(conn->sconn.s_rcvtimeo));
+ _SO_TIMEOUT(conn->sconn.s_rcvtimeo));
if (ret == -ETIMEDOUT)
{
ret = -EAGAIN;
@@ -734,7 +729,7 @@ ssize_t psock_tcp_recvfrom(FAR struct socket *psock, FAR
struct msghdr *msg,
tcp_callback_free(conn, state.ir_cb);
ret = tcp_recvfrom_result(ret, &state);
}
- else
+ else if (ret <= 0)
{
ret = -EBUSY;
}