28 #ifdef FIONREAD_IN_SYS_FILIO
29 # include <sys/filio.h>
32 int vio_errno(
Vio *vio __attribute__((unused)))
36 if (vio->type == VIO_TYPE_NAMEDPIPE ||
37 vio->type == VIO_TYPE_SHARED_MEMORY)
38 return GetLastError();
55 int vio_socket_io_wait(
Vio *vio,
enum enum_vio_io_event
event)
59 DBUG_ASSERT(event == VIO_IO_EVENT_READ || event == VIO_IO_EVENT_WRITE);
62 if (event == VIO_IO_EVENT_READ)
63 timeout= vio->read_timeout;
65 timeout= vio->write_timeout;
68 switch (vio_io_wait(vio, event, timeout))
93 #if defined(__linux__)
94 #define VIO_USE_DONTWAIT 1
95 #define VIO_DONTWAIT MSG_DONTWAIT
97 #define VIO_DONTWAIT 0
101 size_t vio_read(
Vio *vio, uchar *
buf,
size_t size)
105 DBUG_ENTER(
"vio_read");
108 DBUG_ASSERT(vio->read_end == vio->read_pos);
111 if (vio->read_timeout >= 0)
114 while ((ret=
mysql_socket_recv(vio->mysql_socket, (SOCKBUF_T *)buf, size, flags)) == -1)
116 int error= socket_errno;
119 if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK)
123 if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_READ)))
136 size_t vio_read_buff(
Vio *vio, uchar* buf,
size_t size)
139 #define VIO_UNBUFFERED_READ_MIN_SIZE 2048
140 DBUG_ENTER(
"vio_read_buff");
141 DBUG_PRINT(
"enter", (
"sd: %d buf: 0x%lx size: %u",
142 mysql_socket_getfd(vio->mysql_socket), (
long)buf, (uint)size));
144 if (vio->read_pos < vio->read_end)
146 rc= MY_MIN((
size_t) (vio->read_end - vio->read_pos), size);
147 memcpy(buf, vio->read_pos, rc);
155 else if (size < VIO_UNBUFFERED_READ_MIN_SIZE)
157 rc= vio_read(vio, (uchar*) vio->read_buffer, VIO_READ_BUFFER_SIZE);
158 if (rc != 0 && rc != (
size_t) -1)
162 vio->read_pos= vio->read_buffer +
size;
163 vio->read_end= vio->read_buffer + rc;
166 memcpy(buf, vio->read_buffer, rc);
170 rc= vio_read(vio, buf, size);
172 #undef VIO_UNBUFFERED_READ_MIN_SIZE
176 my_bool vio_buff_has_data(
Vio *vio)
178 return (vio->read_pos != vio->read_end);
182 size_t vio_write(
Vio *vio,
const uchar* buf,
size_t size)
186 DBUG_ENTER(
"vio_write");
189 if (vio->write_timeout >= 0)
192 while ((ret=
mysql_socket_send(vio->mysql_socket, (SOCKBUF_T *)buf, size, flags)) == -1)
194 int error= socket_errno;
197 if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK)
201 if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_WRITE)))
209 static int vio_set_blocking(
Vio *vio, my_bool status)
211 DBUG_ENTER(
"vio_set_blocking");
214 DBUG_ASSERT(vio->type != VIO_TYPE_NAMEDPIPE);
215 DBUG_ASSERT(vio->type != VIO_TYPE_SHARED_MEMORY);
218 u_long arg= status ? 0 : 1;
219 ret= ioctlsocket(mysql_socket_getfd(vio->mysql_socket), FIONBIO, &arg);
226 if ((flags= fcntl(mysql_socket_getfd(vio->mysql_socket), F_GETFL, NULL)) < 0)
240 if (fcntl(mysql_socket_getfd(vio->mysql_socket), F_SETFL, flags) == -1)
249 int vio_socket_timeout(
Vio *vio,
250 uint which __attribute__((unused)),
251 my_bool old_mode __attribute__((unused)))
254 DBUG_ENTER(
"vio_socket_timeout");
260 const char *optval= (
const char *) &timeout;
272 DBUG_ASSERT(which || vio->read_timeout);
273 DBUG_ASSERT(!which || vio->write_timeout);
277 optname= SO_SNDTIMEO;
278 if (vio->write_timeout > 0)
279 timeout= vio->write_timeout;
283 optname= SO_RCVTIMEO;
284 if (vio->read_timeout > 0)
285 timeout= vio->read_timeout;
289 optval,
sizeof(timeout));
300 #ifdef VIO_USE_DONTWAIT
301 if (vio->type == VIO_TYPE_SSL)
305 my_bool new_mode= vio->write_timeout < 0 && vio->read_timeout < 0;
308 if (new_mode != old_mode)
309 ret= vio_set_blocking(vio, new_mode);
317 int vio_fastsend(
Vio * vio __attribute__((unused)))
320 DBUG_ENTER(
"vio_fastsend");
322 #if defined(IPTOS_THROUGHPUT)
324 int tos = IPTOS_THROUGHPUT;
326 (
void *)&tos,
sizeof(tos));
338 IF_WIN((
const char*), (
void*)) &nodelay,
344 DBUG_PRINT(
"warning", (
"Couldn't set socket option for fast send"));
347 DBUG_PRINT(
"exit", (
"%d", r));
351 int vio_keepalive(
Vio* vio, my_bool set_keep_alive)
355 DBUG_ENTER(
"vio_keepalive");
356 DBUG_PRINT(
"enter", (
"sd: %d set_keep_alive: %d",
357 mysql_socket_getfd(vio->mysql_socket), (
int)set_keep_alive));
358 if (vio->type != VIO_TYPE_NAMEDPIPE)
363 (
char *)&opt,
sizeof(opt));
380 vio_should_retry(
Vio *vio)
382 return (vio_errno(vio) == SOCKET_EINTR);
397 vio_was_timeout(
Vio *vio)
399 return (vio_errno(vio) == SOCKET_ETIMEDOUT);
403 int vio_shutdown(
Vio * vio)
406 DBUG_ENTER(
"vio_shutdown");
408 if (vio->inactive == FALSE)
410 DBUG_ASSERT(vio->type == VIO_TYPE_TCPIP ||
411 vio->type == VIO_TYPE_SOCKET ||
412 vio->type == VIO_TYPE_SSL);
414 DBUG_ASSERT(mysql_socket_getfd(vio->mysql_socket) >= 0);
422 DBUG_PRINT(
"vio_error", (
"close() failed, error: %d",socket_errno));
431 const char *vio_description(
Vio * vio)
435 my_snprintf(vio->desc, VIO_DESCRIPTION_SIZE,
436 (vio->type == VIO_TYPE_SOCKET ?
"socket (%d)" :
"TCP/IP (%d)"),
437 mysql_socket_getfd(vio->mysql_socket));
442 enum enum_vio_type vio_type(
Vio* vio)
447 my_socket vio_fd(
Vio* vio)
449 return mysql_socket_getfd(vio->mysql_socket);
475 static void vio_get_normalized_ip(
const struct sockaddr *src,
477 struct sockaddr *dst,
480 switch (src->sa_family) {
482 memcpy(dst, src, src_length);
483 *dst_length= src_length;
489 const struct sockaddr_in6 *src_addr6= (
const struct sockaddr_in6 *) src;
490 const struct in6_addr *src_ip6= &(src_addr6->sin6_addr);
491 const uint32 *src_ip6_int32= (uint32 *) src_ip6->s6_addr;
493 if (IN6_IS_ADDR_V4MAPPED(src_ip6) || IN6_IS_ADDR_V4COMPAT(src_ip6))
495 struct sockaddr_in *dst_ip4= (
struct sockaddr_in *) dst;
502 *dst_length=
sizeof (
struct sockaddr_in);
504 memset(dst_ip4, 0, *dst_length);
505 dst_ip4->sin_family= AF_INET;
506 dst_ip4->sin_port= src_addr6->sin6_port;
513 dst_ip4->sin_addr.s_addr= src_ip6_int32[3];
519 memcpy(dst, src, src_length);
520 *dst_length= src_length;
551 my_bool vio_get_normalized_ip_string(
const struct sockaddr *addr,
554 size_t ip_string_size)
556 struct sockaddr_storage norm_addr_storage;
557 struct sockaddr *norm_addr= (
struct sockaddr *) &norm_addr_storage;
558 int norm_addr_length;
561 vio_get_normalized_ip(addr, addr_length, norm_addr, &norm_addr_length);
563 err_code= vio_getnameinfo(norm_addr, ip_string, ip_string_size, NULL, 0,
569 DBUG_PRINT(
"error", (
"getnameinfo() failed with %d (%s).",
571 (
const char *) gai_strerror(err_code)));
586 my_bool vio_peer_addr(
Vio *vio,
char *ip_buffer, uint16 *port,
587 size_t ip_buffer_size)
589 DBUG_ENTER(
"vio_peer_addr");
590 DBUG_PRINT(
"enter", (
"Client socked fd: %d",
591 (
int)mysql_socket_getfd(vio->mysql_socket)));
599 struct in_addr *ip4= &((
struct sockaddr_in *) &(vio->remote))->sin_addr;
601 vio->remote.ss_family= AF_INET;
602 vio->addrLen=
sizeof (
struct sockaddr_in);
604 ip4->s_addr= htonl(INADDR_LOOPBACK);
608 strmov(ip_buffer,
"127.0.0.1");
614 char port_buffer[NI_MAXSERV];
616 struct sockaddr_storage addr_storage;
617 struct sockaddr *addr= (
struct sockaddr *) &addr_storage;
618 size_socket addr_length=
sizeof (addr_storage);
626 DBUG_PRINT(
"exit", (
"getpeername() gave error: %d", socket_errno));
632 vio_get_normalized_ip(addr, addr_length,
633 (
struct sockaddr *) &vio->remote, &vio->addrLen);
637 err_code= vio_getnameinfo((
struct sockaddr *) &vio->remote,
638 ip_buffer, ip_buffer_size,
639 port_buffer, NI_MAXSERV,
640 NI_NUMERICHOST | NI_NUMERICSERV);
644 DBUG_PRINT(
"exit", (
"getnameinfo() gave error: %s",
645 gai_strerror(err_code)));
649 *port= (uint16) strtol(port_buffer, NULL, 10);
652 DBUG_PRINT(
"exit", (
"Client IP address: %s; port: %d",
653 (
const char *) ip_buffer,
669 static my_bool socket_peek_read(
Vio *vio, uint *bytes)
671 my_socket sd= mysql_socket_getfd(vio->mysql_socket);
674 if (ioctlsocket(sd, FIONREAD, &len))
678 #elif defined(FIONREAD_IN_SYS_IOCTL) || defined(FIONREAD_IN_SYS_FILIO)
680 if (ioctl(sd, FIONREAD, &len) < 0)
686 ssize_t res= recv(sd, &buf,
sizeof(buf), MSG_PEEK);
710 #define MY_POLL_SET_IN (POLLIN | POLLPRI)
712 #define MY_POLL_SET_OUT (POLLOUT)
714 #define MY_POLL_SET_ERR (POLLERR | POLLHUP | POLLNVAL)
734 #if !defined(_WIN32) && !defined(__APPLE__)
735 int vio_io_wait(
Vio *vio,
enum enum_vio_io_event event,
int timeout)
740 my_socket sd= mysql_socket_getfd(vio->mysql_socket);
742 DBUG_ENTER("vio_io_wait");
744 memset(&pfd, 0, sizeof(pfd));
754 case VIO_IO_EVENT_READ:
755 pfd.events= MY_POLL_SET_IN;
756 revents= MY_POLL_SET_IN | MY_POLL_SET_ERR | POLLRDHUP;
758 case VIO_IO_EVENT_WRITE:
759 case VIO_IO_EVENT_CONNECT:
760 pfd.events= MY_POLL_SET_OUT;
761 revents= MY_POLL_SET_OUT | MY_POLL_SET_ERR;
771 switch ((ret= poll(&pfd, 1, timeout)))
781 errno= SOCKET_ETIMEDOUT;
785 DBUG_ASSERT(pfd.revents & revents);
795 int vio_io_wait(
Vio *vio,
enum enum_vio_io_event event,
int timeout)
799 my_socket fd= mysql_socket_getfd(vio->mysql_socket);
800 fd_set readfds, writefds, exceptfds;
802 DBUG_ENTER("vio_io_wait");
807 tm.tv_sec= timeout / 1000;
808 tm.tv_usec= (timeout % 1000) * 1000;
816 FD_SET(fd, &exceptfds);
820 case VIO_IO_EVENT_READ:
822 FD_SET(fd, &readfds);
824 case VIO_IO_EVENT_WRITE:
825 case VIO_IO_EVENT_CONNECT:
827 FD_SET(fd, &writefds);
834 ret= select(fd + 1, &readfds, &writefds, &exceptfds,
835 (timeout >= 0) ? &tm : NULL);
842 WSASetLastError(SOCKET_ETIMEDOUT);
843 #elif defined(__APPLE__)
844 errno= SOCKET_ETIMEDOUT;
846 #error Oops...Wrong OS
856 case VIO_IO_EVENT_READ:
857 ret=
test(FD_ISSET(fd, &readfds));
859 case VIO_IO_EVENT_WRITE:
860 case VIO_IO_EVENT_CONNECT:
861 ret=
test(FD_ISSET(fd, &writefds));
866 ret|=
test(FD_ISSET(fd, &exceptfds));
891 vio_socket_connect(
Vio *vio,
struct sockaddr *addr, socklen_t len,
int timeout)
894 DBUG_ENTER(
"vio_socket_connect");
897 DBUG_ASSERT(vio->type == VIO_TYPE_SOCKET || vio->type == VIO_TYPE_TCPIP);
900 if ((timeout > -1) && vio_set_blocking(vio, FALSE))
907 wait= (ret == SOCKET_ERROR) &&
908 (WSAGetLastError() == WSAEINPROGRESS ||
909 WSAGetLastError() == WSAEWOULDBLOCK);
911 wait= (ret == -1) && (errno == EINPROGRESS || errno == EALREADY);
928 if (wait && (vio_io_wait(vio, VIO_IO_EVENT_CONNECT, timeout) == 1))
931 IF_WIN(
int, socklen_t) optlen= sizeof(error);
932 IF_WIN(
char,
void) *optval= (IF_WIN(
char,
void) *) &error;
945 WSASetLastError(error);
954 if ((timeout > -1) && (ret == 0))
956 if (vio_set_blocking(vio, TRUE))
960 DBUG_RETURN(
test(ret));
976 my_bool vio_is_connected(
Vio *vio)
979 DBUG_ENTER(
"vio_is_connected");
987 if (!vio_io_wait(vio, VIO_IO_EVENT_READ, 0))
998 while (socket_peek_read(vio, &bytes))
1000 if (socket_errno != SOCKET_EINTR)
1006 if (!bytes && vio->type == VIO_TYPE_SSL)
1007 bytes= SSL_pending((SSL*) vio->ssl_arg);
1010 DBUG_RETURN(bytes ? TRUE : FALSE);
1023 ssize_t vio_pending(
Vio *vio)
1028 if (vio->read_pos < vio->read_end)
1029 return vio->read_end - vio->read_pos;
1032 if (vio->type == VIO_TYPE_TCPIP || vio->type == VIO_TYPE_SOCKET)
1035 if (socket_peek_read(vio, &bytes))
1044 return (ssize_t) bytes;
1063 my_bool vio_is_no_name_error(
int err_code)
1067 return err_code == WSANO_DATA || err_code == EAI_NONAME;
1071 return err_code == EAI_NONAME;
1086 int vio_getnameinfo(
const struct sockaddr *sa,
1087 char *hostname,
size_t hostname_size,
1088 char *port,
size_t port_size,
1093 switch (sa->sa_family) {
1095 sa_length=
sizeof (
struct sockaddr_in);
1096 #ifdef HAVE_SOCKADDR_IN_SIN_LEN
1097 ((
struct sockaddr_in *) sa)->sin_len= sa_length;
1103 sa_length=
sizeof (
struct sockaddr_in6);
1104 # ifdef HAVE_SOCKADDR_IN6_SIN6_LEN
1105 ((
struct sockaddr_in6 *) sa)->sin6_len= sa_length;
1111 return getnameinfo(sa, sa_length,
1112 hostname, hostname_size,