完善webSocket协议实现

优化代码
This commit is contained in:
xiongziliang 2018-09-26 23:12:03 +08:00
parent bf88cc018b
commit 05e6d32576
18 changed files with 275 additions and 155 deletions

@ -1 +1 @@
Subproject commit 4916fec31fcbe383ae4d38570b84858f6ec7747d Subproject commit bb2ba9005b0191f709897bf51e5bb719eac856bb

View File

@ -57,7 +57,7 @@ void HttpClientImp::sendRequest(const string& url,float fTimeOutSec) {
#if defined(__GNUC__) && (__GNUC__ < 5) #if defined(__GNUC__) && (__GNUC__ < 5)
public_send(data,len); public_send(data,len);
#else//defined(__GNUC__) && (__GNUC__ < 5) #else//defined(__GNUC__) && (__GNUC__ < 5)
HttpClient::send(data,len); HttpClient::send(obtainBuffer(data,len));
#endif//defined(__GNUC__) && (__GNUC__ < 5) #endif//defined(__GNUC__) && (__GNUC__ < 5)
}); });
#endif //ENABLE_OPENSSL #endif //ENABLE_OPENSSL
@ -78,28 +78,12 @@ void HttpClientImp::onRecvBytes(const char* data, int size) {
} }
} }
int HttpClientImp::send(const string& str) { int HttpClientImp::send(const Buffer::Ptr &buf) {
if(_sslBox){ if(_sslBox){
_sslBox->onSend(str.data(),str.size()); _sslBox->onSend(buf->data(),buf->size());
return str.size(); return buf->size();
} }
return HttpClient::send(str); return HttpClient::send(buf);
}
int HttpClientImp::send(string &&str){
if(_sslBox){
_sslBox->onSend(str.data(),str.size());
return str.size();
}
return HttpClient::send(std::move(str));
}
int HttpClientImp::send(const char* str, int len) {
if(_sslBox){
_sslBox->onSend(str,len);
return len;
}
return HttpClient::send(str,len);
} }
#endif //ENABLE_OPENSSL #endif //ENABLE_OPENSSL

View File

@ -48,15 +48,13 @@ public:
HttpClient::onRecvBytes(data,len); HttpClient::onRecvBytes(data,len);
} }
void public_send(const char *data, uint32_t len){ void public_send(const char *data, uint32_t len){
HttpClient::send(data,len); HttpClient::send(obtainBuffer(data,len));
} }
#endif //defined(__GNUC__) && (__GNUC__ < 5) #endif //defined(__GNUC__) && (__GNUC__ < 5)
private: private:
#ifdef ENABLE_OPENSSL #ifdef ENABLE_OPENSSL
virtual void onRecvBytes(const char *data,int size) override; virtual void onRecvBytes(const char *data,int size) override;
virtual int send(const string &str) override; virtual int send(const Buffer::Ptr &buf) override;
virtual int send(string &&str) override;
virtual int send(const char *str, int len) override;
std::shared_ptr<SSL_Box> _sslBox; std::shared_ptr<SSL_Box> _sslBox;
#endif //ENABLE_OPENSSL #endif //ENABLE_OPENSSL
}; };

View File

