diff --git a/Dockerfile b/Dockerfile index 8aa7827daa..77d5346529 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,7 +41,7 @@ ARG TARGETPLATFORM RUN echo "BUILDPLATFORM: $BUILDPLATFORM, TARGETPLATFORM: $TARGETPLATFORM" # Expose ports for streaming @see https://github.com/ossrs/srs#ports -EXPOSE 1935 1985 8080 8000/udp 10080/udp +EXPOSE 1935 1985 8080 5060 9000 8000/udp 10080/udp # FFMPEG 4.1 COPY --from=build /usr/local/bin/ffmpeg /usr/local/srs/objs/ffmpeg/bin/ffmpeg diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 76d305663b..78805a126e 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -647,8 +647,8 @@ stream_caster { # The available variables: # [stream] The video channel codec ID. output rtmp://127.0.0.1/live/[stream]; - # The listen TCP/UDP port for stream converter. - # For gb28181 converter, listen at TCP/UDP port. for example, 9000. + # The listen TCP port for stream converter. + # For gb28181 converter, listen at TCP port. for example, 9000. # @remark We always enable bundle for media streams at this port. listen 9000; # SIP server for GB28181. Please note that this is only a demonstrated SIP server, please never use it in your @@ -658,7 +658,7 @@ stream_caster { # Whether enable embedded SIP server. # Default: on enabled on; - # The SIP listen port, for both TCP and UDP protocol. + # The SIP listen port, for TCP protocol. # Default: 5060 listen 5060; # The SIP or media transport timeout in seconds. diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 442ebf224d..8758eac269 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for SRS. ## SRS 5.0 Changelog +* v5.0, 2023-08-30, Merge [#3779](https://github.com/ossrs/srs/pull/3779): Support HTTP-API for fetching reload result. v5.0.176 (#3779) * v5.0, 2023-08-28, Merge [#3503](https://github.com/ossrs/srs/pull/3503): SrsContextId assignment can be improved without create a duplicated one. v5.0.175 (#3503) * v5.0, 2023-08-28, Merge [#3781](https://github.com/ossrs/srs/pull/3781): HLS: Fix on_hls and hls_dispose critical zone issue. v5.0.174 (#3781) * v5.0, 2023-08-28, Merge [#3768](https://github.com/ossrs/srs/pull/3768): Support include empty config file. v5.0.173 (#3768) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index ecfbee3777..92386d8e5e 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -1333,18 +1333,22 @@ void SrsConfig::unsubscribe(ISrsReloadHandler* handler) } // LCOV_EXCL_START -srs_error_t SrsConfig::reload() +srs_error_t SrsConfig::reload(SrsReloadState *pstate) { + *pstate = SrsReloadStateInit; + srs_error_t err = srs_success; - + SrsConfig conf; - + + *pstate = SrsReloadStateParsing; if ((err = conf.parse_file(config_file.c_str())) != srs_success) { return srs_error_wrap(err, "parse file"); } srs_info("config reloader parse file success."); // transform config to compatible with previous style of config. + *pstate = SrsReloadStateTransforming; if ((err = srs_config_transform_vhost(conf.root)) != srs_success) { return srs_error_wrap(err, "transform config"); } @@ -1352,11 +1356,13 @@ srs_error_t SrsConfig::reload() if ((err = conf.check_config()) != srs_success) { return srs_error_wrap(err, "check config"); } - + + *pstate = SrsReloadStateApplying; if ((err = reload_conf(&conf)) != srs_success) { return srs_error_wrap(err, "reload config"); } - + + *pstate = SrsReloadStateFinished; return err; } // LCOV_EXCL_STOP diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index b0ee9a71ab..be1a35ec98 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -256,6 +256,19 @@ class SrsConfDirective virtual srs_error_t read_token(srs_internal::SrsConfigBuffer* buffer, std::vector& args, int& line_start, SrsDirectiveState& state); }; +// The state for reloading config. +enum SrsReloadState { + SrsReloadStateInit = 0, + // Start to parse the new config file. + SrsReloadStateParsing = 10, + // Start to transform the new config file to new version. + SrsReloadStateTransforming = 20, + // Start to apply the new config file. + SrsReloadStateApplying = 30, + // The reload is finished. + SrsReloadStateFinished = 90, +}; + // The config service provider. // For the config supports reload, so never keep the reference cross st-thread, // that is, never save the SrsConfDirective* get by any api of config, @@ -308,7 +321,7 @@ class SrsConfig virtual void unsubscribe(ISrsReloadHandler* handler); // Reload the config file. // @remark, user can test the config before reload it. - virtual srs_error_t reload(); + virtual srs_error_t reload(SrsReloadState *pstate); private: // Reload the vhost section of config. virtual srs_error_t reload_vhost(SrsConfDirective* old_root); diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 3696f2c1bd..8c6d16385d 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -863,7 +863,7 @@ srs_error_t SrsGoApiClients::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa } } else { SrsJsonObject* data = SrsJsonAny::object(); - obj->set("client", data);; + obj->set("client", data); if ((err = client->dumps(data)) != srs_success) { int code = srs_error_code(err); @@ -907,6 +907,10 @@ SrsGoApiRaw::~SrsGoApiRaw() _srs_config->unsubscribe(this); } +extern srs_error_t _srs_reload_err; +extern SrsReloadState _srs_reload_state; +extern std::string _srs_reload_id; + srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) { srs_error_t err = srs_success; @@ -937,8 +941,8 @@ srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* ////////////////////////////////////////////////////////////////////////// // the rpc is required. - // the allowd rpc method check. - if (rpc.empty() || rpc != "reload") { + // the allowed rpc method check. + if (rpc.empty() || (rpc != "reload" && rpc != "reload-fetch")) { return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW); } @@ -950,6 +954,16 @@ srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* server->on_signal(SRS_SIGNAL_RELOAD); return srs_api_response_code(w, r, ERROR_SUCCESS); + } else if (rpc == "reload-fetch") { + SrsJsonObject* data = SrsJsonAny::object(); + obj->set("data", data); + + data->set("err", SrsJsonAny::integer(srs_error_code(_srs_reload_err))); + data->set("msg", SrsJsonAny::str(srs_error_summary(_srs_reload_err).c_str())); + data->set("state", SrsJsonAny::integer(_srs_reload_state)); + data->set("rid", SrsJsonAny::str(_srs_reload_id.c_str())); + + return srs_api_response(w, r, obj->dumps()); } return err; diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 587f41649b..4817d34ed9 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -870,7 +870,9 @@ srs_error_t SrsServer::cycle() } // Do server main cycle. - err = do_cycle(); + if ((err = do_cycle()) != srs_success) { + srs_error("server err %s", srs_error_desc(err).c_str()); + } // OK, SRS server is done. wg_->done(); @@ -942,6 +944,10 @@ void SrsServer::on_signal(int signo) } } +srs_error_t _srs_reload_err; +SrsReloadState _srs_reload_state; +std::string _srs_reload_id; + srs_error_t SrsServer::do_cycle() { srs_error_t err = srs_success; @@ -991,12 +997,27 @@ srs_error_t SrsServer::do_cycle() // do reload the config. if (signal_reload) { signal_reload = false; - srs_info("get signal to reload the config."); - - if ((err = _srs_config->reload()) != srs_success) { - return srs_error_wrap(err, "config reload"); + srs_trace("starting reload config."); + + SrsReloadState state = SrsReloadStateInit; + _srs_reload_state = SrsReloadStateInit; srs_freep(_srs_reload_err); _srs_reload_id = srs_random_str(7); + err = _srs_config->reload(&state); + _srs_reload_state = state; _srs_reload_err = srs_error_copy(err); + if (err != srs_success) { + // If the parsing and transformation of the configuration fail, we can tolerate it by simply + // ignoring the new configuration and continuing to use the current one. However, if the + // application of the new configuration fails, some configurations may be applied while + // others may not. For instance, the listening port may be closed when the configuration + // is set to listen on an unavailable port. In such cases, we should terminate the service. + if (state == SrsReloadStateApplying) { + return srs_error_wrap(err, "reload fatal error state=%d", state); + } + + srs_warn("reload failed, state=%d, err %s", state, srs_error_desc(err).c_str()); + srs_freep(err); + } else { + srs_trace("reload config success, state=%d.", state); } - srs_trace("reload config success."); } srs_usleep(1 * SRS_UTIME_SECONDS); diff --git a/trunk/src/app/srs_app_threads.cpp b/trunk/src/app/srs_app_threads.cpp index d1d14bfcec..82aaad2a58 100644 --- a/trunk/src/app/srs_app_threads.cpp +++ b/trunk/src/app/srs_app_threads.cpp @@ -295,6 +295,10 @@ srs_error_t SrsCircuitBreaker::on_timer(srs_utime_t interval) SrsCircuitBreaker* _srs_circuit_breaker = NULL; SrsAsyncCallWorker* _srs_dvr_async = NULL; +extern srs_error_t _srs_reload_err; +extern SrsReloadState _srs_reload_state; +extern std::string _srs_reload_id; + srs_error_t srs_global_initialize() { srs_error_t err = srs_success; @@ -446,6 +450,10 @@ srs_error_t srs_global_initialize() _srs_apm = new SrsApmClient(); #endif + _srs_reload_err = srs_success; + _srs_reload_state = SrsReloadStateInit; + _srs_reload_id = srs_random_str(7); + return err; } diff --git a/trunk/src/core/srs_core_version5.hpp b/trunk/src/core/srs_core_version5.hpp index 87387ba437..7528834d62 100644 --- a/trunk/src/core/srs_core_version5.hpp +++ b/trunk/src/core/srs_core_version5.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 5 #define VERSION_MINOR 0 -#define VERSION_REVISION 175 +#define VERSION_REVISION 176 #endif