winlin

for bug #217, use isolate thread to improve 17% performance.

@@ -493,10 +493,117 @@ int SrsRtmpConn::check_vhost() @@ -493,10 +493,117 @@ int SrsRtmpConn::check_vhost()
493 return ret; 493 return ret;
494 } 494 }
495 495
  496 +class IsolateRecvThread : public ISrsThreadHandler
  497 +{
  498 +private:
  499 + SrsThread* trd;
  500 + SrsRtmpServer* rtmp;
  501 + std::vector<SrsMessage*> queue;
  502 +public:
  503 + IsolateRecvThread(SrsRtmpServer* rtmp_sdk)
  504 + {
  505 + rtmp = rtmp_sdk;
  506 + trd = new SrsThread(this, 0, true);
  507 + }
  508 + virtual ~IsolateRecvThread()
  509 + {
  510 + // stop recv thread.
  511 + stop();
  512 +
  513 + // destroy the thread.
  514 + srs_freep(trd);
  515 +
  516 + // clear all messages.
  517 + std::vector<SrsMessage*>::iterator it;
  518 + for (it = queue.begin(); it != queue.end(); ++it) {
  519 + SrsMessage* msg = *it;
  520 + srs_freep(msg);
  521 + }
  522 + queue.clear();
  523 + }
  524 +public:
  525 + virtual bool empty()
  526 + {
  527 + return queue.empty();
  528 + }
  529 + virtual SrsMessage* pump()
  530 + {
  531 + SrsMessage* msg = *queue.begin();
  532 + queue.erase(queue.begin());
  533 + return msg;
  534 + }
  535 +public:
  536 + virtual int start()
  537 + {
  538 + return trd->start();
  539 + }
  540 + virtual void stop()
  541 + {
  542 + trd->stop();
  543 + }
  544 + virtual int cycle()
  545 + {
  546 + int ret = ERROR_SUCCESS;
  547 +
  548 + SrsMessage* msg = NULL;
  549 +
  550 + if ((ret = rtmp->recv_message(&msg)) != ERROR_SUCCESS) {
  551 + if (!srs_is_client_gracefully_close(ret)) {
  552 + srs_error("recv client control message failed. ret=%d", ret);
  553 + }
  554 +
  555 + // we use no timeout to recv, should never got any error.
  556 + trd->stop_loop();
  557 +
  558 + return ret;
  559 + }
  560 + srs_verbose("play loop recv message. ret=%d", ret);
  561 +
  562 + return ret;
  563 + }
  564 +};
  565 +
