From f7186eb6589122fec494ffb3177f75994ca412f3 Mon Sep 17 00:00:00 2001 From: Thibault Charbonnier Date: Wed, 3 Feb 2016 01:03:48 -0800 Subject: [PATCH] fix(ssl) single settimeout call per socket - fix LuaSec timing out because multiple settimeout calls on the socket used to actually trigger timeouts. - actually, this change is also benefitial to regular luasocket or cosocket usage. - new SSLError type - close socket on timeout --- spec/02-integration/08_ssl_spec.lua | 2 +- src/cassandra.lua | 15 ++++++++------- src/cassandra/errors.lua | 5 ++++- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/spec/02-integration/08_ssl_spec.lua b/spec/02-integration/08_ssl_spec.lua index d2900d2..d1a3013 100644 --- a/spec/02-integration/08_ssl_spec.lua +++ b/spec/02-integration/08_ssl_spec.lua @@ -80,7 +80,7 @@ desc("SSL", function() } } assert.truthy(err) - assert.equal("SocketError", err.type) + assert.equal("SSLError", err.type) assert.falsy(session) end) diff --git a/src/cassandra.lua b/src/cassandra.lua index ade7642..de83543 100644 --- a/src/cassandra.lua +++ b/src/cassandra.lua @@ -173,11 +173,9 @@ end function Host:send(request) request:set_version(self.protocol_version) - self:set_timeout(self.options.socket_options.read_timeout) - local frame_reader, err = send_and_receive(self, request) if err then - if err == "timeout" then + if err == "timeout" or err == "wantread" then -- cosocket/luasocket or LuaSec timeout return nil, Errors.TimeoutError(self.address) else return nil, Errors.SocketError(self.address, err) @@ -271,10 +269,12 @@ function Host:connect() return false, Errors.SocketError(self.address, err), true end + self:set_timeout(self.options.socket_options.read_timeout) + if self.options.ssl_options.enabled then ok, err = do_ssl_handshake(self) if not ok then - return false, Errors.SocketError(self.address, err) + return false, Errors.SSLError(self.address, err) end end @@ -314,7 +314,7 @@ function Host:connect() local ok, err = send_auth(self, self.options.auth) if err then - return nil, Errors.AuthenticationError(err) + return false, Errors.AuthenticationError(err) elseif ok then ready = true end @@ -382,7 +382,7 @@ function Host:set_keep_alive() return true end - if self.socket_type == "ngx" then + if self:can_keep_alive() then -- tcpsock:setkeepalive() does not accept nil values, so this is a quick workaround -- see https://github.com/openresty/lua-nginx-module/pull/625 local ok, err @@ -624,7 +624,7 @@ function RequestHandler:send(request) return self:handle_error(request, err) end - -- Success! Make sure to re-up node in case it was marked as DOWN + -- Success! Make sure to re-up the node in case it was marked as DOWN local ok, cache_err = self.coordinator:set_up() if not ok then return nil, cache_err @@ -685,6 +685,7 @@ function RequestHandler:handle_error(request, err) end function RequestHandler:retry(request) + self.coordinator:close() self.n_retries = self.n_retries + 1 log.info("Retrying request on next coordinator") return self:send_on_next_coordinator(request) diff --git a/src/cassandra/errors.lua b/src/cassandra/errors.lua index 388b5c0..0d647ff 100644 --- a/src/cassandra/errors.lua +++ b/src/cassandra/errors.lua @@ -35,6 +35,9 @@ local ERROR_TYPES = { return message.." for socket with peer "..address end }, + SSLError = { + info = "Represents an error happening during the SSL handshake." + }, TimeoutError = { info = "Represents a client-side error that is raised when the client didn't hear back from the server within {client_options.socket_options.read_timeout}.", message = function(address) @@ -42,7 +45,7 @@ local ERROR_TYPES = { end }, AuthenticationError = { - info = "Represents an authentication error from the driver or from a Cassandra node." + info = "Represents an error happening during the authentication flow." }, SharedDictError = { info = "Represents an error with the lua_shared_dict in use.",