Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/crow/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ namespace crow
else
#endif
{
// TODO(EDev): Move these 6 lines to a method in http_server.
std::vector<crow::websocket::connection*> websockets_to_close = websockets_;
for (auto websocket : websockets_to_close)
{
Expand Down
6 changes: 5 additions & 1 deletion include/crow/http_connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ namespace crow
if (!ec)
{
start_deadline();
parser_.clear();

do_read();
}
Expand Down Expand Up @@ -137,7 +138,7 @@ namespace crow
is_invalid_request = true;
res = response(400);
}
if (req_.upgrade)
else if (req_.upgrade)
{
// h2 or h2c headers
if (req_.get_header_value("upgrade").substr(0, 2) == "h2")
Expand Down Expand Up @@ -409,6 +410,7 @@ namespace crow
res.end();
res.clear();
buffers_.clear();
parser_.clear();
}

void do_write_general()
Expand Down Expand Up @@ -467,6 +469,7 @@ namespace crow
res.end();
res.clear();
buffers_.clear();
parser_.clear();
}
}

Expand Down Expand Up @@ -528,6 +531,7 @@ namespace crow
is_writing = false;
res.clear();
res_body_copy_.clear();
parser_.clear();
if (!ec)
{
if (close_connection_)
Expand Down
8 changes: 0 additions & 8 deletions include/crow/http_parser_merged.h
Original file line number Diff line number Diff line change
Expand Up @@ -1576,7 +1576,6 @@ static const int8_t unhex[256] =

if (parser->flags & F_TRAILING) {
/* End of a chunked request */
parser->state = CROW_NEW_MESSAGE();
CROW_CALLBACK_NOTIFY(message_complete);
break;
}
Expand Down Expand Up @@ -1652,14 +1651,12 @@ static const int8_t unhex[256] =

/* Exit, the rest of the connect is in a different protocol. */
if (parser->upgrade) {
parser->state = CROW_NEW_MESSAGE();
CROW_CALLBACK_NOTIFY(message_complete);
parser->nread = nread;
return (p - data) + 1;
}

if (parser->flags & F_SKIPBODY) {
parser->state = CROW_NEW_MESSAGE();
CROW_CALLBACK_NOTIFY(message_complete);
} else if (parser->flags & F_CHUNKED) {
/* chunked encoding - ignore Content-Length header,
Expand Down Expand Up @@ -1699,7 +1696,6 @@ static const int8_t unhex[256] =
if (parser->content_length == 0)
{
/* Content-Length header given but zero: Content-Length: 0\r\n */
parser->state = CROW_NEW_MESSAGE();
CROW_CALLBACK_NOTIFY(message_complete);
}
else if (parser->content_length != CROW_ULLONG_MAX)
Expand All @@ -1710,7 +1706,6 @@ static const int8_t unhex[256] =
else
{
/* Assume content-length 0 - read the next */
parser->state = CROW_NEW_MESSAGE();
CROW_CALLBACK_NOTIFY(message_complete);
}
}
Expand Down Expand Up @@ -1762,7 +1757,6 @@ static const int8_t unhex[256] =
break;

case s_message_done:
parser->state = CROW_NEW_MESSAGE();
CROW_CALLBACK_NOTIFY(message_complete);
break;

Expand Down Expand Up @@ -2007,9 +2001,7 @@ http_parser_set_max_header_size(uint32_t size) {
#undef CROW_TOKEN
#undef CROW_IS_URL_CHAR
//#undef CROW_IS_HOST_CHAR
#undef CROW_start_state
#undef CROW_STRICT_CHECK
#undef CROW_NEW_MESSAGE

}

Expand Down
16 changes: 12 additions & 4 deletions include/crow/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
#include <unordered_map>
#include <algorithm>

#include "crow/http_parser_merged.h"
#include "crow/http_request.h"
#include "crow/http_parser_merged.h"

