mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
for #742, refine code for recv thread.
This commit is contained in:
parent
a07986f4ee
commit
4583a63789
2 changed files with 130 additions and 110 deletions
|
@ -37,19 +37,27 @@ using namespace std;
|
||||||
// the max small bytes to group
|
// the max small bytes to group
|
||||||
#define SRS_MR_SMALL_BYTES 4096
|
#define SRS_MR_SMALL_BYTES 4096
|
||||||
|
|
||||||
ISrsMessageHandler::ISrsMessageHandler()
|
ISrsMessageConsumer::ISrsMessageConsumer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ISrsMessageHandler::~ISrsMessageHandler()
|
ISrsMessageConsumer::~ISrsMessageConsumer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsRecvThread::SrsRecvThread(ISrsMessageHandler* msg_handler, SrsRtmpServer* rtmp_sdk, int tm)
|
ISrsMessagePumper::ISrsMessagePumper()
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsMessagePumper::~ISrsMessagePumper()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsRecvThread::SrsRecvThread(ISrsMessagePumper* p, SrsRtmpServer* r, int tm)
|
||||||
|
{
|
||||||
|
rtmp = r;
|
||||||
|
pumper = p;
|
||||||
timeout = tm;
|
timeout = tm;
|
||||||
handler = msg_handler;
|
|
||||||
rtmp = rtmp_sdk;
|
|
||||||
trd = new SrsReusableThread2("recv", this);
|
trd = new SrsReusableThread2("recv", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,29 +95,29 @@ int SrsRecvThread::cycle()
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
while (!trd->interrupted()) {
|
while (!trd->interrupted()) {
|
||||||
if (!handler->can_handle()) {
|
// When the pumper is interrupted, wait then retry.
|
||||||
|
if (pumper->interrupted()) {
|
||||||
st_usleep(timeout * 1000);
|
st_usleep(timeout * 1000);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsCommonMessage* msg = NULL;
|
SrsCommonMessage* msg = NULL;
|
||||||
|
|
||||||
// recv and handle message
|
// Process the received message.
|
||||||
ret = rtmp->recv_message(&msg);
|
if ((ret = rtmp->recv_message(&msg)) == ERROR_SUCCESS) {
|
||||||
if (ret == ERROR_SUCCESS) {
|
ret = pumper->consume(msg);
|
||||||
ret = handler->handle(msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != ERROR_SUCCESS) {
|
if (ret != ERROR_SUCCESS) {
|
||||||
if (!srs_is_client_gracefully_close(ret) && !srs_is_system_control_error(ret)) {
|
if (!srs_is_client_gracefully_close(ret) && !srs_is_system_control_error(ret)) {
|
||||||
srs_error("thread process message failed. ret=%d", ret);
|
srs_error("recv thread error. ret=%d", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we use no timeout to recv, should never got any error.
|
// Interrupt the receive thread for any error.
|
||||||
trd->interrupt();
|
trd->interrupt();
|
||||||
|
|
||||||
// notice the handler got a recv error.
|
// Notify the pumper to quit for error.
|
||||||
handler->on_recv_error(ret);
|
pumper->interrupt(ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +136,7 @@ void SrsRecvThread::on_thread_start()
|
||||||
// @see: https://github.com/ossrs/srs/issues/217
|
// @see: https://github.com/ossrs/srs/issues/217
|
||||||
rtmp->set_recv_timeout(SRS_CONSTS_NO_TMMS);
|
rtmp->set_recv_timeout(SRS_CONSTS_NO_TMMS);
|
||||||
|
|
||||||
handler->on_thread_start();
|
pumper->on_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsRecvThread::on_thread_stop()
|
void SrsRecvThread::on_thread_stop()
|
||||||
|
@ -136,7 +144,7 @@ void SrsRecvThread::on_thread_stop()
|
||||||
// reset the timeout to pulse mode.
|
// reset the timeout to pulse mode.
|
||||||
rtmp->set_recv_timeout(timeout * 1000);
|
rtmp->set_recv_timeout(timeout * 1000);
|
||||||
|
|
||||||
handler->on_thread_stop();
|
pumper->on_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsQueueRecvThread::SrsQueueRecvThread(SrsConsumer* consumer, SrsRtmpServer* rtmp_sdk, int timeout_ms)
|
SrsQueueRecvThread::SrsQueueRecvThread(SrsConsumer* consumer, SrsRtmpServer* rtmp_sdk, int timeout_ms)
|
||||||
|
@ -196,16 +204,7 @@ int SrsQueueRecvThread::error_code()
|
||||||
return recv_error_code;
|
return recv_error_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsQueueRecvThread::can_handle()
|
int SrsQueueRecvThread::consume(SrsCommonMessage* msg)
|
||||||
{
|
|
||||||
// we only recv one message and then process it,
|
|
||||||
// for the message may cause the thread to stop,
|
|
||||||
// when stop, the thread is freed, so the messages
|
|
||||||
// are dropped.
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsQueueRecvThread::handle(SrsCommonMessage* msg)
|
|
||||||
{
|
{
|
||||||
// put into queue, the send thread will get and process it,
|
// put into queue, the send thread will get and process it,
|
||||||
// @see SrsRtmpConn::process_play_control_msg
|
// @see SrsRtmpConn::process_play_control_msg
|
||||||
|
@ -218,9 +217,19 @@ int SrsQueueRecvThread::handle(SrsCommonMessage* msg)
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsQueueRecvThread::on_recv_error(int ret)
|
bool SrsQueueRecvThread::interrupted()
|
||||||
|
{
|
||||||
|
// we only recv one message and then process it,
|
||||||
|
// for the message may cause the thread to stop,
|
||||||
|
// when stop, the thread is freed, so the messages
|
||||||
|
// are dropped.
|
||||||
|
return !empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsQueueRecvThread::interrupt(int ret)
|
||||||
{
|
{
|
||||||
recv_error_code = ret;
|
recv_error_code = ret;
|
||||||
|
|
||||||
#ifdef SRS_PERF_QUEUE_COND_WAIT
|
#ifdef SRS_PERF_QUEUE_COND_WAIT
|
||||||
if (_consumer) {
|
if (_consumer) {
|
||||||
_consumer->wakeup();
|
_consumer->wakeup();
|
||||||
|
@ -228,14 +237,14 @@ void SrsQueueRecvThread::on_recv_error(int ret)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsQueueRecvThread::on_thread_start()
|
void SrsQueueRecvThread::on_start()
|
||||||
{
|
{
|
||||||
// disable the protocol auto response,
|
// disable the protocol auto response,
|
||||||
// for the isolate recv thread should never send any messages.
|
// for the isolate recv thread should never send any messages.
|
||||||
rtmp->set_auto_response(false);
|
rtmp->set_auto_response(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsQueueRecvThread::on_thread_stop()
|
void SrsQueueRecvThread::on_stop()
|
||||||
{
|
{
|
||||||
// enable the protocol auto response,
|
// enable the protocol auto response,
|
||||||
// for the isolate recv thread terminated.
|
// for the isolate recv thread terminated.
|
||||||
|
@ -325,7 +334,48 @@ void SrsPublishRecvThread::stop()
|
||||||
trd.stop();
|
trd.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsPublishRecvThread::on_thread_start()
|
int SrsPublishRecvThread::consume(SrsCommonMessage* msg)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// when cid changed, change it.
|
||||||
|
if (ncid != cid) {
|
||||||
|
_srs_context->set_id(ncid);
|
||||||
|
cid = ncid;
|
||||||
|
}
|
||||||
|
|
||||||
|
_nb_msgs++;
|
||||||
|
|
||||||
|
// log to show the time of recv thread.
|
||||||
|
srs_verbose("recv thread now=%"PRId64"us, got msg time=%"PRId64"ms, size=%d",
|
||||||
|
srs_update_system_time_ms(), msg->header.timestamp, msg->size);
|
||||||
|
|
||||||
|
// the rtmp connection will handle this message
|
||||||
|
ret = _conn->handle_publish_message(_source, msg, _is_fmle, _is_edge);
|
||||||
|
|
||||||
|
// must always free it,
|
||||||
|
// the source will copy it if need to use.
|
||||||
|
srs_freep(msg);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SrsPublishRecvThread::interrupted()
|
||||||
|
{
|
||||||
|
// Never interrupted, always can handle message.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsPublishRecvThread::interrupt(int ret)
|
||||||
|
{
|
||||||
|
recv_error_code = ret;
|
||||||
|
|
||||||
|
// when recv thread error, signal the conn thread to process it.
|
||||||
|
// @see https://github.com/ossrs/srs/issues/244
|
||||||
|
st_cond_signal(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsPublishRecvThread::on_start()
|
||||||
{
|
{
|
||||||
// we donot set the auto response to false,
|
// we donot set the auto response to false,
|
||||||
// for the main thread never send message.
|
// for the main thread never send message.
|
||||||
|
@ -342,7 +392,7 @@ void SrsPublishRecvThread::on_thread_start()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsPublishRecvThread::on_thread_stop()
|
void SrsPublishRecvThread::on_stop()
|
||||||
{
|
{
|
||||||
// we donot set the auto response to true,
|
// we donot set the auto response to true,
|
||||||
// for we donot set to false yet.
|
// for we donot set to false yet.
|
||||||
|
@ -360,47 +410,6 @@ void SrsPublishRecvThread::on_thread_stop()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsPublishRecvThread::can_handle()
|
|
||||||
{
|
|
||||||
// publish thread always can handle message.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsPublishRecvThread::handle(SrsCommonMessage* msg)
|
|
||||||
{
|
|
||||||
int ret = ERROR_SUCCESS;
|
|
||||||
|
|
||||||
// when cid changed, change it.
|
|
||||||
if (ncid != cid) {
|
|
||||||
_srs_context->set_id(ncid);
|
|
||||||
cid = ncid;
|
|
||||||
}
|
|
||||||
|
|
||||||
_nb_msgs++;
|
|
||||||
|
|
||||||
// log to show the time of recv thread.
|
|
||||||
srs_verbose("recv thread now=%"PRId64"us, got msg time=%"PRId64"ms, size=%d",
|
|
||||||
srs_update_system_time_ms(), msg->header.timestamp, msg->size);
|
|
||||||
|
|
||||||
// the rtmp connection will handle this message
|
|
||||||
ret = _conn->handle_publish_message(_source, msg, _is_fmle, _is_edge);
|
|
||||||
|
|
||||||
// must always free it,
|
|
||||||
// the source will copy it if need to use.
|
|
||||||
srs_freep(msg);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SrsPublishRecvThread::on_recv_error(int ret)
|
|
||||||
{
|
|
||||||
recv_error_code = ret;
|
|
||||||
|
|
||||||
// when recv thread error, signal the conn thread to process it.
|
|
||||||
// @see https://github.com/ossrs/srs/issues/244
|
|
||||||
st_cond_signal(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SRS_PERF_MERGED_READ
|
#ifdef SRS_PERF_MERGED_READ
|
||||||
void SrsPublishRecvThread::on_read(ssize_t nread)
|
void SrsPublishRecvThread::on_read(ssize_t nread)
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,36 +45,48 @@ class SrsRequest;
|
||||||
class SrsConsumer;
|
class SrsConsumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* for the recv thread to handle the message.
|
* The message consumer which consume a message.
|
||||||
*/
|
*/
|
||||||
class ISrsMessageHandler
|
class ISrsMessageConsumer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ISrsMessageHandler();
|
ISrsMessageConsumer();
|
||||||
virtual ~ISrsMessageHandler();
|
virtual ~ISrsMessageConsumer();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* whether the handler can handle,
|
* Consume the received message.
|
||||||
* for example, when queue recv handler got an message,
|
|
||||||
* it wait the user to process it, then the recv thread
|
|
||||||
* never recv message util the handler is ok.
|
|
||||||
*/
|
|
||||||
virtual bool can_handle() = 0;
|
|
||||||
/**
|
|
||||||
* process the received message.
|
|
||||||
* @remark user must free this message.
|
* @remark user must free this message.
|
||||||
*/
|
*/
|
||||||
virtual int handle(SrsCommonMessage* msg) = 0;
|
virtual int consume(SrsCommonMessage* msg) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message pumper to pump messages to processer.
|
||||||
|
*/
|
||||||
|
class ISrsMessagePumper : public ISrsMessageConsumer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ISrsMessagePumper();
|
||||||
|
virtual ~ISrsMessagePumper();
|
||||||
|
public:
|
||||||
/**
|
/**
|
||||||
* when recv message error.
|
* Whether the pumper is interrupted.
|
||||||
*/
|
* For example, when pumpter is busy, it's interrupted,
|
||||||
virtual void on_recv_error(int ret) = 0;
|
* please wait for a while then try to feed the pumper.
|
||||||
|
*/
|
||||||
|
virtual bool interrupted() = 0;
|
||||||
/**
|
/**
|
||||||
* when thread start or stop,
|
* Interrupt the pumper for a error.
|
||||||
* for example, the message handler can set whether auto response.
|
*/
|
||||||
*/
|
virtual void interrupt(int error) = 0;
|
||||||
virtual void on_thread_start() = 0;
|
/**
|
||||||
virtual void on_thread_stop() = 0;
|
* When start the pumper.
|
||||||
|
*/
|
||||||
|
virtual void on_start() = 0;
|
||||||
|
/**
|
||||||
|
* When stop the pumper.
|
||||||
|
*/
|
||||||
|
virtual void on_stop() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,14 +96,14 @@ class SrsRecvThread : public ISrsReusableThread2Handler
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
SrsReusableThread2* trd;
|
SrsReusableThread2* trd;
|
||||||
ISrsMessageHandler* handler;
|
ISrsMessagePumper* pumper;
|
||||||
SrsRtmpServer* rtmp;
|
SrsRtmpServer* rtmp;
|
||||||
// The recv timeout in ms.
|
// The recv timeout in ms.
|
||||||
int timeout;
|
int timeout;
|
||||||
public:
|
public:
|
||||||
// Constructor.
|
// Constructor.
|
||||||
// @param tm The receive timeout in ms.
|
// @param tm The receive timeout in ms.
|
||||||
SrsRecvThread(ISrsMessageHandler* msg_handler, SrsRtmpServer* rtmp_sdk, int tm);
|
SrsRecvThread(ISrsMessagePumper* p, SrsRtmpServer* r, int tm);
|
||||||
virtual ~SrsRecvThread();
|
virtual ~SrsRecvThread();
|
||||||
public:
|
public:
|
||||||
virtual int cid();
|
virtual int cid();
|
||||||
|
@ -112,7 +124,7 @@ public:
|
||||||
* @see: SrsRtmpConn::playing
|
* @see: SrsRtmpConn::playing
|
||||||
* @see: https://github.com/ossrs/srs/issues/217
|
* @see: https://github.com/ossrs/srs/issues/217
|
||||||
*/
|
*/
|
||||||
class SrsQueueRecvThread : public ISrsMessageHandler
|
class SrsQueueRecvThread : public ISrsMessagePumper
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<SrsCommonMessage*> queue;
|
std::vector<SrsCommonMessage*> queue;
|
||||||
|
@ -132,24 +144,23 @@ public:
|
||||||
virtual int size();
|
virtual int size();
|
||||||
virtual SrsCommonMessage* pump();
|
virtual SrsCommonMessage* pump();
|
||||||
virtual int error_code();
|
virtual int error_code();
|
||||||
|
// interface ISrsMessagePumper
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle();
|
virtual int consume(SrsCommonMessage* msg);
|
||||||
virtual int handle(SrsCommonMessage* msg);
|
virtual bool interrupted();
|
||||||
virtual void on_recv_error(int ret);
|
virtual void interrupt(int ret);
|
||||||
public:
|
virtual void on_start();
|
||||||
virtual void on_thread_start();
|
virtual void on_stop();
|
||||||
virtual void on_thread_stop();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the publish recv thread got message and callback the source method to process message.
|
* the publish recv thread got message and callback the source method to process message.
|
||||||
* @see: https://github.com/ossrs/srs/issues/237
|
* @see: https://github.com/ossrs/srs/issues/237
|
||||||
*/
|
*/
|
||||||
class SrsPublishRecvThread : virtual public ISrsMessageHandler
|
class SrsPublishRecvThread : virtual public ISrsMessagePumper, virtual public ISrsReloadHandler
|
||||||
#ifdef SRS_PERF_MERGED_READ
|
#ifdef SRS_PERF_MERGED_READ
|
||||||
, virtual public IMergeReadHandler
|
, virtual public IMergeReadHandler
|
||||||
#endif
|
#endif
|
||||||
, virtual public ISrsReloadHandler
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SrsRecvThread trd;
|
SrsRecvThread trd;
|
||||||
|
@ -195,13 +206,13 @@ public:
|
||||||
public:
|
public:
|
||||||
virtual int start();
|
virtual int start();
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
virtual void on_thread_start();
|
// interface ISrsMessagePumper
|
||||||
virtual void on_thread_stop();
|
|
||||||
// interface ISrsMessageHandler
|
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle();
|
virtual int consume(SrsCommonMessage* msg);
|
||||||
virtual int handle(SrsCommonMessage* msg);
|
virtual bool interrupted();
|
||||||
virtual void on_recv_error(int ret);
|
virtual void interrupt(int ret);
|
||||||
|
virtual void on_start();
|
||||||
|
virtual void on_stop();
|
||||||
// interface IMergeReadHandler
|
// interface IMergeReadHandler
|
||||||
public:
|
public:
|
||||||
#ifdef SRS_PERF_MERGED_READ
|
#ifdef SRS_PERF_MERGED_READ
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue