winlin

merge from 2.0

@@ -1045,6 +1045,7 @@ Winlin @@ -1045,6 +1045,7 @@ Winlin
1045 [bug #367]: https://github.com/simple-rtmp-server/srs/issues/367 1045 [bug #367]: https://github.com/simple-rtmp-server/srs/issues/367
1046 [bug #471]: https://github.com/simple-rtmp-server/srs/issues/471 1046 [bug #471]: https://github.com/simple-rtmp-server/srs/issues/471
1047 [bug #380]: https://github.com/simple-rtmp-server/srs/issues/380 1047 [bug #380]: https://github.com/simple-rtmp-server/srs/issues/380
  1048 +[bug #475]: https://github.com/simple-rtmp-server/srs/issues/475
1048 [bug #454]: https://github.com/simple-rtmp-server/srs/issues/454 1049 [bug #454]: https://github.com/simple-rtmp-server/srs/issues/454
1049 [bug #442]: https://github.com/simple-rtmp-server/srs/issues/442 1050 [bug #442]: https://github.com/simple-rtmp-server/srs/issues/442
1050 [bug #169]: https://github.com/simple-rtmp-server/srs/issues/169 1051 [bug #169]: https://github.com/simple-rtmp-server/srs/issues/169
@@ -512,24 +512,33 @@ int SrsDvrAsyncCallOnDvr::call() @@ -512,24 +512,33 @@ 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) { 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) {
528 srs_error("hook client on_dvr failed. url=%s, ret=%d", url.c_str(), ret); 538 srs_error("hook client on_dvr failed. url=%s, ret=%d", url.c_str(), ret);
529 return ret; 539 return ret;
530 } 540 }
531 } 541 }
532 - }  
533 #endif 542 #endif
534 543
535 return ret; 544 return ret;
@@ -198,25 +198,33 @@ int SrsDvrAsyncCallOnHls::call() @@ -198,25 +198,33 @@ 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) { 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) {
215 srs_error("hook client on_hls failed. url=%s, ret=%d", url.c_str(), ret); 224 srs_error("hook client on_hls failed. url=%s, ret=%d", url.c_str(), ret);
216 return ret; 225 return ret;
217 } 226 }
218 } 227 }
219 - }  
220 #endif 228 #endif
221 229
222 return ret; 230 return ret;
@@ -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) {  
251 - srs_info("ignore the empty http callback: on_hls_notify"); 254 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
252 return ret; 255 return ret;
253 } 256 }
254 257
255 - std::string url; 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 +
256 if (true) { 263 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); 264 + SrsConfDirective* conf = _srs_config->get_vhost_on_hls_notify(req->vhost);
  265 +
  266 + if (!conf) {
  267 + srs_info("ignore the empty http callback: on_hls_notify");
  268 + return ret;
  269 + }
  270 +
  271 + hooks = conf->args;
