Browse code

libavformat: not treat 0 as EOF

transfer_func variable passed to retry_transfer_wrapper
are h->prot->url_read and h->prot->url_write functions.
These need to return EOF or other error properly.
In case of returning >= 0, url_read/url_write is retried
until error is returned.

Signed-off-by: Daniel Kucera <daniel.kucera@gmail.com>

Daniel Kucera authored on 2017/10/17 17:29:30
Showing 5 changed files
... ...
@@ -391,8 +391,10 @@ static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
391 391
                 }
392 392
                 av_usleep(1000);
393 393
             }
394
-        } else if (ret < 1)
395
-            return (ret < 0 && ret != AVERROR_EOF) ? ret : len;
394
+        } else if (ret == AVERROR_EOF)
395
+            return (len > 0) ? len : AVERROR_EOF;
396
+        else if (ret < 0)
397
+            return ret;
396 398
         if (ret) {
397 399
             fast_retries = FFMAX(fast_retries, 2);
398 400
             wait_since = 0;
... ...
@@ -572,13 +572,14 @@ static void fill_buffer(AVIOContext *s)
572 572
     if (s->read_packet)
573 573
         len = s->read_packet(s->opaque, dst, len);
574 574
     else
575
-        len = 0;
576
-    if (len <= 0) {
575
+        len = AVERROR_EOF;
576
+    if (len == AVERROR_EOF) {
577 577
         /* do not modify buffer if EOF reached so that a seek back can
578 578
            be done without rereading data */
579 579
         s->eof_reached = 1;
580
-        if (len < 0)
581
-            s->error = len;
580
+    } else if (len < 0) {
581
+        s->eof_reached = 1;
582
+        s->error= len;
582 583
     } else {
583 584
         s->pos += len;
584 585
         s->buf_ptr = dst;
... ...
@@ -646,13 +647,16 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size)
646 646
                 // bypass the buffer and read data directly into buf
647 647
                 if(s->read_packet)
648 648
                     len = s->read_packet(s->opaque, buf, size);
649
-
650
-                if (len <= 0) {
649
+                else
650
+                    len = AVERROR_EOF;
651
+                if (len == AVERROR_EOF) {
651 652
                     /* do not modify buffer if EOF reached so that a seek back can
652 653
                     be done without rereading data */
653 654
                     s->eof_reached = 1;
654
-                    if(len<0)
655
-                        s->error= len;
655
+                    break;
656
+                } else if (len < 0) {
657
+                    s->eof_reached = 1;
658
+                    s->error= len;
656 659
                     break;
657 660
                 } else {
658 661
                     s->pos += len;
... ...
@@ -201,7 +201,7 @@ static int cache_read(URLContext *h, unsigned char *buf, int size)
201 201
     }
202 202
 
203 203
     r = ffurl_read(c->inner, buf, size);
204
-    if (r == 0 && size>0) {
204
+    if (r == AVERROR_EOF && size>0) {
205 205
         c->is_true_eof = 1;
206 206
         av_assert0(c->end >= c->logical_pos);
207 207
     }
... ...
@@ -263,7 +263,7 @@ resolve_eof:
263 263
                 if (whence == SEEK_SET)
264 264
                     size = FFMIN(sizeof(tmp), pos - c->logical_pos);
265 265
                 ret = cache_read(h, tmp, size);
266
-                if (ret == 0 && whence == SEEK_END) {
266
+                if (ret == AVERROR_EOF && whence == SEEK_END) {
267 267
                     av_assert0(c->is_true_eof);
268 268
                     goto resolve_eof;
269 269
                 }
... ...
@@ -135,19 +135,20 @@ static int concat_read(URLContext *h, unsigned char *buf, int size)
135 135
 
136 136
     while (size > 0) {
137 137
         result = ffurl_read(nodes[i].uc, buf, size);
138
-        if (result < 0)
139
-            return total ? total : result;
140
-        if (!result) {
138
+        if (result == AVERROR_EOF) {
141 139
             if (i + 1 == data->length ||
142 140
                 ffurl_seek(nodes[++i].uc, 0, SEEK_SET) < 0)
143 141
                 break;
142
+            result = 0;
144 143
         }
144
+        if (result < 0)
145
+            return total ? total : result;
145 146
         total += result;
146 147
         buf   += result;
147 148
         size  -= result;
148 149
     }
149 150
     data->current = i;
150
-    return total;
151
+    return total ? total : result;
151 152
 }
152 153
 
153 154
 static int64_t concat_seek(URLContext *h, int64_t pos, int whence)
... ...
@@ -1296,8 +1296,11 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size)
1296 1296
                    "Chunked encoding data size: %"PRIu64"'\n",
1297 1297
                     s->chunksize);
1298 1298
 
1299
-            if (!s->chunksize)
1299
+            if (!s->chunksize) {
1300
+                av_log(h, AV_LOG_DEBUG, "Last chunk received, closing conn\n");
1301
+                ffurl_closep(&s->hd);
1300 1302
                 return 0;
1303
+            }
1301 1304
             else if (s->chunksize == UINT64_MAX) {
1302 1305
                 av_log(h, AV_LOG_ERROR, "Invalid chunk size %"PRIu64"\n",
1303 1306
                        s->chunksize);