[vlc-devel] [PATCH] RFC: http: add support for byte range requests
Francois Cartegnie
fcvlcdev at free.fr
Fri Jun 14 17:25:21 CEST 2019
ByteRange support in HTTP requests is mandatory
for adaptive.
-> replace adaptive custom http code
-> replace adaptive usage of streamUrl
---
modules/access/http/file.c | 72 +++++++++++++++++++++++++++++---------
modules/access/http/file.h | 20 +++++++++++
2 files changed, 75 insertions(+), 17 deletions(-)
diff --git a/modules/access/http/file.c b/modules/access/http/file.c
index 322c0b2fbe..f7f3ea293d 100644
--- a/modules/access/http/file.c
+++ b/modules/access/http/file.c
@@ -39,17 +39,23 @@
#pragma GCC visibility push(default)
+struct vlc_http_file_bytepos
+{
+ uintmax_t offset;
+ uintmax_t offset_max;
+};
+
struct vlc_http_file
{
struct vlc_http_resource resource;
- uintmax_t offset;
+ struct vlc_http_file_bytepos pos;
};
static int vlc_http_file_req(const struct vlc_http_resource *res,
struct vlc_http_msg *req, void *opaque)
{
struct vlc_http_file *file = (struct vlc_http_file *)res;
- const uintmax_t *offset = opaque;
+ struct vlc_http_file_bytepos *pos = opaque;
if (file->resource.response != NULL)
{
@@ -69,16 +75,30 @@ static int vlc_http_file_req(const struct vlc_http_resource *res,
}
}
- if (vlc_http_msg_add_header(req, "Range", "bytes=%" PRIuMAX "-", *offset)
- && *offset != 0)
+ int ret;
+ if(pos->offset_max == (uintmax_t)-1)
+ {
+ ret = vlc_http_msg_add_header(req, "Range", "bytes=%"
+ PRIuMAX "-",
+ pos->offset);
+ }
+ else
+ {
+ ret = vlc_http_msg_add_header(req, "Range", "bytes=%"
+ PRIuMAX "-%" PRIuMAX,
+ pos->offset, pos->offset_max);
+ }
+
+ if (ret && pos->offset != 0)
return -1;
+
return 0;
}
static int vlc_http_file_resp(const struct vlc_http_resource *res,
const struct vlc_http_msg *resp, void *opaque)
{
- const uintmax_t *offset = opaque;
+ const struct vlc_http_file_bytepos *pos = opaque;
if (vlc_http_msg_get_status(resp) == 206)
{
@@ -90,7 +110,7 @@ static int vlc_http_file_resp(const struct vlc_http_resource *res,
uintmax_t start, end;
if (sscanf(str, "bytes %" SCNuMAX "-%" SCNuMAX, &start, &end) != 2
- || start != *offset || start > end)
+ || start != pos->offset || start > end)
/* A single range response is what we asked for, but not at that
* start offset. */
goto fail;
@@ -110,9 +130,11 @@ static const struct vlc_http_resource_cbs vlc_http_file_callbacks =
vlc_http_file_resp,
};
-struct vlc_http_resource *vlc_http_file_create(struct vlc_http_mgr *mgr,
- const char *uri, const char *ua,
- const char *ref)
+struct vlc_http_resource *vlc_http_file_create_ranged(struct vlc_http_mgr *mgr,
+ const char *uri, const char *ua,
+ const char *ref,
+ uintmax_t rangelow,
+ uintmax_t rangehigh)
{
struct vlc_http_file *file = malloc(sizeof (*file));
if (unlikely(file == NULL))
@@ -125,10 +147,18 @@ struct vlc_http_resource *vlc_http_file_create(struct vlc_http_mgr *mgr,
return NULL;
}
- file->offset = 0;
+ file->pos.offset_max = (rangehigh > rangelow) ? rangehigh : (uintmax_t)-1;
+ file->pos.offset = rangelow;
return &file->resource;
}
+struct vlc_http_resource *vlc_http_file_create(struct vlc_http_mgr *mgr,
+ const char *uri, const char *ua,
+ const char *ref)
+{
+ return vlc_http_file_create_ranged(mgr, uri, ua, ref, 0, 0);
+}
+
static uintmax_t vlc_http_msg_get_file_size(const struct vlc_http_msg *resp)
{
int status = vlc_http_msg_get_status(resp);
@@ -203,11 +233,19 @@ bool vlc_http_file_can_seek(struct vlc_http_resource *res)
int vlc_http_file_seek(struct vlc_http_resource *res, uintmax_t offset)
{
- struct vlc_http_msg *resp = vlc_http_res_open(res, &offset);
- if (resp == NULL)
+ struct vlc_http_file *file = (struct vlc_http_file *)res;
+ if(offset > file->pos.offset_max)
return -1;
- struct vlc_http_file *file = (struct vlc_http_file *)res;
+ struct vlc_http_file_bytepos pos =
+ {
+ .offset = offset,
+ .offset_max = file->pos.offset_max,
+ };
+
+ struct vlc_http_msg *resp = vlc_http_res_open(res, &pos);
+ if (resp == NULL)
+ return -1;
int status = vlc_http_msg_get_status(resp);
if (res->response != NULL)
@@ -225,7 +263,7 @@ int vlc_http_file_seek(struct vlc_http_resource *res, uintmax_t offset)
}
res->response = resp;
- file->offset = offset;
+ file->pos = pos;
return 0;
}
@@ -238,8 +276,8 @@ block_t *vlc_http_file_read(struct vlc_http_resource *res)
{ /* Automatically reconnect on error if server supports seek */
if (res->response != NULL
&& vlc_http_msg_can_seek(res->response)
- && file->offset < vlc_http_msg_get_file_size(res->response)
- && vlc_http_file_seek(res, file->offset) == 0)
+ && file->pos.offset < vlc_http_msg_get_file_size(res->response)
+ && vlc_http_file_seek(res, file->pos.offset) == 0)
block = vlc_http_res_read(res);
if (block == vlc_http_error)
@@ -249,6 +287,6 @@ block_t *vlc_http_file_read(struct vlc_http_resource *res)
if (block == NULL)
return NULL; /* End of stream */
- file->offset += block->i_buffer;
+ file->pos.offset += block->i_buffer;
return block;
}
diff --git a/modules/access/http/file.h b/modules/access/http/file.h
index 802cf8f93a..259238089f 100644
--- a/modules/access/http/file.h
+++ b/modules/access/http/file.h
@@ -46,6 +46,26 @@ struct vlc_http_resource *vlc_http_file_create(struct vlc_http_mgr *mgr,
const char *url, const char *ua,
const char *ref);
+/**
+ * Creates an HTTP file from byte range.
+ *
+ * Allocates a structure for a remote HTTP-served read-only file.
+ * Using this API will fail if the server does not provide
+ * Content-Range support
+ *
+ * @param url URL of the file to read
+ * @param ua user agent string (or NULL to ignore)
+ * @param ref referral URL (or NULL to ignore)
+ * @param rangelow byte range start
+ * @param ref referral URL (< rangelow or (uintmax_t)-1 to ignore)
+ *
+ * @return an HTTP resource object pointer, or NULL on error
+ */
+struct vlc_http_resource *vlc_http_file_create_ranged(struct vlc_http_mgr *mgr,
+ const char *url, const char *ua,
+ const char *ref,
+ uintmax_t rangelow,
+ uintmax_t rangehigh);
/**
* Gets file size.
*
--
2.20.1
More information about the vlc-devel
mailing list