summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Buitenhuis <derek.buitenhuis@gmail.com>2024-04-22 15:25:45 +0100
committerDerek Buitenhuis <derek.buitenhuis@gmail.com>2024-04-25 14:19:50 +0100
commit31de02cf319187855d8d07e893593ae23094a052 (patch)
tree7dd2274934042ef9a2ce5bbfe5048dd18ac944e1
parent10374ab5eddd8bccaa1b809e5cd8782cf1dc28e8 (diff)
downloadffmpeg-31de02cf319187855d8d07e893593ae23094a052.tar.gz
avformat/http: Add option to limit total reconnect delay
The existing option only allows users to set the max delay for a single attempt, rather than the total allowed delay, which is both pretty unintitive, and only applicable when exponential backoff is used. The default for this option is set to 256, which is just above the effective total delay accomplished by the the existing reconnect_delay_max default of 120. Signed-off-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
-rw-r--r--libavformat/http.c12
-rw-r--r--libavformat/version.h2
2 files changed, 11 insertions, 3 deletions
diff --git a/libavformat/http.c b/libavformat/http.c
index 288d27de20..eecc4fd357 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -139,6 +139,7 @@ typedef struct HTTPContext {
AVDictionary *redirect_cache;
uint64_t filesize_from_content_range;
int reconnect_max_retries;
+ int reconnect_delay_total_max;
} HTTPContext;
#define OFFSET(x) offsetof(HTTPContext, x)
@@ -178,6 +179,7 @@ static const AVOption options[] = {
{ "reconnect_streamed", "auto reconnect streamed / non seekable streams", OFFSET(reconnect_streamed), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D },
{ "reconnect_delay_max", "max reconnect delay in seconds after which to give up", OFFSET(reconnect_delay_max), AV_OPT_TYPE_INT, { .i64 = 120 }, 0, UINT_MAX/1000/1000, D },
{ "reconnect_max_retries", "the max number of times to retry a connection", OFFSET(reconnect_max_retries), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, D },
+ { "reconnect_delay_total_max", "max total reconnect delay in seconds after which to give up", OFFSET(reconnect_delay_total_max), AV_OPT_TYPE_INT, { .i64 = 256 }, 0, UINT_MAX/1000/1000, D },
{ "listen", "listen on HTTP", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, D | E },
{ "resource", "The resource requested by a client", OFFSET(resource), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
{ "reply_code", "The http status code to return to a client", OFFSET(reply_code), AV_OPT_TYPE_INT, { .i64 = 200}, INT_MIN, 599, E},
@@ -360,6 +362,7 @@ static int http_open_cnx(URLContext *h, AVDictionary **options)
HTTPContext *s = h->priv_data;
int ret, conn_attempts = 1, auth_attempts = 0, redirects = 0;
int reconnect_delay = 0;
+ int reconnect_delay_total = 0;
uint64_t off;
char *cached;
@@ -386,13 +389,15 @@ redo:
if (ret < 0) {
if (!http_should_reconnect(s, ret) ||
reconnect_delay > s->reconnect_delay_max ||
- (s->reconnect_max_retries >= 0 && conn_attempts > s->reconnect_max_retries))
+ (s->reconnect_max_retries >= 0 && conn_attempts > s->reconnect_max_retries) ||
+ reconnect_delay_total > s->reconnect_delay_total_max)
goto fail;
av_log(h, AV_LOG_WARNING, "Will reconnect at %"PRIu64" in %d second(s).\n", off, reconnect_delay);
ret = ff_network_sleep_interruptible(1000U * 1000 * reconnect_delay, &h->interrupt_callback);
if (ret != AVERROR(ETIMEDOUT))
goto fail;
+ reconnect_delay_total += reconnect_delay;
reconnect_delay = 1 + 2 * reconnect_delay;
conn_attempts++;
@@ -1699,6 +1704,7 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size)
int err, read_ret;
int64_t seek_ret;
int reconnect_delay = 0;
+ int reconnect_delay_total = 0;
int conn_attempts = 1;
if (!s->hd)
@@ -1728,13 +1734,15 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size)
!(s->reconnect_at_eof && read_ret == AVERROR_EOF))
break;
- if (reconnect_delay > s->reconnect_delay_max || (s->reconnect_max_retries >= 0 && conn_attempts > s->reconnect_max_retries))
+ if (reconnect_delay > s->reconnect_delay_max || (s->reconnect_max_retries >= 0 && conn_attempts > s->reconnect_max_retries) ||
+ reconnect_delay_total > s->reconnect_delay_total_max)
return AVERROR(EIO);
av_log(h, AV_LOG_WARNING, "Will reconnect at %"PRIu64" in %d second(s), error=%s.\n", s->off, reconnect_delay, av_err2str(read_ret));
err = ff_network_sleep_interruptible(1000U*1000*reconnect_delay, &h->interrupt_callback);
if (err != AVERROR(ETIMEDOUT))
return err;
+ reconnect_delay_total += reconnect_delay;
reconnect_delay = 1 + 2*reconnect_delay;
conn_attempts++;
seek_ret = http_seek_internal(h, target, SEEK_SET, 1);
diff --git a/libavformat/version.h b/libavformat/version.h
index ee91990360..41dbd4ad01 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,7 +32,7 @@
#include "version_major.h"
#define LIBAVFORMAT_VERSION_MINOR 3
-#define LIBAVFORMAT_VERSION_MICRO 101
+#define LIBAVFORMAT_VERSION_MICRO 102
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \