From 8eabfcc780bf8b0092c30968be585615caf8429f Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Sun, 15 Feb 2026 19:45:23 -0500 Subject: [PATCH] fix #503 recv errors in httpd.c; define CLOSESOCKET, IOCTLSOCKET --- lib/httpd.c | 64 ++++++++++++++++++++++++------------------- lib/netutils.c | 2 +- lib/raop_ntp.c | 8 ++---- lib/raop_rtp.c | 8 +++--- lib/raop_rtp_mirror.c | 8 +++--- lib/sockets.h | 7 +++-- 6 files changed, 52 insertions(+), 45 deletions(-) diff --git a/lib/httpd.c b/lib/httpd.c index ab18f22..58cf2af 100644 --- a/lib/httpd.c +++ b/lib/httpd.c @@ -39,7 +39,6 @@ static const char *typename[] = { struct http_connection_s { int connected; - int socket_fd; void *user_data; connection_type_t type; @@ -50,7 +49,6 @@ typedef struct http_connection_s http_connection_t; struct httpd_s { logger_t *logger; httpd_callbacks_t callbacks; - int max_connections; int open_connections; http_connection_t *connections; @@ -192,17 +190,20 @@ httpd_destroy(httpd_t *httpd) { if (httpd) { httpd_stop(httpd); - free(httpd->connections); free(httpd); } } static void -httpd_remove_connection(httpd_t *httpd, http_connection_t *connection) +httpd_remove_connection(httpd_t *httpd, http_connection_t *connection, int sock_err) { int socket_fd = connection->socket_fd; connection->socket_fd = 0; + if (sock_err) { + logger_log(httpd->logger, LOGGER_INFO, "httpd: recv error %d on socket %d: %s", + sock_err, socket_fd, SOCKET_ERROR_STRING(sock_err)); + } if (connection->request) { http_request_destroy(connection->request); connection->request = NULL; @@ -214,10 +215,12 @@ httpd_remove_connection(httpd_t *httpd, http_connection_t *connection) connection->user_data = NULL; } if (socket_fd) { - shutdown(socket_fd, SHUT_WR); - int ret = closesocket(socket_fd); + if (!sock_err) { + shutdown(socket_fd, SHUT_WR); + } + int ret = CLOSESOCKET(socket_fd); if (ret == -1) { - logger_log(httpd->logger, LOGGER_ERR, "httpd error in closesocket (close): %d %s", errno, strerror(errno)); + logger_log(httpd->logger, LOGGER_ERR, "httpd error in CLOSESOCKET: %d %s", errno, SOCKET_ERROR_STRING(errno)); } else { logger_log(httpd->logger, LOGGER_INFO, "Connection closed on socket %d", socket_fd); } @@ -284,7 +287,7 @@ httpd_accept_connection(httpd_t *httpd, int server_fd, int is_ipv6) ret = getsockname(fd, (struct sockaddr *)&local_saddr, &local_saddrlen); if (ret == -1) { shutdown(fd, SHUT_RDWR); - closesocket(fd); + CLOSESOCKET(fd); return 0; } @@ -303,7 +306,7 @@ httpd_accept_connection(httpd_t *httpd, int server_fd, int is_ipv6) ret = httpd_add_connection(httpd, fd, local, local_len, remote, remote_len, local_zone_id); if (ret == -1) { shutdown(fd, SHUT_RDWR); - closesocket(fd); + CLOSESOCKET(fd); return 0; } return 1; @@ -321,7 +324,7 @@ httpd_remove_known_connections(httpd_t *httpd) { if (!connection->connected || connection->type == CONNECTION_TYPE_UNKNOWN) { continue; } - httpd_remove_connection(httpd, connection); + httpd_remove_connection(httpd, connection, 0); } } @@ -332,7 +335,7 @@ httpd_remove_connections_by_type(httpd_t *httpd, connection_type_t type) { if (!connection->connected || connection->type != type) { continue; } - httpd_remove_connection(httpd, connection); + httpd_remove_connection(httpd, connection, 0); } } @@ -478,18 +481,16 @@ httpd_thread(void *arg) if (!connection->socket_fd) { break; } - ret = recv(connection->socket_fd, buffer + readstart, sizeof(buffer) - 1 - readstart, 0); + ret = recv(connection->socket_fd, buffer + readstart, sizeof(buffer) - readstart, 0); if (ret == 0) { logger_log(httpd->logger, LOGGER_DEBUG, "client closed connection on socket %d", connection->socket_fd); break; } else if (ret == -1) { - if (errno == EAGAIN) { + if (errno == SOCKET_ERRORNAME(EAGAIN) || errno == SOCKET_ERRORNAME(EWOULDBLOCK) || errno == SOCKET_ERRORNAME(EINTR)) { continue; } else { - int sock_err = SOCKET_GET_ERROR(); - logger_log(httpd->logger, LOGGER_ERR, "httpd: recv error %d on socket %d: %s", - sock_err, connection->socket_fd, SOCKET_ERROR_STRING(sock_err)); + httpd_remove_connection(httpd, connection, SOCKET_GET_ERROR()); break; } } else { @@ -506,10 +507,17 @@ httpd_thread(void *arg) } } else { if (connection->socket_fd) { - ret = recv(connection->socket_fd, buffer, sizeof(buffer) - 1, 0); + ret = recv(connection->socket_fd, buffer, sizeof(buffer), 0); if (ret == 0) { - httpd_remove_connection(httpd, connection); + httpd_remove_connection(httpd, connection, 0); continue; + } else if (ret == -1) { + if (errno == SOCKET_ERRORNAME(EAGAIN) || errno == SOCKET_ERRORNAME(EWOULDBLOCK) || errno == SOCKET_ERRORNAME(EINTR)) { + continue; + } else { + httpd_remove_connection(httpd, connection, SOCKET_GET_ERROR()); + break; + } } } else { /* connection was recently removed */ @@ -526,7 +534,7 @@ httpd_thread(void *arg) " on socket %d:\n%s\n", connection->socket_fd, buffer); } if (ret == 0) { - httpd_remove_connection(httpd, connection); + httpd_remove_connection(httpd, connection, 0); } continue; } @@ -540,7 +548,7 @@ httpd_thread(void *arg) http_request_get_error_description(connection->request), data); free (data); - httpd_remove_connection(httpd, connection); + httpd_remove_connection(httpd, connection, 0); continue; } @@ -581,7 +589,7 @@ httpd_thread(void *arg) if (http_response_get_disconnect(response)) { logger_log(httpd->logger, LOGGER_INFO, "Disconnecting on software request"); - httpd_remove_connection(httpd, connection); + httpd_remove_connection(httpd, connection, 0); } } else { logger_log(httpd->logger, LOGGER_WARNING, "httpd didn't get response"); @@ -601,18 +609,18 @@ httpd_thread(void *arg) continue; } logger_log(httpd->logger, LOGGER_INFO, "Removing connection for socket %d", connection->socket_fd); - httpd_remove_connection(httpd, connection); + httpd_remove_connection(httpd, connection, 0); } /* Close server sockets since they are not used any more */ if (httpd->server_fd4 != -1) { shutdown(httpd->server_fd4, SHUT_RDWR); - closesocket(httpd->server_fd4); + CLOSESOCKET(httpd->server_fd4); httpd->server_fd4 = -1; } if (httpd->server_fd6 != -1) { shutdown(httpd->server_fd6, SHUT_RDWR); - closesocket(httpd->server_fd6); + CLOSESOCKET(httpd->server_fd6); httpd->server_fd6 = -1; } @@ -655,15 +663,15 @@ httpd_start(httpd_t *httpd, unsigned short *port) if (httpd->server_fd4 != -1 && listen(httpd->server_fd4, backlog) == -1) { logger_log(httpd->logger, LOGGER_ERR, "Error listening to IPv4 socket"); - closesocket(httpd->server_fd4); - closesocket(httpd->server_fd6); + CLOSESOCKET(httpd->server_fd4); + CLOSESOCKET(httpd->server_fd6); MUTEX_UNLOCK(httpd->run_mutex); return -2; } if (httpd->server_fd6 != -1 && listen(httpd->server_fd6, backlog) == -1) { logger_log(httpd->logger, LOGGER_ERR, "Error listening to IPv6 socket"); - closesocket(httpd->server_fd4); - closesocket(httpd->server_fd6); + CLOSESOCKET(httpd->server_fd4); + CLOSESOCKET(httpd->server_fd6); MUTEX_UNLOCK(httpd->run_mutex); return -2; } diff --git a/lib/netutils.c b/lib/netutils.c index aee95d7..726ab13 100644 --- a/lib/netutils.c +++ b/lib/netutils.c @@ -171,7 +171,7 @@ netutils_init_socket(unsigned short *port, int use_ipv6, int use_udp) cleanup: ret = SOCKET_GET_ERROR(); if (server_fd != -1) { - closesocket(server_fd); + CLOSESOCKET(server_fd); } SOCKET_SET_ERROR(ret); return -1; diff --git a/lib/raop_ntp.c b/lib/raop_ntp.c index 255dad7..7da009d 100644 --- a/lib/raop_ntp.c +++ b/lib/raop_ntp.c @@ -244,7 +244,7 @@ raop_ntp_init_socket(raop_ntp_t *raop_ntp, int use_ipv6) return 0; sockets_cleanup: - if (tsock != -1) closesocket(tsock); + if (tsock != -1) CLOSESOCKET(tsock); return -1; } @@ -252,13 +252,11 @@ static void raop_ntp_flush_socket(int fd) { #ifdef _WIN32 -#define IOCTL ioctlsocket u_long bytes_available = 0; #else -#define IOCTL ioctl int bytes_available = 0; #endif - while (IOCTL(fd, FIONREAD, &bytes_available) == 0 && bytes_available > 0) + while (IOCTLSOCKET(fd, FIONREAD, &bytes_available) == 0 && bytes_available > 0) { // We are guaranteed that we won't block, because bytes are available. // Read 1 byte. Extra bytes in the datagram will be discarded. @@ -464,7 +462,7 @@ raop_ntp_stop(raop_ntp_t *raop_ntp) THREAD_JOIN(raop_ntp->thread); if (raop_ntp->tsock != -1) { - closesocket(raop_ntp->tsock); + CLOSESOCKET(raop_ntp->tsock); raop_ntp->tsock = -1; } diff --git a/lib/raop_rtp.c b/lib/raop_rtp.c index e8859a6..413de24 100644 --- a/lib/raop_rtp.c +++ b/lib/raop_rtp.c @@ -270,8 +270,8 @@ raop_rtp_init_sockets(raop_rtp_t *raop_rtp, int use_ipv6) return 0; sockets_cleanup: - if (csock != -1) closesocket(csock); - if (dsock != -1) closesocket(dsock); + if (csock != -1) CLOSESOCKET(csock); + if (dsock != -1) CLOSESOCKET(dsock); return -1; } @@ -832,11 +832,11 @@ raop_rtp_stop(raop_rtp_t *raop_rtp) THREAD_JOIN(raop_rtp->thread); if (raop_rtp->csock != -1) { - closesocket(raop_rtp->csock); + CLOSESOCKET(raop_rtp->csock); raop_rtp->csock = -1; } if (raop_rtp->dsock != -1) { - closesocket(raop_rtp->dsock); + CLOSESOCKET(raop_rtp->dsock); raop_rtp->dsock = -1; } diff --git a/lib/raop_rtp_mirror.c b/lib/raop_rtp_mirror.c index 12792fd..8461f17 100644 --- a/lib/raop_rtp_mirror.c +++ b/lib/raop_rtp_mirror.c @@ -840,7 +840,7 @@ raop_rtp_mirror_thread(void *arg) } /* Close the stream file descriptor */ if (stream_fd != -1) { - closesocket(stream_fd); + CLOSESOCKET(stream_fd); } // Ensure running reflects the actual state @@ -854,7 +854,7 @@ raop_rtp_mirror_thread(void *arg) } if (unsupported_codec) { - closesocket(raop_rtp_mirror->mirror_data_sock); + CLOSESOCKET(raop_rtp_mirror->mirror_data_sock); raop_rtp_mirror_stop(raop_rtp_mirror); raop_rtp_mirror->callbacks.video_reset(raop_rtp_mirror->callbacks.cls, RESET_TYPE_RTP_SHUTDOWN); } @@ -888,7 +888,7 @@ raop_rtp_mirror_init_socket(raop_rtp_mirror_t *raop_rtp_mirror, int use_ipv6) return 0; sockets_cleanup: - if (dsock != -1) closesocket(dsock); + if (dsock != -1) CLOSESOCKET(dsock); return -1; } @@ -947,7 +947,7 @@ void raop_rtp_mirror_stop(raop_rtp_mirror_t *raop_rtp_mirror) { THREAD_JOIN(raop_rtp_mirror->thread_mirror); if (raop_rtp_mirror->mirror_data_sock != -1) { - closesocket(raop_rtp_mirror->mirror_data_sock); + CLOSESOCKET(raop_rtp_mirror->mirror_data_sock); raop_rtp_mirror->mirror_data_sock = -1; } diff --git a/lib/sockets.h b/lib/sockets.h index 7fb2585..ace7fda 100644 --- a/lib/sockets.h +++ b/lib/sockets.h @@ -38,11 +38,12 @@ typedef int socklen_t; #define WSAEAGAIN WSAEWOULDBLOCK #define WSAENOMEM WSA_NOT_ENOUGH_MEMORY - +#define CLOSESOCKET closesocket +#define IOCTLSOCKET ioctlsocket #else -#define closesocket close -#define ioctlsocket ioctl +#define CLOSESOCKET close +#define IOCTLSOCKET ioctl #define SOCKET_GET_ERROR() (errno) #define SOCKET_SET_ERROR(value) (errno = (value))