diff options
Diffstat (limited to 'vio')
-rw-r--r-- | vio/Makefile.am | 4 | ||||
-rw-r--r-- | vio/vio.c | 82 | ||||
-rw-r--r-- | vio/vio_priv.h | 2 | ||||
-rw-r--r-- | vio/viosocket.c | 261 |
4 files changed, 298 insertions, 51 deletions
diff --git a/vio/Makefile.am b/vio/Makefile.am index 56ab21e8922..9c961025080 100644 --- a/vio/Makefile.am +++ b/vio/Makefile.am @@ -14,7 +14,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES= -I$(srcdir)/../include -I../include $(openssl_includes) +INCLUDES= -I$(top_srcdir)/include $(openssl_includes) LDADD= @CLIENT_EXTRA_LDFLAGS@ $(openssl_libs) pkglib_LIBRARIES= libvio.a noinst_PROGRAMS = test-ssl test-sslserver test-sslclient @@ -23,7 +23,7 @@ test_ssl_SOURCES= test-ssl.c test_ssl_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \ ../mysys/libmysys.a ../strings/libmystrings.a \ $(openssl_libs) -test_sslserver_SOURCES= test-sslserver.c +test_sslserver_SOURCES= test-sslserver.c test_sslserver_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \ ../mysys/libmysys.a ../strings/libmystrings.a \ $(openssl_libs) diff --git a/vio/vio.c b/vio/vio.c index 2b745ab3ec6..978780d2632 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -39,7 +39,45 @@ void vio_reset(Vio* vio, enum enum_vio_type type, vio->sd = sd; vio->hPipe = hPipe; vio->localhost= localhost; -#ifdef HAVE_VIO +#ifdef HAVE_VIO +#ifdef __WIN__ + if (type == VIO_TYPE_NAMEDPIPE) + { + vio->viodelete =vio_delete; + vio->vioerrno =vio_errno; + vio->read =vio_read_pipe; + vio->write =vio_write_pipe; + vio->fastsend =vio_fastsend; + vio->viokeepalive =vio_keepalive; + vio->should_retry =vio_should_retry; + vio->vioclose =vio_close_pipe; + vio->peer_addr =vio_peer_addr; + vio->in_addr =vio_in_addr; + vio->vioblocking =vio_blocking; + vio->is_blocking =vio_is_blocking; + vio->timeout =vio_ignore_timeout; + } + else /* default is VIO_TYPE_TCPIP */ +#endif +#ifdef HAVE_SMEM + if (type == VIO_TYPE_SHARED_MEMORY) + { + vio->viodelete =vio_delete; + vio->vioerrno =vio_errno; + vio->read =vio_read_shared_memory; + vio->write =vio_write_shared_memory; + vio->fastsend =vio_fastsend; + vio->viokeepalive =vio_keepalive; + vio->should_retry =vio_should_retry; + vio->vioclose =vio_close_shared_memory; + vio->peer_addr =vio_peer_addr; + vio->in_addr =vio_in_addr; + vio->vioblocking =vio_blocking; + vio->is_blocking =vio_is_blocking; + vio->timeout =vio_ignore_timeout; + } + else +#endif #ifdef HAVE_OPENSSL if (type == VIO_TYPE_SSL) { @@ -130,4 +168,46 @@ Vio *vio_new_win32pipe(HANDLE hPipe) DBUG_RETURN(vio); } +#ifdef HAVE_SMEM +Vio *vio_new_win32shared_memory(NET *net,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) +{ + Vio *vio; + DBUG_ENTER("vio_new_win32shared_memory"); + if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME)))) + { + vio_reset(vio, VIO_TYPE_SHARED_MEMORY, 0, 0, TRUE); + vio->handle_file_map= handle_file_map; + vio->handle_map= handle_map; + vio->event_server_wrote= event_server_wrote; + vio->event_server_read= event_server_read; + vio->event_client_wrote= event_client_wrote; + vio->event_client_read= event_client_read; + 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); +} +#endif #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) +#ifdef HAVE_VIO /*WAX*/ + vio->vioclose(vio); +#else + vio_close(vio); +#endif + my_free((gptr) vio,MYF(0)); + } +} diff --git a/vio/vio_priv.h b/vio/vio_priv.h index 66a9bde4e0d..9a925a2c4c9 100644 --- a/vio/vio_priv.h +++ b/vio/vio_priv.h @@ -23,6 +23,8 @@ #include <m_string.h> #include <violite.h> +void vio_ignore_timeout(Vio *vio, uint timeout); + #ifdef HAVE_OPENSSL #include "my_net.h" /* needed because of struct in_addr */ diff --git a/vio/viosocket.c b/vio/viosocket.c index f45c9dd98c4..77922594469 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -23,18 +23,6 @@ #include "vio_priv.h" -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((gptr) vio,MYF(0)); - } -} - int vio_errno(Vio *vio __attribute__((unused))) { return socket_errno; /* On Win32 this mapped to WSAGetLastError() */ @@ -46,14 +34,8 @@ int vio_read(Vio * vio, gptr buf, int size) int r; DBUG_ENTER("vio_read"); DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size)); + #ifdef __WIN__ - if (vio->type == VIO_TYPE_NAMEDPIPE) - { - DWORD length; - if (!ReadFile(vio->hPipe, buf, size, &length, NULL)) - DBUG_RETURN(-1); - DBUG_RETURN(length); - } r = recv(vio->sd, buf, size,0); #else errno=0; /* For linux */ @@ -75,15 +57,8 @@ int vio_write(Vio * vio, const gptr buf, int size) int r; DBUG_ENTER("vio_write"); DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size)); -#if defined( __WIN__) - if ( vio->type == VIO_TYPE_NAMEDPIPE) - { - DWORD length; - if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL)) - DBUG_RETURN(-1); - DBUG_RETURN(length); - } - r = send(vio->sd, buf, size, 0); +#ifdef __WIN__ + r = send(vio->sd, buf, size,0); #else r = write(vio->sd, buf, size); #endif /* __WIN__ */ @@ -97,7 +72,6 @@ int vio_write(Vio * vio, const gptr buf, int size) DBUG_RETURN(r); } - int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode, my_bool *old_mode) { @@ -168,23 +142,29 @@ int vio_fastsend(Vio * vio __attribute__((unused))) int r=0; DBUG_ENTER("vio_fastsend"); -#ifdef IPTOS_THROUGHPUT +#if defined(IPTOS_THROUGHPUT) && !defined(__EMX__) { -#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; - } - } + r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)); + } +#endif /* IPTOS_THROUGHPUT && !__EMX__ */ + if (!r) + { +#ifdef __WIN__ + BOOL nodelay= 1; + r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (const char*) &nodelay, + sizeof(nodelay)); +#else + int nodelay = 1; + r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay, + sizeof(nodelay)); +#endif /* __WIN__ */ + } + if (r) + { + DBUG_PRINT("warning", ("Couldn't set socket option for fast send")); + r= -1; } -#endif /* IPTOS_THROUGHPUT */ DBUG_PRINT("exit", ("%d", r)); DBUG_RETURN(r); } @@ -218,7 +198,7 @@ vio_should_retry(Vio * vio __attribute__((unused))) int vio_close(Vio * vio) { - int r; + int r=0; DBUG_ENTER("vio_close"); #ifdef __WIN__ if (vio->type == VIO_TYPE_NAMEDPIPE) @@ -229,10 +209,11 @@ int vio_close(Vio * vio) #endif r=CloseHandle(vio->hPipe); } - else if (vio->type != VIO_CLOSED) + else #endif /* __WIN__ */ + if (vio->type != VIO_CLOSED) { - r=0; + DBUG_ASSERT(vio->sd >= 0); if (shutdown(vio->sd,2)) r= -1; if (closesocket(vio->sd)) @@ -276,8 +257,8 @@ my_bool vio_peer_addr(Vio * vio, char *buf, uint16 *port) } else { - size_socket addrLen = sizeof(struct sockaddr); - if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)), + size_socket addrLen = sizeof(vio->remote); + if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote), &addrLen) != 0) { DBUG_PRINT("exit", ("getpeername gave error: %d", socket_errno)); @@ -345,3 +326,187 @@ void vio_timeout(Vio *vio __attribute__((unused)), sizeof(wait_timeout)); #endif /* __WIN__ */ } + + +#ifdef __WIN__ +int vio_read_pipe(Vio * vio, gptr buf, int size) +{ + DWORD length; + DBUG_ENTER("vio_read_pipe"); + DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size)); + + if (!ReadFile(vio->hPipe, buf, size, &length, NULL)) + DBUG_RETURN(-1); + + DBUG_PRINT("exit", ("%d", length)); + DBUG_RETURN(length); +} + + +int vio_write_pipe(Vio * vio, const gptr buf, int size) +{ + DWORD length; + DBUG_ENTER("vio_write_pipe"); + DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size)); + + if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL)) + DBUG_RETURN(-1); + + DBUG_PRINT("exit", ("%d", length)); + DBUG_RETURN(length); +} + +int vio_close_pipe(Vio * vio) +{ + int r; + DBUG_ENTER("vio_close_pipe"); +#if defined(__NT__) && defined(MYSQL_SERVER) + CancelIo(vio->hPipe); + DisconnectNamedPipe(vio->hPipe); +#endif + r=CloseHandle(vio->hPipe); + if (r) + { + DBUG_PRINT("vio_error", ("close() failed, error: %d",GetLastError())); + /* FIXME: error handling (not critical for MySQL) */ + } + vio->type= VIO_CLOSED; + vio->sd= -1; + DBUG_RETURN(r); +} + + +void vio_ignore_timeout(Vio *vio __attribute__((unused)), + uint timeout __attribute__((unused))) +{ +} + + +#ifdef HAVE_SMEM + +int vio_read_shared_memory(Vio * vio, gptr buf, int size) +{ + int length; + int remain_local; + char *current_postion; + + DBUG_ENTER("vio_read_shared_memory"); + DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size)); + + remain_local = size; + current_postion=buf; + do + { + if (vio->shared_memory_remain == 0) + { + HANDLE events[2]; + events[0]= vio->event_server_wrote; + events[1]= vio->event_conn_closed; + /* + WaitForMultipleObjects can return next values: + WAIT_OBJECT_0+0 - event from vio->event_server_wrote + WAIT_OBJECT_0+1 - event from vio->event_conn_closed. We can't read anything + WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail. We can't read anything + */ + if (WaitForMultipleObjects(2, (HANDLE*)&events,FALSE, + vio->net->read_timeout*1000) != WAIT_OBJECT_0) + { + DBUG_RETURN(-1); + }; + + vio->shared_memory_pos = vio->handle_map; + vio->shared_memory_remain = uint4korr((ulong*)vio->shared_memory_pos); + vio->shared_memory_pos+=4; + } + + length = size; + + if (vio->shared_memory_remain < length) + length = vio->shared_memory_remain; + if (length > remain_local) + length = remain_local; + + memcpy(current_postion,vio->shared_memory_pos,length); + + vio->shared_memory_remain-=length; + vio->shared_memory_pos+=length; + current_postion+=length; + remain_local-=length; + + if (!vio->shared_memory_remain) + if (!SetEvent(vio->event_client_read)) DBUG_RETURN(-1); + } while (remain_local); + length = size; + + DBUG_PRINT("exit", ("%d", length)); + DBUG_RETURN(length); +} + + +int vio_write_shared_memory(Vio * vio, const gptr buf, int size) +{ + int length; + uint remain; + HANDLE pos; + int sz; + char *current_postion; + + DBUG_ENTER("vio_write_shared_memory"); + DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size)); + + remain = size; + current_postion = buf; + while (remain != 0) + { + if (WaitForSingleObject(vio->event_server_read, vio->net->write_timeout*1000) + != WAIT_OBJECT_0) + { + DBUG_RETURN(-1); + }; + + sz = remain > shared_memory_buffer_length ? shared_memory_buffer_length: remain; + + int4store(vio->handle_map,sz); + pos = vio->handle_map + 4; + memcpy(pos,current_postion,sz); + remain-=sz; + current_postion+=sz; + if (!SetEvent(vio->event_client_wrote)) DBUG_RETURN(-1); + } + length = size; + + DBUG_PRINT("exit", ("%d", length)); + DBUG_RETURN(length); +} + + +int vio_close_shared_memory(Vio * vio) +{ + int r; + DBUG_ENTER("vio_close_shared_memory"); + if (vio->type != VIO_CLOSED) + { + /* + Set event_conn_closed for notification of both client and server that + connection is closed + */ + SetEvent(vio->event_conn_closed); + /* + Close all handlers. UnmapViewOfFile and CloseHandle return non-zero + result if they are success. + */ + r= UnmapViewOfFile(vio->handle_map) || CloseHandle(vio->event_server_wrote) || + CloseHandle(vio->event_server_read) || CloseHandle(vio->event_client_wrote) || + CloseHandle(vio->event_client_read) || CloseHandle(vio->handle_file_map); + if (!r) + { + DBUG_PRINT("vio_error", ("close() failed, error: %d",r)); + /* FIXME: error handling (not critical for MySQL) */ + } + } + vio->type= VIO_CLOSED; + vio->sd= -1; + DBUG_RETURN(!r); +} +#endif /* HAVE_SMEM */ +#endif /* __WIN__ */ |