1
0
mirror of https://github.com/mariadb-corporation/mariadb-connector-c.git synced 2025-08-07 02:42:49 +03:00

- Renamed cio to pvio (pluggable virtual IO)

- minor fixes in windows schannel
This commit is contained in:
Georg Richter
2015-10-27 10:24:48 +01:00
parent 04a4592271
commit 7500f37150
36 changed files with 1711 additions and 1645 deletions

View File

@@ -176,7 +176,7 @@ IF(WIN32)
MESSAGE(STATUS "SSL_TYPE ${SSL_TYPE}")
ADD_DEFINITIONS(-DHAVE_SCHANNEL -DHAVE_SSL)
SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/libmariadb/secure/schannel.c" "${CMAKE_SOURCE_DIR}/libmariadb/secure/ma_schannel.c")
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/plugins/cio/")
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/plugins/pvio/")
ENDIF()
ENDIF()

View File

@@ -8,40 +8,65 @@
#include <my_dir.h>
#include <m_string.h>
#define CLIENT_PLUGIN_INFO_VERSION "1.0.0"
static struct option long_options[]=
{
{"all", no_argument, 0, 'a'},
{"builtin", no_argument, 0, 'b'},
{"dynamic", no_argument, 0, 'd'},
{"all", no_argument, 0, 'a'},
{"plugin", 1, 0, 'p'},
{"directory", 1, 0, 'p'},
{"plugin_name", 1, 0, 'n'},
{"version", no_argument, 0, 'v'},
{"help", no_argument, 0, '?'},
{NULL, 0, 0, 0}
};
static char *values[] =
{
"show information for all plugins",
"show informaion for builtin plugins",
"show information for dynamic plugins",
"show information for dynamic plugins in specified directory",
"show information for specified plugin",
"show version information",
"display this help and exit",
NULL
};
struct st_plugin_type
{
int type;
char *typename;
};
int my_errno=0;
static struct st_plugin_type plugin_types[]=
{
{MYSQL_CLIENT_AUTHENTICATION_PLUGIN, "authentication"},
{MARIADB_CLIENT_CIO_PLUGIN, "client/server protocol"},
{MARIADB_CLIENT_PVIO_PLUGIN, "virtual IO"},
{MARIADB_CLIENT_TRACE_PLUGIN, "trace"},
{MARIADB_CLIENT_REMOTEIO_PLUGIN, "remote file access"},
{MARIADB_CLIENT_CONNECTION_PLUGIN, "connection handler"},
{0, "unknown"}
};
static void version()
{
printf("%s Version %s\n", my_progname, CLIENT_PLUGIN_INFO_VERSION);
}
static void usage(void)
{
int i=0;
printf("%s Version %s\n", my_progname, CLIENT_PLUGIN_INFO_VERSION);
puts("Copyright 2015 MariaDB Corporation AB");
puts("Show client plugin information for MariaDB Connector/C.");
printf("Usage: %s [OPTIONS] [plugin_name]\n", my_progname);
while (long_options[i].name)
{
printf(" --%-12s -%c\n", long_options[i].name, long_options[i].val);
printf(" --%-12s -%s\n", long_options[i].name, values[i]);
i++;
}
}
@@ -60,8 +85,8 @@ static char *get_type_name(int type)
static void show_plugin_info(struct st_mysql_client_plugin *plugin, my_bool builtin)
{
printf("Type: %s\n", get_type_name(plugin->type));
printf("Name: %s\n", plugin->name);
printf("Type: %s\n", get_type_name(plugin->type));
printf("Desc: %s\n", plugin->desc);
printf("Author: %s\n", plugin->author);
printf("License: %s\n", plugin->license);
@@ -103,18 +128,23 @@ static void show_file(char *filename)
}
}
static void show_dynamic()
static void show_dynamic(const char *directory)
{
MY_DIR *dir= NULL;
unsigned int i;
char *env_plugin_dir= getenv("MARIADB_PLUGIN_DIR");
char *plugin_dir= directory ? (char *)directory : getenv("MARIADB_PLUGIN_DIR");
dir= my_dir(env_plugin_dir ? env_plugin_dir : PLUGINDIR, 0);
if (!plugin_dir)
plugin_dir= PLUGINDIR;
if (!dir->number_off_files)
printf("plugin_dir %s\n", plugin_dir);
dir= my_dir(plugin_dir, 0);
if (!dir || !dir->number_off_files)
{
printf("No plugins found in %s\n", env_plugin_dir ? env_plugin_dir : PLUGINDIR);
return;
printf("No plugins found in %s\n", plugin_dir);
goto end;
}
for (i=0; i < dir->number_off_files; i++)
@@ -123,6 +153,7 @@ static void show_dynamic()
if (p)
show_file(dir->dir_entry[i].name);
}
end:
if (dir)
my_dirend(dir);
}
@@ -133,34 +164,44 @@ int main(int argc, char *argv[])
int c;
my_progname= argv[0];
mysql_server_init(0, NULL, NULL);
if (argc <= 1)
{
usage();
exit(1);
}
c= getopt_long(argc, argv, "bdap", long_options, &option_index);
c= getopt_long(argc, argv, "bdapvgh?", long_options, &option_index);
switch(c) {
case 'a': /* all */
show_builtin();
show_dynamic();
show_dynamic(NULL);
break;
case 'b': /* builtin */
show_builtin();
break;
case 'd': /* dynamic */
show_dynamic();
show_dynamic(NULL);
break;
case 'v':
version();
break;
case 'n':
if (argc > 2)
show_file(argv[2]);
break;
case 'p':
if (argc > 2)
{
show_file(argv[2]);
show_dynamic(argv[2]);
break;
}
default:
case '?':
usage();
break;
default:
printf("unrecocognized option: %s", argv[1]);
exit(1);
}
exit(0);
}

View File

@@ -15,10 +15,10 @@ ENDMACRO()
MARK_AS_ADVANCED(PLUGINS)
# CIO
REGISTER_PLUGIN("SOCKET" "${CMAKE_SOURCE_DIR}/plugins/cio/cio_socket.c" "cio_socket_plugin" "STATIC" 0)
REGISTER_PLUGIN("SOCKET" "${CMAKE_SOURCE_DIR}/plugins/pvio/pvio_socket.c" "pvio_socket_plugin" "STATIC" 0)
IF(WIN32)
REGISTER_PLUGIN("NPIPE" "${CMAKE_SOURCE_DIR}/plugins/cio/cio_npipe.c" "cio_npipe_plugin" "DYNAMIC" 1)
REGISTER_PLUGIN("SHMEM" "${CMAKE_SOURCE_DIR}/plugins/cio/cio_shmem.c" "cio_shmem_plugin" "DYNAMIC" 1)
REGISTER_PLUGIN("NPIPE" "${CMAKE_SOURCE_DIR}/plugins/pvio/pvio_npipe.c" "pvio_npipe_plugin" "DYNAMIC" 1)
REGISTER_PLUGIN("SHMEM" "${CMAKE_SOURCE_DIR}/plugins/pvio/pvio_shmem.c" "pvio_shmem_plugin" "DYNAMIC" 1)
ENDIF()
# AUTHENTICATION

View File

@@ -4,6 +4,8 @@ SET(MARIADB_CLIENT_INCLUDES config-win.h
getopt.h
hash.h
ma_common.h
ma_pvio.h
ma_ssl.h
m_ctype.h
m_string.h
ma_dyncol.h

View File

@@ -1,121 +0,0 @@
#ifndef _ma_cio_h_
#define _ma_cio_h_
#define cio_defined
#ifdef HAVE_SSL
#include <ma_ssl.h>
#endif
#define CIO_SET_ERROR if (cio->set_error) \
cio->set_error
#define CIO_READ_AHEAD_CACHE_SIZE 16384
#define CIO_READ_AHEAD_CACHE_MIN_SIZE 2048
#define CIO_EINTR_TRIES 2
struct st_ma_cio_methods;
typedef struct st_ma_cio_methods CIO_METHODS;
#ifndef ssl_defined
#define ssl_defined
struct st_ma_cio_ssl;
typedef struct st_ma_cio_ssl MARIADB_SSL;
#endif
enum enum_cio_timeout {
CIO_CONNECT_TIMEOUT= 0,
CIO_READ_TIMEOUT,
CIO_WRITE_TIMEOUT
};
enum enum_cio_io_event
{
VIO_IO_EVENT_READ,
VIO_IO_EVENT_WRITE,
VIO_IO_EVENT_CONNECT
};
enum enum_cio_type {
CIO_TYPE_UNIXSOCKET= 0,
CIO_TYPE_SOCKET,
CIO_TYPE_NAMEDPIPE
};
enum enum_cio_operation {
CIO_READ= 0,
CIO_WRITE=1
};
struct st_cio_callback;
typedef struct st_cio_callback {
void (*callback)(MYSQL *mysql, uchar *buffer, size_t size);
struct st_cio_callback *next;
} CIO_CALLBACK;
struct st_ma_cio {
void *data;
/* read ahead cache */
uchar *cache;
uchar *cache_pos;
size_t cache_size;
enum enum_cio_type type;
int timeout[3];
int ssl_type; /* todo: change to enum (ssl plugins) */
MARIADB_SSL *cssl;
MYSQL *mysql;
struct mysql_async_context *async_context; /* For non-blocking API */
CIO_METHODS *methods;
FILE *fp;
void (*set_error)(MYSQL *mysql, unsigned int error_nr, const char *sqlstate, const char *format, ...);
void (*callback)(MARIADB_CIO *cio, my_bool is_read, const char *buffer, size_t length);
};
typedef struct st_ma_cio_cinfo
{
const char *host;
const char *unix_socket;
int port;
enum enum_cio_type type;
MYSQL *mysql;
} MA_CIO_CINFO;
struct st_ma_cio_methods
{
my_bool (*set_timeout)(MARIADB_CIO *cio, enum enum_cio_timeout type, int timeout);
int (*get_timeout)(MARIADB_CIO *cio, enum enum_cio_timeout type);
size_t (*read)(MARIADB_CIO *cio, const uchar *buffer, size_t length);
size_t (*async_read)(MARIADB_CIO *cio, const uchar *buffer, size_t length);
size_t (*write)(MARIADB_CIO *cio, const uchar *buffer, size_t length);
size_t (*async_write)(MARIADB_CIO *cio, const uchar *buffer, size_t length);
int (*wait_io_or_timeout)(MARIADB_CIO *cio, my_bool is_read, int timeout);
my_bool (*blocking)(MARIADB_CIO *cio, my_bool value, my_bool *old_value);
my_bool (*connect)(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo);
my_bool (*close)(MARIADB_CIO *cio);
int (*fast_send)(MARIADB_CIO *cio);
int (*keepalive)(MARIADB_CIO *cio);
my_bool (*get_handle)(MARIADB_CIO *cio, void *handle);
my_bool (*is_blocking)(MARIADB_CIO *cio);
my_bool (*is_alive)(MARIADB_CIO *cio);
};
/* Function prototypes */
MARIADB_CIO *ma_cio_init(MA_CIO_CINFO *cinfo);
void ma_cio_close(MARIADB_CIO *cio);
size_t ma_cio_cache_read(MARIADB_CIO *cio, uchar *buffer, size_t length);
size_t ma_cio_read(MARIADB_CIO *cio, const uchar *buffer, size_t length);
size_t ma_cio_write(MARIADB_CIO *cio, const uchar *buffer, size_t length);
int ma_cio_get_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type);
my_bool ma_cio_set_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type, int timeout);
int ma_cio_fast_send(MARIADB_CIO *cio);
int ma_cio_keepalive(MARIADB_CIO *cio);
my_socket ma_cio_get_socket(MARIADB_CIO *cio);
my_bool ma_cio_is_blocking(MARIADB_CIO *cio);
my_bool ma_cio_blocking(MARIADB_CIO *cio, my_bool block, my_bool *previous_mode);
my_bool ma_cio_is_blocking(MARIADB_CIO *cio);
int ma_cio_wait_io_or_timeout(MARIADB_CIO *cio, my_bool is_read, int timeout);
my_bool ma_cio_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo);
my_bool ma_cio_is_alive(MARIADB_CIO *cio);
my_bool ma_cio_get_handle(MARIADB_CIO *cio, void *handle);
#endif /* _ma_cio_h_ */

121
include/ma_pvio.h Normal file
View File

@@ -0,0 +1,121 @@
#ifndef _ma_pvio_h_
#define _ma_pvio_h_
#define cio_defined
#ifdef HAVE_SSL
#include <ma_ssl.h>
#endif
#define PVIO_SET_ERROR if (pvio->set_error) \
pvio->set_error
#define PVIO_READ_AHEAD_CACHE_SIZE 16384
#define PVIO_READ_AHEAD_CACHE_MIN_SIZE 2048
#define PVIO_EINTR_TRIES 2
struct st_ma_pvio_methods;
typedef struct st_ma_pvio_methods PVIO_METHODS;
#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,
PVIO_WRITE_TIMEOUT
};
enum enum_pvio_io_event
{
VIO_IO_EVENT_READ,
VIO_IO_EVENT_WRITE,
VIO_IO_EVENT_CONNECT
};
enum enum_pvio_type {
PVIO_TYPE_UNIXSOCKET= 0,
PVIO_TYPE_SOCKET,
PVIO_TYPE_NAMEDPIPE
};
enum enum_pvio_operation {
PVIO_READ= 0,
PVIO_WRITE=1
};
struct st_pvio_callback;
typedef struct st_pvio_callback {
void (*callback)(MYSQL *mysql, uchar *buffer, size_t size);
struct st_pvio_callback *next;
} PVIO_CALLBACK;
typedef struct st_ma_pvio {
void *data;
/* read ahead cache */
uchar *cache;
uchar *cache_pos;
size_t cache_size;
enum enum_pvio_type type;
int timeout[3];
int ssl_type; /* todo: change to enum (ssl plugins) */
MARIADB_SSL *cssl;
MYSQL *mysql;
struct mysql_async_context *async_context; /* For non-blocking API */
PVIO_METHODS *methods;
FILE *fp;
void (*set_error)(MYSQL *mysql, unsigned int error_nr, const char *sqlstate, const char *format, ...);
void (*callback)(MARIADB_PVIO *pvio, my_bool is_read, const char *buffer, size_t length);
} MARIADB_PVIO;
typedef struct st_ma_pvio_cinfo
{
const char *host;
const char *unix_socket;
int port;
enum enum_pvio_type type;
MYSQL *mysql;
} MA_PVIO_CINFO;
struct st_ma_pvio_methods
{
my_bool (*set_timeout)(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout);
int (*get_timeout)(MARIADB_PVIO *pvio, enum enum_pvio_timeout type);
size_t (*read)(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
size_t (*async_read)(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
size_t (*write)(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
size_t (*async_write)(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
int (*wait_io_or_timeout)(MARIADB_PVIO *pvio, my_bool is_read, int timeout);
my_bool (*blocking)(MARIADB_PVIO *pvio, my_bool value, my_bool *old_value);
my_bool (*connect)(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo);
my_bool (*close)(MARIADB_PVIO *pvio);
int (*fast_send)(MARIADB_PVIO *pvio);
int (*keepalive)(MARIADB_PVIO *pvio);
my_bool (*get_handle)(MARIADB_PVIO *pvio, void *handle);
my_bool (*is_blocking)(MARIADB_PVIO *pvio);
my_bool (*is_alive)(MARIADB_PVIO *pvio);
};
/* Function prototypes */
MARIADB_PVIO *ma_pvio_init(MA_PVIO_CINFO *cinfo);
void ma_pvio_close(MARIADB_PVIO *pvio);
size_t ma_pvio_cache_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length);
size_t ma_pvio_read(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
size_t ma_pvio_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
int ma_pvio_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type);
my_bool ma_pvio_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout);
int ma_pvio_fast_send(MARIADB_PVIO *pvio);
int ma_pvio_keepalive(MARIADB_PVIO *pvio);
my_socket ma_pvio_get_socket(MARIADB_PVIO *pvio);
my_bool ma_pvio_is_blocking(MARIADB_PVIO *pvio);
my_bool ma_pvio_blocking(MARIADB_PVIO *pvio, my_bool block, my_bool *previous_mode);
my_bool ma_pvio_is_blocking(MARIADB_PVIO *pvio);
int ma_pvio_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout);
my_bool ma_pvio_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo);
my_bool ma_pvio_is_alive(MARIADB_PVIO *pvio);
my_bool ma_pvio_get_handle(MARIADB_PVIO *pvio, void *handle);
#endif /* _ma_pvio_h_ */

View File

@@ -1,7 +1,7 @@
#ifndef _ma_ssl_h_
#define _ma_ssl_h_
enum enum_cio_ssl_type {
enum enum_pvio_ssl_type {
SSL_TYPE_DEFAULT=0,
#ifdef _WIN32
SSL_TYPE_SCHANNEL,
@@ -10,9 +10,9 @@ enum enum_cio_ssl_type {
SSL_TYPE_GNUTLS
};
typedef struct st_ma_cio_ssl {
typedef struct st_ma_pvio_ssl {
void *data;
MARIADB_CIO *cio;
MARIADB_PVIO *pvio;
void *ssl;
} MARIADB_SSL;
@@ -125,14 +125,14 @@ 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);
/* Function prototypes */
MARIADB_SSL *ma_cio_ssl_init(MYSQL *mysql);
my_bool ma_cio_ssl_connect(MARIADB_SSL *cssl);
size_t ma_cio_ssl_read(MARIADB_SSL *cssl, const uchar *buffer, size_t length);
size_t ma_cio_ssl_write(MARIADB_SSL *cssl, const uchar *buffer, size_t length);
my_bool ma_cio_ssl_close(MARIADB_SSL *cssl);
int ma_cio_ssl_verify_server_cert(MARIADB_SSL *cssl);
const char *ma_cio_ssl_cipher(MARIADB_SSL *cssl);
my_bool ma_cio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_list);
my_bool ma_cio_start_ssl(MARIADB_CIO *cio);
MARIADB_SSL *ma_pvio_ssl_init(MYSQL *mysql);
my_bool ma_pvio_ssl_connect(MARIADB_SSL *cssl);
size_t ma_pvio_ssl_read(MARIADB_SSL *cssl, const uchar *buffer, size_t length);
size_t ma_pvio_ssl_write(MARIADB_SSL *cssl, const uchar *buffer, size_t length);
my_bool ma_pvio_ssl_close(MARIADB_SSL *cssl);
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);
#endif /* _ma_ssl_h_ */

View File

@@ -48,12 +48,12 @@
/* Connector/C specific plugin types */
#define MARIADB_CLIENT_REMOTEIO_PLUGIN 100 /* communication IO */
#define MARIADB_CLIENT_CIO_PLUGIN 101
#define MARIADB_CLIENT_PVIO_PLUGIN 101
#define MARIADB_CLIENT_TRACE_PLUGIN 102
#define MARIADB_CLIENT_CONNECTION_PLUGIN 103
#define MARIADB_CLIENT_REMOTEIO_PLUGIN_INTERFACE_VERSION 0x0100
#define MARIADB_CLIENT_CIO_PLUGIN_INTERFACE_VERSION 0x0100
#define MARIADB_CLIENT_PVIO_PLUGIN_INTERFACE_VERSION 0x0100
#define MARIADB_CLIENT_TRACE_PLUGIN_INTERFACE_VERSION 0x0100
#define MARIADB_CLIENT_CONNECTION_PLUGIN_INTERFACE_VERSION 0x0100
@@ -100,16 +100,16 @@ typedef struct st_ma_connection_plugin
#define MARIADB_DB_DRIVER(a) ((a)->ext_db)
/******************* Communication IO plugin *****************/
#include <ma_cio.h>
#include <ma_pvio.h>
#ifdef HAVE_SSL
#include <ma_ssl.h>
#endif
typedef struct st_mariadb_client_plugin_CIO
typedef struct st_mariadb_client_plugin_PVIO
{
MYSQL_CLIENT_PLUGIN_HEADER
struct st_ma_cio_methods *methods;
} MARIADB_CIO_PLUGIN;
struct st_ma_pvio_methods *methods;
} MARIADB_PVIO_PLUGIN;
/******** authentication plugin specific declarations *********/
#include <mysql/plugin_auth_common.h>

View File