@ -43,6 +43,16 @@ void HttpRequestSplitter::input(const char *data,uint64_t len) {
splitPacket: splitPacket:
/*确保ptr最后一个字节是0防止strstr越界
*ZLToolKit确保内存最后一个字节是保留未使用字节并置0
*0
*0
*/
char &tail_ref = ((char *) ptr)[len];
char tail_tmp = tail_ref;
tail_ref = 0;
//数据按照请求头处理 //数据按照请求头处理
const char *index = nullptr; const char *index = nullptr;
while (_content_len == 0 && (index = strstr(ptr,"\r\n\r\n")) != nullptr) { while (_content_len == 0 && (index = strstr(ptr,"\r\n\r\n")) != nullptr) {
@ -51,6 +61,11 @@ splitPacket:
ptr = index + 4; ptr = index + 4;
} }
/*
*
*/
tail_ref = tail_tmp;
uint64_t remain = len - (ptr - data); uint64_t remain = len - (ptr - data);
if(remain <= 0){ if(remain <= 0){
//没有剩余数据,清空缓存 //没有剩余数据,清空缓存

View File

@ -49,7 +49,7 @@ using namespace ZL::Util;
namespace ZL { namespace ZL {
namespace Http { namespace Http {
static int sock_flags = SOCKET_DEFAULE_FLAGS | FLAG_MORE; static int kSockFlags = SOCKET_DEFAULE_FLAGS | FLAG_MORE;
string dateStr() { string dateStr() {
char buf[64]; char buf[64];
@ -235,7 +235,7 @@ inline bool HttpSession::checkLiveFlvStream(){
//开始发送rtmp负载 //开始发送rtmp负载
//关闭tcp_nodelay ,优化性能 //关闭tcp_nodelay ,优化性能
SockUtil::setNoDelay(_sock->rawFD(),false); SockUtil::setNoDelay(_sock->rawFD(),false);
(*this) << SocketFlags(sock_flags); (*this) << SocketFlags(kSockFlags);
try{ try{
start(mediaSrc); start(mediaSrc);
@ -425,29 +425,10 @@ inline bool HttpSession::Handle_Req_GET(int64_t &content_len) {
//关闭tcp_nodelay ,优化性能 //关闭tcp_nodelay ,优化性能
SockUtil::setNoDelay(_sock->rawFD(),false); SockUtil::setNoDelay(_sock->rawFD(),false);
//设置MSG_MORE优化性能 //设置MSG_MORE优化性能
(*this) << SocketFlags(sock_flags); (*this) << SocketFlags(kSockFlags);
//后台线程执行onFlush
auto onFlushWrapper = [onFlush,weakSelf](){
auto strongSelf = weakSelf.lock();
if(!strongSelf){
return false;
}
strongSelf->async([onFlush,weakSelf](){
//在后台线程完成文件读取,释放主线程性能
if(!onFlush()){
//如果onFlush返回false则说明不再监听flush事件
auto strongSelf = weakSelf.lock();
if(strongSelf){
strongSelf->_sock->setOnFlush(nullptr);
}
}
});
return true;
};
onFlush(); onFlush();
_sock->setOnFlush(onFlushWrapper); _sock->setOnFlush(onFlush);
return true; return true;
} }

View File

@ -126,34 +126,185 @@ private:
const string &contentOut); const string &contentOut);
}; };
/** /**
* WebSocket会话 * WebSocket协议
* WebSock协议下的具体业务协议WebSocket协议的Rtmp协议等
* @tparam SessionType TcpSession类
*/ */
class EchoWebSocketSession : public HttpSession { template <typename SessionType>
class WebSocketSession : public HttpSession {
public: public:
EchoWebSocketSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock) : HttpSession(pTh,pSock){}; WebSocketSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock) : HttpSession(pTh,pSock){
virtual ~EchoWebSocketSession(){}; _session = std::make_shared<SessionImp>(pTh,pSock);
}
virtual ~WebSocketSession(){};
//收到eof或其他导致脱离TcpServer事件的回调
void onError(const SockException &err) override{
HttpSession::onError(err);
_session->onError(err);
}
//每隔一段时间触发,用来做超时管理
void onManager() override{
HttpSession::onManager();
_session->onManager();
}
//在创建TcpSession后TcpServer会把自身的配置参数通过该函数传递给TcpSession
void attachServer(const TcpServer &server) override{
HttpSession::attachServer(server);
_session->attachServer(server);
//此处截取数据并进行websocket协议打包
weak_ptr<WebSocketSession> weakSelf = dynamic_pointer_cast<WebSocketSession>(shared_from_this());
_session->setOnBeforeSendCB([weakSelf](const Buffer::Ptr &buf){
auto strongSelf = weakSelf.lock();
if(strongSelf){
bool mask_flag = strongSelf->_mask_flag;
strongSelf->_mask_flag = false;
strongSelf->WebSocketSplitter::encode((uint8_t *)buf->data(),buf->size());
strongSelf->_mask_flag = mask_flag;
}
return buf->size();
});
}
//作为该TcpSession的唯一标识符
string getIdentifier() const override{
return _session->getIdentifier();
}
protected: protected:
/**
* webSocket数据包
* @param packet
*/
void onWebSocketDecodeHeader(const WebSocketHeader &packet) override{ void onWebSocketDecodeHeader(const WebSocketHeader &packet) override{
DebugL << packet._playload_len; //新包,原来的包残余数据清空掉
}; _remian_data.clear();
}
/**
* websocket数据包负载
* @param packet
* @param ptr
* @param len
* @param recved
*/
void onWebSocketDecodePlayload(const WebSocketHeader &packet,const uint8_t *ptr,uint64_t len,uint64_t recved) override { void onWebSocketDecodePlayload(const WebSocketHeader &packet,const uint8_t *ptr,uint64_t len,uint64_t recved) override {
DebugL << string((char *)ptr,len) << " " << recved; if(packet._playload_len == recved){
//收到完整的包
//webSocket服务器不允许对数据进行掩码加密 if(_remian_data.empty()){
bool mask_flag = _mask_flag; onRecvWholePacket((char *)ptr,len);
_mask_flag = false; }else{
WebSocketSplitter::encode((uint8_t *)ptr,len); _remian_data.append((char *)ptr,len);
_mask_flag = mask_flag; onRecvWholePacket(_remian_data);
_remian_data.clear();
}; }
} else {
//部分数据
_remian_data.append((char *)ptr,len);
}
}
/**
* websocket协议打包后回调
* @param ptr
* @param len
*/
void onWebSocketEncodeData(const uint8_t *ptr,uint64_t len) override{ void onWebSocketEncodeData(const uint8_t *ptr,uint64_t len) override{
send((char *)ptr,len); _session->realSend(_session->obtainBuffer((char *)ptr,len));
}; }
/**
* websock数据包
* @param data
* @param len
*/
void onRecvWholePacket(const char *data,uint64_t len){
BufferRaw::Ptr buffer = _session->obtainBuffer(data,len);
_session->onRecv(buffer);
}
/**
* websock数据包
* @param str
*/
void onRecvWholePacket(const string &str){
BufferString::Ptr buffer = std::make_shared<BufferString>(str);
_session->onRecv(buffer);
}
private:
typedef function<int(const Buffer::Ptr &buf)> onBeforeSendCB;
/**
* TcpSession派生类发送数据的截取
* websocket协议的打包
*/
class SessionImp : public SessionType{
public:
SessionImp(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock) : SessionType(pTh,pSock){};
~SessionImp(){}
/**
* webSocket协议打包
* socket
* @param buf
* @return
*/
int realSend(const Buffer::Ptr &buf){
return SessionType::send(buf);
}
/**
*
* @param cb
*/
void setOnBeforeSendCB(const onBeforeSendCB &cb){
_beforeSendCB = cb;
}
protected:
/**
* send函数截取数据
* @param buf
* @return
*/
int send(const Buffer::Ptr &buf) override {
if(_beforeSendCB){
return _beforeSendCB(buf);
}
return SessionType::send(buf);
}
private:
onBeforeSendCB _beforeSendCB;
};
private:
std::shared_ptr<SessionImp> _session;
string _remian_data;
}; };
/**
*
*/
class EchoSession : public TcpSession {
public:
EchoSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock) : TcpSession(pTh,pSock){};
virtual ~EchoSession(){};
void onRecv(const Buffer::Ptr &buffer) override {
send(buffer);
}
void onError(const SockException &err) override{
WarnL << err.what();
}
//每隔一段时间触发,用来做超时管理
void onManager() override{
DebugL;
}
};
typedef WebSocketSession<EchoSession> EchoWebSocketSession;
} /* namespace Http */ } /* namespace Http */
} /* namespace ZL */ } /* namespace ZL */

