Skip to content

Commit 8e008e3

Browse files
committed
fix: fix status page api stability
1 parent 0f6183e commit 8e008e3

File tree

7 files changed

+53
-47
lines changed

7 files changed

+53
-47
lines changed

src/connection.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@ connection_t *connection_create(int fd, int epfd,
230230
c->state = CONN_READ_REQ_LINE;
231231
c->service = NULL;
232232
c->streaming = 0;
233-
c->sse_active = 0;
234233
c->status_index = -1; /* Not registered yet */
235234
c->next = NULL;
236235

@@ -386,14 +385,14 @@ int connection_queue_output(connection_t *c, const uint8_t *data, size_t len)
386385
return 0;
387386
}
388387

389-
int connection_queue_output_and_flush(connection_t *c, const uint8_t *data, size_t len, int set_closing)
388+
int connection_queue_output_and_flush(connection_t *c, const uint8_t *data, size_t len)
390389
{
391390
int result = connection_queue_output(c, data, len);
392391
if (result < 0)
393392
return result;
394393
connection_epoll_update_events(c->epfd, c->fd, EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLHUP | EPOLLERR);
395394

396-
if (set_closing && c)
395+
if (c)
397396
{
398397
c->state = CONN_CLOSING;
399398
}
@@ -757,7 +756,7 @@ int connection_route_and_start(connection_t *c)
757756
{
758757
logger(LOG_INFO, "HEAD request detected, returning success without upstream connection", url);
759758
send_http_headers(c, STATUS_200, "video/mp2t", NULL);
760-
connection_queue_output_and_flush(c, NULL, 0, 1);
759+
connection_queue_output_and_flush(c, NULL, 0);
761760
service_free(service);
762761
return 0;
763762
}
@@ -1039,7 +1038,7 @@ static void handle_playlist_request(connection_t *c)
10391038
server_addr_header[0] ? server_addr_header : NULL);
10401039

10411040
send_http_headers(c, STATUS_200, "audio/x-mpegurl", extra_headers);
1042-
connection_queue_output_and_flush(c, (const uint8_t *)playlist, playlist_len, 1);
1041+
connection_queue_output_and_flush(c, (const uint8_t *)playlist, playlist_len);
10431042
}
10441043

10451044
/* Handle /epg.xml or /epg.xml.gz request - serve cached EPG data

src/connection.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ typedef struct connection_s
4949
stream_context_t stream;
5050
int streaming;
5151
/* SSE */
52-
int sse_active;
5352
int64_t next_sse_ts; /* Next SSE heartbeat time in milliseconds */
5453
int sse_sent_initial;
5554
int sse_last_write_index;
@@ -156,13 +155,13 @@ int connection_queue_output(connection_t *c, const uint8_t *data, size_t len);
156155
/**
157156
* Queue data to connection output buffer and flush immediately
158157
* Data will be sent via connection_handle_write() with proper flow control
158+
* Set connection state to CONN_CLOSING after queueing
159159
* @param c Connection
160160
* @param data Data to send
161161
* @param len Length of data
162-
* @param set_closing If non-zero, set connection state to CONN_CLOSING after queueing
163162
* @return 0 on success, -1 if buffer full
164163
*/
165-
int connection_queue_output_and_flush(connection_t *c, const uint8_t *data, size_t len, int set_closing);
164+
int connection_queue_output_and_flush(connection_t *c, const uint8_t *data, size_t len);
166165

167166
/**
168167
* Queue data for zero-copy send (no memcpy)

src/embedded_web.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ void handle_embedded_file(connection_t *c, const char *path)
127127
file->size);
128128

129129
send_http_headers(c, STATUS_200, file->mime_type, extra_headers);
130-
connection_queue_output_and_flush(c, file->data, file->size, 1);
130+
connection_queue_output_and_flush(c, file->data, file->size);
131131
}
132132
else
133133
{
@@ -144,6 +144,6 @@ void handle_embedded_file(connection_t *c, const char *path)
144144
"Content-Encoding: gzip");
145145

146146
send_http_headers(c, STATUS_200, file->mime_type, extra_headers);
147-
connection_queue_output_and_flush(c, file->data, file->size, 1);
147+
connection_queue_output_and_flush(c, file->data, file->size);
148148
}
149149
}

src/http.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ void http_send_400(connection_t *conn)
466466
send_http_headers(conn, STATUS_400, "text/html; charset=utf-8", NULL);
467467

468468
/* Send body and flush */
469-
connection_queue_output_and_flush(conn, (const uint8_t *)body, sizeof(body) - 1, 1);
469+
connection_queue_output_and_flush(conn, (const uint8_t *)body, sizeof(body) - 1);
470470
}
471471

472472
/**
@@ -481,7 +481,7 @@ void http_send_404(connection_t *conn)
481481
send_http_headers(conn, STATUS_404, "text/html; charset=utf-8", NULL);
482482

483483
/* Send body and flush */
484-
connection_queue_output_and_flush(conn, (const uint8_t *)body, sizeof(body) - 1, 1);
484+
connection_queue_output_and_flush(conn, (const uint8_t *)body, sizeof(body) - 1);
485485
}
486486

487487
/**
@@ -496,7 +496,7 @@ void http_send_500(connection_t *conn)
496496
send_http_headers(conn, STATUS_500, "text/html; charset=utf-8", NULL);
497497

498498
/* Send body and flush */
499-
connection_queue_output_and_flush(conn, (const uint8_t *)body, sizeof(body) - 1, 1);
499+
connection_queue_output_and_flush(conn, (const uint8_t *)body, sizeof(body) - 1);
500500
}
501501

502502
/**
@@ -511,7 +511,7 @@ void http_send_503(connection_t *conn)
511511
send_http_headers(conn, STATUS_503, "text/html; charset=utf-8", NULL);
512512

513513
/* Send body and flush */
514-
connection_queue_output_and_flush(conn, (const uint8_t *)body, sizeof(body) - 1, 1);
514+
connection_queue_output_and_flush(conn, (const uint8_t *)body, sizeof(body) - 1);
515515
}
516516

517517
/**
@@ -526,7 +526,7 @@ void http_send_401(connection_t *conn)
526526
send_http_headers(conn, STATUS_401, "text/html; charset=utf-8", "WWW-Authenticate: Bearer\r\n");
527527

528528
/* Send body and flush */
529-
connection_queue_output_and_flush(conn, (const uint8_t *)body, sizeof(body) - 1, 1);
529+
connection_queue_output_and_flush(conn, (const uint8_t *)body, sizeof(body) - 1);
530530
}
531531

532532
/**
@@ -810,7 +810,7 @@ int http_check_etag_and_send_304(connection_t *c, const char *etag, const char *
810810
etag);
811811

812812
send_http_headers(c, STATUS_304, content_type, extra_headers);
813-
connection_queue_output_and_flush(c, NULL, 0, 1);
813+
connection_queue_output_and_flush(c, NULL, 0);
814814

815815
return 1; /* 304 was sent */
816816
}

src/rtsp.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
static int rtsp_prepare_request(rtsp_session_t *session, const char *method, const char *extra_headers);
4646
static int rtsp_try_send_pending(rtsp_session_t *session);
4747
static int rtsp_try_receive_response(rtsp_session_t *session);
48-
static int rtsp_parse_response(rtsp_session_t *session, const char *response, size_t *response_offset, size_t *response_len);
48+
static int rtsp_parse_response_header(rtsp_session_t *session, const char *response, size_t *response_offset, size_t *response_len);
4949
static int rtsp_setup_udp_sockets(rtsp_session_t *session);
5050
static void rtsp_close_udp_sockets(rtsp_session_t *session, const char *reason);
5151
static char *rtsp_find_header(const char *response, const char *header_name);
@@ -1328,7 +1328,7 @@ static int rtsp_try_receive_response(rtsp_session_t *session)
13281328
size_t response_offset = 0;
13291329
size_t response_len = 0;
13301330
int was_keepalive = session->awaiting_keepalive_response;
1331-
int parse_result = rtsp_parse_response(session, (const char *)session->response_buffer, &response_offset, &response_len);
1331+
int parse_result = rtsp_parse_response_header(session, (const char *)session->response_buffer, &response_offset, &response_len);
13321332

