Completely working version git, websockets and /dashboard.

This commit is contained in:
retoor 2025-09-26 00:17:16 +02:00
parent eb2decd36d
commit 559c22fffa

View File

@ -2093,6 +2093,7 @@ void handle_client_read(connection_t *conn) {
} }
} }
static void handle_forwarding(connection_t *conn) { static void handle_forwarding(connection_t *conn) {
connection_t *pair = conn->pair; connection_t *pair = conn->pair;
if (!pair || pair->fd == -1) { if (!pair || pair->fd == -1) {
@ -2111,41 +2112,62 @@ static void handle_forwarding(connection_t *conn) {
int bytes_read = do_read(conn); int bytes_read = do_read(conn);
// --- START: GIT HALF-CLOSE FIX --- // --- START: COMPLETE PIPELINE FIX ---
if (bytes_read == 0) { // EOF received, meaning this side is done writing. // This is the crucial fix for the keep-alive pipelining problem.
// If we read new data FROM THE CLIENT, we must inspect it before forwarding.
if (bytes_read > 0 && conn->type == CONN_TYPE_CLIENT) {
char* data_start = conn->read_buf.data + conn->read_buf.head;
size_t data_len = buffer_available_read(&conn->read_buf);
// Heuristic check: Does the new data look like a new HTTP request for an internal route?
// We check for "GET /" and then the specific paths.
if (data_len > 10 && memcmp(data_start, "GET /", 5) == 0) {
// Temporarily null-terminate to use strncmp safely on the URI part.
char old_char = data_start[data_len-1];
data_start[data_len-1] = '\0';
bool is_internal_route = (strstr(data_start, "/dashboard") || strstr(data_start, "/api/stats"));
data_start[data_len-1] = old_char; // Restore buffer
if (is_internal_route) {
log_info("[ROUTING-INTERCEPT] Intercepted internal route on keep-alive fd=%d. Re-routing.", conn->fd);
// This is an internal request. We must break the link to the old upstream server.
// The close_connection logic will handle un-pairing and resetting our state.
close_connection(pair->fd);
// The close_connection call above should have already reset this client's state
// and called handle_client_read if data was present. We can safely return.
return;
}
}
}
// --- END: COMPLETE PIPELINE FIX ---
if (bytes_read == 0) { // EOF received
log_debug("EOF on fd %d, performing half-close on pair fd %d", conn->fd, pair->fd); log_debug("EOF on fd %d, performing half-close on pair fd %d", conn->fd, pair->fd);
conn->half_closed = 1; conn->half_closed = 1;
// Stop listening for reads on this socket, as it's closed.
modify_epoll(conn->fd, buffer_available_read(&conn->write_buf) ? EPOLLOUT : 0); modify_epoll(conn->fd, buffer_available_read(&conn->write_buf) ? EPOLLOUT : 0);
// Tell the other side we are done writing to it.
if (pair->fd != -1 && !pair->write_shutdown) { if (pair->fd != -1 && !pair->write_shutdown) {
if (shutdown(pair->fd, SHUT_WR) == -1 && errno != ENOTCONN) { if (shutdown(pair->fd, SHUT_WR) == -1 && errno != ENOTCONN) {
log_debug("shutdown(SHUT_WR) failed for fd %d: %s", pair->fd, strerror(errno)); log_debug("shutdown(SHUT_WR) failed for fd %d: %s", pair->fd, strerror(errno));
} }
pair->write_shutdown = 1; pair->write_shutdown = 1;
} }
// If the other side had already signaled it was done writing, we can now fully close.
if (pair->half_closed) { if (pair->half_closed) {
close_connection(conn->fd); close_connection(conn->fd);
} }
return; return;
} }
// --- END: GIT HALF-CLOSE FIX ---
if (bytes_read < 0 && (errno != EAGAIN && errno != EWOULDBLOCK)) { if (bytes_read < 0 && (errno != EAGAIN && errno != EWOULDBLOCK)) {
close_connection(conn->fd); close_connection(conn->fd);
return; return;
} }
// Pipelining check remains unchanged...
if (bytes_read > 0 && conn->type == CONN_TYPE_CLIENT) {
// ...
}
// Forwarding logic remains unchanged...
size_t data_to_forward = buffer_available_read(&conn->read_buf); size_t data_to_forward = buffer_available_read(&conn->read_buf);
if (data_to_forward > 0) { if (data_to_forward > 0) {
if (buffer_ensure_capacity(&pair->write_buf, pair->write_buf.tail + data_to_forward) < 0) { if (buffer_ensure_capacity(&pair->write_buf, pair->write_buf.tail + data_to_forward) < 0) {
@ -2161,8 +2183,6 @@ static void handle_forwarding(connection_t *conn) {
} }
} }
static void handle_ssl_handshake(connection_t *conn) { static void handle_ssl_handshake(connection_t *conn) {
if (!conn->ssl || conn->ssl_handshake_done) return; if (!conn->ssl || conn->ssl_handshake_done) return;