improve some websocket error messages + add a utility function with unittest to parse status line and stop using scanf which triggers warnings on Windows

This commit is contained in:
Benjamin Sergeant 2019-09-09 21:23:57 -07:00
parent 6c0890594b
commit 64d3c99f99
6 changed files with 55 additions and 7 deletions

View File

@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file.
## [6.2.0] - 2019-09-09
- websocket and http server: server does not close the bound client socket in many cases
- improve some websocket error messages
- add a utility function with unittest to parse status line and stop using scanf which triggers warnings on Windows
## [6.1.0] - 2019-09-08

View File

@ -27,6 +27,36 @@ namespace ix
return out;
}
std::pair<std::string, int> Http::parseStatusLine(const std::string& line)
{
// Request-Line = Method SP Request-URI SP HTTP-Version CRLF
std::string token;
std::stringstream tokenStream(line);
std::vector<std::string> tokens;
// Split by ' '
while (std::getline(tokenStream, token, ' '))
{
tokens.push_back(token);
}
std::string httpVersion;
if (tokens.size() >= 1)
{
httpVersion = trim(tokens[0]);
}
int statusCode = -1;
if (tokens.size() >= 2)
{
std::stringstream ss;
ss << trim(tokens[1]);
ss >> statusCode;
}
return std::make_pair(httpVersion, statusCode);
}
std::tuple<std::string, std::string, std::string> Http::parseRequestLine(const std::string& line)
{
// Request-Line = Method SP Request-URI SP HTTP-Version CRLF

View File

@ -115,6 +115,8 @@ namespace ix
std::shared_ptr<Socket> socket);
static bool sendResponse(HttpResponsePtr response, std::shared_ptr<Socket> socket);
static std::pair<std::string, int> parseStatusLine(
const std::string& line);
static std::tuple<std::string, std::string, std::string> parseRequestLine(
const std::string& line);
static std::string trim(const std::string& str);

View File

@ -164,20 +164,23 @@ namespace ix
}
// Validate status
int status;
auto statusLine = Http::parseStatusLine(line);
std::string httpVersion = statusLine.first;
int status = statusLine.second;
// HTTP/1.0 is too old.
if (sscanf(line.c_str(), "HTTP/1.0 %d", &status) == 1)
if (httpVersion != "HTTP/1.1")
{
std::stringstream ss;
ss << "Server version is HTTP/1.0. Rejecting connection to " << host
ss << "Expecting HTTP/1.1, got " << httpVersion << ". "
<< "Rejecting connection to " << host
<< ", status: " << status
<< ", HTTP Status line: " << line;
return WebSocketInitResult(false, status, ss.str());
}
// We want an 101 HTTP status
if (sscanf(line.c_str(), "HTTP/1.1 %d", &status) != 1 || status != 101)
if (status != 101)
{
std::stringstream ss;
ss << "Got bad status connecting to " << host
@ -295,9 +298,15 @@ namespace ix
return sendErrorResponse(400, "Missing Sec-WebSocket-Key value");
}
if (headers.find("upgrade") == headers.end())
{
return sendErrorResponse(400, "Missing Upgrade header");
}
if (!insensitiveStringCompare(headers["upgrade"], "WebSocket"))
{
return sendErrorResponse(400, "Invalid or missing Upgrade header");
return sendErrorResponse(400, "Invalid Upgrade header, "
"need WebSocket, got " + headers["upgrade"]);
}
if (headers.find("sec-websocket-version") == headers.end())
@ -314,7 +323,7 @@ namespace ix
if (version != 13)
{
return sendErrorResponse(400, "Invalid Sec-WebSocket-Version, "
"need 13, got" + ss.str());
"need 13, got " + ss.str());
}
}

View File

@ -681,8 +681,12 @@ namespace ix
reason = WebSocketCloseConstants::kInvalidFramePayloadDataMessage;
}
//
// Validate close codes. Autobahn 7.9.*
// 1014, 1015 are debattable. The firefox MSDN has a description for them
// 1014, 1015 are debattable. The firefox MSDN has a description for them.
// Full list of status code and status range is defined in the dedicated
// RFC section at https://tools.ietf.org/html/rfc6455#page-45
//
if (code < 1000 || code == 1004 || code == 1006 ||
(code > 1013 && code < 3000))
{

View File

@ -62,6 +62,7 @@ set (SOURCES
IXHttpClientTest.cpp
IXHttpServerTest.cpp
IXUnityBuildsTest.cpp
IXHttpTest.cpp
)
# Some unittest don't work on windows yet