Added backend connections via session_alloc called after AUTH_OK
the newSession calls connect_dcb and then the connect() in mysql_backend.c The selected backend is always the last one ath the moment. For the transparent Authentication dcb->data is used to store MySQL session data before starting the session. This could be revisited. Please note the COM_QUIT in mysql_client.c has the close functionalities but they are now disabled for testing/debug
This commit is contained in:
parent
ccf658d905
commit
e767c70acb
@ -41,9 +41,6 @@
|
||||
#include <buffer.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#define MYSQL_CONN_DEBUG
|
||||
//#undef MYSQL_CONN_DEBUG
|
||||
|
||||
/*
|
||||
* mysql_send_ok
|
||||
*
|
||||
|
@ -15,8 +15,7 @@
|
||||
*
|
||||
* Copyright SkySQL Ab 2013
|
||||
*/
|
||||
#include <session.h>
|
||||
#include <server.h>
|
||||
|
||||
#include "mysql_client_server_protocol.h"
|
||||
|
||||
/*
|
||||
@ -31,11 +30,12 @@
|
||||
|
||||
static char *version_str = "V1.0.0";
|
||||
|
||||
int gw_create_backend_connection(DCB *client_dcb, SERVER *server, SESSION *in_session);
|
||||
int gw_read_backend_event(DCB* dcb);
|
||||
int gw_write_backend_event(DCB *dcb);
|
||||
int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue);
|
||||
int gw_error_backend_event(DCB *dcb);
|
||||
static int mysql_backend_connect(DCB *dcb, SERVER *server, SESSION *session);
|
||||
static int gw_backend_close(DCB *dcb);
|
||||
|
||||
static GWPROTOCOL MyObject = {
|
||||
gw_read_backend_event, /* Read - EPOLLIN handler */
|
||||
@ -44,8 +44,8 @@ static GWPROTOCOL MyObject = {
|
||||
gw_error_backend_event, /* Error - EPOLLERR handler */
|
||||
NULL, /* HangUp - EPOLLHUP handler */
|
||||
NULL, /* Accept */
|
||||
NULL, /* Connect */
|
||||
NULL, /* Close */
|
||||
gw_create_backend_connection, /* Connect */
|
||||
gw_backend_close, /* Close */
|
||||
NULL /* Listen */
|
||||
};
|
||||
|
||||
@ -266,36 +266,74 @@ int gw_error_backend_event(DCB *dcb) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a database server
|
||||
/*
|
||||
* Create a new MySQL backend connection.
|
||||
*
|
||||
* @param dcb The DCB for the new connection
|
||||
* @param server The server we are connecting to
|
||||
* @param session The client session
|
||||
* @return The file descriptor we conencted with
|
||||
* This routine performs the MySQL connection to the backend and fills the session->backends of the callier dcb
|
||||
* with the new allocatetd dcb and adds the new socket to the poll set
|
||||
*
|
||||
* - backend dcb allocation
|
||||
* - MySQL session data fetch
|
||||
* - backend connection using data in MySQL session
|
||||
*
|
||||
* @param client_dcb The client DCB struct
|
||||
* @return 0 on Success or 1 on Failure.
|
||||
*/
|
||||
static int
|
||||
mysql_backend_connect(DCB *dcb, SERVER *server, SESSION *session)
|
||||
{
|
||||
MySQLProtocol *ptr_proto = NULL;
|
||||
MySQLProtocol *client_protocol = NULL;
|
||||
MYSQL_session *s_data = NULL;
|
||||
|
||||
dcb->protocol = (MySQLProtocol *)gw_mysql_init(NULL);
|
||||
/*
|
||||
* This function cannot work as it will be called from mysql_client.c but it needs function pointers from mysql_backend.c
|
||||
* They are modules loaded separately!!
|
||||
*/
|
||||
|
||||
ptr_proto = (MySQLProtocol *)dcb->protocol;
|
||||
int gw_create_backend_connection(DCB *backend, SERVER *server, SESSION *session) {
|
||||
MySQLProtocol *ptr_proto = NULL;
|
||||
MYSQL_session *s_data = NULL;
|
||||
|
||||
s_data = (MYSQL_session *)session->data;
|
||||
fprintf(stderr, "HERE new backend dcb fd is %i, state %i\n", backend->fd, backend->state);
|
||||
|
||||
fprintf(stderr, "HERE, the server to connect is [%s]:[%i]\n", server->name, server->port);
|
||||
|
||||
backend->protocol = (MySQLProtocol *) calloc(1, sizeof(MySQLProtocol));
|
||||
|
||||
ptr_proto = (MySQLProtocol *)backend->protocol;
|
||||
s_data = (MYSQL_session *)session->client->data;
|
||||
|
||||
|
||||
fprintf(stderr, "HERE before connect, s_data is [%p]\n", s_data);
|
||||
|
||||
fprintf(stderr, "HERE before connect, username is [%s]\n", s_data->user);
|
||||
|
||||
// this is blocking until auth done
|
||||
if (gw_mysql_connect(server->name, server->port, s_data->db, s_data->user, s_data->client_sha1, dcb->protocol) == 0) {
|
||||
fprintf(stderr, "Connected to backend mysql server\n");
|
||||
dcb->fd = ptr_proto->fd;
|
||||
setnonblocking(dcb->fd);
|
||||
if (gw_mysql_connect(server->name, server->port, s_data->db, s_data->user, s_data->client_sha1, backend->protocol) == 0) {
|
||||
memcpy(&backend->fd, &ptr_proto->fd, sizeof(backend->fd));
|
||||
|
||||
setnonblocking(backend->fd);
|
||||
fprintf(stderr, "Connected to backend mysql server. fd is %i\n", backend->fd);
|
||||
} else {
|
||||
fprintf(stderr, "<<<< NOT Connected to backend mysql server!!!\n");
|
||||
dcb->fd = -1;
|
||||
backend->fd = -1;
|
||||
}
|
||||
|
||||
return dcb->fd;
|
||||
// if connected, it will be addeed to the epoll from the caller of connect()
|
||||
|
||||
if (backend->fd <= 0) {
|
||||
perror("ERROR: epoll_ctl: backend sock");
|
||||
return 1;
|
||||
} else {
|
||||
fprintf(stderr, "--> Backend conn added, bk_fd [%i], scramble [%s], is session with client_fd [%i]\n", backend->fd, ptr_proto->scramble, session->client->fd);
|
||||
backend->state = DCB_STATE_POLLING;
|
||||
//(backend->func).read = gw_read_backend_event;
|
||||
//(backend->func).write = gw_MySQLWrite_backend;
|
||||
//(backend->func).write_ready = gw_write_backend_event;
|
||||
//(backend->func).error = gw_error_backend_event;
|
||||
|
||||
return backend->fd;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
gw_backend_close(DCB *dcb)
|
||||
{
|
||||
dcb_close(dcb);
|
||||
}
|
||||
|
@ -29,7 +29,6 @@
|
||||
*/
|
||||
|
||||
#include "mysql_client_server_protocol.h"
|
||||
#include "poll.h"
|
||||
|
||||
static char *version_str = "V1.0.0";
|
||||
|
||||
@ -39,6 +38,7 @@ static int gw_read_client_event(DCB* dcb);
|
||||
static int gw_write_client_event(DCB *dcb);
|
||||
static int gw_MySQLWrite_client(DCB *dcb, GWBUF *queue);
|
||||
static int gw_error_client_event(DCB *dcb);
|
||||
static int gw_client_close(DCB *dcb);
|
||||
|
||||
static int gw_check_mysql_scramble_data(uint8_t *token, unsigned int token_len, uint8_t *scramble, unsigned int scramble_len, char *username, uint8_t *stage1_hash);
|
||||
static int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_password, void *repository);
|
||||
@ -58,7 +58,7 @@ static GWPROTOCOL MyObject = {
|
||||
NULL, /* HangUp - EPOLLHUP handler */
|
||||
gw_MySQLAccept, /* Accept */
|
||||
NULL, /* Connect */
|
||||
NULL, /* Close */
|
||||
gw_client_close, /* Close */
|
||||
gw_MySQLListener /* Listen */
|
||||
};
|
||||
|
||||
@ -443,7 +443,9 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
|
||||
protocol = DCB_PROTOCOL(dcb, MySQLProtocol);
|
||||
|
||||
session = DCB_SESSION(dcb);
|
||||
client_data = (MYSQL_session *)session->data;
|
||||
|
||||
client_data = (MYSQL_session *)calloc(1, sizeof(MYSQL_session));
|
||||
dcb->data = client_data;
|
||||
|
||||
stage1_hash = client_data->client_sha1;
|
||||
username = client_data->user;
|
||||
@ -663,6 +665,10 @@ int w, saved_errno = 0;
|
||||
* @return TRUE on error
|
||||
*/
|
||||
int gw_read_client_event(DCB* dcb) {
|
||||
SESSION *session = NULL;
|
||||
ROUTER_OBJECT *router = NULL;
|
||||
ROUTER *router_instance = NULL;
|
||||
void *rsession = NULL;
|
||||
MySQLProtocol *protocol = NULL;
|
||||
uint8_t buffer[MAX_BUFFER_SIZE] = "";
|
||||
int n = 0;
|
||||
@ -736,6 +742,11 @@ int gw_read_client_event(DCB* dcb) {
|
||||
uint8_t *ptr_buff = NULL;
|
||||
int mysql_command = -1;
|
||||
int ret = -1;
|
||||
|
||||
session = dcb->session;
|
||||
router = session->service->router;
|
||||
router_instance = session->service->router_instance;
|
||||
rsession = session->router_session;
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// read and handle errors & close, or return if busy
|
||||
@ -767,11 +778,20 @@ int gw_read_client_event(DCB* dcb) {
|
||||
//////////////////////////
|
||||
if (mysql_command == '\x01') {
|
||||
fprintf(stderr, "COM_QUIT received\n");
|
||||
if (dcb->session->backends) {
|
||||
dcb->session->backends->func.write(dcb, queue);
|
||||
(dcb->session->backends->func).error(dcb->session->backends);
|
||||
}
|
||||
(dcb->func).error(dcb);
|
||||
// uncomment the following lines for closing
|
||||
// client and backend conns
|
||||
// dcb still to be freed
|
||||
|
||||
// this will propagate COM_QUIT to backends
|
||||
//router->routeQuery(router_instance, rsession, queue);
|
||||
// close client
|
||||
//(dcb->func).close(dcb);
|
||||
// remove dcb
|
||||
//poll_remove_dcb(dcb);
|
||||
// close the session
|
||||
//router->closeSession(router_instance, rsession);
|
||||
// call errors, it will be removed after tests
|
||||
//(dcb->func).error(dcb);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -779,9 +799,10 @@ int gw_read_client_event(DCB* dcb) {
|
||||
protocol->state = MYSQL_ROUTING;
|
||||
|
||||
///////////////////////////////////////
|
||||
// writing in the backend buffer queue
|
||||
// writing in the backend buffer queue, via routeQuery
|
||||
///////////////////////////////////////
|
||||
dcb->session->backends->func.write(dcb->session->backends, queue);
|
||||
|
||||
router->routeQuery(router_instance, rsession, queue);
|
||||
|
||||
protocol->state = MYSQL_WAITING_RESULT;
|
||||
|
||||
@ -819,29 +840,20 @@ int gw_write_client_event(DCB *dcb) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dcb->session) {
|
||||
} else {
|
||||
fprintf(stderr, "DCB session is NULL, return\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dcb->session->backends) {
|
||||
} else {
|
||||
fprintf(stderr, "DCB backend is NULL, continue\n");
|
||||
}
|
||||
|
||||
if(protocol->state == MYSQL_AUTH_RECV) {
|
||||
SESSION *session = NULL;
|
||||
MYSQL_session *s_data = dcb->data;
|
||||
|
||||
//write to client mysql AUTH_OK packet, packet n. is 2
|
||||
//write to client mysql AUTH_OK packet, packet n. is 2
|
||||
mysql_send_ok(dcb, 2, 0, NULL);
|
||||
|
||||
// create one backend connection
|
||||
// This is not working now, as the backend dcb functions are in the mysql_protocol.c
|
||||
// and it will loaded separately
|
||||
//gw_create_backend_connection(dcb);
|
||||
// start a new session, and connect to backends
|
||||
session = session_alloc(dcb->service, dcb);
|
||||
|
||||
protocol->state = MYSQL_IDLE;
|
||||
|
||||
session->data = (MYSQL_session *)dcb->data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -850,8 +862,6 @@ int gw_write_client_event(DCB *dcb) {
|
||||
mysql_send_auth_error(dcb, 2, 0, "Authorization failed");
|
||||
|
||||
dcb->func.error(dcb);
|
||||
if (dcb->session->backends)
|
||||
dcb->session->backends->func.error(dcb->session->backends);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -981,6 +991,8 @@ int gw_MySQLListener(DCB *listener, char *config_bind) {
|
||||
|
||||
listener->state = DCB_STATE_LISTENING;
|
||||
|
||||
fprintf(stderr, "HERE listening\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1025,10 +1037,10 @@ int gw_MySQLAccept(DCB *listener) {
|
||||
setnonblocking(c_sock);
|
||||
|
||||
client = alloc_dcb();
|
||||
client->service = listener->session->service;
|
||||
client->fd = c_sock;
|
||||
client->remote = strdup(inet_ntoa(local.sin_addr));
|
||||
|
||||
session = session_alloc(listener->session->service, client);
|
||||
client->session = session;
|
||||
|
||||
protocol = (MySQLProtocol *) calloc(1, sizeof(MySQLProtocol));
|
||||
@ -1039,8 +1051,6 @@ int gw_MySQLAccept(DCB *listener) {
|
||||
protocol->descriptor = client;
|
||||
protocol->fd = c_sock;
|
||||
|
||||
session->backends = NULL;
|
||||
|
||||
// assign function poiters to "func" field
|
||||
memcpy(&client->func, &MyObject, sizeof(GWPROTOCOL));
|
||||
|
||||
@ -1117,3 +1127,9 @@ static int gw_error_client_event(DCB *dcb) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
gw_client_close(DCB *dcb)
|
||||
{
|
||||
dcb_close(dcb);
|
||||
}
|
||||
|
@ -28,9 +28,8 @@
|
||||
|
||||
static char *version_str = "V1.0.0";
|
||||
|
||||
//static int gw_create_backend_connection(DCB *client_dcb, int efd);
|
||||
static MySQLProtocol *gw_mysql_init(MySQLProtocol *data);
|
||||
static void gw_mysql_close(MySQLProtocol **ptr);
|
||||
MySQLProtocol *gw_mysql_init(MySQLProtocol *data);
|
||||
void gw_mysql_close(MySQLProtocol **ptr);
|
||||
|
||||
extern gw_read_backend_event(DCB* dcb);
|
||||
extern gw_write_backend_event(DCB *dcb);
|
||||
@ -97,76 +96,3 @@ void gw_mysql_close(MySQLProtocol **ptr) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new MySQL backend connection.
|
||||
*
|
||||
* This routine performs the MySQL connection to the backend and fills the session->backends of the callier dcb
|
||||
* with the new allocatetd dcb and adds the new socket to the poll set
|
||||
*
|
||||
* - backend dcb allocation
|
||||
* - MySQL session data fetch
|
||||
* - backend connection using data in MySQL session
|
||||
*
|
||||
* @param client_dcb The client DCB struct
|
||||
* @return 0 on Success or 1 on Failure.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This function cannot work as it will be called from mysql_client.c but it needs function pointers from mysql_backend.c
|
||||
* They are modules loaded separately!!
|
||||
*
|
||||
int gw_create_backend_connection(DCB *client_dcb) {
|
||||
DCB *backend = NULL;
|
||||
MySQLProtocol *ptr_proto = NULL;
|
||||
MySQLProtocol *client_protocol = NULL;
|
||||
SESSION *session = NULL;
|
||||
MYSQL_session *s_data = NULL;
|
||||
|
||||
backend = (DCB *) calloc(1, sizeof(DCB));
|
||||
backend->state = DCB_STATE_ALLOC;
|
||||
backend->session = NULL;
|
||||
backend->protocol = (MySQLProtocol *)gw_mysql_init(NULL);
|
||||
|
||||
ptr_proto = (MySQLProtocol *)backend->protocol;
|
||||
client_protocol = (MySQLProtocol *)client_dcb->protocol;
|
||||
session = DCB_SESSION(client_dcb);
|
||||
s_data = (MYSQL_session *)session->data;
|
||||
|
||||
// this is blocking until auth done
|
||||
if (gw_mysql_connect("127.0.0.1", 3306, s_data->db, s_data->user, s_data->client_sha1, backend->protocol) == 0) {
|
||||
fprintf(stderr, "Connected to backend mysql server\n");
|
||||
backend->fd = ptr_proto->fd;
|
||||
setnonblocking(backend->fd);
|
||||
} else {
|
||||
fprintf(stderr, "<<<< NOT Connected to backend mysql server!!!\n");
|
||||
backend->fd = -1;
|
||||
}
|
||||
|
||||
// edge triggering flag added
|
||||
ee.events = EPOLLIN | EPOLLET | EPOLLOUT;
|
||||
ee.data.ptr = backend;
|
||||
|
||||
// if connected, add it to the epoll
|
||||
if (backend->fd > 0) {
|
||||
if (epoll_ctl(efd, EPOLL_CTL_ADD, backend->fd, &ee) == -1) {
|
||||
perror("epoll_ctl: backend sock");
|
||||
} else {
|
||||
fprintf(stderr, "--> Backend conn added, bk_fd [%i], scramble [%s], is session with client_fd [%i]\n", ptr_proto->fd, ptr_proto->scramble, client_dcb->fd);
|
||||
backend->state = DCB_STATE_POLLING;
|
||||
backend->session = DCB_SESSION(client_dcb);
|
||||
(backend->func).read = gw_read_backend_event;
|
||||
(backend->func).write = gw_MySQLWrite_backend;
|
||||
(backend->func).write_ready = gw_write_backend_event;
|
||||
(backend->func).error = gw_error_backend_event;
|
||||
|
||||
// assume here one backend only.
|
||||
// in session.h
|
||||
// struct dcb *backends;
|
||||
// instead of a list **backends;
|
||||
client_dcb->session->backends = backend;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user