From 4d5215e2676163a6169231621445c886651e834d Mon Sep 17 00:00:00 2001 From: Massimiliano Pinto Date: Mon, 17 Jun 2013 22:47:14 +0200 Subject: [PATCH] mysql_client_server_protocol.h, new file name that avoids conflicts with previous one --- .../include/mysql_client_server_protocol.h | 201 ++++++++++++++++++ modules/protocol/Makefile | 2 +- modules/protocol/mysql_backend.c | 22 +- modules/protocol/mysql_client.c | 46 ++-- modules/protocol/mysql_common.c | 91 +++++++- 5 files changed, 330 insertions(+), 32 deletions(-) create mode 100644 modules/include/mysql_client_server_protocol.h diff --git a/modules/include/mysql_client_server_protocol.h b/modules/include/mysql_client_server_protocol.h new file mode 100644 index 000000000..b4967ee33 --- /dev/null +++ b/modules/include/mysql_client_server_protocol.h @@ -0,0 +1,201 @@ +#ifndef _MYSQL_PROTOCOL_H +#define _MYSQL_PROTOCOL_H +/* + * This file is distributed as part of the SkySQL Gateway. It is free + * software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, + * version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright SkySQL Ab 2013 + */ + +/* + * Revision History + * + * Date Who Description + * 01-06-2013 Mark Riddoch Initial implementation + * 14-06-2013 Massimiliano Pinto Added specific data + * for MySQL session + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dcb.h" +#include "session.h" +#include "buffer.h" + +#ifndef MYSQL_SCRAMBLE_LEN +#define MYSQL_SCRAMBLE_LEN GW_MYSQL_SCRAMBLE_SIZE +#endif + +#define MYSQL_USER_MAXLEN 128 +#define MYSQL_DATABASE_MAXLEN 128 + +#define GW_VERSION "0.1.0" +#define GW_MYSQL_VERSION "5.5.22-SKYSQL-" GW_VERSION +#define GW_MYSQL_LOOP_TIMEOUT 300000000 +#define GW_MYSQL_READ 0 +#define GW_MYSQL_WRITE 1 + +#define GW_MYSQL_PROTOCOL_VERSION 10 // version is 10 +#define GW_MYSQL_HANDSHAKE_FILLER 0x00 +#define GW_MYSQL_SERVER_CAPABILITIES_BYTE1 0xff +#define GW_MYSQL_SERVER_CAPABILITIES_BYTE2 0xf7 +#define GW_MYSQL_SERVER_LANGUAGE 0x08 +#define GW_MYSQL_MAX_PACKET_LEN 0xffffffL; +#define GW_MYSQL_SCRAMBLE_SIZE 20 + +#define GW_NOINTR_CALL(A) do { errno = 0; A; } while (errno == EINTR) +// network buffer is 32K +#define MAX_BUFFER_SIZE 32768 +// socket send buffer for backend +#define GW_BACKEND_SO_SNDBUF 1024 +#define SMALL_CHUNK 1024 +#define MAX_CHUNK SMALL_CHUNK * 8 * 4 +#define ToHex(Y) (Y>='0'&&Y<='9'?Y-'0':Y-'A'+10) + +struct dcb; + +/* + * MySQL Protocol specific state data + */ +typedef struct { + int fd; /* The socket descriptor */ + struct dcb *descriptor; /* The DCB of the socket we are running on */ + int state; /* Current descriptor state */ + char scramble[MYSQL_SCRAMBLE_LEN]; /* server scramble, created or received */ + uint32_t server_capabilities; /* server capabilities, created or received */ + uint32_t client_capabilities; /* client capabilities, created or received */ + unsigned long tid; /* MySQL Thread ID, in handshake */ +} MySQLProtocol; + +/* + * MySQL session specific data + * + */ +typedef struct mysql_session { + uint8_t client_sha1[MYSQL_SCRAMBLE_LEN]; /* SHA1(passowrd) */ + char user[MYSQL_USER_MAXLEN]; /* username */ + char db[MYSQL_DATABASE_MAXLEN]; /* database */ +} MYSQL_session; + +/* MySQL Protocol States */ +#define MYSQL_ALLOC 0 /* Allocate data */ +#define MYSQL_AUTH_SENT 1 /* Authentication handshake has been sent */ +#define MYSQL_AUTH_RECV 2 /* Received user, password, db and capabilities */ +#define MYSQL_AUTH_FAILED 3 /* Auth failed, return error packet */ +#define MYSQL_IDLE 4 /* Auth done. Protocol is idle, waiting for statements */ +#define MYSQL_ROUTING 5 /* The received command has been routed to backend(s) */ +#define MYSQL_WAITING_RESULT 6 /* Waiting for result set */ + +/* Protocol packing macros. */ +#define gw_mysql_set_byte2(__buffer, __int) do { \ + (__buffer)[0]= (uint8_t)((__int) & 0xFF); \ + (__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); } while (0) +#define gw_mysql_set_byte3(__buffer, __int) do { \ + (__buffer)[0]= (uint8_t)((__int) & 0xFF); \ + (__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); \ + (__buffer)[2]= (uint8_t)(((__int) >> 16) & 0xFF); } while (0) +#define gw_mysql_set_byte4(__buffer, __int) do { \ + (__buffer)[0]= (uint8_t)((__int) & 0xFF); \ + (__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); \ + (__buffer)[2]= (uint8_t)(((__int) >> 16) & 0xFF); \ + (__buffer)[3]= (uint8_t)(((__int) >> 24) & 0xFF); } while (0) + +/* Protocol unpacking macros. */ +#define gw_mysql_get_byte2(__buffer) \ + (uint16_t)((__buffer)[0] | \ + ((__buffer)[1] << 8)) +#define gw_mysql_get_byte3(__buffer) \ + (uint32_t)((__buffer)[0] | \ + ((__buffer)[1] << 8) | \ + ((__buffer)[2] << 16)) +#define gw_mysql_get_byte4(__buffer) \ + (uint32_t)((__buffer)[0] | \ + ((__buffer)[1] << 8) | \ + ((__buffer)[2] << 16) | \ + ((__buffer)[3] << 24)) +#define gw_mysql_get_byte8(__buffer) \ + ((uint64_t)(__buffer)[0] | \ + ((uint64_t)(__buffer)[1] << 8) | \ + ((uint64_t)(__buffer)[2] << 16) | \ + ((uint64_t)(__buffer)[3] << 24) | \ + ((uint64_t)(__buffer)[4] << 32) | \ + ((uint64_t)(__buffer)[5] << 40) | \ + ((uint64_t)(__buffer)[6] << 48) | \ + ((uint64_t)(__buffer)[7] << 56)) + +/* MySQL protocol constants */ +typedef enum +{ + GW_MYSQL_CAPABILITIES_NONE= 0, + GW_MYSQL_CAPABILITIES_LONG_PASSWORD= (1 << 0), + GW_MYSQL_CAPABILITIES_FOUND_ROWS= (1 << 1), + GW_MYSQL_CAPABILITIES_LONG_FLAG= (1 << 2), + GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB= (1 << 3), + GW_MYSQL_CAPABILITIES_NO_SCHEMA= (1 << 4), + GW_MYSQL_CAPABILITIES_COMPRESS= (1 << 5), + GW_MYSQL_CAPABILITIES_ODBC= (1 << 6), + GW_MYSQL_CAPABILITIES_LOCAL_FILES= (1 << 7), + GW_MYSQL_CAPABILITIES_IGNORE_SPACE= (1 << 8), + GW_MYSQL_CAPABILITIES_PROTOCOL_41= (1 << 9), + GW_MYSQL_CAPABILITIES_INTERACTIVE= (1 << 10), + GW_MYSQL_CAPABILITIES_SSL= (1 << 11), + GW_MYSQL_CAPABILITIES_IGNORE_SIGPIPE= (1 << 12), + GW_MYSQL_CAPABILITIES_TRANSACTIONS= (1 << 13), + GW_MYSQL_CAPABILITIES_RESERVED= (1 << 14), + GW_MYSQL_CAPABILITIES_SECURE_CONNECTION= (1 << 15), + GW_MYSQL_CAPABILITIES_MULTI_STATEMENTS= (1 << 16), + GW_MYSQL_CAPABILITIES_MULTI_RESULTS= (1 << 17), + GW_MYSQL_CAPABILITIES_PS_MULTI_RESULTS= (1 << 18), + GW_MYSQL_CAPABILITIES_PLUGIN_AUTH= (1 << 19), + GW_MYSQL_CAPABILITIES_SSL_VERIFY_SERVER_CERT= (1 << 30), + GW_MYSQL_CAPABILITIES_REMEMBER_OPTIONS= (1 << 31), + GW_MYSQL_CAPABILITIES_CLIENT= (GW_MYSQL_CAPABILITIES_LONG_PASSWORD | + GW_MYSQL_CAPABILITIES_FOUND_ROWS | + GW_MYSQL_CAPABILITIES_LONG_FLAG | + GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB | + GW_MYSQL_CAPABILITIES_LOCAL_FILES | + GW_MYSQL_CAPABILITIES_PLUGIN_AUTH | + GW_MYSQL_CAPABILITIES_TRANSACTIONS | + GW_MYSQL_CAPABILITIES_PROTOCOL_41 | + GW_MYSQL_CAPABILITIES_MULTI_STATEMENTS | + GW_MYSQL_CAPABILITIES_MULTI_RESULTS | + GW_MYSQL_CAPABILITIES_PS_MULTI_RESULTS | + GW_MYSQL_CAPABILITIES_SECURE_CONNECTION), + GW_MYSQL_CAPABILITIES_CLIENT_COMPRESS= (GW_MYSQL_CAPABILITIES_LONG_PASSWORD | + GW_MYSQL_CAPABILITIES_FOUND_ROWS | + GW_MYSQL_CAPABILITIES_LONG_FLAG | + GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB | + GW_MYSQL_CAPABILITIES_LOCAL_FILES | + GW_MYSQL_CAPABILITIES_PLUGIN_AUTH | + GW_MYSQL_CAPABILITIES_TRANSACTIONS | + GW_MYSQL_CAPABILITIES_PROTOCOL_41 | + GW_MYSQL_CAPABILITIES_MULTI_STATEMENTS | + GW_MYSQL_CAPABILITIES_MULTI_RESULTS | + GW_MYSQL_CAPABILITIES_PS_MULTI_RESULTS | + GW_MYSQL_CAPABILITIES_COMPRESS + ), +} gw_mysql_capabilities_t; +#endif diff --git a/modules/protocol/Makefile b/modules/protocol/Makefile index 6aa0afba1..dc5e33b86 100644 --- a/modules/protocol/Makefile +++ b/modules/protocol/Makefile @@ -20,7 +20,7 @@ # 17/06/2013 Massimiliano Pinto Added mysql_common top both libraries CC=cc -CFLAGS=-c -fPIC -I/usr/include -I../include -I../../include -Wall +CFLAGS=-c -fPIC -I/usr/include -I../include -I../../include LDFLAGS=-shared MYSQLCLIENTSRCS=mysql_client.c mysql_common.c MYSQLCLIENTOBJ=$(MYSQLCLIENTSRCS:.c=.o) diff --git a/modules/protocol/mysql_backend.c b/modules/protocol/mysql_backend.c index 397279691..37dc6274f 100644 --- a/modules/protocol/mysql_backend.c +++ b/modules/protocol/mysql_backend.c @@ -16,7 +16,7 @@ * Copyright SkySQL Ab 2013 */ -#include "mysql_protocol.h" +#include "mysql_client_server_protocol.h" /* * MySQL Protocol module for handling the protocol between the gateway @@ -30,10 +30,10 @@ static char *version_str = "V1.0.0"; -static int gw_read_backend_event(DCB* dcb, int epfd); -static int gw_write_backend_event(DCB *dcb, int epfd); -static int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue); -static int gw_error_backend_event(DCB *dcb, int epfd, int event); +int gw_read_backend_event(DCB* dcb, int epfd); +int gw_write_backend_event(DCB *dcb, int epfd); +int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue); +int gw_error_backend_event(DCB *dcb, int epfd, int event); static GWPROTOCOL MyObject = { gw_read_backend_event, /* Read - EPOLLIN handler */ @@ -43,7 +43,8 @@ static GWPROTOCOL MyObject = { NULL, /* HangUp - EPOLLHUP handler */ NULL, /* Accept */ NULL, /* Connect */ - NULL /* Close */ + NULL, /* Close */ + NULL /* Listen */ }; /* @@ -85,7 +86,6 @@ GetModuleObject() ////////////////////////////////////////// //backend read event triggered by EPOLLIN ////////////////////////////////////////// - int gw_read_backend_event(DCB *dcb, int epfd) { int n; MySQLProtocol *client_protocol = NULL; @@ -144,7 +144,7 @@ int gw_read_backend_event(DCB *dcb, int epfd) { return 1; } - return 1; + return 0; } ////////////////////////////////////////// @@ -156,7 +156,7 @@ int gw_write_backend_event(DCB *dcb, int epfd) { } /* - * Write function for client DCB + * Write function for backend DCB * * @param dcb The DCB of the client * @param queue Queue of buffers to write @@ -223,10 +223,10 @@ int w, saved_errno = 0; if (queue && (saved_errno != EAGAIN || saved_errno != EWOULDBLOCK)) { /* We had a real write failure that we must deal with */ - return 0; + return 1; } - return 1; + return 0; } int gw_error_backend_event(DCB *dcb, int epfd, int event) { diff --git a/modules/protocol/mysql_client.c b/modules/protocol/mysql_client.c index 5878c7f81..1f5835b93 100644 --- a/modules/protocol/mysql_client.c +++ b/modules/protocol/mysql_client.c @@ -26,12 +26,12 @@ * 17/06/2013 Massimiliano Pinto Added Client To Gateway routines */ -#include "mysql_protocol.h" +#include "mysql_client_server_protocol.h" static char *version_str = "V1.0.0"; static int gw_MySQLAccept(DCB *listener, int efd); -static void gw_MySQLListener(int epfd, char *config_bind); +static int gw_MySQLListener(int epfd, char *config_bind); static int gw_read_client_event(DCB* dcb, int epfd); static int gw_write_client_event(DCB *dcb, int epfd); static int gw_MySQLWrite_client(DCB *dcb, GWBUF *queue); @@ -42,6 +42,7 @@ static int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_pas int mysql_send_ok(DCB *dcb, int packet_number, int in_affected_rows, const char* mysql_message); int mysql_send_auth_error (DCB *dcb, int packet_number, int in_affected_rows, const char* mysql_message); int MySQLSendHandshake(DCB* dcb); +static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue); /* * The "module object" for the mysqld client protocol module. @@ -50,11 +51,12 @@ static GWPROTOCOL MyObject = { gw_read_client_event, /* Read - EPOLLIN handler */ gw_MySQLWrite_client, /* Write - data from gateway */ gw_write_client_event, /* WriteReady - EPOLLOUT handler */ - gw_error_client_event, /* Error - EPOLLERR handler */ + gw_error_client_event, /* Error - EPOLLERR handler */ NULL, /* HangUp - EPOLLHUP handler */ gw_MySQLAccept, /* Accept */ NULL, /* Connect */ - NULL /* Close */ + NULL, /* Close */ + gw_MySQLListener /* Listen */ }; /* @@ -167,7 +169,7 @@ mysql_send_ok(DCB *dcb, int packet_number, int in_affected_rows, const char* mys memcpy(mysql_payload, mysql_message, strlen(mysql_message)); } - // write data + // writing data in the Client buffer queue dcb->func.write(dcb, buf); return sizeof(mysql_packet_header) + mysql_payload_size; @@ -251,7 +253,7 @@ mysql_send_auth_error (DCB *dcb, int packet_number, int in_affected_rows, const // write err messg memcpy(mysql_payload, mysql_error_msg, strlen(mysql_error_msg)); - // write data + // writing data in the Client buffer queue dcb->func.write(dcb, buf); return sizeof(mysql_packet_header) + mysql_payload_size; @@ -398,7 +400,7 @@ MySQLSendHandshake(DCB* dcb) mysql_handshake_payload++; - // write data + // writing data in the Client buffer queue dcb->func.write(dcb, buf); return sizeof(mysql_packet_header) + mysql_payload_size; @@ -483,7 +485,6 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) { return auth_ret; } - ///////////////////////////////////////////////// // get the sha1(sha1(password) from repository ///////////////////////////////////////////////// @@ -645,10 +646,10 @@ int w, saved_errno = 0; if (queue && (saved_errno != EAGAIN || saved_errno != EWOULDBLOCK)) { /* We had a real write failure that we must deal with */ - return 0; + return 1; } - return 1; + return 0; } ////////////////////////////////////////// @@ -669,6 +670,7 @@ int gw_read_client_event(DCB* dcb, int epfd) { if (ioctl(dcb->fd, FIONREAD, &b)) { fprintf(stderr, "Client Ioctl FIONREAD error %i, %s\n", errno , strerror(errno)); + return 1; } else { //fprintf(stderr, "Client IOCTL FIONREAD bytes to read = %i\n", b); } @@ -788,7 +790,7 @@ int gw_read_client_event(DCB* dcb, int epfd) { } /////////////////////////////////////////////// -// client write event triggered by EPOLLOUT +// client write event to Client triggered by EPOLLOUT ////////////////////////////////////////////// int gw_write_client_event(DCB *dcb, int epfd) { MySQLProtocol *protocol = NULL; @@ -827,6 +829,11 @@ int gw_write_client_event(DCB *dcb, int epfd) { //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, epfd); + protocol->state = MYSQL_IDLE; return 0; @@ -890,7 +897,7 @@ int gw_write_client_event(DCB *dcb, int epfd) { /// // set listener for mysql protocol /// -void MySQLListener(int epfd, char *config_bind) { +int gw_MySQLListener(int epfd, char *config_bind) { DCB *listener; int l_so; int fl; @@ -935,7 +942,8 @@ void MySQLListener(int epfd, char *config_bind) { // socket create if ((l_so = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - error("can't open listening socket"); + fprintf(stderr, ">>> Error: can't open listening socket. Errno %i, %s\n", errno, strerror(errno)); + return 1; } // socket options @@ -946,9 +954,9 @@ void MySQLListener(int epfd, char *config_bind) { // bind address and port if (bind(l_so, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { - fprintf(stderr, ">>>> Bind failed !!! %i, [%s]\n", errno, strerror(errno)); - error("can't bind to address and port"); - exit(1); + fprintf(stderr, ">>> Bind failed !!! %i, [%s]\n", errno, strerror(errno)); + fprintf(stderr, ">>> can't bind to address and port"); + return 1; } fprintf(stderr, ">> GATEWAY bind is: %s:%i. FD is %i\n", address, port, l_so); @@ -970,13 +978,15 @@ void MySQLListener(int epfd, char *config_bind) { // add listening socket to epoll structure if (epoll_ctl(epfd, EPOLL_CTL_ADD, l_so, &ev) == -1) { - perror("epoll_ctl: listen_sock"); - exit(EXIT_FAILURE); + fprintf(stderr, ">>> epoll_ctl: can't add the listen_sock! Errno %i, %s\n", errno, strerror(errno)); + return 1; } listener->func.accept = gw_MySQLAccept; listener->state = DCB_STATE_LISTENING; + + return 0; } diff --git a/modules/protocol/mysql_common.c b/modules/protocol/mysql_common.c index d8e16a95f..0b64e312a 100644 --- a/modules/protocol/mysql_common.c +++ b/modules/protocol/mysql_common.c @@ -24,10 +24,21 @@ * 17/06/2013 Massimiliano Pinto Common MySQL protocol routines */ -#include "mysql_protocol.h" +#include "mysql_client_server_protocol.h" 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); + +extern gw_read_backend_event(DCB* dcb, int epfd); +extern gw_write_backend_event(DCB *dcb, int epfd); +extern int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue); +extern int gw_error_backend_event(DCB *dcb, int epfd, int event); + +/////////////////////////////// +// Initialize mysql protocol struct /////////////////////////////////////// MySQLProtocol *gw_mysql_init(MySQLProtocol *data) { int rv = -1; @@ -53,7 +64,7 @@ MySQLProtocol *gw_mysql_init(MySQLProtocol *data) { ////////////////////////////////////// // close a connection if opened -// free data scructure +// free data scructure for MySQLProtocol ////////////////////////////////////// void gw_mysql_close(MySQLProtocol **ptr) { MySQLProtocol *conn = *ptr; @@ -85,3 +96,79 @@ void gw_mysql_close(MySQLProtocol **ptr) { fprintf(stderr, "mysqlgw_mysql_close() free(conn) done\n"); #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 epoll set + * + * - backend dcb allocation + * - MySQL session data fetch + * - backend connection using data in MySQL session + * + * @param client_dcb The client DCB struct + * @param epfd The epoll set to add the new connection + * @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, int efd) { + struct epoll_event ee; + 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; +} +*/