@@ -18,16 +18,16 @@
#ifndef MYSQL_ASYNC_H
#define MYSQL_ASYNC_H
extern int my_connect_async(MARIADB_CIO *cio,
extern int my_connect_async(MARIADB_PVIO *pvio,
const struct sockaddr *name, uint namelen,
int vio_timeout);
extern ssize_t my_recv_async(MARIADB_CIO *cio,
extern ssize_t my_recv_async(MARIADB_PVIO *pvio,
const unsigned char *buf, size_t size, int timeout);
extern ssize_t my_send_async(MARIADB_CIO *cio,
extern ssize_t my_send_async(MARIADB_PVIO *pvio,
const unsigned char *buf, size_t size,
int timeout);
extern my_bool my_io_wait_async(struct mysql_async_context *b,
enum enum_cio_io_event event, int timeout);
enum enum_pvio_io_event event, int timeout);
#ifdef HAVE_SSL
extern int my_ssl_read_async(struct mysql_async_context *b, MARIADB_SSL *ssl,
void *buf, int size);

View File

@@ -209,10 +209,10 @@ enum enum_server_command
#define NET_WRITE_TIMEOUT 60 /* Timeout on write */
#define NET_WAIT_TIMEOUT 8*60*60 /* Wait for new query */
#ifndef cio_defined
#define cio_defined
struct st_ma_cio;
typedef struct st_ma_cio MARIADB_CIO;
#ifndef pvio_defined
#define pvio_defined
struct st_ma_pvio;
typedef struct st_ma_pvio MARIADB_PVIO;
#endif
#define MAX_CHAR_WIDTH 255 /* Max length for a CHAR colum */
@@ -237,7 +237,7 @@ typedef struct st_connection_handler
} MA_CONNECTION_HANDLER;
typedef struct st_net {
MARIADB_CIO *cio;
MARIADB_PVIO *pvio;
unsigned char *buff;
unsigned char *buff_end,*write_pos,*read_pos;
my_socket fd; /* For Perl DBI/dbd */
@@ -328,7 +328,7 @@ extern unsigned long net_buffer_length;
#define net_new_transaction(net) ((net)->pkt_nr=0)
int my_net_init(NET *net, MARIADB_CIO *cio);
int my_net_init(NET *net, MARIADB_PVIO *pvio);
void net_end(NET *net);
void net_clear(NET *net);
int net_flush(NET *net);

View File

@@ -9,7 +9,7 @@ ADD_DEFINITIONS(-D THREAD)
SET(EXPORT_SYMBOLS
load_defaults
ma_cio_register_callback
ma_pvio_register_callback
mariadb_connection
mariadb_convert_string
mariadb_dyncol_check
@@ -272,7 +272,7 @@ libmariadb.c
list.c
llstr.c
longlong2str.c
ma_cio.c
ma_pvio.c
ma_ssl.c
mf_dirname.c
mf_fn_ext.c

View File

@@ -58,7 +58,7 @@ static MEM_ROOT mem_root;
static uint valid_plugins[][2]= {
{MYSQL_CLIENT_AUTHENTICATION_PLUGIN, MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION},
{MARIADB_CLIENT_CIO_PLUGIN, MARIADB_CLIENT_CIO_PLUGIN_INTERFACE_VERSION},
{MARIADB_CLIENT_PVIO_PLUGIN, MARIADB_CLIENT_PVIO_PLUGIN_INTERFACE_VERSION},
{MARIADB_CLIENT_TRACE_PLUGIN, MARIADB_CLIENT_TRACE_PLUGIN_INTERFACE_VERSION},
{MARIADB_CLIENT_REMOTEIO_PLUGIN, MARIADB_CLIENT_REMOTEIO_PLUGIN_INTERFACE_VERSION},
{MARIADB_CLIENT_CONNECTION_PLUGIN, MARIADB_CLIENT_CONNECTION_PLUGIN_INTERFACE_VERSION},
@@ -183,8 +183,11 @@ add_plugin(MYSQL *mysql, struct st_mysql_client_plugin *plugin, void *dlhandle,
errmsg= "Unknown client plugin type";
goto err1;
}
if (check_plugin_version(plugin, valid_plugins[plugin_nr][1], errmsg))
if (check_plugin_version(plugin, valid_plugins[plugin_nr][1], errbuf))
{
errmsg= errbuf;
goto err1;
}
/* Call the plugin initialization function, if any */
if (plugin->init && plugin->init(errbuf, sizeof(errbuf), argc, args))

View File

@@ -65,7 +65,7 @@
#ifndef _WIN32
#include <poll.h>
#endif
#include <ma_cio.h>
#include <ma_pvio.h>
#include <ma_dyncol.h>
#include <mysql/client_plugin.h>
@@ -88,7 +88,7 @@ extern const CHARSET_INFO * mysql_find_charset_name(const char * const name);
extern int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
const char *data_plugin, const char *db);
extern LIST *cio_callback;
extern LIST *pvio_callback;
/* prepare statement methods from my_stmt.c */
extern my_bool mthd_supported_buffer_type(enum enum_field_types type);
@@ -178,7 +178,7 @@ net_safe_read(MYSQL *mysql)
ulong len=0;
restart:
if (net->cio != 0)
if (net->pvio != 0)
len=my_net_read(net);
if (len == packet_error || len == 0)
@@ -361,7 +361,7 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
DBUG_RETURN(result);
}
if (mysql->net.cio == 0)
if (mysql->net.pvio == 0)
{ /* Do reconnect if possible */
if (mysql_reconnect(mysql))
{
@@ -562,10 +562,10 @@ end_server(MYSQL *mysql)
/* if net->error 2 and reconnect is activated, we need to inforn
connection handler */
if (mysql->net.cio != 0)
if (mysql->net.pvio != 0)
{
ma_cio_close(mysql->net.cio);
mysql->net.cio= 0; /* Marker */
ma_pvio_close(mysql->net.pvio);
mysql->net.pvio= 0; /* Marker */
}
net_end(&mysql->net);
free_old_query(mysql);
@@ -1129,7 +1129,7 @@ mysql_init(MYSQL *mysql)
if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
return 0;
mysql->free_me=1;
mysql->net.cio= 0;
mysql->net.pvio= 0;
}
else
bzero((char*) (mysql),sizeof(*(mysql)));
@@ -1173,9 +1173,9 @@ const char * STDCALL
mysql_get_ssl_cipher(MYSQL *mysql)
{
#ifdef HAVE_SSL
if (mysql->net.cio && mysql->net.cio->cssl)
if (mysql->net.pvio && mysql->net.pvio->cssl)
{
return ma_cio_ssl_cipher(mysql->net.cio->cssl);
return ma_pvio_ssl_cipher(mysql->net.pvio->cssl);
}
#endif
return(NULL);
@@ -1297,8 +1297,8 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
char buff[NAME_LEN+USERNAME_LENGTH+100];
char *end, *end_pkt, *host_info,
*charset_name= NULL;
MA_CIO_CINFO cinfo= {NULL, NULL, 0, -1, NULL};
MARIADB_CIO *cio= NULL;
MA_PVIO_CINFO cinfo= {NULL, NULL, 0, -1, NULL};
MARIADB_PVIO *pvio= NULL;
char *scramble_data;
const char *scramble_plugin;
uint pkt_length, scramble_len, pkt_scramble_len= 0;
@@ -1341,7 +1341,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
ma_set_connect_attrs(mysql);
if (net->cio) /* check if we are already connected */
if (net->pvio) /* check if we are already connected */
{
SET_CLIENT_ERROR(mysql, CR_ALREADY_CONNECTED, SQLSTATE_UNKNOWN, 0);
DBUG_RETURN(NULL);
@@ -1383,7 +1383,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
/* try to connect via cio_init */
/* try to connect via pvio_init */
cinfo.host= host;
cinfo.unix_socket= unix_socket;
cinfo.port= port;
@@ -1400,7 +1400,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
{
cinfo.host= LOCAL_HOST;
cinfo.unix_socket= (unix_socket) ? unix_socket : mysql_unix_port;
cinfo.type= CIO_TYPE_UNIXSOCKET;
cinfo.type= PVIO_TYPE_UNIXSOCKET;
sprintf(host_info=buff,ER(CR_LOCALHOST_CONNECTION),cinfo.host);
}
else
@@ -1414,7 +1414,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
!have_tcpip) &&
mysql->options.protocol != MYSQL_PROTOCOL_TCP)
{
cinfo.type= CIO_TYPE_NAMEDPIPE;
cinfo.type= PVIO_TYPE_NAMEDPIPE;
sprintf(host_info=buff,ER(CR_NAMEDPIPE_CONNECTION),cinfo.host);
}
else
@@ -1427,30 +1427,30 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
host=LOCAL_HOST;
cinfo.host= host;
cinfo.port= port;
cinfo.type= CIO_TYPE_SOCKET;
cinfo.type= PVIO_TYPE_SOCKET;
sprintf(host_info=buff,ER(CR_TCP_CONNECTION), cinfo.host);
}
/* Initialize and load cio plugin */
if (!(cio= ma_cio_init(&cinfo)))
/* Initialize and load pvio plugin */
if (!(pvio= ma_pvio_init(&cinfo)))
goto error;
/* try to connect */
if (ma_cio_connect(cio, &cinfo) != 0)
if (ma_pvio_connect(pvio, &cinfo) != 0)
{
ma_cio_close(cio);
ma_pvio_close(pvio);
goto error;
}
if (my_net_init(net, cio))
if (my_net_init(net, pvio))
goto error;
ma_cio_keepalive(net->cio);
ma_pvio_keepalive(net->pvio);
strmov(mysql->net.sqlstate, "00000");
/* Get version info */
mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */
/*
if (ma_cio_wait_io_or_timeout(net->cio, FALSE, 0) < 1)
if (ma_pvio_wait_io_or_timeout(net->pvio, FALSE, 0) < 1)
{
my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
ER(CR_SERVER_LOST_EXTENDED),
@@ -1930,7 +1930,7 @@ void my_set_error(MYSQL *mysql,
void mysql_close_slow_part(MYSQL *mysql)
{
if (mysql->net.cio)
if (mysql->net.pvio)
{
free_old_query(mysql);
mysql->status=MYSQL_STATUS_READY; /* Force command */
@@ -1978,7 +1978,7 @@ mysql_close(MYSQL *mysql)
if (mysql->extension)
my_free(mysql->extension);
mysql->net.cio= 0;
mysql->net.pvio= 0;
if (mysql->free_me)
my_free(mysql);
}
@@ -2711,8 +2711,8 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
goto end;
}
mysql->options.extension->async_context= ctxt;
if (mysql->net.cio)
mysql->net.cio->async_context= ctxt;
if (mysql->net.pvio)
mysql->net.pvio->async_context= ctxt;
break;
case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
@@ -3170,7 +3170,7 @@ void STDCALL mysql_server_end()
mysql_client_plugin_deinit();
list_free(cio_callback, 0);
list_free(pvio_callback, 0);
if (my_init_done)
my_end(0);
mysql_client_init= 0;
@@ -3247,9 +3247,9 @@ my_socket STDCALL
mysql_get_socket(const MYSQL *mysql)
{
my_socket sock;
if (mysql->net.cio)
if (mysql->net.pvio)
{
ma_cio_get_handle(mysql->net.cio, &sock);
ma_pvio_get_handle(mysql->net.pvio, &sock);
return sock;
}
return INVALID_SOCKET;

View File

@@ -1,470 +0,0 @@
/************************************************************************************
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 <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
/* MariaDB Communication IO (CIO) interface
CIO is the interface for client server communication and replaces former vio
component of the client library.
CIO support various protcols like sockets, pipes and shared memory, which are
implemented as plugins and can be extended therfore easily.
Interface function description:
ma_cio_init allocates a new CIO object which will be used
for the current connection
ma_cio_close frees all resources of previously allocated CIO object
and closes open connections
ma_cio_read reads data from server
ma_cio_write sends data to server
ma_cio_set_timeout sets timeout for connection, read and write
ma_cio_register_callback
register callback functions for read and write
*/
#include <my_global.h>
#include <my_sys.h>
#include <mysql.h>
#include <errmsg.h>
#include <mysql/client_plugin.h>
#include <string.h>
#include <ma_common.h>
#include <ma_cio.h>
#include <mysql_async.h>
#include <my_context.h>
extern pthread_mutex_t THR_LOCK_lock;
/* callback functions for read/write */
LIST *cio_callback= NULL;
/* {{{ MARIADB_CIO *ma_cio_init */
MARIADB_CIO *ma_cio_init(MA_CIO_CINFO *cinfo)
{
/* check connection type and load the required plugin.
* Currently we support the following cio types:
* cio_socket
* cio_namedpipe
*/
char *cio_plugins[] = {"cio_socket", "cio_npipe"};
int type;
MARIADB_CIO_PLUGIN *cio_plugin;
MARIADB_CIO *cio= NULL;
switch (cinfo->type)
{
case CIO_TYPE_UNIXSOCKET:
case CIO_TYPE_SOCKET:
type= 0;
break;
#ifdef _WIN32
case CIO_TYPE_NAMEDPIPE:
type= 1;
break;
#endif
default:
return NULL;
}
if (!(cio_plugin= (MARIADB_CIO_PLUGIN *)
mysql_client_find_plugin(cinfo->mysql,
cio_plugins[type],
MARIADB_CLIENT_CIO_PLUGIN)))
{
/* error handling */
return NULL;
}
if (!(cio= (MARIADB_CIO *)my_malloc(sizeof(MARIADB_CIO),
MYF(MY_WME | MY_ZEROFILL))))
{
CIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
return NULL;
}
/* register error routine and methods */
cio->methods= cio_plugin->methods;
cio->set_error= my_set_error;
/* set tineouts */
if (cio->methods->set_timeout)
{
cio->methods->set_timeout(cio, CIO_CONNECT_TIMEOUT, cinfo->mysql->options.connect_timeout);
cio->methods->set_timeout(cio, CIO_READ_TIMEOUT, cinfo->mysql->options.read_timeout);
cio->methods->set_timeout(cio, CIO_WRITE_TIMEOUT, cinfo->mysql->options.write_timeout);
}
if (!(cio->cache= my_malloc(CIO_READ_AHEAD_CACHE_SIZE, MYF(MY_ZEROFILL))))
{
CIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
return NULL;
}
cio->cache_size= 0;
cio->cache_pos= cio->cache;
return cio;
}
/* }}} */
/* {{{ my_bool ma_cio_is_alive */
my_bool ma_cio_is_alive(MARIADB_CIO *cio)
{
if (cio->methods->is_alive)
return cio->methods->is_alive(cio);
return FALSE;
}
/* }}} */
/* {{{ int ma_cio_fast_send */
int ma_cio_fast_send(MARIADB_CIO *cio)
{
if (!cio || !cio->methods->fast_send)
return 1;
return cio->methods->fast_send(cio);
}
/* }}} */
/* {{{ int ma_cio_keepalive */
int ma_cio_keepalive(MARIADB_CIO *cio)
{
if (!cio || !cio->methods->keepalive)
return 1;
return cio->methods->keepalive(cio);
}
/* }}} */
/* {{{ my_bool ma_cio_set_timeout */
my_bool ma_cio_set_timeout(MARIADB_CIO *cio,
enum enum_cio_timeout type,
int timeout)
{
if (!cio)
return 1;
if (cio->methods->set_timeout)
return cio->methods->set_timeout(cio, type, timeout);
return 1;
}
/* }}} */
/* {{{ size_t ma_cio_read_async */
static size_t ma_cio_read_async(MARIADB_CIO *cio, const uchar *buffer, size_t length)
{
ssize_t res;
struct mysql_async_context *b= cio->async_context;
int timeout= cio->timeout[CIO_READ_TIMEOUT];
for (;;)
{
/* todo: async */
if (cio->methods->async_read)
res= cio->methods->async_read(cio, buffer, length);
if (res >= 0 /* || IS_BLOCKING_ERROR()*/)
return res;
b->events_to_wait_for= MYSQL_WAIT_READ;
if (timeout >= 0)
{
b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
b->timeout_value= timeout;
}
if (b->suspend_resume_hook)
(*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
my_context_yield(&b->async_context);
if (b->suspend_resume_hook)
(*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
if (b->events_occured & MYSQL_WAIT_TIMEOUT)
return -1;
}
}
/* }}} */
/* {{{ size_t ma_cio_read */
size_t ma_cio_read(MARIADB_CIO *cio, const uchar *buffer, size_t length)
{
size_t r= -1;
if (!cio)
return -1;
if (cio && cio->async_context && cio->async_context->active)
{
goto end;
r= ma_cio_read_async(cio, buffer, length);
}
else
{
if (cio->async_context)
{
/*
If switching from non-blocking to blocking API usage, set the socket
back to blocking mode.
*/
my_bool old_mode;
ma_cio_blocking(cio, TRUE, &old_mode);
}
}
/* secure connection */
#ifdef HAVE_SSL
if (cio->cssl)
r= ma_cio_ssl_read(cio->cssl, buffer, length);
else
#endif
if (cio->methods->read)
r= cio->methods->read(cio, buffer, length);
end:
if (cio_callback)
{
void (*callback)(int mode, MYSQL *mysql, const uchar *buffer, size_t length);
LIST *p= cio_callback;
while (p)
{
callback= p->data;
callback(0, cio->mysql, buffer, r);
p= p->next;
}
}
return r;
}
/* }}} */
/* {{{ size_t ma_cio_cache_read */
size_t ma_cio_cache_read(MARIADB_CIO *cio, uchar *buffer, size_t length)
{
size_t r;
if (!cio)
return -1;
if (!cio->cache)
return ma_cio_read(cio, buffer, length);
if (cio->cache + cio->cache_size > cio->cache_pos)
{
r= MIN(length, (size_t)(cio->cache + cio->cache_size - cio->cache_pos));
memcpy(buffer, cio->cache_pos, r);
cio->cache_pos+= r;
}
else if (length >= CIO_READ_AHEAD_CACHE_MIN_SIZE)
{
r= ma_cio_read(cio, buffer, length);
}
else
{
r= ma_cio_read(cio, cio->cache, CIO_READ_AHEAD_CACHE_SIZE);
if ((ssize_t)r > 0)
{
if (length < r)
{
cio->cache_size= r;
cio->cache_pos= cio->cache + length;
r= length;
}
memcpy(buffer, cio->cache, r);
}
}
return r;
}
/* }}} */
/* {{{ size_t ma_cio_write */
size_t ma_cio_write(MARIADB_CIO *cio, const uchar *buffer, size_t length)
{
size_t r;
if (!cio)
return -1;
if (cio_callback)
{
void (*callback)(int mode, MYSQL *mysql, const uchar *buffer, size_t length);
LIST *p= cio_callback;
while (p)
{
callback= p->data;
callback(1, cio->mysql, buffer, length);
p= p->next;
}
}
/* secure connection */
#ifdef HAVE_SSL
if (cio->cssl)
r= ma_cio_ssl_write(cio->cssl, buffer, length);
else
#endif
if (cio->methods->write)
r= cio->methods->write(cio, buffer, length);
if (cio->callback)
cio->callback(cio, 0, buffer, r);
return r;
}
/* }}} */
/* {{{ void ma_cio_close */
void ma_cio_close(MARIADB_CIO *cio)
{
/* free internal structures and close connection */
#ifdef HAVE_SSL
if (cio && cio->cssl)
{
ma_cio_ssl_close(cio->cssl);
my_free((gptr)cio->cssl);
}
#endif
if (cio && cio->methods->close)
cio->methods->close(cio);
if (cio->cache)
my_free((gptr)cio->cache);
if (cio->fp)
my_fclose(cio->fp, MYF(0));
my_free((gptr)cio);
}
/* }}} */
/* {{{ my_bool ma_cio_get_handle */
my_bool ma_cio_get_handle(MARIADB_CIO *cio, void *handle)
{
if (cio && cio->methods->get_handle)
return cio->methods->get_handle(cio, handle);
return 1;
}
/* }}} */
/* {{{ ma_cio_wait_io_or_timeout */
int ma_cio_wait_io_or_timeout(MARIADB_CIO *cio, my_bool is_read, int timeout)
{
if (cio && cio->async_context && cio->async_context->active)
return my_io_wait_async(cio->async_context,
(is_read) ? VIO_IO_EVENT_READ : VIO_IO_EVENT_WRITE,
timeout);
if (cio && cio->methods->wait_io_or_timeout)
return cio->methods->wait_io_or_timeout(cio, is_read, timeout);
return 1;
}
/* }}} */
/* {{{ my_bool ma_cio_connect */
my_bool ma_cio_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo)
{
if (cio && cio->methods->connect)
return cio->methods->connect(cio, cinfo);
return 1;
}
/* }}} */
/* {{{ my_bool ma_cio_blocking */
my_bool ma_cio_blocking(MARIADB_CIO *cio, my_bool block, my_bool *previous_mode)
{
if (cio && cio->methods->blocking)
return cio->methods->blocking(cio, block, previous_mode);
return 1;
}
/* }}} */
/* {{{ my_bool ma_cio_is_blocking */
my_bool ma_cio_is_blocking(MARIADB_CIO *cio)
{
if (cio && cio->methods->is_blocking)
return cio->methods->is_blocking(cio);
return 1;
}
/* }}} */
#ifdef HAVE_SSL
/* {{{ my_bool ma_cio_start_ssl */
my_bool ma_cio_start_ssl(MARIADB_CIO *cio)
{
if (!cio || !cio->mysql)
return 1;
CLEAR_CLIENT_ERROR(cio->mysql);
if (!(cio->cssl= ma_cio_ssl_init(cio->mysql)))
{
return 1;
}
if (ma_cio_ssl_connect(cio->cssl))
{
my_free((gptr)cio->cssl);
cio->cssl= NULL;
return 1;
}
if ((cio->mysql->options.ssl_ca || cio->mysql->options.ssl_capath) &&
(cio->mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
ma_cio_ssl_verify_server_cert(cio->cssl))
return 1;
if (cio->mysql->options.extension &&
(cio->mysql->options.extension->ssl_fp || cio->mysql->options.extension->ssl_fp_list))
{
if (ma_cio_ssl_check_fp(cio->cssl,
cio->mysql->options.extension->ssl_fp,
cio->mysql->options.extension->ssl_fp_list))
return 1;
}
return 0;
}
/* }}} */
#endif
/* {{{ ma_cio_register_callback */
int ma_cio_register_callback(my_bool register_callback,
void (*callback_function)(int mode, MYSQL *mysql, const uchar *buffer, size_t length))
{
LIST *list;
if (!callback_function)
return 1;
/* plugin will unregister in it's deinit function */
if (register_callback)
{
list= (LIST *)malloc(sizeof(LIST));
list->data= (void *)callback_function;
cio_callback= list_add(cio_callback, list);
}
else /* unregister callback function */
{
LIST *p= cio_callback;
while (p)
{
if (p->data == callback_function)
{
list_delete(cio_callback, p);
break;
}
p= p->next;
}
}
return 0;
}
/* }}} */

470
libmariadb/ma_pvio.c Normal file
View File

@@ -0,0 +1,470 @@
/************************************************************************************
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 <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
/* MariaDB Communication IO (PVIO) interface
PVIO is the interface for client server communication and replaces former vio
component of the client library.
PVIO support various protcols like sockets, pipes and shared memory, which are
implemented as plugins and can be extended therfore easily.
Interface function description:
ma_pvio_init allocates a new PVIO object which will be used
for the current connection
ma_pvio_close frees all resources of previously allocated PVIO object
and closes open connections
ma_pvio_read reads data from server
ma_pvio_write sends data to server
ma_pvio_set_timeout sets timeout for connection, read and write
ma_pvio_register_callback
register callback functions for read and write
*/
#include <my_global.h>
#include <my_sys.h>
#include <mysql.h>
#include <errmsg.h>
#include <mysql/client_plugin.h>
#include <string.h>
#include <ma_common.h>
#include <ma_pvio.h>
#include <mysql_async.h>
#include <my_context.h>
extern pthread_mutex_t THR_LOCK_lock;
/* callback functions for read/write */
LIST *pvio_callback= NULL;
/* {{{ MARIADB_PVIO *ma_pvio_init */
MARIADB_PVIO *ma_pvio_init(MA_PVIO_CINFO *cinfo)
{
/* check connection type and load the required plugin.
* Currently we support the following pvio types:
* pvio_socket
* pvio_namedpipe
*/
char *pvio_plugins[] = {"pvio_socket", "pvio_npipe"};
int type;
MARIADB_PVIO_PLUGIN *pvio_plugin;
MARIADB_PVIO *pvio= NULL;
switch (cinfo->type)
{
case PVIO_TYPE_UNIXSOCKET:
case PVIO_TYPE_SOCKET:
type= 0;
break;
#ifdef _WIN32
case PVIO_TYPE_NAMEDPIPE:
type= 1;
break;
#endif
default:
return NULL;
}
if (!(pvio_plugin= (MARIADB_PVIO_PLUGIN *)
mysql_client_find_plugin(cinfo->mysql,
pvio_plugins[type],
MARIADB_CLIENT_PVIO_PLUGIN)))
{
/* error handling */
return NULL;
}
if (!(pvio= (MARIADB_PVIO *)my_malloc(sizeof(MARIADB_PVIO),
MYF(MY_WME | MY_ZEROFILL))))
{
PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
return NULL;
}
/* register error routine and methods */
pvio->methods= pvio_plugin->methods;
pvio->set_error= my_set_error;
/* set tineouts */
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= my_malloc(PVIO_READ_AHEAD_CACHE_SIZE, MYF(MY_ZEROFILL))))
{
PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
return NULL;
}
pvio->cache_size= 0;
pvio->cache_pos= pvio->cache;
return pvio;
}
/* }}} */
/* {{{ my_bool ma_pvio_is_alive */
my_bool ma_pvio_is_alive(MARIADB_PVIO *pvio)
{
if (pvio->methods->is_alive)
return pvio->methods->is_alive(pvio);
return FALSE;
}
/* }}} */
/* {{{ int ma_pvio_fast_send */
int ma_pvio_fast_send(MARIADB_PVIO *pvio)
{
if (!pvio || !pvio->methods->fast_send)
return 1;
return pvio->methods->fast_send(pvio);
}
/* }}} */
/* {{{ int ma_pvio_keepalive */
int ma_pvio_keepalive(MARIADB_PVIO *pvio)
{
if (!pvio || !pvio->methods->keepalive)
return 1;
return pvio->methods->keepalive(pvio);
}
/* }}} */
/* {{{ my_bool ma_pvio_set_timeout */
my_bool ma_pvio_set_timeout(MARIADB_PVIO *pvio,
enum enum_pvio_timeout type,
int timeout)
{
if (!pvio)
return 1;
if (pvio->methods->set_timeout)
return pvio->methods->set_timeout(pvio, type, timeout);
return 1;
}
/* }}} */
/* {{{ size_t ma_pvio_read_async */
static size_t ma_pvio_read_async(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
{
ssize_t res;
struct mysql_async_context *b= pvio->async_context;
int timeout= pvio->timeout[PVIO_READ_TIMEOUT];
for (;;)
{
/* todo: async */
if (pvio->methods->async_read)
res= pvio->methods->async_read(pvio, buffer, length);
if (res >= 0 /* || IS_BLOCKING_ERROR()*/)
return res;
b->events_to_wait_for= MYSQL_WAIT_READ;
if (timeout >= 0)
{
b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
b->timeout_value= timeout;
}
if (b->suspend_resume_hook)
(*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
my_context_yield(&b->async_context);
if (b->suspend_resume_hook)
(*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
if (b->events_occured & MYSQL_WAIT_TIMEOUT)
return -1;
}
}
/* }}} */
/* {{{ size_t ma_pvio_read */
size_t ma_pvio_read(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
{
size_t r= -1;
if (!pvio)
return -1;
if (pvio && pvio->async_context && pvio->async_context->active)
{
goto end;
r= ma_pvio_read_async(pvio, buffer, length);
}
else
{
if (pvio->async_context)
{
/*
If switching from non-blocking to blocking API usage, set the socket
back to blocking mode.
*/
my_bool old_mode;
ma_pvio_blocking(pvio, TRUE, &old_mode);
}
}
/* secure connection */
#ifdef HAVE_SSL
if (pvio->cssl)
r= ma_pvio_ssl_read(pvio->cssl, buffer, length);
else
#endif
if (pvio->methods->read)
r= pvio->methods->read(pvio, buffer, length);
end:
if (pvio_callback)
{
void (*callback)(int mode, MYSQL *mysql, const uchar *buffer, size_t length);
LIST *p= pvio_callback;
while (p)
{
callback= p->data;
callback(0, pvio->mysql, buffer, r);
p= p->next;
}
}
return r;
}
/* }}} */
/* {{{ size_t ma_pvio_cache_read */
size_t ma_pvio_cache_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
{
size_t r;
if (!pvio)
return -1;
if (!pvio->cache)
return ma_pvio_read(pvio, buffer, length);
if (pvio->cache + pvio->cache_size > pvio->cache_pos)
{
r= MIN(length, (size_t)(pvio->cache + pvio->cache_size - pvio->cache_pos));
memcpy(buffer, pvio->cache_pos, r);
pvio->cache_pos+= r;
}
else if (length >= PVIO_READ_AHEAD_CACHE_MIN_SIZE)
{
r= ma_pvio_read(pvio, buffer, length);
}
else
{
r= ma_pvio_read(pvio, pvio->cache, PVIO_READ_AHEAD_CACHE_SIZE);
if ((ssize_t)r > 0)
{
if (length < r)
{
pvio->cache_size= r;
pvio->cache_pos= pvio->cache + length;
r= length;
}
memcpy(buffer, pvio->cache, r);
}
}
return r;
}
/* }}} */
/* {{{ size_t ma_pvio_write */
size_t ma_pvio_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
{
size_t r;
if (!pvio)
return -1;
if (pvio_callback)
{
void (*callback)(int mode, MYSQL *mysql, const uchar *buffer, size_t length);
LIST *p= pvio_callback;
while (p)
{
callback= p->data;
callback(1, pvio->mysql, buffer, length);
p= p->next;
}
}
/* secure connection */
#ifdef HAVE_SSL
if (pvio->cssl)
r= ma_pvio_ssl_write(pvio->cssl, buffer, length);
else
#endif
if (pvio->methods->write)
r= pvio->methods->write(pvio, buffer, length);
if (pvio->callback)
pvio->callback(pvio, 0, buffer, r);
return r;
}
/* }}} */
/* {{{ void ma_pvio_close */
void ma_pvio_close(MARIADB_PVIO *pvio)
{
/* free internal structures and close connection */
#ifdef HAVE_SSL
if (pvio && pvio->cssl)
{
ma_pvio_ssl_close(pvio->cssl);
my_free((gptr)pvio->cssl);
}
#endif
if (pvio && pvio->methods->close)
pvio->methods->close(pvio);
if (pvio->cache)
my_free((gptr)pvio->cache);
if (pvio->fp)
my_fclose(pvio->fp, MYF(0));
my_free((gptr)pvio);
}
/* }}} */
/* {{{ my_bool ma_pvio_get_handle */
my_bool ma_pvio_get_handle(MARIADB_PVIO *pvio, void *handle)
{
if (pvio && pvio->methods->get_handle)
return pvio->methods->get_handle(pvio, handle);
return 1;
}
/* }}} */
/* {{{ ma_pvio_wait_io_or_timeout */
int ma_pvio_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout)
{
if (pvio && pvio->async_context && pvio->async_context->active)
return my_io_wait_async(pvio->async_context,
(is_read) ? VIO_IO_EVENT_READ : VIO_IO_EVENT_WRITE,
timeout);
if (pvio && pvio->methods->wait_io_or_timeout)
return pvio->methods->wait_io_or_timeout(pvio, is_read, timeout);
return 1;
}
/* }}} */
/* {{{ my_bool ma_pvio_connect */
my_bool ma_pvio_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
{
if (pvio && pvio->methods->connect)
return pvio->methods->connect(pvio, cinfo);
return 1;
}
/* }}} */
/* {{{ my_bool ma_pvio_blocking */
my_bool ma_pvio_blocking(MARIADB_PVIO *pvio, my_bool block, my_bool *previous_mode)
{
if (pvio && pvio->methods->blocking)
return pvio->methods->blocking(pvio, block, previous_mode);
return 1;
}
/* }}} */
/* {{{ my_bool ma_pvio_is_blocking */
my_bool ma_pvio_is_blocking(MARIADB_PVIO *pvio)
{
if (pvio && pvio->methods->is_blocking)
return pvio->methods->is_blocking(pvio);
return 1;
}
/* }}} */
#ifdef HAVE_SSL
/* {{{ my_bool ma_pvio_start_ssl */
my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio)
{
if (!pvio || !pvio->mysql)
return 1;
CLEAR_CLIENT_ERROR(pvio->mysql);
if (!(pvio->cssl= ma_pvio_ssl_init(pvio->mysql)))
{
return 1;
}
if (ma_pvio_ssl_connect(pvio->cssl))
{
my_free((gptr)pvio->cssl);
pvio->cssl= NULL;
return 1;
}
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))
return 1;
if (pvio->mysql->options.extension &&
(pvio->mysql->options.extension->ssl_fp || pvio->mysql->options.extension->ssl_fp_list))
{
if (ma_pvio_ssl_check_fp(pvio->cssl,
pvio->mysql->options.extension->ssl_fp,
pvio->mysql->options.extension->ssl_fp_list))
return 1;
}
return 0;
}
/* }}} */
#endif
/* {{{ ma_pvio_register_callback */
int ma_pvio_register_callback(my_bool register_callback,
void (*callback_function)(int mode, MYSQL *mysql, const uchar *buffer, size_t length))
{
LIST *list;
if (!callback_function)
return 1;
/* plugin will unregister in it's deinit function */
if (register_callback)
{
list= (LIST *)malloc(sizeof(LIST));
list->data= (void *)callback_function;
pvio_callback= list_add(pvio_callback, list);
}
else /* unregister callback function */
{
LIST *p= pvio_callback;
while (p)
{
if (p->data == callback_function)
{
list_delete(pvio_callback, p);
break;
}
p= p->next;
}
}
return 0;
}
/* }}} */

View File

@@ -38,7 +38,7 @@
#include <string.h>
//#include <ma_secure.h>
#include <errmsg.h>
#include <ma_cio.h>
#include <ma_pvio.h>
#include <ma_ssl.h>
#include <mysql/client_plugin.h>
@@ -47,25 +47,25 @@
#include <my_context.h>
*/
/* Errors should be handled via cio callback function */
/* Errors should be handled via pvio callback function */
my_bool ma_ssl_initialized= FALSE;
unsigned int mariadb_deinitialize_ssl= 1;
MARIADB_SSL *ma_cio_ssl_init(MYSQL *mysql)
MARIADB_SSL *ma_pvio_ssl_init(MYSQL *mysql)
{
MARIADB_SSL *cssl= NULL;
if (!ma_ssl_initialized)
ma_ssl_start(mysql->net.last_error, MYSQL_ERRMSG_SIZE);
if (!(cssl= (MARIADB_SSL *)my_malloc(sizeof(MARIADB_CIO),
if (!(cssl= (MARIADB_SSL *)my_malloc(sizeof(MARIADB_SSL),
MYF(MY_WME | MY_ZEROFILL))))
{
return NULL;
}
/* register error routine and methods */
cssl->cio= mysql->net.cio;
cssl->pvio= mysql->net.pvio;
if (!(cssl->ssl= ma_ssl_init(mysql)))
{
my_free(cssl);
@@ -74,37 +74,37 @@ MARIADB_SSL *ma_cio_ssl_init(MYSQL *mysql)
return cssl;
}
my_bool ma_cio_ssl_connect(MARIADB_SSL *cssl)
my_bool ma_pvio_ssl_connect(MARIADB_SSL *cssl)
{
return ma_ssl_connect(cssl);
}
size_t ma_cio_ssl_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
size_t ma_pvio_ssl_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
{
return ma_ssl_read(cssl, buffer, length);
}
size_t ma_cio_ssl_write(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
size_t ma_pvio_ssl_write(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
{
return ma_ssl_write(cssl, buffer, length);
}
my_bool ma_cio_ssl_close(MARIADB_SSL *cssl)
my_bool ma_pvio_ssl_close(MARIADB_SSL *cssl)
{
return ma_ssl_close(cssl);
}
int ma_cio_ssl_verify_server_cert(MARIADB_SSL *cssl)
int ma_pvio_ssl_verify_server_cert(MARIADB_SSL *cssl)
{
return ma_ssl_verify_server_cert(cssl);
}
const char *ma_cio_ssl_cipher(MARIADB_SSL *cssl)
const char *ma_pvio_ssl_cipher(MARIADB_SSL *cssl)
{
return ma_ssl_get_cipher(cssl);
}
static my_bool ma_cio_ssl_compare_fp(char *fp1, unsigned int fp1_len,
static my_bool ma_pvio_ssl_compare_fp(char *fp1, unsigned int fp1_len,
char *fp2, unsigned int fp2_len)
{
char hexstr[64];
@@ -119,7 +119,7 @@ static my_bool ma_cio_ssl_compare_fp(char *fp1, unsigned int fp1_len,
return 0;
}
my_bool ma_cio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_list)
my_bool ma_pvio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_list)
{
unsigned int cert_fp_len= 64;
unsigned char cert_fp[64];
@@ -129,7 +129,7 @@ my_bool ma_cio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_li
if ((cert_fp_len= ma_ssl_get_finger_print(cssl, cert_fp, cert_fp_len)) < 1)
goto end;
if (fp)
rc= ma_cio_ssl_compare_fp(cert_fp, cert_fp_len, fp, strlen(fp));
rc= ma_pvio_ssl_compare_fp(cert_fp, cert_fp_len, fp, strlen(fp));
else if (fp_list)
{
FILE *fp;
@@ -154,7 +154,7 @@ my_bool ma_cio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_li
if (pos)
*pos= '\0';
if (!ma_cio_ssl_compare_fp(cert_fp, cert_fp_len, buff, strlen(buff)))
if (!ma_pvio_ssl_compare_fp(cert_fp, cert_fp_len, buff, strlen(buff)))
{
/* finger print is valid: close file and exit */
fclose(fp);

View File

@@ -53,7 +53,7 @@
#include "mysql_version.h"
#include "mysqld_error.h"
#include "errmsg.h"
#include <ma_cio.h>
#include <ma_pvio.h>
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
@@ -988,7 +988,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
{
DBUG_ENTER("mysql_stmt_close");
if (stmt && stmt->mysql && stmt->mysql->net.cio)
if (stmt && stmt->mysql && stmt->mysql->net.pvio)
mysql_stmt_reset(stmt);
net_stmt_close(stmt, 1);

View File

@@ -30,7 +30,7 @@
#include "ma_common.h"
#endif
#include "my_context.h"
#include "ma_cio.h"
#include "ma_pvio.h"
#include "mysql_async.h"
#include <string.h>
@@ -42,7 +42,7 @@
*/
#define WIN_SET_NONBLOCKING(mysql) { \
my_bool old_mode; \
if ((mysql)->net.cio) ma_cio_blocking((mysql)->net.cio, FALSE, &old_mode); \
if ((mysql)->net.pvio) ma_pvio_blocking((mysql)->net.pvio, FALSE, &old_mode); \
}
#else
#define WIN_SET_NONBLOCKING(mysql)
@@ -63,18 +63,18 @@ my_context_install_suspend_resume_hook(struct mysql_async_context *b,
/* Asynchronous connect(); socket must already be set non-blocking. */
int
my_connect_async(MARIADB_CIO *cio,
my_connect_async(MARIADB_PVIO *pvio,
const struct sockaddr *name, uint namelen, int vio_timeout)
{
int res;
size_socket s_err_size;
struct mysql_async_context *b= cio->mysql->options.extension->async_context;
struct mysql_async_context *b= pvio->mysql->options.extension->async_context;
my_socket sock;
ma_cio_get_handle(cio, &sock);
ma_pvio_get_handle(pvio, &sock);
/* Make the socket non-blocking. */
ma_cio_blocking(cio, 0, 0);
ma_pvio_blocking(pvio, 0, 0);
b->events_to_wait_for= 0;
/*
@@ -135,15 +135,15 @@ my_connect_async(MARIADB_CIO *cio,
#endif
ssize_t
my_recv_async(MARIADB_CIO *cio, const unsigned char *buf, size_t size, int timeout)
my_recv_async(MARIADB_PVIO *pvio, const unsigned char *buf, size_t size, int timeout)
{
ssize_t res;
struct mysql_async_context *b= cio->async_context;
struct mysql_async_context *b= pvio->async_context;
for (;;)
{
/* todo: async */
if (cio->methods->async_read)
res= cio->methods->async_read(cio, buf, size);
if (pvio->methods->async_read)
res= pvio->methods->async_read(pvio, buf, size);
if (res >= 0 || IS_BLOCKING_ERROR())
return res;
b->events_to_wait_for= MYSQL_WAIT_READ;
@@ -164,15 +164,15 @@ my_recv_async(MARIADB_CIO *cio, const unsigned char *buf, size_t size, int timeo
ssize_t
my_send_async(MARIADB_CIO *cio, const unsigned char *buf, size_t size, int timeout)
my_send_async(MARIADB_PVIO *pvio, const unsigned char *buf, size_t size, int timeout)
{
ssize_t res;
struct mysql_async_context *b= cio->async_context;
struct mysql_async_context *b= pvio->async_context;
for (;;)
{
if (cio->methods->async_write)
res= cio->methods->async_write(cio, buf, size);
if (pvio->methods->async_write)
res= pvio->methods->async_write(pvio, buf, size);
if (res >= 0 || IS_BLOCKING_ERROR())
return res;
b->events_to_wait_for= MYSQL_WAIT_WRITE;
@@ -193,7 +193,7 @@ my_send_async(MARIADB_CIO *cio, const unsigned char *buf, size_t size, int timeo
my_bool
my_io_wait_async(struct mysql_async_context *b, enum enum_cio_io_event event,
my_io_wait_async(struct mysql_async_context *b, enum enum_pvio_io_event event,
int timeout)
{
switch (event)
@@ -825,7 +825,7 @@ mysql_close_start(MYSQL *sock)
int res;
/* It is legitimate to have NULL sock argument, which will do nothing. */
if (sock && sock->net.cio)
if (sock && sock->net.pvio)
{
res= mysql_close_slow_part_start(sock);
/* If we need to block, return now and do the rest in mysql_close_cont(). */

View File

@@ -25,7 +25,7 @@
#include <my_global.h>
#include <mysql.h>
#include <ma_cio.h>
#include <ma_pvio.h>
#include <my_sys.h>
#include <m_string.h>
#include "mysql.h"
@@ -33,7 +33,7 @@
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <ma_cio.h>
#include <ma_pvio.h>
#ifndef _WIN32
#include <poll.h>
#endif
@@ -113,13 +113,13 @@ static int net_write_buff(NET *net,const char *packet, size_t len);
/* Init with packet info */
int my_net_init(NET *net, MARIADB_CIO* cio)
int my_net_init(NET *net, MARIADB_PVIO* pvio)
{
if (!(net->buff=(uchar*) my_malloc(net_buffer_length,MYF(MY_WME | MY_ZEROFILL))))
return 1;
max_allowed_packet= net->max_packet_size= MAX(net_buffer_length, max_allowed_packet);
net->buff_end=net->buff+(net->max_packet=net_buffer_length);
net->cio = cio;
net->pvio = pvio;
net->error=0; net->return_status=0;
net->read_timeout=(uint) net_read_timeout; /* Timeout for read */
net->compress_pkt_nr= net->pkt_nr= 0;
@@ -130,11 +130,11 @@ int my_net_init(NET *net, MARIADB_CIO* cio)
net->where_b = net->remain_in_buf=0;
net->last_errno=0;
if (cio != 0) /* If real connection */
if (pvio != 0) /* If real connection */
{
ma_cio_get_handle(cio, &net->fd);
ma_cio_blocking(cio, 1, 0);
ma_cio_fast_send(cio);
ma_pvio_get_handle(pvio, &net->fd);
ma_pvio_blocking(pvio, 1, 0);
ma_pvio_fast_send(pvio);
}
return 0;
}
@@ -226,14 +226,14 @@ void net_clear(NET *net)
my_socket sock;
DBUG_ENTER("net_clear");
ma_cio_get_handle(net->cio, &sock);
ma_pvio_get_handle(net->pvio, &sock);
/* see conc-71: we need to check the socket status first:
if the socket is dead we set net->error, so net_flush
will report an error */
while (net_check_socket_status(sock))
{
if ((ssize_t)ma_cio_cache_read(net->cio, (gptr)net->buff, (size_t) net->max_packet) <= 0)
if ((ssize_t)ma_pvio_cache_read(net->pvio, (gptr)net->buff, (size_t) net->max_packet) <= 0)
{
net->error= 2;
DBUG_PRINT("info", ("socket disconnected"));
@@ -429,7 +429,7 @@ net_real_write(NET *net,const char *packet,size_t len)
pos=(char*) packet; end=pos+len;
while (pos != end)
{
if ((ssize_t) (length=ma_cio_write(net->cio,pos,(size_t) (end-pos))) <= 0)
if ((ssize_t) (length=ma_pvio_write(net->pvio,pos,(size_t) (end-pos))) <= 0)
{
net->error=2; /* Close socket */
net->last_errno= ER_NET_ERROR_ON_WRITE;
@@ -470,7 +470,7 @@ my_real_read(NET *net, size_t *complen)
while (remain > 0)
{
/* First read is done with non blocking mode */
if ((ssize_t) (length=ma_cio_cache_read(net->cio,(char*) pos,remain)) <= 0L)
if ((ssize_t) (length=ma_pvio_cache_read(net->pvio,(char*) pos,remain)) <= 0L)
{
len= packet_error;
net->error=2; /* Close socket */

View File

@@ -24,7 +24,7 @@
#include <my_global.h>
#include <my_sys.h>
#include <ma_common.h>
#include <ma_cio.h>
#include <ma_pvio.h>
#include <errmsg.h>
#include <my_pthread.h>
#include <mysql/client_plugin.h>
@@ -44,21 +44,21 @@ static void ma_ssl_set_error(MYSQL *mysql, int ssl_errno)
{
char ssl_error[MAX_SSL_ERR_LEN];
const char *ssl_error_reason;
MARIADB_CIO *cio= mysql->net.cio;
MARIADB_PVIO *pvio= mysql->net.pvio;
if (!ssl_errno)
{
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error");
return;
}
if ((ssl_error_reason= gnutls_strerror(ssl_errno)))
{
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0,
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0,
ssl_error_reason);
return;
}
my_snprintf(ssl_error, MAX_SSL_ERR_LEN, "SSL errno=%lu", ssl_errno, mysql->charset);
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ssl_error);
}
@@ -219,25 +219,42 @@ error:
return NULL;
}
ssize_t ma_ssl_push(gnutls_transport_ptr_t ptr, const void* data, size_t len)
{
MARIADB_PVIO *pvio= (MARIADB_PVIO *)ptr;
ssize_t rc= pvio->methods->write(pvio, data, len);
return rc;
}
ssize_t ma_ssl_pull(gnutls_transport_ptr_t ptr, void* data, size_t len)
{
MARIADB_PVIO *pvio= (MARIADB_PVIO *)ptr;
ssize_t rc= pvio->methods->read(pvio, data, len);
return rc;
}
my_bool ma_ssl_connect(MARIADB_SSL *cssl)
{
gnutls_session_t ssl = (gnutls_session_t)cssl->ssl;
my_bool blocking;
MYSQL *mysql;
MARIADB_CIO *cio;
MARIADB_PVIO *pvio;
int ret;
mysql= (MYSQL *)gnutls_session_get_ptr(ssl);
if (!mysql)
return 1;
cio= mysql->net.cio;
pvio= mysql->net.pvio;
/* Set socket to blocking if not already set */
if (!(blocking= cio->methods->is_blocking(cio)))
cio->methods->blocking(cio, TRUE, 0);
if (!(blocking= pvio->methods->is_blocking(pvio)))
pvio->methods->blocking(pvio, TRUE, 0);
gnutls_transport_set_int(ssl, mysql_get_socket(mysql));
/* we don't use GnuTLS read/write functions */
gnutls_transport_set_ptr(ssl, pvio);
gnutls_transport_set_push_function(ssl, ma_ssl_push);
gnutls_transport_set_pull_function(ssl, ma_ssl_pull);
gnutls_handshake_set_timeout(ssl, mysql->options.connect_timeout);
do {
@@ -249,7 +266,7 @@ my_bool ma_ssl_connect(MARIADB_SSL *cssl)
ma_ssl_set_error(mysql, ret);
/* restore blocking mode */
if (!blocking)
cio->methods->blocking(cio, FALSE, 0);
pvio->methods->blocking(pvio, FALSE, 0);
return 1;
}
cssl->ssl= (void *)ssl;
@@ -296,7 +313,7 @@ static int my_verify_callback(gnutls_session_t ssl)
unsigned int cert_list_size;
int ret;
MYSQL *mysql= (MYSQL *)gnutls_session_get_ptr(ssl);
MARIADB_CIO *cio= mysql->net.cio;
MARIADB_PVIO *pvio= mysql->net.pvio;
gnutls_x509_crt_t cert;
const char *hostname;
@@ -313,7 +330,7 @@ static int my_verify_callback(gnutls_session_t ssl)
ret = gnutls_certificate_verify_peers2 (ssl, &status);
if (ret < 0)
{
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "CA verification failed");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "CA verification failed");
return GNUTLS_E_CERTIFICATE_ERROR;
}
@@ -329,33 +346,33 @@ static int my_verify_callback(gnutls_session_t ssl)
*/
if (gnutls_certificate_type_get (ssl) != GNUTLS_CRT_X509)
{
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Expected X509 certificate");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Expected X509 certificate");
return GNUTLS_E_CERTIFICATE_ERROR;
}
if (gnutls_x509_crt_init (&cert) < 0)
{
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Error during certificate initialization");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Error during certificate initialization");
return GNUTLS_E_CERTIFICATE_ERROR;
}
cert_list = gnutls_certificate_get_peers (ssl, &cert_list_size);
if (cert_list == NULL)
{
gnutls_x509_crt_deinit (cert);
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "No certificate found");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "No certificate found");
return GNUTLS_E_CERTIFICATE_ERROR;
}
if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
{
gnutls_x509_crt_deinit (cert);
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error");
return GNUTLS_E_CERTIFICATE_ERROR;
}
if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
gnutls_x509_crt_check_hostname (cert, hostname) < 0)
!gnutls_x509_crt_check_hostname (cert, hostname))
{
gnutls_x509_crt_deinit (cert);
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Hostname in certificate doesn't match");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Hostname in certificate doesn't match");
return GNUTLS_E_CERTIFICATE_ERROR;
}
gnutls_x509_crt_deinit (cert);

View File

@@ -28,46 +28,46 @@
#define SCHANNEL_PAYLOAD(A) (A).cbMaximumMessage - (A).cbHeader - (A).cbTrailer
/* {{{ void ma_schannel_set_sec_error */
void ma_schannel_set_sec_error(MARIADB_CIO *cio, DWORD ErrorNo)
void ma_schannel_set_sec_error(MARIADB_PVIO *pvio, DWORD ErrorNo)
{
MYSQL *mysql= cio->mysql;
MYSQL *mysql= pvio->mysql;
switch(ErrorNo) {
case SEC_E_UNTRUSTED_ROOT:
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Untrusted root certificate");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Untrusted root certificate");
break;
case SEC_E_BUFFER_TOO_SMALL:
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Buffer too small");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Buffer too small");
break;
case SEC_E_CRYPTO_SYSTEM_INVALID:
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Cipher is not supported");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Cipher is not supported");
break;
case SEC_E_INSUFFICIENT_MEMORY:
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Out of memory");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Out of memory");
break;
case SEC_E_OUT_OF_SEQUENCE:
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Invalid message sequence");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Invalid message sequence");
break;
case SEC_E_DECRYPT_FAILURE:
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "An error occured during decrypting data");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "An error occured during decrypting data");
break;
case SEC_I_INCOMPLETE_CREDENTIALS:
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Incomplete credentials");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Incomplete credentials");
break;
case SEC_E_ENCRYPT_FAILURE:
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "An error occured during encrypting data");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "An error occured during encrypting data");
break;
case SEC_I_CONTEXT_EXPIRED:
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Context expired: ");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Context expired: ");
case SEC_E_OK:
break;
default:
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error (%d)", ErrorNo);
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error (%d)", ErrorNo);
}
}
/* }}} */
/* {{{ void ma_schnnel_set_win_error */
void ma_schannel_set_win_error(MARIADB_CIO *cio)
void ma_schannel_set_win_error(MARIADB_PVIO *pvio)
{
ulong ssl_errno= GetLastError();
char ssl_error[MAX_SSL_ERR_LEN];
@@ -75,14 +75,14 @@ void ma_schannel_set_win_error(MARIADB_CIO *cio)
if (!ssl_errno)
{
cio->set_error(cio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error");
pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error");
return;
}
/* todo: obtain error messge */
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, ssl_errno, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &ssl_error_reason, 0, NULL );
cio->set_error(cio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ssl_error_reason);
pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ssl_error_reason);
if (ssl_error_reason)
LocalFree(ssl_error_reason);
@@ -111,7 +111,7 @@ void ma_schannel_set_win_error(MARIADB_CIO *cio)
LPBYTE * a pointer to a binary der object
buffer_len will contain the length of binary der object
*/
static LPBYTE ma_schannel_load_pem(MARIADB_CIO *cio, const char *PemFileName, DWORD *buffer_len)
static LPBYTE ma_schannel_load_pem(MARIADB_PVIO *pvio, const char *PemFileName, DWORD *buffer_len)
{
HANDLE hfile;
char *buffer= NULL;
@@ -127,25 +127,25 @@ static LPBYTE ma_schannel_load_pem(MARIADB_CIO *cio, const char *PemFileName, DW
if ((hfile= CreateFile(PemFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE)
{
ma_schannel_set_win_error(cio);
ma_schannel_set_win_error(pvio);
return NULL;
}
if (!(*buffer_len = GetFileSize(hfile, NULL)))
{
cio->set_error(cio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Invalid pem format");
pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Invalid pem format");
goto end;
}
if (!(buffer= LocalAlloc(0, *buffer_len + 1)))
{
cio->set_error(cio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
pvio->set_error(pvio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
goto end;
}
if (!ReadFile(hfile, buffer, *buffer_len, &dwBytesRead, NULL))
{
ma_schannel_set_win_error(cio);
ma_schannel_set_win_error(pvio);
goto end;
}
@@ -155,20 +155,20 @@ static LPBYTE ma_schannel_load_pem(MARIADB_CIO *cio, const char *PemFileName, DW
if (!CryptStringToBinaryA(buffer, *buffer_len, CRYPT_STRING_BASE64HEADER,
NULL, &der_buffer_length, NULL, NULL))
{
ma_schannel_set_win_error(cio);
ma_schannel_set_win_error(pvio);
goto end;
}
/* allocate DER binary buffer */
if (!(der_buffer= (LPBYTE)LocalAlloc(0, der_buffer_length)))
{
cio->set_error(cio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
pvio->set_error(pvio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
goto end;
}
/* convert to DER binary */
if (!CryptStringToBinaryA(buffer, *buffer_len, CRYPT_STRING_BASE64HEADER,
der_buffer, &der_buffer_length, NULL, NULL))
{
ma_schannel_set_win_error(cio);
ma_schannel_set_win_error(pvio);
goto end;
}
@@ -189,13 +189,13 @@ end:
}
/* }}} */
/* {{{ CERT_CONTEXT *ma_schannel_create_cert_context(MARIADB_CIO *cio, const char *pem_file) */
/* {{{ CERT_CONTEXT *ma_schannel_create_cert_context(MARIADB_PVIO *pvio, const char *pem_file) */
/*
Create a certification context from ca or cert file
SYNOPSIS
ma_schannel_create_cert_context()
cio cio object
pvio pvio object
pem_file name of certificate or ca file
DESCRIPTION
@@ -208,7 +208,7 @@ end:
NULL If loading of the file or creating context failed
CERT_CONTEXT * A pointer to a certification context structure
*/
CERT_CONTEXT *ma_schannel_create_cert_context(MARIADB_CIO *cio, const char *pem_file)
CERT_CONTEXT *ma_schannel_create_cert_context(MARIADB_PVIO *pvio, const char *pem_file)
{
DWORD der_buffer_length;
LPBYTE der_buffer= NULL;
@@ -216,11 +216,11 @@ CERT_CONTEXT *ma_schannel_create_cert_context(MARIADB_CIO *cio, const char *pem_
CERT_CONTEXT *ctx= NULL;
/* create DER binary object from ca/certification file */
if (!(der_buffer= ma_schannel_load_pem(cio, pem_file, (DWORD *)&der_buffer_length)))
if (!(der_buffer= ma_schannel_load_pem(pvio, pem_file, (DWORD *)&der_buffer_length)))
goto end;
if (!(ctx= CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
der_buffer, der_buffer_length)))
ma_schannel_set_win_error(cio);
ma_schannel_set_win_error(pvio);
end:
if (der_buffer)
@@ -229,7 +229,7 @@ end:
}
/* }}} */
/* {{{ PCCRL_CONTEXT ma_schannel_create_crl_context(MARIADB_CIO *cio, const char *pem_file) */
/* {{{ PCCRL_CONTEXT ma_schannel_create_crl_context(MARIADB_PVIO *pvio, const char *pem_file) */
/*
Create a crl context from crlfile
@@ -247,7 +247,7 @@ end:
NULL If loading of the file or creating context failed
PCCRL_CONTEXT A pointer to a certification context structure
*/
PCCRL_CONTEXT ma_schannel_create_crl_context(MARIADB_CIO *cio, const char *pem_file)
PCCRL_CONTEXT ma_schannel_create_crl_context(MARIADB_PVIO *pvio, const char *pem_file)
{
DWORD der_buffer_length;
LPBYTE der_buffer= NULL;
@@ -255,11 +255,11 @@ PCCRL_CONTEXT ma_schannel_create_crl_context(MARIADB_CIO *cio, const char *pem_f
PCCRL_CONTEXT ctx= NULL;
/* load ca pem file into memory */
if (!(der_buffer= ma_schannel_load_pem(cio, pem_file, (DWORD *)&der_buffer_length)))
if (!(der_buffer= ma_schannel_load_pem(pvio, pem_file, (DWORD *)&der_buffer_length)))
goto end;
if (!(ctx= CertCreateCRLContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
der_buffer, der_buffer_length)))
ma_schannel_set_win_error(cio);
ma_schannel_set_win_error(pvio);
end:
if (der_buffer)
LocalFree(der_buffer);
@@ -267,7 +267,7 @@ end:
}
/* }}} */
/* {{{ my_bool ma_schannel_load_private_key(MARIADB_CIO *cio, CERT_CONTEXT *ctx, char *key_file) */
/* {{{ my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, CERT_CONTEXT *ctx, char *key_file) */
/*
Load privte key into context
@@ -287,7 +287,7 @@ end:
PCCRL_CONTEXT A pointer to a certification context structure
*/
my_bool ma_schannel_load_private_key(MARIADB_CIO *cio, CERT_CONTEXT *ctx, char *key_file)
my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, CERT_CONTEXT *ctx, char *key_file)
{
DWORD der_buffer_len= 0;
LPBYTE der_buffer= NULL;
@@ -299,7 +299,7 @@ my_bool ma_schannel_load_private_key(MARIADB_CIO *cio, CERT_CONTEXT *ctx, char *
my_bool rc= 0;
/* load private key into der binary object */
if (!(der_buffer= ma_schannel_load_pem(cio, key_file, &der_buffer_len)))
if (!(der_buffer= ma_schannel_load_pem(pvio, key_file, &der_buffer_len)))
return 0;
/* determine required buffer size for decoded private key */
@@ -309,14 +309,14 @@ my_bool ma_schannel_load_private_key(MARIADB_CIO *cio, CERT_CONTEXT *ctx, char *
0, NULL,
NULL, &priv_key_len))
{
ma_schannel_set_win_error(cio);
ma_schannel_set_win_error(pvio);
goto end;
}
/* allocate buffer for decoded private key */
if (!(priv_key= LocalAlloc(0, priv_key_len)))
{
cio->set_error(cio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
pvio->set_error(pvio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
goto end;
}
@@ -327,22 +327,22 @@ my_bool ma_schannel_load_private_key(MARIADB_CIO *cio, CERT_CONTEXT *ctx, char *
0, NULL,
priv_key, &priv_key_len))
{
ma_schannel_set_win_error(cio);
ma_schannel_set_win_error(pvio);
goto end;
}
/* Acquire context:
If cio_schannel context doesn't exist, create a new one */
if (!CryptAcquireContext(&crypt_prov, "cio_schannel", MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
if (!CryptAcquireContext(&crypt_prov, "cio_schannel", MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET))
If pvio_schannel context doesn't exist, create a new one */
if (!CryptAcquireContext(&crypt_prov, "pvio_schannel", MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
if (!CryptAcquireContext(&crypt_prov, "pvio_schannel", MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
ma_schannel_set_win_error(cio);
ma_schannel_set_win_error(pvio);
goto end;
}
/* ... and import the private key */
if (!CryptImportKey(crypt_prov, priv_key, priv_key_len, NULL, 0, &crypt_key))
{
ma_schannel_set_win_error(cio);
ma_schannel_set_win_error(pvio);
goto end;
}
@@ -355,7 +355,7 @@ my_bool ma_schannel_load_private_key(MARIADB_CIO *cio, CERT_CONTEXT *ctx, char *
if (CertSetCertificateContextProperty(ctx, CERT_KEY_CONTEXT_PROP_ID, 0, &kpi))
rc= 1;
else
ma_schannel_set_win_error(cio);
ma_schannel_set_win_error(pvio);
end:
if (der_buffer)
@@ -373,20 +373,20 @@ end:
}
/* }}} */
/* {{{ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_CIO *cio, my_bool InitialRead, SecBuffer *pExtraData) */
/* {{{ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRead, SecBuffer *pExtraData) */
/*
perform handshake loop
SYNOPSIS
ma_schannel_handshake_loop()
cio Pointer to an Communication/IO structure
pvio Pointer to an Communication/IO structure
InitialRead TRUE if it's the very first read
ExtraData Pointer to an SecBuffer which contains extra data (sent by application)
*/
SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_CIO *cio, my_bool InitialRead, SecBuffer *pExtraData)
SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRead, SecBuffer *pExtraData)
{
SecBufferDesc OutBuffer, InBuffer;
SecBuffer InBuffers[2], OutBuffers[1];
@@ -395,7 +395,7 @@ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_CIO *cio, my_bool InitialRead
SECURITY_STATUS rc;
PUCHAR IoBuffer;
BOOL fDoRead;
MARIADB_SSL *cssl= cio->cssl;
MARIADB_SSL *cssl= pvio->cssl;
SC_CTX *sctx= (SC_CTX *)cssl->ssl;
@@ -429,7 +429,7 @@ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_CIO *cio, my_bool InitialRead
{
if(fDoRead)
{
cbData = cio->methods->read(cio, IoBuffer + cbIoBuffer, SC_IO_BUFFER_SIZE - cbIoBuffer, 0);
cbData = pvio->methods->read(pvio, IoBuffer + cbIoBuffer, SC_IO_BUFFER_SIZE - cbIoBuffer, 0);
if (cbData == SOCKET_ERROR || cbData == 0)
{
rc = SEC_E_INTERNAL_ERROR;
@@ -488,7 +488,7 @@ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_CIO *cio, my_bool InitialRead
{
if(OutBuffers[0].cbBuffer && OutBuffers[0].pvBuffer)
{
cbData= cio->methods->write(cio, (uchar *)OutBuffers[0].pvBuffer, OutBuffers[0].cbBuffer);
cbData= pvio->methods->write(pvio, (uchar *)OutBuffers[0].pvBuffer, OutBuffers[0].cbBuffer);
if(cbData == SOCKET_ERROR || cbData == 0)
{
FreeContextBuffer(OutBuffers[0].pvBuffer);
@@ -538,7 +538,7 @@ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_CIO *cio, my_bool InitialRead
default:
if (FAILED(rc))
{
ma_schannel_set_sec_error(cio, rc);
ma_schannel_set_sec_error(pvio, rc);
goto loopend;
}
break;
@@ -579,7 +579,7 @@ loopend:
SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl)
{
MARIADB_CIO *cio;
MARIADB_PVIO *pvio;
SECURITY_STATUS sRet;
DWORD OutFlags;
DWORD r;
@@ -593,10 +593,10 @@ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl)
SecBufferDesc BufferIn, BufferOut;
SecBuffer BuffersOut[1], BuffersIn[2];
if (!cssl || !cssl->cio)
if (!cssl || !cssl->pvio)
return 1;
cio= cssl->cio;
pvio= cssl->pvio;
sctx= (SC_CTX *)cssl->ssl;
/* Initialie securifty context */
@@ -611,7 +611,7 @@ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl)
sRet = InitializeSecurityContext(&sctx->CredHdl,
NULL,
cio->mysql->host,
pvio->mysql->host,
SFlags,
0,
SECURITY_NATIVE_DREP,
@@ -624,7 +624,7 @@ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl)
if(sRet != SEC_I_CONTINUE_NEEDED)
{
ma_schannel_set_sec_error(cio, sRet);
ma_schannel_set_sec_error(pvio, sRet);
return sRet;
}
@@ -639,14 +639,14 @@ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl)
/* send client hello packaet */
if(BuffersOut[0].cbBuffer != 0 && BuffersOut[0].pvBuffer != NULL)
{
r= cio->methods->write(cio, (uchar *)BuffersOut[0].pvBuffer, BuffersOut[0].cbBuffer);
r= pvio->methods->write(pvio, (uchar *)BuffersOut[0].pvBuffer, BuffersOut[0].cbBuffer);
if (r <= 0)
{
sRet= SEC_E_INTERNAL_ERROR;
goto end;
}
}
sRet= ma_schannel_handshake_loop(cio, TRUE, &ExtraData);
sRet= ma_schannel_handshake_loop(pvio, TRUE, &ExtraData);
/* Reallocate IO-Buffer for write operations: After handshake
was successfull, we are able now to calculate payload */
@@ -664,14 +664,14 @@ end:
}
/* }}} */
/* {{{ SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_CIO *cio, PCredHandle phCreds, CtxtHandle * phContext,
/* {{{ SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_PVIO *pvio, PCredHandle phCreds, CtxtHandle * phContext,
DWORD DecryptLength, uchar *ReadBuffer, DWORD ReadBufferSize) */
/*
Reads encrypted data from a SSL stream and decrypts it.
SYNOPSIS
ma_schannel_read
cio pointer to Communication IO structure
pvio pointer to Communication IO structure
phContext a context handle
DecryptLength size of decrypted buffer
ReadBuffer Buffer for decrypted data
@@ -686,7 +686,7 @@ end:
SEC_E_* if an error occured
*/
SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_CIO *cio,
SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_PVIO *pvio,
PCredHandle phCreds,
CtxtHandle * phContext,
DWORD *DecryptLength,
@@ -703,17 +703,17 @@ SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_CIO *cio,
*pData, *pExtra;
int i;
if (!cio || !cio->methods || !cio->methods->read || !cio->cssl || !DecryptLength)
if (!pvio || !pvio->methods || !pvio->methods->read || !pvio->cssl || !DecryptLength)
return SEC_E_INTERNAL_ERROR;
sctx= (SC_CTX *)cio->cssl->ssl;
sctx= (SC_CTX *)pvio->cssl->ssl;
*DecryptLength= 0;
while (1)
{
if (!dwBytesRead || sRet == SEC_E_INCOMPLETE_MESSAGE)
{
dwBytesRead= cio->methods->read(cio, sctx->IoBuffer + dwOffset, sctx->IoBufferSize - dwOffset);
dwBytesRead= pvio->methods->read(pvio, sctx->IoBuffer + dwOffset, sctx->IoBufferSize - dwOffset);
if (dwBytesRead == 0)
{
/* server closed connection */
@@ -748,7 +748,7 @@ SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_CIO *cio,
if (sRet != SEC_E_OK && sRet != SEC_I_CONTEXT_EXPIRED &&
sRet != SEC_I_RENEGOTIATE && sRet != SEC_E_INCOMPLETE_MESSAGE)
{
ma_schannel_set_sec_error(cio, sRet);
ma_schannel_set_sec_error(pvio, sRet);
return sRet;
}
@@ -784,12 +784,12 @@ my_bool ma_schannel_verify_certs(SC_CTX *sctx, DWORD dwCertFlags)
{
SECURITY_STATUS sRet;
DWORD flags;
MARIADB_CIO *cio= sctx->mysql->net.cio;
MARIADB_PVIO *pvio= sctx->mysql->net.pvio;
PCCERT_CONTEXT pServerCert= NULL;
if ((sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pServerCert)) != SEC_E_OK)
{
ma_schannel_set_sec_error(cio, sRet);
ma_schannel_set_sec_error(pvio, sRet);
return 0;
}
@@ -804,20 +804,20 @@ my_bool ma_schannel_verify_certs(SC_CTX *sctx, DWORD dwCertFlags)
sctx->client_ca_ctx,
&flags)))
{
ma_schannel_set_win_error(cio);
ma_schannel_set_win_error(pvio);
return 0;
}
if (flags)
{
if ((flags & CERT_STORE_SIGNATURE_FLAG) != 0)
cio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Client certificate signature check failed");
pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Certificate signature check failed");
else if ((flags & CERT_STORE_REVOCATION_FLAG) != 0)
cio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Client certificate was revoked");
pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "certificate was revoked");
else if ((flags & CERT_STORE_TIME_VALIDITY_FLAG) != 0)
cio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Client certificate has expired");
pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "certificate has expired");
else
cio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown error during client certificate validation");
pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown error during certificate validation");
return 0;
}
}
@@ -832,7 +832,7 @@ my_bool ma_schannel_verify_certs(SC_CTX *sctx, DWORD dwCertFlags)
pServerCert->pCertInfo,
1, Info)) )
{
cio->set_error(cio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "CRL Revocation failed");
pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "CRL Revocation failed");
return 0;
}
}
@@ -840,12 +840,12 @@ my_bool ma_schannel_verify_certs(SC_CTX *sctx, DWORD dwCertFlags)
}
/* {{{ size_t ma_schannel_write_encrypt(MARIADB_CIO *cio, PCredHandle phCreds, CtxtHandle * phContext) */
/* {{{ size_t ma_schannel_write_encrypt(MARIADB_PVIO *pvio, PCredHandle phCreds, CtxtHandle * phContext) */
/*
Decrypts data and write to SSL stream
SYNOPSIS
ma_schannel_write_decrypt
cio pointer to Communication IO structure
pvio pointer to Communication IO structure
phContext a context handle
DecryptLength size of decrypted buffer
ReadBuffer Buffer for decrypted data
@@ -858,7 +858,7 @@ my_bool ma_schannel_verify_certs(SC_CTX *sctx, DWORD dwCertFlags)
SEC_E_OK on success
SEC_E_* if an error occured
*/
size_t ma_schannel_write_encrypt(MARIADB_CIO *cio,
size_t ma_schannel_write_encrypt(MARIADB_PVIO *pvio,
uchar *WriteBuffer,
size_t WriteBufferSize)
{
@@ -867,7 +867,7 @@ size_t ma_schannel_write_encrypt(MARIADB_CIO *cio,
SecBuffer Buffers[4];
DWORD cbMessage, cbData;
PBYTE pbMessage;
SC_CTX *sctx= (SC_CTX *)cio->cssl->ssl;
SC_CTX *sctx= (SC_CTX *)pvio->cssl->ssl;
size_t payload;
@@ -900,7 +900,7 @@ size_t ma_schannel_write_encrypt(MARIADB_CIO *cio,
if ((scRet = EncryptMessage(&sctx->ctxt, 0, &Message, 0))!= SEC_E_OK)
return -1;
if (cio->methods->write(cio, sctx->IoBuffer, Buffers[0].cbBuffer + Buffers[1].cbBuffer + Buffers[2].cbBuffer))
if (pvio->methods->write(pvio, sctx->IoBuffer, Buffers[0].cbBuffer + Buffers[1].cbBuffer + Buffers[2].cbBuffer))
return payload;
}
/* }}} */

View File

@@ -26,7 +26,7 @@
#include <my_global.h>
#include <my_sys.h>
#include <ma_common.h>
#include <ma_cio.h>
#include <ma_pvio.h>
#include <errmsg.h>
@@ -59,6 +59,7 @@ struct st_schannel {
CERT_CONTEXT *client_ca_ctx;
CRL_CONTEXT *client_crl_ctx;
CredHandle CredHdl;
my_bool FreeCredHdl;
PUCHAR IoBuffer;
DWORD IoBufferSize;
/* PUCHAR EncryptBuffer;
@@ -76,15 +77,16 @@ struct st_schannel {
typedef struct st_schannel SC_CTX;
CERT_CONTEXT *ma_schannel_create_cert_context(MARIADB_CIO *cio, const char *pem_file);
SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_CIO *cio, my_bool InitialRead, SecBuffer *pExtraData);
my_bool ma_schannel_load_private_key(MARIADB_CIO *cio, CERT_CONTEXT *ctx, char *key_file);
PCCRL_CONTEXT ma_schannel_create_crl_context(MARIADB_CIO *cio, const char *pem_file);
CERT_CONTEXT *ma_schannel_create_cert_context(MARIADB_PVIO *pvio, const char *pem_file);
SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl);
SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRead, SecBuffer *pExtraData);
my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, CERT_CONTEXT *ctx, char *key_file);
PCCRL_CONTEXT ma_schannel_create_crl_context(MARIADB_PVIO *pvio, const char *pem_file);
my_bool ma_schannel_verify_certs(SC_CTX *sctx, DWORD dwCertFlags);
size_t ma_schannel_write_encrypt(MARIADB_CIO *cio,
size_t ma_schannel_write_encrypt(MARIADB_PVIO *pvio,
uchar *WriteBuffer,
size_t WriteBufferSize);
size_t ma_schannel_read_decrypt(MARIADB_CIO *cio,
size_t ma_schannel_read_decrypt(MARIADB_PVIO *pvio,
PCredHandle phCreds,
CtxtHandle * phContext,
DWORD *DecryptLength,

View File

@@ -20,7 +20,7 @@
#include <my_global.h>
#include <my_sys.h>
#include <ma_common.h>
#include <ma_cio.h>
#include <ma_pvio.h>
#include <errmsg.h>
#include <string.h>
#include <mysql/client_plugin.h>
@@ -54,21 +54,21 @@ static void ma_ssl_set_error(MYSQL *mysql)
ulong ssl_errno= ERR_get_error();
char ssl_error[MAX_SSL_ERR_LEN];
const char *ssl_error_reason;
MARIADB_CIO *cio= mysql->net.cio;
MARIADB_PVIO *pvio= mysql->net.pvio;
if (!ssl_errno)
{
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error");
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error");
return;
}
if ((ssl_error_reason= ERR_reason_error_string(ssl_errno)))
{
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
0, ssl_error_reason);
return;
}
snprintf(ssl_error, MAX_SSL_ERR_LEN, "SSL errno=%lu", ssl_errno, mysql->charset);
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, ssl_error);
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, ssl_error);
return;
}
@@ -367,15 +367,15 @@ my_bool ma_ssl_connect(MARIADB_SSL *cssl)
SSL *ssl = (SSL *)cssl->ssl;
my_bool blocking;
MYSQL *mysql;
MARIADB_CIO *cio;
MARIADB_PVIO *pvio;
int rc;
mysql= (MYSQL *)SSL_get_app_data(ssl);
cio= mysql->net.cio;
pvio= mysql->net.pvio;
/* Set socket to blocking if not already set */
if (!(blocking= cio->methods->is_blocking(cio)))
cio->methods->blocking(cio, TRUE, 0);
if (!(blocking= pvio->methods->is_blocking(pvio)))
pvio->methods->blocking(pvio, TRUE, 0);
SSL_clear(ssl);
SSL_SESSION_set_timeout(SSL_get_session(ssl),
@@ -387,7 +387,7 @@ my_bool ma_ssl_connect(MARIADB_SSL *cssl)
ma_ssl_set_error(mysql);
/* restore blocking mode */
if (!blocking)
cio->methods->blocking(cio, FALSE, 0);
pvio->methods->blocking(pvio, FALSE, 0);
return 1;
}
rc= SSL_get_verify_result(ssl);
@@ -397,12 +397,12 @@ my_bool ma_ssl_connect(MARIADB_SSL *cssl)
ER(CR_SSL_CONNECTION_ERROR), X509_verify_cert_error_string(rc));
/* restore blocking mode */
if (!blocking)
cio->methods->blocking(cio, FALSE, 0);
pvio->methods->blocking(pvio, FALSE, 0);
return 1;
}
cio->cssl->ssl= cssl->ssl= (void *)ssl;
pvio->cssl->ssl= cssl->ssl= (void *)ssl;
return 0;
}
@@ -442,7 +442,7 @@ int ma_ssl_verify_server_cert(MARIADB_SSL *cssl)
{
X509 *cert;
MYSQL *mysql;
MARIADB_CIO *cio;
MARIADB_PVIO *pvio;
SSL *ssl;
char *p1, *p2, buf[256];
@@ -451,18 +451,18 @@ int ma_ssl_verify_server_cert(MARIADB_SSL *cssl)
ssl= (SSL *)cssl->ssl;
mysql= (MYSQL *)SSL_get_app_data(ssl);
cio= mysql->net.cio;
pvio= mysql->net.pvio;
if (!mysql->host)
{
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0,
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0,
"Invalid (empty) hostname");
return 1;
}
if (!(cert= SSL_get_peer_certificate(ssl)))
{
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0,
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0,
"Unable to get server certificate");
return 1;
}
@@ -480,7 +480,7 @@ int ma_ssl_verify_server_cert(MARIADB_SSL *cssl)
if (!strcmp(mysql->host, p1))
return(0);
}
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0,
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0,
"Validation of SSL server certificate failed");
return 1;
}
@@ -497,10 +497,10 @@ unsigned int ma_ssl_get_finger_print(MARIADB_SSL *cssl, unsigned char *fp, unsig
EVP_MD *digest= (EVP_MD *)EVP_sha1();
X509 *cert;
MYSQL *mysql;
unsigned int *fp_len;
unsigned int fp_len;
if (!cssl || !cssl->ssl)
return NULL;
return 0;
mysql= SSL_get_app_data(cssl->ssl);
@@ -519,8 +519,8 @@ unsigned int ma_ssl_get_finger_print(MARIADB_SSL *cssl, unsigned char *fp, unsig
"Finger print buffer too small");
return 0;
}
*fp_len= len;
if (!X509_digest(cert, digest, fp, fp_len))
fp_len= len;
if (!X509_digest(cert, digest, fp, &fp_len))
{
my_free(fp);
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
@@ -528,5 +528,5 @@ unsigned int ma_ssl_get_finger_print(MARIADB_SSL *cssl, unsigned char *fp, unsig
"invalid finger print of server certificate");
return 0;
}
return (*fp_len);
return (fp_len);
}

View File

@@ -34,7 +34,7 @@ struct st_cipher_suite {
CHAR *cipher;
};
void ma_schannel_set_sec_error(MARIADB_CIO *cio, DWORD ErrorNo);
void ma_schannel_set_sec_error(MARIADB_PVIO *pvio, DWORD ErrorNo);
void ma_schannel_set_win_error(MYSQL *mysql);
const struct st_cipher_suite sc_ciphers[]=
@@ -147,20 +147,20 @@ void ma_ssl_end()
/* {{{ static int ma_ssl_set_client_certs(MARIADB_SSL *cssl) */
static int ma_ssl_set_client_certs(MARIADB_SSL *cssl)
{
MYSQL *mysql= cssl->cio->mysql;
MYSQL *mysql= cssl->pvio->mysql;
char *certfile= mysql->options.ssl_cert,
*keyfile= mysql->options.ssl_key,
*cafile= mysql->options.ssl_ca;
SC_CTX *sctx= (SC_CTX *)cssl->ssl;
MARIADB_CIO *cio= cssl->cio;
MARIADB_PVIO *pvio= cssl->pvio;
if (cafile)
{
HCERTSTORE myCS= NULL;
char szName[64];
if (!(sctx->client_ca_ctx = ma_schannel_create_cert_context(cio, cafile)))
if (!(sctx->client_ca_ctx = ma_schannel_create_cert_context(pvio, cafile)))
goto end;
/* For X509 authentication we need to add ca certificate to local MY store.
@@ -186,16 +186,16 @@ static int ma_ssl_set_client_certs(MARIADB_SSL *cssl)
keyfile= certfile;
if (certfile && certfile[0])
if (!(sctx->client_cert_ctx = ma_schannel_create_cert_context(cssl->cio, certfile)))
if (!(sctx->client_cert_ctx = ma_schannel_create_cert_context(cssl->pvio, certfile)))
goto end;
if (sctx->client_cert_ctx && keyfile[0])
if (!ma_schannel_load_private_key(cio, sctx->client_cert_ctx, keyfile))
if (!ma_schannel_load_private_key(pvio, sctx->client_cert_ctx, keyfile))
goto end;
if (mysql->options.extension && mysql->options.extension->ssl_crl)
{
if (!(sctx->client_crl_ctx= ma_schannel_create_crl_context(cio, mysql->options.extension->ssl_crl)))
if (!(sctx->client_crl_ctx= (CRL_CONTEXT *)ma_schannel_create_crl_context(pvio, mysql->options.extension->ssl_crl)))
goto end;
}
return 0;
@@ -221,7 +221,7 @@ void *ma_ssl_init(MYSQL *mysql)
pthread_mutex_lock(&LOCK_schannel_config);
if ((sctx= LocalAlloc(0, sizeof(SC_CTX))))
if ((sctx= (SC_CTX *)LocalAlloc(0, sizeof(SC_CTX))))
{
ZeroMemory(sctx, sizeof(SC_CTX));
sctx->mysql= mysql;
@@ -239,24 +239,25 @@ my_bool ma_ssl_connect(MARIADB_SSL *cssl)
my_bool blocking;
MYSQL *mysql;
SCHANNEL_CRED Cred;
MARIADB_CIO *cio;
MARIADB_PVIO *pvio;
my_bool rc= 1;
SC_CTX *sctx;
SECURITY_STATUS sRet;
PCCERT_CONTEXT pRemoteCertContext = NULL,
pLocalCertContext= NULL;
ALG_ID AlgId[2]= {0, 0};
if (!cssl || !cssl->cio)
if (!cssl || !cssl->pvio)
return 1;;
cio= cssl->cio;
pvio= cssl->pvio;
sctx= (SC_CTX *)cssl->ssl;
/* Set socket to blocking if not already set */
if (!(blocking= cio->methods->is_blocking(cio)))
cio->methods->blocking(cio, TRUE, 0);
if (!(blocking= pvio->methods->is_blocking(pvio)))
pvio->methods->blocking(pvio, TRUE, 0);
mysql= cio->mysql;
mysql= pvio->mysql;
if (ma_ssl_set_client_certs(cssl))
goto end;
@@ -272,7 +273,7 @@ my_bool ma_ssl_connect(MARIADB_SSL *cssl)
break;
}
}
Cred.palgSupportedAlgs= &AlgId;
Cred.palgSupportedAlgs= (ALG_ID *)&AlgId;
}
@@ -290,29 +291,33 @@ my_bool ma_ssl_connect(MARIADB_SSL *cssl)
if ((sRet= AcquireCredentialsHandleA(NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND,
NULL, &Cred, NULL, NULL, &sctx->CredHdl, NULL)) != SEC_E_OK)
{
ma_schannel_set_sec_error(cio, sRet);
ma_schannel_set_sec_error(pvio, sRet);
goto end;
}
sctx->FreeCredHdl= 1;
if (ma_schannel_client_handshake(cssl))
if (ma_schannel_client_handshake(cssl) != SEC_E_OK)
goto end;
sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pRemoteCertContext);
if (sRet != SEC_E_OK)
{
ma_schannel_set_sec_error(cio, sRet);
ma_schannel_set_sec_error(pvio, sRet);
goto end;
}
if (!ma_schannel_verify_certs(sctx, 0))
goto end;
return 0;
end:
/* todo: cleanup */
if (sctx->IoBufferSize)
if (pRemoteCertContext)
CertFreeCertificateContext(pRemoteCertContext);
if (rc && sctx->IoBufferSize)
LocalFree(sctx->IoBuffer);
sctx->IoBufferSize= 0;
if (sctx->client_ca_ctx)
CertFreeCertificateContext(sctx->client_ca_ctx);
if (sctx->client_cert_ctx)
@@ -325,23 +330,23 @@ end:
size_t ma_ssl_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
{
SC_CTX *sctx= (SC_CTX *)cssl->ssl;
MARIADB_CIO *cio= sctx->mysql->net.cio;
size_t dlength= -1;
MARIADB_PVIO *pvio= sctx->mysql->net.pvio;
DWORD dlength= -1;
ma_schannel_read_decrypt(cio, &sctx->CredHdl, &sctx->ctxt, &dlength, buffer, length);
ma_schannel_read_decrypt(pvio, &sctx->CredHdl, &sctx->ctxt, &dlength, (uchar *)buffer, length);
return dlength;
}
size_t ma_ssl_write(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
{
SC_CTX *sctx= (SC_CTX *)cssl->ssl;
MARIADB_CIO *cio= sctx->mysql->net.cio;
MARIADB_PVIO *pvio= sctx->mysql->net.pvio;
size_t rc, wlength= 0;
size_t remain= length;
while (remain)
{
if ((rc= ma_schannel_write_encrypt(cio, (uchar *)buffer + wlength, remain)) <= 0)
if ((rc= ma_schannel_write_encrypt(pvio, (uchar *)buffer + wlength, remain)) <= 0)
return rc;
wlength+= rc;
remain-= rc;
@@ -349,14 +354,12 @@ size_t ma_ssl_write(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
return length;
}
/* {{{ void ma_ssl_close(MARIADB_CIO *cio) */
void ma_ssl_close(MARIADB_CIO *cio)
/* {{{ my_bool ma_ssl_close(MARIADB_PVIO *pvio) */
my_bool ma_ssl_close(MARIADB_SSL *cssl)
{
SC_CTX *sctx;
if (!cio || !cio->cssl)
return;
SC_CTX *sctx= (SC_CTX *)cssl->ssl;
if ((sctx= (SC_CTX *)cio->cssl))
if (sctx)
{
if (sctx->IoBufferSize)
LocalFree(sctx->IoBuffer);
@@ -370,16 +373,17 @@ void ma_ssl_close(MARIADB_CIO *cio)
DeleteSecurityContext(&sctx->ctxt);
}
LocalFree(sctx);
return 0;
}
/* }}} */
int ma_ssl_verify_server_cert(MARIADB_SSL *cssl)
{
SC_CTX *sctx= (SC_CTX *)cssl->ssl;
MARIADB_CIO *cio= cssl->cio;
MARIADB_PVIO *pvio= cssl->pvio;
int rc= 1;
char *szName= NULL;
char *pszServerName= cio->mysql->host;
char *pszServerName= pvio->mysql->host;
/* check server name */
if (pszServerName && (sctx->mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT))
@@ -391,7 +395,7 @@ int ma_ssl_verify_server_cert(MARIADB_SSL *cssl)
if ((sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pServerCert)) != SEC_E_OK)
{
ma_schannel_set_sec_error(cio, sRet);
ma_schannel_set_sec_error(pvio, sRet);
return 1;
}
@@ -400,13 +404,13 @@ int ma_ssl_verify_server_cert(MARIADB_SSL *cssl)
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
NULL, 0)))
{
cio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Can't retrieve name of server certificate");
pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Can't retrieve name of server certificate");
return 1;
}
if (!(szName= LocalAlloc(0, NameSize + 1)))
if (!(szName= (char *)LocalAlloc(0, NameSize + 1)))
{
cio->set_error(sctx->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
pvio->set_error(sctx->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
goto end;
}
@@ -415,7 +419,7 @@ int ma_ssl_verify_server_cert(MARIADB_SSL *cssl)
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
szName, NameSize))
{
cio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Can't retrieve name of server certificate");
pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Can't retrieve name of server certificate");
goto end;
}
if ((p1 = strstr(szName, "CN=")))
@@ -428,7 +432,7 @@ int ma_ssl_verify_server_cert(MARIADB_SSL *cssl)
rc= 0;
goto end;
}
cio->set_error(cio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
"Name of server certificate didn't match");
}
}
@@ -469,6 +473,6 @@ unsigned int ma_ssl_get_finger_print(MARIADB_SSL *cssl, unsigned char *fp, unsig
PCCERT_CONTEXT pRemoteCertContext = NULL;
if (QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pRemoteCertContext) != SEC_E_OK)
return NULL;
CertGetCertificateContextProperty(pRemoteCertContext, CERT_HASH_PROP_ID, fp, &len);
CertGetCertificateContextProperty(pRemoteCertContext, CERT_HASH_PROP_ID, fp, (DWORD *)&len);
return len;
}

View File

@@ -4,7 +4,7 @@
#include <errmsg.h>
#include <ma_common.h>
#include <mysql/client_plugin.h>
#include <ma_cio.h>
#include <ma_pvio.h>
typedef struct st_mysql_client_plugin_AUTHENTICATION auth_plugin_t;
static int client_mpvio_write_packet(struct st_plugin_vio*, const uchar*, size_t);
@@ -311,7 +311,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
errno);
goto error;
}
if (ma_cio_start_ssl(mysql->net.cio))
if (ma_pvio_start_ssl(mysql->net.pvio))
goto error;
}
#endif /* HAVE_SSL */
@@ -480,17 +480,17 @@ static int client_mpvio_write_packet(struct st_plugin_vio *mpv,
connection
*/
void mpvio_info(MARIADB_CIO *cio, MYSQL_PLUGIN_VIO_INFO *info)
void mpvio_info(MARIADB_PVIO *pvio, MYSQL_PLUGIN_VIO_INFO *info)
{
bzero(info, sizeof(*info));
switch (cio->type) {
case CIO_TYPE_SOCKET:
switch (pvio->type) {
case PVIO_TYPE_SOCKET:
info->protocol= MYSQL_VIO_TCP;
ma_cio_get_handle(cio, &info->socket);
ma_pvio_get_handle(pvio, &info->socket);
return;
case CIO_TYPE_UNIXSOCKET:
case PVIO_TYPE_UNIXSOCKET:
info->protocol= MYSQL_VIO_SOCKET;
ma_cio_get_handle(cio, &info->socket);
ma_pvio_get_handle(pvio, &info->socket);
return;
/*
case VIO_TYPE_SSL:
@@ -527,7 +527,7 @@ static void client_mpvio_info(MYSQL_PLUGIN_VIO *vio,
MYSQL_PLUGIN_VIO_INFO *info)
{
MCPVIO_EXT *mpvio= (MCPVIO_EXT*)vio;
mpvio_info(mpvio->mysql->net.cio, info);
mpvio_info(mpvio->mysql->net.pvio, info);
}
/**

View File

@@ -1,448 +0,0 @@
/************************************************************************************
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 <http://www.gnu.org/licenses>
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 Communication IO (CIO) plugin for named pipe communication */
#ifdef _WIN32
#include <my_global.h>
#include <my_sys.h>
#include <errmsg.h>
#include <mysql.h>
#include <mysql/client_plugin.h>
#include <string.h>
#include <m_string.h>
#ifdef HAVE_SHMEM_DYNAMIC
#define my_malloc(A, B) malloc((A))
#undef my_free
#define my_free(A,B) free(((A)))
#endif
#define SHM_DEFAULT_NAME "MYSQL"
#define CIO_SHM_BUFFER_SIZE 16000 + 4
my_bool cio_shm_set_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type, int timeout);
int cio_shm_get_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type);
size_t cio_shm_read(MARIADB_CIO *cio, const uchar *buffer, size_t length);
size_t cio_shm_write(MARIADB_CIO *cio, uchar *buffer, size_t length);
int cio_shm_wait_io_or_timeout(MARIADB_CIO *cio, my_bool is_read, int timeout);
my_bool cio_shm_blocking(MARIADB_CIO *cio, my_bool value, my_bool *old_value);
my_bool cio_shm_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo);
my_bool cio_shm_close(MARIADB_CIO *cio);
struct st_ma_cio_methods cio_shm_methods= {
cio_shm_set_timeout,
cio_shm_get_timeout,
cio_shm_read,
NULL,
cio_shm_write,
NULL,
cio_shm_wait_io_or_timeout,
cio_shm_blocking,
cio_shm_connect,
cio_shm_close,
NULL,
NULL,
NULL,
NULL,
NULL
};
#ifndef HAVE_SHMEM_DYNAMIC
MARIADB_CIO_PLUGIN cio_shmem_plugin=
#else
MARIADB_CIO_PLUGIN _mysql_client_plugin_declaration_=
#endif
{
MARIADB_CLIENT_CIO_PLUGIN,
MARIADB_CLIENT_CIO_PLUGIN_INTERFACE_VERSION,
"cio_shmem",
"Georg Richter",
"MariaDB communication IO plugin for Windows shared memory communication",
{1, 0, 0},
"LGPPL",
NULL,
NULL,
&cio_shm_methods,
};
enum enum_shm_events
{
CIO_SHM_SERVER_WROTE= 0,
CIO_SHM_SERVER_READ,
CIO_SHM_CLIENT_WROTE,
CIO_SHM_CLIENT_READ,
CIO_SHM_CONNECTION_CLOSED
};
typedef struct {
HANDLE event[5];
HANDLE file_map;
LPVOID *map;
char *read_pos;
size_t buffer_size;
} CIO_SHM;
char *StrEvent[]= {"SERVER_WROTE", "SERVER_READ", "CLIENT_WROTE", "CLIENT_READ", "CONNECTION_CLOSED"};
struct st_cio_shm {
char *shm_name;
};
my_bool cio_shm_set_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type, int timeout)
{
if (!cio)
return 1;
cio->timeout[type]= (timeout > 0) ? timeout * 1000 : INFINITE;
return 0;
}
int cio_shm_get_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type)
{
if (!cio)
return -1;
return cio->timeout[type] / 1000;
}
size_t cio_shm_read(MARIADB_CIO *cio, const uchar *buffer, size_t length)
{
CIO_SHM *cio_shm= (CIO_SHM *)cio->data;
size_t copy_size= length;
HANDLE events[2];
if (!cio_shm)
return -1;
/* we need to wait for write and close events */
if (!cio_shm->buffer_size)
{
events[0]= cio_shm->event[CIO_SHM_CONNECTION_CLOSED];
events[1]= cio_shm->event[CIO_SHM_SERVER_WROTE];
switch(WaitForMultipleObjects(2, events, 0, cio->timeout[CIO_READ_TIMEOUT]))
{
case WAIT_OBJECT_0: /* server closed connection */
SetLastError(ERROR_GRACEFUL_DISCONNECT);
return -1;
case WAIT_OBJECT_0 +1: /* server_wrote event */
break;
case WAIT_TIMEOUT:
SetLastError(ETIMEDOUT);
default:
return -1;
}
/* server sent data */
cio_shm->read_pos= cio_shm->map;
cio_shm->buffer_size= uint4korr(cio_shm->read_pos);
cio_shm->read_pos+= 4;
}
if (cio_shm->buffer_size < copy_size)
copy_size= cio_shm->buffer_size;
if (copy_size)
{
memcpy(buffer, cio_shm->read_pos, cio_shm->buffer_size);
cio_shm->read_pos+= copy_size;
cio_shm->buffer_size-= copy_size;
}
/* we need to read again */
if (!cio_shm->buffer_size)
if (!SetEvent(cio_shm->event[CIO_SHM_CLIENT_READ]))
return -1;
return copy_size;
}
size_t cio_shm_write(MARIADB_CIO *cio, uchar *buffer, size_t length)
{
HANDLE events[2];
CIO_SHM *cio_shm= (CIO_SHM *)cio->data;
size_t bytes_to_write= length;
uchar *buffer_pos= buffer;
if (!cio_shm)
return -1;
events[0]= cio_shm->event[CIO_SHM_CONNECTION_CLOSED];
events[1]= cio_shm->event[CIO_SHM_SERVER_READ];
while (bytes_to_write)
{
size_t pkt_length;
switch (WaitForMultipleObjects(2, events, 0, cio->timeout[CIO_WRITE_TIMEOUT])) {
case WAIT_OBJECT_0: /* connection closed */
SetLastError(ERROR_GRACEFUL_DISCONNECT);
return -1;
case WAIT_OBJECT_0 + 1: /* server_read */
break;
case WAIT_TIMEOUT:
SetLastError(ETIMEDOUT);
default:
return -1;
}
pkt_length= MIN(CIO_SHM_BUFFER_SIZE, length);
int4store(cio_shm->map, pkt_length);
memcpy((uchar *)cio_shm->map + 4, buffer_pos, length);
buffer_pos+= length;
bytes_to_write-= length;
if (!SetEvent(cio_shm->event[CIO_SHM_CLIENT_WROTE]))
return -1;
}
return length;
}
int cio_shm_wait_io_or_timeout(MARIADB_CIO *cio, my_bool is_read, int timeout)
{
}
my_bool cio_shm_blocking(MARIADB_CIO *cio, my_bool block, my_bool *previous_mode)
{
/* not supported */
return 0;
}
int cio_shm_keepalive(MARIADB_CIO *cio)
{
/* not supported */
return 0;
}
int cio_shm_fast_send(MARIADB_CIO *cio)
{
/* not supported */
return 0;
}
my_bool cio_shm_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo)
{
char *base_memory_name;
char *prefixes[]= {"", "Global\\", NULL};
char *shm_name, *shm_suffix, *shm_prefix;
uchar i= 0;
int len;
DWORD cid;
char connection_id[28];
char *connection_id_str;
DWORD dwDesiredAccess= EVENT_MODIFY_STATE | SYNCHRONIZE;
HANDLE hdlConnectRequest= NULL,
hdlConnectRequestAnswer= NULL,
file_map= NULL;
LPVOID map= NULL;
CIO_SHM *cio_shm= (CIO_SHM*)LocalAlloc(LMEM_ZEROINIT, sizeof(CIO_SHM));
if (!cio_shm)
{
CIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0, "");
return 0;
}
/* MariaDB server constructs the event name as follows:
"Global\\base_memory_name" or
"\\base_memory_name"
*/
base_memory_name= (cinfo->mysql->options.shared_memory_base_name) ?
cinfo->mysql->options.shared_memory_base_name : SHM_DEFAULT_NAME;
if (!(shm_name= LocalAlloc(LMEM_ZEROINIT, strlen(base_memory_name) + 40)))
{
CIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0, "");
goto error;
}
/* iterate through prefixes */
while (prefixes[i])
{
len= sprintf(shm_name, "%s%s_", prefixes[i], base_memory_name);
shm_suffix= shm_name + len;
strcpy(shm_suffix, "CONNECT_REQUEST");
if ((hdlConnectRequest= OpenEvent(dwDesiredAccess, 0, shm_name)))
{
/* save prefix to prevent further loop */
shm_prefix= prefixes[i];
break;
}
i++;
}
if (!hdlConnectRequest)
{
CIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Opening CONNECT_REQUEST event failed", GetLastError());
goto error;
}
strcpy(shm_suffix, "CONNECT_ANSWER");
if (!(hdlConnectRequestAnswer= OpenEvent(dwDesiredAccess, 0, shm_name)))
{
CIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Opening CONNECT_ANSWER event failed", GetLastError());
goto error;
}
/* get connection id, so we can build the filename used for connection */
strcpy(shm_suffix, "CONNECT_DATA");
if (!(file_map= OpenFileMapping(FILE_MAP_WRITE, 0, shm_name)))
{
CIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "OpenFileMapping failed", GetLastError());
goto error;
}
/* try to get first 4 bytes, which represents connection_id */
if (!(map= MapViewOfFile(file_map, FILE_MAP_WRITE, 0, 0, sizeof(cid))))
{
CIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Reading connection_id failed", GetLastError());
goto error;
}
/* notify server */
if (!SetEvent(hdlConnectRequest))
{
CIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Failed sending connection request", GetLastError());
goto error;
}
/* Wait for server answer */
switch(WaitForSingleObject(hdlConnectRequestAnswer, cio->timeout[CIO_CONNECT_TIMEOUT])) {
case WAIT_ABANDONED:
CIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Mutex was not released in time", GetLastError());
goto error;
break;
case WAIT_FAILED:
CIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Operation wait failed", GetLastError());
goto error;
break;
case WAIT_TIMEOUT:
CIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Operation timed out", GetLastError());
goto error;
break;
case WAIT_OBJECT_0:
break;
default:
CIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Wait for server failed", GetLastError());
break;
}
cid= uint4korr(map);
len= sprintf(shm_name, "%s%s_%d_", shm_prefix, base_memory_name, cid);
shm_suffix= shm_name + len;
strcpy(shm_suffix, "DATA");
cio_shm->file_map= OpenFileMapping(FILE_MAP_WRITE, 0, shm_name);
if (cio_shm->file_map == NULL)
{
CIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "OpenFileMapping failed", GetLastError());
goto error;
}
if (!(cio_shm->map= MapViewOfFile(cio_shm->file_map, FILE_MAP_WRITE, 0, 0, CIO_SHM_BUFFER_SIZE)))
{
CIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "MapViewOfFile failed", GetLastError());
goto error;
}
for (i=0; i < 5; i++)
{
strcpy(shm_suffix, StrEvent[i]);
if (!(cio_shm->event[i]= OpenEvent(dwDesiredAccess, 0, shm_name)))
{
CIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Couldn't create event", GetLastError());
goto error;
}
}
/* we will first read from server */
SetEvent(cio_shm->event[CIO_SHM_SERVER_READ]);
error:
if (hdlConnectRequest)
CloseHandle(hdlConnectRequest);
if (hdlConnectRequestAnswer)
CloseHandle(hdlConnectRequestAnswer);
if (shm_name)
LocalFree(shm_name);
if (map)
UnmapViewOfFile(map);
if (file_map)
CloseHandle(file_map);
if (cio_shm)
{
/* check if all events are set */
if (cio_shm->event[4])
{
cio->data= (void *)cio_shm;
cio->mysql= cinfo->mysql;
cio->type= cinfo->type;
cio_shm->read_pos= cio_shm->map;
cio->mysql->net.cio= cio;
return 0;
}
for (i=0;i < 5; i++)
if (cio_shm->event[i])
CloseHandle(cio_shm->event[i]);
if (cio_shm->map)
UnmapViewOfFile(cio_shm->map);
if (cio_shm->file_map)
CloseHandle(cio_shm->file_map);
LocalFree(cio_shm);
}
return 1;
}
my_bool cio_shm_close(MARIADB_CIO *cio)
{
CIO_SHM *cio_shm= (CIO_SHM *)cio->data;
int i;
if (!cio_shm)
return 1;
/* notify server */
SetEvent(cio_shm->event[CIO_SHM_CONNECTION_CLOSED]);
UnmapViewOfFile(cio_shm->map);
CloseHandle(cio_shm->file_map);
for (i=0; i < 5; i++)
CloseHandle(cio_shm->event[i]);
LocalFree(cio_shm);
cio->data= NULL;
return 0;
}
my_socket cio_shm_get_socket(MARIADB_CIO *cio)
{
}
my_bool cio_shm_is_blocking(MARIADB_CIO *cio)
{
return 1;
}
#endif

