From b2b715fcae327c46fce262ee7bc53d897214fa0f Mon Sep 17 00:00:00 2001 From: Massimiliano Pinto Date: Fri, 13 Sep 2013 18:22:24 +0200 Subject: [PATCH] Fixed failed handshake handling, taking care of dcb->delayq before sending reply one time and not twice. --- server/modules/protocol/mysql_backend.c | 71 +++++++++++++++---------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/server/modules/protocol/mysql_backend.c b/server/modules/protocol/mysql_backend.c index 72559cbde..000c80a5d 100644 --- a/server/modules/protocol/mysql_backend.c +++ b/server/modules/protocol/mysql_backend.c @@ -170,31 +170,36 @@ static int gw_read_backend_event(DCB *dcb) { * 3. and return */ if (backend_protocol->state == MYSQL_CONNECTED) { - if (gw_read_backend_handshake(backend_protocol) < 0) { + // read mysql handshake + if (gw_read_backend_handshake(backend_protocol) != 0) { backend_protocol->state = MYSQL_AUTH_FAILED; rc = 1; - goto return_rc; + } else { + // handshake decoded, send the auth credentials + if (gw_send_authentication_to_backend( + current_session->db, + current_session->user, + current_session->client_sha1, + backend_protocol) != 0) { + backend_protocol->state = MYSQL_AUTH_FAILED; + rc = 1; + } else { + // next step is waiting server response with a new EPOLLIN event + backend_protocol->state = MYSQL_AUTH_RECV; + rc = 0; + goto return_rc; + } } - - if (gw_send_authentication_to_backend( - current_session->db, - current_session->user, - current_session->client_sha1, - backend_protocol) != 0) { - backend_protocol->state = MYSQL_AUTH_FAILED; - rc = 1; - goto return_rc; - } - - // the protocol state here is MYSQL_AUTH_RECV - ss_dassert(backend_protocol->state == MYSQL_AUTH_RECV); - rc = 1; - goto return_rc; } - /* ready to check the authentication reply from backend */ + /* + * Now: + * -- check the authentication reply from backend + * OR + * -- handle a previous handshake error + */ - if (backend_protocol->state == MYSQL_AUTH_RECV) { + if (backend_protocol->state == MYSQL_AUTH_RECV || backend_protocol->state == MYSQL_AUTH_FAILED) { ROUTER_OBJECT *router = NULL; ROUTER *router_instance = NULL; void *rsession = NULL; @@ -205,9 +210,14 @@ static int gw_read_backend_event(DCB *dcb) { router = session->service->router; router_instance = session->service->router_instance; - - /* read backed auth reply */ - rv = gw_receive_backend_auth(backend_protocol); + + /* if a MYSQL_AUTH_FAILED is detected, don't read from backend and set rv */ + if (backend_protocol->state == MYSQL_AUTH_FAILED) { + rv = MYSQL_FAILED_AUTHENTICATION; + } else { + /* yes, do read backed auth reply */ + rv = gw_receive_backend_auth(backend_protocol); + } switch (rv) { case MYSQL_FAILED_AUTHENTICATION: @@ -222,12 +232,17 @@ static int gw_read_backend_event(DCB *dcb) { current_session->user); backend_protocol->state = MYSQL_AUTH_FAILED; - /* send an error to the client */ - mysql_send_custom_error( - dcb->session->client, - 1, - 0, - "Connection to backend lost right now"); + + /* check the delayq before the reply */ + if (dcb->delayq) { + /* send an error to the client */ + mysql_send_custom_error( + dcb->session->client, + 1, + 0, + "Connection to backend lost right now"); + } + /** * Protect call of closeSession. */