aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--project/VS2010Express/XBMC.vcxproj2
-rw-r--r--project/VS2010Express/XBMC.vcxproj.filters6
-rw-r--r--xbmc/network/websocket/Makefile1
-rw-r--r--xbmc/network/websocket/WebSocketV13.cpp166
-rw-r--r--xbmc/network/websocket/WebSocketV13.h32
5 files changed, 207 insertions, 0 deletions
diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj
index ff80a5776c..648e776d6c 100644
--- a/project/VS2010Express/XBMC.vcxproj
+++ b/project/VS2010Express/XBMC.vcxproj
@@ -675,6 +675,7 @@
<ClCompile Include="..\..\xbmc\network\WebServer.cpp" />
<ClCompile Include="..\..\xbmc\network\websocket\WebSocket.cpp" />
<ClCompile Include="..\..\xbmc\network\websocket\WebSocketManager.cpp" />
+ <ClCompile Include="..\..\xbmc\network\websocket\WebSocketV13.cpp" />
<ClCompile Include="..\..\xbmc\network\websocket\WebSocketV8.cpp" />
<ClCompile Include="..\..\xbmc\network\windows\NetworkWin32.cpp" />
<ClCompile Include="..\..\xbmc\network\windows\ZeroconfWIN.cpp" />
@@ -764,6 +765,7 @@
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\pythreadstate.h" />
<ClInclude Include="..\..\xbmc\network\websocket\WebSocket.h" />
<ClInclude Include="..\..\xbmc\network\websocket\WebSocketManager.h" />
+ <ClInclude Include="..\..\xbmc\network\websocket\WebSocketV13.h" />
<ClInclude Include="..\..\xbmc\network\websocket\WebSocketV8.h" />
<ClInclude Include="..\..\xbmc\threads\platform\win\Implementation.cpp" />
<ClCompile Include="..\..\xbmc\threads\SystemClock.cpp" />
diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters
index a0b45b91eb..3cc187c9df 100644
--- a/project/VS2010Express/XBMC.vcxproj.filters
+++ b/project/VS2010Express/XBMC.vcxproj.filters
@@ -2586,6 +2586,9 @@
<ClCompile Include="..\..\xbmc\network\websocket\WebSocketManager.cpp">
<Filter>network\websocket</Filter>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\network\websocket\WebSocketV13.cpp">
+ <Filter>network\websocket</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\xbmc\win32\pch.h">
@@ -5193,6 +5196,9 @@
<ClInclude Include="..\..\xbmc\network\websocket\WebSocketManager.h">
<Filter>network\websocket</Filter>
</ClInclude>
+ <ClInclude Include="..\..\xbmc\network\websocket\WebSocketV13.h">
+ <Filter>network\websocket</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\xbmc\win32\XBMC_PC.rc">
diff --git a/xbmc/network/websocket/Makefile b/xbmc/network/websocket/Makefile
index f3005eda2d..f3d9d41270 100644
--- a/xbmc/network/websocket/Makefile
+++ b/xbmc/network/websocket/Makefile
@@ -1,6 +1,7 @@
SRCS=WebSocket.cpp \
WebSocketManager.cpp \
WebSocketV8.cpp \
+ WebSocketV13.cpp \
LIB=websocket.a
diff --git a/xbmc/network/websocket/WebSocketV13.cpp b/xbmc/network/websocket/WebSocketV13.cpp
new file mode 100644
index 0000000000..aa084839db
--- /dev/null
+++ b/xbmc/network/websocket/WebSocketV13.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2011 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <string>
+#include <sstream>
+#include <boost/uuid/sha1.hpp>
+
+#include "WebSocketV13.h"
+#include "WebSocket.h"
+#include "utils/Base64.h"
+#include "utils/CharsetConverter.h"
+#include "utils/HttpParser.h"
+#include "utils/HttpResponse.h"
+#include "utils/log.h"
+#include "utils/StringUtils.h"
+
+#define WS_HTTP_METHOD "GET"
+#define WS_HTTP_TAG "HTTP/"
+
+#define WS_HEADER_UPGRADE "Upgrade"
+#define WS_HEADER_UPGRADE_LC "upgrade"
+#define WS_HEADER_CONNECTION "Connection"
+#define WS_HEADER_CONNECTION_LC "connection"
+
+#define WS_HEADER_KEY_LC "sec-websocket-key" // "Sec-WebSocket-Key"
+#define WS_HEADER_ACCEPT "Sec-WebSocket-Accept"
+#define WS_HEADER_PROTOCOL "Sec-WebSocket-Protocol"
+#define WS_HEADER_PROTOCOL_LC "sec-websocket-protocol" // "Sec-WebSocket-Protocol"
+
+#define WS_PROTOCOL_JSONRPC "jsonrpc.xbmc.org"
+#define WS_HEADER_UPGRADE_VALUE "websocket"
+
+using namespace std;
+
+bool CWebSocketV13::Handshake(const char* data, size_t length, std::string &response)
+{
+ string strHeader(data, length);
+ const char *value;
+ HttpParser header;
+ if (header.addBytes(data, length) != HttpParser::Done)
+ {
+ CLog::Log(LOGINFO, "WebSocket [RFC6455]: incomplete handshake received");
+ return false;
+ }
+
+ // The request must be GET
+ value = header.getMethod();
+ if (value == NULL || strnicmp(value, WS_HTTP_METHOD, strlen(WS_HTTP_METHOD)) != 0)
+ {
+ CLog::Log(LOGINFO, "WebSocket [RFC6455]: invalid HTTP method received (GET expected)");
+ return false;
+ }
+
+ // The request must be HTTP/1.1 or higher
+ int pos;
+ if ((pos = strHeader.find(WS_HTTP_TAG)) == string::npos)
+ {
+ CLog::Log(LOGINFO, "WebSocket [RFC6455]: invalid handshake received");
+ return false;
+ }
+
+ pos += strlen(WS_HTTP_TAG);
+ istringstream converter(strHeader.substr(pos, strHeader.find_first_of(" \r\n\t", pos) - pos));
+ float fVersion;
+ converter >> fVersion;
+
+ if (fVersion < 1.1f)
+ {
+ CLog::Log(LOGINFO, "WebSocket [RFC6455]: invalid HTTP version %f (1.1 or higher expected)", fVersion);
+ return false;
+ }
+
+ string websocketKey, websocketProtocol;
+ // There must be a "Host" header
+ value = header.getValue("host");
+ if (value == NULL || strlen(value) == 0)
+ {
+ CLog::Log(LOGINFO, "WebSocket [RFC6455]: \"Host\" header missing");
+ return true;
+ }
+
+ // There must be a "Upgrade" header with the value "websocket"
+ value = header.getValue(WS_HEADER_UPGRADE_LC);
+ if (value == NULL || strcmp(value, WS_HEADER_UPGRADE_VALUE) != 0)
+ {
+ CLog::Log(LOGINFO, "WebSocket [RFC6455]: invalid \"%s\" received", WS_HEADER_UPGRADE);
+ return true;
+ }
+
+ // There must be a "Connection" header with the value "Upgrade"
+ value = header.getValue(WS_HEADER_CONNECTION_LC);
+ if (value == NULL || strcmp(value, WS_HEADER_UPGRADE) != 0)
+ {
+ CLog::Log(LOGINFO, "WebSocket [RFC6455]: invalid \"%s\" received", WS_HEADER_CONNECTION_LC);
+ return true;
+ }
+
+ // There must be a base64 encoded 16 byte (=> 24 byte as base62) "Sec-WebSocket-Key" header
+ value = header.getValue(WS_HEADER_KEY_LC);
+ if (value == NULL || (websocketKey = value).size() != 24)
+ {
+ CLog::Log(LOGINFO, "WebSocket [RFC6455]: invalid \"Sec-WebSocket-Key\" received");
+ return true;
+ }
+
+ // There might be a "Sec-WebSocket-Protocol" header
+ value = header.getValue(WS_HEADER_PROTOCOL_LC);
+ if (value && strlen(value) > 0)
+ {
+ CStdStringArray protocols;
+ StringUtils::SplitString(value, ",", protocols);
+ for (unsigned int index = 0; index < protocols.size(); index++)
+ {
+ if (protocols.at(index).Trim().Equals(WS_PROTOCOL_JSONRPC))
+ {
+ websocketProtocol = WS_PROTOCOL_JSONRPC;
+ break;
+ }
+ }
+ }
+
+ CHttpResponse httpResponse(HTTP::Get, HTTP::SwitchingProtocols, HTTP::Version1_1);
+ httpResponse.AddHeader(WS_HEADER_UPGRADE, WS_HEADER_UPGRADE_VALUE);
+ httpResponse.AddHeader(WS_HEADER_CONNECTION, WS_HEADER_UPGRADE);
+ std::string responseKey = calculateKey(websocketKey);
+ httpResponse.AddHeader(WS_HEADER_ACCEPT, responseKey);
+ if (!websocketProtocol.empty())
+ httpResponse.AddHeader(WS_HEADER_PROTOCOL, websocketProtocol);
+
+ char *responseBuffer;
+ int responseLength = httpResponse.Create(responseBuffer);
+ response = std::string(responseBuffer, responseLength);
+
+ m_state = WebSocketStateConnected;
+
+ return true;
+}
+
+const CWebSocketFrame* CWebSocketV13::Close(WebSocketCloseReason reason /* = WebSocketCloseNormal */, const std::string &message /* = "" */)
+{
+ if (m_state == WebSocketStateNotConnected || m_state == WebSocketStateHandshaking || m_state == WebSocketStateClosed)
+ {
+ CLog::Log(LOGINFO, "WebSocket [RFC6455]: Cannot send a closing handshake if no connection has been established");
+ return NULL;
+ }
+
+ return close(reason, message);
+}
diff --git a/xbmc/network/websocket/WebSocketV13.h b/xbmc/network/websocket/WebSocketV13.h
new file mode 100644
index 0000000000..254d6486e2
--- /dev/null
+++ b/xbmc/network/websocket/WebSocketV13.h
@@ -0,0 +1,32 @@
+#pragma once
+/*
+ * Copyright (C) 2011 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "WebSocketV8.h"
+
+class CWebSocketV13 : public CWebSocketV8
+{
+public:
+ CWebSocketV13() { m_version = 13; }
+
+ virtual bool Handshake(const char* data, size_t length, std::string &response);
+ virtual const CWebSocketFrame* Close(WebSocketCloseReason reason = WebSocketCloseNormal, const std::string &message = "");
+};