diff --git a/modules/protocol/mysql_backend.c b/modules/protocol/mysql_backend.c index bcad4f848..6acff0705 100644 --- a/modules/protocol/mysql_backend.c +++ b/modules/protocol/mysql_backend.c @@ -29,7 +29,8 @@ */ static char *version_str = "V1.0.0"; - +extern char *gw_strend(register const char *s); +int gw_mysql_connect(char *host, int port, char *dbname, char *user, uint8_t *passwd, MySQLProtocol *conn); 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); @@ -305,20 +306,18 @@ int gw_create_backend_connection(DCB *backend, SERVER *server, SESSION *session) } else { fprintf(stderr, "<<<< NOT Connected to backend mysql server!!!\n"); backend->fd = -1; + return -1; } // 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; + backend->fd = -1; + 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; } @@ -330,3 +329,440 @@ gw_backend_close(DCB *dcb) { dcb_close(dcb); } + +/* + * Create a new MySQL connection. + * + * This routine performs the full MySQL connection to the specified server. + * It does + * - socket init + * - socket connect + * - server handshake parsing + * - authenticatio reply + * - the Auth ack receive + * + * Please note, all socket operation are in blocking state + * Status: work in progress. + * + * @param host The TCP/IP host address to connect to + * @param port The TCP/IP host port to connect to + * @param dbname The optional database name. Use NULL if not interested in + * @param user The MySQL database Username: required + * @param passwd The MySQL database Password: required + * @param conn The MySQLProtocol structure to be filled: must be preallocated with gw_mysql_init() + * @return 0 on Success or 1 on Failure. + */ +int gw_mysql_connect(char *host, int port, char *dbname, char *user, uint8_t *passwd, MySQLProtocol *conn) { + + struct sockaddr_in serv_addr; + int compress = 0; + int rv; + int so = 0; + int ciclo = 0; + char buffer[SMALL_CHUNK]; + uint8_t packet_buffer[SMALL_CHUNK]; + uint8_t *payload = NULL; + int server_protocol; + uint8_t *server_version_end = NULL; + uint16_t mysql_server_capabilities_one; + uint16_t mysql_server_capabilities_two; + unsigned long tid =0; + long bytes; + uint8_t scramble_data_1[8 + 1] = ""; + uint8_t scramble_data_2[12 + 1] = ""; + uint8_t capab_ptr[4]; + int scramble_len; + uint8_t scramble[GW_MYSQL_SCRAMBLE_SIZE + 1]; + uint8_t client_scramble[GW_MYSQL_SCRAMBLE_SIZE + 1]; + uint8_t client_capabilities[4]; + uint32_t server_capabilities; + uint32_t final_capabilities; + char dbpass[500]=""; + + char *curr_db = NULL; + uint8_t *curr_passwd = NULL; + + if (strlen(dbname)) + curr_db = dbname; + + if (strlen(passwd)) + curr_passwd = passwd; + + conn->state = MYSQL_ALLOC; + conn->fd = -1; + +//#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, ")))) Connect to MySQL: user[%s], SHA1(passwd)[%s], db [%s]\n", user, passwd, dbname); +//#endif + + memset(&serv_addr, 0, sizeof serv_addr); + serv_addr.sin_family = AF_INET; + + so = socket(AF_INET,SOCK_STREAM,0); + if (so < 0) { + fprintf(stderr, "Errore creazione socket: [%s] %i\n", strerror(errno), errno); + return 1; + } + + conn->fd = so; + + setipaddress(&serv_addr.sin_addr, host); + serv_addr.sin_port = htons(port); + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "Socket initialized\n"); + fflush(stderr); +#endif + + while(1) { + if ((rv = connect(so, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) < 0) { + fprintf(stderr, "Errore connect %i, %s: RV = [%i]\n", errno, strerror(errno), rv); + + if (errno == EINPROGRESS) { + continue; + } else { + close(so); + return -1; + } + } else { + break; + } + } + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "CONNECT is DONE\n"); + fprintf(stderr, "Socket FD is %i\n", so); + fflush(stderr); +#endif + + + memset(&buffer, '\0', sizeof(buffer)); + + bytes = 16384; + + rv = read(so, buffer, bytes); + + if ( rv >0 ) { +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "RESPONSE ciclo %i HO letto [%s] bytes %li\n",ciclo, buffer, bytes); + fflush(stderr); +#endif + ciclo++; + } else { + if (rv == 0 && errno == EOF) { +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "EOF reached. Bytes = %li\n", bytes); + fflush(stderr); +#endif + } else { +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "###### Receive error FINAL : connection not completed %i %s: RV = [%i]\n", errno, strerror(errno), rv); +#endif + close(so); + + return -1; + } + } + +#ifdef MYSQL_CONN_DEBUG + fwrite(buffer, bytes, 1, stderr); + fflush(stderr); +#endif + + //decode mysql handshake + + payload = buffer + 4; + server_protocol= payload[0]; + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "Server Protocol [%i]\n", server_protocol); + +#endif + payload++; + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "Protocol Version [%s]\n", payload); + fflush(stderr); +#endif + + server_version_end = (uint8_t *) gw_strend((char*) payload); + payload = server_version_end + 1; + + // TID + tid = gw_mysql_get_byte4(payload); + memcpy(&conn->tid, &tid, 4); + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "Thread ID is %lu\n", conn->tid); + fflush(stderr); +#endif + + payload +=4; + + // scramble_part 1 + memcpy(scramble_data_1, payload, 8); + payload += 8; + + // 1 filler + payload++; + + mysql_server_capabilities_one = gw_mysql_get_byte2(payload); + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "Capab_1[\n"); + fwrite(&mysql_server_capabilities_one, 2, 1, stderr); + fflush(stderr); +#endif + + //2 capab_part 1 + 1 language + 2 server_status + payload +=5; + + mysql_server_capabilities_two = gw_mysql_get_byte2(payload); + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "]Capab_2[\n"); + fwrite(&mysql_server_capabilities_two, 2, 1, stderr); + fprintf(stderr, "]\n"); + fflush(stderr); +#endif + + memcpy(&capab_ptr, &mysql_server_capabilities_one, 2); + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "Capab_1[\n"); + fwrite(capab_ptr, 2, 1, stderr); + fflush(stderr); +#endif + + memcpy(&(capab_ptr[2]), &mysql_server_capabilities_two, 2); + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "Capab_2[\n"); + fwrite(capab_ptr, 2, 1, stderr); + fflush(stderr); +#endif + + // 2 capab_part 2 + payload+=2; + + scramble_len = payload[0] -1; + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "Scramble_len [%i]\n", scramble_len); + fflush(stderr); +#endif + + payload += 11; + + memcpy(scramble_data_2, payload, scramble_len - 8); + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "Scramble_buff1["); + fwrite(scramble_data_1, 8, 1, stderr); + fprintf(stderr, "]\nScramble_buff2 ["); + fwrite(scramble_data_2, scramble_len - 8, 1, stderr); + fprintf(stderr, "]\n"); + fflush(stderr); +#endif + + memcpy(scramble, scramble_data_1, 8); + memcpy(scramble + 8, scramble_data_2, scramble_len - 8); + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "Full Scramble 20 bytes is [\n"); + fwrite(scramble, GW_MYSQL_SCRAMBLE_SIZE, 1, stderr); + fprintf(stderr, "\n]\n"); + fflush(stderr); +#endif + + memcpy(conn->scramble, scramble, GW_MYSQL_SCRAMBLE_SIZE); + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "Scramble from MYSQL_Conn is [\n"); + fwrite(scramble, GW_MYSQL_SCRAMBLE_SIZE, 1, stderr); + fprintf(stderr, "\n]\n"); + fflush(stderr); + fprintf(stderr, "Now sending user, pass & db\n["); + fwrite(&server_capabilities, 4, 1, stderr); + fprintf(stderr, "]\n"); +#endif + + final_capabilities = gw_mysql_get_byte4((uint8_t *)&server_capabilities); + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "CAPABS [%u]\n", final_capabilities); + fflush(stderr); +#endif + memset(packet_buffer, '\0', sizeof(packet_buffer)); + //packet_header(byte3 +1 pack#) + packet_buffer[3] = '\x01'; + + final_capabilities |= GW_MYSQL_CAPABILITIES_PROTOCOL_41; + final_capabilities |= GW_MYSQL_CAPABILITIES_CLIENT; + if (compress) { + final_capabilities |= GW_MYSQL_CAPABILITIES_COMPRESS; + fprintf(stderr, "Backend Connection with compression\n"); + fflush(stderr); + } + + if (curr_passwd != NULL) { + uint8_t hash1[GW_MYSQL_SCRAMBLE_SIZE]=""; + uint8_t hash2[GW_MYSQL_SCRAMBLE_SIZE]=""; + uint8_t new_sha[GW_MYSQL_SCRAMBLE_SIZE]=""; + + + memcpy(hash1, passwd, GW_MYSQL_SCRAMBLE_SIZE); + gw_sha1_str(hash1, GW_MYSQL_SCRAMBLE_SIZE, hash2); + gw_bin2hex(dbpass, hash2, GW_MYSQL_SCRAMBLE_SIZE); + gw_sha1_2_str(scramble, GW_MYSQL_SCRAMBLE_SIZE, hash2, GW_MYSQL_SCRAMBLE_SIZE, new_sha); + gw_str_xor(client_scramble, new_sha, hash1, GW_MYSQL_SCRAMBLE_SIZE); + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "Hash1 [%s]\n", hash1); + fprintf(stderr, "Hash2 [%s]\n", hash2); + fprintf(stderr, "SHA1(SHA1(password in hex)\n"); + fprintf(stderr, "PAss [%s]\n", dbpass); + fflush(stderr); + fprintf(stderr, "newsha [%s]\n", new_sha); + fprintf(stderr, "Client send scramble 20 [\n"); + fwrite(client_scramble, GW_MYSQL_SCRAMBLE_SIZE, 1, stderr); + fprintf(stderr, "\n]\n"); + fflush(stderr); +#endif + } + + if (curr_db == NULL) { + // now without db!! + final_capabilities &= ~GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB; + } else { + final_capabilities |= GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB; + } + + payload = packet_buffer + 4; + + final_capabilities |= GW_MYSQL_CAPABILITIES_PLUGIN_AUTH; + + gw_mysql_set_byte4(client_capabilities, final_capabilities); + memcpy(payload, client_capabilities, 4); + + //packet_buffer[4] = '\x8d'; + //packet_buffer[5] = '\xa6'; + //packet_buffer[6] = '\x0f'; + //packet_buffer[7] = '\x00'; + + // set now the max-packet size + payload += 4; + gw_mysql_set_byte4(payload, 16777216); + + // set the charset + payload += 4; + *payload = '\x08'; + + payload++; + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "User is [%s]\n", user); + fflush(stderr); +#endif + + + // 4 + 4 + 4 + 1 + 23 = 36 + payload += 23; + strcpy(payload, user); + + // 4 + 4 + 1 + 23 = 32 + 1 (scramble_len) + 20 (fixed_scramble) + 1 (user NULL term) + 1 (db NULL term) = 55 + bytes = 32; + + bytes += strlen(user); + // the NULL + bytes++; + + payload += strlen(user); + payload++; + + if (curr_passwd != NULL) { + // set the auth-length + *payload = GW_MYSQL_SCRAMBLE_SIZE; + payload++; + bytes++; + + //copy the 20 bytes scramble data after packet_buffer+36+user+NULL+1 (byte of auth-length) + memcpy(payload, client_scramble, GW_MYSQL_SCRAMBLE_SIZE); + + payload += GW_MYSQL_SCRAMBLE_SIZE; + bytes += GW_MYSQL_SCRAMBLE_SIZE; + + } else { + // skip the auth-length and write a NULL + payload++; + bytes++; + } + + // if the db is not NULL append it + if (curr_db) { + strcpy(payload, curr_db); + payload += strlen(curr_db); + payload++; + bytes += strlen(curr_db); + // the NULL + bytes++; + } + + strcpy(payload, "mysql_native_password"); + + payload += strlen("mysql_native_password"); + payload++; + + bytes +=strlen("mysql_native_password"); + bytes++; + + gw_mysql_set_byte3(packet_buffer, bytes); + + // the packet header + bytes += 4; + + rv = write(so, packet_buffer, bytes); + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "Sent [%s], [%i] bytes\n", packet_buffer, bytes); + fflush(stderr); +#endif + + if (rv == -1) { + fprintf(stderr, "CONNECT Error in send auth\n"); + } + + bytes = 4096; + + memset(buffer, '\0', sizeof (buffer)); + + rv = read(so, buffer, 4096); + + + if (rv == -1) { + fprintf(stderr, "CONNCET Error in recv OK for auth\n"); + } + +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "ok packet\["); + fwrite(buffer, bytes, 1, stderr); + fprintf(stderr, "]\n"); + fflush(stderr); +#endif + if (buffer[4] == '\x00') { +#ifdef MYSQL_CONN_DEBUG + fprintf(stderr, "OK packet received, packet # %i\n", buffer[3]); + fflush(stderr); +#endif + conn->state = MYSQL_IDLE; + + return 0; + } else { + + close(so); + } + + return 1; + +} + diff --git a/modules/protocol/mysql_client.c b/modules/protocol/mysql_client.c index e09da360f..c6b88e848 100644 --- a/modules/protocol/mysql_client.c +++ b/modules/protocol/mysql_client.c @@ -179,6 +179,89 @@ mysql_send_ok(DCB *dcb, int packet_number, int in_affected_rows, const char* mys return sizeof(mysql_packet_header) + mysql_payload_size; } +/** + * mysql_send_auth_error + * + * Send a MySQL protocol Generic ERR message, to the dcb + * Note the errno and state are still fixed now + * + * @param dcb Descriptor Control Block for the connection to which the OK is sent + * @param packet_number + * @param in_affected_rows + * @param mysql_message + * @return packet length + * + */ + +int +mysql_send_custom_error (DCB *dcb, int packet_number, int in_affected_rows, const char* mysql_message) { + uint8_t *outbuf = NULL; + uint8_t mysql_payload_size = 0; + uint8_t mysql_packet_header[4]; + uint8_t *mysql_payload = NULL; + uint8_t field_count = 0; + uint8_t affected_rows = 0; + uint8_t insert_id = 0; + uint8_t mysql_err[2]; + uint8_t mysql_statemsg[6]; + unsigned int mysql_errno = 0; + const char *mysql_error_msg = NULL; + const char *mysql_state = NULL; + + GWBUF *buf; + + mysql_errno = 2003; + mysql_error_msg = "An errorr occurred ..."; + mysql_state = "HY000"; + + field_count = 0xff; + gw_mysql_set_byte2(mysql_err, mysql_errno); + mysql_statemsg[0]='#'; + memcpy(mysql_statemsg+1, mysql_state, 5); + + if (mysql_message != NULL) { + mysql_error_msg = mysql_message; + } + + mysql_payload_size = sizeof(field_count) + sizeof(mysql_err) + sizeof(mysql_statemsg) + strlen(mysql_error_msg); + + // allocate memory for packet header + payload + if ((buf = gwbuf_alloc(sizeof(mysql_packet_header) + mysql_payload_size)) == NULL) + { + return 0; + } + outbuf = GWBUF_DATA(buf); + + // write packet header with packet number + gw_mysql_set_byte3(mysql_packet_header, mysql_payload_size); + mysql_packet_header[3] = packet_number; + + // write header + memcpy(outbuf, mysql_packet_header, sizeof(mysql_packet_header)); + + mysql_payload = outbuf + sizeof(mysql_packet_header); + + // write field + memcpy(mysql_payload, &field_count, sizeof(field_count)); + mysql_payload = mysql_payload + sizeof(field_count); + + // write errno + memcpy(mysql_payload, mysql_err, sizeof(mysql_err)); + mysql_payload = mysql_payload + sizeof(mysql_err); + + // write sqlstate + memcpy(mysql_payload, mysql_statemsg, sizeof(mysql_statemsg)); + mysql_payload = mysql_payload + sizeof(mysql_statemsg); + + // write err messg + memcpy(mysql_payload, mysql_error_msg, strlen(mysql_error_msg)); + + // writing data in the Client buffer queue + dcb->func.write(dcb, buf); + + return sizeof(mysql_packet_header) + mysql_payload_size; +} + /** * mysql_send_auth_error * @@ -219,9 +302,6 @@ mysql_send_auth_error (DCB *dcb, int packet_number, int in_affected_rows, const if (mysql_message != NULL) { mysql_error_msg = mysql_message; - } else { - mysql_error_msg = "Access denied!"; - } mysql_payload_size = sizeof(field_count) + sizeof(mysql_err) + sizeof(mysql_statemsg) + strlen(mysql_error_msg); @@ -450,36 +530,42 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) { stage1_hash = client_data->client_sha1; username = client_data->user; - database = client_data->db; memcpy(&protocol->client_capabilities, client_auth_packet + 4, 4); connect_with_db = GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB & gw_mysql_get_byte4(&protocol->client_capabilities); compress = GW_MYSQL_CAPABILITIES_COMPRESS & gw_mysql_get_byte4(&protocol->client_capabilities); - strncpy(username, client_auth_packet + 4 + 4 + 4 + 1 + 23, 128); + // now get the user + strncpy(username, client_auth_packet + 4 + 4 + 4 + 1 + 23, 128); + fprintf(stderr, "<<< Client username is [%s]\n", username); + + // get the auth token len memcpy(&auth_token_len, client_auth_packet + 4 + 4 + 4 + 1 + 23 + strlen(username) + 1, 1); - auth_token = (uint8_t *)malloc(auth_token_len); - memcpy(auth_token, client_auth_packet + 4 + 4 + 4 + 1 + 23 + strlen(username) + 1 + 1, auth_token_len); - if (connect_with_db) { - fprintf(stderr, "<<< Client is connected with db\n"); + database = client_data->db; + strncpy(database, client_auth_packet + 4 + 4 + 4 + 1 + 23 + strlen(username) + 1 + 1 + auth_token_len, 128); + fprintf(stderr, "<<< Client selected db is [%s]\n", database); } else { fprintf(stderr, "<<< Client is NOT connected with db\n"); } - if (connect_with_db) { - strncpy(database, client_auth_packet + 4 + 4 + 4 + 1 + 23 + strlen(username) + 1 + 1 + auth_token_len, 128); - } - fprintf(stderr, "<<< Client selected db is [%s]\n", database); + fprintf(stderr, "HERE auth token len is %i\n", auth_token_len); - fprintf(stderr, "<<< Client username is [%s]\n", username); + // allocate memory for token only if auth_token_len > 0 + if (auth_token_len) { + auth_token = (uint8_t *)malloc(auth_token_len); + memcpy(auth_token, client_auth_packet + 4 + 4 + 4 + 1 + 23 + strlen(username) + 1 + 1, auth_token_len); + } // decode the token and check the password + // Note: if auth_token_len == 0 && auth_token == NULL, user is without password so check only the user. auth_ret = gw_check_mysql_scramble_data(dcb, auth_token, auth_token_len, protocol->scramble, sizeof(protocol->scramble), username, stage1_hash); - free(auth_token); + // let's free the auth_token now + if (auth_token) + free(auth_token); if (auth_ret == 0) { fprintf(stderr, "<<< CLIENT AUTH is OK\n"); @@ -509,14 +595,15 @@ static int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_pas fprintf(stderr, ">>> MYSQL user NOT FOUND: %s\n", username); return 1; } - fprintf(stderr, ">>> MYSQL user FOUND !!!!: %si:%s\n", username, user_password); + fprintf(stderr, ">>> MYSQL user FOUND !!!!: [%s]:[%s]\n", username, user_password); // convert hex data (40 bytes) to binary (20 bytes) // gateway_password represents the SHA1(SHA1(real_password)) // please not real_password is unknown and SHA1(real_password) // is unknown as well - gw_hex2bin(gateway_password, user_password, SHA_DIGEST_LENGTH * 2); + if (strlen(user_password)) + gw_hex2bin(gateway_password, user_password, SHA_DIGEST_LENGTH * 2); return 0; } @@ -529,24 +616,30 @@ static int gw_check_mysql_scramble_data(DCB *dcb, uint8_t *token, unsigned int t uint8_t password[GW_MYSQL_SCRAMBLE_SIZE]=""; int ret_val = 1; - if ((username == NULL) || (token == NULL) || (scramble == NULL) || (stage1_hash == NULL)) { + if ((username == NULL) || (scramble == NULL) || (stage1_hash == NULL)) { return 1; } // get the user's password from repository in SHA1(SHA1(real_password)); - // please note 'real_password' in unknown! + // please note 'real_password' is unknown! ret_val = gw_find_mysql_user_password_sha1(username, password, (DCB *) dcb); if (ret_val) { - //fprintf(stderr, "<<<< User [%s] was not found\n", username); + fprintf(stderr, "<<<< User [%s] was not found\n", username); return 1; } else { - //fprintf(stderr, "<<<< User [%s] OK\n", username); + fprintf(stderr, "<<<< User [%s] OK\n", username); } - // convert in hex format: this is the content of mysql.user table, field password without the '*' prefix - // an it is 40 bytes long - gw_bin2hex(hex_double_sha1, password, SHA_DIGEST_LENGTH); + if (token && token_len) { + fprintf(stderr, ">>> continue with auth\n"); + // convert in hex format: this is the content of mysql.user table, field password without the '*' prefix + // an it is 40 bytes long + gw_bin2hex(hex_double_sha1, password, SHA_DIGEST_LENGTH); + } else { + fprintf(stderr, ">>> continue WITHOUT auth, no password\n"); + return 0; + } /////////////////////////// // Auth check in 3 steps @@ -584,6 +677,9 @@ static int gw_check_mysql_scramble_data(DCB *dcb, uint8_t *token, unsigned int t gw_sha1_str(step2, SHA_DIGEST_LENGTH, check_hash); + + fprintf(stderr, "<<<< Client_SHA1 [%20s]\n", stage1_hash); + #ifdef GW_DEBUG_CLIENT_AUTH { char inpass[128]=""; @@ -785,7 +881,22 @@ int gw_read_client_event(DCB* dcb) { //else //fprintf(stderr, "<<< Reading from Client %i bytes: [%s]\n", len, ptr_buff); } - + + + if(!rsession) { + + if (mysql_command == '\x01') { + fprintf(stderr, "COM_QUIT received with no connected backends\n"); + (dcb->func).close(dcb); + + return 1; + } + mysql_send_custom_error(dcb, 1, 0, "Connection to backend lost"); + protocol->state = MYSQL_IDLE; + + break; + } + /////////////////////////// // Handling the COM_QUIT ////////////////////////// @@ -870,7 +981,7 @@ int gw_write_client_event(DCB *dcb) { // still to implement mysql_send_auth_error(dcb, 2, 0, "Authorization failed"); - dcb->func.error(dcb); + dcb->func.close(dcb); return 0; } @@ -967,8 +1078,6 @@ int gw_MySQLListener(DCB *listener, char *config_bind) { listener->state = DCB_STATE_LISTENING; - fprintf(stderr, "HERE listening\n"); - return 0; } @@ -1060,46 +1169,9 @@ static int gw_error_client_event(DCB *dcb) { MySQLProtocol *protocol = DCB_PROTOCOL(dcb, MySQLProtocol); - fprintf(stderr, "#### Handle error function for [%i] is [%s]\n", dcb->state, gw_dcb_state2string(dcb->state)); - - if (dcb->state == DCB_STATE_DISCONNECTED) { - fprintf(stderr, "#### Handle error function, session is %p\n", dcb->session); - return 1; - } - -#ifdef GW_EVENT_DEBUG - if (event != -1) { - fprintf(stderr, ">>>>>> DCB state %i, Protocol State %i: event %i, %i\n", dcb->state, protocol->state, event & EPOLLERR, event & EPOLLHUP); - if(event & EPOLLHUP) - fprintf(stderr, "EPOLLHUP\n"); - - if(event & EPOLLERR) - fprintf(stderr, "EPOLLERR\n"); - - } -#endif - - if (dcb->state != DCB_STATE_LISTENING) { - if (poll_remove_dcb(dcb) == -1) { - fprintf(stderr, "***** poll_remove_dcb: from events check failed to delete %i, [%i]:[%s]\n", dcb->fd, errno, strerror(errno)); - } - -#ifdef GW_EVENT_DEBUG - fprintf(stderr, "closing fd [%i]=[%i], from events\n", dcb->fd, protocol->fd); -#endif - if (dcb->fd) { - - gw_mysql_close((MySQLProtocol **)&dcb->protocol); - - dcb->state = DCB_STATE_DISCONNECTED; - } - } - - //free(dcb->session); - dcb->state = DCB_STATE_FREED; + fprintf(stderr, "#### Handle error function gw_error_client_event, for [%i] is [%s]\n", dcb->state, gw_dcb_state2string(dcb->state)); fprintf(stderr, "#### Handle error function RETURN for [%i] is [%s]\n", dcb->state, gw_dcb_state2string(dcb->state)); - //free(dcb); return 1; }