summaryrefslogtreecommitdiff
path: root/ext/mysqlnd/mysqlnd.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mysqlnd/mysqlnd.c')
-rw-r--r--ext/mysqlnd/mysqlnd.c173
1 files changed, 85 insertions, 88 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);