mysql_client_server_protocol.h :

changed gw_receive_backend_auth declaration to return int instead of boolean.
mysql_backend.c:
	gw_read_backend_event calls gw_receive_backend_auth which either fails (== -1), succeeds with nothing to read (== 0) or succeeds (== 1). For each case there is handling. If dcb_read succeeds without read bytes, return asap.
mysql_client.c:
	gw_error_client_event, gw_client_close, gw_client_hangup_event : all close client dcb but now they also close backend dcb.
mysql_common.c:
	gw_receive_backend_auth, return -1, 0, or 1 if read from backend failed, was empty, or succeed, respectively.:
This commit is contained in:
vraatikka
2013-10-07 14:00:44 +03:00
parent 80b67d1083
commit 655a6537b2
6 changed files with 138 additions and 34 deletions

View File

@ -525,8 +525,7 @@ int rc;
* @param dcb The DCB to read from * @param dcb The DCB to read from
* @param head Pointer to linked list to append data to * @param head Pointer to linked list to append data to
* @return -1 on error, otherwise the number of read bytes on the last. * @return -1 on error, otherwise the number of read bytes on the last.
* 0 is returned if no data available. * 0 is returned if no data available on the last iteration of while loop.
* iteration of while loop.
*/ */
int int
dcb_read(DCB *dcb, GWBUF **head) dcb_read(DCB *dcb, GWBUF **head)

View File

