Summary
6be7932 (avformat/libcurl: also continue sending requests on unknown size) treats resources of unknown size as infinite "at least until we see a 416 Range Not Satisfiable". But nothing handles that 416. on_done() keeps issuing follow-up requests while file_end < 0. The follow-up issued after the true end gets a 416, which header_callback() treats as an ordinary HTTP error. So after the whole resource has been delivered correctly, the read returns AVERROR_HTTP_RANGE_NOT_SATISFIABLE instead of EOF. If reconnect_on_http_error contains 4xx or 416, it instead retries the 416 with backoff until max_retries runs out.
This is the libcurl counterpart of #46 (http.c).
Location
- Continuation on unknown size:
|
if (code == CURLE_OK && c->stream_ok) { |
|
int64_t file_end = c->content_size > 0 ? c->content_size - 1 : -1; |
|
if (c->end_off > 0) |
|
file_end = FFMIN(file_end, c->end_off - 1); |
|
if (c->seekable && c->request_end >= 0 && |
|
(c->request_end < file_end || file_end < 0)) |
|
{ |
|
c->is_initial = 0; |
|
start_request(c); |
|
return; |
|
} |
- Error branch in
header_callback():
|
} else { |
|
c->loop->num_errors++; |
|
c->stream_ok = 0; |
|
if (!c->status) { |
|
if (http_error_is_recoverable(c, status)) |
|
c->status = AVERROR(EAGAIN); |
|
else |
|
c->status = ff_http_averror(status, AVERROR(EIO)); |
|
} |
|
|
|
curl_off_t retry_after = 0; |
|
curl_easy_getinfo(c->easy, CURLINFO_RETRY_AFTER, &retry_after); |
|
c->retry_after = retry_after; |
|
} |
Reproduction
Server replies 206 with Content-Range: bytes 0-1048575/* (harness from #71):
$ t libcurl:http://127.0.0.1:18080/unknown --readall
size: -78 seekable: 1
readall: total=1048576 last=-909194488 (Server returned 416 Range Not Satisfiable) pb->error=-909194488 eof=1
All 1048576 bytes are delivered, and then the stream ends in an error rather than EOF.
Suggested fix
In header_callback(), when a follow-up request gets a 416 and content_size is unknown (probed, request_start equals the bytes delivered so far), set status = AVERROR_EOF and learn content_size = request_start. Exclude this case from the reconnect_on_http_error matching. Doing the same for a seek past the (unknown) end also covers the unknown-size variant of #74.
Summary
6be7932 (
avformat/libcurl: also continue sending requests on unknown size) treats resources of unknown size as infinite "at least until we see a 416 Range Not Satisfiable". But nothing handles that 416.on_done()keeps issuing follow-up requests whilefile_end < 0. The follow-up issued after the true end gets a 416, whichheader_callback()treats as an ordinary HTTP error. So after the whole resource has been delivered correctly, the read returnsAVERROR_HTTP_RANGE_NOT_SATISFIABLEinstead of EOF. Ifreconnect_on_http_errorcontains4xxor416, it instead retries the 416 with backoff untilmax_retriesruns out.This is the libcurl counterpart of #46 (http.c).
Location
FFmpeg/libavformat/libcurl.c
Lines 554 to 564 in fe63f8f
header_callback():FFmpeg/libavformat/libcurl.c
Lines 405 to 418 in fe63f8f
Reproduction
Server replies
206withContent-Range: bytes 0-1048575/*(harness from #71):All 1048576 bytes are delivered, and then the stream ends in an error rather than EOF.
Suggested fix
In
header_callback(), when a follow-up request gets a 416 andcontent_sizeis unknown (probed,request_startequals the bytes delivered so far), setstatus = AVERROR_EOFand learncontent_size = request_start. Exclude this case from thereconnect_on_http_errormatching. Doing the same for a seek past the (unknown) end also covers the unknown-size variant of #74.