From ebe3cc9935d339486213b8a61fbbf524630073b5 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 23 Nov 2015 10:58:28 +0100 Subject: [PATCH 01/40] - Added new function mariadb_get_connection_type which returns -1 on error, or MARIADB_CONNECTION_{UNIX_SOCKET,TCP,NAMEDPIPE,SHAREDMEM} - Disabled asynchronous API for named pipes and shared memory connecit++ions - Added package suffix ("alpha") - removed myodbc_remove_escape api function - Fixed return value (length) for named pipe read/write operations --- CMakeLists.txt | 12 +++++++++--- include/errmsg.h | 1 + include/ma_pvio.h | 3 ++- include/mysql.h | 2 +- include/mysql_com.h | 6 ++++++ libmariadb/CMakeLists.txt | 2 +- libmariadb/errmsg.c | 1 + libmariadb/libmariadb.c | 35 +++++++++-------------------------- libmariadb/ma_pvio.c | 14 +++++++++++--- libmariadb/net.c | 7 +------ plugins/pvio/pvio_npipe.c | 20 +++++++++++--------- unittest/libmariadb/async.c | 31 +++++++++++++++++++++++++++++-- win/packaging/CMakeLists.txt | 6 +++++- 13 files changed, 87 insertions(+), 53 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 636de894..8bbdaab7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,8 @@ # This is the LGPL libmariadb project. PROJECT(mariadb-connector-c C) +SET(PACKAGE_STATUS_SUFFIX "alpha") + SET(CPACK_PACKAGE_VERSION_MAJOR 3) SET(CPACK_PACKAGE_VERSION_MINOR 0) SET(CPACK_PACKAGE_VERSION_PATCH 0) @@ -264,12 +266,16 @@ SET(CPACK_PACKAGE_VENDOR "MariaDB Corporation Ab") SET(CPACK_PACKAGE_DESCRIPTION "MariaDB Connector/C. A library for connecting to MariaDB and MySQL servers") SET(CPACK_PACKAGE_NAME "mariadb_connector_c") STRING(TOLOWER ${CMAKE_SYSTEM_NAME} system_name) -SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${system_name}-${CMAKE_SYSTEM_PROCESSOR}") SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING.LIB") SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") INCLUDE(cmake/ConnectorName.cmake) -SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-src") - +IF(NOT PACKAGE_STATUS_SUFFIX) + SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-src") + SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${system_name}-${CMAKE_SYSTEM_PROCESSOR}") +ELSE() + SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-src") + SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-${system_name}-${CMAKE_SYSTEM_PROCESSOR}") +ENDIF() # Build source packages IF(GIT_BUILD_SRCPKG) # get branch name diff --git a/include/errmsg.h b/include/errmsg.h index ff795a7b..6306ab96 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -84,6 +84,7 @@ extern const char *mariadb_client_errors[]; /* Error messages */ #define CR_EVENT_CREATE_FAILED 5000 #define CR_BIND_ADDR_FAILED 5001 +#define CR_ASYNC_NOT_SUPPORTED 5002 #define SQLSTATE_UNKNOWN "HY000" diff --git a/include/ma_pvio.h b/include/ma_pvio.h index 0fada961..7ac4be94 100644 --- a/include/ma_pvio.h +++ b/include/ma_pvio.h @@ -50,7 +50,8 @@ enum enum_pvio_io_event enum enum_pvio_type { PVIO_TYPE_UNIXSOCKET= 0, PVIO_TYPE_SOCKET, - PVIO_TYPE_NAMEDPIPE + PVIO_TYPE_NAMEDPIPE, + PVIO_TYPE_SHAREDMEM, }; enum enum_pvio_operation { diff --git a/include/mysql.h b/include/mysql.h index b61eb84f..ca47367e 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -469,7 +469,6 @@ unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, void STDCALL mysql_debug(const char *debug); #define mysql_debug_init(A) mysql_debug((A)); void STDCALL mysql_debug_end(void); -void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name); unsigned int STDCALL mysql_thread_safe(void); unsigned int STDCALL mysql_warning_count(MYSQL *mysql); const char * STDCALL mysql_sqlstate(MYSQL *mysql); @@ -493,6 +492,7 @@ unsigned long STDCALL mysql_hex_string(char *to, const char *from, size_t len); my_socket STDCALL mysql_get_socket(const MYSQL *mysql); unsigned int STDCALL mysql_get_timeout_value(const MYSQL *mysql); unsigned int STDCALL mysql_get_timeout_value_ms(const MYSQL *mysql); +int STDCALL mariadb_get_connection_type(MYSQL *mysql); /* Async API */ int STDCALL mysql_close_start(MYSQL *sock); diff --git a/include/mysql_com.h b/include/mysql_com.h index f1d4eb69..415e002d 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -364,6 +364,12 @@ typedef struct st_udf_init my_bool const_item; /* 0 if result is independent of arguments */ } UDF_INIT; +/* Connection types */ +#define MARIADB_CONNECTION_UNIXSOCKET 0 +#define MARIADB_CONNECTION_TCP 1 +#define MARIADB_CONNECTION_NAMEDPIPE 2 +#define MARIADB_CONNECTION_SHAREDMEM 3 + /* Constants when using compression */ #define NET_HEADER_SIZE 4 /* standard header size */ #define COMP_HEADER_SIZE 3 /* compression header extra size */ diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index ed0c041e..e42f3888 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -34,7 +34,7 @@ SET(EXPORT_SYMBOLS mariadb_dyncol_val_double mariadb_dyncol_val_long mariadb_dyncol_val_str - myodbc_remove_escape + mariadb_get_connection_type mysql_affected_rows mysql_autocommit mysql_autocommit_cont diff --git a/libmariadb/errmsg.c b/libmariadb/errmsg.c index 8ae0fa04..a2d6fbb3 100644 --- a/libmariadb/errmsg.c +++ b/libmariadb/errmsg.c @@ -149,6 +149,7 @@ const char *mariadb_client_errors[] = { /* 5000 */ "Creating an event failed (Errorcode: %d)", /* 5001 */ "Bind to local interface '-.%64s' failed (Errorcode: %d)", + /* 5002 */ "Connection type doesn't support asynchronous IO operations", "" }; diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 1590df17..3a1e7177 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -3069,32 +3069,6 @@ mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, return (ulong)mysql_cset_escape_slashes(mysql->charset, to, from, length); } -void STDCALL -myodbc_remove_escape(MYSQL *mysql,char *name) -{ - char *to; - my_bool use_mb_flag= (mysql->charset->char_maxlen > 1); - char *end= 0; - if (use_mb_flag) - for (end=name; *end ; end++) ; - - for (to=name ; *name ; name++) - { - int l; - if (use_mb_flag && (l = mysql->charset->mb_valid(name , end))) - { - while (l--) - *to++ = *name++; - name--; - continue; - } - if (*name == '\\' && name[1]) - name++; - *to++= *name; - } - *to=0; -} - void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *cs) { DBUG_ENTER("mysql_get_character_set_info"); @@ -3295,6 +3269,15 @@ mysql_get_socket(const MYSQL *mysql) return sock; } +int STDCALL mariadb_get_connection_type(MYSQL *mysql) +{ + /* check if we are connected */ + if (!mysql || !mysql->net.pvio) + return -1; + + return (int)mysql->net.pvio->type; +} + /* * Default methods for a connection. These methods are * stored in mysql->methods and can be overwritten by diff --git a/libmariadb/ma_pvio.c b/libmariadb/ma_pvio.c index 2f9d2744..9ba111b6 100644 --- a/libmariadb/ma_pvio.c +++ b/libmariadb/ma_pvio.c @@ -71,7 +71,7 @@ MARIADB_PVIO *ma_pvio_init(MA_PVIO_CINFO *cinfo) * pvio_socket * pvio_namedpipe */ - char *pvio_plugins[] = {"pvio_socket", "pvio_npipe"}; + char *pvio_plugins[] = {"pvio_socket", "pvio_npipe", "pvio_shmem"}; int type; MARIADB_PVIO_PLUGIN *pvio_plugin; MARIADB_PVIO *pvio= NULL; @@ -86,6 +86,9 @@ MARIADB_PVIO *ma_pvio_init(MA_PVIO_CINFO *cinfo) case PVIO_TYPE_NAMEDPIPE: type= 1; break; + case PVIO_TYPE_SHAREDMEM: + type= 2; + break; #endif default: return NULL; @@ -96,7 +99,6 @@ MARIADB_PVIO *ma_pvio_init(MA_PVIO_CINFO *cinfo) pvio_plugins[type], MARIADB_CLIENT_PVIO_PLUGIN))) { - /* error handling */ return NULL; } @@ -111,6 +113,7 @@ MARIADB_PVIO *ma_pvio_init(MA_PVIO_CINFO *cinfo) /* register error routine and methods */ pvio->methods= pvio_plugin->methods; pvio->set_error= my_set_error; + pvio->type= cinfo->type; /* set tineouts */ if (pvio->methods->set_timeout) @@ -180,9 +183,14 @@ static size_t ma_pvio_read_async(MARIADB_PVIO *pvio, uchar *buffer, size_t lengt struct mysql_async_context *b= pvio->mysql->options.extension->async_context; int timeout= pvio->timeout[PVIO_READ_TIMEOUT]; + if (!pvio->methods->async_read) + { + PVIO_SET_ERROR(pvio->mysql, CR_ASYNC_NOT_SUPPORTED, unknown_sqlstate, 0); + return -1; + } + for (;;) { - /* todo: async */ if (pvio->methods->async_read) res= pvio->methods->async_read(pvio, buffer, length); if (res >= 0 || IS_BLOCKING_ERROR()) diff --git a/libmariadb/net.c b/libmariadb/net.c index 8c657d2a..b8dbf45c 100644 --- a/libmariadb/net.c +++ b/libmariadb/net.c @@ -180,7 +180,6 @@ static my_bool net_realloc(NET *net, size_t length) } /* Remove unwanted characters from connection */ - void net_clear(NET *net) { DBUG_ENTER("net_clear"); @@ -189,9 +188,7 @@ void net_clear(NET *net) DBUG_VOID_RETURN; } - - /* Flush write_buffer if not empty. */ - +/* Flush write_buffer if not empty. */ int net_flush(NET *net) { int error=0; @@ -207,12 +204,10 @@ int net_flush(NET *net) DBUG_RETURN(error); } - /***************************************************************************** ** Write something to server/client buffer *****************************************************************************/ - /* ** Write a logical packet with packet header ** Format: Packet length (3 bytes), packet number(1 byte) diff --git a/plugins/pvio/pvio_npipe.c b/plugins/pvio/pvio_npipe.c index 95b11a0b..00d0c5e7 100644 --- a/plugins/pvio/pvio_npipe.c +++ b/plugins/pvio/pvio_npipe.c @@ -34,7 +34,9 @@ my_bool pvio_npipe_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout); int pvio_npipe_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type); size_t pvio_npipe_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length); +size_t pvio_npipe_async_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length); size_t pvio_npipe_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length); +size_t pvio_npipe_async_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length); int pvio_npipe_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout); my_bool pvio_npipe_blocking(MARIADB_PVIO *pvio, my_bool value, my_bool *old_value); my_bool pvio_npipe_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo); @@ -118,10 +120,10 @@ size_t pvio_npipe_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length) goto end; } if (GetLastError() == ERROR_IO_PENDING) - r= pvio_npipe_wait_io_or_timeout(pvio, 1, 0); - - if (!r) - r= cpipe->rw_size; + { + if (!pvio_npipe_wait_io_or_timeout(pvio, 1, 0)) + r= cpipe->rw_size; + } end: return r; } @@ -143,10 +145,10 @@ size_t pvio_npipe_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length) goto end; } if (GetLastError() == ERROR_IO_PENDING) - r= pvio_npipe_wait_io_or_timeout(pvio, 1, 0); - - if (!r) - r= cpipe->rw_size; + { + if (!pvio_npipe_wait_io_or_timeout(pvio, 1, 0)) + r= cpipe->rw_size; + } end: return r; } @@ -216,7 +218,7 @@ my_bool pvio_npipe_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo) if (!pvio || !cinfo) return 1; - if (!(cpipe= (struct st_pvio_npipe *)LocalAlloc(sizeof(struct st_pvio_npipe), 0))) + if (!(cpipe= (struct st_pvio_npipe *)LocalAlloc(LMEM_ZEROINIT, sizeof(struct st_pvio_npipe)))) { PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0, ""); return 1; diff --git a/unittest/libmariadb/async.c b/unittest/libmariadb/async.c index a0c3381b..7fdf120a 100644 --- a/unittest/libmariadb/async.c +++ b/unittest/libmariadb/async.c @@ -30,6 +30,19 @@ #define SL(s) (s), sizeof(s) +my_bool skip_async= 0; + +static int test_async(MYSQL *mysql) +{ + int type= mariadb_get_connection_type(mysql); + if (type > MARIADB_CONNECTION_TCP) + { + skip_async= 1; + diag("Asnyc IO not supported"); + } + return OK; +} + static int wait_for_mysql(MYSQL *mysql, int status) { @@ -126,6 +139,9 @@ static int async1(MYSQL *my) uint default_timeout; int i; + if (skip_async) + return SKIP; + for (i=0; i < 100; i++) { @@ -196,7 +212,12 @@ static int test_conc131(MYSQL *my) { int rc; /* this test needs to run under valgrind */ - MYSQL *mysql=mysql_init(NULL); + MYSQL *mysql; + + if (skip_async) + return SKIP; + + mysql= mysql_init(NULL); rc= mysql_options(mysql, MYSQL_OPT_NONBLOCK, 0); check_mysql_rc(rc, mysql); mysql_close(mysql); @@ -205,13 +226,19 @@ static int test_conc131(MYSQL *my) static int test_conc129(MYSQL *my) { - MYSQL *mysql= mysql_init(NULL); + MYSQL *mysql; + + if (skip_async) + return SKIP; + + mysql= mysql_init(NULL); FAIL_IF(mysql_close_start(mysql), "No error expected"); return OK; } struct my_tests_st my_tests[] = { + {"test_async", test_async, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"async1", async1, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc131", test_conc131, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_conc129", test_conc129, TEST_CONNECTION_NONE, 0, NULL, NULL}, diff --git a/win/packaging/CMakeLists.txt b/win/packaging/CMakeLists.txt index ec1ba8b3..6decef34 100644 --- a/win/packaging/CMakeLists.txt +++ b/win/packaging/CMakeLists.txt @@ -57,7 +57,11 @@ IF(NOT WIX_DIR) SET(WIX_DIR $ENV{WIX}/bin) ENDIF() -SET(MSI_PACKAGE "mariadb-connector-c-${PRODUCT_VERSION}-${PLATFORM}.msi") +IF(NOT PACKAGE_STATUS_SUFFIX) + SET(MSI_PACKAGE "mariadb-connector-c-${PRODUCT_VERSION}-${PLATFORM}.msi") +ELSE() + SET(MSI_PACKAGE "mariadb-connector-c-${PRODUCT_VERSION}-${PACKAGE_STATUS_SUFFIX}-${PLATFORM}.msi") +ENDIF() IF(WITH_SIGNCODE) IF(EXISTS "/tools/sign.bat") From cbf02265526164bd72e28462dc348a154e6c5701 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Tue, 8 Dec 2015 19:08:48 +0100 Subject: [PATCH 02/40] Fix for MDEV-9212 (manually merged from 2.2 branch) Added support for CMake >= 3.0 --- CMakeLists.txt | 7 +++++ libmariadb/secure/openssl.c | 55 +++++++++++++++++++++------------ mariadb_config/libmariadb.pc.in | 19 ++++++++++++ 3 files changed, 62 insertions(+), 19 deletions(-) create mode 100644 mariadb_config/libmariadb.pc.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bbdaab7..a7544aab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,13 @@ IF(COMMAND CMAKE_POLICY) CMAKE_POLICY(SET CMP0003 NEW) ENDIF() +#Allow access to non existing targets +IF(CMAKE_VERSION VERSION_GREATER "2.9.9") + CMAKE_POLICY(SET CMP0026 OLD) + CMAKE_POLICY(SET CMP0045 OLD) + CMAKE_POLICY(SET CMP0042 OLD) +ENDIF() + SET(MARIADB_CONNECTOR_C_COPYRIGHT "2013-2015 MariaDB Corporation Ab") ### Options ### diff --git a/libmariadb/secure/openssl.c b/libmariadb/secure/openssl.c index 37256efc..d4164403 100644 --- a/libmariadb/secure/openssl.c +++ b/libmariadb/secure/openssl.c @@ -464,9 +464,13 @@ int ma_ssl_verify_server_cert(MARIADB_SSL *cssl) { X509 *cert; MYSQL *mysql; - MARIADB_PVIO *pvio; + X509_NAME *x509sn; + int cn_pos; + X509_NAME_ENTRY *cn_entry; + ASN1_STRING *cn_asn1; + const char *cn_str; SSL *ssl; - char *p1, *p2, buf[256]; + MARIADB_PVIO *pvio; if (!cssl || !cssl->ssl) return 1; @@ -477,33 +481,46 @@ int ma_ssl_verify_server_cert(MARIADB_SSL *cssl) if (!mysql->host) { - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, - "Invalid (empty) hostname"); + pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, + ER(CR_SSL_CONNECTION_ERROR), "Invalid (empty) hostname"); return 1; } if (!(cert= SSL_get_peer_certificate(ssl))) { - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, - "Unable to get server certificate"); + pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, + ER(CR_SSL_CONNECTION_ERROR), "Unable to get server certificate"); return 1; } - X509_NAME_oneline(X509_get_subject_name(cert), buf, 256); + x509sn= X509_get_subject_name(cert); + + if ((cn_pos= X509_NAME_get_index_by_NID(x509sn, NID_commonName, -1)) < 0) + goto error; + + if (!(cn_entry= X509_NAME_get_entry(x509sn, cn_pos))) + goto error; + + if (!(cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry))) + goto error; + + cn_str = (char *)ASN1_STRING_data(cn_asn1); + + /* Make sure there is no embedded \0 in the CN */ + if ((size_t)ASN1_STRING_length(cn_asn1) != strlen(cn_str)) + goto error; + + if (strcmp(cn_str, mysql->host)) + goto error; + X509_free(cert); - /* Extract the server name from buffer: - Format: ....CN=/hostname/.... */ - if ((p1= strstr(buf, "/CN="))) - { - p1+= 4; - if ((p2= strchr(p1, '/'))) - *p2= 0; - if (!strcmp(mysql->host, p1)) - return(0); - } - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, - "Validation of SSL server certificate failed"); + return 0; +error: + X509_free(cert); + + pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, + ER(CR_SSL_CONNECTION_ERROR), "Validation of SSL server certificate failed"); return 1; } diff --git a/mariadb_config/libmariadb.pc.in b/mariadb_config/libmariadb.pc.in new file mode 100644 index 00000000..e9161554 --- /dev/null +++ b/mariadb_config/libmariadb.pc.in @@ -0,0 +1,19 @@ +# +# pkg_config.pc.in +# +# pkg_config configuration file +# For a detailled description of options, please visit +# Dan Nicholson’s Guide to pkg-config (http://www.freedesktop.org/wiki/Software/pkg-config/) +# + +includedir=@PREFIX_INSTALL_DIR@/@INCLUDE_INSTALL_DIR@/@SUFFIX_INSTALL_DIR@ +libdir=@PREFIX_INSTALL_DIR@/@INCLUDE_INSTALL_DIR@/@SUFFIX_INSTALL_DIR@ +prefix=@PREFIX_INSTALL_DIR@ + +Name: libmariadb +Version: @LIBMARIADB_VERSION@ +Description: MariaDB Connector/C dynamic library +Cflags: -I@PREFIX_INSTALL_DIR@/@INCLUDE_INSTALL_DIR@/@SUFFIX_INSTALL_DIR@ @CMAKE_C_FLAGS@ +Libs: -L@PREFIX_INSTALL_DIR@/@LIB_INSTALL_DIR@/@SUFFIX_INSTALL_DIR@ -lmariadb @extra_dynamic_LDFLAGS@ + + From edcfe061c1c4c2c2226861ecc0b7067f23660f43 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Thu, 10 Dec 2015 06:51:01 +0100 Subject: [PATCH 03/40] Added new functions mysql_get_optionv and mysql_get_option --- CMakeLists.txt | 6 +- include/mysql.h | 5 +- libmariadb/CMakeLists.txt | 2 + libmariadb/libmariadb.c | 231 ++++++++++++++++++++++++++----- libmariadb/my_stmt.c | 1 - unittest/libmariadb/connection.c | 75 ++++++++++ 6 files changed, 282 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a7544aab..2066a077 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -291,10 +291,10 @@ IF(GIT_BUILD_SRCPKG) STRING(REGEX REPLACE "\\[|\\]" "" GIT_BRANCH ${git_branch}) MESSAGE(STATUS "${GIT_BRANCH}") IF(WIN32) - EXECUTE_PROCESS(COMMAND git archive ${GIT_BRANCH} --format=zip --output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.zip) + EXECUTE_PROCESS(COMMAND git archive ${GIT_BRANCH} --format=zip --prefix=${CPACK_SOURCE_PACKAGE_FILE_NAME}/ --output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.zip) ELSE() - EXECUTE_PROCESS(COMMAND git archive ${GIT_BRANCH} --format=zip --output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.zip) - EXECUTE_PROCESS(COMMAND git archive ${GIT_BRANCH} --format=tar --output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar) + EXECUTE_PROCESS(COMMAND git archive ${GIT_BRANCH} --format=zip --prefix=${CPACK_SOURCE_PACKAGE_FILE_NAME}/ --output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.zip) + EXECUTE_PROCESS(COMMAND git archive ${GIT_BRANCH} --format=tar --prefix=${CPACK_SOURCE_PACKAGE_FILE_NAME}/ --output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar) EXECUTE_PROCESS(COMMAND gzip -9 -f ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar) ENDIF() ENDIF() diff --git a/include/mysql.h b/include/mysql.h index ca47367e..bd94f867 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -214,7 +214,8 @@ extern unsigned int mariadb_deinitialize_ssl; MARIADB_OPT_SSL_FP, /* single finger print for server certificate verification */ MARIADB_OPT_SSL_FP_LIST, /* finger print white list for server certificate verification */ MARIADB_OPT_SSL_PASSWORD, /* password for encrypted certificates */ - MARIADB_OPT_CONNECTION_READ_ONLY + MARIADB_OPT_CONNECTION_READ_ONLY, + MYSQL_OPT_CONNECT_ATTRS /* for mysql_get_optionv */ }; enum mysql_status { MYSQL_STATUS_READY, @@ -487,6 +488,8 @@ CHARSET_INFO * STDCALL mysql_get_charset_by_nr(unsigned int csnr); size_t STDCALL mariadb_convert_string(const char *from, size_t *from_len, CHARSET_INFO *from_cs, char *to, size_t *to_len, CHARSET_INFO *to_cs, int *errorcode); int STDCALL mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...); +int STDCALL mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...); +int STDCALL mysql_get_option(MYSQL *mysql, enum mysql_option option, void *arg); MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void); unsigned long STDCALL mysql_hex_string(char *to, const char *from, size_t len); my_socket STDCALL mysql_get_socket(const MYSQL *mysql); diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index e42f3888..ea9fbf01 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -79,6 +79,8 @@ SET(EXPORT_SYMBOLS mysql_get_client_info mysql_get_client_version mysql_get_host_info + mysql_get_option + mysql_get_optionv mysql_get_parameters mysql_get_proto_info mysql_get_server_info diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 3a1e7177..2c3b240b 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -1231,15 +1231,13 @@ uchar *ma_send_connect_attr(MYSQL *mysql, uchar *buffer) size_t len; uchar *p= hash_element(&mysql->options.extension->connect_attrs, i); - len= *(size_t *)p; + len= strlen(p); buffer= mysql_net_store_length(buffer, len); - p+= sizeof(size_t); memcpy(buffer, p, len); - buffer+= len; - p+= len; - len= *(size_t *)p; + buffer+= (len); + p+= (len + 1); + len= strlen(p); buffer= mysql_net_store_length(buffer, len); - p+= sizeof(size_t); memcpy(buffer, p, len); buffer+= len; } @@ -2567,21 +2565,17 @@ static size_t get_store_length(size_t length) return 9; } -uchar *ma_get_hash_key(const uchar *hash_entry, +uchar *ma_get_hash_keyval(const uchar *hash_entry, unsigned int *length, my_bool not_used __attribute__((unused))) { /* Hash entry has the following format: - Offset: 0 key length - sizeof(size_t) key - key_length + - sizeof(size_t) value length - value + Offset: 0 key (\0 terminated) + key_length + 1 valu (\0 terminated) */ uchar *p= (uchar *)hash_entry; - size_t len=*((size_t*)p); - p+= sizeof(size_t); - *length= (uint)len; + size_t len= strlen(p); + *length= len; return p; } @@ -2779,19 +2773,19 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) break; case MYSQL_OPT_CONNECT_ATTR_DELETE: { - uchar *p; + uchar *h; CHECK_OPT_EXTENSION_SET(&mysql->options); if (hash_inited(&mysql->options.extension->connect_attrs) && - (p= (uchar *)hash_search(&mysql->options.extension->connect_attrs, (uchar *)arg1, + (h= (uchar *)hash_search(&mysql->options.extension->connect_attrs, (uchar *)arg1, arg1 ? (uint)strlen((char *)arg1) : 0))) { - size_t key_len= *(size_t *)p; - mysql->options.extension->connect_attrs_len-= key_len; - mysql->options.extension->connect_attrs_len-= get_store_length(key_len); - key_len= *(size_t *)(p + sizeof(size_t) + key_len); - mysql->options.extension->connect_attrs_len-= key_len; - mysql->options.extension->connect_attrs_len-= get_store_length(key_len); - hash_delete(&mysql->options.extension->connect_attrs, p); + uchar *p= h; + size_t key_len= strlen(p); + mysql->options.extension->connect_attrs_len-= key_len + get_store_length(key_len); + p+= key_len + 1; + key_len= strlen(p); + mysql->options.extension->connect_attrs_len-= key_len + get_store_length(key_len); + hash_delete(&mysql->options.extension->connect_attrs, h); } } @@ -2813,6 +2807,11 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) size_t storage_len= key_len + value_len + get_store_length(key_len) + get_store_length(value_len); + + /* since we store terminating zero character in hash, we need + * to increase lengths */ + key_len++; + value_len++; CHECK_OPT_EXTENSION_SET(&mysql->options); if (!key_len || @@ -2825,24 +2824,20 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) if (!hash_inited(&mysql->options.extension->connect_attrs)) { if (_hash_init(&mysql->options.extension->connect_attrs, - 0, 0, 0, ma_get_hash_key, ma_hash_free, 0)) + 0, 0, 0, ma_get_hash_keyval, ma_hash_free, 0)) { SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); goto end; } } - if ((buffer= (uchar *)my_malloc(2 * sizeof(size_t) + key_len + value_len, + if ((buffer= (uchar *)my_malloc(key_len + value_len, MYF(MY_WME | MY_ZEROFILL)))) { uchar *p= buffer; - *((size_t *)p)= key_len; - p+= sizeof(size_t); - memcpy(p, arg1, key_len); - p+= key_len; - *((size_t *)p)= value_len; - p+= sizeof(size_t); + strcpy(p, arg1); + p+= (strlen(arg1) + 1); if (arg2) - memcpy(p, arg2, value_len); + strcpy(p, arg2); if (hash_insert(&mysql->options.extension->connect_attrs, buffer)) { @@ -2893,6 +2888,176 @@ end: DBUG_RETURN(1); } +int STDCALL +mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) +{ + va_list ap; + + DBUG_ENTER("mariadb_get_optionv"); + DBUG_PRINT("enter",("option: %d",(int) option)); + + va_start(ap, arg); + + switch(option) { + case MYSQL_OPT_CONNECT_TIMEOUT: + *((uint *)arg)= mysql->options.connect_timeout; + break; + case MYSQL_OPT_COMPRESS: + *((my_bool *)arg)= mysql->options.compress; + break; + case MYSQL_OPT_NAMED_PIPE: + *((my_bool *)arg)= mysql->options.named_pipe; + break; + case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/ + *((uint *)arg)= test(mysql->options.client_flag & CLIENT_LOCAL_FILES); + break; + case MYSQL_INIT_COMMAND: + /* mysql_get_optionsv(mysql, MYSQL_INIT_COMMAND, commands, elements) */ + { + unsigned int *elements; + if (arg) + *((char **)arg)= mysql->options.init_command ? mysql->options.init_command->buffer : NULL; + if ((elements= va_arg(ap, unsigned int *))) + *elements= mysql->options.init_command ? mysql->options.init_command->elements : 0; + } + break; + case MYSQL_READ_DEFAULT_FILE: + *((char **)arg)= mysql->options.my_cnf_file; + break; + case MYSQL_READ_DEFAULT_GROUP: + *((char **)arg)= mysql->options.my_cnf_group; + break; + case MYSQL_SET_CHARSET_DIR: + /* not supported in this version. Since all character sets + are internally available, we don't throw an error */ + *((char **)arg)= NULL; + break; + case MYSQL_SET_CHARSET_NAME: + *((char **)arg)= mysql->options.charset_name; + break; + case MYSQL_OPT_RECONNECT: + *((uint *)arg)= mysql->reconnect; + break; + case MYSQL_OPT_PROTOCOL: + *((uint *)arg)= mysql->options.protocol; + break; + case MYSQL_OPT_READ_TIMEOUT: + *((uint *)arg)= mysql->options.read_timeout; + break; + case MYSQL_OPT_WRITE_TIMEOUT: + *((uint *)arg)= mysql->options.write_timeout; + break; + case MYSQL_REPORT_DATA_TRUNCATION: + *((uint *)arg)= mysql->options.report_data_truncation; + break; + case MYSQL_PROGRESS_CALLBACK: + *((void (**)(const MYSQL *, uint, uint, double, const char *, uint))arg)= + mysql->options.extension ? mysql->options.extension->report_progress : NULL; + break; + case MYSQL_PLUGIN_DIR: + *((char **)arg)= mysql->options.extension ? mysql->options.extension->plugin_dir : NULL; + break; + case MYSQL_DEFAULT_AUTH: + *((char **)arg)= mysql->options.extension ? mysql->options.extension->default_auth : NULL; + break; + case MYSQL_OPT_NONBLOCK: + *((my_bool *)arg)= test(mysql->options.extension && mysql->options.extension->async_context); + break; + case MYSQL_OPT_SSL_VERIFY_SERVER_CERT: + *((my_bool *)arg)= test(mysql->options.client_flag & CLIENT_SSL_VERIFY_SERVER_CERT); + break; + case MYSQL_OPT_SSL_KEY: + *((char **)arg)= mysql->options.ssl_key; + break; + case MYSQL_OPT_SSL_CERT: + *((char **)arg)= mysql->options.ssl_cert; + break; + case MYSQL_OPT_SSL_CA: + *((char **)arg)= mysql->options.ssl_ca; + break; + case MYSQL_OPT_SSL_CAPATH: + *((char **)arg)= mysql->options.ssl_capath; + break; + case MYSQL_OPT_SSL_CIPHER: + *((char **)arg)= mysql->options.ssl_cipher; + break; + case MYSQL_OPT_SSL_CRL: + *((char **)arg)= mysql->options.extension ? mysql->options.ssl_cipher : NULL; + break; + case MYSQL_OPT_SSL_CRLPATH: + *((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_crlpath : NULL; + break; + case MYSQL_OPT_CONNECT_ATTRS: + /* mysql_get_optionsv(mysql, MYSQL_OPT_CONNECT_ATTRS, keys, vals, elements) */ + { + int i, *elements; + char **key= (char **)arg; + char **val; + + if (!elements) + goto error; + + val= va_arg(ap, char **); + + if (!(elements= va_arg(ap, unsigned int *))) + goto error; + + *elements= 0; + + if (!mysql->options.extension || + !hash_inited(&mysql->options.extension->connect_attrs)) + break; + + *elements= mysql->options.extension->connect_attrs.records; + + if (val || key) + { + for (i=0; i < *elements; i++) + { + uchar *p= hash_element(&mysql->options.extension->connect_attrs, i); + if (key) + key[i]= p; + p+= strlen(p) + 1; + if (val) + val[i]= p; + } + } + } + break; + case MYSQL_SECURE_AUTH: + *((my_bool *)arg)= mysql->options.secure_auth; + break; + case MYSQL_OPT_BIND: + *((char **)arg)= mysql->options.bind_address; + break; + case MARIADB_OPT_SSL_FP: + *((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_fp : NULL; + break; + case MARIADB_OPT_SSL_FP_LIST: + *((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_fp_list : NULL; + break; + case MARIADB_OPT_SSL_PASSWORD: + *((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_pw : NULL; + break; + /* todo + case MARIADB_OPT_CONNECTION_READ_ONLY: + break; + */ + default: + va_end(ap); + DBUG_RETURN(-1); + } + va_end(ap); + DBUG_RETURN(0); +error: + va_end(ap); + DBUG_RETURN(-1); +} + +int STDCALL mysql_get_option(MYSQL *mysql, enum mysql_option option, void *arg) +{ + return mysql_get_optionv(mysql, option, arg); +} int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) diff --git a/libmariadb/my_stmt.c b/libmariadb/my_stmt.c index 7f0355b5..58a5c951 100644 --- a/libmariadb/my_stmt.c +++ b/libmariadb/my_stmt.c @@ -416,7 +416,6 @@ int store_param(MYSQL_STMT *stmt, int column, unsigned char **p) { DBUG_ENTER("store_param"); DBUG_PRINT("info", ("column: %d type: %d", column, stmt->params[column].buffer_type)); - printf("type: %d\n", column, stmt->params[column].buffer_type); switch (stmt->params[column].buffer_type) { case MYSQL_TYPE_TINY: int1store(*p, *(uchar *)stmt->params[column].buffer); diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index 11452977..88b480e1 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -740,7 +740,82 @@ static int test_bind_address(MYSQL *my) return OK; } +static int test_get_options(MYSQL *my) +{ + MYSQL *mysql= mysql_init(NULL); + int options_int[]= {MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_LOCAL_INFILE, + MYSQL_OPT_RECONNECT, MYSQL_OPT_PROTOCOL, MYSQL_OPT_READ_TIMEOUT, MYSQL_OPT_WRITE_TIMEOUT, 0}; + my_bool options_bool[]= {MYSQL_OPT_COMPRESS, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_SECURE_AUTH, +#ifdef _WIN32 + MYSQL_OPT_NAMED_PIPE, +#endif + 0}; + int options_char[]= {MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP, MYSQL_SET_CHARSET_NAME, + MYSQL_OPT_SSL_KEY, MYSQL_OPT_SSL_CA, MYSQL_OPT_SSL_CERT, MYSQL_OPT_SSL_CAPATH, + MYSQL_OPT_SSL_CIPHER, MYSQL_OPT_BIND, MARIADB_OPT_SSL_FP, MARIADB_OPT_SSL_FP_LIST, + MARIADB_OPT_SSL_PASSWORD, 0}; + + char *init_command[3]= {"SET @a:=1", "SET @b:=2", "SET @c:=3"}; + int elements= 0; + char **command; + + + int intval[2]= {1, 0}; + my_bool boolval[2]= {1, 0}; + char *char1= "test", *char2; + int i; + char *attr_key[] = {"foo1", "foo2", "foo3"}; + char *attr_val[] = {"bar1", "bar2", "bar3"}; + char *key[3], *val[3]; + + for (i=0; options_int[i]; i++) + { + mysql_options(mysql, options_int[i], &intval[0]); + intval[1]= 0; + mariadb_get_optionv(mysql, options_int[i], &intval[1]); + FAIL_IF(intval[0] != intval[1], "mariadb_get_optionv (int) failed"); + } + for (i=0; options_bool[i]; i++) + { + mysql_options(mysql, options_bool[i], &boolval[0]); + intval[1]= 0; + mariadb_get_optionv(mysql, options_bool[i], &boolval[1]); + FAIL_IF(boolval[0] != boolval[1], "mariadb_get_optionv (my_bool) failed"); + } + for (i=0; options_char[i]; i++) + { + mysql_options(mysql, options_char[i], char1); + char2= NULL; + mariadb_get_optionv(mysql, options_char[i], (void *)&char2); + FAIL_IF(strcmp(char1, char2), "mariadb_get_optionv (char) failed"); + } + + for (i=0; i < 3; i++) + mysql_options(mysql, MYSQL_INIT_COMMAND, init_command[i]); + + mariadb_get_optionv(mysql, MYSQL_INIT_COMMAND, &command, &elements); + FAIL_IF(elements != 3, "expected 3 elements"); + for (i=0; i < 3; i++) + FAIL_IF(strcmp(init_command[i], command[i]), "wrong init command"); + + for (i=0; i < 3; i++) + mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, attr_key[i], attr_val[i]); + + mariadb_get_optionv(mysql, MYSQL_OPT_CONNECT_ATTRS, NULL, NULL, &elements); + FAIL_IF(elements != 3, "expected 3 connection attributes"); + + mariadb_get_optionv(mysql, MYSQL_OPT_CONNECT_ATTRS, &key, &val, &elements); + for (i=0; i < elements; i++) + { + diag("%s => %s", key[i], val[i]); + } + + mysql_close(mysql); + return OK; +} + struct my_tests_st my_tests[] = { + {"test_get_options", test_get_options, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_wrong_bind_address", test_wrong_bind_address, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_bind_address", test_bind_address, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc118", test_conc118, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, From bec245a9130cbedd461fe1f88682f276e7c18639 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Thu, 10 Dec 2015 12:52:51 +0100 Subject: [PATCH 04/40] Initial aurora implementation --- CMakeLists.txt | 12 + cmake/plugins.cmake | 11 +- include/ma_common.h | 4 +- include/mysql.h | 6 +- include/mysql/client_plugin.h | 1 + include/mysql_com.h | 1 + libmariadb/CMakeLists.txt | 3 + libmariadb/libmariadb.c | 145 +++-- libmariadb/my_stmt.c | 1 - libmariadb/net.c | 3 + plugins/connection/CMakeLists.txt | 16 +- plugins/connection/aurora.c | 820 +++++++++++++++++++++++++++++ plugins/connection/replication.c | 48 +- plugins/pvio/pvio_npipe.c | 2 +- unittest/libmariadb/CMakeLists.txt | 4 +- unittest/libmariadb/aurora.c | 67 +++ unittest/libmariadb/basic-t.c | 55 +- unittest/libmariadb/charset.c | 2 +- unittest/libmariadb/connection.c | 14 +- unittest/libmariadb/my_test.h | 30 +- unittest/libmariadb/ps.c | 5 +- unittest/libmariadb/ps_bugs.c | 3 +- 22 files changed, 1143 insertions(+), 110 deletions(-) create mode 100644 plugins/connection/aurora.c create mode 100644 unittest/libmariadb/aurora.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bbdaab7..1dbdc8a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,14 @@ IF(COMMAND CMAKE_POLICY) CMAKE_POLICY(SET CMP0003 NEW) ENDIF() +#Allow access to non existing targets +IF(CMAKE_VERSION VERSION_GREATER "2.9.9") + CMAKE_POLICY(SET CMP0026 OLD) + CMAKE_POLICY(SET CMP0042 OLD) + CMAKE_POLICY(SET CMP0045 OLD) +ENDIF() + + SET(MARIADB_CONNECTOR_C_COPYRIGHT "2013-2015 MariaDB Corporation Ab") ### Options ### @@ -149,6 +157,10 @@ IF(CMAKE_HAVE_PTHREAD_H) SET(CMAKE_REQUIRED_INCLUDES pthread.h) ENDIF() +IF(DBUG_OFF) + ADD_DEFINITIONS(-DDBUG_OFF=1) +ENDIF() + IF(WIN32) SET(HAVE_THREADS 1) ADD_DEFINITIONS(-DHAVE_DLOPEN) diff --git a/cmake/plugins.cmake b/cmake/plugins.cmake index 47e15597..2d09bb3a 100644 --- a/cmake/plugins.cmake +++ b/cmake/plugins.cmake @@ -1,12 +1,16 @@ # plugin configuration MACRO(REGISTER_PLUGIN name source struct type target allow) + SET(PLUGIN_TYPE ${${name}}) + IF(NOT PLUGIN_TYPE STREQUAL "OFF") + SET(PLUGIN_TYPE ${type}) + ENDIF() IF(PLUGINS) LIST(REMOVE_ITEM PLUGINS ${name}) ENDIF() SET(${name}_PLUGIN_SOURCE ${source}) MARK_AS_ADVANCED(${name}_PLUGIN_SOURCE}) - SET(${name}_PLUGIN_TYPE ${type}) + SET(${name}_PLUGIN_TYPE ${PLUGIN_TYPE}) IF(NOT ${target} STREQUAL "") SET(${name}_PLUGIN_TARGET ${target}) ENDIF() @@ -41,6 +45,7 @@ REGISTER_PLUGIN("TRACE_EXAMPLE" "${CMAKE_SOURCE_DIR}/plugins/trace/trace_example #Connection REGISTER_PLUGIN("REPLICATION" "${CMAKE_SOURCE_DIR}/plugins/connection/replication.c" "connection_replication_plugin" "STATIC" "" 1) +REGISTER_PLUGIN("AURORA" "${CMAKE_SOURCE_DIR}/plugins/connection/aurora.c" "connection_aurora_plugin" "STATIC" "" 1) # Allow registration of additional plugins IF(PLUGIN_CONF_FILE) @@ -50,7 +55,7 @@ ENDIF() SET(LIBMARIADB_SOURCES "") -MESSAGE(STATUS "Plugin configuration") +MESSAGE(STATUS "Plugin configuration:") FOREACH(PLUGIN ${PLUGINS}) IF(WITH_${PLUGIN}_PLUGIN AND ${${PLUGIN}_PLUGIN_CHG} GREATER 0) SET(${PLUGIN}_PLUGIN_TYPE ${WITH_${PLUGIN}_PLUGIN}) @@ -72,6 +77,6 @@ ENDIF() LIST(REMOVE_DUPLICATES LIBMARIADB_SOURCES) CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/libmariadb/client_plugin.c.in - ${CMAKE_BINARY_DIR}/libmariadb/client_plugin.c) + ${CMAKE_BINARY_DIR}/libmariadb/client_plugin.c) MARK_AS_ADVANCED(LIBMARIADB_SOURCES) diff --git a/include/ma_common.h b/include/ma_common.h index 6a6a80a0..048fc9ae 100644 --- a/include/ma_common.h +++ b/include/ma_common.h @@ -48,10 +48,12 @@ struct st_mysql_options_extension { double progress, const char *proc_info, unsigned int proc_info_length); - MARIADB_DB_DRIVER *db_driver; + MARIADB_DB_DRIVER *db_driver; char *ssl_fp; /* finger print of server certificate */ char *ssl_fp_list; /* white list of finger prints */ char *ssl_pw; /* password for encrypted certificates */ + char *url; /* for connection handler we need to save URL for reconnect */ + my_bool read_only; }; #define OPT_HAS_EXT_VAL(a,key) \ diff --git a/include/mysql.h b/include/mysql.h index ca47367e..3c000741 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -482,8 +482,8 @@ const char * STDCALL mysql_get_client_info(void); unsigned long STDCALL mysql_get_client_version(void); my_bool STDCALL mariadb_connection(MYSQL *mysql); const char * STDCALL mysql_get_server_name(MYSQL *mysql); -CHARSET_INFO * STDCALL mysql_get_charset_by_name(const char *csname); -CHARSET_INFO * STDCALL mysql_get_charset_by_nr(unsigned int csnr); +CHARSET_INFO * STDCALL mariadb_get_charset_by_name(const char *csname); +CHARSET_INFO * STDCALL mariadb_get_charset_by_nr(unsigned int csnr); size_t STDCALL mariadb_convert_string(const char *from, size_t *from_len, CHARSET_INFO *from_cs, char *to, size_t *to_len, CHARSET_INFO *to_cs, int *errorcode); int STDCALL mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...); @@ -493,6 +493,7 @@ my_socket STDCALL mysql_get_socket(const MYSQL *mysql); unsigned int STDCALL mysql_get_timeout_value(const MYSQL *mysql); unsigned int STDCALL mysql_get_timeout_value_ms(const MYSQL *mysql); int STDCALL mariadb_get_connection_type(MYSQL *mysql); +my_bool STDCALL mysql_reconnect(MYSQL *mysql); /* Async API */ int STDCALL mysql_close_start(MYSQL *sock); @@ -628,6 +629,7 @@ struct st_mysql_methods { int (*db_stmt_fetch_to_bind)(MYSQL_STMT *stmt, unsigned char *row); void (*db_stmt_flush_unbuffered)(MYSQL_STMT *stmt); void (*set_error)(MYSQL *mysql, unsigned int error_nr, const char *sqlstate, const char *format, ...); + my_bool (*reconnect)(MYSQL *mysql); }; /* synonyms/aliases functions */ diff --git a/include/mysql/client_plugin.h b/include/mysql/client_plugin.h index f9c4199b..616de69e 100644 --- a/include/mysql/client_plugin.h +++ b/include/mysql/client_plugin.h @@ -95,6 +95,7 @@ typedef struct st_ma_connection_plugin int (*options)(MYSQL *mysql, enum mysql_option, void *arg); int (*set_connection)(MYSQL *mysql,enum enum_server_command command, const char *arg, size_t length, my_bool skipp_check, void *opt_arg); + my_bool (*reconnect)(MYSQL *mysql); } MARIADB_CONNECTION_PLUGIN; #define MARIADB_DB_DRIVER(a) ((a)->ext_db) diff --git a/include/mysql_com.h b/include/mysql_com.h index 415e002d..4c684d74 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -230,6 +230,7 @@ typedef struct st_connection_handler { struct st_ma_connection_plugin *plugin; void *data; + my_bool active; my_bool free_data; } MA_CONNECTION_HANDLER; diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index e42f3888..7f0ba6e8 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -34,6 +34,8 @@ SET(EXPORT_SYMBOLS mariadb_dyncol_val_double mariadb_dyncol_val_long mariadb_dyncol_val_str + mariadb_get_charset_by_name + mariadb_get_charset_by_nr mariadb_get_connection_type mysql_affected_rows mysql_autocommit @@ -124,6 +126,7 @@ SET(EXPORT_SYMBOLS mysql_query mysql_query_cont mysql_query_start + mysql_reconnect mysql_read_query_result mysql_read_query_result_cont mysql_read_query_result_start diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 3a1e7177..bab2a079 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -124,11 +124,14 @@ struct st_mysql_methods MARIADB_DEFAULT_METHODS; #define native_password_plugin_name "mysql_native_password" +#define IS_CONNHDLR_ACTIVE(mysql)\ + ((mysql)->net.conn_hdlr && (mysql)->net.conn_hdlr->active) + static void end_server(MYSQL *mysql); static void mysql_close_memory(MYSQL *mysql); void read_user_name(char *name); static void append_wild(char *to,char *end,const char *wild); -static my_bool mysql_reconnect(MYSQL *mysql); +my_bool mysql_reconnect(MYSQL *mysql); static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length); extern int mysql_client_plugin_init(); @@ -354,13 +357,6 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg, DBUG_PRINT("info", ("server_command: %d packet_size: %u", command, length)); - if (mysql->net.conn_hdlr && mysql->net.conn_hdlr->data) - { - result= mysql->net.conn_hdlr->plugin->set_connection(mysql, command, arg, length, skipp_check, opt_arg); - if (result== -1) - DBUG_RETURN(result); - } - if (mysql->net.pvio == 0) { /* Do reconnect if possible */ if (mysql_reconnect(mysql)) @@ -376,6 +372,14 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg, goto end; } + if (IS_CONNHDLR_ACTIVE(mysql)) + { + result= mysql->net.conn_hdlr->plugin->set_connection(mysql, command, arg, length, skipp_check, opt_arg); + if (result== -1) + DBUG_RETURN(result); + } + + CLEAR_CLIENT_ERROR(mysql); mysql->info=0; @@ -384,13 +388,6 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg, if (!arg) arg=""; - /* check if connection kills itself */ - if (command == COM_PROCESS_KILL) - { - unsigned long thread_id= uint4korr(arg); - if (thread_id == mysql->thread_id) - skipp_check= 1; - } if (net_write_command(net,(uchar) command,arg, length ? length : (ulong) strlen(arg))) { @@ -660,7 +657,7 @@ enum option_val #define OPT_SET_EXTENDED_VALUE_INT(OPTS, KEY, VAL) \ CHECK_OPT_EXTENSION_SET(OPTS) \ -+ (OPTS)->extension->KEY= (VAL) + (OPTS)->extension->KEY= (VAL) static TYPELIB option_types={array_elements(default_options)-1, @@ -1145,6 +1142,7 @@ mysql_init(MYSQL *mysql) bzero((char*) (mysql),sizeof(*(mysql))); mysql->options.connect_timeout=CONNECT_TIMEOUT; mysql->charset= default_charset_info; + mysql->methods= &MARIADB_DEFAULT_METHODS; strmov(mysql->net.sqlstate, "00000"); mysql->net.last_error[0]= mysql->net.last_errno= 0; @@ -1291,9 +1289,38 @@ mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, uint port, const char *unix_socket,unsigned long client_flag) { + char *end; + if (!mysql->methods) mysql->methods= &MARIADB_DEFAULT_METHODS; + if (host && (end= strstr(host, "://"))) + { + MARIADB_CONNECTION_PLUGIN *plugin; + char plugin_name[64]; + + bzero(plugin_name, 64); + strncpy(plugin_name, host, MIN(end - host, 63)); + end+= 3; + + if (!(plugin= (MARIADB_CONNECTION_PLUGIN *)mysql_client_find_plugin(mysql, plugin_name, MARIADB_CLIENT_CONNECTION_PLUGIN))) + return NULL; + + if (!(mysql->net.conn_hdlr= (MA_CONNECTION_HANDLER *)my_malloc(sizeof(MA_CONNECTION_HANDLER), MYF(MY_ZEROFILL)))) + { + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); + return NULL; + } + + /* save URL for reconnect */ + OPT_SET_EXTENDED_VALUE_STR(&mysql->options, url, host); + + mysql->net.conn_hdlr->plugin= plugin; + + if (plugin && plugin->connect) + return plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag); + } + return mysql->methods->db_connect(mysql, host, user, passwd, db, port, unix_socket, client_flag); } @@ -1320,32 +1347,6 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, if (!mysql->methods) mysql->methods= &MARIADB_DEFAULT_METHODS; - /* special case: - * If hostname contains "://", e.g. "repl://localhost", we need to process connection - * by connection plugin - */ - if (host && (end= strstr(host, "://"))) - { - MARIADB_CONNECTION_PLUGIN *plugin; - char plugin_name[64]; - - bzero(plugin_name, 64); - strncpy(plugin_name, host, MIN(end - host, 63)); - end+= 3; - if (!(plugin= (MARIADB_CONNECTION_PLUGIN *)mysql_client_find_plugin(mysql, plugin_name, MARIADB_CLIENT_CONNECTION_PLUGIN))) - DBUG_RETURN(NULL); - - if (!(mysql->net.conn_hdlr= (MA_CONNECTION_HANDLER *)my_malloc(sizeof(MA_CONNECTION_HANDLER), MYF(MY_ZEROFILL)))) - { - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); - DBUG_RETURN(NULL); - } - - mysql->net.conn_hdlr->plugin= plugin; - - if (plugin->connect) - return plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag); - } ma_set_connect_attrs(mysql); @@ -1659,7 +1660,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, mysql->reconnect= 0; for (;begin < end; begin++) - { + { if (mysql_real_query(mysql, *begin, (unsigned long)strlen(*begin))) goto error; @@ -1715,14 +1716,22 @@ my_suspend_hook(my_bool suspend, void *data) } -static my_bool mysql_reconnect(MYSQL *mysql) +my_bool STDCALL mysql_reconnect(MYSQL *mysql) { MYSQL tmp_mysql; struct my_hook_data hook_data; struct mysql_async_context *ctxt= NULL; + LIST *li_stmt= mysql->stmts; DBUG_ENTER("mysql_reconnect"); + /* check if connection handler is active */ + if (IS_CONNHDLR_ACTIVE(mysql)) + { + if (mysql->net.conn_hdlr->plugin && mysql->net.conn_hdlr->plugin->connect) + DBUG_RETURN(mysql->net.conn_hdlr->plugin->reconnect(mysql)); + } + if (!mysql->reconnect || (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) { @@ -1734,6 +1743,13 @@ static my_bool mysql_reconnect(MYSQL *mysql) mysql_init(&tmp_mysql); tmp_mysql.options=mysql->options; + if (mysql->net.conn_hdlr) + { + tmp_mysql.net.conn_hdlr= mysql->net.conn_hdlr; + mysql->net.conn_hdlr= 0; + } + + /* don't reread options from configuration files */ tmp_mysql.options.my_cnf_group= tmp_mysql.options.my_cnf_file= NULL; @@ -1762,6 +1778,17 @@ static my_bool mysql_reconnect(MYSQL *mysql) DBUG_RETURN(1); } + for (;li_stmt;li_stmt= li_stmt->next) + { + MYSQL_STMT *stmt= (MYSQL_STMT *)li_stmt->data; + + if (stmt->state != MYSQL_STMT_INITTED) + { + stmt->state= MYSQL_STMT_INITTED; + SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0); + } + } + tmp_mysql.reconnect= mysql->reconnect; tmp_mysql.free_me= mysql->free_me; tmp_mysql.stmts= mysql->stmts; @@ -1923,6 +1950,7 @@ static void mysql_close_options(MYSQL *mysql) my_free(mysql->options.extension->ssl_fp); my_free(mysql->options.extension->ssl_fp_list); my_free(mysql->options.extension->ssl_pw); + my_free(mysql->options.extension->url); if(hash_inited(&mysql->options.extension->connect_attrs)) hash_free(&mysql->options.extension->connect_attrs); if ((ctxt = mysql->options.extension->async_context) != 0) @@ -1985,7 +2013,8 @@ mysql_close(MYSQL *mysql) DBUG_ENTER("mysql_close"); if (mysql) /* Some simple safety */ { - if (mysql->net.conn_hdlr && mysql->net.conn_hdlr->data) + + if (IS_CONNHDLR_ACTIVE(mysql)) { void *p= (void *)mysql->net.conn_hdlr; mysql->net.conn_hdlr->plugin->close(mysql); @@ -1998,6 +2027,7 @@ mysql_close(MYSQL *mysql) /* reset the connection in all active statements */ ma_invalidate_stmts(mysql, "mysql_close()"); + mysql_close_memory(mysql); mysql_close_options(mysql); mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; @@ -2048,7 +2078,9 @@ int mthd_my_read_query_result(MYSQL *mysql) DBUG_ENTER("mthd_my_read_query_result"); if (!mysql || (length = net_safe_read(mysql)) == packet_error) + { DBUG_RETURN(1); + } free_old_query(mysql); /* Free old result */ get_info: pos=(uchar*) mysql->net.read_pos; @@ -2496,7 +2528,6 @@ mysql_stat(MYSQL *mysql) DBUG_RETURN((char*) mysql->net.read_pos); } - int STDCALL mysql_ping(MYSQL *mysql) { @@ -2510,7 +2541,6 @@ mysql_ping(MYSQL *mysql) return rc; } - char * STDCALL mysql_get_server_info(MYSQL *mysql) { @@ -2878,10 +2908,8 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_pw, (char *)arg1); break; case MARIADB_OPT_CONNECTION_READ_ONLY: - if (mysql->net.conn_hdlr) - DBUG_RETURN(mysql->net.conn_hdlr->plugin->options(mysql, MARIADB_OPT_CONNECTION_READ_ONLY, arg1)); - else - return -1; + OPT_SET_EXTENDED_VALUE_INT(&mysql->options, read_only, *(my_bool *)arg1); + break; default: va_end(ap); DBUG_RETURN(-1); @@ -3278,6 +3306,15 @@ int STDCALL mariadb_get_connection_type(MYSQL *mysql) return (int)mysql->net.pvio->type; } +CHARSET_INFO * STDCALL mariadb_get_charset_by_name(const char *csname) +{ + return (CHARSET_INFO *)mysql_find_charset_name(csname); +} + +CHARSET_INFO * STDCALL mariadb_get_charset_by_nr(unsigned int csnr) +{ + return (CHARSET_INFO *)mysql_find_charset_nr(csnr); +} /* * Default methods for a connection. These methods are * stored in mysql->methods and can be overwritten by @@ -3315,5 +3352,9 @@ struct st_mysql_methods MARIADB_DEFAULT_METHODS = { /* store values in bind buffer */ mthd_stmt_fetch_to_bind, /* skip unbuffered stmt result */ - mthd_stmt_flush_unbuffered + mthd_stmt_flush_unbuffered, + /* set error */ + my_set_error, + /* reconnect */ + mysql_reconnect }; diff --git a/libmariadb/my_stmt.c b/libmariadb/my_stmt.c index 7f0355b5..58a5c951 100644 --- a/libmariadb/my_stmt.c +++ b/libmariadb/my_stmt.c @@ -416,7 +416,6 @@ int store_param(MYSQL_STMT *stmt, int column, unsigned char **p) { DBUG_ENTER("store_param"); DBUG_PRINT("info", ("column: %d type: %d", column, stmt->params[column].buffer_type)); - printf("type: %d\n", column, stmt->params[column].buffer_type); switch (stmt->params[column].buffer_type) { case MYSQL_TYPE_TINY: int1store(*p, *(uchar *)stmt->params[column].buffer); diff --git a/libmariadb/net.c b/libmariadb/net.c index b8dbf45c..94c32104 100644 --- a/libmariadb/net.c +++ b/libmariadb/net.c @@ -182,7 +182,9 @@ static my_bool net_realloc(NET *net, size_t length) /* Remove unwanted characters from connection */ void net_clear(NET *net) { + size_t len; DBUG_ENTER("net_clear"); + ma_pvio_has_data(net->pvio, &len); net->compress_pkt_nr= net->pkt_nr=0; /* Ready for new command */ net->write_pos=net->buff; DBUG_VOID_RETURN; @@ -193,6 +195,7 @@ int net_flush(NET *net) { int error=0; DBUG_ENTER("net_flush"); + if (net->buff != net->write_pos) { error=net_real_write(net,(char*) net->buff, diff --git a/plugins/connection/CMakeLists.txt b/plugins/connection/CMakeLists.txt index f5d7cc19..f68269b6 100644 --- a/plugins/connection/CMakeLists.txt +++ b/plugins/connection/CMakeLists.txt @@ -13,10 +13,24 @@ IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC") "FILE_DESCRIPTION:Connection plugin for master/slave environment") ENDIF() ADD_DEFINITIONS(-DHAVE_REPLICATION_DYNAMIC=1) - ADD_LIBRARY(replication SHARED replication.c ${EXPORT_FILE}) + ADD_LIBRARY(replication SHARED ${replication_RC} replication.c ${EXPORT_FILE}) SET(INSTALL_LIBS replication) ENDIF() +IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC") + IF(WIN32) + SET_VERSION_INFO("TARGET:aurora" + "FILE_TYPE:VFT_DLL" + "SOURCE_FILE:plugins/connection/aurora.c" + "ORIGINAL_FILE_NAME:aurora.dll" + "FILE_DESCRIPTION:Connection plugin for Amazon AWS Aurora") + ENDIF() + ADD_DEFINITIONS(-DHAVE_AURORA_DYNAMIC=1) + ADD_LIBRARY(aurora SHARED ${aurora_RC} aurora.c ${EXPORT_FILE}) + SET(INSTALL_LIBS ${INSTALL_LIBS} aurora) +ENDIF() + + IF(INSTALL_LIBS) INSTALL(TARGETS ${INSTALL_LIBS} diff --git a/plugins/connection/aurora.c b/plugins/connection/aurora.c new file mode 100644 index 00000000..4c605058 --- /dev/null +++ b/plugins/connection/aurora.c @@ -0,0 +1,820 @@ +/************************************************************************************ + Copyright (C) 2015 MariaDB Corporation AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not see + or write to the Free Software Foundation, Inc., + 51 Franklin St., Fifth Floor, Boston, MA 02110, USA + + Part of this code includes code from the PHP project which + is freely available from http://www.php.net + *************************************************************************************/ + +/* MariaDB Connection plugin for Aurora failover */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef WIN32 +#include +#endif + +/* function prototypes */ +int aurora_init(char *errormsg, size_t errormsg_size, + int unused __attribute__((unused)), + va_list unused1 __attribute__((unused))); + +MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, + const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag); +void aurora_close(MYSQL *mysql); +int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *arg, + size_t length, my_bool skipp_check, void *opt_arg); +int aurora_set_options(MYSQL *msql, enum mysql_option option, void *arg); +my_bool aurora_reconnect(MYSQL *mysql); + +#define AURORA_MAX_INSTANCES 16 + +#define AURORA_UNKNOWN -1 +#define AURORA_PRIMARY 0 +#define AURORA_REPLICA 1 +#define AURORA_UNAVAILABLE 2 + +#define ENABLE_AURORA(mysql)\ + (mysql)->net.conn_hdlr->active= 1; +#define DISABLE_AURORA(mysql)\ + (mysql)->net.conn_hdlr->active= 0; + +#ifndef HAVE_REPLICATION_DYNAMIC +MARIADB_CONNECTION_PLUGIN connection_aurora_plugin = +#else +MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ = +#endif +{ + MARIADB_CLIENT_CONNECTION_PLUGIN, + MARIADB_CLIENT_CONNECTION_PLUGIN_INTERFACE_VERSION, + "aurora", + "Georg Richter", + "MariaDB connection plugin for Aurora failover", + {1, 0, 0}, + "LGPL", + aurora_init, + NULL, + aurora_connect, + aurora_close, + aurora_set_options, + aurora_command, + aurora_reconnect +}; + +typedef struct st_aurora_instance { + char *host; + int port; + time_t blacklisted; + int type; +} AURORA_INSTANCE; + +typedef struct st_conn_aurora { + MARIADB_PVIO *pvio[2]; + MYSQL *mysql[2]; + my_bool active[2]; + char *url; + unsigned int num_instances; + AURORA_INSTANCE instance[AURORA_MAX_INSTANCES]; + char *username, *password, *database; + unsigned int port; + unsigned long client_flag; + unsigned int last_instance_type; /* Primary or Replica */ + char primary_id[100]; +} AURORA; + +#define AURORA_BLACKLIST_TIMEOUT 150 + +#define AURORA_IS_BLACKLISTED(a, i) \ + ((time(NULL) - (a)->instance[(i)].blacklisted) < AURORA_BLACKLIST_TIMEOUT) + +/* {{{ my_bool aurora_swutch_connection */ +my_bool aurora_switch_connection(MYSQL *mysql, AURORA *aurora, int type) +{ + switch (type) + { + case AURORA_REPLICA: + if (aurora->mysql[AURORA_REPLICA]) + { + mysql->net.pvio= aurora->pvio[AURORA_REPLICA]; + aurora->pvio[AURORA_REPLICA]->mysql= mysql; + mysql->thread_id= aurora->mysql[AURORA_REPLICA]->thread_id; + aurora->last_instance_type= AURORA_REPLICA; + } + break; + case AURORA_PRIMARY: + if (aurora->mysql[AURORA_PRIMARY]) + { + if (aurora->mysql[AURORA_REPLICA]) + aurora->mysql[AURORA_REPLICA]->net.pvio->mysql= aurora->mysql[AURORA_REPLICA]; + mysql->net.pvio= aurora->pvio[AURORA_PRIMARY]; + mysql->thread_id= aurora->mysql[AURORA_PRIMARY]->thread_id; + aurora->last_instance_type= AURORA_PRIMARY; + } + break; + } +} +/* }}} */ + +/* {{{ int aurora_init + * + * plugin initialization function + */ +int aurora_init(char *errormsg, size_t errormsg_size, + int unused __attribute__((unused)), + va_list unused1 __attribute__((unused))) +{ + /* random generator initialization */ +#ifndef WIN32 + struct timeval tp; + gettimeofday(&tp,NULL); + srand(tp.tv_usec / 1000 + tp.tv_sec * 1000); +#else + srand(GetTickCount()); +#endif + return 0; +} +/* }}} */ + +/* {{{ void aurora_close_memory */ +void aurora_close_memory(AURORA *aurora) +{ + free(aurora->url); + free(aurora->username); + free(aurora->password); + free(aurora->database); + free(aurora); +} +/* }}} */ + +/* {{{ my_bool aurora_parse_url + * + * parse url + * Url has the following format: + * instance1:port, instance2:port, .., instanceN:port + * + */ +my_bool aurora_parse_url(const char *url, AURORA *aurora) +{ + char *p, *c; + int i; + + if (!url || url[0] == 0) + return 1; + + bzero(aurora->instance, (AURORA_MAX_INSTANCES + 1) * sizeof(char *)); + bzero(&aurora->port, (AURORA_MAX_INSTANCES + 1) * sizeof(int)); + + if (aurora->url) + free(aurora->url); + + aurora->url= strdup(url); + c= aurora->url; + + /* get instances */ + while((c)) + { + if (p= strchr(c, ',')) + { + *p= '\0'; + p++; + } + if (*c) + { + aurora->instance[aurora->num_instances].host= c; + aurora->num_instances++; + } + c= p; + } + + if (!aurora->num_instances) + return 0; + + /* check ports */ + for (i=0; i < aurora->num_instances && aurora->instance[i].host; i++) + { + aurora->instance[i].type= AURORA_UNKNOWN; + + /* We need to be aware of IPv6 addresses: According to RFC3986 sect. 3.2.2 + hostnames have to be enclosed in square brackets if a port is given */ + if (aurora->instance[i].host[0]== '[' && + strchr(aurora->instance[i].host, ':') && + (p= strchr(aurora->instance[i].host,']'))) + { + /* ignore first square bracket */ + memmove(aurora->instance[i].host, + aurora->instance[i].host+1, + strlen(aurora->instance[i].host) - 1); + p= strchr(aurora->instance[i].host,']'); + *p= 0; + p++; + } + else + p= aurora->instance[i].host; + if (p && (p= strchr(p, ':'))) + { + *p= '\0'; + p++; + aurora->instance[i].port= atoi(p); + } + } + return 0; +} +/* }}} */ + +/* {{{ int aurora_get_instance_type + * + * RETURNS: + * + * AURORA_PRIMARY + * AURORA_REPLICA + * -1 on error + */ +int aurora_get_instance_type(MYSQL *mysql) +{ + int rc; + char *query= "select variable_value from information_schema.global_variables where variable_name='INNODB_READ_ONLY' AND variable_value='OFF'"; + + if (!mysql_query(mysql, query)) + { + MYSQL_RES *res= mysql_store_result(mysql); + rc= mysql_num_rows(res) ? AURORA_PRIMARY : AURORA_REPLICA; + mysql_free_result(res); + return rc; + } + return -1; +} +/* }}} */ + +/* {{{ my_bool aurora_get_primary_id + * + * try to find primary instance from slave by retrieving + * primary_id information_schema.replica_host_status information + * + * If the function succeeds, primary_id will be copied into + * aurora->primary_id + * + * Returns: + * 1 on success + * 0 if an error occured or primary_id couldn't be + * found + */ +my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora) +{ + my_bool rc= 0; + + if (!mysql_query(mysql, "select server_id from information_schema.replica_host_status " + "where session_id = 'MASTER_SESSION_ID'")) + { + MYSQL_RES *res; + MYSQL_ROW row; + + if ((res= mysql_store_result(mysql))) + { + if ((row= mysql_fetch_row(res))) + { + if (row[0]) + { + strcpy(aurora->primary_id, row[0]); + rc= 1; + } + } + mysql_free_result(res); + } + } + return rc; +} +/* }}} */ + +/* {{{ unsigned int aurora_get_valid_instances + * + * returns the number of instances which are + * not blacklisted or don't have a type assigned. + */ +static unsigned int aurora_get_valid_instances(AURORA *aurora, AURORA_INSTANCE **instances) +{ + int i, valid_instances= 0; + + memset(instances, 0, sizeof(AURORA_INSTANCE *) * AURORA_MAX_INSTANCES); + + for (i=0; i < aurora->num_instances; i++) + { + if (aurora->instance[i].type != AURORA_UNAVAILABLE) + { + if (aurora->instance[i].type == AURORA_PRIMARY && aurora->active[AURORA_PRIMARY]) + continue; + instances[valid_instances]= &aurora->instance[i]; + valid_instances++; + } + } + return valid_instances; +} +/* }}} */ + +/* {{{ void aurora_refresh_blacklist() */ +void aurora_refresh_blacklist(AURORA *aurora) +{ + int i; + for (i=0; i < aurora->num_instances; i++) + { + if (aurora->instance[i].blacklisted && + !(AURORA_IS_BLACKLISTED(aurora, i))) + { + aurora->instance[i].blacklisted= 0; + aurora->instance[i].type= AURORA_UNKNOWN; + } + } +} +/* }}} */ + +/* {{{ MYSQL *aurora_connect_instance() */ +MYSQL *aurora_connect_instance(AURORA *aurora, AURORA_INSTANCE *instance, MYSQL *mysql) +{ + if (!mysql->methods->db_connect(mysql, + instance->host, + aurora->username, + aurora->password, + aurora->database, + instance->port ? instance->port : aurora->port, + NULL, + aurora->client_flag)) + { + /* connection not available */ + instance->blacklisted= time(NULL); + instance->type= AURORA_UNAVAILABLE; + return NULL; + } + + /* check if we are slave or master */ + switch (aurora_get_instance_type(mysql)) + { + case AURORA_PRIMARY: + instance->type= AURORA_PRIMARY; + return mysql; + break; + case AURORA_REPLICA: + instance->type= AURORA_REPLICA; + break; + default: + instance->type= AURORA_UNAVAILABLE; + instance->blacklisted= time(NULL); + return NULL; + } + if (!aurora->primary_id[0]) + aurora_get_primary_id(mysql, aurora); + return mysql; +} +/* }}} */ + +/* {{{ void aurora_copy_mysql() */ +void aurora_copy_mysql(MYSQL *from, MYSQL *to) +{ + LIST *li_stmt= to->stmts; + + for (;li_stmt;li_stmt= li_stmt->next) + { + MYSQL_STMT *stmt= (MYSQL_STMT *)li_stmt->data; + + if (stmt->state != MYSQL_STMT_INITTED) + { + stmt->state= MYSQL_STMT_INITTED; + SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0); + } + } + + from->free_me= to->free_me; + from->reconnect= to->reconnect; + from->net.conn_hdlr= to->net.conn_hdlr; + from->stmts= to->stmts; + to->stmts= NULL; + + memset(&to->options, 0, sizeof(to->options)); + to->free_me= 0; + to->net.conn_hdlr= 0; + mysql_close(to); + *to= *from; + to->net.pvio= from->net.pvio; + to->net.pvio->mysql= to; + from->net.pvio= NULL; +} +/* }}} */ + +/* {{{ my_bool aurora_find_replica() */ +my_bool aurora_find_replica(AURORA *aurora) +{ + int valid_instances; + my_bool replica_found= 0; + AURORA_INSTANCE *instance[AURORA_MAX_INSTANCES]; + MYSQL mysql; +// struct st_dynamic_array *init_command= aurora->mysql[AURORA_PRIMARY]->options.init_command; + + if (aurora->num_instances < 2) + return 0; + + mysql_init(&mysql); + mysql.options= aurora->mysql[AURORA_PRIMARY]->options; + + /* don't execute init_command on slave */ + mysql.net.conn_hdlr= aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr; + + valid_instances= aurora_get_valid_instances(aurora, instance); + + while (valid_instances && !replica_found) + { + int random_pick= rand() % valid_instances; + if ((aurora_connect_instance(aurora, instance[random_pick], &mysql))) + { + switch (instance[random_pick]->type) { + case AURORA_REPLICA: + if (!aurora->mysql[AURORA_REPLICA]) + { + aurora->mysql[AURORA_REPLICA]= mysql_init(NULL); + } + aurora_copy_mysql(&mysql, aurora->mysql[AURORA_REPLICA]); + aurora->active[AURORA_REPLICA]= 1; + return 1; + break; + case AURORA_PRIMARY: + aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]); + aurora->pvio[AURORA_PRIMARY]= aurora->mysql[AURORA_PRIMARY]->net.pvio; + aurora->active[AURORA_PRIMARY]= 1; + continue; + break; + default: + mysql_close(&mysql); + return 0; + break; + } + } + valid_instances= aurora_get_valid_instances(aurora, instance); + } + return 0; +} +/* }}} */ + +/* {{{ AURORA_INSTANCE aurora_get_primary_id_instance() */ +AURORA_INSTANCE *aurora_get_primary_id_instance(AURORA *aurora) +{ + int i; + + if (!aurora->primary_id[0]) + return 0; + + for (i=0; i < aurora->num_instances; i++) + { + if (!strncmp(aurora->instance[i].host, aurora->primary_id, strlen(aurora->primary_id))) + return &aurora->instance[i]; + } + return NULL; +} +/* }}} */ + +/* {{{ my_bool aurora_find_primary() */ +my_bool aurora_find_primary(AURORA *aurora) +{ + int i; + AURORA_INSTANCE *instance= NULL; + MYSQL mysql; + my_bool check_primary= 1; + + if (!aurora->num_instances) + return 0; + + mysql_init(&mysql); + mysql.options= aurora->mysql[AURORA_PRIMARY]->options; + mysql.net.conn_hdlr= aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr; + + for (i=0; i < aurora->num_instances; i++) + { + if (check_primary && aurora->primary_id[0]) + { + if ((instance= aurora_get_primary_id_instance(aurora)) && + aurora_connect_instance(aurora, instance, &mysql) && + instance->type == AURORA_PRIMARY) + { + aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]); + aurora->active[AURORA_PRIMARY]= 1; + return 1; + } + /* primary id connect failed, don't try again */ + aurora->primary_id[0]= 0; + check_primary= 0; + } + if (aurora->instance[i].type != AURORA_UNAVAILABLE) + { + if (aurora_connect_instance(aurora, &aurora->instance[i], &mysql) + && aurora->instance[i].type == AURORA_PRIMARY) + { + aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]); + aurora->active[AURORA_PRIMARY]= 1; + return 1; + } + } + } + return 0; +} +/* }}} */ + +/* {{{ void aurora_close_replica() */ +void aurora_close_replica(MYSQL *mysql, AURORA *aurora) +{ + if (aurora->mysql[AURORA_REPLICA]) + { + aurora->mysql[AURORA_REPLICA]->net.pvio->mysql= aurora->mysql[AURORA_REPLICA]; + aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0; + mysql_close(aurora->mysql[AURORA_REPLICA]); + aurora->pvio[AURORA_REPLICA]= 0; + aurora->mysql[AURORA_REPLICA]= NULL; + } +} +/* }}} */ + +/* {{{ MYSQL *aurora_connect */ +MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, + const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag) +{ + AURORA *aurora= NULL; + MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; + my_bool is_reconnect= 0; + + if ((aurora= (AURORA *)hdlr->data)) + { + aurora_refresh_blacklist(aurora); + if (aurora->mysql[aurora->last_instance_type]->net.pvio) + { + SET_CLIENT_ERROR(mysql, CR_ALREADY_CONNECTED, SQLSTATE_UNKNOWN, 0); + return NULL; + } + is_reconnect= 1; + } + else + { + if (!(aurora= (AURORA *)my_malloc(sizeof(AURORA), MYF(MY_ZEROFILL)))) + { + mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); + return NULL; + } + + mysql->net.conn_hdlr->data= (void *)aurora; + + aurora->mysql[AURORA_PRIMARY]= mysql; + + if (aurora_parse_url(host, aurora)) + { + goto error; + } + + if (user) + aurora->username= strdup(user); + if (passwd) + aurora->password= strdup(passwd); + if (db) + aurora->database= strdup(db); + aurora->port= port; + aurora->client_flag= client_flag; + aurora->pvio[AURORA_PRIMARY]= aurora->pvio[AURORA_REPLICA]= NULL; + hdlr->data= aurora; + } + + + /* In case of reconnect, close broken connection first */ + if (is_reconnect) + { + DISABLE_AURORA(mysql); + switch (aurora->last_instance_type) { + case AURORA_REPLICA: + aurora_close_replica(mysql, aurora); + aurora->pvio[AURORA_REPLICA]= NULL; + break; + case AURORA_PRIMARY: + /* pvio will be closed in mysql_reconnect() */ + aurora->pvio[AURORA_PRIMARY]= NULL; + aurora->primary_id[0]= 0; + break; + } + aurora->active[aurora->last_instance_type]= 0; + } + + if (!aurora->active[AURORA_REPLICA]) + { + if (aurora_find_replica(aurora)) + { + aurora->pvio[AURORA_REPLICA]= aurora->mysql[AURORA_REPLICA]->net.pvio; + aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= mysql->net.conn_hdlr; + } + else + aurora->pvio[AURORA_REPLICA]= NULL; + } + + if (!aurora->active[AURORA_PRIMARY]) + { + if (aurora_find_primary(aurora)) + { + aurora->active[AURORA_PRIMARY]= 1; + aurora->pvio[AURORA_PRIMARY]= aurora->mysql[AURORA_PRIMARY]->net.pvio; + } + } + + aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + ENABLE_AURORA(mysql); + return mysql; +error: + aurora_close_memory(aurora); + return NULL; +} +/* }}} */ + +/* {{{ my_bool aurora_reconnect */ +my_bool aurora_reconnect(MYSQL *mysql) +{ + AURORA *aurora; + MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; + my_bool rc= 1; + + aurora= (AURORA *)hdlr->data; + + DISABLE_AURORA(mysql); + switch (aurora->last_instance_type) + { + case AURORA_REPLICA: + if (!(rc= mysql->methods->reconnect(aurora->mysql[aurora->last_instance_type]))) + aurora_switch_connection(mysql, aurora, AURORA_REPLICA); + break; + case AURORA_PRIMARY: + if (!(rc= mysql->methods->reconnect(aurora->mysql[aurora->last_instance_type]))) + aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + break; + default: + /* todo: error message */ + break; + } + ENABLE_AURORA(mysql); + return rc; +} +/* }}} */ + +/* {{{ void aurora_close */ +void aurora_close(MYSQL *mysql) +{ + MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; + AURORA *aurora= (AURORA *)hdlr->data; + + aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + + /* if the connection is not active yet, just return */ + if (!aurora->active[1]) + return; + + if (aurora->mysql[AURORA_REPLICA]) + { + /* we got options from primary, so don't free it twice */ + memset(&aurora->mysql[AURORA_REPLICA]->options, 0, sizeof(mysql->options)); + /* connection handler wull be freed in mysql_close() */ + aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0; + + mysql_close(aurora->mysql[AURORA_REPLICA]); + } + + if (aurora->mysql[AURORA_PRIMARY]) + { + /* connection handler wull be freed in mysql_close() */ + aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr= 0; + + aurora->mysql[AURORA_PRIMARY]->net.pvio= aurora->pvio[AURORA_PRIMARY]; + + mysql_close(aurora->mysql[AURORA_PRIMARY]); + } + + + +/* + if (aurora->mysql[AURORA_PRIMARY]) + { + aurora->mysql[AURORA_PRIMARY]->net.pvio= aurora->pvio[AURORA_PRIMARY]; + aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr= 0; + mysql_close(aurora->mysql[AURORA_PRIMARY]); + } +*/ + /* free masrwe information */ + aurora_close_memory(aurora); +} +/* }}} */ + +/* {{{ my_bool is_replica_command */ +my_bool is_replica_command(const char *buffer, size_t buffer_len) +{ + const char *buffer_end= buffer + buffer_len; + + for (; buffer < buffer_end; ++buffer) + { + char c; + if (isalpha(c=*buffer)) + { + if (tolower(c) == 's') + return 1; + return 0; + } + } + return 0; +} +/* }}} */ + +/* {{{ my_bool is_replica_stmt */ +my_bool is_replica_stmt(MYSQL *mysql, const char *buffer) +{ + unsigned long stmt_id= uint4korr(buffer); + LIST *stmt_list= mysql->stmts; + + for (; stmt_list; stmt_list= stmt_list->next) + { + MYSQL_STMT *stmt= (MYSQL_STMT *)stmt_list->data; + if (stmt->stmt_id == stmt_id) + return 1; + } + return 0; +} +/* }}} */ + +/* {{{ int aurora_command */ +int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *arg, + size_t length, my_bool skipp_check, void *opt_arg) +{ + AURORA *aurora= (AURORA *)mysql->net.conn_hdlr->data; + + /* if we don't have slave or slave became unavailable root traffic to master */ + if (!aurora->mysql[AURORA_REPLICA] || !OPT_HAS_EXT_VAL(mysql, read_only)) + { + if (command != COM_INIT_DB) + { + aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + return 0; + } + } + + switch(command) { + case COM_INIT_DB: + /* we need to change default database on primary and replica */ + if (aurora->mysql[AURORA_REPLICA] && aurora->last_instance_type != AURORA_REPLICA) + { + aurora_switch_connection(mysql, aurora, AURORA_REPLICA); + DISABLE_AURORA(mysql); + mysql_select_db(aurora->mysql[AURORA_REPLICA], arg); + ENABLE_AURORA(mysql); + aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + } + break; + case COM_QUERY: + case COM_STMT_PREPARE: + if (aurora->mysql[AURORA_REPLICA] && aurora->last_instance_type != AURORA_REPLICA) + aurora_switch_connection(mysql, aurora, AURORA_REPLICA); + break; + case COM_STMT_EXECUTE: + case COM_STMT_FETCH: + if (aurora->pvio[AURORA_REPLICA]->mysql->stmts && is_replica_stmt(aurora->pvio[AURORA_REPLICA]->mysql, arg)) + { + if (aurora->last_instance_type != AURORA_REPLICA) + aurora_switch_connection(mysql, aurora, AURORA_REPLICA); + } + else + { + if (aurora->last_instance_type != AURORA_PRIMARY) + aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + } + + default: + aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + break; + } + return 0; +} +/* }}} */ + +/* {{{ int aurora_set_options() */ +int aurora_set_options(MYSQL *mysql, enum mysql_option option, void *arg) +{ + switch(option) { + default: + return -1; + } +} +/* }}} */ diff --git a/plugins/connection/replication.c b/plugins/connection/replication.c index cf5320ec..c9415c01 100644 --- a/plugins/connection/replication.c +++ b/plugins/connection/replication.c @@ -70,7 +70,8 @@ MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ = repl_connect, repl_close, repl_set_options, - repl_command + repl_command, + NULL }; typedef struct st_conn_repl { @@ -81,10 +82,20 @@ typedef struct st_conn_repl { char *url; char *host[2]; int port[2]; + unsigned int current_type; } REPL_DATA; -#define SET_SLAVE(mysql, data) mysql->net.pvio= data->pvio[MARIADB_SLAVE] -#define SET_MASTER(mysql, data) mysql->net.pvio= data->pvio[MARIADB_MASTER] +#define SET_SLAVE(mysql, data)\ +{\ + mysql->net.pvio= data->pvio[MARIADB_SLAVE]; \ + data->current_type= MARIADB_SLAVE;\ +} + +#define SET_MASTER(mysql, data)\ +{\ + mysql->net.pvio= data->pvio[MARIADB_MASTER];\ + data->current_type= MARIADB_MASTER;\ +} /* parse url @@ -108,10 +119,8 @@ my_bool repl_parse_url(const char *url, REPL_DATA *data) memset(data->host, 0, 2 * sizeof(char *)); memset(data->port, 0, 2 * sizeof(int)); - if (data->url) - my_free(data->url); - - data->url= my_strdup(url, MYF(0)); + if (!data->url) + data->url= my_strdup(url, MYF(0)); data->host[MARIADB_MASTER]= p= data->url; /* get slaves */ @@ -150,10 +159,11 @@ my_bool repl_parse_url(const char *url, REPL_DATA *data) { /* We need to be aware of IPv6 addresses: According to RFC3986 sect. 3.2.2 hostnames have to be enclosed in square brackets if a port is given */ - if (data->host[i][0]= '[' && strchr(data->host[i], ':') && (p= strchr(data->host[i],']'))) + if (data->host[i][0]== '[' && strchr(data->host[i], ':') && (p= strchr(data->host[i],']'))) { /* ignore first square bracket */ - data->host[i]++; + memmove(data->host[i], data->host[i]+1, strlen(data->host[i]) - 1); + p= strchr(data->host[i],']'); *p= 0; p++; } @@ -176,12 +186,18 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char REPL_DATA *data= NULL; MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; + if ((data= (REPL_DATA *)hdlr->data)) + { + ma_pvio_close(data->pvio[MARIADB_MASTER]); + data->pvio[MARIADB_MASTER]= 0; + repl_close(mysql); + } + if (!(data= calloc(1, sizeof(REPL_DATA)))) { mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); return NULL; } - memset(data->pvio, 0, 2 * sizeof(MARIADB_PVIO *)); if (repl_parse_url(host, data)) @@ -194,6 +210,7 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char data->pvio[MARIADB_MASTER]= mysql->net.pvio; hdlr->data= data; + SET_MASTER(mysql, data); /* to allow immediate access without connection delay, we will start * connecting to slave(s) in background */ @@ -245,7 +262,6 @@ void repl_close(MYSQL *mysql) my_free(data->url); my_free(data); mysql->net.conn_hdlr->data= NULL; - mysql_close(mysql); } static my_bool is_slave_command(const char *buffer, size_t buffer_len) @@ -295,20 +311,20 @@ int repl_command(MYSQL *mysql,enum enum_server_command command, const char *arg, case COM_QUERY: case COM_STMT_PREPARE: if (is_slave_command(arg, length)) - SET_SLAVE(mysql, data); + SET_SLAVE(mysql, data) else - SET_MASTER(mysql,data); + SET_MASTER(mysql,data) break; case COM_STMT_EXECUTE: case COM_STMT_FETCH: if (data->pvio[MARIADB_SLAVE]->mysql->stmts && is_slave_stmt(data->pvio[MARIADB_SLAVE]->mysql, arg)) - SET_SLAVE(mysql, data); + SET_SLAVE(mysql, data) else - SET_MASTER(mysql,data); + SET_MASTER(mysql,data) break; default: - SET_MASTER(mysql,data); + SET_MASTER(mysql,data) break; } return 0; diff --git a/plugins/pvio/pvio_npipe.c b/plugins/pvio/pvio_npipe.c index 00d0c5e7..623f6ba9 100644 --- a/plugins/pvio/pvio_npipe.c +++ b/plugins/pvio/pvio_npipe.c @@ -251,7 +251,7 @@ my_bool pvio_npipe_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo) 0, /* no sharing */ NULL, /* default security attributes */ OPEN_EXISTING, - 0, /* default attributes */ + FILE_FLAG_OVERLAPPED, NULL)) != INVALID_HANDLE_VALUE) break; diff --git a/unittest/libmariadb/CMakeLists.txt b/unittest/libmariadb/CMakeLists.txt index 4e8d2125..f60d8638 100644 --- a/unittest/libmariadb/CMakeLists.txt +++ b/unittest/libmariadb/CMakeLists.txt @@ -21,7 +21,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/unittest/mytap) ADD_DEFINITIONS(-DLIBMARIADB) -SET(API_TESTS "async" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" +SET(API_TESTS "aurora" "async" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" "sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread" "dyncol") # Get finger print from server certificate @@ -61,7 +61,7 @@ ENDIF() FOREACH(API_TEST ${API_TESTS}) ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c) - TARGET_LINK_LIBRARIES(${API_TEST} mytap mariadbclient ) + TARGET_LINK_LIBRARIES(${API_TEST} mytap libmariadb) ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST}) SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 120) ENDFOREACH(API_TEST) diff --git a/unittest/libmariadb/aurora.c b/unittest/libmariadb/aurora.c new file mode 100644 index 00000000..d9c89c45 --- /dev/null +++ b/unittest/libmariadb/aurora.c @@ -0,0 +1,67 @@ +/* +*/ + +#include "my_test.h" + +static int aurora1(MYSQL *mysql) +{ + int rc; + my_bool read_only= 1; + char *primary, *replica; + MYSQL_RES *res; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE t1 (a int, b varchar(20))"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1, 'foo'), (2, 'bar')"); + check_mysql_rc(rc, mysql); + + primary= mysql->host; + diag("primary: %s", primary); + + mysql_options(mysql, MARIADB_OPT_CONNECTION_READ_ONLY, &read_only); + + /* ensure, that this is a replica, so INSERT should fail */ + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (3, 'error')"); + if (rc) + diag("Expected error: %s", mysql_error(mysql)); + + rc= mysql_query(mysql, "SELECT a, b FROM t1"); + check_mysql_rc(rc, mysql); + + res= mysql_store_result(mysql); + + diag("Num_rows: %d", mysql_num_rows(res)); + mysql_free_result(res); + + replica= mysql->host; + diag("replica: %s", replica); + diag("db: %s", mysql->db); + + return OK; +} + +struct my_tests_st my_tests[] = { + {"aurora1", aurora1, TEST_CONNECTION_NEW, 0, NULL, NULL}, + {NULL, NULL, 0, 0, NULL, NULL} +}; + + +int main(int argc, char **argv) +{ + + mysql_library_init(0,0,NULL); + + if (argc > 1) + get_options(argc, argv); + + get_envvars(); + + run_tests(my_tests); + + mysql_server_end(); + return(exit_status()); +} diff --git a/unittest/libmariadb/basic-t.c b/unittest/libmariadb/basic-t.c index 4e535852..610ab460 100644 --- a/unittest/libmariadb/basic-t.c +++ b/unittest/libmariadb/basic-t.c @@ -55,13 +55,17 @@ static int test_conc75(MYSQL *my) { ulong thread_id= mysql_thread_id(mysql); /* force reconnect */ + mysql->reconnect= 1; + diag("killing connection"); mysql_kill(my, thread_id); - sleep(1); + sleep(2); + mysql_ping(mysql); rc= mysql_query(mysql, "load data local infile './nonexistingfile.csv' into table a (`a`)"); FAIL_IF(!test(mysql->options.client_flag | CLIENT_LOCAL_FILES), "client_flags not correct"); + diag("thread1: %d %d", thread_id, mysql_thread_id(mysql)); FAIL_IF(thread_id == mysql_thread_id(mysql), "new thread id expected"); - diag("cs: %s", mysql->charset->csname); - FAIL_IF(strcmp(mysql->charset->csname, "utf8"), "wrong character set"); + //diag("cs: %s", mysql->charset->csname); + //FAIL_IF(strcmp(mysql->charset->csname, "utf8"), "wrong character set"); } mysql_close(mysql); return OK; @@ -76,7 +80,12 @@ static int test_conc74(MYSQL *my) mysql= mysql_init(NULL); - mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS); + if (!mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS)) + { + diag("Error: %s", mysql_error(mysql)); + mysql_close(mysql); + return FAIL; + } rc= mysql_query(mysql, "DROP TABLE IF EXISTS a"); check_mysql_rc(rc, mysql); @@ -128,7 +137,11 @@ static int test_conc70(MYSQL *my) int rc; MYSQL_RES *res; MYSQL_ROW row; - MYSQL *mysql= mysql_init(NULL); + MYSQL *mysql; + + SKIP_CONNECTION_HANDLER; + + mysql= mysql_init(NULL); rc= mysql_query(my, "SET @a:=@@max_allowed_packet"); check_mysql_rc(rc, my); @@ -148,6 +161,14 @@ static int test_conc70(MYSQL *my) rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))"); check_mysql_rc(rc, mysql); + if (mysql_warning_count(mysql)) + { + diag("server doesn't accept package size"); + return SKIP; + } + + sleep(20); + rc= mysql_query(mysql, "SELECT a FROM t1"); check_mysql_rc(rc, mysql); @@ -175,7 +196,11 @@ static int test_conc68(MYSQL *my) int rc; MYSQL_RES *res; MYSQL_ROW row; - MYSQL *mysql= mysql_init(NULL); + MYSQL *mysql; + + SKIP_CONNECTION_HANDLER; + + mysql= mysql_init(NULL); rc= mysql_query(my, "SET @a:=@@max_allowed_packet"); check_mysql_rc(rc, my); @@ -193,6 +218,11 @@ static int test_conc68(MYSQL *my) rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))"); check_mysql_rc(rc, mysql); + if (mysql_warning_count(mysql)) + { + diag("server doesn't accept package size"); + return SKIP; + } rc= mysql_query(mysql, "SELECT a FROM t1"); check_mysql_rc(rc, mysql); @@ -504,6 +534,7 @@ static int test_mysql_insert_id(MYSQL *mysql) according to the manual, this might be 20 or 300, but it looks like auto_increment column takes priority over last_insert_id(). */ + diag("res: %d", res); FAIL_UNLESS(res == 20, ""); /* If first autogenerated number fails and 2nd works: */ rc= mysql_query(mysql, "drop table t2"); @@ -618,12 +649,9 @@ static int bug_conc1(MYSQL *mysql) { mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0); + diag("errno: %d", mysql_errno(mysql)); FAIL_IF(mysql_errno(mysql) != CR_ALREADY_CONNECTED, "Expected errno=CR_ALREADY_CONNECTED"); - FAIL_IF(strcmp(mysql_error(mysql), ER(CR_ALREADY_CONNECTED)) != 0, - "Wrong error message"); - FAIL_IF(strcmp(ER(CR_ALREADY_CONNECTED), "Can't connect twice. Already connected") != 0, - "wrong error message"); return OK; } @@ -668,11 +696,14 @@ static int test_reconnect_maxpackage(MYSQL *my) { int rc; ulong max_packet= 0; - MYSQL *mysql= mysql_init(NULL); + MYSQL *mysql; MYSQL_RES *res; MYSQL_ROW row; char *query; + SKIP_CONNECTION_HANDLER; + mysql= mysql_init(NULL); + FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql)); @@ -770,6 +801,8 @@ int main(int argc, char **argv) get_envvars(); + diag("user: %s", username); + run_tests(my_tests); return(exit_status()); diff --git a/unittest/libmariadb/charset.c b/unittest/libmariadb/charset.c index b5cdbf89..0226bc18 100644 --- a/unittest/libmariadb/charset.c +++ b/unittest/libmariadb/charset.c @@ -679,7 +679,7 @@ static int test_utf16_utf32_noboms(MYSQL *mysql) for (i= 0; i < sizeof(csname)/sizeof(char*); ++i) { - csinfo[i]= mysql_find_charset_name(csname[i]); + csinfo[i]= mariadb_get_charset_by_name(csname[i]); if (csinfo[i] == NULL) { diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index 11452977..e40b05e0 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -32,6 +32,7 @@ static int test_conc66(MYSQL *my) MYSQL *mysql= mysql_init(NULL); int rc; FILE *fp; + char query[1024]; if (!(fp= fopen("./my.cnf", "w"))) return FAIL; @@ -47,7 +48,8 @@ static int test_conc66(MYSQL *my) rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./my.cnf"); check_mysql_rc(rc, mysql); - rc= mysql_query(my, "GRANT ALL ON test.* TO 'conc66'@'localhost' IDENTIFIED BY 'test\";#test'"); + sprintf(query, "GRANT ALL ON %s.* TO 'conc66'@'%s' IDENTIFIED BY 'test\";#test'", schema, hostname); + rc= mysql_query(my, query); check_mysql_rc(rc, my); rc= mysql_query(my, "FLUSH PRIVILEGES"); check_mysql_rc(rc, my); @@ -57,7 +59,8 @@ static int test_conc66(MYSQL *my) diag("Error: %s", mysql_error(mysql)); return FAIL; } - rc= mysql_query(my, "DROP USER conc66@localhost"); + sprintf(query, "DROP user conc66@%s", hostname); + rc= mysql_query(my, query); check_mysql_rc(rc, my); mysql_close(mysql); @@ -561,6 +564,8 @@ static int test_reconnect(MYSQL *mysql) mysql_kill(mysql, mysql_thread_id(mysql1)); sleep(4); + mysql_ping(mysql1); + rc= mysql_query(mysql1, "SELECT 1 FROM DUAL LIMIT 0"); check_mysql_rc(rc, mysql1); diag("Thread_id after kill: %lu", mysql_thread_id(mysql1)); @@ -649,6 +654,8 @@ static int test_conc118(MYSQL *mysql) rc= mysql_kill(mysql, mysql_thread_id(mysql)); sleep(2); + mysql_ping(mysql); + rc= mysql_query(mysql, "SET @a:=1"); check_mysql_rc(rc, mysql); @@ -657,12 +664,9 @@ static int test_conc118(MYSQL *mysql) rc= mysql_kill(mysql, mysql_thread_id(mysql)); sleep(2); - mysql->host= "foo"; - rc= mysql_query(mysql, "SET @a:=1"); FAIL_IF(!rc, "error expected"); - mysql->host= hostname; rc= mysql_query(mysql, "SET @a:=1"); check_mysql_rc(rc, mysql); diff --git a/unittest/libmariadb/my_test.h b/unittest/libmariadb/my_test.h index e862ced1..e0db2beb 100644 --- a/unittest/libmariadb/my_test.h +++ b/unittest/libmariadb/my_test.h @@ -82,6 +82,13 @@ if (!(expr))\ return FAIL;\ } +#define SKIP_CONNECTION_HANDLER \ + if (hostname && strstr(hostname, "://"))\ + {\ + diag("Test skipped (connection handler)");\ + return SKIP;\ + } + /* connection options */ #define TEST_CONNECTION_DEFAULT 1 /* default connection */ #define TEST_CONNECTION_NONE 2 /* tests creates own connection */ @@ -104,7 +111,7 @@ struct my_tests_st char *skipmsg; }; -static char *schema = "test_c"; +static char *schema = 0; static char *hostname = 0; static char *password = 0; static unsigned int port = 0; @@ -368,18 +375,19 @@ int check_variable(MYSQL *mysql, char *variable, char *value) MYSQL *test_connect(struct my_tests_st *test) { MYSQL *mysql; char query[255]; - int i= 1; + int i= 0; + int timeout= 10; + int truncation_report= 1; if (!(mysql = mysql_init(NULL))) { diag("%s", "mysql_init failed - exiting"); return(NULL); } - mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, &i); - mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&i); + mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, &truncation_report); + mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); /* option handling */ if (test && test->options) { - int i=0; while (test->options[i].option) { @@ -403,6 +411,8 @@ MYSQL *test_connect(struct my_tests_st *test) { /* change database or create if it doesn't exist */ if (mysql_select_db(mysql, schema)) { + diag("Error number: %d", mysql_errno(mysql)); + if(mysql_errno(mysql) == 1049) { sprintf(query, "CREATE DATABASE %s", schema); if (mysql_query(mysql, query)) { @@ -425,11 +435,6 @@ static int reset_connection(MYSQL *mysql) { rc= mysql_change_user(mysql, username, password, schema); check_mysql_rc(rc, mysql); - if (mysql_get_server_version(mysql) < 50400) - rc= mysql_query(mysql, "SET table_type='MyISAM'"); - else - rc= mysql_query(mysql, "SET storage_engine='MyISAM'"); - check_mysql_rc(rc, mysql); rc= mysql_query(mysql, "SET sql_mode=''"); check_mysql_rc(rc, mysql); @@ -452,6 +457,8 @@ void get_envvars() { password= envvar; if (!schema && (envvar= getenv("MYSQL_TEST_DB"))) schema= envvar; + if (!schema) + schema= "testc"; if (!port && (envvar= getenv("MYSQL_TEST_PORT"))) port= atoi(envvar); if (!socketname && (envvar= getenv("MYSQL_TEST_SOCKET"))) @@ -470,7 +477,8 @@ void run_tests(struct my_tests_st *test) { if ((mysql_default= test_connect(NULL))) { diag("Testing against MySQL Server %s", mysql_get_server_info(mysql_default)); - diag("Host %s", mysql_get_host_info(mysql_default)); + diag("Host: %s", mysql_get_host_info(mysql_default)); + diag("Client library: %s", mysql_get_client_info()); } else { diff --git a/unittest/libmariadb/ps.c b/unittest/libmariadb/ps.c index 1c96baca..85e5528c 100644 --- a/unittest/libmariadb/ps.c +++ b/unittest/libmariadb/ps.c @@ -64,7 +64,10 @@ static int test_conc83(MYSQL *my) /* 1. Status is inited, so prepare should work */ rc= mysql_kill(mysql, mysql_thread_id(mysql)); - sleep(2); + sleep(5); + + rc= mysql_ping(mysql); + check_mysql_rc(rc, mysql); rc= mysql_stmt_prepare(stmt, query, strlen(query)); check_stmt_rc(rc, stmt); diff --git a/unittest/libmariadb/ps_bugs.c b/unittest/libmariadb/ps_bugs.c index bd072646..b7d54d26 100644 --- a/unittest/libmariadb/ps_bugs.c +++ b/unittest/libmariadb/ps_bugs.c @@ -528,9 +528,8 @@ static int test_bug12744(MYSQL *mysql) rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, "1"); check_mysql_rc(rc, mysql); rc= mysql_kill(mysql, mysql_thread_id(mysql)); - check_mysql_rc(rc, mysql); - sleep(2); + sleep(4); rc= mysql_ping(mysql); check_mysql_rc(rc, mysql); From 4c7e5cbd1b0fd891d3c72c0d7d95b28faf099910 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 14 Dec 2015 11:56:17 +0100 Subject: [PATCH 05/40] Added new option MARIADB_OPT_USERDATA. Syntax: mysql_optionsv(MYSQL *mysql, MYSQL_OPT_USERDATA, void *key, void *data) --- include/ma_common.h | 1 + include/mysql.h | 3 +- libmariadb/libmariadb.c | 116 +++++++++++++++++++++++-------- libmariadb/ma_dyncol.c | 2 +- unittest/libmariadb/basic-t.c | 4 +- unittest/libmariadb/connection.c | 18 +++-- 6 files changed, 106 insertions(+), 38 deletions(-) diff --git a/include/ma_common.h b/include/ma_common.h index 048fc9ae..83fb4291 100644 --- a/include/ma_common.h +++ b/include/ma_common.h @@ -54,6 +54,7 @@ struct st_mysql_options_extension { char *ssl_pw; /* password for encrypted certificates */ char *url; /* for connection handler we need to save URL for reconnect */ my_bool read_only; + HASH userdata; }; #define OPT_HAS_EXT_VAL(a,key) \ diff --git a/include/mysql.h b/include/mysql.h index b1feac36..c5966abb 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -215,7 +215,8 @@ extern unsigned int mariadb_deinitialize_ssl; MARIADB_OPT_SSL_FP_LIST, /* finger print white list for server certificate verification */ MARIADB_OPT_SSL_PASSWORD, /* password for encrypted certificates */ MARIADB_OPT_CONNECTION_READ_ONLY, - MYSQL_OPT_CONNECT_ATTRS /* for mysql_get_optionv */ + MYSQL_OPT_CONNECT_ATTRS, /* for mysql_get_optionv */ + MARIADB_OPT_USERDATA, }; enum mysql_status { MYSQL_STATUS_READY, diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 7eaa7b42..78d0d3f5 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -164,7 +164,7 @@ void net_get_error(char *buf, size_t buf_len, else { *error_no= CR_UNKNOWN_ERROR; - memcpy(sqlstate, unknown_sqlstate, SQLSTATE_LENGTH); + memcpy(sqlstate, SQLSTATE_UNKNOWN, SQLSTATE_LENGTH); } } @@ -208,7 +208,7 @@ restart: if (cli_report_progress(mysql, (uchar *)pos, (uint) (len-1))) { /* Wrong packet */ - my_set_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate, 0); + my_set_error(mysql, CR_MALFORMED_PACKET, SQLSTATE_UNKNOWN, 0); return (packet_error); } goto restart; @@ -368,7 +368,7 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg, if (mysql->status != MYSQL_STATUS_READY || mysql->server_status & SERVER_MORE_RESULTS_EXIST) { - SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0); goto end; } @@ -379,7 +379,6 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg, DBUG_RETURN(result); } - CLEAR_CLIENT_ERROR(mysql); mysql->info=0; @@ -998,7 +997,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), MYF(MY_WME | MY_ZEROFILL)))) { - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(0); } init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */ @@ -1017,7 +1016,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, (fields+1)*sizeof(char *)+fields+pkt_len)))) { free_rows(result); - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(0); } *prev_ptr=cur; @@ -1036,7 +1035,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, if (len > (ulong) (end_to - to)) { free_rows(result); - SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(0); } memcpy(to,(char*) cp,len); to[len]=0; @@ -1519,7 +1518,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, !(mysql->user=my_strdup(user,MYF(0))) || !(mysql->passwd=my_strdup(passwd,MYF(0)))) { - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); goto error; } strmov(mysql->host_info,host_info); @@ -1535,7 +1534,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, { if (!(mysql->server_version= my_strdup(end + 6, 0))) { - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); goto error; } } @@ -1543,7 +1542,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, { if (!(mysql->server_version= my_strdup(end, MYF(0)))) { - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); goto error; } } @@ -1599,7 +1598,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION; if (mysql->options.secure_auth) { - SET_CLIENT_ERROR(mysql, CR_SECURE_AUTH, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_SECURE_AUTH, SQLSTATE_UNKNOWN, 0); goto error; } } @@ -1636,7 +1635,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, { if (mysql_select_db(mysql, db)) { - my_set_error(mysql, CR_SERVER_LOST, unknown_sqlstate, + my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN, ER(CR_SERVER_LOST_EXTENDED), "Setting intital database", errno); @@ -1867,7 +1866,7 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, if (db && !(mysql->db= my_strdup(db,MYF(MY_WME)))) { - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); rc= 1; } } else @@ -2153,7 +2152,7 @@ mysql_store_result(MYSQL *mysql) DBUG_RETURN(0); if (mysql->status != MYSQL_STATUS_GET_RESULT) { - SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(0); } mysql->status=MYSQL_STATUS_READY; /* server is ready */ @@ -2161,7 +2160,7 @@ mysql_store_result(MYSQL *mysql) sizeof(ulong)*mysql->field_count, MYF(MY_WME | MY_ZEROFILL)))) { - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(0); } result->eof=1; /* Marker for buffered */ @@ -2203,7 +2202,7 @@ mysql_use_result(MYSQL *mysql) DBUG_RETURN(0); if (mysql->status != MYSQL_STATUS_GET_RESULT) { - SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(0); } if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+ @@ -2520,7 +2519,7 @@ mysql_stat(MYSQL *mysql) mysql->net.read_pos[mysql->packet_length]=0; /* End of stat string */ if (!mysql->net.read_pos[0]) { - SET_CLIENT_ERROR(mysql, CR_WRONG_HOST_INFO , unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_WRONG_HOST_INFO , SQLSTATE_UNKNOWN, 0); return mysql->net.last_error; } DBUG_RETURN((char*) mysql->net.read_pos); @@ -2601,7 +2600,7 @@ uchar *ma_get_hash_keyval(const uchar *hash_entry, { /* Hash entry has the following format: Offset: 0 key (\0 terminated) - key_length + 1 valu (\0 terminated) + key_length + 1 value (\0 terminated) */ uchar *p= (uchar *)hash_entry; size_t len= strlen(p); @@ -2743,7 +2742,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) if (!(ctxt= (struct mysql_async_context *) my_malloc(sizeof(*ctxt), MYF(MY_ZEROFILL)))) { - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); goto end; } stacksize= 0; @@ -2761,7 +2760,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) my_malloc(sizeof(struct st_mysql_options_extension), MYF(MY_WME | MY_ZEROFILL)))) { - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); goto end; } mysql->options.extension->async_context= ctxt; @@ -2828,6 +2827,42 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) mysql->options.extension->connect_attrs_len= 0; } break; + case MARIADB_OPT_USERDATA: + { + void *data= va_arg(ap, void *); + uchar *buffer, *p; + char *key= (char *)arg1; + + if (!key || !data) + { + SET_CLIENT_ERROR(mysql, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0); + goto end; + } + + CHECK_OPT_EXTENSION_SET(&mysql->options); + if (!hash_inited(&mysql->options.extension->userdata)) + { + if (_hash_init(&mysql->options.extension->userdata, + 0, 0, 0, ma_get_hash_keyval, ma_hash_free, 0) || + !(buffer= (uchar *)my_malloc(strlen(key) + 1 + sizeof(void *), MYF(MY_ZEROFILL)))) + { + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); + goto end; + } + } + p= buffer; + strcpy(p, key); + p+= strlen(key) + 1; + memcpy(p, &data, sizeof(void *)); + + if (hash_insert(&mysql->options.extension->userdata, buffer)) + { + my_free(buffer); + SET_CLIENT_ERROR(mysql, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0); + goto end; + } + } + break; case MYSQL_OPT_CONNECT_ATTR_ADD: { uchar *buffer; @@ -2847,7 +2882,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) if (!key_len || storage_len + mysql->options.extension->connect_attrs_len > 0xFFFF) { - SET_CLIENT_ERROR(mysql, CR_INVALID_PARAMETER_NO, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0); goto end; } @@ -2856,7 +2891,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) if (_hash_init(&mysql->options.extension->connect_attrs, 0, 0, 0, ma_get_hash_keyval, ma_hash_free, 0)) { - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); goto end; } } @@ -2872,14 +2907,14 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) if (hash_insert(&mysql->options.extension->connect_attrs, buffer)) { my_free(buffer); - SET_CLIENT_ERROR(mysql, CR_INVALID_PARAMETER_NO, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0); goto end; } mysql->options.extension->connect_attrs_len+= storage_len; } else { - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); goto end; } } @@ -3019,13 +3054,19 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) /* mysql_get_optionsv(mysql, MYSQL_OPT_CONNECT_ATTRS, keys, vals, elements) */ { int i, *elements; - char **key= (char **)arg; - char **val; + char **key= NULL; + void *arg1; + char **val= NULL; if (!elements) goto error; + + if (arg) + key= *(char ***)arg; - val= va_arg(ap, char **); + arg1= va_arg(ap, char **); + if (arg1) + val= *(char ***)arg1; if (!(elements= va_arg(ap, unsigned int *))) goto error; @@ -3071,6 +3112,24 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) case MARIADB_OPT_CONNECTION_READ_ONLY: break; */ + case MARIADB_OPT_USERDATA: + /* nysql_get_optionv(mysql, MARIADB_OPT_USERDATA, key, value) */ + { + uchar *p; + void *data= va_arg(ap, void *); + char *key= (char *)arg; + if (key && data && mysql->options.extension && hash_inited(&mysql->options.extension->userdata) && + (p= (uchar *)hash_search(&mysql->options.extension->userdata, (uchar *)key, + strlen((char *)key)))) + { + p+= strlen(key) + 1; + *((void **)data)= *((void **)p); + break; + } + if (data) + *((void **)data)= NULL; + } + break; default: va_end(ap); DBUG_RETURN(-1); @@ -3093,7 +3152,6 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) return mysql_optionsv(mysql, option, arg); } - /**************************************************************************** ** Functions to get information from the MySQL structure ** These are functions to make shared libraries more usable. @@ -3200,7 +3258,7 @@ int STDCALL mysql_next_result(MYSQL *mysql) /* make sure communication is not blocking */ if (mysql->status != MYSQL_STATUS_READY) { - SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, 0); + SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(1); } diff --git a/libmariadb/ma_dyncol.c b/libmariadb/ma_dyncol.c index c7c3b66d..aa8391b6 100644 --- a/libmariadb/ma_dyncol.c +++ b/libmariadb/ma_dyncol.c @@ -1114,7 +1114,7 @@ dynamic_column_string_read(DYNAMIC_COLUMN_VALUE *store_it_here, #ifndef LIBMARIADB store_it_here->x.string.charset= get_charset_by_nr(charset_nr); #else - store_it_here->x.string.charset= mysql_get_charset_by_nr(charset_nr); + store_it_here->x.string.charset= mariadb_get_charset_by_nr(charset_nr); #endif if (store_it_here->x.string.charset == NULL) return ER_DYNCOL_UNKNOWN_CHARSET; diff --git a/unittest/libmariadb/basic-t.c b/unittest/libmariadb/basic-t.c index 610ab460..02dcc294 100644 --- a/unittest/libmariadb/basic-t.c +++ b/unittest/libmariadb/basic-t.c @@ -457,7 +457,7 @@ static int test_mysql_insert_id(MYSQL *mysql) FAIL_UNLESS(res == 400, ""); /* table with auto_increment column */ - rc= mysql_query(mysql, "create table t2 (f1 int not null primary key auto_increment, f2 varchar(255))"); + rc= mysql_query(mysql, "create table t2 (f1 int not null primary key auto_increment, f2 varchar(255)) engine=MyISAM"); check_mysql_rc(rc, mysql); rc= mysql_query(mysql, "insert into t2 values (1,'a')"); check_mysql_rc(rc, mysql); @@ -540,7 +540,7 @@ static int test_mysql_insert_id(MYSQL *mysql) rc= mysql_query(mysql, "drop table t2"); check_mysql_rc(rc, mysql); rc= mysql_query(mysql, "create table t2 (f1 int not null primary key " - "auto_increment, f2 varchar(255), unique (f2))"); + "auto_increment, f2 varchar(255), unique (f2)) engine=MyISAM"); check_mysql_rc(rc, mysql); rc= mysql_query(mysql, "insert into t2 values (null,'e')"); res= mysql_insert_id(mysql); diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index 1b6c6d7f..0ce22450 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -664,9 +664,7 @@ static int test_conc118(MYSQL *mysql) rc= mysql_kill(mysql, mysql_thread_id(mysql)); sleep(2); - rc= mysql_query(mysql, "SET @a:=1"); - FAIL_IF(!rc, "error expected"); - + mysql_ping(mysql); rc= mysql_query(mysql, "SET @a:=1"); check_mysql_rc(rc, mysql); @@ -768,9 +766,10 @@ static int test_get_options(MYSQL *my) my_bool boolval[2]= {1, 0}; char *char1= "test", *char2; int i; + MYSQL *userdata; char *attr_key[] = {"foo1", "foo2", "foo3"}; char *attr_val[] = {"bar1", "bar2", "bar3"}; - char *key[3], *val[3]; + char **key, **val; for (i=0; options_int[i]; i++) { @@ -801,19 +800,28 @@ static int test_get_options(MYSQL *my) FAIL_IF(elements != 3, "expected 3 elements"); for (i=0; i < 3; i++) FAIL_IF(strcmp(init_command[i], command[i]), "wrong init command"); - for (i=0; i < 3; i++) mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, attr_key[i], attr_val[i]); mysql_get_optionv(mysql, MYSQL_OPT_CONNECT_ATTRS, NULL, NULL, &elements); FAIL_IF(elements != 3, "expected 3 connection attributes"); + key= (char **)malloc(sizeof(char *) * elements); + val= (char **)malloc(sizeof(char *) * elements); + mysql_get_optionv(mysql, MYSQL_OPT_CONNECT_ATTRS, &key, &val, &elements); for (i=0; i < elements; i++) { diag("%s => %s", key[i], val[i]); } + free(key); + free(val); + + mysql_optionsv(mysql, MARIADB_OPT_USERDATA, "my_app", (void *)mysql); + mysql_get_optionv(mysql, MARIADB_OPT_USERDATA, "my_app", &userdata); + + FAIL_IF(mysql != userdata, "wrong userdata"); mysql_close(mysql); return OK; } From 57cc05ace95be3f3b8d768bbf41fd490432c66f6 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 14 Dec 2015 13:30:22 +0100 Subject: [PATCH 06/40] Free userdata hash structure in mysql_close_options --- libmariadb/libmariadb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 78d0d3f5..137da400 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -1950,6 +1950,8 @@ static void mysql_close_options(MYSQL *mysql) my_free(mysql->options.extension->url); if(hash_inited(&mysql->options.extension->connect_attrs)) hash_free(&mysql->options.extension->connect_attrs); + if (hash_inited(&mysql->options.extension->userdata)) + hash_free(&mysql->options.extension->userdata); if ((ctxt = mysql->options.extension->async_context) != 0) { my_context_destroy(&ctxt->async_context); From 518a30675ce38807687eab046b3586ae983ef2cd Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Tue, 15 Dec 2015 19:19:08 +0100 Subject: [PATCH 07/40] added missing mutex_init/destroy for ssl test conc-102 --- unittest/libmariadb/ssl.c.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unittest/libmariadb/ssl.c.in b/unittest/libmariadb/ssl.c.in index b6e51965..c38408fb 100644 --- a/unittest/libmariadb/ssl.c.in +++ b/unittest/libmariadb/ssl.c.in @@ -646,6 +646,7 @@ static int test_conc_102(MYSQL *mysql) check_mysql_rc(rc, mysql); rc= mysql_query(mysql, "INSERT INTO t_conc102 VALUES (0)"); check_mysql_rc(rc, mysql); + pthread_mutex_init(&LOCK_test, NULL); for (i=0; i < 50; i++) { @@ -665,6 +666,7 @@ static int test_conc_102(MYSQL *mysql) WaitForSingleObject(hthreads[i], INFINITE); #endif } + pthread_mutex_destroy(&LOCK_test); rc= mysql_query(mysql, "SELECT a FROM t_conc102"); check_mysql_rc(rc, mysql); res= mysql_store_result(mysql); From 5649ddf73e48347783bda5b59a8cf962bd884365 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Wed, 16 Dec 2015 06:57:31 +0100 Subject: [PATCH 08/40] Added initial configuration for AppVeyor build --- appveyor.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..ffc70360 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,17 @@ +version: 3.0.0.{build} + +branches: + only: + - master +configuration: RelWithDebInfo +platform: x64 +clone_folder: c:\projects\mariadb-connector-c +before_build: +- cmd: >- + cd c:\projects\mariadb-connector-c + echo running cmake + cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE=RelWithDebInfo +build: + project: mariadb-connector-c.sln + parallel: true + verbosity: minimal From d5fa84d2baf35b7c141b33061125cb4a51967905 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Wed, 16 Dec 2015 07:21:14 +0100 Subject: [PATCH 09/40] Added VS2015 to AppVeyor configuration --- appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index ffc70360..373dbd0e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,15 +1,17 @@ version: 3.0.0.{build} - branches: only: - master +os: Visual Studio 2015 configuration: RelWithDebInfo platform: x64 clone_folder: c:\projects\mariadb-connector-c before_build: - cmd: >- cd c:\projects\mariadb-connector-c + echo running cmake + cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE=RelWithDebInfo build: project: mariadb-connector-c.sln From 0485ddb8a384e6a77a6e16a5b7b7431f669febd4 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Wed, 16 Dec 2015 07:30:18 +0100 Subject: [PATCH 10/40] Link tests statically, since we need to access getopt (which is not exported by shared object) --- unittest/libmariadb/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittest/libmariadb/CMakeLists.txt b/unittest/libmariadb/CMakeLists.txt index f60d8638..7ce00e48 100644 --- a/unittest/libmariadb/CMakeLists.txt +++ b/unittest/libmariadb/CMakeLists.txt @@ -61,7 +61,7 @@ ENDIF() FOREACH(API_TEST ${API_TESTS}) ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c) - TARGET_LINK_LIBRARIES(${API_TEST} mytap libmariadb) + TARGET_LINK_LIBRARIES(${API_TEST} mytap mariadbclient) ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST}) SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 120) ENDFOREACH(API_TEST) From 52e11040eba086a5da254aa62b5b205caaa2fe89 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Wed, 16 Dec 2015 09:35:36 +0100 Subject: [PATCH 11/40] Added tests for appveyor: --- appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 373dbd0e..cf96c2dc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,7 +7,7 @@ configuration: RelWithDebInfo platform: x64 clone_folder: c:\projects\mariadb-connector-c before_build: -- cmd: >- +- ps: >- cd c:\projects\mariadb-connector-c echo running cmake @@ -17,3 +17,5 @@ build: project: mariadb-connector-c.sln parallel: true verbosity: minimal +test_script: + - ps: "mkdir c:\\tmp\n(new-object System.Net.WebClient).DownloadFile('https://downloads.mariadb.org/f/mariadb-10.1.8/winx64-packages/mariadb-10.1.8-winx64.zip/from/http%3A/mirrors.n-ix.net/mariadb/?serve','C:\\tmp\\mariadb-10.1.8-winx64.zip')\nmkdir c:\\tmp\\mariadb\nunzip c:\\tmp\\mariadb-10.1.8-winx64.zip -d c:\\tmp\\mariadb\nSET BIN_DIR=c:\\tmp\\mariadb\nSET CERT_DIR=c:\\projects\\mariadb-connector-c\\unittest\\libmariadb\\certs\nstart %BINDIR%\\mysqld.exe --console --max_allowed_packet=1G --enable-named-pipe --socket=JDBC-test-socket --ssl-ca=%CERTDIR%\\cacert.pem --ssl-cert=%CERTDIR%\\server-cert.pem --ssl-key=%CERTDIR%\\server-key.pem\ntimeout 20\nset MYSQL_TEST_USER=root\nset MYSQL_TEST_HOST=127.0.0.1\ncd \\projects\\mariadb-connector-c\\unittest\\libmariadb\nctest -V\ncall %BINDIR%\\mysqladmin -uroot shutdown" From 279ea7ea8cb102abcbf42b2e377489f8ef369af5 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Wed, 16 Dec 2015 10:41:35 +0100 Subject: [PATCH 12/40] suppress openssl output while generating certificates --- unittest/libmariadb/CMakeLists.txt | 10 +++++----- unittest/libmariadb/certs/dummy.pem | 21 --------------------- 2 files changed, 5 insertions(+), 26 deletions(-) delete mode 100644 unittest/libmariadb/certs/dummy.pem diff --git a/unittest/libmariadb/CMakeLists.txt b/unittest/libmariadb/CMakeLists.txt index 7ce00e48..d7e3a5d6 100644 --- a/unittest/libmariadb/CMakeLists.txt +++ b/unittest/libmariadb/CMakeLists.txt @@ -31,15 +31,15 @@ IF(WITH_SSL) IF(EXISTS "${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs/server-cert.pem") MESSAGE(STATUS "certificates already exist") ELSE() - MESSAGE(STATUS "cerating certificates") - EXECUTE_PROCESS(COMMAND openssl req -x509 -newkey rsa:1024 -keyout server-key-enc.pem -out server-cert.pem -subj "/DC=com/DC=example/CN=server" -passout pass:qwerty + MESSAGE(STATUS "creating certificates") + EXECUTE_PROCESS(COMMAND openssl req -x509 -newkey rsa:1024 -keyout server-key-enc.pem -out server-cert.pem -subj "/DC=com/DC=example/CN=server" -passout pass:qwerty OUTPUT_FILE x.1 ERROR_FILE x.2 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs) EXECUTE_PROCESS(COMMAND openssl rsa -in server-key-enc.pem -out server-key.pem -passin pass:qwerty -passout pass: - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs) - EXECUTE_PROCESS(COMMAND openssl req -x509 -newkey rsa:1024 -keyout client-key-enc.pem -out client-cert.pem -subj "/DC=com/DC=example/CN=client" -passout pass:qwerty + OUTPUT_FILE x.1 ERROR_FILE x.2 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs) + EXECUTE_PROCESS(COMMAND openssl req -x509 -newkey rsa:1024 -keyout client-key-enc.pem -out client-cert.pem -subj "/DC=com/DC=example/CN=client" -passout pass:qwerty OUTPUT_FILE x.1 ERROR_FILE x.2 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs) EXECUTE_PROCESS(COMMAND openssl rsa -in client-key-enc.pem -out client-key.pem -passin pass:qwerty -passout pass: - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs) + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs OUTPUT_FILE x.1 ERROR_FILE x.2) FILE(READ ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs/server-cert.pem F1) FILE(READ ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs/client-cert.pem F2) FILE(WRITE ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs/ca-cert.pem ${F1} ${F2}) diff --git a/unittest/libmariadb/certs/dummy.pem b/unittest/libmariadb/certs/dummy.pem deleted file mode 100644 index 1fc34aa1..00000000 --- a/unittest/libmariadb/certs/dummy.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDXTCCAkWgAwIBAgIJAL4tmDe5DR0sMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV -BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX -aWRnaXRzIFB0eSBMdGQwHhcNMTUwMzEwMjAyMDI4WhcNMTYwMzA5MjAyMDI4WjBF -MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 -ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEApV9UfWmeXYdexOEn+adOm6FdJUhKMrjTiycwETmDXRVpY4wl+LNGsANp -ohSRovDjFiFO+Ti0bUhpf552oE23wYw+P6f0UY0KkV/PgSght1Ezfffe0BaEjI0X -tA5zdNmxzL3OUWJVcg+I4UE3rbYFHUgymu72P0IRXjmJv1tToNxUxbTBLxU/KAlq -Uy49upB3q3/IPOdP9UzAZDHnRv1gjwUzNgumfcc5d5lSsGpwLDYCQs4I539fCkBD -MfU2BN/qpmPhb/nm5ZUdFUFYGN+XxVPVpJLmeWVRwMSQR2LN5CkqnK9e2Q/QaJ53 -G3AAng+fpfEGPpjQdFWuhFjQozOD0wIDAQABo1AwTjAdBgNVHQ4EFgQUyg6WfzL2 -JhhjKm1Ex28s4Y3vNGQwHwYDVR0jBBgwFoAUyg6WfzL2JhhjKm1Ex28s4Y3vNGQw -DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAIrj/bHiRf8UJIfv8hyZ1 -dXEqvqjxUMXtJ/QhhCQs42p9pHv+mPTkeXh0K18Oj6k/Vp4J1/0mp/kqiQUHt9yO -/3pJPc+JordTjlVLgb95cfBIs4yiPT9biGaA7j0Dh9EcDBOCT4v56Z9BLqGMfBUK -YeZ7ZecWmZCZOYk/X+CPB30GxLy5Wm9D50qEUXXBPZ9Bie6FYaQYOFlQlqxYuLX0 -NVqLDvX6zz6FMsgqoyDJ1BMuMsjPDUUUrwGY+R3YqiqkPRbDkr8zvzpqiYvjTZi0 -LTJO7GRfwzfhkeEPL/hl/TYdB1GZHixMrAKx1HGKHAa0sgWTWxQGYhfclH8DI7AR -Tw== ------END CERTIFICATE----- From 1eca44a07ac0dc6e0c2b83a01e25127314a660c4 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Wed, 16 Dec 2015 10:53:26 +0100 Subject: [PATCH 13/40] Fix for appveyor-build: wrong mariadb server path was specified for tests --- appveyor.yml | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index cf96c2dc..e1f972ae 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,4 +18,27 @@ build: parallel: true verbosity: minimal test_script: - - ps: "mkdir c:\\tmp\n(new-object System.Net.WebClient).DownloadFile('https://downloads.mariadb.org/f/mariadb-10.1.8/winx64-packages/mariadb-10.1.8-winx64.zip/from/http%3A/mirrors.n-ix.net/mariadb/?serve','C:\\tmp\\mariadb-10.1.8-winx64.zip')\nmkdir c:\\tmp\\mariadb\nunzip c:\\tmp\\mariadb-10.1.8-winx64.zip -d c:\\tmp\\mariadb\nSET BIN_DIR=c:\\tmp\\mariadb\nSET CERT_DIR=c:\\projects\\mariadb-connector-c\\unittest\\libmariadb\\certs\nstart %BINDIR%\\mysqld.exe --console --max_allowed_packet=1G --enable-named-pipe --socket=JDBC-test-socket --ssl-ca=%CERTDIR%\\cacert.pem --ssl-cert=%CERTDIR%\\server-cert.pem --ssl-key=%CERTDIR%\\server-key.pem\ntimeout 20\nset MYSQL_TEST_USER=root\nset MYSQL_TEST_HOST=127.0.0.1\ncd \\projects\\mariadb-connector-c\\unittest\\libmariadb\nctest -V\ncall %BINDIR%\\mysqladmin -uroot shutdown" +- ps: >- + mkdir c:\tmp + + (new-object System.Net.WebClient).DownloadFile('https://downloads.mariadb.org/f/mariadb-10.1.8/winx64-packages/mariadb-10.1.8-winx64.zip/from/http%3A/mirrors.n-ix.net/mariadb/?serve','C:\tmp\') + + unzip c:\tmp\mariadb-10.1.8-winx64.zip + + SET BIN_DIR=c:\tmp\mariadb\mariadb-10.1.8-winx64 + + SET CERT_DIR=c:\projects\mariadb-connector-c\unittest\libmariadb\certs + + start %BINDIR%\mysqld.exe --console --max_allowed_packet=1G --enable-named-pipe --socket=JDBC-test-socket --ssl-ca=%CERTDIR%\cacert.pem --ssl-cert=%CERTDIR%\server-cert.pem --ssl-key=%CERTDIR%\server-key.pem + + timeout 20 + + set MYSQL_TEST_USER=root + + set MYSQL_TEST_HOST=127.0.0.1 + + cd \projects\mariadb-connector-c\unittest\libmariadb + + ctest -V + + call %BINDIR%\mysqladmin -uroot shutdown From d68c7dae957144e14a0f5de60998750b4f08c91c Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Sat, 19 Dec 2015 17:07:10 +0100 Subject: [PATCH 14/40] Fixed warning on Windows 64-bit build --- appveyor.yml | 29 ++++++----------------- include/my_context.h | 4 ++++ include/mysql.h | 1 - libmariadb/libmariadb.c | 17 +++++++------ libmariadb/ma_pvio.c | 2 +- libmariadb/my_static.c | 2 -- libmariadb/my_static.h | 1 - libmariadb/mysql_async.c | 8 +++---- libmariadb/secure/ma_schannel.c | 17 +++++++------ plugins/connection/aurora.c | 17 +++++++------ plugins/pvio/pvio_socket.c | 2 +- unittest/libmariadb/CMakeLists.txt | 19 +++++++-------- unittest/libmariadb/certs/create_certs.sh | 15 ------------ unittest/libmariadb/cursor.c | 8 +++---- unittest/libmariadb/logs.c | 2 +- unittest/libmariadb/ps.c | 6 ++--- unittest/libmariadb/ps_bugs.c | 8 +++---- unittest/libmariadb/ssl.c.in | 15 ++++++++---- win-iconv/win_iconv.c | 6 ++--- 19 files changed, 77 insertions(+), 102 deletions(-) delete mode 100755 unittest/libmariadb/certs/create_certs.sh diff --git a/appveyor.yml b/appveyor.yml index e1f972ae..89566c92 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,6 +6,11 @@ os: Visual Studio 2015 configuration: RelWithDebInfo platform: x64 clone_folder: c:\projects\mariadb-connector-c +environment: + MYSQL_TEST_USER: root + MYSQL_TEST_HOST: 127.0.0.1 + MYSQL_TEST_PASSWD: Password12! +services: mysql56 before_build: - ps: >- cd c:\projects\mariadb-connector-c @@ -18,27 +23,7 @@ build: parallel: true verbosity: minimal test_script: -- ps: >- - mkdir c:\tmp - - (new-object System.Net.WebClient).DownloadFile('https://downloads.mariadb.org/f/mariadb-10.1.8/winx64-packages/mariadb-10.1.8-winx64.zip/from/http%3A/mirrors.n-ix.net/mariadb/?serve','C:\tmp\') - - unzip c:\tmp\mariadb-10.1.8-winx64.zip - - SET BIN_DIR=c:\tmp\mariadb\mariadb-10.1.8-winx64 - - SET CERT_DIR=c:\projects\mariadb-connector-c\unittest\libmariadb\certs - - start %BINDIR%\mysqld.exe --console --max_allowed_packet=1G --enable-named-pipe --socket=JDBC-test-socket --ssl-ca=%CERTDIR%\cacert.pem --ssl-cert=%CERTDIR%\server-cert.pem --ssl-key=%CERTDIR%\server-key.pem - - timeout 20 - - set MYSQL_TEST_USER=root - - set MYSQL_TEST_HOST=127.0.0.1 - - cd \projects\mariadb-connector-c\unittest\libmariadb +- cmd: >- + cd c:\projects\mariadb-connector-c\unittest\libmariadb ctest -V - - call %BINDIR%\mysqladmin -uroot shutdown diff --git a/include/my_context.h b/include/my_context.h index 591a064a..2694fd09 100644 --- a/include/my_context.h +++ b/include/my_context.h @@ -112,6 +112,10 @@ struct my_context { }; #endif +extern void +my_context_install_suspend_resume_hook(struct mysql_async_context *b, + void (*hook)(my_bool, void *), + void *user_data); /* Initialize an asynchroneous context object. diff --git a/include/mysql.h b/include/mysql.h index c5966abb..25dddf0f 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -633,7 +633,6 @@ struct st_mysql_methods { int (*db_stmt_fetch_to_bind)(MYSQL_STMT *stmt, unsigned char *row); void (*db_stmt_flush_unbuffered)(MYSQL_STMT *stmt); void (*set_error)(MYSQL *mysql, unsigned int error_nr, const char *sqlstate, const char *format, ...); - my_bool (*reconnect)(MYSQL *mysql); }; /* synonyms/aliases functions */ diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 137da400..bff15c96 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -37,6 +37,7 @@ #include #include #include + #ifdef HAVE_PWD_H #include #endif @@ -131,7 +132,7 @@ static void end_server(MYSQL *mysql); static void mysql_close_memory(MYSQL *mysql); void read_user_name(char *name); static void append_wild(char *to,char *end,const char *wild); -my_bool mysql_reconnect(MYSQL *mysql); +my_bool STDCALL mysql_reconnect(MYSQL *mysql); static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length); extern int mysql_client_plugin_init(); @@ -1228,7 +1229,7 @@ uchar *ma_send_connect_attr(MYSQL *mysql, uchar *buffer) size_t len; uchar *p= hash_element(&mysql->options.extension->connect_attrs, i); - len= strlen(p); + len= strlen((char *)p); buffer= mysql_net_store_length(buffer, len); memcpy(buffer, p, len); buffer+= (len); @@ -2606,7 +2607,7 @@ uchar *ma_get_hash_keyval(const uchar *hash_entry, */ uchar *p= (uchar *)hash_entry; size_t len= strlen(p); - *length= len; + *length= (unsigned int)len; return p; } @@ -3060,9 +3061,6 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) void *arg1; char **val= NULL; - if (!elements) - goto error; - if (arg) key= *(char ***)arg; @@ -3073,6 +3071,9 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) if (!(elements= va_arg(ap, unsigned int *))) goto error; + if (!elements) + goto error; + *elements= 0; if (!mysql->options.extension || @@ -3122,7 +3123,7 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) char *key= (char *)arg; if (key && data && mysql->options.extension && hash_inited(&mysql->options.extension->userdata) && (p= (uchar *)hash_search(&mysql->options.extension->userdata, (uchar *)key, - strlen((char *)key)))) + (uint)strlen((char *)key)))) { p+= strlen(key) + 1; *((void **)data)= *((void **)p); @@ -3580,6 +3581,4 @@ struct st_mysql_methods MARIADB_DEFAULT_METHODS = { mthd_stmt_flush_unbuffered, /* set error */ my_set_error, - /* reconnect */ - mysql_reconnect }; diff --git a/libmariadb/ma_pvio.c b/libmariadb/ma_pvio.c index 9ba111b6..054ef45d 100644 --- a/libmariadb/ma_pvio.c +++ b/libmariadb/ma_pvio.c @@ -490,7 +490,7 @@ my_bool ma_pvio_has_data(MARIADB_PVIO *pvio, ssize_t *data_len) /* check if we still have unread data in cache */ if (pvio->cache) if (pvio->cache_pos > pvio->cache) - return pvio->cache_pos - pvio->cache; + return test(pvio->cache_pos - pvio->cache); if (pvio && pvio->methods->has_data) return pvio->methods->has_data(pvio, data_len); return 1; diff --git a/libmariadb/my_static.c b/libmariadb/my_static.c index 61d25574..9a892996 100644 --- a/libmariadb/my_static.c +++ b/libmariadb/my_static.c @@ -73,8 +73,6 @@ uint sf_malloc_prehunc=0, /* If you have problem with core- */ size_t lCurMemory = 0L; /* Current memory usage */ size_t lMaxMemory = 0L; /* Maximum memory usage */ uint cNewCount = 0; /* Number of times NEW() was called */ -unsigned char *sf_min_adress= (unsigned char*) ~(unsigned long) 0L, - *sf_max_adress= (unsigned char*) 0L; /* Root of the linked list of remembers */ struct remember *pRememberRoot = NULL; diff --git a/libmariadb/my_static.h b/libmariadb/my_static.h index a30b462d..8a6be025 100644 --- a/libmariadb/my_static.h +++ b/libmariadb/my_static.h @@ -61,7 +61,6 @@ extern uint my_once_extra; extern int _my_tempnam_used; #endif -extern unsigned char *sf_min_adress,*sf_max_adress; extern uint cNewCount; extern struct remember *pRememberRoot; diff --git a/libmariadb/mysql_async.c b/libmariadb/mysql_async.c index 4a86ab90..f7dfc998 100644 --- a/libmariadb/mysql_async.c +++ b/libmariadb/mysql_async.c @@ -394,7 +394,7 @@ MK_ASYNC_CONT_BODY( struct mysql_real_query_params { MYSQL *mysql; const char *stmt_str; - unsigned long length; + size_t length; }; static void mysql_real_query_start_internal(void *d) @@ -578,7 +578,7 @@ MK_ASYNC_CONT_BODY( struct mysql_send_query_params { MYSQL *mysql; const char *q; - unsigned long length; + size_t length; }; static void mysql_send_query_start_internal(void *d) @@ -1311,7 +1311,7 @@ MK_ASYNC_CONT_BODY( struct mysql_stmt_prepare_params { MYSQL_STMT *stmt; const char *query; - unsigned long length; + size_t length; }; static void mysql_stmt_prepare_start_internal(void *d) @@ -1614,7 +1614,7 @@ struct mysql_stmt_send_long_data_params { MYSQL_STMT *stmt; unsigned int param_number; const char *data; - unsigned long length; + size_t length; }; static void mysql_stmt_send_long_data_start_internal(void *d) diff --git a/libmariadb/secure/ma_schannel.c b/libmariadb/secure/ma_schannel.c index 065a9ab7..6266212f 100644 --- a/libmariadb/secure/ma_schannel.c +++ b/libmariadb/secure/ma_schannel.c @@ -338,7 +338,7 @@ my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, CERT_CONTEXT *ctx, char goto end; } /* ... and import the private key */ - if (!CryptImportKey(crypt_prov, priv_key, priv_key_len, NULL, 0, (HCRYPTKEY *)&crypt_key)) + if (!CryptImportKey(crypt_prov, priv_key, priv_key_len, 0, 0, (HCRYPTKEY *)&crypt_key)) { ma_schannel_set_win_error(pvio); goto end; @@ -427,7 +427,7 @@ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRe { if(fDoRead) { - cbData = pvio->methods->read(pvio, IoBuffer + cbIoBuffer, (size_t)(SC_IO_BUFFER_SIZE - cbIoBuffer)); + cbData = (DWORD)pvio->methods->read(pvio, IoBuffer + cbIoBuffer, (size_t)(SC_IO_BUFFER_SIZE - cbIoBuffer)); if (cbData == SOCKET_ERROR || cbData == 0) { rc = SEC_E_INTERNAL_ERROR; @@ -486,7 +486,7 @@ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRe { if(OutBuffers[0].cbBuffer && OutBuffers[0].pvBuffer) { - cbData= pvio->methods->write(pvio, (uchar *)OutBuffers[0].pvBuffer, (size_t)OutBuffers[0].cbBuffer); + cbData= (DWORD)pvio->methods->write(pvio, (uchar *)OutBuffers[0].pvBuffer, (size_t)OutBuffers[0].cbBuffer); if(cbData == SOCKET_ERROR || cbData == 0) { FreeContextBuffer(OutBuffers[0].pvBuffer); @@ -637,7 +637,7 @@ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl) /* send client hello packaet */ if(BuffersOut[0].cbBuffer != 0 && BuffersOut[0].pvBuffer != NULL) { - r= pvio->methods->write(pvio, (uchar *)BuffersOut[0].pvBuffer, (size_t)BuffersOut[0].cbBuffer); + r= (DWORD)pvio->methods->write(pvio, (uchar *)BuffersOut[0].pvBuffer, (size_t)BuffersOut[0].cbBuffer); if (r <= 0) { sRet= SEC_E_INTERNAL_ERROR; @@ -697,7 +697,6 @@ SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_PVIO *pvio, SECURITY_STATUS sRet= 0; SecBufferDesc Msg; SecBuffer Buffers[4], - ExtraBuffer, *pData, *pExtra; int i; @@ -711,18 +710,18 @@ SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_PVIO *pvio, { if (!dwBytesRead || sRet == SEC_E_INCOMPLETE_MESSAGE) { - dwBytesRead= pvio->methods->read(pvio, sctx->IoBuffer + dwOffset, (size_t)(sctx->IoBufferSize - dwOffset)); + dwBytesRead= (DWORD)pvio->methods->read(pvio, sctx->IoBuffer + dwOffset, (size_t)(sctx->IoBufferSize - dwOffset)); if (dwBytesRead == 0) { /* server closed connection */ // todo: error - return NULL; + return SEC_E_INVALID_HANDLE; } if (dwBytesRead < 0) { /* socket error */ // todo: error - return NULL; + return SEC_E_INVALID_HANDLE; } dwOffset+= dwBytesRead; } @@ -863,7 +862,7 @@ size_t ma_schannel_write_encrypt(MARIADB_PVIO *pvio, SECURITY_STATUS scRet; SecBufferDesc Message; SecBuffer Buffers[4]; - DWORD cbMessage, cbData; + DWORD cbMessage; PBYTE pbMessage; SC_CTX *sctx= (SC_CTX *)pvio->cssl->ssl; size_t payload; diff --git a/plugins/connection/aurora.c b/plugins/connection/aurora.c index 4c605058..3f54dd04 100644 --- a/plugins/connection/aurora.c +++ b/plugins/connection/aurora.c @@ -132,7 +132,10 @@ my_bool aurora_switch_connection(MYSQL *mysql, AURORA *aurora, int type) aurora->last_instance_type= AURORA_PRIMARY; } break; + default: + return 1; } + return 0; } /* }}} */ @@ -177,7 +180,7 @@ void aurora_close_memory(AURORA *aurora) my_bool aurora_parse_url(const char *url, AURORA *aurora) { char *p, *c; - int i; + unsigned int i; if (!url || url[0] == 0) return 1; @@ -313,7 +316,7 @@ my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora) */ static unsigned int aurora_get_valid_instances(AURORA *aurora, AURORA_INSTANCE **instances) { - int i, valid_instances= 0; + unsigned int i, valid_instances= 0; memset(instances, 0, sizeof(AURORA_INSTANCE *) * AURORA_MAX_INSTANCES); @@ -334,7 +337,7 @@ static unsigned int aurora_get_valid_instances(AURORA *aurora, AURORA_INSTANCE * /* {{{ void aurora_refresh_blacklist() */ void aurora_refresh_blacklist(AURORA *aurora) { - int i; + unsigned int i; for (i=0; i < aurora->num_instances; i++) { if (aurora->instance[i].blacklisted && @@ -475,7 +478,7 @@ my_bool aurora_find_replica(AURORA *aurora) /* {{{ AURORA_INSTANCE aurora_get_primary_id_instance() */ AURORA_INSTANCE *aurora_get_primary_id_instance(AURORA *aurora) { - int i; + unsigned int i; if (!aurora->primary_id[0]) return 0; @@ -492,7 +495,7 @@ AURORA_INSTANCE *aurora_get_primary_id_instance(AURORA *aurora) /* {{{ my_bool aurora_find_primary() */ my_bool aurora_find_primary(AURORA *aurora) { - int i; + unsigned int i; AURORA_INSTANCE *instance= NULL; MYSQL mysql; my_bool check_primary= 1; @@ -657,11 +660,11 @@ my_bool aurora_reconnect(MYSQL *mysql) switch (aurora->last_instance_type) { case AURORA_REPLICA: - if (!(rc= mysql->methods->reconnect(aurora->mysql[aurora->last_instance_type]))) + if (!(rc= mysql_reconnect(aurora->mysql[aurora->last_instance_type]))) aurora_switch_connection(mysql, aurora, AURORA_REPLICA); break; case AURORA_PRIMARY: - if (!(rc= mysql->methods->reconnect(aurora->mysql[aurora->last_instance_type]))) + if (!(rc= mysql_reconnect(aurora->mysql[aurora->last_instance_type]))) aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); break; default: diff --git a/plugins/pvio/pvio_socket.c b/plugins/pvio/pvio_socket.c index 01df4775..809a6b97 100644 --- a/plugins/pvio/pvio_socket.c +++ b/plugins/pvio/pvio_socket.c @@ -948,7 +948,7 @@ my_bool pvio_socket_is_alive(MARIADB_PVIO *pvio) my_bool pvio_socket_has_data(MARIADB_PVIO *pvio, ssize_t *data_len) { struct st_pvio_socket *csock= NULL; - char tmp_buf[1024]; + char tmp_buf; ssize_t len; my_bool mode; diff --git a/unittest/libmariadb/CMakeLists.txt b/unittest/libmariadb/CMakeLists.txt index d7e3a5d6..6af35f39 100644 --- a/unittest/libmariadb/CMakeLists.txt +++ b/unittest/libmariadb/CMakeLists.txt @@ -32,17 +32,14 @@ IF(WITH_SSL) MESSAGE(STATUS "certificates already exist") ELSE() MESSAGE(STATUS "creating certificates") - EXECUTE_PROCESS(COMMAND openssl req -x509 -newkey rsa:1024 -keyout server-key-enc.pem -out server-cert.pem -subj "/DC=com/DC=example/CN=server" -passout pass:qwerty OUTPUT_FILE x.1 ERROR_FILE x.2 - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs) - EXECUTE_PROCESS(COMMAND openssl rsa -in server-key-enc.pem -out server-key.pem -passin pass:qwerty -passout pass: - OUTPUT_FILE x.1 ERROR_FILE x.2 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs) - EXECUTE_PROCESS(COMMAND openssl req -x509 -newkey rsa:1024 -keyout client-key-enc.pem -out client-cert.pem -subj "/DC=com/DC=example/CN=client" -passout pass:qwerty OUTPUT_FILE x.1 ERROR_FILE x.2 - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs) - EXECUTE_PROCESS(COMMAND openssl rsa -in client-key-enc.pem -out client-key.pem -passin pass:qwerty -passout pass: - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs OUTPUT_FILE x.1 ERROR_FILE x.2) - FILE(READ ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs/server-cert.pem F1) - FILE(READ ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs/client-cert.pem F2) - FILE(WRITE ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs/ca-cert.pem ${F1} ${F2}) + IF(WIN32) + EXECUTE_PROCESS(COMMAND create_certs.bat + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs + OUTPUT_FILE x.1 ERROR_FILE x.2) + ELSE() + EXECUTE_PROCESS(COMMAND ./create_certs.sh + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs) + ENDIF() ENDIF() EXECUTE_PROCESS(COMMAND openssl x509 -in server-cert.pem -sha1 -fingerprint -noout diff --git a/unittest/libmariadb/certs/create_certs.sh b/unittest/libmariadb/certs/create_certs.sh deleted file mode 100755 index 47ea98e8..00000000 --- a/unittest/libmariadb/certs/create_certs.sh +++ /dev/null @@ -1,15 +0,0 @@ -openssl req -x509 -newkey rsa:1024 \ --keyout server-key-enc.pem -out server-cert.pem \ --subj '/DC=com/DC=example/CN=server' -passout pass:qwerty - -openssl rsa -in server-key-enc.pem -out server-key.pem \ --passin pass:qwerty -passout pass: - -openssl req -x509 -newkey rsa:1024 \ --keyout client-key-enc.pem -out client-cert.pem \ --subj '/DC=com/DC=example/CN=client' -passout pass:qwerty - -openssl rsa -in client-key-enc.pem -out client-key.pem \ --passin pass:qwerty -passout pass: - -cat server-cert.pem client-cert.pem > ca-cert.pem diff --git a/unittest/libmariadb/cursor.c b/unittest/libmariadb/cursor.c index 97a75bc2..97bafd2e 100644 --- a/unittest/libmariadb/cursor.c +++ b/unittest/libmariadb/cursor.c @@ -59,12 +59,12 @@ MYSQL_STMT *open_cursor(MYSQL *mysql, const char *query) fetch buffers. */ -int stmt_fetch_init(MYSQL *mysql, Stmt_fetch *fetch, unsigned stmt_no_arg, +int stmt_fetch_init(MYSQL *mysql, Stmt_fetch *fetch, unsigned int stmt_no_arg, const char *query_arg) { unsigned long type= CURSOR_TYPE_READ_ONLY; int rc; - unsigned i; + unsigned int i; MYSQL_RES *metadata; /* Save query and statement number for error messages */ @@ -180,7 +180,7 @@ int fetch_n(MYSQL *mysql, const char **query_list, unsigned query_count, for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch) { - if (stmt_fetch_init(mysql, fetch, fetch - fetch_array, + if (stmt_fetch_init(mysql, fetch, (unsigned int)(fetch - fetch_array), query_list[fetch - fetch_array])) return FAIL; } @@ -322,7 +322,7 @@ static int test_bug21206(MYSQL *mysql) for (fetch= fetch_array; fetch < fetch_array + cursor_count; ++fetch) { - if ((retcode= stmt_fetch_init(mysql, fetch, fetch - fetch_array, query))) + if ((retcode= stmt_fetch_init(mysql, fetch, (unsigned int)(fetch - fetch_array), query))) break; } diff --git a/unittest/libmariadb/logs.c b/unittest/libmariadb/logs.c index 534feeb2..38dfd8a7 100644 --- a/unittest/libmariadb/logs.c +++ b/unittest/libmariadb/logs.c @@ -89,7 +89,7 @@ static int test_logs(MYSQL *mysql) my_bind[1].buffer_type= MYSQL_TYPE_STRING; my_bind[1].buffer= (void *)&data; my_bind[1].buffer_length= 255; - my_bind[1].length= &length; + my_bind[1].length= (unsigned long *)&length; id= 9876; strcpy((char *)data, "MySQL - Open Source Database"); diff --git a/unittest/libmariadb/ps.c b/unittest/libmariadb/ps.c index 85e5528c..add7a493 100644 --- a/unittest/libmariadb/ps.c +++ b/unittest/libmariadb/ps.c @@ -1386,7 +1386,7 @@ static int test_long_data_str1(MYSQL *mysql) my_bind[0].buffer= data; /* string data */ my_bind[0].buffer_length= sizeof(data); - my_bind[0].length= &length1; + my_bind[0].length= (unsigned long *)&length1; my_bind[0].buffer_type= MYSQL_TYPE_STRING; length1= 0; @@ -1485,7 +1485,7 @@ static int test_long_data_str1(MYSQL *mysql) my_bind[0].buffer_type= MYSQL_TYPE_BLOB; my_bind[0].buffer= (void *) &data; /* this buffer won't be altered */ my_bind[0].buffer_length= 16; - my_bind[0].length= &blob_length; + my_bind[0].length= (unsigned long *)&blob_length; my_bind[0].error= &my_bind[0].error_value; rc= mysql_stmt_bind_result(stmt, my_bind); data[16]= 0; @@ -1501,7 +1501,7 @@ static int test_long_data_str1(MYSQL *mysql) my_bind[1].buffer_type= MYSQL_TYPE_BLOB; my_bind[1].buffer= (void *) &data; /* this buffer won't be altered */ my_bind[1].buffer_length= sizeof(data); - my_bind[1].length= &blob_length; + my_bind[1].length= (unsigned long *)&blob_length; memset(data, '\0', sizeof(data)); mysql_stmt_fetch_column(stmt, my_bind+1, 0, 0); FAIL_UNLESS(strlen(data) == max_blob_length, "strlen(data) != max_blob_length"); diff --git a/unittest/libmariadb/ps_bugs.c b/unittest/libmariadb/ps_bugs.c index b7d54d26..e5204ea4 100644 --- a/unittest/libmariadb/ps_bugs.c +++ b/unittest/libmariadb/ps_bugs.c @@ -643,7 +643,7 @@ static int test_bug1500(MYSQL *mysql) data= "Grave"; my_bind[0].buffer_type= MYSQL_TYPE_STRING; my_bind[0].buffer= (void *) data; - my_bind[0].buffer_length= strlen(data); + my_bind[0].buffer_length= (unsigned long)strlen(data); rc= mysql_stmt_bind_param(stmt, my_bind); check_stmt_rc(rc, stmt); @@ -2651,7 +2651,7 @@ static int test_bug5194(MYSQL *mysql) for (i= 1; i < COLUMN_COUNT; ++i) strcat(param_str, "?, "); strcat(param_str, "?)"); - param_str_length= strlen(param_str); + param_str_length= (int)strlen(param_str); /* setup bind array */ memset(my_bind, '\0', MAX_PARAM_COUNT * sizeof(MYSQL_BIND)); @@ -3229,7 +3229,7 @@ static int test_mem_overun(MYSQL *mysql) sprintf(field, "c%d int, ", i); strcat(buffer, field); } - length= strlen(buffer); + length= (int)strlen(buffer); buffer[length-2]= ')'; buffer[--length]= '\0'; @@ -3241,7 +3241,7 @@ static int test_mem_overun(MYSQL *mysql) { strcat(buffer, "1, "); } - length= strlen(buffer); + length= (int)strlen(buffer); buffer[length-2]= ')'; buffer[--length]= '\0'; diff --git a/unittest/libmariadb/ssl.c.in b/unittest/libmariadb/ssl.c.in index c38408fb..3ac318dd 100644 --- a/unittest/libmariadb/ssl.c.in +++ b/unittest/libmariadb/ssl.c.in @@ -53,10 +53,12 @@ static int check_cipher(MYSQL *mysql) return 1; #ifdef HAVE_GNUTLS return strcmp(cipher, "AES-128-GCM"); -#endif -#ifdef HAVE_OPENSSL +#elif HAVE_OPENSSL return strcmp(cipher, "DHE-RSA-AES256-SHA"); +#elif HAVE_SCHANNEL + return strcmp(cipher, "CALG_AES_256"); #endif + return 1; } static int create_ssl_user(const char *ssluser, my_bool is_X509) @@ -268,6 +270,7 @@ DWORD WINAPI ssl_thread(void *dummy) mysql_close(mysql); mysql_thread_end(); pthread_exit(0); + return; } static int test_ssl_threads(MYSQL *mysql) @@ -291,6 +294,7 @@ static int test_ssl_threads(MYSQL *mysql) check_mysql_rc(rc, mysql); rc= mysql_query(mysql, "INSERT into ssltest VALUES (0)"); check_mysql_rc(rc, mysql); + pthread_mutex_init(&LOCK_test, NULL); pthread_mutex_init(&LOCK_test, NULL); @@ -640,6 +644,9 @@ static int test_conc_102(MYSQL *mysql) DWORD threads[50]; #endif + if (check_skip_ssl()) + return SKIP; + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t_conc102"); check_mysql_rc(rc, mysql); rc= mysql_query(mysql, "CREATE TABLE t_conc102 ( a int)"); @@ -701,10 +708,10 @@ static int test_ssl_fp(MYSQL *unused) FAIL_IF(check_cipher(my) != 0, "Invalid cipher"); - mysql_query(my, "SET @a:=1"); + rc= mysql_query(my, "SET @a:=1"); check_mysql_rc(rc, my); - mysql_query(my, "SELECT @a"); + rc= mysql_query(my, "SELECT @a"); check_mysql_rc(rc, my); if ((res= mysql_store_result(my))) diff --git a/win-iconv/win_iconv.c b/win-iconv/win_iconv.c index 6699c022..d1740fe1 100644 --- a/win-iconv/win_iconv.c +++ b/win-iconv/win_iconv.c @@ -789,7 +789,7 @@ win_iconv(iconv_t _cd, const char **inbuf, size_t *inbytesleft, char **outbuf, s if (outbuf != NULL && *outbuf != NULL && cd->to.flush != NULL) { tomode = cd->to.mode; - outsize = cd->to.flush(&cd->to, (uchar *)*outbuf, *outbytesleft); + outsize = cd->to.flush(&cd->to, (uchar *)*outbuf, (int)*outbytesleft); if (outsize == -1) { if ((cd->to.flags & FLAG_IGNORE) && errno != E2BIG) @@ -816,7 +816,7 @@ win_iconv(iconv_t _cd, const char **inbuf, size_t *inbytesleft, char **outbuf, s tomode = cd->to.mode; wsize = MB_CHAR_MAX; - insize = cd->from.mbtowc(&cd->from, (const uchar *)*inbuf, *inbytesleft, wbuf, &wsize); + insize = cd->from.mbtowc(&cd->from, (const uchar *)*inbuf, (int)*inbytesleft, wbuf, &wsize); if (insize == -1) { if (cd->to.flags & FLAG_IGNORE) @@ -867,7 +867,7 @@ win_iconv(iconv_t _cd, const char **inbuf, size_t *inbytesleft, char **outbuf, s } } - outsize = cd->to.wctomb(&cd->to, wbuf, wsize, (uchar *)*outbuf, *outbytesleft); + outsize = cd->to.wctomb(&cd->to, wbuf, wsize, (uchar *)*outbuf, (int)*outbytesleft); if (outsize == -1) { if ((cd->to.flags & FLAG_IGNORE) && errno != E2BIG) From 1308b0598fd263fc0a8e1be0191cc2d5542be866 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Sun, 20 Dec 2015 11:14:03 +0100 Subject: [PATCH 15/40] Skip test for key protected keyfile when using Schannel --- unittest/libmariadb/ssl.c.in | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/unittest/libmariadb/ssl.c.in b/unittest/libmariadb/ssl.c.in index 3ac318dd..d9676a89 100644 --- a/unittest/libmariadb/ssl.c.in +++ b/unittest/libmariadb/ssl.c.in @@ -482,7 +482,7 @@ static int test_conc50_3(MYSQL *my) mysql_ssl_set(mysql, NULL, NULL, "@CMAKE_SOURCE_DIR@/unittest/libmariadb/certs/ca-cert.pem", NULL, NULL); - mysql_real_connect(mysql, hostname, "ssltest", NULL, schema, + mysql_real_connect(mysql, hostname, ssluser, sslpw, schema, port, socketname, 0); diag("Error: %s<", mysql_error(mysql)); FAIL_IF(mysql_errno(mysql), "No error expected"); @@ -767,8 +767,9 @@ struct my_tests_st my_tests[] = { {"test_multi_ssl_connections", test_multi_ssl_connections, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_conc_102", test_conc_102, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_ssl_threads", test_ssl_threads, TEST_CONNECTION_NEW, 0, NULL, NULL}, +#ifndef HAVE_SCHANNEL {"test_password_protected", test_password_protected, TEST_CONNECTION_NEW, 0, NULL, NULL}, - +#endif {NULL, NULL, 0, 0, NULL, NULL} }; From 2c8ef31641a7591b55f646f099a0a1ea97eed6b4 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 21 Dec 2015 08:13:17 +0100 Subject: [PATCH 16/40] renamed aurora test to t_aurora, since we already have a so target aurora (if plugin was build dynamicilly) --- cmake/plugins.cmake | 4 ++-- unittest/libmariadb/CMakeLists.txt | 2 +- unittest/libmariadb/{aurora.c => t_aurora.c} | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename unittest/libmariadb/{aurora.c => t_aurora.c} (100%) diff --git a/cmake/plugins.cmake b/cmake/plugins.cmake index 2d09bb3a..a68bd509 100644 --- a/cmake/plugins.cmake +++ b/cmake/plugins.cmake @@ -44,8 +44,8 @@ ENDIF() REGISTER_PLUGIN("TRACE_EXAMPLE" "${CMAKE_SOURCE_DIR}/plugins/trace/trace_example.c" "trace_example_plugin" "DYNAMIC" "trace_example" 1) #Connection -REGISTER_PLUGIN("REPLICATION" "${CMAKE_SOURCE_DIR}/plugins/connection/replication.c" "connection_replication_plugin" "STATIC" "" 1) -REGISTER_PLUGIN("AURORA" "${CMAKE_SOURCE_DIR}/plugins/connection/aurora.c" "connection_aurora_plugin" "STATIC" "" 1) +REGISTER_PLUGIN("REPLICATION" "${CMAKE_SOURCE_DIR}/plugins/connection/replication.c" "connection_replication_plugin" "DYNAMIC" "" 1) +REGISTER_PLUGIN("AURORA" "${CMAKE_SOURCE_DIR}/plugins/connection/aurora.c" "connection_aurora_plugin" "DYNAMIC" "" 1) # Allow registration of additional plugins IF(PLUGIN_CONF_FILE) diff --git a/unittest/libmariadb/CMakeLists.txt b/unittest/libmariadb/CMakeLists.txt index 6af35f39..8e6dae62 100644 --- a/unittest/libmariadb/CMakeLists.txt +++ b/unittest/libmariadb/CMakeLists.txt @@ -21,7 +21,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/unittest/mytap) ADD_DEFINITIONS(-DLIBMARIADB) -SET(API_TESTS "aurora" "async" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" +SET(API_TESTS "t_aurora" "async" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" "sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread" "dyncol") # Get finger print from server certificate diff --git a/unittest/libmariadb/aurora.c b/unittest/libmariadb/t_aurora.c similarity index 100% rename from unittest/libmariadb/aurora.c rename to unittest/libmariadb/t_aurora.c From d73e4c23a26feafbb7c4c5171b809506822322ce Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 28 Dec 2015 07:32:53 +0100 Subject: [PATCH 17/40] Added new API function mysql_get_info/mysql_get_infov which retrieves global or connection dependent information: mysql_get_infov(MYSQL *mysql, enum mariadb_value value, void *arg, ...) the following value types are supported: MARIADB_CHARSET_ID (requires numeric 4th parameter) MARIADB_CHARSET_INFO (requires string 4th parameter) MARIADB_CHARSET_NAME MARIADB_CLIENT_ERRORS MARIADB_CLIENT_VERSION MARIADB_CLIENT_VERSION_ID MARIADB_CONNECTION_ASYNC_TIMEOUT MARIADB_CONNECTION_ASYNC_TIMEOUT_MS MARIADB_CONNECTION_HOST MARIADB_CONNECTION_INFO MARIADB_CONNECTION_PORT MARIADB_CONNECTION_PROTOCOL_VERSION_ID MARIADB_CONNECTION_PVIO_TYPE MARIADB_CONNECTION_SCHEMA MARIADB_CONNECTION_SERVER_TYPE MARIADB_CONNECTION_SERVER_VERSION MARIADB_CONNECTION_SERVER_VERSION_ID MARIADB_CONNECTION_SOCKET MARIADB_CONNECTION_SSL_CIPHER MARIADB_CONNECTION_SSL_VERSION MARIADB_CONNECTION_SSL_VERSION_ID MARIADB_CONNECTION_TYPE MARIADB_CONNECTION_UNIX_SOCKET MARIADB_CONNECTION_USER MARIADB_MAX_ALLOWED_PACKET MARIADB_NET_BUFFER_LENGTH MARIADB_CONNECTION prefix indicates that a valid connection handle has to be passed as first parameter. --- include/ma_ssl.h | 17 +++ include/mysql.h | 36 ++++- libmariadb/CMakeLists.txt | 3 +- libmariadb/libmariadb.c | 227 +++++++++++++++++++++++++++-- libmariadb/ma_ssl.c | 7 + libmariadb/secure/gnutls.c | 10 +- libmariadb/secure/ma_schannel.c | 60 ++++++-- libmariadb/secure/openssl.c | 41 +++++- libmariadb/secure/schannel.c | 2 +- plugins/connection/CMakeLists.txt | 6 + plugins/connection/replication.c | 19 +-- unittest/libmariadb/CMakeLists.txt | 2 +- unittest/libmariadb/async.c | 3 +- unittest/libmariadb/misc.c | 63 ++++++++ unittest/libmariadb/ssl.c.in | 56 ++++++- 15 files changed, 502 insertions(+), 50 deletions(-) diff --git a/include/ma_ssl.h b/include/ma_ssl.h index ded44e3e..b994f08c 100644 --- a/include/ma_ssl.h +++ b/include/ma_ssl.h @@ -16,6 +16,11 @@ typedef struct st_ma_pvio_ssl { void *ssl; } MARIADB_SSL; +struct st_ssl_version { + unsigned int iversion; + char *cversion; +}; + /* Function prototypes */ /* ma_ssl_start @@ -124,6 +129,17 @@ const char *ma_ssl_get_cipher(MARIADB_SSL *ssl); */ unsigned int ma_ssl_get_finger_print(MARIADB_SSL *cssl, unsigned char *fp, unsigned int fp_len); +/* ma_ssl_get_protocol_version + returns protocol version in use + Parameter: + MARIADB_SSL MariaDB SSL container + version pointer to ssl version info + Returns: + 0 success + 1 error +*/ +my_bool ma_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *version); + /* Function prototypes */ MARIADB_SSL *ma_pvio_ssl_init(MYSQL *mysql); my_bool ma_pvio_ssl_connect(MARIADB_SSL *cssl); @@ -134,5 +150,6 @@ int ma_pvio_ssl_verify_server_cert(MARIADB_SSL *cssl); const char *ma_pvio_ssl_cipher(MARIADB_SSL *cssl); my_bool ma_pvio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_list); my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio); +my_bool ma_pvio_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *version); #endif /* _ma_ssl_h_ */ diff --git a/include/mysql.h b/include/mysql.h index 25dddf0f..dc2577a4 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -216,7 +216,36 @@ extern unsigned int mariadb_deinitialize_ssl; MARIADB_OPT_SSL_PASSWORD, /* password for encrypted certificates */ MARIADB_OPT_CONNECTION_READ_ONLY, MYSQL_OPT_CONNECT_ATTRS, /* for mysql_get_optionv */ - MARIADB_OPT_USERDATA, + MARIADB_OPT_USERDATA + }; + + enum mariadb_value { + MARIADB_CHARSET_ID, + MARIADB_CHARSET_INFO, + MARIADB_CHARSET_NAME, + MARIADB_CLIENT_ERRORS, + MARIADB_CLIENT_VERSION, + MARIADB_CLIENT_VERSION_ID, + MARIADB_CONNECTION_ASYNC_TIMEOUT, + MARIADB_CONNECTION_ASYNC_TIMEOUT_MS, + MARIADB_CONNECTION_HOST, + MARIADB_CONNECTION_INFO, + MARIADB_CONNECTION_PORT, + MARIADB_CONNECTION_PROTOCOL_VERSION_ID, + MARIADB_CONNECTION_PVIO_TYPE, + MARIADB_CONNECTION_SCHEMA, + MARIADB_CONNECTION_SERVER_TYPE, + MARIADB_CONNECTION_SERVER_VERSION, + MARIADB_CONNECTION_SERVER_VERSION_ID, + MARIADB_CONNECTION_SOCKET, + MARIADB_CONNECTION_SSL_CIPHER, + MARIADB_CONNECTION_SSL_VERSION, + MARIADB_CONNECTION_SSL_VERSION_ID, + MARIADB_CONNECTION_TYPE, + MARIADB_CONNECTION_UNIX_SOCKET, + MARIADB_CONNECTION_USER, + MARIADB_MAX_ALLOWED_PACKET, + MARIADB_NET_BUFFER_LENGTH }; enum mysql_status { MYSQL_STATUS_READY, @@ -407,6 +436,8 @@ const char * STDCALL mysql_character_set_name(MYSQL *mysql); void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *cs); int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname); +my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *arg, ...); +my_bool STDCALL mariadb_get_info(MYSQL *mysql, enum mariadb_value value, void *arg); MYSQL * STDCALL mysql_init(MYSQL *mysql); int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key, const char *cert, const char *ca, @@ -493,10 +524,9 @@ int STDCALL mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, int STDCALL mysql_get_option(MYSQL *mysql, enum mysql_option option, void *arg); MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void); unsigned long STDCALL mysql_hex_string(char *to, const char *from, size_t len); -my_socket STDCALL mysql_get_socket(const MYSQL *mysql); +my_socket STDCALL mysql_get_socket(MYSQL *mysql); unsigned int STDCALL mysql_get_timeout_value(const MYSQL *mysql); unsigned int STDCALL mysql_get_timeout_value_ms(const MYSQL *mysql); -int STDCALL mariadb_get_connection_type(MYSQL *mysql); my_bool STDCALL mysql_reconnect(MYSQL *mysql); /* Async API */ diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index 32d1f451..51b683f7 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -36,7 +36,8 @@ SET(EXPORT_SYMBOLS mariadb_dyncol_val_str mariadb_get_charset_by_name mariadb_get_charset_by_nr - mariadb_get_connection_type + mariadb_get_info + mariadb_get_infov mysql_affected_rows mysql_autocommit mysql_autocommit_cont diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index bff15c96..9d8a43c5 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -67,6 +67,9 @@ #include #endif #include +#ifdef HAVE_SSL +#include +#endif #include #include @@ -2547,9 +2550,9 @@ mysql_get_server_info(MYSQL *mysql) return((char*) mysql->server_version); } -unsigned long STDCALL mysql_get_server_version(MYSQL *mysql) +static size_t mariadb_server_version_id(MYSQL *mysql) { - long major, minor, patch; + size_t major, minor, patch; char *p; if (!(p = mysql->server_version)) { @@ -2562,7 +2565,12 @@ unsigned long STDCALL mysql_get_server_version(MYSQL *mysql) p += 1; /* consume the dot */ patch = strtol(p, &p, 10); - return (unsigned long)(major * 10000L + (unsigned long)(minor * 100L + patch)); + return (major * 10000L + (unsigned long)(minor * 100L + patch)); +} + +unsigned long STDCALL mysql_get_server_version(MYSQL *mysql) +{ + return (unsigned long)mariadb_server_version_id(mysql); } @@ -3323,9 +3331,9 @@ mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, return (ulong)mysql_cset_escape_slashes(mysql->charset, to, from, length); } -void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *cs) +static void mariadb_get_charset_info(MYSQL *mysql, MY_CHARSET_INFO *cs) { - DBUG_ENTER("mysql_get_character_set_info"); + DBUG_ENTER("mariadb_get_charset_info"); if (!cs) DBUG_VOID_RETURN; @@ -3342,6 +3350,11 @@ void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *cs) DBUG_VOID_RETURN; } +void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *cs) +{ + return mariadb_get_charset_info(mysql, cs); +} + int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname) { const CHARSET_INFO *cs; @@ -3503,8 +3516,7 @@ mysql_get_parameters(void) return &mariadb_internal_parameters; } -my_socket STDCALL -mysql_get_socket(const MYSQL *mysql) +static my_socket mariadb_get_socket(MYSQL *mysql) { my_socket sock= INVALID_SOCKET; if (mysql->net.pvio) @@ -3523,13 +3535,10 @@ mysql_get_socket(const MYSQL *mysql) return sock; } -int STDCALL mariadb_get_connection_type(MYSQL *mysql) +my_socket STDCALL +mysql_get_socket(MYSQL *mysql) { - /* check if we are connected */ - if (!mysql || !mysql->net.pvio) - return -1; - - return (int)mysql->net.pvio->type; + return mariadb_get_socket(mysql); } CHARSET_INFO * STDCALL mariadb_get_charset_by_name(const char *csname) @@ -3541,6 +3550,198 @@ CHARSET_INFO * STDCALL mariadb_get_charset_by_nr(unsigned int csnr) { return (CHARSET_INFO *)mysql_find_charset_nr(csnr); } + +my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *arg, ...) +{ + va_list ap; + + DBUG_ENTER("mariadb_get_valuev"); + DBUG_PRINT("enter",("value: %d",(int) value)); + + va_start(ap, arg); + + switch(value) { + case MARIADB_MAX_ALLOWED_PACKET: + *((size_t *)arg)= (size_t)max_allowed_packet; + break; + case MARIADB_NET_BUFFER_LENGTH: + *((size_t *)arg)= (size_t)net_buffer_length; + break; + case MARIADB_CONNECTION_SSL_VERSION: + #ifdef HAVE_SSL + if (mysql && mysql->net.pvio && mysql->net.pvio->cssl) + { + struct st_ssl_version version; + if (!ma_pvio_ssl_get_protocol_version(mysql->net.pvio->cssl, &version)) + *((char **)arg)= version.cversion; + } + else + #endif + goto error; + break; + case MARIADB_CONNECTION_SSL_VERSION_ID: + #ifdef HAVE_SSL + if (mysql && mysql->net.pvio && mysql->net.pvio->cssl) + { + struct st_ssl_version version; + if (!ma_pvio_ssl_get_protocol_version(mysql->net.pvio->cssl, &version)) + *((unsigned int *)arg)= version.iversion; + } + else + #endif + goto error; + break; + case MARIADB_CLIENT_VERSION: + *((char **)arg)= MYSQL_CLIENT_VERSION; + break; + case MARIADB_CLIENT_VERSION_ID: + *((size_t *)arg)= MYSQL_VERSION_ID; + break; + case MARIADB_CONNECTION_SERVER_VERSION: + if (mysql) + *((char **)arg)= mysql->server_version; + else + goto error; + break; + case MARIADB_CONNECTION_SERVER_TYPE: + if (mysql) + *((char **)arg)= mariadb_connection(mysql) ? "MariaDB" : "MySQL"; + else + goto error; + break; + case MARIADB_CONNECTION_SERVER_VERSION_ID: + if (mysql) + *((size_t *)arg)= mariadb_server_version_id(mysql); + else + goto error; + break; + case MARIADB_CONNECTION_PROTOCOL_VERSION_ID: + if (mysql) + *((unsigned int *)arg)= mysql->protocol_version; + else + goto error; + break; + case MARIADB_CHARSET_INFO: + if (mysql) + mariadb_get_charset_info(mysql, (MY_CHARSET_INFO *)arg); + else + goto error; + break; + case MARIADB_CONNECTION_SOCKET: + if (mysql) + *((my_socket *)arg)= mariadb_get_socket(mysql); + else + goto error; + break; + case MARIADB_CONNECTION_TYPE: + if (mysql && mysql->net.pvio) + *((int *)arg)= (int)mysql->net.pvio->type; + else + goto error; + break; + case MARIADB_CONNECTION_ASYNC_TIMEOUT_MS: + if (mysql && mysql->options.extension && mysql->options.extension->async_context) + *((unsigned int *)arg)= mysql->options.extension->async_context->timeout_value; + else + goto error; + break; + case MARIADB_CONNECTION_ASYNC_TIMEOUT: + if (mysql && mysql->options.extension && mysql->options.extension->async_context) + { + unsigned int timeout= mysql->options.extension->async_context->timeout_value; + if (timeout > UINT_MAX - 999) + *((unsigned int *)arg)= (timeout - 1)/1000 + 1; + else + *((unsigned int *)arg)= (timeout+999)/1000; + } + else + goto error; + break; + case MARIADB_CHARSET_NAME: + { + char *name; + name= va_arg(ap, char *); + if (name) + *((CHARSET_INFO **)arg)= (CHARSET_INFO *)mysql_find_charset_name(name); + else + goto error; + } + break; + case MARIADB_CHARSET_ID: + { + unsigned int nr; + nr= va_arg(ap, unsigned int); + *((CHARSET_INFO **)arg)= (CHARSET_INFO *)mysql_find_charset_nr(nr); + } + break; + case MARIADB_CONNECTION_SSL_CIPHER: + #ifdef HAVE_SSL + if (mysql && mysql->net.pvio && mysql->net.pvio->cssl) + *((char **)arg)= (char *)ma_pvio_ssl_cipher(mysql->net.pvio->cssl); + else + #endif + goto error; + break; + case MARIADB_CLIENT_ERRORS: + *((char ***)arg)= (char **)client_errors; + break; + case MARIADB_CONNECTION_INFO: + if (mysql) + *((char **)arg)= (char *)mysql->info; + else + goto error; + break; + case MARIADB_CONNECTION_PVIO_TYPE: + if (mysql && !mysql->net.pvio) + *((unsigned int *)arg)= (unsigned int)mysql->net.pvio->type; + else + goto error; + break; + case MARIADB_CONNECTION_SCHEMA: + if (mysql) + *((char **)arg)= mysql->db; + else + goto error; + break; + case MARIADB_CONNECTION_USER: + if (mysql) + *((char **)arg)= mysql->user; + else + goto error; + break; + case MARIADB_CONNECTION_PORT: + if (mysql) + *((unsigned int *)arg)= mysql->port; + else + goto error; + break; + case MARIADB_CONNECTION_UNIX_SOCKET: + if (mysql) + *((char **)arg)= mysql->unix_socket; + else + goto error; + break; + case MARIADB_CONNECTION_HOST: + if (mysql) + *((char **)arg)= mysql->host; + else + goto error; + break; + default: + va_end(ap); + DBUG_RETURN(-1); + } + va_end(ap); + DBUG_RETURN(0); +error: + va_end(ap); + DBUG_RETURN(-1); +} + +my_bool STDCALL mariadb_get_info(MYSQL *mysql, enum mariadb_value value, void *arg) +{ + return mariadb_get_infov(mysql, value, arg); +} /* * Default methods for a connection. These methods are * stored in mysql->methods and can be overwritten by diff --git a/libmariadb/ma_ssl.c b/libmariadb/ma_ssl.c index 3ea613e3..2ea474a8 100644 --- a/libmariadb/ma_ssl.c +++ b/libmariadb/ma_ssl.c @@ -51,6 +51,8 @@ my_bool ma_ssl_initialized= FALSE; unsigned int mariadb_deinitialize_ssl= 1; +char *ssl_protocol_version[5]= {"unknown", "SSL3", "TLS1.0", "TLS1.1", "TLS1.2"}; + MARIADB_SSL *ma_pvio_ssl_init(MYSQL *mysql) { MARIADB_SSL *cssl= NULL; @@ -104,6 +106,11 @@ const char *ma_pvio_ssl_cipher(MARIADB_SSL *cssl) return ma_ssl_get_cipher(cssl); } +my_bool ma_pvio_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *version) +{ + return ma_ssl_get_protocol_version(cssl, version); +} + static my_bool ma_pvio_ssl_compare_fp(char *fp1, unsigned int fp1_len, char *fp2, unsigned int fp2_len) { diff --git a/libmariadb/secure/gnutls.c b/libmariadb/secure/gnutls.c index cfa89006..5b955e1b 100644 --- a/libmariadb/secure/gnutls.c +++ b/libmariadb/secure/gnutls.c @@ -423,5 +423,13 @@ unsigned int ma_ssl_get_finger_print(MARIADB_SSL *cssl, unsigned char *fp, unsig } } -#endif /* HAVE_GNUTLS */ +my_bool ma_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *version) +{ + if (!cssl || !cssl->ssl) + return 1; + version->iversion= gnutls_protocol_get_version(cssl->ssl); + version->cversion= (char *)gnutls_protocol_get_name(version->iversion); + return 0; +} +#endif /* HAVE_GNUTLS */ diff --git a/libmariadb/secure/ma_schannel.c b/libmariadb/secure/ma_schannel.c index 6266212f..063ce361 100644 --- a/libmariadb/secure/ma_schannel.c +++ b/libmariadb/secure/ma_schannel.c @@ -626,14 +626,6 @@ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl) return sRet; } - /* Allocate IO-Buffer */ - sctx->IoBufferSize= 2 * net_buffer_length; - if (!(sctx->IoBuffer= (PUCHAR)LocalAlloc(LMEM_ZEROINIT, sctx->IoBufferSize))) - { - sRet= SEC_E_INSUFFICIENT_MEMORY; - goto end; - } - /* send client hello packaet */ if(BuffersOut[0].cbBuffer != 0 && BuffersOut[0].pvBuffer != NULL) { @@ -646,11 +638,17 @@ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl) } sRet= ma_schannel_handshake_loop(pvio, TRUE, &ExtraData); - /* Reallocate IO-Buffer for write operations: After handshake + /* allocate IO-Buffer for write operations: After handshake was successfull, we are able now to calculate payload */ - QueryContextAttributes( &sctx->ctxt, SECPKG_ATTR_STREAM_SIZES, &sctx->Sizes ); + if ((sRet = QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_STREAM_SIZES, &sctx->Sizes ))) + goto end; + sctx->IoBufferSize= SCHANNEL_PAYLOAD(sctx->Sizes); - sctx->IoBuffer= LocalReAlloc(sctx->IoBuffer, sctx->IoBufferSize, LMEM_ZEROINIT); + if (!(sctx->IoBuffer= (PUCHAR)LocalAlloc(0, sctx->IoBufferSize))) + { + sRet= SEC_E_INSUFFICIENT_MEMORY; + goto end; + } return sRet; end: @@ -776,6 +774,7 @@ SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_PVIO *pvio, dwOffset= 0; } } +/* }}} */ my_bool ma_schannel_verify_certs(SC_CTX *sctx, DWORD dwCertFlags) { @@ -897,8 +896,45 @@ size_t ma_schannel_write_encrypt(MARIADB_PVIO *pvio, return -1; if (pvio->methods->write(pvio, sctx->IoBuffer, Buffers[0].cbBuffer + Buffers[1].cbBuffer + Buffers[2].cbBuffer)) - return payload; + return payload; return 0; } /* }}} */ +extern char *ssl_protocol_version[5]; + +/* {{{ ma_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *version) */ +my_bool ma_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *version) +{ + SC_CTX *sctx; + SecPkgContext_ConnectionInfo ConnectionInfo; + if (!cssl->ssl) + return 1; + + sctx= (SC_CTX *)cssl->ssl; + + if (QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_CONNECTION_INFO, &ConnectionInfo) != SEC_E_OK) + return 1; + + switch(ConnectionInfo.dwProtocol) + { + case SP_PROT_SSL3_CLIENT: + version->iversion= 1; + break; + case SP_PROT_TLS1_CLIENT: + version->iversion= 2; + break; + case SP_PROT_TLS1_1_CLIENT: + version->iversion= 3; + break; + case SP_PROT_TLS1_2_CLIENT: + version->iversion= 4; + break; + default: + version->iversion= 0; + break; + } + version->cversion= ssl_protocol_version[version->iversion]; + return 0; +} +/* }}} */ diff --git a/libmariadb/secure/openssl.c b/libmariadb/secure/openssl.c index d4164403..e659a1a1 100644 --- a/libmariadb/secure/openssl.c +++ b/libmariadb/secure/openssl.c @@ -177,8 +177,11 @@ int ma_ssl_start(char *errmsg, size_t errmsg_len) SSL_load_error_strings(); /* digests and ciphers */ OpenSSL_add_all_algorithms(); - - if (!(SSL_context= SSL_CTX_new(TLSv1_client_method()))) +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) + if (!(SSL_context= SSL_CTX_new(TLS_client_method()))) +#else + if (!(SSL_context= SSL_CTX_new(SSLv23_client_method()))) +#endif { ma_ssl_get_error(errmsg, errmsg_len); goto end; @@ -569,3 +572,37 @@ unsigned int ma_ssl_get_finger_print(MARIADB_SSL *cssl, unsigned char *fp, unsig } return (fp_len); } + + +extern char *ssl_protocol_version[5]; + +my_bool ma_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *version) +{ + SSL *ssl; + + if (!cssl || !cssl->ssl) + return 1; + + ssl = (SSL *)cssl->ssl; + switch(ssl->version) + { + case SSL3_VERSION: + version->iversion= 1; + break; + case TLS1_VERSION: + version->iversion= 2; + break; + case TLS1_1_VERSION: + version->iversion= 3; + break; + case TLS1_2_VERSION: + version->iversion= 4; + break; + default: + version->iversion= 0; + break; + } + version->cversion= ssl_protocol_version[version->iversion]; + return 0; +} + diff --git a/libmariadb/secure/schannel.c b/libmariadb/secure/schannel.c index cc0fd4e2..3f84c17f 100644 --- a/libmariadb/secure/schannel.c +++ b/libmariadb/secure/schannel.c @@ -284,7 +284,7 @@ my_bool ma_ssl_connect(MARIADB_SSL *cssl) Cred.cCreds = 1; Cred.paCred = &sctx->client_cert_ctx; } - Cred.grbitEnabledProtocols= SP_PROT_TLS1; + Cred.grbitEnabledProtocols= SP_PROT_TLS1_1PLUS; if ((sRet= AcquireCredentialsHandleA(NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL, &Cred, NULL, NULL, &sctx->CredHdl, NULL)) != SEC_E_OK) diff --git a/plugins/connection/CMakeLists.txt b/plugins/connection/CMakeLists.txt index f68269b6..4ccdd611 100644 --- a/plugins/connection/CMakeLists.txt +++ b/plugins/connection/CMakeLists.txt @@ -14,6 +14,9 @@ IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC") ENDIF() ADD_DEFINITIONS(-DHAVE_REPLICATION_DYNAMIC=1) ADD_LIBRARY(replication SHARED ${replication_RC} replication.c ${EXPORT_FILE}) + IF(WIN32) + TARGET_LINK_LIBRARIES(replication libmariadb) + ENDIF() SET(INSTALL_LIBS replication) ENDIF() @@ -27,6 +30,9 @@ IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC") ENDIF() ADD_DEFINITIONS(-DHAVE_AURORA_DYNAMIC=1) ADD_LIBRARY(aurora SHARED ${aurora_RC} aurora.c ${EXPORT_FILE}) + IF(WIN32) + TARGET_LINK_LIBRARIES(aurora libmariadb) + ENDIF() SET(INSTALL_LIBS ${INSTALL_LIBS} aurora) ENDIF() diff --git a/plugins/connection/replication.c b/plugins/connection/replication.c index c9415c01..7c5eeabf 100644 --- a/plugins/connection/replication.c +++ b/plugins/connection/replication.c @@ -42,13 +42,6 @@ int repl_command(MYSQL *mysql,enum enum_server_command command, const char *arg, size_t length, my_bool skipp_check, void *opt_arg); int repl_set_options(MYSQL *msql, enum mysql_option option, void *arg); -#ifdef HAVE_REPLICATION_DYNAMIC - -#undef my_free -#define my_malloc(a,b) malloc(a) -#define my_free(a) free(a) -#endif - #define MARIADB_MASTER 0 #define MARIADB_SLAVE 1 @@ -120,7 +113,7 @@ my_bool repl_parse_url(const char *url, REPL_DATA *data) memset(data->port, 0, 2 * sizeof(int)); if (!data->url) - data->url= my_strdup(url, MYF(0)); + data->url= strdup(url); data->host[MARIADB_MASTER]= p= data->url; /* get slaves */ @@ -188,7 +181,7 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char if ((data= (REPL_DATA *)hdlr->data)) { - ma_pvio_close(data->pvio[MARIADB_MASTER]); + data->pvio[MARIADB_MASTER]->methods->close(data->pvio[MARIADB_MASTER]); data->pvio[MARIADB_MASTER]= 0; repl_close(mysql); } @@ -234,8 +227,8 @@ error: if (data) { if (data->url) - my_free(data->url); - my_free(data); + free(data->url); + free(data); } return NULL; } @@ -259,8 +252,8 @@ void repl_close(MYSQL *mysql) } /* free masrwe information and close connection */ - my_free(data->url); - my_free(data); + free(data->url); + free(data); mysql->net.conn_hdlr->data= NULL; } diff --git a/unittest/libmariadb/CMakeLists.txt b/unittest/libmariadb/CMakeLists.txt index 8e6dae62..f2976b38 100644 --- a/unittest/libmariadb/CMakeLists.txt +++ b/unittest/libmariadb/CMakeLists.txt @@ -58,7 +58,7 @@ ENDIF() FOREACH(API_TEST ${API_TESTS}) ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c) - TARGET_LINK_LIBRARIES(${API_TEST} mytap mariadbclient) + TARGET_LINK_LIBRARIES(${API_TEST} mytap libmariadb) ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST}) SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 120) ENDFOREACH(API_TEST) diff --git a/unittest/libmariadb/async.c b/unittest/libmariadb/async.c index 7fdf120a..c9f6c49b 100644 --- a/unittest/libmariadb/async.c +++ b/unittest/libmariadb/async.c @@ -34,7 +34,8 @@ my_bool skip_async= 0; static int test_async(MYSQL *mysql) { - int type= mariadb_get_connection_type(mysql); + int type; + mariadb_get_info(mysql, MARIADB_CONNECTION_PVIO_TYPE, &type); if (type > MARIADB_CONNECTION_TCP) { skip_async= 1; diff --git a/unittest/libmariadb/misc.c b/unittest/libmariadb/misc.c index ede78ace..fcb6a14c 100644 --- a/unittest/libmariadb/misc.c +++ b/unittest/libmariadb/misc.c @@ -1021,11 +1021,74 @@ static int test_remote2(MYSQL *my) } #endif +static int test_get_info(MYSQL *mysql) +{ + size_t sval; + unsigned int ival; + char *cval; + int rc; + MY_CHARSET_INFO cs; + CHARSET_INFO *ci; + char **errors; + + rc= mariadb_get_infov(mysql, MARIADB_MAX_ALLOWED_PACKET, &sval); + FAIL_IF(rc, "mysql_get_info failed"); + diag("max_allowed_packet: %d", sval); + rc= mariadb_get_infov(mysql, MARIADB_NET_BUFFER_LENGTH, &sval); + FAIL_IF(rc, "mysql_get_info failed"); + diag("net_buffer_length: %d", sval); + rc= mariadb_get_infov(mysql, MARIADB_CLIENT_VERSION_ID, &sval); + FAIL_IF(rc, "mysql_get_info failed"); + diag("client_version_id: %d", sval); + rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_VERSION_ID, &sval); + FAIL_IF(rc, "mysql_get_info failed"); + diag("server_version_id: %d", sval); + rc= mariadb_get_infov(mysql, MARIADB_CHARSET_INFO, &cs); + FAIL_IF(rc, "mysql_get_info failed"); + diag("charset name: %s", cs.csname); + rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_PVIO_TYPE, &ival); + FAIL_IF(rc, "mysql_get_info failed"); + diag("connection type: %d", ival); + rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_PROTOCOL_VERSION_ID, &ival); + FAIL_IF(rc, "mysql_get_info failed"); + diag("protocol_version: %d", ival); + rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_TYPE, &cval); + FAIL_IF(rc, "mysql_get_info failed"); + diag("server_type: %s", cval); + rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_VERSION, &cval); + FAIL_IF(rc, "mysql_get_info failed"); + diag("server_version: %s", cval); + rc= mariadb_get_infov(mysql, MARIADB_CLIENT_VERSION, &cval); + FAIL_IF(rc, "mysql_get_info failed"); + diag("client_version: %s", cval); + rc= mariadb_get_infov(mysql, MARIADB_CHARSET_NAME, &ci, "utf8"); + FAIL_IF(rc, "mysql_get_info failed"); + diag("charset_name: %s", ci->csname); + diag("charset_nr: %d", ci->nr); + rc= mariadb_get_infov(mysql, MARIADB_CHARSET_ID, &ci, 63); + FAIL_IF(rc, "mysql_get_info failed"); + diag("charset_name: %s", ci->csname); + rc= mariadb_get_infov(mysql, MARIADB_CLIENT_ERRORS, &errors); + FAIL_IF(rc, "mysql_get_info failed"); + diag("error[0]: %s", errors[0]); + rc= mysql_query(mysql, "DROP TABLE IF exists t1"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE t1 (a int)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1),(2)"); + check_mysql_rc(rc, mysql); + rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_INFO, &cval); + FAIL_IF(rc, "mysql_get_info failed"); + diag("mariadb_info: %s", cval); + return OK; +} + struct my_tests_st my_tests[] = { #ifdef HAVE_REMOTEIO {"test_remote1", test_remote1, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_remote2", test_remote2, TEST_CONNECTION_NEW, 0, NULL, NULL}, #endif + {"test_get_info", test_get_info, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc117", test_conc117, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc_114", test_conc_114, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_connect_attrs", test_connect_attrs, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, diff --git a/unittest/libmariadb/ssl.c.in b/unittest/libmariadb/ssl.c.in index d9676a89..6982e41b 100644 --- a/unittest/libmariadb/ssl.c.in +++ b/unittest/libmariadb/ssl.c.in @@ -51,10 +51,16 @@ static int check_cipher(MYSQL *mysql) char *cipher= (char *)mysql_get_ssl_cipher(mysql); if (!cipher) return 1; + diag("cipher: %s", cipher); + #ifdef HAVE_GNUTLS - return strcmp(cipher, "AES-128-GCM"); + { + return strcmp(cipher, "AES-128-GCM"); + } #elif HAVE_OPENSSL - return strcmp(cipher, "DHE-RSA-AES256-SHA"); + if (!strcmp(cipher, "DHE-RSA-AES256-SHA") || + !strcmp(cipher, "DHE-RSA-AES256-GCM-SHA384")) + return 0; #elif HAVE_SCHANNEL return strcmp(cipher, "CALG_AES_256"); #endif @@ -107,6 +113,14 @@ static int test_ssl(MYSQL *mysql) } mysql_free_result(res); +#ifdef HAVE_GNUTLS + diag("SSL library: GNUTLS"); +#elif HAVE_OPENSSL + diag("SSL library: OPENSSL"); +#elif HAVE_SCHANNEL + diag("SSL library: SCHANNEL"); +#endif + sslhost[0]= 0; if (!skip_ssl) @@ -129,6 +143,9 @@ static int test_ssl(MYSQL *mysql) static int test_ssl_cipher(MYSQL *unused) { MYSQL *my; + MYSQL_RES *res; + MYSQL_ROW row; + int rc; if (check_skip_ssl()) return SKIP; @@ -141,6 +158,14 @@ static int test_ssl_cipher(MYSQL *unused) FAIL_IF(!mysql_real_connect(my, hostname, ssluser, sslpw, schema, port, socketname, 0), mysql_error(my)); + rc= mysql_query(my, "SHOW session status like 'Ssl_version'"); + check_mysql_rc(rc, my); + res= mysql_store_result(my); + row= mysql_fetch_row(res); + diag("%s: %s", row[0], row[1]); + diag("cipher: %s", mysql_get_ssl_cipher(my)); + mysql_free_result(res); + FAIL_IF(check_cipher(my) != 0, "Invalid cipher"); mysql_close(my); return OK; @@ -747,7 +772,33 @@ static int test_ssl_fp_list(MYSQL *unused) return OK; } +static int test_ssl_version(MYSQL *mysql) +{ + unsigned int iversion; + char *version; + MYSQL *my; + if (check_skip_ssl()) + return SKIP; + + my= mysql_init(NULL); + FAIL_IF(!my, "mysql_init() failed"); + + mysql_ssl_set(my,0, 0, "@CMAKE_SOURCE_DIR@/unittest/libmariadb/certs/ca-cert.pem", 0, 0); + FAIL_IF(!mysql_real_connect(my, hostname, ssluser, sslpw, schema, + port, socketname, 0), mysql_error(my)); + + diag("cipher: %s", mysql_get_ssl_cipher(my)); + mariadb_get_infov(my, MARIADB_CONNECTION_SSL_VERSION_ID, &iversion); + diag("protocol: %d", iversion); + mariadb_get_infov(my, MARIADB_CONNECTION_SSL_VERSION, &version); + diag("protocol: %s", version); + + mysql_close(my); + + return OK; +} + struct my_tests_st my_tests[] = { {"test_ssl", test_ssl, TEST_CONNECTION_NEW, 0, NULL, NULL}, @@ -766,6 +817,7 @@ struct my_tests_st my_tests[] = { {"test_ssl_cipher", test_ssl_cipher, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_multi_ssl_connections", test_multi_ssl_connections, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_conc_102", test_conc_102, TEST_CONNECTION_NEW, 0, NULL, NULL}, + {"test_ssl_version", test_ssl_version, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_ssl_threads", test_ssl_threads, TEST_CONNECTION_NEW, 0, NULL, NULL}, #ifndef HAVE_SCHANNEL {"test_password_protected", test_password_protected, TEST_CONNECTION_NEW, 0, NULL, NULL}, From 46a975bd04d7609ba9c912aa8c4de91ffb3d00a1 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 28 Dec 2015 09:00:24 +0100 Subject: [PATCH 18/40] Added st_mariadb_api structure which contains api definition for use in dynamic plugins --- include/mysql.h | 124 +++++++++++++++++++++++++++++- libmariadb/libmariadb.c | 125 +++++++++++++++++++++++++++++++ plugins/connection/aurora.c | 23 +++--- plugins/connection/replication.c | 11 ++- 4 files changed, 270 insertions(+), 13 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index dc2577a4..473f7401 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -443,7 +443,6 @@ int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher); const char * STDCALL mysql_get_ssl_cipher(MYSQL *mysql); -int STDCALL mysql_ssl_clear(MYSQL *mysql); MYSQL * STDCALL mysql_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd); my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, @@ -640,6 +639,128 @@ int STDCALL mysql_stmt_send_long_data_cont(my_bool *ret, MYSQL_STMT *stmt, int status); +/* API function calls (used by dynmic plugins) */ +struct st_mariadb_api { + my_ulonglong (*mysql_num_rows)(MYSQL_RES *res); + unsigned int (*mysql_num_fields)(MYSQL_RES *res); + my_bool (*mysql_eof)(MYSQL_RES *res); + MYSQL_FIELD *(*mysql_fetch_field_direct)(MYSQL_RES *res, unsigned int fieldnr); + MYSQL_FIELD * (*mysql_fetch_fields)(MYSQL_RES *res); + MYSQL_ROWS * (*mysql_row_tell)(MYSQL_RES *res); + unsigned int (*mysql_field_tell)(MYSQL_RES *res); + unsigned int (*mysql_field_count)(MYSQL *mysql); + my_bool (*mysql_more_results)(MYSQL *mysql); + int (*mysql_next_result)(MYSQL *mysql); + my_ulonglong (*mysql_affected_rows)(MYSQL *mysql); + my_bool (*mysql_autocommit)(MYSQL *mysql, my_bool mode); + my_bool (*mysql_commit)(MYSQL *mysql); + my_bool (*mysql_rollback)(MYSQL *mysql); + my_ulonglong (*mysql_insert_id)(MYSQL *mysql); + unsigned int (*mysql_errno)(MYSQL *mysql); + char * (*mysql_error)(MYSQL *mysql); + char * (*mysql_info)(MYSQL *mysql); + unsigned long (*mysql_thread_id)(MYSQL *mysql); + const char * (*mysql_character_set_name)(MYSQL *mysql); + void (*mysql_get_character_set_info)(MYSQL *mysql, MY_CHARSET_INFO *cs); + int (*mysql_set_character_set)(MYSQL *mysql, const char *csname); + my_bool (*mariadb_get_infov)(MYSQL *mysql, enum mariadb_value value, void *arg, ...); + my_bool (*mariadb_get_info)(MYSQL *mysql, enum mariadb_value value, void *arg); + MYSQL * (*mysql_init)(MYSQL *mysql); + int (*mysql_ssl_set)(MYSQL *mysql, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher); + const char * (*mysql_get_ssl_cipher)(MYSQL *mysql); + MYSQL * (*mysql_connect)(MYSQL *mysql, const char *host, const char *user, const char *passwd); + my_bool (*mysql_change_user)(MYSQL *mysql, const char *user, const char *passwd, const char *db); + MYSQL * (*mysql_real_connect)(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag); + void (*mysql_close)(MYSQL *sock); + int (*mysql_select_db)(MYSQL *mysql, const char *db); + int (*mysql_query)(MYSQL *mysql, const char *q); + int (*mysql_send_query)(MYSQL *mysql, const char *q, size_t length); + my_bool (*mysql_read_query_result)(MYSQL *mysql); + int (*mysql_real_query)(MYSQL *mysql, const char *q, size_t length); + int (*mysql_create_db)(MYSQL *mysql, const char *DB); + int (*mysql_drop_db)(MYSQL *mysql, const char *DB); + int (*mysql_shutdown)(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level); + int (*mysql_dump_debug_info)(MYSQL *mysql); + int (*mysql_refresh)(MYSQL *mysql, unsigned int refresh_options); + int (*mysql_kill)(MYSQL *mysql,unsigned long pid); + int (*mysql_ping)(MYSQL *mysql); + char * (*mysql_stat)(MYSQL *mysql); + char * (*mysql_get_server_info)(MYSQL *mysql); + unsigned long (*mysql_get_server_version)(MYSQL *mysql); + char * (*mysql_get_host_info)(MYSQL *mysql); + unsigned int (*mysql_get_proto_info)(MYSQL *mysql); + MYSQL_RES * (*mysql_list_dbs)(MYSQL *mysql,const char *wild); + MYSQL_RES * (*mysql_list_tables)(MYSQL *mysql,const char *wild); + MYSQL_RES * (*mysql_list_fields)(MYSQL *mysql, const char *table, const char *wild); + MYSQL_RES * (*mysql_list_processes)(MYSQL *mysql); + MYSQL_RES * (*mysql_store_result)(MYSQL *mysql); + MYSQL_RES * (*mysql_use_result)(MYSQL *mysql); + int (*mysql_options)(MYSQL *mysql,enum mysql_option option, const void *arg); + void (*mysql_free_result)(MYSQL_RES *result); + void (*mysql_data_seek)(MYSQL_RES *result, my_ulonglong offset); + MYSQL_ROW_OFFSET (*mysql_row_seek)(MYSQL_RES *result, MYSQL_ROW_OFFSET); + MYSQL_FIELD_OFFSET (*mysql_field_seek)(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset); + MYSQL_ROW (*mysql_fetch_row)(MYSQL_RES *result); + unsigned long * (*mysql_fetch_lengths)(MYSQL_RES *result); + MYSQL_FIELD * (*mysql_fetch_field)(MYSQL_RES *result); + unsigned long (*mysql_escape_string)(char *to,const char *from, unsigned long from_length); + unsigned long (*mysql_real_escape_string)(MYSQL *mysql, char *to,const char *from, unsigned long length); + void (*mysql_debug)(const char *debug); + void (*mysql_debug_end)(void); + unsigned int (*mysql_thread_safe)(void); + unsigned int (*mysql_warning_count)(MYSQL *mysql); + const char * (*mysql_sqlstate)(MYSQL *mysql); + int (*mysql_server_init)(int argc, char **argv, char **groups); + void (*mysql_server_end)(void); + void (*mysql_thread_end)(void); + my_bool (*mysql_thread_init)(void); + int (*mysql_set_server_option)(MYSQL *mysql, enum enum_mysql_set_option option); + const char * (*mysql_get_client_info)(void); + unsigned long (*mysql_get_client_version)(void); + my_bool (*mariadb_connection)(MYSQL *mysql); + const char * (*mysql_get_server_name)(MYSQL *mysql); + CHARSET_INFO * (*mariadb_get_charset_by_name)(const char *csname); + CHARSET_INFO * (*mariadb_get_charset_by_nr)(unsigned int csnr); + size_t (*mariadb_convert_string)(const char *from, size_t *from_len, CHARSET_INFO *from_cs, char *to, size_t *to_len, CHARSET_INFO *to_cs, int *errorcode); + int (*mysql_optionsv)(MYSQL *mysql,enum mysql_option option, ...); + int (*mysql_get_optionv)(MYSQL *mysql, enum mysql_option option, void *arg, ...); + int (*mysql_get_option)(MYSQL *mysql, enum mysql_option option, void *arg); + MYSQL_PARAMETERS *(*mysql_get_parameters)(void); + unsigned long (*mysql_hex_string)(char *to, const char *from, size_t len); + my_socket (*mysql_get_socket)(MYSQL *mysql); + unsigned int (*mysql_get_timeout_value)(const MYSQL *mysql); + unsigned int (*mysql_get_timeout_value_ms)(const MYSQL *mysql); + my_bool (*mysql_reconnect)(MYSQL *mysql); + MYSQL_STMT * (*mysql_stmt_init)(MYSQL *mysql); + int (*mysql_stmt_prepare)(MYSQL_STMT *stmt, const char *query, size_t length); + int (*mysql_stmt_execute)(MYSQL_STMT *stmt); + int (*mysql_stmt_fetch)(MYSQL_STMT *stmt); + int (*mysql_stmt_fetch_column)(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg, unsigned int column, unsigned long offset); + int (*mysql_stmt_store_result)(MYSQL_STMT *stmt); + unsigned long (*mysql_stmt_param_count)(MYSQL_STMT * stmt); + my_bool (*mysql_stmt_attr_set)(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, const void *attr); + my_bool (*mysql_stmt_attr_get)(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, void *attr); + my_bool (*mysql_stmt_bind_param)(MYSQL_STMT * stmt, MYSQL_BIND * bnd); + my_bool (*mysql_stmt_bind_result)(MYSQL_STMT * stmt, MYSQL_BIND * bnd); + my_bool (*mysql_stmt_close)(MYSQL_STMT * stmt); + my_bool (*mysql_stmt_reset)(MYSQL_STMT * stmt); + my_bool (*mysql_stmt_free_result)(MYSQL_STMT *stmt); + my_bool (*mysql_stmt_send_long_data)(MYSQL_STMT *stmt, unsigned int param_number, const char *data, size_t length); + MYSQL_RES *(*mysql_stmt_result_metadata)(MYSQL_STMT *stmt); + MYSQL_RES *(*mysql_stmt_param_metadata)(MYSQL_STMT *stmt); + unsigned int (*mysql_stmt_errno)(MYSQL_STMT * stmt); + const char *(*mysql_stmt_error)(MYSQL_STMT * stmt); + const char *(*mysql_stmt_sqlstate)(MYSQL_STMT * stmt); + MYSQL_ROW_OFFSET (*mysql_stmt_row_seek)(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET offset); + MYSQL_ROW_OFFSET (*mysql_stmt_row_tell)(MYSQL_STMT *stmt); + void (*mysql_stmt_data_seek)(MYSQL_STMT *stmt, my_ulonglong offset); + my_ulonglong (*mysql_stmt_num_rows)(MYSQL_STMT *stmt); + my_ulonglong (*mysql_stmt_affected_rows)(MYSQL_STMT *stmt); + my_ulonglong (*mysql_stmt_insert_id)(MYSQL_STMT *stmt); + unsigned int (*mysql_stmt_field_count)(MYSQL_STMT *stmt); + int (*mysql_stmt_next_result)(MYSQL_STMT *stmt); + my_bool (*mysql_stmt_more_results)(MYSQL_STMT *stmt); +}; /* these methods can be overwritten by db plugins */ struct st_mysql_methods { @@ -663,6 +784,7 @@ struct st_mysql_methods { int (*db_stmt_fetch_to_bind)(MYSQL_STMT *stmt, unsigned char *row); void (*db_stmt_flush_unbuffered)(MYSQL_STMT *stmt); void (*set_error)(MYSQL *mysql, unsigned int error_nr, const char *sqlstate, const char *format, ...); + struct st_mariadb_api *api; }; /* synonyms/aliases functions */ diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 9d8a43c5..bb976041 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -3742,6 +3742,130 @@ my_bool STDCALL mariadb_get_info(MYSQL *mysql, enum mariadb_value value, void *a { return mariadb_get_infov(mysql, value, arg); } + +/* API functions for usage in dynamic plugins */ +struct st_mariadb_api MARIADB_API= { + mysql_num_rows, + mysql_num_fields, + mysql_eof, + mysql_fetch_field_direct, + mysql_fetch_fields, + mysql_row_tell, + mysql_field_tell, + mysql_field_count, + mysql_more_results, + mysql_next_result, + mysql_affected_rows, + mysql_autocommit, + mysql_commit, + mysql_rollback, + mysql_insert_id, + mysql_errno, + mysql_error, + mysql_info, + mysql_thread_id, + mysql_character_set_name, + mysql_get_character_set_info, + mysql_set_character_set, + mariadb_get_infov, + mariadb_get_info, + mysql_init, + mysql_ssl_set, + mysql_get_ssl_cipher, + mysql_connect, + mysql_change_user, + mysql_real_connect, + mysql_close, + mysql_select_db, + mysql_query, + mysql_send_query, + mysql_read_query_result, + mysql_real_query, + mysql_create_db, + mysql_drop_db, + mysql_shutdown, + mysql_dump_debug_info, + mysql_refresh, + mysql_kill, + mysql_ping, + mysql_stat, + mysql_get_server_info, + mysql_get_server_version, + mysql_get_host_info, + mysql_get_proto_info, + mysql_list_dbs, + mysql_list_tables, + mysql_list_fields, + mysql_list_processes, + mysql_store_result, + mysql_use_result, + mysql_options, + mysql_free_result, + mysql_data_seek, + mysql_row_seek, + mysql_field_seek, + mysql_fetch_row, + mysql_fetch_lengths, + mysql_fetch_field, + mysql_escape_string, + mysql_real_escape_string, + mysql_debug, + mysql_debug_end, + mysql_thread_safe, + mysql_warning_count, + mysql_sqlstate, + mysql_server_init, + mysql_server_end, + mysql_thread_end, + mysql_thread_init, + mysql_set_server_option, + mysql_get_client_info, + mysql_get_client_version, + mariadb_connection, + mysql_get_server_name, + mariadb_get_charset_by_name, + mariadb_get_charset_by_nr, + mariadb_convert_string, + mysql_optionsv, + mysql_get_optionv, + mysql_get_option, + mysql_get_parameters, + mysql_hex_string, + mysql_get_socket, + mysql_get_timeout_value, + mysql_get_timeout_value_ms, + mysql_reconnect, + mysql_stmt_init, + mysql_stmt_prepare, + mysql_stmt_execute, + mysql_stmt_fetch, + mysql_stmt_fetch_column, + mysql_stmt_store_result, + mysql_stmt_param_count, + mysql_stmt_attr_set, + mysql_stmt_attr_get, + mysql_stmt_bind_param, + mysql_stmt_bind_result, + mysql_stmt_close, + mysql_stmt_reset, + mysql_stmt_free_result, + mysql_stmt_send_long_data, + mysql_stmt_result_metadata, + mysql_stmt_param_metadata, + mysql_stmt_errno, + mysql_stmt_error, + mysql_stmt_sqlstate, + mysql_stmt_row_seek, + mysql_stmt_row_tell, + mysql_stmt_data_seek, + mysql_stmt_num_rows, + mysql_stmt_affected_rows, + mysql_stmt_insert_id, + mysql_stmt_field_count, + mysql_stmt_next_result, + mysql_stmt_more_results +}; + /* * Default methods for a connection. These methods are * stored in mysql->methods and can be overwritten by @@ -3782,4 +3906,5 @@ struct st_mysql_methods MARIADB_DEFAULT_METHODS = { mthd_stmt_flush_unbuffered, /* set error */ my_set_error, + &MARIADB_API }; diff --git a/plugins/connection/aurora.c b/plugins/connection/aurora.c index 3f54dd04..76d828de 100644 --- a/plugins/connection/aurora.c +++ b/plugins/connection/aurora.c @@ -82,6 +82,8 @@ MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ = aurora_reconnect }; +struct st_mariadb_api *mariadb_api= NULL; + typedef struct st_aurora_instance { char *host; int port; @@ -258,7 +260,7 @@ int aurora_get_instance_type(MYSQL *mysql) int rc; char *query= "select variable_value from information_schema.global_variables where variable_name='INNODB_READ_ONLY' AND variable_value='OFF'"; - if (!mysql_query(mysql, query)) + if (!mariadb_api->mysql_query(mysql, query)) { MYSQL_RES *res= mysql_store_result(mysql); rc= mysql_num_rows(res) ? AURORA_PRIMARY : AURORA_REPLICA; @@ -286,7 +288,7 @@ my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora) { my_bool rc= 0; - if (!mysql_query(mysql, "select server_id from information_schema.replica_host_status " + if (!mariadb_api->mysql_query(mysql, "select server_id from information_schema.replica_host_status " "where session_id = 'MASTER_SESSION_ID'")) { MYSQL_RES *res; @@ -414,7 +416,7 @@ void aurora_copy_mysql(MYSQL *from, MYSQL *to) memset(&to->options, 0, sizeof(to->options)); to->free_me= 0; to->net.conn_hdlr= 0; - mysql_close(to); + mariadb_api->mysql_close(to); *to= *from; to->net.pvio= from->net.pvio; to->net.pvio->mysql= to; @@ -434,7 +436,7 @@ my_bool aurora_find_replica(AURORA *aurora) if (aurora->num_instances < 2) return 0; - mysql_init(&mysql); + mariadb_api->mysql_init(&mysql); mysql.options= aurora->mysql[AURORA_PRIMARY]->options; /* don't execute init_command on slave */ @@ -503,7 +505,7 @@ my_bool aurora_find_primary(AURORA *aurora) if (!aurora->num_instances) return 0; - mysql_init(&mysql); + mariadb_api->mysql_init(&mysql); mysql.options= aurora->mysql[AURORA_PRIMARY]->options; mysql.net.conn_hdlr= aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr; @@ -545,7 +547,7 @@ void aurora_close_replica(MYSQL *mysql, AURORA *aurora) { aurora->mysql[AURORA_REPLICA]->net.pvio->mysql= aurora->mysql[AURORA_REPLICA]; aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0; - mysql_close(aurora->mysql[AURORA_REPLICA]); + mariadb_api->mysql_close(aurora->mysql[AURORA_REPLICA]); aurora->pvio[AURORA_REPLICA]= 0; aurora->mysql[AURORA_REPLICA]= NULL; } @@ -560,6 +562,9 @@ MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const ch MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; my_bool is_reconnect= 0; + if (!mariadb_api) + mariadb_api= mysql->methods->api; + if ((aurora= (AURORA *)hdlr->data)) { aurora_refresh_blacklist(aurora); @@ -660,7 +665,7 @@ my_bool aurora_reconnect(MYSQL *mysql) switch (aurora->last_instance_type) { case AURORA_REPLICA: - if (!(rc= mysql_reconnect(aurora->mysql[aurora->last_instance_type]))) + if (!(rc= mariadb_api->mysql_reconnect(aurora->mysql[aurora->last_instance_type]))) aurora_switch_connection(mysql, aurora, AURORA_REPLICA); break; case AURORA_PRIMARY: @@ -692,7 +697,7 @@ void aurora_close(MYSQL *mysql) { /* we got options from primary, so don't free it twice */ memset(&aurora->mysql[AURORA_REPLICA]->options, 0, sizeof(mysql->options)); - /* connection handler wull be freed in mysql_close() */ + /* connection handler wull be freed in mariadb_api->mysql_close() */ aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0; mysql_close(aurora->mysql[AURORA_REPLICA]); @@ -781,7 +786,7 @@ int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *ar { aurora_switch_connection(mysql, aurora, AURORA_REPLICA); DISABLE_AURORA(mysql); - mysql_select_db(aurora->mysql[AURORA_REPLICA], arg); + mariadb_api->mysql_select_db(aurora->mysql[AURORA_REPLICA], arg); ENABLE_AURORA(mysql); aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); } diff --git a/plugins/connection/replication.c b/plugins/connection/replication.c index 7c5eeabf..9b4d1865 100644 --- a/plugins/connection/replication.c +++ b/plugins/connection/replication.c @@ -45,6 +45,8 @@ int repl_set_options(MYSQL *msql, enum mysql_option option, void *arg); #define MARIADB_MASTER 0 #define MARIADB_SLAVE 1 +struct st_mariadb_api *mariadb_api= NULL; + #ifndef HAVE_REPLICATION_DYNAMIC MARIADB_CONNECTION_PLUGIN connection_replication_plugin = #else @@ -179,6 +181,9 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char REPL_DATA *data= NULL; MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; + if (!mariadb_api) + mariadb_api= mysql->methods->api; + if ((data= (REPL_DATA *)hdlr->data)) { data->pvio[MARIADB_MASTER]->methods->close(data->pvio[MARIADB_MASTER]); @@ -209,12 +214,12 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char * connecting to slave(s) in background */ /* if slave connection will fail, we will not return error but use master instead */ - if (!(data->slave_mysql= mysql_init(NULL)) || + if (!(data->slave_mysql= mariadb_api->mysql_init(NULL)) || !(mysql->methods->db_connect(data->slave_mysql, data->host[MARIADB_SLAVE], user, passwd, db, data->port[MARIADB_SLAVE] ? data->port[MARIADB_SLAVE] : port, unix_socket, clientflag))) { if (data->slave_mysql) - mysql_close(data->slave_mysql); + mariadb_api->mysql_close(data->slave_mysql); data->pvio[MARIADB_SLAVE]= NULL; } else @@ -246,7 +251,7 @@ void repl_close(MYSQL *mysql) { /* restore mysql */ data->pvio[MARIADB_SLAVE]->mysql= data->slave_mysql; - mysql_close(data->slave_mysql); + mariadb_api->mysql_close(data->slave_mysql); data->pvio[MARIADB_SLAVE]= NULL; data->slave_mysql= NULL; } From 5f98f7710abfd6b6d578db919e36fc64bf9823fd Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Tue, 29 Dec 2015 20:37:18 +0100 Subject: [PATCH 19/40] Fixed mysql_api methods: On Windows functions need to be declared with STDCALL. Fixed warning in my_context.h --- include/my_context.h | 5 - include/my_stmt.h | 1 + include/mysql.h | 239 +++++++++++++++-------------- libmariadb/libmariadb.c | 17 +- plugins/connection/aurora.c | 21 +-- unittest/libmariadb/CMakeLists.txt | 2 +- unittest/libmariadb/misc.c | 4 +- 7 files changed, 140 insertions(+), 149 deletions(-) diff --git a/include/my_context.h b/include/my_context.h index 2694fd09..b66482a4 100644 --- a/include/my_context.h +++ b/include/my_context.h @@ -112,11 +112,6 @@ struct my_context { }; #endif -extern void -my_context_install_suspend_resume_hook(struct mysql_async_context *b, - void (*hook)(my_bool, void *), - void *user_data); - /* Initialize an asynchroneous context object. Returns 0 on success, non-zero on failure. diff --git a/include/my_stmt.h b/include/my_stmt.h index 77046caf..0dfb1ba1 100644 --- a/include/my_stmt.h +++ b/include/my_stmt.h @@ -165,6 +165,7 @@ struct st_mysqlnd_stmt_methods my_bool (*get_attribute)(const MYSQL_STMT * stmt, enum enum_stmt_attr_type attr_type, const void * value); my_bool (*set_attribute)(const MYSQL_STMT * stmt, enum enum_stmt_attr_type attr_type, const void * value); + void (*set_error)(MYSQL_STMT *stmt, unsigned int error_nr, const char *sqlstate, const char *format, ...); }; typedef int (*mysql_stmt_fetch_row_func)(MYSQL_STMT *stmt, unsigned char **row); diff --git a/include/mysql.h b/include/mysql.h index 473f7401..04cce7f0 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -641,125 +641,125 @@ int STDCALL mysql_stmt_send_long_data_cont(my_bool *ret, MYSQL_STMT *stmt, /* API function calls (used by dynmic plugins) */ struct st_mariadb_api { - my_ulonglong (*mysql_num_rows)(MYSQL_RES *res); - unsigned int (*mysql_num_fields)(MYSQL_RES *res); - my_bool (*mysql_eof)(MYSQL_RES *res); - MYSQL_FIELD *(*mysql_fetch_field_direct)(MYSQL_RES *res, unsigned int fieldnr); - MYSQL_FIELD * (*mysql_fetch_fields)(MYSQL_RES *res); - MYSQL_ROWS * (*mysql_row_tell)(MYSQL_RES *res); - unsigned int (*mysql_field_tell)(MYSQL_RES *res); - unsigned int (*mysql_field_count)(MYSQL *mysql); - my_bool (*mysql_more_results)(MYSQL *mysql); - int (*mysql_next_result)(MYSQL *mysql); - my_ulonglong (*mysql_affected_rows)(MYSQL *mysql); - my_bool (*mysql_autocommit)(MYSQL *mysql, my_bool mode); - my_bool (*mysql_commit)(MYSQL *mysql); - my_bool (*mysql_rollback)(MYSQL *mysql); - my_ulonglong (*mysql_insert_id)(MYSQL *mysql); - unsigned int (*mysql_errno)(MYSQL *mysql); - char * (*mysql_error)(MYSQL *mysql); - char * (*mysql_info)(MYSQL *mysql); - unsigned long (*mysql_thread_id)(MYSQL *mysql); - const char * (*mysql_character_set_name)(MYSQL *mysql); - void (*mysql_get_character_set_info)(MYSQL *mysql, MY_CHARSET_INFO *cs); - int (*mysql_set_character_set)(MYSQL *mysql, const char *csname); - my_bool (*mariadb_get_infov)(MYSQL *mysql, enum mariadb_value value, void *arg, ...); - my_bool (*mariadb_get_info)(MYSQL *mysql, enum mariadb_value value, void *arg); - MYSQL * (*mysql_init)(MYSQL *mysql); - int (*mysql_ssl_set)(MYSQL *mysql, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher); - const char * (*mysql_get_ssl_cipher)(MYSQL *mysql); - MYSQL * (*mysql_connect)(MYSQL *mysql, const char *host, const char *user, const char *passwd); - my_bool (*mysql_change_user)(MYSQL *mysql, const char *user, const char *passwd, const char *db); - MYSQL * (*mysql_real_connect)(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag); - void (*mysql_close)(MYSQL *sock); - int (*mysql_select_db)(MYSQL *mysql, const char *db); - int (*mysql_query)(MYSQL *mysql, const char *q); - int (*mysql_send_query)(MYSQL *mysql, const char *q, size_t length); - my_bool (*mysql_read_query_result)(MYSQL *mysql); - int (*mysql_real_query)(MYSQL *mysql, const char *q, size_t length); - int (*mysql_create_db)(MYSQL *mysql, const char *DB); - int (*mysql_drop_db)(MYSQL *mysql, const char *DB); - int (*mysql_shutdown)(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level); - int (*mysql_dump_debug_info)(MYSQL *mysql); - int (*mysql_refresh)(MYSQL *mysql, unsigned int refresh_options); - int (*mysql_kill)(MYSQL *mysql,unsigned long pid); - int (*mysql_ping)(MYSQL *mysql); - char * (*mysql_stat)(MYSQL *mysql); - char * (*mysql_get_server_info)(MYSQL *mysql); - unsigned long (*mysql_get_server_version)(MYSQL *mysql); - char * (*mysql_get_host_info)(MYSQL *mysql); - unsigned int (*mysql_get_proto_info)(MYSQL *mysql); - MYSQL_RES * (*mysql_list_dbs)(MYSQL *mysql,const char *wild); - MYSQL_RES * (*mysql_list_tables)(MYSQL *mysql,const char *wild); - MYSQL_RES * (*mysql_list_fields)(MYSQL *mysql, const char *table, const char *wild); - MYSQL_RES * (*mysql_list_processes)(MYSQL *mysql); - MYSQL_RES * (*mysql_store_result)(MYSQL *mysql); - MYSQL_RES * (*mysql_use_result)(MYSQL *mysql); - int (*mysql_options)(MYSQL *mysql,enum mysql_option option, const void *arg); - void (*mysql_free_result)(MYSQL_RES *result); - void (*mysql_data_seek)(MYSQL_RES *result, my_ulonglong offset); - MYSQL_ROW_OFFSET (*mysql_row_seek)(MYSQL_RES *result, MYSQL_ROW_OFFSET); - MYSQL_FIELD_OFFSET (*mysql_field_seek)(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset); - MYSQL_ROW (*mysql_fetch_row)(MYSQL_RES *result); - unsigned long * (*mysql_fetch_lengths)(MYSQL_RES *result); - MYSQL_FIELD * (*mysql_fetch_field)(MYSQL_RES *result); - unsigned long (*mysql_escape_string)(char *to,const char *from, unsigned long from_length); - unsigned long (*mysql_real_escape_string)(MYSQL *mysql, char *to,const char *from, unsigned long length); - void (*mysql_debug)(const char *debug); - void (*mysql_debug_end)(void); - unsigned int (*mysql_thread_safe)(void); - unsigned int (*mysql_warning_count)(MYSQL *mysql); - const char * (*mysql_sqlstate)(MYSQL *mysql); - int (*mysql_server_init)(int argc, char **argv, char **groups); - void (*mysql_server_end)(void); - void (*mysql_thread_end)(void); - my_bool (*mysql_thread_init)(void); - int (*mysql_set_server_option)(MYSQL *mysql, enum enum_mysql_set_option option); - const char * (*mysql_get_client_info)(void); - unsigned long (*mysql_get_client_version)(void); - my_bool (*mariadb_connection)(MYSQL *mysql); - const char * (*mysql_get_server_name)(MYSQL *mysql); - CHARSET_INFO * (*mariadb_get_charset_by_name)(const char *csname); - CHARSET_INFO * (*mariadb_get_charset_by_nr)(unsigned int csnr); - size_t (*mariadb_convert_string)(const char *from, size_t *from_len, CHARSET_INFO *from_cs, char *to, size_t *to_len, CHARSET_INFO *to_cs, int *errorcode); - int (*mysql_optionsv)(MYSQL *mysql,enum mysql_option option, ...); - int (*mysql_get_optionv)(MYSQL *mysql, enum mysql_option option, void *arg, ...); - int (*mysql_get_option)(MYSQL *mysql, enum mysql_option option, void *arg); - MYSQL_PARAMETERS *(*mysql_get_parameters)(void); - unsigned long (*mysql_hex_string)(char *to, const char *from, size_t len); - my_socket (*mysql_get_socket)(MYSQL *mysql); - unsigned int (*mysql_get_timeout_value)(const MYSQL *mysql); - unsigned int (*mysql_get_timeout_value_ms)(const MYSQL *mysql); - my_bool (*mysql_reconnect)(MYSQL *mysql); - MYSQL_STMT * (*mysql_stmt_init)(MYSQL *mysql); - int (*mysql_stmt_prepare)(MYSQL_STMT *stmt, const char *query, size_t length); - int (*mysql_stmt_execute)(MYSQL_STMT *stmt); - int (*mysql_stmt_fetch)(MYSQL_STMT *stmt); - int (*mysql_stmt_fetch_column)(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg, unsigned int column, unsigned long offset); - int (*mysql_stmt_store_result)(MYSQL_STMT *stmt); - unsigned long (*mysql_stmt_param_count)(MYSQL_STMT * stmt); - my_bool (*mysql_stmt_attr_set)(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, const void *attr); - my_bool (*mysql_stmt_attr_get)(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, void *attr); - my_bool (*mysql_stmt_bind_param)(MYSQL_STMT * stmt, MYSQL_BIND * bnd); - my_bool (*mysql_stmt_bind_result)(MYSQL_STMT * stmt, MYSQL_BIND * bnd); - my_bool (*mysql_stmt_close)(MYSQL_STMT * stmt); - my_bool (*mysql_stmt_reset)(MYSQL_STMT * stmt); - my_bool (*mysql_stmt_free_result)(MYSQL_STMT *stmt); - my_bool (*mysql_stmt_send_long_data)(MYSQL_STMT *stmt, unsigned int param_number, const char *data, size_t length); - MYSQL_RES *(*mysql_stmt_result_metadata)(MYSQL_STMT *stmt); - MYSQL_RES *(*mysql_stmt_param_metadata)(MYSQL_STMT *stmt); - unsigned int (*mysql_stmt_errno)(MYSQL_STMT * stmt); - const char *(*mysql_stmt_error)(MYSQL_STMT * stmt); - const char *(*mysql_stmt_sqlstate)(MYSQL_STMT * stmt); - MYSQL_ROW_OFFSET (*mysql_stmt_row_seek)(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET offset); - MYSQL_ROW_OFFSET (*mysql_stmt_row_tell)(MYSQL_STMT *stmt); - void (*mysql_stmt_data_seek)(MYSQL_STMT *stmt, my_ulonglong offset); - my_ulonglong (*mysql_stmt_num_rows)(MYSQL_STMT *stmt); - my_ulonglong (*mysql_stmt_affected_rows)(MYSQL_STMT *stmt); - my_ulonglong (*mysql_stmt_insert_id)(MYSQL_STMT *stmt); - unsigned int (*mysql_stmt_field_count)(MYSQL_STMT *stmt); - int (*mysql_stmt_next_result)(MYSQL_STMT *stmt); - my_bool (*mysql_stmt_more_results)(MYSQL_STMT *stmt); + my_ulonglong (STDCALL *mysql_num_rows)(MYSQL_RES *res); + unsigned int (STDCALL *mysql_num_fields)(MYSQL_RES *res); + my_bool (STDCALL *mysql_eof)(MYSQL_RES *res); + MYSQL_FIELD *(STDCALL *mysql_fetch_field_direct)(MYSQL_RES *res, unsigned int fieldnr); + MYSQL_FIELD * (STDCALL *mysql_fetch_fields)(MYSQL_RES *res); + MYSQL_ROWS * (STDCALL *mysql_row_tell)(MYSQL_RES *res); + unsigned int (STDCALL *mysql_field_tell)(MYSQL_RES *res); + unsigned int (STDCALL *mysql_field_count)(MYSQL *mysql); + my_bool (STDCALL *mysql_more_results)(MYSQL *mysql); + int (STDCALL *mysql_next_result)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_affected_rows)(MYSQL *mysql); + my_bool (STDCALL *mysql_autocommit)(MYSQL *mysql, my_bool mode); + my_bool (STDCALL *mysql_commit)(MYSQL *mysql); + my_bool (STDCALL *mysql_rollback)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_insert_id)(MYSQL *mysql); + unsigned int (STDCALL *mysql_errno)(MYSQL *mysql); + char * (STDCALL *mysql_error)(MYSQL *mysql); + char * (STDCALL *mysql_info)(MYSQL *mysql); + unsigned long (STDCALL *mysql_thread_id)(MYSQL *mysql); + const char * (STDCALL *mysql_character_set_name)(MYSQL *mysql); + void (STDCALL *mysql_get_character_set_info)(MYSQL *mysql, MY_CHARSET_INFO *cs); + int (STDCALL *mysql_set_character_set)(MYSQL *mysql, const char *csname); + my_bool (STDCALL *mariadb_get_infov)(MYSQL *mysql, enum mariadb_value value, void *arg, ...); + my_bool (STDCALL *mariadb_get_info)(MYSQL *mysql, enum mariadb_value value, void *arg); + MYSQL * (STDCALL *mysql_init)(MYSQL *mysql); + int (STDCALL *mysql_ssl_set)(MYSQL *mysql, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher); + const char * (STDCALL *mysql_get_ssl_cipher)(MYSQL *mysql); + MYSQL * (STDCALL *mysql_connect)(MYSQL *mysql, const char *host, const char *user, const char *passwd); + my_bool (STDCALL *mysql_change_user)(MYSQL *mysql, const char *user, const char *passwd, const char *db); + MYSQL * (STDCALL *mysql_real_connect)(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag); + void (STDCALL *mysql_close)(MYSQL *sock); + int (STDCALL *mysql_select_db)(MYSQL *mysql, const char *db); + int (STDCALL *mysql_query)(MYSQL *mysql, const char *q); + int (STDCALL *mysql_send_query)(MYSQL *mysql, const char *q, size_t length); + my_bool (STDCALL *mysql_read_query_result)(MYSQL *mysql); + int (STDCALL *mysql_real_query)(MYSQL *mysql, const char *q, size_t length); + int (STDCALL *mysql_create_db)(MYSQL *mysql, const char *DB); + int (STDCALL *mysql_drop_db)(MYSQL *mysql, const char *DB); + int (STDCALL *mysql_shutdown)(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level); + int (STDCALL *mysql_dump_debug_info)(MYSQL *mysql); + int (STDCALL *mysql_refresh)(MYSQL *mysql, unsigned int refresh_options); + int (STDCALL *mysql_kill)(MYSQL *mysql,unsigned long pid); + int (STDCALL *mysql_ping)(MYSQL *mysql); + char * (STDCALL *mysql_stat)(MYSQL *mysql); + char * (STDCALL *mysql_get_server_info)(MYSQL *mysql); + unsigned long (STDCALL *mysql_get_server_version)(MYSQL *mysql); + char * (STDCALL *mysql_get_host_info)(MYSQL *mysql); + unsigned int (STDCALL *mysql_get_proto_info)(MYSQL *mysql); + MYSQL_RES * (STDCALL *mysql_list_dbs)(MYSQL *mysql,const char *wild); + MYSQL_RES * (STDCALL *mysql_list_tables)(MYSQL *mysql,const char *wild); + MYSQL_RES * (STDCALL *mysql_list_fields)(MYSQL *mysql, const char *table, const char *wild); + MYSQL_RES * (STDCALL *mysql_list_processes)(MYSQL *mysql); + MYSQL_RES * (STDCALL *mysql_store_result)(MYSQL *mysql); + MYSQL_RES * (STDCALL *mysql_use_result)(MYSQL *mysql); + int (STDCALL *mysql_options)(MYSQL *mysql,enum mysql_option option, const void *arg); + void (STDCALL *mysql_free_result)(MYSQL_RES *result); + void (STDCALL *mysql_data_seek)(MYSQL_RES *result, my_ulonglong offset); + MYSQL_ROW_OFFSET (STDCALL *mysql_row_seek)(MYSQL_RES *result, MYSQL_ROW_OFFSET); + MYSQL_FIELD_OFFSET (STDCALL *mysql_field_seek)(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset); + MYSQL_ROW (STDCALL *mysql_fetch_row)(MYSQL_RES *result); + unsigned long * (STDCALL *mysql_fetch_lengths)(MYSQL_RES *result); + MYSQL_FIELD * (STDCALL *mysql_fetch_field)(MYSQL_RES *result); + unsigned long (STDCALL *mysql_escape_string)(char *to,const char *from, unsigned long from_length); + unsigned long (STDCALL *mysql_real_escape_string)(MYSQL *mysql, char *to,const char *from, unsigned long length); + void (STDCALL *mysql_debug)(const char *debug); + void (STDCALL *mysql_debug_end)(void); + unsigned int (STDCALL *mysql_thread_safe)(void); + unsigned int (STDCALL *mysql_warning_count)(MYSQL *mysql); + const char * (STDCALL *mysql_sqlstate)(MYSQL *mysql); + int (STDCALL *mysql_server_init)(int argc, char **argv, char **groups); + void (STDCALL *mysql_server_end)(void); + void (STDCALL *mysql_thread_end)(void); + my_bool (STDCALL *mysql_thread_init)(void); + int (STDCALL *mysql_set_server_option)(MYSQL *mysql, enum enum_mysql_set_option option); + const char * (STDCALL *mysql_get_client_info)(void); + unsigned long (STDCALL *mysql_get_client_version)(void); + my_bool (STDCALL *mariadb_connection)(MYSQL *mysql); + const char * (STDCALL *mysql_get_server_name)(MYSQL *mysql); + CHARSET_INFO * (STDCALL *mariadb_get_charset_by_name)(const char *csname); + CHARSET_INFO * (STDCALL *mariadb_get_charset_by_nr)(unsigned int csnr); + size_t (STDCALL *mariadb_convert_string)(const char *from, size_t *from_len, CHARSET_INFO *from_cs, char *to, size_t *to_len, CHARSET_INFO *to_cs, int *errorcode); + int (STDCALL *mysql_optionsv)(MYSQL *mysql,enum mysql_option option, ...); + int (STDCALL *mysql_get_optionv)(MYSQL *mysql, enum mysql_option option, void *arg, ...); + int (STDCALL *mysql_get_option)(MYSQL *mysql, enum mysql_option option, void *arg); + MYSQL_PARAMETERS *(STDCALL *mysql_get_parameters)(void); + unsigned long (STDCALL *mysql_hex_string)(char *to, const char *from, size_t len); + my_socket (STDCALL *mysql_get_socket)(MYSQL *mysql); + unsigned int (STDCALL *mysql_get_timeout_value)(const MYSQL *mysql); + unsigned int (STDCALL *mysql_get_timeout_value_ms)(const MYSQL *mysql); + my_bool (STDCALL *mysql_reconnect)(MYSQL *mysql); + MYSQL_STMT * (STDCALL *mysql_stmt_init)(MYSQL *mysql); + int (STDCALL *mysql_stmt_prepare)(MYSQL_STMT *stmt, const char *query, size_t length); + int (STDCALL *mysql_stmt_execute)(MYSQL_STMT *stmt); + int (STDCALL *mysql_stmt_fetch)(MYSQL_STMT *stmt); + int (STDCALL *mysql_stmt_fetch_column)(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg, unsigned int column, unsigned long offset); + int (STDCALL *mysql_stmt_store_result)(MYSQL_STMT *stmt); + unsigned long (STDCALL *mysql_stmt_param_count)(MYSQL_STMT * stmt); + my_bool (STDCALL *mysql_stmt_attr_set)(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, const void *attr); + my_bool (STDCALL *mysql_stmt_attr_get)(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, void *attr); + my_bool (STDCALL *mysql_stmt_bind_param)(MYSQL_STMT * stmt, MYSQL_BIND * bnd); + my_bool (STDCALL *mysql_stmt_bind_result)(MYSQL_STMT * stmt, MYSQL_BIND * bnd); + my_bool (STDCALL *mysql_stmt_close)(MYSQL_STMT * stmt); + my_bool (STDCALL *mysql_stmt_reset)(MYSQL_STMT * stmt); + my_bool (STDCALL *mysql_stmt_free_result)(MYSQL_STMT *stmt); + my_bool (STDCALL *mysql_stmt_send_long_data)(MYSQL_STMT *stmt, unsigned int param_number, const char *data, size_t length); + MYSQL_RES *(STDCALL *mysql_stmt_result_metadata)(MYSQL_STMT *stmt); + MYSQL_RES *(STDCALL *mysql_stmt_param_metadata)(MYSQL_STMT *stmt); + unsigned int (STDCALL *mysql_stmt_errno)(MYSQL_STMT * stmt); + const char *(STDCALL *mysql_stmt_error)(MYSQL_STMT * stmt); + const char *(STDCALL *mysql_stmt_sqlstate)(MYSQL_STMT * stmt); + MYSQL_ROW_OFFSET (STDCALL *mysql_stmt_row_seek)(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET offset); + MYSQL_ROW_OFFSET (STDCALL *mysql_stmt_row_tell)(MYSQL_STMT *stmt); + void (STDCALL *mysql_stmt_data_seek)(MYSQL_STMT *stmt, my_ulonglong offset); + my_ulonglong (STDCALL *mysql_stmt_num_rows)(MYSQL_STMT *stmt); + my_ulonglong (STDCALL *mysql_stmt_affected_rows)(MYSQL_STMT *stmt); + my_ulonglong (STDCALL *mysql_stmt_insert_id)(MYSQL_STMT *stmt); + unsigned int (STDCALL *mysql_stmt_field_count)(MYSQL_STMT *stmt); + int (STDCALL *mysql_stmt_next_result)(MYSQL_STMT *stmt); + my_bool (STDCALL *mysql_stmt_more_results)(MYSQL_STMT *stmt); }; /* these methods can be overwritten by db plugins */ @@ -784,6 +784,7 @@ struct st_mysql_methods { int (*db_stmt_fetch_to_bind)(MYSQL_STMT *stmt, unsigned char *row); void (*db_stmt_flush_unbuffered)(MYSQL_STMT *stmt); void (*set_error)(MYSQL *mysql, unsigned int error_nr, const char *sqlstate, const char *format, ...); + void (*invalidate_stmts)(MYSQL *mysql, const char *function_name); struct st_mariadb_api *api; }; diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index bb976041..7086831b 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -519,7 +519,7 @@ append_wild(char *to, char *end, const char *wild) /************************************************************************** ** Init debugging if MYSQL_DEBUG environment variable is found **************************************************************************/ -void STDCALL mysql_debug_end() +void STDCALL mysql_debug_end(void) { #ifndef DBUG_OFF DEBUGGER_OFF; @@ -1806,8 +1806,7 @@ my_bool STDCALL mysql_reconnect(MYSQL *mysql) DBUG_RETURN(0); } - -static void ma_invalidate_stmts(MYSQL *mysql, const char *function_name) +void ma_invalidate_stmts(MYSQL *mysql, const char *function_name) { if (mysql->stmts) { @@ -3352,7 +3351,7 @@ static void mariadb_get_charset_info(MYSQL *mysql, MY_CHARSET_INFO *cs) void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *cs) { - return mariadb_get_charset_info(mysql, cs); + mariadb_get_charset_info(mysql, cs); } int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname) @@ -3451,7 +3450,7 @@ void STDCALL mysql_server_end() my_init_done= 0; } -my_bool STDCALL mysql_thread_init() +my_bool STDCALL mysql_thread_init(void) { #ifdef THREAD return my_thread_init(); @@ -3459,7 +3458,7 @@ my_bool STDCALL mysql_thread_init() return 0; } -void STDCALL mysql_thread_end() +void STDCALL mysql_thread_end(void) { #ifdef THREAD my_thread_end(); @@ -3743,8 +3742,10 @@ my_bool STDCALL mariadb_get_info(MYSQL *mysql, enum mariadb_value value, void *a return mariadb_get_infov(mysql, value, arg); } +#undef STDCALL /* API functions for usage in dynamic plugins */ -struct st_mariadb_api MARIADB_API= { +struct st_mariadb_api MARIADB_API= +{ mysql_num_rows, mysql_num_fields, mysql_eof, @@ -3906,5 +3907,7 @@ struct st_mysql_methods MARIADB_DEFAULT_METHODS = { mthd_stmt_flush_unbuffered, /* set error */ my_set_error, + /* invalidate statements */ + ma_invalidate_stmts, &MARIADB_API }; diff --git a/plugins/connection/aurora.c b/plugins/connection/aurora.c index 76d828de..524f4364 100644 --- a/plugins/connection/aurora.c +++ b/plugins/connection/aurora.c @@ -60,7 +60,7 @@ my_bool aurora_reconnect(MYSQL *mysql); #define DISABLE_AURORA(mysql)\ (mysql)->net.conn_hdlr->active= 0; -#ifndef HAVE_REPLICATION_DYNAMIC +#ifndef HAVE_AURORA_DYNAMIC MARIADB_CONNECTION_PLUGIN connection_aurora_plugin = #else MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ = @@ -394,18 +394,8 @@ MYSQL *aurora_connect_instance(AURORA *aurora, AURORA_INSTANCE *instance, MYSQL /* {{{ void aurora_copy_mysql() */ void aurora_copy_mysql(MYSQL *from, MYSQL *to) { - LIST *li_stmt= to->stmts; - - for (;li_stmt;li_stmt= li_stmt->next) - { - MYSQL_STMT *stmt= (MYSQL_STMT *)li_stmt->data; - - if (stmt->state != MYSQL_STMT_INITTED) - { - stmt->state= MYSQL_STMT_INITTED; - SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0); - } - } + /* invalidate statements */ + to->methods->invalidate_stmts(to, "aurora connect/reconnect"); from->free_me= to->free_me; from->reconnect= to->reconnect; @@ -431,7 +421,6 @@ my_bool aurora_find_replica(AURORA *aurora) my_bool replica_found= 0; AURORA_INSTANCE *instance[AURORA_MAX_INSTANCES]; MYSQL mysql; -// struct st_dynamic_array *init_command= aurora->mysql[AURORA_PRIMARY]->options.init_command; if (aurora->num_instances < 2) return 0; @@ -565,6 +554,8 @@ MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const ch if (!mariadb_api) mariadb_api= mysql->methods->api; + mariadb_api->mariadb_get_info(mysql, MARIADB_CLIENT_ERRORS, &client_errors); + if ((aurora= (AURORA *)hdlr->data)) { aurora_refresh_blacklist(aurora); @@ -577,7 +568,7 @@ MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const ch } else { - if (!(aurora= (AURORA *)my_malloc(sizeof(AURORA), MYF(MY_ZEROFILL)))) + if (!(aurora= (AURORA *)calloc(1, sizeof(AURORA)))) { mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); return NULL; diff --git a/unittest/libmariadb/CMakeLists.txt b/unittest/libmariadb/CMakeLists.txt index f2976b38..7d1c0be4 100644 --- a/unittest/libmariadb/CMakeLists.txt +++ b/unittest/libmariadb/CMakeLists.txt @@ -57,7 +57,7 @@ IF(WITH_SSL) ENDIF() FOREACH(API_TEST ${API_TESTS}) - ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c) + ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c ${CMAKE_SOURCE_DIR}/libmariadb/getopt.c) TARGET_LINK_LIBRARIES(${API_TEST} mytap libmariadb) ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST}) SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 120) diff --git a/unittest/libmariadb/misc.c b/unittest/libmariadb/misc.c index fcb6a14c..1dd9f478 100644 --- a/unittest/libmariadb/misc.c +++ b/unittest/libmariadb/misc.c @@ -266,7 +266,7 @@ static int test_frm_bug(MYSQL *mysql) sprintf(test_frm, "%s/%s/test_frm_bug.frm", data_dir, schema); - if (!(test_file= my_fopen(test_frm, (int) (O_RDWR | O_CREAT), MYF(MY_WME)))) + if (!(test_file= fopen(test_frm, "rw"))) { mysql_stmt_close(stmt); diag("Can't write to file %s -> SKIP", test_frm); @@ -294,7 +294,7 @@ static int test_frm_bug(MYSQL *mysql) mysql_free_result(result); mysql_stmt_close(stmt); - my_fclose(test_file, MYF(0)); + fclose(test_file); mysql_query(mysql, "drop table if exists test_frm_bug"); return OK; } From 97a6aeafff71e85f6e72954bf42ac24d57f98975 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Sun, 3 Jan 2016 17:29:44 +0100 Subject: [PATCH 20/40] - Fixed build errors for remote_io plugin - Bumped client version number to 10.1.7 --- CMakeLists.txt | 32 +++++++++++++++++++---------- cmake/FindIconv.cmake | 2 +- cmake/plugins.cmake | 3 ++- include/errmsg.h | 1 + include/mysql/client_plugin.h | 4 ++-- libmariadb/CMakeLists.txt | 2 +- libmariadb/errmsg.c | 1 + libmariadb/libmariadb.c | 2 +- mariadb_config/CMakeLists.txt | 38 ++++++++++++++++++++--------------- plugins/io/CMakeLists.txt | 1 + plugins/io/remote_io.c | 10 ++++----- 11 files changed, 57 insertions(+), 39 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b8e45c18..051e2bbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ IF(CMAKE_VERSION VERSION_GREATER "2.9.9") CMAKE_POLICY(SET CMP0045 OLD) ENDIF() -SET(MARIADB_CONNECTOR_C_COPYRIGHT "2013-2015 MariaDB Corporation Ab") +SET(MARIADB_CONNECTOR_C_COPYRIGHT "2013-2016 MariaDB Corporation Ab") ### Options ### IF(NOT WIN32) @@ -37,7 +37,6 @@ ELSE() OPTION(WITH_SIGNCODE "digitally sign files" OFF) OPTION(WITH_RTC "enables run time checks for debug builds" OFF) ENDIF() -OPTION(WITH_REMOTEIO "enables remote io support (requires libcurl)" OFF) OPTION(WITH_EXTERNAL_ZLIB "Enables use of external zlib" OFF) ############### @@ -53,6 +52,11 @@ IF(WITH_RTC) SET(RTC_OPTIONS "/RTC1 /RTCc") ENDIF() +INCLUDE(FindCURL) +IF(CURL_FOUND) + ADD_DEFINITIONS(-DHAVE_CURL=1) +ENDIF() + INCLUDE(${CMAKE_SOURCE_DIR}/cmake/plugins.cmake) IF(WIN32) @@ -101,9 +105,9 @@ ENDIF() # various defines for generating include/mysql_version.h SET(PROTOCOL_VERSION 10) # we adapted new password option from PHP's mysqlnd ! -SET(MYSQL_CLIENT_VERSION_MAJOR "5") -SET(MYSQL_CLIENT_VERSION_MINOR "5") -SET(MYSQL_CLIENT_VERSION_PATCH "2") +SET(MYSQL_CLIENT_VERSION_MAJOR "10") +SET(MYSQL_CLIENT_VERSION_MINOR "1") +SET(MYSQL_CLIENT_VERSION_PATCH "7") SET(MYSQL_CLIENT_VERSION "${MYSQL_CLIENT_VERSION_MAJOR}.${MYSQL_CLIENT_VERSION_MINOR}.${MYSQL_CLIENT_VERSION_PATCH}") MATH(EXPR MYSQL_VERSION_ID "${MYSQL_CLIENT_VERSION_MAJOR} * 10000 + ${MYSQL_CLIENT_VERSION_MINOR} * 100 + @@ -133,17 +137,15 @@ ENDIF() IF(UNIX) - SEARCH_LIBRARY(LIBNSL inet_ntoa "nsl_r;nsl") - SEARCH_LIBRARY(LIBBIND bind "bind;socket") - SEARCH_LIBRARY(LIBSOCKET setsockopt "socket") SEARCH_LIBRARY(LIBDL dlopen "dl") SEARCH_LIBRARY(LIBM floor m) - # SEARCH_LIBRARY(LIBICONV iconv iconv) SEARCH_LIBRARY(LIBPTHREAD pthread_getspecific "pthread;pthreads") - SET(EXTRA_LIBS "${LIBNSL}" "${LIBBIND}" "${LIBSOCKET}") FIND_PACKAGE(Threads) SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${LIBNSL} ${LIBBIND} ${LIBICONV} ${LIBSOCKET} ${LIBDL} ${LIBM} ${LIBPTHREAD}) + SET(SYSTEM_LIBS ${LIBNSL} ${LIBBIND} ${LIBICONV} + ${LIBSOCKET} ${LIBDL} ${LIBM} ${LIBPTHREAD}) + MESSAGE(STATUS "SYSTEM_LIBS ${SYSTEM_LIBS}") #remove possible dups from required libraries LIST(LENGTH CMAKE_REQUIRED_LIBRARIES rllength) IF(${rllength} GREATER 0) @@ -178,7 +180,7 @@ INCLUDE(${CMAKE_SOURCE_DIR}/cmake/CheckFunctions.cmake) # check for various types INCLUDE(${CMAKE_SOURCE_DIR}/cmake/CheckTypes.cmake) -IF(NOT WITH_SSL) +IF(NOT WITH_SSL AND NOT WITH_SSL STREQUAL "OFF") IF(WIN32) SET(WITH_SSL "SCHANNEL") ELSE() @@ -245,7 +247,15 @@ ENDIF() IF(WITH_SSL) SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${SSL_LIBRARIES}) ENDIF() +MARK_AS_ADVANCED(SYSTEM_LIBS) +IF(NOT REMOTEIO_PLUGIN_TYPE MATCHES "OFF") + INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIRS}) + IF(REMOTEIO_PLUGIN_TYPE MATCHES "STATIC") + SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${CURL_LIBRARIES}) + ENDIF() + ADD_DEFINITIONS("-DHAVE_REMOTEIO=1") +ENDIF() ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(libmariadb) ADD_SUBDIRECTORY(plugins) diff --git a/cmake/FindIconv.cmake b/cmake/FindIconv.cmake index f0768f71..e99a3b2f 100644 --- a/cmake/FindIconv.cmake +++ b/cmake/FindIconv.cmake @@ -15,7 +15,7 @@ ELSE() ENDIF() IF(APPLE) - find_library(ICONV_LIBRARIES NAMES iconv libiconv c PATHS + find_library(ICONV_LIBRARIES NAMES iconv libiconv PATHS /opt/local/lib/ /usr/lib/ NO_CMAKE_SYSTEM_PATH) diff --git a/cmake/plugins.cmake b/cmake/plugins.cmake index a68bd509..2ccac127 100644 --- a/cmake/plugins.cmake +++ b/cmake/plugins.cmake @@ -2,7 +2,7 @@ MACRO(REGISTER_PLUGIN name source struct type target allow) SET(PLUGIN_TYPE ${${name}}) - IF(NOT PLUGIN_TYPE STREQUAL "OFF") + IF(NOT PLUGIN_TYPE STREQUAL "OFF" AND NOT PLUGIN_TYPE) SET(PLUGIN_TYPE ${type}) ENDIF() IF(PLUGINS) @@ -18,6 +18,7 @@ MACRO(REGISTER_PLUGIN name source struct type target allow) SET(${name}_PLUGIN_SOURCE ${source}) SET(${name}_PLUGIN_CHG ${allow}) SET(PLUGINS ${PLUGINS} "${name}") + ADD_DEFINITIONS(-DHAVE_${name}=1) ENDMACRO() MARK_AS_ADVANCED(PLUGINS) diff --git a/include/errmsg.h b/include/errmsg.h index 6306ab96..0af17b20 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -85,6 +85,7 @@ extern const char *mariadb_client_errors[]; /* Error messages */ #define CR_EVENT_CREATE_FAILED 5000 #define CR_BIND_ADDR_FAILED 5001 #define CR_ASYNC_NOT_SUPPORTED 5002 +#define CR_FUNCTION_NOT_SUPPORTED 5003 #define SQLSTATE_UNKNOWN "HY000" diff --git a/include/mysql/client_plugin.h b/include/mysql/client_plugin.h index 616de69e..977ef2c4 100644 --- a/include/mysql/client_plugin.h +++ b/include/mysql/client_plugin.h @@ -151,11 +151,11 @@ typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql, #include /* Remote IO plugin */ -struct st_mysql_client_plugin_REMOTEIO +typedef struct st_mysql_client_plugin_REMOTEIO { MYSQL_CLIENT_PLUGIN_HEADER struct st_rio_methods *methods; -}; +} MARIADB_REMOTEIO_PLUGIN; #endif /******** using plugins ************/ diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index 51b683f7..93dadff3 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -402,7 +402,7 @@ ENDIF() ADD_LIBRARY(mariadbclient STATIC ${ariadbclient_RC} $ ${EMPTY_FILE} ${EXPORT_LINK}) TARGET_LINK_LIBRARIES(mariadbclient ${SYSTEM_LIBS}) - +MESSAGE(STATUS "SYSLIBS: ${SYSTEM_LIBS}") ADD_LIBRARY(libmariadb SHARED ${libmariadb_RC} $ ${EMPTY_FILE} ${EXPORT_LINK}) TARGET_LINK_LIBRARIES(libmariadb ${SYSTEM_LIBS}) IF(UNIX) diff --git a/libmariadb/errmsg.c b/libmariadb/errmsg.c index a2d6fbb3..936db98e 100644 --- a/libmariadb/errmsg.c +++ b/libmariadb/errmsg.c @@ -150,6 +150,7 @@ const char *mariadb_client_errors[] = /* 5000 */ "Creating an event failed (Errorcode: %d)", /* 5001 */ "Bind to local interface '-.%64s' failed (Errorcode: %d)", /* 5002 */ "Connection type doesn't support asynchronous IO operations", + /* 5003 */ "Server doesn't support function '%s'", "" }; diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 7086831b..d5dae214 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -3691,7 +3691,7 @@ my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void * goto error; break; case MARIADB_CONNECTION_PVIO_TYPE: - if (mysql && !mysql->net.pvio) + if (mysql && mysql->net.pvio) *((unsigned int *)arg)= (unsigned int)mysql->net.pvio->type; else goto error; diff --git a/mariadb_config/CMakeLists.txt b/mariadb_config/CMakeLists.txt index 69d7c3ac..4c8d973d 100644 --- a/mariadb_config/CMakeLists.txt +++ b/mariadb_config/CMakeLists.txt @@ -1,27 +1,33 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) -# Figure out additional libraries for use with +# Figure out additional libraries for use with -FOREACH (dep ${libmariadb_LIB_DEPENDS}) - STRING(REGEX MATCH "^-l.*$" out "${dep}") - IF(out) - SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} ${dep}") - ENDIF(out) -ENDFOREACH(dep) +FUNCTION(GET_LIB_NAME LIB_NAME LIB_OUT) + STRING(FIND ${LIB_NAME} ".so" IS_SO) + IF(NOT ${IS_SO} STREQUAL "-1") + GET_FILENAME_COMPONENT(LIB_FILE ${LIB_NAME} NAME_WE) + ELSE() + SET(LIB_FILE ${LIB_NAME}) + ENDIF() + SET(LIB_FILE "-l${LIB_FILE}") + STRING(REPLACE "-llib" "-l" LIB_FILE ${LIB_FILE}) + SET(${LIB_OUT} ${LIB_FILE} PARENT_SCOPE) +ENDFUNCTION() + +LIST(LENGTH SYSTEM_LIBS rllength) +IF(${rllength} GREATER 0) + LIST(REMOVE_DUPLICATES SYSTEM_LIBS) +ENDIF() + +FOREACH (LIB_NAME ${SYSTEM_LIBS}) + GET_LIB_NAME(${LIB_NAME} LIB_OUT) + SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} ${LIB_OUT}") +ENDFOREACH() IF(UNIX) - IF(OPENSSL_LIBRARIES) - SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} -lssl") - ENDIF() IF(ICONV_EXTERNAL) SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} ${ICONV_LIBRARIES}") ENDIF() - FOREACH(lib ${EXTRA_LIBS}) - SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} -l${lib}") - ENDFOREACH() - IF(WITH_SQLITE) - SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} -lsqlite") - ENDIF() ENDIF(UNIX) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/mariadb_config.c.in diff --git a/plugins/io/CMakeLists.txt b/plugins/io/CMakeLists.txt index 2d3d61b8..44850b49 100644 --- a/plugins/io/CMakeLists.txt +++ b/plugins/io/CMakeLists.txt @@ -17,6 +17,7 @@ IF(REMOTEIO_PLUGIN_TYPE MATCHES "DYNAMIC") # remote file plugin INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR}) SET(REMOTE_IO_SOURCES ${remote_io_RC} remote_io.c) + ADD_DEFINITIONS(-DHAVE_REMOTEIO_DYNAMIC=1) ADD_LIBRARY(remote_io SHARED ${REMOTE_IO_SOURCES} ${CMAKE_SOURCE_DIR}/plugins/plugin.def) TARGET_LINK_LIBRARIES(remote_io ${CURL_LIBRARIES}) SET_TARGET_PROPERTIES(remote_io PROPERTIES PREFIX "") diff --git a/plugins/io/remote_io.c b/plugins/io/remote_io.c index dd9be58d..f3af31e8 100644 --- a/plugins/io/remote_io.c +++ b/plugins/io/remote_io.c @@ -43,7 +43,6 @@ smb:// */ -#ifdef HAVE_CURL #include #include #include @@ -58,6 +57,7 @@ #endif #include #include +#include /* Internal file structure */ @@ -89,11 +89,10 @@ typedef struct CURLM *multi_handle= NULL; -#ifndef HAVE_REMOTE_IO_DYNAMIC -struct st_mysql_client_plugin remote_io_plugin= -{ +#ifndef HAVE_REMOTEIO_DYNAMIC +MARIADB_REMOTEIO_PLUGIN remote_io_plugin= #else -struct st_mysql_client_plugin _mysql_client_plugin_declare_ = +MARIADB_REMOTEIO_PLUGIN _mysql_client_plugin_declare_ = #endif { MARIADB_CLIENT_REMOTEIO_PLUGIN, @@ -439,4 +438,3 @@ char *ma_rio_gets(char *ptr, size_t size, MA_FILE *file) return ptr;/*success */ } -#endif From b5cf4436819c2bdbbd8beb0a9063297fd0d470b5 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 4 Jan 2016 10:02:10 +0100 Subject: [PATCH 21/40] Windows fixes for remote_io plugin --- CMakeLists.txt | 10 ++++++---- include/config-win.h | 2 ++ libmariadb/CMakeLists.txt | 1 - libmariadb/libmariadb.c | 6 +++++- libmariadb/secure/ma_schannel.c | 1 + plugins/connection/aurora.c | 4 +--- plugins/io/remote_io.c | 7 ++++--- plugins/pvio/pvio_socket.c | 4 ++-- unittest/libmariadb/misc.c | 1 + 9 files changed, 22 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 051e2bbb..f7715716 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -250,11 +250,13 @@ ENDIF() MARK_AS_ADVANCED(SYSTEM_LIBS) IF(NOT REMOTEIO_PLUGIN_TYPE MATCHES "OFF") - INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIRS}) - IF(REMOTEIO_PLUGIN_TYPE MATCHES "STATIC") - SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${CURL_LIBRARIES}) + IF(CURL_FOUND) + INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIRS}) + IF(REMOTEIO_PLUGIN_TYPE MATCHES "STATIC") + SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${CURL_LIBRARIES}) + ENDIF() + ADD_DEFINITIONS("-DHAVE_REMOTEIO=1") ENDIF() - ADD_DEFINITIONS("-DHAVE_REMOTEIO=1") ENDIF() ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(libmariadb) diff --git a/include/config-win.h b/include/config-win.h index 1f433567..cd0b1ddf 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -210,7 +210,9 @@ inline double ulonglong2double(ulonglong value) #define HAVE_PUTENV #define HAVE_SELECT #define HAVE_SETLOCALE +#ifndef HAVE_SOCKET #define HAVE_SOCKET /* Giangi */ +#endif #define HAVE_FLOAT_H #define HAVE_LIMITS_H #define HAVE_STDDEF_H diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index 93dadff3..1f4dac70 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -402,7 +402,6 @@ ENDIF() ADD_LIBRARY(mariadbclient STATIC ${ariadbclient_RC} $ ${EMPTY_FILE} ${EXPORT_LINK}) TARGET_LINK_LIBRARIES(mariadbclient ${SYSTEM_LIBS}) -MESSAGE(STATUS "SYSLIBS: ${SYSTEM_LIBS}") ADD_LIBRARY(libmariadb SHARED ${libmariadb_RC} $ ${EMPTY_FILE} ${EXPORT_LINK}) TARGET_LINK_LIBRARIES(libmariadb ${SYSTEM_LIBS}) IF(UNIX) diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index d5dae214..4491f7e3 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -104,6 +104,10 @@ extern int mthd_stmt_fetch_to_bind(MYSQL_STMT *stmt, unsigned char *row); extern int mthd_stmt_read_all_rows(MYSQL_STMT *stmt); extern void mthd_stmt_flush_unbuffered(MYSQL_STMT *stmt); extern unsigned char *mysql_net_store_length(unsigned char *packet, size_t length); +extern void +my_context_install_suspend_resume_hook(struct mysql_async_context *b, + void (*hook)(my_bool, void *), + void *user_data); uint mysql_port=0; my_string mysql_unix_port=0; @@ -3436,7 +3440,7 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)), return(rc); } -void STDCALL mysql_server_end() +void STDCALL mysql_server_end(void) { if (!mysql_client_init) return; diff --git a/libmariadb/secure/ma_schannel.c b/libmariadb/secure/ma_schannel.c index 063ce361..2ed2d739 100644 --- a/libmariadb/secure/ma_schannel.c +++ b/libmariadb/secure/ma_schannel.c @@ -908,6 +908,7 @@ my_bool ma_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *ve { SC_CTX *sctx; SecPkgContext_ConnectionInfo ConnectionInfo; + if (!cssl->ssl) return 1; diff --git a/plugins/connection/aurora.c b/plugins/connection/aurora.c index 524f4364..5cca298c 100644 --- a/plugins/connection/aurora.c +++ b/plugins/connection/aurora.c @@ -554,14 +554,12 @@ MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const ch if (!mariadb_api) mariadb_api= mysql->methods->api; - mariadb_api->mariadb_get_info(mysql, MARIADB_CLIENT_ERRORS, &client_errors); - if ((aurora= (AURORA *)hdlr->data)) { aurora_refresh_blacklist(aurora); if (aurora->mysql[aurora->last_instance_type]->net.pvio) { - SET_CLIENT_ERROR(mysql, CR_ALREADY_CONNECTED, SQLSTATE_UNKNOWN, 0); + mysql->methods->set_error(mysql, CR_ALREADY_CONNECTED, SQLSTATE_UNKNOWN, 0); return NULL; } is_reconnect= 1; diff --git a/plugins/io/remote_io.c b/plugins/io/remote_io.c index f3af31e8..1d30ebcb 100644 --- a/plugins/io/remote_io.c +++ b/plugins/io/remote_io.c @@ -1,5 +1,5 @@ /************************************************************************************ - * Copyright (C) 2015 Monty Program AB + * Copyright (C) 2015, 2016 Monty Program AB * Copyright (c) 2003 Simtec Electronics * * Re-implemented by Vincent Sanders with extensive @@ -89,10 +89,10 @@ typedef struct CURLM *multi_handle= NULL; -#ifndef HAVE_REMOTEIO_DYNAMIC +#ifndef HAVE_REMOTEIO_DYNAMIC MARIADB_REMOTEIO_PLUGIN remote_io_plugin= #else -MARIADB_REMOTEIO_PLUGIN _mysql_client_plugin_declare_ = +MARIADB_REMOTEIO_PLUGIN _mysql_client_plugin_declaration_ = #endif { MARIADB_CLIENT_REMOTEIO_PLUGIN, @@ -126,6 +126,7 @@ int ma_rio_deinit(void) multi_handle= NULL; } curl_global_cleanup(); + return 0; } /* }}} */ diff --git a/plugins/pvio/pvio_socket.c b/plugins/pvio/pvio_socket.c index 809a6b97..841acfcb 100644 --- a/plugins/pvio/pvio_socket.c +++ b/plugins/pvio/pvio_socket.c @@ -1,5 +1,5 @@ /************************************************************************************ - Copyright (C) 2015 MariaDB Corporation AB, + Copyright (C) 2015,2016 MariaDB Corporation AB, This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -106,7 +106,7 @@ struct st_ma_pvio_methods pvio_socket_methods= { #ifndef HAVE_SOCKET_DYNAMIC MARIADB_PVIO_PLUGIN pvio_socket_plugin= #else -MARIADB_PVIO_PLUGIN _mysql_client_plugin_declare_ +MARIADB_PVIO_PLUGIN _mysql_client_plugin_declaration_ #endif { MARIADB_CLIENT_PVIO_PLUGIN, diff --git a/unittest/libmariadb/misc.c b/unittest/libmariadb/misc.c index 1dd9f478..13dd8697 100644 --- a/unittest/libmariadb/misc.c +++ b/unittest/libmariadb/misc.c @@ -982,6 +982,7 @@ static int test_remote1(MYSQL *mysql) if (!remote_plugin) { diag("skip - no remote io plugin available"); + diag("error: %s", mysql_error(mysql)); return SKIP; } From 4cb9b79cedbcec16d6980c3c6061afdb88202610 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Tue, 5 Jan 2016 09:49:49 +0100 Subject: [PATCH 22/40] renamed MARIADB_OPT_SSL_PASSWORD to PASSPHRASE Since MySQL server is picky about cipher suites, cipher suites in GnuTLS switched back to default (NORMAL) without RHE_DSA --- include/mysql.h | 2 +- libmariadb/libmariadb.c | 4 ++-- libmariadb/secure/gnutls.c | 2 +- unittest/libmariadb/connection.c | 2 +- unittest/libmariadb/ssl.c.in | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index 04cce7f0..f0c6b153 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -213,7 +213,7 @@ extern unsigned int mariadb_deinitialize_ssl; MYSQL_DATABASE_DRIVER=7000, MARIADB_OPT_SSL_FP, /* single finger print for server certificate verification */ MARIADB_OPT_SSL_FP_LIST, /* finger print white list for server certificate verification */ - MARIADB_OPT_SSL_PASSWORD, /* password for encrypted certificates */ + MARIADB_OPT_SSL_PASSPHRASE, /* passphrase for encrypted certificates */ MARIADB_OPT_CONNECTION_READ_ONLY, MYSQL_OPT_CONNECT_ATTRS, /* for mysql_get_optionv */ MARIADB_OPT_USERDATA diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 4491f7e3..acb4ece1 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -2948,7 +2948,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) case MARIADB_OPT_SSL_FP_LIST: OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_fp_list, (char *)arg1); break; - case MARIADB_OPT_SSL_PASSWORD: + case MARIADB_OPT_SSL_PASSPHRASE: OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_pw, (char *)arg1); break; case MARIADB_OPT_CONNECTION_READ_ONLY: @@ -3119,7 +3119,7 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) case MARIADB_OPT_SSL_FP_LIST: *((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_fp_list : NULL; break; - case MARIADB_OPT_SSL_PASSWORD: + case MARIADB_OPT_SSL_PASSPHRASE: *((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_pw : NULL; break; /* todo diff --git a/libmariadb/secure/gnutls.c b/libmariadb/secure/gnutls.c index 5b955e1b..a315bb5d 100644 --- a/libmariadb/secure/gnutls.c +++ b/libmariadb/secure/gnutls.c @@ -204,7 +204,7 @@ void *ma_ssl_init(MYSQL *mysql) goto error; gnutls_session_set_ptr(ssl, (void *)mysql); - ssl_error= gnutls_priority_set_direct(ssl, "NORMAL:-DHE-RSA", &err); + ssl_error= gnutls_priority_set_direct(ssl, "NORMAL", &err); if (ssl_error < 0) goto error; diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index 0ce22450..0d81b6c7 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -755,7 +755,7 @@ static int test_get_options(MYSQL *my) int options_char[]= {MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP, MYSQL_SET_CHARSET_NAME, MYSQL_OPT_SSL_KEY, MYSQL_OPT_SSL_CA, MYSQL_OPT_SSL_CERT, MYSQL_OPT_SSL_CAPATH, MYSQL_OPT_SSL_CIPHER, MYSQL_OPT_BIND, MARIADB_OPT_SSL_FP, MARIADB_OPT_SSL_FP_LIST, - MARIADB_OPT_SSL_PASSWORD, 0}; + MARIADB_OPT_SSL_PASSPHRASE, 0}; char *init_command[3]= {"SET @a:=1", "SET @b:=2", "SET @c:=3"}; int elements= 0; diff --git a/unittest/libmariadb/ssl.c.in b/unittest/libmariadb/ssl.c.in index 6982e41b..1f77c446 100644 --- a/unittest/libmariadb/ssl.c.in +++ b/unittest/libmariadb/ssl.c.in @@ -55,7 +55,7 @@ static int check_cipher(MYSQL *mysql) #ifdef HAVE_GNUTLS { - return strcmp(cipher, "AES-128-GCM"); + return strcmp(cipher, "AES-256-CBC"); } #elif HAVE_OPENSSL if (!strcmp(cipher, "DHE-RSA-AES256-SHA") || @@ -388,7 +388,7 @@ static int test_password_protected(MYSQL *my) "@CMAKE_SOURCE_DIR@/unittest/libmariadb/certs/client-cert.pem", "@CMAKE_SOURCE_DIR@/unittest/libmariadb/certs/ca-cert.pem", 0, 0); - mysql_options(mysql, MARIADB_OPT_SSL_PASSWORD, "qwerty"); + mysql_options(mysql, MARIADB_OPT_SSL_PASSPHRASE, "qwerty"); FAIL_IF(!mysql_real_connect(mysql, hostname, ssluser, sslpw, schema, port, socketname, 0), mysql_error(mysql)); From e3d75b994d2da07091fe11663511c9365a3740ec Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Tue, 5 Jan 2016 13:06:48 +0100 Subject: [PATCH 23/40] Build remoteio plugin as built-in (static) --- cmake/plugins.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/plugins.cmake b/cmake/plugins.cmake index 2ccac127..dc63253f 100644 --- a/cmake/plugins.cmake +++ b/cmake/plugins.cmake @@ -38,7 +38,7 @@ REGISTER_PLUGIN("AUTH_CLEARTEXT" "${CMAKE_SOURCE_DIR}/plugins/auth/mariadb_clear #Remote_IO IF(CURL_FOUND) - REGISTER_PLUGIN("REMOTEIO" "${CMAKE_SOURCE_DIR}/plugins/io/remote_io.c" "remote_io_plugin" "DYNAMIC" "remote_io" 1) + REGISTER_PLUGIN("REMOTEIO" "${CMAKE_SOURCE_DIR}/plugins/io/remote_io.c" "remote_io_plugin" "STATIC" "remote_io" 1) ENDIF() #Trace From f62a2e0270409f23896ec5e4aa4a95952c9c4cbc Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Thu, 7 Jan 2016 13:23:28 +0100 Subject: [PATCH 24/40] Fixed several memory leaks in ma_ssl.c --- include/ma_ssl.h | 1 + include/mysql.h | 4 ++++ libmariadb/libmariadb.c | 34 +++++++++++++++++++++++++++++-- libmariadb/ma_pvio.c | 1 + libmariadb/ma_ssl.c | 11 +++++++++- libmariadb/secure/gnutls.c | 4 +++- libmariadb/secure/openssl.c | 26 +++++++++++++++-------- libmariadb/secure/schannel.c | 4 +++- plugins/connection/CMakeLists.txt | 2 +- unittest/libmariadb/ssl.c.in | 21 ++++++++----------- 10 files changed, 80 insertions(+), 28 deletions(-) diff --git a/include/ma_ssl.h b/include/ma_ssl.h index b994f08c..b227ac5e 100644 --- a/include/ma_ssl.h +++ b/include/ma_ssl.h @@ -151,5 +151,6 @@ const char *ma_pvio_ssl_cipher(MARIADB_SSL *cssl); my_bool ma_pvio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_list); my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio); my_bool ma_pvio_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *version); +void ma_pvio_ssl_end(); #endif /* _ma_ssl_h_ */ diff --git a/include/mysql.h b/include/mysql.h index f0c6b153..ef8f133d 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -226,6 +226,9 @@ extern unsigned int mariadb_deinitialize_ssl; MARIADB_CLIENT_ERRORS, MARIADB_CLIENT_VERSION, MARIADB_CLIENT_VERSION_ID, + MARIADB_CONNECTION_ERROR, + MARIADB_CONNECTION_ERROR_ID, + MARIADB_CONNECTION_SQLSTATE, MARIADB_CONNECTION_ASYNC_TIMEOUT, MARIADB_CONNECTION_ASYNC_TIMEOUT_MS, MARIADB_CONNECTION_HOST, @@ -239,6 +242,7 @@ extern unsigned int mariadb_deinitialize_ssl; MARIADB_CONNECTION_SERVER_VERSION_ID, MARIADB_CONNECTION_SOCKET, MARIADB_CONNECTION_SSL_CIPHER, + MARIADB_CONNECTION_SSL_LIBRARY, MARIADB_CONNECTION_SSL_VERSION, MARIADB_CONNECTION_SSL_VERSION_ID, MARIADB_CONNECTION_TYPE, diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index acb4ece1..11fc88cc 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -3122,10 +3122,9 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) case MARIADB_OPT_SSL_PASSPHRASE: *((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_pw : NULL; break; - /* todo case MARIADB_OPT_CONNECTION_READ_ONLY: + *((my_bool *)arg)= mysql->options.extension ? mysql->options.extension->read_only : 0; break; - */ case MARIADB_OPT_USERDATA: /* nysql_get_optionv(mysql, MARIADB_OPT_USERDATA, key, value) */ { @@ -3450,6 +3449,9 @@ void STDCALL mysql_server_end(void) list_free(pvio_callback, 0); if (my_init_done) my_end(0); +#ifdef HAVE_SSL + ma_pvio_ssl_end(); +#endif mysql_client_init= 0; my_init_done= 0; } @@ -3570,6 +3572,21 @@ my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void * case MARIADB_NET_BUFFER_LENGTH: *((size_t *)arg)= (size_t)net_buffer_length; break; + case MARIADB_CONNECTION_ERROR_ID: + if (!mysql) + goto error; + *((unsigned int *)arg)= mysql->net.last_errno; + break; + case MARIADB_CONNECTION_ERROR: + if (!mysql) + goto error; + *((char **)arg)= mysql->net.last_error; + break; + case MARIADB_CONNECTION_SQLSTATE: + if (!mysql) + goto error; + *((char **)arg)= mysql->net.sqlstate; + break; case MARIADB_CONNECTION_SSL_VERSION: #ifdef HAVE_SSL if (mysql && mysql->net.pvio && mysql->net.pvio->cssl) @@ -3594,6 +3611,19 @@ my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void * #endif goto error; break; + case MARIADB_CONNECTION_SSL_LIBRARY: +#ifdef HAVE_SSL +#ifdef HAVE_GNUTLS + *((char **)arg)= "GNUTLS"; +#elif HAVE_OPENSSL + *((char **)arg)= "OPENSSL"; +#elif HAVE_SCHANNEL + *((char **)arg)= "SCHANNEL"; +#endif +#else + *((char **)arg)= "OFF"; +#endif + break; case MARIADB_CLIENT_VERSION: *((char **)arg)= MYSQL_CLIENT_VERSION; break; diff --git a/libmariadb/ma_pvio.c b/libmariadb/ma_pvio.c index 054ef45d..1d763381 100644 --- a/libmariadb/ma_pvio.c +++ b/libmariadb/ma_pvio.c @@ -70,6 +70,7 @@ MARIADB_PVIO *ma_pvio_init(MA_PVIO_CINFO *cinfo) * Currently we support the following pvio types: * pvio_socket * pvio_namedpipe + * pvio_sharedmed */ char *pvio_plugins[] = {"pvio_socket", "pvio_npipe", "pvio_shmem"}; int type; diff --git a/libmariadb/ma_ssl.c b/libmariadb/ma_ssl.c index 2ea474a8..529979ea 100644 --- a/libmariadb/ma_ssl.c +++ b/libmariadb/ma_ssl.c @@ -78,7 +78,11 @@ MARIADB_SSL *ma_pvio_ssl_init(MYSQL *mysql) my_bool ma_pvio_ssl_connect(MARIADB_SSL *cssl) { - return ma_ssl_connect(cssl); + my_bool rc; + + if ((rc= ma_ssl_connect(cssl))) + ma_ssl_close(cssl); + return rc; } size_t ma_pvio_ssl_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length) @@ -106,6 +110,11 @@ const char *ma_pvio_ssl_cipher(MARIADB_SSL *cssl) return ma_ssl_get_cipher(cssl); } +void ma_pvio_ssl_end() +{ + return ma_ssl_end(); +} + my_bool ma_pvio_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *version) { return ma_ssl_get_protocol_version(cssl, version); diff --git a/libmariadb/secure/gnutls.c b/libmariadb/secure/gnutls.c index a315bb5d..534c2592 100644 --- a/libmariadb/secure/gnutls.c +++ b/libmariadb/secure/gnutls.c @@ -35,6 +35,7 @@ pthread_mutex_t LOCK_gnutls_config; static gnutls_certificate_credentials_t GNUTLS_xcred; extern my_bool ma_ssl_initialized; +extern unsigned int mariadb_deinitialize_ssl; static int my_verify_callback(gnutls_session_t ssl); @@ -137,7 +138,8 @@ void ma_ssl_end() gnutls_certificate_free_crls(GNUTLS_xcred); gnutls_certificate_free_ca_names(GNUTLS_xcred); gnutls_certificate_free_credentials(GNUTLS_xcred); - gnutls_global_deinit(); + if (mariadb_deinitialize_ssl) + gnutls_global_deinit(); ma_ssl_initialized= FALSE; } pthread_mutex_unlock(&LOCK_gnutls_config); diff --git a/libmariadb/secure/openssl.c b/libmariadb/secure/openssl.c index e659a1a1..f8a844dd 100644 --- a/libmariadb/secure/openssl.c +++ b/libmariadb/secure/openssl.c @@ -41,6 +41,7 @@ #include extern my_bool ma_ssl_initialized; +extern unsigned int mariadb_deinitialize_ssl; static SSL_CTX *SSL_context= NULL; #define MAX_SSL_ERR_LEN 100 @@ -226,14 +227,16 @@ void ma_ssl_end() SSL_CTX_free(SSL_context); SSL_context= NULL; } - ERR_remove_state(0); - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - ERR_free_strings(); - //ENGINE_cleanup(); - CONF_modules_free(); - CONF_modules_unload(1); - sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); + if (mariadb_deinitialize_ssl) + { + ERR_remove_state(0); + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + ERR_free_strings(); + CONF_modules_free(); + CONF_modules_unload(1); + sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); + } ma_ssl_initialized= FALSE; } pthread_mutex_unlock(&LOCK_openssl_config); @@ -293,7 +296,12 @@ static int ma_ssl_set_certs(MYSQL *mysql) if (keyfile && keyfile[0]) { if (SSL_CTX_use_PrivateKey_file(SSL_context, keyfile, SSL_FILETYPE_PEM) != 1) - goto error; + { + unsigned long err= ERR_peek_error(); + if (!(ERR_GET_LIB(err) == ERR_LIB_X509 && + ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) + goto error; + } } if (OPT_HAS_EXT_VAL(mysql, ssl_pw)) { diff --git a/libmariadb/secure/schannel.c b/libmariadb/secure/schannel.c index 3f84c17f..1f27dd44 100644 --- a/libmariadb/secure/schannel.c +++ b/libmariadb/secure/schannel.c @@ -310,7 +310,6 @@ my_bool ma_ssl_connect(MARIADB_SSL *cssl) return 0; end: - /* todo: cleanup */ if (pRemoteCertContext) CertFreeCertificateContext(pRemoteCertContext); if (rc && sctx->IoBufferSize) @@ -322,6 +321,9 @@ end: CertFreeCertificateContext(sctx->client_cert_ctx); if (sctx->client_crl_ctx) CertFreeCRLContext(sctx->client_crl_ctx); + sctx->client_ca_ctx= 0; + sctx->client_cert_ctx= 0; + sctx->client_crl_ctx= 0; return 1; } diff --git a/plugins/connection/CMakeLists.txt b/plugins/connection/CMakeLists.txt index 4ccdd611..c9cc1932 100644 --- a/plugins/connection/CMakeLists.txt +++ b/plugins/connection/CMakeLists.txt @@ -20,7 +20,7 @@ IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC") SET(INSTALL_LIBS replication) ENDIF() -IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC") +IF(AURORA_PLUGIN_TYPE MATCHES "DYNAMIC") IF(WIN32) SET_VERSION_INFO("TARGET:aurora" "FILE_TYPE:VFT_DLL" diff --git a/unittest/libmariadb/ssl.c.in b/unittest/libmariadb/ssl.c.in index 1f77c446..866aa34b 100644 --- a/unittest/libmariadb/ssl.c.in +++ b/unittest/libmariadb/ssl.c.in @@ -53,18 +53,7 @@ static int check_cipher(MYSQL *mysql) return 1; diag("cipher: %s", cipher); -#ifdef HAVE_GNUTLS - { - return strcmp(cipher, "AES-256-CBC"); - } -#elif HAVE_OPENSSL - if (!strcmp(cipher, "DHE-RSA-AES256-SHA") || - !strcmp(cipher, "DHE-RSA-AES256-GCM-SHA384")) - return 0; -#elif HAVE_SCHANNEL - return strcmp(cipher, "CALG_AES_256"); -#endif - return 1; + return 0; } static int create_ssl_user(const char *ssluser, my_bool is_X509) @@ -90,6 +79,8 @@ static int create_ssl_user(const char *ssluser, my_bool is_X509) rc= mysql_query(mysql, "FLUSH PRIVILEGES"); check_mysql_rc(rc,mysql); + mysql_close(mysql); + return rc; } @@ -775,7 +766,7 @@ static int test_ssl_fp_list(MYSQL *unused) static int test_ssl_version(MYSQL *mysql) { unsigned int iversion; - char *version; + const char *version, *library; MYSQL *my; if (check_skip_ssl()) @@ -794,6 +785,10 @@ static int test_ssl_version(MYSQL *mysql) mariadb_get_infov(my, MARIADB_CONNECTION_SSL_VERSION, &version); diag("protocol: %s", version); + mariadb_get_infov(my, MARIADB_CONNECTION_SSL_LIBRARY, &library); + diag("library: %s", library); + + mysql_close(my); return OK; From 9ab4d1b116a1d61a3380e58dfea49dc1517d4df3 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Sun, 10 Jan 2016 08:15:02 +0100 Subject: [PATCH 25/40] Fixed userdata allocation: - prevent double free crash - check if given key already exists and update value --- libmariadb/libmariadb.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 11fc88cc..233e7cd3 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -2857,13 +2857,27 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) if (!hash_inited(&mysql->options.extension->userdata)) { if (_hash_init(&mysql->options.extension->userdata, - 0, 0, 0, ma_get_hash_keyval, ma_hash_free, 0) || - !(buffer= (uchar *)my_malloc(strlen(key) + 1 + sizeof(void *), MYF(MY_ZEROFILL)))) + 0, 0, 0, ma_get_hash_keyval, ma_hash_free, 0)) { SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); goto end; } } + /* check if key is already in buffer */ + if (p= (uchar *)hash_search(&mysql->options.extension->userdata, (uchar *)key, + (uint)strlen((char *)key))) + { + p+= strlen(key) + 1; + memcpy(p, &data, sizeof(void *)); + break; + } + + if (!(buffer= (uchar *)my_malloc(strlen(key) + 1 + sizeof(void *), MYF(MY_ZEROFILL)))) + { + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); + goto end; + } + p= buffer; strcpy(p, key); p+= strlen(key) + 1; From 43c9aec83d56fd430bb8643080c706b06d962ebd Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Sun, 10 Jan 2016 17:21:03 +0100 Subject: [PATCH 26/40] Aurora fixes: use mariadb_api structure for calling api functions. --- plugins/connection/aurora.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/plugins/connection/aurora.c b/plugins/connection/aurora.c index 5cca298c..3697e608 100644 --- a/plugins/connection/aurora.c +++ b/plugins/connection/aurora.c @@ -262,9 +262,9 @@ int aurora_get_instance_type(MYSQL *mysql) if (!mariadb_api->mysql_query(mysql, query)) { - MYSQL_RES *res= mysql_store_result(mysql); + MYSQL_RES *res= mariadb_api->mysql_store_result(mysql); rc= mysql_num_rows(res) ? AURORA_PRIMARY : AURORA_REPLICA; - mysql_free_result(res); + mariadb_api->mysql_free_result(res); return rc; } return -1; @@ -294,9 +294,9 @@ my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora) MYSQL_RES *res; MYSQL_ROW row; - if ((res= mysql_store_result(mysql))) + if ((res= mariadb_api->mysql_store_result(mysql))) { - if ((row= mysql_fetch_row(res))) + if ((row= mariadb_api->mysql_fetch_row(res))) { if (row[0]) { @@ -304,7 +304,7 @@ my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora) rc= 1; } } - mysql_free_result(res); + mariadb_api->mysql_free_result(res); } } return rc; @@ -355,7 +355,7 @@ void aurora_refresh_blacklist(AURORA *aurora) /* {{{ MYSQL *aurora_connect_instance() */ MYSQL *aurora_connect_instance(AURORA *aurora, AURORA_INSTANCE *instance, MYSQL *mysql) { - if (!mysql->methods->db_connect(mysql, + if (!mariadb_api->mysql_real_connect(mysql, instance->host, aurora->username, aurora->password, @@ -442,7 +442,7 @@ my_bool aurora_find_replica(AURORA *aurora) case AURORA_REPLICA: if (!aurora->mysql[AURORA_REPLICA]) { - aurora->mysql[AURORA_REPLICA]= mysql_init(NULL); + aurora->mysql[AURORA_REPLICA]= mariadb_api->mysql_init(NULL); } aurora_copy_mysql(&mysql, aurora->mysql[AURORA_REPLICA]); aurora->active[AURORA_REPLICA]= 1; @@ -455,7 +455,7 @@ my_bool aurora_find_replica(AURORA *aurora) continue; break; default: - mysql_close(&mysql); + mariadb_api->mysql_close(&mysql); return 0; break; } @@ -658,7 +658,7 @@ my_bool aurora_reconnect(MYSQL *mysql) aurora_switch_connection(mysql, aurora, AURORA_REPLICA); break; case AURORA_PRIMARY: - if (!(rc= mysql_reconnect(aurora->mysql[aurora->last_instance_type]))) + if (!(rc= mariadb_api->mysql_reconnect(aurora->mysql[aurora->last_instance_type]))) aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); break; default: @@ -689,7 +689,7 @@ void aurora_close(MYSQL *mysql) /* connection handler wull be freed in mariadb_api->mysql_close() */ aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0; - mysql_close(aurora->mysql[AURORA_REPLICA]); + mariadb_api->mysql_close(aurora->mysql[AURORA_REPLICA]); } if (aurora->mysql[AURORA_PRIMARY]) @@ -699,19 +699,9 @@ void aurora_close(MYSQL *mysql) aurora->mysql[AURORA_PRIMARY]->net.pvio= aurora->pvio[AURORA_PRIMARY]; - mysql_close(aurora->mysql[AURORA_PRIMARY]); + mariadb_api->mysql_close(aurora->mysql[AURORA_PRIMARY]); } - - -/* - if (aurora->mysql[AURORA_PRIMARY]) - { - aurora->mysql[AURORA_PRIMARY]->net.pvio= aurora->pvio[AURORA_PRIMARY]; - aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr= 0; - mysql_close(aurora->mysql[AURORA_PRIMARY]); - } -*/ /* free masrwe information */ aurora_close_memory(aurora); } From 77fec5c58f4c0fbe86bd684e700c26c2f556975a Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 11 Jan 2016 08:58:15 +0100 Subject: [PATCH 27/40] Fix for aurora: remember options when trying to connect inside plugin to avoid double free of options --- libmariadb/libmariadb.c | 2 ++ plugins/connection/aurora.c | 14 ++++++++++++-- unittest/libmariadb/CMakeLists.txt | 11 +++++++++-- unittest/libmariadb/t_aurora.c | 25 ++++++++++++++++++++----- 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 233e7cd3..85657e60 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -1323,7 +1323,9 @@ mysql_real_connect(MYSQL *mysql, const char *host, const char *user, mysql->net.conn_hdlr->plugin= plugin; if (plugin && plugin->connect) + { return plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag); + } } return mysql->methods->db_connect(mysql, host, user, passwd, diff --git a/plugins/connection/aurora.c b/plugins/connection/aurora.c index 3697e608..2ac5de00 100644 --- a/plugins/connection/aurora.c +++ b/plugins/connection/aurora.c @@ -362,7 +362,7 @@ MYSQL *aurora_connect_instance(AURORA *aurora, AURORA_INSTANCE *instance, MYSQL aurora->database, instance->port ? instance->port : aurora->port, NULL, - aurora->client_flag)) + aurora->client_flag | CLIENT_REMEMBER_OPTIONS)) { /* connection not available */ instance->blacklisted= time(NULL); @@ -630,8 +630,13 @@ MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const ch aurora->active[AURORA_PRIMARY]= 1; aurora->pvio[AURORA_PRIMARY]= aurora->mysql[AURORA_PRIMARY]->net.pvio; } + else + aurora->pvio[AURORA_PRIMARY]= NULL; } + if (!aurora->pvio[AURORA_PRIMARY] && !aurora->pvio[AURORA_REPLICA]) + goto error; + aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); ENABLE_AURORA(mysql); return mysql; @@ -676,6 +681,11 @@ void aurora_close(MYSQL *mysql) MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; AURORA *aurora= (AURORA *)hdlr->data; + if (!aurora->pvio[AURORA_PRIMARY] && !aurora->pvio[AURORA_REPLICA]) + { + return; + } + aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); /* if the connection is not active yet, just return */ @@ -702,7 +712,7 @@ void aurora_close(MYSQL *mysql) mariadb_api->mysql_close(aurora->mysql[AURORA_PRIMARY]); } - /* free masrwe information */ + /* free information */ aurora_close_memory(aurora); } /* }}} */ diff --git a/unittest/libmariadb/CMakeLists.txt b/unittest/libmariadb/CMakeLists.txt index 7d1c0be4..77867cb2 100644 --- a/unittest/libmariadb/CMakeLists.txt +++ b/unittest/libmariadb/CMakeLists.txt @@ -21,9 +21,11 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/unittest/mytap) ADD_DEFINITIONS(-DLIBMARIADB) -SET(API_TESTS "t_aurora" "async" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" - "sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread" "dyncol") +SET(API_TESTS "async" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" + "sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread" "dyncol") +#exclude following tests from ctests, since we need to run them maually with different credentials +SET(MANUAL_TESTS "t_aurora") # Get finger print from server certificate IF(WITH_SSL) @@ -62,3 +64,8 @@ FOREACH(API_TEST ${API_TESTS}) ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST}) SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 120) ENDFOREACH(API_TEST) + +FOREACH(API_TEST ${MANUAL_TESTS}) + ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c ${CMAKE_SOURCE_DIR}/libmariadb/getopt.c) + TARGET_LINK_LIBRARIES(${API_TEST} mytap libmariadb) +ENDFOREACH() diff --git a/unittest/libmariadb/t_aurora.c b/unittest/libmariadb/t_aurora.c index d9c89c45..4336a3c5 100644 --- a/unittest/libmariadb/t_aurora.c +++ b/unittest/libmariadb/t_aurora.c @@ -2,12 +2,13 @@ */ #include "my_test.h" +#include "ma_pvio.h" static int aurora1(MYSQL *mysql) { int rc; my_bool read_only= 1; - char *primary, *replica; + const char *primary, *schema; MYSQL_RES *res; rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); @@ -19,7 +20,7 @@ static int aurora1(MYSQL *mysql) rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1, 'foo'), (2, 'bar')"); check_mysql_rc(rc, mysql); - primary= mysql->host; + mariadb_get_infov(mysql, MARIADB_CONNECTION_HOST, &primary); diag("primary: %s", primary); mysql_options(mysql, MARIADB_OPT_CONNECTION_READ_ONLY, &read_only); @@ -37,15 +38,29 @@ static int aurora1(MYSQL *mysql) diag("Num_rows: %d", mysql_num_rows(res)); mysql_free_result(res); - replica= mysql->host; - diag("replica: %s", replica); - diag("db: %s", mysql->db); + mariadb_get_infov(mysql, MARIADB_CONNECTION_SCHEMA, &schema); + diag("db: %s", schema); return OK; } +static int test_wrong_user(MYSQL *my) +{ + MYSQL *mysql= mysql_init(NULL); + + if (mysql_real_connect(mysql, hostname, "wrong_user", NULL, NULL, 0, NULL, 0)) + { + diag("Error expected"); + mysql_close(mysql); + return FAIL; + } + mysql_close(mysql); + return OK; +} + struct my_tests_st my_tests[] = { {"aurora1", aurora1, TEST_CONNECTION_NEW, 0, NULL, NULL}, + {"test_wrong_user", test_wrong_user, TEST_CONNECTION_NONE, 0, NULL, NULL}, {NULL, NULL, 0, 0, NULL, NULL} }; From f8912935b1fbb51a3d5ecb1f1907602284c8bf5d Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Sat, 16 Jan 2016 07:04:28 +0100 Subject: [PATCH 28/40] - Fixed several aurora plugin crashes (after reconnect) - moved mysql->reconnect to mysql->options.reconnect --- include/ma_common.h | 1 + include/mysql.h | 11 +- libmariadb/libmariadb.c | 80 ++++--- libmariadb/ma_pvio.c | 4 +- libmariadb/net.c | 5 +- plugins/connection/aurora.c | 364 +++++++++++++------------------ plugins/connection/replication.c | 4 +- unittest/libmariadb/basic-t.c | 12 +- unittest/libmariadb/connection.c | 42 ++-- unittest/libmariadb/misc.c | 3 +- unittest/libmariadb/my_test.h | 22 +- unittest/libmariadb/ps.c | 12 +- unittest/libmariadb/result.c | 3 +- unittest/libmariadb/t_aurora.c | 92 +++++++- 14 files changed, 351 insertions(+), 304 deletions(-) diff --git a/include/ma_common.h b/include/ma_common.h index 83fb4291..87fca0e8 100644 --- a/include/ma_common.h +++ b/include/ma_common.h @@ -54,6 +54,7 @@ struct st_mysql_options_extension { char *ssl_pw; /* password for encrypted certificates */ char *url; /* for connection handler we need to save URL for reconnect */ my_bool read_only; + char *connection_handler; HASH userdata; }; diff --git a/include/mysql.h b/include/mysql.h index ef8f133d..b6078699 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -216,7 +216,8 @@ extern unsigned int mariadb_deinitialize_ssl; MARIADB_OPT_SSL_PASSPHRASE, /* passphrase for encrypted certificates */ MARIADB_OPT_CONNECTION_READ_ONLY, MYSQL_OPT_CONNECT_ATTRS, /* for mysql_get_optionv */ - MARIADB_OPT_USERDATA + MARIADB_OPT_USERDATA, + MARIADB_OPT_CONNECTION_HANDLER }; enum mariadb_value { @@ -284,7 +285,7 @@ struct st_mysql_options { unsigned long max_allowed_packet; my_bool use_ssl; /* if to use SSL or not */ my_bool compress,named_pipe; - my_bool unused_1, unused_2, unused_3, unused_4; + my_bool reconnect, unused_1, unused_2, unused_3; enum mysql_option methods_to_use; char *bind_address; my_bool secure_auth; @@ -321,11 +322,11 @@ struct st_mysql_options { struct st_mysql_options options; enum mysql_status status; my_bool free_me; /* If free in mysql_close */ - my_bool reconnect; /* set to 1 if automatic reconnect */ + my_bool unused_1; char scramble_buff[20+ 1]; /* madded after 3.23.58 */ - my_bool unused_1; - void *unused_2, *unused_3, *unused_4, *unused_5; + my_bool unused_2; + void *unused_3, *unused_4, *unused_5, *unused_6; LIST *stmts; const struct st_mysql_methods *methods; void *thd; diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 85657e60..9a960ab7 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -133,7 +133,7 @@ struct st_mysql_methods MARIADB_DEFAULT_METHODS; #define native_password_plugin_name "mysql_native_password" #define IS_CONNHDLR_ACTIVE(mysql)\ - ((mysql)->net.conn_hdlr && (mysql)->net.conn_hdlr->active) + (((mysql)->net.conn_hdlr)) static void end_server(MYSQL *mysql); static void mysql_close_memory(MYSQL *mysql); @@ -1160,7 +1160,7 @@ mysql_init(MYSQL *mysql) #ifdef ENABLED_LOCAL_INFILE mysql->options.client_flag|= CLIENT_LOCAL_FILES; #endif - mysql->reconnect= 0; + mysql->options.reconnect= 0; return mysql; } @@ -1295,18 +1295,26 @@ mysql_real_connect(MYSQL *mysql, const char *host, const char *user, uint port, const char *unix_socket,unsigned long client_flag) { char *end; + char *connection_handler= (mysql->options.extension) ? + mysql->options.extension->connection_handler : 0; if (!mysql->methods) mysql->methods= &MARIADB_DEFAULT_METHODS; - if (host && (end= strstr(host, "://"))) + if (connection_handler || + (host && (end= strstr(host, "://")))) { MARIADB_CONNECTION_PLUGIN *plugin; char plugin_name[64]; - bzero(plugin_name, 64); - strncpy(plugin_name, host, MIN(end - host, 63)); - end+= 3; + if (!connection_handler || !connection_handler[0]) + { + bzero(plugin_name, 64); + strncpy(plugin_name, host, MIN(end - host, 63)); + end+= 3; + } + else + strncpy(plugin_name, connection_handler, MIN(63, strlen(connection_handler))); if (!(plugin= (MARIADB_CONNECTION_PLUGIN *)mysql_client_find_plugin(mysql, plugin_name, MARIADB_CLIENT_CONNECTION_PLUGIN))) return NULL; @@ -1324,7 +1332,13 @@ mysql_real_connect(MYSQL *mysql, const char *host, const char *user, if (plugin && plugin->connect) { - return plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag); + MYSQL *my= plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag); + if (!my) + { + my_free(mysql->net.conn_hdlr); + mysql->net.conn_hdlr= NULL; + } + return my; } } @@ -1663,8 +1677,8 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, char **end= begin + mysql->options.init_command->elements; /* Avoid reconnect in mysql_real_connect */ - my_bool save_reconnect= mysql->reconnect; - mysql->reconnect= 0; + my_bool save_reconnect= mysql->options.reconnect; + mysql->options.reconnect= 0; for (;begin < end; begin++) { @@ -1678,7 +1692,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, mysql_free_result(res); } while (!mysql_next_result(mysql)); } - mysql->reconnect= save_reconnect; + mysql->options.reconnect= save_reconnect; } strmov(mysql->net.sqlstate, "00000"); @@ -1733,13 +1747,13 @@ my_bool STDCALL mysql_reconnect(MYSQL *mysql) DBUG_ENTER("mysql_reconnect"); /* check if connection handler is active */ - if (IS_CONNHDLR_ACTIVE(mysql)) + if (IS_CONNHDLR_ACTIVE(mysql)) { - if (mysql->net.conn_hdlr->plugin && mysql->net.conn_hdlr->plugin->connect) + if (mysql->net.conn_hdlr->plugin && mysql->net.conn_hdlr->plugin->reconnect) DBUG_RETURN(mysql->net.conn_hdlr->plugin->reconnect(mysql)); } - if (!mysql->reconnect || + if (!mysql->options.reconnect || (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) { /* Allow reconnect next time */ @@ -1750,13 +1764,6 @@ my_bool STDCALL mysql_reconnect(MYSQL *mysql) mysql_init(&tmp_mysql); tmp_mysql.options=mysql->options; - if (mysql->net.conn_hdlr) - { - tmp_mysql.net.conn_hdlr= mysql->net.conn_hdlr; - mysql->net.conn_hdlr= 0; - } - - /* don't reread options from configuration files */ tmp_mysql.options.my_cnf_group= tmp_mysql.options.my_cnf_file= NULL; @@ -1796,7 +1803,6 @@ my_bool STDCALL mysql_reconnect(MYSQL *mysql) } } - tmp_mysql.reconnect= mysql->reconnect; tmp_mysql.free_me= mysql->free_me; tmp_mysql.stmts= mysql->stmts; mysql->stmts= NULL; @@ -1957,6 +1963,7 @@ static void mysql_close_options(MYSQL *mysql) my_free(mysql->options.extension->ssl_fp_list); my_free(mysql->options.extension->ssl_pw); my_free(mysql->options.extension->url); + my_free(mysql->options.extension->connection_handler); if(hash_inited(&mysql->options.extension->connect_attrs)) hash_free(&mysql->options.extension->connect_attrs); if (hash_inited(&mysql->options.extension->userdata)) @@ -2009,8 +2016,9 @@ void mysql_close_slow_part(MYSQL *mysql) { free_old_query(mysql); mysql->status=MYSQL_STATUS_READY; /* Force command */ - mysql->reconnect=0; - simple_command(mysql, COM_QUIT,NullS,0,1,0); + mysql->options.reconnect=0; + if (mysql->net.pvio && mysql->net.buff) + simple_command(mysql, COM_QUIT,NullS,0,1,0); end_server(mysql); } } @@ -2021,13 +2029,11 @@ mysql_close(MYSQL *mysql) DBUG_ENTER("mysql_close"); if (mysql) /* Some simple safety */ { - - if (IS_CONNHDLR_ACTIVE(mysql)) + if (mysql->net.conn_hdlr) { - void *p= (void *)mysql->net.conn_hdlr; - mysql->net.conn_hdlr->plugin->close(mysql); + MA_CONNECTION_HANDLER *p= mysql->net.conn_hdlr; + p->plugin->close(mysql); my_free(p); - DBUG_VOID_RETURN; } if (mysql->methods) @@ -2544,7 +2550,7 @@ mysql_ping(MYSQL *mysql) rc= simple_command(mysql, COM_PING,0,0,0,0); /* if connection was terminated and reconnect is true, try again */ - if (rc!=0 && mysql->reconnect) + if (rc!=0 && mysql->options.reconnect) rc= simple_command(mysql, COM_PING,0,0,0,0); return rc; } @@ -2682,7 +2688,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) mysql->options.charset_name=my_strdup((char *)arg1,MYF(MY_WME)); break; case MYSQL_OPT_RECONNECT: - mysql->reconnect= *(uint *)arg1; + mysql->options.reconnect= *(uint *)arg1; break; case MYSQL_OPT_PROTOCOL: #ifdef _WIN32 @@ -2700,7 +2706,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) mysql->options.write_timeout= *(uint *)arg1; break; case MYSQL_REPORT_DATA_TRUNCATION: - mysql->options.report_data_truncation= *(uint *)arg1; + mysql->options.report_data_truncation= *(my_bool *)arg1; break; case MYSQL_PROGRESS_CALLBACK: if (!mysql->options.extension) @@ -2785,7 +2791,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) break; case MYSQL_OPT_SSL_VERIFY_SERVER_CERT: - if (*(uint *)arg1) + if (*(my_bool *)arg1) mysql->options.client_flag |= CLIENT_SSL_VERIFY_SERVER_CERT; else mysql->options.client_flag &= ~CLIENT_SSL_VERIFY_SERVER_CERT; @@ -2843,6 +2849,9 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) mysql->options.extension->connect_attrs_len= 0; } break; + case MARIADB_OPT_CONNECTION_HANDLER: + OPT_SET_EXTENDED_VALUE_STR(&mysql->options, connection_handler, (char *)arg1); + break; case MARIADB_OPT_USERDATA: { void *data= va_arg(ap, void *); @@ -3029,7 +3038,7 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) *((char **)arg)= mysql->options.charset_name; break; case MYSQL_OPT_RECONNECT: - *((uint *)arg)= mysql->reconnect; + *((my_bool *)arg)= mysql->options.reconnect; break; case MYSQL_OPT_PROTOCOL: *((uint *)arg)= mysql->options.protocol; @@ -3041,7 +3050,7 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) *((uint *)arg)= mysql->options.write_timeout; break; case MYSQL_REPORT_DATA_TRUNCATION: - *((uint *)arg)= mysql->options.report_data_truncation; + *((my_bool *)arg)= mysql->options.report_data_truncation; break; case MYSQL_PROGRESS_CALLBACK: *((void (**)(const MYSQL *, uint, uint, double, const char *, uint))arg)= @@ -3159,6 +3168,9 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) *((void **)data)= NULL; } break; + case MARIADB_OPT_CONNECTION_HANDLER: + *((char **)arg)= mysql->options.extension ? mysql->options.extension->connection_handler : NULL; + break; default: va_end(ap); DBUG_RETURN(-1); diff --git a/libmariadb/ma_pvio.c b/libmariadb/ma_pvio.c index 1d763381..7d012c66 100644 --- a/libmariadb/ma_pvio.c +++ b/libmariadb/ma_pvio.c @@ -489,8 +489,8 @@ my_bool ma_pvio_is_blocking(MARIADB_PVIO *pvio) my_bool ma_pvio_has_data(MARIADB_PVIO *pvio, ssize_t *data_len) { /* check if we still have unread data in cache */ - if (pvio->cache) - if (pvio->cache_pos > pvio->cache) + if (pvio && pvio->cache) + if (pvio->cache_pos > pvio->cache) return test(pvio->cache_pos - pvio->cache); if (pvio && pvio->methods->has_data) return pvio->methods->has_data(pvio, data_len); diff --git a/libmariadb/net.c b/libmariadb/net.c index 94c32104..5a850ad7 100644 --- a/libmariadb/net.c +++ b/libmariadb/net.c @@ -182,9 +182,10 @@ static my_bool net_realloc(NET *net, size_t length) /* Remove unwanted characters from connection */ void net_clear(NET *net) { - size_t len; +// size_t len; DBUG_ENTER("net_clear"); - ma_pvio_has_data(net->pvio, &len); +/* if (net->pvio) + ma_pvio_has_data(net->pvio, &len); */ net->compress_pkt_nr= net->pkt_nr=0; /* Ready for new command */ net->write_pos=net->buff; DBUG_VOID_RETURN; diff --git a/plugins/connection/aurora.c b/plugins/connection/aurora.c index 2ac5de00..32fbfe31 100644 --- a/plugins/connection/aurora.c +++ b/plugins/connection/aurora.c @@ -45,7 +45,6 @@ MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const ch void aurora_close(MYSQL *mysql); int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *arg, size_t length, my_bool skipp_check, void *opt_arg); -int aurora_set_options(MYSQL *msql, enum mysql_option option, void *arg); my_bool aurora_reconnect(MYSQL *mysql); #define AURORA_MAX_INSTANCES 16 @@ -55,11 +54,6 @@ my_bool aurora_reconnect(MYSQL *mysql); #define AURORA_REPLICA 1 #define AURORA_UNAVAILABLE 2 -#define ENABLE_AURORA(mysql)\ - (mysql)->net.conn_hdlr->active= 1; -#define DISABLE_AURORA(mysql)\ - (mysql)->net.conn_hdlr->active= 0; - #ifndef HAVE_AURORA_DYNAMIC MARIADB_CONNECTION_PLUGIN connection_aurora_plugin = #else @@ -77,7 +71,7 @@ MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ = NULL, aurora_connect, aurora_close, - aurora_set_options, + NULL, aurora_command, aurora_reconnect }; @@ -92,16 +86,14 @@ typedef struct st_aurora_instance { } AURORA_INSTANCE; typedef struct st_conn_aurora { - MARIADB_PVIO *pvio[2]; - MYSQL *mysql[2]; - my_bool active[2]; + MYSQL *mysql[2], + save_mysql; char *url; unsigned int num_instances; AURORA_INSTANCE instance[AURORA_MAX_INSTANCES]; char *username, *password, *database; unsigned int port; unsigned long client_flag; - unsigned int last_instance_type; /* Primary or Replica */ char primary_id[100]; } AURORA; @@ -118,20 +110,13 @@ my_bool aurora_switch_connection(MYSQL *mysql, AURORA *aurora, int type) case AURORA_REPLICA: if (aurora->mysql[AURORA_REPLICA]) { - mysql->net.pvio= aurora->pvio[AURORA_REPLICA]; - aurora->pvio[AURORA_REPLICA]->mysql= mysql; - mysql->thread_id= aurora->mysql[AURORA_REPLICA]->thread_id; - aurora->last_instance_type= AURORA_REPLICA; + *mysql= *aurora->mysql[AURORA_REPLICA]; } break; case AURORA_PRIMARY: if (aurora->mysql[AURORA_PRIMARY]) { - if (aurora->mysql[AURORA_REPLICA]) - aurora->mysql[AURORA_REPLICA]->net.pvio->mysql= aurora->mysql[AURORA_REPLICA]; - mysql->net.pvio= aurora->pvio[AURORA_PRIMARY]; - mysql->thread_id= aurora->mysql[AURORA_PRIMARY]->thread_id; - aurora->last_instance_type= AURORA_PRIMARY; + *mysql= *aurora->mysql[AURORA_PRIMARY]; } break; default: @@ -257,17 +242,23 @@ my_bool aurora_parse_url(const char *url, AURORA *aurora) */ int aurora_get_instance_type(MYSQL *mysql) { - int rc; + int rc= -1; + MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr; + char *query= "select variable_value from information_schema.global_variables where variable_name='INNODB_READ_ONLY' AND variable_value='OFF'"; + if (!mysql) + return -1; + + mysql->net.conn_hdlr= 0; if (!mariadb_api->mysql_query(mysql, query)) { MYSQL_RES *res= mariadb_api->mysql_store_result(mysql); rc= mysql_num_rows(res) ? AURORA_PRIMARY : AURORA_REPLICA; mariadb_api->mysql_free_result(res); - return rc; } - return -1; + mysql->net.conn_hdlr= save_hdlr; + return rc; } /* }}} */ @@ -287,7 +278,9 @@ int aurora_get_instance_type(MYSQL *mysql) my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora) { my_bool rc= 0; + MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr; + mysql->net.conn_hdlr= 0; if (!mariadb_api->mysql_query(mysql, "select server_id from information_schema.replica_host_status " "where session_id = 'MASTER_SESSION_ID'")) { @@ -307,6 +300,7 @@ my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora) mariadb_api->mysql_free_result(res); } } + mysql->net.conn_hdlr= save_hdlr; return rc; } /* }}} */ @@ -326,7 +320,7 @@ static unsigned int aurora_get_valid_instances(AURORA *aurora, AURORA_INSTANCE * { if (aurora->instance[i].type != AURORA_UNAVAILABLE) { - if (aurora->instance[i].type == AURORA_PRIMARY && aurora->active[AURORA_PRIMARY]) + if (aurora->instance[i].type == AURORA_PRIMARY && aurora->mysql[AURORA_PRIMARY]) continue; instances[valid_instances]= &aurora->instance[i]; valid_instances++; @@ -386,31 +380,21 @@ MYSQL *aurora_connect_instance(AURORA *aurora, AURORA_INSTANCE *instance, MYSQL return NULL; } if (!aurora->primary_id[0]) - aurora_get_primary_id(mysql, aurora); + if (aurora_get_primary_id(mysql, aurora)) + return NULL; return mysql; } /* }}} */ -/* {{{ void aurora_copy_mysql() */ -void aurora_copy_mysql(MYSQL *from, MYSQL *to) +/* {{{ void aurora_close_internal */ +void aurora_close_internal(MYSQL *mysql) { - /* invalidate statements */ - to->methods->invalidate_stmts(to, "aurora connect/reconnect"); - - from->free_me= to->free_me; - from->reconnect= to->reconnect; - from->net.conn_hdlr= to->net.conn_hdlr; - from->stmts= to->stmts; - to->stmts= NULL; - - memset(&to->options, 0, sizeof(to->options)); - to->free_me= 0; - to->net.conn_hdlr= 0; - mariadb_api->mysql_close(to); - *to= *from; - to->net.pvio= from->net.pvio; - to->net.pvio->mysql= to; - from->net.pvio= NULL; + if (mysql) + { + mysql->net.conn_hdlr= 0; + memset(&mysql->options, 0, sizeof(struct st_mysql_options)); + mariadb_api->mysql_close(mysql); + } } /* }}} */ @@ -420,46 +404,45 @@ my_bool aurora_find_replica(AURORA *aurora) int valid_instances; my_bool replica_found= 0; AURORA_INSTANCE *instance[AURORA_MAX_INSTANCES]; - MYSQL mysql; + MYSQL *mysql; if (aurora->num_instances < 2) return 0; - mariadb_api->mysql_init(&mysql); - mysql.options= aurora->mysql[AURORA_PRIMARY]->options; - - /* don't execute init_command on slave */ - mysql.net.conn_hdlr= aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr; valid_instances= aurora_get_valid_instances(aurora, instance); while (valid_instances && !replica_found) { int random_pick= rand() % valid_instances; - if ((aurora_connect_instance(aurora, instance[random_pick], &mysql))) + mysql= mariadb_api->mysql_init(NULL); + mysql->options= aurora->save_mysql.options; + + /* don't execute init_command on slave */ +// mysql->net.conn_hdlr= aurora->save_mysql.net.conn_hdlr; + if ((aurora_connect_instance(aurora, instance[random_pick], mysql))) { switch (instance[random_pick]->type) { case AURORA_REPLICA: if (!aurora->mysql[AURORA_REPLICA]) - { - aurora->mysql[AURORA_REPLICA]= mariadb_api->mysql_init(NULL); - } - aurora_copy_mysql(&mysql, aurora->mysql[AURORA_REPLICA]); - aurora->active[AURORA_REPLICA]= 1; + aurora->mysql[AURORA_REPLICA]= mysql; return 1; break; case AURORA_PRIMARY: - aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]); - aurora->pvio[AURORA_PRIMARY]= aurora->mysql[AURORA_PRIMARY]->net.pvio; - aurora->active[AURORA_PRIMARY]= 1; + if (!aurora->mysql[AURORA_PRIMARY]) + aurora->mysql[AURORA_PRIMARY]= mysql; + else + aurora_close_internal(mysql); continue; break; default: - mariadb_api->mysql_close(&mysql); + aurora_close_internal(mysql); return 0; break; } } + else + aurora_close_internal(mysql); valid_instances= aurora_get_valid_instances(aurora, instance); } return 0; @@ -488,99 +471,79 @@ my_bool aurora_find_primary(AURORA *aurora) { unsigned int i; AURORA_INSTANCE *instance= NULL; - MYSQL mysql; + MYSQL *mysql; my_bool check_primary= 1; + /* We try to find a primary: + * by looking 1st if a replica connect provided primary_id already + * by walking through instances */ + if (!aurora->num_instances) return 0; - mariadb_api->mysql_init(&mysql); - mysql.options= aurora->mysql[AURORA_PRIMARY]->options; - mysql.net.conn_hdlr= aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr; - for (i=0; i < aurora->num_instances; i++) { + mysql= mariadb_api->mysql_init(NULL); + mysql->options= aurora->save_mysql.options; + if (check_primary && aurora->primary_id[0]) { if ((instance= aurora_get_primary_id_instance(aurora)) && - aurora_connect_instance(aurora, instance, &mysql) && + aurora_connect_instance(aurora, instance, mysql) && instance->type == AURORA_PRIMARY) { - aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]); - aurora->active[AURORA_PRIMARY]= 1; + aurora->primary_id[0]= 0; + aurora->mysql[AURORA_PRIMARY]= mysql; return 1; } /* primary id connect failed, don't try again */ aurora->primary_id[0]= 0; check_primary= 0; } - if (aurora->instance[i].type != AURORA_UNAVAILABLE) + else if (aurora->instance[i].type != AURORA_UNAVAILABLE) { - if (aurora_connect_instance(aurora, &aurora->instance[i], &mysql) + if (aurora_connect_instance(aurora, &aurora->instance[i], mysql) && aurora->instance[i].type == AURORA_PRIMARY) { - aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]); - aurora->active[AURORA_PRIMARY]= 1; + aurora->mysql[AURORA_PRIMARY]= mysql; return 1; } } + aurora_close_internal(mysql); } return 0; } /* }}} */ -/* {{{ void aurora_close_replica() */ -void aurora_close_replica(MYSQL *mysql, AURORA *aurora) -{ - if (aurora->mysql[AURORA_REPLICA]) - { - aurora->mysql[AURORA_REPLICA]->net.pvio->mysql= aurora->mysql[AURORA_REPLICA]; - aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0; - mariadb_api->mysql_close(aurora->mysql[AURORA_REPLICA]); - aurora->pvio[AURORA_REPLICA]= 0; - aurora->mysql[AURORA_REPLICA]= NULL; - } -} -/* }}} */ - /* {{{ MYSQL *aurora_connect */ MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag) { AURORA *aurora= NULL; - MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; - my_bool is_reconnect= 0; + MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr; if (!mariadb_api) mariadb_api= mysql->methods->api; - if ((aurora= (AURORA *)hdlr->data)) - { - aurora_refresh_blacklist(aurora); - if (aurora->mysql[aurora->last_instance_type]->net.pvio) - { - mysql->methods->set_error(mysql, CR_ALREADY_CONNECTED, SQLSTATE_UNKNOWN, 0); - return NULL; - } - is_reconnect= 1; - } - else + /* we call aurora_connect either from mysql_real_connect or from mysql_reconnect, + * so make sure in case of reconnect we don't allocate aurora twice */ + if (!(aurora= (AURORA *)save_hdlr->data)) { if (!(aurora= (AURORA *)calloc(1, sizeof(AURORA)))) { mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); return NULL; } + aurora->save_mysql= *mysql; - mysql->net.conn_hdlr->data= (void *)aurora; - - aurora->mysql[AURORA_PRIMARY]= mysql; + save_hdlr->data= (void *)aurora; if (aurora_parse_url(host, aurora)) { goto error; } + /* store login credentials for connect/reconnect */ if (user) aurora->username= strdup(user); if (passwd) @@ -589,56 +552,35 @@ MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const ch aurora->database= strdup(db); aurora->port= port; aurora->client_flag= client_flag; - aurora->pvio[AURORA_PRIMARY]= aurora->pvio[AURORA_REPLICA]= NULL; - hdlr->data= aurora; } - - /* In case of reconnect, close broken connection first */ - if (is_reconnect) + /* we look for replica first: + if it's a primary we don't need to call find_aurora_primary + if it's a replica we can obtain primary_id */ + if (!aurora->mysql[AURORA_REPLICA]) { - DISABLE_AURORA(mysql); - switch (aurora->last_instance_type) { - case AURORA_REPLICA: - aurora_close_replica(mysql, aurora); - aurora->pvio[AURORA_REPLICA]= NULL; - break; - case AURORA_PRIMARY: - /* pvio will be closed in mysql_reconnect() */ - aurora->pvio[AURORA_PRIMARY]= NULL; - aurora->primary_id[0]= 0; - break; - } - aurora->active[aurora->last_instance_type]= 0; - } - - if (!aurora->active[AURORA_REPLICA]) - { - if (aurora_find_replica(aurora)) - { - aurora->pvio[AURORA_REPLICA]= aurora->mysql[AURORA_REPLICA]->net.pvio; - aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= mysql->net.conn_hdlr; - } + if (!aurora_find_replica(aurora)) + aurora->mysql[AURORA_REPLICA]= NULL; else - aurora->pvio[AURORA_REPLICA]= NULL; + aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= save_hdlr; } - if (!aurora->active[AURORA_PRIMARY]) + if (!aurora->mysql[AURORA_PRIMARY]) { - if (aurora_find_primary(aurora)) - { - aurora->active[AURORA_PRIMARY]= 1; - aurora->pvio[AURORA_PRIMARY]= aurora->mysql[AURORA_PRIMARY]->net.pvio; - } + if (!aurora_find_primary(aurora)) + aurora->mysql[AURORA_PRIMARY]= NULL; else - aurora->pvio[AURORA_PRIMARY]= NULL; + aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr= save_hdlr; } - if (!aurora->pvio[AURORA_PRIMARY] && !aurora->pvio[AURORA_REPLICA]) + if (!aurora->mysql[AURORA_PRIMARY] && !aurora->mysql[AURORA_REPLICA]) goto error; - aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); - ENABLE_AURORA(mysql); + if (aurora->mysql[AURORA_PRIMARY]) + aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + else + aurora_switch_connection(mysql, aurora, AURORA_REPLICA); + mysql->net.conn_hdlr= save_hdlr; return mysql; error: aurora_close_memory(aurora); @@ -650,28 +592,53 @@ error: my_bool aurora_reconnect(MYSQL *mysql) { AURORA *aurora; - MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; - my_bool rc= 1; + MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr; + int i; - aurora= (AURORA *)hdlr->data; + /* We can't determine if a new primary was promotoed, or if + * line just dropped - we will close both primary and replica + * connection and establish a new connection via + * aurora_connect */ - DISABLE_AURORA(mysql); - switch (aurora->last_instance_type) + aurora= (AURORA *)save_hdlr->data; + + /* removed blacklisted instances */ + for (i=0; i < aurora->num_instances; i++) + aurora->instance[i].type= AURORA_UNKNOWN; + + if (aurora->mysql[AURORA_PRIMARY]->thread_id == mysql->thread_id) { - case AURORA_REPLICA: - if (!(rc= mariadb_api->mysql_reconnect(aurora->mysql[aurora->last_instance_type]))) - aurora_switch_connection(mysql, aurora, AURORA_REPLICA); - break; - case AURORA_PRIMARY: - if (!(rc= mariadb_api->mysql_reconnect(aurora->mysql[aurora->last_instance_type]))) - aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); - break; - default: - /* todo: error message */ - break; + /* don't send COM_QUIT */ + aurora->mysql[AURORA_PRIMARY]->net.pvio= NULL; + aurora_close_internal(aurora->mysql[AURORA_PRIMARY]); + aurora->mysql[AURORA_PRIMARY]= NULL; + aurora_close_internal(aurora->mysql[AURORA_REPLICA]); + aurora->mysql[AURORA_REPLICA]= NULL; } - ENABLE_AURORA(mysql); - return rc; + else if (aurora->mysql[AURORA_REPLICA]->thread_id == mysql->thread_id) + { + /* don't send COM_QUIT */ + aurora->mysql[AURORA_REPLICA]->net.pvio= NULL; + aurora_close_internal(aurora->mysql[AURORA_REPLICA]); + aurora->mysql[AURORA_REPLICA]= NULL; + aurora_close_internal(aurora->mysql[AURORA_PRIMARY]); + aurora->mysql[AURORA_PRIMARY]= NULL; + } + + /* unset connections, so we can connect to primary and replica again */ + aurora->mysql[AURORA_PRIMARY]= aurora->mysql[AURORA_REPLICA]= NULL; + + if (aurora_connect(mysql, NULL, NULL, NULL, NULL, 0, NULL, 0)) + { + if (aurora->mysql[AURORA_PRIMARY]) + *mysql= *aurora->mysql[AURORA_PRIMARY]; + return 0; + } + if (aurora->mysql[AURORA_REPLICA]) + *mysql= *aurora->mysql[AURORA_REPLICA]; + else + *mysql= aurora->save_mysql; + return 1; } /* }}} */ @@ -679,41 +646,34 @@ my_bool aurora_reconnect(MYSQL *mysql) void aurora_close(MYSQL *mysql) { MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; - AURORA *aurora= (AURORA *)hdlr->data; + AURORA *aurora; + int i; - if (!aurora->pvio[AURORA_PRIMARY] && !aurora->pvio[AURORA_REPLICA]) - { + if (!hdlr || !hdlr->data) return; - } + + aurora= (AURORA *)hdlr->data; + *mysql= aurora->save_mysql; - aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + if (!aurora->mysql[AURORA_PRIMARY] && !aurora->mysql[AURORA_REPLICA]) + goto end; - /* if the connection is not active yet, just return */ - if (!aurora->active[1]) - return; - - if (aurora->mysql[AURORA_REPLICA]) + for (i=0; i < 2; i++) { - /* we got options from primary, so don't free it twice */ - memset(&aurora->mysql[AURORA_REPLICA]->options, 0, sizeof(mysql->options)); - /* connection handler wull be freed in mariadb_api->mysql_close() */ - aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0; + if (aurora->mysql[i]) + { + /* Make sure that connection wasn't closed before, e.g. after disconnect */ + if (mysql->thread_id == aurora->mysql[i]->thread_id && !mysql->net.pvio) + aurora->mysql[i]->net.pvio= 0; - mariadb_api->mysql_close(aurora->mysql[AURORA_REPLICA]); + aurora_close_internal(aurora->mysql[i]); + aurora->mysql[i]= NULL; + } } - - if (aurora->mysql[AURORA_PRIMARY]) - { - /* connection handler wull be freed in mysql_close() */ - aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr= 0; - - aurora->mysql[AURORA_PRIMARY]->net.pvio= aurora->pvio[AURORA_PRIMARY]; - - mariadb_api->mysql_close(aurora->mysql[AURORA_PRIMARY]); - } - /* free information */ +end: aurora_close_memory(aurora); + mysql->net.conn_hdlr= hdlr; } /* }}} */ @@ -756,7 +716,8 @@ my_bool is_replica_stmt(MYSQL *mysql, const char *buffer) int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *arg, size_t length, my_bool skipp_check, void *opt_arg) { - AURORA *aurora= (AURORA *)mysql->net.conn_hdlr->data; + MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr; + AURORA *aurora= (AURORA *)save_hdlr->data; /* if we don't have slave or slave became unavailable root traffic to master */ if (!aurora->mysql[AURORA_REPLICA] || !OPT_HAS_EXT_VAL(mysql, read_only)) @@ -764,54 +725,43 @@ int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *ar if (command != COM_INIT_DB) { aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); - return 0; + goto end; } } switch(command) { case COM_INIT_DB: /* we need to change default database on primary and replica */ - if (aurora->mysql[AURORA_REPLICA] && aurora->last_instance_type != AURORA_REPLICA) + if (aurora->mysql[AURORA_REPLICA] && mysql->thread_id == aurora->mysql[AURORA_PRIMARY]->thread_id) { - aurora_switch_connection(mysql, aurora, AURORA_REPLICA); - DISABLE_AURORA(mysql); + aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0; mariadb_api->mysql_select_db(aurora->mysql[AURORA_REPLICA], arg); - ENABLE_AURORA(mysql); - aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= mysql->net.conn_hdlr; } break; case COM_QUERY: case COM_STMT_PREPARE: - if (aurora->mysql[AURORA_REPLICA] && aurora->last_instance_type != AURORA_REPLICA) + if (aurora->mysql[AURORA_REPLICA]) aurora_switch_connection(mysql, aurora, AURORA_REPLICA); break; case COM_STMT_EXECUTE: case COM_STMT_FETCH: - if (aurora->pvio[AURORA_REPLICA]->mysql->stmts && is_replica_stmt(aurora->pvio[AURORA_REPLICA]->mysql, arg)) + if (aurora->mysql[AURORA_REPLICA] && aurora->mysql[AURORA_REPLICA]->stmts && + is_replica_stmt(aurora->mysql[AURORA_REPLICA], arg)) { - if (aurora->last_instance_type != AURORA_REPLICA) - aurora_switch_connection(mysql, aurora, AURORA_REPLICA); + aurora_switch_connection(mysql, aurora, AURORA_REPLICA); } else { - if (aurora->last_instance_type != AURORA_PRIMARY) - aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); } default: aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); break; } +end: + mysql->net.conn_hdlr= save_hdlr; return 0; } /* }}} */ - -/* {{{ int aurora_set_options() */ -int aurora_set_options(MYSQL *mysql, enum mysql_option option, void *arg) -{ - switch(option) { - default: - return -1; - } -} -/* }}} */ diff --git a/plugins/connection/replication.c b/plugins/connection/replication.c index 9b4d1865..6bb74cef 100644 --- a/plugins/connection/replication.c +++ b/plugins/connection/replication.c @@ -202,8 +202,8 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char goto error; /* try to connect to master */ - if (!(mysql->methods->db_connect(mysql, data->host[MARIADB_MASTER], user, passwd, db, - data->port[MARIADB_MASTER] ? data->port[MARIADB_MASTER] : port, unix_socket, clientflag))) + if (!(mariadb_api->mysql_real_connect(mysql, data->host[MARIADB_MASTER], user, passwd, db, + data->port[MARIADB_MASTER] ? data->port[MARIADB_MASTER] : port, unix_socket, clientflag))) goto error; data->pvio[MARIADB_MASTER]= mysql->net.pvio; diff --git a/unittest/libmariadb/basic-t.c b/unittest/libmariadb/basic-t.c index 02dcc294..ff4fc547 100644 --- a/unittest/libmariadb/basic-t.c +++ b/unittest/libmariadb/basic-t.c @@ -35,11 +35,11 @@ static int test_conc75(MYSQL *my) int rc; MYSQL *mysql; int i; + my_bool reconnect= 1; mysql= mysql_init(NULL); - - mysql->reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS); rc= mysql_query(mysql, "DROP TABLE IF EXISTS a"); @@ -55,7 +55,7 @@ static int test_conc75(MYSQL *my) { ulong thread_id= mysql_thread_id(mysql); /* force reconnect */ - mysql->reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); diag("killing connection"); mysql_kill(my, thread_id); sleep(2); @@ -700,6 +700,7 @@ static int test_reconnect_maxpackage(MYSQL *my) MYSQL_RES *res; MYSQL_ROW row; char *query; + my_bool reconnect= 1; SKIP_CONNECTION_HANDLER; mysql= mysql_init(NULL); @@ -707,7 +708,7 @@ static int test_reconnect_maxpackage(MYSQL *my) FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql)); - mysql->reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); rc= mysql_query(mysql, "SELECT @@max_allowed_packet"); check_mysql_rc(rc, mysql); @@ -753,12 +754,13 @@ static int test_compressed(MYSQL *my) int rc; MYSQL *mysql= mysql_init(NULL); MYSQL_RES *res; + my_bool reconnect= 1; mysql_options(mysql, MYSQL_OPT_COMPRESS, (void *)1); FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql)); - mysql->reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); rc= mysql_query(mysql, "SHOW VARIABLES"); check_mysql_rc(rc, mysql); diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index 0d81b6c7..fe1f220b 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -455,16 +455,21 @@ static int test_opt_reconnect(MYSQL *mysql) { my_bool my_true= TRUE; int rc; + my_bool reconnect; + + printf("true: %d\n", TRUE); mysql= mysql_init(NULL); FAIL_IF(!mysql, "not enough memory"); - FAIL_UNLESS(mysql->reconnect == 0, "reconnect != 0"); + mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 0, "reconnect != 0"); rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, &my_true); check_mysql_rc(rc, mysql); - FAIL_UNLESS(mysql->reconnect == 1, "reconnect != 1"); + mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 1, "reconnect != 1"); if (!(mysql_real_connect(mysql, hostname, username, password, schema, port, @@ -475,14 +480,16 @@ static int test_opt_reconnect(MYSQL *mysql) return FAIL; } - FAIL_UNLESS(mysql->reconnect == 1, "reconnect != 1"); + mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 1, "reconnect != 1"); mysql_close(mysql); mysql= mysql_init(NULL); FAIL_IF(!mysql, "not enough memory"); - FAIL_UNLESS(mysql->reconnect == 0, "reconnect != 0"); + mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 0, "reconnect != 0"); if (!(mysql_real_connect(mysql, hostname, username, password, schema, port, @@ -493,7 +500,8 @@ static int test_opt_reconnect(MYSQL *mysql) return FAIL; } - FAIL_UNLESS(mysql->reconnect == 0, "reconnect != 0"); + mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 0, "reconnect != 0"); mysql_close(mysql); return OK; @@ -538,16 +546,19 @@ static int test_reconnect(MYSQL *mysql) my_bool my_true= TRUE; MYSQL *mysql1; int rc; + my_bool reconnect; mysql1= mysql_init(NULL); FAIL_IF(!mysql1, "not enough memory"); - FAIL_UNLESS(mysql1->reconnect == 0, "reconnect != 0"); + mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 0, "reconnect != 0"); rc= mysql_options(mysql1, MYSQL_OPT_RECONNECT, &my_true); check_mysql_rc(rc, mysql1); - FAIL_UNLESS(mysql1->reconnect == 1, "reconnect != 1"); + mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 1, "reconnect != 1"); if (!(mysql_real_connect(mysql1, hostname, username, password, schema, port, @@ -558,7 +569,8 @@ static int test_reconnect(MYSQL *mysql) return FAIL; } - FAIL_UNLESS(mysql1->reconnect == 1, "reconnect != 1"); + mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 1, "reconnect != 1"); diag("Thread_id before kill: %lu", mysql_thread_id(mysql1)); mysql_kill(mysql, mysql_thread_id(mysql1)); @@ -570,7 +582,8 @@ static int test_reconnect(MYSQL *mysql) check_mysql_rc(rc, mysql1); diag("Thread_id after kill: %lu", mysql_thread_id(mysql1)); - FAIL_UNLESS(mysql1->reconnect == 1, "reconnect != 1"); + mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 1, "reconnect != 1"); mysql_close(mysql1); return OK; } @@ -647,8 +660,10 @@ int test_connection_timeout(MYSQL *my) static int test_conc118(MYSQL *mysql) { int rc; + my_bool reconnect= 1; + + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); - mysql->reconnect= 1; mysql->options.unused_1= 1; rc= mysql_kill(mysql, mysql_thread_id(mysql)); @@ -745,9 +760,10 @@ static int test_bind_address(MYSQL *my) static int test_get_options(MYSQL *my) { MYSQL *mysql= mysql_init(NULL); - int options_int[]= {MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_LOCAL_INFILE, - MYSQL_OPT_RECONNECT, MYSQL_OPT_PROTOCOL, MYSQL_OPT_READ_TIMEOUT, MYSQL_OPT_WRITE_TIMEOUT, 0}; - my_bool options_bool[]= {MYSQL_OPT_COMPRESS, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_SECURE_AUTH, + int options_int[]= {MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_LOCAL_INFILE, + MYSQL_OPT_PROTOCOL, MYSQL_OPT_READ_TIMEOUT, MYSQL_OPT_WRITE_TIMEOUT, 0}; + my_bool options_bool[]= {MYSQL_OPT_RECONNECT, MYSQL_REPORT_DATA_TRUNCATION, + MYSQL_OPT_COMPRESS, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_SECURE_AUTH, #ifdef _WIN32 MYSQL_OPT_NAMED_PIPE, #endif diff --git a/unittest/libmariadb/misc.c b/unittest/libmariadb/misc.c index 13dd8697..bb179128 100644 --- a/unittest/libmariadb/misc.c +++ b/unittest/libmariadb/misc.c @@ -957,6 +957,7 @@ static int test_conc_114(MYSQL *mysql) /* run with valgrind */ static int test_conc117(MYSQL *mysql) { + my_bool reconnect= 1; MYSQL *my= mysql_init(NULL); FAIL_IF(!mysql_real_connect(my, hostname, username, password, schema, port, socketname, 0), mysql_error(my)); @@ -964,7 +965,7 @@ static int test_conc117(MYSQL *mysql) mysql_kill(my, mysql_thread_id(my)); sleep(5); - my->reconnect= 1; + mysql_options(my, MYSQL_OPT_RECONNECT, &reconnect); mysql_query(my, "SET @a:=1"); mysql_close(my); diff --git a/unittest/libmariadb/my_test.h b/unittest/libmariadb/my_test.h index e0db2beb..c756318f 100644 --- a/unittest/libmariadb/my_test.h +++ b/unittest/libmariadb/my_test.h @@ -374,7 +374,6 @@ int check_variable(MYSQL *mysql, char *variable, char *value) */ MYSQL *test_connect(struct my_tests_st *test) { MYSQL *mysql; - char query[255]; int i= 0; int timeout= 10; int truncation_report= 1; @@ -401,7 +400,7 @@ MYSQL *test_connect(struct my_tests_st *test) { } } if (!(mysql_real_connect(mysql, hostname, username, password, - NULL, port, socketname, (test) ? test->connect_flags:0))) + schema, port, socketname, (test) ? test->connect_flags:0))) { diag("Couldn't establish connection to server %s. Error (%d): %s", hostname, mysql_errno(mysql), mysql_error(mysql)); @@ -409,24 +408,6 @@ MYSQL *test_connect(struct my_tests_st *test) { return(NULL); } - /* change database or create if it doesn't exist */ - if (mysql_select_db(mysql, schema)) { - diag("Error number: %d", mysql_errno(mysql)); - - if(mysql_errno(mysql) == 1049) { - sprintf(query, "CREATE DATABASE %s", schema); - if (mysql_query(mysql, query)) { - diag("Can't create database %s", schema); - mysql_close(mysql); - return NULL; - } - } else { - diag("Error (%d): %s", mysql_errno(mysql), mysql_error(mysql)); - mysql_close(mysql); - return NULL; - } - } - return(mysql); } @@ -526,6 +507,7 @@ void run_tests(struct my_tests_st *test) { } } if (mysql_default) { + diag("close default"); mysql_close(mysql_default); } mysql_server_end(); diff --git a/unittest/libmariadb/ps.c b/unittest/libmariadb/ps.c index add7a493..d6545a21 100644 --- a/unittest/libmariadb/ps.c +++ b/unittest/libmariadb/ps.c @@ -52,12 +52,13 @@ static int test_conc83(MYSQL *my) MYSQL_STMT *stmt; int rc; MYSQL *mysql= mysql_init(NULL); + my_bool reconnect= 1; char *query= "SELECT 1,2,3 FROM DUAL"; stmt= mysql_stmt_init(mysql); - mysql->reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); FAIL_IF(!(mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0)), "mysql_real_connect failed"); @@ -4544,9 +4545,9 @@ static int test_stmt_close(MYSQL *mysql) unsigned int count; int rc; char query[MAX_TEST_QUERY_LENGTH]; + my_bool reconnect= 1; - - mysql->reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); /* set AUTOCOMMIT to ON*/ mysql_autocommit(mysql, TRUE); @@ -4644,9 +4645,8 @@ static int test_new_date(MYSQL *mysql) MYSQL_BIND bind[1]; int rc; char buffer[50]; - - - mysql->reconnect= 1; + my_bool reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); /* set AUTOCOMMIT to ON*/ mysql_autocommit(mysql, TRUE); diff --git a/unittest/libmariadb/result.c b/unittest/libmariadb/result.c index 885b70bc..69293b1b 100644 --- a/unittest/libmariadb/result.c +++ b/unittest/libmariadb/result.c @@ -932,6 +932,7 @@ select 1;\ DROP TABLE IF EXISTS test_multi_tab"; uint count, exp_value; uint rows[]= {0, 0, 2, 1, 3, 2, 2, 1, 1, 0, 0, 1, 0}; + my_bool reconnect= 1; /* First test that we get an error for multi statements @@ -950,7 +951,7 @@ DROP TABLE IF EXISTS test_multi_tab"; mysql_close(mysql); mysql= mysql_local; - mysql_local->reconnect= 1; + mysql_options(mysql_local, MYSQL_OPT_RECONNECT, &reconnect); rc= mysql_query(mysql_local, query); check_mysql_rc(rc, mysql); diff --git a/unittest/libmariadb/t_aurora.c b/unittest/libmariadb/t_aurora.c index 4336a3c5..0b9c0241 100644 --- a/unittest/libmariadb/t_aurora.c +++ b/unittest/libmariadb/t_aurora.c @@ -4,12 +4,20 @@ #include "my_test.h" #include "ma_pvio.h" -static int aurora1(MYSQL *mysql) +static int aurora1(MYSQL *my) { int rc; my_bool read_only= 1; - const char *primary, *schema; + const char *primary, *my_schema; MYSQL_RES *res; + MYSQL *mysql= mysql_init(NULL); + + if (!mysql_real_connect(mysql, hostname, username, password, schema, port, NULL, 0)) + { + diag("Error: %s", mysql_error(mysql)); + mysql_close(mysql); + return FAIL; + } rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); check_mysql_rc(rc, mysql); @@ -38,8 +46,10 @@ static int aurora1(MYSQL *mysql) diag("Num_rows: %d", mysql_num_rows(res)); mysql_free_result(res); - mariadb_get_infov(mysql, MARIADB_CONNECTION_SCHEMA, &schema); - diag("db: %s", schema); + mariadb_get_infov(mysql, MARIADB_CONNECTION_SCHEMA, &my_schema); + diag("db: %s", my_schema); + + mysql_close(mysql); return OK; } @@ -58,16 +68,86 @@ static int test_wrong_user(MYSQL *my) return OK; } +static int test_reconnect(MYSQL *my) +{ + MYSQL *mysql= mysql_init(NULL); + MYSQL_RES *res; + my_bool read_only= 1; + int rc; + my_bool reconnect= 1; + const char *aurora_host; + + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); + + if (!mysql_real_connect(mysql, hostname, username, password, schema, port, NULL, 0)) + { + diag("Error: %s", mysql_error(mysql)); + mysql_close(mysql); + return FAIL; + } + + mariadb_get_infov(mysql, MARIADB_CONNECTION_HOST, &aurora_host); + diag("host: %s", aurora_host); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS tx01"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE tx01 (a int)"); + check_mysql_rc(rc, mysql); + + /* we force cluster restart and promoting new primary: + * we wait for 50 seconds - however there is no guarantee that + * cluster was restarted already - so this test might fail */ + system("/usr/local/aws/bin/aws rds failover-db-cluster --db-cluster-identifier instance-1-cluster"); + + sleep(50); + diag("Q1"); + rc= mysql_query(mysql, "INSERT INTO tx01 VALUES (1)"); + if (!rc) + diag("error expected!"); + diag("Error: %s", mysql_error(mysql)); + + diag("Q2"); + rc= mysql_query(mysql, "INSERT INTO tx01 VALUES (1)"); + if (rc) + { + diag("no error expected!"); + diag("Error: %s", mysql_error(mysql)); + diag("host: %s", mysql->host); + } + else + { + mariadb_get_infov(mysql, MARIADB_CONNECTION_HOST, &aurora_host); + diag("host: %s", aurora_host); + } + + mysql_options(mysql, MARIADB_OPT_CONNECTION_READ_ONLY, &read_only); + + rc= mysql_query(mysql, "SELECT * from tx01"); + check_mysql_rc(rc, mysql); + + if ((res= mysql_store_result(mysql))) + { + diag("num_rows: %d", mysql_num_rows(res)); + mysql_free_result(res); + } + + mariadb_get_infov(mysql, MARIADB_CONNECTION_HOST, &aurora_host); + diag("host: %s", aurora_host); + + mysql_close(mysql); + return OK; +} + struct my_tests_st my_tests[] = { - {"aurora1", aurora1, TEST_CONNECTION_NEW, 0, NULL, NULL}, + {"aurora1", aurora1, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_wrong_user", test_wrong_user, TEST_CONNECTION_NONE, 0, NULL, NULL}, + {"test_reconnect", test_reconnect, TEST_CONNECTION_NONE, 0, NULL, NULL}, {NULL, NULL, 0, 0, NULL, NULL} }; int main(int argc, char **argv) { - mysql_library_init(0,0,NULL); if (argc > 1) From f9232bacffe7a2c3d6b2e9bfb250428d8ff8a731 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 18 Jan 2016 06:36:38 +0100 Subject: [PATCH 29/40] Fixed redefinition for ssl structure --- include/ma_pvio.h | 6 ------ include/mysql.h | 8 ++++---- libmariadb/CMakeLists.txt | 2 +- libmariadb/libmariadb.c | 8 +------- unittest/libmariadb/misc.c | 2 +- 5 files changed, 7 insertions(+), 19 deletions(-) diff --git a/include/ma_pvio.h b/include/ma_pvio.h index 7ac4be94..4d1a5a45 100644 --- a/include/ma_pvio.h +++ b/include/ma_pvio.h @@ -28,12 +28,6 @@ typedef struct st_ma_pvio_methods PVIO_METHODS; #define IS_MYSQL_ASYNC_ACTIVE(a) \ (IS_MYSQL_ASYNC(a)&& (a)->options.extension->async_context->active) -#ifndef ssl_defined -#define ssl_defined -struct st_ma_pvio_ssl; -typedef struct st_ma_pvio_ssl MARIADB_SSL; -#endif - enum enum_pvio_timeout { PVIO_CONNECT_TIMEOUT= 0, PVIO_READ_TIMEOUT, diff --git a/include/mysql.h b/include/mysql.h index b6078699..f9d03294 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -222,16 +222,15 @@ extern unsigned int mariadb_deinitialize_ssl; enum mariadb_value { MARIADB_CHARSET_ID, - MARIADB_CHARSET_INFO, MARIADB_CHARSET_NAME, MARIADB_CLIENT_ERRORS, MARIADB_CLIENT_VERSION, MARIADB_CLIENT_VERSION_ID, - MARIADB_CONNECTION_ERROR, - MARIADB_CONNECTION_ERROR_ID, - MARIADB_CONNECTION_SQLSTATE, MARIADB_CONNECTION_ASYNC_TIMEOUT, MARIADB_CONNECTION_ASYNC_TIMEOUT_MS, + MARIADB_CONNECTION_CHARSET_INFO, + MARIADB_CONNECTION_ERROR, + MARIADB_CONNECTION_ERROR_ID, MARIADB_CONNECTION_HOST, MARIADB_CONNECTION_INFO, MARIADB_CONNECTION_PORT, @@ -242,6 +241,7 @@ extern unsigned int mariadb_deinitialize_ssl; MARIADB_CONNECTION_SERVER_VERSION, MARIADB_CONNECTION_SERVER_VERSION_ID, MARIADB_CONNECTION_SOCKET, + MARIADB_CONNECTION_SQLSTATE, MARIADB_CONNECTION_SSL_CIPHER, MARIADB_CONNECTION_SSL_LIBRARY, MARIADB_CONNECTION_SSL_VERSION, diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index 1f4dac70..26767358 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -112,7 +112,7 @@ SET(EXPORT_SYMBOLS mysql_list_tables mysql_list_tables_cont mysql_list_tables_start - mysql_load_plugin; + mysql_load_plugin mysql_load_plugin_v mysql_more_results mysql_next_result diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 9a960ab7..a5ec2869 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -2691,12 +2691,6 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) mysql->options.reconnect= *(uint *)arg1; break; case MYSQL_OPT_PROTOCOL: -#ifdef _WIN32 - if (*(uint *)arg1 > MYSQL_PROTOCOL_PIPE) -#else - if (*(uint *)arg1 > MYSQL_PROTOCOL_SOCKET) -#endif - goto end; mysql->options.protocol= *(uint *)arg1; break; case MYSQL_OPT_READ_TIMEOUT: @@ -3682,7 +3676,7 @@ my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void * else goto error; break; - case MARIADB_CHARSET_INFO: + case MARIADB_CONNECTION_CHARSET_INFO: if (mysql) mariadb_get_charset_info(mysql, (MY_CHARSET_INFO *)arg); else diff --git a/unittest/libmariadb/misc.c b/unittest/libmariadb/misc.c index bb179128..dd156fe8 100644 --- a/unittest/libmariadb/misc.c +++ b/unittest/libmariadb/misc.c @@ -1045,7 +1045,7 @@ static int test_get_info(MYSQL *mysql) rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_VERSION_ID, &sval); FAIL_IF(rc, "mysql_get_info failed"); diag("server_version_id: %d", sval); - rc= mariadb_get_infov(mysql, MARIADB_CHARSET_INFO, &cs); + rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_CHARSET_INFO, &cs); FAIL_IF(rc, "mysql_get_info failed"); diag("charset name: %s", cs.csname); rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_PVIO_TYPE, &ival); From fdaa90e64771dc77dfe51426911be544e0c23c2f Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 18 Jan 2016 10:34:45 +0100 Subject: [PATCH 30/40] Wix installer fixes Added lib and lib/plugin to PATH --- cmake/plugins.cmake | 4 ++-- win/packaging/mariadb-connector-c.xml.in | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/plugins.cmake b/cmake/plugins.cmake index dc63253f..7a4530c6 100644 --- a/cmake/plugins.cmake +++ b/cmake/plugins.cmake @@ -45,8 +45,8 @@ ENDIF() REGISTER_PLUGIN("TRACE_EXAMPLE" "${CMAKE_SOURCE_DIR}/plugins/trace/trace_example.c" "trace_example_plugin" "DYNAMIC" "trace_example" 1) #Connection -REGISTER_PLUGIN("REPLICATION" "${CMAKE_SOURCE_DIR}/plugins/connection/replication.c" "connection_replication_plugin" "DYNAMIC" "" 1) -REGISTER_PLUGIN("AURORA" "${CMAKE_SOURCE_DIR}/plugins/connection/aurora.c" "connection_aurora_plugin" "DYNAMIC" "" 1) +REGISTER_PLUGIN("REPLICATION" "${CMAKE_SOURCE_DIR}/plugins/connection/replication.c" "connection_replication_plugin" "DYNAMIC" "replication" 1) +REGISTER_PLUGIN("AURORA" "${CMAKE_SOURCE_DIR}/plugins/connection/aurora.c" "connection_aurora_plugin" "DYNAMIC" "aurora" 1) # Allow registration of additional plugins IF(PLUGIN_CONF_FILE) diff --git a/win/packaging/mariadb-connector-c.xml.in b/win/packaging/mariadb-connector-c.xml.in index 4213bbed..38e648e1 100644 --- a/win/packaging/mariadb-connector-c.xml.in +++ b/win/packaging/mariadb-connector-c.xml.in @@ -51,6 +51,7 @@ + @@ -61,6 +62,7 @@ Source="@CLIENT_BIN_DIR@/mariadb_client_plugin_info.exe" /> + @MARIADB_PLUGINS@ From 7c7fae22864f218e6e922c58d8ddfc63c8246edd Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 18 Jan 2016 10:42:12 +0100 Subject: [PATCH 31/40] Added include path for connection plugins --- plugins/connection/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/connection/CMakeLists.txt b/plugins/connection/CMakeLists.txt index c9cc1932..f57d08a5 100644 --- a/plugins/connection/CMakeLists.txt +++ b/plugins/connection/CMakeLists.txt @@ -3,6 +3,7 @@ IF(WIN32) ENDIF() SET(CMAKE_SHARED_LIBRARY_PREFIX "") +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC") IF(WIN32) From 9a5904a52f83b1e594d72d0e8c744c419576c6b1 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 18 Jan 2016 11:32:41 +0100 Subject: [PATCH 32/40] Don't build remote io on Windows as "static", since curl libraries are not installed by default on Windows --- cmake/plugins.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/plugins.cmake b/cmake/plugins.cmake index 7a4530c6..740709b8 100644 --- a/cmake/plugins.cmake +++ b/cmake/plugins.cmake @@ -38,7 +38,11 @@ REGISTER_PLUGIN("AUTH_CLEARTEXT" "${CMAKE_SOURCE_DIR}/plugins/auth/mariadb_clear #Remote_IO IF(CURL_FOUND) - REGISTER_PLUGIN("REMOTEIO" "${CMAKE_SOURCE_DIR}/plugins/io/remote_io.c" "remote_io_plugin" "STATIC" "remote_io" 1) + IF(WIN32) + REGISTER_PLUGIN("REMOTEIO" "${CMAKE_SOURCE_DIR}/plugins/io/remote_io.c" "remote_io_plugin" "DYNAMIC" "remote_io" 1) + ELSE() + REGISTER_PLUGIN("REMOTEIO" "${CMAKE_SOURCE_DIR}/plugins/io/remote_io.c" "remote_io_plugin" "STATIC" "remote_io" 1) + ENDIF() ENDIF() #Trace From 8b3099b319dbd198f6d6f1bbb6ae6784d7b1f1fe Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 18 Jan 2016 13:22:34 +0100 Subject: [PATCH 33/40] Fix unsresolved external for remoteio plugin (windows) --- plugins/io/remote_io.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/io/remote_io.c b/plugins/io/remote_io.c index 1d30ebcb..411aa3c5 100644 --- a/plugins/io/remote_io.c +++ b/plugins/io/remote_io.c @@ -54,6 +54,8 @@ #include #ifndef WIN32 #include +#else +#pragma comment(lib, "Ws2_32.lib") #endif #include #include From f0215ab09159bd73bb482c0f59210e53bc6669d3 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Fri, 22 Jan 2016 20:00:40 +0100 Subject: [PATCH 34/40] Added GSSAPI authentication plugin --- CMakeLists.txt | 11 ++ cmake/CheckIncludeFiles.cmake | 1 + cmake/plugins.cmake | 9 ++ include/my_config.h.in | 1 + include/my_context.h | 2 +- libmariadb/libmariadb.c | 3 + libmariadb/my_context.c | 1 + libmariadb/my_stmt.c | 3 + plugins/auth/CMakeLists.txt | 34 ++++ plugins/auth/auth_gssapi_client.c | 119 ++++++++++++++ plugins/auth/common.h | 4 + plugins/auth/gssapi_client.c | 127 +++++++++++++++ plugins/auth/gssapi_errmsg.c | 75 +++++++++ plugins/auth/gssapi_errmsg.h | 29 ++++ plugins/auth/server_plugin.h | 51 ++++++ plugins/auth/sspi_client.c | 183 ++++++++++++++++++++++ plugins/auth/sspi_common.h | 38 +++++ plugins/auth/sspi_errmsg.c | 150 ++++++++++++++++++ unittest/libmariadb/certs/create_certs.sh | 15 ++ unittest/libmariadb/certs/dummy.pem | 21 +++ unittest/libmariadb/my_test.h | 4 + unittest/libmariadb/ps.c | 6 +- 22 files changed, 883 insertions(+), 4 deletions(-) create mode 100644 plugins/auth/auth_gssapi_client.c create mode 100644 plugins/auth/common.h create mode 100644 plugins/auth/gssapi_client.c create mode 100644 plugins/auth/gssapi_errmsg.c create mode 100644 plugins/auth/gssapi_errmsg.h create mode 100644 plugins/auth/server_plugin.h create mode 100644 plugins/auth/sspi_client.c create mode 100644 plugins/auth/sspi_common.h create mode 100644 plugins/auth/sspi_errmsg.c create mode 100755 unittest/libmariadb/certs/create_certs.sh create mode 100644 unittest/libmariadb/certs/dummy.pem diff --git a/CMakeLists.txt b/CMakeLists.txt index f7715716..7fd67723 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -258,6 +258,17 @@ IF(NOT REMOTEIO_PLUGIN_TYPE MATCHES "OFF") ADD_DEFINITIONS("-DHAVE_REMOTEIO=1") ENDIF() ENDIF() +IF(NOT WIN32) + IF(NOT AUTH_GSSAPI_PLUGIN_TYPE MATCHES "OFF") + INCLUDE(${CMAKE_SOURCE_DIR}/cmake/FindGSSAPI.cmake) + IF(GSSAPI_FOUND) + INCLUDE_DIRECTORIES(${GSSAPI_INCS}) + IF(AUTH_GSSAPI_PLUGIN_TYPE MATCHES "STATIC") + SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${GSSAPI_LIBS}) + ENDIF() + ENDIF() + ENDIF() +ENDIF() ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(libmariadb) ADD_SUBDIRECTORY(plugins) diff --git a/cmake/CheckIncludeFiles.cmake b/cmake/CheckIncludeFiles.cmake index f5dde977..5aaabc8e 100644 --- a/cmake/CheckIncludeFiles.cmake +++ b/cmake/CheckIncludeFiles.cmake @@ -66,3 +66,4 @@ CHECK_INCLUDE_FILES (termio.h HAVE_TERMIO_H) CHECK_INCLUDE_FILES (termios.h HAVE_TERMIOS_H) CHECK_INCLUDE_FILES (unistd.h HAVE_UNISTD_H) CHECK_INCLUDE_FILES (utime.h HAVE_UTIME_H) +CHECK_INCLUDE_FILES (ucontext.h HAVE_UCONTEXT_H) diff --git a/cmake/plugins.cmake b/cmake/plugins.cmake index 740709b8..71e47285 100644 --- a/cmake/plugins.cmake +++ b/cmake/plugins.cmake @@ -35,6 +35,15 @@ REGISTER_PLUGIN("AUTH_NATIVE" "${CMAKE_SOURCE_DIR}/plugins/auth/my_auth.c" "nati REGISTER_PLUGIN("AUTH_OLDPASSWORD" "${CMAKE_SOURCE_DIR}/plugins/auth/old_password.c" "old_password_client_plugin" "DYNAMIC" "old_password" 1) REGISTER_PLUGIN("AUTH_DIALOG" "${CMAKE_SOURCE_DIR}/plugins/auth/dialog.c" "auth_dialog_plugin" "DYNAMIC" dialog 1) REGISTER_PLUGIN("AUTH_CLEARTEXT" "${CMAKE_SOURCE_DIR}/plugins/auth/mariadb_clear_text.c" "auth_cleartext_plugin" "DYNAMIC" "mysql_clear_password" 1) +IF(WIN32) + SET(GSSAPI_SOURCES ${CMAKE_SOURCE_DIR}/plugins/auth/auth_gssapi_client.c ${CMAKE_SOURCE_DIR}/plugins/auth/sspi_client.c ${CMAKE_SOURCE_DIR}/plugins/auth/sspi_errmsg.c) + REGISTER_PLUGIN("AUTH_GSSAPI" "${GSSAPI_SOURCES}" "auth_gssapi_plugin" "DYNAMIC" "auth_gssapi_client" 1) +ELSE() + IF(GSSAPI_FOUND) + SET(GSSAPI_SOURCES ${CMAKE_SOURCE_DIR}/plugins/auth/auth_gssapi_client.c ${CMAKE_SOURCE_DIR}/plugins/auth/gssapi_client.c ${CMAKE_SOURCE_DIR}/plugins/auth/gssapi_errmsg.c) + REGISTER_PLUGIN("AUTH_GSSAPI" "${GSSAPI_SOURCES}" "auth_gssapi_plugin" "DYNAMIC" "auth_gssapi_client" 1) + ENDIF() +ENDIF() #Remote_IO IF(CURL_FOUND) diff --git a/include/my_config.h.in b/include/my_config.h.in index a1181d0b..dc187721 100644 --- a/include/my_config.h.in +++ b/include/my_config.h.in @@ -46,6 +46,7 @@ #cmakedefine HAVE_TERMIOS_H 1 #cmakedefine HAVE_UNISTD_H 1 #cmakedefine HAVE_UTIME_H 1 +#cmakedefine HAVE_UCONTEXT_H 1 /* * function definitions - processed in LibmysqlFunctions.txt diff --git a/include/my_context.h b/include/my_context.h index b66482a4..2cc40d25 100644 --- a/include/my_context.h +++ b/include/my_context.h @@ -31,7 +31,7 @@ #define MY_CONTEXT_USE_X86_64_GCC_ASM #elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__i386__) #define MY_CONTEXT_USE_I386_GCC_ASM -#elif defined(HAVE_UCONTEXT) +#elif defined(HAVE_UCONTEXT_H) #define MY_CONTEXT_USE_UCONTEXT #else #define MY_CONTEXT_DISABLE diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index a5ec2869..2d305089 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -2147,6 +2147,9 @@ mysql_real_query(MYSQL *mysql, const char *query, size_t length) DBUG_PRINT("enter",("handle: %lx",mysql)); DBUG_PRINT("query",("Query = \"%.255s\" length=%u",query, length)); + if (length == -1) + length= strlen(query); + free_old_query(mysql); if (simple_command(mysql, COM_QUERY,query,length,1,0)) diff --git a/libmariadb/my_context.c b/libmariadb/my_context.c index 545cfe8e..0fda2a73 100644 --- a/libmariadb/my_context.c +++ b/libmariadb/my_context.c @@ -20,6 +20,7 @@ swapcontext(). */ +#include "my_global.h" #include "mysys_priv.h" #include "m_string.h" #include "my_context.h" diff --git a/libmariadb/my_stmt.c b/libmariadb/my_stmt.c index 58a5c951..ea9e9bee 100644 --- a/libmariadb/my_stmt.c +++ b/libmariadb/my_stmt.c @@ -1227,6 +1227,9 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, size_t lengt int rc= 1; DBUG_ENTER("mysql_stmt_prepare"); + if (length == -1) + length= strlen(query); + if (!stmt->mysql) { SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0); diff --git a/plugins/auth/CMakeLists.txt b/plugins/auth/CMakeLists.txt index f32ba1b2..7dedb9d1 100644 --- a/plugins/auth/CMakeLists.txt +++ b/plugins/auth/CMakeLists.txt @@ -1,4 +1,5 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/plugins/auth) INCLUDE(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) IF(WITH_SIGNCODE) @@ -64,3 +65,36 @@ IF(AUTH_CLEARTEXT_PLUGIN_TYPE MATCHES "DYNAMIC") INSTALL_PLUGIN(mysql_clear_password ${CMAKE_BINARY_DIR}/plugins/auth) SIGN_TARGET(mysql_clear_password) ENDIF() + +# SSPI/GSSAPI plugin +IF(WIN32) + SET(USE_SSPI 1) +ENDIF() + +MESSAGE(STATUS "GSSAPI: ${AUTH_GSSAPI_PLUGIN_TYPE}") +IF(${AUTH_GSSAPI_PLUGIN_TYPE} MATCHES "DYNAMIC") + IF(WIN32) + SET_VERSION_INFO("TARGET:auth_gssapi_client" + "FILE_TYPE:VFT_DLL" + "SOURCE_FILE:plugins/auth/auth_gssapi_client.c" + "ORIGINAL_FILE_NAME:auth_gssapi_client.dll" + "FILE_DESCRIPTION:Authentication plugin") + ADD_DEFINITIONS(-DHAVE_AUTH_GSSAPI_DYNAMIC=1) + SET(GSSAPI_SOURCES auth_gssapi_client.c sspi_client.c sspi_errmsg.c ${CMAKE_SOURCE_DIR}/plugins/plugin.def ${gssapi_RC}) + ELSE() + IF(GSSAPI_FOUND) + SET(GSSAPI_SOURCES auth_gssapi_client.c gssapi_client.c gssapi_errmsg.c) + ENDIF() + ENDIF() + IF(GSSAPI_FOUND) + ADD_LIBRARY(auth_gssapi_client SHARED ${GSSAPI_SOURCES}) + IF(WIN32) + TARGET_LINK_LIBRARIES(auth_gssapi_client secur32.lib) + ELSE() + TARGET_LINK_LIBRARIES(auth_gssapi_client ${GSSAPI_LIBS}) + ENDIF() + SET_TARGET_PROPERTIES(auth_gssapi_client PROPERTIES PREFIX "") + INSTALL_PLUGIN(auth_gssapi_client ${CMAKE_BINARY_DIR}/plugins/auth) + SIGN_TARGET(auth_gssapi_client) + ENDIF() +ENDIF() diff --git a/plugins/auth/auth_gssapi_client.c b/plugins/auth/auth_gssapi_client.c new file mode 100644 index 00000000..82db1a30 --- /dev/null +++ b/plugins/auth/auth_gssapi_client.c @@ -0,0 +1,119 @@ +/* Copyright (c) 2015-2016, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + @file + + GSSAPI authentication plugin, client side +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +extern int auth_client(char *principal_name, + char *mech, + MYSQL *mysql, + MYSQL_PLUGIN_VIO *vio); + +static void parse_server_packet(char *packet, size_t packet_len, char *spn, char *mech) +{ + size_t spn_len; + spn_len = strnlen(packet, packet_len); + strncpy(spn, packet, PRINCIPAL_NAME_MAX); + if (spn_len == packet_len - 1) + { + /* Mechanism not included into packet */ + *mech = 0; + } + else + { + strncpy(mech, packet + spn_len + 1, MECH_NAME_MAX); + } +} + +/** + Set client error message. + */ +void log_client_error(MYSQL *mysql, const char *format, ...) +{ + NET *net= &mysql->net; + va_list args; + + net->last_errno= ER_UNKNOWN_ERROR; + va_start(args, format); + vsnprintf(net->last_error, sizeof(net->last_error) - 1, + format, args); + va_end(args); + memcpy(net->sqlstate, "HY000", sizeof(net->sqlstate)); +} + +/** + The main client function of the GSSAPI plugin. + */ +static int gssapi_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) +{ + int packet_len; + unsigned char *packet; + char spn[PRINCIPAL_NAME_MAX + 1]; + char mech[MECH_NAME_MAX + 1]; + + /* read from server for service principal name */ + packet_len= vio->read_packet(vio, &packet); + if (packet_len < 0) + { + return CR_ERROR; + } + parse_server_packet((char *)packet, (size_t)packet_len, spn, mech); + return auth_client(spn, mech, mysql, vio); +} + + +/* register client plugin */ +#ifndef HAVE_GSSAPI_DYNAMIC +struct st_mysql_client_plugin_AUTHENTICATION auth_gssapi_plugin= +#else +struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ = +#endif +{ + MYSQL_CLIENT_AUTHENTICATION_PLUGIN, + MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION, + "auth_gssapi_client", + "Shuang Qiu, Robbie Harwood, Vladislav Vaintroub, Georg Richter", + "GSSAPI/SSPI based authentication", + {0, 1, 0}, + "BSD", + NULL, + NULL, + gssapi_auth_client +}; diff --git a/plugins/auth/common.h b/plugins/auth/common.h new file mode 100644 index 00000000..c04241ac --- /dev/null +++ b/plugins/auth/common.h @@ -0,0 +1,4 @@ +/** Maximal length of the target name */ +#define PRINCIPAL_NAME_MAX 256 +/** Maximal length of the mech string */ +#define MECH_NAME_MAX 30 diff --git a/plugins/auth/gssapi_client.c b/plugins/auth/gssapi_client.c new file mode 100644 index 00000000..a05ea158 --- /dev/null +++ b/plugins/auth/gssapi_client.c @@ -0,0 +1,127 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include +#include +#include "gssapi_errmsg.h" + +extern void log_client_error(MYSQL *mysql,const char *fmt,...); + + +/* This sends the error to the client */ +static void log_error(MYSQL *mysql, OM_uint32 major, OM_uint32 minor, const char *msg) +{ + if (GSS_ERROR(major)) + { + char sysmsg[1024]; + gssapi_errmsg(major, minor, sysmsg, sizeof(sysmsg)); + log_client_error(mysql, + "Client GSSAPI error (major %u, minor %u) : %s - %s", + major, minor, msg, sysmsg); + } + else + { + log_client_error(mysql, "Client GSSAPI error : %s", msg); + } +} + +int auth_client(char *principal_name, char *mech, MYSQL *mysql, MYSQL_PLUGIN_VIO *vio) +{ + + int ret= CR_ERROR; + OM_uint32 major= 0, minor= 0; + gss_ctx_id_t ctxt= GSS_C_NO_CONTEXT; + gss_name_t service_name= GSS_C_NO_NAME; + + if (principal_name && principal_name[0]) + { + /* import principal from plain text */ + gss_buffer_desc principal_name_buf; + principal_name_buf.length= strlen(principal_name); + principal_name_buf.value= (void *) principal_name; + major= gss_import_name(&minor, &principal_name_buf, GSS_C_NT_USER_NAME, &service_name); + if (GSS_ERROR(major)) + { + log_error(mysql, major, minor, "gss_import_name"); + return CR_ERROR; + } + } + + gss_buffer_desc input= {0,0}; + do + { + gss_buffer_desc output= {0,0}; + major= gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ctxt, service_name, + GSS_C_NO_OID, 0, 0, GSS_C_NO_CHANNEL_BINDINGS, + &input, NULL, &output, NULL, NULL); + if (output.length) + { + /* send credential */ + if(vio->write_packet(vio, (unsigned char *)output.value, output.length)) + { + /* Server error packet contains detailed message. */ + ret= CR_OK_HANDSHAKE_COMPLETE; + gss_release_buffer (&minor, &output); + goto cleanup; + } + } + gss_release_buffer (&minor, &output); + + if (GSS_ERROR(major)) + { + log_error(mysql, major, minor,"gss_init_sec_context"); + goto cleanup; + } + + if (major & GSS_S_CONTINUE_NEEDED) + { + int len= vio->read_packet(vio, (unsigned char **) &input.value); + if (len <= 0) + { + /* Server error packet contains detailed message. */ + ret= CR_OK_HANDSHAKE_COMPLETE; + goto cleanup; + } + input.length= len; + } + } while (major & GSS_S_CONTINUE_NEEDED); + + ret= CR_OK; + +cleanup: + if (service_name != GSS_C_NO_NAME) + gss_release_name(&minor, &service_name); + if (ctxt != GSS_C_NO_CONTEXT) + gss_delete_sec_context(&minor, &ctxt, GSS_C_NO_BUFFER); + + return ret; +} diff --git a/plugins/auth/gssapi_errmsg.c b/plugins/auth/gssapi_errmsg.c new file mode 100644 index 00000000..8ea4cab5 --- /dev/null +++ b/plugins/auth/gssapi_errmsg.c @@ -0,0 +1,75 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +void gssapi_errmsg(OM_uint32 major, OM_uint32 minor, char *buf, size_t size) +{ + OM_uint32 message_context; + OM_uint32 status_code; + OM_uint32 maj_status; + OM_uint32 min_status; + gss_buffer_desc status_string; + char *p= buf; + char *end= buf + size - 1; + int types[] = {GSS_C_GSS_CODE,GSS_C_MECH_CODE}; + + for(int i= 0; i < 2;i++) + { + message_context= 0; + status_code= types[i] == GSS_C_GSS_CODE?major:minor; + + if(!status_code) + continue; + do + { + maj_status = gss_display_status( + &min_status, + status_code, + types[i], + GSS_C_NO_OID, + &message_context, + &status_string); + + if(maj_status) + break; + + if(p + status_string.length + 2 < end) + { + memcpy(p,status_string.value, status_string.length); + p += status_string.length; + *p++ = '.'; + *p++ = ' '; + } + + gss_release_buffer(&min_status, &status_string); + } + while (message_context != 0); + } + *p= 0; +} diff --git a/plugins/auth/gssapi_errmsg.h b/plugins/auth/gssapi_errmsg.h new file mode 100644 index 00000000..26db8439 --- /dev/null +++ b/plugins/auth/gssapi_errmsg.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +extern void gssapi_errmsg(OM_uint32 major, OM_uint32 minor, char *buf, size_t size); diff --git a/plugins/auth/server_plugin.h b/plugins/auth/server_plugin.h new file mode 100644 index 00000000..1348835e --- /dev/null +++ b/plugins/auth/server_plugin.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Plugin variables*/ +#include +typedef enum +{ + PLUGIN_MECH_KERBEROS = 0, + PLUGIN_MECH_SPNEGO = 1, + PLUGIN_MECH_DEFAULT = 2 +}PLUGIN_MECH; + +extern unsigned long srv_mech; +extern char *srv_principal_name; +extern char *srv_mech_name; +extern char *srv_keytab_path; +/* + Check, with GSSAPI/SSPI username of logged on user. + + Depending on use_full_name parameter, compare either full name + (principal name like user@real), or local name (first component) +*/ +int plugin_init(); +int plugin_deinit(); + +int auth_server(MYSQL_PLUGIN_VIO *vio, const char *username, size_t username_len, int use_full_name); diff --git a/plugins/auth/sspi_client.c b/plugins/auth/sspi_client.c new file mode 100644 index 00000000..41461297 --- /dev/null +++ b/plugins/auth/sspi_client.c @@ -0,0 +1,183 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#define SECURITY_WIN32 +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sspi_common.h" + +extern void log_client_error(MYSQL *mysql, const char *fmt, ...); +static void log_error(MYSQL *mysql, SECURITY_STATUS err, const char *msg) +{ + if (err) + { + char buf[1024]; + sspi_errmsg(err, buf, sizeof(buf)); + log_client_error(mysql, "SSPI client error 0x%x - %s - %s", err, msg, buf); + } + else + { + log_client_error(mysql, "SSPI client error %s", msg); + } +} + + +/** Client side authentication*/ +int auth_client(char *principal_name, char *mech, MYSQL *mysql, MYSQL_PLUGIN_VIO *vio) +{ + + int ret; + CredHandle cred; + CtxtHandle ctxt; + ULONG attribs = 0; + TimeStamp lifetime; + SECURITY_STATUS sspi_err; + + SecBufferDesc inbuf_desc; + SecBuffer inbuf; + SecBufferDesc outbuf_desc; + SecBuffer outbuf; + PBYTE out = NULL; + + ret= CR_ERROR; + SecInvalidateHandle(&ctxt); + SecInvalidateHandle(&cred); + + if (!mech || strcmp(mech, "Negotiate") != 0) + { + mech= "Kerberos"; + } + + sspi_err = AcquireCredentialsHandle( + NULL, + mech, + SECPKG_CRED_OUTBOUND, + NULL, + NULL, + NULL, + NULL, + &cred, + &lifetime); + + if (SEC_ERROR(sspi_err)) + { + log_error(mysql, sspi_err, "AcquireCredentialsHandle"); + return CR_ERROR; + } + + out = (PBYTE)malloc(SSPI_MAX_TOKEN_SIZE); + if (!out) + { + log_error(mysql, SEC_E_OK, "memory allocation error"); + goto cleanup; + } + + /* Prepare buffers */ + inbuf_desc.ulVersion = SECBUFFER_VERSION; + inbuf_desc.cBuffers = 1; + inbuf_desc.pBuffers = &inbuf; + inbuf.BufferType = SECBUFFER_TOKEN; + inbuf.cbBuffer = 0; + inbuf.pvBuffer = NULL; + + outbuf_desc.ulVersion = SECBUFFER_VERSION; + outbuf_desc.cBuffers = 1; + outbuf_desc.pBuffers = &outbuf; + outbuf.BufferType = SECBUFFER_TOKEN; + outbuf.pvBuffer = out; + + do + { + outbuf.cbBuffer= SSPI_MAX_TOKEN_SIZE; + sspi_err= InitializeSecurityContext( + &cred, + SecIsValidHandle(&ctxt) ? &ctxt : NULL, + principal_name, + 0, + 0, + SECURITY_NATIVE_DREP, + inbuf.cbBuffer ? &inbuf_desc : NULL, + 0, + &ctxt, + &outbuf_desc, + &attribs, + &lifetime); + if (SEC_ERROR(sspi_err)) + { + log_error(mysql, sspi_err, "InitializeSecurityContext"); + goto cleanup; + } + if (sspi_err != SEC_E_OK && sspi_err != SEC_I_CONTINUE_NEEDED) + { + log_error(mysql, sspi_err, "Unexpected response from InitializeSecurityContext"); + goto cleanup; + } + + if (outbuf.cbBuffer) + { + /* send credential to server */ + if (vio->write_packet(vio, (unsigned char *)outbuf.pvBuffer, outbuf.cbBuffer)) + { + /* Server error packet contains detailed message. */ + ret= CR_OK_HANDSHAKE_COMPLETE; + goto cleanup; + } + } + + if (sspi_err == SEC_I_CONTINUE_NEEDED) + { + int len= vio->read_packet(vio, (unsigned char **)&inbuf.pvBuffer); + if (len <= 0) + { + /* Server side error is in the last server packet. */ + ret= CR_OK_HANDSHAKE_COMPLETE; + goto cleanup; + } + inbuf.cbBuffer= len; + } + } while (sspi_err == SEC_I_CONTINUE_NEEDED); + + ret= CR_OK; + +cleanup: + + if (SecIsValidHandle(&ctxt)) + DeleteSecurityContext(&ctxt); + if (SecIsValidHandle(&cred)) + FreeCredentialsHandle(&cred); + free(out); + return ret; +} diff --git a/plugins/auth/sspi_common.h b/plugins/auth/sspi_common.h new file mode 100644 index 00000000..34b8a56a --- /dev/null +++ b/plugins/auth/sspi_common.h @@ -0,0 +1,38 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#define SECURITY_WIN32 +#include +#include +#include +#include +#include + +#define SSPI_MAX_TOKEN_SIZE 50000 +#define SEC_ERROR(err) (err < 0) +extern void sspi_errmsg(int err, char *buf, size_t size); \ No newline at end of file diff --git a/plugins/auth/sspi_errmsg.c b/plugins/auth/sspi_errmsg.c new file mode 100644 index 00000000..961ef51f --- /dev/null +++ b/plugins/auth/sspi_errmsg.c @@ -0,0 +1,150 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +#define ERRSYM(x) {x, #x} +static struct { + int error; + const char *sym; +} error_symbols[] = +{ + ERRSYM(SEC_E_OK), + ERRSYM(SEC_E_INSUFFICIENT_MEMORY), + ERRSYM(SEC_E_INVALID_HANDLE), + ERRSYM(SEC_E_UNSUPPORTED_FUNCTION), + ERRSYM(SEC_E_TARGET_UNKNOWN), + ERRSYM(SEC_E_INTERNAL_ERROR), + ERRSYM(SEC_E_SECPKG_NOT_FOUND), + ERRSYM(SEC_E_NOT_OWNER), + ERRSYM(SEC_E_CANNOT_INSTALL), + ERRSYM(SEC_E_INVALID_TOKEN), + ERRSYM(SEC_E_CANNOT_PACK), + ERRSYM(SEC_E_QOP_NOT_SUPPORTED), + ERRSYM(SEC_E_NO_IMPERSONATION), + ERRSYM(SEC_E_LOGON_DENIED), + ERRSYM(SEC_E_UNKNOWN_CREDENTIALS), + ERRSYM(SEC_E_NO_CREDENTIALS), + ERRSYM(SEC_E_MESSAGE_ALTERED), + ERRSYM(SEC_E_OUT_OF_SEQUENCE), + ERRSYM(SEC_E_NO_AUTHENTICATING_AUTHORITY), + ERRSYM(SEC_E_BAD_PKGID), + ERRSYM(SEC_E_CONTEXT_EXPIRED), + ERRSYM(SEC_E_INCOMPLETE_MESSAGE), + ERRSYM(SEC_E_INCOMPLETE_CREDENTIALS), + ERRSYM(SEC_E_BUFFER_TOO_SMALL), + ERRSYM(SEC_E_WRONG_PRINCIPAL), + ERRSYM(SEC_E_TIME_SKEW), + ERRSYM(SEC_E_UNTRUSTED_ROOT), + ERRSYM(SEC_E_ILLEGAL_MESSAGE), + ERRSYM(SEC_E_CERT_UNKNOWN), + ERRSYM(SEC_E_CERT_EXPIRED), + ERRSYM(SEC_E_ENCRYPT_FAILURE), + ERRSYM(SEC_E_DECRYPT_FAILURE), + ERRSYM(SEC_E_ALGORITHM_MISMATCH), + ERRSYM(SEC_E_SECURITY_QOS_FAILED), + ERRSYM(SEC_E_UNFINISHED_CONTEXT_DELETED), + ERRSYM(SEC_E_NO_TGT_REPLY), + ERRSYM(SEC_E_NO_IP_ADDRESSES), + ERRSYM(SEC_E_WRONG_CREDENTIAL_HANDLE), + ERRSYM(SEC_E_CRYPTO_SYSTEM_INVALID), + ERRSYM(SEC_E_MAX_REFERRALS_EXCEEDED), + ERRSYM(SEC_E_MUST_BE_KDC), + ERRSYM(SEC_E_STRONG_CRYPTO_NOT_SUPPORTED), + ERRSYM(SEC_E_TOO_MANY_PRINCIPALS), + ERRSYM(SEC_E_NO_PA_DATA), + ERRSYM(SEC_E_PKINIT_NAME_MISMATCH), + ERRSYM(SEC_E_SMARTCARD_LOGON_REQUIRED), + ERRSYM(SEC_E_SHUTDOWN_IN_PROGRESS), + ERRSYM(SEC_E_KDC_INVALID_REQUEST), + ERRSYM(SEC_E_KDC_UNABLE_TO_REFER), + ERRSYM(SEC_E_KDC_UNKNOWN_ETYPE), + ERRSYM(SEC_E_UNSUPPORTED_PREAUTH), + ERRSYM(SEC_E_DELEGATION_REQUIRED), + ERRSYM(SEC_E_BAD_BINDINGS), + ERRSYM(SEC_E_MULTIPLE_ACCOUNTS), + ERRSYM(SEC_E_NO_KERB_KEY), + ERRSYM(SEC_E_CERT_WRONG_USAGE), + ERRSYM(SEC_E_DOWNGRADE_DETECTED), + ERRSYM(SEC_E_SMARTCARD_CERT_REVOKED), + ERRSYM(SEC_E_ISSUING_CA_UNTRUSTED), + ERRSYM(SEC_E_REVOCATION_OFFLINE_C), + ERRSYM(SEC_E_PKINIT_CLIENT_FAILURE), + ERRSYM(SEC_E_SMARTCARD_CERT_EXPIRED), + ERRSYM(SEC_E_NO_S4U_PROT_SUPPORT), + ERRSYM(SEC_E_CROSSREALM_DELEGATION_FAILURE), + ERRSYM(SEC_E_REVOCATION_OFFLINE_KDC), + ERRSYM(SEC_E_ISSUING_CA_UNTRUSTED_KDC), + ERRSYM(SEC_E_KDC_CERT_EXPIRED), + ERRSYM(SEC_E_KDC_CERT_REVOKED), + ERRSYM(SEC_E_INVALID_PARAMETER), + ERRSYM(SEC_E_DELEGATION_POLICY), + ERRSYM(SEC_E_POLICY_NLTM_ONLY), + ERRSYM(SEC_E_NO_CONTEXT), + ERRSYM(SEC_E_PKU2U_CERT_FAILURE), + ERRSYM(SEC_E_MUTUAL_AUTH_FAILED), + ERRSYM(SEC_E_NO_SPM), + ERRSYM(SEC_E_NOT_SUPPORTED), + {0,0} +}; + +void sspi_errmsg(int err, char *buf, size_t size) +{ + buf[size - 1] = 0; + size_t len; + + for (size_t i= 0; error_symbols[i].sym; i++) + { + if (error_symbols[i].error == err) + { + size_t len= strlen(error_symbols[i].sym); + if (len + 2 < size) + { + memcpy(buf, error_symbols[i].sym, len); + buf[len]= ' '; + buf += len + 1; + size-= len + 1; + } + break; + } + } + + len = FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, + err, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + buf, size, NULL); + + if(len > 0) + { + /* Trim trailing \n\r*/ + char *p; + for(p= buf + len;p > buf && (*p == '\n' || *p=='\r' || *p == 0);p--) + *p= 0; + } +} diff --git a/unittest/libmariadb/certs/create_certs.sh b/unittest/libmariadb/certs/create_certs.sh new file mode 100755 index 00000000..47ea98e8 --- /dev/null +++ b/unittest/libmariadb/certs/create_certs.sh @@ -0,0 +1,15 @@ +openssl req -x509 -newkey rsa:1024 \ +-keyout server-key-enc.pem -out server-cert.pem \ +-subj '/DC=com/DC=example/CN=server' -passout pass:qwerty + +openssl rsa -in server-key-enc.pem -out server-key.pem \ +-passin pass:qwerty -passout pass: + +openssl req -x509 -newkey rsa:1024 \ +-keyout client-key-enc.pem -out client-cert.pem \ +-subj '/DC=com/DC=example/CN=client' -passout pass:qwerty + +openssl rsa -in client-key-enc.pem -out client-key.pem \ +-passin pass:qwerty -passout pass: + +cat server-cert.pem client-cert.pem > ca-cert.pem diff --git a/unittest/libmariadb/certs/dummy.pem b/unittest/libmariadb/certs/dummy.pem new file mode 100644 index 00000000..1fc34aa1 --- /dev/null +++ b/unittest/libmariadb/certs/dummy.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDXTCCAkWgAwIBAgIJAL4tmDe5DR0sMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTUwMzEwMjAyMDI4WhcNMTYwMzA5MjAyMDI4WjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEApV9UfWmeXYdexOEn+adOm6FdJUhKMrjTiycwETmDXRVpY4wl+LNGsANp +ohSRovDjFiFO+Ti0bUhpf552oE23wYw+P6f0UY0KkV/PgSght1Ezfffe0BaEjI0X +tA5zdNmxzL3OUWJVcg+I4UE3rbYFHUgymu72P0IRXjmJv1tToNxUxbTBLxU/KAlq +Uy49upB3q3/IPOdP9UzAZDHnRv1gjwUzNgumfcc5d5lSsGpwLDYCQs4I539fCkBD +MfU2BN/qpmPhb/nm5ZUdFUFYGN+XxVPVpJLmeWVRwMSQR2LN5CkqnK9e2Q/QaJ53 +G3AAng+fpfEGPpjQdFWuhFjQozOD0wIDAQABo1AwTjAdBgNVHQ4EFgQUyg6WfzL2 +JhhjKm1Ex28s4Y3vNGQwHwYDVR0jBBgwFoAUyg6WfzL2JhhjKm1Ex28s4Y3vNGQw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAIrj/bHiRf8UJIfv8hyZ1 +dXEqvqjxUMXtJ/QhhCQs42p9pHv+mPTkeXh0K18Oj6k/Vp4J1/0mp/kqiQUHt9yO +/3pJPc+JordTjlVLgb95cfBIs4yiPT9biGaA7j0Dh9EcDBOCT4v56Z9BLqGMfBUK +YeZ7ZecWmZCZOYk/X+CPB30GxLy5Wm9D50qEUXXBPZ9Bie6FYaQYOFlQlqxYuLX0 +NVqLDvX6zz6FMsgqoyDJ1BMuMsjPDUUUrwGY+R3YqiqkPRbDkr8zvzpqiYvjTZi0 +LTJO7GRfwzfhkeEPL/hl/TYdB1GZHixMrAKx1HGKHAa0sgWTWxQGYhfclH8DI7AR +Tw== +-----END CERTIFICATE----- diff --git a/unittest/libmariadb/my_test.h b/unittest/libmariadb/my_test.h index c756318f..329aa545 100644 --- a/unittest/libmariadb/my_test.h +++ b/unittest/libmariadb/my_test.h @@ -29,6 +29,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include +#ifndef WIN32 +#include +#endif + #ifndef OK # define OK 0 #endif diff --git a/unittest/libmariadb/ps.c b/unittest/libmariadb/ps.c index d6545a21..3eb74bb9 100644 --- a/unittest/libmariadb/ps.c +++ b/unittest/libmariadb/ps.c @@ -70,7 +70,7 @@ static int test_conc83(MYSQL *my) rc= mysql_ping(mysql); check_mysql_rc(rc, mysql); - rc= mysql_stmt_prepare(stmt, query, strlen(query)); + rc= mysql_stmt_prepare(stmt, query, -1); check_stmt_rc(rc, stmt); diag("Ok"); @@ -78,7 +78,7 @@ static int test_conc83(MYSQL *my) rc= mysql_kill(mysql, mysql_thread_id(mysql)); sleep(2); - rc= mysql_stmt_prepare(stmt, query, strlen(query)); + rc= mysql_stmt_prepare(stmt, query, -1); FAIL_IF(!rc, "Error expected"); mysql_stmt_close(stmt); @@ -98,7 +98,7 @@ static int test_conc60(MYSQL *mysql) rc= mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void *)&x); - rc= mysql_stmt_prepare(stmt, query, strlen(query)); + rc= mysql_stmt_prepare(stmt, query, -1); if (rc && mysql_stmt_errno(stmt) == 1146) { diag("Internal test - customer data not available"); mysql_stmt_close(stmt); From cbef19f650ca69b18d0e2719f038a9c5e0b015c3 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Fri, 22 Jan 2016 20:14:55 +0100 Subject: [PATCH 35/40] Windows fixes for GSSAPI plugin --- plugins/auth/CMakeLists.txt | 2 +- plugins/auth/auth_gssapi_client.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/auth/CMakeLists.txt b/plugins/auth/CMakeLists.txt index 7dedb9d1..bf7d0266 100644 --- a/plugins/auth/CMakeLists.txt +++ b/plugins/auth/CMakeLists.txt @@ -86,7 +86,7 @@ IF(${AUTH_GSSAPI_PLUGIN_TYPE} MATCHES "DYNAMIC") SET(GSSAPI_SOURCES auth_gssapi_client.c gssapi_client.c gssapi_errmsg.c) ENDIF() ENDIF() - IF(GSSAPI_FOUND) + IF(GSSAPI_FOUND OR WIN32) ADD_LIBRARY(auth_gssapi_client SHARED ${GSSAPI_SOURCES}) IF(WIN32) TARGET_LINK_LIBRARIES(auth_gssapi_client secur32.lib) diff --git a/plugins/auth/auth_gssapi_client.c b/plugins/auth/auth_gssapi_client.c index 82db1a30..d0ed3795 100644 --- a/plugins/auth/auth_gssapi_client.c +++ b/plugins/auth/auth_gssapi_client.c @@ -100,7 +100,7 @@ static int gssapi_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) /* register client plugin */ -#ifndef HAVE_GSSAPI_DYNAMIC +#ifndef HAVE_AUTH_GSSAPI_DYNAMIC struct st_mysql_client_plugin_AUTHENTICATION auth_gssapi_plugin= #else struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ = From 17ab9f81ad09990f3a6a9175fb09ec313d384846 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Sat, 23 Jan 2016 15:57:33 +0100 Subject: [PATCH 36/40] Added missing FindGSSAPI.cmake for non windows builds --- CMakeLists.txt | 12 +++++ cmake/FindGSSAPI.cmake | 99 ++++++++++++++++++++++++++++++++++++++++++ cmake/plugins.cmake | 2 +- 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 cmake/FindGSSAPI.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fd67723..fbe44933 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,8 +57,20 @@ IF(CURL_FOUND) ADD_DEFINITIONS(-DHAVE_CURL=1) ENDIF() +IF(NOT WIN32) + INCLUDE(${CMAKE_SOURCE_DIR}/cmake/FindGSSAPI.cmake) + IF(GSSAPI_FOUND) + INCLUDE_DIRECTORIES(${GSSAPI_INCS}) + ENDIF() +ENDIF() + INCLUDE(${CMAKE_SOURCE_DIR}/cmake/plugins.cmake) +IF(AUTH_GSSAPI_PLUGIN_TYPE MATCHES "STATIC") + SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${GSSAPI_LIBS}) +ENDIF() + + IF(WIN32) FILE(REMOVE ${CMAKE_BINARY_DIR}/win/packaging/plugin.conf) INCLUDE(${CMAKE_SOURCE_DIR}/cmake/version_info.cmake) diff --git a/cmake/FindGSSAPI.cmake b/cmake/FindGSSAPI.cmake new file mode 100644 index 00000000..3a1c83cd --- /dev/null +++ b/cmake/FindGSSAPI.cmake @@ -0,0 +1,99 @@ +# - Try to detect the GSSAPI support +# Once done this will define +# +# GSSAPI_FOUND - system supports GSSAPI +# GSSAPI_INCS - the GSSAPI include directory +# GSSAPI_LIBS - the libraries needed to use GSSAPI +# GSSAPI_FLAVOR - the type of API - MIT or HEIMDAL + +# Copyright (c) 2006, Pino Toscano, +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +if(GSSAPI_LIBS AND GSSAPI_FLAVOR) + + # in cache already + set(GSSAPI_FOUND TRUE) + +else(GSSAPI_LIBS AND GSSAPI_FLAVOR) + + find_program(KRB5_CONFIG NAMES krb5-config PATHS + /opt/local/bin + /usr/lib/mit/bin/ + ONLY_CMAKE_FIND_ROOT_PATH # this is required when cross compiling with cmake 2.6 and ignored with cmake 2.4, Alex + ) + mark_as_advanced(KRB5_CONFIG) + + #reset vars + set(GSSAPI_INCS) + set(GSSAPI_LIBS) + set(GSSAPI_FLAVOR) + + if(KRB5_CONFIG) + + set(HAVE_KRB5_GSSAPI TRUE) + exec_program(${KRB5_CONFIG} ARGS --libs gssapi RETURN_VALUE _return_VALUE OUTPUT_VARIABLE GSSAPI_LIBS) + if(_return_VALUE) + message(STATUS "GSSAPI configure check failed.") + set(HAVE_KRB5_GSSAPI FALSE) + endif(_return_VALUE) + + exec_program(${KRB5_CONFIG} ARGS --cflags gssapi RETURN_VALUE _return_VALUE OUTPUT_VARIABLE GSSAPI_INCS) + string(REGEX REPLACE "(\r?\n)+$" "" GSSAPI_INCS "${GSSAPI_INCS}") + string(REGEX REPLACE " *-I" ";" GSSAPI_INCS "${GSSAPI_INCS}") + + exec_program(${KRB5_CONFIG} ARGS --vendor RETURN_VALUE _return_VALUE OUTPUT_VARIABLE gssapi_flavor_tmp) + set(GSSAPI_FLAVOR_MIT) + if(gssapi_flavor_tmp MATCHES ".*Massachusetts.*") + set(GSSAPI_FLAVOR "MIT") + else(gssapi_flavor_tmp MATCHES ".*Massachusetts.*") + set(GSSAPI_FLAVOR "HEIMDAL") + endif(gssapi_flavor_tmp MATCHES ".*Massachusetts.*") + + if(NOT HAVE_KRB5_GSSAPI) + if (gssapi_flavor_tmp MATCHES "Sun Microsystems.*") + message(STATUS "Solaris Kerberos does not have GSSAPI; this is normal.") + set(GSSAPI_LIBS) + set(GSSAPI_INCS) + else(gssapi_flavor_tmp MATCHES "Sun Microsystems.*") + message(WARNING "${KRB5_CONFIG} failed unexpectedly.") + endif(gssapi_flavor_tmp MATCHES "Sun Microsystems.*") + endif(NOT HAVE_KRB5_GSSAPI) + + if(GSSAPI_LIBS) # GSSAPI_INCS can be also empty, so don't rely on that + set(GSSAPI_FOUND TRUE CACHE STRING "") + message(STATUS "Found GSSAPI: ${GSSAPI_LIBS}") + + set(GSSAPI_INCS ${GSSAPI_INCS} CACHE STRING "") + set(GSSAPI_LIBS ${GSSAPI_LIBS} CACHE STRING "") + set(GSSAPI_FLAVOR ${GSSAPI_FLAVOR} CACHE STRING "") + + mark_as_advanced(GSSAPI_INCS GSSAPI_LIBS GSSAPI_FLAVOR) + + endif(GSSAPI_LIBS) + + endif(KRB5_CONFIG) + +endif(GSSAPI_LIBS AND GSSAPI_FLAVOR) diff --git a/cmake/plugins.cmake b/cmake/plugins.cmake index 71e47285..2068b1e3 100644 --- a/cmake/plugins.cmake +++ b/cmake/plugins.cmake @@ -59,7 +59,7 @@ REGISTER_PLUGIN("TRACE_EXAMPLE" "${CMAKE_SOURCE_DIR}/plugins/trace/trace_example #Connection REGISTER_PLUGIN("REPLICATION" "${CMAKE_SOURCE_DIR}/plugins/connection/replication.c" "connection_replication_plugin" "DYNAMIC" "replication" 1) -REGISTER_PLUGIN("AURORA" "${CMAKE_SOURCE_DIR}/plugins/connection/aurora.c" "connection_aurora_plugin" "DYNAMIC" "aurora" 1) +REGISTER_PLUGIN("AURORA" "${CMAKE_SOURCE_DIR}/plugins/connection/aurora.c" "connection_aurora_plugin" "DYNAMIC" "aurora" 1) # Allow registration of additional plugins IF(PLUGIN_CONF_FILE) From 56b4bdee1b62e37ce218fd359c34076ff5022a04 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 25 Jan 2016 13:37:14 +0100 Subject: [PATCH 37/40] Renamed option for mysql_get_infov from MARIADB_CONNECTION_SSL_LIBRARY to MARIADB_SSL_LIBRARY --- include/mysql.h | 2 +- libmariadb/libmariadb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index f9d03294..10cad813 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -243,7 +243,7 @@ extern unsigned int mariadb_deinitialize_ssl; MARIADB_CONNECTION_SOCKET, MARIADB_CONNECTION_SQLSTATE, MARIADB_CONNECTION_SSL_CIPHER, - MARIADB_CONNECTION_SSL_LIBRARY, + MARIADB_SSL_LIBRARY, MARIADB_CONNECTION_SSL_VERSION, MARIADB_CONNECTION_SSL_VERSION_ID, MARIADB_CONNECTION_TYPE, diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 2d305089..af17972f 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -3636,7 +3636,7 @@ my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void * #endif goto error; break; - case MARIADB_CONNECTION_SSL_LIBRARY: + case MARIADB_SSL_LIBRARY: #ifdef HAVE_SSL #ifdef HAVE_GNUTLS *((char **)arg)= "GNUTLS"; From 736913d961afb676ad615313f958e41ce7b584e3 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 25 Jan 2016 13:35:15 +0100 Subject: [PATCH 38/40] Fix for CONC-154: set stmt->state to MYSQL_STMT_FETCH_DONE if - result set is empty (nothing to fetch) - when madb_stmt_reset was called --- libmariadb/my_stmt.c | 9 ++- unittest/libmariadb/ps_bugs.c | 104 ++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 2 deletions(-) diff --git a/libmariadb/my_stmt.c b/libmariadb/my_stmt.c index ea9e9bee..4894ceb2 100644 --- a/libmariadb/my_stmt.c +++ b/libmariadb/my_stmt.c @@ -1377,8 +1377,12 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) stmt->result_cursor= stmt->result.data; stmt->fetch_row_func= stmt_buffered_fetch; - stmt->mysql->status= MYSQL_STATUS_READY; - stmt->state= MYSQL_STMT_USE_OR_STORE_CALLED; + stmt->mysql->status= MYSQL_STATUS_READY; + + if (!stmt->result.rows) + stmt->state= MYSQL_STMT_FETCH_DONE; + else + stmt->state= MYSQL_STMT_USE_OR_STORE_CALLED; /* set affected rows: see bug 2247 */ stmt->upsert_status.affected_rows= stmt->result.rows; @@ -1643,6 +1647,7 @@ static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags) stmt->result.rows= 0; stmt->result_cursor= NULL; stmt->mysql->status= MYSQL_STATUS_READY; + stmt->state= MYSQL_STMT_FETCH_DONE; } /* if there is a pending result set, we will flush it */ diff --git a/unittest/libmariadb/ps_bugs.c b/unittest/libmariadb/ps_bugs.c index e5204ea4..94b946ea 100644 --- a/unittest/libmariadb/ps_bugs.c +++ b/unittest/libmariadb/ps_bugs.c @@ -3909,7 +3909,111 @@ static int test_conc141(MYSQL *mysql) return OK; } +static int test_conc154(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + const char *stmtstr= "SELECT * FROM t1"; + int rc; + + /* 1st: empty result set without free_result */ + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE t1 (a varchar(20))"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, stmtstr, strlen(stmtstr)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + + /* 2nd: empty result set with free_result */ + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, stmtstr, strlen(stmtstr)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_free_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_free_result(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + + /* 3rd: non empty result without free_result */ + rc= mysql_query(mysql, "INSERT INTO t1 VALUES ('test_conc154')"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, stmtstr, strlen(stmtstr)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + + /* 4th non empty result set with free_result */ + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, stmtstr, strlen(stmtstr)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_free_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_free_result(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + + return OK; +} + struct my_tests_st my_tests[] = { + {"test_conc154", test_conc154, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, {"test_conc141", test_conc141, TEST_CONNECTION_NEW, 0, NULL , NULL}, {"test_conc67", test_conc67, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, {"test_conc_5", test_conc_5, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, From 6b5ff864f3e9d27a0d693ba385ecb7e22055acbf Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 25 Jan 2016 13:40:07 +0100 Subject: [PATCH 39/40] Fixed SSL test (option was renamed before) --- unittest/libmariadb/ssl.c.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittest/libmariadb/ssl.c.in b/unittest/libmariadb/ssl.c.in index 866aa34b..8b79761e 100644 --- a/unittest/libmariadb/ssl.c.in +++ b/unittest/libmariadb/ssl.c.in @@ -785,7 +785,7 @@ static int test_ssl_version(MYSQL *mysql) mariadb_get_infov(my, MARIADB_CONNECTION_SSL_VERSION, &version); diag("protocol: %s", version); - mariadb_get_infov(my, MARIADB_CONNECTION_SSL_LIBRARY, &library); + mariadb_get_infov(my, MARIADB_SSL_LIBRARY, &library); diag("library: %s", library); From 6bed75bba6a5b1f07c655206e1344d00b19a5126 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 25 Jan 2016 13:51:52 +0100 Subject: [PATCH 40/40] Bumped version number to 3.0.1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fbe44933..c31d5b89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ SET(PACKAGE_STATUS_SUFFIX "alpha") SET(CPACK_PACKAGE_VERSION_MAJOR 3) SET(CPACK_PACKAGE_VERSION_MINOR 0) -SET(CPACK_PACKAGE_VERSION_PATCH 0) +SET(CPACK_PACKAGE_VERSION_PATCH 1) SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") #Minimum required version is Cmake 2.8.8, since we need to build object libraries