namespace crow
{
Expand All @@ -16,10 +16,8 @@ namespace crow
template<typename Handler>
struct HTTPParser : public http_parser
{
static int on_message_begin(http_parser* self_)
static int on_message_begin(http_parser*)
{
HTTPParser* self = static_cast<HTTPParser*>(self_);
self->clear();
return 0;
}
static int on_method(http_parser* self_)
Expand Down Expand Up @@ -97,6 +95,7 @@ namespace crow
{
HTTPParser* self = static_cast<HTTPParser*>(self_);

self->message_complete = true;
self->process_message();
return 0;
}
Expand All @@ -110,6 +109,9 @@ namespace crow
/// Parse a buffer into the different sections of an HTTP request.
bool feed(const char* buffer, int length)
{
if (message_complete)
return true;

const static http_parser_settings settings_{
on_message_begin,
on_method,
Expand Down Expand Up @@ -141,6 +143,8 @@ namespace crow
header_value.clear();
header_building_state = 0;
qs_point = 0;
message_complete = false;
state = CROW_NEW_MESSAGE();
}

inline void process_url()
Expand Down Expand Up @@ -184,9 +188,13 @@ namespace crow

private:
int header_building_state = 0;
bool message_complete = false;
std::string header_field;
std::string header_value;

Handler* handler_; ///< This is currently an HTTP connection object (\ref crow.Connection).
};
} // namespace crow

#undef CROW_NEW_MESSAGE
#undef CROW_start_state
60 changes: 58 additions & 2 deletions tests/unittest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2472,7 +2472,7 @@ TEST_CASE("stream_response")

TEST_CASE("websocket")
{
static std::string http_message = "GET /ws HTTP/1.1\r\nConnection: keep-alive, Upgrade\r\nupgrade: websocket\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n";
static std::string http_message = "GET /ws HTTP/1.1\r\nConnection: keep-alive, Upgrade\r\nupgrade: websocket\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\nHost: localhost\r\n\r\n";

static bool connected{false};

Expand Down Expand Up @@ -2633,14 +2633,70 @@ TEST_CASE("websocket")
app.stop();
} // websocket

TEST_CASE("websocket_max_payload")
TEST_CASE("websocket_missing_host")
{
static std::string http_message = "GET /ws HTTP/1.1\r\nConnection: keep-alive, Upgrade\r\nupgrade: websocket\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n";

static bool connected{false};

SimpleApp app;

CROW_WEBSOCKET_ROUTE(app, "/ws")
.onaccept([&](const crow::request& req, void**) {
CROW_LOG_INFO << "Accepted websocket with URL " << req.url;
return true;
})
.onopen([&](websocket::connection&) {
connected = true;
CROW_LOG_INFO << "Connected websocket and value is " << connected;
})
.onmessage([&](websocket::connection& conn, const std::string& message, bool isbin) {
CROW_LOG_INFO << "Message is \"" << message << '\"';
if (!isbin && message == "PINGME")
conn.send_ping("");
else if (!isbin && message == "Hello")
conn.send_text("Hello back");
else if (isbin && message == "Hello bin")
conn.send_binary("Hello back bin");
})
.onclose([&](websocket::connection&, const std::string&) {
CROW_LOG_INFO << "Closing websocket";
});

app.validate();

auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(45471).run_async();
app.wait_for_server_start();
asio::io_service is;

asio::ip::tcp::socket c(is);
c.connect(asio::ip::tcp::endpoint(
asio::ip::address::from_string(LOCALHOST_ADDRESS), 45471));


char buf[2048];

// Handshake should fail
{
std::fill_n(buf, 2048, 0);
c.send(asio::buffer(http_message));

c.receive(asio::buffer(buf, 2048));
std::this_thread::sleep_for(std::chrono::milliseconds(5));
CHECK(!connected);
}

app.stop();
} // websocket

TEST_CASE("websocket_max_payload")
{
static std::string http_message = "GET /ws HTTP/1.1\r\nConnection: keep-alive, Upgrade\r\nupgrade: websocket\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\nHost: localhost\r\n\r\n";

static bool connected{false};

SimpleApp app;

CROW_WEBSOCKET_ROUTE(app, "/ws")
.onopen([&](websocket::connection&) {
connected = true;
Expand Down