View File

@ -44,7 +44,7 @@ public:
#if defined(__GNUC__) && (__GNUC__ < 5) #if defined(__GNUC__) && (__GNUC__ < 5)
public_send(data,len); public_send(data,len);
#else//defined(__GNUC__) && (__GNUC__ < 5) #else//defined(__GNUC__) && (__GNUC__ < 5)
HttpSession::send(data,len); HttpSession::send(obtainBuffer(data,len));
#endif//defined(__GNUC__) && (__GNUC__ < 5) #endif//defined(__GNUC__) && (__GNUC__ < 5)
}); });
m_sslBox.setOnDecData([&](const char *data, uint32_t len){ m_sslBox.setOnDecData([&](const char *data, uint32_t len){
@ -64,27 +64,17 @@ public:
} }
#if defined(__GNUC__) && (__GNUC__ < 5) #if defined(__GNUC__) && (__GNUC__ < 5)
int public_send(const char *data, uint32_t len){ int public_send(const char *data, uint32_t len){
return HttpSession::send(data,len); return HttpSession::send(obtainBuffer(data,len));
} }
void public_onRecv(const char *data, uint32_t len){ void public_onRecv(const char *data, uint32_t len){
HttpSession::onRecv(data,len); HttpSession::onRecv(data,len);
} }
#endif//defined(__GNUC__) && (__GNUC__ < 5) #endif//defined(__GNUC__) && (__GNUC__ < 5)
private: private:
virtual int send(const string &buf) override{ virtual int send(const Buffer::Ptr &buf) override{
TimeTicker(); TimeTicker();
m_sslBox.onSend(buf.data(), buf.size()); m_sslBox.onSend(buf->data(), buf->size());
return buf.size(); return buf->size();
}
virtual int send(string &&buf) override{
TimeTicker();
m_sslBox.onSend(buf.data(), buf.size());
return buf.size();
}
virtual int send(const char *buf, int size) override{
TimeTicker();
m_sslBox.onSend(buf, size);
return size;
} }
SSL_Box m_sslBox; SSL_Box m_sslBox;
}; };

View File

@ -105,11 +105,8 @@ private:
//fro RtmpProtocol //fro RtmpProtocol
void onRtmpChunk(RtmpPacket &chunkData) override; void onRtmpChunk(RtmpPacket &chunkData) override;
void onStreamDry(uint32_t ui32StreamId) override; void onStreamDry(uint32_t ui32StreamId) override;
void onSendRawData(const char *pcRawData, int iSize) override { void onSendRawData(const Buffer::Ptr &buffer) override{
send(pcRawData, iSize); send(buffer);
}
void onSendRawData(const Buffer::Ptr &buffer,int flags) override{
_sock->send(buffer,flags);
} }
template<typename FUN> template<typename FUN>

View File

