From 4d4379901a0a01859728d56795a7ab6ada9c876b Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 21 Mar 2010 14:13:18 +0100 Subject: [PATCH] udp_recv: Close receiver after 5 seconds of inactivitly. There is no way for the UDP receiver to tell that para_server won't send any more data, e.g. because the UDP target has been deleted. Currently, in this case the UDP receiver listens on its socket indefinitely and the buffer tree stays active as well. This can be fatal if para_server starts sending data for another audio format much later. So close the UDP socket if no data has been received for 5 seconds. --- error.h | 1 + udp_recv.c | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/error.h b/error.h index 731387c7..2cca4c2e 100644 --- a/error.h +++ b/error.h @@ -234,6 +234,7 @@ extern const char **para_errlist[]; #define UDP_RECV_ERRORS \ PARA_ERROR(UDP_SYNTAX, "udp_recv syntax error"), \ PARA_ERROR(UDP_OVERRUN, "output buffer overrun"), \ + PARA_ERROR(UDP_TIMEOUT, "timeout reading on UDP socket"), \ #define HTTP_RECV_ERRORS \ diff --git a/udp_recv.c b/udp_recv.c index 8dc8edc0..4f363ccb 100644 --- a/udp_recv.c +++ b/udp_recv.c @@ -32,6 +32,7 @@ struct private_udp_recv_data { /** The socket file descriptor. */ int fd; struct btr_pool *btrp; + struct timeval last_read_time; }; static void udp_recv_pre_select(struct sched *s, struct task *t) @@ -77,8 +78,15 @@ static void udp_recv_post_select(__a_unused struct sched *s, struct task *t) goto err; if (ret == 0) return; - if (!FD_ISSET(purd->fd, &s->rfds)) + if (!FD_ISSET(purd->fd, &s->rfds)) { + struct timeval tmp; + tv_add(&purd->last_read_time, &(struct timeval)EMBRACE(5, 0), + &tmp); + ret = -E_UDP_TIMEOUT; + if (tv_diff(now, &tmp, NULL) > 0) + goto err; return; + } iovcnt = btr_pool_get_buffers(purd->btrp, iov); ret = -E_UDP_OVERRUN; if (iovcnt == 0) @@ -92,6 +100,7 @@ static void udp_recv_post_select(__a_unused struct sched *s, struct task *t) ret = udp_check_eof(packet_size, iov); if (ret < 0) goto err; + purd->last_read_time = *now; if (iov[0].iov_len >= packet_size) btr_add_output_pool(purd->btrp, packet_size, btrn); else { /* both buffers contain data */ @@ -220,6 +229,7 @@ static int udp_recv_open(struct receiver_node *rn) PARA_INFO_LOG("receiving from %s:%d, fd=%d\n", c->host_arg, c->port_arg, purd->fd); purd->btrp = btr_pool_new("udp_recv", 320 * 1024); + purd->last_read_time = *now; return purd->fd; err: free(rn->private_data); -- 2.39.2