From 87e60a04a9d470e21dfe6e85970e2d7465a0a350 Mon Sep 17 00:00:00 2001 From: xqq Date: Mon, 14 Nov 2016 16:24:59 +0800 Subject: [PATCH] Add crossdomain config in http_remux and hls for HTML5 playback --- trunk/src/app/srs_app_config.cpp | 43 ++++++++++++++++++++-- trunk/src/app/srs_app_config.hpp | 8 +++++ trunk/src/app/srs_app_http_stream.cpp | 52 ++++++++++++++++++++++----- trunk/src/app/srs_app_http_stream.hpp | 16 ++++++--- 4 files changed, 104 insertions(+), 15 deletions(-) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 1894b5781b..4b37e91174 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -70,6 +70,7 @@ const char* _srs_version = "XCORE-"RTMP_SIG_SRS_SERVER; #define SRS_CONF_DEFAULT_UTC_TIME false #define SRS_CONF_DEFAULT_MAX_CONNECTIONS 1000 +#define SRS_CONF_DEFAULT_HLS_CROSSDOMAIN true #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html" #define SRS_CONF_DEFAULT_HLS_M3U8_FILE "[app]/[stream].m3u8" #define SRS_CONF_DEFAULT_HLS_TS_FILE "[app]/[stream]-[seq].ts" @@ -107,6 +108,7 @@ const char* _srs_version = "XCORE-"RTMP_SIG_SRS_SERVER; #define SRS_CONF_DEFAULT_HTTP_MOUNT "[vhost]/" #define SRS_CONF_DEFAULT_HTTP_REMUX_MOUNT "[vhost]/[app]/[stream].flv" +#define SRS_CONF_DEFAULT_HTTP_REMUX_CROSSDOMAIN true #define SRS_CONF_DEFAULT_HTTP_DIR SRS_CONF_DEFAULT_HLS_PATH #define SRS_CONF_DEFAULT_HTTP_AUDIO_FAST_CACHE 0 @@ -1888,7 +1890,7 @@ int SrsConfig::check_config() } else if (n == "http_remux") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); - if (m != "enabled" && m != "mount" && m != "fast_cache" && m != "hstrs") { + if (m != "enabled" && m != "mount" && m != "crossdomain" && m != "fast_cache" && m != "hstrs") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost http_remux directive %s, ret=%d", m.c_str(), ret); return ret; @@ -1897,7 +1899,7 @@ int SrsConfig::check_config() } else if (n == "hls") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); - if (m != "enabled" && m != "hls_entry_prefix" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error" + if (m != "enabled" && m != "crossdomain" && m != "hls_entry_prefix" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error" && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_aof_ratio" && m != "hls_acodec" && m != "hls_vcodec" && m != "hls_m3u8_file" && m != "hls_ts_file" && m != "hls_ts_floor" && m != "hls_cleanup" && m != "hls_nb_notify" && m != "hls_wait_keyframe" && m != "hls_dispose" @@ -3623,6 +3625,23 @@ bool SrsConfig::get_hls_enabled(string vhost) return SRS_CONF_PERFER_FALSE(conf->arg0()); } +bool SrsConfig::get_hls_crossdomain(string vhost) +{ + SrsConfDirective* hls = get_hls(vhost); + + if (!hls) { + return SRS_CONF_DEFAULT_HLS_CROSSDOMAIN; + } + + SrsConfDirective* conf = hls->get("crossdomain"); + + if (!conf || conf->arg0().empty()) { + return SRS_CONF_DEFAULT_HLS_CROSSDOMAIN; + } + + return SRS_CONF_PERFER_TRUE(conf->arg0()); +} + string SrsConfig::get_hls_entry_prefix(string vhost) { SrsConfDirective* hls = get_hls(vhost); @@ -4334,6 +4353,26 @@ bool SrsConfig::get_vhost_http_remux_enabled(string vhost) return SRS_CONF_PERFER_FALSE(conf->arg0()); } +bool SrsConfig::get_vhost_http_remux_crossdomain(string vhost) +{ + SrsConfDirective* conf = get_vhost(vhost); + if (!conf) { + return SRS_CONF_DEFAULT_HTTP_REMUX_CROSSDOMAIN; + } + + conf = conf->get("http_remux"); + if (!conf) { + return SRS_CONF_DEFAULT_HTTP_REMUX_CROSSDOMAIN; + } + + conf = conf->get("crossdomain"); + if (!conf || conf->arg0().empty()) { + return SRS_CONF_DEFAULT_HTTP_REMUX_CROSSDOMAIN; + } + + return SRS_CONF_PERFER_TRUE(conf->arg0()); +} + double SrsConfig::get_vhost_http_remux_fast_cache(string vhost) { SrsConfDirective* conf = get_vhost(vhost); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 7fae47fead..9595925130 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -870,6 +870,10 @@ class SrsConfig */ virtual bool get_hls_enabled(std::string vhost); /** + * whether enable crossdomain for HLS. + */ + virtual bool get_hls_crossdomain(std::string vhost); + /** * get the HLS m3u8 list ts segment entry prefix info. */ virtual std::string get_hls_entry_prefix(std::string vhost); @@ -1071,6 +1075,10 @@ class SrsConfig */ virtual bool get_vhost_http_remux_enabled(std::string vhost); /** + * whether enable crossdomain for http remux. + */ + virtual bool get_vhost_http_remux_crossdomain(std::string vhost); + /** * get the fast cache duration for http audio live stream. */ virtual double get_vhost_http_remux_fast_cache(std::string vhost); diff --git a/trunk/src/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp index 0cd864a970..cc137381a1 100755 --- a/trunk/src/app/srs_app_http_stream.cpp +++ b/trunk/src/app/srs_app_http_stream.cpp @@ -450,11 +450,12 @@ int SrsStreamWriter::writev(iovec* iov, int iovcnt, ssize_t* pnwrite) return writer->writev(iov, iovcnt, pnwrite); } -SrsLiveStream::SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c) +SrsLiveStream::SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c, bool crossdomain) { source = s; cache = c; req = r->copy(); + enable_crossdomain = crossdomain; } SrsLiveStream::~SrsLiveStream() @@ -473,6 +474,11 @@ int SrsLiveStream::update(SrsSource* s, SrsRequest* r) return ret; } +void SrsLiveStream::reset_crossdomain(bool crossdomain) +{ + enable_crossdomain = crossdomain; +} + int SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) { int ret = ERROR_SUCCESS; @@ -503,6 +509,10 @@ int SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) } SrsAutoFree(ISrsStreamEncoder, enc); + if (enable_crossdomain) { + w->header()->set("Access-Control-Allow-Origin", "*"); + } + // create consumer of souce, ignore gop cache, use the audio gop cache. SrsConsumer* consumer = NULL; if ((ret = source->create_consumer(NULL, consumer, true, true, !enc->has_cache())) != ERROR_SUCCESS) { @@ -614,9 +624,10 @@ int SrsLiveStream::streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrM return ret; } -SrsLiveEntry::SrsLiveEntry(std::string m, bool h) +SrsLiveEntry::SrsLiveEntry(std::string m, bool c, bool h) { mount = m; + crossdomain = c; hstrs = h; stream = NULL; @@ -641,6 +652,11 @@ void SrsLiveEntry::reset_hstrs(bool h) hstrs = h; } +void SrsLiveEntry::reset_crossdomain(bool c) +{ + crossdomain = c; +} + bool SrsLiveEntry::is_flv() { return _is_flv; @@ -661,8 +677,9 @@ bool SrsLiveEntry::is_mp3() return _is_mp3; } -SrsHlsM3u8Stream::SrsHlsM3u8Stream() +SrsHlsM3u8Stream::SrsHlsM3u8Stream(bool crossdomain) { + enable_crossdomain = crossdomain; } SrsHlsM3u8Stream::~SrsHlsM3u8Stream() @@ -683,6 +700,10 @@ int SrsHlsM3u8Stream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) w->header()->set_content_length((int)data.length()); w->header()->set_content_type("application/x-mpegURL;charset=utf-8"); + if (enable_crossdomain) { + w->header()->set("Access-Control-Allow-Origin", "*"); + } + if ((ret = w->write((char*)data.data(), (int)data.length())) != ERROR_SUCCESS) { if (!srs_is_client_gracefully_close(ret)) { srs_error("send m3u8 failed. ret=%d", ret); @@ -693,8 +714,9 @@ int SrsHlsM3u8Stream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) return ret; } -SrsHlsTsStream::SrsHlsTsStream() +SrsHlsTsStream::SrsHlsTsStream(bool crossdomain) { + enable_crossdomain = crossdomain; } SrsHlsTsStream::~SrsHlsTsStream() @@ -715,6 +737,10 @@ int SrsHlsTsStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) w->header()->set_content_length((int)data.length()); w->header()->set_content_type("video/MP2T"); + if (enable_crossdomain) { + w->header()->set("Access-Control-Allow-Origin", "*"); + } + if ((ret = w->write((char*)data.data(), (int)data.length())) != ERROR_SUCCESS) { if (!srs_is_client_gracefully_close(ret)) { srs_error("send ts failed. ret=%d", ret); @@ -823,10 +849,10 @@ int SrsHttpStreamServer::http_mount(SrsSource* s, SrsRequest* r) // remove the default vhost mount mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/"); - entry = new SrsLiveEntry(mount, tmpl->hstrs); + entry = new SrsLiveEntry(mount, tmpl->crossdomain, tmpl->hstrs); entry->cache = new SrsStreamCache(s, r); - entry->stream = new SrsLiveStream(s, r, entry->cache); + entry->stream = new SrsLiveStream(s, r, entry->cache, entry->crossdomain); // TODO: FIXME: maybe refine the logic of http remux service. // if user push streams followed: @@ -924,8 +950,10 @@ int SrsHttpStreamServer::on_reload_vhost_http_remux_updated(string vhost) string old_tmpl_mount = tmpl->mount; string new_tmpl_mount = _srs_config->get_vhost_http_remux_mount(vhost); bool hstrs = _srs_config->get_vhost_http_remux_hstrs(vhost); + bool crossdomain = _srs_config->get_vhost_http_remux_crossdomain(vhost); tmpl->reset_hstrs(hstrs); + tmpl->reset_crossdomain(crossdomain); /** * TODO: not support to reload different mount url for the time being. @@ -941,6 +969,8 @@ int SrsHttpStreamServer::on_reload_vhost_http_remux_updated(string vhost) if (sflvs.find(sid) != sflvs.end()) { SrsLiveEntry* stream = sflvs[sid]; stream->reset_hstrs(hstrs); + stream->reset_crossdomain(crossdomain); + stream->stream->reset_crossdomain(crossdomain); } // remount stream. if ((ret = http_mount(source, req)) != ERROR_SUCCESS) { @@ -1013,9 +1043,11 @@ int SrsHttpStreamServer::hls_update_m3u8(SrsRequest* r, string m3u8) entry->tmpl = tmpl; entry->mount = mount; shls[sid] = entry; - + + bool enable_crossdomain = _srs_config->get_hls_crossdomain(r->vhost); + if (entry->streams.find(mount) == entry->streams.end()) { - ISrsHttpHandler* he = new SrsHlsM3u8Stream(); + ISrsHttpHandler* he = new SrsHlsM3u8Stream(enable_crossdomain); entry->streams[mount] = he; if ((ret = mux.handle(mount, he)) != ERROR_SUCCESS) { @@ -1061,10 +1093,11 @@ int SrsHttpStreamServer::hls_update_ts(SrsRequest* r, string uri, string ts) srs_assert(entry); srs_assert(entry->tmpl); + bool enable_crossdomain = _srs_config->get_hls_crossdomain(r->vhost); std::string mount = hls_mount_generate(r, uri, entry->tmpl->mount); if (entry->streams.find(mount) == entry->streams.end()) { - ISrsHttpHandler* he = new SrsHlsTsStream(); + ISrsHttpHandler* he = new SrsHlsTsStream(enable_crossdomain); entry->streams[mount] = he; if ((ret = mux.handle(mount, he)) != ERROR_SUCCESS) { @@ -1287,6 +1320,7 @@ int SrsHttpStreamServer::initialize_flv_entry(std::string vhost) SrsLiveEntry* entry = new SrsLiveEntry( _srs_config->get_vhost_http_remux_mount(vhost), + _srs_config->get_vhost_http_remux_crossdomain(vhost), _srs_config->get_vhost_http_remux_hstrs(vhost) ); diff --git a/trunk/src/app/srs_app_http_stream.hpp b/trunk/src/app/srs_app_http_stream.hpp index 83b90bcf56..4158fea1aa 100755 --- a/trunk/src/app/srs_app_http_stream.hpp +++ b/trunk/src/app/srs_app_http_stream.hpp @@ -225,10 +225,13 @@ class SrsLiveStream : public ISrsHttpHandler SrsRequest* req; SrsSource* source; SrsStreamCache* cache; + bool enable_crossdomain; public: - SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c); + SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c, bool crossdomain); virtual ~SrsLiveStream(); virtual int update(SrsSource* s, SrsRequest* r); +public: + void reset_crossdomain(bool crossdomain); public: virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); private: @@ -252,14 +255,17 @@ struct SrsLiveEntry // for template, the mount contains variables. // for concrete stream, the mount is url to access. std::string mount; + // whether crossdomain(Access-Control-Allow-Origin) + bool crossdomain; // whether hstrs(http stream trigger rtmp source) bool hstrs; SrsLiveStream* stream; SrsStreamCache* cache; - SrsLiveEntry(std::string m, bool h); + SrsLiveEntry(std::string m, bool c, bool h); void reset_hstrs(bool h); + void reset_crossdomain(bool c); bool is_flv(); bool is_ts(); @@ -274,8 +280,9 @@ class SrsHlsM3u8Stream : public ISrsHttpHandler { private: std::string m3u8; + bool enable_crossdomain; public: - SrsHlsM3u8Stream(); + SrsHlsM3u8Stream(bool crossdomain); virtual ~SrsHlsM3u8Stream(); public: virtual void set_m3u8(std::string v); @@ -290,8 +297,9 @@ class SrsHlsTsStream : public ISrsHttpHandler { private: std::string ts; + bool enable_crossdomain; public: - SrsHlsTsStream(); + SrsHlsTsStream(bool crossdomain); virtual ~SrsHlsTsStream(); public: virtual void set_ts(std::string v);