Commit:    1ff43522630f0f98c20e884890f77e6593a43f3b
Author:    Andrey Hristov <and...@php.net>         Tue, 15 Jan 2013 10:04:59 
+0100
Parents:   be07f815f240803fe7a48a5fb3d68a169bef4707
Branches:  PHP-5.5 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=1ff43522630f0f98c20e884890f77e6593a43f3b

Log:
Add support for connect attributes, as of MySQL 5.6

Changed paths:
  M  ext/mysqlnd/mysqlnd.c
  M  ext/mysqlnd/mysqlnd.h
  M  ext/mysqlnd/mysqlnd_auth.c
  M  ext/mysqlnd/mysqlnd_enum_n_def.h
  M  ext/mysqlnd/mysqlnd_libmysql_compat.h
  M  ext/mysqlnd/mysqlnd_structs.h
  M  ext/mysqlnd/mysqlnd_wireprotocol.c
  M  ext/mysqlnd/mysqlnd_wireprotocol.h

diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c
index ebc4a77..1023b3e 100644
--- a/ext/mysqlnd/mysqlnd.c
+++ b/ext/mysqlnd/mysqlnd.c
@@ -95,6 +95,11 @@ MYSQLND_METHOD(mysqlnd_conn_data, 
free_options)(MYSQLND_CONN_DATA * conn TSRMLS_
                mnd_pefree(conn->options->cfg_section, pers);
                conn->options->cfg_section = NULL;
        }
+       if (conn->options->connect_attr) {
+               zend_hash_destroy(conn->options->connect_attr);
+               mnd_pefree(conn->options->connect_attr, pers);
+               conn->options->connect_attr = NULL;
+       }
 }
 /* }}} */
 
@@ -797,13 +802,14 @@ MYSQLND_METHOD(mysqlnd_conn_data, 
connect_handshake)(MYSQLND_CONN_DATA * conn,
                goto err;
        }
 
+       conn->client_flag                       = mysql_flags;
+       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 TSRMLS_CC))
        {
                goto err;
        }
-       conn->client_flag                       = mysql_flags;
-       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->affected_rows = 0;
@@ -811,6 +817,8 @@ MYSQLND_METHOD(mysqlnd_conn_data, 
connect_handshake)(MYSQLND_CONN_DATA * conn,
        PACKET_FREE(greet_packet);
        DBG_RETURN(PASS);
 err:
+       conn->client_flag = 0;
+       conn->server_capabilities = 0;
        PACKET_FREE(greet_packet);
        DBG_RETURN(FAIL);
 }
@@ -1086,6 +1094,7 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * 
conn_handle,
        DBG_ENTER("mysqlnd_conn::connect");
 
        if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+               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 TSRMLS_CC);
 
                conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC);
@@ -2375,6 +2384,19 @@ MYSQLND_METHOD(mysqlnd_conn_data, 
set_client_option)(MYSQLND_CONN_DATA * const c
                                conn->options->flags &= 
~CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS;
                        }
                        break;
+               case MYSQL_OPT_CONNECT_ATTR_RESET:
+                       if (conn->options->connect_attr) {
+                               DBG_INF_FMT("Before reset %d attribute(s)", 
zend_hash_num_elements(conn->options->connect_attr));
+                               zend_hash_clean(conn->options->connect_attr);
+                       }
+                       break;
+               case MYSQL_OPT_CONNECT_ATTR_DELETE:
+                       if (conn->options->connect_attr && value) {
+                               DBG_INF_FMT("Before delete %d attribute(s)", 
zend_hash_num_elements(conn->options->connect_attr));
+                               zend_hash_del(conn->options->connect_attr, 
value, strlen(value));
+                               DBG_INF_FMT("%d left", 
zend_hash_num_elements(conn->options->connect_attr));
+                       }
+                       break;
 #ifdef WHEN_SUPPORTED_BY_MYSQLI
                case MYSQL_SHARED_MEMORY_BASE_NAME:
                case MYSQL_OPT_USE_RESULT:
@@ -2395,6 +2417,69 @@ end:
 /* }}} */
 
 
+/* {{{ connect_attr_item_dtor */
+static void
+connect_attr_item_dtor(void * pDest)
+{
+#ifdef ZTS
+       TSRMLS_FETCH();
+#endif
+       DBG_ENTER("connect_attr_item_dtor");
+       mnd_pefree(*(char **) pDest, 1);
+       DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_conn_data::set_client_option_2d */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d)(MYSQLND_CONN_DATA * 
const conn,
+                                                                               
                                enum mysqlnd_option option,
+                                                                               
                                const char * const key,
+                                                                               
                                const char * const value
+                                                                               
                                TSRMLS_DC)
+{
+       size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, 
set_client_option_2d);
+       enum_func_status ret = PASS;
+       DBG_ENTER("mysqlnd_conn_data::set_client_option_2d");
+       DBG_INF_FMT("conn=%llu option=%u", conn->thread_id, option);
+
+       if (PASS != conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+               goto end;
+       }
+       switch (option) {
+               case MYSQL_OPT_CONNECT_ATTR_ADD:
+                       if (!conn->options->connect_attr) {
+                               DBG_INF("Initializing connect_attr hash");
+                               conn->options->connect_attr = 
mnd_pemalloc(sizeof(HashTable), conn->persistent);
+                               if (!conn->options->connect_attr) {
+                                       goto oom;
+                               }
+                               zend_hash_init(conn->options->connect_attr, 0, 
NULL, NULL, conn->persistent);
+                       }
+                       DBG_INF_FMT("Adding [%s][%s]", key, value);
+                       {
+                               const char * copyv = mnd_pestrdup(value, 1);
+                               if (!copyv) {
+                                       goto oom;
+                               }
+                               zend_hash_update(conn->options->connect_attr, 
key, strlen(key), &copyv, sizeof(char *), NULL);
+                       }
+                       break;
+               default:
+                       ret = FAIL;
+       }
+       conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);  
+       DBG_RETURN(ret);
+oom:
+       SET_OOM_ERROR(*conn->error_info);
+       conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC); 
+end:
+       DBG_RETURN(FAIL);
+}
+/* }}} */
+
+
 /* {{{ mysqlnd_conn_data::use_result */
 static MYSQLND_RES *
 MYSQLND_METHOD(mysqlnd_conn_data, use_result)(MYSQLND_CONN_DATA * const conn 
TSRMLS_DC)
@@ -2662,7 +2747,9 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
        MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags),
        MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake),
        MYSQLND_METHOD(mysqlnd_conn_data, simple_command_send_request),
-       MYSQLND_METHOD(mysqlnd_conn_data, fetch_auth_plugin_by_name)    
+       MYSQLND_METHOD(mysqlnd_conn_data, fetch_auth_plugin_by_name),
+
+       MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d)
 MYSQLND_CLASS_METHODS_END;
 
 
