avformat/http: Add options to set the max number of connection retries
Not every use case benefits from setting retries in terms of the backoff. Signed-off-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
This commit is contained in:
		
							parent
							
								
									a776d524e1
								
							
						
					
					
						commit
						10374ab5ed
					
				| @ -138,6 +138,7 @@ typedef struct HTTPContext { | |||||||
|     char *new_location; |     char *new_location; | ||||||
|     AVDictionary *redirect_cache; |     AVDictionary *redirect_cache; | ||||||
|     uint64_t filesize_from_content_range; |     uint64_t filesize_from_content_range; | ||||||
|  |     int reconnect_max_retries; | ||||||
| } HTTPContext; | } HTTPContext; | ||||||
| 
 | 
 | ||||||
| #define OFFSET(x) offsetof(HTTPContext, x) | #define OFFSET(x) offsetof(HTTPContext, x) | ||||||
| @ -176,6 +177,7 @@ static const AVOption options[] = { | |||||||
|     { "reconnect_on_http_error", "list of http status codes to reconnect on", OFFSET(reconnect_on_http_error), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, |     { "reconnect_on_http_error", "list of http status codes to reconnect on", OFFSET(reconnect_on_http_error), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, | ||||||
|     { "reconnect_streamed", "auto reconnect streamed / non seekable streams", OFFSET(reconnect_streamed), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D }, |     { "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_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 }, | ||||||
|     { "listen", "listen on HTTP", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, D | E }, |     { "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 }, |     { "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}, |     { "reply_code", "The http status code to return to a client", OFFSET(reply_code), AV_OPT_TYPE_INT, { .i64 = 200}, INT_MIN, 599, E}, | ||||||
| @ -356,7 +358,7 @@ static int http_open_cnx(URLContext *h, AVDictionary **options) | |||||||
| { | { | ||||||
|     HTTPAuthType cur_auth_type, cur_proxy_auth_type; |     HTTPAuthType cur_auth_type, cur_proxy_auth_type; | ||||||
|     HTTPContext *s = h->priv_data; |     HTTPContext *s = h->priv_data; | ||||||
|     int ret, auth_attempts = 0, redirects = 0; |     int ret, conn_attempts = 1, auth_attempts = 0, redirects = 0; | ||||||
|     int reconnect_delay = 0; |     int reconnect_delay = 0; | ||||||
|     uint64_t off; |     uint64_t off; | ||||||
|     char *cached; |     char *cached; | ||||||
| @ -383,7 +385,8 @@ redo: | |||||||
|     ret = http_open_cnx_internal(h, options); |     ret = http_open_cnx_internal(h, options); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         if (!http_should_reconnect(s, ret) || |         if (!http_should_reconnect(s, ret) || | ||||||
|             reconnect_delay > s->reconnect_delay_max) |             reconnect_delay > s->reconnect_delay_max || | ||||||
|  |             (s->reconnect_max_retries >= 0 && conn_attempts > s->reconnect_max_retries)) | ||||||
|             goto fail; |             goto fail; | ||||||
| 
 | 
 | ||||||
|         av_log(h, AV_LOG_WARNING, "Will reconnect at %"PRIu64" in %d second(s).\n", off, reconnect_delay); |         av_log(h, AV_LOG_WARNING, "Will reconnect at %"PRIu64" in %d second(s).\n", off, reconnect_delay); | ||||||
| @ -391,6 +394,7 @@ redo: | |||||||
|         if (ret != AVERROR(ETIMEDOUT)) |         if (ret != AVERROR(ETIMEDOUT)) | ||||||
|             goto fail; |             goto fail; | ||||||
|         reconnect_delay = 1 + 2 * reconnect_delay; |         reconnect_delay = 1 + 2 * reconnect_delay; | ||||||
|  |         conn_attempts++; | ||||||
| 
 | 
 | ||||||
|         /* restore the offset (http_connect resets it) */ |         /* restore the offset (http_connect resets it) */ | ||||||
|         s->off = off; |         s->off = off; | ||||||
| @ -1695,6 +1699,7 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) | |||||||
|     int err, read_ret; |     int err, read_ret; | ||||||
|     int64_t seek_ret; |     int64_t seek_ret; | ||||||
|     int reconnect_delay = 0; |     int reconnect_delay = 0; | ||||||
|  |     int conn_attempts = 1; | ||||||
| 
 | 
 | ||||||
|     if (!s->hd) |     if (!s->hd) | ||||||
|         return AVERROR_EOF; |         return AVERROR_EOF; | ||||||
| @ -1723,7 +1728,7 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) | |||||||
|             !(s->reconnect_at_eof && read_ret == AVERROR_EOF)) |             !(s->reconnect_at_eof && read_ret == AVERROR_EOF)) | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         if (reconnect_delay > s->reconnect_delay_max) |         if (reconnect_delay > s->reconnect_delay_max || (s->reconnect_max_retries >= 0 && conn_attempts > s->reconnect_max_retries)) | ||||||
|             return AVERROR(EIO); |             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)); |         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)); | ||||||
| @ -1731,6 +1736,7 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) | |||||||
|         if (err != AVERROR(ETIMEDOUT)) |         if (err != AVERROR(ETIMEDOUT)) | ||||||
|             return err; |             return err; | ||||||
|         reconnect_delay = 1 + 2*reconnect_delay; |         reconnect_delay = 1 + 2*reconnect_delay; | ||||||
|  |         conn_attempts++; | ||||||
|         seek_ret = http_seek_internal(h, target, SEEK_SET, 1); |         seek_ret = http_seek_internal(h, target, SEEK_SET, 1); | ||||||
|         if (seek_ret >= 0 && seek_ret != target) { |         if (seek_ret >= 0 && seek_ret != target) { | ||||||
|             av_log(h, AV_LOG_ERROR, "Failed to reconnect at %"PRIu64".\n", target); |             av_log(h, AV_LOG_ERROR, "Failed to reconnect at %"PRIu64".\n", target); | ||||||
|  | |||||||
| @ -32,7 +32,7 @@ | |||||||
| #include "version_major.h" | #include "version_major.h" | ||||||
| 
 | 
 | ||||||
| #define LIBAVFORMAT_VERSION_MINOR   3 | #define LIBAVFORMAT_VERSION_MINOR   3 | ||||||
| #define LIBAVFORMAT_VERSION_MICRO 100 | #define LIBAVFORMAT_VERSION_MICRO 101 | ||||||
| 
 | 
 | ||||||
| #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | ||||||
|                                                LIBAVFORMAT_VERSION_MINOR, \ |                                                LIBAVFORMAT_VERSION_MINOR, \ | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user