static int64_t http_seek(URLContext *h, int64_t off, int whence) { HTTPContext *s = h->priv_data; URLContext *old_hd = s->hd; int64_t old_off = s->off; if (whence == AVSEEK_SIZE) return s->filesize; else if ((s->filesize == -1 && whence == SEEK_END) || h->is_streamed) return -1; /* we save the old context in case the seek fails */ s->hd = NULL; if (whence == SEEK_CUR) off += s->off; else if (whence == SEEK_END) off += s->filesize; s->off = off; /* if it fails, continue on old connection */ if (http_open_cnx(h) < 0) { s->hd = old_hd; s->off = old_off; return -1; } url_close(old_hd); return off; }
static int64_t http_seek(URLContext *h, int64_t off, int whence) { HTTPContext *s = h->priv_data; URLContext *old_hd = s->hd; int64_t old_off = s->off; uint8_t old_buf[BUFFER_SIZE]; int old_buf_size; if (whence == AVSEEK_SIZE) return s->filesize; else if ((s->filesize == -1 && whence == SEEK_END) || h->is_streamed) return -1; /* we save the old context in case the seek fails */ old_buf_size = s->buf_end - s->buf_ptr; memcpy(old_buf, s->buf_ptr, old_buf_size); s->hd = NULL; if (whence == SEEK_CUR) off += s->off; else if (whence == SEEK_END) off += s->filesize; s->off = off; /* if it fails, continue on old connection */ if (http_open_cnx(h) < 0) { memcpy(s->buffer, old_buf, old_buf_size); s->buf_ptr = s->buffer; s->buf_end = s->buffer + old_buf_size; s->hd = old_hd; s->off = old_off; return -1; } url_close(old_hd); return off; }
static int http_open(URLContext *h, const char *uri, int flags, AVDictionary **options) { HTTPContext *s = h->priv_data; int ret; if( s->seekable == 1 ) h->is_streamed = 0; else h->is_streamed = 1; s->filesize = -1; s->location = av_strdup(uri); if (!s->location) return AVERROR(ENOMEM); if (options) av_dict_copy(&s->chained_options, *options, 0); if (s->headers) { int len = strlen(s->headers); if (len < 2 || strcmp("\r\n", s->headers + len - 2)) av_log(h, AV_LOG_WARNING, "No trailing CRLF found in HTTP header.\n"); } if (s->listen) { return http_listen(h, uri, flags, options); } ret = http_open_cnx(h, options); if (ret < 0) av_dict_free(&s->chained_options); return ret; }
static int http_read(URLContext *h, uint8_t *buf, int size) { HTTPContext *s = h->priv_data; int len; if (!s->init) { int ret = http_open_cnx(h); if (ret != 0) return ret; } if (!s->hd) return AVERROR(EIO); /* A size of zero can be used to force * initializaton of the connection. */ if (!size) return 0; if (s->chunksize >= 0) { if (!s->chunksize) { char line[32]; for(;;) { do { if (http_get_line(s, line, sizeof(line)) < 0) return AVERROR(EIO); } while (!*line); /* skip CR LF from last chunk */ s->chunksize = strtoll(line, NULL, 16); dprintf(NULL, "Chunked encoding data size: %"PRId64"'\n", s->chunksize); if (!s->chunksize) return 0; break; } } size = FFMIN(size, s->chunksize); } /* read bytes from input buffer first */ len = s->buf_end - s->buf_ptr; if (len > 0) { if (len > size) len = size; memcpy(buf, s->buf_ptr, len); s->buf_ptr += len; } else { len = url_read(s->hd, buf, size); } if (len > 0) { s->off += len; if (s->chunksize > 0) s->chunksize -= len; } return len; }
static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int force_reconnect) { HTTPContext *s = h->priv_data; URLContext *old_hd = s->hd; int64_t old_off = s->off; uint8_t old_buf[BUFFER_SIZE]; int old_buf_size, ret; AVDictionary *options = NULL; if (whence == AVSEEK_SIZE) return s->filesize; else if (!force_reconnect && ((whence == SEEK_CUR && off == 0) || (whence == SEEK_SET && off == s->off))) return s->off; else if ((s->filesize == -1 && whence == SEEK_END) || h->is_streamed) return AVERROR(ENOSYS); if (whence == SEEK_CUR) off += s->off; else if (whence == SEEK_END) off += s->filesize; else if (whence != SEEK_SET) return AVERROR(EINVAL); if (off < 0) return AVERROR(EINVAL); s->off = off; /* we save the old context in case the seek fails */ old_buf_size = s->buf_end - s->buf_ptr; memcpy(old_buf, s->buf_ptr, old_buf_size); s->hd = NULL; /* if it fails, continue on old connection */ if ((ret = http_open_cnx(h, &options)) < 0) { av_dict_free(&options); memcpy(s->buffer, old_buf, old_buf_size); s->buf_ptr = s->buffer; s->buf_end = s->buffer + old_buf_size; s->hd = old_hd; s->off = old_off; return ret; } av_dict_free(&options); ffurl_close(old_hd); return off; }
int ff_http_do_new_request(URLContext *h, const char *uri) { HTTPContext *s = h->priv_data; AVDictionary *options = NULL; int ret; s->off = 0; s->icy_data_read = 0; av_free(s->location); s->location = av_strdup(uri); if (!s->location) return AVERROR(ENOMEM); ret = http_open_cnx(h, &options); av_dict_free(&options); return ret; }
static int http_open(URLContext *h, const char *uri, int flags) { HTTPContext *s; int ret; s = av_malloc(sizeof(HTTPContext)); if (!s) { return AVERROR(ENOMEM); } h->priv_data = s; s->filesize = -1; s->chunksize = -1; s->off = 0; av_strlcpy(s->location, uri, URL_SIZE); ret = http_open_cnx(h); if (ret != 0) av_free (s); h->is_streamed = 1;/*make sure we are streamed*/ return ret; }
/* used only when posting data */ static int http_write(URLContext *h, const uint8_t *buf, int size) { char temp[11] = ""; /* 32-bit hex + CRLF + nul */ int ret; char crlf[] = "\r\n"; HTTPContext *s = h->priv_data; if (!s->init) { int ret = http_open_cnx(h); if (ret != 0) return ret; } if (!s->hd) return AVERROR(EIO); if (s->chunksize == -1) { /* headers are sent without any special encoding */ return url_write(s->hd, buf, size); } /* silently ignore zero-size data since chunk encoding that would * signal EOF */ if (size > 0) { /* upload data using chunked encoding */ if(s->is_chunked) { snprintf(temp, sizeof(temp), "%x\r\n", size); if ((ret = url_write(s->hd, temp, strlen(temp))) < 0) return ret; } if ((ret = url_write(s->hd, buf, size)) < 0) return ret; if (s->is_chunked && (ret = url_write(s->hd, crlf, sizeof(crlf) - 1)) < 0) return ret; } return size; }