diff --git a/src/Http/HttpRequestSplitter.cpp b/src/Http/HttpRequestSplitter.cpp index 30974e99..6ec1bb6a 100644 --- a/src/Http/HttpRequestSplitter.cpp +++ b/src/Http/HttpRequestSplitter.cpp @@ -21,6 +21,10 @@ splitPacket: _remain_data.erase(0, index + 4); } + if(_remain_data.empty()){ + return; + } + if(_content_len > 0){ //数据按照固定长度content处理 if(_remain_data.size() < _content_len){ diff --git a/src/Http/HttpSession.cpp b/src/Http/HttpSession.cpp index e47126ab..b02f072b 100644 --- a/src/Http/HttpSession.cpp +++ b/src/Http/HttpSession.cpp @@ -40,6 +40,8 @@ #include "Util/onceToken.h" #include "Util/mini.h" #include "Util/NoticeCenter.h" +#include "Util/base64.h" +#include "Util/SHA1.h" #include "Rtmp/utils.h" using namespace ZL::Util; @@ -180,6 +182,23 @@ void HttpSession::onManager() { shutdown(); } } + + +inline bool HttpSession::checkWebSocket(){ + if(m_parser["Connection"] != "Upgrade" || + m_parser["Upgrade"] != "websocket" ){ + return false; + } + auto Sec_WebSocket_Key = m_parser["Sec-WebSocket-Key"]; + auto Sec_WebSocket_Accept = encodeBase64(SHA1::encode_bin(Sec_WebSocket_Key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")); + + KeyValue headerOut; + headerOut["Upgrade"] = "websocket"; + headerOut["Connection"] = "Upgrade"; + headerOut["Sec-WebSocket-Accept"] = Sec_WebSocket_Accept; + sendResponse("101 Switching Protocols",headerOut,""); + return true; +} //http-flv 链接格式:http://vhost-url:port/app/streamid.flv?key1=value1&key2=value2 //如果url(除去?以及后面的参数)后缀是.flv,那么表明该url是一个http-flv直播。 inline bool HttpSession::checkLiveFlvStream(){ @@ -248,16 +267,29 @@ inline bool HttpSession::checkLiveFlvStream(){ return true; } inline bool HttpSession::Handle_Req_GET(int64_t &content_len) { + //先看看是否为WebSocket请求 + if(checkWebSocket()){ + content_len = -1; + auto parserCopy = m_parser; + m_contentCallBack = [this,parserCopy](const string &data){ + onRecvWebSocketData(parserCopy,data); + //m_contentCallBack是可持续的,后面还要处理后续数据 + return true; + }; + return true; + } + //先看看该http事件是否被拦截 if(emitHttpEvent(false)){ return true; } + //再看看是否为http-flv直播请求 if(checkLiveFlvStream()){ return true; } - //事件未被拦截,则认为是http下载请求 + //事件未被拦截,则认为是http下载请求 auto fullUrl = string(HTTP_SCHEMA) + "://" + m_parser["Host"] + m_parser.FullUrl(); m_mediaInfo.parse(fullUrl); diff --git a/src/Http/HttpSession.h b/src/Http/HttpSession.h index aa985506..daec04c2 100644 --- a/src/Http/HttpSession.h +++ b/src/Http/HttpSession.h @@ -85,7 +85,7 @@ protected: /** * 重载之用于处理不定长度的content - * 这个函数可用于处理大文件上传、http-flv推流,WebSocket数据 + * 这个函数可用于处理大文件上传、http-flv推流 * @param header http请求头 * @param content content分片数据 * @param content_size content大小,如果为0则是不限长度content @@ -95,6 +95,15 @@ protected: shutdown(); } + + /** + * 重载之用于处理websocket数据 + * @param header http请求头 + * @param data websocket数据 + */ + virtual void onRecvWebSocketData(const Parser &header,const string &data){ + shutdown(); + } private: Parser m_parser; string m_strPath; @@ -110,6 +119,7 @@ private: inline bool Handle_Req_GET(int64_t &content_len); inline bool Handle_Req_POST(int64_t &content_len); inline bool checkLiveFlvStream(); + inline bool checkWebSocket(); inline bool emitHttpEvent(bool doInvoke); inline void urlDecode(Parser &parser); inline bool makeMeun(const string &strFullPath,const string &vhost, string &strRet); @@ -121,6 +131,20 @@ private: const string &contentOut); }; +/** + * 回显WebSocket会话 + */ +class EchoWebSocketSession : public HttpSession { +public: + EchoWebSocketSession(const std::shared_ptr &pTh, const Socket::Ptr &pSock) : HttpSession(pTh,pSock){}; + virtual ~EchoWebSocketSession(){}; +protected: + void onRecvWebSocketData(const Parser &header,const string &data) override { + DebugL << "收到websocket数据:" << data; + (*this) << "echo:" << data; + } +}; + } /* namespace Http */ } /* namespace ZL */