winlin

support reload config(listen and chunk_size) by SIGHUP(1).

@@ -48,6 +48,7 @@ url: rtmp://127.0.0.1:1935/live/livestream @@ -48,6 +48,7 @@ url: rtmp://127.0.0.1:1935/live/livestream
48 * nginx v1.5.0: 139524 lines <br/> 48 * nginx v1.5.0: 139524 lines <br/>
49 49
50 ### History 50 ### History
  51 +* v0.4, 2013-11-09, support reload config(listen and chunk_size) by SIGHUP(1).
51 * v0.4, 2013-11-09, support longtime(>4.6hours) publish/play. 52 * v0.4, 2013-11-09, support longtime(>4.6hours) publish/play.
52 * v0.4, 2013-11-09, support config the chunk_size. 53 * v0.4, 2013-11-09, support config the chunk_size.
53 * v0.4, 2013-11-09, support pause for live stream. 54 * v0.4, 2013-11-09, support pause for live stream.
1 # the listen ports, split by space. 1 # the listen ports, split by space.
2 -listen 1935 19350; 2 +listen 1935;
3 # the default chunk size is 128, max is 65536, 3 # the default chunk size is 128, max is 65536,
4 # some client does not support chunk size change, 4 # some client does not support chunk size change,
5 # however, most clients supports it and it can improve 5 # however, most clients supports it and it can improve
@@ -91,7 +91,7 @@ MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server" @@ -91,7 +91,7 @@ MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server"
91 "srs_core_auto_free" "srs_core_protocol" "srs_core_amf0" 91 "srs_core_auto_free" "srs_core_protocol" "srs_core_amf0"
92 "srs_core_stream" "srs_core_source" "srs_core_codec" 92 "srs_core_stream" "srs_core_source" "srs_core_codec"
93 "srs_core_complex_handshake" "srs_core_pithy_print" 93 "srs_core_complex_handshake" "srs_core_pithy_print"
94 - "srs_core_config" "srs_core_refer") 94 + "srs_core_config" "srs_core_refer" "srs_core_reload")
95 MODULE_DIR="src/core" . auto/modules.sh 95 MODULE_DIR="src/core" . auto/modules.sh
96 CORE_OBJS="${MODULE_OBJS[@]}" 96 CORE_OBJS="${MODULE_OBJS[@]}"
97 97
@@ -84,4 +84,7 @@ extern int64_t srs_get_system_time_ms(); @@ -84,4 +84,7 @@ extern int64_t srs_get_system_time_ms();
84 // the deamon st-thread will update it. 84 // the deamon st-thread will update it.
85 extern void srs_update_system_time_ms(); 85 extern void srs_update_system_time_ms();
86 86
  87 +// signal defines.
  88 +#define SIGNAL_RELOAD SIGHUP
  89 +
87 #endif 90 #endif
@@ -34,8 +34,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -34,8 +34,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 #include <fcntl.h> 34 #include <fcntl.h>
35 35
36 #include <vector> 36 #include <vector>
  37 +#include <algorithm>
37 38
38 #include <srs_core_error.hpp> 39 #include <srs_core_error.hpp>
  40 +#include <srs_core_log.hpp>
  41 +#include <srs_core_auto_free.hpp>
