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:
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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(
|
||||||
|
@ -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 {
|
switch (receive_rc) {
|
||||||
|
case -1:
|
||||||
backend_protocol->state = MYSQL_AUTH_FAILED;
|
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;
|
||||||
}
|
}
|
||||||
|
@ -554,6 +554,13 @@ int gw_read_client_event(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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user