diff --git a/server/core/dcb.c b/server/core/dcb.c index 3660708c2..8a04c9b3c 100644 --- a/server/core/dcb.c +++ b/server/core/dcb.c @@ -525,8 +525,7 @@ int rc; * @param dcb The DCB to read from * @param head Pointer to linked list to append data to * @return -1 on error, otherwise the number of read bytes on the last. - * 0 is returned if no data available. - * iteration of while loop. + * 0 is returned if no data available on the last iteration of while loop. */ int dcb_read(DCB *dcb, GWBUF **head) diff --git a/server/core/gw_utils.c b/server/core/gw_utils.c index 04f99b07d..3408f9f28 100644 --- a/server/core/gw_utils.c +++ b/server/core/gw_utils.c @@ -135,6 +135,7 @@ int gw_read_gwbuff(DCB *dcb, GWBUF **head, int b) { if (b <= 0) { //fprintf(stderr, "||| read_gwbuff called with 0 bytes for %i, closing\n", dcb->fd); + ss_dassert(false); #if 0 dcb->func.close(dcb); #endif diff --git a/server/modules/include/mysql_client_server_protocol.h b/server/modules/include/mysql_client_server_protocol.h index c82444349..576053b81 100644 --- a/server/modules/include/mysql_client_server_protocol.h +++ b/server/modules/include/mysql_client_server_protocol.h @@ -239,7 +239,7 @@ void gw_mysql_close(MySQLProtocol **ptr); MySQLProtocol* mysql_protocol_init(DCB* dcb, int fd); MySQLProtocol *gw_mysql_init(MySQLProtocol *data); void gw_mysql_close(MySQLProtocol **ptr); -bool gw_receive_backend_auth(MySQLProtocol *protocol); +int gw_receive_backend_auth(MySQLProtocol *protocol); int gw_decode_mysql_server_handshake(MySQLProtocol *protocol, uint8_t *payload); int gw_read_backend_handshake(MySQLProtocol *protocol); int gw_send_authentication_to_backend( diff --git a/server/modules/protocol/mysql_backend.c b/server/modules/protocol/mysql_backend.c index e477e082a..354433567 100644 --- a/server/modules/protocol/mysql_backend.c +++ b/server/modules/protocol/mysql_backend.c @@ -203,6 +203,7 @@ static int gw_read_backend_event(DCB *dcb) { ROUTER *router_instance = NULL; void *rsession = NULL; SESSION *session = dcb->session; + int receive_rc = 0; CHK_SESSION(session); @@ -213,21 +214,46 @@ static int gw_read_backend_event(DCB *dcb) { /** * Read backed auth reply */ - if (gw_receive_backend_auth(backend_protocol)) { - backend_protocol->state = MYSQL_IDLE; - } else { - backend_protocol->state = MYSQL_AUTH_FAILED; + receive_rc = gw_receive_backend_auth(backend_protocol); + switch (receive_rc) { + case -1: + backend_protocol->state = MYSQL_AUTH_FAILED; + skygw_log_write_flush( LOGFILE_ERROR, + "Error : backend server didn't accept " + "authentication for user %s.", + current_session->user); + break; + case 1: + backend_protocol->state = MYSQL_IDLE; + skygw_log_write_flush( + LOGFILE_TRACE, "%lu [gw_read_backend_event] " - "gw_receive_backend_auth failed. dcb " + "gw_receive_backend_auth succeed. dcb " "%p fd %d, user %s.", pthread_self(), dcb, dcb->fd, current_session->user); - } + break; + default: + ss_dassert(receive_rc == 0); + skygw_log_write_flush( + LOGFILE_TRACE, + "%lu [gw_read_backend_event] " + "gw_receive_backend_auth read " + "successfully " + "nothing. dcb %p fd %d, user %s.", + pthread_self(), + dcb, + dcb->fd, + current_session->user); + rc = 0; + goto return_rc; + break; + } /* switch */ } if (backend_protocol->state == MYSQL_AUTH_FAILED) { @@ -294,7 +320,7 @@ static int gw_read_backend_event(DCB *dcb) { /* reading MySQL command output from backend and writing to the client */ { - GWBUF *head = NULL; + GWBUF *writebuf = NULL; ROUTER_OBJECT *router = NULL; ROUTER *router_instance = NULL; void *rsession = NULL; @@ -302,7 +328,7 @@ static int gw_read_backend_event(DCB *dcb) { CHK_SESSION(session); /* read available backend data */ - rc = dcb_read(dcb, &head); + rc = dcb_read(dcb, &writebuf); if (rc < 0) { /** @@ -314,6 +340,11 @@ static int gw_read_backend_event(DCB *dcb) { rc = 0; goto return_rc; } + + if (writebuf == NULL) { + rc = 0; + goto return_rc; + } router = session->service->router; router_instance = session->service->router_instance; rsession = session->router_session; @@ -341,7 +372,7 @@ static int gw_read_backend_event(DCB *dcb) { { router->clientReply(router_instance, rsession, - head, + writebuf, dcb); rc = 1; } diff --git a/server/modules/protocol/mysql_client.c b/server/modules/protocol/mysql_client.c index 44a0f501d..a5fed9e24 100644 --- a/server/modules/protocol/mysql_client.c +++ b/server/modules/protocol/mysql_client.c @@ -552,8 +552,15 @@ int gw_read_client_event(DCB* dcb) { pthread_self(), dcb, dcb->fd); - + if (dcb->state == DCB_STATE_POLLING) { + /* Send a custom error as MySQL command reply */ + mysql_send_custom_error( + dcb, + 1, + 0, + "ioctl returned b==0"); + dcb->func.close(dcb); } rc = 0; @@ -1143,15 +1150,12 @@ return_rc: return rc; } -/* -*/ static int gw_error_client_event(DCB *dcb) { - /** - * should this be removed if we don't want to execute it ? - * - //fprintf(stderr, "#### Handle error function gw_error_client_event, for [%i] is [%s]\n", dcb->fd, gw_state2string(dcb->state)); - //dcb_close(dcb); - */ + SESSION* session; + ROUTER_OBJECT* router; + void* router_instance; + void* rsession; + #if defined(SS_DEBUG) MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol; if (dcb->state == DCB_STATE_POLLING || @@ -1161,12 +1165,31 @@ static int gw_error_client_event(DCB *dcb) { CHK_PROTOCOL(protocol); } #endif +#if 1 + session = dcb->session; + + if (session != NULL) { + CHK_SESSION(session); + router = session->service->router; + router_instance = session->service->router_instance; + rsession = session->router_session; + + if (rsession) { + router->closeSession(router_instance, rsession); + } + } +#endif + dcb_close(dcb); return 1; } static int gw_client_close(DCB *dcb) { + SESSION* session; + ROUTER_OBJECT* router; + void* router_instance; + void* rsession; #if defined(SS_DEBUG) MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol; if (dcb->state == DCB_STATE_POLLING || @@ -1175,8 +1198,23 @@ gw_client_close(DCB *dcb) { CHK_PROTOCOL(protocol); } +#endif +#if 1 + session = dcb->session; + + if (session != NULL) { + CHK_SESSION(session); + router = session->service->router; + router_instance = session->service->router_instance; + rsession = session->router_session; + + if (rsession) { + router->closeSession(router_instance, rsession); + } + } #endif dcb_close(dcb); + return 1; } @@ -1191,6 +1229,10 @@ gw_client_close(DCB *dcb) static int gw_client_hangup_event(DCB *dcb) { + SESSION* session; + ROUTER_OBJECT* router; + void* router_instance; + void* rsession; #if defined(SS_DEBUG) MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol; if (dcb->state == DCB_STATE_POLLING || @@ -1199,6 +1241,20 @@ gw_client_hangup_event(DCB *dcb) { CHK_PROTOCOL(protocol); } +#endif +#if 1 + session = dcb->session; + + if (session != NULL) { + CHK_SESSION(session); + router = session->service->router; + router_instance = session->service->router_instance; + rsession = session->router_session; + + if (rsession) { + router->closeSession(router_instance, rsession); + } + } #endif dcb_close(dcb); return 1; diff --git a/server/modules/protocol/mysql_common.c b/server/modules/protocol/mysql_common.c index 67d60997e..a1e602083 100644 --- a/server/modules/protocol/mysql_common.c +++ b/server/modules/protocol/mysql_common.c @@ -296,16 +296,17 @@ int gw_decode_mysql_server_handshake(MySQLProtocol *conn, uint8_t *payload) { * Receive the MySQL authentication packet from backend, packet # is 2 * * @param conn The MySQL protocol structure - * @return true if authentication succeed, false otherwise + * @return -1 in case of failure, 0 if there was nothing to read, 1 if read + * was successful. */ -bool gw_receive_backend_auth( +int gw_receive_backend_auth( MySQLProtocol *protocol) { int n = -1; GWBUF *head = NULL; DCB *dcb = protocol->owner_dcb; uint8_t *ptr = NULL; - bool succp = false; + int rc = 0; n = dcb_read(dcb, &head); @@ -321,7 +322,7 @@ bool gw_receive_backend_auth( * 5th byte is 0x0 if successful. */ if (ptr[4] == '\x00') { - succp = true; + rc = 1; } else { uint8_t* tmpbuf = (uint8_t *)calloc(1, GWBUF_LENGTH(head)+1); @@ -342,25 +343,24 @@ bool gw_receive_backend_auth( "Error : Invalid authentication message from " "backend server. Authentication failed."); free(tmpbuf); + rc = -1; } /** * Remove data from buffer. */ head = gwbuf_consume(head, gwbuf_length(head)); - } else { -#if 1 + } + else if (n == 0) + { /** * This is considered as success because call didn't fail, * although no bytes was read. */ - if (n == 0) { - succp = true; - } -#endif + rc = 0; skygw_log_write( LOGFILE_TRACE, - "%lu [gw_receive_backend_auth] Reading from backend dcb " - "%p fd %d in state %s failed. n %d, head %p, len %d", + "%lu [gw_receive_backend_auth] Read zero bytes from " + "backend dcb %p fd %d in state %s. n %d, head %p, len %d", pthread_self(), dcb, dcb->fd, @@ -369,7 +369,24 @@ bool gw_receive_backend_auth( head, (head == NULL) ? 0 : GWBUF_LENGTH(head)); } - return succp; + else + { + ss_dassert(n < 0 && head == NULL); + rc = -1; + skygw_log_write( + LOGFILE_TRACE, + "%lu [gw_receive_backend_auth] Reading from backend dcb %p " + "fd %d in state %s failed. n %d, head %p, len %d", + pthread_self(), + dcb, + dcb->fd, + STRDCBSTATE(dcb->state), + n, + head, + (head == NULL) ? 0 : GWBUF_LENGTH(head)); + } + + return rc; } /**