From b821a3b2533c3d8c17cde13a22aa3f1996ce4b5e Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Tue, 26 Nov 2019 13:44:22 +0800 Subject: [PATCH 01/37] adjust design. If redirection is on, ssl is of, no conn will be made, give error. If redirect is on, last msg not available, abort conn. If redirect conn fail, abort whole connect. Rename option enabled to enableRedirect --- Notes.txt | 2 +- README.md | 6 +- mysqlnd_azure.c | 79 +++++++++++++------- mysqlnd_azure.h | 6 +- php_mysqlnd_azure.c | 10 +-- php_mysqlnd_azure.h | 2 +- redirect_cache.c | 12 +-- tests/mysqli_azure_redirection_disabled.phpt | 8 +- tests/mysqli_azure_redirection_enabled.phpt | 8 +- 9 files changed, 77 insertions(+), 56 deletions(-) diff --git a/Notes.txt b/Notes.txt index a8e0f7f..9ac4083 100644 --- a/Notes.txt +++ b/Notes.txt @@ -9,7 +9,7 @@ connection, and use the new one afterward. +---------------------------+ OPTION DESCRIPTION ------------------ ---------------------------------------------------------- -mysqlnd_azure.enabled This option is to control enable or disable mysqlnd_rd. +mysqlnd_azure.enableRedirect This option is to control enable or disable redirection feature of mysqlnd_azure. If this is set to 0, it will not use redirection. (Default: 0) diff --git a/README.md b/README.md index 11b9788..3fd2b06 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ Then you can run **make install** to put the .so to your php so library. However - put mysqlnd_azure.so under extension_dir. - under directory for additional .ini files, you will find the ini files for the common used modules, e.g. 10-mysqlnd.ini for mysqlnd, 20-mysqli.ini for mysqli. Create a new ini file for mysqlnd_azure here. **Make sure the alphabet order of the name is after that of mysqnld**, since the modules are loaded according to the name order of the ini files. E.g. if mysqlnd ini is with name 10-mysqlnd.ini,then name the ini as 20-mysqlnd-azure.ini. In the ini file, add the following two lines: - extension=mysqlnd_azure - - mysqlnd_azure.enabled = on ; you can also set this to off to disable redirection + - mysqlnd_azure.enableRedirect = on ; you can also set this to off to disable redirection ## Step to build on Windows @@ -131,14 +131,14 @@ After this, the code directory should look like C:\php-sdk\phpdev\vc15\x64\php-s - extension=mysqlnd_azure - Under the Module Settings section add: - [mysqlnd_azure] - - mysqlnd_azure.enabled = on + - mysqlnd_azure.enableRedirect = on ## Test * Currently redirection is only possible when the connection is via ssl, and it need that the redirection feature switch is enabled on server side. Following is a snippet to test connection with redirection: ```php - echo "mysqlnd_azure.enabled: ", ini_get("mysqlnd_azure.enabled") == true?"On":"Off", "\n"; + echo "mysqlnd_azure.enableRedirect: ", ini_get("mysqlnd_azure.enableRedirect") == true?"On":"Off", "\n"; $db = mysqli_init(); $link = mysqli_real_connect ($db, 'your-hostname-with-redirection-enabled', 'user@host', 'password', "db", 3306, NULL, MYSQLI_CLIENT_SSL); if (!$link) { diff --git a/mysqlnd_azure.c b/mysqlnd_azure.c index 5c75cbd..e10c11e 100644 --- a/mysqlnd_azure.c +++ b/mysqlnd_azure.c @@ -323,62 +323,76 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, DBG_INF_FMT("[redirect]: redirect host=%s user=%s port=%s ", redirect_host, redirect_user, redirect_port); ret = set_redirect_client_options(conn, redirect_conn); + + //Close the first connection first before establish the redirected connection + conn->m->send_close(conn); + conn->m->dtor(conn); + pfc = NULL; + if (transport.s) { + mnd_sprintf_free(transport.s); + transport.s = NULL; + } + if (ret == FAIL) { //init redirect_conn failed redirect_conn->m->dtor(redirect_conn); - DBG_ENTER("[redirect]: mysql redirect fails to copy MYSQLND_CONN_DATA, use original connection information!"); + php_error_docref(NULL, E_ERROR, "[redirect]: mysql redirect fails to copy MYSQLND_CONN_DATA. Abort the connection."); + DBG_RETURN(FAIL); } else { //init redirect_conn succeeded, use this conn to start a new connection and handshake + MYSQLND_CSTRING redirect_hostname = { redirect_host, strlen(redirect_host) }; MYSQLND_CSTRING redirect_username = { redirect_user, strlen(redirect_user) }; MYSQLND_STRING redirect_transport = redirect_conn->m->get_scheme(redirect_conn, redirect_hostname, &socket_or_pipe, ui_redirect_port, &unix_socket, &named_pipe); const MYSQLND_CSTRING redirect_scheme = { redirect_transport.s, redirect_transport.l }; + //upate conn, transport, pconn for later user + conn = redirect_conn; + transport = redirect_transport; + pfc = redirect_conn->protocol_frame_codec; + *pconn = redirect_conn; //use new conn outside for caller + mysqlnd_azure_set_is_using_redirect(redirect_conn, 1); enum_func_status redirectState = redirect_conn->m->connect_handshake(redirect_conn, &redirect_scheme, &redirect_username, &password, &database, mysql_flags); - if (redirectState == FAIL) { //handshake with new redirection MYSQLND_CONN_DATA failed, release resource and use original connection - redirect_conn->m->dtor(redirect_conn); - if (redirect_transport.s) { - mnd_sprintf_free(redirect_transport.s); - redirect_transport.s = NULL; - } - DBG_ENTER("[redirect]: mysql redirect handshake fails, use original connection information!"); - } - else { //handshake with redirect_conn succeeded, close and release resource of original conn and replace it with redirect_conn + if (redirectState == PASS) { //handshake with redirect_conn succeeded, replace original connection info with redirect_conn //add the redirect info into cache table - mysqlnd_azure_add_redirect_cache(conn, username.s, hostname.s, port, redirect_username.s, redirect_hostname.s, ui_redirect_port); - - conn->m->send_close(conn); - conn->m->dtor(conn); - pfc = NULL; - //upate conn, transport, pconn for later user - conn = redirect_conn; - if (transport.s) { - mnd_sprintf_free(transport.s); - transport.s = NULL; - } - transport = redirect_transport; - *pconn = redirect_conn; //use new conn outside for caller + mysqlnd_azure_add_redirect_cache(redirect_conn->persistent, username.s, hostname.s, port, redirect_username.s, redirect_hostname.s, ui_redirect_port); ///upate host, user, pfc for later user hostname = redirect_hostname; username = redirect_username; port = ui_redirect_port; - pfc = redirect_conn->protocol_frame_codec; DBG_ENTER("[redirect]: mysql redirect handshake succeeded."); } + else { + goto err; + } } } else { DBG_ENTER("[redirect]: redirection info are equal to origin, no need to redirect"); } } - else { - DBG_ENTER("[redirect]: already use redirection info or can not find redirection location in ok packet"); + else if (!(*pdata)->is_using_redirect) { + //If there is no redirection information contained in the last_message, then redirection is not possible. In this case, abort the connection + php_error_docref(NULL, E_ERROR, "No redirection information available, redirection is not possible. Abort the connection."); + conn->m->send_close(conn); + conn->m->dtor(conn); + pfc = NULL; + + if (transport.s) { + mnd_sprintf_free(transport.s); + transport.s = NULL; + } + + DBG_RETURN(FAIL); } + else { + DBG_ENTER("[redirect]: already use redirection info."); + } } /*end of Azure Redirection Logic*/ @@ -534,15 +548,22 @@ MYSQLND_METHOD(mysqlnd_azure, connect)(MYSQLND * conn_handle, mysqlnd_options4(conn_handle, MYSQL_OPT_CONNECT_ATTR_ADD, "_server_host", hostname.s); } - if(!MYSQLND_AZURE_G(enabled)) { + if(!MYSQLND_AZURE_G(enableRedirect)) { DBG_ENTER("mysqlnd_azure::connect redirect disabled"); ret = org_conn_d_m.connect(*pconn, hostname, username, password, database, port, socket_or_pipe, mysql_flags); } else { DBG_ENTER("mysqlnd_azure::connect redirect enabled"); + //Redirection is only possible with SSL + unsigned int temp_flags = (*pconn)->m->get_updated_connect_flags(*pconn, mysql_flags); + if(!(temp_flags & CLIENT_SSL)) { + php_error_docref(NULL, E_ERROR, "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL."); + DBG_RETURN(FAIL); + } + //first check whether the redirect info already cached - MYSQLND_AZURE_REDIRECT_INFO* redirect_info = mysqlnd_azure_find_redirect_cache(*pconn, username.s, hostname.s, port); + MYSQLND_AZURE_REDIRECT_INFO* redirect_info = mysqlnd_azure_find_redirect_cache(username.s, hostname.s, port); if (redirect_info != NULL) { DBG_ENTER("mysqlnd_azure::connect try the cached info first"); MYSQLND_CSTRING redirect_host = { redirect_info->redirect_host, strlen(redirect_info->redirect_host) }; @@ -552,7 +573,7 @@ MYSQLND_METHOD(mysqlnd_azure, connect)(MYSQLND * conn_handle, ret = (*pconn)->m->connect(pconn, redirect_host, redirect_user, password, database, redirect_info->redirect_port, socket_or_pipe, mysql_flags); if (ret == FAIL) { //remove invalid cache - mysqlnd_azure_remove_redirect_cache(*pconn, username.s, hostname.s, port); + mysqlnd_azure_remove_redirect_cache(username.s, hostname.s, port); mysqlnd_azure_set_is_using_redirect(*pconn, 0); ret = (*pconn)->m->connect(pconn, hostname, username, password, database, port, socket_or_pipe, mysql_flags); diff --git a/mysqlnd_azure.h b/mysqlnd_azure.h index 1d472a1..e37c467 100644 --- a/mysqlnd_azure.h +++ b/mysqlnd_azure.h @@ -46,9 +46,9 @@ void mysqlnd_azure_minit_register_hooks(); MYSQLND_AZURE_CONN_DATA** mysqlnd_azure_get_is_using_redirect(const MYSQLND_CONN_DATA *conn); MYSQLND_AZURE_CONN_DATA** mysqlnd_azure_set_is_using_redirect(MYSQLND_CONN_DATA *conn, zend_bool is_using_redirect); -enum_func_status mysqlnd_azure_add_redirect_cache(const MYSQLND_CONN_DATA* conn, const char* user, const char* host, int port, const char* redirect_user, const char* redirect_host, int redirect_port); -enum_func_status mysqlnd_azure_remove_redirect_cache(const MYSQLND_CONN_DATA* conn, const char* user, const char* host, int port); -MYSQLND_AZURE_REDIRECT_INFO* mysqlnd_azure_find_redirect_cache(const MYSQLND_CONN_DATA* conn, const char* user, const char* host, int port); +enum_func_status mysqlnd_azure_add_redirect_cache(zend_bool persistent, const char* user, const char* host, int port, const char* redirect_user, const char* redirect_host, int redirect_port); +enum_func_status mysqlnd_azure_remove_redirect_cache(const char* user, const char* host, int port); +MYSQLND_AZURE_REDIRECT_INFO* mysqlnd_azure_find_redirect_cache(const char* user, const char* host, int port); #if defined(ZTS) && defined(COMPILE_DL_MYSQLND_AZURE) ZEND_TSRMLS_CACHE_EXTERN() diff --git a/php_mysqlnd_azure.c b/php_mysqlnd_azure.c index d485326..4cb32ae 100644 --- a/php_mysqlnd_azure.c +++ b/php_mysqlnd_azure.c @@ -34,7 +34,7 @@ static PHP_GINIT_FUNCTION(mysqlnd_azure) #if defined(COMPILE_DL_MYSQLND_AZURE) && defined(ZTS) ZEND_TSRMLS_CACHE_UPDATE(); #endif - mysqlnd_azure_globals->enabled = 0; + mysqlnd_azure_globals->enableRedirect = 0; mysqlnd_azure_globals->redirectCache = NULL; } /* }}} */ @@ -53,11 +53,11 @@ static PHP_GSHUTDOWN_FUNCTION(mysqlnd_azure) /* {{{ PHP_INI */ /* It is handy to allow users to disable any mysqlnd plugin globally - not only for debugging :-) - Because we register our plugin in MINIT changes to mysqlnd_ed.enabled shall be bound to + Because we register our plugin in MINIT changes to myqlnd_azure.enableRedirect shall be bound to INI_SYSTEM (and PHP restarts). */ PHP_INI_BEGIN() -STD_PHP_INI_ENTRY("mysqlnd_azure.enabled", "0", PHP_INI_ALL, OnUpdateBool, enabled, zend_mysqlnd_azure_globals, mysqlnd_azure_globals) +STD_PHP_INI_ENTRY("mysqlnd_azure.enableRedirect", "0", PHP_INI_ALL, OnUpdateBool, enableRedirect, zend_mysqlnd_azure_globals, mysqlnd_azure_globals) PHP_INI_END() /* }}} */ @@ -87,8 +87,8 @@ static PHP_MSHUTDOWN_FUNCTION(mysqlnd_azure) PHP_MINFO_FUNCTION(mysqlnd_azure) { php_info_print_table_start(); - php_info_print_table_header(2, "mysqlnd_azure", "enabled"); - php_info_print_table_row(2, "enabled", MYSQLND_AZURE_G(enabled)? "Yes":"No"); + php_info_print_table_header(2, "mysqlnd_azure", "enableRedirect"); + php_info_print_table_row(2, "enableRedirect", MYSQLND_AZURE_G(enableRedirect)? "Yes":"No"); php_info_print_table_end(); } /* }}} */ diff --git a/php_mysqlnd_azure.h b/php_mysqlnd_azure.h index 8c90a08..e0ba551 100644 --- a/php_mysqlnd_azure.h +++ b/php_mysqlnd_azure.h @@ -32,7 +32,7 @@ extern zend_module_entry mysqlnd_azure_module_entry; #define EXT_MYSQLND_AZURE_VERSION "1.0.2" ZEND_BEGIN_MODULE_GLOBALS(mysqlnd_azure) - zend_bool enabled; + zend_bool enableRedirect; HashTable* redirectCache; ZEND_END_MODULE_GLOBALS(mysqlnd_azure) diff --git a/redirect_cache.c b/redirect_cache.c index 84dbd2a..ca7bc21 100644 --- a/redirect_cache.c +++ b/redirect_cache.c @@ -76,7 +76,7 @@ MYSQLND_AZURE_CONN_DATA** mysqlnd_azure_set_is_using_redirect(MYSQLND_CONN_DATA /* }}} */ /* {{{ mysqlnd_azure_add_redirect_cache */ -enum_func_status mysqlnd_azure_add_redirect_cache(const MYSQLND_CONN_DATA* conn, const char* user, const char* host, int port, const char* redirect_user, const char* redirect_host, int redirect_port) +enum_func_status mysqlnd_azure_add_redirect_cache(zend_bool persistent, const char* user, const char* host, int port, const char* redirect_user, const char* redirect_host, int redirect_port) { if (MYSQLND_AZURE_G(redirectCache) == NULL) { MYSQLND_AZURE_G(redirectCache) = mnd_pemalloc(sizeof(HashTable), 1); @@ -86,9 +86,9 @@ enum_func_status mysqlnd_azure_add_redirect_cache(const MYSQLND_CONN_DATA* conn, char *key = NULL; mnd_sprintf(&key, MAX_REDIRECT_HOST_LEN+ MAX_REDIRECT_USER_LEN+8, "%s_%s_%d", user, host, port); - MYSQLND_AZURE_REDIRECT_INFO* redirect_info = pemalloc(sizeof(MYSQLND_AZURE_REDIRECT_INFO), conn->persistent); - redirect_info->redirect_user = mnd_pestrndup(redirect_user, strlen(redirect_user), conn->persistent); - redirect_info->redirect_host = mnd_pestrndup(redirect_host, strlen(redirect_host), conn->persistent); + MYSQLND_AZURE_REDIRECT_INFO* redirect_info = pemalloc(sizeof(MYSQLND_AZURE_REDIRECT_INFO), persistent); + redirect_info->redirect_user = mnd_pestrndup(redirect_user, strlen(redirect_user), persistent); + redirect_info->redirect_host = mnd_pestrndup(redirect_host, strlen(redirect_host), persistent); redirect_info->redirect_port = redirect_port; zend_hash_str_update_ptr(MYSQLND_AZURE_G(redirectCache), key, strlen(key), redirect_info); @@ -100,7 +100,7 @@ enum_func_status mysqlnd_azure_add_redirect_cache(const MYSQLND_CONN_DATA* conn, /* }}} */ /* {{{ mysqlnd_azure_remove_redirect_cache */ -enum_func_status mysqlnd_azure_remove_redirect_cache(const MYSQLND_CONN_DATA* conn, const char* user, const char* host, int port) +enum_func_status mysqlnd_azure_remove_redirect_cache(const char* user, const char* host, int port) { if (MYSQLND_AZURE_G(redirectCache) == NULL) return PASS; @@ -117,7 +117,7 @@ enum_func_status mysqlnd_azure_remove_redirect_cache(const MYSQLND_CONN_DATA* co /* }}} */ /* {{{ mysqlnd_azure_find_redirect_cache */ -MYSQLND_AZURE_REDIRECT_INFO* mysqlnd_azure_find_redirect_cache(const MYSQLND_CONN_DATA* conn, const char* user, const char* host, int port) +MYSQLND_AZURE_REDIRECT_INFO* mysqlnd_azure_find_redirect_cache(const char* user, const char* host, int port) { if (MYSQLND_AZURE_G(redirectCache) == NULL) return NULL; diff --git a/tests/mysqli_azure_redirection_disabled.phpt b/tests/mysqli_azure_redirection_disabled.phpt index 1d82f88..055edf9 100644 --- a/tests/mysqli_azure_redirection_disabled.phpt +++ b/tests/mysqli_azure_redirection_disabled.phpt @@ -1,7 +1,7 @@ --TEST-- -Azure redirection test for servers with mysqlnd_azure.enabled=0 +Azure redirection test for servers with mysqlnd_azure.enableRedirect=0 --INI-- -mysqlnd_azure.enabled=0 +mysqlnd_azure.enableRedirect=0 --SKIPIF-- Date: Tue, 26 Nov 2019 14:38:24 +0800 Subject: [PATCH 02/37] Update package.xml for 1.0.3 adjust design --- package.xml | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/package.xml b/package.xml index f17aa4c..f379aa9 100644 --- a/package.xml +++ b/package.xml @@ -16,11 +16,11 @@ Qianqian.Bu@microsoft.com yes - 2019-11-20 - + 2019-11-26 + - 1.0.2 - 1.0.2 + 1.0.3 + 1.0.3 stable @@ -28,7 +28,10 @@ PHP License -- apply fix for database null/empty problem change in https://github.com/php/php-src/pull/4340 in MYSQLND_METHOD(mysqlnd_conn_data, connect) to MYSQLND_METHOD(mysqlnd_azure_data, connect) +- 1. If redirection is on, ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." +- 2. If redirection is on, but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." +- 3. If redirected connection failed, also abort the first gateway connection. Return the error of the redirected connection. +- 4. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect. @@ -65,6 +68,24 @@ mysqlnd_azure + + + 1.0.3 + 1.0.3 + + + stable + stable + + 2019-11-26 + PHP License + +- 1. If redirection is on, ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." +- 2. If redirection is on, but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." +- 3. If redirected connection failed, also abort the first gateway connection. Return the error of the redirected connection. +- 4. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect. + + 1.0.2 From 55109dba1ab71ace0f507c3e1d4728edd5f93d37 Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Tue, 26 Nov 2019 14:44:59 +0800 Subject: [PATCH 03/37] Update README.md for v1.0.3 --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 3fd2b06..905a613 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,11 @@ Valid version: - 1.0.0 Change: initial version. Limitation: cannot install with pecl on linux; cannot work with 7.2.23+ and 7.3.10+ - 1.0.1 Change: with pecl install command line support on linux. Limitation: cannot work with 7.2.23+ and 7.3.10+ - 1.0.2 Change: fix compatibility problem with 7.2.23+ and 7.3.10+ +- 1.0.3 Change: + 1. Enfore ssl when using redirection. + 2. Enfore server support redrection if using redirection. + 3. If redirected connection failed, also abort the first gateway connection. Return the error of the redirected connection. + 4. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect. Following is a brief guide of how to install using pecl or build and test the extension from source. From 39f2de6d9ba39b81d10a0a7afef8e38d4c80ec2c Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Tue, 26 Nov 2019 14:58:54 +0800 Subject: [PATCH 04/37] Update readme for 1.0.3 and SSL --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 905a613..eb65903 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ Valid version: - 1.0.0 Change: initial version. Limitation: cannot install with pecl on linux; cannot work with 7.2.23+ and 7.3.10+ - 1.0.1 Change: with pecl install command line support on linux. Limitation: cannot work with 7.2.23+ and 7.3.10+ - 1.0.2 Change: fix compatibility problem with 7.2.23+ and 7.3.10+ -- 1.0.3 Change: - 1. Enfore ssl when using redirection. - 2. Enfore server support redrection if using redirection. +- 1.0.3 Change: In preious versions, if connection doesnot use SSL, or server doesnot support redirection, or redirected connection fails to connect for some reason, it will fallback to the first proxy connection. Since 1.0.3, the logic changes as follows: + 1. If redirection is on, ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." + 2. If redirection is on, but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." 3. If redirected connection failed, also abort the first gateway connection. Return the error of the redirected connection. - 4. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect. + 4. The option mysqlnd_azure.enabled is also renamed to mysqlnd_azure.enableRedirect. Following is a brief guide of how to install using pecl or build and test the extension from source. @@ -90,7 +90,8 @@ Then you can run **make install** to put the .so to your php so library. However - put mysqlnd_azure.so under extension_dir. - under directory for additional .ini files, you will find the ini files for the common used modules, e.g. 10-mysqlnd.ini for mysqlnd, 20-mysqli.ini for mysqli. Create a new ini file for mysqlnd_azure here. **Make sure the alphabet order of the name is after that of mysqnld**, since the modules are loaded according to the name order of the ini files. E.g. if mysqlnd ini is with name 10-mysqlnd.ini,then name the ini as 20-mysqlnd-azure.ini. In the ini file, add the following two lines: - extension=mysqlnd_azure - - mysqlnd_azure.enableRedirect = on ; you can also set this to off to disable redirection + - mysqlnd_azure.enableRedirect = on ; you can also set this to off to disable redirection. + - **Notice:** since 1.0.3, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. ## Step to build on Windows @@ -137,6 +138,7 @@ After this, the code directory should look like C:\php-sdk\phpdev\vc15\x64\php-s - Under the Module Settings section add: - [mysqlnd_azure] - mysqlnd_azure.enableRedirect = on + - **Notice:** since 1.0.3, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. ## Test @@ -145,6 +147,7 @@ After this, the code directory should look like C:\php-sdk\phpdev\vc15\x64\php-s ```php echo "mysqlnd_azure.enableRedirect: ", ini_get("mysqlnd_azure.enableRedirect") == true?"On":"Off", "\n"; $db = mysqli_init(); + //The connection must be configured with SSL for redirection test $link = mysqli_real_connect ($db, 'your-hostname-with-redirection-enabled', 'user@host', 'password', "db", 3306, NULL, MYSQLI_CLIENT_SSL); if (!$link) { die ('Connect error (' . mysqli_connect_errno() . '): ' . mysqli_connect_error() . "\n"); From 95de5e154f0369860b6ceae3d7a2830a1c5db1f3 Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Tue, 26 Nov 2019 15:00:38 +0800 Subject: [PATCH 05/37] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eb65903..90c3897 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ After this, the code directory should look like C:\php-sdk\phpdev\vc15\x64\php-s - Under the Module Settings section add: - [mysqlnd_azure] - mysqlnd_azure.enableRedirect = on - - **Notice:** since 1.0.3, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. + - **Notice:** since 1.0.3, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. ## Test From 520c7819653519c2f8c12845c440c261301c5615 Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Tue, 26 Nov 2019 15:45:05 +0800 Subject: [PATCH 06/37] update version number in header file --- php_mysqlnd_azure.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_mysqlnd_azure.h b/php_mysqlnd_azure.h index e0ba551..5e64153 100644 --- a/php_mysqlnd_azure.h +++ b/php_mysqlnd_azure.h @@ -29,7 +29,7 @@ extern zend_module_entry mysqlnd_azure_module_entry; # define phpext_mysqlnd_azure_ptr &mysqlnd_azure_module_entry #define EXT_MYSQLND_AZURE_NAME "mysqlnd_azure" -#define EXT_MYSQLND_AZURE_VERSION "1.0.2" +#define EXT_MYSQLND_AZURE_VERSION "1.0.3" ZEND_BEGIN_MODULE_GLOBALS(mysqlnd_azure) zend_bool enableRedirect; From 25119efe80c1b4a37320caa5a02a1703791fb664 Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Wed, 27 Nov 2019 16:47:14 +0800 Subject: [PATCH 07/37] adjust the error message according to review --- mysqlnd_azure.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysqlnd_azure.c b/mysqlnd_azure.c index e10c11e..d917050 100644 --- a/mysqlnd_azure.c +++ b/mysqlnd_azure.c @@ -378,7 +378,7 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, } else if (!(*pdata)->is_using_redirect) { //If there is no redirection information contained in the last_message, then redirection is not possible. In this case, abort the connection - php_error_docref(NULL, E_ERROR, "No redirection information available, redirection is not possible. Abort the connection."); + php_error_docref(NULL, E_ERROR, "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol."); conn->m->send_close(conn); conn->m->dtor(conn); pfc = NULL; From a2ebb9efcc75792418935ea11f33acc86882bf41 Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Mon, 2 Dec 2019 10:20:46 +0800 Subject: [PATCH 08/37] change module global to treu global to increase cache share for multi-thread scenario --- php_mysqlnd_azure.c | 29 ++++++------ php_mysqlnd_azure.h | 13 +++++- redirect_cache.c | 108 ++++++++++++++++++++++++++++++++++---------- 3 files changed, 111 insertions(+), 39 deletions(-) diff --git a/php_mysqlnd_azure.c b/php_mysqlnd_azure.c index 4cb32ae..5a00b60 100644 --- a/php_mysqlnd_azure.c +++ b/php_mysqlnd_azure.c @@ -35,18 +35,6 @@ static PHP_GINIT_FUNCTION(mysqlnd_azure) ZEND_TSRMLS_CACHE_UPDATE(); #endif mysqlnd_azure_globals->enableRedirect = 0; - mysqlnd_azure_globals->redirectCache = NULL; -} -/* }}} */ - -/* {{{ PHP_GSHUTDOWN_FUNCTION */ -static PHP_GSHUTDOWN_FUNCTION(mysqlnd_azure) -{ - if (mysqlnd_azure_globals->redirectCache) { - zend_hash_destroy(mysqlnd_azure_globals->redirectCache); - mnd_pefree(mysqlnd_azure_globals->redirectCache, 1); - mysqlnd_azure_globals->redirectCache = NULL; - } } /* }}} */ @@ -70,6 +58,11 @@ static PHP_MINIT_FUNCTION(mysqlnd_azure) /* register mysqlnd plugin */ mysqlnd_azure_minit_register_hooks(); + #ifdef ZTS + mysqlnd_azure_redirect_cache_lock_alloc(); + #endif + redirectCache = NULL; + return SUCCESS; } @@ -79,6 +72,16 @@ static PHP_MSHUTDOWN_FUNCTION(mysqlnd_azure) { UNREGISTER_INI_ENTRIES(); + if (redirectCache) { + zend_hash_destroy(redirectCache); + mnd_pefree(redirectCache, 1); + redirectCache = NULL; + } + + #ifdef ZTS + mysqlnd_azure_redirect_cache_lock_free(); + #endif + return SUCCESS; } @@ -113,7 +116,7 @@ zend_module_entry mysqlnd_azure_module_entry = { EXT_MYSQLND_AZURE_VERSION, PHP_MODULE_GLOBALS(mysqlnd_azure), PHP_GINIT(mysqlnd_azure), - PHP_GSHUTDOWN(mysqlnd_azure), + NULL, NULL, STANDARD_MODULE_PROPERTIES_EX }; diff --git a/php_mysqlnd_azure.h b/php_mysqlnd_azure.h index 5e64153..55c81b7 100644 --- a/php_mysqlnd_azure.h +++ b/php_mysqlnd_azure.h @@ -31,9 +31,20 @@ extern zend_module_entry mysqlnd_azure_module_entry; #define EXT_MYSQLND_AZURE_NAME "mysqlnd_azure" #define EXT_MYSQLND_AZURE_VERSION "1.0.3" +/* true global environment */ +HashTable* redirectCache; + +#ifdef ZTS +/* exclusive locking for redirectCache*/ +void mysqlnd_azure_redirect_cache_lock(void); +void mysqlnd_azure_redirect_cache_unlock(void); +void mysqlnd_azure_redirect_cache_lock_alloc(void); +void mysqlnd_azure_redirect_cache_lock_free(void); +#endif + + ZEND_BEGIN_MODULE_GLOBALS(mysqlnd_azure) zend_bool enableRedirect; - HashTable* redirectCache; ZEND_END_MODULE_GLOBALS(mysqlnd_azure) PHPAPI ZEND_EXTERN_MODULE_GLOBALS(mysqlnd_azure) diff --git a/redirect_cache.c b/redirect_cache.c index ca7bc21..46ccc35 100644 --- a/redirect_cache.c +++ b/redirect_cache.c @@ -29,6 +29,43 @@ #include "ext/mysqlnd/mysqlnd_statistics.h" #include "ext/mysqlnd/mysqlnd_connection.h" +#ifdef ZTS +#include +#endif + +#ifdef ZTS +static MUTEX_T redirect_cache_mutex; + +/* {{{ mysqlnd_azure_redirect_cache_lock */ +void mysqlnd_azure_redirect_cache_lock(void) +{ + tsrm_mutex_lock(redirect_cache_mutex); +} +/* }}} */ + +/* {{{ mysqlnd_azure_redirect_cache_unlock */ +void mysqlnd_azure_redirect_cache_unlock(void) +{ + tsrm_mutex_unlock(redirect_cache_mutex); +} +/* }}} */ + +/* {{{ mysqlnd_azure_redirect_cache_lock_alloc */ +void mysqlnd_azure_redirect_cache_lock_alloc(void) +{ + redirect_cache_mutex = tsrm_mutex_alloc(); +} +/* }}} */ + +/* {{{ mysqlnd_azure_redirect_cache_lock_free */ +void mysqlnd_azure_redirect_cache_lock_free(void) +{ + tsrm_mutex_free(redirect_cache_mutex); +} +/* }}} */ + +#endif + /* {{{ mysqlnd_azure_redirect_info_dtor */ static void mysqlnd_azure_redirect_info_dtor(zval *zv) { @@ -78,12 +115,7 @@ MYSQLND_AZURE_CONN_DATA** mysqlnd_azure_set_is_using_redirect(MYSQLND_CONN_DATA /* {{{ mysqlnd_azure_add_redirect_cache */ enum_func_status mysqlnd_azure_add_redirect_cache(zend_bool persistent, const char* user, const char* host, int port, const char* redirect_user, const char* redirect_host, int redirect_port) { - if (MYSQLND_AZURE_G(redirectCache) == NULL) { - MYSQLND_AZURE_G(redirectCache) = mnd_pemalloc(sizeof(HashTable), 1); - zend_hash_init(MYSQLND_AZURE_G(redirectCache), 0, NULL, mysqlnd_azure_redirect_info_dtor, 1); - } - - char *key = NULL; + char *key = NULL; mnd_sprintf(&key, MAX_REDIRECT_HOST_LEN+ MAX_REDIRECT_USER_LEN+8, "%s_%s_%d", user, host, port); MYSQLND_AZURE_REDIRECT_INFO* redirect_info = pemalloc(sizeof(MYSQLND_AZURE_REDIRECT_INFO), persistent); @@ -91,9 +123,21 @@ enum_func_status mysqlnd_azure_add_redirect_cache(zend_bool persistent, const ch redirect_info->redirect_host = mnd_pestrndup(redirect_host, strlen(redirect_host), persistent); redirect_info->redirect_port = redirect_port; - zend_hash_str_update_ptr(MYSQLND_AZURE_G(redirectCache), key, strlen(key), redirect_info); + #ifdef ZTS + mysqlnd_azure_redirect_cache_lock(); + #endif + if (redirectCache == NULL) { + redirectCache = mnd_pemalloc(sizeof(HashTable), 1); + zend_hash_init(redirectCache, 0, NULL, mysqlnd_azure_redirect_info_dtor, 1); + } + + zend_hash_str_update_ptr(redirectCache, key, strlen(key), redirect_info); - mnd_sprintf_free(key); + #ifdef ZTS + mysqlnd_azure_redirect_cache_unlock(); + #endif + + mnd_sprintf_free(key); return PASS; } @@ -102,15 +146,21 @@ enum_func_status mysqlnd_azure_add_redirect_cache(zend_bool persistent, const ch /* {{{ mysqlnd_azure_remove_redirect_cache */ enum_func_status mysqlnd_azure_remove_redirect_cache(const char* user, const char* host, int port) { - if (MYSQLND_AZURE_G(redirectCache) == NULL) - return PASS; + if(redirectCache != NULL) { + char *key = NULL; + mnd_sprintf(&key, MAX_REDIRECT_HOST_LEN + MAX_REDIRECT_USER_LEN + 8, "%s_%s_%d", user, host, port); - char *key = NULL; - mnd_sprintf(&key, MAX_REDIRECT_HOST_LEN + MAX_REDIRECT_USER_LEN + 8, "%s_%s_%d", user, host, port); + #ifdef ZTS + mysqlnd_azure_redirect_cache_lock(); + #endif - zend_hash_str_del(MYSQLND_AZURE_G(redirectCache), key, strlen(key)); + zend_hash_str_del(redirectCache, key, strlen(key)); + #ifdef ZTS + mysqlnd_azure_redirect_cache_unlock(); + #endif - mnd_sprintf_free(key); + mnd_sprintf_free(key); + } return PASS; } @@ -119,15 +169,23 @@ enum_func_status mysqlnd_azure_remove_redirect_cache(const char* user, const cha /* {{{ mysqlnd_azure_find_redirect_cache */ MYSQLND_AZURE_REDIRECT_INFO* mysqlnd_azure_find_redirect_cache(const char* user, const char* host, int port) { - if (MYSQLND_AZURE_G(redirectCache) == NULL) - return NULL; - - char *key = NULL; - mnd_sprintf(&key, MAX_REDIRECT_HOST_LEN + MAX_REDIRECT_USER_LEN + 8, "%s_%s_%d", user, host, port); - - void* zv_dest = zend_hash_str_find_ptr(MYSQLND_AZURE_G(redirectCache), key, strlen(key)); - mnd_sprintf_free(key); - - return (MYSQLND_AZURE_REDIRECT_INFO*)zv_dest; + if (redirectCache != NULL) { + char *key = NULL; + mnd_sprintf(&key, MAX_REDIRECT_HOST_LEN + MAX_REDIRECT_USER_LEN + 8, "%s_%s_%d", user, host, port); + + #ifdef ZTS + mysqlnd_azure_redirect_cache_lock(); + #endif + + void* zv_dest = zend_hash_str_find_ptr(redirectCache, key, strlen(key)); + #ifdef ZTS + mysqlnd_azure_redirect_cache_unlock(); + #endif + mnd_sprintf_free(key); + + return (MYSQLND_AZURE_REDIRECT_INFO*)zv_dest; + } else { + return NULL; + } } -/* }}} */ +/* }}} */ \ No newline at end of file From 459f9bc0e8528ac855152102357b7ff40c11e02e Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Tue, 3 Dec 2019 13:42:46 +0800 Subject: [PATCH 09/37] change E_ERROR to E_WARNING as a typical PHP error handling --- mysqlnd_azure.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mysqlnd_azure.c b/mysqlnd_azure.c index d917050..6c0431c 100644 --- a/mysqlnd_azure.c +++ b/mysqlnd_azure.c @@ -335,7 +335,7 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, if (ret == FAIL) { //init redirect_conn failed redirect_conn->m->dtor(redirect_conn); - php_error_docref(NULL, E_ERROR, "[redirect]: mysql redirect fails to copy MYSQLND_CONN_DATA. Abort the connection."); + php_error_docref(NULL, E_WARNING, "[redirect]: mysql redirect fails to copy MYSQLND_CONN_DATA. Abort the connection."); DBG_RETURN(FAIL); } else { //init redirect_conn succeeded, use this conn to start a new connection and handshake @@ -378,7 +378,7 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, } else if (!(*pdata)->is_using_redirect) { //If there is no redirection information contained in the last_message, then redirection is not possible. In this case, abort the connection - php_error_docref(NULL, E_ERROR, "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol."); + php_error_docref(NULL, E_WARNING, "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol."); conn->m->send_close(conn); conn->m->dtor(conn); pfc = NULL; @@ -558,7 +558,7 @@ MYSQLND_METHOD(mysqlnd_azure, connect)(MYSQLND * conn_handle, //Redirection is only possible with SSL unsigned int temp_flags = (*pconn)->m->get_updated_connect_flags(*pconn, mysql_flags); if(!(temp_flags & CLIENT_SSL)) { - php_error_docref(NULL, E_ERROR, "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL."); + php_error_docref(NULL, E_WARNING, "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL."); DBG_RETURN(FAIL); } From 81a5243e6770abbed5c6daa1230d265a48c6ec88 Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Tue, 3 Dec 2019 16:07:46 +0800 Subject: [PATCH 10/37] comment enhancement --- mysqlnd_azure.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysqlnd_azure.c b/mysqlnd_azure.c index 6c0431c..7cd6d59 100644 --- a/mysqlnd_azure.c +++ b/mysqlnd_azure.c @@ -355,7 +355,7 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, enum_func_status redirectState = redirect_conn->m->connect_handshake(redirect_conn, &redirect_scheme, &redirect_username, &password, &database, mysql_flags); - if (redirectState == PASS) { //handshake with redirect_conn succeeded, replace original connection info with redirect_conn + if (redirectState == PASS) { //handshake with redirect_conn succeeded, replace original connection info with redirect_conn and add the redirect info into cache table //add the redirect info into cache table mysqlnd_azure_add_redirect_cache(redirect_conn->persistent, username.s, hostname.s, port, redirect_username.s, redirect_hostname.s, ui_redirect_port); From 3959529b3521f8c575227e7265e1910111ac5ca8 Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Thu, 5 Dec 2019 10:47:43 +0800 Subject: [PATCH 11/37] update version number and macro according to Christoph and remicollet's comment, enhance document --- README.md | 17 +++++++++++++++-- php_mysqlnd_azure.c | 8 +++----- php_mysqlnd_azure.h | 4 ++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 90c3897..328ecdd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,19 @@ # PHP mysqlnd redirection extension mysqlnd_azure The source code here is a PHP extension implemented using mysqlnd plugin API (https://www.php.net/manual/en/mysqlnd.plugin.php), which provides redirection feature support. The extension is also available on PECL website at https://pecl.php.net/package/mysqlnd_azure. +Please notice that there is a limitation that redirection is only possible when the connection is configured with SSL. +In 1.0.x versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for some reason, +it will fallback to the first proxy connection. Since 1.1.0Beta, the logic changes as follows: + 1. If redirection is on, ssl is off, no connection will be made, it will return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." + 2. If redirection is on, but on server side redirection is not available (e.g. a community verion mysql installed locally), it will abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." + 3. If redirected connection failed for any reason, it will also abort the first proxy connection, and return the error of the redirected connection. +Ask from you: in version 1.1.0Beta, we add many restrictions when the feature is turned on, but fallback is then not possible any more. We also want to hear from you that given the + following two options, what will you prefer: + 1. Add another option "preferred" with fallback support (i.e. go without redirection if SSL is not used or server doesnot support redirection or do not need redirection). + 2. Remove the restrictions when redrection is turned on, still go without redirection if SSL is not used or server doesnot support redirection or do not need redirection. + + You may vote for your preference by giving comment on issue page on github or send email to the people of maintenance which you can find in the file named with package.xml. + ## Name and Extension Version Extension name: **mysqlnd_azure** @@ -10,10 +23,10 @@ Valid version: - 1.0.0 Change: initial version. Limitation: cannot install with pecl on linux; cannot work with 7.2.23+ and 7.3.10+ - 1.0.1 Change: with pecl install command line support on linux. Limitation: cannot work with 7.2.23+ and 7.3.10+ - 1.0.2 Change: fix compatibility problem with 7.2.23+ and 7.3.10+ -- 1.0.3 Change: In preious versions, if connection doesnot use SSL, or server doesnot support redirection, or redirected connection fails to connect for some reason, it will fallback to the first proxy connection. Since 1.0.3, the logic changes as follows: +- 1.1.0Beta Change: In preious versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for some reason, it will fallback to the first proxy connection. Since 1.0.3, the logic changes as follows: 1. If redirection is on, ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." 2. If redirection is on, but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." - 3. If redirected connection failed, also abort the first gateway connection. Return the error of the redirected connection. + 3. If redirected connection failed, also abort the first proxy connection. Return the error of the redirected connection. 4. The option mysqlnd_azure.enabled is also renamed to mysqlnd_azure.enableRedirect. Following is a brief guide of how to install using pecl or build and test the extension from source. diff --git a/php_mysqlnd_azure.c b/php_mysqlnd_azure.c index 5a00b60..58daab8 100644 --- a/php_mysqlnd_azure.c +++ b/php_mysqlnd_azure.c @@ -41,11 +41,9 @@ static PHP_GINIT_FUNCTION(mysqlnd_azure) /* {{{ PHP_INI */ /* It is handy to allow users to disable any mysqlnd plugin globally - not only for debugging :-) - Because we register our plugin in MINIT changes to myqlnd_azure.enableRedirect shall be bound to - INI_SYSTEM (and PHP restarts). */ PHP_INI_BEGIN() -STD_PHP_INI_ENTRY("mysqlnd_azure.enableRedirect", "0", PHP_INI_ALL, OnUpdateBool, enableRedirect, zend_mysqlnd_azure_globals, mysqlnd_azure_globals) +STD_PHP_INI_ENTRY("mysqlnd_azure.enableRedirect", "0", PHP_INI_PERDIR, OnUpdateBool, enableRedirect, zend_mysqlnd_azure_globals, mysqlnd_azure_globals) PHP_INI_END() /* }}} */ @@ -106,14 +104,14 @@ zend_module_entry mysqlnd_azure_module_entry = { STANDARD_MODULE_HEADER_EX, NULL, mysqlnd_azure_deps, - EXT_MYSQLND_AZURE_NAME, + PHP_MYSQLND_AZURE_NAME, NULL, PHP_MINIT(mysqlnd_azure), PHP_MSHUTDOWN(mysqlnd_azure), NULL, NULL, PHP_MINFO(mysqlnd_azure), - EXT_MYSQLND_AZURE_VERSION, + PHP_MYSQLND_AZURE_VERSION, PHP_MODULE_GLOBALS(mysqlnd_azure), PHP_GINIT(mysqlnd_azure), NULL, diff --git a/php_mysqlnd_azure.h b/php_mysqlnd_azure.h index 55c81b7..099ffcc 100644 --- a/php_mysqlnd_azure.h +++ b/php_mysqlnd_azure.h @@ -28,8 +28,8 @@ extern zend_module_entry mysqlnd_azure_module_entry; # define phpext_mysqlnd_azure_ptr &mysqlnd_azure_module_entry -#define EXT_MYSQLND_AZURE_NAME "mysqlnd_azure" -#define EXT_MYSQLND_AZURE_VERSION "1.0.3" +#define PHP_MYSQLND_AZURE_NAME "mysqlnd_azure" +#define PHP_MYSQLND_AZURE_VERSION "1.1.0Beta" /* true global environment */ HashTable* redirectCache; From aa8088b804f62a53a510e76c2f268bb203d94de9 Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Thu, 5 Dec 2019 10:52:17 +0800 Subject: [PATCH 12/37] enhance doc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 328ecdd..ff311f8 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Extension name: **mysqlnd_azure** Required PHP min version: PHP7.2.15+ and PHP7.3.2+. Valid version: -- 1.0.0 Change: initial version. Limitation: cannot install with pecl on linux; cannot work with 7.2.23+ and 7.3.10+ +- 1.0.0 Change: initial version. Limitation: cannot install with pecl on linux, the package on PECL website is invalid, only possible to install with manual compilation on Linux. Cannot work with 7.2.23+ and 7.3.10+ - 1.0.1 Change: with pecl install command line support on linux. Limitation: cannot work with 7.2.23+ and 7.3.10+ - 1.0.2 Change: fix compatibility problem with 7.2.23+ and 7.3.10+ - 1.1.0Beta Change: In preious versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for some reason, it will fallback to the first proxy connection. Since 1.0.3, the logic changes as follows: From fd22245168b1103023b7f07f7f84f543ff2bdb78 Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Thu, 5 Dec 2019 11:17:33 +0800 Subject: [PATCH 13/37] Update README.md --- README.md | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index ff311f8..4c424b2 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,23 @@ # PHP mysqlnd redirection extension mysqlnd_azure The source code here is a PHP extension implemented using mysqlnd plugin API (https://www.php.net/manual/en/mysqlnd.plugin.php), which provides redirection feature support. The extension is also available on PECL website at https://pecl.php.net/package/mysqlnd_azure. -Please notice that there is a limitation that redirection is only possible when the connection is configured with SSL. -In 1.0.x versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for some reason, -it will fallback to the first proxy connection. Since 1.1.0Beta, the logic changes as follows: - 1. If redirection is on, ssl is off, no connection will be made, it will return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." - 2. If redirection is on, but on server side redirection is not available (e.g. a community verion mysql installed locally), it will abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." - 3. If redirected connection failed for any reason, it will also abort the first proxy connection, and return the error of the redirected connection. -Ask from you: in version 1.1.0Beta, we add many restrictions when the feature is turned on, but fallback is then not possible any more. We also want to hear from you that given the - following two options, what will you prefer: - 1. Add another option "preferred" with fallback support (i.e. go without redirection if SSL is not used or server doesnot support redirection or do not need redirection). - 2. Remove the restrictions when redrection is turned on, still go without redirection if SSL is not used or server doesnot support redirection or do not need redirection. - - You may vote for your preference by giving comment on issue page on github or send email to the people of maintenance which you can find in the file named with package.xml. +**Important notice:** There is a limitation that for Azure MySQL, redirection is only possible when the connection is configured with SSL. + +In 1.0.x versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. + +Since 1.1.0Beta, the logic changes as follows: +- If redirection is on, ssl is off, no connection will be made, it will return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." +- If redirection is on, but on server side redirection is not available (e.g. a community verion mysql installed locally), it will abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." +- If redirected connection failed for any reason, it will also abort the first proxy connection, and return the error of the redirected connection. + +``` +Ask from you: +In version 1.1.0Beta, we add many restrictions when the feature is turned on, but fallback is then not possible any +more. We also want to hear from you that given the following two options, what will you prefer: + 1. Add another option "preferred" with fallback support (i.e. go without redirection if SSL is not used or server doesnot support +redirection or do not need redirection). + 2. Remove the restrictions when redrection is turned on, still go without redirection if SSL is not used or server doesnot support redirection or do not need redirection. + +You may vote for your preference by giving comment on issue page on github or send email to the people of maintenance which you can find in the file named with package.xml. +``` ## Name and Extension Version Extension name: **mysqlnd_azure** From 57772ddd4f5ba8c88d37baa3ee4a210ed7df924f Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Thu, 5 Dec 2019 11:22:46 +0800 Subject: [PATCH 14/37] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4c424b2..c91ff61 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ Since 1.1.0Beta, the logic changes as follows: ``` Ask from you: -In version 1.1.0Beta, we add many restrictions when the feature is turned on, but fallback is then not possible any +more. We also want to hear from you that given the following two options, what will you prefer: - 1. Add another option "preferred" with fallback support (i.e. go without redirection if SSL is not used or server doesnot support +redirection or do not need redirection). - 2. Remove the restrictions when redrection is turned on, still go without redirection if SSL is not used or server doesnot support redirection or do not need redirection. +In version 1.1.0Beta, we add many restrictions when the feature is turned on, but fallback is then not possible anymore. We also want to hear from you that given the following two options, what will you prefer: + 1. Add another option "preferred" with fallback support (i.e. go without redirection if SSL is not used or server does not support redirection or do not need redirection). + 2. Remove the restrictions when redrection is turned on, still go without redirection if SSL is not used or server does not support redirection or do not need redirection. You may vote for your preference by giving comment on issue page on github or send email to the people of maintenance which you can find in the file named with package.xml. ``` From 3f7d1a1f8bc280a49bed89e799f48b938c1440d9 Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Thu, 5 Dec 2019 11:26:54 +0800 Subject: [PATCH 15/37] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c91ff61..20beded 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ Since 1.1.0Beta, the logic changes as follows: ``` Ask from you: In version 1.1.0Beta, we add many restrictions when the feature is turned on, but fallback is then not possible anymore. We also want to hear from you that given the following two options, what will you prefer: - 1. Add another option "preferred" with fallback support (i.e. go without redirection if SSL is not used or server does not support redirection or do not need redirection). - 2. Remove the restrictions when redrection is turned on, still go without redirection if SSL is not used or server does not support redirection or do not need redirection. + 1. Add another option with name "preferred" with fallback support (i.e. go without redirection if SSL is not used, or server does not support redirection, or server does not need redirection). + 2. Remove the restrictions when redrection is turned on, still use the fallback logic as a single solution (i.e. redirect when posssible, and go without redirection if SSL is not used, or server does not support redirection, or server does not need redirection). You may vote for your preference by giving comment on issue page on github or send email to the people of maintenance which you can find in the file named with package.xml. ``` From 7ab1786fac3ed7d0efe549f9765488192b1bb4b3 Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Thu, 5 Dec 2019 11:35:34 +0800 Subject: [PATCH 16/37] Update version number and stability --- package.xml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/package.xml b/package.xml index f379aa9..72b913e 100644 --- a/package.xml +++ b/package.xml @@ -19,19 +19,19 @@ 2019-11-26 - 1.0.3 - 1.0.3 + 1.1.0Beta + 1.1.0Beta - stable - stable + Beta + Beta PHP License -- 1. If redirection is on, ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." -- 2. If redirection is on, but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." -- 3. If redirected connection failed, also abort the first gateway connection. Return the error of the redirected connection. -- 4. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect. +- 1. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect. +- 2. If enableRedirect is on, ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." +- 3. If enableRedirect is on, but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." +- 4. If enableRedirect is on and server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection. @@ -70,20 +70,20 @@ - 1.0.3 - 1.0.3 + 1.1.0Beta + 1.1.0Beta - stable - stable + Beta + Beta 2019-11-26 PHP License -- 1. If redirection is on, ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." -- 2. If redirection is on, but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." -- 3. If redirected connection failed, also abort the first gateway connection. Return the error of the redirected connection. -- 4. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect. +- 1. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect. +- 2. If enableRedirect is on, ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." +- 3. If enableRedirect is on, but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." +- 4. If enableRedirect is on and server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection. From 9d45a86f6a506d9a0dc49e7b99f190010aedf7b4 Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Thu, 5 Dec 2019 11:38:25 +0800 Subject: [PATCH 17/37] Keep it as PHP_INI_ALL --- php_mysqlnd_azure.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_mysqlnd_azure.c b/php_mysqlnd_azure.c index 58daab8..3214122 100644 --- a/php_mysqlnd_azure.c +++ b/php_mysqlnd_azure.c @@ -40,10 +40,10 @@ static PHP_GINIT_FUNCTION(mysqlnd_azure) /* {{{ PHP_INI */ /* - It is handy to allow users to disable any mysqlnd plugin globally - not only for debugging :-) + It is handy to allow users to set the value for debug and other behavior check purpose) */ PHP_INI_BEGIN() -STD_PHP_INI_ENTRY("mysqlnd_azure.enableRedirect", "0", PHP_INI_PERDIR, OnUpdateBool, enableRedirect, zend_mysqlnd_azure_globals, mysqlnd_azure_globals) +STD_PHP_INI_ENTRY("mysqlnd_azure.enableRedirect", "0", PHP_INI_ALL, OnUpdateBool, enableRedirect, zend_mysqlnd_azure_globals, mysqlnd_azure_globals) PHP_INI_END() /* }}} */ From 0fc3fd93faff616488220cdfbe8fa2b05d1a76e4 Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Thu, 5 Dec 2019 13:14:28 +0800 Subject: [PATCH 18/37] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 20beded..086dc2f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ In 1.0.x versions, if connection does not use SSL, or server does not support re Since 1.1.0Beta, the logic changes as follows: - If redirection is on, ssl is off, no connection will be made, it will return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." -- If redirection is on, but on server side redirection is not available (e.g. a community verion mysql installed locally), it will abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." +- If redirection is on, but on server side redirection is not supported/needed (e.g. a community verion mysql installed locally), and there is no last message in OK packet, it will abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." - If redirected connection failed for any reason, it will also abort the first proxy connection, and return the error of the redirected connection. ``` @@ -28,10 +28,10 @@ Valid version: - 1.0.0 Change: initial version. Limitation: cannot install with pecl on linux, the package on PECL website is invalid, only possible to install with manual compilation on Linux. Cannot work with 7.2.23+ and 7.3.10+ - 1.0.1 Change: with pecl install command line support on linux. Limitation: cannot work with 7.2.23+ and 7.3.10+ - 1.0.2 Change: fix compatibility problem with 7.2.23+ and 7.3.10+ -- 1.1.0Beta Change: In preious versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for some reason, it will fallback to the first proxy connection. Since 1.0.3, the logic changes as follows: +- 1.1.0Beta Change: In 1.0.x versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. Since 1.1.0Beta, the logic changes as follows: 1. If redirection is on, ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." - 2. If redirection is on, but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." - 3. If redirected connection failed, also abort the first proxy connection. Return the error of the redirected connection. + 2. If redirection is on, but on server side redirection is not supported/needed, and there is no last message in OK packet, abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." + 3. If redirected connection failed for any reason, it will also abort the first proxy connection, and return the error of the redirected connection. 4. The option mysqlnd_azure.enabled is also renamed to mysqlnd_azure.enableRedirect. Following is a brief guide of how to install using pecl or build and test the extension from source. From e193823759c129e08c42067825f5e6f90f8a0a02 Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Thu, 5 Dec 2019 13:18:45 +0800 Subject: [PATCH 19/37] add comment --- mysqlnd_azure.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysqlnd_azure.c b/mysqlnd_azure.c index 7cd6d59..e71da9a 100644 --- a/mysqlnd_azure.c +++ b/mysqlnd_azure.c @@ -367,7 +367,7 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, DBG_ENTER("[redirect]: mysql redirect handshake succeeded."); } - else { + else { //redirect failed goto err; } } From 7d4cd809732511a000e834cadb1ddf4e7e1352e2 Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Thu, 5 Dec 2019 13:30:49 +0800 Subject: [PATCH 20/37] Update package.xml --- package.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package.xml b/package.xml index 72b913e..946c3b7 100644 --- a/package.xml +++ b/package.xml @@ -19,12 +19,12 @@ 2019-11-26 - 1.1.0Beta - 1.1.0Beta + 1.1.0beta1 + 1.1.0beta1 - Beta - Beta + beta + beta PHP License @@ -70,12 +70,12 @@ - 1.1.0Beta - 1.1.0Beta + 1.1.0beta1 + 1.1.0beta1 - Beta - Beta + beta + beta 2019-11-26 PHP License From 40821b054cecba2db816247a8fbb2473eb3276cf Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Thu, 5 Dec 2019 13:32:14 +0800 Subject: [PATCH 21/37] Update php_mysqlnd_azure.h --- php_mysqlnd_azure.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_mysqlnd_azure.h b/php_mysqlnd_azure.h index 099ffcc..ad0dd97 100644 --- a/php_mysqlnd_azure.h +++ b/php_mysqlnd_azure.h @@ -29,7 +29,7 @@ extern zend_module_entry mysqlnd_azure_module_entry; # define phpext_mysqlnd_azure_ptr &mysqlnd_azure_module_entry #define PHP_MYSQLND_AZURE_NAME "mysqlnd_azure" -#define PHP_MYSQLND_AZURE_VERSION "1.1.0Beta" +#define PHP_MYSQLND_AZURE_VERSION "1.1.0beta1" /* true global environment */ HashTable* redirectCache; From c524bc1783e210f94d3c45956756007e21f10b72 Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Thu, 5 Dec 2019 13:35:19 +0800 Subject: [PATCH 22/37] Update package.xml --- package.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.xml b/package.xml index 946c3b7..c39530c 100644 --- a/package.xml +++ b/package.xml @@ -16,7 +16,7 @@ Qianqian.Bu@microsoft.com yes - 2019-11-26 + 2019-12-05 1.1.0beta1 @@ -77,7 +77,7 @@ beta beta - 2019-11-26 + 2019-12-05 PHP License - 1. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect. From 0280b96ad43e1cd23288f325477be60793b70c7c Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Thu, 5 Dec 2019 14:22:07 +0800 Subject: [PATCH 23/37] direct host info has been changed, change test accordingly --- tests/mysqli_azure_redirection_disabled.phpt | 2 +- tests/mysqli_azure_redirection_enabled.phpt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/mysqli_azure_redirection_disabled.phpt b/tests/mysqli_azure_redirection_disabled.phpt index 055edf9..70d2fe7 100644 --- a/tests/mysqli_azure_redirection_disabled.phpt +++ b/tests/mysqli_azure_redirection_disabled.phpt @@ -33,6 +33,6 @@ echo "Done\n"; ?> --EXPECTF-- %s -Location: mysql://tr%d.%s:%d/user=%s@%s +Location: mysql://%s:%d/user=%s@%s 1 Done diff --git a/tests/mysqli_azure_redirection_enabled.phpt b/tests/mysqli_azure_redirection_enabled.phpt index 274d9bb..dfe3baa 100644 --- a/tests/mysqli_azure_redirection_enabled.phpt +++ b/tests/mysqli_azure_redirection_enabled.phpt @@ -32,7 +32,7 @@ mysqli_close($link); echo "Done\n"; ?> --EXPECTF-- -tr%d.%s -Location: mysql://tr%d.%s:%d/user=%s@%s +%s +Location: mysql://%s:%d/user=%s@%s 0 Done From 192017e99f7a70f416fbeaa06a281fb95853f4cf Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Thu, 5 Dec 2019 14:57:34 +0800 Subject: [PATCH 24/37] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 086dc2f..bc5cd9b 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,14 @@ The source code here is a PHP extension implemented using mysqlnd plugin API (ht In 1.0.x versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. -Since 1.1.0Beta, the logic changes as follows: +Since 1.1.0beta1, the logic changes as follows: - If redirection is on, ssl is off, no connection will be made, it will return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." - If redirection is on, but on server side redirection is not supported/needed (e.g. a community verion mysql installed locally), and there is no last message in OK packet, it will abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." - If redirected connection failed for any reason, it will also abort the first proxy connection, and return the error of the redirected connection. ``` Ask from you: -In version 1.1.0Beta, we add many restrictions when the feature is turned on, but fallback is then not possible anymore. We also want to hear from you that given the following two options, what will you prefer: +In version 1.1.0beta1, we add many restrictions when the feature is turned on, but fallback is then not possible anymore. We also want to hear from you that given the following two options, what will you prefer: 1. Add another option with name "preferred" with fallback support (i.e. go without redirection if SSL is not used, or server does not support redirection, or server does not need redirection). 2. Remove the restrictions when redrection is turned on, still use the fallback logic as a single solution (i.e. redirect when posssible, and go without redirection if SSL is not used, or server does not support redirection, or server does not need redirection). @@ -109,7 +109,7 @@ Then you can run **make install** to put the .so to your php so library. However - under directory for additional .ini files, you will find the ini files for the common used modules, e.g. 10-mysqlnd.ini for mysqlnd, 20-mysqli.ini for mysqli. Create a new ini file for mysqlnd_azure here. **Make sure the alphabet order of the name is after that of mysqnld**, since the modules are loaded according to the name order of the ini files. E.g. if mysqlnd ini is with name 10-mysqlnd.ini,then name the ini as 20-mysqlnd-azure.ini. In the ini file, add the following two lines: - extension=mysqlnd_azure - mysqlnd_azure.enableRedirect = on ; you can also set this to off to disable redirection. - - **Notice:** since 1.0.3, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. + - **Notice:** since 1.1.0beta1, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. ## Step to build on Windows @@ -156,7 +156,7 @@ After this, the code directory should look like C:\php-sdk\phpdev\vc15\x64\php-s - Under the Module Settings section add: - [mysqlnd_azure] - mysqlnd_azure.enableRedirect = on - - **Notice:** since 1.0.3, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. + - **Notice:** since 1.1.0beta1, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. ## Test From c07e47fcd1ada3691178c38cd03e70b7f80d9361 Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Thu, 5 Dec 2019 17:14:36 +0800 Subject: [PATCH 25/37] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bc5cd9b..04bd15d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # PHP mysqlnd redirection extension mysqlnd_azure The source code here is a PHP extension implemented using mysqlnd plugin API (https://www.php.net/manual/en/mysqlnd.plugin.php), which provides redirection feature support. The extension is also available on PECL website at https://pecl.php.net/package/mysqlnd_azure. - -**Important notice:** There is a limitation that for Azure MySQL, redirection is only possible when the connection is configured with SSL. - +```diff +!**Important notice:** There is a limitation that for Azure MySQL, redirection is only possible when the connection is configured with SSL. +``` In 1.0.x versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. Since 1.1.0beta1, the logic changes as follows: From 5387b1b1e1384b5853df87b3544701c60c06cb02 Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Thu, 5 Dec 2019 17:16:38 +0800 Subject: [PATCH 26/37] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 04bd15d..c17840b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # PHP mysqlnd redirection extension mysqlnd_azure The source code here is a PHP extension implemented using mysqlnd plugin API (https://www.php.net/manual/en/mysqlnd.plugin.php), which provides redirection feature support. The extension is also available on PECL website at https://pecl.php.net/package/mysqlnd_azure. -```diff -!**Important notice:** There is a limitation that for Azure MySQL, redirection is only possible when the connection is configured with SSL. -``` + +**Important notice: There is a limitation that for Azure MySQL, redirection is only possible when the connection is configured with SSL.** + In 1.0.x versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. Since 1.1.0beta1, the logic changes as follows: From 2b7f8c02ff69591b70813a9e3b9bb78c0f5c7090 Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Thu, 5 Dec 2019 14:02:51 +0800 Subject: [PATCH 27/37] add preferred --- mysqlnd_azure.c | 134 +++++++++++++++++++++++++++++--------------- php_mysqlnd_azure.c | 54 ++++++++++++++---- php_mysqlnd_azure.h | 11 +++- 3 files changed, 141 insertions(+), 58 deletions(-) diff --git a/mysqlnd_azure.c b/mysqlnd_azure.c index e71da9a..a7e51fa 100644 --- a/mysqlnd_azure.c +++ b/mysqlnd_azure.c @@ -324,19 +324,26 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, ret = set_redirect_client_options(conn, redirect_conn); - //Close the first connection first before establish the redirected connection - conn->m->send_close(conn); - conn->m->dtor(conn); - pfc = NULL; - if (transport.s) { - mnd_sprintf_free(transport.s); - transport.s = NULL; - } + //Close the first connection first before establish the redirected connection when REDIRECT_ON + if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON) { + conn->m->send_close(conn); + conn->m->dtor(conn); + pfc = NULL; + if (transport.s) { + mnd_sprintf_free(transport.s); + transport.s = NULL; + } + } - if (ret == FAIL) { //init redirect_conn failed - redirect_conn->m->dtor(redirect_conn); - php_error_docref(NULL, E_WARNING, "[redirect]: mysql redirect fails to copy MYSQLND_CONN_DATA. Abort the connection."); - DBG_RETURN(FAIL); + if (ret == FAIL) { //init redirect_conn failed, if REDIRECT_ON, abort connection, if REDIRECT_PREFERRED, use the proxy connection + if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON) { + redirect_conn->m->dtor(redirect_conn); + php_error_docref(NULL, E_WARNING, "[redirect]: mysql redirect fails to copy MYSQLND_CONN_DATA. Abort the connection."); + DBG_RETURN(FAIL); + } + else { + //REDIRECT_PREFERRED, just use previous direct connection, do nothing here + } } else { //init redirect_conn succeeded, use this conn to start a new connection and handshake @@ -345,11 +352,13 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, MYSQLND_STRING redirect_transport = redirect_conn->m->get_scheme(redirect_conn, redirect_hostname, &socket_or_pipe, ui_redirect_port, &unix_socket, &named_pipe); const MYSQLND_CSTRING redirect_scheme = { redirect_transport.s, redirect_transport.l }; - //upate conn, transport, pconn for later user - conn = redirect_conn; - transport = redirect_transport; - pfc = redirect_conn->protocol_frame_codec; - *pconn = redirect_conn; //use new conn outside for caller + if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON) { //when REDIRECT_ON, previous connection has been closed, need update variable to handle both success/failure case + //upate conn, transport, pconn for later user + conn = redirect_conn; + transport = redirect_transport; + pfc = redirect_conn->protocol_frame_codec; + *pconn = redirect_conn; //use new conn outside for caller + } mysqlnd_azure_set_is_using_redirect(redirect_conn, 1); @@ -360,6 +369,22 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, //add the redirect info into cache table mysqlnd_azure_add_redirect_cache(redirect_conn->persistent, username.s, hostname.s, port, redirect_username.s, redirect_hostname.s, ui_redirect_port); + if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_PREFERRED) { + //close previous proxy connection + conn->m->send_close(conn); + conn->m->dtor(conn); + pfc = NULL; + if (transport.s) { + mnd_sprintf_free(transport.s); + transport.s = NULL; + } + //upate conn, transport, pconn for later user + conn = redirect_conn; + transport = redirect_transport; + pfc = redirect_conn->protocol_frame_codec; + *pconn = redirect_conn; //use new conn outside for caller + } + ///upate host, user, pfc for later user hostname = redirect_hostname; username = redirect_username; @@ -368,7 +393,18 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, DBG_ENTER("[redirect]: mysql redirect handshake succeeded."); } else { //redirect failed - goto err; + if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_PREFERRED) { + //REDIRECT_PREFERRED, redirect failed, use original connection information + redirect_conn->m->dtor(redirect_conn); + if (redirect_transport.s) { + mnd_sprintf_free(redirect_transport.s); + redirect_transport.s = NULL; + } + DBG_ENTER("[redirect]: mysql redirect handshake fails, use original connection information!"); + } + else { + goto err; //REDIRECT_ON, redirect failed, fail the connection and report error + } } } } @@ -376,8 +412,8 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, DBG_ENTER("[redirect]: redirection info are equal to origin, no need to redirect"); } } - else if (!(*pdata)->is_using_redirect) { - //If there is no redirection information contained in the last_message, then redirection is not possible. In this case, abort the connection + else if (!(*pdata)->is_using_redirect && MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON) { //!is_using_redirect, but does not find redirection info in last_message + //When REDIRECT_ON, if there is no redirection information contained in the last_message, then redirection is not possible. In this case, abort the connection php_error_docref(NULL, E_WARNING, "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol."); conn->m->send_close(conn); conn->m->dtor(conn); @@ -391,7 +427,7 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, DBG_RETURN(FAIL); } else { - DBG_ENTER("[redirect]: already use redirection info."); + DBG_ENTER("[redirect]: already use redirection info or do not find redrection information."); } } /*end of Azure Redirection Logic*/ @@ -548,40 +584,48 @@ MYSQLND_METHOD(mysqlnd_azure, connect)(MYSQLND * conn_handle, mysqlnd_options4(conn_handle, MYSQL_OPT_CONNECT_ATTR_ADD, "_server_host", hostname.s); } - if(!MYSQLND_AZURE_G(enableRedirect)) { + if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_OFF) { DBG_ENTER("mysqlnd_azure::connect redirect disabled"); ret = org_conn_d_m.connect(*pconn, hostname, username, password, database, port, socket_or_pipe, mysql_flags); } else { DBG_ENTER("mysqlnd_azure::connect redirect enabled"); - //Redirection is only possible with SSL + //Redirection is only possible with SSL at present. Abort the connection attempt when REDIRECT_ON. Continue with no redirection if REDIRECT_PREFERRED unsigned int temp_flags = (*pconn)->m->get_updated_connect_flags(*pconn, mysql_flags); if(!(temp_flags & CLIENT_SSL)) { - php_error_docref(NULL, E_WARNING, "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL."); - DBG_RETURN(FAIL); + if((MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON)) { + php_error_docref(NULL, E_WARNING, "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL."); + DBG_RETURN(FAIL); + } + else { + ret = org_conn_d_m.connect(*pconn, hostname, username, password, database, port, socket_or_pipe, mysql_flags); + } } + else { //SSL is enabled + + //first check whether the redirect info already cached + MYSQLND_AZURE_REDIRECT_INFO* redirect_info = mysqlnd_azure_find_redirect_cache(username.s, hostname.s, port); + if (redirect_info != NULL) { + DBG_ENTER("mysqlnd_azure::connect try the cached info first"); + MYSQLND_CSTRING redirect_host = { redirect_info->redirect_host, strlen(redirect_info->redirect_host) }; + MYSQLND_CSTRING redirect_user = { redirect_info->redirect_user, strlen(redirect_info->redirect_user) }; + + mysqlnd_azure_set_is_using_redirect(*pconn, 1); + ret = (*pconn)->m->connect(pconn, redirect_host, redirect_user, password, database, redirect_info->redirect_port, socket_or_pipe, mysql_flags); + if (ret == FAIL) { + //remove invalid cache + mysqlnd_azure_remove_redirect_cache(username.s, hostname.s, port); + + mysqlnd_azure_set_is_using_redirect(*pconn, 0); + ret = (*pconn)->m->connect(pconn, hostname, username, password, database, port, socket_or_pipe, mysql_flags); + } + } + else { + ret = (*pconn)->m->connect(pconn, hostname, username, password, database, port, socket_or_pipe, mysql_flags); + } - //first check whether the redirect info already cached - MYSQLND_AZURE_REDIRECT_INFO* redirect_info = mysqlnd_azure_find_redirect_cache(username.s, hostname.s, port); - if (redirect_info != NULL) { - DBG_ENTER("mysqlnd_azure::connect try the cached info first"); - MYSQLND_CSTRING redirect_host = { redirect_info->redirect_host, strlen(redirect_info->redirect_host) }; - MYSQLND_CSTRING redirect_user = { redirect_info->redirect_user, strlen(redirect_info->redirect_user) }; - - mysqlnd_azure_set_is_using_redirect(*pconn, 1); - ret = (*pconn)->m->connect(pconn, redirect_host, redirect_user, password, database, redirect_info->redirect_port, socket_or_pipe, mysql_flags); - if (ret == FAIL) { - //remove invalid cache - mysqlnd_azure_remove_redirect_cache(username.s, hostname.s, port); - - mysqlnd_azure_set_is_using_redirect(*pconn, 0); - ret = (*pconn)->m->connect(pconn, hostname, username, password, database, port, socket_or_pipe, mysql_flags); - } - } - else { - ret = (*pconn)->m->connect(pconn, hostname, username, password, database, port, socket_or_pipe, mysql_flags); - } + } } (*pconn)->m->local_tx_end(*pconn, this_func, FAIL); } diff --git a/php_mysqlnd_azure.c b/php_mysqlnd_azure.c index 3214122..378fe96 100644 --- a/php_mysqlnd_azure.c +++ b/php_mysqlnd_azure.c @@ -26,26 +26,58 @@ #include "php_mysqlnd_azure.h" #include "ext/mysqlnd/mysqlnd_ext_plugin.h" + ZEND_DECLARE_MODULE_GLOBALS(mysqlnd_azure) + +/* {{{ OnUpdateEnableRedirect */ +static ZEND_INI_MH(OnUpdateEnableRedirect) +{ + if (zend_string_equals_literal_ci(new_value, "preferred")) { + + MYSQLND_AZURE_G(enableRedirect) = REDIRECT_PREFERRED; + + } else if (zend_string_equals_literal_ci(new_value, "1") + || zend_string_equals_literal_ci(new_value, "on") + || zend_string_equals_literal_ci(new_value, "yes") + || zend_string_equals_literal_ci(new_value, "true")) { + + MYSQLND_AZURE_G(enableRedirect) = REDIRECT_ON; + + } else if (zend_string_equals_literal_ci(new_value, "0") + || new_value->val == NULL + || new_value->val[0]==0 + || new_value->val == "off" + || new_value->val == "on" + || new_value->val == "false") { + + MYSQLND_AZURE_G(enableRedirect) = REDIRECT_OFF; + + } + + return SUCCESS; + +} +/* }}} */ + + +/* {{{ PHP_INI */ +PHP_INI_BEGIN() +STD_PHP_INI_ENTRY("mysqlnd_azure.enableRedirect", "preferred", PHP_INI_ALL, OnUpdateEnableRedirect, enableRedirect, zend_mysqlnd_azure_globals, mysqlnd_azure_globals) +PHP_INI_END() +/* }}} */ + + /* {{{ PHP_GINIT_FUNCTION */ static PHP_GINIT_FUNCTION(mysqlnd_azure) { #if defined(COMPILE_DL_MYSQLND_AZURE) && defined(ZTS) ZEND_TSRMLS_CACHE_UPDATE(); #endif - mysqlnd_azure_globals->enableRedirect = 0; + mysqlnd_azure_globals->enableRedirect = REDIRECT_PREFERRED; } /* }}} */ -/* {{{ PHP_INI */ -/* - It is handy to allow users to set the value for debug and other behavior check purpose) -*/ -PHP_INI_BEGIN() -STD_PHP_INI_ENTRY("mysqlnd_azure.enableRedirect", "0", PHP_INI_ALL, OnUpdateBool, enableRedirect, zend_mysqlnd_azure_globals, mysqlnd_azure_globals) -PHP_INI_END() -/* }}} */ /* {{{ PHP_MINIT_FUNCTION */ @@ -89,7 +121,7 @@ PHP_MINFO_FUNCTION(mysqlnd_azure) { php_info_print_table_start(); php_info_print_table_header(2, "mysqlnd_azure", "enableRedirect"); - php_info_print_table_row(2, "enableRedirect", MYSQLND_AZURE_G(enableRedirect)? "Yes":"No"); + php_info_print_table_row(2, "enableRedirect", MYSQLND_AZURE_G(enableRedirect) == REDIRECT_OFF ? "off" : (MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON ? "on" : "preferred")); php_info_print_table_end(); } /* }}} */ @@ -111,7 +143,7 @@ zend_module_entry mysqlnd_azure_module_entry = { NULL, NULL, PHP_MINFO(mysqlnd_azure), - PHP_MYSQLND_AZURE_VERSION, + PHP_MYSQLND_AZURE_VERSION, PHP_MODULE_GLOBALS(mysqlnd_azure), PHP_GINIT(mysqlnd_azure), NULL, diff --git a/php_mysqlnd_azure.h b/php_mysqlnd_azure.h index ad0dd97..7acff98 100644 --- a/php_mysqlnd_azure.h +++ b/php_mysqlnd_azure.h @@ -29,7 +29,7 @@ extern zend_module_entry mysqlnd_azure_module_entry; # define phpext_mysqlnd_azure_ptr &mysqlnd_azure_module_entry #define PHP_MYSQLND_AZURE_NAME "mysqlnd_azure" -#define PHP_MYSQLND_AZURE_VERSION "1.1.0beta1" +#define PHP_MYSQLND_AZURE_VERSION "1.1.0beta2" /* true global environment */ HashTable* redirectCache; @@ -42,11 +42,18 @@ void mysqlnd_azure_redirect_cache_lock_alloc(void); void mysqlnd_azure_redirect_cache_lock_free(void); #endif +typedef enum _mysqlnd_azure_redirect_mode { + REDIRECT_OFF = 0, /* completely disabled */ + REDIRECT_PREFERRED = 1, /* enabled without fallback, block if redirection fail */ + REDIRECT_ON = 2 /* enabled with fallback */ +} mysqlnd_azure_redirect_mode; + ZEND_BEGIN_MODULE_GLOBALS(mysqlnd_azure) - zend_bool enableRedirect; + mysqlnd_azure_redirect_mode enableRedirect; ZEND_END_MODULE_GLOBALS(mysqlnd_azure) + PHPAPI ZEND_EXTERN_MODULE_GLOBALS(mysqlnd_azure) #define MYSQLND_AZURE_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(mysqlnd_azure, v) From 5357e4412f04f04de21262929b3fe09f56aa0354 Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Fri, 6 Dec 2019 10:56:35 +0800 Subject: [PATCH 28/37] fix option set --- php_mysqlnd_azure.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/php_mysqlnd_azure.c b/php_mysqlnd_azure.c index 378fe96..dd4d23c 100644 --- a/php_mysqlnd_azure.c +++ b/php_mysqlnd_azure.c @@ -33,11 +33,12 @@ ZEND_DECLARE_MODULE_GLOBALS(mysqlnd_azure) /* {{{ OnUpdateEnableRedirect */ static ZEND_INI_MH(OnUpdateEnableRedirect) { - if (zend_string_equals_literal_ci(new_value, "preferred")) { + if (zend_string_equals_literal_ci(new_value, "preferred") + || zend_string_equals_literal_ci(new_value, "1")) { MYSQLND_AZURE_G(enableRedirect) = REDIRECT_PREFERRED; - } else if (zend_string_equals_literal_ci(new_value, "1") + } else if (zend_string_equals_literal_ci(new_value, "2") || zend_string_equals_literal_ci(new_value, "on") || zend_string_equals_literal_ci(new_value, "yes") || zend_string_equals_literal_ci(new_value, "true")) { From 86437be34308354d32d62c7501db396adaea2b52 Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Mon, 9 Dec 2019 16:36:08 +0800 Subject: [PATCH 29/37] refactor code design accordingly to pm desigin change for easier right implementation --- mysqlnd_azure.c | 294 ++++++++++++++++++++++++-------------------- php_mysqlnd_azure.c | 24 ++-- php_mysqlnd_azure.h | 4 +- 3 files changed, 170 insertions(+), 152 deletions(-) diff --git a/mysqlnd_azure.c b/mysqlnd_azure.c index a7e51fa..19ea450 100644 --- a/mysqlnd_azure.c +++ b/mysqlnd_azure.c @@ -174,6 +174,45 @@ set_redirect_client_options(MYSQLND_CONN_DATA * const conn, MYSQLND_CONN_DATA * } /* }}} */ +/* {{{ get_redirect_info */ +static zend_bool +get_redirect_info(MYSQLND_CONN_DATA * const conn, char* redirect_host, char* redirect_user, unsigned int* p_ui_redirect_port) +{ + /** + * Get redirected server information contained in OK packet. + * Redirection string somehow look like: + * Location: mysql://redirectedHostName:redirectedPort/user=redirectedUser + * the minimal len is 27 bytes + */ + if (conn->last_message.l > 27 && (strncmp((char*)conn->last_message.s, "Location:", strlen("Location:")) == 0) && ((strstr((char*)conn->last_message.s, "mysql://")) != NULL)) { + char redirect_port[8] = { 0 }; + + int redirect_total_len = conn->last_message.l; + unsigned char *cur_pos = conn->last_message.s; + char *p1 = strstr((char*)cur_pos, "//"); + char *p2 = strstr(p1, ":"); + char *p3 = strstr((char*)cur_pos, "user="); + + int redirect_host_len = p2 - p1 - 2; + int redirect_port_len = p3 - p2 - 2; + int redirect_user_len = redirect_total_len - (p3 + 5 - ((char*)cur_pos)); + if (redirect_host_len <= 0 || redirect_port_len <= 0 || redirect_user_len <= 0) { + redirect_host_len = redirect_port_len = redirect_user_len = 0; + } else { + memcpy(redirect_host, p1 + 2, redirect_host_len); + memcpy(redirect_user, p3 + 5, redirect_user_len); + memcpy(redirect_port, p2 + 1, redirect_port_len); + *p_ui_redirect_port = atoi(redirect_port); + } + + return redirect_host_len > 0 && redirect_user_len > 0 && redirect_port_len > 0; + + } else { + return FALSE; + } +} + + /* {{{ mysqlnd_azure_data::connect */ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, MYSQLND_CSTRING hostname, @@ -277,55 +316,94 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, { SET_CONNECTION_STATE(&conn->state, CONN_READY); //set ready status so the connection can be closed correctly later if redirect succeeds + DBG_ENTER("[redirect] mysqlnd_azure_data::connect::redirect"); + char redirect_host[MAX_REDIRECT_HOST_LEN] = { 0 }; + char redirect_user[MAX_REDIRECT_USER_LEN] = { 0 }; + unsigned int ui_redirect_port = 0; + zend_bool serverSupportRedirect = get_redirect_info(conn, redirect_host, redirect_user, &ui_redirect_port); + if(!serverSupportRedirect) { + if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON) { + //When REDIRECT_ON, if there is no redirection information contained in the last_message, then redirection is not possible. In this case, abort the connection + conn->m->send_close(conn); + SET_CLIENT_ERROR(conn->error_info, -1, UNKNOWN_SQLSTATE, "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol."); + DBG_ENTER("[redirect]: Server doesnot supoort redirection, Abort the connection. "); + goto err; + } else { + //REDIRECT_PREFERRED, do nothing else for redirection, just use the previous connection + DBG_ENTER("[redirect]: Server doesnot supoort redirection, do not need redirection. "); + goto after_conn; + } + } + + //Get here means serverSupportRedirect MYSQLND_AZURE_CONN_DATA** pdata = mysqlnd_azure_get_is_using_redirect(conn); - if (!(*pdata)->is_using_redirect && conn->last_message.l > 27 && (strncmp((char*)conn->last_message.s, "Location:", strlen("Location:")) == 0) && ((strstr((char*)conn->last_message.s, "mysql://")) != NULL)) { //there is a redirection connection info we can take use of - /** - * Get redirected server information contained in OK packet. - * Redirection string somehow look like: - * Location: mysql://redirectedHostName:redirectedPort/user=redirectedUser - * the minimal len is 27 bytes - */ - DBG_ENTER("[redirect] mysqlnd_azure_data::connect::redirect"); - char redirect_host[MAX_REDIRECT_HOST_LEN] = { 0 }; - char redirect_user[MAX_REDIRECT_USER_LEN] = { 0 }; - unsigned int ui_redirect_port = 0; - char redirect_port[8] = { 0 }; - - int redirect_total_len = conn->last_message.l; - unsigned char *cur_pos = conn->last_message.s; - char *p1 = strstr((char*)cur_pos, "//"); - char *p2 = strstr(p1, ":"); - char *p3 = strstr((char*)cur_pos, "user="); - - int redirect_host_len = p2 - p1 - 2; - int redirect_port_len = p3 - p2 - 2; - int redirect_user_len = redirect_total_len - (p3 + 5 - ((char*)cur_pos)); - if (redirect_host_len <= 0 || redirect_port_len <= 0 || redirect_user_len <= 0) { - redirect_host_len = redirect_port_len = redirect_user_len = 0; - } - else { - memcpy(redirect_host, p1 + 2, redirect_host_len); - memcpy(redirect_user, p3 + 5, redirect_user_len); - memcpy(redirect_port, p2 + 1, redirect_port_len); - ui_redirect_port = atoi(redirect_port); - } + //Already use redirected connection, or the connection string is a redirected on + if((*pdata)->is_using_redirect || (strcmp(redirect_host, hostname.s)==0 && strcmp(redirect_user, username.s)==0 && ui_redirect_port == port)) { + DBG_ENTER("[redirect]: Is using redirection, or redirection info are equal to origin, no need to redirect"); + goto after_conn; + } - if (redirect_host_len > 0 && redirect_user_len > 0 && redirect_port_len > 0 - && (strcmp(redirect_host, hostname.s) || strcmp(redirect_user, username.s) || ui_redirect_port != port)) { //currently used conn is not redirected connection - enum_func_status ret = FAIL; - MYSQLND* redirect_conneHandle = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, conn->persistent); //init MYSQLND but only need only MYSQLND_CONN_DATA here - MYSQLND_CONN_DATA* redirect_conn = redirect_conneHandle->data; - redirect_conneHandle->data = NULL; - mnd_pefree(redirect_conneHandle, redirect_conneHandle->persistent); - redirect_conneHandle = NULL; - - DBG_INF_FMT("[redirect]: redirect host=%s user=%s port=%s ", redirect_host, redirect_user, redirect_port); + //serverSupportRedirect, and currently used conn is not redirected connection, start redirection handshake + { + DBG_INF_FMT("[redirect]: redirect host=%s user=%s port=%d ", redirect_host, redirect_user, ui_redirect_port); + enum_func_status ret = FAIL; + MYSQLND* redirect_conneHandle = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, conn->persistent); //init MYSQLND but only need only MYSQLND_CONN_DATA here + MYSQLND_CONN_DATA* redirect_conn = redirect_conneHandle->data; + redirect_conneHandle->data = NULL; + mnd_pefree(redirect_conneHandle, redirect_conneHandle->persistent); + redirect_conneHandle = NULL; + + ret = set_redirect_client_options(conn, redirect_conn); + + //when REDIRECT_ON, fallback is not supported. Close the first connection first before establish the redirected connection + if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON) { + conn->m->send_close(conn); + conn->m->dtor(conn); + pfc = NULL; + if (transport.s) { + mnd_sprintf_free(transport.s); + transport.s = NULL; + } - ret = set_redirect_client_options(conn, redirect_conn); + //when REDIRECT_ON, previous connection has been closed, need update variable to handle both success/failure case + conn = redirect_conn; + *pconn = redirect_conn; //use new conn outside for caller + pfc = redirect_conn->protocol_frame_codec; + } - //Close the first connection first before establish the redirected connection when REDIRECT_ON + //init redirect_conn failed, if REDIRECT_ON, abort connection, if REDIRECT_PREFERRED, use the proxy connection + if (ret == FAIL) { if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON) { + SET_CLIENT_ERROR(conn->error_info, -1, UNKNOWN_SQLSTATE, "[redirect]: mysql redirect fails to copy MYSQLND_CONN_DATA. Abort the connection."); + goto err; + } + else { + //REDIRECT_PREFERRED, just use previous direct connection + redirect_conn->m->dtor(redirect_conn); + goto after_conn; + } + } + + //init redirect_conn succeeded, use this conn to start a new connection and handshake + MYSQLND_CSTRING redirect_hostname = { redirect_host, strlen(redirect_host) }; + MYSQLND_CSTRING redirect_username = { redirect_user, strlen(redirect_user) }; + MYSQLND_STRING redirect_transport = redirect_conn->m->get_scheme(redirect_conn, redirect_hostname, &socket_or_pipe, ui_redirect_port, &unix_socket, &named_pipe); + + const MYSQLND_CSTRING redirect_scheme = { redirect_transport.s, redirect_transport.l }; + + //set is_using_redirect flag + mysqlnd_azure_set_is_using_redirect(redirect_conn, 1); + + enum_func_status redirectState = redirect_conn->m->connect_handshake(redirect_conn, &redirect_scheme, &redirect_username, &password, &database, mysql_flags); + + if (redirectState == PASS) { //handshake with redirect_conn succeeded, replace original connection info with redirect_conn and add the redirect info into cache table + + //add the redirect info into cache table + mysqlnd_azure_add_redirect_cache(redirect_conn->persistent, username.s, hostname.s, port, redirect_username.s, redirect_hostname.s, ui_redirect_port); + + if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_PREFERRED) { //when REDIRECT_PREFERRED, previous proxy conn is not closed by now, need close it + //close previous proxy connection conn->m->send_close(conn); conn->m->dtor(conn); pfc = NULL; @@ -333,105 +411,48 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, mnd_sprintf_free(transport.s); transport.s = NULL; } + //upate conn, pfc, pconn for later user + conn = redirect_conn; + pfc = redirect_conn->protocol_frame_codec; + *pconn = redirect_conn; //use new conn outside for caller } - if (ret == FAIL) { //init redirect_conn failed, if REDIRECT_ON, abort connection, if REDIRECT_PREFERRED, use the proxy connection - if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON) { - redirect_conn->m->dtor(redirect_conn); - php_error_docref(NULL, E_WARNING, "[redirect]: mysql redirect fails to copy MYSQLND_CONN_DATA. Abort the connection."); - DBG_RETURN(FAIL); - } - else { - //REDIRECT_PREFERRED, just use previous direct connection, do nothing here - } - } - else { //init redirect_conn succeeded, use this conn to start a new connection and handshake - - MYSQLND_CSTRING redirect_hostname = { redirect_host, strlen(redirect_host) }; - MYSQLND_CSTRING redirect_username = { redirect_user, strlen(redirect_user) }; - MYSQLND_STRING redirect_transport = redirect_conn->m->get_scheme(redirect_conn, redirect_hostname, &socket_or_pipe, ui_redirect_port, &unix_socket, &named_pipe); - const MYSQLND_CSTRING redirect_scheme = { redirect_transport.s, redirect_transport.l }; - - if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON) { //when REDIRECT_ON, previous connection has been closed, need update variable to handle both success/failure case - //upate conn, transport, pconn for later user - conn = redirect_conn; - transport = redirect_transport; - pfc = redirect_conn->protocol_frame_codec; - *pconn = redirect_conn; //use new conn outside for caller - } + //following variable need update for both REDIRECT_PREFERRED and REDIRECT_ON + + //upate host, user, transport for later user + hostname = redirect_hostname; + username = redirect_username; + port = ui_redirect_port; + transport = redirect_transport; + + DBG_ENTER("[redirect]: mysql redirect handshake succeeded."); + + } else { //redirect failed. If REDIRECT_ON, redirect failed, fail the connection and report error; if REDIRECT_PREFERRED, use original connection information + + //clear is_using_redirect flag + mysqlnd_azure_set_is_using_redirect(redirect_conn, 0); - mysqlnd_azure_set_is_using_redirect(redirect_conn, 1); - - enum_func_status redirectState = redirect_conn->m->connect_handshake(redirect_conn, &redirect_scheme, &redirect_username, &password, &database, mysql_flags); - - if (redirectState == PASS) { //handshake with redirect_conn succeeded, replace original connection info with redirect_conn and add the redirect info into cache table - - //add the redirect info into cache table - mysqlnd_azure_add_redirect_cache(redirect_conn->persistent, username.s, hostname.s, port, redirect_username.s, redirect_hostname.s, ui_redirect_port); - - if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_PREFERRED) { - //close previous proxy connection - conn->m->send_close(conn); - conn->m->dtor(conn); - pfc = NULL; - if (transport.s) { - mnd_sprintf_free(transport.s); - transport.s = NULL; - } - //upate conn, transport, pconn for later user - conn = redirect_conn; - transport = redirect_transport; - pfc = redirect_conn->protocol_frame_codec; - *pconn = redirect_conn; //use new conn outside for caller - } - - ///upate host, user, pfc for later user - hostname = redirect_hostname; - username = redirect_username; - port = ui_redirect_port; - - DBG_ENTER("[redirect]: mysql redirect handshake succeeded."); - } - else { //redirect failed - if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_PREFERRED) { - //REDIRECT_PREFERRED, redirect failed, use original connection information - redirect_conn->m->dtor(redirect_conn); - if (redirect_transport.s) { - mnd_sprintf_free(redirect_transport.s); - redirect_transport.s = NULL; - } - DBG_ENTER("[redirect]: mysql redirect handshake fails, use original connection information!"); - } - else { - goto err; //REDIRECT_ON, redirect failed, fail the connection and report error - } + if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_PREFERRED) { + //free resource, and use original connection information + redirect_conn->m->dtor(redirect_conn); + if (redirect_transport.s) { + mnd_sprintf_free(redirect_transport.s); + redirect_transport.s = NULL; } - } - } - else { - DBG_ENTER("[redirect]: redirection info are equal to origin, no need to redirect"); - } - } - else if (!(*pdata)->is_using_redirect && MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON) { //!is_using_redirect, but does not find redirection info in last_message - //When REDIRECT_ON, if there is no redirection information contained in the last_message, then redirection is not possible. In this case, abort the connection - php_error_docref(NULL, E_WARNING, "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol."); - conn->m->send_close(conn); - conn->m->dtor(conn); - pfc = NULL; - - if (transport.s) { - mnd_sprintf_free(transport.s); - transport.s = NULL; - } + DBG_ENTER("[redirect]: mysql redirect handshake fails, use original connection information!"); + } else { //REDIRECT_ON - DBG_RETURN(FAIL); - } - else { - DBG_ENTER("[redirect]: already use redirection info or do not find redrection information."); + DBG_ENTER("[redirect]: mysql redirect handshake fails, report error"); + goto err; //REDIRECT_ON, redirect failed, fail the connection and report error + + } + } } + } /*end of Azure Redirection Logic*/ +after_conn: { SET_CONNECTION_STATE(&conn->state, CONN_READY); @@ -595,8 +616,9 @@ MYSQLND_METHOD(mysqlnd_azure, connect)(MYSQLND * conn_handle, unsigned int temp_flags = (*pconn)->m->get_updated_connect_flags(*pconn, mysql_flags); if(!(temp_flags & CLIENT_SSL)) { if((MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON)) { - php_error_docref(NULL, E_WARNING, "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL."); - DBG_RETURN(FAIL); + SET_CLIENT_ERROR((*pconn)->error_info, -1, UNKNOWN_SQLSTATE, "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL."); + (*pconn)->m->free_contents(*pconn); + ret = FAIL; } else { ret = org_conn_d_m.connect(*pconn, hostname, username, password, database, port, socket_or_pipe, mysql_flags); @@ -627,7 +649,9 @@ MYSQLND_METHOD(mysqlnd_azure, connect)(MYSQLND * conn_handle, } } + (*pconn)->m->local_tx_end(*pconn, this_func, FAIL); + } DBG_RETURN(ret); } diff --git a/php_mysqlnd_azure.c b/php_mysqlnd_azure.c index dd4d23c..294431a 100644 --- a/php_mysqlnd_azure.c +++ b/php_mysqlnd_azure.c @@ -26,35 +26,29 @@ #include "php_mysqlnd_azure.h" #include "ext/mysqlnd/mysqlnd_ext_plugin.h" - ZEND_DECLARE_MODULE_GLOBALS(mysqlnd_azure) /* {{{ OnUpdateEnableRedirect */ static ZEND_INI_MH(OnUpdateEnableRedirect) { - if (zend_string_equals_literal_ci(new_value, "preferred") - || zend_string_equals_literal_ci(new_value, "1")) { + if ((ZSTR_LEN(new_value) == 9 && strcasecmp("preferred", ZSTR_VAL(new_value)) == 0) + || (ZSTR_LEN(new_value) == 1 && strcasecmp("2", ZSTR_VAL(new_value)) == 0)) { - MYSQLND_AZURE_G(enableRedirect) = REDIRECT_PREFERRED; + MYSQLND_AZURE_G(enableRedirect) = REDIRECT_PREFERRED; - } else if (zend_string_equals_literal_ci(new_value, "2") - || zend_string_equals_literal_ci(new_value, "on") - || zend_string_equals_literal_ci(new_value, "yes") - || zend_string_equals_literal_ci(new_value, "true")) { + } else if ((ZSTR_LEN(new_value) == 2 && strcasecmp("on", ZSTR_VAL(new_value)) == 0) + || (ZSTR_LEN(new_value) == 3 && strcasecmp("yes", ZSTR_VAL(new_value)) == 0) + || (ZSTR_LEN(new_value) == 4 && strcasecmp("true", ZSTR_VAL(new_value)) == 0) + || (ZSTR_LEN(new_value) == 1 && strcasecmp("1", ZSTR_VAL(new_value)) == 0)) { MYSQLND_AZURE_G(enableRedirect) = REDIRECT_ON; - } else if (zend_string_equals_literal_ci(new_value, "0") - || new_value->val == NULL - || new_value->val[0]==0 - || new_value->val == "off" - || new_value->val == "on" - || new_value->val == "false") { + } else { MYSQLND_AZURE_G(enableRedirect) = REDIRECT_OFF; - } + } return SUCCESS; diff --git a/php_mysqlnd_azure.h b/php_mysqlnd_azure.h index 7acff98..3b5f5c5 100644 --- a/php_mysqlnd_azure.h +++ b/php_mysqlnd_azure.h @@ -44,8 +44,8 @@ void mysqlnd_azure_redirect_cache_lock_free(void); typedef enum _mysqlnd_azure_redirect_mode { REDIRECT_OFF = 0, /* completely disabled */ - REDIRECT_PREFERRED = 1, /* enabled without fallback, block if redirection fail */ - REDIRECT_ON = 2 /* enabled with fallback */ + REDIRECT_ON = 1, /* enabled with fallback */ + REDIRECT_PREFERRED = 2 /* enabled without fallback, block if redirection fail */ } mysqlnd_azure_redirect_mode; From 738bae5097a86ffa008c1245a70a5d4f0d403dc8 Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Tue, 10 Dec 2019 11:36:02 +0800 Subject: [PATCH 30/37] update and add new test cases accordingly --- tests/mysqli_azure_redirection_disabled.phpt | 38 ---------- tests/mysqli_azure_redirection_enabled.phpt | 38 ---------- tests/mysqli_azure_redirection_off.phpt | 72 +++++++++++++++++++ tests/mysqli_azure_redirection_on.phpt | 68 ++++++++++++++++++ tests/mysqli_azure_redirection_preferred.phpt | 72 +++++++++++++++++++ tests/skipifconnectfailure.inc | 16 ----- 6 files changed, 212 insertions(+), 92 deletions(-) delete mode 100644 tests/mysqli_azure_redirection_disabled.phpt delete mode 100644 tests/mysqli_azure_redirection_enabled.phpt create mode 100644 tests/mysqli_azure_redirection_off.phpt create mode 100644 tests/mysqli_azure_redirection_on.phpt create mode 100644 tests/mysqli_azure_redirection_preferred.phpt delete mode 100644 tests/skipifconnectfailure.inc diff --git a/tests/mysqli_azure_redirection_disabled.phpt b/tests/mysqli_azure_redirection_disabled.phpt deleted file mode 100644 index 70d2fe7..0000000 --- a/tests/mysqli_azure_redirection_disabled.phpt +++ /dev/null @@ -1,38 +0,0 @@ ---TEST-- -Azure redirection test for servers with mysqlnd_azure.enableRedirect=0 ---INI-- -mysqlnd_azure.enableRedirect=0 ---SKIPIF-- - ---FILE-- -host_info."\n"; -echo $link->info."\n"; -if(substr($link->host_info, 0, strlen($host)) == $host) - echo "1\n"; -else - echo "0\n"; -mysqli_close($link); -echo "Done\n"; -?> ---EXPECTF-- -%s -Location: mysql://%s:%d/user=%s@%s -1 -Done diff --git a/tests/mysqli_azure_redirection_enabled.phpt b/tests/mysqli_azure_redirection_enabled.phpt deleted file mode 100644 index dfe3baa..0000000 --- a/tests/mysqli_azure_redirection_enabled.phpt +++ /dev/null @@ -1,38 +0,0 @@ ---TEST-- -Azure redirection test for servers when mysqlnd_azure.enableRedirect ---INI-- -mysqlnd_azure.enableRedirect=1 ---SKIPIF-- - ---FILE-- -host_info."\n"; -echo $link->info."\n"; -if(substr($link->host_info, 0, strlen($host)) == $host) - echo "1\n"; -else - echo "0\n"; -mysqli_close($link); -echo "Done\n"; -?> ---EXPECTF-- -%s -Location: mysql://%s:%d/user=%s@%s -0 -Done diff --git a/tests/mysqli_azure_redirection_off.phpt b/tests/mysqli_azure_redirection_off.phpt new file mode 100644 index 0000000..517c28d --- /dev/null +++ b/tests/mysqli_azure_redirection_off.phpt @@ -0,0 +1,72 @@ +--TEST-- +Azure redirection test for servers when mysqlnd_azure.enableRedirect="off" +--INI-- +mysqlnd_azure.enableRedirect="off" +--SKIPIF-- + +--FILE-- +host_info."\n"; +$last_message = $link->info; + +//Server supports redirection +if(strlen($last_message) > 27 && strcmp(substr($last_message, 0, strlen("Location:")), "Location:")==0) { + if(substr($link->host_info, 0, strlen($host)) == $host) + echo "[003] pass\n"; + else + echo "[003] fail\n"; +} +else { //Server does not support redirection, use the proxy connection + if(substr($link->host_info, 0, strlen($host)) == $host) + echo "[003] pass\n"; + else + echo "[003] fail\n"; +} + +mysqli_close($link); + +//Step 3: check connection result when not use SSL +$link = mysqli_init(); +$ret = @mysqli_real_connect($link, $host, $user, $passwd, $db, $port, NULL, NULL); +if (!$ret || !is_object($link)) +{ + printf("[004] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n - [%d] %s without ssl\n", + $host, $user, $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error()); + die(); +} + +if(substr($link->host_info, 0, strlen($host)) == $host) + echo "[004] pass\n"; +else + echo "[004] fail\n"; + +echo "Done\n"; +?> +--EXPECTF-- +off +%s +[003] pass +[004] pass +Done diff --git a/tests/mysqli_azure_redirection_on.phpt b/tests/mysqli_azure_redirection_on.phpt new file mode 100644 index 0000000..e136865 --- /dev/null +++ b/tests/mysqli_azure_redirection_on.phpt @@ -0,0 +1,68 @@ +--TEST-- +Azure redirection test for servers when mysqlnd_azure.enableRedirect="on" +--INI-- +mysqlnd_azure.enableRedirect="on" +--SKIPIF-- + +--FILE-- +info; + +//Server supports redirection +if(strlen($last_message) > 27 && strcmp(substr($last_message, 0, strlen("Location:")), "Location:")==0) { + if(substr($link->host_info, 0, strlen($host)) == $host) + echo "[003] fail\n"; + else + echo "[003] pass\n"; +} +else { //Server does not support redirection + $lastError = error_get_last()["message"]; + if (strpos($lastError, "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol.") !== false) + echo "[003] pass\n"; + else + echo "[003] fail\n"; +} + +mysqli_close($link); + +//Step 3: check connection result when not use SSL +$link = mysqli_init(); +$ret = @mysqli_real_connect($link, $host, $user, $passwd, $db, $port, NULL, NULL); +if ($ret) +{ + printf("[004] When enableRedirect=on, connect without SSL expects failure, got pass\n"); + die(); +} + +$lastError = error_get_last()["message"]; +if (strpos($lastError, "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL.") !== false) + echo "[004] pass\n"; + else + echo "[004] fail\n"; + +echo "Done\n"; +?> +--EXPECTF-- +on +[003] pass +[004] pass +Done diff --git a/tests/mysqli_azure_redirection_preferred.phpt b/tests/mysqli_azure_redirection_preferred.phpt new file mode 100644 index 0000000..76f5df3 --- /dev/null +++ b/tests/mysqli_azure_redirection_preferred.phpt @@ -0,0 +1,72 @@ +--TEST-- +Azure redirection test for servers when mysqlnd_azure.enableRedirect="preferred" +--INI-- +mysqlnd_azure.enableRedirect="preferred" +--SKIPIF-- + +--FILE-- +host_info."\n"; +$last_message = $link->info; + +//Server supports redirection +if(strlen($last_message) > 27 && strcmp(substr($last_message, 0, strlen("Location:")), "Location:")==0) { + if(substr($link->host_info, 0, strlen($host)) == $host) + echo "[003] fail\n"; + else + echo "[003] pass\n"; +} +else { //Server does not support redirection, use the proxy connection + if(substr($link->host_info, 0, strlen($host)) == $host) + echo "[003] pass\n"; + else + echo "[003] fail\n"; +} + +mysqli_close($link); + +//Step 3: check connection result when not use SSL +$link = mysqli_init(); +$ret = @mysqli_real_connect($link, $host, $user, $passwd, $db, $port, NULL, NULL); +if (!$ret || !is_object($link)) +{ + printf("[004] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n - [%d] %s without ssl\n", + $host, $user, $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error()); + die(); +} + +if(substr($link->host_info, 0, strlen($host)) == $host) + echo "[004] pass\n"; +else + echo "[004] fail\n"; + +echo "Done\n"; +?> +--EXPECTF-- +preferred +%s +[003] pass +[004] pass +Done diff --git a/tests/skipifconnectfailure.inc b/tests/skipifconnectfailure.inc deleted file mode 100644 index 87adc0d..0000000 --- a/tests/skipifconnectfailure.inc +++ /dev/null @@ -1,16 +0,0 @@ -info || substr( $link->info, 0, 18 ) != "Location: mysql://") { - mysqli_close($link); - die("skip this mysql server does not support redirection, do not find valid redirection info"); - } - mysqli_close($link); -?> From f7f61bb2beea0ee6f380f09fb54f409a0391c017 Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Tue, 10 Dec 2019 13:40:22 +0800 Subject: [PATCH 31/37] update document, package and version --- Notes.txt | 21 +++++++++++++++++-- README.md | 49 +++++++++++++++++++++++++++------------------ package.xml | 30 ++++++++++++++++----------- php_mysqlnd_azure.h | 2 +- 4 files changed, 67 insertions(+), 35 deletions(-) diff --git a/Notes.txt b/Notes.txt index 9ac4083..88fe759 100644 --- a/Notes.txt +++ b/Notes.txt @@ -10,6 +10,23 @@ connection, and use the new one afterward. OPTION DESCRIPTION ------------------ ---------------------------------------------------------- mysqlnd_azure.enableRedirect This option is to control enable or disable redirection feature of mysqlnd_azure. -If this is set to 0, it will not use redirection. -(Default: 0) +If this is set to off, it will not use redirection. + +Available option values: +(Default: off) +---------------------------------------------------------------------------------------------------------------------------------------------------------- +off(0) | - It will not use redirection. +---------------------------------------------------------------------------------------------------------------------------------------------------------- +on(1) | - If ssl is off, no connection will be made, return error: + | "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." + | - If on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error: + | "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." + | - If server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. + | Return the error of the redirected connection. +---------------------------------------------------------------------------------------------------------------------------------------------------------- +preferred(2) | - it will use redirection if possible. + | - If connection does not use SSL, or server does not support redirection, or redirected connection fails + | to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback + | to the first proxy connection. +---------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/README.md b/README.md index c17840b..192d4fb 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,25 @@ The source code here is a PHP extension implemented using mysqlnd plugin API (ht In 1.0.x versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. Since 1.1.0beta1, the logic changes as follows: -- If redirection is on, ssl is off, no connection will be made, it will return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." -- If redirection is on, but on server side redirection is not supported/needed (e.g. a community verion mysql installed locally), and there is no last message in OK packet, it will abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." -- If redirected connection failed for any reason, it will also abort the first proxy connection, and return the error of the redirected connection. - -``` -Ask from you: -In version 1.1.0beta1, we add many restrictions when the feature is turned on, but fallback is then not possible anymore. We also want to hear from you that given the following two options, what will you prefer: - 1. Add another option with name "preferred" with fallback support (i.e. go without redirection if SSL is not used, or server does not support redirection, or server does not need redirection). - 2. Remove the restrictions when redrection is turned on, still use the fallback logic as a single solution (i.e. redirect when posssible, and go without redirection if SSL is not used, or server does not support redirection, or server does not need redirection). - -You may vote for your preference by giving comment on issue page on github or send email to the people of maintenance which you can find in the file named with package.xml. -``` +- The option mysqlnd_azure.enabled is renamed to mysqlnd_azure.enableRedirect, and there is a new option value "preferred" provided. +- The detailed usage of the option enableRedirect is as follows: + +(Default: off) +---------------------------------------------------------------------------------------------------------------------------------------------------------- +off(0) | - It will not use redirection. +---------------------------------------------------------------------------------------------------------------------------------------------------------- +on(1) | - If ssl is off, no connection will be made, return error: + | "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." + | - If on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error: + | "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." + | - If server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. + | Return the error of the redirected connection. +---------------------------------------------------------------------------------------------------------------------------------------------------------- +preferred(2) | - it will use redirection if possible. + | - If connection does not use SSL, or server does not support redirection, or redirected connection fails + | to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback + | to the first proxy connection. +---------------------------------------------------------------------------------------------------------------------------------------------------------- ## Name and Extension Version Extension name: **mysqlnd_azure** @@ -28,11 +35,13 @@ Valid version: - 1.0.0 Change: initial version. Limitation: cannot install with pecl on linux, the package on PECL website is invalid, only possible to install with manual compilation on Linux. Cannot work with 7.2.23+ and 7.3.10+ - 1.0.1 Change: with pecl install command line support on linux. Limitation: cannot work with 7.2.23+ and 7.3.10+ - 1.0.2 Change: fix compatibility problem with 7.2.23+ and 7.3.10+ -- 1.1.0Beta Change: In 1.0.x versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. Since 1.1.0Beta, the logic changes as follows: - 1. If redirection is on, ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." - 2. If redirection is on, but on server side redirection is not supported/needed, and there is no last message in OK packet, abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." - 3. If redirected connection failed for any reason, it will also abort the first proxy connection, and return the error of the redirected connection. - 4. The option mysqlnd_azure.enabled is also renamed to mysqlnd_azure.enableRedirect. +- 1.1.0beta1 Change: In 1.0.x versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. Since 1.1.0beta1, the logic changes as follows: + 1. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect, and add a new option value "preferred". + 2. When enableRedirect is "preferred", it will use redirection if possible. If connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. + 3. If enableRedirect is with value "on", ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." + 4. If enableRedirect is with value "on", but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." + 5. If enableRedirect is with value "on" and server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection. + 6. The cache implementation has been changed from module global to true global to improve share range for multi-thread scenario. Following is a brief guide of how to install using pecl or build and test the extension from source. @@ -108,7 +117,7 @@ Then you can run **make install** to put the .so to your php so library. However - put mysqlnd_azure.so under extension_dir. - under directory for additional .ini files, you will find the ini files for the common used modules, e.g. 10-mysqlnd.ini for mysqlnd, 20-mysqli.ini for mysqli. Create a new ini file for mysqlnd_azure here. **Make sure the alphabet order of the name is after that of mysqnld**, since the modules are loaded according to the name order of the ini files. E.g. if mysqlnd ini is with name 10-mysqlnd.ini,then name the ini as 20-mysqlnd-azure.ini. In the ini file, add the following two lines: - extension=mysqlnd_azure - - mysqlnd_azure.enableRedirect = on ; you can also set this to off to disable redirection. + - mysqlnd_azure.enableRedirect = on/off/preferred - **Notice:** since 1.1.0beta1, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. @@ -155,7 +164,7 @@ After this, the code directory should look like C:\php-sdk\phpdev\vc15\x64\php-s - extension=mysqlnd_azure - Under the Module Settings section add: - [mysqlnd_azure] - - mysqlnd_azure.enableRedirect = on + - mysqlnd_azure.enableRedirect = on/off/preferred - **Notice:** since 1.1.0beta1, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. @@ -163,7 +172,7 @@ After this, the code directory should look like C:\php-sdk\phpdev\vc15\x64\php-s * Currently redirection is only possible when the connection is via ssl, and it need that the redirection feature switch is enabled on server side. Following is a snippet to test connection with redirection: ```php - echo "mysqlnd_azure.enableRedirect: ", ini_get("mysqlnd_azure.enableRedirect") == true?"On":"Off", "\n"; + echo "mysqlnd_azure.enableRedirect: ", ini_get("mysqlnd_azure.enableRedirect"), "\n"; $db = mysqli_init(); //The connection must be configured with SSL for redirection test $link = mysqli_real_connect ($db, 'your-hostname-with-redirection-enabled', 'user@host', 'password', "db", 3306, NULL, MYSQLI_CLIENT_SSL); diff --git a/package.xml b/package.xml index c39530c..319f22b 100644 --- a/package.xml +++ b/package.xml @@ -16,7 +16,7 @@ Qianqian.Bu@microsoft.com yes - 2019-12-05 + 2019-12-10 1.1.0beta1 @@ -29,9 +29,12 @@ PHP License - 1. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect. -- 2. If enableRedirect is on, ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." -- 3. If enableRedirect is on, but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." -- 4. If enableRedirect is on and server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection. +- 2. If enableRedirect is with value "on", ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." +- 3. If enableRedirect is with value "on", but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." +- 4. If enableRedirect is with value "on" and server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection. +- 5. A new option for mysqlnd_azure.enableRedirect is introduced with name "preferred". When enableRedirect is "preferred", it will use redirection if possible. + If connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. +- 6. The cache implementation has been changed from module global to true global to improve share range for multi-thread scenario. @@ -42,11 +45,11 @@ - - + + + - @@ -77,13 +80,16 @@ beta beta - 2019-12-05 + 2019-12-10 PHP License -- 1. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect. -- 2. If enableRedirect is on, ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." -- 3. If enableRedirect is on, but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "No redirection information available, redirection is not possible. Abort the connection." -- 4. If enableRedirect is on and server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection. +- 1. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect, and add a new option value "preferred". +- 2. If enableRedirect is with value "on", ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." +- 3. If enableRedirect is with value "on", but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." +- 4. If enableRedirect is with value "on" and server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection. +- 5. A new option for mysqlnd_azure.enableRedirect is introduced with name "preferred". When enableRedirect is "preferred", it will use redirection if possible. + If connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. +- 6. The cache implementation has been changed from module global to true global to improve share range for multi-thread scenario. diff --git a/php_mysqlnd_azure.h b/php_mysqlnd_azure.h index 3b5f5c5..15887e2 100644 --- a/php_mysqlnd_azure.h +++ b/php_mysqlnd_azure.h @@ -29,7 +29,7 @@ extern zend_module_entry mysqlnd_azure_module_entry; # define phpext_mysqlnd_azure_ptr &mysqlnd_azure_module_entry #define PHP_MYSQLND_AZURE_NAME "mysqlnd_azure" -#define PHP_MYSQLND_AZURE_VERSION "1.1.0beta2" +#define PHP_MYSQLND_AZURE_VERSION "1.1.0beta1" /* true global environment */ HashTable* redirectCache; From 4b26066f46fa07287b724bc46d47071cba3820f7 Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Tue, 10 Dec 2019 13:45:29 +0800 Subject: [PATCH 32/37] update format --- Notes.txt | 8 ++++---- README.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Notes.txt b/Notes.txt index 88fe759..bffa132 100644 --- a/Notes.txt +++ b/Notes.txt @@ -14,19 +14,19 @@ If this is set to off, it will not use redirection. Available option values: (Default: off) ----------------------------------------------------------------------------------------------------------------------------------------------------------- +---------------|------------------------------------------------------------------------------------------------------------------------------------------ off(0) | - It will not use redirection. ----------------------------------------------------------------------------------------------------------------------------------------------------------- +---------------|------------------------------------------------------------------------------------------------------------------------------------------ on(1) | - If ssl is off, no connection will be made, return error: | "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." | - If on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error: | "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." | - If server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. | Return the error of the redirected connection. ----------------------------------------------------------------------------------------------------------------------------------------------------------- +---------------|------------------------------------------------------------------------------------------------------------------------------------------ preferred(2) | - it will use redirection if possible. | - If connection does not use SSL, or server does not support redirection, or redirected connection fails | to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback | to the first proxy connection. ----------------------------------------------------------------------------------------------------------------------------------------------------------- +---------------|------------------------------------------------------------------------------------------------------------------------------------------ diff --git a/README.md b/README.md index 192d4fb..005dce9 100644 --- a/README.md +++ b/README.md @@ -10,21 +10,21 @@ Since 1.1.0beta1, the logic changes as follows: - The detailed usage of the option enableRedirect is as follows: (Default: off) ----------------------------------------------------------------------------------------------------------------------------------------------------------- +---------------|------------------------------------------------------------------------------------------------------------------------------------------ off(0) | - It will not use redirection. ----------------------------------------------------------------------------------------------------------------------------------------------------------- +---------------|------------------------------------------------------------------------------------------------------------------------------------------ on(1) | - If ssl is off, no connection will be made, return error: | "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." | - If on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error: | "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." | - If server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. | Return the error of the redirected connection. ----------------------------------------------------------------------------------------------------------------------------------------------------------- +---------------|------------------------------------------------------------------------------------------------------------------------------------------ preferred(2) | - it will use redirection if possible. | - If connection does not use SSL, or server does not support redirection, or redirected connection fails | to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback | to the first proxy connection. ----------------------------------------------------------------------------------------------------------------------------------------------------------- +---------------|------------------------------------------------------------------------------------------------------------------------------------------ ## Name and Extension Version Extension name: **mysqlnd_azure** From c7ca7338182fcbd47489217f4603af1753f0da0c Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Tue, 10 Dec 2019 14:09:38 +0800 Subject: [PATCH 33/37] Update README.md --- README.md | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 005dce9..fabda29 100644 --- a/README.md +++ b/README.md @@ -10,21 +10,29 @@ Since 1.1.0beta1, the logic changes as follows: - The detailed usage of the option enableRedirect is as follows: (Default: off) ----------------|------------------------------------------------------------------------------------------------------------------------------------------ -off(0) | - It will not use redirection. ----------------|------------------------------------------------------------------------------------------------------------------------------------------ -on(1) | - If ssl is off, no connection will be made, return error: - | "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." - | - If on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error: - | "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." - | - If server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. - | Return the error of the redirected connection. ----------------|------------------------------------------------------------------------------------------------------------------------------------------ -preferred(2) | - it will use redirection if possible. - | - If connection does not use SSL, or server does not support redirection, or redirected connection fails - | to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback - | to the first proxy connection. ----------------|------------------------------------------------------------------------------------------------------------------------------------------ + + + + + + + + + + + + + + +
off(0) - It will not use redirection.
on(1) - If SSL is off, no connection will be made, return error: + "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL."
+ - If on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error: "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol."
+ - If server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection. +
+preferred(2) + - It will use redirection if possible.
+ - If connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. +
## Name and Extension Version Extension name: **mysqlnd_azure** @@ -169,7 +177,7 @@ After this, the code directory should look like C:\php-sdk\phpdev\vc15\x64\php-s ## Test -* Currently redirection is only possible when the connection is via ssl, and it need that the redirection feature switch is enabled on server side. Following is a snippet to test connection with redirection: +* Currently redirection is only possible when the connection is configured with SSL, and it need that the redirection is supported and enabled on server side. Following is a snippet to test connection with redirection: ```php echo "mysqlnd_azure.enableRedirect: ", ini_get("mysqlnd_azure.enableRedirect"), "\n"; From 7b1935f6bee2ad57d70f073ce6fac7c7da61e560 Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Tue, 10 Dec 2019 14:11:36 +0800 Subject: [PATCH 34/37] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fabda29..60e874b 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Valid version: - 1.1.0beta1 Change: In 1.0.x versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. Since 1.1.0beta1, the logic changes as follows: 1. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect, and add a new option value "preferred". 2. When enableRedirect is "preferred", it will use redirection if possible. If connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. - 3. If enableRedirect is with value "on", ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." + 3. If enableRedirect is with value "on", SSL is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." 4. If enableRedirect is with value "on", but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." 5. If enableRedirect is with value "on" and server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection. 6. The cache implementation has been changed from module global to true global to improve share range for multi-thread scenario. From 5f17bdc1f09aac5311f8d8fc815da54f531f414f Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Tue, 10 Dec 2019 15:04:03 +0800 Subject: [PATCH 35/37] Update README.md --- README.md | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 60e874b..9178af8 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,28 @@ The source code here is a PHP extension implemented using mysqlnd plugin API (ht **Important notice: There is a limitation that for Azure MySQL, redirection is only possible when the connection is configured with SSL.** -In 1.0.x versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. +In 1.0.x versions, when redirection is turned on, but if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. The detailed usage of the option enableRedirect is as follows: + +(Config name: **mysqlnd_azure.enableRedirect**. Valid value: on/off. Default value: off) + + + + + + + + + + +
off(0) - It will not use redirection.
on(1) - It will use redirection if possible (Connection is with SSL and Server supports/need redirection).
+ - If connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. +
Since 1.1.0beta1, the logic changes as follows: -- The option mysqlnd_azure.enabled is renamed to mysqlnd_azure.enableRedirect, and there is a new option value "preferred" provided. +- The option mysqlnd_azure.enabled is renamed to **mysqlnd_azure.enableRedirect**, and there is a new option value "preferred" provided. - The detailed usage of the option enableRedirect is as follows: -(Default: off) +(Config name: **mysqlnd_azure.enableRedirect**. Valid value: on/off/preferred. Default value: off) @@ -20,7 +35,7 @@ Since 1.1.0beta1, the logic changes as follows: @@ -47,7 +62,7 @@ Valid version: 1. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect, and add a new option value "preferred". 2. When enableRedirect is "preferred", it will use redirection if possible. If connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. 3. If enableRedirect is with value "on", SSL is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." - 4. If enableRedirect is with value "on", but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." + 4. If enableRedirect is with value "on", but on server side redirection is not supported, abort the first connection and return error "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." 5. If enableRedirect is with value "on" and server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection. 6. The cache implementation has been changed from module global to true global to improve share range for multi-thread scenario. From f2ae3ffe80ea51a9c127f488baa2725a859fb1c1 Mon Sep 17 00:00:00 2001 From: GuuBu <46982854+GuuBu@users.noreply.github.com> Date: Tue, 10 Dec 2019 15:09:16 +0800 Subject: [PATCH 36/37] Update README.md --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9178af8..d884884 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,11 @@ The source code here is a PHP extension implemented using mysqlnd plugin API (ht **Important notice: There is a limitation that for Azure MySQL, redirection is only possible when the connection is configured with SSL.** +## Option Usage + In 1.0.x versions, when redirection is turned on, but if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. The detailed usage of the option enableRedirect is as follows: -(Config name: **mysqlnd_azure.enableRedirect**. Valid value: on/off. Default value: off) +(Version 1.0.x. Config name: **mysqlnd_azure.enableRedirect**. Valid value: on/off. Default value: off)
off(0)on(1) - If SSL is off, no connection will be made, return error: "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL."
- - If on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error: "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol."
+ - If on server side redirection is not supported, abort the first connection and return error: "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol."
- If server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection.
@@ -24,7 +26,7 @@ Since 1.1.0beta1, the logic changes as follows: - The option mysqlnd_azure.enabled is renamed to **mysqlnd_azure.enableRedirect**, and there is a new option value "preferred" provided. - The detailed usage of the option enableRedirect is as follows: -(Config name: **mysqlnd_azure.enableRedirect**. Valid value: on/off/preferred. Default value: off) +(Version 1.1.0beta1. Config name: **mysqlnd_azure.enableRedirect**. Valid value: on/off/preferred. Default value: off)
off(0)
@@ -141,7 +143,7 @@ Then you can run **make install** to put the .so to your php so library. However - under directory for additional .ini files, you will find the ini files for the common used modules, e.g. 10-mysqlnd.ini for mysqlnd, 20-mysqli.ini for mysqli. Create a new ini file for mysqlnd_azure here. **Make sure the alphabet order of the name is after that of mysqnld**, since the modules are loaded according to the name order of the ini files. E.g. if mysqlnd ini is with name 10-mysqlnd.ini,then name the ini as 20-mysqlnd-azure.ini. In the ini file, add the following two lines: - extension=mysqlnd_azure - mysqlnd_azure.enableRedirect = on/off/preferred - - **Notice:** since 1.1.0beta1, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. + - **Notice:** since 1.1.0beta1, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. Please check the Option Usage section for detailed information. ## Step to build on Windows @@ -188,7 +190,7 @@ After this, the code directory should look like C:\php-sdk\phpdev\vc15\x64\php-s - Under the Module Settings section add: - [mysqlnd_azure] - mysqlnd_azure.enableRedirect = on/off/preferred - - **Notice:** since 1.1.0beta1, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. + - **Notice:** since 1.1.0beta1, if this value is set to on, the connection must be configured with SSL, and it requires server support redirection. Otherwise, the connection will fail. Please check the Option Usage section for detailed information. ## Test From d3b85bc05c1db1c995a0c57301f44d689897effb Mon Sep 17 00:00:00 2001 From: Qianqian Bu Date: Fri, 13 Dec 2019 10:21:20 +0800 Subject: [PATCH 37/37] update error message according to PR review --- Notes.txt | 4 ++-- README.md | 10 +++++----- mysqlnd_azure.c | 4 ++-- package.xml | 8 ++++---- tests/mysqli_azure_redirection_on.phpt | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Notes.txt b/Notes.txt index bffa132..df70f20 100644 --- a/Notes.txt +++ b/Notes.txt @@ -18,9 +18,9 @@ Available option values: off(0) | - It will not use redirection. ---------------|------------------------------------------------------------------------------------------------------------------------------------------ on(1) | - If ssl is off, no connection will be made, return error: - | "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." + | "mysqlnd_azure.enableRedirect is on, but SSL option is not set in connection string. Redirection is only possible with SSL." | - If on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error: - | "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." + | "Connection aborted because redirection is not enabled on the MySQL server or the network package doesn't meet meet redirection protocol." | - If server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. | Return the error of the redirected connection. ---------------|------------------------------------------------------------------------------------------------------------------------------------------ diff --git a/README.md b/README.md index d884884..74ef439 100644 --- a/README.md +++ b/README.md @@ -36,8 +36,8 @@ Since 1.1.0beta1, the logic changes as follows: @@ -63,8 +63,8 @@ Valid version: - 1.1.0beta1 Change: In 1.0.x versions, if connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. Since 1.1.0beta1, the logic changes as follows: 1. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect, and add a new option value "preferred". 2. When enableRedirect is "preferred", it will use redirection if possible. If connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. - 3. If enableRedirect is with value "on", SSL is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." - 4. If enableRedirect is with value "on", but on server side redirection is not supported, abort the first connection and return error "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." + 3. If enableRedirect is with value "on", SSL is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set in connection string. Redirection is only possible with SSL." + 4. If enableRedirect is with value "on", but on server side redirection is not supported, abort the first connection and return error "Connection aborted because redirection is not enabled on the MySQL server or the network package doesn't meet meet redirection protocol." 5. If enableRedirect is with value "on" and server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection. 6. The cache implementation has been changed from module global to true global to improve share range for multi-thread scenario. @@ -210,4 +210,4 @@ After this, the code directory should look like C:\php-sdk\phpdev\vc15\x64\php-s print_r ($res); $db->close(); } -``` +``` \ No newline at end of file diff --git a/mysqlnd_azure.c b/mysqlnd_azure.c index 19ea450..2996e22 100644 --- a/mysqlnd_azure.c +++ b/mysqlnd_azure.c @@ -325,7 +325,7 @@ MYSQLND_METHOD(mysqlnd_azure_data, connect)(MYSQLND_CONN_DATA ** pconn, if(MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON) { //When REDIRECT_ON, if there is no redirection information contained in the last_message, then redirection is not possible. In this case, abort the connection conn->m->send_close(conn); - SET_CLIENT_ERROR(conn->error_info, -1, UNKNOWN_SQLSTATE, "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol."); + SET_CLIENT_ERROR(conn->error_info, -1, UNKNOWN_SQLSTATE, "Connection aborted because redirection is not enabled on the MySQL server or the network package doesn't meet meet redirection protocol."); DBG_ENTER("[redirect]: Server doesnot supoort redirection, Abort the connection. "); goto err; } else { @@ -616,7 +616,7 @@ MYSQLND_METHOD(mysqlnd_azure, connect)(MYSQLND * conn_handle, unsigned int temp_flags = (*pconn)->m->get_updated_connect_flags(*pconn, mysql_flags); if(!(temp_flags & CLIENT_SSL)) { if((MYSQLND_AZURE_G(enableRedirect) == REDIRECT_ON)) { - SET_CLIENT_ERROR((*pconn)->error_info, -1, UNKNOWN_SQLSTATE, "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL."); + SET_CLIENT_ERROR((*pconn)->error_info, -1, UNKNOWN_SQLSTATE, "mysqlnd_azure.enableRedirect is on, but SSL option is not set in connection string. Redirection is only possible with SSL."); (*pconn)->m->free_contents(*pconn); ret = FAIL; } diff --git a/package.xml b/package.xml index 319f22b..b1df1fd 100644 --- a/package.xml +++ b/package.xml @@ -29,8 +29,8 @@ PHP License - 1. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect. -- 2. If enableRedirect is with value "on", ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." -- 3. If enableRedirect is with value "on", but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." +- 2. If enableRedirect is with value "on", ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set in connection string. Redirection is only possible with SSL." +- 3. If enableRedirect is with value "on", but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "Connection aborted because redirection is not enabled on the MySQL server or the network package doesn't meet meet redirection protocol." - 4. If enableRedirect is with value "on" and server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection. - 5. A new option for mysqlnd_azure.enableRedirect is introduced with name "preferred". When enableRedirect is "preferred", it will use redirection if possible. If connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. @@ -84,8 +84,8 @@ PHP License - 1. Rename option mysqlnd_azure.enabled to mysqlnd_azure.enableRedirect, and add a new option value "preferred". -- 2. If enableRedirect is with value "on", ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL." -- 3. If enableRedirect is with value "on", but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol." +- 2. If enableRedirect is with value "on", ssl is off, no connection will be made, return error "mysqlnd_azure.enableRedirect is on, but SSL option is not set in connection string. Redirection is only possible with SSL." +- 3. If enableRedirect is with value "on", but on server side redirection is not available, and there is no last message in OK packet, abort the first connection and return error "Connection aborted because redirection is not enabled on the MySQL server or the network package doesn't meet meet redirection protocol." - 4. If enableRedirect is with value "on" and server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection. - 5. A new option for mysqlnd_azure.enableRedirect is introduced with name "preferred". When enableRedirect is "preferred", it will use redirection if possible. If connection does not use SSL, or server does not support redirection, or redirected connection fails to connect for any non-fatal reason while the proxy connection is still a valid one, it will fallback to the first proxy connection. diff --git a/tests/mysqli_azure_redirection_on.phpt b/tests/mysqli_azure_redirection_on.phpt index e136865..a849ec1 100644 --- a/tests/mysqli_azure_redirection_on.phpt +++ b/tests/mysqli_azure_redirection_on.phpt @@ -36,7 +36,7 @@ if(strlen($last_message) > 27 && strcmp(substr($last_message, 0, strlen("Locatio } else { //Server does not support redirection $lastError = error_get_last()["message"]; - if (strpos($lastError, "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol.") !== false) + if (strpos($lastError, "Connection aborted because redirection is not enabled on the MySQL server or the network package doesn't meet meet redirection protocol.") !== false) echo "[003] pass\n"; else echo "[003] fail\n"; @@ -54,7 +54,7 @@ if ($ret) } $lastError = error_get_last()["message"]; -if (strpos($lastError, "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL.") !== false) +if (strpos($lastError, "mysqlnd_azure.enableRedirect is on, but SSL option is not set in connection string. Redirection is only possible with SSL.") !== false) echo "[004] pass\n"; else echo "[004] fail\n";
off(0)
on(1) - If SSL is off, no connection will be made, return error: - "mysqlnd_azure.enableRedirect is on, but SSL option is not set. Redirection is only possible with SSL."
- - If on server side redirection is not supported, abort the first connection and return error: "Abort the connection because MySQL server does not enable redirection or network package doesn't meet redirection protocol."
+ "mysqlnd_azure.enableRedirect is on, but SSL option is not set in connection string. Redirection is only possible with SSL."
+ - If on server side redirection is not supported, abort the first connection and return error: "Connection aborted because redirection is not enabled on the MySQL server or the network package doesn't meet meet redirection protocol."
- If server supports redirection, but the redirected connection failed for any reason, also abort the first proxy connection. Return the error of the redirected connection.