39 42
40 #define FILE_OFFSET(fd) lseek(fd, 0, SEEK_CUR) 43 #define FILE_OFFSET(fd) lseek(fd, 0, SEEK_CUR)
41 44
@@ -79,7 +82,7 @@ int SrsFileBuffer::open(const char* filename) @@ -79,7 +82,7 @@ int SrsFileBuffer::open(const char* filename)
79 assert(fd == -1); 82 assert(fd == -1);
80 83
81 if ((fd = ::open(filename, O_RDONLY, 0)) < 0) { 84 if ((fd = ::open(filename, O_RDONLY, 0)) < 0) {
82 - fprintf(stderr, "open conf file error. errno=%d(%s)\n", errno, strerror(errno)); 85 + srs_error("open conf file error. errno=%d(%s)", errno, strerror(errno));
83 return ERROR_SYSTEM_CONFIG_INVALID; 86 return ERROR_SYSTEM_CONFIG_INVALID;
84 } 87 }
85 88
@@ -182,21 +185,21 @@ int SrsConfDirective::parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type) @@ -182,21 +185,21 @@ int SrsConfDirective::parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type)
182 } 185 }
183 if (ret == ERROR_SYSTEM_CONFIG_BLOCK_END) { 186 if (ret == ERROR_SYSTEM_CONFIG_BLOCK_END) {
184 if (type != parse_block) { 187 if (type != parse_block) {
185 - fprintf(stderr, "line %d: unexpected \"}\"\n", buffer->line); 188 + srs_error("line %d: unexpected \"}\"", buffer->line);
186 return ret; 189 return ret;
187 } 190 }
188 return ERROR_SUCCESS; 191 return ERROR_SUCCESS;
189 } 192 }
190 if (ret == ERROR_SYSTEM_CONFIG_EOF) { 193 if (ret == ERROR_SYSTEM_CONFIG_EOF) {
191 if (type == parse_block) { 194 if (type == parse_block) {
192 - fprintf(stderr, "line %d: unexpected end of file, expecting \"}\"\n", buffer->line); 195 + srs_error("line %d: unexpected end of file, expecting \"}\"", buffer->line);
193 return ret; 196 return ret;
194 } 197 }
195 return ERROR_SUCCESS; 198 return ERROR_SUCCESS;
196 } 199 }
197 200
198 if (args.empty()) { 201 if (args.empty()) {
199 - fprintf(stderr, "line %d: empty directive.\n", buffer->line); 202 + srs_error("line %d: empty directive.", buffer->line);
200 return ret; 203 return ret;
201 } 204 }
202 205
@@ -239,7 +242,7 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string> @@ -239,7 +242,7 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string>
239 while (true) { 242 while (true) {
240 if ((ret = refill_buffer(buffer, d_quoted, s_quoted, startline, pstart)) != ERROR_SUCCESS) { 243 if ((ret = refill_buffer(buffer, d_quoted, s_quoted, startline, pstart)) != ERROR_SUCCESS) {
241 if (!args.empty() || !last_space) { 244 if (!args.empty() || !last_space) {
242 - fprintf(stderr, "line %d: unexpected end of file, expecting ; or \"}\"\n", buffer->line); 245 + srs_error("line %d: unexpected end of file, expecting ; or \"}\"", buffer->line);
243 return ERROR_SYSTEM_CONFIG_INVALID; 246 return ERROR_SYSTEM_CONFIG_INVALID;
244 } 247 }
245 return ret; 248 return ret;
@@ -268,7 +271,7 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string> @@ -268,7 +271,7 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string>
268 if (ch == '{') { 271 if (ch == '{') {
269 return ERROR_SYSTEM_CONFIG_BLOCK_START; 272 return ERROR_SYSTEM_CONFIG_BLOCK_START;
270 } 273 }
271 - fprintf(stderr, "line %d: unexpected '%c'\n", buffer->line, ch); 274 + srs_error("line %d: unexpected '%c'", buffer->line, ch);
272 return ERROR_SYSTEM_CONFIG_INVALID; 275 return ERROR_SYSTEM_CONFIG_INVALID;
273 } 276 }
274 277
@@ -282,19 +285,19 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string> @@ -282,19 +285,19 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string>
282 switch (ch) { 285 switch (ch) {
283 case ';': 286 case ';':
284 if (args.size() == 0) { 287 if (args.size() == 0) {
285 - fprintf(stderr, "line %d: unexpected ';'\n", buffer->line); 288 + srs_error("line %d: unexpected ';'", buffer->line);
286 return ERROR_SYSTEM_CONFIG_INVALID; 289 return ERROR_SYSTEM_CONFIG_INVALID;
287 } 290 }
288 return ERROR_SYSTEM_CONFIG_DIRECTIVE; 291 return ERROR_SYSTEM_CONFIG_DIRECTIVE;
289 case '{': 292 case '{':
290 if (args.size() == 0) { 293 if (args.size() == 0) {
291 - fprintf(stderr, "line %d: unexpected '{'\n", buffer->line); 294 + srs_error("line %d: unexpected '{'", buffer->line);
292 return ERROR_SYSTEM_CONFIG_INVALID; 295 return ERROR_SYSTEM_CONFIG_INVALID;
293 } 296 }
294 return ERROR_SYSTEM_CONFIG_BLOCK_START; 297 return ERROR_SYSTEM_CONFIG_BLOCK_START;
295 case '}': 298 case '}':
296 if (args.size() != 0) { 299 if (args.size() != 0) {
297 - fprintf(stderr, "line %d: unexpected '}'\n", buffer->line); 300 + srs_error("line %d: unexpected '}'", buffer->line);
298 return ERROR_SYSTEM_CONFIG_INVALID; 301 return ERROR_SYSTEM_CONFIG_INVALID;
299 } 302 }
300 return ERROR_SYSTEM_CONFIG_BLOCK_END; 303 return ERROR_SYSTEM_CONFIG_BLOCK_END;
@@ -376,12 +379,12 @@ int SrsConfDirective::refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s @@ -376,12 +379,12 @@ int SrsConfDirective::refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s
376 buffer->line = startline; 379 buffer->line = startline;
377 380
378 if (!d_quoted && !s_quoted) { 381 if (!d_quoted && !s_quoted) {
379 - fprintf(stderr, "line %d: too long parameter \"%*s...\" started\n", 382 + srs_error("line %d: too long parameter \"%*s...\" started",
380 buffer->line, 10, buffer->start); 383 buffer->line, 10, buffer->start);
381 384
382 } else { 385 } else {
383 - fprintf(stderr, "line %d: too long parameter, "  
384 - "probably missing terminating '%c' character\n", buffer->line, d_quoted? '"':'\''); 386 + srs_error("line %d: too long parameter, "
  387 + "probably missing terminating '%c' character", buffer->line, d_quoted? '"':'\'');
385 } 388 }
386 return ERROR_SYSTEM_CONFIG_INVALID; 389 return ERROR_SYSTEM_CONFIG_INVALID;
387 } 390 }
@@ -393,7 +396,7 @@ int SrsConfDirective::refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s @@ -393,7 +396,7 @@ int SrsConfDirective::refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s
393 size = srs_min(size, buffer->end - (buffer->start + len)); 396 size = srs_min(size, buffer->end - (buffer->start + len));
394 int n = read(buffer->fd, buffer->start + len, size); 397 int n = read(buffer->fd, buffer->start + len, size);
395 if (n != size) { 398 if (n != size) {
396 - fprintf(stderr, "read file read error. expect %d, actual %d bytes.\n", size, n); 399 + srs_error("read file read error. expect %d, actual %d bytes.", size, n);
397 return ERROR_SYSTEM_CONFIG_INVALID; 400 return ERROR_SYSTEM_CONFIG_INVALID;
398 } 401 }
399 402
@@ -404,26 +407,85 @@ int SrsConfDirective::refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s @@ -404,26 +407,85 @@ int SrsConfDirective::refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s
404 return ret; 407 return ret;
405 } 408 }
406 409
407 -Config* config = new Config(); 410 +SrsConfig* config = new SrsConfig();
408 411
409 -Config::Config() 412 +SrsConfig::SrsConfig()
410 { 413 {
411 show_help = false; 414 show_help = false;
412 show_version = false; 415 show_version = false;
413 - config_file = NULL;  
414 416
415 root = new SrsConfDirective(); 417 root = new SrsConfDirective();
416 root->conf_line = 0; 418 root->conf_line = 0;
417 root->name = "root"; 419 root->name = "root";
418 } 420 }
419 421
420 -Config::~Config() 422 +SrsConfig::~SrsConfig()
421 { 423 {
422 srs_freep(root); 424 srs_freep(root);
423 } 425 }
424 426
  427 +int SrsConfig::reload()
  428 +{
  429 + int ret = ERROR_SUCCESS;
  430 +
  431 + SrsConfig conf;
  432 + if ((ret = conf.parse_file(config_file.c_str())) != ERROR_SUCCESS) {
  433 + srs_error("config reloader parse file failed. ret=%d", ret);
  434 + return ret;
  435 + }
  436 + srs_info("config reloader parse file success.");
  437 +
  438 + // store current root to old_root,
  439 + // and reap the root from conf to current root.
  440 + SrsConfDirective* old_root = root;
  441 + SrsAutoFree(SrsConfDirective, old_root, false);
  442 +
  443 + root = conf.root;
  444 + conf.root = NULL;
  445 +
  446 + // merge config.
  447 + std::vector<SrsReloadHandler*>::iterator it;
  448 +
  449 + // merge config: listen
  450 + if (!srs_directive_equals(root->get("listen"), old_root->get("listen"))) {
  451 + for (it = subscribes.begin(); it != subscribes.end(); ++it) {
  452 + SrsReloadHandler* subscribe = *it;
  453 + if ((ret = subscribe->on_reload_listen()) != ERROR_SUCCESS) {
  454 + srs_error("notify subscribes reload listen failed. ret=%d", ret);
  455 + return ret;
  456 + }
  457 + }
  458 + }
  459 +
  460 + return ret;
  461 +}
  462 +
  463 +void SrsConfig::subscribe(SrsReloadHandler* handler)
  464 +{
  465 + std::vector<SrsReloadHandler*>::iterator it;
  466 +
  467 + it = std::find(subscribes.begin(), subscribes.end(), handler);
  468 + if (it != subscribes.end()) {
  469 + return;
  470 + }
  471 +
  472 + subscribes.push_back(handler);
  473 +}
  474 +
  475 +void SrsConfig::unsubscribe(SrsReloadHandler* handler)
  476 +{
  477 + std::vector<SrsReloadHandler*>::iterator it;
  478 +
  479 + it = std::find(subscribes.begin(), subscribes.end(), handler);
  480 + if (it == subscribes.end()) {
  481 + return;
  482 + }
  483 +
  484 + subscribes.erase(it);
  485 +}
  486 +
425 // see: ngx_get_options 487 // see: ngx_get_options
426 -int Config::parse_options(int argc, char** argv) 488 +int SrsConfig::parse_options(int argc, char** argv)
427 { 489 {
428 int ret = ERROR_SUCCESS; 490 int ret = ERROR_SUCCESS;
429 491
@@ -438,33 +500,23 @@ int Config::parse_options(int argc, char** argv) @@ -438,33 +500,23 @@ int Config::parse_options(int argc, char** argv)
438 } 500 }
439 501
440 if (show_version) { 502 if (show_version) {
441 - fprintf(stderr, "%s\n", RTMP_SIG_SRS_VERSION); 503 + printf("%s\n", RTMP_SIG_SRS_VERSION);
442 } 504 }
443 505
444 if (show_help || show_version) { 506 if (show_help || show_version) {
445 exit(0); 507 exit(0);
446 } 508 }
447 509
448 - if (!config_file) {  
449 - fprintf(stderr, "config file not specified, see help: %s -h\n", argv[0]);  
450 - return ERROR_SYSTEM_CONFIG_INVALID;  
451 - }  
452 -  
453 - if ((ret = root->parse(config_file)) != ERROR_SUCCESS) { 510 + if (config_file.empty()) {
  511 + ret = ERROR_SYSTEM_CONFIG_INVALID;
  512 + srs_error("config file not specified, see help: %s -h, ret=%d", argv[0], ret);
454 return ret; 513 return ret;
455 } 514 }
456 -  
457 - SrsConfDirective* conf = NULL;  
458 - if ((conf = get_listen()) == NULL || conf->args.size() == 0) {  
459 - fprintf(stderr, "line %d: conf error, "  
460 - "directive \"listen\" is empty\n", conf? conf->conf_line:0);  
461 - return ERROR_SYSTEM_CONFIG_INVALID;  
462 - }  
463 -  
464 - return ret; 515 +
  516 + return parse_file(config_file.c_str());
465 } 517 }
466 518
467 -SrsConfDirective* Config::get_vhost(std::string vhost) 519 +SrsConfDirective* SrsConfig::get_vhost(std::string vhost)
468 { 520 {
469 srs_assert(root); 521 srs_assert(root);
470 522
@@ -487,7 +539,7 @@ SrsConfDirective* Config::get_vhost(std::string vhost) @@ -487,7 +539,7 @@ SrsConfDirective* Config::get_vhost(std::string vhost)
487 return NULL; 539 return NULL;
488 } 540 }
489 541
490 -SrsConfDirective* Config::get_gop_cache(std::string vhost) 542 +SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost)
491 { 543 {
492 SrsConfDirective* conf = get_vhost(vhost); 544 SrsConfDirective* conf = get_vhost(vhost);
493 545
@@ -498,7 +550,7 @@ SrsConfDirective* Config::get_gop_cache(std::string vhost) @@ -498,7 +550,7 @@ SrsConfDirective* Config::get_gop_cache(std::string vhost)
498 return conf->get("gop_cache"); 550 return conf->get("gop_cache");
499 } 551 }
500 552
501 -SrsConfDirective* Config::get_refer(std::string vhost) 553 +SrsConfDirective* SrsConfig::get_refer(std::string vhost)
502 { 554 {
503 SrsConfDirective* conf = get_vhost(vhost); 555 SrsConfDirective* conf = get_vhost(vhost);
504 556
@@ -509,7 +561,7 @@ SrsConfDirective* Config::get_refer(std::string vhost) @@ -509,7 +561,7 @@ SrsConfDirective* Config::get_refer(std::string vhost)
509 return conf->get("refer"); 561 return conf->get("refer");
510 } 562 }
511 563
512 -SrsConfDirective* Config::get_refer_play(std::string vhost) 564 +SrsConfDirective* SrsConfig::get_refer_play(std::string vhost)
513 { 565 {
514 SrsConfDirective* conf = get_vhost(vhost); 566 SrsConfDirective* conf = get_vhost(vhost);
515 567
@@ -520,7 +572,7 @@ SrsConfDirective* Config::get_refer_play(std::string vhost) @@ -520,7 +572,7 @@ SrsConfDirective* Config::get_refer_play(std::string vhost)
520 return conf->get("refer_play"); 572 return conf->get("refer_play");
521 } 573 }
522 574
523 -SrsConfDirective* Config::get_refer_publish(std::string vhost) 575 +SrsConfDirective* SrsConfig::get_refer_publish(std::string vhost)
524 { 576 {
525 SrsConfDirective* conf = get_vhost(vhost); 577 SrsConfDirective* conf = get_vhost(vhost);
526 578
@@ -531,26 +583,52 @@ SrsConfDirective* Config::get_refer_publish(std::string vhost) @@ -531,26 +583,52 @@ SrsConfDirective* Config::get_refer_publish(std::string vhost)
531 return conf->get("refer_publish"); 583 return conf->get("refer_publish");
532 } 584 }
533 585
534 -SrsConfDirective* Config::get_listen() 586 +SrsConfDirective* SrsConfig::get_listen()
535 { 587 {
536 return root->get("listen"); 588 return root->get("listen");
537 } 589 }
538 590
539 -SrsConfDirective* Config::get_chunk_size() 591 +SrsConfDirective* SrsConfig::get_chunk_size()
540 { 592 {
541 return root->get("chunk_size"); 593 return root->get("chunk_size");
542 } 594 }
543 595
544 -int Config::parse_argv(int& i, char** argv) 596 +int SrsConfig::parse_file(const char* filename)
  597 +{
  598 + int ret = ERROR_SUCCESS;
  599 +
  600 + config_file = filename;
  601 +
  602 + if (config_file.empty()) {
  603 + return ERROR_SYSTEM_CONFIG_INVALID;
  604 + }
  605 +
  606 + if ((ret = root->parse(config_file.c_str())) != ERROR_SUCCESS) {
  607 + return ret;
  608 + }
  609 +
  610 + SrsConfDirective* conf = NULL;
  611 + if ((conf = get_listen()) == NULL || conf->args.size() == 0) {
  612 + ret = ERROR_SYSTEM_CONFIG_INVALID;
  613 + srs_error("line %d: conf error, "
  614 + "directive \"listen\" is empty, ret=%d", (conf? conf->conf_line:0), ret);
  615 + return ret;
  616 + }
  617 +
  618 + return ret;
  619 +}
  620 +
  621 +int SrsConfig::parse_argv(int& i, char** argv)
