Commit d617f64c authored by Marvin Scholz's avatar Marvin Scholz

access/https: Handle ICY streams

parent dd0f2d12
......@@ -32,6 +32,9 @@
#include <vlc_keystore.h>
#include <vlc_plugin.h>
#include <vlc_url.h>
#include <vlc_modules.h>
#include <vlc_meta.h>
#include <vlc_input.h>
#include "connmgr.h"
#include "resource.h"
......@@ -66,6 +69,7 @@ static int FileSeek(stream_t *access, uint64_t pos)
static int FileControl(stream_t *access, int query, va_list args)
{
access_sys_t *sys = access->p_sys;
vlc_meta_t *meta;
switch (query)
{
......@@ -104,6 +108,14 @@ static int FileControl(stream_t *access, int query, va_list args)
case STREAM_SET_PAUSE_STATE:
break;
case STREAM_GET_META:
Please register or sign in to reply
meta = va_arg(args, vlc_meta_t *);
char *icy = vlc_http_res_get_icy_metaint(sys->resource);
if (icy != NULL)
vlc_meta_AddExtra(meta, "icy-metaint", icy);
free(icy);
break;
default:
return VLC_EGENERIC;
}
......@@ -130,6 +142,7 @@ static int NoSeek(stream_t *access, uint64_t pos)
static int LiveControl(stream_t *access, int query, va_list args)
{
access_sys_t *sys = access->p_sys;
vlc_meta_t *meta;
switch (query)
{
......@@ -149,6 +162,15 @@ static int LiveControl(stream_t *access, int query, va_list args)
*va_arg(args, char **) = vlc_http_live_get_type(sys->resource);
break;
case STREAM_GET_META:
meta = va_arg(args, vlc_meta_t *);
char *icy = vlc_http_res_get_icy_metaint(sys->resource);
if (icy != NULL)
vlc_meta_AddExtra(meta, "icy-metaint", icy);
free(icy);
break;
default:
return VLC_EGENERIC;
}
......@@ -167,6 +189,8 @@ static int Open(vlc_object_t *obj)
sys->manager = NULL;
sys->resource = NULL;
bool icy_enabled = module_exists("icy");
void *jar = NULL;
if (var_InheritBool(obj, "http-forward-cookies"))
jar = var_InheritAddress(obj, "http-cookies");
......@@ -187,7 +211,7 @@ static int Open(vlc_object_t *obj)
bool live = var_InheritBool(obj, "http-continuous");
sys->resource = (live ? vlc_http_live_create : vlc_http_file_create)(
sys->manager, access->psz_url, ua, referer);
sys->manager, access->psz_url, ua, referer, icy_enabled);
free(referer);
free(ua);
......@@ -260,6 +284,10 @@ static int Open(vlc_object_t *obj)
access->pf_control = FileControl;
}
access->p_sys = sys;
if (icy_enabled)
var_SetString(access->p_input, "stream-filter", "icy");
return VLC_SUCCESS;
error:
......
......@@ -112,14 +112,15 @@ static const struct vlc_http_resource_cbs vlc_http_file_callbacks =
struct vlc_http_resource *vlc_http_file_create(struct vlc_http_mgr *mgr,
const char *uri, const char *ua,
const char *ref)
const char *ref,
bool icy_enabled)
{
struct vlc_http_file *file = malloc(sizeof (*file));
if (unlikely(file == NULL))
return NULL;
if (vlc_http_res_init(&file->resource, &vlc_http_file_callbacks, mgr,
uri, ua, ref))
uri, ua, ref, icy_enabled))
{
free(file);
return NULL;
......
......@@ -44,7 +44,8 @@ struct block_t;
*/
struct vlc_http_resource *vlc_http_file_create(struct vlc_http_mgr *mgr,
const char *url, const char *ua,
const char *ref);
const char *ref,
bool icy_enabled);
/**
* Gets file size.
......
......@@ -173,7 +173,7 @@ static struct vlc_http_msg *vlc_h1_stream_wait(struct vlc_http_stream *stream)
struct vlc_http_msg *resp;
const char *str;
size_t len;
int minor;
int minor = -1;
assert(conn->active);
......@@ -187,13 +187,16 @@ static struct vlc_http_msg *vlc_h1_stream_wait(struct vlc_http_stream *stream)
vlc_http_dbg(CO(conn), "incoming response:\n%.*s", (int)len, payload);
resp = vlc_http_msg_headers(payload);
minor = vlc_http_minor(payload);
free(payload);
if (resp == NULL)
return vlc_h1_stream_fatal(conn);
assert(minor >= 0);
if (!vlc_http_msg_is_icy(resp))
{
minor = vlc_http_minor(payload);
assert(minor >= 0);
}
free(payload);
conn->content_length = vlc_http_msg_get_size(resp);
conn->connection_close = false;
......
......@@ -57,13 +57,15 @@ static const struct vlc_http_resource_cbs vlc_http_live_callbacks =
struct vlc_http_resource *vlc_http_live_create(struct vlc_http_mgr *mgr,
const char *uri, const char *ua,
const char *ref)
const char *ref,
bool icy_enabled)
{
struct vlc_http_resource *res = malloc(sizeof (*res));
if (unlikely(res == NULL))
return NULL;
if (vlc_http_res_init(res, &vlc_http_live_callbacks, mgr, uri, ua, ref))
if (vlc_http_res_init(res, &vlc_http_live_callbacks,
mgr, uri, ua, ref, icy_enabled))
{
free(res);
res = NULL;
......
......@@ -30,7 +30,8 @@ struct block_t;
struct vlc_http_resource *vlc_http_live_create(struct vlc_http_mgr *mgr,
const char *uri, const char *ua,
const char *ref);
const char *ref,
bool icy_enabled);
struct block_t *vlc_http_live_read(struct vlc_http_resource *);
#define vlc_http_live_get_status vlc_http_res_get_status
......
......@@ -46,6 +46,7 @@ struct vlc_http_msg
char *authority;
char *path;
char *(*headers)[2];
bool icy;
unsigned count;
struct vlc_http_stream *payload;
};
......@@ -189,6 +190,11 @@ const char *vlc_http_msg_get_path(const struct vlc_http_msg *m)
return m->path;
}
bool vlc_http_msg_is_icy(const struct vlc_http_msg *m)
{
return m->icy;
}
void vlc_http_msg_destroy(struct vlc_http_msg *m)
{
if (m->payload != NULL)
......@@ -222,6 +228,7 @@ vlc_http_req_create(const char *method, const char *scheme,
m->scheme = (scheme != NULL) ? strdup(scheme) : NULL;
m->authority = (authority != NULL) ? strdup(authority) : NULL;
m->path = (path != NULL) ? strdup(path) : NULL;
m->icy = false;
m->count = 0;
m->headers = NULL;
m->payload = NULL;
......@@ -338,6 +345,13 @@ struct vlc_http_msg *vlc_http_msg_headers(const char *msg)
if (unlikely(m == NULL))
return NULL;
}
else if (sscanf(msg, "ICY %3hu %*s", &code) == 1)
{
m = vlc_http_resp_create(code);
if (unlikely(m == NULL))
return NULL;
m->icy = true;
}
else
return NULL; /* TODO: request support */
......
......@@ -216,6 +216,13 @@ const char *vlc_http_msg_get_authority(const struct vlc_http_msg *);
*/
const char *vlc_http_msg_get_path(const struct vlc_http_msg *);
/**
* Indicates if the ICY protocol is used.
*
* @return true if ICY, or false if not
*/
bool vlc_http_msg_is_icy(const struct vlc_http_msg *);
/**
* Looks up a token in a header field.
*
......
......@@ -68,6 +68,10 @@ vlc_http_res_req(const struct vlc_http_resource *res, void *opaque)
if (res->referrer != NULL) /* TODO: validate URL */
vlc_http_msg_add_header(req, "Referer", "%s", res->referrer);
/* ICY metadata request */
if (res->icy_enabled)
vlc_http_msg_add_header(req, "Icy-MetaData", "1");
vlc_http_msg_add_cookies(req, vlc_http_mgr_get_jar(res->manager));
/* TODO: vlc_http_msg_add_header(req, "TE", "gzip, deflate"); */
......@@ -180,7 +184,8 @@ static char *vlc_http_authority(const char *host, unsigned port)
int vlc_http_res_init(struct vlc_http_resource *restrict res,
const struct vlc_http_resource_cbs *cbs,
struct vlc_http_mgr *mgr,
const char *uri, const char *ua, const char *ref)
const char *uri, const char *ua, const char *ref,
bool icy_enabled)
{
vlc_url_t url;
bool secure;
......@@ -197,6 +202,8 @@ int vlc_http_res_init(struct vlc_http_resource *restrict res,
secure = true;
else if (!vlc_ascii_strcasecmp(url.psz_protocol, "http"))
secure = false;
else if (!vlc_ascii_strcasecmp(url.psz_protocol, "icyx"))
secure = false;
else
{
errno = ENOTSUP;
......@@ -217,6 +224,7 @@ int vlc_http_res_init(struct vlc_http_resource *restrict res,
: NULL;
res->agent = (ua != NULL) ? strdup(ua) : NULL;
res->referrer = (ref != NULL) ? strdup(ref) : NULL;
res->icy_enabled = icy_enabled;
const char *path = url.psz_path;
if (path == NULL)
......@@ -260,12 +268,6 @@ char *vlc_http_res_get_redirect(struct vlc_http_resource *restrict res)
if (pragma != NULL && !vlc_ascii_strcasecmp(pragma, "features")
&& asprintf(&url, "mmsh://%s%s", res->authority, res->path) >= 0)
return url;
/* HACK: Seems like an ICY server. Redirect to ICYX scheme. */
if ((vlc_http_msg_get_header(res->response, "Icy-Name") != NULL
|| vlc_http_msg_get_header(res->response, "Icy-Genre") != NULL)
&& asprintf(&url, "icyx://%s%s", res->authority, res->path) >= 0)
return url;
}
/* TODO: if (status == 426 Upgrade Required) */
......@@ -319,6 +321,16 @@ char *vlc_http_res_get_type(struct vlc_http_resource *res)
return (type != NULL) ? strdup(type) : NULL;
}
char *vlc_http_res_get_icy_metaint(struct vlc_http_resource *res)
  • This function does not return the meta int anymore, but the whole header, no ? If so, you could rename it.

Please register or sign in to reply
{
int status = vlc_http_res_get_status(res);
if (status < 200 || status >= 300)
return NULL;
const char *metaint = vlc_http_msg_get_header(res->response, "Icy-Metaint");
return (metaint != NULL) ? strdup(metaint) : NULL;
}
struct block_t *vlc_http_res_read(struct vlc_http_resource *res)
{
int status = vlc_http_res_get_status(res);
......
......@@ -56,12 +56,14 @@ struct vlc_http_resource
char *password;
char *agent;
char *referrer;
bool icy_enabled;
};
int vlc_http_res_init(struct vlc_http_resource *,
const struct vlc_http_resource_cbs *cbs,
struct vlc_http_mgr *mgr,
const char *uri, const char *ua, const char *ref);
const char *uri, const char *ua, const char *ref,
bool icy_enabled);
/**
* Destroys an HTTP resource.
......@@ -91,6 +93,13 @@ char *vlc_http_res_get_redirect(struct vlc_http_resource *);
*/
char *vlc_http_res_get_type(struct vlc_http_resource *);
/**
* Gets ICY metadata interval, if any.
*
* @return Icy metaint or NULL.
*/
char *vlc_http_res_get_icy_metaint(struct vlc_http_resource *);
/**
* Reads data.
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment