diff options
author | Konstantin Osipov <kostja@sun.com> | 2009-11-20 17:18:37 +0300 |
---|---|---|
committer | Konstantin Osipov <kostja@sun.com> | 2009-11-20 17:18:37 +0300 |
commit | 34b11fb627df93e395158a27f48baa1c049ddf85 (patch) | |
tree | 126efa7bce0c3c70a1d3c3cb0099c6615f951e39 /vio/viosocket.c | |
parent | 3937a79886f9c3a1e0c998e66565a71b4a87d984 (diff) | |
parent | 5aeeaaf507ac87f6ff56806fe8a356cea7d4a48f (diff) | |
download | mariadb-git-34b11fb627df93e395158a27f48baa1c049ddf85.tar.gz |
Merge with next-mr
Diffstat (limited to 'vio/viosocket.c')
-rw-r--r-- | vio/viosocket.c | 166 |
1 files changed, 158 insertions, 8 deletions
diff --git a/vio/viosocket.c b/vio/viosocket.c index 89b3e36eb20..86268795e60 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -350,28 +350,163 @@ void vio_in_addr(Vio *vio, struct in_addr *in) } -/* Return 0 if there is data to be read */ +/** + Indicate whether there is data to read on a given socket. + + @note An exceptional condition event and/or errors are + interpreted as if there is data to read. + + @param sd A connected socket. + @param timeout Maximum time in seconds to poll. + + @retval FALSE There is data to read. + @retval TRUE There is no data to read. +*/ -my_bool vio_poll_read(Vio *vio,uint timeout) +static my_bool socket_poll_read(my_socket sd, uint timeout) { -#ifndef HAVE_POLL - return 0; -#else +#ifdef __WIN__ + int res; + my_socket fd= sd; + fd_set readfds, errorfds; + struct timeval tm; + DBUG_ENTER("socket_poll_read"); + tm.tv_sec= timeout; + tm.tv_usec= 0; + FD_ZERO(&readfds); + FD_ZERO(&errorfds); + FD_SET(fd, &readfds); + FD_SET(fd, &errorfds); + if ((res= select(fd, &readfds, NULL, &errorfds, &tm) <= 0)) + { + DBUG_RETURN(res < 0 ? 0 : 1); + } + res= FD_ISSET(fd, &readfds) || FD_ISSET(fd, &errorfds); + DBUG_RETURN(!res); +#elif defined(HAVE_POLL) struct pollfd fds; int res; - DBUG_ENTER("vio_poll"); - fds.fd=vio->sd; + DBUG_ENTER("socket_poll_read"); + fds.fd=sd; fds.events=POLLIN; fds.revents=0; if ((res=poll(&fds,1,(int) timeout*1000)) <= 0) { DBUG_RETURN(res < 0 ? 0 : 1); /* Don't return 1 on errors */ } - DBUG_RETURN(fds.revents & POLLIN ? 0 : 1); + DBUG_RETURN(fds.revents & (POLLIN | POLLERR | POLLHUP) ? 0 : 1); +#else + return 0; #endif } +/** + Retrieve the amount of data that can be read from a socket. + + @param vio A VIO object. + @param bytes[out] The amount of bytes available. + + @retval FALSE Success. + @retval TRUE Failure. +*/ + +static my_bool socket_peek_read(Vio *vio, uint *bytes) +{ +#ifdef __WIN__ + int len; + if (ioctlsocket(vio->sd, FIONREAD, &len)) + return TRUE; + *bytes= len; + return FALSE; +#elif FIONREAD_IN_SYS_IOCTL + int len; + if (ioctl(vio->sd, FIONREAD, &len) < 0) + return TRUE; + *bytes= len; + return FALSE; +#else + char buf[1024]; + ssize_t res= recv(vio->sd, &buf, sizeof(buf), MSG_PEEK); + if (res < 0) + return TRUE; + *bytes= res; + return FALSE; +#endif +} + + +/** + Indicate whether there is data to read on a given socket. + + @remark Errors are interpreted as if there is data to read. + + @param sd A connected socket. + @param timeout Maximum time in seconds to wait. + + @retval FALSE There is data (or EOF) to read. Also FALSE if error. + @retval TRUE There is _NO_ data to read or timed out. +*/ + +my_bool vio_poll_read(Vio *vio, uint timeout) +{ + my_socket sd= vio->sd; + DBUG_ENTER("vio_poll_read"); +#ifdef HAVE_OPENSSL + if (vio->type == VIO_TYPE_SSL) + sd= SSL_get_fd((SSL*) vio->ssl_arg); +#endif + DBUG_RETURN(socket_poll_read(sd, timeout)); +} + + +/** + Determine if the endpoint of a connection is still available. + + @remark The socket is assumed to be disconnected if an EOF + condition is encountered. + + @param vio The VIO object. + + @retval TRUE EOF condition not found. + @retval FALSE EOF condition is signaled. +*/ + +my_bool vio_is_connected(Vio *vio) +{ + uint bytes= 0; + DBUG_ENTER("vio_is_connected"); + + /* In the presence of errors the socket is assumed to be connected. */ + + /* + The first step of detecting a EOF condition is veryfing + whether there is data to read. Data in this case would + be the EOF. + */ + if (vio_poll_read(vio, 0)) + DBUG_RETURN(TRUE); + + /* + The second step is read() or recv() from the socket returning + 0 (EOF). Unfortunelly, it's not possible to call read directly + as we could inadvertently read meaningful connection data. + Simulate a read by retrieving the number of bytes available to + read -- 0 meaning EOF. + */ + if (socket_peek_read(vio, &bytes)) + DBUG_RETURN(TRUE); + +#ifdef HAVE_OPENSSL + /* There might be buffered data at the SSL layer. */ + if (!bytes && vio->type == VIO_TYPE_SSL) + bytes= SSL_pending((SSL*) vio->ssl_arg); +#endif + + DBUG_RETURN(bytes ? TRUE : FALSE); +} + + void vio_timeout(Vio *vio, uint which, uint timeout) { #if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO) @@ -494,6 +629,15 @@ size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size) } +my_bool vio_is_connected_pipe(Vio *vio) +{ + if (PeekNamedPipe(vio->hPipe, NULL, 0, NULL, NULL, NULL)) + return TRUE; + else + return (GetLastError() != ERROR_BROKEN_PIPE); +} + + int vio_close_pipe(Vio * vio) { int r; @@ -645,6 +789,12 @@ size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size) } +my_bool vio_is_connected_shared_memory(Vio *vio) +{ + return (WaitForSingleObject(vio->event_conn_closed, 0) != WAIT_OBJECT_0); +} + + /** Close shared memory and DBUG_PRINT any errors that happen on closing. @return Zero if all closing functions succeed, and nonzero otherwise. |