winlin

#475, fix http hooks crash for st context switch. 2.0.187

@@ -343,6 +343,7 @@ Remark: @@ -343,6 +343,7 @@ Remark:
343 343
344 ## History 344 ## History
345 345
  346 +* v2.0, 2015-09-14, for [#475][bug #475] fix http hooks crash for st context switch. 2.0.187
346 * v2.0, 2015-09-09, support reload utc_time. 2.0.186 347 * v2.0, 2015-09-09, support reload utc_time. 2.0.186
347 * <strong>v2.0, 2015-08-23, [2.0 alpha(2.0.185)][r2.0a0] released. 89022 lines.</strong> 348 * <strong>v2.0, 2015-08-23, [2.0 alpha(2.0.185)][r2.0a0] released. 89022 lines.</strong>
348 * v2.0, 2015-08-22, HTTP API support JSONP by specifies the query string callback=xxx. 349 * v2.0, 2015-08-22, HTTP API support JSONP by specifies the query string callback=xxx.
@@ -1024,6 +1025,7 @@ Winlin @@ -1024,6 +1025,7 @@ Winlin
1024 [bug #133]: https://github.com/simple-rtmp-server/srs/issues/133 1025 [bug #133]: https://github.com/simple-rtmp-server/srs/issues/133
1025 [bug #92]: https://github.com/simple-rtmp-server/srs/issues/92 1026 [bug #92]: https://github.com/simple-rtmp-server/srs/issues/92
1026 [bug #380]: https://github.com/simple-rtmp-server/srs/issues/380 1027 [bug #380]: https://github.com/simple-rtmp-server/srs/issues/380
  1028 +[bug #475]: https://github.com/simple-rtmp-server/srs/issues/475
1027 [bug #454]: https://github.com/simple-rtmp-server/srs/issues/454 1029 [bug #454]: https://github.com/simple-rtmp-server/srs/issues/454
1028 [bug #442]: https://github.com/simple-rtmp-server/srs/issues/442 1030 [bug #442]: https://github.com/simple-rtmp-server/srs/issues/442
1029 [bug #169]: https://github.com/simple-rtmp-server/srs/issues/169 1031 [bug #169]: https://github.com/simple-rtmp-server/srs/issues/169
@@ -512,22 +512,31 @@ int SrsDvrAsyncCallOnDvr::call() @@ -512,22 +512,31 @@ int SrsDvrAsyncCallOnDvr::call()
512 int ret = ERROR_SUCCESS; 512 int ret = ERROR_SUCCESS;
513 513
514 #ifdef SRS_AUTO_HTTP_CALLBACK 514 #ifdef SRS_AUTO_HTTP_CALLBACK
515 - // http callback for on_dvr in config.  
516 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
517 - // HTTP: on_dvr  
518 - SrsConfDirective* on_dvr = _srs_config->get_vhost_on_dvr(req->vhost);  
519 - if (!on_dvr) { 515 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  516 + return ret;
  517 + }
  518 +
  519 + // the http hooks will cause context switch,
  520 + // so we must copy all hooks for the on_connect may freed.
  521 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  522 + vector<string> hooks;
  523 +
  524 + if (true) {
  525 + SrsConfDirective* conf = _srs_config->get_vhost_on_dvr(req->vhost);
  526 +
  527 + if (!conf) {
520 srs_info("ignore the empty http callback: on_dvr"); 528 srs_info("ignore the empty http callback: on_dvr");
521 return ret; 529 return ret;
522 } 530 }
523 531
524 - std::string file = path;  
525 - for (int i = 0; i < (int)on_dvr->args.size(); i++) {  
526 - std::string url = on_dvr->args.at(i);  
527 - if ((ret = SrsHttpHooks::on_dvr(url, req, file)) != ERROR_SUCCESS) {  
528 - srs_error("hook client on_dvr failed. url=%s, ret=%d", url.c_str(), ret);  
529 - return ret;  
530 - } 532 + hooks = conf->args;
  533 + }
  534 +
  535 + for (int i = 0; i < (int)hooks.size(); i++) {
  536 + std::string url = hooks.at(i);
  537 + if ((ret = SrsHttpHooks::on_dvr(url, req, path)) != ERROR_SUCCESS) {
  538 + srs_error("hook client on_dvr failed. url=%s, ret=%d", url.c_str(), ret);
  539 + return ret;
531 } 540 }
532 } 541 }
533 #endif 542 #endif
@@ -198,23 +198,31 @@ int SrsDvrAsyncCallOnHls::call() @@ -198,23 +198,31 @@ int SrsDvrAsyncCallOnHls::call()
198 int ret = ERROR_SUCCESS; 198 int ret = ERROR_SUCCESS;
199 199
200 #ifdef SRS_AUTO_HTTP_CALLBACK 200 #ifdef SRS_AUTO_HTTP_CALLBACK
201 - // http callback for on_hls in config.  
202 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
203 - // HTTP: on_hls  
204 - SrsConfDirective* on_hls = _srs_config->get_vhost_on_hls(req->vhost);  
205 - if (!on_hls) { 201 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  202 + return ret;
  203 + }
  204 +
  205 + // the http hooks will cause context switch,
  206 + // so we must copy all hooks for the on_connect may freed.
  207 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  208 + vector<string> hooks;
  209 +
  210 + if (true) {
  211 + SrsConfDirective* conf = _srs_config->get_vhost_on_hls(req->vhost);
  212 +
  213 + if (!conf) {
206 srs_info("ignore the empty http callback: on_hls"); 214 srs_info("ignore the empty http callback: on_hls");
207 return ret; 215 return ret;
208 } 216 }
209 217
210 - std::string file = path;  
211 - int sn = seq_no;  
212 - for (int i = 0; i < (int)on_hls->args.size(); i++) {  
213 - std::string url = on_hls->args.at(i);  
214 - if ((ret = SrsHttpHooks::on_hls(url, req, file, ts_url, m3u8, m3u8_url, sn, duration)) != ERROR_SUCCESS) {  
215 - srs_error("hook client on_hls failed. url=%s, ret=%d", url.c_str(), ret);  
216 - return ret;  
217 - } 218 + hooks = conf->args;
  219 + }
  220 +
  221 + for (int i = 0; i < (int)hooks.size(); i++) {
  222 + std::string url = hooks.at(i);
  223 + if ((ret = SrsHttpHooks::on_hls(url, req, path, ts_url, m3u8, m3u8_url, seq_no, duration)) != ERROR_SUCCESS) {
  224 + srs_error("hook client on_hls failed. url=%s, ret=%d", url.c_str(), ret);
  225 + return ret;
218 } 226 }
219 } 227 }
220 #endif 228 #endif
@@ -243,25 +251,31 @@ int SrsDvrAsyncCallOnHlsNotify::call() @@ -243,25 +251,31 @@ int SrsDvrAsyncCallOnHlsNotify::call()
243 int ret = ERROR_SUCCESS; 251 int ret = ERROR_SUCCESS;
244 252
245 #ifdef SRS_AUTO_HTTP_CALLBACK 253 #ifdef SRS_AUTO_HTTP_CALLBACK
246 - // http callback for on_hls_notify in config.  
247 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
248 - // HTTP: on_hls  
249 - SrsConfDirective* on_hls = _srs_config->get_vhost_on_hls_notify(req->vhost);  
250 - if (!on_hls) { 254 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  255 + return ret;
  256 + }
  257 +
  258 + // the http hooks will cause context switch,
  259 + // so we must copy all hooks for the on_connect may freed.
  260 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  261 + vector<string> hooks;
  262 +
  263 + if (true) {
  264 + SrsConfDirective* conf = _srs_config->get_vhost_on_hls_notify(req->vhost);
  265 +
  266 + if (!conf) {
251 srs_info("ignore the empty http callback: on_hls_notify"); 267 srs_info("ignore the empty http callback: on_hls_notify");
252 return ret; 268 return ret;
253 } 269 }
254 270
255 - std::string url;  
256 - if (true) {  
257 - static u_int32_t nb_call = 0;  
258 - int index = nb_call++ % on_hls->args.size();  
259 - url = on_hls->args.at(index);  
260 - }  
261 -  
262 - int nb_notify = _srs_config->get_vhost_hls_nb_notify(req->vhost); 271 + hooks = conf->args;
  272 + }
  273 +
  274 + int nb_notify = _srs_config->get_vhost_hls_nb_notify(req->vhost);
  275 + for (int i = 0; i < (int)hooks.size(); i++) {
  276 + std::string url = hooks.at(i);
263 if ((ret = SrsHttpHooks::on_hls_notify(url, req, ts_url, nb_notify)) != ERROR_SUCCESS) { 277 if ((ret = SrsHttpHooks::on_hls_notify(url, req, ts_url, nb_notify)) != ERROR_SUCCESS) {
264 - srs_error("hook client on_hls_notify failed. url=%s, ts=%s, ret=%d", url.c_str(), ts_url.c_str(), ret); 278 + srs_error("hook client on_hls_notify failed. url=%s, ret=%d", url.c_str(), ret);
265 return ret; 279 return ret;
266 } 280 }
267 } 281 }
@@ -1322,20 +1322,31 @@ int SrsRtmpConn::http_hooks_on_connect() @@ -1322,20 +1322,31 @@ int SrsRtmpConn::http_hooks_on_connect()
1322 int ret = ERROR_SUCCESS; 1322 int ret = ERROR_SUCCESS;
1323 1323
1324 #ifdef SRS_AUTO_HTTP_CALLBACK 1324 #ifdef SRS_AUTO_HTTP_CALLBACK
1325 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
1326 - // HTTP: on_connect  
1327 - SrsConfDirective* on_connect = _srs_config->get_vhost_on_connect(req->vhost);  
1328 - if (!on_connect) { 1325 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  1326 + return ret;
  1327 + }
  1328 +
  1329 + // the http hooks will cause context switch,
  1330 + // so we must copy all hooks for the on_connect may freed.
  1331 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  1332 + vector<string> hooks;
  1333 +
  1334 + if (true) {
  1335 + SrsConfDirective* conf = _srs_config->get_vhost_on_connect(req->vhost);
  1336 +
  1337 + if (!conf) {
1329 srs_info("ignore the empty http callback: on_connect"); 1338 srs_info("ignore the empty http callback: on_connect");
1330 return ret; 1339 return ret;
1331 } 1340 }
1332 1341
1333 - for (int i = 0; i < (int)on_connect->args.size(); i++) {  
1334 - std::string url = on_connect->args.at(i);  
1335 - if ((ret = SrsHttpHooks::on_connect(url, req)) != ERROR_SUCCESS) {  
1336 - srs_error("hook client on_connect failed. url=%s, ret=%d", url.c_str(), ret);  
1337 - return ret;  
1338 - } 1342 + hooks = conf->args;
  1343 + }
  1344 +
  1345 + for (int i = 0; i < (int)hooks.size(); i++) {
  1346 + std::string url = hooks.at(i);
  1347 + if ((ret = SrsHttpHooks::on_connect(url, req)) != ERROR_SUCCESS) {
  1348 + srs_error("hook client on_connect failed. url=%s, ret=%d", url.c_str(), ret);
  1349 + return ret;
1339 } 1350 }
1340 } 1351 }
1341 #endif 1352 #endif
@@ -1346,19 +1357,29 @@ int SrsRtmpConn::http_hooks_on_connect() @@ -1346,19 +1357,29 @@ int SrsRtmpConn::http_hooks_on_connect()
1346 void SrsRtmpConn::http_hooks_on_close() 1357 void SrsRtmpConn::http_hooks_on_close()
1347 { 1358 {
1348 #ifdef SRS_AUTO_HTTP_CALLBACK 1359 #ifdef SRS_AUTO_HTTP_CALLBACK
1349 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
1350 - // whatever the ret code, notify the api hooks.  
1351 - // HTTP: on_close  
1352 - SrsConfDirective* on_close = _srs_config->get_vhost_on_close(req->vhost);  
1353 - if (!on_close) { 1360 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  1361 + return;
  1362 + }
  1363 +
  1364 + // the http hooks will cause context switch,
  1365 + // so we must copy all hooks for the on_connect may freed.
  1366 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  1367 + vector<string> hooks;
  1368 +
  1369 + if (true) {
  1370 + SrsConfDirective* conf = _srs_config->get_vhost_on_close(req->vhost);
  1371 +
  1372 + if (!conf) {
1354 srs_info("ignore the empty http callback: on_close"); 1373 srs_info("ignore the empty http callback: on_close");
1355 return; 1374 return;
1356 } 1375 }
1357 1376
1358 - for (int i = 0; i < (int)on_close->args.size(); i++) {  
1359 - std::string url = on_close->args.at(i);  
1360 - SrsHttpHooks::on_close(url, req, kbps->get_send_bytes(), kbps->get_recv_bytes());  
1361 - } 1377 + hooks = conf->args;
  1378 + }
  1379 +
  1380 + for (int i = 0; i < (int)hooks.size(); i++) {
  1381 + std::string url = hooks.at(i);
  1382 + SrsHttpHooks::on_close(url, req, kbps->get_send_bytes(), kbps->get_recv_bytes());
1362 } 1383 }
1363 #endif 1384 #endif
1364 } 1385 }
@@ -1368,20 +1389,31 @@ int SrsRtmpConn::http_hooks_on_publish() @@ -1368,20 +1389,31 @@ int SrsRtmpConn::http_hooks_on_publish()
1368 int ret = ERROR_SUCCESS; 1389 int ret = ERROR_SUCCESS;
1369 1390
1370 #ifdef SRS_AUTO_HTTP_CALLBACK 1391 #ifdef SRS_AUTO_HTTP_CALLBACK
1371 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
1372 - // HTTP: on_publish  
1373 - SrsConfDirective* on_publish = _srs_config->get_vhost_on_publish(req->vhost);  
1374 - if (!on_publish) { 1392 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  1393 + return ret;
  1394 + }
  1395 +
  1396 + // the http hooks will cause context switch,
  1397 + // so we must copy all hooks for the on_connect may freed.
  1398 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  1399 + vector<string> hooks;
  1400 +
  1401 + if (true) {
  1402 + SrsConfDirective* conf = _srs_config->get_vhost_on_publish(req->vhost);
  1403 +
  1404 + if (!conf) {
1375 srs_info("ignore the empty http callback: on_publish"); 1405 srs_info("ignore the empty http callback: on_publish");
1376 return ret; 1406 return ret;
1377 } 1407 }
1378 1408
1379 - for (int i = 0; i < (int)on_publish->args.size(); i++) {  
1380 - std::string url = on_publish->args.at(i);  
1381 - if ((ret = SrsHttpHooks::on_publish(url, req)) != ERROR_SUCCESS) {  
1382 - srs_error("hook client on_publish failed. url=%s, ret=%d", url.c_str(), ret);  
1383 - return ret;  
1384 - } 1409 + hooks = conf->args;
  1410 + }
  1411 +
  1412 + for (int i = 0; i < (int)hooks.size(); i++) {
  1413 + std::string url = hooks.at(i);
  1414 + if ((ret = SrsHttpHooks::on_publish(url, req)) != ERROR_SUCCESS) {
  1415 + srs_error("hook client on_publish failed. url=%s, ret=%d", url.c_str(), ret);
  1416 + return ret;
1385 } 1417 }
1386 } 1418 }
1387 #endif 1419 #endif
@@ -1392,19 +1424,29 @@ int SrsRtmpConn::http_hooks_on_publish() @@ -1392,19 +1424,29 @@ int SrsRtmpConn::http_hooks_on_publish()
1392 void SrsRtmpConn::http_hooks_on_unpublish() 1424 void SrsRtmpConn::http_hooks_on_unpublish()
1393 { 1425 {
1394 #ifdef SRS_AUTO_HTTP_CALLBACK 1426 #ifdef SRS_AUTO_HTTP_CALLBACK
1395 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
1396 - // whatever the ret code, notify the api hooks.  
1397 - // HTTP: on_unpublish  
1398 - SrsConfDirective* on_unpublish = _srs_config->get_vhost_on_unpublish(req->vhost);  
1399 - if (!on_unpublish) { 1427 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  1428 + return;
  1429 + }
  1430 +
  1431 + // the http hooks will cause context switch,
  1432 + // so we must copy all hooks for the on_connect may freed.
  1433 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  1434 + vector<string> hooks;
  1435 +
  1436 + if (true) {
  1437 + SrsConfDirective* conf = _srs_config->get_vhost_on_unpublish(req->vhost);
  1438 +
  1439 + if (!conf) {
1400 srs_info("ignore the empty http callback: on_unpublish"); 1440 srs_info("ignore the empty http callback: on_unpublish");
1401 return; 1441 return;
1402 } 1442 }
1403 1443
1404 - for (int i = 0; i < (int)on_unpublish->args.size(); i++) {  
1405 - std::string url = on_unpublish->args.at(i);  
1406 - SrsHttpHooks::on_unpublish(url, req);  
1407 - } 1444 + hooks = conf->args;
  1445 + }
  1446 +
  1447 + for (int i = 0; i < (int)hooks.size(); i++) {
  1448 + std::string url = hooks.at(i);
  1449 + SrsHttpHooks::on_unpublish(url, req);
1408 } 1450 }
1409 #endif 1451 #endif
1410 } 1452 }
@@ -1414,20 +1456,31 @@ int SrsRtmpConn::http_hooks_on_play() @@ -1414,20 +1456,31 @@ int SrsRtmpConn::http_hooks_on_play()
1414 int ret = ERROR_SUCCESS; 1456 int ret = ERROR_SUCCESS;
1415 1457
1416 #ifdef SRS_AUTO_HTTP_CALLBACK 1458 #ifdef SRS_AUTO_HTTP_CALLBACK
1417 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
1418 - // HTTP: on_play  
1419 - SrsConfDirective* on_play = _srs_config->get_vhost_on_play(req->vhost);  
1420 - if (!on_play) { 1459 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  1460 + return ret;
  1461 + }
  1462 +
  1463 + // the http hooks will cause context switch,
  1464 + // so we must copy all hooks for the on_connect may freed.
  1465 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  1466 + vector<string> hooks;
  1467 +
  1468 + if (true) {
  1469 + SrsConfDirective* conf = _srs_config->get_vhost_on_play(req->vhost);
  1470 +
  1471 + if (!conf) {
1421 srs_info("ignore the empty http callback: on_play"); 1472 srs_info("ignore the empty http callback: on_play");
1422 return ret; 1473 return ret;
1423 } 1474 }
1424 1475
1425 - for (int i = 0; i < (int)on_play->args.size(); i++) {  
1426 - std::string url = on_play->args.at(i);  
1427 - if ((ret = SrsHttpHooks::on_play(url, req)) != ERROR_SUCCESS) {  
1428 - srs_error("hook client on_play failed. url=%s, ret=%d", url.c_str(), ret);  
1429 - return ret;  
1430 - } 1476 + hooks = conf->args;
  1477 + }
  1478 +
  1479 + for (int i = 0; i < (int)hooks.size(); i++) {
  1480 + std::string url = hooks.at(i);
  1481 + if ((ret = SrsHttpHooks::on_play(url, req)) != ERROR_SUCCESS) {
  1482 + srs_error("hook client on_play failed. url=%s, ret=%d", url.c_str(), ret);
  1483 + return ret;
1431 } 1484 }
1432 } 1485 }
1433 #endif 1486 #endif
@@ -1438,19 +1491,29 @@ int SrsRtmpConn::http_hooks_on_play() @@ -1438,19 +1491,29 @@ int SrsRtmpConn::http_hooks_on_play()
1438 void SrsRtmpConn::http_hooks_on_stop() 1491 void SrsRtmpConn::http_hooks_on_stop()
1439 { 1492 {
1440 #ifdef SRS_AUTO_HTTP_CALLBACK 1493 #ifdef SRS_AUTO_HTTP_CALLBACK
1441 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
1442 - // whatever the ret code, notify the api hooks.  
1443 - // HTTP: on_stop  
1444 - SrsConfDirective* on_stop = _srs_config->get_vhost_on_stop(req->vhost);  
1445 - if (!on_stop) { 1494 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  1495 + return;
  1496 + }
  1497 +
  1498 + // the http hooks will cause context switch,
  1499 + // so we must copy all hooks for the on_connect may freed.
  1500 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  1501 + vector<string> hooks;
  1502 +
  1503 + if (true) {
  1504 + SrsConfDirective* conf = _srs_config->get_vhost_on_stop(req->vhost);
  1505 +
  1506 + if (!conf) {
1446 srs_info("ignore the empty http callback: on_stop"); 1507 srs_info("ignore the empty http callback: on_stop");
1447 return; 1508 return;
1448 } 1509 }
1449 1510
1450 - for (int i = 0; i < (int)on_stop->args.size(); i++) {  
1451 - std::string url = on_stop->args.at(i);  
1452 - SrsHttpHooks::on_stop(url, req);  
1453 - } 1511 + hooks = conf->args;
  1512 + }
  1513 +
  1514 + for (int i = 0; i < (int)hooks.size(); i++) {
  1515 + std::string url = hooks.at(i);
  1516 + SrsHttpHooks::on_stop(url, req);
1454 } 1517 }
1455 #endif 1518 #endif
1456 1519
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 // current release version 31 // current release version
32 #define VERSION_MAJOR 2 32 #define VERSION_MAJOR 2
33 #define VERSION_MINOR 0 33 #define VERSION_MINOR 0
34 -#define VERSION_REVISION 186 34 +#define VERSION_REVISION 187
35 35
36 // server info. 36 // server info.
37 #define RTMP_SIG_SRS_KEY "SRS" 37 #define RTMP_SIG_SRS_KEY "SRS"