View File

@@ -74,7 +74,7 @@ MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ =
};
typedef struct st_conn_repl {
MARIADB_CIO *cio[2];
MARIADB_PVIO *pvio[2];
MYSQL *slave_mysql;
my_bool read_only;
my_bool round_robin;
@@ -83,8 +83,8 @@ typedef struct st_conn_repl {
int port[2];
} REPL_DATA;
#define SET_SLAVE(mysql, data) mysql->net.cio= data->cio[MARIADB_SLAVE]
#define SET_MASTER(mysql, data) mysql->net.cio= data->cio[MARIADB_MASTER]
#define SET_SLAVE(mysql, data) mysql->net.pvio= data->pvio[MARIADB_SLAVE]
#define SET_MASTER(mysql, data) mysql->net.pvio= data->pvio[MARIADB_MASTER]
/* parse url
@@ -182,7 +182,7 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char
return NULL;
}
memset(data->cio, 0, 2 * sizeof(MARIADB_CIO *));
memset(data->pvio, 0, 2 * sizeof(MARIADB_PVIO *));
if (repl_parse_url(host, data))
goto error;
@@ -192,7 +192,7 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char
data->port[MARIADB_MASTER] ? data->port[MARIADB_MASTER] : port, unix_socket, clientflag)))
goto error;
data->cio[MARIADB_MASTER]= mysql->net.cio;
data->pvio[MARIADB_MASTER]= mysql->net.pvio;
hdlr->data= data;
/* to allow immediate access without connection delay, we will start
@@ -205,12 +205,12 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char
{
if (data->slave_mysql)
mysql_close(data->slave_mysql);
data->cio[MARIADB_SLAVE]= NULL;
data->pvio[MARIADB_SLAVE]= NULL;
}
else
{
data->cio[MARIADB_SLAVE]= data->slave_mysql->net.cio;
data->slave_mysql->net.cio->mysql= mysql;
data->pvio[MARIADB_SLAVE]= data->slave_mysql->net.pvio;
data->slave_mysql->net.pvio->mysql= mysql;
}
return mysql;
error:
@@ -232,12 +232,12 @@ void repl_close(MYSQL *mysql)
SET_MASTER(mysql, data);
/* free slave information and close connection */
if (data->cio[MARIADB_SLAVE])
if (data->pvio[MARIADB_SLAVE])
{
/* restore mysql */
data->cio[MARIADB_SLAVE]->mysql= data->slave_mysql;
data->pvio[MARIADB_SLAVE]->mysql= data->slave_mysql;
mysql_close(data->slave_mysql);
data->cio[MARIADB_SLAVE]= NULL;
data->pvio[MARIADB_SLAVE]= NULL;
data->slave_mysql= NULL;
}
@@ -286,7 +286,7 @@ int repl_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
REPL_DATA *data= (REPL_DATA *)mysql->net.conn_hdlr->data;
/* if we don't have slave or slave became unavailable root traffic to master */
if (!data->cio[MARIADB_SLAVE] || !data->read_only)
if (!data->pvio[MARIADB_SLAVE] || !data->read_only)
{
SET_MASTER(mysql, data);
return 0;
@@ -301,7 +301,7 @@ int repl_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
break;
case MYSQL_COM_STMT_EXECUTE:
case MYSQL_COM_STMT_FETCH:
if (data->cio[MARIADB_SLAVE]->mysql->stmts && is_slave_stmt(data->cio[MARIADB_SLAVE]->mysql, arg))
if (data->pvio[MARIADB_SLAVE]->mysql->stmts && is_slave_stmt(data->pvio[MARIADB_SLAVE]->mysql, arg))
SET_SLAVE(mysql, data);
else
SET_MASTER(mysql,data);

View File

@@ -1,5 +1,5 @@
IF(WIN32)
SET(EXPORT_FILE "cio_plugin.def")
SET(EXPORT_FILE "pvio_plugin.def")
ENDIF()
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
@@ -8,20 +8,20 @@ SET(CMAKE_SHARED_LIBRARY_PREFIX "")
IF(SOCKET_PLUGIN_TYPE MATCHES "DYNAMIC")
ADD_DEFINITIONS(-DHAVE_SOCKET_DYNAMIC=1)
ADD_LIBRARY(cio_socket SHARED cio_socket.c ${EXPORT_FILE})
SET(INSTALL_LIBS cio_socket)
ADD_LIBRARY(pvio_socket SHARED pvio_socket.c ${EXPORT_FILE})
SET(INSTALL_LIBS pvio_socket)
ENDIF()
IF(WIN32)
IF(NPIPE_PLUGIN_TYPE MATCHES "DYNAMIC")
ADD_DEFINITIONS(-DHAVE_NPIPE_DYNAMIC=1)
ADD_LIBRARY(cio_npipe SHARED cio_npipe.c ${EXPORT_FILE})
SET(INSTALL_LIBS ${INSTALL_LIBS} cio_npipe)
ADD_LIBRARY(pvio_npipe SHARED pvio_npipe.c ${EXPORT_FILE})
SET(INSTALL_LIBS ${INSTALL_LIBS} pvio_npipe)
ENDIF()
IF(SHMEM_PLUGIN_TYPE MATCHES "DYNAMIC")
ADD_DEFINITIONS(-DHAVE_SHMEM_DYNAMIC=1)
ADD_LIBRARY(cio_shmem SHARED cio_shmem.c ${EXPORT_FILE})
SET(INSTALL_LIBS ${INSTALL_LIBS} cio_shmem)
ADD_LIBRARY(pvio_shmem SHARED pvio_shmem.c ${EXPORT_FILE})
SET(INSTALL_LIBS ${INSTALL_LIBS} pvio_shmem)
ENDIF()
ENDIF()

View File

@@ -1,5 +1,5 @@
/************************************************************************************
Copyright (C) 2015 MariaDB Corporation AB
Copyright (C) 2015 Georg Richter and 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
@@ -16,11 +16,9 @@
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 Communication IO (CIO) plugin for named pipe communication */
/* MariaDB virtual IO plugin for Windows named pipe communication */
#ifdef _WIN32
@@ -39,53 +37,53 @@
#endif
/* Function prototypes */
my_bool cio_npipe_set_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type, int timeout);
int cio_npipe_get_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type);
size_t cio_npipe_read(MARIADB_CIO *cio, uchar *buffer, size_t length);
size_t cio_npipe_write(MARIADB_CIO *cio, uchar *buffer, size_t length);
int cio_npipe_wait_io_or_timeout(MARIADB_CIO *cio, my_bool is_read, int timeout);
my_bool cio_npipe_blocking(MARIADB_CIO *cio, my_bool value, my_bool *old_value);
my_bool cio_npipe_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo);
my_bool cio_npipe_close(MARIADB_CIO *cio);
int cio_npipe_fast_send(MARIADB_CIO *cio);
int cio_npipe_keepalive(MARIADB_CIO *cio);
my_socket cio_npipe_get_socket(MARIADB_CIO *cio);
my_bool cio_npipe_is_blocking(MARIADB_CIO *cio);
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_write(MARIADB_PVIO *pvio, 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);
my_bool pvio_npipe_close(MARIADB_PVIO *pvio);
int pvio_npipe_fast_send(MARIADB_PVIO *pvio);
int pvio_npipe_keepalive(MARIADB_PVIO *pvio);
my_socket pvio_npipe_get_socket(MARIADB_PVIO *pvio);
my_bool pvio_npipe_is_blocking(MARIADB_PVIO *pvio);
struct st_ma_cio_methods cio_npipe_methods= {
cio_npipe_set_timeout,
cio_npipe_get_timeout,
cio_npipe_read,
cio_npipe_write,
cio_npipe_wait_io_or_timeout,
cio_npipe_blocking,
cio_npipe_connect,
cio_npipe_close,
cio_npipe_fast_send,
cio_npipe_keepalive,
cio_npipe_get_socket,
cio_npipe_is_blocking
struct st_ma_pvio_methods pvio_npipe_methods= {
pvio_npipe_set_timeout,
pvio_npipe_get_timeout,
pvio_npipe_read,
pvio_npipe_write,
pvio_npipe_wait_io_or_timeout,
pvio_npipe_blocking,
pvio_npipe_connect,
pvio_npipe_close,
pvio_npipe_fast_send,
pvio_npipe_keepalive,
pvio_npipe_get_socket,
pvio_npipe_is_blocking
};
#ifndef HAVE_NPIPE_DYNAMIC
MARIADB_CIO_PLUGIN cio_npipe_plugin =
MARIADB_PVIO_PLUGIN pvio_npipe_plugin =
#else
MARIADB_CIO_PLUGIN _mysql_client_plugin_declaration_ =
MARIADB_PVIO_PLUGIN _mysql_client_plugin_declaration_ =
#endif
{
MARIADB_CLIENT_CIO_PLUGIN,
MARIADB_CLIENT_CIO_PLUGIN_INTERFACE_VERSION,
"cio_npipe",
MARIADB_CLIENT_PVIO_PLUGIN,
MARIADB_CLIENT_PVIO_PLUGIN_INTERFACE_VERSION,
"pvio_npipe",
"Georg Richter",
"MariaDB communication IO plugin for named pipe communication",
"MariaDB virtual IO plugin for named pipe connection",
{1, 0, 0},
"LGPL",
NULL,
NULL,
&cio_npipe_methods
&pvio_npipe_methods
};
struct st_cio_npipe {
struct st_pvio_npipe {
HANDLE pipe;
OVERLAPPED overlapped;
size_t rw_size;
@@ -93,31 +91,31 @@ struct st_cio_npipe {
MYSQL *mysql;
};
my_bool cio_npipe_set_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type, int timeout)
my_bool pvio_npipe_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout)
{
if (!cio)
if (!pvio)
return 1;
cio->timeout[type]= (timeout > 0) ? timeout * 1000 : -1;
pvio->timeout[type]= (timeout > 0) ? timeout * 1000 : -1;
return 0;
}
int cio_npipe_get_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type)
int pvio_npipe_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type)
{
if (!cio)
if (!pvio)
return -1;
return cio->timeout[type] / 1000;
return pvio->timeout[type] / 1000;
}
size_t cio_npipe_read(MARIADB_CIO *cio, uchar *buffer, size_t length)
size_t pvio_npipe_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
{
DWORD dwRead= 0;
size_t r= -1;
struct st_cio_npipe *cpipe= NULL;
struct st_pvio_npipe *cpipe= NULL;
if (!cio || !cio->data)
if (!pvio || !pvio->data)
return -1;
cpipe= (struct st_cio_npipe *)cio->data;
cpipe= (struct st_pvio_npipe *)pvio->data;
if (ReadFile(cpipe->pipe, buffer, length, &dwRead, &cpipe->overlapped))
{
@@ -125,7 +123,7 @@ size_t cio_npipe_read(MARIADB_CIO *cio, uchar *buffer, size_t length)
goto end;
}
if (GetLastError() == ERROR_IO_PENDING)
r= cio_npipe_wait_io_or_timeout(cio, 1, 0);
r= pvio_npipe_wait_io_or_timeout(pvio, 1, 0);
if (!r)
r= cpipe->rw_size;
@@ -133,16 +131,16 @@ end:
return r;
}
size_t cio_npipe_write(MARIADB_CIO *cio, uchar *buffer, size_t length)
size_t pvio_npipe_write(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
{
DWORD dwWrite= 0;
size_t r= -1;
struct st_cio_npipe *cpipe= NULL;
struct st_pvio_npipe *cpipe= NULL;
if (!cio || !cio->data)
if (!pvio || !pvio->data)
return -1;
cpipe= (struct st_cio_npipe *)cio->data;
cpipe= (struct st_pvio_npipe *)pvio->data;
if (WriteFile(cpipe->pipe, buffer, length, &dwWrite, &cpipe->overlapped))
{
@@ -150,7 +148,7 @@ size_t cio_npipe_write(MARIADB_CIO *cio, uchar *buffer, size_t length)
goto end;
}
if (GetLastError() == ERROR_IO_PENDING)
r= cio_npipe_wait_io_or_timeout(cio, 1, 0);
r= pvio_npipe_wait_io_or_timeout(pvio, 1, 0);
if (!r)
r= cpipe->rw_size;
@@ -158,17 +156,17 @@ end:
return r;
}
int cio_npipe_wait_io_or_timeout(MARIADB_CIO *cio, my_bool is_read, int timeout)
int pvio_npipe_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout)
{
int r= -1;
DWORD status;
int save_error;
struct st_cio_npipe *cpipe= NULL;
struct st_pvio_npipe *cpipe= NULL;
cpipe= (struct st_cio_npipe *)cio->data;
cpipe= (struct st_pvio_npipe *)pvio->data;
if (!timeout)
timeout= (is_read) ? cio->timeout[CIO_READ_TIMEOUT] : cio->timeout[CIO_WRITE_TIMEOUT];
timeout= (is_read) ? pvio->timeout[PVIO_READ_TIMEOUT] : pvio->timeout[PVIO_WRITE_TIMEOUT];
status= WaitForSingleObject(cpipe->overlapped.hEvent, timeout);
if (status == WAIT_OBJECT_0)
@@ -183,42 +181,42 @@ int cio_npipe_wait_io_or_timeout(MARIADB_CIO *cio, my_bool is_read, int timeout)
return -1;
}
my_bool cio_npipe_blocking(MARIADB_CIO *cio, my_bool block, my_bool *previous_mode)
my_bool pvio_npipe_blocking(MARIADB_PVIO *pvio, my_bool block, my_bool *previous_mode)
{
/* not supported */
return 0;
}
int cio_npipe_keepalive(MARIADB_CIO *cio)
int pvio_npipe_keepalive(MARIADB_PVIO *pvio)
{
/* not supported */
return 0;
}
int cio_npipe_fast_send(MARIADB_CIO *cio)
int pvio_npipe_fast_send(MARIADB_PVIO *pvio)
{
/* not supported */
return 0;
}
my_bool cio_npipe_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo)
my_bool pvio_npipe_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
{
struct st_cio_npipe *cpipe= NULL;
struct st_pvio_npipe *cpipe= NULL;
if (!cio || !cinfo)
if (!pvio || !cinfo)
return 1;
if (!(cpipe= (struct st_cio_npipe *)my_malloc(sizeof(struct st_cio_npipe), MYF(0))))
if (!(cpipe= (struct st_pvio_npipe *)my_malloc(sizeof(struct st_pvio_npipe), MYF(0))))
{
CIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0, "");
PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0, "");
return 1;
}
bzero(cpipe, sizeof(struct st_cio_npipe));
cio->data= (void *)cpipe;
bzero(cpipe, sizeof(struct st_pvio_npipe));
pvio->data= (void *)cpipe;
cpipe->pipe= INVALID_HANDLE_VALUE;
cio->mysql= cinfo->mysql;
cio->type= cinfo->type;
pvio->mysql= cinfo->mysql;
pvio->type= cinfo->type;
if (cinfo->type == CIO_TYPE_NAMEDPIPE)
if (cinfo->type == PVIO_TYPE_NAMEDPIPE)
{
my_bool has_timedout= 0;
char szPipeName[MAX_PATH];
@@ -246,14 +244,14 @@ my_bool cio_npipe_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo)
if (GetLastError() != ERROR_PIPE_BUSY)
{
cio->set_error(cio, CR_NAMEDPIPEOPEN_ERROR, SQLSTATE_UNKNOWN, 0,
pvio->set_error(pvio, CR_NAMEDPIPEOPEN_ERROR, SQLSTATE_UNKNOWN, 0,
cinfo->host, cinfo->unix_socket, GetLastError());
goto end;
}
if (has_timedout || !WaitNamedPipe(szPipeName, cio->timeout[CIO_CONNECT_TIMEOUT]))
if (has_timedout || !WaitNamedPipe(szPipeName, pvio->timeout[PVIO_CONNECT_TIMEOUT]))
{
cio->set_error(cio, CR_NAMEDPIPEWAIT_ERROR, SQLSTATE_UNKNOWN, 0,
pvio->set_error(pvio, CR_NAMEDPIPEWAIT_ERROR, SQLSTATE_UNKNOWN, 0,
cinfo->host, cinfo->unix_socket, GetLastError());
goto end;
}
@@ -263,7 +261,7 @@ my_bool cio_npipe_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo)
dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
if (!SetNamedPipeHandleState(cpipe->pipe, &dwMode, NULL, NULL))
{
cio->set_error(cio, CR_NAMEDPIPESETSTATE_ERROR, SQLSTATE_UNKNOWN, 0,
pvio->set_error(pvio, CR_NAMEDPIPESETSTATE_ERROR, SQLSTATE_UNKNOWN, 0,
cinfo->host, cinfo->unix_socket, (ulong) GetLastError());
goto end;
}
@@ -271,7 +269,7 @@ my_bool cio_npipe_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo)
/* Register event handler for overlapped IO */
if (!(cpipe->overlapped.hEvent= CreateEvent(NULL, FALSE, FALSE, NULL)))
{
cio->set_error(cio, CR_EVENT_CREATE_FAILED, SQLSTATE_UNKNOWN, 0,
pvio->set_error(pvio, CR_EVENT_CREATE_FAILED, SQLSTATE_UNKNOWN, 0,
GetLastError());
goto end;
}
@@ -283,42 +281,42 @@ end:
if (cpipe->pipe != INVALID_HANDLE_VALUE)
CloseHandle(cpipe->pipe);
my_free((gptr)cpipe, MYF(0));
cio->data= NULL;
pvio->data= NULL;
}
return 1;
}
my_bool cio_npipe_close(MARIADB_CIO *cio)
my_bool pvio_npipe_close(MARIADB_PVIO *pvio)
{
struct st_cio_npipe *cpipe= NULL;
struct st_pvio_npipe *cpipe= NULL;
int r= 0;
if (!cio)
if (!pvio)
return 1;
if (cio->data)
if (pvio->data)
{
cpipe= (struct st_cio_npipe *)cio->data;
cpipe= (struct st_pvio_npipe *)pvio->data;
CloseHandle(cpipe->overlapped.hEvent);
if (cpipe->pipe != INVALID_HANDLE_VALUE)
{
CloseHandle(cpipe->pipe);
cpipe->pipe= INVALID_HANDLE_VALUE;
}
my_free((gptr)cio->data, MYF(0));
cio->data= NULL;
my_free((gptr)pvio->data, MYF(0));
pvio->data= NULL;
}
return r;
}
my_socket cio_npipe_get_socket(MARIADB_CIO *cio)
my_socket pvio_npipe_get_socket(MARIADB_PVIO *pvio)
{
if (cio && cio->data)
return (my_socket)((struct st_cio_npipe *)cio->data)->pipe;
if (pvio && pvio->data)
return (my_socket)((struct st_pvio_npipe *)pvio->data)->pipe;
return INVALID_SOCKET;
}
my_bool cio_npipe_is_blocking(MARIADB_CIO *cio)
my_bool pvio_npipe_is_blocking(MARIADB_PVIO *pvio)
{
return 1;
}