@ -190,7 +190,7 @@ void RtmpProtocol::sendRequest(int iCmd, const string& str) {
} }
void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId, void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId,
const std::string& strBuf, uint32_t ui32TimeStamp, int iChunkId , bool msg_more) { const std::string& strBuf, uint32_t ui32TimeStamp, int iChunkId) {
if (iChunkId < 2 || iChunkId > 63) { if (iChunkId < 2 || iChunkId > 63) {
auto strErr = StrPrinter << "不支持发送该类型的块流 ID:" << iChunkId << endl; auto strErr = StrPrinter << "不支持发送该类型的块流 ID:" << iChunkId << endl;
throw std::runtime_error(strErr); throw std::runtime_error(strErr);
@ -235,7 +235,7 @@ void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId,
pos += chunk; pos += chunk;
} }
buffer->setSize(totalSize); buffer->setSize(totalSize);
onSendRawData(buffer,msg_more ? SOCKET_DEFAULE_FLAGS : (SOCKET_DEFAULE_FLAGS | FLAG_MORE)); onSendRawData(buffer);
m_ui32ByteSent += totalSize; m_ui32ByteSent += totalSize;
if (m_ui32WinSize > 0 && m_ui32ByteSent - m_ui32LastSent >= m_ui32WinSize) { if (m_ui32WinSize > 0 && m_ui32ByteSent - m_ui32LastSent >= m_ui32WinSize) {
m_ui32LastSent = m_ui32ByteSent; m_ui32LastSent = m_ui32ByteSent;
@ -253,9 +253,9 @@ void RtmpProtocol::onParseRtmp(const char *pcRawData, int iSize) {
void RtmpProtocol::startClientSession(const function<void()> &callBack) { void RtmpProtocol::startClientSession(const function<void()> &callBack) {
//发送 C0C1 //发送 C0C1
char handshake_head = HANDSHAKE_PLAINTEXT; char handshake_head = HANDSHAKE_PLAINTEXT;
onSendRawData(&handshake_head, 1); onSendRawData(obtainBuffer(&handshake_head, 1));
RtmpHandshake c1(0); RtmpHandshake c1(0);
onSendRawData((char *) (&c1), sizeof(c1)); onSendRawData(obtainBuffer((char *) (&c1), sizeof(c1)));
m_nextHandle = [this,callBack]() { m_nextHandle = [this,callBack]() {
//等待 S0+S1+S2 //等待 S0+S1+S2
handle_S0S1S2(callBack); handle_S0S1S2(callBack);
@ -271,7 +271,7 @@ void RtmpProtocol::handle_S0S1S2(const function<void()> &callBack) {
} }
//发送 C2 //发送 C2
const char *pcC2 = m_strRcvBuf.data() + 1; const char *pcC2 = m_strRcvBuf.data() + 1;
onSendRawData(pcC2, C1_HANDSHARK_SIZE); onSendRawData(obtainBuffer(pcC2, C1_HANDSHARK_SIZE));
m_strRcvBuf.erase(0, 1 + 2 * C1_HANDSHARK_SIZE); m_strRcvBuf.erase(0, 1 + 2 * C1_HANDSHARK_SIZE);
//握手结束 //握手结束
m_nextHandle = [this]() { m_nextHandle = [this]() {
@ -306,12 +306,12 @@ void RtmpProtocol::handle_C0C1() {
void RtmpProtocol::handle_C1_simple(){ void RtmpProtocol::handle_C1_simple(){
//发送S0 //发送S0
char handshake_head = HANDSHAKE_PLAINTEXT; char handshake_head = HANDSHAKE_PLAINTEXT;
onSendRawData(&handshake_head, 1); onSendRawData(obtainBuffer(&handshake_head, 1));
//发送S1 //发送S1
RtmpHandshake s1(0); RtmpHandshake s1(0);
onSendRawData((char *) &s1, C1_HANDSHARK_SIZE); onSendRawData(obtainBuffer((char *) &s1, C1_HANDSHARK_SIZE));
//发送S2 //发送S2
onSendRawData(m_strRcvBuf.c_str() + 1, C1_HANDSHARK_SIZE); onSendRawData(obtainBuffer(m_strRcvBuf.c_str() + 1, C1_HANDSHARK_SIZE));
//等待C2 //等待C2
m_nextHandle = [this]() { m_nextHandle = [this]() {
handle_C2(); handle_C2();
@ -433,7 +433,7 @@ void RtmpProtocol::send_complex_S0S1S2(int schemeType,const string &digest){
//S1S2计算参考自:https://github.com/hitYangfei/golang/blob/master/rtmpserver.go //S1S2计算参考自:https://github.com/hitYangfei/golang/blob/master/rtmpserver.go
//发送S0 //发送S0
char handshake_head = HANDSHAKE_PLAINTEXT; char handshake_head = HANDSHAKE_PLAINTEXT;
onSendRawData(&handshake_head, 1); onSendRawData(obtainBuffer(&handshake_head, 1));
//S1 //S1
RtmpHandshake s1(0); RtmpHandshake s1(0);
memcpy(s1.zero,"\x04\x05\x00\x01",4); memcpy(s1.zero,"\x04\x05\x00\x01",4);
@ -460,7 +460,7 @@ void RtmpProtocol::send_complex_S0S1S2(int schemeType,const string &digest){
s1_joined.erase(digestPos - s1_start,C1_DIGEST_SIZE); s1_joined.erase(digestPos - s1_start,C1_DIGEST_SIZE);
string s1_digest = openssl_HMACsha256(FMSKey,S1_FMS_KEY_SIZE,s1_joined.data(),s1_joined.size()); string s1_digest = openssl_HMACsha256(FMSKey,S1_FMS_KEY_SIZE,s1_joined.data(),s1_joined.size());
memcpy(digestPos,s1_digest.data(),s1_digest.size()); memcpy(digestPos,s1_digest.data(),s1_digest.size());
onSendRawData((char *) &s1, sizeof(s1)); onSendRawData(obtainBuffer((char *) &s1, sizeof(s1)));
//S2 //S2
string s2_key = openssl_HMACsha256(FMSKey,S2_FMS_KEY_SIZE,digest.data(),digest.size()); string s2_key = openssl_HMACsha256(FMSKey,S2_FMS_KEY_SIZE,digest.data(),digest.size());
@ -468,7 +468,7 @@ void RtmpProtocol::send_complex_S0S1S2(int schemeType,const string &digest){
s2.random_generate((char *)&s2,8); s2.random_generate((char *)&s2,8);
string s2_digest = openssl_HMACsha256(s2_key.data(),s2_key.size(),&s2,sizeof(s2) - C1_DIGEST_SIZE); string s2_digest = openssl_HMACsha256(s2_key.data(),s2_key.size(),&s2,sizeof(s2) - C1_DIGEST_SIZE);
memcpy((char *)&s2 + C1_HANDSHARK_SIZE - C1_DIGEST_SIZE,s2_digest.data(),C1_DIGEST_SIZE); memcpy((char *)&s2 + C1_HANDSHARK_SIZE - C1_DIGEST_SIZE,s2_digest.data(),C1_DIGEST_SIZE);
onSendRawData((char *)&s2, sizeof(s2)); onSendRawData(obtainBuffer((char *)&s2, sizeof(s2)));
//等待C2 //等待C2
m_nextHandle = [this]() { m_nextHandle = [this]() {
handle_C2(); handle_C2();
@ -691,5 +691,11 @@ BufferRaw::Ptr RtmpProtocol::obtainBuffer() {
return std::make_shared<BufferRaw>() ;//_bufferPool.obtain(); return std::make_shared<BufferRaw>() ;//_bufferPool.obtain();
} }
BufferRaw::Ptr RtmpProtocol::obtainBuffer(const void *data, int len) {
auto buffer = obtainBuffer();
buffer->assign((const char *)data,len);
return buffer;
}
} /* namespace Rtmp */ } /* namespace Rtmp */
} /* namespace ZL */ } /* namespace ZL */

View File

@ -54,11 +54,8 @@ public:
void onParseRtmp(const char *pcRawData,int iSize); void onParseRtmp(const char *pcRawData,int iSize);
void reset(); void reset();
protected: protected:
virtual void onSendRawData(const char *pcRawData,int iSize) = 0; virtual void onSendRawData(const Buffer::Ptr &buffer) = 0;
virtual void onSendRawData(const Buffer::Ptr &buffer,int flags) = 0;
virtual void onRtmpChunk(RtmpPacket &chunkData) = 0; virtual void onRtmpChunk(RtmpPacket &chunkData) = 0;
virtual void onStreamBegin(uint32_t ui32StreamId){ virtual void onStreamBegin(uint32_t ui32StreamId){
m_ui32StreamId = ui32StreamId; m_ui32StreamId = ui32StreamId;
} }
@ -78,19 +75,19 @@ protected:
void sendInvoke(const string &strCmd, const AMFValue &val); void sendInvoke(const string &strCmd, const AMFValue &val);
void sendRequest(int iCmd, const string &str); void sendRequest(int iCmd, const string &str);
void sendResponse(int iType, const string &str); void sendResponse(int iType, const string &str);
void sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId, const std::string &strBuf, uint32_t ui32TimeStamp, int iChunkID,bool msg_more = false); void sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId, const std::string &strBuf, uint32_t ui32TimeStamp, int iChunkID);
protected: protected:
int m_iReqID = 0; int m_iReqID = 0;
uint32_t m_ui32StreamId = STREAM_CONTROL; uint32_t m_ui32StreamId = STREAM_CONTROL;
int m_iNowStreamID = 0; int m_iNowStreamID = 0;
int m_iNowChunkID = 0; int m_iNowChunkID = 0;
bool m_bDataStarted = false; bool m_bDataStarted = false;
BufferRaw::Ptr obtainBuffer(); inline BufferRaw::Ptr obtainBuffer();
inline BufferRaw::Ptr obtainBuffer(const void *data, int len);
//ResourcePool<BufferRaw,MAX_SEND_PKT> m_bufferPool; //ResourcePool<BufferRaw,MAX_SEND_PKT> m_bufferPool;
private: private:
void handle_S0S1S2(const function<void()> &cb); void handle_S0S1S2(const function<void()> &cb);
void handle_C0C1(); void handle_C0C1();
void handle_C1_simple(); void handle_C1_simple();
#ifdef ENABLE_OPENSSL #ifdef ENABLE_OPENSSL
void handle_C1_complex(); void handle_C1_complex();
@ -104,6 +101,7 @@ private:
void handle_rtmp(); void handle_rtmp();
void handle_rtmpChunk(RtmpPacket &chunkData); void handle_rtmpChunk(RtmpPacket &chunkData);
private:
////////////ChunkSize//////////// ////////////ChunkSize////////////
size_t m_iChunkLenIn = DEFAULT_CHUNK_LEN; size_t m_iChunkLenIn = DEFAULT_CHUNK_LEN;
size_t m_iChunkLenOut = DEFAULT_CHUNK_LEN; size_t m_iChunkLenOut = DEFAULT_CHUNK_LEN;

View File

@ -35,6 +35,8 @@ using namespace ZL::Util;
namespace ZL { namespace ZL {
namespace Rtmp { namespace Rtmp {
static int kSockFlags = SOCKET_DEFAULE_FLAGS | FLAG_MORE;
unordered_map<string, RtmpPusher::rtmpCMDHandle> RtmpPusher::g_mapCmd; unordered_map<string, RtmpPusher::rtmpCMDHandle> RtmpPusher::g_mapCmd;
RtmpPusher::RtmpPusher(const char *strVhost,const char *strApp,const char *strStream) { RtmpPusher::RtmpPusher(const char *strVhost,const char *strApp,const char *strStream) {
auto src = dynamic_pointer_cast<RtmpMediaSource>(MediaSource::find(RTMP_SCHEMA,strVhost,strApp,strStream)); auto src = dynamic_pointer_cast<RtmpMediaSource>(MediaSource::find(RTMP_SCHEMA,strVhost,strApp,strStream));
@ -200,7 +202,7 @@ inline void RtmpPusher::send_metaData(){
sendRequest(MSG_DATA, enc.data()); sendRequest(MSG_DATA, enc.data());
src->getConfigFrame([&](const RtmpPacket::Ptr &pkt){ src->getConfigFrame([&](const RtmpPacket::Ptr &pkt){
sendRtmp(pkt->typeId, m_ui32StreamId, pkt->strBuf, pkt->timeStamp, pkt->chunkId , true); sendRtmp(pkt->typeId, m_ui32StreamId, pkt->strBuf, pkt->timeStamp, pkt->chunkId );
}); });
m_pRtmpReader = src->getRing()->attach(); m_pRtmpReader = src->getRing()->attach();
@ -210,7 +212,7 @@ inline void RtmpPusher::send_metaData(){
if(!strongSelf) { if(!strongSelf) {
return; return;
} }
strongSelf->sendRtmp(pkt->typeId, strongSelf->m_ui32StreamId, pkt->strBuf, pkt->timeStamp, pkt->chunkId , true); strongSelf->sendRtmp(pkt->typeId, strongSelf->m_ui32StreamId, pkt->strBuf, pkt->timeStamp, pkt->chunkId);
}); });
m_pRtmpReader->setDetachCB([weakSelf](){ m_pRtmpReader->setDetachCB([weakSelf](){
auto strongSelf = weakSelf.lock(); auto strongSelf = weakSelf.lock();
@ -220,6 +222,9 @@ inline void RtmpPusher::send_metaData(){
} }
}); });
onPublishResult(SockException(Err_success,"success")); onPublishResult(SockException(Err_success,"success"));
//提高发送性能
(*this) << SocketFlags(kSockFlags);
SockUtil::setNoDelay(_sock->rawFD(),false);
} }
void RtmpPusher::onCmd_result(AMFDecoder &dec){ void RtmpPusher::onCmd_result(AMFDecoder &dec){
auto iReqId = dec.load<int>(); auto iReqId = dec.load<int>();

View File

@ -54,19 +54,15 @@ public:
} }
protected: protected:
//for Tcpclient override
//for Tcpclient
void onRecv(const Buffer::Ptr &pBuf) override; void onRecv(const Buffer::Ptr &pBuf) override;
void onConnect(const SockException &err) override; void onConnect(const SockException &err) override;
void onErr(const SockException &ex) override; void onErr(const SockException &ex) override;
//fro RtmpProtocol //for RtmpProtocol override
void onRtmpChunk(RtmpPacket &chunkData) override; void onRtmpChunk(RtmpPacket &chunkData) override;
void onSendRawData(const char *pcRawData, int iSize) override { void onSendRawData(const Buffer::Ptr &buffer) override{
send(pcRawData, iSize); send(buffer);
}
void onSendRawData(const Buffer::Ptr &buffer,int flags) override{
_sock->send(buffer,flags);
} }
private: private:
void init(const RtmpMediaSource::Ptr &src); void init(const RtmpMediaSource::Ptr &src);

View File

@ -32,6 +32,8 @@
namespace ZL { namespace ZL {
namespace Rtmp { namespace Rtmp {
static int kSockFlags = SOCKET_DEFAULE_FLAGS | FLAG_MORE;
RtmpSession::RtmpSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock) : RtmpSession::RtmpSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock) :
TcpSession(pTh, pSock) { TcpSession(pTh, pSock) {
DebugL << get_peer_ip(); DebugL << get_peer_ip();
@ -366,6 +368,10 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
if (src->getRing()->readerCount() == 1) { if (src->getRing()->readerCount() == 1) {
src->seekTo(0); src->seekTo(0);
} }
//提高发送性能
(*this) << SocketFlags(kSockFlags);
SockUtil::setNoDelay(_sock->rawFD(),false);
} }
void RtmpSession::doPlay(AMFDecoder &dec){ void RtmpSession::doPlay(AMFDecoder &dec){
@ -539,7 +545,7 @@ void RtmpSession::onSendMedia(const RtmpPacket::Ptr &pkt) {
CLEAR_ARR(m_aui32FirstStamp); CLEAR_ARR(m_aui32FirstStamp);
modifiedStamp = 0; modifiedStamp = 0;
} }
sendRtmp(pkt->typeId, pkt->streamId, pkt->strBuf, modifiedStamp, pkt->chunkId , true); sendRtmp(pkt->typeId, pkt->streamId, pkt->strBuf, modifiedStamp, pkt->chunkId);
} }
void RtmpSession::doDelay(int delaySec, const std::function<void()> &fun) { void RtmpSession::doDelay(int delaySec, const std::function<void()> &fun) {

View File

@ -69,13 +69,9 @@ private:
void setMetaData(AMFDecoder &dec); void setMetaData(AMFDecoder &dec);
void onSendMedia(const RtmpPacket::Ptr &pkt); void onSendMedia(const RtmpPacket::Ptr &pkt);
void onSendRawData(const char *pcRawData,int iSize) override{ void onSendRawData(const Buffer::Ptr &buffer) override{
m_ui64TotalBytes += iSize;
send(pcRawData, iSize);
}
void onSendRawData(const Buffer::Ptr &buffer,int flags) override{
m_ui64TotalBytes += buffer->size(); m_ui64TotalBytes += buffer->size();
_sock->send(buffer,flags); send(buffer);
} }
void onRtmpChunk(RtmpPacket &chunkData) override; void onRtmpChunk(RtmpPacket &chunkData) override;

View File

@ -130,7 +130,7 @@ RtpBroadCaster::RtpBroadCaster(const string &strLocalIp,const string &strVhost,c
auto &pSock = m_apUdpSock[i]; auto &pSock = m_apUdpSock[i];
auto &peerAddr = m_aPeerUdpAddr[i]; auto &peerAddr = m_aPeerUdpAddr[i];
BufferRtp::Ptr buffer(new BufferRtp(pkt,4)); BufferRtp::Ptr buffer(new BufferRtp(pkt,4));
pSock->send(buffer,SOCKET_DEFAULE_FLAGS,(struct sockaddr *)(&peerAddr)); pSock->send(buffer,SOCKET_DEFAULE_FLAGS | FLAG_MORE,(struct sockaddr *)(&peerAddr));
}); });
m_pReader->setDetachCB([this](){ m_pReader->setDetachCB([this](){
unordered_map<void * , onDetach > m_mapDetach_copy; unordered_map<void * , onDetach > m_mapDetach_copy;

View File

@ -43,6 +43,8 @@ using namespace ZL::Network;
namespace ZL { namespace ZL {
namespace Rtsp { namespace Rtsp {
static int kSockFlags = SOCKET_DEFAULE_FLAGS | FLAG_MORE;
string dateHeader() { string dateHeader() {
char buf[200]; char buf[200];
time_t tt = time(NULL); time_t tt = time(NULL);
@ -210,7 +212,7 @@ bool RtspSession::handleReq_Options() {
m_iCseq, SERVER_NAME, m_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data()); dateHeader().data());
send(m_pcBuf, n); SocketHelper::send(m_pcBuf, n);
return true; return true;
} }
@ -277,7 +279,7 @@ void RtspSession::onAuthSuccess(const weak_ptr<RtspSession> &weakSelf) {
RTSP_VERSION, RTSP_BUILDTIME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), strongSelf->m_strUrl.data(), dateHeader().data(), strongSelf->m_strUrl.data(),
(int) strongSelf->m_strSdp.length(), strongSelf->m_strSdp.data()); (int) strongSelf->m_strSdp.length(), strongSelf->m_strSdp.data());
strongSelf->send(response, n); strongSelf->SocketHelper::send(response, n);
}); });
} }
void RtspSession::onAuthFailed(const weak_ptr<RtspSession> &weakSelf,const string &realm) { void RtspSession::onAuthFailed(const weak_ptr<RtspSession> &weakSelf,const string &realm) {
@ -320,7 +322,7 @@ void RtspSession::onAuthFailed(const weak_ptr<RtspSession> &weakSelf,const strin
RTSP_VERSION, RTSP_BUILDTIME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), realm.data()); dateHeader().data(), realm.data());
} }
strongSelf->send(response, n); strongSelf->SocketHelper::send(response, n);
}); });
} }
@ -471,7 +473,7 @@ inline void RtspSession::send_StreamNotFound() {
m_iCseq, SERVER_NAME, m_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data()); dateHeader().data());
send(m_pcBuf, n); SocketHelper::send(m_pcBuf, n);
} }
inline void RtspSession::send_UnsupportedTransport() { inline void RtspSession::send_UnsupportedTransport() {
int n = sprintf(m_pcBuf, "RTSP/1.0 461 Unsupported Transport\r\n" int n = sprintf(m_pcBuf, "RTSP/1.0 461 Unsupported Transport\r\n"
@ -482,7 +484,7 @@ inline void RtspSession::send_UnsupportedTransport() {
m_iCseq, SERVER_NAME, m_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data()); dateHeader().data());
send(m_pcBuf, n); SocketHelper::send(m_pcBuf, n);
} }
inline void RtspSession::send_SessionNotFound() { inline void RtspSession::send_SessionNotFound() {
@ -494,7 +496,7 @@ inline void RtspSession::send_SessionNotFound() {
m_iCseq, SERVER_NAME, m_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data()); dateHeader().data());
send(m_pcBuf, n); SocketHelper::send(m_pcBuf, n);
/*40 Method Not Allowed*/ /*40 Method Not Allowed*/
@ -562,7 +564,7 @@ bool RtspSession::handleReq_Setup() {
trackRef.type * 2 + 1, trackRef.type * 2 + 1,
printSSRC(trackRef.ssrc).data(), printSSRC(trackRef.ssrc).data(),
m_strSession.data()); m_strSession.data());
send(m_pcBuf, iLen); SocketHelper::send(m_pcBuf, iLen);
} }
break; break;
case PlayerBase::RTP_UDP: { case PlayerBase::RTP_UDP: {
@ -607,7 +609,7 @@ bool RtspSession::handleReq_Setup() {
pSockRtp->get_local_port(), pSockRtcp->get_local_port(), pSockRtp->get_local_port(), pSockRtcp->get_local_port(),
printSSRC(trackRef.ssrc).data(), printSSRC(trackRef.ssrc).data(),
m_strSession.data()); m_strSession.data());
send(m_pcBuf, n); SocketHelper::send(m_pcBuf, n);
} }
break; break;
case PlayerBase::RTP_MULTICAST: { case PlayerBase::RTP_MULTICAST: {
@ -650,7 +652,7 @@ bool RtspSession::handleReq_Setup() {
get_local_ip().data(), iSrvPort, pSockRtcp->get_local_port(), get_local_ip().data(), iSrvPort, pSockRtcp->get_local_port(),
udpTTL,printSSRC(trackRef.ssrc).data(), udpTTL,printSSRC(trackRef.ssrc).data(),
m_strSession.data()); m_strSession.data());
send(m_pcBuf, n); SocketHelper::send(m_pcBuf, n);
} }
break; break;
default: default:
@ -685,7 +687,7 @@ bool RtspSession::handleReq_Play() {
m_iCseq, SERVER_NAME, m_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(),(int)err.size(),err.data()); dateHeader().data(),(int)err.size(),err.data());
send(m_pcBuf,n); SocketHelper::send(m_pcBuf,n);
shutdown(); shutdown();
return; return;
} }
@ -757,7 +759,11 @@ bool RtspSession::handleReq_Play() {
iLen -= 1; iLen -= 1;
(m_pcBuf)[iLen] = '\0'; (m_pcBuf)[iLen] = '\0';
iLen += sprintf(m_pcBuf + iLen, "\r\n\r\n"); iLen += sprintf(m_pcBuf + iLen, "\r\n\r\n");
send(m_pcBuf, iLen); SocketHelper::send(m_pcBuf, iLen);
//提高发送性能
(*this) << SocketFlags(kSockFlags);
SockUtil::setNoDelay(m_pSender->rawFD(),false);
}; };
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this()); weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
@ -793,7 +799,7 @@ bool RtspSession::handleReq_Pause() {
"%s" "%s"
"Session: %s\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, "Session: %s\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), m_strSession.data()); dateHeader().data(), m_strSession.data());
send(m_pcBuf, n); SocketHelper::send(m_pcBuf, n);
if(m_pRtpReader){ if(m_pRtpReader){
m_pRtpReader->setReadCB(nullptr); m_pRtpReader->setReadCB(nullptr);
} }
@ -809,7 +815,7 @@ bool RtspSession::handleReq_Teardown() {
"Session: %s\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, "Session: %s\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), m_strSession.data()); dateHeader().data(), m_strSession.data());
send(m_pcBuf, n); SocketHelper::send(m_pcBuf, n);
TraceL << "播放器断开连接!"; TraceL << "播放器断开连接!";
return false; return false;
} }
@ -827,7 +833,7 @@ bool RtspSession::handleReq_Get() {
lock_guard<recursive_mutex> lock(g_mtxGetter); lock_guard<recursive_mutex> lock(g_mtxGetter);
g_mapGetter[m_strSessionCookie] = dynamic_pointer_cast<RtspSession>(shared_from_this()); g_mapGetter[m_strSessionCookie] = dynamic_pointer_cast<RtspSession>(shared_from_this());
//InfoL << m_strSessionCookie; //InfoL << m_strSessionCookie;
send(m_pcBuf, n); SocketHelper::send(m_pcBuf, n);
return true; return true;
} }
@ -862,7 +868,7 @@ bool RtspSession::handleReq_SET_PARAMETER() {
"%s" "%s"
"Session: %s\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, "Session: %s\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), m_strSession.data()); dateHeader().data(), m_strSession.data());
send(m_pcBuf, n); SocketHelper::send(m_pcBuf, n);
return true; return true;
} }
@ -873,7 +879,7 @@ inline void RtspSession::send_NotAcceptable() {
"%s" "%s"
"Connection: Close\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, "Connection: Close\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data()); dateHeader().data());
send(m_pcBuf, n); SocketHelper::send(m_pcBuf, n);
} }
@ -939,7 +945,7 @@ inline void RtspSession::sendRtpPacket(const RtpPacket::Ptr & pkt) {
} }
BufferRtp::Ptr buffer(new BufferRtp(pkt,4)); BufferRtp::Ptr buffer(new BufferRtp(pkt,4));
m_ui64TotalBytes += buffer->size(); m_ui64TotalBytes += buffer->size();
pSock->send(buffer,SOCKET_DEFAULE_FLAGS, peerAddr.get()); pSock->send(buffer,kSockFlags, peerAddr.get());
} }
break; break;
default: default:

