Developing support for charset , issue #223

Added functions:
MySQL_Protocol::generate_COM_QUERY()
MySQL_Connection::set_charset()
MySQL_Session::handler___status_CHANGING_CHARSET()
MySQL_Session::handler___client_DSS_QUERY_SENT___send_SET_NAMES_to_backend()

Added CHANGING_CHARSET in enum session_status, and handled in MySQL_Session

Still TODO:
track and handle client’s change of charset
pull/248/head
René Cannaò 11 years ago
parent f0ec7e509b
commit f5ea427a4d

@ -41,6 +41,7 @@ class MySQL_Protocol {
bool generate_COM_QUIT(bool send, void **ptr, unsigned int *len);
bool generate_COM_INIT_DB(bool send, void **ptr, unsigned int *len, char *schema);
bool generate_COM_PING(bool send, void **ptr, unsigned int *len);
bool generate_COM_QUERY(bool send, void **ptr, unsigned int *len, char *query);
bool generate_COM_RESET_CONNECTION(bool send, void **ptr, unsigned int *len);
bool generate_COM_CHANGE_USER(bool send, void **ptr, unsigned int *len);

@ -52,6 +52,7 @@ class MySQL_Connection {
// void free_mshge();
MyConnArray *set_MCA(MySQL_Connection_Pool *_MyConnPool, const char *hostname, const char *username, const char *password, const char *db, unsigned int port);
bool return_to_connection_pool();
uint8_t set_charset(uint8_t);
friend class MyConnArray;
};
#endif /* __CLASS_MYSQL_CONNECTION_H */

@ -36,6 +36,7 @@ class MySQL_Session
private:
bool handler___status_CHANGING_SCHEMA(PtrSize_t *);
bool handler___status_CHANGING_USER_SERVER(PtrSize_t *);
bool handler___status_CHANGING_CHARSET(PtrSize_t *);
void handler___status_WAITING_SERVER_DATA___STATE_QUERY_SENT(PtrSize_t *);
void handler___status_WAITING_SERVER_DATA___STATE_PING_SENT(PtrSize_t *);
void handler___status_WAITING_SERVER_DATA___STATE_ROW(PtrSize_t *);
@ -58,6 +59,7 @@ class MySQL_Session
void handler___client_DSS_QUERY_SENT___server_DSS_NOT_INITIALIZED__get_connection();
void handler___client_DSS_QUERY_SENT___send_INIT_DB_to_backend();
void handler___client_DSS_QUERY_SENT___send_CHANGE_USER_to_backend();
void handler___client_DSS_QUERY_SENT___send_SET_NAMES_to_backend();
public:
void * operator new(size_t);

@ -57,6 +57,7 @@ enum session_status {
WAITING_CLIENT_DATA,
WAITING_SERVER_DATA,
CHANGING_SCHEMA,
CHANGING_CHARSET,
CHANGING_USER_CLIENT,
CHANGING_USER_SERVER,
NONE

@ -900,6 +900,28 @@ bool MySQL_Protocol::generate_COM_INIT_DB(bool send, void **ptr, unsigned int *l
return true;
}
bool MySQL_Protocol::generate_COM_QUERY(bool send, void **ptr, unsigned int *len, char *query) {
uint32_t query_len=strlen(query);
mysql_hdr myhdr;
myhdr.pkt_id=0;
myhdr.pkt_length=1+query_len;
unsigned int size=myhdr.pkt_length+sizeof(mysql_hdr);
unsigned char *_ptr=(unsigned char *)l_alloc(size);
memcpy(_ptr, &myhdr, sizeof(mysql_hdr));
//Copy4B(_ptr, &myhdr);
int l=sizeof(mysql_hdr);
_ptr[l]=0x03; l++;
memcpy(_ptr+l, query, query_len);
if (send==true) { (*myds)->PSarrayOUT->add((void *)_ptr,size); }
if (len) { *len=size; }
if (ptr) { *ptr=(void *)_ptr; }
#ifdef DEBUG
if (dump_pkt) { __dump_pkt(__func__,_ptr,size); }
#endif
return true;
}
//bool MySQL_Protocol::generate_COM_PING(MySQL_Data_Stream *myds, bool send, void **ptr, unsigned int *len) {
bool MySQL_Protocol::generate_COM_PING(bool send, void **ptr, unsigned int *len) {
mysql_hdr myhdr;
@ -1103,7 +1125,10 @@ bool MySQL_Protocol::generate_pkt_handshake_response(bool send, void **ptr, unsi
uint32_t capabilities = CLIENT_LONG_PASSWORD | CLIENT_FOUND_ROWS | CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB | CLIENT_PROTOCOL_41 | CLIENT_TRANSACTIONS | CLIENT_SECURE_CONNECTION | CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS | CLIENT_PS_MULTI_RESULTS ;
uint32_t max_allowed_packet=1*1024*1024;
uint8_t charset=21;
assert(sess);
assert(sess->client_myds);
assert(sess->client_myds->myconn);
uint8_t charset=sess->client_myds->myconn->options.charset;
uint8_t _tmp;
/*
pkt += sizeof(mysql_hdr);
@ -1533,7 +1558,10 @@ bool MySQL_Protocol::process_pkt_handshake_response(unsigned char *pkt, unsigned
}
proxy_debug(PROXY_DEBUG_MYSQL_PROTOCOL,1,"Handshake (%s auth) <user:\"%s\" pass:\"%s\" scramble:\"%s\" db:\"%s\" max_pkt:%u>, capabilities:%u char:%u, use_ssl:%s\n",
(capabilities & CLIENT_SECURE_CONNECTION ? "new" : "old"), user, password, pass, db, max_pkt, capabilities, charset, ((*myds)->encrypted ? "yes" : "no"));
assert(sess);
assert(sess->client_myds);
assert(sess->client_myds->myconn);
sess->client_myds->myconn->set_charset(charset);
#ifdef DEBUG
if (dump_pkt) { __dump_pkt(__func__,_ptr,len); }
#endif

@ -465,9 +465,13 @@ __get_a_backend:
handler___client_DSS_QUERY_SENT___send_INIT_DB_to_backend();
}
} else {
//server_myds->PSarrayOUT->add(pkt.ptr, pkt.size);
mybe->server_myds->DSS=STATE_QUERY_SENT_DS;
status=WAITING_SERVER_DATA;
if (client_myds->myconn->options.charset!=mybe->server_myds->myconn->options.charset || rand()%3==0) {
handler___client_DSS_QUERY_SENT___send_SET_NAMES_to_backend();
} else {
//server_myds->PSarrayOUT->add(pkt.ptr, pkt.size);
mybe->server_myds->DSS=STATE_QUERY_SENT_DS;
status=WAITING_SERVER_DATA;
}
}
}
// } TRY #1
@ -534,6 +538,12 @@ __exit_DSS__STATE_NOT_INITIALIZED:
}
break;
case CHANGING_CHARSET:
if (handler___status_CHANGING_CHARSET(&pkt)==false) {
return -1;
}
break;
default:
assert(0);
}
@ -667,6 +677,33 @@ bool MySQL_Session::handler___status_CHANGING_USER_SERVER(PtrSize_t *pkt) {
return false;
}
bool MySQL_Session::handler___status_CHANGING_CHARSET(PtrSize_t *pkt) {
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Statuses: CHANGING_CHARSET - UNKNWON\n");
if (mybe->server_myds->myprot.process_pkt_OK((unsigned char *)pkt->ptr,pkt->size)==true) {
l_free(pkt->size,pkt->ptr);
mybe->server_myds->DSS=STATE_READY;
//mybe->myconn=server_myds->myconn;
status=WAITING_SERVER_DATA;
unsigned int k;
PtrSize_t pkt2;
for (k=0; k<mybe->server_myds->PSarrayOUTpending->len;) {
mybe->server_myds->PSarrayOUTpending->remove_index(0,&pkt2);
mybe->server_myds->PSarrayOUT->add(pkt2.ptr, pkt2.size);
mybe->server_myds->DSS=STATE_QUERY_SENT_DS;
}
return true;
} else {
l_free(pkt->size,pkt->ptr);
set_unhealthy();
//mybe->myconn=server_myds->myconn;
// if we reach here, server_myds->DSS should be STATE_QUERY_SENT , therefore the connection to the backend should be dropped anyway
// although we enforce this here
mybe->server_myds->myconn->reusable=false;
return false;
}
return false;
}
void MySQL_Session::handler___status_WAITING_SERVER_DATA___STATE_PING_SENT(PtrSize_t *pkt) {
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Statuses: WAITING_SERVER_DATA - STATE_PING_SENT\n");
@ -1105,6 +1142,18 @@ void MySQL_Session::handler___client_DSS_QUERY_SENT___send_INIT_DB_to_backend()
status=CHANGING_SCHEMA;
}
void MySQL_Session::handler___client_DSS_QUERY_SENT___send_SET_NAMES_to_backend() {
mybe->server_myds->move_from_OUT_to_OUTpending();
mybe->server_myds->myconn->set_charset(client_myds->myconn->options.charset);
//userinfo_server.set_schemaname(userinfo_client.schemaname,strlen(userinfo_client.schemaname));
//mybe->server_myds->myconn->userinfo->set_schemaname(client_myds->myconn->userinfo->schemaname,strlen(client_myds->myconn->userinfo->schemaname));
//myprot_server.generate_COM_INIT_DB(true,NULL,NULL,userinfo_server.schemaname);
//mybe->server_myds->myprot.generate_COM_INIT_DB(true,NULL,NULL,mybe->server_myds->myconn->userinfo->schemaname);
mybe->server_myds->myprot.generate_COM_QUERY(true,NULL,NULL,"SET NAMES utf8");
mybe->server_myds->DSS=STATE_QUERY_SENT_DS;
status=CHANGING_SCHEMA;
}
void MySQL_Session::handler___client_DSS_QUERY_SENT___send_CHANGE_USER_to_backend() {
mybe->server_myds->move_from_OUT_to_OUTpending();
//userinfo_server.set_schemaname(userinfo_client.schemaname,strlen(userinfo_client.schemaname));

@ -148,6 +148,11 @@ MySQL_Connection::~MySQL_Connection() {
}
};
uint8_t MySQL_Connection::set_charset(uint8_t _c) {
proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 4, "Setting charset %d\n", _c);
options.charset=_c;
return _c;
}
MyConnArray * MySQL_Connection::set_MCA(MySQL_Connection_Pool *_MyConnPool, const char *hostname, const char *username, const char *password, const char *db, unsigned int port) {
proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 4, "MySQL_Connection_Pool=%p, Host=%s, user=%s, pass=%s, db=%s, port=%d\n", _MyConnPool, hostname, username, password, db, port);

Loading…
Cancel
Save