diff options
author | Vladislav Vaintroub <vvaintroub@mysql.com> | 2009-11-13 13:26:16 +0100 |
---|---|---|
committer | Vladislav Vaintroub <vvaintroub@mysql.com> | 2009-11-13 13:26:16 +0100 |
commit | 63546824fc0d52ba86820b1d178dc537b5f718ee (patch) | |
tree | 5351c4626f402917a764b36f5e0825b90264f258 /vio | |
parent | 91916e7f054f4afd33bfda327a45589f2e2b7f16 (diff) | |
parent | 780871d8b90fe3146db39b4be65ebedb309b9f9b (diff) | |
download | mariadb-git-63546824fc0d52ba86820b1d178dc537b5f718ee.tar.gz |
automerge
Diffstat (limited to 'vio')
-rw-r--r-- | vio/vio.c | 27 | ||||
-rw-r--r-- | vio/vio_priv.h | 5 | ||||
-rw-r--r-- | vio/viosocket.c | 120 | ||||
-rw-r--r-- | vio/viosslfactories.c | 61 |
4 files changed, 115 insertions, 98 deletions
diff --git a/vio/vio.c b/vio/vio.c index e088687098b..fd8e2e5a402 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -43,7 +43,7 @@ static void vio_init(Vio* vio, enum enum_vio_type type, if ((flags & VIO_BUFFERED_READ) && !(vio->read_buffer= (char*)my_malloc(VIO_READ_BUFFER_SIZE, MYF(MY_WME)))) flags&= ~VIO_BUFFERED_READ; -#ifdef __WIN__ +#ifdef _WIN32 if (type == VIO_TYPE_NAMEDPIPE) { vio->viodelete =vio_delete; @@ -59,9 +59,16 @@ static void vio_init(Vio* vio, enum enum_vio_type type, vio->in_addr =vio_in_addr; vio->vioblocking =vio_blocking; vio->is_blocking =vio_is_blocking; - vio->timeout =vio_ignore_timeout; + + vio->timeout=vio_win32_timeout; + /* Set default timeout */ + vio->read_timeout_millis = INFINITE; + vio->write_timeout_millis = INFINITE; + + memset(&(vio->pipe_overlapped), 0, sizeof(OVERLAPPED)); + vio->pipe_overlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL); + DBUG_VOID_RETURN; } - else /* default is VIO_TYPE_TCPIP */ #endif #ifdef HAVE_SMEM if (type == VIO_TYPE_SHARED_MEMORY) @@ -79,9 +86,14 @@ static void vio_init(Vio* vio, enum enum_vio_type type, vio->in_addr =vio_in_addr; vio->vioblocking =vio_blocking; vio->is_blocking =vio_is_blocking; - vio->timeout =vio_ignore_timeout; + + /* Currently, shared memory is on Windows only, hence the below is ok*/ + vio->timeout= vio_win32_timeout; + /* Set default timeout */ + vio->read_timeout_millis= INFINITE; + vio->write_timeout_millis= INFINITE; + DBUG_VOID_RETURN; } - else #endif #ifdef HAVE_OPENSSL if (type == VIO_TYPE_SSL) @@ -100,8 +112,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type, vio->vioblocking =vio_ssl_blocking; vio->is_blocking =vio_is_blocking; vio->timeout =vio_timeout; + DBUG_VOID_RETURN; } - else /* default is VIO_TYPE_TCPIP */ #endif /* HAVE_OPENSSL */ { vio->viodelete =vio_delete; @@ -193,7 +205,7 @@ Vio *vio_new_win32pipe(HANDLE hPipe) } #ifdef HAVE_SMEM -Vio *vio_new_win32shared_memory(NET *net,HANDLE handle_file_map, HANDLE handle_map, +Vio *vio_new_win32shared_memory(HANDLE handle_file_map, HANDLE handle_map, HANDLE event_server_wrote, HANDLE event_server_read, HANDLE event_client_wrote, HANDLE event_client_read, HANDLE event_conn_closed) @@ -212,7 +224,6 @@ Vio *vio_new_win32shared_memory(NET *net,HANDLE handle_file_map, HANDLE handle_m vio->event_conn_closed= event_conn_closed; vio->shared_memory_remain= 0; vio->shared_memory_pos= handle_map; - vio->net= net; strmov(vio->desc, "shared memory"); } DBUG_RETURN(vio); diff --git a/vio/vio_priv.h b/vio/vio_priv.h index 792fad4cc66..21fa80143cd 100644 --- a/vio/vio_priv.h +++ b/vio/vio_priv.h @@ -25,7 +25,10 @@ #include <m_string.h> #include <violite.h> -void vio_ignore_timeout(Vio *vio, uint which, uint timeout); +#ifdef _WIN32 +void vio_win32_timeout(Vio *vio, uint which, uint timeout); +#endif + void vio_timeout(Vio *vio,uint which, uint timeout); #ifdef HAVE_OPENSSL diff --git a/vio/viosocket.c b/vio/viosocket.c index 2a22f8c7c15..c929cac2a05 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -261,19 +261,13 @@ int vio_close(Vio * vio) { int r=0; DBUG_ENTER("vio_close"); -#ifdef __WIN__ - if (vio->type == VIO_TYPE_NAMEDPIPE) - { -#if defined(MYSQL_SERVER) - CancelIo(vio->hPipe); - DisconnectNamedPipe(vio->hPipe); -#endif - r=CloseHandle(vio->hPipe); - } - else -#endif /* __WIN__ */ + if (vio->type != VIO_CLOSED) { + DBUG_ASSERT(vio->type == VIO_TYPE_TCPIP || + vio->type == VIO_TYPE_SOCKET || + vio->type == VIO_TYPE_SSL); + DBUG_ASSERT(vio->sd >= 0); if (shutdown(vio->sd, SHUT_RDWR)) r= -1; @@ -417,44 +411,97 @@ void vio_timeout(Vio *vio, uint which, uint timeout) #ifdef __WIN__ -size_t vio_read_pipe(Vio * vio, uchar* buf, size_t size) + +/* + Finish pending IO on pipe. Honor wait timeout +*/ +static int pipe_complete_io(Vio* vio, char* buf, size_t size, DWORD timeout_millis) { DWORD length; + DWORD ret; + + DBUG_ENTER("pipe_complete_io"); + + ret= WaitForSingleObject(vio->pipe_overlapped.hEvent, timeout_millis); + /* + WaitForSingleObjects will normally return WAIT_OBJECT_O (success, IO completed) + or WAIT_TIMEOUT. + */ + if(ret != WAIT_OBJECT_0) + { + CancelIo(vio->hPipe); + DBUG_PRINT("error",("WaitForSingleObject() returned %d", ret)); + DBUG_RETURN(-1); + } + + if (!GetOverlappedResult(vio->hPipe,&(vio->pipe_overlapped),&length, FALSE)) + { + DBUG_PRINT("error",("GetOverlappedResult() returned last error %d", + GetLastError())); + DBUG_RETURN(-1); + } + + DBUG_RETURN(length); +} + + +size_t vio_read_pipe(Vio * vio, uchar *buf, size_t size) +{ + DWORD bytes_read; DBUG_ENTER("vio_read_pipe"); DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %u", vio->sd, (long) buf, (uint) size)); - if (!ReadFile(vio->hPipe, buf, size, &length, NULL)) - DBUG_RETURN(-1); + if (!ReadFile(vio->hPipe, buf, (DWORD)size, &bytes_read, + &(vio->pipe_overlapped))) + { + if (GetLastError() != ERROR_IO_PENDING) + { + DBUG_PRINT("error",("ReadFile() returned last error %d", + GetLastError())); + DBUG_RETURN((size_t)-1); + } + bytes_read= pipe_complete_io(vio, buf, size,vio->read_timeout_millis); + } - DBUG_PRINT("exit", ("%d", length)); - DBUG_RETURN((size_t) length); + DBUG_PRINT("exit", ("%d", bytes_read)); + DBUG_RETURN(bytes_read); } size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size) { - DWORD length; + DWORD bytes_written; DBUG_ENTER("vio_write_pipe"); DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %u", vio->sd, (long) buf, (uint) size)); - if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL)) - DBUG_RETURN(-1); + if (!WriteFile(vio->hPipe, buf, (DWORD)size, &bytes_written, + &(vio->pipe_overlapped))) + { + if (GetLastError() != ERROR_IO_PENDING) + { + DBUG_PRINT("vio_error",("WriteFile() returned last error %d", + GetLastError())); + DBUG_RETURN((size_t)-1); + } + bytes_written = pipe_complete_io(vio, (char *)buf, size, + vio->write_timeout_millis); + } - DBUG_PRINT("exit", ("%d", length)); - DBUG_RETURN((size_t) length); + DBUG_PRINT("exit", ("%d", bytes_written)); + DBUG_RETURN(bytes_written); } + int vio_close_pipe(Vio * vio) { int r; DBUG_ENTER("vio_close_pipe"); -#if defined(MYSQL_SERVER) - CancelIo(vio->hPipe); + + CloseHandle(vio->pipe_overlapped.hEvent); DisconnectNamedPipe(vio->hPipe); -#endif - r=CloseHandle(vio->hPipe); + r= CloseHandle(vio->hPipe); if (r) { DBUG_PRINT("vio_error", ("close() failed, error: %d",GetLastError())); @@ -466,10 +513,23 @@ int vio_close_pipe(Vio * vio) } -void vio_ignore_timeout(Vio *vio __attribute__((unused)), - uint which __attribute__((unused)), - uint timeout __attribute__((unused))) +void vio_win32_timeout(Vio *vio, uint which , uint timeout_sec) { + DWORD timeout_millis; + /* + Windows is measuring timeouts in milliseconds. Check for possible int + overflow. + */ + if (timeout_sec > UINT_MAX/1000) + timeout_millis= INFINITE; + else + timeout_millis= timeout_sec * 1000; + + /* which == 1 means "write", which == 0 means "read".*/ + if(which) + vio->write_timeout_millis= timeout_millis; + else + vio->read_timeout_millis= timeout_millis; } @@ -504,7 +564,7 @@ size_t vio_read_shared_memory(Vio * vio, uchar* buf, size_t size) WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail. We can't read anything */ if (WaitForMultipleObjects(array_elements(events), events, FALSE, - vio->net->read_timeout*1000) != WAIT_OBJECT_0) + vio->read_timeout_millis) != WAIT_OBJECT_0) { DBUG_RETURN(-1); }; @@ -561,7 +621,7 @@ size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size) while (remain != 0) { if (WaitForMultipleObjects(array_elements(events), events, FALSE, - vio->net->write_timeout*1000) != WAIT_OBJECT_0) + vio->write_timeout_millis) != WAIT_OBJECT_0) { DBUG_RETURN((size_t) -1); } diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 6a6e08818c6..51d049b18b9 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -144,55 +144,6 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file, } -static int -vio_verify_callback(int ok, X509_STORE_CTX *ctx) -{ - char buf[256]; - X509 *err_cert; - - DBUG_ENTER("vio_verify_callback"); - DBUG_PRINT("enter", ("ok: %d ctx: 0x%lx", ok, (long) ctx)); - - err_cert= X509_STORE_CTX_get_current_cert(ctx); - X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); - DBUG_PRINT("info", ("cert: %s", buf)); - if (!ok) - { - int err, depth; - err= X509_STORE_CTX_get_error(ctx); - depth= X509_STORE_CTX_get_error_depth(ctx); - - DBUG_PRINT("error",("verify error: %d '%s'",err, - X509_verify_cert_error_string(err))); - /* - Approve cert if depth is greater then "verify_depth", currently - verify_depth is always 0 and there is no way to increase it. - */ - if (verify_depth >= depth) - ok= 1; - } - switch (ctx->error) - { - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256); - DBUG_PRINT("info",("issuer= %s\n", buf)); - break; - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - DBUG_PRINT("error", ("notBefore")); - /*ASN1_TIME_print_fp(stderr,X509_get_notBefore(ctx->current_cert));*/ - break; - case X509_V_ERR_CERT_HAS_EXPIRED: - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - DBUG_PRINT("error", ("notAfter error")); - /*ASN1_TIME_print_fp(stderr,X509_get_notAfter(ctx->current_cert));*/ - break; - } - DBUG_PRINT("exit", ("%d", ok)); - DBUG_RETURN(ok); -} - - #ifdef __NETWARE__ /* NetWare SSL cleanup */ @@ -354,11 +305,7 @@ new_VioSSLConnectorFd(const char *key_file, const char *cert_file, /* Init the VioSSLFd as a "connector" ie. the client side */ - /* - The verify_callback function is used to control the behaviour - when the SSL_VERIFY_PEER flag is set. - */ - SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback); + SSL_CTX_set_verify(ssl_fd->ssl_context, verify, NULL); return ssl_fd; } @@ -382,11 +329,7 @@ new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, /* Set max number of cached sessions, returns the previous size */ SSL_CTX_sess_set_cache_size(ssl_fd->ssl_context, 128); - /* - The verify_callback function is used to control the behaviour - when the SSL_VERIFY_PEER flag is set. - */ - SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback); + SSL_CTX_set_verify(ssl_fd->ssl_context, verify, NULL); /* Set session_id - an identifier for this server session |