mirror of
https://github.com/morgan9e/UxPlay
synced 2026-04-14 00:04:13 +09:00
httpd.c: reworked to eliminate select error; "not a socket"
This commit is contained in:
56
lib/httpd.c
56
lib/httpd.c
@@ -12,7 +12,7 @@
|
|||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
*===================================================================
|
*===================================================================
|
||||||
* modified by fduncanh 2022
|
* modified by fduncanh 2022-2026
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -43,6 +43,7 @@ struct http_connection_s {
|
|||||||
void *user_data;
|
void *user_data;
|
||||||
connection_type_t type;
|
connection_type_t type;
|
||||||
http_request_t *request;
|
http_request_t *request;
|
||||||
|
int pending_remove;
|
||||||
};
|
};
|
||||||
typedef struct http_connection_s http_connection_t;
|
typedef struct http_connection_s http_connection_t;
|
||||||
|
|
||||||
@@ -171,6 +172,14 @@ httpd_init(logger_t *logger, httpd_callbacks_t *callbacks, int nohold)
|
|||||||
free(httpd);
|
free(httpd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < httpd->max_connections; i++) {
|
||||||
|
httpd->connections[i].connected = 0;
|
||||||
|
httpd->connections[i].socket_fd = -1;
|
||||||
|
httpd->connections[i].user_data = NULL;
|
||||||
|
httpd->connections[i].type = CONNECTION_TYPE_UNKNOWN;
|
||||||
|
httpd->connections[i].request = NULL;
|
||||||
|
httpd->connections[i].pending_remove = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Use the logger provided */
|
/* Use the logger provided */
|
||||||
httpd->logger = logger;
|
httpd->logger = logger;
|
||||||
@@ -199,11 +208,14 @@ static void
|
|||||||
httpd_remove_connection(httpd_t *httpd, http_connection_t *connection, int sock_err)
|
httpd_remove_connection(httpd_t *httpd, http_connection_t *connection, int sock_err)
|
||||||
{
|
{
|
||||||
int socket_fd = connection->socket_fd;
|
int socket_fd = connection->socket_fd;
|
||||||
connection->socket_fd = 0;
|
|
||||||
if (sock_err) {
|
if (sock_err) {
|
||||||
logger_log(httpd->logger, LOGGER_ERR, "httpd: recv error %d on socket %d: %s",
|
logger_log(httpd->logger, LOGGER_ERR, "httpd: recv error %d on socket %d: %s",
|
||||||
sock_err, socket_fd, SOCKET_ERROR_STRING(sock_err));
|
sock_err, socket_fd, SOCKET_ERROR_STRING(sock_err));
|
||||||
}
|
}
|
||||||
|
if (connection->pending_remove) {
|
||||||
|
logger_log(httpd->logger, LOGGER_DEBUG, "connection removal was requested");
|
||||||
|
connection->pending_remove = 0;
|
||||||
|
}
|
||||||
if (connection->request) {
|
if (connection->request) {
|
||||||
http_request_destroy(connection->request);
|
http_request_destroy(connection->request);
|
||||||
connection->request = NULL;
|
connection->request = NULL;
|
||||||
@@ -214,11 +226,12 @@ httpd_remove_connection(httpd_t *httpd, http_connection_t *connection, int sock_
|
|||||||
httpd->callbacks.conn_destroy(connection->user_data);
|
httpd->callbacks.conn_destroy(connection->user_data);
|
||||||
connection->user_data = NULL;
|
connection->user_data = NULL;
|
||||||
}
|
}
|
||||||
if (socket_fd) {
|
if (socket_fd != -1) {
|
||||||
if (!sock_err) {
|
if (!sock_err) {
|
||||||
shutdown(socket_fd, SHUT_WR);
|
shutdown(socket_fd, SHUT_WR);
|
||||||
}
|
}
|
||||||
int ret = CLOSESOCKET(socket_fd);
|
int ret = CLOSESOCKET(socket_fd);
|
||||||
|
connection->socket_fd = -1;
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
logger_log(httpd->logger, LOGGER_ERR, "httpd error in CLOSESOCKET: %d %s", errno, SOCKET_ERROR_STRING(errno));
|
logger_log(httpd->logger, LOGGER_ERR, "httpd error in CLOSESOCKET: %d %s", errno, SOCKET_ERROR_STRING(errno));
|
||||||
} else {
|
} else {
|
||||||
@@ -259,6 +272,7 @@ httpd_add_connection(httpd_t *httpd, int fd, unsigned char *local, int local_len
|
|||||||
httpd->connections[i].socket_fd = fd;
|
httpd->connections[i].socket_fd = fd;
|
||||||
httpd->connections[i].connected = 1;
|
httpd->connections[i].connected = 1;
|
||||||
httpd->connections[i].user_data = user_data;
|
httpd->connections[i].user_data = user_data;
|
||||||
|
httpd->connections[i].pending_remove = 0;
|
||||||
httpd->connections[i].type = CONNECTION_TYPE_UNKNOWN; //should not be necessary ...
|
httpd->connections[i].type = CONNECTION_TYPE_UNKNOWN; //should not be necessary ...
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -327,7 +341,7 @@ httpd_remove_known_connections(httpd_t *httpd) {
|
|||||||
if (!connection->connected || connection->type == CONNECTION_TYPE_UNKNOWN) {
|
if (!connection->connected || connection->type == CONNECTION_TYPE_UNKNOWN) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
httpd_remove_connection(httpd, connection, 0);
|
connection->pending_remove = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +352,7 @@ httpd_remove_connections_by_type(httpd_t *httpd, connection_type_t type) {
|
|||||||
if (!connection->connected || connection->type != type) {
|
if (!connection->connected || connection->type != type) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
httpd_remove_connection(httpd, connection, 0);
|
connection->pending_remove = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,9 +371,7 @@ httpd_thread(void *arg)
|
|||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
int nfds = 0;
|
int nfds = 0;
|
||||||
int ret = 0;
|
int nfds_set = 0;
|
||||||
int new_request = 0;
|
|
||||||
int recv_datalen = 0;
|
|
||||||
|
|
||||||
MUTEX_LOCK(httpd->run_mutex);
|
MUTEX_LOCK(httpd->run_mutex);
|
||||||
if (!httpd->running) {
|
if (!httpd->running) {
|
||||||
@@ -393,6 +405,10 @@ httpd_thread(void *arg)
|
|||||||
if (!httpd->connections[i].connected) {
|
if (!httpd->connections[i].connected) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (httpd->connections[i].pending_remove) {
|
||||||
|
httpd_remove_connection(httpd, &httpd->connections[i], 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
socket_fd = httpd->connections[i].socket_fd;
|
socket_fd = httpd->connections[i].socket_fd;
|
||||||
FD_SET(socket_fd, &rfds);
|
FD_SET(socket_fd, &rfds);
|
||||||
if (nfds <= socket_fd) {
|
if (nfds <= socket_fd) {
|
||||||
@@ -400,11 +416,11 @@ httpd_thread(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = select(nfds, &rfds, NULL, NULL, &tv);
|
nfds_set = select(nfds, &rfds, NULL, NULL, &tv);
|
||||||
if (ret == 0) {
|
if (nfds_set == 0) {
|
||||||
/* Timeout happened */
|
/* Timeout happened */
|
||||||
continue;
|
continue;
|
||||||
} else if (ret == -1) {
|
} else if (nfds_set == -1) {
|
||||||
int sock_err = SOCKET_GET_ERROR();
|
int sock_err = SOCKET_GET_ERROR();
|
||||||
logger_log(httpd->logger, LOGGER_ERR,
|
logger_log(httpd->logger, LOGGER_ERR,
|
||||||
"httpd error in select: %d %s", sock_err, SOCKET_ERROR_STRING(sock_err));
|
"httpd error in select: %d %s", sock_err, SOCKET_ERROR_STRING(sock_err));
|
||||||
@@ -432,6 +448,8 @@ httpd_thread(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < httpd->max_connections; i++) {
|
for (int i = 0; i < httpd->max_connections; i++) {
|
||||||
|
int recv_datalen = 0;
|
||||||
|
int new_request = 0;
|
||||||
http_connection_t *connection = &httpd->connections[i];
|
http_connection_t *connection = &httpd->connections[i];
|
||||||
|
|
||||||
if (!connection->connected) {
|
if (!connection->connected) {
|
||||||
@@ -481,15 +499,12 @@ httpd_thread(void *arg)
|
|||||||
int readstart = 0;
|
int readstart = 0;
|
||||||
new_request = 0;
|
new_request = 0;
|
||||||
while (readstart < 8) {
|
while (readstart < 8) {
|
||||||
if (!connection->socket_fd) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
int ret = recv(connection->socket_fd, buffer + readstart, sizeof(buffer) - readstart, 0);
|
int ret = recv(connection->socket_fd, buffer + readstart, sizeof(buffer) - readstart, 0);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
logger_log(httpd->logger, LOGGER_DEBUG, "client closed connection on socket %d",
|
logger_log(httpd->logger, LOGGER_DEBUG, "client closed connection on socket %d",
|
||||||
connection->socket_fd);
|
connection->socket_fd);
|
||||||
httpd_remove_connection(httpd, connection, 0);
|
httpd_remove_connection(httpd, connection, 0);
|
||||||
continue;
|
break;
|
||||||
} else if (ret == -1) {
|
} else if (ret == -1) {
|
||||||
if (errno == SOCKET_ERRORNAME(EAGAIN) || errno == SOCKET_ERRORNAME(EWOULDBLOCK) || errno == SOCKET_ERRORNAME(EINTR)) {
|
if (errno == SOCKET_ERRORNAME(EAGAIN) || errno == SOCKET_ERRORNAME(EWOULDBLOCK) || errno == SOCKET_ERRORNAME(EINTR)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -502,15 +517,14 @@ httpd_thread(void *arg)
|
|||||||
recv_datalen = readstart;
|
recv_datalen = readstart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!connection->socket_fd) {
|
if (connection->socket_fd == -1) {
|
||||||
/* connection was recently removed */
|
/* connection was removed */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!memcmp(buffer, http, 8) || !memcmp(buffer, event, 8)) {
|
if (!memcmp(buffer, http, 8) || !memcmp(buffer, event, 8)) {
|
||||||
http_request_set_reverse(connection->request);
|
http_request_set_reverse(connection->request);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (connection->socket_fd) {
|
|
||||||
int ret = recv(connection->socket_fd, buffer, sizeof(buffer), 0);
|
int ret = recv(connection->socket_fd, buffer, sizeof(buffer), 0);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
httpd_remove_connection(httpd, connection, 0);
|
httpd_remove_connection(httpd, connection, 0);
|
||||||
@@ -520,15 +534,11 @@ httpd_thread(void *arg)
|
|||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
httpd_remove_connection(httpd, connection, SOCKET_GET_ERROR());
|
httpd_remove_connection(httpd, connection, SOCKET_GET_ERROR());
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
recv_datalen = ret;
|
recv_datalen = ret;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
/* connection was recently removed */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (http_request_is_reverse(connection->request)) {
|
if (http_request_is_reverse(connection->request)) {
|
||||||
/* this is a response from the client to a
|
/* this is a response from the client to a
|
||||||
|
|||||||
Reference in New Issue
Block a user