check_config函数分析
int SrsConfig::check_config() { int ret = ERROR_SUCCESS; srs_trace("srs checking config..."); //////////////////////////////////////////////////////////////////////// // check empty //////////////////////////////////////////////////////////////////////// if (root->directives.size() == 0) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("conf is empty, ret=%d", ret); return ret; } //////////////////////////////////////////////////////////////////////// // check root directives. //////////////////////////////////////////////////////////////////////// for (int i = 0; i < (int)root->directives.size(); i++) { SrsConfDirective* conf = root->at(i); std::string n = conf->name; if (n != "listen" && n != "pid" && n != "chunk_size" && n != "ff_log_dir" && n != "srs_log_tank" && n != "srs_log_level" && n != "srs_log_file" && n != "max_connections" && n != "daemon" && n != "heartbeat" && n != "http_api" && n != "stats" && n != "vhost" && n != "pithy_print_ms" && n != "http_stream" && n != "http_server" && n != "stream_caster" && n != "utc_time" && n != "work_dir" && n != "asprocess" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported directive %s, ret=%d", n.c_str(), ret); return ret; } } if (true) { SrsConfDirective* conf = get_http_api(); for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "crossdomain") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported http_api directive %s, ret=%d", n.c_str(), ret); return ret; } } } if (true) { SrsConfDirective* conf = get_http_stream(); for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "dir") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported http_stream directive %s, ret=%d", n.c_str(), ret); return ret; } } } if (true) { SrsConfDirective* conf = get_heartbeart(); for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "enabled" && n != "interval" && n != "url" && n != "device_id" && n != "summaries" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported heartbeat directive %s, ret=%d", n.c_str(), ret); return ret; } } } if (true) { SrsConfDirective* conf = get_stats(); for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "network" && n != "disk") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported stats directive %s, ret=%d", n.c_str(), ret); return ret; } } } //////////////////////////////////////////////////////////////////////// // check listen for rtmp. //////////////////////////////////////////////////////////////////////// if (true) { vector<string> listens = get_listens(); if (listens.size() <= 0) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive \"listen\" is empty, ret=%d", ret); return ret; } for (int i = 0; i < (int)listens.size(); i++) { string port = listens[i]; if (port.empty() || ::atoi(port.c_str()) <= 0) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive listen invalid, port=%s, ret=%d", port.c_str(), ret); return ret; } } } //////////////////////////////////////////////////////////////////////// // check max connections //////////////////////////////////////////////////////////////////////// if (get_max_connections() <= 0) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive max_connections invalid, max_connections=%d, ret=%d", get_max_connections(), ret); return ret; } // check max connections of system limits if (true) { int nb_consumed_fds = (int)get_listens().size(); if (!get_http_api_listen().empty()) { nb_consumed_fds++; } if (!get_http_stream_listen().empty()) { nb_consumed_fds++; } if (get_log_tank_file()) { nb_consumed_fds++; } // 0, 1, 2 for stdin, stdout and stderr. nb_consumed_fds += 3; int nb_connections = get_max_connections(); int nb_total = nb_connections + nb_consumed_fds; int max_open_files = (int)sysconf(_SC_OPEN_MAX); int nb_canbe = max_open_files - nb_consumed_fds - 1; // for each play connections, we open a pipe(2fds) to convert SrsConsumver to io, // refine performance, @see: https://github.com/ossrs/srs/issues/194 if (nb_total >= max_open_files) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("invalid max_connections=%d, required=%d, system limit to %d, " "total=%d(max_connections=%d, nb_consumed_fds=%d), ret=%d. " "you can change max_connections from %d to %d, or " "you can login as root and set the limit: ulimit -HSn %d", nb_connections, nb_total + 1, max_open_files, nb_total, nb_connections, nb_consumed_fds, ret, nb_connections, nb_canbe, nb_total + 1); return ret; } } //////////////////////////////////////////////////////////////////////// // check heartbeat //////////////////////////////////////////////////////////////////////// if (get_heartbeat_interval() <= 0) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive heartbeat interval invalid, interval=%"PRId64", ret=%d", get_heartbeat_interval(), ret); return ret; } //////////////////////////////////////////////////////////////////////// // check stats //////////////////////////////////////////////////////////////////////// if (get_stats_network() < 0) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive stats network invalid, network=%d, ret=%d", get_stats_network(), ret); return ret; } if (true) { vector<std::string> ips = srs_get_local_ipv4_ips(); int index = get_stats_network(); if (index >= (int)ips.size()) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("stats network invalid, total local ip count=%d, index=%d, ret=%d", (int)ips.size(), index, ret); return ret; } srs_warn("stats network use index=%d, ip=%s", index, ips.at(index).c_str()); } if (true) { SrsConfDirective* conf = get_stats_disk_device(); if (conf == NULL || (int)conf->args.size() <= 0) { srs_warn("stats disk not configed, disk iops disabled."); } else { string disks; for (int i = 0; i < (int)conf->args.size(); i++) { disks += conf->args.at(i); disks += " "; } srs_warn("stats disk list: %s", disks.c_str()); } } //////////////////////////////////////////////////////////////////////// // check http api //////////////////////////////////////////////////////////////////////// if (get_http_api_listen().empty()) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive http_api listen invalid, listen=%s, ret=%d", get_http_api_listen().c_str(), ret); return ret; } //////////////////////////////////////////////////////////////////////// // check http stream //////////////////////////////////////////////////////////////////////// if (get_http_stream_listen().empty()) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive http_stream listen invalid, listen=%s, ret=%d", get_http_stream_listen().c_str(), ret); return ret; } //////////////////////////////////////////////////////////////////////// // check log name and level //////////////////////////////////////////////////////////////////////// if (true) { std::string log_filename = this->get_log_file(); if (get_log_tank_file() && log_filename.empty()) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("must specifies the file to write log to. ret=%d", ret); return ret; } if (get_log_tank_file()) { srs_trace("write log to file %s", log_filename.c_str()); srs_trace("you can: tailf %s", log_filename.c_str()); srs_trace("@see: %s", SRS_WIKI_URL_LOG); } else { srs_trace("write log to console"); } } //////////////////////////////////////////////////////////////////////// // check features //////////////////////////////////////////////////////////////////////// #ifndef SRS_AUTO_HTTP_SERVER if (get_http_stream_enabled()) { srs_warn("http_stream is disabled by configure"); } #endif #ifndef SRS_AUTO_HTTP_API if (get_http_api_enabled()) { srs_warn("http_api is disabled by configure"); } #endif vector<SrsConfDirective*> stream_casters = get_stream_casters(); for (int n = 0; n < (int)stream_casters.size(); n++) { SrsConfDirective* stream_caster = stream_casters[n]; for (int i = 0; stream_caster && i < (int)stream_caster->directives.size(); i++) { SrsConfDirective* conf = stream_caster->at(i); string n = conf->name; if (n != "enabled" && n != "caster" && n != "output" && n != "listen" && n != "rtp_port_min" && n != "rtp_port_max" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported stream_caster directive %s, ret=%d", n.c_str(), ret); return ret; } } } vector<SrsConfDirective*> vhosts; get_vhosts(vhosts); for (int n = 0; n < (int)vhosts.size(); n++) { SrsConfDirective* vhost = vhosts[n]; for (int i = 0; vhost && i < (int)vhost->directives.size(); i++) { SrsConfDirective* conf = vhost->at(i); string n = conf->name; if (n != "enabled" && n != "chunk_size" && n != "mode" && n != "origin" && n != "token_traverse" && n != "vhost" && n != "dvr" && n != "ingest" && n != "hls" && n != "http_hooks" && n != "gop_cache" && n != "queue_length" && n != "refer" && n != "refer_publish" && n != "refer_play" && n != "forward" && n != "transcode" && n != "bandcheck" && n != "time_jitter" && n != "mix_correct" && n != "atc" && n != "atc_auto" && n != "debug_srs_upnode" && n != "mr" && n != "mw_latency" && n != "min_latency" && n != "publish" && n != "tcp_nodelay" && n != "send_min_interval" && n != "reduce_sequence_header" && n != "publish_1stpkt_timeout" && n != "publish_normal_timeout" && n != "security" && n != "http_remux" && n != "http" && n != "http_static" && n != "hds" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost directive %s, ret=%d", n.c_str(), ret); return ret; } // for each sub directives of vhost. if (n == "dvr") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "dvr_path" && m != "dvr_plan" && m != "dvr_duration" && m != "dvr_wait_keyframe" && m != "time_jitter" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost dvr directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "mr") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "latency" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost mr directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "publish") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "parse_sps" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost publish directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "ingest") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "input" && m != "ffmpeg" && m != "engine" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost ingest directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "http" || n == "http_static") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "mount" && m != "dir") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost http directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "http_remux") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "mount" && m != "fast_cache" && m != "hstrs") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost http_remux directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "hls") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "hls_entry_prefix" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error" && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_aof_ratio" && m != "hls_acodec" && m != "hls_vcodec" && m != "hls_m3u8_file" && m != "hls_ts_file" && m != "hls_ts_floor" && m != "hls_cleanup" && m != "hls_nb_notify" && m != "hls_wait_keyframe" && m != "hls_dispose" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost hls directive %s, ret=%d", m.c_str(), ret); return ret; } // TODO: FIXME: remove it in future. if (m == "hls_storage" || m == "hls_mount") { srs_warn("HLS RAM is removed from SRS2 to SRS3+, please read https://github.com/ossrs/srs/issues/513."); } } } else if (n == "http_hooks") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "on_connect" && m != "on_close" && m != "on_publish" && m != "on_unpublish" && m != "on_play" && m != "on_stop" && m != "on_dvr" && m != "on_hls" && m != "on_hls_notify" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost http_hooks directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "forward") { // TODO: FIXME: implements it. /*for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "vhost" && m != "refer") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost forward directive %s, ret=%d", m.c_str(), ret); return ret; } }*/ } else if (n == "security") { for (int j = 0; j < (int)conf->directives.size(); j++) { SrsConfDirective* security = conf->at(j); string m = security->name.c_str(); if (m != "enabled" && m != "deny" && m != "allow") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost security directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "transcode") { for (int j = 0; j < (int)conf->directives.size(); j++) { SrsConfDirective* trans = conf->at(j); string m = trans->name.c_str(); if (m != "enabled" && m != "ffmpeg" && m != "engine") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost transcode directive %s, ret=%d", m.c_str(), ret); return ret; } if (m == "engine") { for (int k = 0; k < (int)trans->directives.size(); k++) { string e = trans->at(k)->name; if (e != "enabled" && e != "vfilter" && e != "vcodec" && e != "vbitrate" && e != "vfps" && e != "vwidth" && e != "vheight" && e != "vthreads" && e != "vprofile" && e != "vpreset" && e != "vparams" && e != "acodec" && e != "abitrate" && e != "asample_rate" && e != "achannels" && e != "aparams" && e != "output" && e != "iformat" && e != "oformat" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost transcode engine directive %s, ret=%d", e.c_str(), ret); return ret; } } } } } else if (n == "bandcheck") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "key" && m != "interval" && m != "limit_kbps") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost bandcheck directive %s, ret=%d", m.c_str(), ret); return ret; } } } } } // check ingest id unique. for (int i = 0; i < (int)vhosts.size(); i++) { SrsConfDirective* vhost = vhosts[i]; std::vector<std::string> ids; for (int j = 0; j < (int)vhost->directives.size(); j++) { SrsConfDirective* conf = vhost->at(j); if (conf->name != "ingest") { continue; } std::string id = conf->arg0(); for (int k = 0; k < (int)ids.size(); k++) { if (id == ids.at(k)) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive \"ingest\" id duplicated, vhost=%s, id=%s, ret=%d", vhost->name.c_str(), id.c_str(), ret); return ret; } } ids.push_back(id); } } //////////////////////////////////////////////////////////////////////// // check chunk size //////////////////////////////////////////////////////////////////////// if (get_global_chunk_size() < SRS_CONSTS_RTMP_MIN_CHUNK_SIZE || get_global_chunk_size() > SRS_CONSTS_RTMP_MAX_CHUNK_SIZE ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive chunk_size invalid, chunk_size=%d, must in [%d, %d], ret=%d", get_global_chunk_size(), SRS_CONSTS_RTMP_MIN_CHUNK_SIZE, SRS_CONSTS_RTMP_MAX_CHUNK_SIZE, ret); return ret; } for (int i = 0; i < (int)vhosts.size(); i++) { SrsConfDirective* vhost = vhosts[i]; if (get_chunk_size(vhost->arg0()) < SRS_CONSTS_RTMP_MIN_CHUNK_SIZE || get_chunk_size(vhost->arg0()) > SRS_CONSTS_RTMP_MAX_CHUNK_SIZE ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive vhost %s chunk_size invalid, chunk_size=%d, must in [%d, %d], ret=%d", vhost->arg0().c_str(), get_chunk_size(vhost->arg0()), SRS_CONSTS_RTMP_MIN_CHUNK_SIZE, SRS_CONSTS_RTMP_MAX_CHUNK_SIZE, ret); return ret; } } for (int i = 0; i < (int)vhosts.size(); i++) { SrsConfDirective* vhost = vhosts[i]; srs_assert(vhost != NULL); #ifndef SRS_AUTO_DVR if (get_dvr_enabled(vhost->arg0())) { srs_warn("dvr of vhost %s is disabled by configure", vhost->arg0().c_str()); } #endif #ifndef SRS_AUTO_HLS if (get_hls_enabled(vhost->arg0())) { srs_warn("hls of vhost %s is disabled by configure", vhost->arg0().c_str()); } #endif #ifndef SRS_AUTO_HTTP_CALLBACK if (get_vhost_http_hooks_enabled(vhost->arg0())) { srs_warn("http_hooks of vhost %s is disabled by configure", vhost->arg0().c_str()); } #endif #ifndef SRS_AUTO_TRANSCODE if (get_transcode_enabled(get_transcode(vhost->arg0(), ""))) { srs_warn("transcode of vhost %s is disabled by configure", vhost->arg0().c_str()); } #endif #ifndef SRS_AUTO_INGEST vector<SrsConfDirective*> ingesters = get_ingesters(vhost->arg0()); for (int j = 0; j < (int)ingesters.size(); j++) { SrsConfDirective* ingest = ingesters[j]; if (get_ingest_enabled(ingest)) { srs_warn("ingest %s of vhost %s is disabled by configure", ingest->arg0().c_str(), vhost->arg0().c_str() ); } } #endif // TODO: FIXME: required http server when hls storage is ram or both. } // asprocess conflict with daemon if (get_asprocess() && get_deamon()) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("daemon conflict with asprocess, ret=%d", ret); return ret; } return ret; }
int SrsConfig::check_config() { int ret = ERROR_SUCCESS; srs_trace("srs checking config..."); //////////////////////////////////////////////////////////////////////// // check empty //////////////////////////////////////////////////////////////////////// if (root->directives.size() == 0) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("conf is empty, ret=%d", ret); return ret; } //////////////////////////////////////////////////////////////////////// // check root directives. //////////////////////////////////////////////////////////////////////// for (int i = 0; i < (int)root->directives.size(); i++) { SrsConfDirective* conf = root->at(i); std::string n = conf->name; if (n != "listen" && n != "pid" && n != "chunk_size" && n != "ff_log_dir" && n != "srs_log_tank" && n != "srs_log_level" && n != "srs_log_file" && n != "max_connections" && n != "daemon" && n != "heartbeat" && n != "http_api" && n != "stats" && n != "vhost" && n != "pithy_print_ms" && n != "http_stream" && n != "http_server" && n != "stream_caster" && n != "utc_time" && n != "work_dir" && n != "asprocess" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported directive %s, ret=%d", n.c_str(), ret); return ret; } } if (true) { SrsConfDirective* conf = get_http_api(); for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "crossdomain") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported http_api directive %s, ret=%d", n.c_str(), ret); return ret; } } } if (true) { SrsConfDirective* conf = get_http_stream(); for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "dir") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported http_stream directive %s, ret=%d", n.c_str(), ret); return ret; } } } if (true) { SrsConfDirective* conf = get_heartbeart(); for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "enabled" && n != "interval" && n != "url" && n != "device_id" && n != "summaries" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported heartbeat directive %s, ret=%d", n.c_str(), ret); return ret; } } } if (true) { SrsConfDirective* conf = get_stats(); for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "network" && n != "disk") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported stats directive %s, ret=%d", n.c_str(), ret); return ret; } } } //////////////////////////////////////////////////////////////////////// // check listen for rtmp. //////////////////////////////////////////////////////////////////////// if (true) { vector<string> listens = get_listens(); if (listens.size() <= 0) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive \"listen\" is empty, ret=%d", ret); return ret; } for (int i = 0; i < (int)listens.size(); i++) { string port = listens[i]; if (port.empty() || ::atoi(port.c_str()) <= 0) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive listen invalid, port=%s, ret=%d", port.c_str(), ret); return ret; } } } //////////////////////////////////////////////////////////////////////// // check max connections //////////////////////////////////////////////////////////////////////// if (get_max_connections() <= 0) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive max_connections invalid, max_connections=%d, ret=%d", get_max_connections(), ret); return ret; } // check max connections of system limits if (true) { int nb_consumed_fds = (int)get_listens().size(); if (!get_http_api_listen().empty()) { nb_consumed_fds++; } if (!get_http_stream_listen().empty()) { nb_consumed_fds++; } if (get_log_tank_file()) { nb_consumed_fds++; } // 0, 1, 2 for stdin, stdout and stderr. nb_consumed_fds += 3; int nb_connections = get_max_connections(); int nb_total = nb_connections + nb_consumed_fds; int max_open_files = (int)sysconf(_SC_OPEN_MAX); int nb_canbe = max_open_files - nb_consumed_fds - 1; // for each play connections, we open a pipe(2fds) to convert SrsConsumver to io, // refine performance, @see: https://github.com/ossrs/srs/issues/194 if (nb_total >= max_open_files) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("invalid max_connections=%d, required=%d, system limit to %d, " "total=%d(max_connections=%d, nb_consumed_fds=%d), ret=%d. " "you can change max_connections from %d to %d, or " "you can login as root and set the limit: ulimit -HSn %d", nb_connections, nb_total + 1, max_open_files, nb_total, nb_connections, nb_consumed_fds, ret, nb_connections, nb_canbe, nb_total + 1); return ret; } } //////////////////////////////////////////////////////////////////////// // check heartbeat //////////////////////////////////////////////////////////////////////// if (get_heartbeat_interval() <= 0) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive heartbeat interval invalid, interval=%"PRId64", ret=%d", get_heartbeat_interval(), ret); return ret; } //////////////////////////////////////////////////////////////////////// // check stats //////////////////////////////////////////////////////////////////////// if (get_stats_network() < 0) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive stats network invalid, network=%d, ret=%d", get_stats_network(), ret); return ret; } if (true) { vector<std::string> ips = srs_get_local_ipv4_ips(); int index = get_stats_network(); if (index >= (int)ips.size()) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("stats network invalid, total local ip count=%d, index=%d, ret=%d", (int)ips.size(), index, ret); return ret; } srs_warn("stats network use index=%d, ip=%s", index, ips.at(index).c_str()); } if (true) { SrsConfDirective* conf = get_stats_disk_device(); if (conf == NULL || (int)conf->args.size() <= 0) { srs_warn("stats disk not configed, disk iops disabled."); } else { string disks; for (int i = 0; i < (int)conf->args.size(); i++) { disks += conf->args.at(i); disks += " "; } srs_warn("stats disk list: %s", disks.c_str()); } } //////////////////////////////////////////////////////////////////////// // check http api //////////////////////////////////////////////////////////////////////// if (get_http_api_listen().empty()) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive http_api listen invalid, listen=%s, ret=%d", get_http_api_listen().c_str(), ret); return ret; } //////////////////////////////////////////////////////////////////////// // check http stream //////////////////////////////////////////////////////////////////////// if (get_http_stream_listen().empty()) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive http_stream listen invalid, listen=%s, ret=%d", get_http_stream_listen().c_str(), ret); return ret; } //////////////////////////////////////////////////////////////////////// // check log name and level //////////////////////////////////////////////////////////////////////// if (true) { std::string log_filename = this->get_log_file(); if (get_log_tank_file() && log_filename.empty()) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("must specifies the file to write log to. ret=%d", ret); return ret; } if (get_log_tank_file()) { srs_trace("write log to file %s", log_filename.c_str()); srs_trace("you can: tailf %s", log_filename.c_str()); srs_trace("@see: %s", SRS_WIKI_URL_LOG); } else { srs_trace("write log to console"); } } //////////////////////////////////////////////////////////////////////// // check features //////////////////////////////////////////////////////////////////////// #ifndef SRS_AUTO_HTTP_SERVER if (get_http_stream_enabled()) { srs_warn("http_stream is disabled by configure"); } #endif #ifndef SRS_AUTO_HTTP_API if (get_http_api_enabled()) { srs_warn("http_api is disabled by configure"); } #endif vector<SrsConfDirective*> stream_casters = get_stream_casters(); for (int n = 0; n < (int)stream_casters.size(); n++) { SrsConfDirective* stream_caster = stream_casters[n]; for (int i = 0; stream_caster && i < (int)stream_caster->directives.size(); i++) { SrsConfDirective* conf = stream_caster->at(i); string n = conf->name; if (n != "enabled" && n != "caster" && n != "output" && n != "listen" && n != "rtp_port_min" && n != "rtp_port_max" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported stream_caster directive %s, ret=%d", n.c_str(), ret); return ret; } } } vector<SrsConfDirective*> vhosts; get_vhosts(vhosts); for (int n = 0; n < (int)vhosts.size(); n++) { SrsConfDirective* vhost = vhosts[n]; for (int i = 0; vhost && i < (int)vhost->directives.size(); i++) { SrsConfDirective* conf = vhost->at(i); string n = conf->name; if (n != "enabled" && n != "chunk_size" && n != "mode" && n != "origin" && n != "token_traverse" && n != "vhost" && n != "dvr" && n != "ingest" && n != "hls" && n != "http_hooks" && n != "gop_cache" && n != "queue_length" && n != "refer" && n != "refer_publish" && n != "refer_play" && n != "forward" && n != "transcode" && n != "bandcheck" && n != "time_jitter" && n != "mix_correct" && n != "atc" && n != "atc_auto" && n != "debug_srs_upnode" && n != "mr" && n != "mw_latency" && n != "min_latency" && n != "publish" && n != "tcp_nodelay" && n != "send_min_interval" && n != "reduce_sequence_header" && n != "publish_1stpkt_timeout" && n != "publish_normal_timeout" && n != "security" && n != "http_remux" && n != "http" && n != "http_static" && n != "hds" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost directive %s, ret=%d", n.c_str(), ret); return ret; } // for each sub directives of vhost. if (n == "dvr") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "dvr_path" && m != "dvr_plan" && m != "dvr_duration" && m != "dvr_wait_keyframe" && m != "time_jitter" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost dvr directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "mr") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "latency" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost mr directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "publish") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "parse_sps" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost publish directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "ingest") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "input" && m != "ffmpeg" && m != "engine" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost ingest directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "http" || n == "http_static") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "mount" && m != "dir") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost http directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "http_remux") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "mount" && m != "fast_cache" && m != "hstrs") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost http_remux directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "hls") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "hls_entry_prefix" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error" && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_aof_ratio" && m != "hls_acodec" && m != "hls_vcodec" && m != "hls_m3u8_file" && m != "hls_ts_file" && m != "hls_ts_floor" && m != "hls_cleanup" && m != "hls_nb_notify" && m != "hls_wait_keyframe" && m != "hls_dispose" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost hls directive %s, ret=%d", m.c_str(), ret); return ret; } // TODO: FIXME: remove it in future. if (m == "hls_storage" || m == "hls_mount") { srs_warn("HLS RAM is removed from SRS2 to SRS3+, please read https://github.com/ossrs/srs/issues/513."); } } } else if (n == "http_hooks") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "on_connect" && m != "on_close" && m != "on_publish" && m != "on_unpublish" && m != "on_play" && m != "on_stop" && m != "on_dvr" && m != "on_hls" && m != "on_hls_notify" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost http_hooks directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "forward") { // TODO: FIXME: implements it. /*for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "vhost" && m != "refer") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost forward directive %s, ret=%d", m.c_str(), ret); return ret; } }*/ } else if (n == "security") { for (int j = 0; j < (int)conf->directives.size(); j++) { SrsConfDirective* security = conf->at(j); string m = security->name.c_str(); if (m != "enabled" && m != "deny" && m != "allow") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost security directive %s, ret=%d", m.c_str(), ret); return ret; } } } else if (n == "transcode") { for (int j = 0; j < (int)conf->directives.size(); j++) { SrsConfDirective* trans = conf->at(j); string m = trans->name.c_str(); if (m != "enabled" && m != "ffmpeg" && m != "engine") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost transcode directive %s, ret=%d", m.c_str(), ret); return ret; } if (m == "engine") { for (int k = 0; k < (int)trans->directives.size(); k++) { string e = trans->at(k)->name; if (e != "enabled" && e != "vfilter" && e != "vcodec" && e != "vbitrate" && e != "vfps" && e != "vwidth" && e != "vheight" && e != "vthreads" && e != "vprofile" && e != "vpreset" && e != "vparams" && e != "acodec" && e != "abitrate" && e != "asample_rate" && e != "achannels" && e != "aparams" && e != "output" && e != "iformat" && e != "oformat" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost transcode engine directive %s, ret=%d", e.c_str(), ret); return ret; } } } } } else if (n == "bandcheck") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "key" && m != "interval" && m != "limit_kbps") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost bandcheck directive %s, ret=%d", m.c_str(), ret); return ret; } } } } } // check ingest id unique. for (int i = 0; i < (int)vhosts.size(); i++) { SrsConfDirective* vhost = vhosts[i]; std::vector<std::string> ids; for (int j = 0; j < (int)vhost->directives.size(); j++) { SrsConfDirective* conf = vhost->at(j); if (conf->name != "ingest") { continue; } std::string id = conf->arg0(); for (int k = 0; k < (int)ids.size(); k++) { if (id == ids.at(k)) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive \"ingest\" id duplicated, vhost=%s, id=%s, ret=%d", vhost->name.c_str(), id.c_str(), ret); return ret; } } ids.push_back(id); } } //////////////////////////////////////////////////////////////////////// // check chunk size //////////////////////////////////////////////////////////////////////// if (get_global_chunk_size() < SRS_CONSTS_RTMP_MIN_CHUNK_SIZE || get_global_chunk_size() > SRS_CONSTS_RTMP_MAX_CHUNK_SIZE ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive chunk_size invalid, chunk_size=%d, must in [%d, %d], ret=%d", get_global_chunk_size(), SRS_CONSTS_RTMP_MIN_CHUNK_SIZE, SRS_CONSTS_RTMP_MAX_CHUNK_SIZE, ret); return ret; } for (int i = 0; i < (int)vhosts.size(); i++) { SrsConfDirective* vhost = vhosts[i]; if (get_chunk_size(vhost->arg0()) < SRS_CONSTS_RTMP_MIN_CHUNK_SIZE || get_chunk_size(vhost->arg0()) > SRS_CONSTS_RTMP_MAX_CHUNK_SIZE ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("directive vhost %s chunk_size invalid, chunk_size=%d, must in [%d, %d], ret=%d", vhost->arg0().c_str(), get_chunk_size(vhost->arg0()), SRS_CONSTS_RTMP_MIN_CHUNK_SIZE, SRS_CONSTS_RTMP_MAX_CHUNK_SIZE, ret); return ret; } } for (int i = 0; i < (int)vhosts.size(); i++) { SrsConfDirective* vhost = vhosts[i]; srs_assert(vhost != NULL); #ifndef SRS_AUTO_DVR if (get_dvr_enabled(vhost->arg0())) { srs_warn("dvr of vhost %s is disabled by configure", vhost->arg0().c_str()); } #endif #ifndef SRS_AUTO_HLS if (get_hls_enabled(vhost->arg0())) { srs_warn("hls of vhost %s is disabled by configure", vhost->arg0().c_str()); } #endif #ifndef SRS_AUTO_HTTP_CALLBACK if (get_vhost_http_hooks_enabled(vhost->arg0())) { srs_warn("http_hooks of vhost %s is disabled by configure", vhost->arg0().c_str()); } #endif #ifndef SRS_AUTO_TRANSCODE if (get_transcode_enabled(get_transcode(vhost->arg0(), ""))) { srs_warn("transcode of vhost %s is disabled by configure", vhost->arg0().c_str()); } #endif #ifndef SRS_AUTO_INGEST vector<SrsConfDirective*> ingesters = get_ingesters(vhost->arg0()); for (int j = 0; j < (int)ingesters.size(); j++) { SrsConfDirective* ingest = ingesters[j]; if (get_ingest_enabled(ingest)) { srs_warn("ingest %s of vhost %s is disabled by configure", ingest->arg0().c_str(), vhost->arg0().c_str() ); } } #endif // TODO: FIXME: required http server when hls storage is ram or both. } // asprocess conflict with daemon if (get_asprocess() && get_deamon()) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("daemon conflict with asprocess, ret=%d", ret); return ret; } return ret; }
check_config函数主要功能
1. 检查根指令,必须是 listen,pid,chunk_size,ff_log_dir,srs_log_tank,srs_log_level,srs_log_file,max_connections.
daemon,heartbeat,http_api,stats,vhost,pithy_print_ms,http_stream,http_server,stream_caster,utc_time,work_dir,asprocess
2. 检查 http_api 指令的子指令,必须是enabled,listen,crossdomain
3. 检查 http_stream 指令的子指令,必须是enabled,listen,dir
SrsConfDirective* SrsConfig::get_http_stream() { SrsConfDirective* conf = root->get("http_stream"); // http_stream renamed to http_server in SRS2. if (!conf) { conf = root->get("http_server"); } return conf; }
http_stream被http_server替代
4. 检查 heartbeat 指令的子指令,必须是enabled,interval,url,device_id,summaries
5. 检查 stats 指令的子指令,必须是network,disk
6. 检查根指令指定的RTMP监听端口
7. 检查根指令 get_max_connections,没指定的情况下使用 SRS_CONF_DEFAULT_MAX_CONNECTIONS
8. 检测进程需要的最大文件描述符数量有没有超过系统的限制
// check max connections of system limits if (true) { int nb_consumed_fds = (int)get_listens().size(); if (!get_http_api_listen().empty()) { nb_consumed_fds++; } if (!get_http_stream_listen().empty()) { nb_consumed_fds++; } if (get_log_tank_file()) { nb_consumed_fds++; } // 0, 1, 2 for stdin, stdout and stderr. nb_consumed_fds += 3; int nb_connections = get_max_connections(); int nb_total = nb_connections + nb_consumed_fds; int max_open_files = (int)sysconf(_SC_OPEN_MAX); int nb_canbe = max_open_files - nb_consumed_fds - 1; // for each play connections, we open a pipe(2fds) to convert SrsConsumver to io, // refine performance, @see: https://github.com/ossrs/srs/issues/194 if (nb_total >= max_open_files) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("invalid max_connections=%d, required=%d, system limit to %d, " "total=%d(max_connections=%d, nb_consumed_fds=%d), ret=%d. " "you can change max_connections from %d to %d, or " "you can login as root and set the limit: ulimit -HSn %d", nb_connections, nb_total + 1, max_open_files, nb_total, nb_connections, nb_consumed_fds, ret, nb_connections, nb_canbe, nb_total + 1); return ret; } }
9. 检查 heartbeat.interval 和 stats.network
if (true) { vector<std::string> ips = srs_get_local_ipv4_ips(); int index = get_stats_network(); if (index >= (int)ips.size()) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("stats network invalid, total local ip count=%d, index=%d, ret=%d", (int)ips.size(), index, ret); return ret; } srs_warn("stats network use index=%d, ip=%s", index, ips.at(index).c_str()); }
srs_get_local_ipv4_ips返回非lo的网卡ip
10.检查http_api和http_stream的listen端口
11.检查日志设置
12.检查 stream_caster指令,必须是 enabled,caster,output,listen,rtp_port_min,rtp_port_max
13.检查 vhost配置