1/*
2 Copyright (c) 2001, 2012, Oracle and/or its affiliates
3 Copyright (c) 2012, Monty Program Ab
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; version 2 of
8 the License.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 02110-1301 USA */
19
20/*
21 Note that we can't have assertion on file descriptors; The reason for
22 this is that during mysql shutdown, another thread can close a file
23 we are working on. In this case we should just return read errors from
24 the file descriptior.
25*/
26
27#include "vio_priv.h"
28#ifdef __WIN__
29 #include <winsock2.h>
30 #include <MSWSock.h>
31 #include <mstcpip.h>
32 #pragma comment(lib, "ws2_32.lib")
33#endif
34#include "my_context.h"
35#include <mysql_async.h>
36
37#ifdef FIONREAD_IN_SYS_FILIO
38# include <sys/filio.h>
39#endif
40
41/* Network io wait callbacks for threadpool */
42static void (*before_io_wait)(void)= 0;
43static void (*after_io_wait)(void)= 0;
44
45/* Wait callback macros (both performance schema and threadpool */
46#define START_SOCKET_WAIT(locker, state_ptr, sock, which, timeout) \
47do \
48{ \
49 MYSQL_START_SOCKET_WAIT(locker, state_ptr, sock, \
50 which, 0); \
51 if (timeout && before_io_wait) \
52 before_io_wait(); \
53} while(0)
54
55
56#define END_SOCKET_WAIT(locker,timeout) \
57do \
58{ \
59 MYSQL_END_SOCKET_WAIT(locker, 0); \
60 if (timeout && after_io_wait) \
61 after_io_wait(); \
62} while(0)
63
64
65
66void vio_set_wait_callback(void (*before_wait)(void),
67 void (*after_wait)(void))
68{
69 before_io_wait= before_wait;
70 after_io_wait= after_wait;
71}
72
73int vio_errno(Vio *vio __attribute__((unused)))
74{
75 /* These transport types are not Winsock based. */
76#ifdef _WIN32
77 if (vio->type == VIO_TYPE_NAMEDPIPE ||
78 vio->type == VIO_TYPE_SHARED_MEMORY)
79 return GetLastError();
80#endif
81
82 /* Mapped to WSAGetLastError() on Win32. */
83 return socket_errno;
84}
85
86static int vio_set_linger(my_socket s, unsigned short timeout_sec)
87{
88 struct linger s_linger;
89 int ret;
90 s_linger.l_onoff = 1;
91 s_linger.l_linger = timeout_sec;
92 ret = setsockopt(s, SOL_SOCKET, SO_LINGER, (const char *)&s_linger, (int)sizeof(s_linger));
93 return ret;
94}
95
96
97/**
98 Attempt to wait for an I/O event on a socket.
99
100 @param vio VIO object representing a connected socket.
101 @param event The type of I/O event (read or write) to wait for.
102
103 @return Return value is -1 on failure, 0 on success.
104*/
105
106int vio_socket_io_wait(Vio *vio, enum enum_vio_io_event event)
107{
108 int timeout, ret;
109
110 DBUG_ASSERT(event == VIO_IO_EVENT_READ || event == VIO_IO_EVENT_WRITE);
111
112 /* Choose an appropriate timeout. */
113 if (event == VIO_IO_EVENT_READ)
114 timeout= vio->read_timeout;
115 else
116 timeout= vio->write_timeout;
117
118 /* Wait for input data to become available. */
119 switch (vio_io_wait(vio, event, timeout))
120 {
121 case -1:
122 /* Upon failure, vio_read/write() shall return -1. */
123 ret= -1;
124 break;
125 case 0:
126 /* The wait timed out. */
127 ret= -1;
128 vio_set_linger(vio->mysql_socket.fd, 0);
129 break;
130 default:
131 /* A positive value indicates an I/O event. */
132 ret= 0;
133 break;
134 }
135
136 return ret;
137}
138
139
140/*
141 Define a stub MSG_DONTWAIT if unavailable. In this case, fcntl
142 (or a equivalent) is used to enable non-blocking operations.
143 The flag must be supported in both send and recv operations.
144*/
145#if defined(__linux__)
146#define VIO_USE_DONTWAIT 1
147#define VIO_DONTWAIT MSG_DONTWAIT
148#else
149#define VIO_DONTWAIT 0
150#endif
151
152/*
153 returns number of bytes read or -1 in case of an error
154*/
155size_t vio_read(Vio *vio, uchar *buf, size_t size)
156{
157 ssize_t ret;
158 int flags= 0;
159 DBUG_ENTER("vio_read");
160 DBUG_PRINT("enter", ("sd: %d buf: %p size: %zu",
161 (int)mysql_socket_getfd(vio->mysql_socket), buf,
162 size));
163
164 /* Ensure nobody uses vio_read_buff and vio_read simultaneously. */
165 DBUG_ASSERT(vio->read_end == vio->read_pos);
166
167 /* If timeout is enabled, do not block if data is unavailable. */
168 if (vio->read_timeout >= 0)
169 flags= VIO_DONTWAIT;
170
171 if (vio->async_context && vio->async_context->active)
172 ret= my_recv_async(vio->async_context,
173 mysql_socket_getfd(vio->mysql_socket),
174 buf, size, vio->read_timeout);
175 else
176 {
177 if (vio->async_context)
178 {
179 /*
180 If switching from non-blocking to blocking API usage, set the socket
181 back to blocking mode.
182 */
183 my_bool old_mode;
184 vio_blocking(vio, TRUE, &old_mode);
185 }
186 while ((ret= mysql_socket_recv(vio->mysql_socket, (SOCKBUF_T *)buf, size,
187 flags)) == -1)
188 {
189 int error= socket_errno;
190
191 /* The operation would block? */
192 if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK)
193 break;
194
195 /* Wait for input data to become available. */
196 if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_READ)))
197 break;
198 }
199 }
200#ifndef DBUG_OFF
201 if (ret == -1)
202 {
203 DBUG_PRINT("vio_error", ("Got error %d during read", errno));
204 }
205#ifndef DEBUG_DATA_PACKETS
206 else
207 {
208 DBUG_DUMP("read_data", buf, ret);
209 }
210#endif /* DEBUG_DATA_PACKETS */
211#endif /* DBUG_OFF */
212 DBUG_PRINT("exit", ("%d", (int) ret));
213 DBUG_RETURN(ret);
214}
215
216
217/*
218 Buffered read: if average read size is small it may
219 reduce number of syscalls.
220*/
221
222size_t vio_read_buff(Vio *vio, uchar* buf, size_t size)
223{
224 size_t rc;
225#define VIO_UNBUFFERED_READ_MIN_SIZE 2048
226 DBUG_ENTER("vio_read_buff");
227 DBUG_PRINT("enter", ("sd: %d buf: %p size:%zu",
228 (int)mysql_socket_getfd(vio->mysql_socket),
229 buf, size));
230
231 if (vio->read_pos < vio->read_end)
232 {
233 rc= MY_MIN((size_t) (vio->read_end - vio->read_pos), size);
234 memcpy(buf, vio->read_pos, rc);
235 vio->read_pos+= rc;
236 /*
237 Do not try to read from the socket now even if rc < size:
238 vio_read can return -1 due to an error or non-blocking mode, and
239 the safest way to handle it is to move to a separate branch.
240 */
241 }
242 else if (size < VIO_UNBUFFERED_READ_MIN_SIZE)
243 {
244 rc= vio_read(vio, (uchar*) vio->read_buffer, VIO_READ_BUFFER_SIZE);
245 if (rc != 0 && rc != (size_t) -1)
246 {
247 if (rc > size)
248 {
249 vio->read_pos= vio->read_buffer + size;
250 vio->read_end= vio->read_buffer + rc;
251 rc= size;
252 }
253 memcpy(buf, vio->read_buffer, rc);
254 }
255 }
256 else
257 rc= vio_read(vio, buf, size);
258 DBUG_RETURN(rc);
259#undef VIO_UNBUFFERED_READ_MIN_SIZE
260}
261
262
263my_bool vio_buff_has_data(Vio *vio)
264{
265 return (vio->read_pos != vio->read_end);
266}
267
268
269size_t vio_write(Vio *vio, const uchar* buf, size_t size)
270{
271 ssize_t ret;
272 int flags= 0;
273 DBUG_ENTER("vio_write");
274 DBUG_PRINT("enter", ("sd: %d buf: %p size: %zu",
275 (int)mysql_socket_getfd(vio->mysql_socket), buf,
276 size));
277
278 /* If timeout is enabled, do not block. */
279 if (vio->write_timeout >= 0)
280 flags= VIO_DONTWAIT;
281
282 if (vio->async_context && vio->async_context->active)
283 ret= my_send_async(vio->async_context,
284 mysql_socket_getfd(vio->mysql_socket), buf, size,
285 vio->write_timeout);
286 else
287 {
288 if (vio->async_context)
289 {
290 /*
291 If switching from non-blocking to blocking API usage, set the socket
292 back to blocking mode.
293 */
294 my_bool old_mode;
295 vio_blocking(vio, TRUE, &old_mode);
296 }
297 while ((ret= mysql_socket_send(vio->mysql_socket, (SOCKBUF_T *)buf, size,
298 flags)) == -1)
299 {
300 int error= socket_errno;
301 /* The operation would block? */
302 if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK)
303 break;
304
305 /* Wait for the output buffer to become writable.*/
306 if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_WRITE)))
307 break;
308 }
309 }
310#ifndef DBUG_OFF
311 if (ret == -1)
312 {
313 DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno));
314 }
315#endif /* DBUG_OFF */
316 DBUG_PRINT("exit", ("%d", (int) ret));
317 DBUG_RETURN(ret);
318}
319
320int vio_socket_shutdown(Vio *vio, int how)
321{
322 int ret= shutdown(mysql_socket_getfd(vio->mysql_socket), how);
323#ifdef _WIN32
324 /* Cancel possible IO in progress (shutdown does not do that on Windows). */
325 (void) CancelIoEx((HANDLE)mysql_socket_getfd(vio->mysql_socket), NULL);
326#endif
327 return ret;
328}
329
330
331int vio_blocking(Vio *vio, my_bool set_blocking_mode, my_bool *old_mode)
332{
333 int r= 0;
334#if defined(__WIN__) || !defined(NO_FCNTL_NONBLOCK)
335 my_socket sd= mysql_socket_getfd(vio->mysql_socket);
336#endif
337 DBUG_ENTER("vio_blocking");
338
339 *old_mode= MY_TEST(!(vio->fcntl_mode & O_NONBLOCK));
340 DBUG_PRINT("enter", ("set_blocking_mode: %d old_mode: %d",
341 (int) set_blocking_mode, (int) *old_mode));
342
343#if !defined(__WIN__)
344#if !defined(NO_FCNTL_NONBLOCK)
345 if (sd >= 0)
346 {
347 int old_fcntl= vio->fcntl_mode;
348 if (set_blocking_mode)
349 vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
350 else
351 vio->fcntl_mode |= O_NONBLOCK; /* set bit */
352 if (old_fcntl != vio->fcntl_mode)
353 {
354 r= fcntl(sd, F_SETFL, vio->fcntl_mode);
355 if (r == -1)
356 {
357 DBUG_PRINT("info", ("fcntl failed, errno %d", errno));
358 vio->fcntl_mode= old_fcntl;
359 }
360 }
361 }
362#else
363 r= set_blocking_mode ? 0 : 1;
364#endif /* !defined(NO_FCNTL_NONBLOCK) */
365#else /* !defined(__WIN__) */
366 if (vio->type != VIO_TYPE_NAMEDPIPE && vio->type != VIO_TYPE_SHARED_MEMORY)
367 {
368 ulong arg;
369 int old_fcntl=vio->fcntl_mode;
370 if (set_blocking_mode)
371 {
372 arg = 0;
373 vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
374 }
375 else
376 {
377 arg = 1;
378 vio->fcntl_mode |= O_NONBLOCK; /* set bit */
379 }
380 if (old_fcntl != vio->fcntl_mode)
381 r = ioctlsocket(sd,FIONBIO,(void*) &arg);
382 }
383 else
384 r= MY_TEST(!(vio->fcntl_mode & O_NONBLOCK)) != set_blocking_mode;
385#endif /* !defined(__WIN__) */
386 DBUG_PRINT("exit", ("%d", r));
387 DBUG_RETURN(r);
388}
389
390/*
391 Check if vio is blocking
392
393 @retval 0 is not blocking
394 @retval 1 is blocking
395*/
396
397my_bool
398vio_is_blocking(Vio * vio)
399{
400 my_bool r;
401 DBUG_ENTER("vio_is_blocking");
402 r = !(vio->fcntl_mode & O_NONBLOCK);
403 DBUG_PRINT("exit", ("%d", (int) r));
404 DBUG_RETURN(r);
405}
406
407
408int vio_socket_timeout(Vio *vio,
409 uint which __attribute__((unused)),
410 my_bool old_mode __attribute__((unused)))
411{
412 int ret= 0;
413 DBUG_ENTER("vio_socket_timeout");
414 /*
415 The MSG_DONTWAIT trick is not used with SSL sockets as the send and
416 receive I/O operations are wrapped through SSL-specific functions
417 (SSL_read and SSL_write) which are not equivalent to the standard
418 recv(2) and send(2) used in vio_read() and vio_write(). Hence, the
419 socket blocking mode is changed and vio_io_wait() is used to wait
420 for I/O or timeout.
421 */
422#ifdef VIO_USE_DONTWAIT
423 if (vio->type == VIO_TYPE_SSL)
424#endif
425 {
426 /* Deduce what should be the new blocking mode of the socket. */
427 my_bool new_mode= vio->write_timeout < 0 && vio->read_timeout < 0;
428 my_bool not_used;
429
430 /* If necessary, update the blocking mode. */
431 if (new_mode != old_mode)
432 ret= vio_blocking(vio, new_mode, &not_used);
433 }
434
435 DBUG_RETURN(ret);
436}
437
438
439int vio_fastsend(Vio * vio __attribute__((unused)))
440{
441 int r=0;
442 DBUG_ENTER("vio_fastsend");
443
444 if (vio->type == VIO_TYPE_NAMEDPIPE ||vio->type == VIO_TYPE_SHARED_MEMORY)
445 {
446 DBUG_RETURN(0);
447 }
448
449#if defined(IPTOS_THROUGHPUT)
450 {
451 int tos = IPTOS_THROUGHPUT;
452 r= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_IP, IP_TOS,
453 (void *)&tos, sizeof(tos));
454 }
455#endif /* IPTOS_THROUGHPUT */
456 if (!r)
457 {
458#ifdef __WIN__
459 BOOL nodelay= 1;
460#else
461 int nodelay = 1;
462#endif
463
464 r= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_TCP, TCP_NODELAY,
465 IF_WIN((const char*), (void*)) &nodelay,
466 sizeof(nodelay));
467
468 }
469 if (r)
470 {
471 DBUG_PRINT("warning",
472 ("Couldn't set socket option for fast send, error %d",
473 socket_errno));
474 r= -1;
475 }
476 DBUG_PRINT("exit", ("%d", r));
477 DBUG_RETURN(r);
478}
479
480int vio_keepalive(Vio* vio, my_bool set_keep_alive)
481{
482 int r=0;
483 uint opt = 0;
484 DBUG_ENTER("vio_keepalive");
485 DBUG_PRINT("enter", ("sd: %d set_keep_alive: %d",
486 (int)mysql_socket_getfd(vio->mysql_socket),
487 (int)set_keep_alive));
488
489 if (vio->type != VIO_TYPE_NAMEDPIPE && vio->type != VIO_TYPE_SHARED_MEMORY)
490 {
491 if (set_keep_alive)
492 opt = 1;
493 r = mysql_socket_setsockopt(vio->mysql_socket, SOL_SOCKET, SO_KEEPALIVE,
494 (char *)&opt, sizeof(opt));
495 }
496 DBUG_RETURN(r);
497}
498
499/*
500 Set socket options for keepalive e.g., TCP_KEEPCNT, TCP_KEEPIDLE/TCP_KEEPALIVE, TCP_KEEPINTVL
501*/
502int vio_set_keepalive_options(Vio* vio, const struct vio_keepalive_opts *opts)
503{
504#if defined _WIN32
505 struct tcp_keepalive s;
506 DWORD nbytes;
507
508 if (vio->type == VIO_TYPE_NAMEDPIPE || vio->type == VIO_TYPE_SHARED_MEMORY)
509 return 0;
510
511 if (!opts->idle && !opts->interval)
512 return 0;
513
514 s.onoff= 1;
515 s.keepalivetime= opts->idle? opts->idle * 1000 : 7200;
516 s.keepaliveinterval= opts->interval?opts->interval * 1000 : 1;
517
518 return WSAIoctl(vio->mysql_socket.fd, SIO_KEEPALIVE_VALS, (LPVOID) &s, sizeof(s),
519 NULL, 0, &nbytes, NULL, NULL);
520
521#elif defined (TCP_KEEPIDLE) || defined (TCP_KEEPALIVE)
522
523 int ret= 0;
524 if (opts->idle)
525 {
526#ifdef TCP_KEEPIDLE // Linux only
527 ret= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&opts->idle, sizeof(opts->idle));
528#elif defined (TCP_KEEPALIVE)
529 ret= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_TCP, TCP_KEEPALIVE, (char *)&opts->idle, sizeof(opts->idle));
530#endif
531 if(ret)
532 return ret;
533 }
534
535#ifdef TCP_KEEPCNT // Linux only
536 if(opts->probes)
537 {
538 ret= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_TCP, TCP_KEEPCNT, (char *)&opts->probes, sizeof(opts->probes));
539 if(ret)
540 return ret;
541 }
542#endif
543
544#ifdef TCP_KEEPINTVL // Linux only
545 if(opts->interval)
546 {
547 ret= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_TCP, TCP_KEEPINTVL, (char *)&opts->interval, sizeof(opts->interval));
548 }
549#endif
550 return ret;
551#else /*TCP_KEEPIDLE || TCP_KEEPALIVE */
552 return -1;
553#endif
554}
555
556
557/**
558 Indicate whether a I/O operation must be retried later.
559
560 @param vio A VIO object
561
562 @return Whether a I/O operation should be deferred.
563 @retval TRUE Temporary failure, retry operation.
564 @retval FALSE Indeterminate failure.
565*/
566
567my_bool
568vio_should_retry(Vio *vio)
569{
570 DBUG_ENTER("vio_should_retry");
571 DBUG_PRINT("info", ("vio_errno: %d", vio_errno(vio)));
572 DBUG_RETURN(vio_errno(vio) == SOCKET_EINTR);
573}
574
575
576/**
577 Indicate whether a I/O operation timed out.
578
579 @param vio A VIO object
580
581 @return Whether a I/O operation timed out.
582 @retval TRUE Operation timed out.
583 @retval FALSE Not a timeout failure.
584*/
585
586my_bool
587vio_was_timeout(Vio *vio)
588{
589 return (vio_errno(vio) == SOCKET_ETIMEDOUT);
590}
591
592
593int vio_close(Vio *vio)
594{
595 int r=0;
596 DBUG_ENTER("vio_close");
597 DBUG_PRINT("enter", ("sd: %d", (int)mysql_socket_getfd(vio->mysql_socket)));
598
599 if (vio->type != VIO_CLOSED)
600 {
601 DBUG_ASSERT(vio->type == VIO_TYPE_TCPIP ||
602 vio->type == VIO_TYPE_SOCKET ||
603 vio->type == VIO_TYPE_SSL);
604
605 DBUG_ASSERT(mysql_socket_getfd(vio->mysql_socket) >= 0);
606 if (mysql_socket_close(vio->mysql_socket))
607 r= -1;
608 }
609 if (r)
610 {
611 DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno));
612 /* FIXME: error handling (not critical for MySQL) */
613 }
614 vio->type= VIO_CLOSED;
615 vio->mysql_socket= MYSQL_INVALID_SOCKET;
616 DBUG_RETURN(r);
617}
618
619
620const char *vio_description(Vio * vio)
621{
622 return vio->desc;
623}
624
625enum enum_vio_type vio_type(Vio* vio)
626{
627 return vio->type;
628}
629
630my_socket vio_fd(Vio* vio)
631{
632 return mysql_socket_getfd(vio->mysql_socket);
633}
634
635/**
636 Convert a sock-address (AF_INET or AF_INET6) into the "normalized" form,
637 which is the IPv4 form for IPv4-mapped or IPv4-compatible IPv6 addresses.
638
639 @note Background: when IPv4 and IPv6 are used simultaneously, IPv4
640 addresses may be written in a form of IPv4-mapped or IPv4-compatible IPv6
641 addresses. That means, one address (a.b.c.d) can be written in three forms:
642 - IPv4: a.b.c.d;
643 - IPv4-compatible IPv6: ::a.b.c.d;
644 - IPv4-mapped IPv4: ::ffff:a.b.c.d;
645
646 Having three forms of one address makes it a little difficult to compare
647 addresses with each other (the IPv4-compatible IPv6-address of foo.bar
648 will be different from the IPv4-mapped IPv6-address of foo.bar).
649
650 @note This function can be made public when it's needed.
651
652 @param src [in] source IP address (AF_INET or AF_INET6).
653 @param src_length [in] length of the src.
654 @param dst [out] a buffer to store normalized IP address
655 (sockaddr_storage).
656 @param dst_length [out] optional - actual length of the normalized IP address.
657*/
658
659void vio_get_normalized_ip(const struct sockaddr *src, size_t src_length,
660 struct sockaddr *dst)
661{
662 switch (src->sa_family) {
663 case AF_INET:
664 memcpy(dst, src, src_length);
665 break;
666
667#ifdef HAVE_IPV6
668 case AF_INET6:
669 {
670 const struct sockaddr_in6 *src_addr6= (const struct sockaddr_in6 *) src;
671 const struct in6_addr *src_ip6= &(src_addr6->sin6_addr);
672 const uint32 *src_ip6_int32= (uint32 *) src_ip6->s6_addr;
673
674 if (IN6_IS_ADDR_V4MAPPED(src_ip6) || IN6_IS_ADDR_V4COMPAT(src_ip6))
675 {
676 struct sockaddr_in *dst_ip4= (struct sockaddr_in *) dst;
677
678 /*
679 This is an IPv4-mapped or IPv4-compatible IPv6 address. It should
680 be converted to the IPv4 form.
681 */
682
683 memset(dst_ip4, 0, sizeof (struct sockaddr_in));
684 dst_ip4->sin_family= AF_INET;
685 dst_ip4->sin_port= src_addr6->sin6_port;
686
687 /*
688 In an IPv4 mapped or compatible address, the last 32 bits represent
689 the IPv4 address. The byte orders for IPv6 and IPv4 addresses are
690 the same, so a simple copy is possible.
691 */
692 dst_ip4->sin_addr.s_addr= src_ip6_int32[3];
693 }
694 else
695 {
696 /* This is a "native" IPv6 address. */
697 memcpy(dst, src, src_length);
698 }
699
700 break;
701 }
702#endif /* HAVE_IPV6 */
703 }
704}
705
706
707/**
708 Return the normalized IP address string for a sock-address.
709
710 The idea is to return an IPv4-address for an IPv4-mapped and
711 IPv4-compatible IPv6 address.
712
713 The function writes the normalized IP address to the given buffer.
714 The buffer should have enough space, otherwise error flag is returned.
715 The system constant INET6_ADDRSTRLEN can be used to reserve buffers of
716 the right size.
717
718 @param addr [in] sockaddr object (AF_INET or AF_INET6).
719 @param addr_length [in] length of the addr.
720 @param ip_string [out] buffer to write normalized IP address.
721 @param ip_string_size [in] size of the ip_string.
722
723 @return Error status.
724 @retval TRUE in case of error (the ip_string buffer is not enough).
725 @retval FALSE on success.
726*/
727
728my_bool vio_get_normalized_ip_string(const struct sockaddr *addr, size_t addr_length,
729 char *ip_string,
730 size_t ip_string_size)
731{
732 struct sockaddr_storage norm_addr_storage;
733 struct sockaddr *norm_addr= (struct sockaddr *) &norm_addr_storage;
734 int err_code;
735
736 vio_get_normalized_ip(addr, addr_length, norm_addr);
737
738 err_code= vio_getnameinfo(norm_addr, ip_string, ip_string_size, NULL, 0,
739 NI_NUMERICHOST);
740
741 if (!err_code)
742 return FALSE;
743
744 DBUG_PRINT("error", ("getnameinfo() failed with %d (%s).",
745 (int) err_code,
746 (const char *) gai_strerror(err_code)));
747 return TRUE;
748}
749
750
751/**
752 Return IP address and port of a VIO client socket.
753
754 The function returns an IPv4 address if IPv6 support is disabled.
755
756 The function returns an IPv4 address if the client socket is associated
757 with an IPv4-compatible or IPv4-mapped IPv6 address. Otherwise, the native
758 IPv6 address is returned.
759*/
760
761my_bool vio_peer_addr(Vio *vio, char *ip_buffer, uint16 *port,
762 size_t ip_buffer_size)
763{
764 DBUG_ENTER("vio_peer_addr");
765 DBUG_PRINT("enter", ("Client socked fd: %d",
766 (int)mysql_socket_getfd(vio->mysql_socket)));
767
768 if (vio->localhost)
769 {
770 /*
771 Initialize vio->remote and vio->addLen. Set vio->remote to IPv4 loopback
772 address.
773 */
774 struct in_addr *ip4= &((struct sockaddr_in *) &(vio->remote))->sin_addr;
775 vio->remote.ss_family= AF_INET;
776
777 ip4->s_addr= htonl(INADDR_LOOPBACK);
778
779 /* Initialize ip_buffer and port. */
780
781 strmov(ip_buffer, "127.0.0.1");
782 *port= 0;
783 }
784 else
785 {
786 int err_code;
787 char port_buffer[NI_MAXSERV];
788
789 struct sockaddr_storage addr_storage;
790 struct sockaddr *addr= (struct sockaddr *) &addr_storage;
791 size_socket addr_length= sizeof (addr_storage);
792 /* Get sockaddr by socked fd. */
793
794 err_code= mysql_socket_getpeername(vio->mysql_socket, addr, &addr_length);
795
796 if (err_code)
797 {
798 DBUG_PRINT("exit", ("getpeername() gave error: %d", socket_errno));
799 DBUG_RETURN(TRUE);
800 }
801
802 /* Normalize IP address. */
803
804 vio_get_normalized_ip(addr, addr_length,
805 (struct sockaddr *) &vio->remote);
806
807 /* Get IP address & port number. */
808
809 err_code= vio_getnameinfo((struct sockaddr *) &vio->remote,
810 ip_buffer, ip_buffer_size,
811 port_buffer, NI_MAXSERV,
812 NI_NUMERICHOST | NI_NUMERICSERV);
813
814 if (err_code)
815 {
816 DBUG_PRINT("exit", ("getnameinfo() gave error: %s",
817 gai_strerror(err_code)));
818 DBUG_RETURN(TRUE);
819 }
820
821 *port= (uint16) strtol(port_buffer, NULL, 10);
822 }
823
824 DBUG_PRINT("exit", ("Client IP address: %s; port: %d",
825 (const char *) ip_buffer,
826 (int) *port));
827 DBUG_RETURN(FALSE);
828}
829
830
831/**
832 Retrieve the amount of data that can be read from a socket.
833
834 @param vio A VIO object.
835 @param bytes[out] The amount of bytes available.
836
837 @retval FALSE Success.
838 @retval TRUE Failure.
839*/
840// WL#4896: Not covered
841
842static my_bool socket_peek_read(Vio *vio, uint *bytes)
843{
844 my_socket sd= mysql_socket_getfd(vio->mysql_socket);
845#if defined(_WIN32)
846 u_long len;
847 if (ioctlsocket(sd, FIONREAD, &len))
848 return TRUE;
849 *bytes= len;
850 return FALSE;
851#elif defined(FIONREAD_IN_SYS_IOCTL) || defined(FIONREAD_IN_SYS_FILIO)
852 int len;
853 if (ioctl(sd, FIONREAD, &len) < 0)
854 return TRUE;
855 *bytes= len;
856 return FALSE;
857#else
858 char buf[1024];
859 ssize_t res= recv(sd, &buf, sizeof(buf), MSG_PEEK);
860 if (res < 0)
861 return TRUE;
862 *bytes= res;
863 return FALSE;
864#endif /*_WIN32*/
865}
866
867#ifndef _WIN32
868
869/**
870 Set of event flags grouped by operations.
871*/
872
873/*
874 Linux specific flag used to detect connection shutdown. The flag is
875 also used for half-closed notification, which here is interpreted as
876 if there is data available to be read from the socket.
877*/
878#ifndef POLLRDHUP
879#define POLLRDHUP 0
880#endif
881
882/* Data may be read. */
883#define MY_POLL_SET_IN (POLLIN | POLLPRI)
884/* Data may be written. */
885#define MY_POLL_SET_OUT (POLLOUT)
886/* An error or hangup. */
887#define MY_POLL_SET_ERR (POLLERR | POLLHUP | POLLNVAL)
888
889#endif /* _WIN32 */
890
891/**
892 Wait for an I/O event on a VIO socket.
893
894 @param vio VIO object representing a connected socket.
895 @param event The type of I/O event to wait for.
896 @param timeout Interval (in milliseconds) to wait for an I/O event.
897 A negative timeout value means an infinite timeout.
898
899 @remark sock_errno is set to SOCKET_ETIMEDOUT on timeout.
900
901 @return A three-state value which indicates the operation status.
902 @retval -1 Failure, socket_errno indicates the error.
903 @retval 0 The wait has timed out.
904 @retval 1 The requested I/O event has occurred.
905*/
906
907#ifndef _WIN32
908int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout)
909{
910 int ret;
911 short revents __attribute__((unused)) = 0;
912 struct pollfd pfd;
913 my_socket sd= mysql_socket_getfd(vio->mysql_socket);
914 MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */
915 DBUG_ENTER("vio_io_wait");
916 DBUG_PRINT("enter", ("timeout: %d", timeout));
917
918 /*
919 Note that if zero timeout, then we will not block, so we do not need to
920 yield to calling application in the async case.
921 */
922 if (timeout != 0 && vio->async_context && vio->async_context->active)
923 {
924 START_SOCKET_WAIT(locker, &state, vio->mysql_socket,
925 PSI_SOCKET_SELECT, timeout);
926 ret= my_io_wait_async(vio->async_context, event, timeout);
927 if (ret == 0)
928 {
929 DBUG_PRINT("info", ("timeout"));
930 errno= SOCKET_ETIMEDOUT;
931 }
932 END_SOCKET_WAIT(locker,timeout);
933 DBUG_RETURN(ret);
934 }
935
936 memset(&pfd, 0, sizeof(pfd));
937
938 pfd.fd= sd;
939
940 /*
941 Set the poll bitmask describing the type of events.
942 The error flags are only valid in the revents bitmask.
943 */
944 switch (event)
945 {
946 case VIO_IO_EVENT_READ:
947 pfd.events= MY_POLL_SET_IN;
948 revents= MY_POLL_SET_IN | MY_POLL_SET_ERR | POLLRDHUP;
949 break;
950 case VIO_IO_EVENT_WRITE:
951 case VIO_IO_EVENT_CONNECT:
952 pfd.events= MY_POLL_SET_OUT;
953 revents= MY_POLL_SET_OUT | MY_POLL_SET_ERR;
954 break;
955 }
956
957 START_SOCKET_WAIT(locker, &state, vio->mysql_socket, PSI_SOCKET_SELECT, timeout);
958 /*
959 Wait for the I/O event and return early in case of
960 error or timeout.
961 */
962 switch ((ret= poll(&pfd, 1, timeout)))
963 {
964 case -1:
965 DBUG_PRINT("error", ("poll returned -1"));
966 /* On error, -1 is returned. */
967 break;
968 case 0:
969 /*
970 Set errno to indicate a timeout error.
971 (This is not compiled in on WIN32.)
972 */
973 DBUG_PRINT("info", ("poll timeout"));
974 errno= SOCKET_ETIMEDOUT;
975 break;
976 default:
977 /* Ensure that the requested I/O event has completed. */
978 DBUG_ASSERT(pfd.revents & revents);
979 break;
980 }
981
982 END_SOCKET_WAIT(locker, timeout);
983 DBUG_RETURN(ret);
984}
985
986#else
987
988int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout)
989{
990 int ret;
991 struct timeval tm;
992 my_socket fd= mysql_socket_getfd(vio->mysql_socket);
993 fd_set readfds, writefds, exceptfds;
994 MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */
995 DBUG_ENTER("vio_io_wait");
996
997 /*
998 Note that if zero timeout, then we will not block, so we do not need to
999 yield to calling application in the async case.
1000 */
1001 if (timeout != 0 && vio->async_context && vio->async_context->active)
1002 {
1003 START_SOCKET_WAIT(locker, &state, vio->mysql_socket,
1004 PSI_SOCKET_SELECT, timeout);
1005 ret= my_io_wait_async(vio->async_context, event, timeout);
1006 if (ret == 0)
1007 WSASetLastError(SOCKET_ETIMEDOUT);
1008 END_SOCKET_WAIT(locker, timeout);
1009 DBUG_RETURN(ret);
1010 }
1011
1012 /* Convert the timeout, in milliseconds, to seconds and microseconds. */
1013 if (timeout >= 0)
1014 {
1015 tm.tv_sec= timeout / 1000;
1016 tm.tv_usec= (timeout % 1000) * 1000;
1017 }
1018
1019 FD_ZERO(&readfds);
1020 FD_ZERO(&writefds);
1021 FD_ZERO(&exceptfds);
1022
1023 /* Always receive notification of exceptions. */
1024 FD_SET(fd, &exceptfds);
1025
1026 switch (event)
1027 {
1028 case VIO_IO_EVENT_READ:
1029 /* Readiness for reading. */
1030 FD_SET(fd, &readfds);
1031 break;
1032 case VIO_IO_EVENT_WRITE:
1033 case VIO_IO_EVENT_CONNECT:
1034 /* Readiness for writing. */
1035 FD_SET(fd, &writefds);
1036 break;
1037 }
1038
1039 START_SOCKET_WAIT(locker, &state, vio->mysql_socket, PSI_SOCKET_SELECT, timeout);
1040
1041 /* The first argument is ignored on Windows. */
1042 ret= select(0, &readfds, &writefds, &exceptfds, (timeout >= 0) ? &tm : NULL);
1043
1044 END_SOCKET_WAIT(locker, timeout);
1045
1046 /* Set error code to indicate a timeout error. */
1047 if (ret == 0)
1048 WSASetLastError(SOCKET_ETIMEDOUT);
1049
1050 /* Error or timeout? */
1051 if (ret <= 0)
1052 DBUG_RETURN(ret);
1053
1054 /* The requested I/O event is ready? */
1055 switch (event)
1056 {
1057 case VIO_IO_EVENT_READ:
1058 ret= MY_TEST(FD_ISSET(fd, &readfds));
1059 break;
1060 case VIO_IO_EVENT_WRITE:
1061 case VIO_IO_EVENT_CONNECT:
1062 ret= MY_TEST(FD_ISSET(fd, &writefds));
1063 break;
1064 }
1065
1066 /* Error conditions pending? */
1067 ret|= MY_TEST(FD_ISSET(fd, &exceptfds));
1068
1069 /* Not a timeout, ensure that a condition was met. */
1070 DBUG_ASSERT(ret);
1071
1072 DBUG_RETURN(ret);
1073}
1074
1075#endif /* _WIN32 */
1076
1077
1078/**
1079 Connect to a peer address.
1080
1081 @param vio A VIO object.
1082 @param addr Socket address containing the peer address.
1083 @param len Length of socket address.
1084 @param timeout Interval (in milliseconds) to wait until a
1085 connection is established.
1086
1087 @retval FALSE A connection was successfully established.
1088 @retval TRUE A fatal error. See socket_errno.
1089*/
1090
1091my_bool
1092vio_socket_connect(Vio *vio, struct sockaddr *addr, socklen_t len, int timeout)
1093{
1094 int ret, wait;
1095 my_bool not_used;
1096 DBUG_ENTER("vio_socket_connect");
1097
1098 /* Only for socket-based transport types. */
1099 DBUG_ASSERT(vio->type == VIO_TYPE_SOCKET || vio->type == VIO_TYPE_TCPIP);
1100
1101 /* If timeout is not infinite, set socket to non-blocking mode. */
1102 if ((timeout > -1) && vio_blocking(vio, FALSE, &not_used))
1103 DBUG_RETURN(TRUE);
1104
1105 /* Initiate the connection. */
1106 ret= mysql_socket_connect(vio->mysql_socket, addr, len);
1107
1108#ifdef _WIN32
1109 wait= (ret == SOCKET_ERROR) &&
1110 (WSAGetLastError() == WSAEINPROGRESS ||
1111 WSAGetLastError() == WSAEWOULDBLOCK);
1112#else
1113 wait= (ret == -1) && (errno == EINPROGRESS || errno == EALREADY);
1114#endif
1115
1116 /*
1117 The connection is in progress. The vio_io_wait() call can be used
1118 to wait up to a specified period of time for the connection to
1119 succeed.
1120
1121 If vio_io_wait() returns 0 (after waiting however many seconds),
1122 the socket never became writable (host is probably unreachable.)
1123 Otherwise, if vio_io_wait() returns 1, then one of two conditions
1124 exist:
1125
1126 1. An error occurred. Use getsockopt() to check for this.
1127 2. The connection was set up successfully: getsockopt() will
1128 return 0 as an error.
1129 */
1130 if (wait && (vio_io_wait(vio, VIO_IO_EVENT_CONNECT, timeout) == 1))
1131 {
1132 int error;
1133 IF_WIN(int, socklen_t) optlen= sizeof(error);
1134 IF_WIN(char, void) *optval= (IF_WIN(char, void) *) &error;
1135
1136 /*
1137 At this point, we know that something happened on the socket.
1138 But this does not means that everything is alright. The connect
1139 might have failed. We need to retrieve the error code from the
1140 socket layer. We must return success only if we are sure that
1141 it was really a success. Otherwise we might prevent the caller
1142 from trying another address to connect to.
1143 */
1144 if (!(ret= mysql_socket_getsockopt(vio->mysql_socket, SOL_SOCKET,
1145 SO_ERROR, optval, &optlen)))
1146 {
1147#ifdef _WIN32
1148 WSASetLastError(error);
1149#else
1150 errno= error;
1151#endif
1152 ret= MY_TEST(error);
1153 }
1154 }
1155
1156 /* If necessary, restore the blocking mode, but only if connect succeeded. */
1157 if ((timeout > -1) && (ret == 0))
1158 {
1159 my_bool not_used;
1160 if (vio_blocking(vio, TRUE, &not_used))
1161 DBUG_RETURN(TRUE);
1162 }
1163
1164 DBUG_RETURN(MY_TEST(ret));
1165}
1166
1167
1168/**
1169 Determine if the endpoint of a connection is still available.
1170
1171 @remark The socket is assumed to be disconnected if an EOF
1172 condition is encountered.
1173
1174 @param vio The VIO object.
1175
1176 @retval TRUE EOF condition not found.
1177 @retval FALSE EOF condition is signaled.
1178*/
1179
1180my_bool vio_is_connected(Vio *vio)
1181{
1182 uint bytes= 0;
1183 DBUG_ENTER("vio_is_connected");
1184
1185 /*
1186 The first step of detecting an EOF condition is verifying
1187 whether there is data to read. Data in this case would be
1188 the EOF. An exceptional condition event and/or errors are
1189 interpreted as if there is data to read.
1190 */
1191 if (!vio_io_wait(vio, VIO_IO_EVENT_READ, 0))
1192 DBUG_RETURN(TRUE);
1193
1194 /*
1195 The second step is read() or recv() from the socket returning
1196 0 (EOF). Unfortunately, it's not possible to call read directly
1197 as we could inadvertently read meaningful connection data.
1198 Simulate a read by retrieving the number of bytes available to
1199 read -- 0 meaning EOF. In the presence of unrecoverable errors,
1200 the socket is assumed to be disconnected.
1201 */
1202 while (socket_peek_read(vio, &bytes))
1203 {
1204 if (socket_errno != SOCKET_EINTR)
1205 DBUG_RETURN(FALSE);
1206 }
1207
1208#ifdef HAVE_OPENSSL
1209 /* There might be buffered data at the SSL layer. */
1210 if (!bytes && vio->type == VIO_TYPE_SSL)
1211 bytes= SSL_pending((SSL*) vio->ssl_arg);
1212#endif
1213
1214 DBUG_RETURN(bytes ? TRUE : FALSE);
1215}
1216
1217#ifndef DBUG_OFF
1218
1219/**
1220 Number of bytes in the read or socket buffer
1221
1222 @remark An EOF condition might count as one readable byte.
1223
1224 @return number of bytes in one of the buffers or < 0 if error.
1225*/
1226
1227ssize_t vio_pending(Vio *vio)
1228{
1229 uint bytes= 0;
1230
1231 /* Data pending on the read buffer. */
1232 if (vio->read_pos < vio->read_end)
1233 return vio->read_end - vio->read_pos;
1234
1235 /* Skip non-socket based transport types. */
1236 if (vio->type == VIO_TYPE_TCPIP || vio->type == VIO_TYPE_SOCKET)
1237 {
1238 /* Obtain number of readable bytes in the socket buffer. */
1239 if (socket_peek_read(vio, &bytes))
1240 return -1;
1241 }
1242
1243 /*
1244 SSL not checked due to a yaSSL bug in SSL_pending that
1245 causes it to attempt to read from the socket.
1246 */
1247
1248 return (ssize_t) bytes;
1249}
1250
1251#endif /* DBUG_OFF */
1252
1253/**
1254 Checks if the error code, returned by vio_getnameinfo(), means it was the
1255 "No-name" error.
1256
1257 Windows-specific note: getnameinfo() returns WSANO_DATA instead of
1258 EAI_NODATA or EAI_NONAME when no reverse mapping is available at the host
1259 (i.e. Windows can't get hostname by IP-address). This error should be
1260 treated as EAI_NONAME.
1261
1262 @return if the error code is actually EAI_NONAME.
1263 @retval true if the error code is EAI_NONAME.
1264 @retval false otherwise.
1265*/
1266
1267my_bool vio_is_no_name_error(int err_code)
1268{
1269#ifdef _WIN32
1270
1271 return err_code == WSANO_DATA || err_code == EAI_NONAME;
1272
1273#else
1274
1275 return err_code == EAI_NONAME;
1276
1277#endif
1278}
1279
1280
1281/**
1282 This is a wrapper for the system getnameinfo(), because different OS
1283 differ in the getnameinfo() implementation:
1284 - Solaris 10 requires that the 2nd argument (salen) must match the
1285 actual size of the struct sockaddr_storage passed to it;
1286 - Mac OS X has sockaddr_in::sin_len and sockaddr_in6::sin6_len and
1287 requires them to be filled.
1288*/
1289
1290int vio_getnameinfo(const struct sockaddr *sa,
1291 char *hostname, size_t hostname_size,
1292 char *port, size_t port_size,
1293 int flags)
1294{
1295 int sa_length= 0;
1296
1297 switch (sa->sa_family) {
1298 case AF_INET:
1299 sa_length= sizeof (struct sockaddr_in);
1300#ifdef HAVE_SOCKADDR_IN_SIN_LEN
1301 ((struct sockaddr_in *) sa)->sin_len= sa_length;
1302#endif /* HAVE_SOCKADDR_IN_SIN_LEN */
1303 break;
1304
1305#ifdef HAVE_IPV6
1306 case AF_INET6:
1307 sa_length= sizeof (struct sockaddr_in6);
1308# ifdef HAVE_SOCKADDR_IN6_SIN6_LEN
1309 ((struct sockaddr_in6 *) sa)->sin6_len= sa_length;
1310# endif /* HAVE_SOCKADDR_IN6_SIN6_LEN */
1311 break;
1312#endif /* HAVE_IPV6 */
1313 }
1314
1315 return getnameinfo(sa, sa_length,
1316 hostname, (uint)hostname_size,
1317 port, (uint)port_size,
1318 flags);
1319}
1320