545 { 622 {
546 int ret = ERROR_SUCCESS; 623 int ret = ERROR_SUCCESS;
547 624
548 char* p = argv[i]; 625 char* p = argv[i];
549 626
550 if (*p++ != '-') { 627 if (*p++ != '-') {
551 - fprintf(stderr, "invalid options(index=%d, value=%s), "  
552 - "must starts with -, see help: %s -h\n", i, argv[i], argv[0]);  
553 - return ERROR_SYSTEM_CONFIG_INVALID; 628 + ret = ERROR_SYSTEM_CONFIG_INVALID;
  629 + srs_error("invalid options(index=%d, value=%s), "
  630 + "must starts with -, see help: %s -h, ret=%d", i, argv[i], argv[0], ret);
  631 + return ret;
554 } 632 }
555 633
556 while (*p) { 634 while (*p) {
@@ -572,20 +650,22 @@ int Config::parse_argv(int& i, char** argv) @@ -572,20 +650,22 @@ int Config::parse_argv(int& i, char** argv)
572 config_file = argv[i]; 650 config_file = argv[i];
573 return ret; 651 return ret;
574 } 652 }
575 - fprintf(stderr, "option \"-c\" requires parameter\n");  
576 - return ERROR_SYSTEM_CONFIG_INVALID; 653 + ret = ERROR_SYSTEM_CONFIG_INVALID;
  654 + srs_error("option \"-c\" requires parameter, ret=%d", ret);
  655 + return ret;
577 default: 656 default:
578 - fprintf(stderr, "invalid option: \"%c\", see help: %s -h\n", *(p - 1), argv[0]);  
579 - return ERROR_SYSTEM_CONFIG_INVALID; 657 + ret = ERROR_SYSTEM_CONFIG_INVALID;
  658 + srs_error("invalid option: \"%c\", see help: %s -h, ret=%d", *(p - 1), argv[0], ret);
  659 + return ret;
580 } 660 }
581 } 661 }
582 662
583 return ret; 663 return ret;
584 } 664 }
585 665
586 -void Config::print_help(char** argv) 666 +void SrsConfig::print_help(char** argv)
587 { 667 {
588 - fprintf(stderr, RTMP_SIG_SRS_NAME" "RTMP_SIG_SRS_VERSION 668 + printf(RTMP_SIG_SRS_NAME" "RTMP_SIG_SRS_VERSION
589 " Copyright (c) 2013 winlin\n" 669 " Copyright (c) 2013 winlin\n"
590 "Usage: %s [-h?vV] [-c <filename>]\n" 670 "Usage: %s [-h?vV] [-c <filename>]\n"
591 "\n" 671 "\n"
@@ -600,3 +680,39 @@ void Config::print_help(char** argv) @@ -600,3 +680,39 @@ void Config::print_help(char** argv)
600 argv[0]); 680 argv[0]);
601 } 681 }
602 682
  683 +bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b)
  684 +{
  685 + if (!a || !b) {
  686 + return false;
  687 + }
  688 +
  689 + if (a->name != b->name) {
  690 + return false;
  691 + }
  692 +
  693 + if (a->args.size() != b->args.size()) {
  694 + return false;
  695 + }
  696 +
  697 + for (int i = 0; i < (int)a->args.size(); i++) {
  698 + if (a->args.at(i) != b->args.at(i)) {
  699 + return false;
  700 + }
  701 + }
  702 +
  703 + if (a->directives.size() != b->directives.size()) {
  704 + return false;
  705 + }
  706 +
  707 + for (int i = 0; i < (int)a->directives.size(); i++) {
  708 + SrsConfDirective* a0 = a->at(i);
  709 + SrsConfDirective* b0 = b->at(i);
  710 +
  711 + if (!srs_directive_equals(a0, b0)) {
  712 + return false;
  713 + }
  714 + }
  715 +
  716 + return true;
  717 +}
  718 +
@@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 #include <vector> 32 #include <vector>
33 #include <string> 33 #include <string>
34 34
  35 +#include <srs_core_reload.hpp>
  36 +
