From ad041207a44f34a9c022a6444c4f013cb58e85b6 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 11 Aug 2015 14:23:29 +0300 Subject: [PATCH 1/4] transport/server: Catch all request processing errors We need to also catch exceptions in top-level connection::process() so that they are converted to proper CQL protocol errors. Signed-off-by: Pekka Enberg --- transport/server.cc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/transport/server.cc b/transport/server.cc index 448b128123..b8123daf84 100644 --- a/transport/server.cc +++ b/transport/server.cc @@ -207,8 +207,22 @@ public: _server._notifier->unregister_connection(this); } future<> process() { - return do_until([this] { return _read_buf.eof(); }, [this] { return process_request(); }) - .finally([this] { + return do_until([this] { + return _read_buf.eof(); + }, [this] { + return process_request(); + }).then_wrapped([this] (future<> f) { + try { + f.get(); + return make_ready_future<>(); + } catch (const exceptions::cassandra_exception& ex) { + return write_error(0, ex.code(), ex.what()); + } catch (std::exception& ex) { + return write_error(0, exceptions::exception_code::SERVER_ERROR, ex.what()); + } catch (...) { + return write_error(0, exceptions::exception_code::SERVER_ERROR, "unknown error"); + } + }).finally([this] { return _pending_requests_gate.close().then([this] { return std::move(_ready_to_respond); }); From bb067782d7ef763afead7961a7bd19b5d9130041 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Mon, 10 Aug 2015 13:04:09 +0300 Subject: [PATCH 2/4] transport/server: Fix CQL binary protocol version validation We only support up to CQL protocol v3. Fixes #117. Signed-off-by: Pekka Enberg --- transport/server.cc | 4 ++-- transport/server.hh | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/transport/server.cc b/transport/server.cc index b8123daf84..f39725f898 100644 --- a/transport/server.cc +++ b/transport/server.cc @@ -659,8 +659,8 @@ cql_server::connection::read_frame() { } _version = buf[0]; init_serialization_format(); - if (_version < 1 || _version > 4) { - throw bad_cql_protocol_version(); + if (_version < 1 || _version > current_version) { + throw exceptions::protocol_exception(sprint("Invalid or unsupported protocol version: %d", _version)); } return _read_buf.read_exactly(frame_size() - 1).then([this] (temporary_buffer tail) { temporary_buffer full(frame_size()); diff --git a/transport/server.hh b/transport/server.hh index 19669780b3..7e1c283afb 100644 --- a/transport/server.hh +++ b/transport/server.hh @@ -24,6 +24,8 @@ class database; class cql_server { class event_notifier; + static constexpr int current_version = 3; + std::vector _listeners; distributed& _proxy; distributed& _query_processor; From 48abeefdda05337a1624ae4d9a770ada88db177b Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 11 Aug 2015 10:46:33 +0300 Subject: [PATCH 3/4] transport/server: Fix connection version mismatch validation Signed-off-by: Pekka Enberg --- transport/server.cc | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/transport/server.cc b/transport/server.cc index f39725f898..0c37eaac38 100644 --- a/transport/server.cc +++ b/transport/server.cc @@ -37,12 +37,6 @@ struct cql_frame_error : std::exception { } }; -struct bad_cql_protocol_version : std::exception { - const char* what() const throw () override { - return "bad cql binary protocol version"; - } -}; - struct [[gnu::packed]] cql_binary_frame_v1 { uint8_t version; uint8_t flags; @@ -642,7 +636,8 @@ cql_server::connection::parse_frame(temporary_buffer buf) { abort(); } if (v3.version != _version) { - throw bad_cql_protocol_version(); + throw exceptions::protocol_exception(sprint("Invalid message version. Got %d but previous messages on this connection had version %d", v3.version, _version)); + } return v3; } From d461443bf24f343cb787adca7a222b6fe1746f74 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 11 Aug 2015 11:02:20 +0300 Subject: [PATCH 4/4] transport/server: Fix error handling in parse_frame() Throw a protocol exception instead of killing the process with abort(). Signed-off-by: Pekka Enberg --- transport/server.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/server.cc b/transport/server.cc index 0c37eaac38..13f16c20df 100644 --- a/transport/server.cc +++ b/transport/server.cc @@ -633,7 +633,7 @@ cql_server::connection::parse_frame(temporary_buffer buf) { break; } default: - abort(); + throw exceptions::protocol_exception(sprint("Invalid or unsupported protocol version: %d", _version)); } if (v3.version != _version) { throw exceptions::protocol_exception(sprint("Invalid message version. Got %d but previous messages on this connection had version %d", v3.version, _version));