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,