diff options
-rw-r--r-- | ext/mysqlnd/mysqlnd.c | 173 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_net.c | 4 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_net.h | 2 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_ps.c | 48 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_result.c | 60 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_result_meta.c | 30 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_structs.h | 38 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_wireprotocol.c | 188 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_wireprotocol.h | 21 |
9 files changed, 388 insertions, 176 deletions
diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c index fea5f6988b..b66c458cde 100644 --- a/ext/mysqlnd/mysqlnd.c +++ b/ext/mysqlnd/mysqlnd.c @@ -222,6 +222,12 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor)(MYSQLND *conn TSRMLS_DC) conn->net = NULL; } + if (conn->protocol) { + DBG_INF("Freeing protocol"); + mysqlnd_protocol_free(conn->protocol TSRMLS_CC); + conn->protocol = NULL; + } + mnd_pefree(conn, conn->persistent); DBG_VOID_RETURN; @@ -242,9 +248,8 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND *conn, enum switch (ok_packet) { case PROT_OK_PACKET:{ - php_mysql_packet_ok ok_response; - PACKET_INIT_ALLOCA(ok_response, PROT_OK_PACKET); - if (FAIL == (ret = PACKET_READ_ALLOCA(ok_response, conn))) { + php_mysql_packet_ok * ok_response = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC); + if (FAIL == (ret = PACKET_READ(ok_response, conn))) { if (!silent) { DBG_ERR_FMT("Error while reading %s's OK packet", mysqlnd_command_to_text[command]); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading %s's OK packet. PID=%d", @@ -252,10 +257,9 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND *conn, enum } } else { DBG_INF_FMT("OK from server"); - if (0xFF == ok_response.field_count) { + if (0xFF == ok_response->field_count) { /* The server signalled error. Set the error */ - SET_CLIENT_ERROR(conn->error_info, ok_response.error_no, - ok_response.sqlstate, ok_response.error); + SET_CLIENT_ERROR(conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error); ret = FAIL; /* Cover a protocol design error: error packet does not @@ -270,24 +274,23 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND *conn, enum SET_ERROR_AFF_ROWS(conn); } else { SET_NEW_MESSAGE(conn->last_message, conn->last_message_len, - ok_response.message, ok_response.message_len, + ok_response->message, ok_response->message_len, conn->persistent); if (!ignore_upsert_status) { - conn->upsert_status.warning_count = ok_response.warning_count; - conn->upsert_status.server_status = ok_response.server_status; - conn->upsert_status.affected_rows = ok_response.affected_rows; - conn->upsert_status.last_insert_id = ok_response.last_insert_id; + conn->upsert_status.warning_count = ok_response->warning_count; + conn->upsert_status.server_status = ok_response->server_status; + conn->upsert_status.affected_rows = ok_response->affected_rows; + conn->upsert_status.last_insert_id = ok_response->last_insert_id; } } } - PACKET_FREE_ALLOCA(ok_response); + PACKET_FREE(ok_response); break; } case PROT_EOF_PACKET:{ - php_mysql_packet_eof ok_response; - PACKET_INIT_ALLOCA(ok_response, PROT_EOF_PACKET); - if (FAIL == (ret = PACKET_READ_ALLOCA(ok_response, conn))) { + php_mysql_packet_eof * ok_response = conn->protocol->m.get_eof_packet(conn->protocol, FALSE TSRMLS_CC); + if (FAIL == (ret = PACKET_READ(ok_response, conn))) { SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet"); if (!silent) { @@ -295,24 +298,23 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND *conn, enum php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading %s's EOF packet. PID=%d", mysqlnd_command_to_text[command], getpid()); } - } else if (0xFF == ok_response.field_count) { + } else if (0xFF == ok_response->field_count) { /* The server signalled error. Set the error */ - SET_CLIENT_ERROR(conn->error_info, ok_response.error_no, - ok_response.sqlstate, ok_response.error); + SET_CLIENT_ERROR(conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error); SET_ERROR_AFF_ROWS(conn); - } else if (0xFE != ok_response.field_count) { + } else if (0xFE != ok_response->field_count) { SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet"); if (!silent) { - DBG_ERR_FMT("EOF packet expected, field count wasn't 0xFE but 0x%2X", ok_response.field_count); + DBG_ERR_FMT("EOF packet expected, field count wasn't 0xFE but 0x%2X", ok_response->field_count); php_error_docref(NULL TSRMLS_CC, E_WARNING, "EOF packet expected, field count wasn't 0xFE but 0x%2X", - ok_response.field_count); + ok_response->field_count); } } else { DBG_INF_FMT("OK from server"); } - PACKET_FREE_ALLOCA(ok_response); + PACKET_FREE(ok_response); break; } default: @@ -336,7 +338,7 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command)(MYSQLND *conn, enum php_mysqlnd_ser zend_bool ignore_upsert_status TSRMLS_DC) { enum_func_status ret = PASS; - php_mysql_packet_command cmd_packet; + php_mysql_packet_command * cmd_packet; DBG_ENTER("mysqlnd_conn::simple_command"); DBG_INF_FMT("command=%s ok_packet=%d silent=%d", mysqlnd_command_to_text[command], ok_packet, silent); @@ -362,16 +364,16 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command)(MYSQLND *conn, enum php_mysqlnd_ser SET_ERROR_AFF_ROWS(conn); SET_EMPTY_ERROR(conn->error_info); - PACKET_INIT_ALLOCA(cmd_packet, PROT_CMD_PACKET); - cmd_packet.command = command; + cmd_packet = conn->protocol->m.get_command_packet(conn->protocol, FALSE TSRMLS_CC); + cmd_packet->command = command; if (arg && arg_len) { - cmd_packet.argument = arg; - cmd_packet.arg_len = arg_len; + cmd_packet->argument = arg; + cmd_packet->arg_len = arg_len; } MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_COM_QUIT + command - 1 /* because of COM_SLEEP */ ); - if (! PACKET_WRITE_ALLOCA(cmd_packet, conn)) { + if (! PACKET_WRITE(cmd_packet, conn)) { if (!silent) { DBG_ERR_FMT("Error while sending %s packet", mysqlnd_command_to_text[command]); php_error(E_WARNING, "Error while sending %s packet. PID=%d", mysqlnd_command_to_text[command], getpid()); @@ -382,12 +384,7 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command)(MYSQLND *conn, enum php_mysqlnd_ser ret = conn->m->simple_command_handle_response(conn, ok_packet, silent, command, ignore_upsert_status TSRMLS_CC); } - /* - There is no need to call FREE_ALLOCA on cmd_packet as the - only allocated string is cmd_packet.argument and it was passed - to us. We should not free it. - */ - + PACKET_FREE(cmd_packet); DBG_INF(ret == PASS ? "PASS":"FAIL"); DBG_RETURN(ret); } @@ -457,9 +454,9 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND *conn, zend_bool reconnect = FALSE; zend_bool saved_compression = FALSE; - php_mysql_packet_greet greet_packet; - php_mysql_packet_auth *auth_packet; - php_mysql_packet_ok ok_packet; + php_mysql_packet_greet * greet_packet = NULL; + php_mysql_packet_auth * auth_packet = NULL; + php_mysql_packet_ok * ok_packet = NULL; DBG_ENTER("mysqlnd_conn::connect"); @@ -527,9 +524,9 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND *conn, DBG_INF_FMT("transport=%s", transport); - PACKET_INIT_ALLOCA(greet_packet, PROT_GREET_PACKET); - PACKET_INIT(auth_packet, PROT_AUTH_PACKET, php_mysql_packet_auth *, FALSE); - PACKET_INIT_ALLOCA(ok_packet, PROT_OK_PACKET); + greet_packet = conn->protocol->m.get_greet_packet(conn->protocol, FALSE TSRMLS_CC); + auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC); + ok_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC); if (conn->persistent) { conn->scheme = pestrndup(transport, transport_len, 1); @@ -545,30 +542,28 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND *conn, DBG_INF_FMT("stream=%p", conn->net->stream); - if (FAIL == PACKET_READ_ALLOCA(greet_packet, conn)) { + if (FAIL == PACKET_READ(greet_packet, conn)) { DBG_ERR("Error while reading greeting packet"); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading greeting packet. PID=%d", getpid()); goto err; - } else if (greet_packet.error_no) { - DBG_ERR_FMT("errorno=%d error=%s", greet_packet.error_no, greet_packet.error); - SET_CLIENT_ERROR(conn->error_info, greet_packet.error_no, - greet_packet.sqlstate, greet_packet.error); + } else if (greet_packet->error_no) { + DBG_ERR_FMT("errorno=%d error=%s", greet_packet->error_no, greet_packet->error); + SET_CLIENT_ERROR(conn->error_info, greet_packet->error_no, greet_packet->sqlstate, greet_packet->error); goto err; - } else if (greet_packet.pre41) { - DBG_ERR_FMT("Connecting to 3.22, 3.23 & 4.0 is not supported. Server is %-.32s", - greet_packet.server_version); + } else if (greet_packet->pre41) { + DBG_ERR_FMT("Connecting to 3.22, 3.23 & 4.0 is not supported. Server is %-.32s", greet_packet->server_version); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connecting to 3.22, 3.23 & 4.0 " - " is not supported. Server is %-.32s", greet_packet.server_version); + " is not supported. Server is %-.32s", greet_packet->server_version); SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Connecting to 3.22, 3.23 & 4.0 servers is not supported"); goto err; } - conn->thread_id = greet_packet.thread_id; - conn->protocol_version = greet_packet.protocol_version; - conn->server_version = pestrdup(greet_packet.server_version, conn->persistent); + conn->thread_id = greet_packet->thread_id; + conn->protocol_version = greet_packet->protocol_version; + conn->server_version = pestrdup(greet_packet->server_version, conn->persistent); - conn->greet_charset = mysqlnd_find_charset_nr(greet_packet.charset_no); + conn->greet_charset = mysqlnd_find_charset_nr(greet_packet->charset_no); /* we allow load data local infile by default */ mysql_flags |= CLIENT_LOCAL_FILES | CLIENT_PS_MULTI_RESULTS; #ifndef MYSQLND_COMPRESSION_ENABLED @@ -588,7 +583,7 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND *conn, #if PHP_MAJOR_VERSION >= 6 auth_packet->charset_no = 200;/* utf8 - swedish collation, check mysqlnd_charset.c */ #else - auth_packet->charset_no = greet_packet.charset_no; + auth_packet->charset_no = greet_packet->charset_no; #endif } auth_packet->db = db; @@ -597,29 +592,28 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND *conn, auth_packet->client_flags= mysql_flags; conn->scramble = auth_packet->server_scramble_buf = mnd_pemalloc(SCRAMBLE_LENGTH, conn->persistent); - memcpy(auth_packet->server_scramble_buf, greet_packet.scramble_buf, SCRAMBLE_LENGTH); + memcpy(auth_packet->server_scramble_buf, greet_packet->scramble_buf, SCRAMBLE_LENGTH); if (!PACKET_WRITE(auth_packet, conn)) { CONN_SET_STATE(conn, CONN_QUIT_SENT); SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone); goto err; } - if (FAIL == PACKET_READ_ALLOCA(ok_packet, conn) || ok_packet.field_count >= 0xFE) { - if (ok_packet.field_count == 0xFE) { + if (FAIL == PACKET_READ(ok_packet, conn) || ok_packet->field_count >= 0xFE) { + if (ok_packet->field_count == 0xFE) { /* old authentication with new server !*/ DBG_ERR(mysqlnd_old_passwd); SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd); - } else if (ok_packet.field_count == 0xFF) { - if (ok_packet.sqlstate[0]) { + } else if (ok_packet->field_count == 0xFF) { + if (ok_packet->sqlstate[0]) { if (!self_alloced) { - strlcpy(conn->error_info.sqlstate, ok_packet.sqlstate, sizeof(conn->error_info.sqlstate)); + strlcpy(conn->error_info.sqlstate, ok_packet->sqlstate, sizeof(conn->error_info.sqlstate)); } - DBG_ERR_FMT("ERROR:%d [SQLSTATE:%s] %s", - ok_packet.error_no, ok_packet.sqlstate, ok_packet.error); + DBG_ERR_FMT("ERROR:%d [SQLSTATE:%s] %s", ok_packet->error_no, ok_packet->sqlstate, ok_packet->error); } if (!self_alloced) { - conn->error_info.error_no = ok_packet.error_no; - strlcpy(conn->error_info.error, ok_packet.error, sizeof(conn->error_info.error)); + conn->error_info.error_no = ok_packet->error_no; + strlcpy(conn->error_info.error, ok_packet->error, sizeof(conn->error_info.error)); } } } else { @@ -663,12 +657,12 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND *conn, conn->max_packet_size = auth_packet->max_packet_size; /* todo: check if charset is available */ conn->charset = mysqlnd_find_charset_nr(auth_packet->charset_no); - conn->server_capabilities = greet_packet.server_capabilities; + conn->server_capabilities = greet_packet->server_capabilities; conn->upsert_status.warning_count = 0; - conn->upsert_status.server_status = greet_packet.server_status; + conn->upsert_status.server_status = greet_packet->server_status; conn->upsert_status.affected_rows = 0; SET_NEW_MESSAGE(conn->last_message, conn->last_message_len, - ok_packet.message, ok_packet.message_len, + ok_packet->message, ok_packet->message_len, conn->persistent); SET_EMPTY_ERROR(conn->error_info); @@ -713,16 +707,16 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND *conn, } } - PACKET_FREE_ALLOCA(greet_packet); + PACKET_FREE(greet_packet); PACKET_FREE(auth_packet); - PACKET_FREE_ALLOCA(ok_packet); + PACKET_FREE(ok_packet); DBG_RETURN(PASS); } err: - PACKET_FREE_ALLOCA(greet_packet); + PACKET_FREE(greet_packet); PACKET_FREE(auth_packet); - PACKET_FREE_ALLOCA(ok_packet); + PACKET_FREE(ok_packet); if (errstr) { DBG_ERR_FMT("[%d] %.64s (trying to connect via %s)", errcode, errstr, conn->scheme); @@ -833,7 +827,8 @@ MYSQLND_METHOD(mysqlnd_conn, send_query)(MYSQLND *conn, const char *query, unsig } /* }}} */ -/* {{{ mysqlnd_conn::send_query */ + +/* {{{ mysqlnd_conn::reap_query */ static enum_func_status MYSQLND_METHOD(mysqlnd_conn, reap_query)(MYSQLND * conn TSRMLS_DC) { @@ -843,6 +838,7 @@ MYSQLND_METHOD(mysqlnd_conn, reap_query)(MYSQLND * conn TSRMLS_DC) if (state <= CONN_READY || state == CONN_QUIT_SENT) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not opened, clear or has been closed"); + DBG_ERR_FMT("Connection not opened, clear or has been closed. State=%d", state); DBG_RETURN(FAIL); } DBG_RETURN(conn->m->query_read_result_set_header(conn, NULL TSRMLS_CC)); @@ -991,6 +987,7 @@ _mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long s if (!sets) { php_error_docref(NULL TSRMLS_CC, E_WARNING, *dont_poll ? "All arrays passed are clear":"No stream arrays were passed"); + DBG_ERR_FMT(*dont_poll ? "All arrays passed are clear":"No stream arrays were passed"); DBG_RETURN(FAIL); } @@ -1244,7 +1241,7 @@ static enum_func_status MYSQLND_METHOD(mysqlnd_conn, stat)(MYSQLND *conn, char **message, unsigned int * message_len TSRMLS_DC) { enum_func_status ret; - php_mysql_packet_stats stats_header; + php_mysql_packet_stats * stats_header; DBG_ENTER("mysqlnd_conn::stat"); DBG_INF_FMT("conn=%llu", conn->thread_id); @@ -1253,15 +1250,15 @@ MYSQLND_METHOD(mysqlnd_conn, stat)(MYSQLND *conn, char **message, unsigned int * if (FAIL == ret) { DBG_RETURN(FAIL); } - PACKET_INIT_ALLOCA(stats_header, PROT_STATS_PACKET); - if (FAIL == (ret = PACKET_READ_ALLOCA(stats_header, conn))) { + stats_header = conn->protocol->m.get_stats_packet(conn->protocol, FALSE TSRMLS_CC); + if (FAIL == (ret = PACKET_READ(stats_header, conn))) { DBG_RETURN(FAIL); } - *message = stats_header.message; - *message_len = stats_header.message_len; + *message = stats_header->message; + *message_len = stats_header->message_len; /* Ownership transfer */ - stats_header.message = NULL; - PACKET_FREE_ALLOCA(stats_header); + stats_header->message = NULL; + PACKET_FREE(stats_header); DBG_INF(*message); DBG_RETURN(PASS); @@ -1752,7 +1749,7 @@ MYSQLND_METHOD(mysqlnd_conn, change_user)(MYSQLND * const conn, */ size_t user_len; enum_func_status ret; - php_mysql_packet_chg_user_resp chg_user_resp; + php_mysql_packet_chg_user_resp * chg_user_resp; char buffer[MYSQLND_MAX_ALLOWED_USER_LEN + 1 + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1]; char *p = buffer; @@ -1799,10 +1796,10 @@ MYSQLND_METHOD(mysqlnd_conn, change_user)(MYSQLND * const conn, DBG_RETURN(FAIL); } - PACKET_INIT_ALLOCA(chg_user_resp, PROT_CHG_USER_PACKET); - ret = PACKET_READ_ALLOCA(chg_user_resp, conn); - conn->error_info = chg_user_resp.error_info; - PACKET_FREE_ALLOCA(chg_user_resp); + chg_user_resp = conn->protocol->m.get_change_user_response_packet(conn->protocol, FALSE TSRMLS_CC); + ret = PACKET_READ(chg_user_resp, conn); + conn->error_info = chg_user_resp->error_info; + PACKET_FREE(chg_user_resp); if (conn->error_info.error_no) { ret = FAIL; @@ -1814,10 +1811,9 @@ MYSQLND_METHOD(mysqlnd_conn, change_user)(MYSQLND * const conn, if (mysqlnd_get_server_version(conn) > 50113L && mysqlnd_get_server_version(conn) < 50118L) { - php_mysql_packet_ok redundant_error_packet; - PACKET_INIT_ALLOCA(redundant_error_packet, PROT_OK_PACKET); - PACKET_READ_ALLOCA(redundant_error_packet, conn); - PACKET_FREE_ALLOCA(redundant_error_packet); + php_mysql_packet_ok * redundant_error_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC); + PACKET_READ(redundant_error_packet, conn); + PACKET_FREE(redundant_error_packet); DBG_INF_FMT("Server is %d, buggy, sends two ERR messages", mysqlnd_get_server_version(conn)); } } @@ -2095,6 +2091,7 @@ MYSQLND_METHOD(mysqlnd_conn, init)(MYSQLND * conn TSRMLS_DC) { DBG_ENTER("mysqlnd_conn::init"); conn->net = mysqlnd_net_init(conn->persistent TSRMLS_CC); + conn->protocol = mysqlnd_protocol_init(conn->persistent TSRMLS_CC); SET_ERROR_AFF_ROWS(conn); diff --git a/ext/mysqlnd/mysqlnd_net.c b/ext/mysqlnd/mysqlnd_net.c index 820855eaf7..ea0ece399c 100644 --- a/ext/mysqlnd/mysqlnd_net.c +++ b/ext/mysqlnd/mysqlnd_net.c @@ -687,9 +687,9 @@ mysqlnd_net_init(zend_bool persistent TSRMLS_DC) /* }}} */ -/* {{{ mysqlnd_net_init */ +/* {{{ mysqlnd_net_free */ void -mysqlnd_net_free(MYSQLND_NET * net TSRMLS_DC) +mysqlnd_net_free(MYSQLND_NET * const net TSRMLS_DC) { zend_bool pers = net->persistent; diff --git a/ext/mysqlnd/mysqlnd_net.h b/ext/mysqlnd/mysqlnd_net.h index 6f9e5d9918..01c2158336 100644 --- a/ext/mysqlnd/mysqlnd_net.h +++ b/ext/mysqlnd/mysqlnd_net.h @@ -24,7 +24,7 @@ #define MYSQLND_NET_H MYSQLND_NET * mysqlnd_net_init(zend_bool persistent TSRMLS_DC); -void mysqlnd_net_free(MYSQLND_NET * net TSRMLS_DC); +void mysqlnd_net_free(MYSQLND_NET * const net TSRMLS_DC); #endif /* MYSQLND_NET_H */ diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index d57320d6c4..a90c4a6358 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -218,20 +218,20 @@ mysqlnd_stmt_skip_metadata(MYSQLND_STMT *stmt TSRMLS_DC) /* Follows parameter metadata, we have just to skip it, as libmysql does */ unsigned int i = 0; enum_func_status ret = PASS; - php_mysql_packet_res_field field_packet; + php_mysql_packet_res_field * field_packet; DBG_ENTER("mysqlnd_stmt_skip_metadata"); DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - PACKET_INIT_ALLOCA(field_packet, PROT_RSET_FLD_PACKET); - field_packet.skip_parsing = TRUE; + field_packet = stmt->conn->protocol->m.get_result_field_packet(stmt->conn->protocol, FALSE TSRMLS_CC); + field_packet->skip_parsing = TRUE; for (;i < stmt->param_count; i++) { - if (FAIL == PACKET_READ_ALLOCA(field_packet, stmt->conn)) { + if (FAIL == PACKET_READ(field_packet, stmt->conn)) { ret = FAIL; break; } } - PACKET_FREE_ALLOCA(field_packet); + PACKET_FREE(field_packet); DBG_RETURN(ret); } @@ -242,31 +242,31 @@ mysqlnd_stmt_skip_metadata(MYSQLND_STMT *stmt TSRMLS_DC) static enum_func_status mysqlnd_stmt_read_prepare_response(MYSQLND_STMT *stmt TSRMLS_DC) { - php_mysql_packet_prepare_response prepare_resp; + php_mysql_packet_prepare_response * prepare_resp; enum_func_status ret = PASS; DBG_ENTER("mysqlnd_stmt_read_prepare_response"); DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - PACKET_INIT_ALLOCA(prepare_resp, PROT_PREPARE_RESP_PACKET); - if (FAIL == PACKET_READ_ALLOCA(prepare_resp, stmt->conn)) { + prepare_resp = stmt->conn->protocol->m.get_prepare_response_packet(stmt->conn->protocol, FALSE TSRMLS_CC); + if (FAIL == PACKET_READ(prepare_resp, stmt->conn)) { ret = FAIL; goto done; } - if (0xFF == prepare_resp.error_code) { - stmt->error_info = stmt->conn->error_info = prepare_resp.error_info; + if (0xFF == prepare_resp->error_code) { + stmt->error_info = stmt->conn->error_info = prepare_resp->error_info; ret = FAIL; goto done; } - stmt->stmt_id = prepare_resp.stmt_id; - stmt->warning_count = stmt->conn->upsert_status.warning_count = prepare_resp.warning_count; - stmt->field_count = stmt->conn->field_count = prepare_resp.field_count; - stmt->param_count = prepare_resp.param_count; - PACKET_FREE_ALLOCA(prepare_resp); - + stmt->stmt_id = prepare_resp->stmt_id; + stmt->warning_count = stmt->conn->upsert_status.warning_count = prepare_resp->warning_count; + stmt->field_count = stmt->conn->field_count = prepare_resp->field_count; + stmt->param_count = prepare_resp->param_count; done: + PACKET_FREE(prepare_resp); + DBG_RETURN(ret); } /* }}} */ @@ -276,14 +276,14 @@ done: static enum_func_status mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT *stmt TSRMLS_DC) { - php_mysql_packet_eof fields_eof; + php_mysql_packet_eof * fields_eof; enum_func_status ret; DBG_ENTER("mysqlnd_stmt_prepare_read_eof"); DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - PACKET_INIT_ALLOCA(fields_eof, PROT_EOF_PACKET); - if (FAIL == (ret = PACKET_READ_ALLOCA(fields_eof, stmt->conn))) { + fields_eof = stmt->conn->protocol->m.get_eof_packet(stmt->conn->protocol, FALSE TSRMLS_CC); + if (FAIL == (ret = PACKET_READ(fields_eof, stmt->conn))) { if (stmt->result) { stmt->result->m.free_result_contents(stmt->result TSRMLS_CC); mnd_efree(stmt->result); @@ -291,11 +291,11 @@ mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT *stmt TSRMLS_DC) stmt->state = MYSQLND_STMT_INITTED; } } else { - stmt->upsert_status.server_status = fields_eof.server_status; - stmt->upsert_status.warning_count = fields_eof.warning_count; + stmt->upsert_status.server_status = fields_eof->server_status; + stmt->upsert_status.warning_count = fields_eof->warning_count; stmt->state = MYSQLND_STMT_PREPARED; } - PACKET_FREE_ALLOCA(fields_eof); + PACKET_FREE(fields_eof); DBG_RETURN(ret); } @@ -794,7 +794,7 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int result->meta->fields[i].max_length = Z_STRLEN_P(data); } stmt->result_bind[i].zv->value = data->value; - // copied data, thus also the ownership. Thus null data + /* copied data, thus also the ownership. Thus null data */ ZVAL_NULL(data); } } @@ -973,7 +973,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla result->meta->fields[i].max_length = Z_STRLEN_P(data); } stmt->result_bind[i].zv->value = data->value; - // copied data, thus also the ownership. Thus null data + /* copied data, thus also the ownership. Thus null data */ ZVAL_NULL(data); } } diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 22ea7d325d..c0fefaa093 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -354,21 +354,21 @@ enum_func_status mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC) { enum_func_status ret; - php_mysql_packet_rset_header rset_header; + php_mysql_packet_rset_header * rset_header; DBG_ENTER("mysqlnd_query_read_result_set_header"); DBG_INF_FMT("stmt=%d", stmt? stmt->stmt_id:0); ret = FAIL; - PACKET_INIT_ALLOCA(rset_header, PROT_RSET_HEADER_PACKET); + rset_header = conn->protocol->m.get_rset_header_packet(conn->protocol, FALSE TSRMLS_CC); do { SET_ERROR_AFF_ROWS(conn); - if (FAIL == (ret = PACKET_READ_ALLOCA(rset_header, conn))) { + if (FAIL == (ret = PACKET_READ(rset_header, conn))) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error reading result set's header"); break; } - if (rset_header.error_info.error_no) { + if (rset_header->error_info.error_no) { /* Cover a protocol design error: error packet does not contain the server status. Therefore, the client has no way @@ -383,7 +383,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC This will copy the error code and the messages, as they are buffers in the struct */ - conn->error_info = rset_header.error_info; + conn->error_info = rset_header->error_info; ret = FAIL; /* Return back from CONN_QUERY_SENT */ CONN_SET_STATE(conn, CONN_READY); @@ -391,13 +391,13 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC } conn->error_info.error_no = 0; - switch (rset_header.field_count) { + switch (rset_header->field_count) { case MYSQLND_NULL_LENGTH: { /* LOAD DATA LOCAL INFILE */ zend_bool is_warning; DBG_INF("LOAD DATA"); conn->last_query_type = QUERY_LOAD_LOCAL; CONN_SET_STATE(conn, CONN_SENDING_LOAD_DATA); - ret = mysqlnd_handle_local_infile(conn, rset_header.info_or_local_file, &is_warning TSRMLS_CC); + ret = mysqlnd_handle_local_infile(conn, rset_header->info_or_local_file, &is_warning TSRMLS_CC); CONN_SET_STATE(conn, (ret == PASS || is_warning == TRUE)? CONN_READY:CONN_QUIT_SENT); MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_NON_RSET_QUERY); break; @@ -405,13 +405,13 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC case 0: /* UPSERT */ DBG_INF("UPSERT"); conn->last_query_type = QUERY_UPSERT; - conn->field_count = rset_header.field_count; - conn->upsert_status.warning_count = rset_header.warning_count; - conn->upsert_status.server_status = rset_header.server_status; - conn->upsert_status.affected_rows = rset_header.affected_rows; - conn->upsert_status.last_insert_id = rset_header.last_insert_id; + conn->field_count = rset_header->field_count; + conn->upsert_status.warning_count = rset_header->warning_count; + conn->upsert_status.server_status = rset_header->server_status; + conn->upsert_status.affected_rows = rset_header->affected_rows; + conn->upsert_status.last_insert_id = rset_header->last_insert_id; SET_NEW_MESSAGE(conn->last_message, conn->last_message_len, - rset_header.info_or_local_file, rset_header.info_or_local_file_len, + rset_header->info_or_local_file, rset_header->info_or_local_file_len, conn->persistent); /* Result set can follow UPSERT statement, check server_status */ if (conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) { @@ -423,7 +423,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_NON_RSET_QUERY); break; default:{ /* Result set */ - php_mysql_packet_eof fields_eof; + php_mysql_packet_eof * fields_eof; MYSQLND_RES *result; enum_mysqlnd_collected_stats stat = STAT_LAST; @@ -438,9 +438,9 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC conn->last_query_type = QUERY_SELECT; CONN_SET_STATE(conn, CONN_FETCHING_DATA); /* PS has already allocated it */ - conn->field_count = rset_header.field_count; + conn->field_count = rset_header->field_count; if (!stmt) { - result = conn->current_result = mysqlnd_result_init(rset_header.field_count TSRMLS_CC); + result = conn->current_result = mysqlnd_result_init(rset_header->field_count TSRMLS_CC); } else { if (!stmt->result) { DBG_INF("This is 'SHOW'/'EXPLAIN'-like query."); @@ -449,7 +449,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC prepared statements can't send result set metadata for these queries on prepare stage. Read it now. */ - result = stmt->result = mysqlnd_result_init(rset_header.field_count TSRMLS_CC); + result = stmt->result = mysqlnd_result_init(rset_header->field_count TSRMLS_CC); } else { /* Update result set metadata if it for some reason changed between @@ -478,8 +478,8 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC } /* Check for SERVER_STATUS_MORE_RESULTS if needed */ - PACKET_INIT_ALLOCA(fields_eof, PROT_EOF_PACKET); - if (FAIL == (ret = PACKET_READ_ALLOCA(fields_eof, conn))) { + fields_eof = conn->protocol->m.get_eof_packet(conn->protocol, FALSE TSRMLS_CC); + if (FAIL == (ret = PACKET_READ(fields_eof, conn))) { DBG_ERR("Error ocurred while reading the EOF packet"); result->m.free_result_contents(result TSRMLS_CC); mnd_efree(result); @@ -492,9 +492,9 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC } } else { unsigned int to_log = MYSQLND_G(log_mask); - to_log &= fields_eof.server_status; - DBG_INF_FMT("warnings=%u server_status=%u", fields_eof.warning_count, fields_eof.server_status); - conn->upsert_status.warning_count = fields_eof.warning_count; + to_log &= fields_eof->server_status; + DBG_INF_FMT("warnings=%u server_status=%u", fields_eof->warning_count, fields_eof->server_status); + conn->upsert_status.warning_count = fields_eof->warning_count; /* If SERVER_MORE_RESULTS_EXISTS is set then this is either MULTI_QUERY or a CALL() The first packet after sending the query/com_execute has the bit set only @@ -502,12 +502,12 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC will include many result sets. What actually matters are the bits set at the end of every result set (the EOF packet). */ - conn->upsert_status.server_status = fields_eof.server_status; - if (fields_eof.server_status & SERVER_QUERY_NO_GOOD_INDEX_USED) { + conn->upsert_status.server_status = fields_eof->server_status; + if (fields_eof->server_status & SERVER_QUERY_NO_GOOD_INDEX_USED) { stat = STAT_BAD_INDEX_USED; - } else if (fields_eof.server_status & SERVER_QUERY_NO_INDEX_USED) { + } else if (fields_eof->server_status & SERVER_QUERY_NO_INDEX_USED) { stat = STAT_NO_INDEX_USED; - } else if (fields_eof.server_status & SERVER_QUERY_WAS_SLOW) { + } else if (fields_eof->server_status & SERVER_QUERY_WAS_SLOW) { stat = STAT_QUERY_WAS_SLOW; } if (to_log) { @@ -520,13 +520,13 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC MYSQLND_INC_CONN_STATISTIC(&conn->stats, stat); } - PACKET_FREE_ALLOCA(fields_eof); + PACKET_FREE(fields_eof); break; } } } while (0); - PACKET_FREE_ALLOCA(rset_header); + PACKET_FREE(rset_header); DBG_INF(ret == PASS? "PASS":"FAIL"); DBG_RETURN(ret); @@ -866,7 +866,7 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps this to be not NULL. */ /* FALSE = non-persistent */ - PACKET_INIT(result->row_packet, PROT_ROW_PACKET, php_mysql_packet_row *, FALSE); + result->row_packet = result->conn->protocol->m.get_row_packet(result->conn->protocol, FALSE TSRMLS_CC); result->row_packet->result_set_memory_pool = result->result_set_memory_pool; result->row_packet->field_count = result->field_count; result->row_packet->binary_protocol = ps; @@ -1072,7 +1072,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND * const conn, MYSQL php_mysqlnd_rowp_read_text_protocol; /* non-persistent */ - PACKET_INIT(row_packet, PROT_ROW_PACKET, php_mysql_packet_row *, FALSE); + row_packet = conn->protocol->m.get_row_packet(conn->protocol, FALSE TSRMLS_CC); row_packet->result_set_memory_pool = result->result_set_memory_pool; row_packet->field_count = meta->field_count; row_packet->binary_protocol = binary_protocol; diff --git a/ext/mysqlnd/mysqlnd_result_meta.c b/ext/mysqlnd/mysqlnd_result_meta.c index 95ef93a65b..e545c004b3 100644 --- a/ext/mysqlnd/mysqlnd_result_meta.c +++ b/ext/mysqlnd/mysqlnd_result_meta.c @@ -142,7 +142,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met MYSQLND *conn TSRMLS_DC) { unsigned int i = 0; - php_mysql_packet_res_field field_packet; + php_mysql_packet_res_field * field_packet; #if PHP_MAJOR_VERSION >= 6 UChar *ustr; int ulen; @@ -150,7 +150,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met DBG_ENTER("mysqlnd_res_meta::read_metadata"); - PACKET_INIT_ALLOCA(field_packet, PROT_RSET_FLD_PACKET); + field_packet = conn->protocol->m.get_result_field_packet(conn->protocol, FALSE TSRMLS_CC); for (;i < meta->field_count; i++) { long idx; @@ -160,19 +160,19 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met meta->fields[i].root = NULL; } - field_packet.metadata = &(meta->fields[i]); - if (FAIL == PACKET_READ_ALLOCA(field_packet, conn)) { - PACKET_FREE_ALLOCA(field_packet); + field_packet->metadata = &(meta->fields[i]); + if (FAIL == PACKET_READ(field_packet, conn)) { + PACKET_FREE(field_packet); DBG_RETURN(FAIL); } - if (field_packet.error_info.error_no) { - conn->error_info = field_packet.error_info; + if (field_packet->error_info.error_no) { + conn->error_info = field_packet->error_info; /* Return back from CONN_QUERY_SENT */ - PACKET_FREE_ALLOCA(field_packet); + PACKET_FREE(field_packet); DBG_RETURN(FAIL); } - if (field_packet.stupid_list_fields_eof == TRUE) { + if (field_packet->stupid_list_fields_eof == TRUE) { meta->field_count = i; break; } @@ -184,7 +184,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met "Unknown type %d sent by the server. " "Please send a report to the developers", meta->fields[i].type); - PACKET_FREE_ALLOCA(field_packet); + PACKET_FREE(field_packet); DBG_RETURN(FAIL); } if (meta->fields[i].type == MYSQL_TYPE_BIT) { @@ -240,19 +240,19 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met #else /* For BC we have to check whether the key is numeric and use it like this */ if ((meta->zend_hash_keys[i].is_numeric = - mysqlnd_is_key_numeric(field_packet.metadata->name, - field_packet.metadata->name_length + 1, + mysqlnd_is_key_numeric(field_packet->metadata->name, + field_packet->metadata->name_length + 1, &idx))) { meta->zend_hash_keys[i].key = idx; } else { meta->zend_hash_keys[i].key = - zend_get_hash_value(field_packet.metadata->name, - field_packet.metadata->name_length + 1); + zend_get_hash_value(field_packet->metadata->name, + field_packet->metadata->name_length + 1); } #endif } - PACKET_FREE_ALLOCA(field_packet); + PACKET_FREE(field_packet); DBG_RETURN(PASS); } diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h index ddfc77de64..016b3bd32a 100644 --- a/ext/mysqlnd/mysqlnd_structs.h +++ b/ext/mysqlnd/mysqlnd_structs.h @@ -184,6 +184,7 @@ typedef struct st_mysqlnd_net_options typedef struct st_mysqlnd_connection MYSQLND; typedef struct st_mysqlnd_net MYSQLND_NET; +typedef struct st_mysqlnd_protocol MYSQLND_PROTOCOL; typedef struct st_mysqlnd_res MYSQLND_RES; typedef char** MYSQLND_ROW_C; /* return data as array of strings */ typedef struct st_mysqlnd_stmt MYSQLND_STMT; @@ -243,6 +244,35 @@ struct st_mysqlnd_net_methods }; +struct st_php_mysql_packet_greet; +struct st_php_mysql_packet_greet; +struct st_php_mysql_packet_auth; +struct st_php_mysql_packet_ok; +struct st_php_mysql_packet_command; +struct st_php_mysql_packet_eof; +struct st_php_mysql_packet_rset_header; +struct st_php_mysql_packet_res_field; +struct st_php_mysql_packet_row; +struct st_php_mysql_packet_stats; +struct st_php_mysql_packet_prepare_response; +struct st_php_mysql_packet_chg_user_resp; + +struct st_mysqlnd_protocol_methods +{ + struct st_php_mysql_packet_greet * (*get_greet_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); + struct st_php_mysql_packet_auth * (*get_auth_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); + struct st_php_mysql_packet_ok * (*get_ok_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); + struct st_php_mysql_packet_command * (*get_command_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); + struct st_php_mysql_packet_eof * (*get_eof_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); + struct st_php_mysql_packet_rset_header *(*get_rset_header_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); + struct st_php_mysql_packet_res_field * (*get_result_field_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); + struct st_php_mysql_packet_row * (*get_row_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); + struct st_php_mysql_packet_stats * (*get_stats_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); + struct st_php_mysql_packet_prepare_response *(*get_prepare_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); + struct st_php_mysql_packet_chg_user_resp*(*get_change_user_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); +}; + + struct st_mysqlnd_conn_methods { void (*init)(MYSQLND * conn TSRMLS_DC); @@ -434,10 +464,18 @@ struct st_mysqlnd_net }; +struct st_mysqlnd_protocol +{ + struct st_mysqlnd_protocol_methods m; + zend_bool persistent; +}; + + struct st_mysqlnd_connection { /* Operation related */ MYSQLND_NET * net; + MYSQLND_PROTOCOL * protocol; /* Information related */ char *host; diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index af597d3517..277ad00ab4 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -1786,6 +1786,194 @@ mysqlnd_packet_methods packet_methods[PROT_LAST] = /* }}} */ + +/* {{{ mysqlnd_protocol::get_greet_packet */ +static struct st_php_mysql_packet_greet * +MYSQLND_METHOD(mysqlnd_protocol, get_greet_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC) +{ + struct st_php_mysql_packet_greet * packet = pecalloc(1, packet_methods[PROT_GREET_PACKET].struct_size, persistent); + DBG_ENTER("mysqlnd_protocol::get_greet_packet"); + packet->header.m = &packet_methods[PROT_GREET_PACKET]; + packet->header.persistent = persistent; + DBG_RETURN(packet); +} +/* }}} */ + + +/* {{{ mysqlnd_protocol::get_auth_packet */ +static struct st_php_mysql_packet_auth * +MYSQLND_METHOD(mysqlnd_protocol, get_auth_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC) +{ + struct st_php_mysql_packet_auth * packet = pecalloc(1, packet_methods[PROT_AUTH_PACKET].struct_size, persistent); + DBG_ENTER("mysqlnd_protocol::get_auth_packet"); + packet->header.m = &packet_methods[PROT_AUTH_PACKET]; + packet->header.persistent = persistent; + DBG_RETURN(packet); +} +/* }}} */ + + +/* {{{ mysqlnd_protocol::get_ok_packet */ +static struct st_php_mysql_packet_ok * +MYSQLND_METHOD(mysqlnd_protocol, get_ok_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC) +{ + struct st_php_mysql_packet_ok * packet = pecalloc(1, packet_methods[PROT_OK_PACKET].struct_size, persistent); + DBG_ENTER("mysqlnd_protocol::get_ok_packet"); + packet->header.m = &packet_methods[PROT_OK_PACKET]; + packet->header.persistent = persistent; + DBG_RETURN(packet); +} +/* }}} */ + + +/* {{{ mysqlnd_protocol::get_eof_packet */ +static struct st_php_mysql_packet_eof * +MYSQLND_METHOD(mysqlnd_protocol, get_eof_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC) +{ + struct st_php_mysql_packet_eof * packet = pecalloc(1, packet_methods[PROT_EOF_PACKET].struct_size, persistent); + DBG_ENTER("mysqlnd_protocol::get_eof_packet"); + packet->header.m = &packet_methods[PROT_EOF_PACKET]; + packet->header.persistent = persistent; + DBG_RETURN(packet); +} +/* }}} */ + + +/* {{{ mysqlnd_protocol::get_command_packet */ +static struct st_php_mysql_packet_command * +MYSQLND_METHOD(mysqlnd_protocol, get_command_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC) +{ + struct st_php_mysql_packet_command * packet = pecalloc(1, packet_methods[PROT_CMD_PACKET].struct_size, persistent); + DBG_ENTER("mysqlnd_protocol::get_command_packet"); + packet->header.m = &packet_methods[PROT_CMD_PACKET]; + packet->header.persistent = persistent; + DBG_RETURN(packet); +} +/* }}} */ + + +/* {{{ mysqlnd_protocol::get_rset_packet */ +static struct st_php_mysql_packet_rset_header * +MYSQLND_METHOD(mysqlnd_protocol, get_rset_header_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC) +{ + struct st_php_mysql_packet_rset_header * packet = pecalloc(1, packet_methods[PROT_RSET_HEADER_PACKET].struct_size, persistent); + DBG_ENTER("mysqlnd_protocol::get_rset_header_packet"); + packet->header.m = &packet_methods[PROT_RSET_HEADER_PACKET]; + packet->header.persistent = persistent; + DBG_RETURN(packet); +} +/* }}} */ + + +/* {{{ mysqlnd_protocol::get_result_field_packet */ +static struct st_php_mysql_packet_res_field * +MYSQLND_METHOD(mysqlnd_protocol, get_result_field_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC) +{ + struct st_php_mysql_packet_res_field * packet = pecalloc(1, packet_methods[PROT_RSET_FLD_PACKET].struct_size, persistent); + DBG_ENTER("mysqlnd_protocol::get_result_field_packet"); + packet->header.m = &packet_methods[PROT_RSET_FLD_PACKET]; + packet->header.persistent = persistent; + DBG_RETURN(packet); +} +/* }}} */ + + +/* {{{ mysqlnd_protocol::get_row_packet */ +static struct st_php_mysql_packet_row * +MYSQLND_METHOD(mysqlnd_protocol, get_row_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC) +{ + struct st_php_mysql_packet_row * packet = pecalloc(1, packet_methods[PROT_ROW_PACKET].struct_size, persistent); + DBG_ENTER("mysqlnd_protocol::get_row_packet"); + packet->header.m = &packet_methods[PROT_ROW_PACKET]; + packet->header.persistent = persistent; + DBG_RETURN(packet); +} +/* }}} */ + + +/* {{{ mysqlnd_protocol::get_stats_packet */ +static struct st_php_mysql_packet_stats * +MYSQLND_METHOD(mysqlnd_protocol, get_stats_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC) +{ + struct st_php_mysql_packet_stats * packet = pecalloc(1, packet_methods[PROT_STATS_PACKET].struct_size, persistent); + DBG_ENTER("mysqlnd_protocol::get_stats_packet"); + packet->header.m = &packet_methods[PROT_STATS_PACKET]; + packet->header.persistent = persistent; + DBG_RETURN(packet); +} +/* }}} */ + + +/* {{{ mysqlnd_protocol::get_prepare_response_packet */ +static struct st_php_mysql_packet_prepare_response * +MYSQLND_METHOD(mysqlnd_protocol, get_prepare_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC) +{ + struct st_php_mysql_packet_prepare_response * packet = pecalloc(1, packet_methods[PROT_PREPARE_RESP_PACKET].struct_size, persistent); + DBG_ENTER("mysqlnd_protocol::get_prepare_response_packet"); + packet->header.m = &packet_methods[PROT_PREPARE_RESP_PACKET]; + packet->header.persistent = persistent; + DBG_RETURN(packet); +} +/* }}} */ + + +/* {{{ mysqlnd_protocol::get_change_user_response_packet */ +static struct st_php_mysql_packet_chg_user_resp* +MYSQLND_METHOD(mysqlnd_protocol, get_change_user_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC) +{ + struct st_php_mysql_packet_chg_user_resp * packet = pecalloc(1, packet_methods[PROT_CHG_USER_PACKET].struct_size, persistent); + DBG_ENTER("mysqlnd_protocol::get_change_user_response_packet"); + packet->header.m = &packet_methods[PROT_CHG_USER_PACKET]; + packet->header.persistent = persistent; + DBG_RETURN(packet); +} +/* }}} */ + + +/* {{{ mysqlnd_protocol_init */ +MYSQLND_PROTOCOL * +mysqlnd_protocol_init(zend_bool persistent TSRMLS_DC) +{ + size_t alloc_size = sizeof(MYSQLND_PROTOCOL) + mysqlnd_plugin_count() * sizeof(void *); + MYSQLND_PROTOCOL *ret = mnd_pecalloc(1, alloc_size, persistent); + + DBG_ENTER("mysqlnd_protocol_init"); + DBG_INF_FMT("persistent=%d", persistent); + ret->persistent = persistent; + + ret->m.get_greet_packet = MYSQLND_METHOD(mysqlnd_protocol, get_greet_packet); + ret->m.get_auth_packet = MYSQLND_METHOD(mysqlnd_protocol, get_auth_packet); + ret->m.get_ok_packet = MYSQLND_METHOD(mysqlnd_protocol, get_ok_packet); + ret->m.get_command_packet = MYSQLND_METHOD(mysqlnd_protocol, get_command_packet); + ret->m.get_eof_packet = MYSQLND_METHOD(mysqlnd_protocol, get_eof_packet); + ret->m.get_rset_header_packet = MYSQLND_METHOD(mysqlnd_protocol, get_rset_header_packet); + ret->m.get_result_field_packet = MYSQLND_METHOD(mysqlnd_protocol, get_result_field_packet); + ret->m.get_row_packet = MYSQLND_METHOD(mysqlnd_protocol, get_row_packet); + ret->m.get_stats_packet = MYSQLND_METHOD(mysqlnd_protocol, get_stats_packet); + ret->m.get_prepare_response_packet = MYSQLND_METHOD(mysqlnd_protocol, get_prepare_response_packet); + ret->m.get_change_user_response_packet = MYSQLND_METHOD(mysqlnd_protocol, get_change_user_response_packet); + + DBG_RETURN(ret); +} +/* }}} */ + + +/* {{{ mysqlnd_protocol_free */ +void +mysqlnd_protocol_free(MYSQLND_PROTOCOL * const protocol TSRMLS_DC) +{ + zend_bool pers = protocol->persistent; + + DBG_ENTER("mysqlnd_protocol_free"); + + if (protocol) { + mnd_pefree(protocol, pers); + } + DBG_VOID_RETURN; +} +/* }}} */ + + /* * Local variables: * tab-width: 4 diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.h b/ext/mysqlnd/mysqlnd_wireprotocol.h index 66622e5cc4..7229db59e2 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.h +++ b/ext/mysqlnd/mysqlnd_wireprotocol.h @@ -36,13 +36,6 @@ extern char * mysqlnd_read_body_name; /* Packet handling */ -#define PACKET_INIT(packet, enum_type, c_type, pers) \ - { \ - packet = (c_type) pecalloc(1, packet_methods[(enum_type)].struct_size, (pers)); \ - ((c_type) (packet))->header.m = &packet_methods[(enum_type)]; \ - ((c_type) (packet))->header.persistent = (pers); \ - DBG_INF_FMT("PACKET_INIT(%p, %d, %d)", packet, (int) enum_type, (int) pers); \ - } #define PACKET_WRITE(packet, conn) ((packet)->header.m->write_to_net((packet), (conn) TSRMLS_CC)) #define PACKET_READ(packet, conn) ((packet)->header.m->read_from_net((packet), (conn) TSRMLS_CC)) #define PACKET_FREE(packet) \ @@ -51,15 +44,6 @@ extern char * mysqlnd_read_body_name; ((packet)->header.m->free_mem((packet), FALSE TSRMLS_CC)); \ } while (0); -#define PACKET_INIT_ALLOCA(packet, enum_type) \ - { \ - memset(&(packet), 0, packet_methods[enum_type].struct_size); \ - (packet).header.m = &packet_methods[enum_type]; \ - } -#define PACKET_WRITE_ALLOCA(packet, conn) PACKET_WRITE(&(packet), (conn)) -#define PACKET_READ_ALLOCA(packet, conn) PACKET_READ(&(packet), (conn)) -#define PACKET_FREE_ALLOCA(packet) (packet.header.m->free_mem(&(packet), TRUE TSRMLS_CC)) - extern const char * const mysqlnd_command_to_text[COM_END]; /* Low-level extraction functionality */ @@ -285,6 +269,11 @@ void php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zend_bool as_unicode, zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC); + +MYSQLND_PROTOCOL * mysqlnd_protocol_init(zend_bool persistent TSRMLS_DC); +void mysqlnd_protocol_free(MYSQLND_PROTOCOL * net TSRMLS_DC); + + #endif /* MYSQLND_WIREPROTOCOL_H */ /* |