From patchwork Tue Jan 2 16:19:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: wm4 X-Patchwork-Id: 7082 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.79.195 with SMTP id r64csp14872641jad; Tue, 2 Jan 2018 08:24:55 -0800 (PST) X-Google-Smtp-Source: ACJfBouSoQaJ2Kjoq3LlhFXK1+u0FZqcaU5L+9gu777HyG2ABZE30JjTw2BZDyB5vYNVjUPLaOo+ X-Received: by 10.28.66.145 with SMTP id k17mr33521113wmi.32.1514910295312; Tue, 02 Jan 2018 08:24:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1514910295; cv=none; d=google.com; s=arc-20160816; b=r/hRjw95J6Kk8QN5j22D3UIvQqNWGshSKpQ6P9KfpzcKsrvcaoHrMpqAEjkUt8nZsy DpkFC05xfgM99D2r/yhWuBKkMqveGeVKFAXj7vEZpx4dpKiwCtug/LwxCBYzsqYXz2Ty nF77cKH58PTowVFw18zaNCTAqO7JvVj7r9z0Ug9nogioFzfQD4NjzP/xZyE99B2H6DgJ M6O1ZOinsE+fZ/UO6Is1ukJOD31PGqp1eAiR9Jr8u2sQYZmBBccUrar2p4WGfsdPxnq3 hHExjLTcIt8yPcvAP34nkilKZz4nq+yJ1hELm/qyGoWtpKVmx5MXaF6ExKedlr2g8BuB RDEw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:delivered-to:arc-authentication-results; bh=+xeledChopJCYoCbzJCWyHKx9CKAgr9iGlh5oitYDhw=; b=0dIczscppBkSy+NUhZxN49ED60bHwnBgC7D/1TWWjlrzYiQJWdoZnxL3oopXwxVWLD jCHdEPD0WbLF1U15mb7xcIMvNg5EJvNEl6HSTAZTDPLICYuIN2HRpBx+LiogANpfTwns 6q0iikvhMs5D66qDb0XFLtCNCExbZ7x5kOnsqWWizA5Iz8aJ4JhbZcLS7UyV5Sg+R00X qyRPyVoTchYiO8bbLTFf9LNL8X3U3abwPZQKdOp3JaT7OrAQMtJ6uoy6Bm+Qj8RTFlVX amNf52YiZ9Eswe4MVJ651EsKOI6GdoQoPzQcaZQTF3TjtKRl7K8HBeLXA5CC3GxM4y4T Su1w== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@googlemail.com header.s=20161025 header.b=b9WWMWEV; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id f8si10491254wmc.113.2018.01.02.08.24.54; Tue, 02 Jan 2018 08:24:55 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@googlemail.com header.s=20161025 header.b=b9WWMWEV; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id ED2F26882AD; Tue, 2 Jan 2018 18:24:37 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm0-f67.google.com (mail-wm0-f67.google.com [74.125.82.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3B961687EB1 for ; Tue, 2 Jan 2018 18:24:32 +0200 (EET) Received: by mail-wm0-f67.google.com with SMTP id i11so61635505wmf.4 for ; Tue, 02 Jan 2018 08:24:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Vo3Xmf7BHWuT5E8l3yQLfh32wK6bX0aGY4/FX1dUCn8=; b=b9WWMWEVgVFS9qWDwp5setlBuqeJHhqS/AuoGAOc68/NVVwGwVfilt7RsNVpl1qnzP 76qz8u9Mz4IaDHEDdcNNhzmIYfBV+47FZLWpCIoKfNI0uAHmfJ77JIYTZyzNShgvPb7F 6XzQs3wG6ieM0AfeZcq0IfjJt39kNvtWZZOa0WJ/DTuNyaXKfcO2RY2dpF1ODp2WXxvH hKIV5Zs3y4fYPz+Kbp+bh9Rymi1n+glZNcZTeM2qboBuAzMug8iaH+397hVcDPsjhP6s iZBy48E9BKTqFSd61lucgbJJAA5hy7xYystASaCFHa9Cn4TYNmnMQjlKJ/+P5IQPJorZ iRZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Vo3Xmf7BHWuT5E8l3yQLfh32wK6bX0aGY4/FX1dUCn8=; b=NEYMkL+hqzr8rIFBVRg/3SJ0VmCfd32UrQ/i7qyazyRig4Igj+sEACJp5iUEJvaUh7 mfTJVXgCyiU2Z7P+UYFI59gC+ySoOTD8Zgix2ZYrEo+2TYuys3fePQ0k0vFFugLk096F cMX2WkmkpHz+17WVtxMoa+Nhz+MJ3gg4F1ZifmzSv0myZYfHsrVFrqP428DVuqNQWg5C 0cTXewDu8V3UUbu97LR3lr73vbKwiUkqM8kCh4nkjMwcGNPk8+qQST0PEzouuXhMulPZ hqDS/kzEB3gDPMhkyJiibniOTyhK2cpgkh71IgUwasct0k+w0LvTk+RTk8V4DQ9jWnkF 8GpA== X-Gm-Message-State: AKGB3mIOCiw7KCZXhLXAobcook0rYcY+creYEq1A4l16Z0WAPjnTN/++ 1UehWICgholuxJIVoVfo8SDvdg== X-Received: by 10.28.104.6 with SMTP id d6mr34378929wmc.101.1514909959518; Tue, 02 Jan 2018 08:19:19 -0800 (PST) Received: from debian.speedport.ip (p2003006CCD4EDC821D87AA20F8C6E09A.dip0.t-ipconnect.de. [2003:6c:cd4e:dc82:1d87:aa20:f8c6:e09a]) by smtp.googlemail.com with ESMTPSA id w133sm13205260wmg.9.2018.01.02.08.19.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 02 Jan 2018 08:19:18 -0800 (PST) From: wm4 To: ffmpeg-devel@ffmpeg.org Date: Tue, 2 Jan 2018 17:19:14 +0100 Message-Id: <20180102161915.19575-1-nfxjfg@googlemail.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20171230170726.10824-1-nfxjfg@googlemail.com> References: <20171230170726.10824-1-nfxjfg@googlemail.com> Subject: [FFmpeg-devel] [PATCH v2 1/2] http: block while waiting for reconnecting X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: wm4 MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" It makes no sense to return an error after the first reconnect, and then somehow resume the next time it's called. Usually this will lead to demuxer errors. Make reconnecting block instead, until it has either successfully reconnected, or given up. Also make the wait reasonably interruptible. Since there is no mechanism for this in the API, polling is the best we can do. This behaves roughly the same as other interruptible network functions in libavformat. (The original code would work if it returned AVERROR(EAGAIN) or so, which would make retry_transfer_wrapper() repeat the read call. But I think having an explicit loop for this is better anyway.) I also snuck in a fix for reconnect_at_eof. It has to check for AVERROR_EOF, not 0. --- libavformat/http.c | 19 ++++++++++--------- libavformat/network.c | 18 ++++++++++++++++++ libavformat/network.h | 9 +++++++++ 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/libavformat/http.c b/libavformat/http.c index 8f7e56de54..5eff87f8bb 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -117,7 +117,6 @@ typedef struct HTTPContext { int reconnect; int reconnect_at_eof; int reconnect_streamed; - int reconnect_delay; int reconnect_delay_max; int listen; char *resource; @@ -1433,6 +1432,7 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) HTTPContext *s = h->priv_data; int err, new_location, read_ret; int64_t seek_ret; + int reconnect_delay = 0; if (!s->hd) return AVERROR_EOF; @@ -1448,25 +1448,26 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) return http_buf_read_compressed(h, buf, size); #endif /* CONFIG_ZLIB */ read_ret = http_buf_read(h, buf, size); - if ( (read_ret < 0 && s->reconnect && (!h->is_streamed || s->reconnect_streamed) && s->filesize > 0 && s->off < s->filesize) - || (read_ret == 0 && s->reconnect_at_eof && (!h->is_streamed || s->reconnect_streamed))) { + while ((read_ret < 0 && s->reconnect && (!h->is_streamed || s->reconnect_streamed) && s->filesize > 0 && s->off < s->filesize) + || (read_ret == AVERROR_EOF && s->reconnect_at_eof && (!h->is_streamed || s->reconnect_streamed))) { uint64_t target = h->is_streamed ? 0 : s->off; - if (s->reconnect_delay > s->reconnect_delay_max) + if (reconnect_delay > s->reconnect_delay_max) return AVERROR(EIO); av_log(h, AV_LOG_INFO, "Will reconnect at %"PRIu64" error=%s.\n", s->off, av_err2str(read_ret)); - av_usleep(1000U*1000*s->reconnect_delay); - s->reconnect_delay = 1 + 2*s->reconnect_delay; + err = ff_network_sleep_interruptible(1000U*1000*reconnect_delay, &h->interrupt_callback); + if (err != AVERROR(ETIMEDOUT)) + return err; + reconnect_delay = 1 + 2*reconnect_delay; seek_ret = http_seek_internal(h, target, SEEK_SET, 1); - if (seek_ret != target) { + if (seek_ret >= 0 && seek_ret != target) { av_log(h, AV_LOG_ERROR, "Failed to reconnect at %"PRIu64".\n", target); return read_ret; } read_ret = http_buf_read(h, buf, size); - } else - s->reconnect_delay = 0; + } return read_ret; } diff --git a/libavformat/network.c b/libavformat/network.c index 6c3d9def3b..e9eb4b443a 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -103,6 +103,24 @@ int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterrupt } } +int ff_network_sleep_interruptible(int64_t timeout, AVIOInterruptCB *int_cb) +{ + int64_t wait_start = av_gettime_relative(); + + while (1) { + int64_t time_left; + + if (ff_check_interrupt(int_cb)) + return AVERROR_EXIT; + + time_left = timeout - (av_gettime_relative() - wait_start); + if (time_left <= 0) + return AVERROR(ETIMEDOUT); + + av_usleep(FFMIN(time_left, POLLING_TIME * 1000)); + } +} + void ff_network_close(void) { #if HAVE_WINSOCK2_H diff --git a/libavformat/network.h b/libavformat/network.h index b78e3ad6ed..a663115541 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -96,6 +96,15 @@ int ff_network_wait_fd(int fd, int write); */ int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb); +/** + * Waits for up to 'timeout' microseconds. If the usert's int_cb is set and + * triggered, return before that. + * @timeout Timeout in microseconds. Maybe have lower actual precision. + * @param int_cb Interrupt callback, is checked regularly. + * @return AVERROR(ETIMEDOUT) if timeout expirted, AVERROR_EXIT if interrupted by int_cb + */ +int ff_network_sleep_interruptible(int64_t timeout, AVIOInterruptCB *int_cb); + int ff_inet_aton (const char * str, struct in_addr * add); #if !HAVE_STRUCT_SOCKADDR_STORAGE