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"