| 2090 | } |
| 2091 | |
| 2092 | static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int force_reconnect) |
| 2093 | { |
| 2094 | HTTPContext *s = h->priv_data; |
| 2095 | URLContext *old_hd = NULL; |
| 2096 | uint64_t old_off = s->off; |
| 2097 | uint8_t old_buf[BUFFER_SIZE]; |
| 2098 | int old_buf_size, ret; |
| 2099 | AVDictionary *options = NULL; |
| 2100 | uint8_t discard[4096]; |
| 2101 | |
| 2102 | if (whence == AVSEEK_SIZE) |
| 2103 | return s->filesize; |
| 2104 | else if ((s->filesize == UINT64_MAX && whence == SEEK_END)) |
| 2105 | return AVERROR(ENOSYS); |
| 2106 | |
| 2107 | if (whence == SEEK_CUR) |
| 2108 | off += s->off; |
| 2109 | else if (whence == SEEK_END) |
| 2110 | off += s->filesize; |
| 2111 | else if (whence != SEEK_SET) |
| 2112 | return AVERROR(EINVAL); |
| 2113 | if (off < 0) |
| 2114 | return AVERROR(EINVAL); |
| 2115 | if (!force_reconnect && off == s->off) |
| 2116 | return s->off; |
| 2117 | s->off = off; |
| 2118 | |
| 2119 | if (s->off && h->is_streamed) |
| 2120 | return AVERROR(ENOSYS); |
| 2121 | |
| 2122 | /* do not try to make a new connection if seeking past the end of the file */ |
| 2123 | if (s->end_off || s->filesize != UINT64_MAX) { |
| 2124 | uint64_t end_pos = s->end_off ? s->end_off : s->filesize; |
| 2125 | if (s->off >= end_pos) |
| 2126 | return s->off; |
| 2127 | } |
| 2128 | |
| 2129 | /* if the location changed (redirect), revert to the original uri */ |
| 2130 | if (strcmp(s->uri, s->location)) { |
| 2131 | char *new_uri; |
| 2132 | new_uri = av_strdup(s->uri); |
| 2133 | if (!new_uri) |
| 2134 | return AVERROR(ENOMEM); |
| 2135 | av_free(s->location); |
| 2136 | s->location = new_uri; |
| 2137 | } |
| 2138 | |
| 2139 | /* we save the old context in case the seek fails */ |
| 2140 | old_buf_size = s->buf_end - s->buf_ptr; |
| 2141 | memcpy(old_buf, s->buf_ptr, old_buf_size); |
| 2142 | |
| 2143 | /* try to reuse existing connection for small seeks */ |
| 2144 | uint64_t remaining = s->range_end - old_off - old_buf_size; |
| 2145 | if (s->hd && !s->willclose && s->range_end && remaining <= ffurl_get_short_seek(h)) { |
| 2146 | /* drain remaining data left on the wire from previous request */ |
| 2147 | av_log(h, AV_LOG_DEBUG, "Soft-seeking to offset %"PRIu64" by draining " |
| 2148 | "%"PRIu64" remaining byte(s)\n", s->off, remaining); |
| 2149 | while (remaining) { |
no test coverage detected