diff --git a/README.md b/README.md index be3b4f967..b37b303b7 100755 --- a/README.md +++ b/README.md @@ -343,6 +343,7 @@ Remark: ## History +* v2.0, 2015-09-14, for [#475][bug #475] fix http hooks crash for st context switch. 2.0.187 * v2.0, 2015-09-09, support reload utc_time. 2.0.186 * v2.0, 2015-08-23, [2.0 alpha(2.0.185)][r2.0a0] released. 89022 lines. * v2.0, 2015-08-22, HTTP API support JSONP by specifies the query string callback=xxx. @@ -1024,6 +1025,7 @@ Winlin [bug #133]: https://github.com/simple-rtmp-server/srs/issues/133 [bug #92]: https://github.com/simple-rtmp-server/srs/issues/92 [bug #380]: https://github.com/simple-rtmp-server/srs/issues/380 +[bug #475]: https://github.com/simple-rtmp-server/srs/issues/475 [bug #454]: https://github.com/simple-rtmp-server/srs/issues/454 [bug #442]: https://github.com/simple-rtmp-server/srs/issues/442 [bug #169]: https://github.com/simple-rtmp-server/srs/issues/169 diff --git a/trunk/src/app/srs_app_dvr.cpp b/trunk/src/app/srs_app_dvr.cpp index 2f1e6ab58..3aca55f50 100644 --- a/trunk/src/app/srs_app_dvr.cpp +++ b/trunk/src/app/srs_app_dvr.cpp @@ -512,22 +512,31 @@ int SrsDvrAsyncCallOnDvr::call() int ret = ERROR_SUCCESS; #ifdef SRS_AUTO_HTTP_CALLBACK - // http callback for on_dvr in config. - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { - // HTTP: on_dvr - SrsConfDirective* on_dvr = _srs_config->get_vhost_on_dvr(req->vhost); - if (!on_dvr) { + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { + return ret; + } + + // the http hooks will cause context switch, + // so we must copy all hooks for the on_connect may freed. + // @see https://github.com/simple-rtmp-server/srs/issues/475 + vector hooks; + + if (true) { + SrsConfDirective* conf = _srs_config->get_vhost_on_dvr(req->vhost); + + if (!conf) { srs_info("ignore the empty http callback: on_dvr"); return ret; } - std::string file = path; - for (int i = 0; i < (int)on_dvr->args.size(); i++) { - std::string url = on_dvr->args.at(i); - if ((ret = SrsHttpHooks::on_dvr(url, req, file)) != ERROR_SUCCESS) { - srs_error("hook client on_dvr failed. url=%s, ret=%d", url.c_str(), ret); - return ret; - } + hooks = conf->args; + } + + for (int i = 0; i < (int)hooks.size(); i++) { + std::string url = hooks.at(i); + if ((ret = SrsHttpHooks::on_dvr(url, req, path)) != ERROR_SUCCESS) { + srs_error("hook client on_dvr failed. url=%s, ret=%d", url.c_str(), ret); + return ret; } } #endif diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 526ff3b1e..f85c5478d 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -198,23 +198,31 @@ int SrsDvrAsyncCallOnHls::call() int ret = ERROR_SUCCESS; #ifdef SRS_AUTO_HTTP_CALLBACK - // http callback for on_hls in config. - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { - // HTTP: on_hls - SrsConfDirective* on_hls = _srs_config->get_vhost_on_hls(req->vhost); - if (!on_hls) { + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { + return ret; + } + + // the http hooks will cause context switch, + // so we must copy all hooks for the on_connect may freed. + // @see https://github.com/simple-rtmp-server/srs/issues/475 + vector hooks; + + if (true) { + SrsConfDirective* conf = _srs_config->get_vhost_on_hls(req->vhost); + + if (!conf) { srs_info("ignore the empty http callback: on_hls"); return ret; } - std::string file = path; - int sn = seq_no; - for (int i = 0; i < (int)on_hls->args.size(); i++) { - std::string url = on_hls->args.at(i); - if ((ret = SrsHttpHooks::on_hls(url, req, file, ts_url, m3u8, m3u8_url, sn, duration)) != ERROR_SUCCESS) { - srs_error("hook client on_hls failed. url=%s, ret=%d", url.c_str(), ret); - return ret; - } + hooks = conf->args; + } + + for (int i = 0; i < (int)hooks.size(); i++) { + std::string url = hooks.at(i); + if ((ret = SrsHttpHooks::on_hls(url, req, path, ts_url, m3u8, m3u8_url, seq_no, duration)) != ERROR_SUCCESS) { + srs_error("hook client on_hls failed. url=%s, ret=%d", url.c_str(), ret); + return ret; } } #endif @@ -243,25 +251,31 @@ int SrsDvrAsyncCallOnHlsNotify::call() int ret = ERROR_SUCCESS; #ifdef SRS_AUTO_HTTP_CALLBACK - // http callback for on_hls_notify in config. - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { - // HTTP: on_hls - SrsConfDirective* on_hls = _srs_config->get_vhost_on_hls_notify(req->vhost); - if (!on_hls) { + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { + return ret; + } + + // the http hooks will cause context switch, + // so we must copy all hooks for the on_connect may freed. + // @see https://github.com/simple-rtmp-server/srs/issues/475 + vector hooks; + + if (true) { + SrsConfDirective* conf = _srs_config->get_vhost_on_hls_notify(req->vhost); + + if (!conf) { srs_info("ignore the empty http callback: on_hls_notify"); return ret; } - std::string url; - if (true) { - static u_int32_t nb_call = 0; - int index = nb_call++ % on_hls->args.size(); - url = on_hls->args.at(index); - } - - int nb_notify = _srs_config->get_vhost_hls_nb_notify(req->vhost); + hooks = conf->args; + } + + int nb_notify = _srs_config->get_vhost_hls_nb_notify(req->vhost); + for (int i = 0; i < (int)hooks.size(); i++) { + std::string url = hooks.at(i); if ((ret = SrsHttpHooks::on_hls_notify(url, req, ts_url, nb_notify)) != ERROR_SUCCESS) { - srs_error("hook client on_hls_notify failed. url=%s, ts=%s, ret=%d", url.c_str(), ts_url.c_str(), ret); + srs_error("hook client on_hls_notify failed. url=%s, ret=%d", url.c_str(), ret); return ret; } } diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index d7b5461eb..51fb46d84 100755 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -1322,20 +1322,31 @@ int SrsRtmpConn::http_hooks_on_connect() int ret = ERROR_SUCCESS; #ifdef SRS_AUTO_HTTP_CALLBACK - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { - // HTTP: on_connect - SrsConfDirective* on_connect = _srs_config->get_vhost_on_connect(req->vhost); - if (!on_connect) { + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { + return ret; + } + + // the http hooks will cause context switch, + // so we must copy all hooks for the on_connect may freed. + // @see https://github.com/simple-rtmp-server/srs/issues/475 + vector hooks; + + if (true) { + SrsConfDirective* conf = _srs_config->get_vhost_on_connect(req->vhost); + + if (!conf) { srs_info("ignore the empty http callback: on_connect"); return ret; } - for (int i = 0; i < (int)on_connect->args.size(); i++) { - std::string url = on_connect->args.at(i); - if ((ret = SrsHttpHooks::on_connect(url, req)) != ERROR_SUCCESS) { - srs_error("hook client on_connect failed. url=%s, ret=%d", url.c_str(), ret); - return ret; - } + hooks = conf->args; + } + + for (int i = 0; i < (int)hooks.size(); i++) { + std::string url = hooks.at(i); + if ((ret = SrsHttpHooks::on_connect(url, req)) != ERROR_SUCCESS) { + srs_error("hook client on_connect failed. url=%s, ret=%d", url.c_str(), ret); + return ret; } } #endif @@ -1346,19 +1357,29 @@ int SrsRtmpConn::http_hooks_on_connect() void SrsRtmpConn::http_hooks_on_close() { #ifdef SRS_AUTO_HTTP_CALLBACK - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { - // whatever the ret code, notify the api hooks. - // HTTP: on_close - SrsConfDirective* on_close = _srs_config->get_vhost_on_close(req->vhost); - if (!on_close) { + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { + return; + } + + // the http hooks will cause context switch, + // so we must copy all hooks for the on_connect may freed. + // @see https://github.com/simple-rtmp-server/srs/issues/475 + vector hooks; + + if (true) { + SrsConfDirective* conf = _srs_config->get_vhost_on_close(req->vhost); + + if (!conf) { srs_info("ignore the empty http callback: on_close"); return; } - for (int i = 0; i < (int)on_close->args.size(); i++) { - std::string url = on_close->args.at(i); - SrsHttpHooks::on_close(url, req, kbps->get_send_bytes(), kbps->get_recv_bytes()); - } + hooks = conf->args; + } + + for (int i = 0; i < (int)hooks.size(); i++) { + std::string url = hooks.at(i); + SrsHttpHooks::on_close(url, req, kbps->get_send_bytes(), kbps->get_recv_bytes()); } #endif } @@ -1368,20 +1389,31 @@ int SrsRtmpConn::http_hooks_on_publish() int ret = ERROR_SUCCESS; #ifdef SRS_AUTO_HTTP_CALLBACK - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { - // HTTP: on_publish - SrsConfDirective* on_publish = _srs_config->get_vhost_on_publish(req->vhost); - if (!on_publish) { + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { + return ret; + } + + // the http hooks will cause context switch, + // so we must copy all hooks for the on_connect may freed. + // @see https://github.com/simple-rtmp-server/srs/issues/475 + vector hooks; + + if (true) { + SrsConfDirective* conf = _srs_config->get_vhost_on_publish(req->vhost); + + if (!conf) { srs_info("ignore the empty http callback: on_publish"); return ret; } - for (int i = 0; i < (int)on_publish->args.size(); i++) { - std::string url = on_publish->args.at(i); - if ((ret = SrsHttpHooks::on_publish(url, req)) != ERROR_SUCCESS) { - srs_error("hook client on_publish failed. url=%s, ret=%d", url.c_str(), ret); - return ret; - } + hooks = conf->args; + } + + for (int i = 0; i < (int)hooks.size(); i++) { + std::string url = hooks.at(i); + if ((ret = SrsHttpHooks::on_publish(url, req)) != ERROR_SUCCESS) { + srs_error("hook client on_publish failed. url=%s, ret=%d", url.c_str(), ret); + return ret; } } #endif @@ -1392,19 +1424,29 @@ int SrsRtmpConn::http_hooks_on_publish() void SrsRtmpConn::http_hooks_on_unpublish() { #ifdef SRS_AUTO_HTTP_CALLBACK - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { - // whatever the ret code, notify the api hooks. - // HTTP: on_unpublish - SrsConfDirective* on_unpublish = _srs_config->get_vhost_on_unpublish(req->vhost); - if (!on_unpublish) { + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { + return; + } + + // the http hooks will cause context switch, + // so we must copy all hooks for the on_connect may freed. + // @see https://github.com/simple-rtmp-server/srs/issues/475 + vector hooks; + + if (true) { + SrsConfDirective* conf = _srs_config->get_vhost_on_unpublish(req->vhost); + + if (!conf) { srs_info("ignore the empty http callback: on_unpublish"); return; } - for (int i = 0; i < (int)on_unpublish->args.size(); i++) { - std::string url = on_unpublish->args.at(i); - SrsHttpHooks::on_unpublish(url, req); - } + hooks = conf->args; + } + + for (int i = 0; i < (int)hooks.size(); i++) { + std::string url = hooks.at(i); + SrsHttpHooks::on_unpublish(url, req); } #endif } @@ -1414,20 +1456,31 @@ int SrsRtmpConn::http_hooks_on_play() int ret = ERROR_SUCCESS; #ifdef SRS_AUTO_HTTP_CALLBACK - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { - // HTTP: on_play - SrsConfDirective* on_play = _srs_config->get_vhost_on_play(req->vhost); - if (!on_play) { + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { + return ret; + } + + // the http hooks will cause context switch, + // so we must copy all hooks for the on_connect may freed. + // @see https://github.com/simple-rtmp-server/srs/issues/475 + vector hooks; + + if (true) { + SrsConfDirective* conf = _srs_config->get_vhost_on_play(req->vhost); + + if (!conf) { srs_info("ignore the empty http callback: on_play"); return ret; } - for (int i = 0; i < (int)on_play->args.size(); i++) { - std::string url = on_play->args.at(i); - if ((ret = SrsHttpHooks::on_play(url, req)) != ERROR_SUCCESS) { - srs_error("hook client on_play failed. url=%s, ret=%d", url.c_str(), ret); - return ret; - } + hooks = conf->args; + } + + for (int i = 0; i < (int)hooks.size(); i++) { + std::string url = hooks.at(i); + if ((ret = SrsHttpHooks::on_play(url, req)) != ERROR_SUCCESS) { + srs_error("hook client on_play failed. url=%s, ret=%d", url.c_str(), ret); + return ret; } } #endif @@ -1438,19 +1491,29 @@ int SrsRtmpConn::http_hooks_on_play() void SrsRtmpConn::http_hooks_on_stop() { #ifdef SRS_AUTO_HTTP_CALLBACK - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { - // whatever the ret code, notify the api hooks. - // HTTP: on_stop - SrsConfDirective* on_stop = _srs_config->get_vhost_on_stop(req->vhost); - if (!on_stop) { + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { + return; + } + + // the http hooks will cause context switch, + // so we must copy all hooks for the on_connect may freed. + // @see https://github.com/simple-rtmp-server/srs/issues/475 + vector hooks; + + if (true) { + SrsConfDirective* conf = _srs_config->get_vhost_on_stop(req->vhost); + + if (!conf) { srs_info("ignore the empty http callback: on_stop"); return; } - for (int i = 0; i < (int)on_stop->args.size(); i++) { - std::string url = on_stop->args.at(i); - SrsHttpHooks::on_stop(url, req); - } + hooks = conf->args; + } + + for (int i = 0; i < (int)hooks.size(); i++) { + std::string url = hooks.at(i); + SrsHttpHooks::on_stop(url, req); } #endif diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 3b0e10fc5..b249e26b2 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 186 +#define VERSION_REVISION 187 // server info. #define RTMP_SIG_SRS_KEY "SRS"