35 // default vhost for rtmp 37 // default vhost for rtmp
36 #define RTMP_VHOST_DEFAULT "__defaultVhost__" 38 #define RTMP_VHOST_DEFAULT "__defaultVhost__"
37 39
@@ -84,16 +86,21 @@ public: @@ -84,16 +86,21 @@ public:
84 /** 86 /**
85 * the config parser. 87 * the config parser.
86 */ 88 */
87 -class Config 89 +class SrsConfig
88 { 90 {
89 private: 91 private:
90 bool show_help; 92 bool show_help;
91 bool show_version; 93 bool show_version;
92 - char* config_file; 94 + std::string config_file;
93 SrsConfDirective* root; 95 SrsConfDirective* root;
  96 + std::vector<SrsReloadHandler*> subscribes;
  97 +public:
  98 + SrsConfig();
  99 + virtual ~SrsConfig();
94 public: 100 public:
95 - Config();  
96 - virtual ~Config(); 101 + virtual int reload();
  102 + virtual void subscribe(SrsReloadHandler* handler);
  103 + virtual void unsubscribe(SrsReloadHandler* handler);
97 public: 104 public:
98 virtual int parse_options(int argc, char** argv); 105 virtual int parse_options(int argc, char** argv);
99 virtual SrsConfDirective* get_vhost(std::string vhost); 106 virtual SrsConfDirective* get_vhost(std::string vhost);
@@ -104,11 +111,17 @@ public: @@ -104,11 +111,17 @@ public:
104 virtual SrsConfDirective* get_listen(); 111 virtual SrsConfDirective* get_listen();
105 virtual SrsConfDirective* get_chunk_size(); 112 virtual SrsConfDirective* get_chunk_size();
106 private: 113 private:
  114 + virtual int parse_file(const char* filename);
107 virtual int parse_argv(int& i, char** argv); 115 virtual int parse_argv(int& i, char** argv);
108 virtual void print_help(char** argv); 116 virtual void print_help(char** argv);
109 }; 117 };
110 118
  119 +/**
  120 +* deep compare directive.
  121 +*/
  122 +bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b);
  123 +
111 // global config 124 // global config
112 -extern Config* config; 125 +extern SrsConfig* config;
113 126
114 #endif 127 #endif
@@ -36,8 +36,13 @@ SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd) @@ -36,8 +36,13 @@ SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd)
36 SrsConnection::~SrsConnection() 36 SrsConnection::~SrsConnection()
37 { 37 {
38 if (stfd) { 38 if (stfd) {
  39 + int fd = st_netfd_fileno(stfd);
39 st_netfd_close(stfd); 40 st_netfd_close(stfd);
40 stfd = NULL; 41 stfd = NULL;
  42 +
  43 + // st does not close it sometimes,
  44 + // close it manually.
  45 + close(fd);
41 } 46 }
42 } 47 }
43 48
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <srs_core_reload.hpp>
  25 +
  26 +#include <srs_core_error.hpp>
  27 +
  28 +SrsReloadHandler::SrsReloadHandler()
  29 +{
  30 +}
  31 +
  32 +SrsReloadHandler::~SrsReloadHandler()
  33 +{
  34 +}
  35 +
  36 +int SrsReloadHandler::on_reload_listen()
  37 +{
  38 + int ret = ERROR_SUCCESS;
  39 + return ret;
  40 +}
  41 +
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#ifndef SRS_CORE_RELOAD_HPP
  25 +#define SRS_CORE_RELOAD_HPP
  26 +
  27 +/*
  28 +#include <srs_core_reload.hpp>
  29 +*/
  30 +#include <srs_core.hpp>
  31 +
  32 +/**
  33 +* the handler for config reload.
  34 +*/
  35 +class SrsReloadHandler
  36 +{
  37 +public:
  38 + SrsReloadHandler();
  39 + virtual ~SrsReloadHandler();
  40 +public:
  41 + virtual int on_reload_listen();
  42 +};
  43 +
  44 +#endif
@@ -26,6 +26,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -26,6 +26,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #include <sys/types.h> 26 #include <sys/types.h>
27 #include <sys/socket.h> 27 #include <sys/socket.h>
28 #include <arpa/inet.h> 28 #include <arpa/inet.h>
  29 +#include <signal.h>
29 30
30 #include <algorithm> 31 #include <algorithm>
31 32
@@ -37,7 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -37,7 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 #include <srs_core_config.hpp> 38 #include <srs_core_config.hpp>
38 39
39 #define SERVER_LISTEN_BACKLOG 10 40 #define SERVER_LISTEN_BACKLOG 10
40 -#define SRS_TIME_RESOLUTION_MS 1000 41 +#define SRS_TIME_RESOLUTION_MS 500
41 42
42 SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type) 43 SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type)
43 { 44 {
@@ -47,6 +48,9 @@ SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type) @@ -47,6 +48,9 @@ SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type)
47 port = 0; 48 port = 0;
48 server = _server; 49 server = _server;
49 type = _type; 50 type = _type;
  51 +
  52 + tid = NULL;
  53 + loop = false;
50 } 54 }
51 55
52 SrsListener::~SrsListener() 56 SrsListener::~SrsListener()
@@ -55,6 +59,17 @@ SrsListener::~SrsListener() @@ -55,6 +59,17 @@ SrsListener::~SrsListener()
55 st_netfd_close(stfd); 59 st_netfd_close(stfd);
56 stfd = NULL; 60 stfd = NULL;
57 } 61 }
  62 +
  63 + if (tid) {
  64 + loop = false;
  65 + st_thread_interrupt(tid);
  66 + st_thread_join(tid, NULL);
  67 + tid = NULL;
  68 + }
  69 +
  70 + // st does not close it sometimes,
  71 + // close it manually.
  72 + close(fd);
