Skip to content

Commit 78e8e0d

Browse files
rluboscarlescufi
authored andcommitted
net: sockets: Make use of the status field reported by TCP
Make use of the status field, reported by TCP, in the socket receive callback. This allows to differentiate a graceful connection shutdown from actual errors at TCP level (transmission timeout or RST received). In case of error reported from TCP layer, set a new SOCK_ERROR flag on the socket, and store the error code in the net_context user_data. Signed-off-by: Robert Lubos <[email protected]>
1 parent 0b27f4b commit 78e8e0d

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

subsys/net/lib/sockets/sockets.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ static void zsock_received_cb(struct net_context *ctx,
372372
NET_DBG("ctx=%p, pkt=%p, st=%d, user_data=%p", ctx, pkt, status,
373373
user_data);
374374

375+
if (status < 0) {
376+
ctx->user_data = INT_TO_POINTER(-status);
377+
sock_set_error(ctx);
378+
}
379+
375380
/* if pkt is NULL, EOF */
376381
if (!pkt) {
377382
struct net_pkt *last_pkt = k_fifo_peek_tail(&ctx->recv_q);
@@ -1188,7 +1193,7 @@ static inline ssize_t zsock_recv_stream(struct net_context *ctx,
11881193

11891194
if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
11901195
timeout = K_NO_WAIT;
1191-
} else if (!sock_is_eof(ctx)) {
1196+
} else if (!sock_is_eof(ctx) && !sock_is_error(ctx)) {
11921197
net_context_get_option(ctx, NET_OPT_RCVTIMEO, &timeout, NULL);
11931198
}
11941199

@@ -1199,6 +1204,11 @@ static inline ssize_t zsock_recv_stream(struct net_context *ctx,
11991204
size_t data_len, read_len;
12001205
bool release_pkt = true;
12011206

1207+
if (sock_is_error(ctx)) {
1208+
errno = POINTER_TO_INT(ctx->user_data);
1209+
return -1;
1210+
}
1211+
12021212
if (sock_is_eof(ctx)) {
12031213
return 0;
12041214
}
@@ -1220,6 +1230,9 @@ static inline ssize_t zsock_recv_stream(struct net_context *ctx,
12201230

12211231
if (waitall && (recv_len > 0)) {
12221232
return recv_len;
1233+
} else if (sock_is_error(ctx)) {
1234+
errno = POINTER_TO_INT(ctx->user_data);
1235+
return -1;
12231236
} else if (sock_is_eof(ctx)) {
12241237
return 0;
12251238
} else {
@@ -1400,10 +1413,10 @@ static int zsock_poll_prepare_ctx(struct net_context *ctx,
14001413
return -EALREADY;
14011414
}
14021415

1403-
/* If socket is already in EOF, it can be reported
1416+
/* If socket is already in EOF or error, it can be reported
14041417
* immediately, so we tell poll() to short-circuit wait.
14051418
*/
1406-
if (sock_is_eof(ctx)) {
1419+
if (sock_is_eof(ctx) || sock_is_error(ctx)) {
14071420
return -EALREADY;
14081421
}
14091422

@@ -1428,6 +1441,10 @@ static int zsock_poll_update_ctx(struct net_context *ctx,
14281441
(*pev)++;
14291442
}
14301443

1444+
if (sock_is_error(ctx)) {
1445+
pfd->revents |= ZSOCK_POLLERR;
1446+
}
1447+
14311448
if (sock_is_eof(ctx)) {
14321449
pfd->revents |= ZSOCK_POLLHUP;
14331450
}

subsys/net/lib/sockets/sockets_internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#define SOCK_EOF 1
1313
#define SOCK_NONBLOCK 2
14+
#define SOCK_ERROR 4
1415

1516
int zsock_close_ctx(struct net_context *ctx);
1617
int zsock_poll_internal(struct zsock_pollfd *fds, int nfds, k_timeout_t timeout);
@@ -47,6 +48,8 @@ static inline bool net_socket_is_tls(void *obj)
4748
#define sock_is_eof(ctx) sock_get_flag(ctx, SOCK_EOF)
4849
#define sock_set_eof(ctx) sock_set_flag(ctx, SOCK_EOF, SOCK_EOF)
4950
#define sock_is_nonblock(ctx) sock_get_flag(ctx, SOCK_NONBLOCK)
51+
#define sock_is_error(ctx) sock_get_flag(ctx, SOCK_ERROR)
52+
#define sock_set_error(ctx) sock_set_flag(ctx, SOCK_ERROR, SOCK_ERROR)
5053

5154
struct socket_op_vtable {
5255
struct fd_op_vtable fd_vtable;

0 commit comments

Comments
 (0)