Read write split router can reply the master packet to client in session change.

Mysql backend handles auth and session func.


The MYSQL_SESSION_CHANGE may be not in sync with authentication
This commit is contained in:
Massimiliano Pinto
2013-07-15 18:56:14 +02:00
parent 0d3e798b73
commit e0d9d45f3b
11 changed files with 129 additions and 28 deletions

View File

@ -68,7 +68,7 @@ static GWPROTOCOL MyObject = {
httpd_close, /**< Close */
httpd_listen, /**< Create a listener */
NULL, /**< Authentication */
NULL /**< Generic */
NULL /**< Session */
};
/**

View File

@ -51,6 +51,7 @@ static int gw_backend_hangup(DCB *dcb);
static int backend_write_delayqueue(DCB *dcb);
static void backend_set_delayqueue(DCB *dcb, GWBUF *queue);
static int gw_change_user(DCB *backend_dcb, SERVER *server, SESSION *in_session, GWBUF *queue);
static int gw_session(DCB *backend_dcb, void *data);
extern char *gw_strend(register const char *s);
@ -65,7 +66,7 @@ static GWPROTOCOL MyObject = {
gw_backend_close, /* Close */
NULL, /* Listen */
gw_change_user, /* Authentication */
NULL /* Generic */
gw_session /* Session */
};
/*
@ -200,6 +201,34 @@ static int gw_read_backend_event(DCB *dcb) {
}
}
/* Check for a pending session change */
if (backend_protocol->state == MYSQL_SESSION_CHANGE) {
ROUTER_OBJECT *router = NULL;
ROUTER *router_instance = NULL;
void *rsession = NULL;
SESSION *session = dcb->session;
GWBUF *head = NULL;
/* read the available backend data */
dcb_read(dcb, &head);
if (session) {
router = session->service->router;
router_instance = session->service->router_instance;
rsession = session->router_session;
}
/* The configured router will send this packet to the client */
/* With multiple backends only one reply will be sent */
router->clientReply(router_instance, rsession, head, dcb);
/* Protocol status is now IDLE */
backend_protocol->state = MYSQL_IDLE;
}
/* reading MySQL command output from backend and writing to the client */
if ((client_protocol->state == MYSQL_WAITING_RESULT) || (client_protocol->state == MYSQL_IDLE)) {
@ -260,7 +289,7 @@ gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
/**
* Now put the incoming data to the delay queue unless backend is connected with auth ok
*/
if (backend_protocol->state != MYSQL_IDLE) {
if ( (backend_protocol->state != MYSQL_IDLE) && (backend_protocol->state != MYSQL_SESSION_CHANGE) ) {
//fprintf(stderr, ">>> Writing in the backend %i delay queue\n", dcb->fd);
backend_set_delayqueue(dcb, queue);
@ -442,6 +471,8 @@ static int gw_change_user(DCB *backend, SERVER *server, SESSION *in_session, GWB
backend_protocol = backend->protocol;
client_protocol = in_session->client->protocol;
backend_protocol->state = MYSQL_SESSION_CHANGE;
// now get the user, after 4 bytes header and 1 byte command
client_auth_packet += 5;
strcpy(username, (char *)client_auth_packet);
@ -468,8 +499,10 @@ static int gw_change_user(DCB *backend, SERVER *server, SESSION *in_session, GWB
if (auth_ret != 0) {
fprintf(stderr, "<<< CLIENT AUTH FAILED for user [%s], user session will not change!\n", username);
// send the error packet
mysql_send_auth_error(backend->session->client, 1, 0, "Authorization failed on change_user");
} else {
// get db name
strcpy(database, (char *)client_auth_packet);
@ -482,7 +515,7 @@ static int gw_change_user(DCB *backend, SERVER *server, SESSION *in_session, GWB
strcpy(current_session->db, database);
memcpy(current_session->client_sha1, client_sha1, sizeof(current_session->client_sha1));
fprintf(stderr, ">>> The NEW Backend session data is [%s],[%s],[%s]\n", current_session->user, current_session->client_sha1, current_session->db);
//fprintf(stderr, ">>> The NEW Backend session data is [%s],[%s],[%s]: protocol state [%i]\n", current_session->user, current_session->client_sha1, current_session->db, backend_protocol->state);
}
// consume all the data received from client
@ -491,4 +524,27 @@ static int gw_change_user(DCB *backend, SERVER *server, SESSION *in_session, GWB
return rv;
}
/**
* Session Change wrapper for func.write
* The reply packet will be back routed to the right server
* in the gw_read_backend_event checking the MYSQL_SESSION_CHANGE state
*
* @param
* @return
*/
static int gw_session(DCB *backend_dcb, void *data) {
GWBUF *queue = NULL;
MySQLProtocol *backend_protocol = NULL;
backend_protocol = backend_dcb->protocol;
queue = (GWBUF *) data;
backend_protocol->state = MYSQL_SESSION_CHANGE;
backend_dcb->func.write(backend_dcb, queue);
return 0;
}
/////

View File

@ -60,7 +60,7 @@ static GWPROTOCOL MyObject = {
gw_client_close, /* Close */
gw_MySQLListener, /* Listen */
NULL, /* Authentication */
NULL /* Generic */
NULL /* Session */
};
/**

View File

@ -506,6 +506,8 @@ gw_mysql_protocol_state2string (int state) {
return "MySQL received command has been routed to backend(s)";
case MYSQL_WAITING_RESULT:
return "MySQL Waiting for result set";
case MYSQL_SESSION_CHANGE:
return "MySQL change session";
default:
return "MySQL (unknown protocol state)";
}
@ -772,8 +774,6 @@ int gw_send_change_user_to_backend(char *dbname, char *user, uint8_t *passwd, My
rv = write(dcb->fd, GWBUF_DATA(buffer), bytes);
gwbuf_consume(buffer, bytes);
conn->state = MYSQL_IDLE;
if (rv < 0)
return rv;
else

View File

@ -78,7 +78,7 @@ static GWPROTOCOL MyObject = {
telnetd_close, /**< Close */
telnetd_listen, /**< Create a listener */
NULL, /**< Authentication */
NULL /**< Generic */
NULL /**< Session */
};
static void