58 } 73 }
59 74
60 int SrsListener::listen(int _port) 75 int SrsListener::listen(int _port)
@@ -103,7 +118,7 @@ int SrsListener::listen(int _port) @@ -103,7 +118,7 @@ int SrsListener::listen(int _port)
103 } 118 }
104 srs_verbose("st open socket success. fd=%d", fd); 119 srs_verbose("st open socket success. fd=%d", fd);
105 120
106 - if (st_thread_create(listen_thread, this, 0, 0) == NULL) { 121 + if ((tid = st_thread_create(listen_thread, this, 1, 0)) == NULL) {
107 ret = ERROR_ST_CREATE_LISTEN_THREAD; 122 ret = ERROR_ST_CREATE_LISTEN_THREAD;
108 srs_error("st_thread_create listen thread error. ret=%d", ret); 123 srs_error("st_thread_create listen thread error. ret=%d", ret);
109 return ret; 124 return ret;
@@ -122,7 +137,7 @@ void SrsListener::listen_cycle() @@ -122,7 +137,7 @@ void SrsListener::listen_cycle()
122 log_context->generate_id(); 137 log_context->generate_id();
123 srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd); 138 srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd);
124 139
125 - while (true) { 140 + while (loop) {
126 st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT); 141 st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
127 142
128 if(client_stfd == NULL){ 143 if(client_stfd == NULL){
@@ -146,6 +161,7 @@ void* SrsListener::listen_thread(void* arg) @@ -146,6 +161,7 @@ void* SrsListener::listen_thread(void* arg)
146 SrsListener* obj = (SrsListener*)arg; 161 SrsListener* obj = (SrsListener*)arg;
147 srs_assert(obj != NULL); 162 srs_assert(obj != NULL);
148 163
  164 + obj->loop = true;
149 obj->listen_cycle(); 165 obj->listen_cycle();
150 166
151 return NULL; 167 return NULL;
@@ -153,10 +169,15 @@ void* SrsListener::listen_thread(void* arg) @@ -153,10 +169,15 @@ void* SrsListener::listen_thread(void* arg)
153 169
154 SrsServer::SrsServer() 170 SrsServer::SrsServer()
155 { 171 {
  172 + signal_reload = false;
  173 +
  174 + config->subscribe(this);
156 } 175 }
157 176
158 SrsServer::~SrsServer() 177 SrsServer::~SrsServer()
159 { 178 {
  179 + config->unsubscribe(this);
  180 +
160 if (true) { 181 if (true) {
161 std::vector<SrsConnection*>::iterator it; 182 std::vector<SrsConnection*>::iterator it;
162 for (it = conns.begin(); it != conns.end(); ++it) { 183 for (it = conns.begin(); it != conns.end(); ++it) {
@@ -166,14 +187,7 @@ SrsServer::~SrsServer() @@ -166,14 +187,7 @@ SrsServer::~SrsServer()
166 conns.clear(); 187 conns.clear();
167 } 188 }
168 189
169 - if (true) {  
170 - std::vector<SrsListener*>::iterator it;  
171 - for (it = listeners.begin(); it != listeners.end(); ++it) {  
172 - SrsListener* listener = *it;  
173 - srs_freep(listener);  
174 - }  
175 - listeners.clear();  
176 - } 190 + close_listeners();
177 } 191 }
178 192
179 int SrsServer::initialize() 193 int SrsServer::initialize()
@@ -212,6 +226,8 @@ int SrsServer::listen() @@ -212,6 +226,8 @@ int SrsServer::listen()
212 conf = config->get_listen(); 226 conf = config->get_listen();
213 srs_assert(conf); 227 srs_assert(conf);
214 228
  229 + close_listeners();
  230 +
215 for (int i = 0; i < (int)conf->args.size(); i++) { 231 for (int i = 0; i < (int)conf->args.size(); i++) {
216 SrsListener* listener = new SrsListener(this, SrsListenerStream); 232 SrsListener* listener = new SrsListener(this, SrsListenerStream);
217 listeners.push_back(listener); 233 listeners.push_back(listener);
@@ -234,6 +250,17 @@ int SrsServer::cycle() @@ -234,6 +250,17 @@ int SrsServer::cycle()
234 while (true) { 250 while (true) {
235 st_usleep(SRS_TIME_RESOLUTION_MS * 1000); 251 st_usleep(SRS_TIME_RESOLUTION_MS * 1000);
236 srs_update_system_time_ms(); 252 srs_update_system_time_ms();
  253 +
  254 + if (signal_reload) {
  255 + signal_reload = false;
  256 + srs_info("get signal reload, to reload the config.");
  257 +
  258 + if ((ret = config->reload()) != ERROR_SUCCESS) {
  259 + srs_error("reload config failed. ret=%d", ret);
  260 + return ret;
  261 + }
  262 + srs_trace("reload config success.");
  263 + }
237 } 264 }
238 265
239 return ret; 266 return ret;
@@ -254,6 +281,23 @@ void SrsServer::remove(SrsConnection* conn) @@ -254,6 +281,23 @@ void SrsServer::remove(SrsConnection* conn)
254 srs_freep(conn); 281 srs_freep(conn);
255 } 282 }
256 283
  284 +void SrsServer::on_signal(int signo)
  285 +{
  286 + if (signo == SIGNAL_RELOAD) {
  287 + signal_reload = true;
  288 + }
  289 +}
  290 +
  291 +void SrsServer::close_listeners()
  292 +{
  293 + std::vector<SrsListener*>::iterator it;
  294 + for (it = listeners.begin(); it != listeners.end(); ++it) {
  295 + SrsListener* listener = *it;
  296 + srs_freep(listener);
  297 + }
  298 + listeners.clear();
  299 +}
  300 +
257 int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) 301 int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
258 { 302 {
259 int ret = ERROR_SUCCESS; 303 int ret = ERROR_SUCCESS;
@@ -279,3 +323,10 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) @@ -279,3 +323,10 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
279 return ret; 323 return ret;
280 } 324 }
281 325
  326 +int SrsServer::on_reload_listen()
  327 +{
  328 + return listen();
  329 +}
  330 +
  331 +SrsServer server;
  332 +
@@ -34,6 +34,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -34,6 +34,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 34
35 #include <st.h> 35 #include <st.h>
36 36
  37 +#include <srs_core_reload.hpp>
  38 +
37 class SrsServer; 39 class SrsServer;
38 class SrsConnection; 40 class SrsConnection;
39 41
@@ -52,6 +54,8 @@ private: @@ -52,6 +54,8 @@ private:
52 st_netfd_t stfd; 54 st_netfd_t stfd;
53 int port; 55 int port;
54 SrsServer* server; 56 SrsServer* server;
  57 + st_thread_t tid;
  58 + bool loop;
55 public: 59 public:
56 SrsListener(SrsServer* _server, SrsListenerType _type); 60 SrsListener(SrsServer* _server, SrsListenerType _type);
57 virtual ~SrsListener(); 61 virtual ~SrsListener();
@@ -62,12 +66,13 @@ private: @@ -62,12 +66,13 @@ private:
62 static void* listen_thread(void* arg); 66 static void* listen_thread(void* arg);
63 }; 67 };
64 68
65 -class SrsServer 69 +class SrsServer : public SrsReloadHandler
66 { 70 {
67 friend class SrsListener; 71 friend class SrsListener;
68 private: 72 private:
69 std::vector<SrsConnection*> conns; 73 std::vector<SrsConnection*> conns;
70 std::vector<SrsListener*> listeners; 74 std::vector<SrsListener*> listeners;
  75 + bool signal_reload;
71 public: 76 public:
72 SrsServer(); 77 SrsServer();
73 virtual ~SrsServer(); 78 virtual ~SrsServer();
@@ -76,8 +81,14 @@ public: @@ -76,8 +81,14 @@ public:
76 virtual int listen(); 81 virtual int listen();
77 virtual int cycle(); 82 virtual int cycle();
78 virtual void remove(SrsConnection* conn); 83 virtual void remove(SrsConnection* conn);
  84 + virtual void on_signal(int signo);
79 private: 85 private:
  86 + virtual void close_listeners();
80 virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd); 87 virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd);
  88 +public:
  89 + virtual int on_reload_listen();
81 }; 90 };
  91 +
  92 +extern SrsServer server;
