diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.16-PR2353.patch b/packages/mediacenter/xbmc/patches/xbmc-990.16-PR2353.patch new file mode 100644 index 0000000000..27aca80295 --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.16-PR2353.patch @@ -0,0 +1,309 @@ +From 0a2c144355ed750e61fadabe2dde185a76064f0a Mon Sep 17 00:00:00 2001 +From: montellese +Date: Fri, 1 Mar 2013 17:53:54 +0100 +Subject: [PATCH] websocket: fix inability to handle multiple queued websocket + frames/messages (fixes #13848) + +--- + xbmc/network/TCPServer.cpp | 31 +++--- + xbmc/network/websocket/WebSocket.cpp | 174 +++++++++++++++++++--------------- + xbmc/network/websocket/WebSocket.h | 2 +- + 3 files changed, 114 insertions(+), 93 deletions(-) + +diff --git a/xbmc/network/TCPServer.cpp b/xbmc/network/TCPServer.cpp +index 2d9fde0..e4b5984 100644 +--- a/xbmc/network/TCPServer.cpp ++++ b/xbmc/network/TCPServer.cpp +@@ -654,23 +654,28 @@ void CTCPServer::CWebSocketClient::Send(const char *data, unsigned int size) + void CTCPServer::CWebSocketClient::PushBuffer(CTCPServer *host, const char *buffer, int length) + { + bool send; +- const CWebSocketMessage *msg; +- if ((msg = m_websocket->Handle(buffer, length, send)) != NULL && msg->IsComplete()) ++ const CWebSocketMessage *msg = NULL; ++ size_t len = length; ++ do + { +- std::vector frames = msg->GetFrames(); +- if (send) +- { +- for (unsigned int index = 0; index < frames.size(); index++) +- Send(frames.at(index)->GetFrameData(), (unsigned int)frames.at(index)->GetFrameLength()); +- } +- else ++ if ((msg = m_websocket->Handle(buffer, len, send)) != NULL && msg->IsComplete()) + { +- for (unsigned int index = 0; index < frames.size(); index++) +- CTCPClient::PushBuffer(host, frames.at(index)->GetApplicationData(), (int)frames.at(index)->GetLength()); +- } ++ std::vector frames = msg->GetFrames(); ++ if (send) ++ { ++ for (unsigned int index = 0; index < frames.size(); index++) ++ Send(frames.at(index)->GetFrameData(), (unsigned int)frames.at(index)->GetFrameLength()); ++ } ++ else ++ { ++ for (unsigned int index = 0; index < frames.size(); index++) ++ CTCPClient::PushBuffer(host, frames.at(index)->GetApplicationData(), (int)frames.at(index)->GetLength()); ++ } + +- delete msg; ++ delete msg; ++ } + } ++ while (len > 0 && msg != NULL); + + if (m_websocket->GetState() == WebSocketStateClosed) + Disconnect(); +diff --git a/xbmc/network/websocket/WebSocket.cpp b/xbmc/network/websocket/WebSocket.cpp +index 94e7ab0..5008073 100644 +--- a/xbmc/network/websocket/WebSocket.cpp ++++ b/xbmc/network/websocket/WebSocket.cpp +@@ -80,11 +80,11 @@ + // Get the MASK flag + m_masked = ((m_data[1] & MASK_MASK) == MASK_MASK); + +- // Get the playload length ++ // Get the payload length + m_length = (uint64_t)(m_data[1] & MASK_LENGTH); +- if ((m_length <= 125 && length < m_length + LENGTH_MIN) || +- (m_length == 126 && length < LENGTH_MIN + 2) || +- (m_length == 127 && length < LENGTH_MIN + 8)) ++ if ((m_length <= 125 && m_lengthFrame < m_length + LENGTH_MIN) || ++ (m_length == 126 && m_lengthFrame < LENGTH_MIN + 2) || ++ (m_length == 127 && m_lengthFrame < LENGTH_MIN + 8)) + { + CLog::Log(LOGINFO, "WebSocket: Frame with invalid length received"); + reset(); +@@ -110,7 +110,7 @@ + offset = 8; + } + +- if (length < LENGTH_MIN + offset + m_length) ++ if (m_lengthFrame < LENGTH_MIN + offset + m_length) + { + CLog::Log(LOGINFO, "WebSocket: Frame with invalid length received"); + reset(); +@@ -124,12 +124,8 @@ + offset += 4; + } + +- if (length != LENGTH_MIN + offset + m_length) +- { +- CLog::Log(LOGINFO, "WebSocket: Frame with invalid length received"); +- reset(); +- return; +- } ++ if (m_lengthFrame != LENGTH_MIN + offset + m_length) ++ m_lengthFrame = LENGTH_MIN + offset + m_length; + + // Get application data + if (m_length > 0) +@@ -305,102 +301,122 @@ void CWebSocketMessage::Clear() + m_frames.clear(); + } + +-const CWebSocketMessage* CWebSocket::Handle(const char *buffer, size_t length, bool &send) ++const CWebSocketMessage* CWebSocket::Handle(const char* &buffer, size_t &length, bool &send) + { + send = false; + +- switch (m_state) ++ while (length > 0) + { +- case WebSocketStateConnected: ++ switch (m_state) + { +- CWebSocketFrame *frame = GetFrame(buffer, length); +- if (!frame->IsValid()) ++ case WebSocketStateConnected: + { +- CLog::Log(LOGINFO, "WebSocket: Invalid frame received"); +- delete frame; +- return NULL; +- } +- +- if (frame->IsControlFrame()) +- { +- if (!frame->IsFinal()) ++ CWebSocketFrame *frame = GetFrame(buffer, length); ++ if (!frame->IsValid()) + { ++ CLog::Log(LOGINFO, "WebSocket: Invalid frame received"); + delete frame; + return NULL; + } + +- CWebSocketMessage *msg = NULL; +- switch (frame->GetOpcode()) ++ // adjust the length and the buffer values ++ length -= frame->GetFrameLength(); ++ buffer += frame->GetFrameLength(); ++ ++ if (frame->IsControlFrame()) + { +- case WebSocketPing: +- msg = GetMessage(); +- if (msg != NULL) +- msg->AddFrame(Pong(frame->GetApplicationData())); +- break; ++ if (!frame->IsFinal()) ++ { ++ delete frame; ++ return NULL; ++ } ++ ++ CWebSocketMessage *msg = NULL; ++ switch (frame->GetOpcode()) ++ { ++ case WebSocketPing: ++ msg = GetMessage(); ++ if (msg != NULL) ++ msg->AddFrame(Pong(frame->GetApplicationData())); ++ break; + +- case WebSocketConnectionClose: +- CLog::Log(LOGINFO, "WebSocket: connection closed by client"); +- +- msg = GetMessage(); +- if (msg != NULL) +- msg->AddFrame(Close()); +- +- m_state = WebSocketStateClosed; +- break; +- +- case WebSocketContinuationFrame: +- case WebSocketTextFrame: +- case WebSocketBinaryFrame: +- case WebSocketPong: +- case WebSocketUnknownFrame: +- default: +- break; ++ case WebSocketConnectionClose: ++ CLog::Log(LOGINFO, "WebSocket: connection closed by client"); ++ ++ msg = GetMessage(); ++ if (msg != NULL) ++ msg->AddFrame(Close()); ++ ++ m_state = WebSocketStateClosed; ++ break; ++ ++ case WebSocketContinuationFrame: ++ case WebSocketTextFrame: ++ case WebSocketBinaryFrame: ++ case WebSocketPong: ++ case WebSocketUnknownFrame: ++ default: ++ break; ++ } ++ ++ delete frame; ++ ++ if (msg != NULL) ++ send = true; ++ ++ return msg; + } + +- delete frame; ++ if (m_message == NULL && (m_message = GetMessage()) == NULL) ++ { ++ CLog::Log(LOGINFO, "WebSocket: Could not allocate a new websocket message"); ++ delete frame; ++ return NULL; ++ } + +- if (msg != NULL) +- send = true; ++ m_message->AddFrame(frame); ++ if (!m_message->IsComplete()) ++ { ++ if (length > 0) ++ continue; ++ else ++ return NULL; ++ } + ++ CWebSocketMessage *msg = m_message; ++ m_message = NULL; + return msg; + } + +- if (m_message == NULL && (m_message = GetMessage()) == NULL) ++ case WebSocketStateClosing: + { +- CLog::Log(LOGINFO, "WebSocket: Could not allocate a new websocket message"); +- delete frame; +- return NULL; +- } ++ CWebSocketFrame *frame = GetFrame(buffer, length); + +- m_message->AddFrame(frame); +- if (!m_message->IsComplete()) +- return NULL; ++ if (frame->IsValid()) ++ { ++ // adjust the length and the buffer values ++ length -= frame->GetFrameLength(); ++ buffer += frame->GetFrameLength(); ++ } + +- CWebSocketMessage *msg = m_message; +- m_message = NULL; +- return msg; +- } ++ if (!frame->IsValid() || frame->GetOpcode() == WebSocketConnectionClose) ++ { ++ CLog::Log(LOGINFO, "WebSocket: Invalid or unexpected frame received (only closing handshake expected)"); ++ delete frame; ++ return NULL; ++ } + +- case WebSocketStateClosing: +- { +- CWebSocketFrame *frame = GetFrame(buffer, length); +- if (!frame->IsValid() || frame->GetOpcode() == WebSocketConnectionClose) +- { +- CLog::Log(LOGINFO, "WebSocket: Invalid or unexpected frame received (only closing handshake expected)"); +- delete frame; ++ m_state = WebSocketStateClosed; + return NULL; + } + +- m_state = WebSocketStateClosed; +- return NULL; ++ case WebSocketStateNotConnected: ++ case WebSocketStateClosed: ++ case WebSocketStateHandshaking: ++ default: ++ CLog::Log(LOGINFO, "WebSocket: No frame expected in the current state"); ++ return NULL; + } +- +- case WebSocketStateNotConnected: +- case WebSocketStateClosed: +- case WebSocketStateHandshaking: +- default: +- CLog::Log(LOGINFO, "WebSocket: No frame expected in the current state"); +- return NULL; + } + + return NULL; +diff --git a/xbmc/network/websocket/WebSocket.h b/xbmc/network/websocket/WebSocket.h +index bbfaa89..e0d3cae 100644 +--- a/xbmc/network/websocket/WebSocket.h ++++ b/xbmc/network/websocket/WebSocket.h +@@ -122,7 +122,7 @@ class CWebSocket + WebSocketState GetState() { return m_state; } + + virtual bool Handshake(const char* data, size_t length, std::string &response) = 0; +- virtual const CWebSocketMessage* Handle(const char *buffer, size_t length, bool &send); ++ virtual const CWebSocketMessage* Handle(const char* &buffer, size_t &length, bool &send); + virtual const CWebSocketMessage* Send(WebSocketFrameOpcode opcode, const char* data = NULL, uint32_t length = 0); + virtual const CWebSocketFrame* Ping(const char* data = NULL) const = 0; + virtual const CWebSocketFrame* Pong(const char* data = NULL) const = 0; +-- +1.7.10 +