13331333
if (parse_result == 1)
13341334
{
@@ -1340,20 +1340,20 @@ static int rtsp_try_receive_response(rtsp_session_t *session)
13401340
memmove(session->response_buffer, session->response_buffer + response_offset, remaining);
13411341
session->response_buffer_pos = remaining;
13421342
session->response_buffer[session->response_buffer_pos] = '\0';
1343-
logger(LOG_DEBUG, "RTSP: Moved incomplete RTSP response to buffer start");
1343+
logger(LOG_DEBUG, "RTSP: Moved incomplete RTSP header to buffer start");
13441344
}
13451345
else if (session->response_buffer_pos >= sizeof(session->response_buffer) - 1)
13461346
{
1347-
/* Buffer full but no valid RTSP response - discard everything */
1348-
logger(LOG_DEBUG, "RTSP: Buffer full with no RTSP response, discarding");
1347+
/* Buffer full but no valid RTSP header - discard everything */
1348+
logger(LOG_DEBUG, "RTSP: Buffer full with no RTSP header, discarding");
13491349
session->response_buffer_pos = 0;
13501350
}
13511351
/* Wait for more data */
13521352
return 0;
13531353
}
13541354

13551355
/* Complete response received */
1356-
logger(LOG_DEBUG, "RTSP: Received complete response:\n%.*s", (int)response_len, session->response_buffer + response_offset);
1356+
logger(LOG_DEBUG, "RTSP: Received complete header:\n%.*s", (int)response_len, session->response_buffer + response_offset);
13571357

13581358
session->awaiting_response = 0;
13591359
session->awaiting_keepalive_response = 0;
@@ -1372,12 +1372,18 @@ static int rtsp_try_receive_response(rtsp_session_t *session)
13721372
}
13731373

13741374
/* Calculate data remaining after the RTSP response */
1375-
size_t data_after_response_end = response_offset + response_len;
1375+
size_t data_after_header_end = response_offset + response_len;
13761376
size_t remaining_data_len = 0;
1377-
if (session->response_buffer_pos > data_after_response_end)
1377+
if (session->response_buffer_pos > data_after_header_end)
13781378
{
1379-
remaining_data_len = session->response_buffer_pos - data_after_response_end;
1380-
logger(LOG_DEBUG, "RTSP: Found %zu bytes of data after response", remaining_data_len);
1379+
remaining_data_len = session->response_buffer_pos - data_after_header_end;
1380+
1381+
if (session->state != RTSP_STATE_AWAITING_PLAY)
1382+
{
1383+
logger(LOG_DEBUG, "RTSP: Response body data (state=%d): %.*s",
1384+
session->state, (int)remaining_data_len,
1385+
session->response_buffer + data_after_header_end);
1386+
}
13811387
}
13821388

13831389
if (was_keepalive)
@@ -1417,7 +1423,7 @@ static int rtsp_try_receive_response(rtsp_session_t *session)
14171423
/* For TCP interleaved mode, preserve any RTP data that came after PLAY response */
14181424
if (session->transport_mode == RTSP_TRANSPORT_TCP && remaining_data_len > 0)
14191425
{
1420-
memmove(session->response_buffer, session->response_buffer + data_after_response_end, remaining_data_len);
1426+
memmove(session->response_buffer, session->response_buffer + data_after_header_end, remaining_data_len);
14211427
session->response_buffer_pos = remaining_data_len;
14221428
logger(LOG_DEBUG, "RTSP: Preserved %zu bytes of RTP data after PLAY response", remaining_data_len);
14231429
}
@@ -2046,7 +2052,7 @@ int rtsp_session_is_async_teardown(rtsp_session_t *session)
20462052
}
20472053