82 93
83 #endif 94 #endif
@@ -27,16 +27,23 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -27,16 +27,23 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include <srs_core_config.hpp> 27 #include <srs_core_config.hpp>
28 28
29 #include <stdlib.h> 29 #include <stdlib.h>
  30 +#include <signal.h>
  31 +
  32 +void handler(int signo)
  33 +{
  34 + srs_trace("get a signal, signo=%d", signo);
  35 + server.on_signal(signo);
  36 +}
30 37
31 int main(int argc, char** argv){ 38 int main(int argc, char** argv){
32 int ret = ERROR_SUCCESS; 39 int ret = ERROR_SUCCESS;
33 40
  41 + signal(SIGNAL_RELOAD, handler);
  42 +
34 if ((ret = config->parse_options(argc, argv)) != ERROR_SUCCESS) { 43 if ((ret = config->parse_options(argc, argv)) != ERROR_SUCCESS) {
35 return ret; 44 return ret;
36 } 45 }
37 46
38 - SrsServer server;  
39 -  
40 if ((ret = server.initialize()) != ERROR_SUCCESS) { 47 if ((ret = server.initialize()) != ERROR_SUCCESS) {
41 return ret; 48 return ret;
42 } 49 }
@@ -10,6 +10,8 @@ file @@ -10,6 +10,8 @@ file
10 ..\core\srs_core_auto_free.cpp, 10 ..\core\srs_core_auto_free.cpp,
11 ..\core\srs_core_server.hpp, 11 ..\core\srs_core_server.hpp,
12 ..\core\srs_core_server.cpp, 12 ..\core\srs_core_server.cpp,
  13 + ..\core\srs_core_reload.hpp,
  14 + ..\core\srs_core_reload.cpp,
13 ..\core\srs_core_config.hpp, 15 ..\core\srs_core_config.hpp,
14 ..\core\srs_core_config.cpp, 16 ..\core\srs_core_config.cpp,
15 ..\core\srs_core_refer.hpp, 17 ..\core\srs_core_refer.hpp,