@ -135,6 +135,7 @@ int gw_read_gwbuff(DCB *dcb, GWBUF **head, int b) {
if (b <= 0) { if (b <= 0) {
//fprintf(stderr, "||| read_gwbuff called with 0 bytes for %i, closing\n", dcb->fd); //fprintf(stderr, "||| read_gwbuff called with 0 bytes for %i, closing\n", dcb->fd);
ss_dassert(false);
#if 0 #if 0
dcb->func.close(dcb); dcb->func.close(dcb);
#endif #endif

View File

@ -239,7 +239,7 @@ void gw_mysql_close(MySQLProtocol **ptr);
MySQLProtocol* mysql_protocol_init(DCB* dcb, int fd); MySQLProtocol* mysql_protocol_init(DCB* dcb, int fd);
MySQLProtocol *gw_mysql_init(MySQLProtocol *data); MySQLProtocol *gw_mysql_init(MySQLProtocol *data);
void gw_mysql_close(MySQLProtocol **ptr); 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_decode_mysql_server_handshake(MySQLProtocol *protocol, uint8_t *payload);
int gw_read_backend_handshake(MySQLProtocol *protocol); int gw_read_backend_handshake(MySQLProtocol *protocol);
int gw_send_authentication_to_backend( int gw_send_authentication_to_backend(

View File

@ -203,6 +203,7 @@ static int gw_read_backend_event(DCB *dcb) {
ROUTER *router_instance = NULL; ROUTER *router_instance = NULL;
void *rsession = NULL; void *rsession = NULL;
SESSION *session = dcb->session; SESSION *session = dcb->session;
int receive_rc = 0;
CHK_SESSION(session); CHK_SESSION(session);
@ -213,21 +214,46 @@ static int gw_read_backend_event(DCB *dcb) {
/** /**
* Read backed auth reply * Read backed auth reply
*/ */
if (gw_receive_backend_auth(backend_protocol)) { receive_rc = gw_receive_backend_auth(backend_protocol);
backend_protocol->state = MYSQL_IDLE;
} else {
backend_protocol->state = MYSQL_AUTH_FAILED;
switch (receive_rc) {
case -1:
backend_protocol->state = MYSQL_AUTH_FAILED;
skygw_log_write_flush( skygw_log_write_flush(
LOGFILE_ERROR, 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] " "%lu [gw_read_backend_event] "
"gw_receive_backend_auth failed. dcb " "gw_receive_backend_auth succeed. dcb "
"%p fd %d, user %s.", "%p fd %d, user %s.",
pthread_self(), pthread_self(),
dcb, dcb,
dcb->fd, dcb->fd,
current_session->user); 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) { 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 */ /* reading MySQL command output from backend and writing to the client */
{ {
GWBUF *head = NULL; GWBUF *writebuf = NULL;
ROUTER_OBJECT *router = NULL; ROUTER_OBJECT *router = NULL;
ROUTER *router_instance = NULL; ROUTER *router_instance = NULL;
void *rsession = NULL; void *rsession = NULL;
@ -302,7 +328,7 @@ static int gw_read_backend_event(DCB *dcb) {
CHK_SESSION(session); CHK_SESSION(session);
/* read available backend data */ /* read available backend data */
rc = dcb_read(dcb, &head); rc = dcb_read(dcb, &writebuf);
if (rc < 0) { if (rc < 0) {
/** /**
@ -314,6 +340,11 @@ static int gw_read_backend_event(DCB *dcb) {
rc = 0; rc = 0;
goto return_rc; goto return_rc;
} }
if (writebuf == NULL) {
rc = 0;
goto return_rc;
}
router = session->service->router; router = session->service->router;
router_instance = session->service->router_instance; router_instance = session->service->router_instance;
rsession = session->router_session; rsession = session->router_session;
@ -341,7 +372,7 @@ static int gw_read_backend_event(DCB *dcb) {
{ {
router->clientReply(router_instance, router->clientReply(router_instance,
rsession, rsession,
head, writebuf,
dcb); dcb);
rc = 1; rc = 1;
} }

View File

@ -552,8 +552,15 @@ int gw_read_client_event(DCB* dcb) {
pthread_self(), pthread_self(),
dcb, dcb,
dcb->fd); dcb->fd);
if (dcb->state == DCB_STATE_POLLING) { 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); dcb->func.close(dcb);
} }
rc = 0; rc = 0;
@ -1143,15 +1150,12 @@ return_rc:
return rc; return rc;
} }
/*
*/
static int gw_error_client_event(DCB *dcb) { static int gw_error_client_event(DCB *dcb) {
/** SESSION* session;
* should this be removed if we don't want to execute it ? ROUTER_OBJECT* router;
* void* router_instance;
//fprintf(stderr, "#### Handle error function gw_error_client_event, for [%i] is [%s]\n", dcb->fd, gw_state2string(dcb->state)); void* rsession;
//dcb_close(dcb);
*/
#if defined(SS_DEBUG) #if defined(SS_DEBUG)
MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol; MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol;
if (dcb->state == DCB_STATE_POLLING || if (dcb->state == DCB_STATE_POLLING ||
@ -1161,12 +1165,31 @@ static int gw_error_client_event(DCB *dcb) {
CHK_PROTOCOL(protocol); CHK_PROTOCOL(protocol);
} }
#endif #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; return 1;
} }
static int static int
gw_client_close(DCB *dcb) gw_client_close(DCB *dcb)
{ {
SESSION* session;
ROUTER_OBJECT* router;
void* router_instance;
void* rsession;
#if defined(SS_DEBUG) #if defined(SS_DEBUG)
MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol; MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol;
if (dcb->state == DCB_STATE_POLLING || if (dcb->state == DCB_STATE_POLLING ||
@ -1175,8 +1198,23 @@ gw_client_close(DCB *dcb)
{ {
CHK_PROTOCOL(protocol); 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 #endif
dcb_close(dcb); dcb_close(dcb);
return 1; return 1;
} }
@ -1191,6 +1229,10 @@ gw_client_close(DCB *dcb)
static int static int
gw_client_hangup_event(DCB *dcb) gw_client_hangup_event(DCB *dcb)
{ {
SESSION* session;
ROUTER_OBJECT* router;
void* router_instance;
void* rsession;
#if defined(SS_DEBUG) #if defined(SS_DEBUG)
MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol; MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol;
if (dcb->state == DCB_STATE_POLLING || if (dcb->state == DCB_STATE_POLLING ||
@ -1199,6 +1241,20 @@ gw_client_hangup_event(DCB *dcb)
{ {
CHK_PROTOCOL(protocol); 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 #endif
dcb_close(dcb); dcb_close(dcb);
return 1; return 1;

View File

@ -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 * Receive the MySQL authentication packet from backend, packet # is 2
* *
* @param conn The MySQL protocol structure * @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) MySQLProtocol *protocol)
{ {
int n = -1; int n = -1;
GWBUF *head = NULL; GWBUF *head = NULL;
DCB *dcb = protocol->owner_dcb; DCB *dcb = protocol->owner_dcb;
uint8_t *ptr = NULL; uint8_t *ptr = NULL;
bool succp = false; int rc = 0;
n = dcb_read(dcb, &head); n = dcb_read(dcb, &head);
@ -321,7 +322,7 @@ bool gw_receive_backend_auth(
* 5th byte is 0x0 if successful. * 5th byte is 0x0 if successful.
*/ */
if (ptr[4] == '\x00') { if (ptr[4] == '\x00') {
succp = true; rc = 1;
} else { } else {
uint8_t* tmpbuf = uint8_t* tmpbuf =
(uint8_t *)calloc(1, GWBUF_LENGTH(head)+1); (uint8_t *)calloc(1, GWBUF_LENGTH(head)+1);
@ -342,25 +343,24 @@ bool gw_receive_backend_auth(
"Error : Invalid authentication message from " "Error : Invalid authentication message from "
"backend server. Authentication failed."); "backend server. Authentication failed.");
free(tmpbuf); free(tmpbuf);
rc = -1;
} }
/** /**
* Remove data from buffer. * Remove data from buffer.
*/ */
head = gwbuf_consume(head, gwbuf_length(head)); head = gwbuf_consume(head, gwbuf_length(head));
} else { }
#if 1 else if (n == 0)
{
/** /**
* This is considered as success because call didn't fail, * This is considered as success because call didn't fail,
* although no bytes was read. * although no bytes was read.
*/ */
if (n == 0) { rc = 0;
succp = true;
}
#endif
skygw_log_write( skygw_log_write(
LOGFILE_TRACE, LOGFILE_TRACE,
"%lu [gw_receive_backend_auth] Reading from backend dcb " "%lu [gw_receive_backend_auth] Read zero bytes from "
"%p fd %d in state %s failed. n %d, head %p, len %d", "backend dcb %p fd %d in state %s. n %d, head %p, len %d",
pthread_self(), pthread_self(),
dcb, dcb,
dcb->fd, dcb->fd,
@ -369,7 +369,24 @@ bool gw_receive_backend_auth(
head, head,
(head == NULL) ? 0 : GWBUF_LENGTH(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;
} }
/** /**