496 int SrsRtmpConn::playing(SrsSource* source) 566 int SrsRtmpConn::playing(SrsSource* source)
497 { 567 {
498 int ret = ERROR_SUCCESS; 568 int ret = ERROR_SUCCESS;
499 569
  570 + // the multiple messages writev improve performance large,
  571 + // but the timeout recv will cause 33% sys call performance,
  572 + // to use isolate thread to recv, can improve about 33% performance.
  573 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/194
  574 + // @see: https://github.com/winlinvip/simple-rtmp-server/issues/217
  575 + //rtmp->set_recv_timeout(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US);
  576 + rtmp->set_recv_timeout(ST_UTIME_NO_TIMEOUT);
  577 +
  578 + // disable the protocol auto response,
  579 + // for the isolate recv thread should never send any messages.
  580 + rtmp->set_auto_response(false);
  581 +
  582 + // use isolate thread to recv,
  583 + // start isolate recv thread.
  584 + IsolateRecvThread trd(rtmp);
  585 + if ((ret = trd.start()) != ERROR_SUCCESS) {
  586 + srs_error("start isolate recv thread failed. ret=%d", ret);
  587 + return ret;
  588 + }
  589 +
  590 + // delivery messages for clients playing stream.
  591 + ret = do_playing(source, &trd);
  592 +
  593 + // stop isolate recv thread
  594 + trd.stop();
  595 +
  596 + // enable the protocol auto response,
  597 + // for the isolate recv thread terminated.
  598 + rtmp->set_auto_response(true);
  599 +
  600 + return ret;
  601 +}
  602 +
  603 +int SrsRtmpConn::do_playing(SrsSource* source, IsolateRecvThread* trd)
  604 +{
  605 + int ret = ERROR_SUCCESS;
  606 +
500 if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_play(req->vhost))) != ERROR_SUCCESS) { 607 if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_play(req->vhost))) != ERROR_SUCCESS) {
501 srs_error("check play_refer failed. ret=%d", ret); 608 srs_error("check play_refer failed. ret=%d", ret);
502 return ret; 609 return ret;
@@ -519,38 +626,19 @@ int SrsRtmpConn::playing(SrsSource* source) @@ -519,38 +626,19 @@ int SrsRtmpConn::playing(SrsSource* source)
519 bool user_specified_duration_to_stop = (req->duration > 0); 626 bool user_specified_duration_to_stop = (req->duration > 0);
520 int64_t starttime = -1; 627 int64_t starttime = -1;
521 628
522 - // TODO: use isolate thread to recv,  
523 - // @see: https://github.com/winlinvip/simple-rtmp-server/issues/196  
524 - // the performance bottleneck not in the timeout recv, but  
525 - // in the multiple messages send, so it's ok for timeout recv,  
526 - // @see https://github.com/winlinvip/simple-rtmp-server/issues/194  
527 - rtmp->set_recv_timeout(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US);  
528 -  
529 while (true) { 629 while (true) {
530 - // TODO: to use isolate thread to recv, can improve about 5% performance. 630 + // to use isolate thread to recv, can improve about 33% performance.
531 // @see: https://github.com/winlinvip/simple-rtmp-server/issues/196 631 // @see: https://github.com/winlinvip/simple-rtmp-server/issues/196
532 - // read from client.  
533 - if (true) {  
534 - SrsMessage* msg = NULL;  
535 - ret = rtmp->recv_message(&msg);  
536 - srs_verbose("play loop recv message. ret=%d", ret); 632 + // @see: https://github.com/winlinvip/simple-rtmp-server/issues/217
  633 + while (!trd->empty()) {
  634 + SrsMessage* msg = trd->pump();
  635 + srs_warn("pump client message to process.");
537 636
538 - if (ret == ERROR_SOCKET_TIMEOUT) {  
539 - // it's ok, do nothing.  
540 - ret = ERROR_SUCCESS;  
541 - srs_verbose("recv timeout, ignore. ret=%d", ret);  
542 - } else if (ret != ERROR_SUCCESS) {  
543 - if (!srs_is_client_gracefully_close(ret)) {  
544 - srs_error("recv client control message failed. ret=%d", ret); 637 + if ((ret = process_play_control_msg(consumer, msg)) != ERROR_SUCCESS) {
  638 + if (!srs_is_system_control_error(ret)) {
  639 + srs_error("process play control message failed. ret=%d", ret);
545 } 640 }
546 return ret; 641 return ret;
547 - } else {  
548 - if ((ret = process_play_control_msg(consumer, msg)) != ERROR_SUCCESS) {  
549 - if (!srs_is_system_control_error(ret)) {  
550 - srs_error("process play control message failed. ret=%d", ret);  
551 - }  
552 - return ret;  
553 - }  
554 } 642 }
555 } 643 }
556 644
@@ -564,6 +652,12 @@ int SrsRtmpConn::playing(SrsSource* source) @@ -564,6 +652,12 @@ int SrsRtmpConn::playing(SrsSource* source)
564 srs_error("get messages from consumer failed. ret=%d", ret); 652 srs_error("get messages from consumer failed. ret=%d", ret);
565 return ret; 653 return ret;
566 } 654 }
  655 +
  656 + // no message to send, sleep a while.
  657 + if (count <= 0) {
  658 + srs_verbose("sleep for no messages to send");
  659 + st_usleep(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US);
  660 + }
567 661
568 // reportable 662 // reportable
569 if (pithy_print.can_print()) { 663 if (pithy_print.can_print()) {
@@ -596,7 +690,9 @@ int SrsRtmpConn::playing(SrsSource* source) @@ -596,7 +690,9 @@ int SrsRtmpConn::playing(SrsSource* source)
596 if (count > 0) { 690 if (count > 0) {
597 // no need to assert msg, for the rtmp will assert it. 691 // no need to assert msg, for the rtmp will assert it.
598 if ((ret = rtmp->send_and_free_messages(msgs.msgs, count, res->stream_id)) != ERROR_SUCCESS) { 692 if ((ret = rtmp->send_and_free_messages(msgs.msgs, count, res->stream_id)) != ERROR_SUCCESS) {
599 - srs_error("send messages to client failed. ret=%d", ret); 693 + if (!srs_is_client_gracefully_close(ret)) {
  694 + srs_error("send messages to client failed. ret=%d", ret);
  695 + }
600 return ret; 696 return ret;
601 } 697 }
602 } 698 }
@@ -49,6 +49,7 @@ class SrsBandwidth; @@ -49,6 +49,7 @@ class SrsBandwidth;
49 class SrsKbps; 49 class SrsKbps;
50 class SrsRtmpClient; 50 class SrsRtmpClient;
51 class SrsSharedPtrMessage; 51 class SrsSharedPtrMessage;
  52 +class IsolateRecvThread;
52 53
53 /** 54 /**
54 * the client provides the main logic control for RTMP clients. 55 * the client provides the main logic control for RTMP clients.
@@ -88,6 +89,7 @@ private: @@ -88,6 +89,7 @@ private:
88 virtual int stream_service_cycle(); 89 virtual int stream_service_cycle();
89 virtual int check_vhost(); 90 virtual int check_vhost();
90 virtual int playing(SrsSource* source); 91 virtual int playing(SrsSource* source);
  92 + virtual int do_playing(SrsSource* source, IsolateRecvThread* trd);
91 virtual int fmle_publishing(SrsSource* source); 93 virtual int fmle_publishing(SrsSource* source);
92 virtual int do_fmle_publishing(SrsSource* source); 94 virtual int do_fmle_publishing(SrsSource* source);
93 virtual int flash_publishing(SrsSource* source); 95 virtual int flash_publishing(SrsSource* source);
@@ -161,7 +161,9 @@ void SrsThread::thread_cycle() @@ -161,7 +161,9 @@ void SrsThread::thread_cycle()
161 srs_info("thread on before cycle success"); 161 srs_info("thread on before cycle success");
162 162
163 if ((ret = handler->cycle()) != ERROR_SUCCESS) { 163 if ((ret = handler->cycle()) != ERROR_SUCCESS) {
164 - srs_warn("thread cycle failed, ignored and retry, ret=%d", ret); 164 + if (!srs_is_client_gracefully_close(ret)) {
  165 + srs_warn("thread cycle failed, ignored and retry, ret=%d", ret);
  166 + }
165 goto failed; 167 goto failed;
166 } 168 }
167 srs_info("thread cycle success"); 169 srs_info("thread cycle success");
@@ -735,6 +735,11 @@ SrsRtmpServer::~SrsRtmpServer() @@ -735,6 +735,11 @@ SrsRtmpServer::~SrsRtmpServer()
735 srs_freep(hs_bytes); 735 srs_freep(hs_bytes);
736 } 736 }
737 737
  738 +void SrsRtmpServer::set_auto_response(bool v)
  739 +{
  740 + protocol->set_auto_response(v);
  741 +}
  742 +
738 void SrsRtmpServer::set_recv_timeout(int64_t timeout_us) 743 void SrsRtmpServer::set_recv_timeout(int64_t timeout_us)
739 { 744 {
740 protocol->set_recv_timeout(timeout_us); 745 protocol->set_recv_timeout(timeout_us);
@@ -335,6 +335,12 @@ public: @@ -335,6 +335,12 @@ public:
335 // protocol methods proxy 335 // protocol methods proxy
336 public: 336 public:
337 /** 337 /**
  338 + * set the auto response message when recv for protocol stack.
  339 + * @param v, whether auto response message when recv message.
  340 + * @see: https://github.com/winlinvip/simple-rtmp-server/issues/217
  341 + */
  342 + virtual void set_auto_response(bool v);
  343 + /**
338 * set/get the recv timeout in us. 344 * set/get the recv timeout in us.
339 * if timeout, recv/send message return ERROR_SOCKET_TIMEOUT. 345 * if timeout, recv/send message return ERROR_SOCKET_TIMEOUT.
340 */ 346 */
@@ -415,6 +415,7 @@ SrsProtocol::SrsProtocol(ISrsProtocolReaderWriter* io) @@ -415,6 +415,7 @@ SrsProtocol::SrsProtocol(ISrsProtocolReaderWriter* io)
415 srs_assert(nb_out_iovs >= 2); 415 srs_assert(nb_out_iovs >= 2);
416 416
417 warned_c0c3_cache_dry = false; 417 warned_c0c3_cache_dry = false;
  418 + auto_response_when_recv = true;
418 } 419 }
419 420
420 SrsProtocol::~SrsProtocol() 421 SrsProtocol::~SrsProtocol()
@@ -430,6 +431,15 @@ SrsProtocol::~SrsProtocol() @@ -430,6 +431,15 @@ SrsProtocol::~SrsProtocol()
430 chunk_streams.clear(); 431 chunk_streams.clear();
431 } 432 }
432 433
  434 + if (true) {
  435 + std::vector<SrsPacket*>::iterator it;
  436 + for (it = manual_response_queue.begin(); it != manual_response_queue.end(); ++it) {
  437 + SrsPacket* pkt = *it;
  438 + srs_freep(pkt);
  439 + }
  440 + manual_response_queue.clear();
  441 + }
  442 +
433 srs_freep(in_buffer); 443 srs_freep(in_buffer);
434 444
435 // alloc by malloc, use free directly. 445 // alloc by malloc, use free directly.
@@ -439,6 +449,35 @@ SrsProtocol::~SrsProtocol() @@ -439,6 +449,35 @@ SrsProtocol::~SrsProtocol()
439 } 449 }
440 } 450 }
441 451
  452 +void SrsProtocol::set_auto_response(bool v)
  453 +{
  454 + auto_response_when_recv = v;
  455 +}
  456 +
  457 +int SrsProtocol::manual_response_flush()
  458 +{
  459 + int ret = ERROR_SUCCESS;
  460 +
  461 + if (manual_response_queue.empty()) {
  462 + return ret;
  463 + }
  464 +
  465 + std::vector<SrsPacket*>::iterator it;
  466 + for (it = manual_response_queue.begin(); it != manual_response_queue.end();) {
  467 + SrsPacket* pkt = *it;
  468 +
  469 + // erase this packet, the send api always free it.
  470 + it = manual_response_queue.erase(it);
  471 +
  472 + // use underlayer api to send, donot flush again.
  473 + if ((ret = do_send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) {
  474 + return ret;
  475 + }
  476 + }
  477 +
  478 + return ret;
  479 +}
  480 +
442 void SrsProtocol::set_recv_timeout(int64_t timeout_us) 481 void SrsProtocol::set_recv_timeout(int64_t timeout_us)
443 { 482 {
444 return skt->set_recv_timeout(timeout_us); 483 return skt->set_recv_timeout(timeout_us);
@@ -638,7 +677,9 @@ int SrsProtocol::do_send_messages(SrsMessage** msgs, int nb_msgs) @@ -638,7 +677,9 @@ int SrsProtocol::do_send_messages(SrsMessage** msgs, int nb_msgs)
638 // when c0c3 cache dry, 677 // when c0c3 cache dry,
639 // sendout all messages and reset the cache, then send again. 678 // sendout all messages and reset the cache, then send again.
640 if ((ret = skt->writev(out_iovs, iov_index, NULL)) != ERROR_SUCCESS) { 679 if ((ret = skt->writev(out_iovs, iov_index, NULL)) != ERROR_SUCCESS) {
641 - srs_error("send with writev failed. ret=%d", ret); 680 + if (!srs_is_client_gracefully_close(ret)) {
  681 + srs_error("send with writev failed. ret=%d", ret);
  682 + }
642 return ret; 683 return ret;
643 } 684 }
644 685
@@ -663,13 +704,57 @@ int SrsProtocol::do_send_messages(SrsMessage** msgs, int nb_msgs) @@ -663,13 +704,57 @@ int SrsProtocol::do_send_messages(SrsMessage** msgs, int nb_msgs)
663 // sendout header and payload by writev. 704 // sendout header and payload by writev.
664 // decrease the sys invoke count to get higher performance. 705 // decrease the sys invoke count to get higher performance.
665 if ((ret = skt->writev(out_iovs, iov_index, NULL)) != ERROR_SUCCESS) { 706 if ((ret = skt->writev(out_iovs, iov_index, NULL)) != ERROR_SUCCESS) {
666 - srs_error("send with writev failed. ret=%d", ret); 707 + if (!srs_is_client_gracefully_close(ret)) {
  708 + srs_error("send with writev failed. ret=%d", ret);
  709 + }
667 return ret; 710 return ret;
668 } 711 }
669 712
670 return ret; 713 return ret;
671 } 714 }
672 715
  716 +int SrsProtocol::do_send_and_free_packet(SrsPacket* packet, int stream_id)
  717 +{
  718 + int ret = ERROR_SUCCESS;
  719 +
  720 + srs_assert(packet);
  721 + SrsAutoFree(SrsPacket, packet);
  722 +
  723 + int size = 0;
  724 + char* payload = NULL;
  725 + if ((ret = packet->encode(size, payload)) != ERROR_SUCCESS) {
  726 + srs_error("encode RTMP packet to bytes oriented RTMP message failed. ret=%d", ret);
  727 + return ret;
  728 + }
  729 +
  730 + // encode packet to payload and size.
  731 + if (size <= 0 || payload == NULL) {
  732 + srs_warn("packet is empty, ignore empty message.");
  733 + return ret;
  734 + }
  735 +
  736 + // to message
  737 + SrsMessage* msg = new SrsCommonMessage();
  738 +
  739 + msg->payload = payload;
  740 + msg->size = size;
  741 +
  742 + msg->header.payload_length = size;
  743 + msg->header.message_type = packet->get_message_type();
  744 + msg->header.stream_id = stream_id;
  745 + msg->header.perfer_cid = packet->get_prefer_cid();
  746 +
  747 + // donot use the auto free to free the msg,
  748 + // for performance issue.
  749 + ret = do_send_messages(&msg, 1);
  750 + if (ret == ERROR_SUCCESS) {
  751 + ret = on_send_packet(msg, packet);
  752 + }
  753 + srs_freep(msg);
  754 +
  755 + return ret;
  756 +}
  757 +
673 void SrsProtocol::generate_chunk_header(char* cache, SrsMessageHeader* mh, bool c0, int* pnbh, char** ph) 758 void SrsProtocol::generate_chunk_header(char* cache, SrsMessageHeader* mh, bool c0, int* pnbh, char** ph)
674 { 759 {
675 // to directly set the field. 760 // to directly set the field.
@@ -948,6 +1033,16 @@ int SrsProtocol::send_and_free_messages(SrsMessage** msgs, int nb_msgs, int stre @@ -948,6 +1033,16 @@ int SrsProtocol::send_and_free_messages(SrsMessage** msgs, int nb_msgs, int stre
948 srs_freep(msg); 1033 srs_freep(msg);
949 } 1034 }
950 1035
  1036 + // donot flush when send failed
  1037 + if (ret != ERROR_SUCCESS) {
  1038 + return ret;
  1039 + }
  1040 +
  1041 + // flush messages in manual queue
  1042 + if ((ret = manual_response_flush()) != ERROR_SUCCESS) {
  1043 + return ret;
  1044 + }
  1045 +
951 return ret; 1046 return ret;
952 } 1047 }
953 1048
@@ -955,41 +1050,15 @@ int SrsProtocol::send_and_free_packet(SrsPacket* packet, int stream_id) @@ -955,41 +1050,15 @@ int SrsProtocol::send_and_free_packet(SrsPacket* packet, int stream_id)
955 { 1050 {
956 int ret = ERROR_SUCCESS; 1051 int ret = ERROR_SUCCESS;
957 1052
958 - srs_assert(packet);  
959 - SrsAutoFree(SrsPacket, packet);  
960 -  
961 - int size = 0;  
962 - char* payload = NULL;  
963 - if ((ret = packet->encode(size, payload)) != ERROR_SUCCESS) {  
964 - srs_error("encode RTMP packet to bytes oriented RTMP message failed. ret=%d", ret); 1053 + if ((ret = do_send_and_free_packet(packet, stream_id)) != ERROR_SUCCESS) {
965 return ret; 1054 return ret;
966 } 1055 }
967 1056
968 - // encode packet to payload and size.  
969 - if (size <= 0 || payload == NULL) {  
970 - srs_warn("packet is empty, ignore empty message."); 1057 + // flush messages in manual queue
  1058 + if ((ret = manual_response_flush()) != ERROR_SUCCESS) {
971 return ret; 1059 return ret;
972 } 1060 }
973 1061
974 - // to message  
975 - SrsMessage* msg = new SrsCommonMessage();  
976 -  
977 - msg->payload = payload;  
978 - msg->size = size;  
979 -  
980 - msg->header.payload_length = size;  
981 - msg->header.message_type = packet->get_message_type();  
982 - msg->header.stream_id = stream_id;  
983 - msg->header.perfer_cid = packet->get_prefer_cid();  
984 -  
985 - // donot use the auto free to free the msg,  
986 - // for performance issue.  
987 - ret = do_send_messages(&msg, 1);  
988 - if (ret == ERROR_SUCCESS) {  
989 - ret = on_send_packet(msg, packet);  
990 - }  
991 - srs_freep(msg);  
992 -  
993 return ret; 1062 return ret;
994 } 1063 }
995 1064
@@ -1698,7 +1767,15 @@ int SrsProtocol::response_acknowledgement_message() @@ -1698,7 +1767,15 @@ int SrsProtocol::response_acknowledgement_message()
1698 SrsAcknowledgementPacket* pkt = new SrsAcknowledgementPacket(); 1767 SrsAcknowledgementPacket* pkt = new SrsAcknowledgementPacket();
1699 in_ack_size.acked_size = skt->get_recv_bytes(); 1768 in_ack_size.acked_size = skt->get_recv_bytes();
1700 pkt->sequence_number = (int32_t)in_ack_size.acked_size; 1769 pkt->sequence_number = (int32_t)in_ack_size.acked_size;
1701 - if ((ret = send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { 1770 +
  1771 + // cache the message and use flush to send.
  1772 + if (!auto_response_when_recv) {
  1773 + manual_response_queue.push_back(pkt);
  1774 + return ret;
  1775 + }
  1776 +
  1777 + // use underlayer api to send, donot flush again.
  1778 + if ((ret = do_send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) {
1702 srs_error("send acknowledgement failed. ret=%d", ret); 1779 srs_error("send acknowledgement failed. ret=%d", ret);
1703 return ret; 1780 return ret;
1704 } 1781 }
@@ -1718,7 +1795,14 @@ int SrsProtocol::response_ping_message(int32_t timestamp) @@ -1718,7 +1795,14 @@ int SrsProtocol::response_ping_message(int32_t timestamp)
1718 pkt->event_type = SrcPCUCPingResponse; 1795 pkt->event_type = SrcPCUCPingResponse;
1719 pkt->event_data = timestamp; 1796 pkt->event_data = timestamp;
1720 1797
1721 - if ((ret = send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { 1798 + // cache the message and use flush to send.
  1799 + if (!auto_response_when_recv) {
  1800 + manual_response_queue.push_back(pkt);
  1801 + return ret;
  1802 + }
  1803 +
  1804 + // use underlayer api to send, donot flush again.
  1805 + if ((ret = do_send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) {
1722 srs_error("send ping response failed. ret=%d", ret); 1806 srs_error("send ping response failed. ret=%d", ret);
1723 return ret; 1807 return ret;
1724 } 1808 }
@@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 #include <srs_core.hpp> 31 #include <srs_core.hpp>
32 32
33 #include <map> 33 #include <map>
  34 +#include <vector>
34 #include <string> 35 #include <string>
35 36
36 // for srs-librtmp, @see https://github.com/winlinvip/simple-rtmp-server/issues/213 37 // for srs-librtmp, @see https://github.com/winlinvip/simple-rtmp-server/issues/213
@@ -213,6 +214,16 @@ private: @@ -213,6 +214,16 @@ private:
213 * input ack size, when to send the acked packet. 214 * input ack size, when to send the acked packet.
214 */ 215 */
215 AckWindowSize in_ack_size; 216 AckWindowSize in_ack_size;
  217 + /**
  218 + * whether auto response when recv messages.
  219 + * default to true for it's very easy to use the protocol stack.
  220 + * @see: https://github.com/winlinvip/simple-rtmp-server/issues/217
  221 + */
  222 + bool auto_response_when_recv;
  223 + /**
  224 + * when not auto response message, manual flush the messages in queue.
  225 + */
  226 + std::vector<SrsPacket*> manual_response_queue;
216 // peer out 227 // peer out
217 private: 228 private:
218 /** 229 /**
@@ -246,6 +257,20 @@ public: @@ -246,6 +257,20 @@ public:
246 virtual ~SrsProtocol(); 257 virtual ~SrsProtocol();
247 public: 258 public:
248 /** 259 /**
  260 + * set the auto response message when recv for protocol stack.
  261 + * @param v, whether auto response message when recv message.
  262 + * @see: https://github.com/winlinvip/simple-rtmp-server/issues/217
  263 + */
  264 + virtual void set_auto_response(bool v);
  265 + /**
  266 + * flush for manual response when the auto response is disabled
  267 + * by set_auto_response(false), we default use auto response, so donot
  268 + * need to call this api(the protocol sdk will auto send message).
  269 + * @see the auto_response_when_recv and manual_response_queue.
  270 + */
  271 + virtual int manual_response_flush();
  272 +public:
  273 + /**
249 * set/get the recv timeout in us. 274 * set/get the recv timeout in us.
250 * if timeout, recv/send message return ERROR_SOCKET_TIMEOUT. 275 * if timeout, recv/send message return ERROR_SOCKET_TIMEOUT.
251 */ 276 */
@@ -371,6 +396,10 @@ private: @@ -371,6 +396,10 @@ private:
371 */ 396 */
372 virtual int do_send_messages(SrsMessage** msgs, int nb_msgs); 397 virtual int do_send_messages(SrsMessage** msgs, int nb_msgs);
373 /** 398 /**
  399 + * underlayer api for send and free packet.
  400 + */
  401 + virtual int do_send_and_free_packet(SrsPacket* packet, int stream_id);
  402 + /**
374 * generate the chunk header for msg. 403 * generate the chunk header for msg.
375 * @param mh, the header of msg to send. 404 * @param mh, the header of msg to send.
376 * @param c0, whether the first chunk, the c0 chunk. 405 * @param c0, whether the first chunk, the c0 chunk.