446
plugins/pvio/pvio_shmem.c Normal file
View File

@@ -0,0 +1,446 @@
/************************************************************************************
Copyright (C) 2015 Georg Richter and 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 <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
/* MariaDB virtual IO plugin for Windows shared memory communication */
#ifdef _WIN32
#include <my_global.h>
#include <my_sys.h>
#include <errmsg.h>
#include <mysql.h>
#include <mysql/client_plugin.h>
#include <string.h>
#include <m_string.h>
#ifdef HAVE_SHMEM_DYNAMIC
#define my_malloc(A, B) malloc((A))
#undef my_free
#define my_free(A,B) free(((A)))
#endif
#define SHM_DEFAULT_NAME "MYSQL"
#define PVIO_SHM_BUFFER_SIZE 16000 + 4
my_bool pvio_shm_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout);
int pvio_shm_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type);
size_t pvio_shm_read(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
size_t pvio_shm_write(MARIADB_PVIO *pvio, uchar *buffer, size_t length);
int pvio_shm_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout);
my_bool pvio_shm_blocking(MARIADB_PVIO *pvio, my_bool value, my_bool *old_value);
my_bool pvio_shm_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo);
my_bool pvio_shm_close(MARIADB_PVIO *pvio);
struct st_ma_pvio_methods pvio_shm_methods= {
pvio_shm_set_timeout,
pvio_shm_get_timeout,
pvio_shm_read,
NULL,
pvio_shm_write,
NULL,
pvio_shm_wait_io_or_timeout,
pvio_shm_blocking,
pvio_shm_connect,
pvio_shm_close,
NULL,
NULL,
NULL,
NULL,
NULL
};
#ifndef HAVE_SHMEM_DYNAMIC
MARIADB_PVIO_PLUGIN pvio_shmem_plugin=
#else
MARIADB_PVIO_PLUGIN _mysql_client_plugin_declaration_=
#endif
{
MARIADB_CLIENT_PVIO_PLUGIN,
MARIADB_CLIENT_PVIO_PLUGIN_INTERFACE_VERSION,
"pvio_shmem",
"Georg Richter",
"MariaDB virtual IO plugin for Windows shared memory communication",
{1, 0, 0},
"LGPPL",
NULL,
NULL,
&pvio_shm_methods,
};
enum enum_shm_events
{
PVIO_SHM_SERVER_WROTE= 0,
PVIO_SHM_SERVER_READ,
PVIO_SHM_CLIENT_WROTE,
PVIO_SHM_CLIENT_READ,
PVIO_SHM_CONNECTION_CLOSED
};
typedef struct {
HANDLE event[5];
HANDLE file_map;
LPVOID *map;
char *read_pos;
size_t buffer_size;
} PVIO_SHM;
char *StrEvent[]= {"SERVER_WROTE", "SERVER_READ", "CLIENT_WROTE", "CLIENT_READ", "CONNECTION_CLOSED"};
struct st_pvio_shm {
char *shm_name;
};
my_bool pvio_shm_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout)
{
if (!pvio)
return 1;
pvio->timeout[type]= (timeout > 0) ? timeout * 1000 : INFINITE;
return 0;
}
int pvio_shm_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type)
{
if (!pvio)
return -1;
return pvio->timeout[type] / 1000;
}
size_t pvio_shm_read(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
{
PVIO_SHM *pvio_shm= (PVIO_SHM *)pvio->data;
size_t copy_size= length;
HANDLE events[2];
if (!pvio_shm)
return -1;
/* we need to wait for write and close events */
if (!pvio_shm->buffer_size)
{
events[0]= pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED];
events[1]= pvio_shm->event[PVIO_SHM_SERVER_WROTE];
switch(WaitForMultipleObjects(2, events, 0, pvio->timeout[PVIO_READ_TIMEOUT]))
{
case WAIT_OBJECT_0: /* server closed connection */
SetLastError(ERROR_GRACEFUL_DISCONNECT);
return -1;
case WAIT_OBJECT_0 +1: /* server_wrote event */
break;
case WAIT_TIMEOUT:
SetLastError(ETIMEDOUT);
default:
return -1;
}
/* server sent data */
pvio_shm->read_pos= pvio_shm->map;
pvio_shm->buffer_size= uint4korr(pvio_shm->read_pos);
pvio_shm->read_pos+= 4;
}
if (pvio_shm->buffer_size < copy_size)
copy_size= pvio_shm->buffer_size;
if (copy_size)
{
memcpy(buffer, pvio_shm->read_pos, pvio_shm->buffer_size);
pvio_shm->read_pos+= copy_size;
pvio_shm->buffer_size-= copy_size;
}
/* we need to read again */
if (!pvio_shm->buffer_size)
if (!SetEvent(pvio_shm->event[PVIO_SHM_CLIENT_READ]))
return -1;
return copy_size;
}
size_t pvio_shm_write(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
{
HANDLE events[2];
PVIO_SHM *pvio_shm= (PVIO_SHM *)pvio->data;
size_t bytes_to_write= length;
uchar *buffer_pos= buffer;
if (!pvio_shm)
return -1;
events[0]= pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED];
events[1]= pvio_shm->event[PVIO_SHM_SERVER_READ];
while (bytes_to_write)
{
size_t pkt_length;
switch (WaitForMultipleObjects(2, events, 0, pvio->timeout[PVIO_WRITE_TIMEOUT])) {
case WAIT_OBJECT_0: /* connection closed */
SetLastError(ERROR_GRACEFUL_DISCONNECT);
return -1;
case WAIT_OBJECT_0 + 1: /* server_read */
break;
case WAIT_TIMEOUT:
SetLastError(ETIMEDOUT);
default:
return -1;
}
pkt_length= MIN(PVIO_SHM_BUFFER_SIZE, length);
int4store(pvio_shm->map, pkt_length);
memcpy((uchar *)pvio_shm->map + 4, buffer_pos, length);
buffer_pos+= length;
bytes_to_write-= length;
if (!SetEvent(pvio_shm->event[PVIO_SHM_CLIENT_WROTE]))
return -1;
}
return length;
}
int pvio_shm_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout)
{
}
my_bool pvio_shm_blocking(MARIADB_PVIO *pvio, my_bool block, my_bool *previous_mode)
{
/* not supported */
return 0;
}
int pvio_shm_keepalive(MARIADB_PVIO *pvio)
{
/* not supported */
return 0;
}
int pvio_shm_fast_send(MARIADB_PVIO *pvio)
{
/* not supported */
return 0;
}
my_bool pvio_shm_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
{
char *base_memory_name;
char *prefixes[]= {"", "Global\\", NULL};
char *shm_name, *shm_suffix, *shm_prefix;
uchar i= 0;
int len;
DWORD cid;
char connection_id[28];
char *connection_id_str;
DWORD dwDesiredAccess= EVENT_MODIFY_STATE | SYNCHRONIZE;
HANDLE hdlConnectRequest= NULL,
hdlConnectRequestAnswer= NULL,
file_map= NULL;
LPVOID map= NULL;
PVIO_SHM *pvio_shm= (PVIO_SHM*)LocalAlloc(LMEM_ZEROINIT, sizeof(PVIO_SHM));
if (!pvio_shm)
{
PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0, "");
return 0;
}
/* MariaDB server constructs the event name as follows:
"Global\\base_memory_name" or
"\\base_memory_name"
*/
base_memory_name= (cinfo->mysql->options.shared_memory_base_name) ?
cinfo->mysql->options.shared_memory_base_name : SHM_DEFAULT_NAME;
if (!(shm_name= LocalAlloc(LMEM_ZEROINIT, strlen(base_memory_name) + 40)))
{
PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0, "");
goto error;
}
/* iterate through prefixes */
while (prefixes[i])
{
len= sprintf(shm_name, "%s%s_", prefixes[i], base_memory_name);
shm_suffix= shm_name + len;
strcpy(shm_suffix, "CONNECT_REQUEST");
if ((hdlConnectRequest= OpenEvent(dwDesiredAccess, 0, shm_name)))
{
/* save prefix to prevent further loop */
shm_prefix= prefixes[i];
break;
}
i++;
}
if (!hdlConnectRequest)
{
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Opening CONNECT_REQUEST event failed", GetLastError());
goto error;
}
strcpy(shm_suffix, "CONNECT_ANSWER");
if (!(hdlConnectRequestAnswer= OpenEvent(dwDesiredAccess, 0, shm_name)))
{
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Opening CONNECT_ANSWER event failed", GetLastError());
goto error;
}
/* get connection id, so we can build the filename used for connection */
strcpy(shm_suffix, "CONNECT_DATA");
if (!(file_map= OpenFileMapping(FILE_MAP_WRITE, 0, shm_name)))
{
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "OpenFileMapping failed", GetLastError());
goto error;
}
/* try to get first 4 bytes, which represents connection_id */
if (!(map= MapViewOfFile(file_map, FILE_MAP_WRITE, 0, 0, sizeof(cid))))
{
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Reading connection_id failed", GetLastError());
goto error;
}
/* notify server */
if (!SetEvent(hdlConnectRequest))
{
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Failed sending connection request", GetLastError());
goto error;
}
/* Wait for server answer */
switch(WaitForSingleObject(hdlConnectRequestAnswer, pvio->timeout[PVIO_CONNECT_TIMEOUT])) {
case WAIT_ABANDONED:
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Mutex was not released in time", GetLastError());
goto error;
break;
case WAIT_FAILED:
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Operation wait failed", GetLastError());
goto error;
break;
case WAIT_TIMEOUT:
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Operation timed out", GetLastError());
goto error;
break;
case WAIT_OBJECT_0:
break;
default:
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Wait for server failed", GetLastError());
break;
}
cid= uint4korr(map);
len= sprintf(shm_name, "%s%s_%d_", shm_prefix, base_memory_name, cid);
shm_suffix= shm_name + len;
strcpy(shm_suffix, "DATA");
pvio_shm->file_map= OpenFileMapping(FILE_MAP_WRITE, 0, shm_name);
if (pvio_shm->file_map == NULL)
{
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "OpenFileMapping failed", GetLastError());
goto error;
}
if (!(pvio_shm->map= MapViewOfFile(pvio_shm->file_map, FILE_MAP_WRITE, 0, 0, PVIO_SHM_BUFFER_SIZE)))
{
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "MapViewOfFile failed", GetLastError());
goto error;
}
for (i=0; i < 5; i++)
{
strcpy(shm_suffix, StrEvent[i]);
if (!(pvio_shm->event[i]= OpenEvent(dwDesiredAccess, 0, shm_name)))
{
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, unknown_sqlstate, 0, "Couldn't create event", GetLastError());
goto error;
}
}
/* we will first read from server */
SetEvent(pvio_shm->event[PVIO_SHM_SERVER_READ]);
error:
if (hdlConnectRequest)
CloseHandle(hdlConnectRequest);
if (hdlConnectRequestAnswer)
CloseHandle(hdlConnectRequestAnswer);
if (shm_name)
LocalFree(shm_name);
if (map)
UnmapViewOfFile(map);
if (file_map)
CloseHandle(file_map);
if (pvio_shm)
{
/* check if all events are set */
if (pvio_shm->event[4])
{
pvio->data= (void *)pvio_shm;
pvio->mysql= cinfo->mysql;
pvio->type= cinfo->type;
pvio_shm->read_pos= pvio_shm->map;
pvio->mysql->net.pvio= pvio;
return 0;
}
for (i=0;i < 5; i++)
if (pvio_shm->event[i])
CloseHandle(pvio_shm->event[i]);
if (pvio_shm->map)
UnmapViewOfFile(pvio_shm->map);
if (pvio_shm->file_map)
CloseHandle(pvio_shm->file_map);
LocalFree(pvio_shm);
}
return 1;
}
my_bool pvio_shm_close(MARIADB_PVIO *pvio)
{
PVIO_SHM *pvio_shm= (PVIO_SHM *)pvio->data;
int i;
if (!pvio_shm)
return 1;
/* notify server */
SetEvent(pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED]);
UnmapViewOfFile(pvio_shm->map);
CloseHandle(pvio_shm->file_map);
for (i=0; i < 5; i++)
CloseHandle(pvio_shm->event[i]);
LocalFree(pvio_shm);
pvio->data= NULL;
return 0;
}
my_socket pvio_shm_get_socket(MARIADB_PVIO *pvio)
{
}
my_bool pvio_shm_is_blocking(MARIADB_PVIO *pvio)
{
return 1;
}
#endif