20482054
/* Helper functions */
2049-
static int rtsp_parse_response(rtsp_session_t *session, const char *response, size_t *response_offset, size_t *response_len)
2055+
static int rtsp_parse_response_header(rtsp_session_t *session, const char *response, size_t *response_offset, size_t *response_len)
20502056
{
20512057
char *session_header = NULL;
20522058
char *transport_header = NULL;

src/status.c

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,7 @@ void handle_disconnect_client(connection_t *c)
836836
send_http_headers(c, STATUS_503, "application/json", NULL);
837837
snprintf(response, sizeof(response),
838838
"{\"success\":false,\"error\":\"Status system not initialized\"}");
839-
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response), 1);
839+
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response));
840840
return;
841841
}
842842

@@ -846,7 +846,7 @@ void handle_disconnect_client(connection_t *c)
846846
send_http_headers(c, STATUS_400, "application/json", NULL);
847847
snprintf(response, sizeof(response),
848848
"{\"success\":false,\"error\":\"Method not allowed. Use POST or DELETE\"}");
849-
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response), 1);
849+
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response));
850850
return;
851851
}
852852

@@ -858,7 +858,7 @@ void handle_disconnect_client(connection_t *c)
858858
send_http_headers(c, STATUS_400, "application/json", NULL);
859859
snprintf(response, sizeof(response),
860860
"{\"success\":false,\"error\":\"Missing 'client_id' parameter in request body\"}");
861-
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response), 1);
861+
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response));
862862
return;
863863
}
864864
}
@@ -867,7 +867,7 @@ void handle_disconnect_client(connection_t *c)
867867
send_http_headers(c, STATUS_400, "application/json", NULL);
868868
snprintf(response, sizeof(response),
869869
"{\"success\":false,\"error\":\"Missing request body\"}");
870-
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response), 1);
870+
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response));
871871
return;
872872
}
873873

@@ -877,7 +877,7 @@ void handle_disconnect_client(connection_t *c)
877877
send_http_headers(c, STATUS_400, "application/json", NULL);
878878
snprintf(response, sizeof(response),
879879
"{\"success\":false,\"error\":\"Empty client_id\"}");
880-
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response), 1);
880+
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response));
881881
return;
882882
}
883883

@@ -915,7 +915,7 @@ void handle_disconnect_client(connection_t *c)
915915
"{\"success\":false,\"error\":\"Client not found or already disconnected\"}");
916916
}
917917

918-
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response), 1);
918+
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response));
919919
}
920920

921921
/**
@@ -934,7 +934,7 @@ void handle_set_log_level(connection_t *c)
934934
send_http_headers(c, STATUS_400, "application/json", NULL);
935935
snprintf(response, sizeof(response),
936936
"{\"success\":false,\"error\":\"Method not allowed. Use PUT or PATCH\"}");
937-
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response), 1);
937+
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response));
938938
return;
939939
}
940940

@@ -946,7 +946,7 @@ void handle_set_log_level(connection_t *c)
946946
send_http_headers(c, STATUS_400, "application/json", NULL);
947947
snprintf(response, sizeof(response),
948948
"{\"success\":false,\"error\":\"Missing 'level' parameter in request body\"}");
949-
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response), 1);
949+
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response));
950950
return;
951951
}
952952
}
@@ -955,7 +955,7 @@ void handle_set_log_level(connection_t *c)
955955
send_http_headers(c, STATUS_400, "application/json", NULL);
956956
snprintf(response, sizeof(response),
957957
"{\"success\":false,\"error\":\"Missing request body\"}");
958-
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response), 1);
958+
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response));
959959
return;
960960
}
961961

@@ -966,7 +966,7 @@ void handle_set_log_level(connection_t *c)
966966
send_http_headers(c, STATUS_400, "application/json", NULL);
967967
snprintf(response, sizeof(response),
968968
"{\"success\":false,\"error\":\"Invalid log level (must be 0-4)\"}");
969-
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response), 1);
969+
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response));
970970
return;
971971
}
972972

@@ -975,13 +975,12 @@ void handle_set_log_level(connection_t *c)
975975
{
976976
status_shared->current_log_level = new_level;
977977
}
978-
config.verbosity = new_level;
979978
send_http_headers(c, STATUS_200, "application/json", NULL);
980979

981980
snprintf(response, sizeof(response),
982981
"{\"success\":true,\"message\":\"Log level changed to %s\"}",
983982
status_get_log_level_name(new_level));
984-
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response), 1);
983+
connection_queue_output_and_flush(c, (const uint8_t *)response, strlen(response));
985984
}
986985

987986
/**
@@ -996,7 +995,6 @@ int status_handle_sse_init(connection_t *c)
996995
/* Send SSE headers */
997996
send_http_headers(c, STATUS_200, "text/event-stream", NULL);
998997

999-
c->sse_active = 1;
1000998
c->sse_sent_initial = 0;
1001999
c->sse_last_write_index = -1;
10021000
c->sse_last_log_count = 0;
@@ -1011,7 +1009,7 @@ int status_handle_sse_init(connection_t *c)
10111009

10121010
if (len > 0)
10131011
{
1014-
connection_queue_output_and_flush(c, (const uint8_t *)tmp, (size_t)len, 0);
1012+
connection_queue_output_and_flush(c, (const uint8_t *)tmp, (size_t)len);
10151013
}
10161014

10171015
c->state = CONN_SSE;
@@ -1035,7 +1033,7 @@ int status_handle_sse_notification(connection_t *conn_head)
10351033
* so we must build a separate payload for each connection */
10361034
for (connection_t *cc = conn_head; cc; cc = cc->next)
10371035
{
1038-
if (!cc->sse_active)
1036+
if (cc->state != CONN_SSE)
10391037
continue;
10401038

10411039
char tmp[SSE_BUFFER_SIZE];
@@ -1046,8 +1044,9 @@ int status_handle_sse_notification(connection_t *conn_head)
10461044

10471045
if (len > 0)
10481046
{
1049-
if (connection_queue_output_and_flush(cc, (const uint8_t *)tmp, (size_t)len, 0) == 0)
1047+
if (connection_queue_output_and_flush(cc, (const uint8_t *)tmp, (size_t)len) == 0)
10501048
{
1049+
cc->state = CONN_SSE;
10511050
updated_count++;
10521051
}
10531052
}
@@ -1065,7 +1064,7 @@ int status_handle_sse_notification(connection_t *conn_head)
10651064
*/
10661065
int status_handle_sse_heartbeat(connection_t *c, int64_t now)
10671066
{
1068-
if (!c || !c->sse_active)
1067+
if (!c || c->state != CONN_SSE)
10691068
return -1;
10701069

10711070
/* Check if heartbeat is needed */

src/worker.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ int worker_run_event_loop(int *listen_sockets, int num_sockets, int notif_fd)
523523
{
524524
/* Normal HTTP request handling */
525525
connection_handle_read(c);
526-
if (!c->zc_queue.head && !c->streaming)
526+
if (c->state == CONN_CLOSING && !c->zc_queue.head)
527527
{
528528
worker_close_and_free_connection(c);
529529
continue; /* Skip further processing for this connection */
@@ -589,7 +589,10 @@ int worker_run_event_loop(int *listen_sockets, int num_sockets, int notif_fd)
589589
}
590590
}
591591
}
592-
status_handle_sse_heartbeat(c, now);
592+
else if (c->state == CONN_SSE)
593+
{
594+
status_handle_sse_heartbeat(c, now);
595+
}
593596
c = next;
594597
}
595598

0 commit comments

Comments
 (0)