You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-07 02:42:49 +03:00
- Fixes for 10.2-integration
- As requested by Wlad we use connect timeout for read/write unless the connection was established. - Added experimental session cache support for OpenSSL. It's currently disabled
This commit is contained in:
@@ -54,14 +54,6 @@ void ma_randominit(struct rand_struct *rand_st,ulong seed1, ulong seed2)
|
||||
rand_st->seed2=seed2%rand_st->max_value;
|
||||
}
|
||||
|
||||
static void ma_old_randominit(struct rand_struct *rand_st,ulong seed1)
|
||||
{ /* For mysql 3.20.# */
|
||||
rand_st->max_value= 0x01FFFFFFL;
|
||||
rand_st->max_value_dbl=(double) rand_st->max_value;
|
||||
seed1%=rand_st->max_value;
|
||||
rand_st->seed1=seed1 ; rand_st->seed2=seed1/2;
|
||||
}
|
||||
|
||||
double rnd(struct rand_struct *rand_st)
|
||||
{
|
||||
rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
|
||||
|
@@ -100,6 +100,7 @@ MARIADB_PVIO *ma_pvio_init(MA_PVIO_CINFO *cinfo)
|
||||
pvio_plugins[type],
|
||||
MARIADB_CLIENT_PVIO_PLUGIN)))
|
||||
{
|
||||
/* error already set in mysql_client_find_plugin */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -115,12 +116,11 @@ MARIADB_PVIO *ma_pvio_init(MA_PVIO_CINFO *cinfo)
|
||||
pvio->set_error= my_set_error;
|
||||
pvio->type= cinfo->type;
|
||||
|
||||
/* set tineouts */
|
||||
/* set timeout to connect timeout - after successfull connect we will set
|
||||
* correct values for read and write */
|
||||
if (pvio->methods->set_timeout)
|
||||
{
|
||||
pvio->methods->set_timeout(pvio, PVIO_CONNECT_TIMEOUT, cinfo->mysql->options.connect_timeout);
|
||||
pvio->methods->set_timeout(pvio, PVIO_READ_TIMEOUT, cinfo->mysql->options.read_timeout);
|
||||
pvio->methods->set_timeout(pvio, PVIO_WRITE_TIMEOUT, cinfo->mysql->options.write_timeout);
|
||||
}
|
||||
|
||||
if (!(pvio->cache= calloc(1, PVIO_READ_AHEAD_CACHE_SIZE)))
|
||||
@@ -521,6 +521,12 @@ my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio)
|
||||
pvio->cssl= NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* default behaviour:
|
||||
1. peer certificate verification
|
||||
2. verify CN (requires option ssl_verify_check)
|
||||
3. verrify finger print
|
||||
*/
|
||||
if ((pvio->mysql->options.ssl_ca || pvio->mysql->options.ssl_capath) &&
|
||||
(pvio->mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
|
||||
ma_pvio_ssl_verify_server_cert(pvio->cssl))
|
||||
|
@@ -1349,8 +1349,6 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
|
||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
goto error;
|
||||
}
|
||||
strcpy(mysql->host_info,host_info);
|
||||
strcpy(mysql->host, cinfo.host);
|
||||
if (cinfo.unix_socket)
|
||||
mysql->unix_socket= strdup(cinfo.unix_socket);
|
||||
else
|
||||
@@ -1512,6 +1510,9 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
|
||||
|
||||
strcpy(mysql->net.sqlstate, "00000");
|
||||
|
||||
/* connection established, apply timeouts */
|
||||
ma_pvio_set_timeout(mysql->net.pvio, PVIO_READ_TIMEOUT, mysql->options.read_timeout);
|
||||
ma_pvio_set_timeout(mysql->net.pvio, PVIO_WRITE_TIMEOUT, mysql->options.write_timeout);
|
||||
return(mysql);
|
||||
|
||||
error:
|
||||
@@ -1557,6 +1558,7 @@ my_bool STDCALL mariadb_reconnect(MYSQL *mysql)
|
||||
struct mysql_async_context *ctxt= NULL;
|
||||
#endif
|
||||
LIST *li_stmt= mysql->stmts;
|
||||
mysql_init(&tmp_mysql);
|
||||
|
||||
/* check if connection handler is active */
|
||||
if (IS_CONNHDLR_ACTIVE(mysql))
|
||||
@@ -1835,11 +1837,12 @@ static void mysql_close_options(MYSQL *mysql)
|
||||
static void mysql_close_memory(MYSQL *mysql)
|
||||
{
|
||||
free(mysql->host_info);
|
||||
free(mysql->host);
|
||||
free(mysql->user);
|
||||
free(mysql->passwd);
|
||||
free(mysql->db);
|
||||
free(mysql->server_version);
|
||||
mysql->host_info= mysql->server_version=mysql->user=mysql->passwd=mysql->db=0;
|
||||
mysql->host_info= mysql->host= mysql->server_version=mysql->user=mysql->passwd=mysql->db=0;
|
||||
}
|
||||
|
||||
void my_set_error(MYSQL *mysql,
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/md4.h>
|
||||
|
||||
#define HAVE_SSL_SESSION_CACHE 1
|
||||
#ifndef HAVE_OPENSSL_DEFAULT
|
||||
#include <memory.h>
|
||||
#define ma_malloc(A,B) malloc((A))
|
||||
@@ -111,7 +112,7 @@ static void my_cb_threadid(CRYPTO_THREADID *id)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_SESSION_TICKET
|
||||
#ifdef HAVE_SSL_SESSION_CACHE
|
||||
typedef struct st_ma_ssl_session {
|
||||
char md4_hash[17];
|
||||
SSL_SESSION *session;
|
||||
@@ -120,10 +121,11 @@ typedef struct st_ma_ssl_session {
|
||||
MA_SSL_SESSION *ma_ssl_sessions= NULL;
|
||||
unsigned int ma_ssl_session_cache_size= 128;
|
||||
|
||||
static char *ma_md4_hash(const char *host, unsigned int port, char *md4)
|
||||
static char *ma_md4_hash(const char *host, const char *user, unsigned int port, char *md4)
|
||||
{
|
||||
char buffer[260];
|
||||
snprintf(buffer, 258, "%s:%d", host, port);
|
||||
char buffer[195]; /* MAX_USERNAME_LEN + MAX_HOST_NAME_LEN + 2 + 5 */
|
||||
snprintf(buffer, 194, "%s@%s:%d", user ? user : "", host, port);
|
||||
buffer[194]= 0;
|
||||
MD4(buffer, strlen(buffer), md4);
|
||||
return md4;
|
||||
}
|
||||
@@ -137,7 +139,7 @@ MA_SSL_SESSION *ma_ssl_get_session(MYSQL *mysql)
|
||||
return NULL;
|
||||
|
||||
memset(md4, 0, 16);
|
||||
ma_md4_hash(mysql->host, mysql->port, md4);
|
||||
ma_md4_hash(mysql->host, mysql->user, mysql->port, md4);
|
||||
for (i=0; i < ma_ssl_session_cache_size; i++)
|
||||
{
|
||||
if (ma_ssl_sessions[i].session &&
|
||||
@@ -169,7 +171,7 @@ static int ma_ssl_session_cb(SSL *ssl, SSL_SESSION *session)
|
||||
{
|
||||
if (!ma_ssl_sessions[i].session)
|
||||
{
|
||||
ma_md4_hash(mysql->host, mysql->port, ma_ssl_sessions[i].md4_hash);
|
||||
ma_md4_hash(mysql->host, mysql->user, mysql->port, ma_ssl_sessions[i].md4_hash);
|
||||
ma_ssl_sessions[i].session= session;
|
||||
}
|
||||
return 1;
|
||||
@@ -268,7 +270,7 @@ int ma_ssl_start(char *errmsg, size_t errmsg_len)
|
||||
ma_ssl_get_error(errmsg, errmsg_len);
|
||||
goto end;
|
||||
}
|
||||
#ifdef HAVE_OPENSSL_SESSION_TICKET
|
||||
#ifdef HAVE_SSL_SESSION_CACHE
|
||||
SSL_CTX_set_session_cache_mode(SSL_context, SSL_SESS_CACHE_CLIENT);
|
||||
ma_ssl_sessions= (MA_SSL_SESSION *)calloc(1, sizeof(struct st_ma_ssl_session) * ma_ssl_session_cache_size);
|
||||
SSL_CTX_sess_set_new_cb(SSL_context, ma_ssl_session_cb);
|
||||
@@ -452,7 +454,7 @@ void *ma_ssl_init(MYSQL *mysql)
|
||||
{
|
||||
int verify;
|
||||
SSL *ssl= NULL;
|
||||
#ifdef HAVE_OPENSSL_SESSION_TICKET
|
||||
#ifdef HAVE_SSL_SESSION_CACHE
|
||||
MA_SSL_SESSION *session= ma_ssl_get_session(mysql);
|
||||
#endif
|
||||
pthread_mutex_lock(&LOCK_openssl_config);
|
||||
@@ -468,7 +470,7 @@ void *ma_ssl_init(MYSQL *mysql)
|
||||
if (!SSL_set_app_data(ssl, mysql))
|
||||
goto error;
|
||||
|
||||
#ifdef HAVE_OPENSSL_SESSION_TICKET
|
||||
#ifdef HAVE_SSL_SESSION_CACHE
|
||||
if (session)
|
||||
SSL_set_session(ssl, session->session);
|
||||
#endif
|
||||
|
@@ -158,6 +158,38 @@ static int pvio_socket_end(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
my_bool pvio_socket_change_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout)
|
||||
{
|
||||
struct timeval tm;
|
||||
struct st_pvio_socket *csock= NULL;
|
||||
if (!pvio)
|
||||
return 1;
|
||||
if (!(csock= (struct st_pvio_socket *)pvio->data))
|
||||
return 1;
|
||||
tm.tv_sec= timeout / 1000;
|
||||
tm.tv_usec= (timeout % 1000) * 1000;
|
||||
switch(type)
|
||||
{
|
||||
case PVIO_WRITE_TIMEOUT:
|
||||
#ifndef _WIN32
|
||||
setsockopt(csock->socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tm, sizeof(tm));
|
||||
#else
|
||||
setsockopt(csock->socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(int));
|
||||
#endif
|
||||
break;
|
||||
case PVIO_READ_TIMEOUT:
|
||||
#ifndef _WIN32
|
||||
setsockopt(csock->socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tm, sizeof(tm));
|
||||
#else
|
||||
setsockopt(csock->socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(int));
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* {{{ pvio_socket_set_timeout */
|
||||
/*
|
||||
set timeout value
|
||||
@@ -179,9 +211,13 @@ static int pvio_socket_end(void)
|
||||
*/
|
||||
my_bool pvio_socket_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout)
|
||||
{
|
||||
struct st_pvio_socket *csock= NULL;
|
||||
if (!pvio)
|
||||
return 1;
|
||||
csock= (struct st_pvio_socket *)pvio->data;
|
||||
pvio->timeout[type]= (timeout > 0) ? timeout * 1000 : -1;
|
||||
if (csock)
|
||||
return pvio_socket_change_timeout(pvio, type, timeout);
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -677,15 +713,13 @@ int pvio_socket_fast_send(MARIADB_PVIO *pvio)
|
||||
/* Setting IP_TOS is not recommended on Windows. See
|
||||
http://msdn.microsoft.com/en-us/library/windows/desktop/ms738586(v=vs.85).aspx
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
#ifdef IPTOS_THROUGHPUT
|
||||
#if !defined(_WIN32) && defined(IPTOS_THROUGHPUT)
|
||||
{
|
||||
int tos = IPTOS_THROUGHPUT;
|
||||
r= setsockopt(csock->socket, IPPROTO_IP, IP_TOS,
|
||||
(const void *)&tos, sizeof(tos));
|
||||
}
|
||||
#endif /* IPTOS_THROUGHPUT */
|
||||
#endif
|
||||
#endif /* !_WIN32 && IPTOS_THROUGHPUT */
|
||||
if (!r)
|
||||
{
|
||||
int opt = 1;
|
||||
@@ -723,7 +757,6 @@ pvio_socket_connect_sync_or_async(MARIADB_PVIO *pvio,
|
||||
my_bool pvio_socket_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
|
||||
{
|
||||
struct st_pvio_socket *csock= NULL;
|
||||
struct timeval tm;
|
||||
|
||||
if (!pvio || !cinfo)
|
||||
return 1;
|
||||
@@ -870,25 +903,17 @@ my_bool pvio_socket_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
|
||||
goto error;
|
||||
}
|
||||
/* apply timeouts */
|
||||
if (pvio->timeout[PVIO_WRITE_TIMEOUT] > 0)
|
||||
if (pvio->timeout[PVIO_CONNECT_TIMEOUT] > 0)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
tm.tv_sec= pvio->timeout[PVIO_WRITE_TIMEOUT] / 1000;
|
||||
tm.tv_usec= pvio->timeout[PVIO_WRITE_TIMEOUT] % 1000;
|
||||
setsockopt(csock->socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tm, sizeof(tm));
|
||||
#else
|
||||
setsockopt(csock->socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&pvio->timeout[PVIO_WRITE_TIMEOUT], sizeof(int));
|
||||
#endif
|
||||
pvio_socket_change_timeout(pvio, PVIO_READ_TIMEOUT, pvio->timeout[PVIO_CONNECT_TIMEOUT]);
|
||||
pvio_socket_change_timeout(pvio, PVIO_WRITE_TIMEOUT, pvio->timeout[PVIO_CONNECT_TIMEOUT]);
|
||||
}
|
||||
if (pvio->timeout[PVIO_READ_TIMEOUT] > 0)
|
||||
else
|
||||
{
|
||||
#ifndef _WIN32
|
||||
tm.tv_sec= pvio->timeout[PVIO_READ_TIMEOUT] / 1000;
|
||||
tm.tv_usec= pvio->timeout[PVIO_READ_TIMEOUT] % 1000;
|
||||
setsockopt(csock->socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tm, sizeof(tm));
|
||||
#else
|
||||
setsockopt(csock->socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&pvio->timeout[PVIO_WRITE_TIMEOUT], sizeof(int));
|
||||
#endif
|
||||
if (pvio->timeout[PVIO_WRITE_TIMEOUT] > 0)
|
||||
pvio_socket_change_timeout(pvio, PVIO_WRITE_TIMEOUT, pvio->timeout[PVIO_WRITE_TIMEOUT]);
|
||||
if (pvio->timeout[PVIO_READ_TIMEOUT] > 0)
|
||||
pvio_socket_change_timeout(pvio, PVIO_READ_TIMEOUT, pvio->timeout[PVIO_READ_TIMEOUT]);
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
|
@@ -49,8 +49,8 @@ static int test_conc66(MYSQL *my)
|
||||
|
||||
rc= mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "conc-66");
|
||||
check_mysql_rc(rc, mysql);
|
||||
// rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./my.cnf");
|
||||
// check_mysql_rc(rc, mysql);
|
||||
rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./my.cnf");
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
sprintf(query, "GRANT ALL ON %s.* TO 'conc66'@'%s' IDENTIFIED BY 'test\";#test'", schema, hostname);
|
||||
rc= mysql_query(my, query);
|
||||
@@ -63,6 +63,7 @@ static int test_conc66(MYSQL *my)
|
||||
diag("Error: %s", mysql_error(mysql));
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
sprintf(query, "DROP user conc66@%s", hostname);
|
||||
rc= mysql_query(my, query);
|
||||
|
||||
@@ -660,6 +661,71 @@ int test_connection_timeout(MYSQL *my)
|
||||
return OK;
|
||||
}
|
||||
|
||||
int test_connection_timeout2(MYSQL *my)
|
||||
{
|
||||
unsigned int timeout= 5;
|
||||
time_t start, elapsed;
|
||||
MYSQL *mysql= mysql_init(NULL);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&timeout);
|
||||
mysql_options(mysql, MYSQL_INIT_COMMAND, "set @a:=SLEEP(6)");
|
||||
start= time(NULL);
|
||||
if (mysql_real_connect(mysql, hostname, username, password, schema, port, NULL, CLIENT_REMEMBER_OPTIONS))
|
||||
{
|
||||
diag("timeout error expected");
|
||||
return FAIL;
|
||||
}
|
||||
elapsed= time(NULL) - start;
|
||||
diag("elapsed: %lu", (unsigned long)elapsed);
|
||||
mysql_close(mysql);
|
||||
FAIL_IF(elapsed > 2 * timeout, "timeout ignored")
|
||||
return OK;
|
||||
}
|
||||
|
||||
int test_connection_timeout3(MYSQL *my)
|
||||
{
|
||||
unsigned int timeout= 5;
|
||||
unsigned int read_write_timeout= 10;
|
||||
int rc;
|
||||
time_t start, elapsed;
|
||||
MYSQL *mysql= mysql_init(NULL);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&timeout);
|
||||
mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (unsigned int *)&read_write_timeout);
|
||||
mysql_options(mysql, MYSQL_OPT_WRITE_TIMEOUT, (unsigned int *)&read_write_timeout);
|
||||
mysql_options(mysql, MYSQL_INIT_COMMAND, "set @a:=SLEEP(6)");
|
||||
start= time(NULL);
|
||||
if (mysql_real_connect(mysql, hostname, username, password, schema, port, NULL, CLIENT_REMEMBER_OPTIONS))
|
||||
{
|
||||
diag("timeout error expected");
|
||||
elapsed= time(NULL) - start;
|
||||
diag("elapsed: %lu", (unsigned long)elapsed);
|
||||
return FAIL;
|
||||
}
|
||||
elapsed= time(NULL) - start;
|
||||
diag("elapsed: %lu", (unsigned long)elapsed);
|
||||
FAIL_IF(elapsed > timeout + 1, "timeout ignored")
|
||||
|
||||
mysql_close(mysql);
|
||||
mysql= mysql_init(NULL);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&timeout);
|
||||
mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (unsigned int *)&read_write_timeout);
|
||||
mysql_options(mysql, MYSQL_OPT_WRITE_TIMEOUT, (unsigned int *)&read_write_timeout);
|
||||
|
||||
if (!mysql_real_connect(mysql, hostname, username, password, schema, port, NULL, CLIENT_REMEMBER_OPTIONS))
|
||||
{
|
||||
diag("Error: %s", mysql_error(mysql));
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
start= time(NULL);
|
||||
rc= mysql_query(mysql, "SET @a:=SLEEP(12)");
|
||||
elapsed= time(NULL) - start;
|
||||
diag("elapsed: %lu", (unsigned long)elapsed);
|
||||
FAIL_IF(!rc, "timeout expected");
|
||||
mysql_close(mysql);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/* test should run with valgrind */
|
||||
static int test_conc118(MYSQL *mysql)
|
||||
{
|
||||
@@ -862,6 +928,8 @@ struct my_tests_st my_tests[] = {
|
||||
{"test_conc21", test_conc21, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||
{"test_conc26", test_conc26, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"test_connection_timeout", test_connection_timeout, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"test_connection_timeout2", test_connection_timeout2, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{"test_connection_timeout3", test_connection_timeout3, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||
{NULL, NULL, 0, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@@ -182,8 +182,8 @@ static int test_conc95(MYSQL *my)
|
||||
if (!mysql_real_connect(mysql, hostname, "ssluser1", sslpw, schema,
|
||||
port, socketname, 0))
|
||||
{
|
||||
diag("could not establish x509 connection. Error: %s", mysql_error(mysql));
|
||||
mysql_close(mysql);
|
||||
diag("could not establish x509 connection");
|
||||
return FAIL;
|
||||
}
|
||||
mysql_close(mysql);
|
||||
|
Reference in New Issue
Block a user