From d921d59e5775b34a184d71cf431559608a737ce1 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 27 Aug 2015 18:11:50 +0800 Subject: [PATCH] for #319, support HTTP RAW API reload. --- trunk/conf/full.conf | 4 +++ trunk/src/app/srs_app_config.cpp | 22 +++++++++++++- trunk/src/app/srs_app_config.hpp | 4 +++ trunk/src/app/srs_app_http_api.cpp | 41 ++++++++++++++++++++++++++ trunk/src/app/srs_app_http_api.hpp | 12 ++++++++ trunk/src/app/srs_app_server.cpp | 21 +++++-------- trunk/src/app/srs_app_server.hpp | 22 ++++++++------ trunk/src/kernel/srs_kernel_consts.hpp | 11 +++++++ trunk/src/kernel/srs_kernel_error.hpp | 3 ++ 9 files changed, 117 insertions(+), 23 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 69f27557b5..d46827bd42 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -121,6 +121,10 @@ 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; } # 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 9f5e74504f..8f82544f39 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -1116,6 +1116,9 @@ 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; @@ -1711,7 +1714,7 @@ int SrsConfig::check_config() SrsConfDirective* conf = get_http_api(); for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; - if (n != "enabled" && n != "listen" && n != "crossdomain") { + 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; @@ -4293,6 +4296,23 @@ bool SrsConfig::get_http_api_crossdomain() return SRS_CONF_PERFER_TRUE(conf->arg0()); } +bool SrsConfig::get_http_api_raw_api() +{ + static bool DEFAULT = false; + + SrsConfDirective* conf = get_http_api(); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("raw_api"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_FALSE(conf->arg0()); +} + bool SrsConfig::get_http_stream_enabled() { SrsConfDirective* conf = get_http_stream(); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 650033a27c..a3fcaa2afb 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -1036,6 +1036,10 @@ class SrsConfig * whether enable crossdomain for http api. */ virtual bool get_http_api_crossdomain(); + /** + * whether enable the HTTP RAW API. + */ + virtual bool get_http_api_raw_api(); // 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 218403dee6..2c6eed4e2e 100755 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -42,6 +42,8 @@ using namespace std; #include #include #include +#include +#include int srs_api_response_jsonp(ISrsHttpResponseWriter* w, string callback, string data) { @@ -205,6 +207,7 @@ int SrsGoApiV1::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) << SRS_JFIELD_STR("vhosts", "manage all vhosts or specified vhost") << SRS_JFIELD_CONT << SRS_JFIELD_STR("streams", "manage all streams or specified stream") << SRS_JFIELD_CONT << SRS_JFIELD_STR("clients", "manage all clients or specified client, default query top 10 clients") << SRS_JFIELD_CONT + << SRS_JFIELD_STR("raw", "raw api for srs, support CUID srs for instance the config") << SRS_JFIELD_CONT << SRS_JFIELD_ORG("tests", SRS_JOBJECT_START) << SRS_JFIELD_STR("requests", "show the request info") << SRS_JFIELD_CONT << SRS_JFIELD_STR("errors", "always return an error 100") << SRS_JFIELD_CONT @@ -834,6 +837,44 @@ int SrsGoApiClients::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) return ret; } +SrsGoApiRaw::SrsGoApiRaw(SrsServer* svr) +{ + server = svr; +} + +SrsGoApiRaw::~SrsGoApiRaw() +{ +} + +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()) { + ret = ERROR_SYSTEM_CONFIG_RAW_DISABLED; + srs_warn("raw api disabled. ret=%d", ret); + return srs_api_response_code(w, r, ret); + } + + // the rpc is required. + std::string rpc = r->query_get("rpc"); + if (rpc.empty() || (rpc != "reload" && rpc != "config_query")) { + 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); + } + + // for rpc=reload, trigger the server to reload the config. + if (rpc == "reload") { + srs_trace("raw api trigger reload. ret=%d", ret); + server->on_signal(SRS_SIGNAL_RELOAD); + return srs_api_response_code(w, r, ret); + } + + return ret; +} + SrsGoApiError::SrsGoApiError() { } diff --git a/trunk/src/app/srs_app_http_api.hpp b/trunk/src/app/srs_app_http_api.hpp index 8f5a33d0d1..53f72858dc 100644 --- a/trunk/src/app/srs_app_http_api.hpp +++ b/trunk/src/app/srs_app_http_api.hpp @@ -36,6 +36,7 @@ class SrsStSocket; class ISrsHttpMessage; class SrsHttpParser; class SrsHttpHandler; +class SrsServer; #include #include @@ -177,6 +178,17 @@ class SrsGoApiClients : public ISrsHttpHandler virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); }; +class SrsGoApiRaw : public ISrsHttpHandler +{ +private: + SrsServer* server; +public: + SrsGoApiRaw(SrsServer* svr); + virtual ~SrsGoApiRaw(); +public: + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); +}; + class SrsGoApiError : public ISrsHttpHandler { public: diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 2127f96c1b..fddc401866 100755 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -48,15 +48,7 @@ using namespace std; #include #include #include - -// signal defines. -// reload the config file and apply new config. -#define SRS_SIGNAL_RELOAD SIGHUP -// terminate the srs with dispose to detect memory leak for gmp. -#define SRS_SIGNAL_DISPOSE SIGUSR2 -// persistence the config in memory to config file. -// @see https://github.com/simple-rtmp-server/srs/issues/319#issuecomment-134993922 -#define SRS_SIGNAL_PERSISTENCE_CONFIG SIGUSR1 +#include // system interval in ms, // all resolution times should be times togother, @@ -430,7 +422,7 @@ int SrsSignalManager::start() sa.sa_handler = SrsSignalManager::sig_catcher; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; - sigaction(SIGTERM, &sa, NULL); + sigaction(SRS_SIGNAL_GRACEFULLY_QUIT, &sa, NULL); sa.sa_handler = SrsSignalManager::sig_catcher; sigemptyset(&sa.sa_mask); @@ -824,6 +816,9 @@ int SrsServer::http_handle() if ((ret = http_api_mux->handle("/api/v1/clients/", new SrsGoApiClients())) != ERROR_SUCCESS) { return ret; } + if ((ret = http_api_mux->handle("/api/v1/raw", new SrsGoApiRaw(this))) != ERROR_SUCCESS) { + return ret; + } // test the request info. if ((ret = http_api_mux->handle("/api/v1/tests/requests", new SrsGoApiRequests())) != ERROR_SUCCESS) { @@ -927,7 +922,7 @@ void SrsServer::on_signal(int signo) return; } - if (signo == SIGINT || signo == SIGUSR2) { + if (signo == SIGINT || signo == SRS_SIGNAL_DISPOSE) { #ifdef SRS_AUTO_GPERF_MC srs_trace("gmc is on, main cycle will terminate normally."); signal_gmc_stop = true; @@ -941,7 +936,7 @@ void SrsServer::on_signal(int signo) return; } - if (signo == SIGTERM && !signal_gracefully_quit) { + if (signo == SRS_SIGNAL_GRACEFULLY_QUIT && !signal_gracefully_quit) { srs_trace("user terminate program, gracefully quit."); signal_gracefully_quit = true; return; @@ -982,7 +977,7 @@ int SrsServer::do_cycle() for (int i = 0; i < temp_max; i++) { st_usleep(SRS_SYS_CYCLE_INTERVAL * 1000); - // gracefully quit for SIGINT or SIGTERM. + // gracefully quit for SIGINT or SIGTERM(SRS_SIGNAL_GRACEFULLY_QUIT). if (signal_gracefully_quit) { srs_trace("cleanup for gracefully terminate."); return ret; diff --git a/trunk/src/app/srs_app_server.hpp b/trunk/src/app/srs_app_server.hpp index f471795ac4..2abc8cd757 100644 --- a/trunk/src/app/srs_app_server.hpp +++ b/trunk/src/app/srs_app_server.hpp @@ -319,15 +319,19 @@ class SrsServer : virtual public ISrsReloadHandler // server utilities. public: /** - * callback for signal manager got a signal. - * the signal manager convert signal to io message, - * whatever, we will got the signo like the orignal signal(int signo) handler. - * @remark, direclty exit for SIGTERM. - * @remark, do reload for SIGNAL_RELOAD. - * @remark, for SIGINT and SIGUSR2: - * no gmc, directly exit. - * for gmc, set the variable signal_gmc_stop, the cycle will return and cleanup for gmc. - */ + * callback for signal manager got a signal. + * the signal manager convert signal to io message, + * whatever, we will got the signo like the orignal signal(int signo) handler. + * @param signo the signal number from user, where: + * SRS_SIGNAL_GRACEFULLY_QUIT, the SIGTERM, dispose then quit. + * SRS_SIGNAL_DISPOSE, the SIGUSR2, dispose for gmc. + * SRS_SIGNAL_PERSISTENCE_CONFIG, the SIGUSR1, persistence config to file. + * SRS_SIGNAL_RELOAD, the SIGHUP, reload the config. + * @remark, for SIGINT and SRS_SIGNAL_DISPOSE: + * no gmc, directly exit. + * for gmc, set the variable signal_gmc_stop, the cycle will return and cleanup for gmc. + * @remark, maybe the HTTP RAW API will trigger the on_signal() also. + */ virtual void on_signal(int signo); private: /** diff --git a/trunk/src/kernel/srs_kernel_consts.hpp b/trunk/src/kernel/srs_kernel_consts.hpp index 8b3b9bdcfb..0f7765d7ec 100644 --- a/trunk/src/kernel/srs_kernel_consts.hpp +++ b/trunk/src/kernel/srs_kernel_consts.hpp @@ -134,6 +134,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SRS_CONSTS_NULL_FILE "/dev/null" #define SRS_CONSTS_LOCALHOST "127.0.0.1" +// signal defines. +// reload the config file and apply new config. +#define SRS_SIGNAL_RELOAD SIGHUP +// terminate the srs with dispose to detect memory leak for gmc. +#define SRS_SIGNAL_DISPOSE SIGUSR2 +// persistence the config in memory to config file. +// @see https://github.com/simple-rtmp-server/srs/issues/319#issuecomment-134993922 +#define SRS_SIGNAL_PERSISTENCE_CONFIG SIGUSR1 +// srs should gracefully quit, do dispose then exit. +#define SRS_SIGNAL_GRACEFULLY_QUIT SIGTERM + /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index f9df9d3924..a52d86e302 100755 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -98,6 +98,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_SYSTEM_CREATE_DIR 1057 #define ERROR_SYSTEM_KILL 1058 #define ERROR_SYSTEM_CONFIG_PERSISTENCE 1059 +#define ERROR_SYSTEM_CONFIG_RAW 1060 +#define ERROR_SYSTEM_CONFIG_RAW_DISABLED 1061 +#define ERROR_SYSTEM_CONFIG_RAW_PARAMS 1062 /////////////////////////////////////////////////////// // RTMP protocol error.