View File

@ -89,21 +89,9 @@ protected:
int64_t onRecvHeader(const char *data,uint64_t len) override ; int64_t onRecvHeader(const char *data,uint64_t len) override ;
private: private:
void inputRtspOrRtcp(const char *data,uint64_t len); void inputRtspOrRtcp(const char *data,uint64_t len);
int send(const string &strBuf) override {
m_ui64TotalBytes += strBuf.size();
return m_pSender->send(strBuf);
}
int send(string &&strBuf) override {
m_ui64TotalBytes += strBuf.size();
return m_pSender->send(std::move(strBuf));
}
int send(const char *pcBuf, int iSize) override {
m_ui64TotalBytes += iSize;
return m_pSender->send(pcBuf, iSize);
}
int send(const Buffer::Ptr &pkt) override{ int send(const Buffer::Ptr &pkt) override{
m_ui64TotalBytes += pkt->size(); m_ui64TotalBytes += pkt->size();
return m_pSender->send(pkt,SOCKET_DEFAULE_FLAGS | FLAG_MORE); return m_pSender->send(pkt,_flags);
} }
void shutdown() override ; void shutdown() override ;
void shutdown_l(bool close); void shutdown_l(bool close);

View File

@ -53,8 +53,11 @@ int main(int argc, char *argv[]) {
//下载器map //下载器map
map<string, HttpDownloader::Ptr> downloaderMap; map<string, HttpDownloader::Ptr> downloaderMap;
//下载两个文件一个是http下载一个https下载 //下载两个文件一个是http下载一个https下载
auto urlList = {"http://img3.imgtn.bdimg.com/it/u=158031390,1321729164&fm=214&gp=0.jpg", auto urlList = {"https://timgsa.baidu.com/timg?image&quality=80&"
"https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=931786003,1029770543&fm=27&gp=0.jpg"}; "size=b9999_10000&sec=1537717640404&"
"di=f602efbebbc1e7f6b9ccb0bf0def89d0&"
"imgtype=0&"
"src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F241f95cad1c8a786ff65052a6d09c93d70cf5042.jpg",};
for (auto &url : urlList) { for (auto &url : urlList) {
//创建下载器 //创建下载器