diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c561338..3499d1dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,9 +21,7 @@ ENDIF() ### Options ### IF(NOT WIN32) OPTION(WITH_MYSQLCOMPAT "creates libmysql* symbolic links" ON) - OPTION(WITH_OPENSSL "enables SSL support" ON) ELSE() - OPTION(WITH_OPENSSL "enables SSL support" OFF) OPTION(WITH_SIGNCODE "digitally sign files" OFF) OPTION(WITH_RTC "enables run time checks for debug builds" OFF) ENDIF() @@ -112,9 +110,9 @@ ENDIF() IF(UNIX) SEARCH_LIBRARY(DEFAULT_LIB inet_ntoa "c") - IF(NOT DEFAULT_LIB) + # IF(NOT DEFAULT_LIB) SEARCH_LIBRARY(LIBNSL inet_ntoa "nsl_r;nsl") - ENDIF() + # ENDIF() SEARCH_LIBRARY(DEFAULT_LIB bind "c") IF(NOT DEFAULT_LIB) SEARCH_LIBRARY(LIBBIND bind "bind;socket") @@ -159,18 +157,35 @@ INCLUDE(${CMAKE_SOURCE_DIR}/cmake/CheckFunctions.cmake) # check for various types INCLUDE(${CMAKE_SOURCE_DIR}/cmake/CheckTypes.cmake) -# Check for OpenSSL -IF(WITH_OPENSSL) +IF(WITH_SSL STREQUAL "OPENSSL") FIND_PACKAGE(OpenSSL) IF(OPENSSL_FOUND) - ADD_DEFINITIONS(-DHAVE_OPENSSL) - INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR}) - SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES}) - IF(OPENSSL_CRYPTO_LIBRARIES) - SET(SSL_LIBRARIES ${SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES}) - ENDIF() + ADD_DEFINITIONS(-DHAVE_OPENSSL -DHAVE_SSL) + ADD_DEFINITIONS(-DSSL_PLUGIN=cio_openssl_plugin) + SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/plugins/builtin/cio_openssl.c") + SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES}) ELSE() - MESSAGE(FATAL_ERROR "OpenSSL not found. Please install OpenSSL or disable SSL support via option -DWITH_OPENSSL=Off") + MESSAGE(FATAL "OpenSSL not found") + ENDIF() +ENDIF() +IF(WITH_SSL STREQUAL "GNUTLS") + FIND_PACKAGE(GnuTLS) + IF(GNUTLS_FOUND) + ADD_DEFINITIONS(-DSSL_PLUGIN=cio_gnutls_plugin) + ADD_DEFINITIONS(-DHAVE_GNUTLS -DHAVE_SSL) + SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/plugins/builtin/cio_gnutls.c") + SET(SSL_LIBRARIES ${GNUTLS_LIBRARIES}) + ELSE() + MESSAGE(FATAL "GnuTLS not found") + ENDIF() +ENDIF() +IF(WIN32) + IF(WITH_SSL STREQUAL "SCHANNEL") + ADD_DEFINITIONS(-DSSL_PLUGIN=cio_schannel_plugin) + MESSAGE(STATUS "SSL_TYPE ${SSL_TYPE}") + ADD_DEFINITIONS(-DHAVE_SCHANNEL -DHAVE_SSL) + SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/plugins/builtin/cio_schannel.c" "${CMAKE_SOURCE_DIR}/plugins/builtin/ma_schannel.c") + INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/plugins/cio/") ENDIF() ENDIF() @@ -283,7 +298,7 @@ MESSAGE(STATUS "CPack generation: ${CPACK_GENERATOR}") IF(CLIENT_DOCS) MESSAGE(STATUS "Documentation included from ${CLIENT_DOCS}") ENDIF() -MESSAGE(STATUS "SSL support: ${WITH_OPENSSL}") +MESSAGE(STATUS "SSL support: ${WITH_SSL} Sources: ${SSL_SOURCES}") MESSAGE(STATUS "Experimental Sqlite support: ${WITH_SQLITE}") IF(WITH_EXTERNAL_ZLIB) MESSAGE(STATUS "Zlib support: ${WITH_EXTERNAL_ZLIB}") diff --git a/include/errmsg.h b/include/errmsg.h index 6bcf50ad..55c5a649 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -25,6 +25,7 @@ extern "C" { #endif void init_client_errs(void); extern const char *client_errors[]; /* Error messages */ +extern const char *mariadb_client_errors[]; /* Error messages */ #ifdef __cplusplus } #endif @@ -32,11 +33,10 @@ extern const char *client_errors[]; /* Error messages */ #define CR_MIN_ERROR 2000 /* For easier client code */ #define CR_MAX_ERROR 2999 -#if defined(OS2) && defined( MYSQL_SERVER) -#define CER(X) client_errors[(X)-CR_MIN_ERROR] -#else +#define CER_MIN_ERROR 5000 +#define CER_MAX_ERROR 5999 +#define CER(X) mariadb_client_errors[(X)-CER_MIN_ERROR] #define ER(X) client_errors[(X)-CR_MIN_ERROR] -#endif #define CLIENT_ERRMAP 2 /* Errormap used by my_error() */ #define CR_UNKNOWN_ERROR 2000 @@ -66,6 +66,11 @@ extern const char *client_errors[]; /* Error messages */ #define CR_PARAMS_NOT_BOUND 2031 #define CR_INVALID_PARAMETER_NO 2034 #define CR_UNSUPPORTED_PARAM_TYPE 2036 + +#define CR_SHARED_MEMORY_CONNECTION 2037 +#define CR_SHARED_MEMORY_CONNECT_ERROR 2038 + + #define CR_SECURE_AUTH 2049 #define CR_NO_DATA 2051 #define CR_NO_STMT_METADATA 2052 @@ -76,6 +81,9 @@ extern const char *client_errors[]; /* Error messages */ #define CR_ALREADY_CONNECTED 2059 #define CR_PLUGIN_FUNCTION_NOT_SUPPORTED 2060 +#define CR_EVENT_CREATE_FAILED 5000 +#define CR_BIND_ADDR_FAILED 5001 + #define SQLSTATE_UNKNOWN "HY000" #endif diff --git a/include/mysql.h b/include/mysql.h index 19856282..e2a10e69 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -251,7 +251,7 @@ struct st_mysql_options { my_bool compress,named_pipe; my_bool unused_1, unused_2, unused_3, unused_4; enum mysql_option methods_to_use; - char *client_ip; + char *bind_address; my_bool secure_auth; my_bool report_data_truncation; /* function pointers for local infile support */ diff --git a/include/mysql/client_plugin.h b/include/mysql/client_plugin.h index f0e04637..bcda3852 100644 --- a/include/mysql/client_plugin.h +++ b/include/mysql/client_plugin.h @@ -36,14 +36,17 @@ #endif /* known plugin types */ -#define MYSQL_CLIENT_DB_PLUGIN 0 -#define MYSQL_CLIENT_reserved 1 -#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2 -#define MYSQL_CLIENT_reserved22 3 +#define MYSQL_CLIENT_GENERIC_PLUGIN 0 +#define MYSQL_CLIENT_CIO_PLUGIN 1 /* communication IO */ +#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2 /* authentication */ +#define MYSQL_CLIENT_TRACE_PLUGIN 3 /* cio trace */ #define MYSQL_CLIENT_REMOTEIO_PLUGIN 4 #define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100 #define MYSQL_CLIENT_DB_PLUGIN_INTERFACE_VERSION 0x0100 +#define MYSQL_CLIENT_CIO_PLUGIN_INTERFACE_VERSION 0x0100 +#define MYSQL_CLIENT_SSL_INTERFACE_VERSION 0x0100 +#define MYSQL_CLIENT_TRACE_PLUGIN_INTERFACE_VERSION 0x01000 #define MYSQL_CLIENT_REMOTEIO_PLUGIN_INTERFACE_VERSION 0x0100 #define MYSQL_CLIENT_MAX_PLUGINS 5 @@ -63,9 +66,9 @@ const char *author; \ const char *desc; \ unsigned int version[3]; \ + const char *license; \ int (*init)(char *, size_t, int, va_list); \ - int (*deinit)(void); - + int (*deinit)(); struct st_mysql_client_plugin { MYSQL_CLIENT_PLUGIN_HEADER @@ -83,6 +86,18 @@ typedef struct st_mariadb_client_plugin_DB #define MARIADB_DB_DRIVER(a) ((a)->ext_db) +/******************* Communication IO plugin *****************/ +#include +#include + +typedef struct st_mariadb_client_plugin_CIO +{ + MYSQL_CLIENT_PLUGIN_HEADER + struct st_ma_cio_methods *methods; + struct st_ma_cio_ssl_methods *ssl_methods; + void *compress_methods; +} MARIADB_CIO_PLUGIN; + /******** authentication plugin specific declarations *********/ #include @@ -92,6 +107,11 @@ struct st_mysql_client_plugin_AUTHENTICATION int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql); }; +/******** trace plugin *******/ +struct st_mysql_client_plugin_TRACE +{ + MYSQL_CLIENT_PLUGIN_HEADER +}; /** type of the mysql_authentication_dialog_ask function diff --git a/include/mysql_async.h b/include/mysql_async.h index 298f3f57..60ec1a29 100644 --- a/include/mysql_async.h +++ b/include/mysql_async.h @@ -1,40 +1,37 @@ /* Copyright (C) 2012 MariaDB Services and Kristian Nielsen - 2015 MariaDB Corporation - 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 program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. - This library is distributed in the hope that it will be useful, + This program 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. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU 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, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Common definitions for MariaDB non-blocking client library. */ #ifndef MYSQL_ASYNC_H #define MYSQL_ASYNC_H -extern int my_connect_async(struct mysql_async_context *b, my_socket fd, +extern int my_connect_async(MARIADB_CIO *cio, const struct sockaddr *name, uint namelen, int vio_timeout); -extern ssize_t my_recv_async(struct mysql_async_context *b, int fd, - unsigned char *buf, size_t size, int timeout); -extern ssize_t my_send_async(struct mysql_async_context *b, int fd, +extern ssize_t my_recv_async(MARIADB_CIO *cio, + const unsigned char *buf, size_t size, int timeout); +extern ssize_t my_send_async(MARIADB_CIO *cio, const unsigned char *buf, size_t size, int timeout); extern my_bool my_io_wait_async(struct mysql_async_context *b, - enum enum_vio_io_event event, int timeout); -#ifdef HAVE_OPENSSL -extern int my_ssl_read_async(struct mysql_async_context *b, SSL *ssl, + enum enum_cio_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); -extern int my_ssl_write_async(struct mysql_async_context *b, SSL *ssl, +extern int my_ssl_write_async(struct mysql_async_context *b, MARIADB_SSL *ssl, const void *buf, int size); #endif diff --git a/include/mysql_com.h b/include/mysql_com.h index d4495571..b843dfe1 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -216,6 +216,8 @@ class Vio; /* Fill Vio class in C++ */ #else struct st_vio; /* Only C */ typedef struct st_vio Vio; +struct st_ma_cio; +typedef struct st_ma_cio MARIADB_CIO; #endif #endif @@ -233,7 +235,7 @@ typedef struct st_vio Vio; typedef struct st_net { - Vio *vio; + MARIADB_CIO *cio; unsigned char *buff; unsigned char *buff_end,*write_pos,*read_pos; my_socket fd; /* For Perl DBI/dbd */ @@ -324,7 +326,7 @@ extern unsigned long net_buffer_length; #define net_new_transaction(net) ((net)->pkt_nr=0) -int my_net_init(NET *net, Vio *vio); +int my_net_init(NET *net, MARIADB_CIO *cio); void net_end(NET *net); void net_clear(NET *net); int net_flush(NET *net); diff --git a/include/violite.h b/include/violite.h deleted file mode 100644 index cc66a775..00000000 --- a/include/violite.h +++ /dev/null @@ -1,167 +0,0 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -/* - * Vio Lite. - * Purpose: include file for Vio that will work with C and C++ - */ - -#ifndef vio_violite_h_ -#define vio_violite_h_ - - - -#include "my_net.h" /* needed because of struct in_addr */ - -#ifdef HAVE_VIO -#include /* Full VIO interface */ -#else - -#ifdef HAVE_OPENSSL -#include -#endif - -enum enum_vio_io_event -{ - VIO_IO_EVENT_READ, - VIO_IO_EVENT_WRITE, - VIO_IO_EVENT_CONNECT -}; - -/* Simple vio interface in C; The functions are implemented in violite.c */ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifndef Vio_defined -#define Vio_defined -struct st_vio; /* Only C */ -typedef struct st_vio Vio; -#endif - -#ifndef _WIN32 -#define HANDLE void * -#endif - -/* vio read-ahead cachine */ -#define VIO_CACHE_SIZE 16384 -#define VIO_CACHE_MIN_SIZE 2048 - -enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET, - VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL}; - -Vio* vio_new(my_socket sd, - enum enum_vio_type type, - my_bool localhost); -#ifdef _WIN32 -Vio* vio_new_win32pipe(HANDLE hPipe); -#endif -void vio_delete(Vio* vio); -void vio_reset(Vio* vio, enum enum_vio_type type, - my_socket sd, HANDLE hPipe, - my_bool localhost); - -/* - * vio_read and vio_write should have the same semantics - * as read(2) and write(2). - */ -size_t vio_read(Vio* vio, gptr buf, size_t size); -my_bool vio_read_peek(Vio *vio, size_t *bytes); -size_t vio_write(Vio* vio, const gptr buf, size_t size); -/* - * Whenever the socket is set to blocking mode or not. - */ -int vio_blocking( Vio* vio, - my_bool onoff, - my_bool *prevmode); -my_bool vio_is_blocking( Vio* vio); -/* - * setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible. - */ - int vio_fastsend( Vio* vio); -/* - * setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible. - */ -int vio_keepalive( Vio* vio, - my_bool onoff); -/* - * Whenever we should retry the last read/write operation. - */ -my_bool vio_should_retry( Vio* vio); -/* - * When the workday is over... - */ -int vio_close( Vio* vio); -/* - * Short text description of the socket for those, who are curious.. - */ -const char* vio_description( Vio* vio); - -/* Return the type of the connection */ - enum enum_vio_type vio_type(Vio* vio); - -/* set timeout */ -void vio_read_timeout(Vio *vio, uint seconds); -void vio_write_timeout(Vio *vio, uint seconds); - -/* Return last error number */ -int vio_errno(Vio *vio); - -/* Get socket number */ -my_socket vio_fd(Vio *vio); - -/* - * Remote peer's address and name in text form. - */ -my_bool vio_peer_addr(Vio * vio, char *buf); - -/* Remotes in_addr */ - -void vio_in_addr(Vio *vio, struct in_addr *in); - - /* Return 1 if there is data to be read */ -my_bool vio_poll_read(Vio *vio,uint timeout); -int vio_wait_or_timeout(Vio *vio, my_bool is_read, int timeout); - - -struct st_vio -{ - my_socket sd; /* my_socket - real or imaginary */ - HANDLE hPipe; - my_bool localhost; /* Are we from localhost? */ - int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */ - struct sockaddr_in local; /* Local internet address */ - struct sockaddr_in remote; /* Remote internet address */ - struct mysql_async_context *async_context; /* For non-blocking API */ - int write_timeout; - int read_timeout; - enum enum_vio_type type; /* Type of connection */ - char desc[30]; /* String description */ -#ifdef HAVE_OPENSSL - SSL *ssl; -#endif - uchar *cache; /* read-ahead cache to reduce reads (see CONC-79) */ - uchar *cache_pos; /* position of read-ahead cached data */ - size_t cache_size; /* <= VIO_CACHE_SIZE */ -}; - -#ifdef __cplusplus -} -#endif -#endif /* HAVE_VIO */ -#endif /* vio_violite_h_ */ diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index 3ea50db2..be2d3899 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -8,7 +8,9 @@ ADD_DEFINITIONS(-D LIBMARIADB) ADD_DEFINITIONS(-D THREAD) SET(EXPORT_SYMBOLS + client_errors load_defaults + ma_cio_register_callback mariadb_connection mariadb_convert_string mariadb_deinitialize_ssl @@ -247,7 +249,8 @@ bmove.c bmove_upp.c my_charset.c hash.c -violite.c +ma_cio.c +ma_ssl.c net.c charset.c ma_time.c @@ -321,10 +324,15 @@ my_stmt.c my_loaddata.c my_stmt_codec.c client_plugin.c -my_auth.c -ma_secure.c +# built in plugins +${CMAKE_SOURCE_DIR}/plugins/builtin/my_auth.c +${CMAKE_SOURCE_DIR}/plugins/builtin/cio_socket.c ) +IF(SSL_SOURCES) + SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES} ${SSL_SOURCES}) +ENDIF() + IF(WIN32) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/win-iconv) SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES} diff --git a/libmariadb/client_plugin.c b/libmariadb/client_plugin.c index e8a5ee2b..ee6b3410 100644 --- a/libmariadb/client_plugin.c +++ b/libmariadb/client_plugin.c @@ -61,28 +61,12 @@ static MEM_ROOT mem_root; static uint plugin_version[MYSQL_CLIENT_MAX_PLUGINS]= { MYSQL_CLIENT_DB_PLUGIN_INTERFACE_VERSION, /* these two are taken by Connector/C */ - 0, /* these two are taken by Connector/C */ + MYSQL_CLIENT_CIO_PLUGIN_INTERFACE_VERSION, /* these two are taken by Connector/C */ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION, - 0, + MYSQL_CLIENT_TRACE_PLUGIN_INTERFACE_VERSION, MYSQL_CLIENT_REMOTEIO_PLUGIN_INTERFACE_VERSION }; -typedef struct st_mysql_client_plugin_AUTHENTICATION auth_plugin_t; -extern auth_plugin_t old_password_client_plugin; -extern auth_plugin_t native_password_client_plugin; - -/* built in plugins: - These plugins are part of Connector/C, so no need to - load them -*/ - -struct st_mysql_client_plugin *mysql_client_builtins[]= -{ - (struct st_mysql_client_plugin *)&old_password_client_plugin, - (struct st_mysql_client_plugin *)&native_password_client_plugin, - 0 -}; - /* Loaded plugins are stored in a linked list. The list is append-only, the elements are added to the head (like in a stack). @@ -96,6 +80,26 @@ struct st_client_plugin_int *plugin_list[MYSQL_CLIENT_MAX_PLUGINS]; static pthread_mutex_t LOCK_load_client_plugin; #endif +extern struct st_mysql_client_plugin old_password_client_plugin; +extern struct st_mysql_client_plugin native_password_client_plugin; + +extern MARIADB_CIO_PLUGIN cio_socket_plugin; +#ifdef HAVE_SSL +extern MARIADB_CIO_PLUGIN SSL_PLUGIN; +#endif + +struct st_mysql_client_plugin *mysql_client_builtins[]= +{ + (struct st_mysql_client_plugin *)&old_password_client_plugin, + (struct st_mysql_client_plugin *)&native_password_client_plugin, + (struct st_mysql_client_plugin *)&cio_socket_plugin, +#ifdef HAVE_SSL + (struct st_mysql_client_plugin *)&SSL_PLUGIN, +#endif + 0 +}; + + static int is_not_initialized(MYSQL *mysql, const char *name) { if (initialized) @@ -103,7 +107,7 @@ static int is_not_initialized(MYSQL *mysql, const char *name) my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, SQLSTATE_UNKNOWN, ER(CR_AUTH_PLUGIN_CANNOT_LOAD), - name ? name : "unknown" , "not initialized"); + name, "not initialized"); return 1; } @@ -130,9 +134,12 @@ static struct st_mysql_client_plugin *find_plugin(const char *name, int type) for (p= plugin_list[type]; p; p= p->next) { - if (!name) - return p->plugin; - if (strcmp(p->plugin->name, name) == 0) + if (name) + { + if (strcmp(p->plugin->name, name) == 0) + return p->plugin; + } + else if (p->plugin->type == type) return p->plugin; } return NULL; @@ -207,10 +214,10 @@ err2: if (plugin->deinit) plugin->deinit(); err1: - if (dlhandle) - (void)dlclose(dlhandle); my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, SQLSTATE_UNKNOWN, ER(CR_AUTH_PLUGIN_CANNOT_LOAD), plugin->name, errmsg); + if (dlhandle) + (void)dlclose(dlhandle); return NULL; } @@ -282,7 +289,6 @@ int mysql_client_plugin_init() initialized= 1; pthread_mutex_lock(&LOCK_load_client_plugin); - for (builtin= mysql_client_builtins; *builtin; builtin++) add_plugin(&mysql, *builtin, 0, 0, unused); @@ -386,7 +392,7 @@ mysql_load_plugin_v(MYSQL *mysql, const char *name, int type, mysql->options.extension->plugin_dir : (env_plugin_dir) ? env_plugin_dir : PLUGINDIR, "/", name, SO_EXT, NullS); - + /* Open new dll handle */ if (!(dlhandle= dlopen((const char *)dlpath, RTLD_NOW))) { @@ -403,7 +409,8 @@ mysql_load_plugin_v(MYSQL *mysql, const char *name, int type, goto err; } - if (!(sym= dlsym(dlhandle, plugin_declarations_sym))) + + if (!(sym= (int *)dlsym(dlhandle, plugin_declarations_sym))) { errmsg= "not a plugin"; (void)dlclose(dlhandle); diff --git a/libmariadb/errmsg.c b/libmariadb/errmsg.c index fd51c998..43433031 100644 --- a/libmariadb/errmsg.c +++ b/libmariadb/errmsg.c @@ -55,25 +55,25 @@ const char *client_errors[]= const char *client_errors[]= { "Erro desconhecido do MySQL", - "Não pode criar 'UNIX socket' (%d)", - "Não pode se conectar ao servidor MySQL local através do 'socket' '%-.64s' (%d)", - "Não pode se conectar ao servidor MySQL em '%-.64s' (%d)", - "Não pode criar 'socket TCP/IP' (%d)", + "N�o pode criar 'UNIX socket' (%d)", + "N�o pode se conectar ao servidor MySQL local atrav�s do 'socket' '%-.64s' (%d)", + "N�o pode se conectar ao servidor MySQL em '%-.64s' (%d)", + "N�o pode criar 'socket TCP/IP' (%d)", "'Host' servidor MySQL '%-.64s' (%d) desconhecido", "Servidor MySQL desapareceu", - "Incompatibilidade de protocolos. Versão do Servidor: %d - Versão do Cliente: %d", - "Cliente do MySQL com falta de memória", - "Informação inválida de 'host'", + "Incompatibilidade de protocolos. Vers�o do Servidor: %d - Vers�o do Cliente: %d", + "Cliente do MySQL com falta de mem�ria", + "Informa��o inv�lida de 'host'", "Localhost via 'UNIX socket'", "%-.64s via 'TCP/IP'", - "Erro na negociação de acesso ao servidor", - "Conexão perdida com servidor MySQL durante 'query'", - "Comandos fora de sincronismo. Você não pode executar este comando agora", + "Erro na negocia��o de acesso ao servidor", + "Conex�o perdida com servidor MySQL durante 'query'", + "Comandos fora de sincronismo. Voc� n�o pode executar este comando agora", "%-.64s via 'named pipe'", - "Não pode esperar pelo 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)", - "Não pode abrir 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)", - "Não pode estabelecer o estado do 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)", - "Não pode inicializar conjunto de caracteres %-.64s (caminho %-.64s)", + "N�o pode esperar pelo 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)", + "N�o pode abrir 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)", + "N�o pode estabelecer o estado do 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)", + "N�o pode inicializar conjunto de caracteres %-.64s (caminho %-.64s)", "Obteve pacote maior do que 'max_allowed_packet'" }; @@ -117,8 +117,8 @@ const char *client_errors[]= /* 2034 */ "", /* 2035 */ "", /* 2036 */ "Buffer type is not supported", -/* 2037 */ "", -/* 2038 */ "", +/* 2037 */ "Shared memory: %-.64s", +/* 2038 */ "Shared memory connection failed during %s. (%lu)", /* 2039 */ "", /* 2040 */ "", /* 2041 */ "", @@ -145,6 +145,12 @@ const char *client_errors[]= }; #endif +const char *mariadb_client_errors[] = +{ + /* 5000 */ "Creating an event failed (Errorcode: %d)", + /* 5001 */ "Bind to local interface '-.%64s' failed (Errorcode: %d)", + "" +}; void init_client_errs(void) { diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 8fd87ba7..b32990c8 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -62,15 +62,11 @@ #define INADDR_NONE -1 #endif #include -#include -#ifdef HAVE_OPENSSL -#include -#endif +#include #ifndef _WIN32 #include #endif #include -#include #define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15) @@ -91,6 +87,8 @@ 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; + /* prepare statement methods from my_stmt.c */ extern my_bool mthd_supported_buffer_type(enum enum_field_types type); extern my_bool mthd_stmt_read_prepare_response(MYSQL_STMT *stmt); @@ -130,216 +128,11 @@ static void mysql_close_memory(MYSQL *mysql); void read_user_name(char *name); static void append_wild(char *to,char *end,const char *wild); static my_bool mysql_reconnect(MYSQL *mysql); -static sig_handler pipe_sig_handler(int sig); static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length); extern int mysql_client_plugin_init(); extern void mysql_client_plugin_deinit(); -/* - Let the user specify that we don't want SIGPIPE; This doesn't however work - with threaded applications as we can have multiple read in progress. -*/ - -#if !defined(_WIN32) && defined(SIGPIPE) && !defined(THREAD) -#define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0; -#define set_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) old_signal_handler=signal(SIGPIPE,pipe_sig_handler) -#define reset_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) signal(SIGPIPE,old_signal_handler); -#else -#define init_sigpipe_variables -#define set_sigpipe(mysql) -#define reset_sigpipe(mysql) -#endif - - - -/**************************************************************************** -* A modified version of connect(). connect2() allows you to specify -* a timeout value, in seconds, that we should wait until we -* derermine we can't connect to a particular host. If timeout is 0, -* connect2() will behave exactly like connect(). -* -* Base version coded by Steve Bernacki, Jr. -*****************************************************************************/ - -int socket_block(my_socket s,my_bool blocked) -{ -#ifdef _WIN32 - unsigned long socket_blocked= blocked ? 0 : 1; - return ioctlsocket(s, FIONBIO, &socket_blocked); -#else - int flags= fcntl(s, F_GETFL, 0); - if (blocked) - flags&= ~O_NONBLOCK; - else - flags|= O_NONBLOCK; - return fcntl(s, F_SETFL, flags); -#endif -} - -static int connect2(my_socket s, const struct sockaddr *name, size_t namelen, - uint timeout) -{ - int res, s_err; - socklen_t s_err_size = sizeof(uint); -#ifndef _WIN32 - struct pollfd poll_fd; -#else - FD_SET sfds, efds; - struct timeval tv; -#endif - - if (!timeout) - return connect(s, (struct sockaddr*) name, (int)namelen); - - /* set socket to non blocking */ - if (socket_block(s, 0) == SOCKET_ERROR) - return -1; - - res= connect(s, (struct sockaddr*) name, (int)namelen); - if (res == 0) - return res; - -#ifdef _WIN32 - if (GetLastError() != WSAEWOULDBLOCK && - GetLastError() != WSAEINPROGRESS) -#else - if (errno != EINPROGRESS) -#endif - return -1; -#ifndef _WIN32 - memset(&poll_fd, 0, sizeof(struct pollfd)); - poll_fd.events= POLLOUT | POLLERR; - poll_fd.fd= s; - - /* connection timeout in milliseconds */ - res= poll(&poll_fd, 1, timeout); - - switch(res) - { - /* Error= - 1, timeout = 0 */ - case -1: - break; - case 0: - errno= ETIMEDOUT; - break; - } -#else - FD_ZERO(&sfds); - FD_ZERO(&efds); - FD_SET(s, &sfds); - FD_SET(s, &efds); - - memset(&tv, 0, sizeof(struct timeval)); - tv.tv_sec= timeout; - - res= select((int)s+1, NULL, &sfds, &efds, &tv); - if (res < 1) - return -1; -#endif - - s_err=0; - if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0) - return(-1); - - if (s_err) - { /* getsockopt could succeed */ - errno = s_err; - return(-1); /* but return an error... */ - } - return (0); /* ok */ -} - -static int -connect_sync_or_async(MYSQL *mysql, NET *net, my_socket fd, - const struct sockaddr *name, uint namelen) -{ - int vio_timeout= (mysql->options.connect_timeout >= 0) ? - mysql->options.connect_timeout * 1000 : -1; - - if (mysql->options.extension && mysql->options.extension->async_context && - mysql->options.extension->async_context->active) - { - my_bool old_mode; - vio_blocking(net->vio, FALSE, &old_mode); - return my_connect_async(mysql->options.extension->async_context, fd, - name, namelen, vio_timeout); - } - - return connect2(fd, name, namelen, vio_timeout); -} -/* -** Create a named pipe connection -*/ - -#ifdef _WIN32 - -HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, - char **arg_unix_socket) -{ - HANDLE hPipe=INVALID_HANDLE_VALUE; - char szPipeName [ 257 ]; - DWORD dwMode; - int i; - my_bool testing_named_pipes=0; - char *host= *arg_host, *unix_socket= *arg_unix_socket; - - if ( ! unix_socket || (unix_socket)[0] == 0x00) - unix_socket = mysql_unix_port; - if (!host || !strcmp(host,LOCAL_HOST)) - host=LOCAL_HOST_NAMEDPIPE; - - sprintf( szPipeName, "\\\\%s\\pipe\\%s", host, unix_socket); - DBUG_PRINT("info",("Server name: '%s'. Named Pipe: %s", - host, unix_socket)); - - for (i=0 ; i < 100 ; i++) /* Don't retry forever */ - { - if ((hPipe = CreateFile(szPipeName, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - 0, - NULL )) != INVALID_HANDLE_VALUE) - break; - if (GetLastError() != ERROR_PIPE_BUSY) - { - net->last_errno=CR_NAMEDPIPEOPEN_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - /* wait for for an other instance */ - if (! WaitNamedPipe(szPipeName, connect_timeout) ) - { - net->last_errno=CR_NAMEDPIPEWAIT_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - } - if (hPipe == INVALID_HANDLE_VALUE) - { - net->last_errno=CR_NAMEDPIPEOPEN_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - dwMode = PIPE_READMODE_BYTE | PIPE_WAIT; - if ( !SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL) ) - { - CloseHandle( hPipe ); - net->last_errno=CR_NAMEDPIPESETSTATE_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - *arg_host=host ; *arg_unix_socket=unix_socket; /* connect arg */ - return (hPipe); -} -#endif - /* net_get_error */ void net_get_error(char *buf, size_t buf_len, char *error, size_t error_len, @@ -382,14 +175,10 @@ net_safe_read(MYSQL *mysql) { NET *net= &mysql->net; ulong len=0; - init_sigpipe_variables restart: - /* Don't give sigpipe errors if the client doesn't want them */ - set_sigpipe(mysql); - if (net->vio != 0) + if (net->cio != 0) len=my_net_read(net); - reset_sigpipe(mysql); if (len == packet_error || len == 0) { @@ -560,15 +349,12 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg, { NET *net= &mysql->net; int result= -1; - init_sigpipe_variables DBUG_ENTER("mthd_my_send_command"); DBUG_PRINT("info", ("server_command: %d packet_size: %u", command, length)); - /* Don't give sigpipe errors if the client doesn't want them */ - set_sigpipe(mysql); - if (mysql->net.vio == 0) + if (mysql->net.cio == 0) { /* Do reconnect if possible */ if (mysql_reconnect(mysql)) { @@ -617,7 +403,6 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg, DBUG_PRINT("info", ("packet_length=%llu", mysql->packet_length)); } end: - reset_sigpipe(mysql); DBUG_RETURN(result); } @@ -782,13 +567,10 @@ static void end_server(MYSQL *mysql) { DBUG_ENTER("end_server"); - if (mysql->net.vio != 0) + if (mysql->net.cio != 0) { - init_sigpipe_variables - set_sigpipe(mysql); - vio_delete(mysql->net.vio); - reset_sigpipe(mysql); - mysql->net.vio= 0; /* Marker */ + ma_cio_close(mysql->net.cio); + mysql->net.cio= 0; /* Marker */ } net_end(&mysql->net); free_old_query(mysql); @@ -845,7 +627,7 @@ static const char *default_options[]= "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name", "multi-results", "multi-statements", "multi-queries", "secure-auth", "report-data-truncation", "plugin-dir", "default-auth", "database-type", - "ssl-fp", "ssl-fp-list", + "ssl-fp", "ssl-fp-list", "bind-address", NULL }; @@ -860,7 +642,7 @@ enum option_val OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name, OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth, OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth, OPT_db_type, - OPT_ssl_fp, OPT_ssl_fp_list + OPT_ssl_fp, OPT_ssl_fp_list, OPT_bind_address }; #define CHECK_OPT_EXTENSION_SET(OPTS)\ @@ -869,13 +651,15 @@ enum option_val my_malloc(sizeof(struct st_mysql_options_extension), \ MYF(MY_WME | MY_ZEROFILL)); \ -#define OPT_SET_EXTENDED_VALUE(OPTS, KEY, VAL, IS_STRING) \ - CHECK_OPT_EXTENSION_SET(OPTS) \ - if (IS_STRING) { \ - my_free((OPTS)->extension->KEY); \ - (OPTS)->extension->KEY= my_strdup((char *)(VAL), MYF(MY_WME)); \ - } else \ - (OPTS)->extension->KEY= (VAL); +#define OPT_SET_EXTENDED_VALUE_STR(OPTS, KEY, VAL) \ + CHECK_OPT_EXTENSION_SET(OPTS) \ + my_free((gptr)(OPTS)->extension->KEY);\ + (OPTS)->extension->KEY= my_strdup((char *)(VAL), MYF(MY_WME)) + +#define OPT_SET_EXTENDED_VALUE_INT(OPTS, KEY, VAL) \ + CHECK_OPT_EXTENSION_SET(OPTS) \ ++ (OPTS)->extension->KEY= (VAL) + static TYPELIB option_types={array_elements(default_options)-1, "options",default_options}; @@ -993,7 +777,7 @@ static void mysql_read_default_options(struct st_mysql_options *options, case OPT_return_found_rows: options->client_flag|=CLIENT_FOUND_ROWS; break; -#ifdef HAVE_OPENSSL +#ifdef HAVE_SSL case OPT_ssl_key: my_free(options->ssl_key); options->ssl_key = my_strdup(opt_arg, MYF(MY_WME)); @@ -1013,10 +797,10 @@ static void mysql_read_default_options(struct st_mysql_options *options, case OPT_ssl_cipher: break; case OPT_ssl_fp: - OPT_SET_EXTENDED_VALUE(options, ssl_fp, opt_arg, 1); + OPT_SET_EXTENDED_VALUE_STR(options, ssl_fp, opt_arg); break; case OPT_ssl_fp_list: - OPT_SET_EXTENDED_VALUE(options, ssl_fp_list, opt_arg, 1); + OPT_SET_EXTENDED_VALUE_STR(options, ssl_fp_list, opt_arg); break; #else case OPT_ssl_key: @@ -1027,7 +811,7 @@ static void mysql_read_default_options(struct st_mysql_options *options, case OPT_ssl_fp: case OPT_ssl_fp_list: break; -#endif /* HAVE_OPENSSL */ +#endif /* HAVE_SSL */ case OPT_charset_dir: my_free(options->charset_dir); options->charset_dir = my_strdup(opt_arg, MYF(MY_WME)); @@ -1088,12 +872,16 @@ static void mysql_read_default_options(struct st_mysql_options *options, if (strlen(opt_arg) >= FN_REFLEN) opt_arg[FN_REFLEN]= 0; if (!my_realpath(directory, opt_arg, 0)) - OPT_SET_EXTENDED_VALUE(options, plugin_dir, convert_dirname(directory), 1); + OPT_SET_EXTENDED_VALUE_STR(options, plugin_dir, convert_dirname(directory)); } break; case OPT_default_auth: - OPT_SET_EXTENDED_VALUE(options, default_auth, opt_arg, 1); + OPT_SET_EXTENDED_VALUE_STR(options, default_auth, opt_arg); break; + case OPT_bind_address: + my_free(options->bind_address); + options->bind_address= my_strdup(opt_arg, MYF(MY_WME)); + break; default: DBUG_PRINT("warning",("unknown option: %s",option[0])); } @@ -1346,7 +1134,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.vio= 0; + mysql->net.cio= 0; } else bzero((char*) (mysql),sizeof(*(mysql))); @@ -1391,10 +1179,10 @@ mysql_ssl_set(MYSQL *mysql, const char *key, const char *cert, const char * STDCALL mysql_get_ssl_cipher(MYSQL *mysql) { -#ifdef HAVE_OPENSSL - if (mysql->net.vio && mysql->net.vio->ssl) +#ifdef HAVE_SSL + if (mysql->net.cio && mysql->net.cio->cssl) { - return SSL_get_cipher_name(mysql->net.vio->ssl); + return ma_cio_ssl_cipher(mysql->net.cio->cssl); } #endif return(NULL); @@ -1516,18 +1304,12 @@ 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; - my_socket sock; + MA_CIO_CINFO cinfo= {NULL, NULL, 0, -1, NULL}; + MARIADB_CIO *cio= NULL; char *scramble_data; const char *scramble_plugin; uint pkt_length, scramble_len, pkt_scramble_len= 0; NET *net= &mysql->net; -#ifdef _WIN32 - HANDLE hPipe=INVALID_HANDLE_VALUE; -#endif -#ifdef HAVE_SYS_UN_H - struct sockaddr_un UNIXaddr; -#endif - init_sigpipe_variables DBUG_ENTER("mysql_real_connect"); DBUG_PRINT("enter",("host: %s db: %s user: %s", @@ -1537,15 +1319,12 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, ma_set_connect_attrs(mysql); - if (net->vio) /* check if we are already connected */ + if (net->cio) /* check if we are already connected */ { SET_CLIENT_ERROR(mysql, CR_ALREADY_CONNECTED, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(NULL); } - /* Don't give sigpipe errors if the client doesn't want them */ - set_sigpipe(mysql); - /* use default options */ if (mysql->options.my_cnf_file || mysql->options.my_cnf_group) { @@ -1583,192 +1362,75 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, mysql->reconnect=1; */ mysql->server_status=SERVER_STATUS_AUTOCOMMIT; + + /* try to connect via cio_init */ + cinfo.host= host; + cinfo.unix_socket= unix_socket; + cinfo.port= port; + cinfo.mysql= mysql; + /* ** Grab a socket and connect it to the server */ - +#ifndef _WIN32 #if defined(HAVE_SYS_UN_H) if ((!host || strcmp(host,LOCAL_HOST) == 0) && mysql->options.protocol != MYSQL_PROTOCOL_TCP && (unix_socket || mysql_unix_port)) { - host=LOCAL_HOST; - if (!unix_socket) - unix_socket=mysql_unix_port; - host_info=(char*) ER(CR_LOCALHOST_CONNECTION); - DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket)); - if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR) - { - net->last_errno=CR_SOCKET_CREATE_ERROR; - sprintf(net->last_error,ER(net->last_errno),socket_errno); - goto error; - } - net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE); - bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); - UNIXaddr.sun_family = AF_UNIX; - strmov(UNIXaddr.sun_path, unix_socket); - if (connect_sync_or_async(mysql, net, sock, - (struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr))) - { - DBUG_PRINT("error",("Got error %d on connect to local server",socket_errno)); - my_set_error(mysql, CR_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ER(CR_CONNECTION_ERROR), - unix_socket, socket_errno); - goto error; - } - if (socket_block(sock, 1) == SOCKET_ERROR) - goto error; + cinfo.host= LOCAL_HOST; + cinfo.unix_socket= (unix_socket) ? unix_socket : mysql_unix_port; + cinfo.type= CIO_TYPE_UNIXSOCKET; + sprintf(host_info=buff,ER(CR_LOCALHOST_CONNECTION),cinfo.host); } else -#elif defined(_WIN32) +#endif +#else + /* named pipe */ + if ((unix_socket || + (!host && is_NT()) || + (host && strcmp(host,LOCAL_HOST_NAMEDPIPE) == 0) || + mysql->options.named_pipe || + !have_tcpip) && + mysql->options.protocol != MYSQL_PROTOCOL_TCP) { - if ((unix_socket || - (!host && is_NT()) || - (host && strcmp(host,LOCAL_HOST_NAMEDPIPE) == 0) || - mysql->options.named_pipe || - !have_tcpip) && - mysql->options.protocol != MYSQL_PROTOCOL_TCP) - { - sock=0; - if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout, - (char**) &host, (char**) &unix_socket)) == - INVALID_HANDLE_VALUE) - { - DBUG_PRINT("error", - ("host: '%s' socket: '%s' named_pipe: %d have_tcpip: %d", - host ? host : "", - unix_socket ? unix_socket : "", - (int) mysql->options.named_pipe, - (int) have_tcpip)); - if (mysql->options.named_pipe || - (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) || - (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE))) - goto error; /* User only requested named pipes */ - /* Try also with TCP/IP */ - } - else - { - net->vio=vio_new_win32pipe(hPipe); - sprintf(host_info=buff, ER(CR_NAMEDPIPE_CONNECTION), host, - unix_socket); - } - } + cinfo.type= CIO_TYPE_NAMEDPIPE; + sprintf(host_info=buff,ER(CR_NAMEDPIPE_CONNECTION),cinfo.host); } - if (hPipe == INVALID_HANDLE_VALUE) + else #endif { - struct addrinfo hints, *save_res= 0, *res= 0; - char server_port[NI_MAXSERV]; - int gai_rc; - int rc; - - unix_socket=0; /* This is not used */ + cinfo.unix_socket=0; /* This is not used */ if (!port) port=mysql_port; if (!host) host=LOCAL_HOST; - sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host); - bzero(&server_port, NI_MAXSERV); - - DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port)); - - my_snprintf(server_port, NI_MAXSERV, "%d", port); - - /* set hints for getaddrinfo */ - bzero(&hints, sizeof(hints)); - hints.ai_protocol= IPPROTO_TCP; /* TCP connections only */ - hints.ai_family= AF_UNSPEC; /* includes: IPv4, IPv6 or hostname */ - hints.ai_socktype= SOCK_STREAM; - - /* Get the address information for the server using getaddrinfo() */ - gai_rc= getaddrinfo(host, server_port, &hints, &res); - if (gai_rc != 0) - { - my_set_error(mysql, CR_UNKNOWN_HOST, SQLSTATE_UNKNOWN, - ER(CR_UNKNOWN_HOST), host, gai_rc); - goto error; - } - - /* res is a linked list of addresses. If connect to an address fails we will not return - an error, instead we will try the next address */ - for (save_res= res; save_res; save_res= save_res->ai_next) - { - sock= socket(save_res->ai_family, save_res->ai_socktype, - save_res->ai_protocol); - if (sock == SOCKET_ERROR) - /* we do error handling after for loop only for last call */ - continue; - if (!(net->vio= vio_new(sock, VIO_TYPE_TCPIP, FALSE))) - { - my_set_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); - closesocket(sock); - freeaddrinfo(res); - goto error; - } - rc= connect_sync_or_async(mysql, net, sock, - 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; - else if (socket_block(sock, 1) == SOCKET_ERROR) - { - closesocket(sock); - continue; - } - break; /* success! */ - } - vio_delete(mysql->net.vio); - mysql->net.vio= NULL; - } - - freeaddrinfo(res); - - if (sock == SOCKET_ERROR) - { - my_set_error(mysql, CR_IPSOCK_ERROR, SQLSTATE_UNKNOWN, ER(CR_IPSOCK_ERROR), - socket_errno); - goto error; - } - - /* last call to connect 2 failed */ - if (rc) - { - my_set_error(mysql, CR_CONN_HOST_ERROR, SQLSTATE_UNKNOWN, ER(CR_CONN_HOST_ERROR), - host, socket_errno); - goto error; - } + cinfo.host= host; + cinfo.port= port; + cinfo.type= CIO_TYPE_SOCKET; + sprintf(host_info=buff,ER(CR_TCP_CONNECTION), cinfo.host); } + /* Initialize and load cio plugin */ + if (!(cio= ma_cio_init(&cinfo))) + goto error; - /* set timeouts */ - net->vio->read_timeout= mysql->options.read_timeout; - net->vio->write_timeout= mysql->options.write_timeout; - - if (mysql->options.extension && mysql->options.extension->async_context) - net->vio->async_context= mysql->options.extension->async_context; - - if (!net->vio || my_net_init(net, net->vio)) + /* try to connect */ + if (ma_cio_connect(cio, &cinfo) != 0) { - vio_delete(net->vio); - net->vio = 0; - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); + ma_cio_close(cio); goto error; } - vio_keepalive(net->vio,TRUE); + + if (my_net_init(net, cio)) + goto error; + + ma_cio_keepalive(net->cio); strmov(mysql->net.sqlstate, "00000"); - - /* set read timeout */ - if (mysql->options.read_timeout >= 0) - vio_read_timeout(net->vio, mysql->options.read_timeout); - - /* set write timeout */ - if (mysql->options.write_timeout >= 0) - vio_write_timeout(net->vio, mysql->options.read_timeout); /* Get version info */ mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */ - if (mysql->options.connect_timeout >= 0 && - vio_wait_or_timeout(net->vio, FALSE, mysql->options.connect_timeout * 1000) < 1) +/* + if (ma_cio_wait_io_or_timeout(net->cio, FALSE, 0) < 1) { my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN, ER(CR_SERVER_LOST_EXTENDED), @@ -1776,6 +1438,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, errno); goto error; } + */ if ((pkt_length=net_safe_read(mysql)) == packet_error) { if (mysql->net.last_errno == CR_SERVER_LOST) @@ -1821,9 +1484,9 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, if (!my_multi_malloc(MYF(0), &mysql->host_info, (uint) strlen(host_info)+1, - &mysql->host, (uint) strlen(host)+1, - &mysql->unix_socket,unix_socket ? - (uint) strlen(unix_socket)+1 : (uint) 1, + &mysql->host, (uint) strlen(cinfo.host)+1, + &mysql->unix_socket, cinfo.unix_socket ? + (uint) strlen(cinfo.unix_socket)+1 : (uint) 1, &mysql->server_version, (uint) (end - (char*) net->read_pos), NullS) || !(mysql->user=my_strdup(user,MYF(0))) || @@ -1833,9 +1496,9 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, goto error; } strmov(mysql->host_info,host_info); - strmov(mysql->host,host); - if (unix_socket) - strmov(mysql->unix_socket,unix_socket); + strmov(mysql->host, cinfo.host); + if (cinfo.unix_socket) + strmov(mysql->unix_socket, cinfo.unix_socket); else mysql->unix_socket=0; mysql->port=port; @@ -1985,11 +1648,9 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, strmov(mysql->net.sqlstate, "00000"); DBUG_PRINT("exit",("Mysql handler: %lx",mysql)); - reset_sigpipe(mysql); DBUG_RETURN(mysql); error: - reset_sigpipe(mysql); DBUG_PRINT("error",("message: %u (%s)",net->last_errno,net->last_error)); { /* Free alloced memory */ @@ -2002,7 +1663,6 @@ error: DBUG_RETURN(0); } - static my_bool mysql_reconnect(MYSQL *mysql) { MYSQL tmp_mysql; @@ -2025,13 +1685,13 @@ static my_bool mysql_reconnect(MYSQL *mysql) tmp_mysql.options.my_cnf_group= tmp_mysql.options.my_cnf_file= NULL; /* make sure that we reconnect with the same character set */ - if (!tmp_mysql.options.charset_name || + /* if (!tmp_mysql.options.charset_name || strcmp(tmp_mysql.options.charset_name, mysql->charset->csname)) { my_free(tmp_mysql.options.charset_name); tmp_mysql.options.charset_name= my_strdup(mysql->charset->csname, MYF(MY_WME)); } - +*/ tmp_mysql.reconnect= mysql->reconnect; if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, mysql->db, mysql->port, mysql->unix_socket, @@ -2252,7 +1912,7 @@ void my_set_error(MYSQL *mysql, void mysql_close_slow_part(MYSQL *mysql) { - if (mysql->net.vio) + if (mysql->net.cio) { free_old_query(mysql); mysql->status=MYSQL_STATUS_READY; /* Force command */ @@ -2288,7 +1948,7 @@ mysql_close(MYSQL *mysql) /* Clear pointers for better safety */ bzero((char*) &mysql->options,sizeof(mysql->options)); - mysql->net.vio= 0; + mysql->net.cio= 0; if (mysql->free_me) my_free(mysql); } @@ -2931,7 +2591,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) #else if (*(uint *)arg1 > MYSQL_PROTOCOL_SOCKET) #endif - DBUG_RETURN(-1); + goto end; mysql->options.protocol= *(uint *)arg1; break; case MYSQL_OPT_READ_TIMEOUT: @@ -2953,11 +2613,12 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) (void (*)(const MYSQL *, uint, uint, double, const char *, uint)) arg1; break; case MYSQL_PLUGIN_DIR: - OPT_SET_EXTENDED_VALUE(&mysql->options, plugin_dir, (char *)arg1, 1); + OPT_SET_EXTENDED_VALUE_STR(&mysql->options, plugin_dir, (char *)arg1); break; case MYSQL_DEFAULT_AUTH: - OPT_SET_EXTENDED_VALUE(&mysql->options, default_auth, (char *)arg1, 1); + OPT_SET_EXTENDED_VALUE_STR(&mysql->options, default_auth, (char *)arg1); break; + /* case MYSQL_DATABASE_DRIVER: { MARIADB_DB_PLUGIN *db_plugin; @@ -2981,6 +2642,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) } } break; + */ case MYSQL_OPT_NONBLOCK: if (mysql->options.extension && (ctxt = mysql->options.extension->async_context) != 0) @@ -2990,7 +2652,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) suspended (as the stack is then in use). */ if (ctxt->suspended) - DBUG_RETURN(1); + goto end; my_context_destroy(&ctxt->async_context); my_free(ctxt); } @@ -2998,7 +2660,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) my_malloc(sizeof(*ctxt), MYF(MY_ZEROFILL)))) { SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); - DBUG_RETURN(1); + goto end; } stacksize= 0; if (arg1) @@ -3008,7 +2670,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) if (my_context_init(&ctxt->async_context, stacksize)) { my_free(ctxt); - DBUG_RETURN(1); + goto end; } if (!mysql->options.extension) if(!(mysql->options.extension= (struct st_mysql_options_extension *) @@ -3016,11 +2678,11 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) MYF(MY_WME | MY_ZEROFILL)))) { SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); - DBUG_RETURN(1); + goto end; } mysql->options.extension->async_context= ctxt; - if (mysql->net.vio) - mysql->net.vio->async_context= ctxt; + if (mysql->net.cio) + mysql->net.cio->async_context= ctxt; break; case MYSQL_OPT_SSL_VERIFY_SERVER_CERT: @@ -3050,16 +2712,10 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) mysql->options.ssl_cipher=my_strdup((char *)arg1,MYF(MY_WME)); break; case MYSQL_OPT_SSL_CRL: - OPT_SET_EXTENDED_VALUE(&mysql->options, ssl_crl, (char *)arg1, 1); + OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_crl, (char *)arg1); break; case MYSQL_OPT_SSL_CRLPATH: - OPT_SET_EXTENDED_VALUE(&mysql->options, ssl_crlpath, (char *)arg1, 1); - break; - case MARIADB_OPT_SSL_FP: - OPT_SET_EXTENDED_VALUE(&mysql->options, ssl_fp, (char *)arg1, 1); - break; - case MARIADB_OPT_SSL_FP_LIST: - OPT_SET_EXTENDED_VALUE(&mysql->options, ssl_fp_list, (char *)arg1, 1); + OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_crlpath, (char *)arg1); break; case MYSQL_OPT_CONNECT_ATTR_DELETE: { @@ -3148,6 +2804,10 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) case MYSQL_SECURE_AUTH: mysql->options.secure_auth= *(my_bool *)arg1; break; + case MYSQL_OPT_BIND: + my_free(mysql->options.bind_address); + mysql->options.bind_address= my_strdup(arg1, MYF(MY_WME)); + break; default: va_end(ap); DBUG_RETURN(-1); @@ -3452,9 +3112,6 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)), mysql_unix_port = env; } mysql_debug(NullS); -#if defined(SIGPIPE) && !defined(THREAD) && !defined(_WIN32) - (void) signal(SIGPIPE,SIG_IGN); -#endif } #ifdef THREAD else @@ -3469,12 +3126,10 @@ void STDCALL mysql_server_end() { if (!mysql_client_init) return; -#ifdef HAVE_OPENSSL - my_ssl_end(); -#endif mysql_client_plugin_deinit(); + list_free(cio_callback, 0); if (my_init_done) my_end(0); mysql_client_init= 0; @@ -3550,9 +3205,13 @@ mysql_get_parameters(void) my_socket STDCALL mysql_get_socket(const MYSQL *mysql) { - if (mysql->net.vio) - return vio_fd(mysql->net.vio); - return MARIADB_INVALID_SOCKET; + my_socket sock; + if (mysql->net.cio) + { + ma_cio_get_handle(mysql->net.cio, &sock); + return sock; + } + return INVALID_SOCKET; } /* diff --git a/libmariadb/my_stmt.c b/libmariadb/my_stmt.c index 414be03f..a3225874 100644 --- a/libmariadb/my_stmt.c +++ b/libmariadb/my_stmt.c @@ -53,7 +53,7 @@ #include "mysql_version.h" #include "mysqld_error.h" #include "errmsg.h" -#include +#include #include #include #include @@ -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.vio) + if (stmt && stmt->mysql && stmt->mysql->net.cio) mysql_stmt_reset(stmt); net_stmt_close(stmt, 1); diff --git a/libmariadb/mysql_async.c b/libmariadb/mysql_async.c index e1424509..b384afe9 100644 --- a/libmariadb/mysql_async.c +++ b/libmariadb/mysql_async.c @@ -30,8 +30,9 @@ #include "ma_common.h" #endif #include "my_context.h" -#include "violite.h" +#include "ma_cio.h" #include "mysql_async.h" +#include #ifdef _WIN32 @@ -41,7 +42,7 @@ */ #define WIN_SET_NONBLOCKING(mysql) { \ my_bool old_mode; \ - if ((mysql)->net.vio) vio_blocking((mysql)->net.vio, FALSE, &old_mode); \ + if ((mysql)->net.cio) ma_cio_blocking((mysql)->net.cio, FALSE, &old_mode); \ } #else #define WIN_SET_NONBLOCKING(mysql) @@ -62,19 +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(struct mysql_async_context *b, my_socket fd, +my_connect_async(MARIADB_CIO *cio, 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; + my_socket sock; + + ma_cio_get_handle(cio, &sock); /* Make the socket non-blocking. */ -#ifdef _WIN32 - ulong arg= 1; - ioctlsocket(fd, FIONBIO, (void *)&arg); -#else - fcntl(fd, F_SETFL, O_NONBLOCK); -#endif + ma_cio_blocking(cio, 0, 0); b->events_to_wait_for= 0; /* @@ -83,7 +83,7 @@ my_connect_async(struct mysql_async_context *b, my_socket fd, application context. The application will then resume us when the socket polls ready for write, indicating that the connection attempt completed. */ - res= connect(fd, name, namelen); + res= connect(sock, name, namelen); if (res != 0) { #ifdef _WIN32 @@ -113,7 +113,7 @@ my_connect_async(struct mysql_async_context *b, my_socket fd, return -1; s_err_size= sizeof(res); - if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &res, &s_err_size) != 0) + if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*) &res, &s_err_size) != 0) return -1; if (res) { @@ -135,14 +135,15 @@ my_connect_async(struct mysql_async_context *b, my_socket fd, #endif ssize_t -my_recv_async(struct mysql_async_context *b, int fd, - unsigned char *buf, size_t size, int timeout) +my_recv_async(MARIADB_CIO *cio, const unsigned char *buf, size_t size, int timeout) { ssize_t res; - + struct mysql_async_context *b= cio->async_context; for (;;) { - res= recv(fd, buf, size, IF_WIN(0, MSG_DONTWAIT)); + /* todo: async */ + if (cio->methods->async_read) + res= cio->methods->async_read(cio, buf, size); if (res >= 0 || IS_BLOCKING_ERROR()) return res; b->events_to_wait_for= MYSQL_WAIT_READ; @@ -163,14 +164,15 @@ my_recv_async(struct mysql_async_context *b, int fd, ssize_t -my_send_async(struct mysql_async_context *b, int fd, - const unsigned char *buf, size_t size, int timeout) +my_send_async(MARIADB_CIO *cio, const unsigned char *buf, size_t size, int timeout) { ssize_t res; + struct mysql_async_context *b= cio->async_context; for (;;) { - res= send(fd, buf, size, IF_WIN(0, MSG_DONTWAIT)); + if (cio->methods->async_write) + res= cio->methods->async_write(cio, buf, size); if (res >= 0 || IS_BLOCKING_ERROR()) return res; b->events_to_wait_for= MYSQL_WAIT_WRITE; @@ -191,7 +193,7 @@ my_send_async(struct mysql_async_context *b, int fd, my_bool -my_io_wait_async(struct mysql_async_context *b, enum enum_vio_io_event event, +my_io_wait_async(struct mysql_async_context *b, enum enum_cio_io_event event, int timeout) { switch (event) @@ -221,9 +223,9 @@ my_io_wait_async(struct mysql_async_context *b, enum enum_vio_io_event event, } -#ifdef HAVE_OPENSSL +#ifdef HAVE_SSL_FIXME static my_bool -my_ssl_async_check_result(int res, struct mysql_async_context *b, SSL *ssl) +my_ssl_async_check_result(int res, struct mysql_async_context *b, MARIADB_SSL *cssl) { int ssl_err; b->events_to_wait_for= 0; @@ -496,18 +498,36 @@ MK_ASYNC_INTERNAL_BODY( int STDCALL mysql_real_query_start(int *ret, MYSQL *mysql, const char *stmt_str, unsigned long length) { -MK_ASYNC_START_BODY( - mysql_real_query, - mysql, + int res; + struct mysql_async_context *b; + struct mysql_real_query_params parms; + + b= mysql->options.extension->async_context; { WIN_SET_NONBLOCKING(mysql) parms.mysql= mysql; parms.stmt_str= stmt_str; parms.length= length; - }, - 1, - r_int, - /* Nothing */) + } + + b->active= 1; + res= my_context_spawn(&b->async_context, mysql_real_query_start_internal, &parms); + b->active= b->suspended= 0; + if (res > 0) + { + /* Suspended. */ + b->suspended= 1; + return b->events_to_wait_for; + } + if (res < 0) + { + set_mysql_error((mysql), CR_OUT_OF_MEMORY, unknown_sqlstate); + *ret= 1; + } + else + *ret= b->ret_result.r_int; + return 0; + } int STDCALL mysql_real_query_cont(int *ret, MYSQL *mysql, int ready_status) diff --git a/libmariadb/net.c b/libmariadb/net.c index ddf97321..26949a71 100644 --- a/libmariadb/net.c +++ b/libmariadb/net.c @@ -22,8 +22,10 @@ ** 3 byte length & 1 byte package-number. */ + #include -#include +#include +#include #include #include #include "mysql.h" @@ -31,6 +33,7 @@ #include #include #include +#include #ifndef _WIN32 #include #endif @@ -46,7 +49,7 @@ ulong max_allowed_packet=1024L * 1024L * 1024L; ulong net_read_timeout= NET_READ_TIMEOUT; ulong net_write_timeout= NET_WRITE_TIMEOUT; -ulong net_buffer_length=8192; /* Default length. Enlarged if necessary */ +ulong net_buffer_length= 8192; /* Default length. Enlarged if necessary */ #if !defined(_WIN32) && !defined(MSDOS) #include @@ -110,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, Vio* vio) +int my_net_init(NET *net, MARIADB_CIO* cio) { 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->vio = vio; + net->cio = cio; 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; @@ -127,21 +130,18 @@ int my_net_init(NET *net, Vio* vio) net->where_b = net->remain_in_buf=0; net->last_errno=0; - if (vio != 0) /* If real connection */ + if (cio != 0) /* If real connection */ { - net->fd = vio_fd(vio); /* For perl DBI/DBD */ -#if defined(MYSQL_SERVER) && !defined(__WIN32) && !defined(__EMX__) && !defined(OS2) - if (!(test_flags & TEST_BLOCKING)) - vio_blocking(vio, FALSE, 0); -#endif - vio_fastsend(vio); + ma_cio_get_handle(cio, &net->fd); + ma_cio_blocking(cio, 1, 0); + ma_cio_fast_send(cio); } return 0; } void net_end(NET *net) { - my_free(net->buff); + my_free((gptr) net->buff); net->buff=0; } @@ -219,15 +219,17 @@ static my_bool net_check_socket_status(my_socket sock) void net_clear(NET *net) { + my_socket sock; DBUG_ENTER("net_clear"); + + ma_cio_get_handle(net->cio, &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(net->vio->sd)) + while (net_check_socket_status(sock)) { - /* vio_read returns size_t. so casting to long is required to check for -1 */ - if ((long)vio_read(net->vio, (gptr)net->buff, (size_t) net->max_packet) <= 0) + if ((ssize_t)ma_cio_cache_read(net->cio, (gptr)net->buff, (size_t) net->max_packet) <= 0) { net->error= 2; DBUG_PRINT("info", ("socket disconnected")); @@ -384,12 +386,6 @@ net_real_write(NET *net,const char *packet,size_t len) { size_t length; char *pos,*end; - thr_alarm_t alarmed; -#if !defined(_WIN32) && !defined(__EMX__) && !defined(OS2) - ALARM alarm_buff; -#endif - uint retry_count=0; - my_bool net_blocking = vio_is_blocking(net->vio); DBUG_ENTER("net_real_write"); if (net->error == 2) @@ -426,79 +422,23 @@ net_real_write(NET *net,const char *packet,size_t len) } #endif /* HAVE_COMPRESS */ - alarmed=0; - pos=(char*) packet; end=pos+len; while (pos != end) { - if ((long) (length=vio_write(net->vio,pos,(size_t) (end-pos))) <= 0) + if ((ssize_t) (length=ma_cio_write(net->cio,pos,(size_t) (end-pos))) <= 0) { - my_bool interrupted = vio_should_retry(net->vio); -#if (!defined(_WIN32) && !defined(__EMX__) && !defined(OS2)) - if ((interrupted || length==0) && !thr_alarm_in_use(&alarmed)) - { - if (!thr_alarm(&alarmed,(uint) net_write_timeout,&alarm_buff)) - { /* Always true for client */ - if (!vio_is_blocking(net->vio)) - { - while (vio_blocking(net->vio, TRUE, 0) < 0) - { - if (vio_should_retry(net->vio) && retry_count++ < RETRY_COUNT) - continue; -#ifdef EXTRA_DEBUG - fprintf(stderr, - "%s: my_net_write: fcntl returned error %d, aborting thread\n", - my_progname,vio_errno(net->vio)); -#endif /* EXTRA_DEBUG */ - net->error=2; /* Close socket */ - net->last_errno= (interrupted ? - ER_NET_WRITE_INTERRUPTED : ER_NET_ERROR_ON_WRITE); - goto end; - } - } - retry_count=0; - continue; - } - } - else -#endif /* (!defined(_WIN32) && !defined(__EMX__)) */ - if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) && - interrupted) - { - if (retry_count++ < RETRY_COUNT) - continue; -#ifdef EXTRA_DEBUG - fprintf(stderr, "%s: write looped, aborting thread\n", - my_progname); -#endif /* EXTRA_DEBUG */ - } -#if defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) - if (vio_errno(net->vio) == SOCKET_EINTR) - { - DBUG_PRINT("warning",("Interrupted write. Retrying...")); - continue; - } -#endif /* defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) */ net->error=2; /* Close socket */ - net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED : - ER_NET_ERROR_ON_WRITE); - break; + net->last_errno= ER_NET_ERROR_ON_WRITE; + net->reading_or_writing=0; + DBUG_RETURN(1); } pos+=length; statistic_add(bytes_sent,length,&LOCK_bytes_sent); } -#ifndef _WIN32 - end: -#endif #ifdef HAVE_COMPRESS if (net->compress) - my_free((void *)packet); + my_free((char*) packet); #endif - if (thr_alarm_in_use(&alarmed)) - { - thr_end_alarm(&alarmed); - vio_blocking(net->vio, net_blocking, 0); - } net->reading_or_writing=0; DBUG_RETURN(((int) (pos != end))); } @@ -507,66 +447,18 @@ net_real_write(NET *net,const char *packet,size_t len) /***************************************************************************** ** Read something from server/clinet *****************************************************************************/ - -#ifdef MYSQL_SERVER - -/* - Help function to clear the commuication buffer when we get a too - big packet -*/ - -static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed, - ALARM *alarm_buff) -{ - uint retry_count=0; - if (!thr_alarm_in_use(alarmed)) - { - if (thr_alarm(alarmed,net->timeout,alarm_buff) || - (!vio_is_blocking(net->vio) && vio_blocking(net->vio,TRUE, 0) < 0)) - return; /* Can't setup, abort */ - } - while (remain > 0) - { - ulong length; - if ((int) (length=vio_read(net->vio,(char*) net->buff,remain)) <= 0L) - { - my_bool interrupted = vio_should_retry(net->vio); - if (!thr_got_alarm(alarmed) && interrupted) - { /* Probably in MIT threads */ - if (retry_count++ < RETRY_COUNT) - continue; - } - return; - } - remain -=(ulong) length; - statistic_add(bytes_received,(ulong) length,&LOCK_bytes_received); - } -} -#endif /* MYSQL_SERVER */ - - static ulong my_real_read(NET *net, size_t *complen) { uchar *pos; size_t length; - uint i,retry_count=0; + uint i; ulong len=packet_error; - thr_alarm_t alarmed; -#if (!defined(_WIN32) && !defined(__EMX__) && !defined(OS2)) || defined(MYSQL_SERVER) - ALARM alarm_buff; -#endif - my_bool net_blocking=vio_is_blocking(net->vio); size_t remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE : NET_HEADER_SIZE); *complen = 0; net->reading_or_writing=1; - thr_alarm_init(&alarmed); -#ifdef MYSQL_SERVER - if (net_blocking) - thr_alarm(&alarmed,net->timeout,&alarm_buff); -#endif /* MYSQL_SERVER */ pos = net->buff + net->where_b; /* net->packet -4 */ for (i=0 ; i < 2 ; i++) @@ -574,68 +466,8 @@ my_real_read(NET *net, size_t *complen) while (remain > 0) { /* First read is done with non blocking mode */ - if ((long) (length=vio_read(net->vio,(char*) pos,remain)) <= 0L) + if ((ssize_t) (length=ma_cio_cache_read(net->cio,(char*) pos,remain)) <= 0L) { - my_bool interrupted = vio_should_retry(net->vio); - - DBUG_PRINT("info",("vio_read returned %d, errno: %d", - length, vio_errno(net->vio))); -#if (!defined(_WIN32) && !defined(__EMX__) && !defined(OS2)) || defined(MYSQL_SERVER) - /* - We got an error that there was no data on the socket. We now set up - an alarm to not 'read forever', change the socket to non blocking - mode and try again - */ - if ((interrupted || length == 0) && !thr_alarm_in_use(&alarmed)) - { - if (!thr_alarm(&alarmed,net->read_timeout,&alarm_buff)) /* Don't wait too long */ - { - if (!vio_is_blocking(net->vio)) - { - while (vio_blocking(net->vio,TRUE, 0) < 0) - { - if (vio_should_retry(net->vio) && - retry_count++ < RETRY_COUNT) - continue; - DBUG_PRINT("error", - ("fcntl returned error %d, aborting thread", - vio_errno(net->vio))); -#ifdef EXTRA_DEBUG - fprintf(stderr, - "%s: read: fcntl returned error %d, aborting thread\n", - my_progname,vio_errno(net->vio)); -#endif /* EXTRA_DEBUG */ - len= packet_error; - net->error=2; /* Close socket */ -#ifdef MYSQL_SERVER - net->last_errno=ER_NET_FCNTL_ERROR; -#endif - goto end; - } - } - retry_count=0; - continue; - } - } -#endif /* (!defined(_WIN32) && !defined(__EMX__)) || defined(MYSQL_SERVER) */ - if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) && - interrupted) - { /* Probably in MIT threads */ - if (retry_count++ < RETRY_COUNT) - continue; -#ifdef EXTRA_DEBUG - fprintf(stderr, "%s: read looped with error %d, aborting thread\n", - my_progname,vio_errno(net->vio)); -#endif /* EXTRA_DEBUG */ - } -#if defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) - if (vio_should_retry(net->vio)) - { - DBUG_PRINT("warning",("Interrupted read. Retrying...")); - continue; - } -#endif - DBUG_PRINT("error",("Couldn't read packet: remain: %d errno: %d length: %d alarmed: %d", remain,vio_errno(net->vio),length,alarmed)); len= packet_error; net->error=2; /* Close socket */ goto end; @@ -662,9 +494,6 @@ my_real_read(NET *net, size_t *complen) #endif } len= packet_error; -#ifdef MYSQL_SERVER - net->last_errno=ER_NET_PACKETS_OUT_OF_ORDER; -#endif goto end; } net->compress_pkt_nr= ++net->pkt_nr; @@ -685,10 +514,6 @@ my_real_read(NET *net, size_t *complen) { if (net_realloc(net,helping)) { -#ifdef MYSQL_SERVER - if (i == 1) - my_net_skip_rest(net, len, &alarmed, &alarm_buff); -#endif len= packet_error; /* Return error */ goto end; } @@ -699,11 +524,6 @@ my_real_read(NET *net, size_t *complen) } end: - if (thr_alarm_in_use(&alarmed)) - { - thr_end_alarm(&alarmed); - vio_blocking(net->vio, net_blocking, 0); - } net->reading_or_writing=0; return(len); } diff --git a/libmariadb/violite.c b/libmariadb/violite.c deleted file mode 100644 index 1fbdcc33..00000000 --- a/libmariadb/violite.c +++ /dev/null @@ -1,713 +0,0 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -/* - Note that we can't have assertion on file descriptors; The reason for - this is that during mysql shutdown, another thread can close a file - we are working on. In this case we should just return read errors from - the file descriptior. -*/ - -#ifndef HAVE_VIO /* is Vio suppored by the Vio lib ? */ - -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_POLL -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif - -#ifdef HAVE_OPENSSL -#include -#endif - -#ifdef _WIN32 -#define socklen_t int -#pragma comment (lib, "ws2_32") -#endif - -#if !defined(MSDOS) && !defined(_WIN32) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__) && !defined(__FreeBSD__) -#include -#include -#if !defined(alpha_linux_port) -#include -#endif -#endif - -#if defined(__EMX__) || defined(OS2) -#define ioctlsocket ioctl -#endif /* defined(__EMX__) */ - -#if defined(MSDOS) || defined(_WIN32) -#define O_NONBLOCK 1 /* For emulation of fcntl() */ -#endif -#ifndef EWOULDBLOCK -#define SOCKET_EWOULDBLOCK SOCKET_EAGAIN -#endif - -#include -#include - -#ifdef _WIN32 -#define ma_get_error() WSAGetLastError() -#else -#define ma_get_error() errno -#endif - -typedef void *vio_ptr; -typedef char *vio_cstring; - -/* - * Helper to fill most of the Vio* with defaults. - */ - -void vio_reset(Vio* vio, enum enum_vio_type type, - my_socket sd, HANDLE hPipe, - my_bool localhost) -{ - uchar *save_cache= vio->cache; - int save_timeouts[2]= {vio->read_timeout, vio->write_timeout}; - bzero((char*) vio, sizeof(*vio)); - vio->type= type; - vio->sd= sd; - vio->hPipe= hPipe; - vio->localhost= localhost; - /* do not clear cache */ - vio->cache= vio->cache_pos= save_cache; - vio->cache_size= 0; - vio->read_timeout= save_timeouts[0]; - vio->write_timeout= save_timeouts[1]; -} - -void vio_timeout(Vio *vio, int type, uint timeval) -{ -#ifdef _WIN32 - uint timeout= timeval; /* milli secs */ -#else - struct timeval timeout; - timeout.tv_sec= timeval; - timeout.tv_usec= (timeval % 1000) * 1000; -#endif - - if (setsockopt(vio->sd, SOL_SOCKET, type, -#ifdef _WIN32 - (const char *)&timeout, -#else - (const void *)&timeout, -#endif - sizeof(timeout))) - { - DBUG_PRINT("error", ("setsockopt failed. Errno: %d", errno)); - } -} - -void vio_read_timeout(Vio *vio, uint timeout) -{ - vio->read_timeout= (timeout >= 0) ? timeout * 1000 : -1; - vio_timeout(vio, SO_RCVTIMEO, vio->read_timeout); -} - -void vio_write_timeout(Vio *vio, uint timeout) -{ - vio->write_timeout= (timeout >= 0) ? timeout * 1000 : -1; - vio_timeout(vio, SO_SNDTIMEO, vio->write_timeout); -} - -/* Open the socket or TCP/IP connection and read the fnctl() status */ - -Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost) -{ - Vio *vio; - DBUG_ENTER("vio_new"); - DBUG_PRINT("enter", ("sd=%d", sd)); - if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME)))) - { - vio_reset(vio, type, sd, 0, localhost); - sprintf(vio->desc, - (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"), - vio->sd); -#if !defined(__WIN32) && !defined(__EMX__) && !defined(OS2) -#if !defined(NO_FCNTL_NONBLOCK) - vio->fcntl_mode = fcntl(sd, F_GETFL); -#elif defined(HAVE_SYS_IOCTL_H) /* hpux */ - /* Non blocking sockets doesn't work good on HPUX 11.0 */ - (void) ioctl(sd,FIOSNBIO,0); -#endif -#else /* !defined(_WIN32) && !defined(__EMX__) */ - { - /* set to blocking mode by default */ - ulong arg=0, r; - r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg/*, sizeof(arg)*/); - } -#endif - } - if (!(vio->cache= my_malloc(VIO_CACHE_SIZE, MYF(MY_WME)))) - { - my_free(vio); - vio= NULL; - } - vio->cache_size= 0; - vio->cache_pos= vio->cache; - DBUG_RETURN(vio); -} - - -#ifdef _WIN32 - -Vio *vio_new_win32pipe(HANDLE hPipe) -{ - Vio *vio; - DBUG_ENTER("vio_new_handle"); - if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_ZEROFILL)))) - { - vio_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE); - strmov(vio->desc, "named pipe"); - } - DBUG_RETURN(vio); -} - -#endif - -void vio_delete(Vio * vio) -{ - /* It must be safe to delete null pointers. */ - /* This matches the semantics of C++'s delete operator. */ - if (vio) - { - if (vio->type != VIO_CLOSED) - vio_close(vio); - my_free(vio->cache); - my_free(vio); - } -} - -int vio_errno(Vio *vio __attribute__((unused))) -{ - return socket_errno; /* On Win32 this mapped to WSAGetLastError() */ -} - -int vio_wait_or_timeout(Vio *vio, my_bool is_read, int timeout) -{ - int rc; -#ifndef _WIN32 - struct pollfd p_fd; -#else - struct timeval tv= {0,0}; - fd_set fds, exc_fds; -#endif - - /* we don't support it via named pipes yet. - * maybe this could be handled via PeekNamedPipe somehow !? */ - if (vio->type == VIO_TYPE_NAMEDPIPE) - return 1; - - /* - Note that if zero timeout, then we will not block, so we do not need to - yield to calling application in the async case. - */ - if (timeout != 0 && vio->async_context && vio->async_context->active) - { - rc= my_io_wait_async(vio->async_context, - (is_read) ? VIO_IO_EVENT_READ : VIO_IO_EVENT_WRITE, - timeout); - return(rc); - } - else - { -#ifndef _WIN32 - p_fd.fd= vio->sd; - p_fd.events= (is_read) ? POLLIN : POLLOUT; - - do { - rc= poll(&p_fd, 1, timeout); - } while (rc == -1 || errno == EINTR); - - if (rc == 0) - errno= ETIMEDOUT; -#else - FD_ZERO(&fds); - FD_ZERO(&exc_fds); - - FD_SET(vio->sd, &fds); - FD_SET(vio->sd, &exc_fds); - - if (timeout >= 0) - { - tv.tv_sec= timeout / 1000; - tv.tv_usec= (timeout % 1000) * 1000; - } - - rc= select(0, (is_read) ? &fds : NULL, - (is_read) ? NULL : &fds, - &exc_fds, - (timeout >= 0) ? &tv : NULL); - if (rc == SOCKET_ERROR) - errno= WSAGetLastError(); - if (rc == 0) - errno= ETIMEDOUT; -#endif - } - return rc; -} - - -size_t vio_real_read(Vio *vio, gptr buf, size_t size) -{ - size_t r; - - switch(vio->type) { -#ifdef HAVE_OPENSSL - case VIO_TYPE_SSL: - return my_ssl_read(vio, (char *)buf, size); - break; -#endif -#ifdef _WIN32 - case VIO_TYPE_NAMEDPIPE: - { - DWORD length= 0; - if (!ReadFile(vio->hPipe, buf, (DWORD)size, &length, NULL)) - return -1; - return length; - } - break; -#endif - default: - if (vio->async_context && vio->async_context->active) - r= my_recv_async(vio->async_context, - vio->sd, - buf, size, vio->read_timeout); - else - { - if (vio->async_context) - { - /* - If switching from non-blocking to blocking API usage, set the socket - back to blocking mode. - */ - my_bool old_mode; - vio_blocking(vio, TRUE, &old_mode); - } -#ifndef _WIN32 - do { - r= read(vio->sd, buf, size); - } while (r == -1 && errno == EINTR); - - while (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) - && vio->read_timeout > 0) - { - if (vio_wait_or_timeout(vio, TRUE, vio->write_timeout) < 1) - return 0; - do { - r= read(vio->sd, buf, size); - } while (r == -1 && errno == EINTR); - } -#else - { - WSABUF wsaData; - DWORD dwBytes = 0; - DWORD flags = 0; - - wsaData.len= size; - wsaData.buf= buf; - - if (WSARecv(vio->sd, &wsaData, 1, &dwBytes, &flags, NULL, NULL) == SOCKET_ERROR) - { - errno= WSAGetLastError(); - return 0; - } - r= (size_t)dwBytes; - } -#endif - } - break; - } - return r; -} - - -size_t vio_read(Vio * vio, gptr buf, size_t size) -{ - size_t r; - DBUG_ENTER("vio_read"); - DBUG_PRINT("enter", ("sd=%d size=%d", vio->sd, size)); - - if (!vio->cache) - DBUG_RETURN(vio_real_read(vio, buf, size)); - - if (vio->cache + vio->cache_size > vio->cache_pos) - { - r= MIN(size, vio->cache + vio->cache_size - vio->cache_pos); - memcpy(buf, vio->cache_pos, r); - vio->cache_pos+= r; - } - else if (size >= VIO_CACHE_MIN_SIZE) - { - r= vio_real_read(vio, buf, size); - } - else - { - r= vio_real_read(vio, vio->cache, VIO_CACHE_SIZE); - if (r > 0) - { - if (size < r) - { - vio->cache_size= r; /* might be < VIO_CACHE_SIZE */ - vio->cache_pos= vio->cache + size; - r= size; - } - memcpy(buf, vio->cache, r); - } - } - -#ifndef DBUG_OFF - if ((size_t)r == -1) - { - DBUG_PRINT("vio_error", ("Got error %d during read",socket_errno)); - } -#endif /* DBUG_OFF */ - DBUG_PRINT("exit", ("%u", (uint)r)); - DBUG_RETURN(r); -} - -/* - Return data from the beginning of the receive queue without removing - that data from the queue. A subsequent receive call will return the same data. -*/ -my_bool vio_read_peek(Vio *vio, size_t *bytes) -{ -#ifdef _WIN32 - if (ioctlsocket(vio->sd, FIONREAD, (unsigned long*)bytes)) - return TRUE; -#else - char buffer[1024]; - ssize_t length; - - vio_blocking(vio, 0, 0); - length= recv(vio->sd, &buffer, sizeof(buffer), MSG_PEEK); - if (length < 0) - return TRUE; - *bytes= length; -#endif - return FALSE; -} - - -size_t vio_write(Vio * vio, const gptr buf, size_t size) -{ - size_t r; - DBUG_ENTER("vio_write"); - DBUG_PRINT("enter", ("sd=%d size=%d", vio->sd, size)); -#ifdef HAVE_OPENSSL - if (vio->type == VIO_TYPE_SSL) - { - r= my_ssl_write(vio, (uchar *)buf, size); - DBUG_RETURN(r); - } -#endif -#ifdef _WIN32 - if ( vio->type == VIO_TYPE_NAMEDPIPE) - { - DWORD length; - if (!WriteFile(vio->hPipe, (char*) buf, (DWORD)size, &length, NULL)) - DBUG_RETURN(-1); - DBUG_RETURN(length); - } -#endif - if (vio->async_context && vio->async_context->active) - r= my_send_async(vio->async_context, vio->sd, buf, size, - vio->write_timeout); - else - { - if (vio->async_context) - { - /* - If switching from non-blocking to blocking API usage, set the socket - back to blocking mode. - */ - my_bool old_mode; - vio_blocking(vio, TRUE, &old_mode); - } -#ifndef _WIN32 - do { - r= send(vio->sd, buf, size, vio->write_timeout ? MSG_DONTWAIT : MSG_WAITALL); - } while (r == -1 && errno == EINTR); - - while (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && - vio->write_timeout > 0) - { - if (vio_wait_or_timeout(vio, FALSE, vio->write_timeout) < 1) - return 0; - do { - r= send(vio->sd, buf, size, vio->write_timeout ? MSG_DONTWAIT : MSG_WAITALL); - } while (r == -1 && errno == EINTR); - } -#else - { - WSABUF wsaData; - DWORD dwBytes = 0; - - wsaData.len= size; - wsaData.buf= (char *)buf; - - if (WSASend(vio->sd, &wsaData, 1, &dwBytes, 0, NULL, NULL) == SOCKET_ERROR) - { - errno= WSAGetLastError(); - DBUG_RETURN(0); - } - r= (size_t)dwBytes; - } -#endif - } -#ifndef DBUG_OFF - if ((size_t)r == -1) - { - DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno)); - } -#endif /* DBUG_OFF */ - DBUG_PRINT("exit", ("%u", (uint)r)); - DBUG_RETURN(r); -} - - -int vio_blocking(Vio *vio, my_bool block, my_bool *previous_mode) -{ - int *sd_flags= &vio->fcntl_mode; - int save_flags= vio->fcntl_mode; - my_bool tmp; - my_socket sock= vio->sd; - - if (vio->type == VIO_TYPE_NAMEDPIPE) - return 0; - - if (!previous_mode) - previous_mode= &tmp; - -#ifdef _WIN32 - *previous_mode= (*sd_flags & O_NONBLOCK) != 0; - *sd_flags = (block) ? *sd_flags & ~O_NONBLOCK : *sd_flags | O_NONBLOCK; - { - ulong arg= 1 - block; - if (ioctlsocket(sock, FIONBIO, (void *)&arg)) - { - vio->fcntl_mode= save_flags; - return(WSAGetLastError()); - } - } -#else -#if defined(O_NONBLOCK) - *previous_mode= (*sd_flags & O_NONBLOCK) != 0; - *sd_flags = (block) ? *sd_flags & ~O_NONBLOCK : *sd_flags | O_NONBLOCK; -#elif defined(O_NDELAY) - *previous_mode= (*sd_flags & O_NODELAY) != 0; - *sd_flags = (block) ? *sd_flags & ~O_NODELAY : *sd_flags | O_NODELAY; -#elif defined(FNDELAY) - *previous_mode= (*sd_flags & O_FNDELAY) != 0; - *sd_flags = (block) ? *sd_flags & ~O_FNDELAY : *sd_flags | O_FNDELAY; -#else -#error socket blocking is not supported on this platform -#endif - if (fcntl(sock, F_SETFL, *sd_flags) == -1) - { - vio->fcntl_mode= save_flags; - return errno; - } -#endif - return 0; -} - -my_bool -vio_is_blocking(Vio * vio) -{ - my_bool r; - DBUG_ENTER("vio_is_blocking"); - r = !(vio->fcntl_mode & O_NONBLOCK); - DBUG_PRINT("exit", ("%d", (int) r)); - DBUG_RETURN(r); -} - - -int vio_fastsend(Vio * vio __attribute__((unused))) -{ - int r=0; - DBUG_ENTER("vio_fastsend"); - -#ifdef IPTOS_THROUGHPUT - { -#ifndef __EMX__ - int tos = IPTOS_THROUGHPUT; - if (!setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos))) -#endif /* !__EMX__ */ - { - int nodelay = 1; - if (setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay, - sizeof(nodelay))) { - DBUG_PRINT("warning", - ("Couldn't set socket option for fast send")); - r= -1; - } - } - } -#endif /* IPTOS_THROUGHPUT */ - DBUG_PRINT("exit", ("%d", r)); - DBUG_RETURN(r); -} - -int vio_keepalive(Vio* vio, my_bool set_keep_alive) -{ - int r=0; - uint opt = 0; - DBUG_ENTER("vio_keepalive"); - DBUG_PRINT("enter", ("sd=%d set_keep_alive=%d", vio->sd, (int) - set_keep_alive)); - if (vio->type != VIO_TYPE_NAMEDPIPE) - { - if (set_keep_alive) - opt = 1; - r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, - sizeof(opt)); - } - DBUG_RETURN(r); -} - - -my_bool -vio_should_retry(Vio * vio __attribute__((unused))) -{ - int en = socket_errno; - return en == SOCKET_EAGAIN || en == SOCKET_EINTR || en == SOCKET_EWOULDBLOCK; -} - - -int vio_close(Vio * vio) -{ - int r; - DBUG_ENTER("vio_close"); -#ifdef HAVE_OPENSSL - if (vio->type == VIO_TYPE_SSL) - { - r = my_ssl_close(vio); - } -#endif -#ifdef _WIN32 - if (vio->type == VIO_TYPE_NAMEDPIPE) - { - r=CloseHandle(vio->hPipe); - } - else if (vio->type != VIO_CLOSED) -#endif /* _WIN32 */ - { - r=0; - if (shutdown(vio->sd,2)) - r= -1; - if (closesocket(vio->sd)) - r= -1; - } - if (r) - { - DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno)); - /* FIXME: error handling (not critical for MySQL) */ - } - vio->type= VIO_CLOSED; - vio->sd= -1; - DBUG_RETURN(r); -} - - -const char *vio_description(Vio * vio) -{ - return vio->desc; -} - -enum enum_vio_type vio_type(Vio* vio) -{ - return vio->type; -} - -my_socket vio_fd(Vio* vio) -{ - return vio->sd; -} - - -my_bool vio_peer_addr(Vio * vio, char *buf) -{ - DBUG_ENTER("vio_peer_addr"); - DBUG_PRINT("enter", ("sd=%d", vio->sd)); - if (vio->localhost) - { - strmov(buf,"127.0.0.1"); - } - else - { - socklen_t addrLen = sizeof(struct sockaddr); - if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)), - &addrLen) != 0) - { - DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno)); - DBUG_RETURN(1); - } - my_inet_ntoa(vio->remote.sin_addr,buf); - } - DBUG_PRINT("exit", ("addr=%s", buf)); - DBUG_RETURN(0); -} - - -void vio_in_addr(Vio *vio, struct in_addr *in) -{ - DBUG_ENTER("vio_in_addr"); - if (vio->localhost) - bzero((char*) in, sizeof(*in)); /* This should never be executed */ - else - *in=vio->remote.sin_addr; - DBUG_VOID_RETURN; -} - - -/* Return 0 if there is data to be read */ -/* -my_bool vio_poll_read(Vio *vio,uint timeout) -{ -#ifndef HAVE_POLL - return 0; -#else - struct pollfd fds; - int res; - DBUG_ENTER("vio_poll"); - fds.fd=vio->sd; - fds.events=POLLIN; - fds.revents=0; - if ((res=poll(&fds,1,(int) timeout*1000)) <= 0) - { - DBUG_RETURN(res < 0 ? 0 : 1); - } - DBUG_RETURN(fds.revents & POLLIN ? 0 : 1); -#endif -} -*/ - -#endif /* HAVE_VIO */ diff --git a/plugins/io/remote_io.c b/plugins/io/remote_io.c index 7a01b0e7..2b1f326f 100644 --- a/plugins/io/remote_io.c +++ b/plugins/io/remote_io.c @@ -94,6 +94,7 @@ mysql_declare_client_plugin(REMOTEIO) "Georg Richter", "Remote IO plugin", {0,1,0}, + "LGPL", ma_rio_init, ma_rio_deinit, &ma_rio_methods diff --git a/unittest/libmariadb/CMakeLists.txt b/unittest/libmariadb/CMakeLists.txt index 97fbd06f..22511027 100644 --- a/unittest/libmariadb/CMakeLists.txt +++ b/unittest/libmariadb/CMakeLists.txt @@ -62,7 +62,7 @@ ENDIF() FOREACH(API_TEST ${API_TESTS}) ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c) - TARGET_LINK_LIBRARIES(${API_TEST} mytap mariadbclient ${EXTRA_LIBS}) + TARGET_LINK_LIBRARIES(${API_TEST} mytap libmariadb ${EXTRA_LIBS}) ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST}) SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 120) ENDFOREACH(API_TEST) diff --git a/unittest/libmariadb/misc.c b/unittest/libmariadb/misc.c index 499547dd..2555514c 100644 --- a/unittest/libmariadb/misc.c +++ b/unittest/libmariadb/misc.c @@ -177,35 +177,6 @@ static int test_bug31418(MYSQL *mysql) return OK; } -/* - Altough mysql_create_db(), mysql_rm_db() are deprecated since 4.0 they - should not crash server and should not hang in case of errors. - - Since those functions can't be seen in modern API (unless client library - was compiled with USE_OLD_FUNCTIONS define) we use simple_command() macro. -*/ -static int test_bug6081(MYSQL *mysql) -{ - int rc; - - if (mysql_get_server_version(mysql) < 50100) { - diag("Test requires MySQL Server version 5.1 or above"); - return SKIP; - } - - rc= simple_command(mysql, MYSQL_COM_DROP_DB, (char*) schema, - (ulong)strlen(schema), 0U, NULL); - FAIL_IF(!rc, "Error expected"); - - rc= simple_command(mysql, MYSQL_COM_CREATE_DB, (char*) schema, - (ulong)strlen(schema), 0U, NULL); - FAIL_IF(!rc, "Error expected"); - - rc= mysql_select_db(mysql, schema); - check_mysql_rc(rc, mysql); - return OK; -} - /* Query processing */ static int test_debug_example(MYSQL *mysql) @@ -1051,8 +1022,8 @@ static int test_remote2(MYSQL *my) struct my_tests_st my_tests[] = { {"test_remote1", test_remote1, TEST_CONNECTION_NEW, 0, NULL, NULL}, - {"test_remote2", test_remote2, TEST_CONNECTION_NEW, 0, NULL, NULL}, - {"test_conc117", test_conc117, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_remote2", test_remote2, TEST_CONNECTION_NEW, 0, NULL, NULL}, + {"test_conc117", test_conc117, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_conc_114", test_conc_114, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_connect_attrs", test_connect_attrs, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc49", test_conc49, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, @@ -1061,7 +1032,6 @@ struct my_tests_st my_tests[] = { {"test_debug_example", test_debug_example, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_bug29692", test_bug29692, TEST_CONNECTION_NEW, CLIENT_FOUND_ROWS, NULL, NULL}, {"test_bug31418", test_bug31418, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, - {"test_bug6081", test_bug6081, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_frm_bug", test_frm_bug, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_wl4166_1", test_wl4166_1, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_wl4166_2", test_wl4166_2, TEST_CONNECTION_NEW, 0, NULL, NULL}, diff --git a/unittest/libmariadb/my_test.h b/unittest/libmariadb/my_test.h index 2ad3feaf..8ed79d57 100644 --- a/unittest/libmariadb/my_test.h +++ b/unittest/libmariadb/my_test.h @@ -507,7 +507,9 @@ void run_tests(struct my_tests_st *test) { return; /* default doesn't work anymore */ } else if (mysql && !(test[i].connection & TEST_CONNECTION_DONT_CLOSE)) + { mysql_close(mysql); + } } else { skip(1, "%s", test[i].skipmsg); }