diff --git a/ixwebsocket/IXWebSocketHandshake.cpp b/ixwebsocket/IXWebSocketHandshake.cpp index 0af76d77..54105ef1 100644 --- a/ixwebsocket/IXWebSocketHandshake.cpp +++ b/ixwebsocket/IXWebSocketHandshake.cpp @@ -125,6 +125,16 @@ namespace ix return out; } + bool WebSocketHandshake::insensitiveStringCompare(const std::string& a, const std::string& b) + { + return std::equal(a.begin(), a.end(), + b.begin(), b.end(), + [](char a, char b) + { + return tolower(a) == tolower(b); + }); + } + std::tuple WebSocketHandshake::parseRequestLine(const std::string& line) { // Request-Line = Method SP Request-URI SP HTTP-Version CRLF @@ -354,14 +364,23 @@ namespace ix return WebSocketInitResult(false, status, "Error parsing HTTP headers"); } - // Check the presence of the Upgrade field - if (headers.find("connection") == headers.end() || - headers["connection"] != "Upgrade") + // Check the presence of the connection field + if (headers.find("connection") == headers.end()) { - std::string errorMsg("Invalid or missing connection value"); + std::string errorMsg("Missing connection value"); return WebSocketInitResult(false, status, errorMsg); } + // Check the value of the connection field + // Some websocket servers (Go/Gorilla?) send lowercase values for the + // connection header, so do a case insensitive comparison + if (!insensitiveStringCompare(headers["connection"], "Upgrade")) + { + std::stringstream ss; + ss << "Invalid connection value: " << headers["connection"]; + return WebSocketInitResult(false, status, ss.str()); + } + char output[29] = {}; WebSocketHandshakeKeyGen::generate(secWebSocketKey.c_str(), output); if (std::string(output) != headers["sec-websocket-accept"]) diff --git a/ixwebsocket/IXWebSocketHandshake.h b/ixwebsocket/IXWebSocketHandshake.h index 779f56d3..29814fd6 100644 --- a/ixwebsocket/IXWebSocketHandshake.h +++ b/ixwebsocket/IXWebSocketHandshake.h @@ -76,6 +76,7 @@ namespace ix std::tuple parseRequestLine(const std::string& line); std::string trim(const std::string& str); + bool insensitiveStringCompare(const std::string& a, const std::string& b); std::atomic& _requestInitCancellation; std::shared_ptr _socket;