View File

@@ -18,7 +18,7 @@
*************************************************************************************/
/*
MariaDB Communication IO (CIO) plugin for socket communication:
MariaDB virtual IO plugin for socket communication:
The plugin handles connections via unix and network sockets. it is enabled by
default and compiled into Connector/C.
@@ -61,150 +61,149 @@
/* Function prototypes */
my_bool cio_socket_set_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type, int timeout);
int cio_socket_get_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type);
size_t cio_socket_read(MARIADB_CIO *cio, const uchar *buffer, size_t length);
size_t cio_socket_async_read(MARIADB_CIO *cio, const uchar *buffer, size_t length);
size_t cio_socket_write(MARIADB_CIO *cio, const uchar *buffer, size_t length);
size_t cio_socket_async_write(MARIADB_CIO *cio, const uchar *buffer, size_t length);
int cio_socket_wait_io_or_timeout(MARIADB_CIO *cio, my_bool is_read, int timeout);
my_bool cio_socket_blocking(MARIADB_CIO *cio, my_bool value, my_bool *old_value);
my_bool cio_socket_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo);
my_bool cio_socket_close(MARIADB_CIO *cio);
int cio_socket_fast_send(MARIADB_CIO *cio);
int cio_socket_keepalive(MARIADB_CIO *cio);
my_bool cio_socket_get_handle(MARIADB_CIO *cio, void *handle);
my_bool cio_socket_is_blocking(MARIADB_CIO *cio);
my_bool cio_socket_is_alive(MARIADB_CIO *cio);
my_bool pvio_socket_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout);
int pvio_socket_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type);
size_t pvio_socket_read(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
size_t pvio_socket_async_read(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
size_t pvio_socket_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
size_t pvio_socket_async_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
int pvio_socket_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout);
my_bool pvio_socket_blocking(MARIADB_PVIO *pvio, my_bool value, my_bool *old_value);
my_bool pvio_socket_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo);
my_bool pvio_socket_close(MARIADB_PVIO *pvio);
int pvio_socket_fast_send(MARIADB_PVIO *pvio);
int pvio_socket_keepalive(MARIADB_PVIO *pvio);
my_bool pvio_socket_get_handle(MARIADB_PVIO *pvio, void *handle);
my_bool pvio_socket_is_blocking(MARIADB_PVIO *pvio);
my_bool pvio_socket_is_alive(MARIADB_PVIO *pvio);
static int cio_socket_init(char *unused1,
static int pvio_socket_init(char *unused1,
size_t unused2,
int unused3,
va_list);
static int cio_socket_end(void);
static int pvio_socket_end(void);
struct st_ma_cio_methods cio_socket_methods= {
cio_socket_set_timeout,
cio_socket_get_timeout,
cio_socket_read,
cio_socket_async_read,
cio_socket_write,
cio_socket_async_write,
cio_socket_wait_io_or_timeout,
cio_socket_blocking,
cio_socket_connect,
cio_socket_close,
cio_socket_fast_send,
cio_socket_keepalive,
cio_socket_get_handle,
cio_socket_is_blocking,
cio_socket_is_alive
struct st_ma_pvio_methods pvio_socket_methods= {
pvio_socket_set_timeout,
pvio_socket_get_timeout,
pvio_socket_read,
pvio_socket_async_read,
pvio_socket_write,
pvio_socket_async_write,
pvio_socket_wait_io_or_timeout,
pvio_socket_blocking,
pvio_socket_connect,
pvio_socket_close,
pvio_socket_fast_send,
pvio_socket_keepalive,
pvio_socket_get_handle,
pvio_socket_is_blocking,
pvio_socket_is_alive
};
#ifndef HAVE_SOCKET_DYNAMIC
MARIADB_CIO_PLUGIN cio_socket_plugin=
MARIADB_PVIO_PLUGIN pvio_socket_plugin=
#else
MARIADB_CIO_PLUGIN _mysql_client_plugin_declare_
MARIADB_PVIO_PLUGIN _mysql_client_plugin_declare_
#endif
{
MARIADB_CLIENT_CIO_PLUGIN,
MARIADB_CLIENT_CIO_PLUGIN_INTERFACE_VERSION,
"cio_socket",
MARIADB_CLIENT_PVIO_PLUGIN,
MARIADB_CLIENT_PVIO_PLUGIN_INTERFACE_VERSION,
"pvio_socket",
"Georg Richter",
"MariaDB communication IO plugin for socket communication",
"MariaDB virtual IO plugin for socket communication",
{1, 0, 0},
"LGPL",
&cio_socket_init,
&cio_socket_end,
&cio_socket_methods
&pvio_socket_init,
&pvio_socket_end,
&pvio_socket_methods
};
struct st_cio_socket {
struct st_pvio_socket {
my_socket socket;
int fcntl_mode;
MYSQL *mysql;
};
static my_bool cio_socket_initialized= FALSE;
static my_bool pvio_socket_initialized= FALSE;
static int cio_socket_init(char *errmsg,
static int pvio_socket_init(char *errmsg,
size_t errmsg_length,
int unused,
va_list va)
{
cio_socket_initialized= TRUE;
pvio_socket_initialized= TRUE;
return 0;
}
static int cio_socket_end(void)
static int pvio_socket_end(void)
{
if (!cio_socket_initialized)
if (!pvio_socket_initialized)
return 1;
return 0;
}
/* {{{ cio_socket_set_timeout */
/* {{{ pvio_socket_set_timeout */
/*
set timeout value
SYNOPSIS
cio_socket_set_timeout
cio CIO
pvio_socket_set_timeout
pvio PVIO
type timeout type (connect, read, write)
timeout timeout in seconds
DESCRIPTION
Sets timeout values for connection-, read or write time out.
CIO internally stores all timeout values in milliseconds, but
PVIO internally stores all timeout values in milliseconds, but
accepts and returns all time values in seconds (like api does).
RETURNS
0 Success
1 Error
*/
my_bool cio_socket_set_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type, int timeout)
my_bool pvio_socket_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout)
{
if (!cio)
if (!pvio)
return 1;
cio->timeout[type]= (timeout > 0) ? timeout * 1000 : -1;
pvio->timeout[type]= (timeout > 0) ? timeout * 1000 : -1;
return 0;
}
/* }}} */
/* {{{ cio_socket_get_timeout */
/* {{{ pvio_socket_get_timeout */
/*
get timeout value
SYNOPSIS
cio_socket_get_timeout
cio CIO
pvio_socket_get_timeout
pvio PVIO
type timeout type (connect, read, write)
DESCRIPTION
Returns timeout values for connection-, read or write time out.
CIO internally stores all timeout values in milliseconds, but
PVIO internally stores all timeout values in milliseconds, but
accepts and returns all time values in seconds (like api does).
RETURNS
0...n time out value
-1 error
*/
int cio_socket_get_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type)
int pvio_socket_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type)
{
if (!cio)
if (!pvio)
return -1;
return cio->timeout[type] / 1000;
return pvio->timeout[type] / 1000;
}
/* }}} */
/* {{{ cio_socket_read */
/* {{{ pvio_socket_read */
/*
read from socket
SYNOPSIS
cio_socket_read()
cio CIO
pvio_socket_read()
pvio PVIO
buffer read buffer
length buffer length
@@ -218,7 +217,7 @@ int cio_socket_get_timeout(MARIADB_CIO *cio, enum enum_cio_timeout type)
-1 on error
*/
size_t cio_socket_read(MARIADB_CIO *cio, const uchar *buffer, size_t length)
size_t pvio_socket_read(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
{
ssize_t r= -1;
#ifndef _WIN32
@@ -229,12 +228,12 @@ size_t cio_socket_read(MARIADB_CIO *cio, const uchar *buffer, size_t length)
int read_flags= MSG_NOSIGNAL;
#endif
#endif
struct st_cio_socket *csock= NULL;
struct st_pvio_socket *csock= NULL;
if (!cio || !cio->data)
if (!pvio || !pvio->data)
return -1;
csock= (struct st_cio_socket *)cio->data;
csock= (struct st_pvio_socket *)pvio->data;
#ifndef _WIN32
do {
@@ -242,9 +241,9 @@ size_t cio_socket_read(MARIADB_CIO *cio, const uchar *buffer, size_t length)
} while (r == -1 && errno == EINTR);
while (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)
&& cio->timeout[CIO_READ_TIMEOUT] > 0)
&& pvio->timeout[PVIO_READ_TIMEOUT] > 0)
{
if (cio_socket_wait_io_or_timeout(cio, TRUE, cio->timeout[CIO_READ_TIMEOUT]) < 1)
if (pvio_socket_wait_io_or_timeout(pvio, TRUE, pvio->timeout[PVIO_READ_TIMEOUT]) < 1)
return -1;
do {
r= recv(csock->socket, (void *)buffer, length, read_flags);
@@ -274,13 +273,13 @@ size_t cio_socket_read(MARIADB_CIO *cio, const uchar *buffer, size_t length)
}
/* }}} */
/* {{{ cio_socket_async_read */
/* {{{ pvio_socket_async_read */
/*
read from socket
SYNOPSIS
cio_socket_async_read()
cio CIO
pvio_socket_async_read()
pvio PVIO
buffer read buffer
length buffer length
@@ -294,7 +293,7 @@ size_t cio_socket_read(MARIADB_CIO *cio, const uchar *buffer, size_t length)
-1 on error
*/
size_t cio_socket_async_read(MARIADB_CIO *cio, const uchar *buffer, size_t length)
size_t pvio_socket_async_read(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
{
ssize_t r= -1;
#ifndef _WIN32
@@ -304,12 +303,12 @@ size_t cio_socket_async_read(MARIADB_CIO *cio, const uchar *buffer, size_t lengt
int read_flags= MSG_NOSIGNAL | MSG_DONTWAIT;
#endif
#endif
struct st_cio_socket *csock= NULL;
struct st_pvio_socket *csock= NULL;
if (!cio || !cio->data)
if (!pvio || !pvio->data)
return -1;
csock= (struct st_cio_socket *)cio->data;
csock= (struct st_pvio_socket *)pvio->data;
#ifndef _WIN32
r= recv(csock->socket,(void *)buffer, length, read_flags);
@@ -320,13 +319,13 @@ size_t cio_socket_async_read(MARIADB_CIO *cio, const uchar *buffer, size_t lengt
}
/* }}} */
/* {{{ cio_socket_async_write */
/* {{{ pvio_socket_async_write */
/*
write to socket
SYNOPSIS
cio_socket_async_write()
cio CIO
pvio_socket_async_write()
pvio PVIO
buffer read buffer
length buffer length
@@ -340,7 +339,7 @@ size_t cio_socket_async_read(MARIADB_CIO *cio, const uchar *buffer, size_t lengt
-1 on error
*/
size_t cio_socket_async_write(MARIADB_CIO *cio, const uchar *buffer, size_t length)
size_t pvio_socket_async_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
{
ssize_t r= -1;
#ifndef _WIN32
@@ -350,12 +349,12 @@ size_t cio_socket_async_write(MARIADB_CIO *cio, const uchar *buffer, size_t leng
int write_flags= MSG_NOSIGNAL | MSG_DONTWAIT;
#endif
#endif
struct st_cio_socket *csock= NULL;
struct st_pvio_socket *csock= NULL;
if (!cio || !cio->data)
if (!pvio || !pvio->data)
return -1;
csock= (struct st_cio_socket *)cio->data;
csock= (struct st_pvio_socket *)pvio->data;
#ifndef WIN32
r= send(csock->socket, buffer, length, write_flags);
@@ -366,13 +365,13 @@ size_t cio_socket_async_write(MARIADB_CIO *cio, const uchar *buffer, size_t leng
}
/* }}} */
/* {{{ cio_socket_write */
/* {{{ pvio_socket_write */
/*
write to socket
SYNOPSIS
cio_socket_write()
cio CIO
pvio_socket_write()
pvio PVIO
buffer read buffer
length buffer length
@@ -386,7 +385,7 @@ size_t cio_socket_async_write(MARIADB_CIO *cio, const uchar *buffer, size_t leng
-1 on error
*/
size_t cio_socket_write(MARIADB_CIO *cio, const uchar *buffer, size_t length)
size_t pvio_socket_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
{
ssize_t r= -1;
#ifndef _WIN32
@@ -396,11 +395,11 @@ size_t cio_socket_write(MARIADB_CIO *cio, const uchar *buffer, size_t length)
int send_flags= MSG_NOSIGNAL | MSG_DONTWAIT;
#endif
#endif
struct st_cio_socket *csock= NULL;
if (!cio || !cio->data)
struct st_pvio_socket *csock= NULL;
if (!pvio || !pvio->data)
return -1;
csock= (struct st_cio_socket *)cio->data;
csock= (struct st_pvio_socket *)pvio->data;
#ifndef _WIN32
do {
@@ -408,9 +407,9 @@ size_t cio_socket_write(MARIADB_CIO *cio, const uchar *buffer, size_t length)
} while (r == -1 && errno == EINTR);
while (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
cio->timeout[CIO_WRITE_TIMEOUT] != 0)
pvio->timeout[PVIO_WRITE_TIMEOUT] != 0)
{
if (cio_socket_wait_io_or_timeout(cio, FALSE, cio->timeout[CIO_WRITE_TIMEOUT]) < 1)
if (pvio_socket_wait_io_or_timeout(pvio, FALSE, pvio->timeout[PVIO_WRITE_TIMEOUT]) < 1)
return -1;
do {
r= send(csock->socket, buffer, length, send_flags);
@@ -436,10 +435,10 @@ size_t cio_socket_write(MARIADB_CIO *cio, const uchar *buffer, size_t length)
}
/* }}} */
int cio_socket_wait_io_or_timeout(MARIADB_CIO *cio, my_bool is_read, int timeout)
int pvio_socket_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout)
{
int rc;
struct st_cio_socket *csock= NULL;
struct st_pvio_socket *csock= NULL;
#ifndef _WIN32
struct pollfd p_fd;
@@ -448,10 +447,10 @@ int cio_socket_wait_io_or_timeout(MARIADB_CIO *cio, my_bool is_read, int timeout
fd_set fds, exc_fds;
#endif
if (!cio || !cio->data)
if (!pvio || !pvio->data)
return 0;
csock= (struct st_cio_socket *)cio->data;
csock= (struct st_pvio_socket *)pvio->data;
{
#ifndef _WIN32
memset(&p_fd, 0, sizeof(p_fd));
@@ -490,16 +489,16 @@ int cio_socket_wait_io_or_timeout(MARIADB_CIO *cio, my_bool is_read, int timeout
return rc;
}
my_bool cio_socket_blocking(MARIADB_CIO *cio, my_bool block, my_bool *previous_mode)
my_bool pvio_socket_blocking(MARIADB_PVIO *pvio, my_bool block, my_bool *previous_mode)
{
int *sd_flags, save_flags;
my_bool tmp;
struct st_cio_socket *csock= NULL;
struct st_pvio_socket *csock= NULL;
if (!cio || !cio->data)
if (!pvio || !pvio->data)
return 1;
csock= (struct st_cio_socket *)cio->data;
csock= (struct st_pvio_socket *)pvio->data;
sd_flags= &csock->fcntl_mode;
save_flags= csock->fcntl_mode;
@@ -539,22 +538,22 @@ my_bool cio_socket_blocking(MARIADB_CIO *cio, my_bool block, my_bool *previous_m
return 0;
}
static int cio_socket_internal_connect(MARIADB_CIO *cio,
static int pvio_socket_internal_connect(MARIADB_PVIO *pvio,
const struct sockaddr *name,
size_t namelen)
{
int rc= 0;
struct st_cio_socket *csock= NULL;
struct st_pvio_socket *csock= NULL;
int timeout;
if (!cio || !cio->data)
if (!pvio || !pvio->data)
return 1;
csock= (struct st_cio_socket *)cio->data;
timeout= cio->timeout[CIO_CONNECT_TIMEOUT];
csock= (struct st_pvio_socket *)pvio->data;
timeout= pvio->timeout[PVIO_CONNECT_TIMEOUT];
/* set non blocking */
cio_socket_blocking(cio, 0, 0);
pvio_socket_blocking(pvio, 0, 0);
#ifndef _WIN32
do {
@@ -565,7 +564,7 @@ static int cio_socket_internal_connect(MARIADB_CIO *cio,
if (timeout != 0 && rc == -1 &&
(errno == EINPROGRESS || errno == EAGAIN))
{
rc= cio_socket_wait_io_or_timeout(cio, FALSE, timeout);
rc= pvio_socket_wait_io_or_timeout(pvio, FALSE, timeout);
if (rc < 1)
return -1;
{
@@ -591,7 +590,7 @@ static int cio_socket_internal_connect(MARIADB_CIO *cio,
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
if (cio_socket_wait_io_or_timeout(cio, FALSE, timeout) < 0)
if (pvio_socket_wait_io_or_timeout(pvio, FALSE, timeout) < 0)
return -1;
rc= 0;
}
@@ -601,15 +600,15 @@ static int cio_socket_internal_connect(MARIADB_CIO *cio,
return rc;
}
int cio_socket_keepalive(MARIADB_CIO *cio)
int pvio_socket_keepalive(MARIADB_PVIO *pvio)
{
int opt= 1;
struct st_cio_socket *csock= NULL;
struct st_pvio_socket *csock= NULL;
if (!cio || !cio->data)
if (!pvio || !pvio->data)
return 1;
csock= (struct st_cio_socket *)cio->data;
csock= (struct st_pvio_socket *)pvio->data;
return setsockopt(csock->socket, SOL_SOCKET, SO_KEEPALIVE,
#ifndef _WIN32
@@ -619,15 +618,15 @@ int cio_socket_keepalive(MARIADB_CIO *cio)
#endif
}
int cio_socket_fast_send(MARIADB_CIO *cio)
int pvio_socket_fast_send(MARIADB_PVIO *pvio)
{
int r= 0;
struct st_cio_socket *csock= NULL;
struct st_pvio_socket *csock= NULL;
if (!cio || !cio->data)
if (!pvio || !pvio->data)
return 1;
csock= (struct st_cio_socket *)cio->data;
csock= (struct st_pvio_socket *)pvio->data;
/* Setting IP_TOS is not recommended on Windows. See
http://msdn.microsoft.com/en-us/library/windows/desktop/ms738586(v=vs.85).aspx
@@ -656,59 +655,59 @@ int cio_socket_fast_send(MARIADB_CIO *cio)
}
static int
cio_socket_connect_sync_or_async(MARIADB_CIO *cio,
pvio_socket_connect_sync_or_async(MARIADB_PVIO *pvio,
const struct sockaddr *name, uint namelen)
{
MYSQL *mysql= cio->mysql;
MYSQL *mysql= pvio->mysql;
if (mysql->options.extension && mysql->options.extension->async_context &&
mysql->options.extension->async_context->active)
{
cio_socket_blocking(cio,0, 0);
return my_connect_async(cio, name, namelen, cio->timeout[CIO_CONNECT_TIMEOUT]);
pvio_socket_blocking(pvio,0, 0);
return my_connect_async(pvio, name, namelen, pvio->timeout[PVIO_CONNECT_TIMEOUT]);
}
return cio_socket_internal_connect(cio, name, namelen);
return pvio_socket_internal_connect(pvio, name, namelen);
}
my_bool cio_socket_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo)
my_bool pvio_socket_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
{
struct st_cio_socket *csock= NULL;
struct st_pvio_socket *csock= NULL;
if (!cio || !cinfo)
if (!pvio || !cinfo)
return 1;
if (!(csock= (struct st_cio_socket *)my_malloc(sizeof(struct st_cio_socket),
if (!(csock= (struct st_pvio_socket *)my_malloc(sizeof(struct st_pvio_socket),
MYF(MY_WME | MY_ZEROFILL))))
{
CIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0, "");
PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0, "");
return 1;
}
cio->data= (void *)csock;
pvio->data= (void *)csock;
csock->socket= -1;
cio->mysql= cinfo->mysql;
cio->type= cinfo->type;
pvio->mysql= cinfo->mysql;
pvio->type= cinfo->type;
if (cinfo->type == CIO_TYPE_UNIXSOCKET)
if (cinfo->type == PVIO_TYPE_UNIXSOCKET)
{
#ifndef _WIN32
#ifdef HAVE_SYS_UN_H
struct sockaddr_un UNIXaddr;
if ((csock->socket = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR)
{
CIO_SET_ERROR(cinfo->mysql, CR_SOCKET_CREATE_ERROR, unknown_sqlstate, 0, errno);
PVIO_SET_ERROR(cinfo->mysql, CR_SOCKET_CREATE_ERROR, unknown_sqlstate, 0, errno);
goto error;
}
bzero((char*) &UNIXaddr,sizeof(UNIXaddr));
UNIXaddr.sun_family = AF_UNIX;
strmov(UNIXaddr.sun_path, cinfo->unix_socket);
if (cio_socket_connect_sync_or_async(cio, (struct sockaddr *) &UNIXaddr,
if (pvio_socket_connect_sync_or_async(pvio, (struct sockaddr *) &UNIXaddr,
sizeof(UNIXaddr)))
{
CIO_SET_ERROR(cinfo->mysql, CR_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
PVIO_SET_ERROR(cinfo->mysql, CR_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_CONNECTION_ERROR), cinfo->unix_socket, socket_errno);
goto error;
}
if (cio_socket_blocking(cio, 1, 0) == SOCKET_ERROR)
if (pvio_socket_blocking(pvio, 1, 0) == SOCKET_ERROR)
{
goto error;
}
@@ -716,7 +715,7 @@ my_bool cio_socket_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo)
/* todo: error, not supported */
#endif
#endif
} else if (cinfo->type == CIO_TYPE_SOCKET)
} else if (cinfo->type == PVIO_TYPE_SOCKET)
{
struct addrinfo hints, *save_res= 0, *bind_res= 0, *res= 0, *bres= 0;
char server_port[NI_MAXSERV];
@@ -740,7 +739,7 @@ my_bool cio_socket_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo)
&hints, &res);
if (gai_rc != 0)
{
CIO_SET_ERROR(cinfo->mysql, CR_BIND_ADDR_FAILED, SQLSTATE_UNKNOWN,
PVIO_SET_ERROR(cinfo->mysql, CR_BIND_ADDR_FAILED, SQLSTATE_UNKNOWN,
CER(CR_BIND_ADDR_FAILED), cinfo->mysql->options.bind_address, gai_rc);
goto error;
}
@@ -749,7 +748,7 @@ my_bool cio_socket_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo)
gai_rc= getaddrinfo(cinfo->host, server_port, &hints, &res);
if (gai_rc != 0)
{
CIO_SET_ERROR(cinfo->mysql, CR_UNKNOWN_HOST, SQLSTATE_UNKNOWN,
PVIO_SET_ERROR(cinfo->mysql, CR_UNKNOWN_HOST, SQLSTATE_UNKNOWN,
ER(CR_UNKNOWN_HOST), cinfo->host, gai_rc);
if (bres)
freeaddrinfo(bres);
@@ -780,13 +779,13 @@ my_bool cio_socket_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo)
}
}
rc= cio_socket_connect_sync_or_async(cio, save_res->ai_addr, save_res->ai_addrlen);
rc= pvio_socket_connect_sync_or_async(pvio, save_res->ai_addr, save_res->ai_addrlen);
if (!rc)
{
/* if (mysql->options.extension && mysql->options.extension->async_context &&
mysql->options.extension->async_context->active)
break; */
if (cio_socket_blocking(cio, 1, 0) == SOCKET_ERROR)
if (pvio_socket_blocking(pvio, 1, 0) == SOCKET_ERROR)
{
closesocket(csock->socket);
continue;
@@ -800,7 +799,7 @@ my_bool cio_socket_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo)
if (csock->socket == SOCKET_ERROR)
{
CIO_SET_ERROR(cinfo->mysql, CR_IPSOCK_ERROR, SQLSTATE_UNKNOWN, ER(CR_IPSOCK_ERROR),
PVIO_SET_ERROR(cinfo->mysql, CR_IPSOCK_ERROR, SQLSTATE_UNKNOWN, ER(CR_IPSOCK_ERROR),
socket_errno);
goto error;
}
@@ -808,84 +807,84 @@ my_bool cio_socket_connect(MARIADB_CIO *cio, MA_CIO_CINFO *cinfo)
/* last call to connect 2 failed */
if (rc)
{
CIO_SET_ERROR(cinfo->mysql, CR_CONN_HOST_ERROR, SQLSTATE_UNKNOWN, ER(CR_CONN_HOST_ERROR),
PVIO_SET_ERROR(cinfo->mysql, CR_CONN_HOST_ERROR, SQLSTATE_UNKNOWN, ER(CR_CONN_HOST_ERROR),
cinfo->host, socket_errno);
goto error;
}
}
#ifdef _WIN32
/* apply timeouts */
if (cio->timeout[CIO_WRITE_TIMEOUT] > 0)
setsockopt(csock->socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&cio->timeout[CIO_WRITE_TIMEOUT], sizeof(int));
if (cio->timeout[CIO_READ_TIMEOUT] > 0)
setsockopt(csock->socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&cio->timeout[CIO_READ_TIMEOUT], sizeof(int));
if (pvio->timeout[PVIO_WRITE_TIMEOUT] > 0)
setsockopt(csock->socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&pvio->timeout[PVIO_WRITE_TIMEOUT], sizeof(int));
if (pvio->timeout[PVIO_READ_TIMEOUT] > 0)
setsockopt(csock->socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&pvio->timeout[PVIO_READ_TIMEOUT], sizeof(int));
#endif
return 0;
error:
if (cio->data)
if (pvio->data)
{
my_free((gptr)cio->data);
cio->data= NULL;
my_free((gptr)pvio->data);
pvio->data= NULL;
}
return 1;
}
/* {{{ my_bool cio_socket_close() */
my_bool cio_socket_close(MARIADB_CIO *cio)
/* {{{ my_bool pvio_socket_close() */
my_bool pvio_socket_close(MARIADB_PVIO *pvio)
{
struct st_cio_socket *csock= NULL;
struct st_pvio_socket *csock= NULL;
int r= 0;
if (!cio)
if (!pvio)
return 1;
if (cio->data)
if (pvio->data)
{
csock= (struct st_cio_socket *)cio->data;
csock= (struct st_pvio_socket *)pvio->data;
if (csock && csock->socket != -1)
{
r= shutdown(csock->socket ,2);
r= closesocket(csock->socket);
csock->socket= -1;
}
my_free((gptr)cio->data);
cio->data= NULL;
my_free((gptr)pvio->data);
pvio->data= NULL;
}
return r;
}
/* }}} */
/* {{{ my_socket cio_socket_get_handle */
my_bool cio_socket_get_handle(MARIADB_CIO *cio, void *handle)
/* {{{ my_socket pvio_socket_get_handle */
my_bool pvio_socket_get_handle(MARIADB_PVIO *pvio, void *handle)
{
if (cio && cio->data && handle)
if (pvio && pvio->data && handle)
{
*(my_socket *)handle= ((struct st_cio_socket *)cio->data)->socket;
*(my_socket *)handle= ((struct st_pvio_socket *)pvio->data)->socket;
return 0;
}
return 1;
}
/* }}} */
/* {{{ my_bool cio_socket_is_blocking(MARIADB_CIO *cio) */
my_bool cio_socket_is_blocking(MARIADB_CIO *cio)
/* {{{ my_bool pvio_socket_is_blocking(MARIADB_PVIO *pvio) */
my_bool pvio_socket_is_blocking(MARIADB_PVIO *pvio)
{
struct st_cio_socket *csock= NULL;
struct st_pvio_socket *csock= NULL;
my_bool r;
if (!cio || !cio->data)
if (!pvio || !pvio->data)
return 0;
csock= (struct st_cio_socket *)cio->data;
csock= (struct st_pvio_socket *)pvio->data;
r = !(csock->fcntl_mode & O_NONBLOCK);
return r;
}
/* }}} */
/* {{{ my_bool cio_socket_is_alive(MARIADB_CIO *cio) */
my_bool cio_socket_is_alive(MARIADB_CIO *cio)
/* {{{ my_bool pvio_socket_is_alive(MARIADB_PVIO *pvio) */
my_bool pvio_socket_is_alive(MARIADB_PVIO *pvio)
{
struct st_cio_socket *csock= NULL;
struct st_pvio_socket *csock= NULL;
#ifndef _WIN32
struct pollfd poll_fd;
#else
@@ -894,10 +893,10 @@ my_bool cio_socket_is_alive(MARIADB_CIO *cio)
#endif
int res;
if (!cio || !cio->data)
if (!pvio || !pvio->data)
return 0;
csock= (struct st_cio_socket *)cio->data;
csock= (struct st_pvio_socket *)pvio->data;
#ifndef _WIN32
memset(&poll_fd, 0, sizeof(struct pollfd));
poll_fd.events= POLLPRI | POLLIN;

View File

@@ -179,7 +179,7 @@ static void delete_trace_info(unsigned long thread_id)
unused4
DESCRIPTION
Init function registers a callback handler for CIO interface.
Init function registers a callback handler for PVIO interface.
RETURN
0 success
@@ -192,12 +192,12 @@ static int trace_init(char *errormsg,
void *func;
#ifdef WIN32
if (!(func= GetProcAddress(GetModuleHandle(NULL), "ma_cio_register_callback")))
if (!(func= GetProcAddress(GetModuleHandle(NULL), "ma_pvio_register_callback")))
#else
if (!(func= dlsym(RTLD_DEFAULT, "ma_cio_register_callback")))
if (!(func= dlsym(RTLD_DEFAULT, "ma_pvio_register_callback")))
#endif
{
strncpy(errormsg, "Can't find ma_cio_register_callback function", errormsg_size);
strncpy(errormsg, "Can't find ma_pvio_register_callback function", errormsg_size);
return 1;
}
register_callback= func;

View File

@@ -40,10 +40,9 @@ IF(WITH_SSL)
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)
EXECUTE_PROCESS(COMMAND "cat server-cert.pem client-cert.pem"
OUTPUT_FILE "ca-cert.pem"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs)
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})
ENDIF()
EXECUTE_PROCESS(COMMAND openssl x509 -in server-cert.pem -sha1 -fingerprint -noout

View File

@@ -1816,7 +1816,8 @@ static int test_ps_query_cache(MYSQL *mysql)
};
enum enum_test_ps_query_cache iteration;
diag("test needs to be fixed");
return SKIP;
/* prepare the table */
rc= mysql_query(mysql, "drop table if exists t1");
@@ -1895,7 +1896,7 @@ static int test_ps_query_cache(MYSQL *mysql)
check_stmt_rc(rc, stmt);
rc= mysql_stmt_execute(stmt);
check_stmt_rc(rc, stmt);
// test_ps_query_cache_result(1, "hh", 2, 2, "hh", 2, 1, "ii", 2);
test_ps_query_cache_result(1, "hh", 2, 2, "hh", 2, 1, "ii", 2);
r_metadata= mysql_stmt_result_metadata(stmt);
FAIL_UNLESS(r_metadata != NULL, "");
rc= mysql_stmt_fetch(stmt);

View File

@@ -404,7 +404,6 @@ static int test_conc50_3(MYSQL *my)
sprintf(query, "GRANT ALL ON %s.* TO 'ssltest'@'%' REQUIRE SSL", schema ? schema : "*");
rc= mysql_query(my, query);
check_mysql_rc(rc, my);
sprintf(query, "GRANT ALL ON %s.* TO 'ssltest'@'localhost' REQUIRE SSL", schema ? schema : "*");
rc= mysql_query(my, query);
check_mysql_rc(rc, my);
@@ -670,7 +669,7 @@ static int test_ssl_fp_list(MYSQL *unused)
FAIL_IF(!mysql_real_connect(my, hostname, ssluser, sslpw, schema,
port, socketname, 0), mysql_error(my));
cipher= mysql_get_ssl_cipher(my);
cipher= (char *)mysql_get_ssl_cipher(my);
FAIL_IF(cipher == NULL, "used cipher is NULL");
mysql_close(my);
return OK;
@@ -702,12 +701,15 @@ static int test_ssl_long_msg(MYSQL *unused)
rc= mysql_query(my, buffer);
check_mysql_rc(rc, my);
mysql_close(my);
return OK;
}
struct my_tests_st my_tests[] = {
{"test_ssl", test_ssl, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_ssl_long_msg", test_ssl_long_msg, TEST_CONNECTION_NEW, 0, NULL, NULL},
/* conc127 must be the first test, otherwise it will fail!! */
{"test_conc127", test_conc127, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_ssl_long_msg", test_ssl_long_msg, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_ssl_fp", test_ssl_fp, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_ssl_fp_list", test_ssl_fp_list, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_conc50", test_conc50, TEST_CONNECTION_NEW, 0, NULL, NULL},