diff --git a/README.md b/README.md index 9cd8cde50..cb867a5d5 100755 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ url: rtmp://127.0.0.1:1935/live/livestream * nginx v1.5.0: 139524 lines
### History +* v0.4, 2013-11-09, support reload config(listen and chunk_size) by SIGHUP(1). * v0.4, 2013-11-09, support longtime(>4.6hours) publish/play. * v0.4, 2013-11-09, support config the chunk_size. * v0.4, 2013-11-09, support pause for live stream. diff --git a/trunk/conf/srs.conf b/trunk/conf/srs.conf index 9066be600..7e8bfeb81 100755 --- a/trunk/conf/srs.conf +++ b/trunk/conf/srs.conf @@ -1,5 +1,5 @@ # the listen ports, split by space. -listen 1935 19350; +listen 1935; # the default chunk size is 128, max is 65536, # some client does not support chunk size change, # however, most clients supports it and it can improve diff --git a/trunk/configure b/trunk/configure index 0149d34c7..71876c391 100755 --- a/trunk/configure +++ b/trunk/configure @@ -91,7 +91,7 @@ MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server" "srs_core_auto_free" "srs_core_protocol" "srs_core_amf0" "srs_core_stream" "srs_core_source" "srs_core_codec" "srs_core_complex_handshake" "srs_core_pithy_print" - "srs_core_config" "srs_core_refer") + "srs_core_config" "srs_core_refer" "srs_core_reload") MODULE_DIR="src/core" . auto/modules.sh CORE_OBJS="${MODULE_OBJS[@]}" diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 3ee52085e..0f19d4fe1 100755 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -84,4 +84,7 @@ extern int64_t srs_get_system_time_ms(); // the deamon st-thread will update it. extern void srs_update_system_time_ms(); +// signal defines. +#define SIGNAL_RELOAD SIGHUP + #endif \ No newline at end of file diff --git a/trunk/src/core/srs_core_config.cpp b/trunk/src/core/srs_core_config.cpp index d366a09f4..67feb6414 100755 --- a/trunk/src/core/srs_core_config.cpp +++ b/trunk/src/core/srs_core_config.cpp @@ -34,8 +34,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include #include +#include +#include #define FILE_OFFSET(fd) lseek(fd, 0, SEEK_CUR) @@ -79,7 +82,7 @@ int SrsFileBuffer::open(const char* filename) assert(fd == -1); if ((fd = ::open(filename, O_RDONLY, 0)) < 0) { - fprintf(stderr, "open conf file error. errno=%d(%s)\n", errno, strerror(errno)); + srs_error("open conf file error. errno=%d(%s)", errno, strerror(errno)); return ERROR_SYSTEM_CONFIG_INVALID; } @@ -182,21 +185,21 @@ int SrsConfDirective::parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type) } if (ret == ERROR_SYSTEM_CONFIG_BLOCK_END) { if (type != parse_block) { - fprintf(stderr, "line %d: unexpected \"}\"\n", buffer->line); + srs_error("line %d: unexpected \"}\"", buffer->line); return ret; } return ERROR_SUCCESS; } if (ret == ERROR_SYSTEM_CONFIG_EOF) { if (type == parse_block) { - fprintf(stderr, "line %d: unexpected end of file, expecting \"}\"\n", buffer->line); + srs_error("line %d: unexpected end of file, expecting \"}\"", buffer->line); return ret; } return ERROR_SUCCESS; } if (args.empty()) { - fprintf(stderr, "line %d: empty directive.\n", buffer->line); + srs_error("line %d: empty directive.", buffer->line); return ret; } @@ -239,7 +242,7 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector while (true) { if ((ret = refill_buffer(buffer, d_quoted, s_quoted, startline, pstart)) != ERROR_SUCCESS) { if (!args.empty() || !last_space) { - fprintf(stderr, "line %d: unexpected end of file, expecting ; or \"}\"\n", buffer->line); + srs_error("line %d: unexpected end of file, expecting ; or \"}\"", buffer->line); return ERROR_SYSTEM_CONFIG_INVALID; } return ret; @@ -268,7 +271,7 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector if (ch == '{') { return ERROR_SYSTEM_CONFIG_BLOCK_START; } - fprintf(stderr, "line %d: unexpected '%c'\n", buffer->line, ch); + srs_error("line %d: unexpected '%c'", buffer->line, ch); return ERROR_SYSTEM_CONFIG_INVALID; } @@ -282,19 +285,19 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector switch (ch) { case ';': if (args.size() == 0) { - fprintf(stderr, "line %d: unexpected ';'\n", buffer->line); + srs_error("line %d: unexpected ';'", buffer->line); return ERROR_SYSTEM_CONFIG_INVALID; } return ERROR_SYSTEM_CONFIG_DIRECTIVE; case '{': if (args.size() == 0) { - fprintf(stderr, "line %d: unexpected '{'\n", buffer->line); + srs_error("line %d: unexpected '{'", buffer->line); return ERROR_SYSTEM_CONFIG_INVALID; } return ERROR_SYSTEM_CONFIG_BLOCK_START; case '}': if (args.size() != 0) { - fprintf(stderr, "line %d: unexpected '}'\n", buffer->line); + srs_error("line %d: unexpected '}'", buffer->line); return ERROR_SYSTEM_CONFIG_INVALID; } return ERROR_SYSTEM_CONFIG_BLOCK_END; @@ -376,12 +379,12 @@ int SrsConfDirective::refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s buffer->line = startline; if (!d_quoted && !s_quoted) { - fprintf(stderr, "line %d: too long parameter \"%*s...\" started\n", + srs_error("line %d: too long parameter \"%*s...\" started", buffer->line, 10, buffer->start); } else { - fprintf(stderr, "line %d: too long parameter, " - "probably missing terminating '%c' character\n", buffer->line, d_quoted? '"':'\''); + srs_error("line %d: too long parameter, " + "probably missing terminating '%c' character", buffer->line, d_quoted? '"':'\''); } return ERROR_SYSTEM_CONFIG_INVALID; } @@ -393,7 +396,7 @@ int SrsConfDirective::refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s size = srs_min(size, buffer->end - (buffer->start + len)); int n = read(buffer->fd, buffer->start + len, size); if (n != size) { - fprintf(stderr, "read file read error. expect %d, actual %d bytes.\n", size, n); + srs_error("read file read error. expect %d, actual %d bytes.", size, n); return ERROR_SYSTEM_CONFIG_INVALID; } @@ -404,26 +407,85 @@ int SrsConfDirective::refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s return ret; } -Config* config = new Config(); +SrsConfig* config = new SrsConfig(); -Config::Config() +SrsConfig::SrsConfig() { show_help = false; show_version = false; - config_file = NULL; root = new SrsConfDirective(); root->conf_line = 0; root->name = "root"; } -Config::~Config() +SrsConfig::~SrsConfig() { srs_freep(root); } +int SrsConfig::reload() +{ + int ret = ERROR_SUCCESS; + + SrsConfig conf; + if ((ret = conf.parse_file(config_file.c_str())) != ERROR_SUCCESS) { + srs_error("config reloader parse file failed. ret=%d", ret); + return ret; + } + srs_info("config reloader parse file success."); + + // store current root to old_root, + // and reap the root from conf to current root. + SrsConfDirective* old_root = root; + SrsAutoFree(SrsConfDirective, old_root, false); + + root = conf.root; + conf.root = NULL; + + // merge config. + std::vector::iterator it; + + // merge config: listen + if (!srs_directive_equals(root->get("listen"), old_root->get("listen"))) { + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + SrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_listen()) != ERROR_SUCCESS) { + srs_error("notify subscribes reload listen failed. ret=%d", ret); + return ret; + } + } + } + + return ret; +} + +void SrsConfig::subscribe(SrsReloadHandler* handler) +{ + std::vector::iterator it; + + it = std::find(subscribes.begin(), subscribes.end(), handler); + if (it != subscribes.end()) { + return; + } + + subscribes.push_back(handler); +} + +void SrsConfig::unsubscribe(SrsReloadHandler* handler) +{ + std::vector::iterator it; + + it = std::find(subscribes.begin(), subscribes.end(), handler); + if (it == subscribes.end()) { + return; + } + + subscribes.erase(it); +} + // see: ngx_get_options -int Config::parse_options(int argc, char** argv) +int SrsConfig::parse_options(int argc, char** argv) { int ret = ERROR_SUCCESS; @@ -438,33 +500,23 @@ int Config::parse_options(int argc, char** argv) } if (show_version) { - fprintf(stderr, "%s\n", RTMP_SIG_SRS_VERSION); + printf("%s\n", RTMP_SIG_SRS_VERSION); } if (show_help || show_version) { exit(0); } - if (!config_file) { - fprintf(stderr, "config file not specified, see help: %s -h\n", argv[0]); - return ERROR_SYSTEM_CONFIG_INVALID; - } - - if ((ret = root->parse(config_file)) != ERROR_SUCCESS) { + if (config_file.empty()) { + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("config file not specified, see help: %s -h, ret=%d", argv[0], ret); return ret; } - - SrsConfDirective* conf = NULL; - if ((conf = get_listen()) == NULL || conf->args.size() == 0) { - fprintf(stderr, "line %d: conf error, " - "directive \"listen\" is empty\n", conf? conf->conf_line:0); - return ERROR_SYSTEM_CONFIG_INVALID; - } - - return ret; + + return parse_file(config_file.c_str()); } -SrsConfDirective* Config::get_vhost(std::string vhost) +SrsConfDirective* SrsConfig::get_vhost(std::string vhost) { srs_assert(root); @@ -487,7 +539,7 @@ SrsConfDirective* Config::get_vhost(std::string vhost) return NULL; } -SrsConfDirective* Config::get_gop_cache(std::string vhost) +SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost) { SrsConfDirective* conf = get_vhost(vhost); @@ -498,7 +550,7 @@ SrsConfDirective* Config::get_gop_cache(std::string vhost) return conf->get("gop_cache"); } -SrsConfDirective* Config::get_refer(std::string vhost) +SrsConfDirective* SrsConfig::get_refer(std::string vhost) { SrsConfDirective* conf = get_vhost(vhost); @@ -509,7 +561,7 @@ SrsConfDirective* Config::get_refer(std::string vhost) return conf->get("refer"); } -SrsConfDirective* Config::get_refer_play(std::string vhost) +SrsConfDirective* SrsConfig::get_refer_play(std::string vhost) { SrsConfDirective* conf = get_vhost(vhost); @@ -520,7 +572,7 @@ SrsConfDirective* Config::get_refer_play(std::string vhost) return conf->get("refer_play"); } -SrsConfDirective* Config::get_refer_publish(std::string vhost) +SrsConfDirective* SrsConfig::get_refer_publish(std::string vhost) { SrsConfDirective* conf = get_vhost(vhost); @@ -531,26 +583,52 @@ SrsConfDirective* Config::get_refer_publish(std::string vhost) return conf->get("refer_publish"); } -SrsConfDirective* Config::get_listen() +SrsConfDirective* SrsConfig::get_listen() { return root->get("listen"); } -SrsConfDirective* Config::get_chunk_size() +SrsConfDirective* SrsConfig::get_chunk_size() { return root->get("chunk_size"); } -int Config::parse_argv(int& i, char** argv) +int SrsConfig::parse_file(const char* filename) +{ + int ret = ERROR_SUCCESS; + + config_file = filename; + + if (config_file.empty()) { + return ERROR_SYSTEM_CONFIG_INVALID; + } + + if ((ret = root->parse(config_file.c_str())) != ERROR_SUCCESS) { + return ret; + } + + SrsConfDirective* conf = NULL; + if ((conf = get_listen()) == NULL || conf->args.size() == 0) { + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("line %d: conf error, " + "directive \"listen\" is empty, ret=%d", (conf? conf->conf_line:0), ret); + return ret; + } + + return ret; +} + +int SrsConfig::parse_argv(int& i, char** argv) { int ret = ERROR_SUCCESS; char* p = argv[i]; if (*p++ != '-') { - fprintf(stderr, "invalid options(index=%d, value=%s), " - "must starts with -, see help: %s -h\n", i, argv[i], argv[0]); - return ERROR_SYSTEM_CONFIG_INVALID; + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("invalid options(index=%d, value=%s), " + "must starts with -, see help: %s -h, ret=%d", i, argv[i], argv[0], ret); + return ret; } while (*p) { @@ -572,20 +650,22 @@ int Config::parse_argv(int& i, char** argv) config_file = argv[i]; return ret; } - fprintf(stderr, "option \"-c\" requires parameter\n"); - return ERROR_SYSTEM_CONFIG_INVALID; + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("option \"-c\" requires parameter, ret=%d", ret); + return ret; default: - fprintf(stderr, "invalid option: \"%c\", see help: %s -h\n", *(p - 1), argv[0]); - return ERROR_SYSTEM_CONFIG_INVALID; + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("invalid option: \"%c\", see help: %s -h, ret=%d", *(p - 1), argv[0], ret); + return ret; } } return ret; } -void Config::print_help(char** argv) +void SrsConfig::print_help(char** argv) { - fprintf(stderr, RTMP_SIG_SRS_NAME" "RTMP_SIG_SRS_VERSION + printf(RTMP_SIG_SRS_NAME" "RTMP_SIG_SRS_VERSION " Copyright (c) 2013 winlin\n" "Usage: %s [-h?vV] [-c ]\n" "\n" @@ -600,3 +680,39 @@ void Config::print_help(char** argv) argv[0]); } +bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b) +{ + if (!a || !b) { + return false; + } + + if (a->name != b->name) { + return false; + } + + if (a->args.size() != b->args.size()) { + return false; + } + + for (int i = 0; i < (int)a->args.size(); i++) { + if (a->args.at(i) != b->args.at(i)) { + return false; + } + } + + if (a->directives.size() != b->directives.size()) { + return false; + } + + for (int i = 0; i < (int)a->directives.size(); i++) { + SrsConfDirective* a0 = a->at(i); + SrsConfDirective* b0 = b->at(i); + + if (!srs_directive_equals(a0, b0)) { + return false; + } + } + + return true; +} + diff --git a/trunk/src/core/srs_core_config.hpp b/trunk/src/core/srs_core_config.hpp index 3baa0a11c..70a9d6469 100755 --- a/trunk/src/core/srs_core_config.hpp +++ b/trunk/src/core/srs_core_config.hpp @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include + // default vhost for rtmp #define RTMP_VHOST_DEFAULT "__defaultVhost__" @@ -84,16 +86,21 @@ public: /** * the config parser. */ -class Config +class SrsConfig { private: bool show_help; bool show_version; - char* config_file; + std::string config_file; SrsConfDirective* root; + std::vector subscribes; +public: + SrsConfig(); + virtual ~SrsConfig(); public: - Config(); - virtual ~Config(); + virtual int reload(); + virtual void subscribe(SrsReloadHandler* handler); + virtual void unsubscribe(SrsReloadHandler* handler); public: virtual int parse_options(int argc, char** argv); virtual SrsConfDirective* get_vhost(std::string vhost); @@ -104,11 +111,17 @@ public: virtual SrsConfDirective* get_listen(); virtual SrsConfDirective* get_chunk_size(); private: + virtual int parse_file(const char* filename); virtual int parse_argv(int& i, char** argv); virtual void print_help(char** argv); }; +/** +* deep compare directive. +*/ +bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b); + // global config -extern Config* config; +extern SrsConfig* config; #endif \ No newline at end of file diff --git a/trunk/src/core/srs_core_conn.cpp b/trunk/src/core/srs_core_conn.cpp index 4c99b9922..9bae22167 100755 --- a/trunk/src/core/srs_core_conn.cpp +++ b/trunk/src/core/srs_core_conn.cpp @@ -36,8 +36,13 @@ SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd) SrsConnection::~SrsConnection() { if (stfd) { + int fd = st_netfd_fileno(stfd); st_netfd_close(stfd); stfd = NULL; + + // st does not close it sometimes, + // close it manually. + close(fd); } } diff --git a/trunk/src/core/srs_core_reload.cpp b/trunk/src/core/srs_core_reload.cpp new file mode 100755 index 000000000..52b7c2df2 --- /dev/null +++ b/trunk/src/core/srs_core_reload.cpp @@ -0,0 +1,41 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013 winlin + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include + +SrsReloadHandler::SrsReloadHandler() +{ +} + +SrsReloadHandler::~SrsReloadHandler() +{ +} + +int SrsReloadHandler::on_reload_listen() +{ + int ret = ERROR_SUCCESS; + return ret; +} + diff --git a/trunk/src/core/srs_core_reload.hpp b/trunk/src/core/srs_core_reload.hpp new file mode 100755 index 000000000..be48e19b5 --- /dev/null +++ b/trunk/src/core/srs_core_reload.hpp @@ -0,0 +1,44 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013 winlin + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef SRS_CORE_RELOAD_HPP +#define SRS_CORE_RELOAD_HPP + +/* +#include +*/ +#include + +/** +* the handler for config reload. +*/ +class SrsReloadHandler +{ +public: + SrsReloadHandler(); + virtual ~SrsReloadHandler(); +public: + virtual int on_reload_listen(); +}; + +#endif \ No newline at end of file diff --git a/trunk/src/core/srs_core_server.cpp b/trunk/src/core/srs_core_server.cpp index edf63dbbf..3bdf1776f 100755 --- a/trunk/src/core/srs_core_server.cpp +++ b/trunk/src/core/srs_core_server.cpp @@ -26,6 +26,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include #include @@ -37,7 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #define SERVER_LISTEN_BACKLOG 10 -#define SRS_TIME_RESOLUTION_MS 1000 +#define SRS_TIME_RESOLUTION_MS 500 SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type) { @@ -47,6 +48,9 @@ SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type) port = 0; server = _server; type = _type; + + tid = NULL; + loop = false; } SrsListener::~SrsListener() @@ -55,6 +59,17 @@ SrsListener::~SrsListener() st_netfd_close(stfd); stfd = NULL; } + + if (tid) { + loop = false; + st_thread_interrupt(tid); + st_thread_join(tid, NULL); + tid = NULL; + } + + // st does not close it sometimes, + // close it manually. + close(fd); } int SrsListener::listen(int _port) @@ -103,7 +118,7 @@ int SrsListener::listen(int _port) } srs_verbose("st open socket success. fd=%d", fd); - if (st_thread_create(listen_thread, this, 0, 0) == NULL) { + if ((tid = st_thread_create(listen_thread, this, 1, 0)) == NULL) { ret = ERROR_ST_CREATE_LISTEN_THREAD; srs_error("st_thread_create listen thread error. ret=%d", ret); return ret; @@ -122,7 +137,7 @@ void SrsListener::listen_cycle() log_context->generate_id(); srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd); - while (true) { + while (loop) { st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT); if(client_stfd == NULL){ @@ -146,6 +161,7 @@ void* SrsListener::listen_thread(void* arg) SrsListener* obj = (SrsListener*)arg; srs_assert(obj != NULL); + obj->loop = true; obj->listen_cycle(); return NULL; @@ -153,10 +169,15 @@ void* SrsListener::listen_thread(void* arg) SrsServer::SrsServer() { + signal_reload = false; + + config->subscribe(this); } SrsServer::~SrsServer() { + config->unsubscribe(this); + if (true) { std::vector::iterator it; for (it = conns.begin(); it != conns.end(); ++it) { @@ -166,14 +187,7 @@ SrsServer::~SrsServer() conns.clear(); } - if (true) { - std::vector::iterator it; - for (it = listeners.begin(); it != listeners.end(); ++it) { - SrsListener* listener = *it; - srs_freep(listener); - } - listeners.clear(); - } + close_listeners(); } int SrsServer::initialize() @@ -212,6 +226,8 @@ int SrsServer::listen() conf = config->get_listen(); srs_assert(conf); + close_listeners(); + for (int i = 0; i < (int)conf->args.size(); i++) { SrsListener* listener = new SrsListener(this, SrsListenerStream); listeners.push_back(listener); @@ -234,6 +250,17 @@ int SrsServer::cycle() while (true) { st_usleep(SRS_TIME_RESOLUTION_MS * 1000); srs_update_system_time_ms(); + + if (signal_reload) { + signal_reload = false; + srs_info("get signal reload, to reload the config."); + + if ((ret = config->reload()) != ERROR_SUCCESS) { + srs_error("reload config failed. ret=%d", ret); + return ret; + } + srs_trace("reload config success."); + } } return ret; @@ -254,6 +281,23 @@ void SrsServer::remove(SrsConnection* conn) srs_freep(conn); } +void SrsServer::on_signal(int signo) +{ + if (signo == SIGNAL_RELOAD) { + signal_reload = true; + } +} + +void SrsServer::close_listeners() +{ + std::vector::iterator it; + for (it = listeners.begin(); it != listeners.end(); ++it) { + SrsListener* listener = *it; + srs_freep(listener); + } + listeners.clear(); +} + int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) { int ret = ERROR_SUCCESS; @@ -279,3 +323,10 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) return ret; } +int SrsServer::on_reload_listen() +{ + return listen(); +} + +SrsServer server; + diff --git a/trunk/src/core/srs_core_server.hpp b/trunk/src/core/srs_core_server.hpp index 33db0c9a8..db96205ec 100755 --- a/trunk/src/core/srs_core_server.hpp +++ b/trunk/src/core/srs_core_server.hpp @@ -34,6 +34,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include +#include + class SrsServer; class SrsConnection; @@ -52,6 +54,8 @@ private: st_netfd_t stfd; int port; SrsServer* server; + st_thread_t tid; + bool loop; public: SrsListener(SrsServer* _server, SrsListenerType _type); virtual ~SrsListener(); @@ -62,12 +66,13 @@ private: static void* listen_thread(void* arg); }; -class SrsServer +class SrsServer : public SrsReloadHandler { friend class SrsListener; private: std::vector conns; std::vector listeners; + bool signal_reload; public: SrsServer(); virtual ~SrsServer(); @@ -76,8 +81,14 @@ public: virtual int listen(); virtual int cycle(); virtual void remove(SrsConnection* conn); + virtual void on_signal(int signo); private: + virtual void close_listeners(); virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd); +public: + virtual int on_reload_listen(); }; + +extern SrsServer server; #endif \ No newline at end of file diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index 57ba66417..7d237cf13 100755 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -27,16 +27,23 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include + +void handler(int signo) +{ + srs_trace("get a signal, signo=%d", signo); + server.on_signal(signo); +} int main(int argc, char** argv){ int ret = ERROR_SUCCESS; + signal(SIGNAL_RELOAD, handler); + if ((ret = config->parse_options(argc, argv)) != ERROR_SUCCESS) { return ret; } - SrsServer server; - if ((ret = server.initialize()) != ERROR_SUCCESS) { return ret; } diff --git a/trunk/src/srs/srs.upp b/trunk/src/srs/srs.upp index 887601492..66a7817a8 100755 --- a/trunk/src/srs/srs.upp +++ b/trunk/src/srs/srs.upp @@ -10,6 +10,8 @@ file ..\core\srs_core_auto_free.cpp, ..\core\srs_core_server.hpp, ..\core\srs_core_server.cpp, + ..\core\srs_core_reload.hpp, + ..\core\srs_core_reload.cpp, ..\core\srs_core_config.hpp, ..\core\srs_core_config.cpp, ..\core\srs_core_refer.hpp,