fix #57, use lock(acquire/release publish) to avoid duplicated publishing. 0.9.188.
正在显示
6 个修改的文件
包含
109 行增加
和
33 行删除
@@ -207,6 +207,7 @@ Supported operating systems and hardware: | @@ -207,6 +207,7 @@ Supported operating systems and hardware: | ||
207 | * 2013-10-17, Created.<br/> | 207 | * 2013-10-17, Created.<br/> |
208 | 208 | ||
209 | ## History | 209 | ## History |
210 | +* v1.0, 2014-08-03, fix [#57](https://github.com/winlinvip/simple-rtmp-server/issues/57), use lock(acquire/release publish) to avoid duplicated publishing. 0.9.188. | ||
210 | * v1.0, 2014-08-03, fix [#85](https://github.com/winlinvip/simple-rtmp-server/issues/85), fix the segment-dvr sequence header missing. 0.9.187. | 211 | * v1.0, 2014-08-03, fix [#85](https://github.com/winlinvip/simple-rtmp-server/issues/85), fix the segment-dvr sequence header missing. 0.9.187. |
211 | * v1.0, 2014-08-03, fix [#145](https://github.com/winlinvip/simple-rtmp-server/issues/145), refine ffmpeg log, check abitrate for libaacplus. 0.9.186. | 212 | * v1.0, 2014-08-03, fix [#145](https://github.com/winlinvip/simple-rtmp-server/issues/145), refine ffmpeg log, check abitrate for libaacplus. 0.9.186. |
212 | * v1.0, 2014-08-03, fix [#143](https://github.com/winlinvip/simple-rtmp-server/issues/143), fix retrieve sys stat bug for all linux. 0.9.185. | 213 | * v1.0, 2014-08-03, fix [#143](https://github.com/winlinvip/simple-rtmp-server/issues/143), fix retrieve sys stat bug for all linux. 0.9.185. |
@@ -74,6 +74,9 @@ using namespace std; | @@ -74,6 +74,9 @@ using namespace std; | ||
74 | // when edge timeout, retry next. | 74 | // when edge timeout, retry next. |
75 | #define SRS_EDGE_TOKEN_TRAVERSE_TIMEOUT_US (int64_t)(3*1000*1000LL) | 75 | #define SRS_EDGE_TOKEN_TRAVERSE_TIMEOUT_US (int64_t)(3*1000*1000LL) |
76 | 76 | ||
77 | +// to get msgs then totally send out. | ||
78 | +#define SYS_MAX_PLAY_SEND_MSGS 128 | ||
79 | + | ||
77 | SrsRtmpConn::SrsRtmpConn(SrsServer* srs_server, st_netfd_t client_stfd) | 80 | SrsRtmpConn::SrsRtmpConn(SrsServer* srs_server, st_netfd_t client_stfd) |
78 | : SrsConnection(srs_server, client_stfd) | 81 | : SrsConnection(srs_server, client_stfd) |
79 | { | 82 | { |
@@ -318,10 +321,11 @@ int SrsRtmpConn::stream_service_cycle() | @@ -318,10 +321,11 @@ int SrsRtmpConn::stream_service_cycle() | ||
318 | } | 321 | } |
319 | srs_assert(source != NULL); | 322 | srs_assert(source != NULL); |
320 | 323 | ||
321 | - // check publish available | ||
322 | - // for edge, never check it, for edge use proxy mode. | ||
323 | - if (!vhost_is_edge) { | ||
324 | - if (type != SrsRtmpConnPlay && !source->can_publish()) { | 324 | + // check ASAP, to fail it faster if invalid. |
325 | + if (type != SrsRtmpConnPlay && !vhost_is_edge) { | ||
326 | + // check publish available | ||
327 | + // for edge, never check it, for edge use proxy mode. | ||
328 | + if (!source->can_publish()) { | ||
325 | ret = ERROR_SYSTEM_STREAM_BUSY; | 329 | ret = ERROR_SYSTEM_STREAM_BUSY; |
326 | srs_warn("stream %s is already publishing. ret=%d", | 330 | srs_warn("stream %s is already publishing. ret=%d", |
327 | req->get_stream_url().c_str(), ret); | 331 | req->get_stream_url().c_str(), ret); |
@@ -379,23 +383,18 @@ int SrsRtmpConn::stream_service_cycle() | @@ -379,23 +383,18 @@ int SrsRtmpConn::stream_service_cycle() | ||
379 | return ret; | 383 | return ret; |
380 | } | 384 | } |
381 | 385 | ||
382 | - if ((ret = http_hooks_on_publish()) != ERROR_SUCCESS) { | ||
383 | - srs_error("http hook on_publish failed. ret=%d", ret); | ||
384 | - return ret; | 386 | + if (!vhost_is_edge) { |
387 | + if ((ret = source->acquire_publish()) != ERROR_SUCCESS) { | ||
388 | + return ret; | ||
389 | + } | ||
385 | } | 390 | } |
386 | - | ||
387 | - srs_info("start to publish stream %s success", req->stream.c_str()); | 391 | + |
388 | ret = fmle_publishing(source); | 392 | ret = fmle_publishing(source); |
389 | - | ||
390 | - // when edge, notice edge to change state. | ||
391 | - // when origin, notice all service to unpublish. | ||
392 | - if (vhost_is_edge) { | ||
393 | - source->on_edge_proxy_unpublish(); | ||
394 | - } else { | ||
395 | - source->on_unpublish(); | 393 | + |
394 | + if (!vhost_is_edge) { | ||
395 | + source->release_publish(); | ||
396 | } | 396 | } |
397 | - | ||
398 | - http_hooks_on_unpublish(); | 397 | + |
399 | return ret; | 398 | return ret; |
400 | } | 399 | } |
401 | case SrsRtmpConnFlashPublish: { | 400 | case SrsRtmpConnFlashPublish: { |
@@ -413,23 +412,18 @@ int SrsRtmpConn::stream_service_cycle() | @@ -413,23 +412,18 @@ int SrsRtmpConn::stream_service_cycle() | ||
413 | return ret; | 412 | return ret; |
414 | } | 413 | } |
415 | 414 | ||
416 | - if ((ret = http_hooks_on_publish()) != ERROR_SUCCESS) { | ||
417 | - srs_error("http hook on_publish failed. ret=%d", ret); | ||
418 | - return ret; | 415 | + if (!vhost_is_edge) { |
416 | + if ((ret = source->acquire_publish()) != ERROR_SUCCESS) { | ||
417 | + return ret; | ||
418 | + } | ||
419 | } | 419 | } |
420 | 420 | ||
421 | - srs_info("flash start to publish stream %s success", req->stream.c_str()); | ||
422 | ret = flash_publishing(source); | 421 | ret = flash_publishing(source); |
423 | - | ||
424 | - // when edge, notice edge to change state. | ||
425 | - // when origin, notice all service to unpublish. | ||
426 | - if (vhost_is_edge) { | ||
427 | - source->on_edge_proxy_unpublish(); | ||
428 | - } else { | ||
429 | - source->on_unpublish(); | 422 | + |
423 | + if (!vhost_is_edge) { | ||
424 | + source->release_publish(); | ||
430 | } | 425 | } |
431 | 426 | ||
432 | - http_hooks_on_unpublish(); | ||
433 | return ret; | 427 | return ret; |
434 | } | 428 | } |
435 | default: { | 429 | default: { |
@@ -479,8 +473,6 @@ int SrsRtmpConn::check_vhost() | @@ -479,8 +473,6 @@ int SrsRtmpConn::check_vhost() | ||
479 | return ret; | 473 | return ret; |
480 | } | 474 | } |
481 | 475 | ||
482 | -#define SYS_MAX_PLAY_SEND_MSGS 128 | ||
483 | - | ||
484 | int SrsRtmpConn::playing(SrsSource* source) | 476 | int SrsRtmpConn::playing(SrsSource* source) |
485 | { | 477 | { |
486 | int ret = ERROR_SUCCESS; | 478 | int ret = ERROR_SUCCESS; |
@@ -605,6 +597,33 @@ int SrsRtmpConn::fmle_publishing(SrsSource* source) | @@ -605,6 +597,33 @@ int SrsRtmpConn::fmle_publishing(SrsSource* source) | ||
605 | { | 597 | { |
606 | int ret = ERROR_SUCCESS; | 598 | int ret = ERROR_SUCCESS; |
607 | 599 | ||
600 | + bool vhost_is_edge = _srs_config->get_vhost_is_edge(req->vhost); | ||
601 | + | ||
602 | + if ((ret = http_hooks_on_publish()) != ERROR_SUCCESS) { | ||
603 | + srs_error("http hook on_publish failed. ret=%d", ret); | ||
604 | + return ret; | ||
605 | + } | ||
606 | + | ||
607 | + srs_info("start to publish stream %s success", req->stream.c_str()); | ||
608 | + ret = do_fmle_publishing(source); | ||
609 | + | ||
610 | + // when edge, notice edge to change state. | ||
611 | + // when origin, notice all service to unpublish. | ||
612 | + if (vhost_is_edge) { | ||
613 | + source->on_edge_proxy_unpublish(); | ||
614 | + } else { | ||
615 | + source->on_unpublish(); | ||
616 | + } | ||
617 | + | ||
618 | + http_hooks_on_unpublish(); | ||
619 | + | ||
620 | + return ret; | ||
621 | +} | ||
622 | + | ||
623 | +int SrsRtmpConn::do_fmle_publishing(SrsSource* source) | ||
624 | +{ | ||
625 | + int ret = ERROR_SUCCESS; | ||
626 | + | ||
608 | if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_publish(req->vhost))) != ERROR_SUCCESS) { | 627 | if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_publish(req->vhost))) != ERROR_SUCCESS) { |
609 | srs_error("fmle check publish_refer failed. ret=%d", ret); | 628 | srs_error("fmle check publish_refer failed. ret=%d", ret); |
610 | return ret; | 629 | return ret; |
@@ -684,6 +703,33 @@ int SrsRtmpConn::flash_publishing(SrsSource* source) | @@ -684,6 +703,33 @@ int SrsRtmpConn::flash_publishing(SrsSource* source) | ||
684 | { | 703 | { |
685 | int ret = ERROR_SUCCESS; | 704 | int ret = ERROR_SUCCESS; |
686 | 705 | ||
706 | + bool vhost_is_edge = _srs_config->get_vhost_is_edge(req->vhost); | ||
707 | + | ||
708 | + if ((ret = http_hooks_on_publish()) != ERROR_SUCCESS) { | ||
709 | + srs_error("http hook on_publish failed. ret=%d", ret); | ||
710 | + return ret; | ||
711 | + } | ||
712 | + | ||
713 | + srs_info("flash start to publish stream %s success", req->stream.c_str()); | ||
714 | + ret = do_flash_publishing(source); | ||
715 | + | ||
716 | + // when edge, notice edge to change state. | ||
717 | + // when origin, notice all service to unpublish. | ||
718 | + if (vhost_is_edge) { | ||
719 | + source->on_edge_proxy_unpublish(); | ||
720 | + } else { | ||
721 | + source->on_unpublish(); | ||
722 | + } | ||
723 | + | ||
724 | + http_hooks_on_unpublish(); | ||
725 | + | ||
726 | + return ret; | ||
727 | +} | ||
728 | + | ||
729 | +int SrsRtmpConn::do_flash_publishing(SrsSource* source) | ||
730 | +{ | ||
731 | + int ret = ERROR_SUCCESS; | ||
732 | + | ||
687 | if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_publish(req->vhost))) != ERROR_SUCCESS) { | 733 | if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_publish(req->vhost))) != ERROR_SUCCESS) { |
688 | srs_error("flash check publish_refer failed. ret=%d", ret); | 734 | srs_error("flash check publish_refer failed. ret=%d", ret); |
689 | return ret; | 735 | return ret; |
@@ -89,7 +89,9 @@ private: | @@ -89,7 +89,9 @@ private: | ||
89 | virtual int check_vhost(); | 89 | virtual int check_vhost(); |
90 | virtual int playing(SrsSource* source); | 90 | virtual int playing(SrsSource* source); |
91 | virtual int fmle_publishing(SrsSource* source); | 91 | virtual int fmle_publishing(SrsSource* source); |
92 | + virtual int do_fmle_publishing(SrsSource* source); | ||
92 | virtual int flash_publishing(SrsSource* source); | 93 | virtual int flash_publishing(SrsSource* source); |
94 | + virtual int do_flash_publishing(SrsSource* source); | ||
93 | virtual int process_publish_message(SrsSource* source, SrsMessage* msg, bool vhost_is_edge); | 95 | virtual int process_publish_message(SrsSource* source, SrsMessage* msg, bool vhost_is_edge); |
94 | virtual int process_play_control_msg(SrsConsumer* consumer, SrsMessage* msg); | 96 | virtual int process_play_control_msg(SrsConsumer* consumer, SrsMessage* msg); |
95 | private: | 97 | private: |
@@ -1347,6 +1347,26 @@ int SrsSource::on_aggregate(SrsMessage* msg) | @@ -1347,6 +1347,26 @@ int SrsSource::on_aggregate(SrsMessage* msg) | ||
1347 | return ret; | 1347 | return ret; |
1348 | } | 1348 | } |
1349 | 1349 | ||
1350 | +int SrsSource::acquire_publish() | ||
1351 | +{ | ||
1352 | + int ret = ERROR_SUCCESS; | ||
1353 | + | ||
1354 | + if (!_can_publish) { | ||
1355 | + ret = ERROR_SYSTEM_STREAM_BUSY; | ||
1356 | + srs_warn("publish lock stream failed, ret=%d", ret); | ||
1357 | + return ret; | ||
1358 | + } | ||
1359 | + | ||
1360 | + _can_publish = false; | ||
1361 | + | ||
1362 | + return ret; | ||
1363 | +} | ||
1364 | + | ||
1365 | +void SrsSource::release_publish() | ||
1366 | +{ | ||
1367 | + _can_publish = true; | ||
1368 | +} | ||
1369 | + | ||
1350 | int SrsSource::on_publish() | 1370 | int SrsSource::on_publish() |
1351 | { | 1371 | { |
1352 | int ret = ERROR_SUCCESS; | 1372 | int ret = ERROR_SUCCESS; |
@@ -369,6 +369,13 @@ public: | @@ -369,6 +369,13 @@ public: | ||
369 | virtual int on_video(SrsMessage* video); | 369 | virtual int on_video(SrsMessage* video); |
370 | virtual int on_aggregate(SrsMessage* msg); | 370 | virtual int on_aggregate(SrsMessage* msg); |
371 | /** | 371 | /** |
372 | + * the pre-publish is we are very sure we are | ||
373 | + * trying to publish stream, please lock the resource, | ||
374 | + * and we use release_publish() to release the resource. | ||
375 | + */ | ||
376 | + virtual int acquire_publish(); | ||
377 | + virtual void release_publish(); | ||
378 | + /** | ||
372 | * publish stream event notify. | 379 | * publish stream event notify. |
373 | * @param _req the request from client, the source will deep copy it, | 380 | * @param _req the request from client, the source will deep copy it, |
374 | * for when reload the request of client maybe invalid. | 381 | * for when reload the request of client maybe invalid. |
@@ -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 "0" | 32 | #define VERSION_MAJOR "0" |
33 | #define VERSION_MINOR "9" | 33 | #define VERSION_MINOR "9" |
34 | -#define VERSION_REVISION "187" | 34 | +#define VERSION_REVISION "188" |
35 | #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION | 35 | #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION |
36 | // server info. | 36 | // server info. |
37 | #define RTMP_SIG_SRS_KEY "SRS" | 37 | #define RTMP_SIG_SRS_KEY "SRS" |
-
请 注册 或 登录 后发表评论