diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index d46827bd42..a2b310138b 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -121,10 +121,18 @@ http_api { # whether enable crossdomain request. # default: on crossdomain on; - # whether enable the HTTP RAW API, - # which is more powerful api to change srs state and reload. - # default: off - raw_api off; + # the HTTP RAW API is more powerful api to change srs state and reload. + raw_api { + # whether enable the HTTP RAW API. + # default: off + enabled off; + # whether enable rpc reload. + # default: off + allow_reload off; + # whether enable rpc config_query. + # default: off + allow_config_query off; + } } # embeded http server in srs. # the http streaming config, for HLS/HDS/DASH/HTTPProgressive diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 7e021904d0..914dd44967 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -1143,9 +1143,6 @@ int SrsConfig::reload_http_api(SrsConfDirective* old_root) { int ret = ERROR_SUCCESS; - // always support reload without additional code: - // crossdomain, raw_api - // merge config. std::vector::iterator it; @@ -1199,6 +1196,24 @@ int SrsConfig::reload_http_api(SrsConfDirective* old_root) } srs_trace("reload enabled modified http_api success."); + if (!srs_directive_equals(old_http_api->get("crossdomain"), new_http_api->get("crossdomain"))) { + ISrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_http_api_crossdomain()) != ERROR_SUCCESS) { + srs_error("notify subscribes http_api crossdomain modified failed. ret=%d", ret); + return ret; + } + } + srs_trace("reload crossdomain modified http_api success."); + + if (!srs_directive_equals(old_http_api->get("raw_api"), new_http_api->get("raw_api"))) { + ISrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_http_api_raw_api()) != ERROR_SUCCESS) { + srs_error("notify subscribes http_api raw_api modified failed. ret=%d", ret); + return ret; + } + } + srs_trace("reload raw_api modified http_api success."); + return ret; } @@ -1645,7 +1660,7 @@ int SrsConfig::global_to_json(SrsAmf0Object* obj) } else if (sdir->name == "crossdomain") { sobj->set(sdir->name, sdir->dumps_arg0_to_boolean()); } else if (sdir->name == "raw_api") { - sobj->set(sdir->name, sdir->dumps_arg0_to_boolean()); + sobj->set(sdir->name, SrsAmf0Any::boolean(get_raw_api())); } } obj->set(dir->name, sobj); @@ -1780,6 +1795,49 @@ int SrsConfig::vhost_to_json(SrsConfDirective* vhost, SrsAmf0Object* obj) return ret; } +int SrsConfig::raw_to_json(SrsAmf0Object* obj) +{ + int ret = ERROR_SUCCESS; + + SrsAmf0Object* sobj = SrsAmf0Any::object(); + obj->set("http_api", sobj); + + for (int i = 0; i < (int)root->directives.size(); i++) { + SrsConfDirective* dir = root->directives.at(i); + + if (dir->name != "http_api") { + continue; + } + + for (int j = 0; j < (int)dir->directives.size(); j++) { + SrsConfDirective* sdir = dir->directives.at(j); + if (sdir->name == "enabled") { + sobj->set(sdir->name, sdir->dumps_arg0_to_boolean()); + } else if (sdir->name == "listen") { + sobj->set(sdir->name, sdir->dumps_arg0_to_str()); + } else if (sdir->name == "crossdomain") { + sobj->set(sdir->name, sdir->dumps_arg0_to_boolean()); + } else if (sdir->name == "raw_api") { + SrsAmf0Object* ssobj = SrsAmf0Any::object(); + sobj->set(sdir->name, ssobj); + + for (int k = 0; k < (int)sdir->directives.size(); k++) { + SrsConfDirective* ssdir = sdir->directives.at(k); + if (ssdir->name == "enabled") { + ssobj->set(ssdir->name, ssdir->dumps_arg0_to_boolean()); + } else if (ssdir->name == "allow_reload") { + ssobj->set(ssdir->name, ssdir->dumps_arg0_to_boolean()); + } else if (ssdir->name == "allow_config_query") { + ssobj->set(ssdir->name, ssdir->dumps_arg0_to_boolean()); + } + } + } + } + } + + return ret; +} + string SrsConfig::config() { return config_file; @@ -1946,12 +2004,24 @@ int SrsConfig::check_config() if (true) { SrsConfDirective* conf = get_http_api(); for (int i = 0; conf && i < (int)conf->directives.size(); i++) { - string n = conf->at(i)->name; + SrsConfDirective* obj = conf->at(i); + string n = obj->name; if (n != "enabled" && n != "listen" && n != "crossdomain" && n != "raw_api") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported http_api directive %s, ret=%d", n.c_str(), ret); return ret; } + + if (n == "raw_api") { + for (int j = 0; j < (int)obj->directives.size(); j++) { + string m = obj->at(j)->name; + if (m != "enabled" && m != "allow_reload" && m != "allow_config_query") { + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("unsupported http_api.raw_api directive %s, ret=%d", m.c_str(), ret); + return ret; + } + } + } } } if (true) { @@ -4529,7 +4599,29 @@ bool SrsConfig::get_http_api_crossdomain() return SRS_CONF_PERFER_TRUE(conf->arg0()); } -bool SrsConfig::get_http_api_raw_api() +bool SrsConfig::get_raw_api() +{ + static bool DEFAULT = false; + + SrsConfDirective* conf = get_http_api(); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("raw_api"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("enabled"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_FALSE(conf->arg0()); +} + +bool SrsConfig::get_raw_api_allow_reload() { static bool DEFAULT = false; @@ -4539,6 +4631,33 @@ bool SrsConfig::get_http_api_raw_api() } conf = conf->get("raw_api"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("allow_reload"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_FALSE(conf->arg0()); +} + +bool SrsConfig::get_raw_api_allow_config_query() +{ + static bool DEFAULT = false; + + SrsConfDirective* conf = get_http_api(); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("raw_api"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("allow_config_query"); if (!conf || conf->arg0().empty()) { return DEFAULT; } diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index becc22da02..8ab3f9a146 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -320,6 +320,10 @@ class SrsConfig * dumps the vhost section to json. */ virtual int vhost_to_json(SrsConfDirective* vhost, SrsAmf0Object* obj); + /** + * dumps the http_api sections to json for raw api info. + */ + virtual int raw_to_json(SrsAmf0Object* obj); /** * get the config file path. */ @@ -1061,7 +1065,15 @@ class SrsConfig /** * whether enable the HTTP RAW API. */ - virtual bool get_http_api_raw_api(); + virtual bool get_raw_api(); + /** + * whether allow rpc reload. + */ + virtual bool get_raw_api_allow_reload(); + /** + * whether allow rpc config_query. + */ + virtual bool get_raw_api_allow_config_query(); // http stream section private: /** diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index b6e5f50532..3183c5a686 100755 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -842,10 +842,17 @@ int SrsGoApiClients::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) SrsGoApiRaw::SrsGoApiRaw(SrsServer* svr) { server = svr; + + raw_api = _srs_config->get_raw_api(); + allow_reload = _srs_config->get_raw_api_allow_reload(); + allow_config_query = _srs_config->get_raw_api_allow_config_query(); + + _srs_config->subscribe(this); } SrsGoApiRaw::~SrsGoApiRaw() { + _srs_config->unsubscribe(this); } int SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) @@ -853,7 +860,7 @@ int SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) int ret = ERROR_SUCCESS; // whether enabled the HTTP RAW API. - if (!_srs_config->get_http_api_raw_api()) { + if (!raw_api) { ret = ERROR_SYSTEM_CONFIG_RAW_DISABLED; srs_warn("raw api disabled. ret=%d", ret); return srs_api_response_code(w, r, ret); @@ -861,7 +868,7 @@ int SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) // the rpc is required. std::string rpc = r->query_get("rpc"); - if (rpc.empty() || (rpc != "reload" && rpc != "config_query")) { + if (rpc.empty() || (rpc != "reload" && rpc != "config_query" && rpc != "raw")) { ret = ERROR_SYSTEM_CONFIG_RAW; srs_error("raw api invalid rpc=%s. ret=%d", rpc.c_str(), ret); return srs_api_response_code(w, r, ret); @@ -869,11 +876,33 @@ int SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) // for rpc=reload, trigger the server to reload the config. if (rpc == "reload") { + if (!allow_reload) { + ret = ERROR_SYSTEM_CONFIG_RAW_DISABLED; + srs_error("raw api reload disabled rpc=%s. ret=%d", rpc.c_str(), ret); + return srs_api_response_code(w, r, ret); + } + srs_trace("raw api trigger reload. ret=%d", ret); server->on_signal(SRS_SIGNAL_RELOAD); return srs_api_response_code(w, r, ret); } + // the object to return for request. + SrsAmf0Object* obj = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, obj); + obj->set("code", SrsAmf0Any::number(ERROR_SUCCESS)); + + // for rpc=raw, to query the raw api config for http api. + if (rpc == "raw") { + // query global scope. + if ((ret = _srs_config->raw_to_json(obj)) != ERROR_SUCCESS) { + srs_error("raw api rpc raw failed. ret=%d", ret); + return srs_api_response_code(w, r, ret); + } + + return srs_api_response(w, r, obj->to_json()); + } + // for rpc=config_query, to get the configs of server. // @param scope the scope to query for config, it can be: // global, the configs belongs to the root, donot includes any sub directives. @@ -881,6 +910,12 @@ int SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) // @param vhost the vhost name for @param scope is vhost to query config. // for the default vhost, must be __defaultVhost__ if (rpc == "config_query") { + if (!allow_config_query) { + ret = ERROR_SYSTEM_CONFIG_RAW_DISABLED; + srs_error("raw api allow_config_query disabled rpc=%s. ret=%d", rpc.c_str(), ret); + return srs_api_response_code(w, r, ret); + } + std::string scope = r->query_get("scope"); std::string vhost = r->query_get("vhost"); if (scope.empty() || (scope != "global" && scope != "vhost")) { @@ -889,12 +924,6 @@ int SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) return srs_api_response_code(w, r, ret); } - // config query. - SrsAmf0Object* obj = SrsAmf0Any::object(); - SrsAutoFree(SrsAmf0Object, obj); - - obj->set("code", SrsAmf0Any::number(ERROR_SUCCESS)); - if (scope == "vhost") { // query vhost scope. if (vhost.empty()) { @@ -934,6 +963,15 @@ int SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) return ret; } +int SrsGoApiRaw::on_reload_http_api_raw_api() +{ + raw_api = _srs_config->get_raw_api(); + allow_reload = _srs_config->get_raw_api_allow_reload(); + allow_config_query = _srs_config->get_raw_api_allow_config_query(); + + return ERROR_SUCCESS; +} + SrsGoApiError::SrsGoApiError() { } @@ -954,11 +992,15 @@ SrsHttpApi::SrsHttpApi(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m mux = m; parser = new SrsHttpParser(); crossdomain_required = false; + + _srs_config->subscribe(this); } SrsHttpApi::~SrsHttpApi() { srs_freep(parser); + + _srs_config->unsubscribe(this); } void SrsHttpApi::resample() @@ -1002,6 +1044,9 @@ int SrsHttpApi::do_cycle() // @see https://github.com/simple-rtmp-server/srs/issues/398 skt.set_recv_timeout(SRS_HTTP_RECV_TIMEOUT_US); + // initialize the crossdomain + crossdomain_enabled = _srs_config->get_http_api_crossdomain(); + // process http messages. while(!disposed) { ISrsHttpMessage* req = NULL; @@ -1083,5 +1128,12 @@ int SrsHttpApi::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) return ret; } +int SrsHttpApi::on_reload_http_api_crossdomain() +{ + crossdomain_enabled = _srs_config->get_http_api_crossdomain(); + + return ERROR_SUCCESS; +} + #endif diff --git a/trunk/src/app/srs_app_http_api.hpp b/trunk/src/app/srs_app_http_api.hpp index 53f72858dc..62d92381a5 100644 --- a/trunk/src/app/srs_app_http_api.hpp +++ b/trunk/src/app/srs_app_http_api.hpp @@ -41,6 +41,7 @@ class SrsServer; #include #include #include +#include // for http root. class SrsGoApiRoot : public ISrsHttpHandler @@ -178,15 +179,22 @@ class SrsGoApiClients : public ISrsHttpHandler virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); }; -class SrsGoApiRaw : public ISrsHttpHandler +class SrsGoApiRaw : virtual public ISrsHttpHandler, virtual public ISrsReloadHandler { private: SrsServer* server; +private: + bool raw_api; + bool allow_reload; + bool allow_config_query; public: SrsGoApiRaw(SrsServer* svr); virtual ~SrsGoApiRaw(); public: virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); +// interface ISrsReloadHandler +public: + virtual int on_reload_http_api_raw_api(); }; class SrsGoApiError : public ISrsHttpHandler @@ -198,12 +206,13 @@ class SrsGoApiError : public ISrsHttpHandler virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); }; -class SrsHttpApi : public SrsConnection +class SrsHttpApi : virtual public SrsConnection, virtual public ISrsReloadHandler { private: SrsHttpParser* parser; SrsHttpServeMux* mux; bool crossdomain_required; + bool crossdomain_enabled; public: SrsHttpApi(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m); virtual ~SrsHttpApi(); @@ -217,6 +226,9 @@ class SrsHttpApi : public SrsConnection virtual int do_cycle(); private: virtual int process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); +// interface ISrsReloadHandler +public: + virtual int on_reload_http_api_crossdomain(); }; #endif diff --git a/trunk/src/app/srs_app_reload.cpp b/trunk/src/app/srs_app_reload.cpp index 8e86494f0e..551ca50414 100644 --- a/trunk/src/app/srs_app_reload.cpp +++ b/trunk/src/app/srs_app_reload.cpp @@ -80,6 +80,16 @@ int ISrsReloadHandler::on_reload_http_api_disabled() return ERROR_SUCCESS; } +int ISrsReloadHandler::on_reload_http_api_crossdomain() +{ + return ERROR_SUCCESS; +} + +int ISrsReloadHandler::on_reload_http_api_raw_api() +{ + return ERROR_SUCCESS; +} + int ISrsReloadHandler::on_reload_http_stream_enabled() { return ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_reload.hpp b/trunk/src/app/srs_app_reload.hpp index d6e1648c38..c8a9442c52 100644 --- a/trunk/src/app/srs_app_reload.hpp +++ b/trunk/src/app/srs_app_reload.hpp @@ -53,6 +53,8 @@ class ISrsReloadHandler virtual int on_reload_pithy_print(); virtual int on_reload_http_api_enabled(); virtual int on_reload_http_api_disabled(); + virtual int on_reload_http_api_crossdomain(); + virtual int on_reload_http_api_raw_api(); virtual int on_reload_http_stream_enabled(); virtual int on_reload_http_stream_disabled(); virtual int on_reload_http_stream_updated();