Skip to content

Commit d36f1ef

Browse files
committed
fix: fix mcast sock not being properly cleaned up in some situations
1 parent 1e49a01 commit d36f1ef

File tree

5 files changed

+40
-38
lines changed

5 files changed

+40
-38
lines changed

src/fcc.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ void fcc_session_cleanup(fcc_session_t *fcc, service_t *service, int epoll_fd) {
8484
}
8585

8686
/* Send termination message ONLY if not sent before */
87-
if (!fcc->fcc_term_sent && fcc->fcc_sock && fcc->fcc_server && service) {
87+
if (!fcc->fcc_term_sent && fcc->fcc_sock >= 0 && fcc->fcc_server && service) {
8888
logger(LOG_DEBUG, "FCC: Sending termination packet (cleanup)");
8989
if (fcc_send_term_packet(fcc, service, 0, "cleanup") == 0) {
9090
fcc->fcc_term_sent = 1;
@@ -105,9 +105,9 @@ void fcc_session_cleanup(fcc_session_t *fcc, service_t *service, int epoll_fd) {
105105
fcc->pending_list_tail = NULL;
106106

107107
/* Close FCC socket */
108-
if (fcc->fcc_sock > 0) {
108+
if (fcc->fcc_sock >= 0) {
109109
worker_cleanup_socket_from_epoll(epoll_fd, fcc->fcc_sock);
110-
fcc->fcc_sock = 0;
110+
fcc->fcc_sock = -1;
111111
logger(LOG_DEBUG, "FCC: Socket closed");
112112
}
113113

@@ -144,6 +144,7 @@ static void log_fcc_state_transition(fcc_state_t from, fcc_state_t to,
144144
void fcc_session_init(fcc_session_t *fcc) {
145145
memset(fcc, 0, sizeof(fcc_session_t));
146146
fcc->state = FCC_STATE_INIT;
147+
fcc->fcc_sock = -1;
147148
fcc->status_index = -1;
148149
fcc->redirect_count = 0;
149150
}
@@ -193,7 +194,7 @@ int fcc_initialize_and_request(stream_context_t *ctx) {
193194

194195
logger(LOG_DEBUG, "FCC: Initializing FCC session and sending request");
195196

196-
if (!fcc->fcc_sock) {
197+
if (fcc->fcc_sock < 0) {
197198
/* Create and configure FCC socket */
198199
fcc->fcc_sock = socket(AF_INET, service->fcc_addr->ai_socktype,
199200
service->fcc_addr->ai_protocol);
@@ -207,7 +208,7 @@ int fcc_initialize_and_request(stream_context_t *ctx) {
207208
logger(LOG_ERROR, "FCC: Failed to set socket non-blocking: %s",
208209
strerror(errno));
209210
close(fcc->fcc_sock);
210-
fcc->fcc_sock = 0;
211+
fcc->fcc_sock = -1;
211212
return -1;
212213
}
213214

@@ -245,7 +246,7 @@ int fcc_initialize_and_request(stream_context_t *ctx) {
245246
logger(LOG_ERROR, "FCC: Failed to add socket to epoll: %s",
246247
strerror(errno));
247248
close(fcc->fcc_sock);
248-
fcc->fcc_sock = 0;
249+
fcc->fcc_sock = -1;
249250
return -1;
250251
}
251252
fdmap_set(fcc->fcc_sock, ctx->conn);
@@ -310,7 +311,7 @@ int fcc_handle_sync_notification(stream_context_t *ctx, int timeout_ms) {
310311
timeout_ms ? "Sync notification timeout"
311312
: "Sync notification received");
312313

313-
ctx->mcast_sock = stream_join_mcast_group(ctx);
314+
stream_join_mcast_group(ctx);
314315

315316
return 0; /* Signal to join multicast */
316317
}
@@ -358,7 +359,7 @@ int fcc_handle_unicast_media(stream_context_t *ctx, buffer_ref_t *buf_ref) {
358359
*/
359360
static int fcc_send_term_packet(fcc_session_t *fcc, service_t *service,
360361
uint16_t seqn, const char *reason) {
361-
if (!fcc->fcc_sock || !fcc->fcc_server) {
362+
if (fcc->fcc_sock < 0 || !fcc->fcc_server) {
362363
logger(LOG_DEBUG, "FCC: Cannot send termination - missing socket/server");
363364
return -1;
364365
}

src/fcc_huawei.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ int fcc_huawei_handle_server_response(stream_context_t *ctx, uint8_t *buf,
184184
"multicast",
185185
result_code);
186186
fcc_session_set_state(fcc, FCC_STATE_MCAST_ACTIVE, "Server error");
187-
ctx->mcast_sock = stream_join_mcast_group(ctx);
187+
stream_join_mcast_group(ctx);
188188
return 0;
189189
}
190190

@@ -193,7 +193,7 @@ int fcc_huawei_handle_server_response(stream_context_t *ctx, uint8_t *buf,
193193
logger(LOG_INFO,
194194
"FCC (Huawei): Server says no unicast needed, joining multicast");
195195
fcc_session_set_state(fcc, FCC_STATE_MCAST_ACTIVE, "No unicast needed");
196-
ctx->mcast_sock = stream_join_mcast_group(ctx);
196+
stream_join_mcast_group(ctx);
197197
} else if (type == 2) {
198198
/* Server will send unicast stream */
199199
uint8_t nat_flag = buf[24];
@@ -255,7 +255,7 @@ int fcc_huawei_handle_server_response(stream_context_t *ctx, uint8_t *buf,
255255
"FCC (Huawei): Too many redirects (%d), falling back to multicast",
256256
fcc->redirect_count);
257257
fcc_session_set_state(fcc, FCC_STATE_MCAST_ACTIVE, "Too many redirects");
258-
ctx->mcast_sock = stream_join_mcast_group(ctx);
258+
stream_join_mcast_group(ctx);
259259
return 0;
260260
}
261261

@@ -279,7 +279,7 @@ int fcc_huawei_handle_server_response(stream_context_t *ctx, uint8_t *buf,
279279
"FCC (Huawei): Unsupported type=%u, falling back to multicast",
280280
type);
281281
fcc_session_set_state(fcc, FCC_STATE_MCAST_ACTIVE, "Unsupported type");
282-
ctx->mcast_sock = stream_join_mcast_group(ctx);
282+
stream_join_mcast_group(ctx);
283283
}
284284

285285
return 0;
@@ -289,7 +289,7 @@ int fcc_huawei_send_term_packet(fcc_session_t *fcc, service_t *service,
289289
uint16_t seqn, const char *reason) {
290290
int r;
291291

292-
if (!fcc->fcc_sock || !fcc->fcc_server) {
292+
if (fcc->fcc_sock < 0 || !fcc->fcc_server) {
293293
logger(LOG_DEBUG, "FCC: Cannot send termination - missing socket/server");
294294
return -1;
295295
}

src/fcc_telecom.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ int fcc_telecom_handle_server_response(stream_context_t *ctx, uint8_t *buf) {
161161
"multicast",
162162
result_code);
163163
fcc_session_set_state(fcc, FCC_STATE_MCAST_ACTIVE, "Server error");
164-
ctx->mcast_sock = stream_join_mcast_group(ctx);
164+
stream_join_mcast_group(ctx);
165165
return 0;
166166
}
167167

@@ -196,7 +196,7 @@ int fcc_telecom_handle_server_response(stream_context_t *ctx, uint8_t *buf) {
196196
logger(LOG_INFO,
197197
"FCC (Telecom): Server says no unicast needed, joining multicast");
198198
fcc_session_set_state(fcc, FCC_STATE_MCAST_ACTIVE, "No unicast needed");
199-
ctx->mcast_sock = stream_join_mcast_group(ctx);
199+
stream_join_mcast_group(ctx);
200200
} else if (type == 2) {
201201
/* Normal FCC flow - server will start unicast stream */
202202
if (media_port_changed && fcc->media_port) {
@@ -225,7 +225,7 @@ int fcc_telecom_handle_server_response(stream_context_t *ctx, uint8_t *buf) {
225225
"FCC (Telecom): Too many redirects (%d), falling back to multicast",
226226
fcc->redirect_count);
227227
fcc_session_set_state(fcc, FCC_STATE_MCAST_ACTIVE, "Too many redirects");
228-
ctx->mcast_sock = stream_join_mcast_group(ctx);
228+
stream_join_mcast_group(ctx);
229229
return 0;
230230
}
231231
logger(LOG_DEBUG,
@@ -240,7 +240,7 @@ int fcc_telecom_handle_server_response(stream_context_t *ctx, uint8_t *buf) {
240240
"FCC (Telecom): Unsupported type=%u, falling back to multicast",
241241
type);
242242
fcc_session_set_state(fcc, FCC_STATE_MCAST_ACTIVE, "Unsupported type");
243-
ctx->mcast_sock = stream_join_mcast_group(ctx);
243+
stream_join_mcast_group(ctx);
244244
}
245245

246246
return 0;
@@ -250,7 +250,7 @@ int fcc_telecom_send_term_packet(fcc_session_t *fcc, service_t *service,
250250
uint16_t seqn, const char *reason) {
251251
int r;
252252

253-
if (!fcc->fcc_sock || !fcc->fcc_server) {
253+
if (fcc->fcc_sock < 0 || !fcc->fcc_server) {
254254
logger(LOG_DEBUG, "FCC: Cannot send termination - missing socket/server");
255255
return -1;
256256
}

src/stream.c

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
* function should be used instead of join_mcast_group() directly in all
2525
* stream-related code to ensure proper timeout handling.
2626
*/
27-
int stream_join_mcast_group(stream_context_t *ctx) {
27+
void stream_join_mcast_group(stream_context_t *ctx) {
28+
if (ctx->mcast_sock >= 0)
29+
return;
2830
int sock = join_mcast_group(ctx->service);
29-
if (sock > 0) {
31+
if (sock >= 0) {
3032
/* Register socket with epoll immediately after creation */
3133
struct epoll_event ev;
3234
ev.events = EPOLLIN; /* Level-triggered mode for read events */
@@ -44,8 +46,9 @@ int stream_join_mcast_group(stream_context_t *ctx) {
4446
int64_t now = get_time_ms();
4547
ctx->last_mcast_data_time = now;
4648
ctx->last_mcast_rejoin_time = now;
49+
50+
ctx->mcast_sock = sock;
4751
}
48-
return sock;
4952
}
5053

5154
/*
@@ -78,7 +81,7 @@ int stream_handle_fd_event(stream_context_t *ctx, int fd, uint32_t events,
7881
socklen_t slen = sizeof(peer_addr);
7982

8083
/* Process FCC socket events */
81-
if (ctx->fcc.fcc_sock > 0 && fd == ctx->fcc.fcc_sock) {
84+
if (ctx->fcc.fcc_sock >= 0 && fd == ctx->fcc.fcc_sock) {
8285
/* Allocate a fresh buffer from pool for this receive operation */
8386
buffer_ref_t *recv_buf = buffer_pool_alloc();
8487
if (!recv_buf) {
@@ -143,7 +146,7 @@ int stream_handle_fd_event(stream_context_t *ctx, int fd, uint32_t events,
143146
}
144147

145148
/* Process multicast socket events */
146-
if (ctx->mcast_sock > 0 && fd == ctx->mcast_sock) {
149+
if (ctx->mcast_sock >= 0 && fd == ctx->mcast_sock) {
147150
/* Allocate a fresh buffer from pool for this receive operation */
148151
buffer_ref_t *recv_buf = buffer_pool_alloc();
149152
if (!recv_buf) {
@@ -198,7 +201,7 @@ int stream_handle_fd_event(stream_context_t *ctx, int fd, uint32_t events,
198201
}
199202

200203
/* Process RTSP socket events */
201-
if (ctx->rtsp.socket > 0 && fd == ctx->rtsp.socket) {
204+
if (ctx->rtsp.socket >= 0 && fd == ctx->rtsp.socket) {
202205
/* Handle RTSP socket events (handshake and RTP data in PLAYING state) */
203206
int result = rtsp_handle_socket_event(&ctx->rtsp, events);
204207
if (result < 0) {
@@ -218,7 +221,7 @@ int stream_handle_fd_event(stream_context_t *ctx, int fd, uint32_t events,
218221
}
219222

220223
/* Process RTSP RTP socket events (UDP mode) */
221-
if (ctx->rtsp.rtp_socket > 0 && fd == ctx->rtsp.rtp_socket) {
224+
if (ctx->rtsp.rtp_socket >= 0 && fd == ctx->rtsp.rtp_socket) {
222225
int result = rtsp_handle_udp_rtp_data(&ctx->rtsp, ctx->conn);
223226
if (result < 0) {
224227
return -1; /* Error */
@@ -230,7 +233,7 @@ int stream_handle_fd_event(stream_context_t *ctx, int fd, uint32_t events,
230233
}
231234

232235
/* Handle UDP RTCP socket (for future RTCP processing) */
233-
if (ctx->rtsp.rtcp_socket > 0 && fd == ctx->rtsp.rtcp_socket) {
236+
if (ctx->rtsp.rtcp_socket >= 0 && fd == ctx->rtsp.rtcp_socket) {
234237
/* RTCP data processing could be added here in the future */
235238
/* For now, just consume the data to prevent buffer overflow */
236239
uint8_t rtcp_buffer[RTCP_BUFFER_SIZE];
@@ -252,6 +255,7 @@ int stream_context_init_for_worker(stream_context_t *ctx, connection_t *conn,
252255
ctx->service = service;
253256
ctx->epoll_fd = epoll_fd;
254257
ctx->status_index = status_index;
258+
ctx->mcast_sock = -1;
255259
fcc_session_init(&ctx->fcc);
256260
ctx->fcc.status_index = status_index;
257261
rtsp_session_init(&ctx->rtsp);
@@ -319,7 +323,7 @@ int stream_context_init_for_worker(stream_context_t *ctx, connection_t *conn,
319323
/* Direct multicast join */
320324
/* Note: Both /rtp/ and /udp/ endpoints now use unified packet detection */
321325
/* Packets are automatically detected as RTP or raw UDP at receive time */
322-
ctx->mcast_sock = stream_join_mcast_group(ctx);
326+
stream_join_mcast_group(ctx);
323327
fcc_session_set_state(&ctx->fcc, FCC_STATE_MCAST_ACTIVE,
324328
"Direct multicast");
325329
}
@@ -332,7 +336,7 @@ int stream_tick(stream_context_t *ctx, int64_t now) {
332336
return 0;
333337

334338
/* Periodic multicast rejoin (if enabled) */
335-
if (config.mcast_rejoin_interval > 0 && ctx->mcast_sock > 0) {
339+
if (config.mcast_rejoin_interval > 0 && ctx->mcast_sock >= 0) {
336340
int64_t elapsed_ms = now - ctx->last_mcast_rejoin_time;
337341
if (elapsed_ms >= config.mcast_rejoin_interval * 1000) {
338342
logger(LOG_DEBUG, "Multicast: Periodic rejoin (interval: %d seconds)",
@@ -350,7 +354,7 @@ int stream_tick(stream_context_t *ctx, int64_t now) {
350354
}
351355

352356
/* Check for multicast stream timeout */
353-
if (ctx->mcast_sock > 0) {
357+
if (ctx->mcast_sock >= 0) {
354358
int64_t elapsed_ms = now - ctx->last_mcast_data_time;
355359
if (elapsed_ms >= MCAST_TIMEOUT_SEC * 1000) {
356360
logger(LOG_ERROR,
@@ -361,7 +365,7 @@ int stream_tick(stream_context_t *ctx, int64_t now) {
361365
}
362366

363367
/* Check for FCC timeouts */
364-
if (ctx->fcc.fcc_sock > 0) {
368+
if (ctx->fcc.fcc_sock >= 0) {
365369
int64_t elapsed_ms = now - ctx->last_fcc_data_time;
366370
int timeout_ms = 0;
367371

@@ -383,7 +387,7 @@ int stream_tick(stream_context_t *ctx, int64_t now) {
383387
fcc_session_set_state(&ctx->fcc, FCC_STATE_MCAST_ACTIVE,
384388
"First unicast packet timeout");
385389
}
386-
ctx->mcast_sock = stream_join_mcast_group(ctx);
390+
stream_join_mcast_group(ctx);
387391
}
388392
} else if (ctx->fcc.state == FCC_STATE_UNICAST_ACTIVE ||
389393
ctx->fcc.state == FCC_STATE_MCAST_REQUESTED) {
@@ -397,9 +401,7 @@ int stream_tick(stream_context_t *ctx, int64_t now) {
397401
FCC_TIMEOUT_UNICAST_SEC);
398402
fcc_session_set_state(&ctx->fcc, FCC_STATE_MCAST_ACTIVE,
399403
"Unicast interrupted");
400-
if (!ctx->mcast_sock) {
401-
ctx->mcast_sock = stream_join_mcast_group(ctx);
402-
}
404+
stream_join_mcast_group(ctx);
403405
}
404406

405407
/* Check if we've been waiting too long for sync notification */
@@ -487,9 +489,9 @@ int stream_context_cleanup(stream_context_t *ctx) {
487489
int rtsp_async = rtsp_session_cleanup(&ctx->rtsp);
488490

489491
/* Close multicast socket if active (always safe to cleanup immediately) */
490-
if (ctx->mcast_sock) {
492+
if (ctx->mcast_sock >= 0) {
491493
worker_cleanup_socket_from_epoll(ctx->epoll_fd, ctx->mcast_sock);
492-
ctx->mcast_sock = 0;
494+
ctx->mcast_sock = -1;
493495
logger(LOG_DEBUG, "Multicast socket closed");
494496
}
495497

src/stream.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,8 @@ typedef struct stream_context_s {
4848
* last_mcast_data_time to prevent false timeout triggers. Should be used
4949
* instead of join_mcast_group() directly in all stream-related code.
5050
* @param ctx Stream context
51-
* @return Socket file descriptor on success, exits on failure
5251
*/
53-
int stream_join_mcast_group(stream_context_t *ctx);
52+
void stream_join_mcast_group(stream_context_t *ctx);
5453

5554
/**
5655
* Initialize a stream context for integration into a worker's unified epoll

0 commit comments

Comments
 (0)