summaryrefslogtreecommitdiff
path: root/vio
diff options
context:
space:
mode:
Diffstat (limited to 'vio')
-rw-r--r--vio/viosocket.c137
-rw-r--r--vio/viossl.c2
2 files changed, 78 insertions, 61 deletions
diff --git a/vio/viosocket.c b/vio/viosocket.c
index 6c028c48c46..d9e2b0451b4 100644
--- a/vio/viosocket.c
+++ b/vio/viosocket.c
@@ -28,6 +28,7 @@
#ifdef __WIN__
#include <winsock2.h>
#include <MSWSock.h>
+ #include <mstcpip.h>
#pragma comment(lib, "ws2_32.lib")
#endif
#include "my_context.h"
@@ -82,6 +83,16 @@ int vio_errno(Vio *vio __attribute__((unused)))
return socket_errno;
}
+static int vio_set_linger(my_socket s, unsigned short timeout_sec)
+{
+ struct linger s_linger;
+ int ret;
+ s_linger.l_onoff = 1;
+ s_linger.l_linger = timeout_sec;
+ ret = setsockopt(s, SOL_SOCKET, SO_LINGER, (const char *)&s_linger, (int)sizeof(s_linger));
+ return ret;
+}
+
/**
Attempt to wait for an I/O event on a socket.
@@ -114,6 +125,7 @@ int vio_socket_io_wait(Vio *vio, enum enum_vio_io_event event)
case 0:
/* The wait timed out. */
ret= -1;
+ vio_set_linger(vio->mysql_socket.fd, 0);
break;
default:
/* A positive value indicates an I/O event. */
@@ -399,43 +411,6 @@ int vio_socket_timeout(Vio *vio,
{
int ret= 0;
DBUG_ENTER("vio_socket_timeout");
-
-#if defined(_WIN32)
- {
- int optname;
- DWORD timeout= 0;
- const char *optval= (const char *) &timeout;
-
- /*
- The default socket timeout value is zero, which means an infinite
- timeout. Values less than 500 milliseconds are interpreted to be of
- 500 milliseconds. Hence, the VIO behavior for zero timeout, which is
- intended to cause the send or receive operation to fail immediately
- if no data is available, is not supported on WIN32 and neither is
- necessary as it's not possible to set the VIO timeout value to zero.
-
- Assert that the VIO timeout is either positive or set to infinite.
- */
- DBUG_ASSERT(which || vio->read_timeout);
- DBUG_ASSERT(!which || vio->write_timeout);
-
- if (which)
- {
- optname= SO_SNDTIMEO;
- if (vio->write_timeout > 0)
- timeout= vio->write_timeout;
- }
- else
- {
- optname= SO_RCVTIMEO;
- if (vio->read_timeout > 0)
- timeout= vio->read_timeout;
- }
-
- ret= mysql_socket_setsockopt(vio->mysql_socket, SOL_SOCKET, optname,
- optval, sizeof(timeout));
- }
-#else
/*
The MSG_DONTWAIT trick is not used with SSL sockets as the send and
receive I/O operations are wrapped through SSL-specific functions
@@ -456,7 +431,6 @@ int vio_socket_timeout(Vio *vio,
if (new_mode != old_mode)
ret= vio_blocking(vio, new_mode, &not_used);
}
-#endif
DBUG_RETURN(ret);
}
@@ -522,6 +496,63 @@ int vio_keepalive(Vio* vio, my_bool set_keep_alive)
DBUG_RETURN(r);
}
+/*
+ Set socket options for keepalive e.g., TCP_KEEPCNT, TCP_KEEPIDLE/TCP_KEEPALIVE, TCP_KEEPINTVL
+*/
+int vio_set_keepalive_options(Vio* vio, const struct vio_keepalive_opts *opts)
+{
+#if defined _WIN32
+ struct tcp_keepalive s;
+ DWORD nbytes;
+
+ if (vio->type == VIO_TYPE_NAMEDPIPE || vio->type == VIO_TYPE_SHARED_MEMORY)
+ return 0;
+
+ if (!opts->idle && !opts->interval)
+ return 0;
+
+ s.onoff= 1;
+ s.keepalivetime= opts->idle? opts->idle * 1000 : 7200;
+ s.keepaliveinterval= opts->interval?opts->interval * 1000 : 1;
+
+ return WSAIoctl(vio->mysql_socket.fd, SIO_KEEPALIVE_VALS, (LPVOID) &s, sizeof(s),
+ NULL, 0, &nbytes, NULL, NULL);
+
+#elif defined (TCP_KEEPIDLE) || defined (TCP_KEEPALIVE)
+
+ int ret= 0;
+ if (opts->idle)
+ {
+#ifdef TCP_KEEPIDLE // Linux only
+ ret= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&opts->idle, sizeof(opts->idle));
+#elif defined (TCP_KEEPALIVE)
+ ret= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_TCP, TCP_KEEPALIVE, (char *)&opts->idle, sizeof(opts->idle));
+#endif
+ if(ret)
+ return ret;
+ }
+
+#ifdef TCP_KEEPCNT // Linux only
+ if(opts->probes)
+ {
+ ret= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_TCP, TCP_KEEPCNT, (char *)&opts->probes, sizeof(opts->probes));
+ if(ret)
+ return ret;
+ }
+#endif
+
+#ifdef TCP_KEEPINTVL // Linux only
+ if(opts->interval)
+ {
+ ret= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_TCP, TCP_KEEPINTVL, (char *)&opts->interval, sizeof(opts->interval));
+ }
+#endif
+ return ret;
+#else /*TCP_KEEPIDLE || TCP_KEEPALIVE */
+ return -1;
+#endif
+}
+
/**
Indicate whether a I/O operation must be retried later.
@@ -572,8 +603,6 @@ int vio_close(Vio *vio)
vio->type == VIO_TYPE_SSL);
DBUG_ASSERT(mysql_socket_getfd(vio->mysql_socket) >= 0);
- if (mysql_socket_shutdown(vio->mysql_socket, SHUT_RDWR))
- r= -1;
if (mysql_socket_close(vio->mysql_socket))
r= -1;
}
@@ -624,18 +653,15 @@ my_socket vio_fd(Vio* vio)
@param src_length [in] length of the src.
@param dst [out] a buffer to store normalized IP address
(sockaddr_storage).
- @param dst_length [out] actual length of the normalized IP address.
+ @param dst_length [out] optional - actual length of the normalized IP address.
*/
-static void vio_get_normalized_ip(const struct sockaddr *src,
- int src_length,
- struct sockaddr *dst,
- int *dst_length)
+void vio_get_normalized_ip(const struct sockaddr *src, size_t src_length,
+ struct sockaddr *dst)
{
switch (src->sa_family) {
case AF_INET:
memcpy(dst, src, src_length);
- *dst_length= src_length;
break;
#ifdef HAVE_IPV6
@@ -654,9 +680,7 @@ static void vio_get_normalized_ip(const struct sockaddr *src,
be converted to the IPv4 form.
*/
- *dst_length= sizeof (struct sockaddr_in);
-
- memset(dst_ip4, 0, *dst_length);
+ memset(dst_ip4, 0, sizeof (struct sockaddr_in));
dst_ip4->sin_family= AF_INET;
dst_ip4->sin_port= src_addr6->sin6_port;
@@ -670,9 +694,7 @@ static void vio_get_normalized_ip(const struct sockaddr *src,
else
{
/* This is a "native" IPv6 address. */
-
memcpy(dst, src, src_length);
- *dst_length= src_length;
}
break;
@@ -703,17 +725,15 @@ static void vio_get_normalized_ip(const struct sockaddr *src,
@retval FALSE on success.
*/
-my_bool vio_get_normalized_ip_string(const struct sockaddr *addr,
- int addr_length,
+my_bool vio_get_normalized_ip_string(const struct sockaddr *addr, size_t addr_length,
char *ip_string,
size_t ip_string_size)
{
struct sockaddr_storage norm_addr_storage;
struct sockaddr *norm_addr= (struct sockaddr *) &norm_addr_storage;
- int norm_addr_length;
int err_code;
- vio_get_normalized_ip(addr, addr_length, norm_addr, &norm_addr_length);
+ vio_get_normalized_ip(addr, addr_length, norm_addr);
err_code= vio_getnameinfo(norm_addr, ip_string, ip_string_size, NULL, 0,
NI_NUMERICHOST);
@@ -752,9 +772,7 @@ my_bool vio_peer_addr(Vio *vio, char *ip_buffer, uint16 *port,
address.
*/
struct in_addr *ip4= &((struct sockaddr_in *) &(vio->remote))->sin_addr;
-
vio->remote.ss_family= AF_INET;
- vio->addrLen= sizeof (struct sockaddr_in);
ip4->s_addr= htonl(INADDR_LOOPBACK);
@@ -771,7 +789,6 @@ my_bool vio_peer_addr(Vio *vio, char *ip_buffer, uint16 *port,
struct sockaddr_storage addr_storage;
struct sockaddr *addr= (struct sockaddr *) &addr_storage;
size_socket addr_length= sizeof (addr_storage);
-
/* Get sockaddr by socked fd. */
err_code= mysql_socket_getpeername(vio->mysql_socket, addr, &addr_length);
@@ -785,7 +802,7 @@ my_bool vio_peer_addr(Vio *vio, char *ip_buffer, uint16 *port,
/* Normalize IP address. */
vio_get_normalized_ip(addr, addr_length,
- (struct sockaddr *) &vio->remote, &vio->addrLen);
+ (struct sockaddr *) &vio->remote);
/* Get IP address & port number. */
@@ -826,7 +843,7 @@ static my_bool socket_peek_read(Vio *vio, uint *bytes)
{
my_socket sd= mysql_socket_getfd(vio->mysql_socket);
#if defined(_WIN32)
- int len;
+ u_long len;
if (ioctlsocket(sd, FIONREAD, &len))
return TRUE;
*bytes= len;
diff --git a/vio/viossl.c b/vio/viossl.c
index 02ef41db2de..30946d3261c 100644
--- a/vio/viossl.c
+++ b/vio/viossl.c
@@ -333,7 +333,7 @@ static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout,
DBUG_PRINT("info", ("ssl: %p timeout: %ld", ssl, timeout));
SSL_clear(ssl);
SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
- SSL_set_fd(ssl, sd);
+ SSL_set_fd(ssl, (int)sd);
/*
Since yaSSL does not support non-blocking send operations, use