diff --git a/ext/mysqlnd/mysqlnd.h b/ext/mysqlnd/mysqlnd.h
index 7e02126..bf0f70b 100644
--- a/ext/mysqlnd/mysqlnd.h
+++ b/ext/mysqlnd/mysqlnd.h
@@ -207,6 +207,7 @@ PHPAPI void 
mysqlnd_set_local_infile_handler(MYSQLND_CONN_DATA * const conn, con
 #define mysqlnd_set_character_set(conn, cs)    
((conn)->data)->m->set_charset((conn)->data, (cs) TSRMLS_CC)
 #define mysqlnd_stat(conn, msg, msg_len)       
((conn)->data)->m->get_server_statistics(((conn)->data), (msg), (msg_len) 
TSRMLS_CC)
 #define mysqlnd_options(conn, opt, value)      
((conn)->data)->m->set_client_option((conn)->data, (opt), (value) TSRMLS_CC)
+#define mysqlnd_options4(conn, opt, k, v)      
((conn)->data)->m->set_client_option_2d((conn)->data, (opt), (k), (v) TSRMLS_CC)
 #define mysqlnd_set_server_option(conn, op)    
((conn)->data)->m->set_server_option((conn)->data, (op) TSRMLS_CC)
 
 /* Escaping */
diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c
index a3b4f36..8611d99 100644
--- a/ext/mysqlnd/mysqlnd_auth.c
+++ b/ext/mysqlnd/mysqlnd_auth.c
@@ -28,7 +28,6 @@
 #include "mysqlnd_charset.h"
 #include "mysqlnd_debug.h"
 
-
 /* {{{ mysqlnd_auth_handshake */
 enum_func_status
 mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
@@ -99,6 +98,10 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
                auth_packet->auth_data = auth_plugin_data;
                auth_packet->auth_data_len = auth_plugin_data_len;
                auth_packet->auth_plugin_name = auth_protocol;
+               
+               if (conn->server_capabilities & CLIENT_CONNECT_ATTRS) {
+                       auth_packet->connect_attr = conn->options->connect_attr;
+               }
 
                if (!PACKET_WRITE(auth_packet, conn)) {
                        goto end;
diff --git a/ext/mysqlnd/mysqlnd_enum_n_def.h b/ext/mysqlnd/mysqlnd_enum_n_def.h
index abaaf1f..cf5b027 100644
--- a/ext/mysqlnd/mysqlnd_enum_n_def.h
+++ b/ext/mysqlnd/mysqlnd_enum_n_def.h
@@ -168,6 +168,9 @@ typedef enum mysqlnd_option
        MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
        MYSQL_PLUGIN_DIR,
        MYSQL_DEFAULT_AUTH,
+       MYSQL_OPT_CONNECT_ATTR_RESET,
+       MYSQL_OPT_CONNECT_ATTR_ADD,
+       MYSQL_OPT_CONNECT_ATTR_DELETE,
        MYSQL_SERVER_PUBLIC_KEY,
        MYSQL_ENABLE_CLEARTEXT_PLUGIN,
        MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
diff --git a/ext/mysqlnd/mysqlnd_libmysql_compat.h 
b/ext/mysqlnd/mysqlnd_libmysql_compat.h
index c967fb3..e3ab9ee 100644
--- a/ext/mysqlnd/mysqlnd_libmysql_compat.h
+++ b/ext/mysqlnd/mysqlnd_libmysql_compat.h
@@ -106,7 +106,8 @@
 #define mysql_stmt_more_results(s)             mysqlnd_stmt_more_results((s))
 #define mysql_thread_safe()                            mysqlnd_thread_safe()
 #define mysql_info(r)                                  mysqlnd_info((r))
-#define mysql_options(r,a,b)                   mysqlnd_options((r), (a), (b))
+#define mysql_options(c,a,v)                   mysqlnd_options((c), (a), (v))
+#define mysql_options4(c,a,k,v)                        mysqlnd_options4((c), 
(a), (k), (v))
 #define mysql_stmt_init(r)                             mysqlnd_stmt_init((r))
 #define mysql_free_result(r)                   mysqlnd_free_result((r), FALSE)
 #define mysql_store_result(r)                  mysqlnd_store_result((r))
diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h
index 6302c81..ecb1d89 100644
--- a/ext/mysqlnd/mysqlnd_structs.h
+++ b/ext/mysqlnd/mysqlnd_structs.h
@@ -172,7 +172,7 @@ typedef struct st_mysqlnd_options
          The ABI will be broken and the methods structure will be somewhere 
else
          in the memory which can crash external code. Feel free to reuse these.
        */
-       char            * unused2;
+       HashTable       * connect_attr;
        char            * unused3;
        char            * unused4;
        char            * unused5;
@@ -489,6 +489,8 @@ typedef enum_func_status    
(*func_mysqlnd_conn_data__connect_handshake)(MYSQLND_CO
 typedef enum_func_status       
(*func_mysqlnd_conn_data__simple_command_send_request)(MYSQLND_CONN_DATA * 
conn, enum php_mysqlnd_server_command command, const zend_uchar * const arg, 
size_t arg_len, zend_bool silent, zend_bool ignore_upsert_status TSRMLS_DC);
 typedef struct st_mysqlnd_authentication_plugin * 
(*func_mysqlnd_conn_data__fetch_auth_plugin_by_name)(const char * const 
requested_protocol TSRMLS_DC);
 
+typedef enum_func_status       
(*func_mysqlnd_conn_data__set_client_option_2d)(MYSQLND_CONN_DATA * const conn, 
enum mysqlnd_option option, const char * const key, const char * const value 
TSRMLS_DC);
+
 struct st_mysqlnd_conn_data_methods
 {
        func_mysqlnd_conn_data__init init;
@@ -573,6 +575,8 @@ struct st_mysqlnd_conn_data_methods
        func_mysqlnd_conn_data__connect_handshake connect_handshake;
        func_mysqlnd_conn_data__simple_command_send_request 
simple_command_send_request;
        func_mysqlnd_conn_data__fetch_auth_plugin_by_name 
fetch_auth_plugin_by_name;
+
+       func_mysqlnd_conn_data__set_client_option_2d set_client_option_2d;
 };
 
 
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c 
b/ext/mysqlnd/mysqlnd_wireprotocol.c
index 7c3bf13..6699707 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
@@ -212,6 +212,24 @@ php_mysqlnd_net_store_length(zend_uchar *packet, uint64_t 
length)
 /* }}} */
 
 
+/* {{{ php_mysqlnd_net_store_length_size */
+size_t 
+php_mysqlnd_net_store_length_size(uint64_t length)
+{
+       if (length < (uint64_t) L64(251)) {
+               return 1;
+       }
+       if (length < (uint64_t) L64(65536)) {
+               return 3;
+       }
+       if (length < (uint64_t) L64(16777216)) {
+               return 4;
+       }
+       return 8;
+}
+/* }}} */
+
+
 /* {{{ php_mysqlnd_read_error_from_line */
 static enum_func_status
 php_mysqlnd_read_error_from_line(zend_uchar *buf, size_t buf_len,
@@ -459,7 +477,7 @@ void php_mysqlnd_greet_free_mem(void * _packet, zend_bool 
stack_allocation TSRML
 /* }}} */
 
 
-#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + 
MYSQLND_MAX_ALLOWED_USER_LEN + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 
+ 1024)
+#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + 
MYSQLND_MAX_ALLOWED_USER_LEN + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 
+ 4096)
 
 /* {{{ php_mysqlnd_auth_write */
 static
@@ -540,6 +558,52 @@ size_t php_mysqlnd_auth_write(void * _packet, 
MYSQLND_CONN_DATA * conn TSRMLS_DC
                        p+= len;
                        *p++= '\0';
                }
+
+               if (packet->connect_attr && 
zend_hash_num_elements(packet->connect_attr)) {
+                       HashPosition pos_value;
+                       const char ** entry_value;
+                       size_t ca_payload_len = 0;
+                       
zend_hash_internal_pointer_reset_ex(packet->connect_attr, &pos_value);
+                       while (SUCCESS == 
zend_hash_get_current_data_ex(packet->connect_attr, (void **)&entry_value, 
&pos_value)) {
+                               char *s_key;
+                               unsigned int s_len;
+                               unsigned long num_key;
+                               size_t value_len = strlen(*entry_value);
+                               
+                               if (HASH_KEY_IS_STRING == 
zend_hash_get_current_key_ex(packet->connect_attr, &s_key, &s_len, &num_key, 0, 
&pos_value)) {
+                                       ca_payload_len += 
php_mysqlnd_net_store_length_size(s_len);
+                                       ca_payload_len += s_len;
+                                       ca_payload_len += 
php_mysqlnd_net_store_length_size(value_len);
+                                       ca_payload_len += value_len;
+                               }
+                               
zend_hash_move_forward_ex(conn->options->connect_attr, &pos_value);
+                       }
+
+                       if ((sizeof(buffer) - (p - buffer)) >= (ca_payload_len 
+ php_mysqlnd_net_store_length_size(ca_payload_len))) {
+                               p = php_mysqlnd_net_store_length(p, 
ca_payload_len);
+
+                               
zend_hash_internal_pointer_reset_ex(packet->connect_attr, &pos_value);
+                               while (SUCCESS == 
zend_hash_get_current_data_ex(packet->connect_attr, (void **)&entry_value, 
&pos_value)) {
+                                       char *s_key;
+                                       unsigned int s_len;
+                                       unsigned long num_key;
+                                       size_t value_len = strlen(*entry_value);
+                                       if (HASH_KEY_IS_STRING == 
zend_hash_get_current_key_ex(packet->connect_attr, &s_key, &s_len, &num_key, 0, 
&pos_value)) {
+                                               /* copy key */
+                                               p = 
php_mysqlnd_net_store_length(p, s_len);
+                                               memcpy(p, s_key, s_len);
+                                               p+= s_len;
+                                               /* copy value */
+                                               p = 
php_mysqlnd_net_store_length(p, value_len);
+                                               memcpy(p, *entry_value, 
value_len);
+                                               p+= value_len;
+                                       }
+                                       
zend_hash_move_forward_ex(conn->options->connect_attr, &pos_value);
+                               }
+                       } else {
+                               /* cannot put the data - skip */
+                       }
+               }
        }
        if (packet->is_change_user_packet) {
                if (PASS != conn->m->simple_command(conn, COM_CHANGE_USER, 
buffer + MYSQLND_HEADER_SIZE, p - buffer - MYSQLND_HEADER_SIZE,
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.h 
b/ext/mysqlnd/mysqlnd_wireprotocol.h
index e9c9024..26dd4c6 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.h
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.h
@@ -103,7 +103,7 @@ typedef struct st_mysqlnd_packet_auth {
        zend_bool       send_auth_data;
        zend_bool       is_change_user_packet;
        zend_bool       silent;
-
+       HashTable       *connect_attr;
 } MYSQLND_PACKET_AUTH;
 
 /* Auth response packet */
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to