aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2023-08-04 17:26:48 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2023-08-07 19:16:24 +0200
commit3ee52742656066e60cbddd8a841d077d802c028f (patch)
tree965f657faf0951503ca2e56c5b7ab21b749a5d3b
parenta69a958ae38c289f068d91b073015c90ee5ff514 (diff)
stream_srv: Handle ESHUTDOWN and other write() errors destroying the socket
If internal send() fails with a fatal error, it should destroy the socket. The user will know about the event through the close_cb() called during osmo_stream_srv_destroy(). As a result, the socket is not closed when receiving SHUTDOWN by the peer (through SCTP MSG_NOTIFICATION), but keep it alive since the socket can still keep receiving data from the peer. Only fail if write() to that read-only socket is attempted. Related: OS#6134 Change-Id: I84ddebabdffe47733cb529bcfebec8757e6a172b
-rw-r--r--src/stream_srv.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/src/stream_srv.c b/src/stream_srv.c
index be43a80..cccb811 100644
--- a/src/stream_srv.c
+++ b/src/stream_srv.c
@@ -588,8 +588,18 @@ static void osmo_stream_srv_write(struct osmo_stream_srv *conn)
return;
}
- if (ret == -1) /* send(): On error -1 is returned, and errno is set appropriately */
- LOGSSRV(conn, LOGL_ERROR, "error to send: %s\n", strerror(errno));
+ if (ret == -1) {/* send(): On error -1 is returned, and errno is set appropriately */
+ int err = errno;
+ LOGSSRV(conn, LOGL_ERROR, "send(len=%u) error: %s\n", msgb_length(msg), strerror(err));
+ if (err == EAGAIN) {
+ /* Re-add at the start of the queue to re-attempt: */
+ llist_add(&msg->list, &conn->tx_queue);
+ return;
+ }
+ msgb_free(msg);
+ osmo_stream_srv_destroy(conn);
+ return;
+ }
msgb_free(msg);
@@ -877,8 +887,9 @@ static int _sctp_recvmsg_wrapper(int fd, struct msgb *msg)
break;
case SCTP_SHUTDOWN_EVENT:
LOGP(DLINP, LOGL_DEBUG, "===> SHUTDOWN EVT\n");
- /* Handle this like a regular disconnect */
- return 0;
+ /* RFC6458 3.1.4: Any attempt to send more data will cause sendmsg()
+ * to return with an ESHUTDOWN error. */
+ break;
}
return -EAGAIN;
}