260 } 272 }
261 273
262 int nb_notify = _srs_config->get_vhost_hls_nb_notify(req->vhost); 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 }
@@ -1304,22 +1304,33 @@ int SrsRtmpConn::http_hooks_on_connect() @@ -1304,22 +1304,33 @@ int SrsRtmpConn::http_hooks_on_connect()
1304 int ret = ERROR_SUCCESS; 1304 int ret = ERROR_SUCCESS;
1305 1305
1306 #ifdef SRS_AUTO_HTTP_CALLBACK 1306 #ifdef SRS_AUTO_HTTP_CALLBACK
1307 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
1308 - // HTTP: on_connect  
1309 - SrsConfDirective* on_connect = _srs_config->get_vhost_on_connect(req->vhost);  
1310 - if (!on_connect) { 1307 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  1308 + return ret;
  1309 + }
  1310 +
  1311 + // the http hooks will cause context switch,
  1312 + // so we must copy all hooks for the on_connect may freed.
  1313 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  1314 + vector<string> hooks;
  1315 +
  1316 + if (true) {
  1317 + SrsConfDirective* conf = _srs_config->get_vhost_on_connect(req->vhost);
  1318 +
  1319 + if (!conf) {
1311 srs_info("ignore the empty http callback: on_connect"); 1320 srs_info("ignore the empty http callback: on_connect");
1312 return ret; 1321 return ret;
1313 } 1322 }
1314 1323
1315 - for (int i = 0; i < (int)on_connect->args.size(); i++) {  
1316 - std::string url = on_connect->args.at(i); 1324 + hooks = conf->args;
  1325 + }
  1326 +
  1327 + for (int i = 0; i < (int)hooks.size(); i++) {
  1328 + std::string url = hooks.at(i);
1317 if ((ret = SrsHttpHooks::on_connect(url, req)) != ERROR_SUCCESS) { 1329 if ((ret = SrsHttpHooks::on_connect(url, req)) != ERROR_SUCCESS) {
1318 srs_error("hook client on_connect failed. url=%s, ret=%d", url.c_str(), ret); 1330 srs_error("hook client on_connect failed. url=%s, ret=%d", url.c_str(), ret);
1319 return ret; 1331 return ret;
1320 } 1332 }
1321 } 1333 }
1322 - }  
1323 #endif 1334 #endif
1324 1335
1325 return ret; 1336 return ret;
@@ -1328,19 +1339,29 @@ int SrsRtmpConn::http_hooks_on_connect() @@ -1328,19 +1339,29 @@ int SrsRtmpConn::http_hooks_on_connect()
1328 void SrsRtmpConn::http_hooks_on_close() 1339 void SrsRtmpConn::http_hooks_on_close()
1329 { 1340 {
1330 #ifdef SRS_AUTO_HTTP_CALLBACK 1341 #ifdef SRS_AUTO_HTTP_CALLBACK
1331 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
1332 - // whatever the ret code, notify the api hooks.  
1333 - // HTTP: on_close  
1334 - SrsConfDirective* on_close = _srs_config->get_vhost_on_close(req->vhost);  
1335 - if (!on_close) { 1342 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  1343 + return;
  1344 + }
  1345 +
  1346 + // the http hooks will cause context switch,
  1347 + // so we must copy all hooks for the on_connect may freed.
  1348 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  1349 + vector<string> hooks;
  1350 +
  1351 + if (true) {
  1352 + SrsConfDirective* conf = _srs_config->get_vhost_on_close(req->vhost);
  1353 +
  1354 + if (!conf) {
1336 srs_info("ignore the empty http callback: on_close"); 1355 srs_info("ignore the empty http callback: on_close");
1337 return; 1356 return;
1338 } 1357 }
1339 1358
1340 - for (int i = 0; i < (int)on_close->args.size(); i++) {  
1341 - std::string url = on_close->args.at(i);  
1342 - SrsHttpHooks::on_close(url, req, kbps->get_send_bytes(), kbps->get_recv_bytes()); 1359 + hooks = conf->args;
1343 } 1360 }
  1361 +
  1362 + for (int i = 0; i < (int)hooks.size(); i++) {
  1363 + std::string url = hooks.at(i);
  1364 + SrsHttpHooks::on_close(url, req, kbps->get_send_bytes(), kbps->get_recv_bytes());
1344 } 1365 }
1345 #endif 1366 #endif
1346 } 1367 }
@@ -1350,22 +1371,33 @@ int SrsRtmpConn::http_hooks_on_publish() @@ -1350,22 +1371,33 @@ int SrsRtmpConn::http_hooks_on_publish()
1350 int ret = ERROR_SUCCESS; 1371 int ret = ERROR_SUCCESS;
1351 1372
1352 #ifdef SRS_AUTO_HTTP_CALLBACK 1373 #ifdef SRS_AUTO_HTTP_CALLBACK
1353 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
1354 - // HTTP: on_publish  
1355 - SrsConfDirective* on_publish = _srs_config->get_vhost_on_publish(req->vhost);  
1356 - if (!on_publish) { 1374 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  1375 + return ret;
  1376 + }
  1377 +
  1378 + // the http hooks will cause context switch,
  1379 + // so we must copy all hooks for the on_connect may freed.
  1380 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  1381 + vector<string> hooks;
  1382 +
  1383 + if (true) {
  1384 + SrsConfDirective* conf = _srs_config->get_vhost_on_publish(req->vhost);
  1385 +
  1386 + if (!conf) {
1357 srs_info("ignore the empty http callback: on_publish"); 1387 srs_info("ignore the empty http callback: on_publish");
1358 return ret; 1388 return ret;
1359 } 1389 }
1360 1390
1361 - for (int i = 0; i < (int)on_publish->args.size(); i++) {  
1362 - std::string url = on_publish->args.at(i); 1391 + hooks = conf->args;
  1392 + }
  1393 +
  1394 + for (int i = 0; i < (int)hooks.size(); i++) {
  1395 + std::string url = hooks.at(i);
1363 if ((ret = SrsHttpHooks::on_publish(url, req)) != ERROR_SUCCESS) { 1396 if ((ret = SrsHttpHooks::on_publish(url, req)) != ERROR_SUCCESS) {
1364 srs_error("hook client on_publish failed. url=%s, ret=%d", url.c_str(), ret); 1397 srs_error("hook client on_publish failed. url=%s, ret=%d", url.c_str(), ret);
1365 return ret; 1398 return ret;
1366 } 1399 }
1367 } 1400 }
1368 - }  
1369 #endif 1401 #endif
1370 1402
1371 return ret; 1403 return ret;
@@ -1374,19 +1406,29 @@ int SrsRtmpConn::http_hooks_on_publish() @@ -1374,19 +1406,29 @@ int SrsRtmpConn::http_hooks_on_publish()
1374 void SrsRtmpConn::http_hooks_on_unpublish() 1406 void SrsRtmpConn::http_hooks_on_unpublish()
1375 { 1407 {
1376 #ifdef SRS_AUTO_HTTP_CALLBACK 1408 #ifdef SRS_AUTO_HTTP_CALLBACK
1377 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
1378 - // whatever the ret code, notify the api hooks.  
1379 - // HTTP: on_unpublish  
1380 - SrsConfDirective* on_unpublish = _srs_config->get_vhost_on_unpublish(req->vhost);  
1381 - if (!on_unpublish) { 1409 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  1410 + return;
  1411 + }
  1412 +
  1413 + // the http hooks will cause context switch,
  1414 + // so we must copy all hooks for the on_connect may freed.
  1415 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  1416 + vector<string> hooks;
  1417 +
  1418 + if (true) {
  1419 + SrsConfDirective* conf = _srs_config->get_vhost_on_unpublish(req->vhost);
  1420 +
  1421 + if (!conf) {
1382 srs_info("ignore the empty http callback: on_unpublish"); 1422 srs_info("ignore the empty http callback: on_unpublish");
1383 return; 1423 return;
1384 } 1424 }
1385 1425
1386 - for (int i = 0; i < (int)on_unpublish->args.size(); i++) {  
1387 - std::string url = on_unpublish->args.at(i);  
1388 - SrsHttpHooks::on_unpublish(url, req); 1426 + hooks = conf->args;
1389 } 1427 }
  1428 +
  1429 + for (int i = 0; i < (int)hooks.size(); i++) {
  1430 + std::string url = hooks.at(i);
  1431 + SrsHttpHooks::on_unpublish(url, req);
1390 } 1432 }
1391 #endif 1433 #endif
1392 } 1434 }
@@ -1396,22 +1438,33 @@ int SrsRtmpConn::http_hooks_on_play() @@ -1396,22 +1438,33 @@ int SrsRtmpConn::http_hooks_on_play()
1396 int ret = ERROR_SUCCESS; 1438 int ret = ERROR_SUCCESS;
1397 1439
1398 #ifdef SRS_AUTO_HTTP_CALLBACK 1440 #ifdef SRS_AUTO_HTTP_CALLBACK
1399 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
1400 - // HTTP: on_play  
1401 - SrsConfDirective* on_play = _srs_config->get_vhost_on_play(req->vhost);  
1402 - if (!on_play) { 1441 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  1442 + return ret;
  1443 + }
  1444 +
  1445 + // the http hooks will cause context switch,
  1446 + // so we must copy all hooks for the on_connect may freed.
  1447 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  1448 + vector<string> hooks;
  1449 +
  1450 + if (true) {
  1451 + SrsConfDirective* conf = _srs_config->get_vhost_on_play(req->vhost);
  1452 +
  1453 + if (!conf) {
1403 srs_info("ignore the empty http callback: on_play"); 1454 srs_info("ignore the empty http callback: on_play");
1404 return ret; 1455 return ret;
1405 } 1456 }
1406 1457
1407 - for (int i = 0; i < (int)on_play->args.size(); i++) {  
1408 - std::string url = on_play->args.at(i); 1458 + hooks = conf->args;
  1459 + }
  1460 +
  1461 + for (int i = 0; i < (int)hooks.size(); i++) {
  1462 + std::string url = hooks.at(i);
1409 if ((ret = SrsHttpHooks::on_play(url, req)) != ERROR_SUCCESS) { 1463 if ((ret = SrsHttpHooks::on_play(url, req)) != ERROR_SUCCESS) {
1410 srs_error("hook client on_play failed. url=%s, ret=%d", url.c_str(), ret); 1464 srs_error("hook client on_play failed. url=%s, ret=%d", url.c_str(), ret);
1411 return ret; 1465 return ret;
1412 } 1466 }
1413 } 1467 }
1414 - }  
1415 #endif 1468 #endif
1416 1469
1417 return ret; 1470 return ret;
@@ -1420,19 +1473,29 @@ int SrsRtmpConn::http_hooks_on_play() @@ -1420,19 +1473,29 @@ int SrsRtmpConn::http_hooks_on_play()
1420 void SrsRtmpConn::http_hooks_on_stop() 1473 void SrsRtmpConn::http_hooks_on_stop()
1421 { 1474 {
1422 #ifdef SRS_AUTO_HTTP_CALLBACK 1475 #ifdef SRS_AUTO_HTTP_CALLBACK
1423 - if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {  
1424 - // whatever the ret code, notify the api hooks.  
1425 - // HTTP: on_stop  
1426 - SrsConfDirective* on_stop = _srs_config->get_vhost_on_stop(req->vhost);  
1427 - if (!on_stop) { 1476 + if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
  1477 + return;
  1478 + }
  1479 +
  1480 + // the http hooks will cause context switch,
  1481 + // so we must copy all hooks for the on_connect may freed.
  1482 + // @see https://github.com/simple-rtmp-server/srs/issues/475
  1483 + vector<string> hooks;
  1484 +
  1485 + if (true) {
  1486 + SrsConfDirective* conf = _srs_config->get_vhost_on_stop(req->vhost);
  1487 +
  1488 + if (!conf) {
1428 srs_info("ignore the empty http callback: on_stop"); 1489 srs_info("ignore the empty http callback: on_stop");
1429 return; 1490 return;
1430 } 1491 }
1431 1492
1432 - for (int i = 0; i < (int)on_stop->args.size(); i++) {  
1433 - std::string url = on_stop->args.at(i);  
1434 - SrsHttpHooks::on_stop(url, req); 1493 + hooks = conf->args;
1435 } 1494 }
  1495 +
  1496 + for (int i = 0; i < (int)hooks.size(); i++) {
  1497 + std::string url = hooks.at(i);
  1498 + SrsHttpHooks::on_stop(url, req);
1436 } 1499 }
1437 #endif 1500 #endif
1438 1501