mnd_pefree(conn->host_info, pers);
conn->host_info = NULL;
}
- if (conn->auth_plugin_data) {
- mnd_pefree(conn->auth_plugin_data, pers);
- conn->auth_plugin_data = NULL;
+ if (conn->authentication_plugin_data.s) {
+ mnd_pefree(conn->authentication_plugin_data.s, pers);
+ conn->authentication_plugin_data.s = NULL;
}
if (conn->last_message.s) {
mnd_pefree(conn->last_message.s, pers);
static enum_func_status
mysqlnd_switch_to_ssl_if_needed(
MYSQLND_CONN_DATA * conn,
- const MYSQLND_PACKET_GREET * const greet_packet,
+ unsigned int charset_no,
+ size_t server_capabilities,
const MYSQLND_SESSION_OPTIONS * const session_options,
zend_ulong mysql_flags)
{
enum_func_status ret = FAIL;
const MYSQLND_CHARSET * charset;
- unsigned int charset_no;
DBG_ENTER("mysqlnd_switch_to_ssl_if_needed");
if (session_options->charset_name && (charset = mysqlnd_find_charset_name(session_options->charset_name))) {
charset_no = charset->nr;
- } else {
- charset_no = greet_packet->charset_no;
}
{
size_t client_capabilities = mysql_flags;
- size_t server_capabilities = greet_packet->server_capabilities;
struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_ENABLE_SSL, conn, client_capabilities, server_capabilities, charset_no);
if (command) {
ret = command->run(command);
const size_t passwd_len,
const char * const db,
const size_t db_len,
- const zend_uchar * const auth_plugin_data,
- const size_t auth_plugin_data_len,
+ const MYSQLND_STRING auth_plugin_data,
const char * const auth_protocol,
unsigned int charset_no,
const MYSQLND_SESSION_OPTIONS * const session_options,
DBG_ENTER("mysqlnd_run_authentication");
- plugin_data_len = auth_plugin_data_len;
+ plugin_data_len = auth_plugin_data.l;
plugin_data = mnd_emalloc(plugin_data_len + 1);
if (!plugin_data) {
goto end;
}
- memcpy(plugin_data, auth_plugin_data, plugin_data_len);
+ memcpy(plugin_data, auth_plugin_data.s, plugin_data_len);
plugin_data[plugin_data_len] = '\0';
requested_protocol = mnd_pestrdup(auth_protocol? auth_protocol : MYSQLND_DEFAULT_AUTH_PROTOCOL, FALSE);
switch_to_auth_protocol = NULL;
switch_to_auth_protocol_len = 0;
- if (conn->auth_plugin_data) {
- mnd_pefree(conn->auth_plugin_data, conn->persistent);
- conn->auth_plugin_data = NULL;
+ if (conn->authentication_plugin_data.s) {
+ mnd_pefree(conn->authentication_plugin_data.s, conn->persistent);
+ conn->authentication_plugin_data.s = NULL;
}
- conn->auth_plugin_data_len = plugin_data_len;
- conn->auth_plugin_data = mnd_pemalloc(conn->auth_plugin_data_len, conn->persistent);
- if (!conn->auth_plugin_data) {
+ conn->authentication_plugin_data.l = plugin_data_len;
+ conn->authentication_plugin_data.s = mnd_pemalloc(conn->authentication_plugin_data.l, conn->persistent);
+ if (!conn->authentication_plugin_data.s) {
SET_OOM_ERROR(conn->error_info);
goto end;
}
- memcpy(conn->auth_plugin_data, plugin_data, plugin_data_len);
+ memcpy(conn->authentication_plugin_data.s, plugin_data, plugin_data_len);
DBG_INF_FMT("salt(%d)=[%.*s]", plugin_data_len, plugin_data_len, plugin_data);
/* The data should be allocated with malloc() */
/* {{{ mysqlnd_connect_run_authentication */
-static enum_func_status
+enum_func_status
mysqlnd_connect_run_authentication(
MYSQLND_CONN_DATA * conn,
const char * const user,
const char * const db,
size_t db_len,
size_t passwd_len,
- const MYSQLND_PACKET_GREET * const greet_packet,
+ MYSQLND_STRING authentication_plugin_data,
+ const char * const authentication_protocol,
+ const unsigned int charset_no,
+ size_t server_capabilities,
const MYSQLND_SESSION_OPTIONS * const session_options,
zend_ulong mysql_flags
)
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_connect_run_authentication");
- ret = mysqlnd_switch_to_ssl_if_needed(conn, greet_packet, session_options, mysql_flags);
+ ret = mysqlnd_switch_to_ssl_if_needed(conn, charset_no, server_capabilities, session_options, mysql_flags);
if (PASS == ret) {
ret = mysqlnd_run_authentication(conn, user, passwd, passwd_len, db, db_len,
- greet_packet->auth_plugin_data, greet_packet->auth_plugin_data_len, greet_packet->auth_protocol,
- greet_packet->charset_no, session_options, mysql_flags, FALSE /*silent*/, FALSE/*is_change*/);
+ authentication_plugin_data, authentication_protocol,
+ charset_no, session_options, mysql_flags, FALSE /*silent*/, FALSE/*is_change*/);
}
DBG_RETURN(ret);
}
/* {{{ mysqlnd_conn_data::connect_handshake */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn,
- const char * const host, const char * const user,
- const char * const passwd, const unsigned int passwd_len,
- const char * const db, const unsigned int db_len,
+ const MYSQLND_CSTRING * const username,
+ const MYSQLND_CSTRING * const password,
+ const MYSQLND_CSTRING * const database,
const unsigned int mysql_flags)
{
- MYSQLND_PACKET_GREET * greet_packet;
- MYSQLND_NET * net = conn->net;
-
+ enum_func_status ret = FAIL;
+ size_t client_flags = mysql_flags;
DBG_ENTER("mysqlnd_conn_data::connect_handshake");
- greet_packet = conn->payload_decoder_factory->m.get_greet_packet(conn->payload_decoder_factory, FALSE);
- if (!greet_packet) {
- SET_OOM_ERROR(conn->error_info);
- DBG_RETURN(FAIL); /* OOM */
- }
-
- if (FAIL == net->data->m.connect_ex(conn->net, conn->scheme, conn->persistent,
- conn->stats, conn->error_info))
- {
- goto err;
- }
-
- DBG_INF_FMT("stream=%p", net->data->m.get_stream(net));
-
- if (FAIL == PACKET_READ(greet_packet)) {
- DBG_ERR("Error while reading greeting packet");
- php_error_docref(NULL, E_WARNING, "Error while reading greeting packet. PID=%d", getpid());
- goto err;
- } else if (greet_packet->error_no) {
- DBG_ERR_FMT("errorno=%u 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);
- php_error_docref(NULL, E_WARNING, "Connecting to 3.22, 3.23 & 4.0 "
- " 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 = mnd_pestrdup(greet_packet->server_version, conn->persistent);
-
- conn->greet_charset = mysqlnd_find_charset_nr(greet_packet->charset_no);
- if (!conn->greet_charset) {
- php_error_docref(NULL, E_WARNING,
- "Server sent charset (%d) unknown to the client. Please, report to the developers", greet_packet->charset_no);
- SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
- "Server sent charset unknown to the client. Please, report to the developers");
- goto err;
- }
-
- conn->server_capabilities = greet_packet->server_capabilities;
-
- if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len,
- greet_packet, conn->options, mysql_flags))
- {
- goto err;
+ if (FAIL == conn->net->data->m.connect_ex(conn->net, conn->scheme, conn->persistent, conn->stats, conn->error_info)) {
+ DBG_RETURN(FAIL);
+ } else {
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_HANDSHAKE, conn, username, password, database, client_flags);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ }
}
-
- UPSERT_STATUS_RESET(conn->upsert_status);
- UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, greet_packet->server_status);
-
- PACKET_FREE(greet_packet);
- DBG_RETURN(PASS);
-err:
- conn->server_capabilities = 0;
- PACKET_FREE(greet_packet);
- DBG_RETURN(FAIL);
+ DBG_RETURN(ret);
}
/* }}} */
/* {{{ mysqlnd_conn_data::connect */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
- const char *host, const char *user,
- const char *passwd, unsigned int passwd_len,
- const char *db, unsigned int db_len,
- unsigned int port,
- const char *socket_or_pipe,
- unsigned int mysql_flags
- )
+ MYSQLND_CSTRING hostname,
+ MYSQLND_CSTRING username,
+ MYSQLND_CSTRING password,
+ MYSQLND_CSTRING database,
+ unsigned int port,
+ MYSQLND_CSTRING socket_or_pipe,
+ unsigned int mysql_flags
+ )
{
const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), connect);
- size_t host_len;
zend_bool unix_socket = FALSE;
zend_bool named_pipe = FALSE;
zend_bool reconnect = FALSE;
UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u persistent=%u state=%u",
- host?host:"", user?user:"", db?db:"", port, mysql_flags,
+ hostname.s?hostname.s:"", username.s?username.s:"", database.s?database.s:"", port, mysql_flags,
conn? conn->persistent:0, conn? GET_CONNECTION_STATE(&conn->state):-1);
if (GET_CONNECTION_STATE(&conn->state) > CONN_ALLOCED && GET_CONNECTION_STATE(&conn->state) ) {
conn->m->set_client_option(conn, MYSQLND_OPT_MAX_ALLOWED_PACKET, (char *)&max_allowed_size);
}
- if (!host || !host[0]) {
- host = "localhost";
+ if (!hostname.s || !hostname.s[0]) {
+ hostname.s = "localhost";
+ hostname.l = strlen(hostname.s);
}
- if (!user) {
+ if (!username.s) {
DBG_INF_FMT("no user given, using empty string");
- user = "";
+ username.s = "";
+ username.l = 0;
}
- if (!passwd) {
+ if (!password.s) {
DBG_INF_FMT("no password given, using empty string");
- passwd = "";
- passwd_len = 0;
+ password.s = "";
+ password.l = 0;
}
- if (!db) {
+ if (!database.s) {
DBG_INF_FMT("no db given, using empty string");
- db = "";
- db_len = 0;
+ database.s = "";
+ database.l = 0;
} else {
mysql_flags |= CLIENT_CONNECT_WITH_DB;
}
- host_len = strlen(host);
{
char * transport = NULL;
int transport_len;
#ifndef PHP_WIN32
- if (host_len == sizeof("localhost") - 1 && !strncasecmp(host, "localhost", host_len)) {
- DBG_INF_FMT("socket=%s", socket_or_pipe? socket_or_pipe:"n/a");
- if (!socket_or_pipe) {
- socket_or_pipe = "/tmp/mysql.sock";
+ if (hostname.l == sizeof("localhost") - 1 && !strncasecmp(hostname.s, "localhost", hostname.l)) {
+ DBG_INF_FMT("socket=%s", socket_or_pipe.s? socket_or_pipe.s:"n/a");
+ if (!socket_or_pipe.s) {
+ socket_or_pipe.s = "/tmp/mysql.sock";
+ socket_or_pipe.l = strlen(socket_or_pipe.s);
}
- transport_len = mnd_sprintf(&transport, 0, "unix://%s", socket_or_pipe);
+ transport_len = mnd_sprintf(&transport, 0, "unix://%s", socket_or_pipe.s);
unix_socket = TRUE;
#else
- if (host_len == sizeof(".") - 1 && host[0] == '.') {
+ if (hostname.l == sizeof(".") - 1 && hostname.s[0] == '.') {
/* named pipe in socket */
- if (!socket_or_pipe) {
- socket_or_pipe = "\\\\.\\pipe\\MySQL";
+ if (!socket_or_pipe.s) {
+ socket_or_pipe.s = "\\\\.\\pipe\\MySQL";
+ socket_or_pipe.l = strlen(socket_or_pipe.s);
}
- transport_len = mnd_sprintf(&transport, 0, "pipe://%s", socket_or_pipe);
+ transport_len = mnd_sprintf(&transport, 0, "pipe://%s", socket_or_pipe.s);
named_pipe = TRUE;
#endif
} else {
if (!port) {
port = 3306;
}
- transport_len = mnd_sprintf(&transport, 0, "tcp://%s:%u", host, port);
+ transport_len = mnd_sprintf(&transport, 0, "tcp://%s:%u", hostname.s, port);
}
if (!transport) {
SET_OOM_ERROR(conn->error_info);
mysql_flags = conn->m->get_updated_connect_flags(conn, mysql_flags);
- if (FAIL == conn->m->connect_handshake(conn, host, user, passwd, passwd_len, db, db_len, mysql_flags)) {
- goto err;
+ {
+
+ if (FAIL == conn->m->connect_handshake(conn, &username, &password, &database, mysql_flags)) {
+ goto err;
+ }
}
{
*/
net->data->compressed = mysql_flags & CLIENT_COMPRESS? TRUE:FALSE;
- conn->user_len = strlen(user);
- conn->user = mnd_pestrndup(user, conn->user_len, conn->persistent);
- conn->passwd = mnd_pestrndup(passwd, passwd_len, conn->persistent);
- conn->passwd_len = passwd_len;
+ conn->user_len = username.l;
+ conn->user = mnd_pestrndup(username.s, conn->user_len, conn->persistent);
+ conn->passwd = mnd_pestrndup(password.s, password.l, conn->persistent);
+ conn->passwd_len = password.l;
conn->port = port;
- conn->connect_or_select_db.s = mnd_pestrndup(db, db_len, conn->persistent);
- conn->connect_or_select_db.l = db_len;
+ conn->connect_or_select_db.s = mnd_pestrndup(database.s, database.l, conn->persistent);
+ conn->connect_or_select_db.l = database.l;
if (!conn->user || !conn->passwd || !conn->connect_or_select_db.s) {
SET_OOM_ERROR(conn->error_info);
}
if (!unix_socket && !named_pipe) {
- conn->host = mnd_pestrndup(host, host_len, conn->persistent);
+ conn->host = mnd_pestrndup(hostname.s, hostname.l, conn->persistent);
if (!conn->host) {
SET_OOM_ERROR(conn->error_info);
goto err; /* OOM */
}
- conn->host_len = host_len;
+ conn->host_len = hostname.l;
{
char *p;
mnd_sprintf(&p, 0, "%s via TCP/IP", conn->host);
}
}
} else {
- conn->unix_socket = mnd_pestrdup(socket_or_pipe, conn->persistent);
+ conn->unix_socket = mnd_pestrdup(socket_or_pipe.s, conn->persistent);
if (unix_socket) {
conn->host_info = mnd_pestrdup("Localhost via UNIX socket", conn->persistent);
} else if (named_pipe) {
/* {{{ mysqlnd_conn::connect */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn_handle,
- const char * host, const char * user,
- const char * passwd, unsigned int passwd_len,
- const char * db, unsigned int db_len,
- unsigned int port,
- const char * socket_or_pipe,
- unsigned int mysql_flags
+ const MYSQLND_CSTRING hostname,
+ const MYSQLND_CSTRING username,
+ const MYSQLND_CSTRING password,
+ const MYSQLND_CSTRING database,
+ unsigned int port,
+ const MYSQLND_CSTRING socket_or_pipe,
+ unsigned int mysql_flags
)
{
const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), connect);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
mysqlnd_options4(conn_handle, MYSQL_OPT_CONNECT_ATTR_ADD, "_client_name", "mysqlnd");
- ret = conn->m->connect(conn, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags);
+ ret = conn->m->connect(conn, hostname, username, password, database, port, socket_or_pipe, mysql_flags);
conn->m->local_tx_end(conn, this_func, FAIL);
}
/* {{{ mysqlnd_connect */
PHPAPI MYSQLND * mysqlnd_connection_connect(MYSQLND * conn_handle,
- const char * host, const char * user,
- const char * passwd, unsigned int passwd_len,
- const char * db, unsigned int db_len,
+ const char * const host,
+ const char * const user,
+ const char * const passwd, unsigned int passwd_len,
+ const char * const db, unsigned int db_len,
unsigned int port,
- const char * socket_or_pipe,
+ const char * const sock_or_pipe,
unsigned int mysql_flags,
unsigned int client_api_flags
)
{
enum_func_status ret = FAIL;
zend_bool self_alloced = FALSE;
+ MYSQLND_CSTRING hostname = { host, host? strlen(host) : 0 };
+ MYSQLND_CSTRING username = { user, user? strlen(user) : 0 };
+ MYSQLND_CSTRING password = { passwd, passwd_len };
+ MYSQLND_CSTRING database = { db, db_len };
+ MYSQLND_CSTRING socket_or_pipe = { sock_or_pipe, sock_or_pipe? strlen(sock_or_pipe) : 0 };
DBG_ENTER("mysqlnd_connect");
- DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u", host?host:"", user?user:"", db?db:"", port, mysql_flags);
+ DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u", host? host:"", user? user:"", db? db:"", port, mysql_flags);
if (!conn_handle) {
self_alloced = TRUE;
}
}
- ret = conn_handle->m->connect(conn_handle, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags);
+ ret = conn_handle->m->connect(conn_handle, hostname, username, password, database, port, socket_or_pipe, mysql_flags);
if (ret == FAIL) {
if (self_alloced) {
/* XXX: passwords that have \0 inside work during auth, but in this case won't work with change user */
ret = mysqlnd_run_authentication(conn, user, passwd, passwd_len, db, strlen(db),
- conn->auth_plugin_data, conn->auth_plugin_data_len, conn->options->auth_protocol,
+ conn->authentication_plugin_data, conn->options->auth_protocol,
0 /*charset not used*/, conn->options, conn->server_capabilities, silent, TRUE/*is_change*/);
/*
}
BAIL_IF_NO_MORE_DATA;
- packet->auth_plugin_data = packet->intern_auth_plugin_data;
- packet->auth_plugin_data_len = sizeof(packet->intern_auth_plugin_data);
+ packet->authentication_plugin_data.s = packet->intern_auth_plugin_data;
+ packet->authentication_plugin_data.l = sizeof(packet->intern_auth_plugin_data);
if (packet->header.size < sizeof(buf)) {
/*
p+=4;
BAIL_IF_NO_MORE_DATA;
- memcpy(packet->auth_plugin_data, p, SCRAMBLE_LENGTH_323);
+ memcpy(packet->authentication_plugin_data.s, p, SCRAMBLE_LENGTH_323);
p+= SCRAMBLE_LENGTH_323;
BAIL_IF_NO_MORE_DATA;
if ((size_t) (p - buf) < packet->header.size) {
/* auth_plugin_data is split into two parts */
- memcpy(packet->auth_plugin_data + SCRAMBLE_LENGTH_323, p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
+ memcpy(packet->authentication_plugin_data.s + SCRAMBLE_LENGTH_323, p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
p+= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
p++; /* 0x0 at the end of the scramble and thus last byte in the packet in 5.1 and previous */
} else {
/* Additional 16 bits for server capabilities */
packet->server_capabilities |= uint2korr(pad_start) << 16;
/* And a length of the server scramble in one byte */
- packet->auth_plugin_data_len = uint1korr(pad_start + 2);
- if (packet->auth_plugin_data_len > SCRAMBLE_LENGTH) {
+ packet->authentication_plugin_data.l = uint1korr(pad_start + 2);
+ if (packet->authentication_plugin_data.l > SCRAMBLE_LENGTH) {
/* more data*/
- zend_uchar * new_auth_plugin_data = emalloc(packet->auth_plugin_data_len);
+ char * new_auth_plugin_data = emalloc(packet->authentication_plugin_data.l);
if (!new_auth_plugin_data) {
goto premature_end;
}
/* copy what we already have */
- memcpy(new_auth_plugin_data, packet->auth_plugin_data, SCRAMBLE_LENGTH);
+ memcpy(new_auth_plugin_data, packet->authentication_plugin_data.s, SCRAMBLE_LENGTH);
/* add additional scramble data 5.5+ sent us */
- memcpy(new_auth_plugin_data + SCRAMBLE_LENGTH, p, packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
- p+= (packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
- packet->auth_plugin_data = new_auth_plugin_data;
+ memcpy(new_auth_plugin_data + SCRAMBLE_LENGTH, p, packet->authentication_plugin_data.l - SCRAMBLE_LENGTH);
+ p+= (packet->authentication_plugin_data.l - SCRAMBLE_LENGTH);
+ packet->authentication_plugin_data.s = new_auth_plugin_data;
}
}
DBG_INF_FMT("server_capabilities=%u charset_no=%u server_status=%i auth_protocol=%s scramble_length=%u",
packet->server_capabilities, packet->charset_no, packet->server_status,
- packet->auth_protocol? packet->auth_protocol:"n/a", packet->auth_plugin_data_len);
+ packet->auth_protocol? packet->auth_protocol:"n/a", packet->authentication_plugin_data.l);
DBG_RETURN(PASS);
premature_end:
efree(p->server_version);
p->server_version = NULL;
}
- if (p->auth_plugin_data && p->auth_plugin_data != p->intern_auth_plugin_data) {
- efree(p->auth_plugin_data);
- p->auth_plugin_data = NULL;
+ if (p->authentication_plugin_data.s && p->authentication_plugin_data.s != p->intern_auth_plugin_data) {
+ efree(p->authentication_plugin_data.s);
+ p->authentication_plugin_data.s = NULL;
}
if (p->auth_protocol) {
efree(p->auth_protocol);
cmd_packet->command = command;
if (arg && arg_len) {
- cmd_packet->argument.s = arg;
+ cmd_packet->argument.s = (char *) arg;
cmd_packet->argument.l = arg_len;
}
}
/* }}} */
+/************************** COM_READ_HANDSHAKE ******************************************/
+struct st_mysqlnd_protocol_com_handshake_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_handshake_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ MYSQLND_CSTRING user;
+ MYSQLND_CSTRING passwd;
+ MYSQLND_CSTRING database;
+ size_t client_flags;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_handshake_run */
+static enum_func_status
+mysqlnd_com_handshake_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_handshake_command * command = (struct st_mysqlnd_protocol_com_handshake_command *) cmd;
+ const char * user = command->context.user.s;
+
+ const char * passwd = command->context.passwd.s;
+ size_t passwd_len = command->context.passwd.l;
+
+ const char * db = command->context.database.s;
+ size_t db_len = command->context.database.l;
+
+ size_t mysql_flags = command->context.client_flags;
+
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ MYSQLND_PACKET_GREET * greet_packet;
+
+ DBG_ENTER("mysqlnd_conn_data::connect_handshake");
+ DBG_INF_FMT("stream=%p", conn->net->data->m.get_stream(conn->net));
+ DBG_INF_FMT("[user=%s] [db=%s:%d] [flags=%llu]", user, db, db_len, mysql_flags);
+
+ greet_packet = conn->payload_decoder_factory->m.get_greet_packet(conn->payload_decoder_factory, FALSE);
+ if (!greet_packet) {
+ SET_OOM_ERROR(conn->error_info);
+ DBG_RETURN(FAIL); /* OOM */
+ }
+
+ if (FAIL == PACKET_READ(greet_packet)) {
+ DBG_ERR("Error while reading greeting packet");
+ php_error_docref(NULL, E_WARNING, "Error while reading greeting packet. PID=%d", getpid());
+ goto err;
+ } else if (greet_packet->error_no) {
+ DBG_ERR_FMT("errorno=%u 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);
+ php_error_docref(NULL, E_WARNING, "Connecting to 3.22, 3.23 & 4.0 "
+ " 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 = mnd_pestrdup(greet_packet->server_version, conn->persistent);
+
+ conn->greet_charset = mysqlnd_find_charset_nr(greet_packet->charset_no);
+ if (!conn->greet_charset) {
+ php_error_docref(NULL, E_WARNING,
+ "Server sent charset (%d) unknown to the client. Please, report to the developers", greet_packet->charset_no);
+ SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
+ "Server sent charset unknown to the client. Please, report to the developers");
+ goto err;
+ }
+
+ conn->server_capabilities = greet_packet->server_capabilities;
+
+ if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len,
+ greet_packet->authentication_plugin_data, greet_packet->auth_protocol,
+ greet_packet->charset_no, greet_packet->server_capabilities,
+ conn->options, mysql_flags))
+ {
+ goto err;
+ }
+
+ UPSERT_STATUS_RESET(conn->upsert_status);
+ UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, greet_packet->server_status);
+
+ PACKET_FREE(greet_packet);
+ DBG_RETURN(PASS);
+err:
+ conn->server_capabilities = 0;
+ PACKET_FREE(greet_packet);
+ DBG_RETURN(FAIL);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_handshake_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_handshake_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_handshake_command * command;
+ DBG_ENTER("mysqlnd_com_handshake_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_handshake_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.user = *va_arg(args, const MYSQLND_CSTRING *);
+ command->context.passwd = *va_arg(args, const MYSQLND_CSTRING *);
+ command->context.database = *va_arg(args, const MYSQLND_CSTRING *);
+ command->context.client_flags = va_arg(args, size_t);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_handshake_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
/* {{{ mysqlnd_get_command */
static struct st_mysqlnd_protocol_command *
case COM_ENABLE_SSL:
ret = mysqlnd_com_enable_ssl_create_command(args);
break;
+ case COM_HANDSHAKE:
+ ret = mysqlnd_com_handshake_create_command(args);
+ break;
default:
break;
}