From: Andre Noll Date: Sun, 21 Mar 2010 13:13:18 +0000 (+0100) Subject: udp_recv: Close receiver after 5 seconds of inactivitly. X-Git-Tag: v0.4.2~20^2~2 X-Git-Url: http://git.tue.mpg.de/?a=commitdiff_plain;h=4d4379901a0a01859728d56795a7ab6ada9c876b;p=paraslash.git 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. --- 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);