udp_recv: Close receiver after 5 seconds of inactivitly.
authorAndre Noll <maan@systemlinux.org>
Sun, 21 Mar 2010 13:13:18 +0000 (14:13 +0100)
committerAndre Noll <maan@systemlinux.org>
Sun, 21 Mar 2010 13:13:18 +0000 (14:13 +0100)
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
udp_recv.c

diff --git a/error.h b/error.h
index 731387c725312b145efbd7bb9d14350dc2d3b328..2cca4c2ef3d86c1d3c983661a342f8c2abb9c8a6 100644 (file)
--- 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 \
index 8dc8edc0a3c9588492a47a5d6389236c601dbdbd..4f363ccb7f15b65273867526dcd43e9a98337b9c 100644 (file)
@@ -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);