winlin

for #319, support HTTP RAW API reload.

@@ -121,6 +121,10 @@ http_api { @@ -121,6 +121,10 @@ http_api {
121 # whether enable crossdomain request. 121 # whether enable crossdomain request.
122 # default: on 122 # default: on
123 crossdomain on; 123 crossdomain on;
  124 + # whether enable the HTTP RAW API,
  125 + # which is more powerful api to change srs state and reload.
  126 + # default: off
  127 + raw_api off;
124 } 128 }
125 # embeded http server in srs. 129 # embeded http server in srs.
126 # the http streaming config, for HLS/HDS/DASH/HTTPProgressive 130 # the http streaming config, for HLS/HDS/DASH/HTTPProgressive
@@ -1116,6 +1116,9 @@ int SrsConfig::reload_http_api(SrsConfDirective* old_root) @@ -1116,6 +1116,9 @@ int SrsConfig::reload_http_api(SrsConfDirective* old_root)
1116 { 1116 {
1117 int ret = ERROR_SUCCESS; 1117 int ret = ERROR_SUCCESS;
1118 1118
  1119 + // always support reload without additional code:
  1120 + // crossdomain, raw_api
  1121 +
1119 // merge config. 1122 // merge config.
1120 std::vector<ISrsReloadHandler*>::iterator it; 1123 std::vector<ISrsReloadHandler*>::iterator it;
1121 1124
@@ -1711,7 +1714,7 @@ int SrsConfig::check_config() @@ -1711,7 +1714,7 @@ int SrsConfig::check_config()
1711 SrsConfDirective* conf = get_http_api(); 1714 SrsConfDirective* conf = get_http_api();
1712 for (int i = 0; conf && i < (int)conf->directives.size(); i++) { 1715 for (int i = 0; conf && i < (int)conf->directives.size(); i++) {
1713 string n = conf->at(i)->name; 1716 string n = conf->at(i)->name;
1714 - if (n != "enabled" && n != "listen" && n != "crossdomain") { 1717 + if (n != "enabled" && n != "listen" && n != "crossdomain" && n != "raw_api") {
1715 ret = ERROR_SYSTEM_CONFIG_INVALID; 1718 ret = ERROR_SYSTEM_CONFIG_INVALID;
1716 srs_error("unsupported http_api directive %s, ret=%d", n.c_str(), ret); 1719 srs_error("unsupported http_api directive %s, ret=%d", n.c_str(), ret);
1717 return ret; 1720 return ret;
@@ -4293,6 +4296,23 @@ bool SrsConfig::get_http_api_crossdomain() @@ -4293,6 +4296,23 @@ bool SrsConfig::get_http_api_crossdomain()
4293 return SRS_CONF_PERFER_TRUE(conf->arg0()); 4296 return SRS_CONF_PERFER_TRUE(conf->arg0());
4294 } 4297 }
4295 4298
  4299 +bool SrsConfig::get_http_api_raw_api()
  4300 +{
  4301 + static bool DEFAULT = false;
  4302 +
  4303 + SrsConfDirective* conf = get_http_api();
  4304 + if (!conf) {
  4305 + return DEFAULT;
  4306 + }
  4307 +
  4308 + conf = conf->get("raw_api");
  4309 + if (!conf || conf->arg0().empty()) {
  4310 + return DEFAULT;
  4311 + }
  4312 +
  4313 + return SRS_CONF_PERFER_FALSE(conf->arg0());
  4314 +}
  4315 +
4296 bool SrsConfig::get_http_stream_enabled() 4316 bool SrsConfig::get_http_stream_enabled()
4297 { 4317 {
4298 SrsConfDirective* conf = get_http_stream(); 4318 SrsConfDirective* conf = get_http_stream();
@@ -1036,6 +1036,10 @@ public: @@ -1036,6 +1036,10 @@ public:
1036 * whether enable crossdomain for http api. 1036 * whether enable crossdomain for http api.
1037 */ 1037 */
1038 virtual bool get_http_api_crossdomain(); 1038 virtual bool get_http_api_crossdomain();
  1039 + /**
  1040 + * whether enable the HTTP RAW API.
  1041 + */
  1042 + virtual bool get_http_api_raw_api();
1039 // http stream section 1043 // http stream section
1040 private: 1044 private:
1041 /** 1045 /**
@@ -42,6 +42,8 @@ using namespace std; @@ -42,6 +42,8 @@ using namespace std;
42 #include <srs_app_config.hpp> 42 #include <srs_app_config.hpp>
43 #include <srs_app_source.hpp> 43 #include <srs_app_source.hpp>
44 #include <srs_app_http_conn.hpp> 44 #include <srs_app_http_conn.hpp>
  45 +#include <srs_kernel_consts.hpp>
  46 +#include <srs_app_server.hpp>
45 47
46 int srs_api_response_jsonp(ISrsHttpResponseWriter* w, string callback, string data) 48 int srs_api_response_jsonp(ISrsHttpResponseWriter* w, string callback, string data)
47 { 49 {
@@ -205,6 +207,7 @@ int SrsGoApiV1::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) @@ -205,6 +207,7 @@ int SrsGoApiV1::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
205 << SRS_JFIELD_STR("vhosts", "manage all vhosts or specified vhost") << SRS_JFIELD_CONT 207 << SRS_JFIELD_STR("vhosts", "manage all vhosts or specified vhost") << SRS_JFIELD_CONT
206 << SRS_JFIELD_STR("streams", "manage all streams or specified stream") << SRS_JFIELD_CONT 208 << SRS_JFIELD_STR("streams", "manage all streams or specified stream") << SRS_JFIELD_CONT
207 << SRS_JFIELD_STR("clients", "manage all clients or specified client, default query top 10 clients") << SRS_JFIELD_CONT 209 << SRS_JFIELD_STR("clients", "manage all clients or specified client, default query top 10 clients") << SRS_JFIELD_CONT
  210 + << SRS_JFIELD_STR("raw", "raw api for srs, support CUID srs for instance the config") << SRS_JFIELD_CONT
208 << SRS_JFIELD_ORG("tests", SRS_JOBJECT_START) 211 << SRS_JFIELD_ORG("tests", SRS_JOBJECT_START)
209 << SRS_JFIELD_STR("requests", "show the request info") << SRS_JFIELD_CONT 212 << SRS_JFIELD_STR("requests", "show the request info") << SRS_JFIELD_CONT
210 << SRS_JFIELD_STR("errors", "always return an error 100") << SRS_JFIELD_CONT 213 << SRS_JFIELD_STR("errors", "always return an error 100") << SRS_JFIELD_CONT
@@ -834,6 +837,44 @@ int SrsGoApiClients::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) @@ -834,6 +837,44 @@ int SrsGoApiClients::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
834 return ret; 837 return ret;
835 } 838 }
836 839
  840 +SrsGoApiRaw::SrsGoApiRaw(SrsServer* svr)
  841 +{
  842 + server = svr;
  843 +}
  844 +
  845 +SrsGoApiRaw::~SrsGoApiRaw()
  846 +{
  847 +}
  848 +
  849 +int SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
  850 +{
  851 + int ret = ERROR_SUCCESS;
  852 +
  853 + // whether enabled the HTTP RAW API.
  854 + if (!_srs_config->get_http_api_raw_api()) {
  855 + ret = ERROR_SYSTEM_CONFIG_RAW_DISABLED;
  856 + srs_warn("raw api disabled. ret=%d", ret);
  857 + return srs_api_response_code(w, r, ret);
  858 + }
  859 +
  860 + // the rpc is required.
  861 + std::string rpc = r->query_get("rpc");
  862 + if (rpc.empty() || (rpc != "reload" && rpc != "config_query")) {
  863 + ret = ERROR_SYSTEM_CONFIG_RAW;
  864 + srs_error("raw api invalid rpc=%s. ret=%d", rpc.c_str(), ret);
  865 + return srs_api_response_code(w, r, ret);
  866 + }
  867 +
  868 + // for rpc=reload, trigger the server to reload the config.
  869 + if (rpc == "reload") {
  870 + srs_trace("raw api trigger reload. ret=%d", ret);
  871 + server->on_signal(SRS_SIGNAL_RELOAD);
  872 + return srs_api_response_code(w, r, ret);
  873 + }
  874 +
  875 + return ret;
  876 +}
  877 +
837 SrsGoApiError::SrsGoApiError() 878 SrsGoApiError::SrsGoApiError()
838 { 879 {
839 } 880 }
@@ -36,6 +36,7 @@ class SrsStSocket; @@ -36,6 +36,7 @@ class SrsStSocket;
36 class ISrsHttpMessage; 36 class ISrsHttpMessage;
37 class SrsHttpParser; 37 class SrsHttpParser;
38 class SrsHttpHandler; 38 class SrsHttpHandler;
  39 +class SrsServer;
39 40
40 #include <srs_app_st.hpp> 41 #include <srs_app_st.hpp>
41 #include <srs_app_conn.hpp> 42 #include <srs_app_conn.hpp>
@@ -177,6 +178,17 @@ public: @@ -177,6 +178,17 @@ public:
177 virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); 178 virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
178 }; 179 };
179 180
  181 +class SrsGoApiRaw : public ISrsHttpHandler
  182 +{
  183 +private:
  184 + SrsServer* server;
  185 +public:
  186 + SrsGoApiRaw(SrsServer* svr);
  187 + virtual ~SrsGoApiRaw();
  188 +public:
  189 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
  190 +};
  191 +
180 class SrsGoApiError : public ISrsHttpHandler 192 class SrsGoApiError : public ISrsHttpHandler
181 { 193 {
182 public: 194 public:
@@ -48,15 +48,7 @@ using namespace std; @@ -48,15 +48,7 @@ using namespace std;
48 #include <srs_app_statistic.hpp> 48 #include <srs_app_statistic.hpp>
49 #include <srs_app_caster_flv.hpp> 49 #include <srs_app_caster_flv.hpp>
50 #include <srs_core_mem_watch.hpp> 50 #include <srs_core_mem_watch.hpp>
51 -  
52 -// signal defines.  
53 -// reload the config file and apply new config.  
54 -#define SRS_SIGNAL_RELOAD SIGHUP  
55 -// terminate the srs with dispose to detect memory leak for gmp.  
56 -#define SRS_SIGNAL_DISPOSE SIGUSR2  
57 -// persistence the config in memory to config file.  
58 -// @see https://github.com/simple-rtmp-server/srs/issues/319#issuecomment-134993922  
59 -#define SRS_SIGNAL_PERSISTENCE_CONFIG SIGUSR1 51 +#include <srs_kernel_consts.hpp>
60 52
61 // system interval in ms, 53 // system interval in ms,
62 // all resolution times should be times togother, 54 // all resolution times should be times togother,
@@ -430,7 +422,7 @@ int SrsSignalManager::start() @@ -430,7 +422,7 @@ int SrsSignalManager::start()
430 sa.sa_handler = SrsSignalManager::sig_catcher; 422 sa.sa_handler = SrsSignalManager::sig_catcher;
431 sigemptyset(&sa.sa_mask); 423 sigemptyset(&sa.sa_mask);
432 sa.sa_flags = 0; 424 sa.sa_flags = 0;
433 - sigaction(SIGTERM, &sa, NULL); 425 + sigaction(SRS_SIGNAL_GRACEFULLY_QUIT, &sa, NULL);
434 426
435 sa.sa_handler = SrsSignalManager::sig_catcher; 427 sa.sa_handler = SrsSignalManager::sig_catcher;
436 sigemptyset(&sa.sa_mask); 428 sigemptyset(&sa.sa_mask);
@@ -824,6 +816,9 @@ int SrsServer::http_handle() @@ -824,6 +816,9 @@ int SrsServer::http_handle()
824 if ((ret = http_api_mux->handle("/api/v1/clients/", new SrsGoApiClients())) != ERROR_SUCCESS) { 816 if ((ret = http_api_mux->handle("/api/v1/clients/", new SrsGoApiClients())) != ERROR_SUCCESS) {
825 return ret; 817 return ret;
826 } 818 }
  819 + if ((ret = http_api_mux->handle("/api/v1/raw", new SrsGoApiRaw(this))) != ERROR_SUCCESS) {
  820 + return ret;
  821 + }
827 822
828 // test the request info. 823 // test the request info.
829 if ((ret = http_api_mux->handle("/api/v1/tests/requests", new SrsGoApiRequests())) != ERROR_SUCCESS) { 824 if ((ret = http_api_mux->handle("/api/v1/tests/requests", new SrsGoApiRequests())) != ERROR_SUCCESS) {
@@ -927,7 +922,7 @@ void SrsServer::on_signal(int signo) @@ -927,7 +922,7 @@ void SrsServer::on_signal(int signo)
927 return; 922 return;
928 } 923 }
929 924
930 - if (signo == SIGINT || signo == SIGUSR2) { 925 + if (signo == SIGINT || signo == SRS_SIGNAL_DISPOSE) {
931 #ifdef SRS_AUTO_GPERF_MC 926 #ifdef SRS_AUTO_GPERF_MC
932 srs_trace("gmc is on, main cycle will terminate normally."); 927 srs_trace("gmc is on, main cycle will terminate normally.");
933 signal_gmc_stop = true; 928 signal_gmc_stop = true;
@@ -941,7 +936,7 @@ void SrsServer::on_signal(int signo) @@ -941,7 +936,7 @@ void SrsServer::on_signal(int signo)
941 return; 936 return;
942 } 937 }
943 938
944 - if (signo == SIGTERM && !signal_gracefully_quit) { 939 + if (signo == SRS_SIGNAL_GRACEFULLY_QUIT && !signal_gracefully_quit) {
945 srs_trace("user terminate program, gracefully quit."); 940 srs_trace("user terminate program, gracefully quit.");
946 signal_gracefully_quit = true; 941 signal_gracefully_quit = true;
947 return; 942 return;
@@ -982,7 +977,7 @@ int SrsServer::do_cycle() @@ -982,7 +977,7 @@ int SrsServer::do_cycle()
982 for (int i = 0; i < temp_max; i++) { 977 for (int i = 0; i < temp_max; i++) {
983 st_usleep(SRS_SYS_CYCLE_INTERVAL * 1000); 978 st_usleep(SRS_SYS_CYCLE_INTERVAL * 1000);
984 979
985 - // gracefully quit for SIGINT or SIGTERM. 980 + // gracefully quit for SIGINT or SIGTERM(SRS_SIGNAL_GRACEFULLY_QUIT).
986 if (signal_gracefully_quit) { 981 if (signal_gracefully_quit) {
987 srs_trace("cleanup for gracefully terminate."); 982 srs_trace("cleanup for gracefully terminate.");
988 return ret; 983 return ret;
@@ -319,15 +319,19 @@ public: @@ -319,15 +319,19 @@ public:
319 // server utilities. 319 // server utilities.
320 public: 320 public:
321 /** 321 /**
322 - * callback for signal manager got a signal.  
323 - * the signal manager convert signal to io message,  
324 - * whatever, we will got the signo like the orignal signal(int signo) handler.  
325 - * @remark, direclty exit for SIGTERM.  
326 - * @remark, do reload for SIGNAL_RELOAD.  
327 - * @remark, for SIGINT and SIGUSR2:  
328 - * no gmc, directly exit.  
329 - * for gmc, set the variable signal_gmc_stop, the cycle will return and cleanup for gmc.  
330 - */ 322 + * callback for signal manager got a signal.
  323 + * the signal manager convert signal to io message,
  324 + * whatever, we will got the signo like the orignal signal(int signo) handler.
  325 + * @param signo the signal number from user, where:
  326 + * SRS_SIGNAL_GRACEFULLY_QUIT, the SIGTERM, dispose then quit.
  327 + * SRS_SIGNAL_DISPOSE, the SIGUSR2, dispose for gmc.
  328 + * SRS_SIGNAL_PERSISTENCE_CONFIG, the SIGUSR1, persistence config to file.
  329 + * SRS_SIGNAL_RELOAD, the SIGHUP, reload the config.
  330 + * @remark, for SIGINT and SRS_SIGNAL_DISPOSE:
  331 + * no gmc, directly exit.
  332 + * for gmc, set the variable signal_gmc_stop, the cycle will return and cleanup for gmc.
  333 + * @remark, maybe the HTTP RAW API will trigger the on_signal() also.
  334 + */
331 virtual void on_signal(int signo); 335 virtual void on_signal(int signo);
332 private: 336 private:
333 /** 337 /**
@@ -134,6 +134,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -134,6 +134,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
134 #define SRS_CONSTS_NULL_FILE "/dev/null" 134 #define SRS_CONSTS_NULL_FILE "/dev/null"
135 #define SRS_CONSTS_LOCALHOST "127.0.0.1" 135 #define SRS_CONSTS_LOCALHOST "127.0.0.1"
136 136
  137 +// signal defines.
  138 +// reload the config file and apply new config.
  139 +#define SRS_SIGNAL_RELOAD SIGHUP
  140 +// terminate the srs with dispose to detect memory leak for gmc.
  141 +#define SRS_SIGNAL_DISPOSE SIGUSR2
  142 +// persistence the config in memory to config file.
  143 +// @see https://github.com/simple-rtmp-server/srs/issues/319#issuecomment-134993922
  144 +#define SRS_SIGNAL_PERSISTENCE_CONFIG SIGUSR1
  145 +// srs should gracefully quit, do dispose then exit.
  146 +#define SRS_SIGNAL_GRACEFULLY_QUIT SIGTERM
  147 +
137 /////////////////////////////////////////////////////////// 148 ///////////////////////////////////////////////////////////
138 /////////////////////////////////////////////////////////// 149 ///////////////////////////////////////////////////////////
139 /////////////////////////////////////////////////////////// 150 ///////////////////////////////////////////////////////////
@@ -98,6 +98,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -98,6 +98,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
98 #define ERROR_SYSTEM_CREATE_DIR 1057 98 #define ERROR_SYSTEM_CREATE_DIR 1057
99 #define ERROR_SYSTEM_KILL 1058 99 #define ERROR_SYSTEM_KILL 1058
100 #define ERROR_SYSTEM_CONFIG_PERSISTENCE 1059 100 #define ERROR_SYSTEM_CONFIG_PERSISTENCE 1059
  101 +#define ERROR_SYSTEM_CONFIG_RAW 1060
  102 +#define ERROR_SYSTEM_CONFIG_RAW_DISABLED 1061
  103 +#define ERROR_SYSTEM_CONFIG_RAW_PARAMS 1062
101 104
102 /////////////////////////////////////////////////////// 105 ///////////////////////////////////////////////////////
103 // RTMP protocol error. 106 // RTMP protocol error.