1/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
2 Copyright (c) 2017, MariaDB Corporation.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License as
6published by the Free Software Foundation; version 2 of the
7License.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
1702110-1301 USA
18*/
19
20#ifndef MYSQL_SOCKET_H
21#define MYSQL_SOCKET_H
22
23/* For MY_STAT */
24#include <my_dir.h>
25/* For my_chsize */
26#include <my_sys.h>
27/* For socket api */
28#ifdef __WIN__
29 #include <ws2def.h>
30 #include <winsock2.h>
31 #include <MSWSock.h>
32 #define SOCKBUF_T char
33#else
34 #include <netinet/in.h>
35 #define SOCKBUF_T void
36#endif
37/**
38 @file mysql/psi/mysql_socket.h
39[...]
40*/
41
42#include "mysql/psi/psi.h"
43
44/**
45 @defgroup Socket_instrumentation Socket Instrumentation
46 @ingroup Instrumentation_interface
47 @{
48*/
49
50/**
51 @def mysql_socket_register(P1, P2, P3)
52 Socket registration.
53*/
54#ifdef HAVE_PSI_SOCKET_INTERFACE
55 #define mysql_socket_register(P1, P2, P3) \
56 inline_mysql_socket_register(P1, P2, P3)
57#else
58 #define mysql_socket_register(P1, P2, P3) \
59 do {} while (0)
60#endif
61
62struct st_mysql_socket
63{
64 /** The real socket descriptor. */
65 my_socket fd;
66
67 /**
68 The instrumentation hook.
69 Note that this hook is not conditionally defined,
70 for binary compatibility of the @c MYSQL_SOCKET interface.
71 */
72 struct PSI_socket *m_psi;
73};
74
75/**
76 An instrumented socket.
77 @c MYSQL_SOCKET is a replacement for @c my_socket.
78*/
79typedef struct st_mysql_socket MYSQL_SOCKET;
80
81
82/**
83 @def MYSQL_INVALID_SOCKET
84 MYSQL_SOCKET initial value.
85*/
86//MYSQL_SOCKET MYSQL_INVALID_SOCKET= {INVALID_SOCKET, NULL};
87#define MYSQL_INVALID_SOCKET mysql_socket_invalid()
88
89/**
90 MYSQL_SOCKET helper. Initialize instrumented socket.
91 @sa mysql_socket_getfd
92 @sa mysql_socket_setfd
93*/
94static inline MYSQL_SOCKET
95mysql_socket_invalid()
96{
97 MYSQL_SOCKET mysql_socket= {INVALID_SOCKET, NULL};
98 return mysql_socket;
99}
100
101/**
102 Set socket descriptor and address.
103 @param socket nstrumented socket
104 @param fd socket descriptor
105 @param addr unformatted socket address
106 @param adr_len length of socket address
107*/
108
109static inline void
110mysql_socket_set_address(
111#ifdef HAVE_PSI_SOCKET_INTERFACE
112 MYSQL_SOCKET socket,
113 const struct sockaddr *addr,
114 socklen_t addr_len
115#else
116 MYSQL_SOCKET socket __attribute__ ((unused)),
117 const struct sockaddr *addr __attribute__ ((unused)),
118 socklen_t addr_len __attribute__ ((unused))
119#endif
120)
121{
122#ifdef HAVE_PSI_SOCKET_INTERFACE
123 if (socket.m_psi != NULL)
124 PSI_SOCKET_CALL(set_socket_info)(socket.m_psi, NULL, addr, addr_len);
125#endif
126}
127
128/**
129 Set socket descriptor and address.
130 @param socket instrumented socket
131 @param thread instrumented owning thread
132*/
133static inline void
134mysql_socket_set_thread_owner(
135#ifdef HAVE_PSI_SOCKET_INTERFACE
136MYSQL_SOCKET socket
137#else
138MYSQL_SOCKET socket __attribute__ ((unused))
139#endif
140)
141{
142#ifdef HAVE_PSI_SOCKET_INTERFACE
143 if (socket.m_psi != NULL)
144 PSI_SOCKET_CALL(set_socket_thread_owner)(socket.m_psi);
145#endif
146}
147
148/**
149 MYSQL_SOCKET helper. Get socket descriptor.
150 @param mysql_socket Instrumented socket
151 @sa mysql_socket_getfd
152*/
153static inline my_socket
154mysql_socket_getfd(MYSQL_SOCKET mysql_socket)
155{
156 return mysql_socket.fd;
157}
158
159/**
160 MYSQL_SOCKET helper. Set socket descriptor.
161 @param mysql_socket Instrumented socket
162 @param fd Socket descriptor
163 @sa mysql_socket_setfd
164*/
165static inline void
166mysql_socket_setfd(MYSQL_SOCKET *mysql_socket, my_socket fd)
167{
168 if (likely(mysql_socket != NULL))
169 mysql_socket->fd= fd;
170}
171
172/**
173 @def MYSQL_SOCKET_WAIT_VARIABLES
174 Instrumentation helper for socket waits.
175 This instrumentation declares local variables.
176 Do not use a ';' after this macro
177 @param LOCKER locker
178 @param STATE locker state
179 @sa MYSQL_START_SOCKET_WAIT.
180 @sa MYSQL_END_SOCKET_WAIT.
181*/
182#ifdef HAVE_PSI_SOCKET_INTERFACE
183 #define MYSQL_SOCKET_WAIT_VARIABLES(LOCKER, STATE) \
184 struct PSI_socket_locker* LOCKER; \
185 PSI_socket_locker_state STATE;
186#else
187 #define MYSQL_SOCKET_WAIT_VARIABLES(LOCKER, STATE)
188#endif
189
190/**
191 @def MYSQL_START_SOCKET_WAIT
192 Instrumentation helper for socket waits.
193 This instrumentation marks the start of a wait event.
194 @param LOCKER locker
195 @param STATE locker state
196 @param SOCKET instrumented socket
197 @param OP The socket operation to be performed
198 @param FLAGS per-socket operation flags.
199 @param COUNT bytes to be written/read
200 @sa MYSQL_END_SOCKET_WAIT.
201*/
202#ifdef HAVE_PSI_SOCKET_INTERFACE
203 #define MYSQL_START_SOCKET_WAIT(LOCKER, STATE, SOCKET, OP, COUNT) \
204 LOCKER= inline_mysql_start_socket_wait(STATE, SOCKET, OP, COUNT,\
205 __FILE__, __LINE__)
206#else
207 #define MYSQL_START_SOCKET_WAIT(LOCKER, STATE, SOCKET, OP, COUNT) \
208 do {} while (0)
209#endif
210
211/**
212 @def MYSQL_END_SOCKET_WAIT
213 Instrumentation helper for socket waits.
214 This instrumentation marks the end of a wait event.
215 @param LOCKER locker
216 @param COUNT actual bytes written/read, or -1
217 @sa MYSQL_START_SOCKET_WAIT.
218*/
219#ifdef HAVE_PSI_SOCKET_INTERFACE
220 #define MYSQL_END_SOCKET_WAIT(LOCKER, COUNT) \
221 inline_mysql_end_socket_wait(LOCKER, COUNT)
222#else
223 #define MYSQL_END_SOCKET_WAIT(LOCKER, COUNT) \
224 do {} while (0)
225#endif
226
227#ifdef HAVE_PSI_SOCKET_INTERFACE
228 #define MYSQL_SOCKET_SET_STATE(SOCKET, STATE) \
229 inline_mysql_socket_set_state(SOCKET, STATE)
230#else
231 #define MYSQL_SOCKET_SET_STATE(SOCKET, STATE) \
232 do {} while (0)
233#endif
234
235#ifdef HAVE_PSI_SOCKET_INTERFACE
236/**
237 Instrumentation calls for MYSQL_START_SOCKET_WAIT.
238 @sa MYSQL_START_SOCKET_WAIT.
239*/
240static inline struct PSI_socket_locker*
241inline_mysql_start_socket_wait(PSI_socket_locker_state *state,
242 MYSQL_SOCKET mysql_socket,
243 enum PSI_socket_operation op,
244 size_t byte_count,
245 const char *src_file, uint src_line)
246{
247 struct PSI_socket_locker *locker;
248 if (psi_likely(mysql_socket.m_psi != NULL))
249 {
250 locker= PSI_SOCKET_CALL(start_socket_wait)
251 (state, mysql_socket.m_psi, op, byte_count, src_file, src_line);
252 }
253 else
254 locker= NULL;
255 return locker;
256}
257
258/**
259 Instrumentation calls for MYSQL_END_SOCKET_WAIT.
260 @sa MYSQL_END_SOCKET_WAIT.
261*/
262static inline void
263inline_mysql_end_socket_wait(struct PSI_socket_locker *locker, size_t byte_count)
264{
265 if (psi_likely(locker != NULL))
266 PSI_SOCKET_CALL(end_socket_wait)(locker, byte_count);
267}
268
269/**
270 Set the state (IDLE, ACTIVE) of an instrumented socket.
271 @param socket the instrumented socket
272 @param state the new state
273 @sa PSI_socket_state
274*/
275static inline void
276inline_mysql_socket_set_state(MYSQL_SOCKET socket, enum PSI_socket_state state)
277{
278 if (socket.m_psi != NULL)
279 PSI_SOCKET_CALL(set_socket_state)(socket.m_psi, state);
280}
281#endif /* HAVE_PSI_SOCKET_INTERFACE */
282
283/**
284 @def mysql_socket_socket(K, D, T, P)
285 Create a socket.
286 @c mysql_socket_socket is a replacement for @c socket.
287 @param K PSI_socket_key for this instrumented socket
288 @param D Socket domain
289 @param T Protocol type
290 @param P Transport protocol
291*/
292
293#ifdef HAVE_PSI_SOCKET_INTERFACE
294 #define mysql_socket_socket(K, D, T, P) \
295 inline_mysql_socket_socket(K, D, T, P)
296#else
297 #define mysql_socket_socket(K, D, T, P) \
298 inline_mysql_socket_socket(D, T, P)
299#endif
300
301/**
302 @def mysql_socket_bind(FD, AP, L)
303 Bind a socket to a local port number and IP address
304 @c mysql_socket_bind is a replacement for @c bind.
305 @param FD Instrumented socket descriptor returned by socket()
306 @param AP Pointer to local port number and IP address in sockaddr structure
307 @param L Length of sockaddr structure
308*/
309#ifdef HAVE_PSI_SOCKET_INTERFACE
310 #define mysql_socket_bind(FD, AP, L) \
311 inline_mysql_socket_bind(__FILE__, __LINE__, FD, AP, L)
312#else
313 #define mysql_socket_bind(FD, AP, L) \
314 inline_mysql_socket_bind(FD, AP, L)
315#endif
316
317/**
318 @def mysql_socket_getsockname(FD, AP, LP)
319 Return port number and IP address of the local host
320 @c mysql_socket_getsockname is a replacement for @c getsockname.
321 @param FD Instrumented socket descriptor returned by socket()
322 @param A Pointer to returned address of local host in sockaddr structure
323 @param L Pointer to length of sockaddr structure
324*/
325#ifdef HAVE_PSI_SOCKET_INTERFACE
326 #define mysql_socket_getsockname(FD, AP, LP) \
327 inline_mysql_socket_getsockname(__FILE__, __LINE__, FD, AP, LP)
328#else
329 #define mysql_socket_getsockname(FD, AP, LP) \
330 inline_mysql_socket_getsockname(FD, AP, LP)
331#endif
332
333/**
334 @def mysql_socket_connect(FD, AP, L)
335 Establish a connection to a remote host.
336 @c mysql_socket_connect is a replacement for @c connect.
337 @param FD Instrumented socket descriptor returned by socket()
338 @param AP Pointer to target address in sockaddr structure
339 @param L Length of sockaddr structure
340*/
341#ifdef HAVE_PSI_SOCKET_INTERFACE
342 #define mysql_socket_connect(FD, AP, L) \
343 inline_mysql_socket_connect(__FILE__, __LINE__, FD, AP, L)
344#else
345 #define mysql_socket_connect(FD, AP, L) \
346 inline_mysql_socket_connect(FD, AP, L)
347#endif
348
349/**
350 @def mysql_socket_getpeername(FD, AP, LP)
351 Get port number and IP address of remote host that a socket is connected to.
352 @c mysql_socket_getpeername is a replacement for @c getpeername.
353 @param FD Instrumented socket descriptor returned by socket() or accept()
354 @param AP Pointer to returned address of remote host in sockaddr structure
355 @param LP Pointer to length of sockaddr structure
356*/
357#ifdef HAVE_PSI_SOCKET_INTERFACE
358 #define mysql_socket_getpeername(FD, AP, LP) \
359 inline_mysql_socket_getpeername(__FILE__, __LINE__, FD, AP, LP)
360#else
361 #define mysql_socket_getpeername(FD, AP, LP) \
362 inline_mysql_socket_getpeername(FD, AP, LP)
363#endif
364
365/**
366 @def mysql_socket_send(FD, B, N, FL)
367 Send data from the buffer, B, to a connected socket.
368 @c mysql_socket_send is a replacement for @c send.
369 @param FD Instrumented socket descriptor returned by socket() or accept()
370 @param B Buffer to send
371 @param N Number of bytes to send
372 @param FL Control flags
373*/
374#ifdef HAVE_PSI_SOCKET_INTERFACE
375 #define mysql_socket_send(FD, B, N, FL) \
376 inline_mysql_socket_send(__FILE__, __LINE__, FD, B, N, FL)
377#else
378 #define mysql_socket_send(FD, B, N, FL) \
379 inline_mysql_socket_send(FD, B, N, FL)
380#endif
381
382/**
383 @def mysql_socket_recv(FD, B, N, FL)
384 Receive data from a connected socket.
385 @c mysql_socket_recv is a replacement for @c recv.
386 @param FD Instrumented socket descriptor returned by socket() or accept()
387 @param B Buffer to receive to
388 @param N Maximum bytes to receive
389 @param FL Control flags
390*/
391#ifdef HAVE_PSI_SOCKET_INTERFACE
392 #define mysql_socket_recv(FD, B, N, FL) \
393 inline_mysql_socket_recv(__FILE__, __LINE__, FD, B, N, FL)
394#else
395 #define mysql_socket_recv(FD, B, N, FL) \
396 inline_mysql_socket_recv(FD, B, N, FL)
397#endif
398
399/**
400 @def mysql_socket_sendto(FD, B, N, FL, AP, L)
401 Send data to a socket at the specified address.
402 @c mysql_socket_sendto is a replacement for @c sendto.
403 @param FD Instrumented socket descriptor returned by socket()
404 @param B Buffer to send
405 @param N Number of bytes to send
406 @param FL Control flags
407 @param AP Pointer to destination sockaddr structure
408 @param L Size of sockaddr structure
409*/
410#ifdef HAVE_PSI_SOCKET_INTERFACE
411 #define mysql_socket_sendto(FD, B, N, FL, AP, L) \
412 inline_mysql_socket_sendto(__FILE__, __LINE__, FD, B, N, FL, AP, L)
413#else
414 #define mysql_socket_sendto(FD, B, N, FL, AP, L) \
415 inline_mysql_socket_sendto(FD, B, N, FL, AP, L)
416#endif
417
418/**
419 @def mysql_socket_recvfrom(FD, B, N, FL, AP, L)
420 Receive data from a socket and return source address information
421 @c mysql_socket_recvfrom is a replacement for @c recvfrom.
422 @param FD Instrumented socket descriptor returned by socket()
423 @param B Buffer to receive to
424 @param N Maximum bytes to receive
425 @param FL Control flags
426 @param AP Pointer to source address in sockaddr_storage structure
427 @param L Size of sockaddr_storage structure
428*/
429#ifdef HAVE_PSI_SOCKET_INTERFACE
430 #define mysql_socket_recvfrom(FD, B, N, FL, AP, LP) \
431 inline_mysql_socket_recvfrom(__FILE__, __LINE__, FD, B, N, FL, AP, LP)
432#else
433 #define mysql_socket_recvfrom(FD, B, N, FL, AP, LP) \
434 inline_mysql_socket_recvfrom(FD, B, N, FL, AP, LP)
435#endif
436
437/**
438 @def mysql_socket_getsockopt(FD, LV, ON, OP, OL)
439 Get a socket option for the specified socket.
440 @c mysql_socket_getsockopt is a replacement for @c getsockopt.
441 @param FD Instrumented socket descriptor returned by socket()
442 @param LV Protocol level
443 @param ON Option to query
444 @param OP Buffer which will contain the value for the requested option
445 @param OL Pointer to length of OP
446*/
447#ifdef HAVE_PSI_SOCKET_INTERFACE
448 #define mysql_socket_getsockopt(FD, LV, ON, OP, OL) \
449 inline_mysql_socket_getsockopt(__FILE__, __LINE__, FD, LV, ON, OP, OL)
450#else
451 #define mysql_socket_getsockopt(FD, LV, ON, OP, OL) \
452 inline_mysql_socket_getsockopt(FD, LV, ON, OP, OL)
453#endif
454
455/**
456 @def mysql_socket_setsockopt(FD, LV, ON, OP, OL)
457 Set a socket option for the specified socket.
458 @c mysql_socket_setsockopt is a replacement for @c setsockopt.
459 @param FD Instrumented socket descriptor returned by socket()
460 @param LV Protocol level
461 @param ON Option to modify
462 @param OP Buffer containing the value for the specified option
463 @param OL Pointer to length of OP
464*/
465#ifdef HAVE_PSI_SOCKET_INTERFACE
466 #define mysql_socket_setsockopt(FD, LV, ON, OP, OL) \
467 inline_mysql_socket_setsockopt(__FILE__, __LINE__, FD, LV, ON, OP, OL)
468#else
469 #define mysql_socket_setsockopt(FD, LV, ON, OP, OL) \
470 inline_mysql_socket_setsockopt(FD, LV, ON, OP, OL)
471#endif
472
473/**
474 @def mysql_socket_listen(FD, N)
475 Set socket state to listen for an incoming connection.
476 @c mysql_socket_listen is a replacement for @c listen.
477 @param FD Instrumented socket descriptor, bound and connected
478 @param N Maximum number of pending connections allowed.
479*/
480#ifdef HAVE_PSI_SOCKET_INTERFACE
481 #define mysql_socket_listen(FD, N) \
482 inline_mysql_socket_listen(__FILE__, __LINE__, FD, N)
483#else
484 #define mysql_socket_listen(FD, N) \
485 inline_mysql_socket_listen(FD, N)
486#endif
487
488/**
489 @def mysql_socket_accept(K, FD, AP, LP)
490 Accept a connection from any remote host; TCP only.
491 @c mysql_socket_accept is a replacement for @c accept.
492 @param K PSI_socket_key for this instrumented socket
493 @param FD Instrumented socket descriptor, bound and placed in a listen state
494 @param AP Pointer to sockaddr structure with returned IP address and port of connected host
495 @param LP Pointer to length of valid information in AP
496*/
497#ifdef HAVE_PSI_SOCKET_INTERFACE
498 #define mysql_socket_accept(K, FD, AP, LP) \
499 inline_mysql_socket_accept(__FILE__, __LINE__, K, FD, AP, LP)
500#else
501 #define mysql_socket_accept(K, FD, AP, LP) \
502 inline_mysql_socket_accept(FD, AP, LP)
503#endif
504
505/**
506 @def mysql_socket_close(FD)
507 Close a socket and sever any connections.
508 @c mysql_socket_close is a replacement for @c close.
509 @param FD Instrumented socket descriptor returned by socket() or accept()
510*/
511#ifdef HAVE_PSI_SOCKET_INTERFACE
512 #define mysql_socket_close(FD) \
513 inline_mysql_socket_close(__FILE__, __LINE__, FD)
514#else
515 #define mysql_socket_close(FD) \
516 inline_mysql_socket_close(FD)
517#endif
518
519/**
520 @def mysql_socket_shutdown(FD, H)
521 Disable receives and/or sends on a socket.
522 @c mysql_socket_shutdown is a replacement for @c shutdown.
523 @param FD Instrumented socket descriptor returned by socket() or accept()
524 @param H Specifies which operations to shutdown
525*/
526#ifdef HAVE_PSI_SOCKET_INTERFACE
527 #define mysql_socket_shutdown(FD, H) \
528 inline_mysql_socket_shutdown(__FILE__, __LINE__, FD, H)
529#else
530 #define mysql_socket_shutdown(FD, H) \
531 inline_mysql_socket_shutdown(FD, H)
532#endif
533
534#ifdef HAVE_PSI_SOCKET_INTERFACE
535static inline void inline_mysql_socket_register(
536 const char *category,
537 PSI_socket_info *info,
538 int count)
539{
540 PSI_SOCKET_CALL(register_socket)(category, info, count);
541}
542#endif
543
544/** mysql_socket_socket */
545
546static inline MYSQL_SOCKET
547inline_mysql_socket_socket
548(
549#ifdef HAVE_PSI_SOCKET_INTERFACE
550 PSI_socket_key key,
551#endif
552 int domain, int type, int protocol)
553{
554 MYSQL_SOCKET mysql_socket= MYSQL_INVALID_SOCKET;
555 mysql_socket.fd= socket(domain, type | SOCK_CLOEXEC, protocol);
556
557#ifdef HAVE_PSI_SOCKET_INTERFACE
558 if (likely(mysql_socket.fd != INVALID_SOCKET))
559 {
560 mysql_socket.m_psi= PSI_SOCKET_CALL(init_socket)
561 (key, (const my_socket*)&mysql_socket.fd, NULL, 0);
562 }
563#endif
564 return mysql_socket;
565}
566
567/** mysql_socket_bind */
568
569static inline int
570inline_mysql_socket_bind
571(
572#ifdef HAVE_PSI_SOCKET_INTERFACE
573 const char *src_file, uint src_line,
574#endif
575 MYSQL_SOCKET mysql_socket, const struct sockaddr *addr, size_t len)
576{
577 int result;
578
579#ifdef HAVE_PSI_SOCKET_INTERFACE
580 if (psi_likely(mysql_socket.m_psi != NULL))
581 {
582 /* Instrumentation start */
583 PSI_socket_locker_state state;
584 PSI_socket_locker *locker;
585 locker= PSI_SOCKET_CALL(start_socket_wait)
586 (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line);
587
588 /* Instrumented code */
589 result= bind(mysql_socket.fd, addr, (int)len);
590
591 /* Instrumentation end */
592 if (result == 0)
593 PSI_SOCKET_CALL(set_socket_info)(mysql_socket.m_psi, NULL, addr, (socklen_t)len);
594
595 if (locker != NULL)
596 PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
597
598 return result;
599 }
600#endif
601
602 /* Non instrumented code */
603 result= bind(mysql_socket.fd, addr, (int)len);
604 return result;
605}
606
607/** mysql_socket_getsockname */
608
609static inline int
610inline_mysql_socket_getsockname
611(
612#ifdef HAVE_PSI_SOCKET_INTERFACE
613 const char *src_file, uint src_line,
614#endif
615 MYSQL_SOCKET mysql_socket, struct sockaddr *addr, socklen_t *len)
616{
617 int result;
618
619#ifdef HAVE_PSI_SOCKET_INTERFACE
620 if (psi_likely(mysql_socket.m_psi != NULL))
621 {
622 /* Instrumentation start */
623 PSI_socket_locker *locker;
624 PSI_socket_locker_state state;
625 locker= PSI_SOCKET_CALL(start_socket_wait)
626 (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line);
627
628 /* Instrumented code */
629 result= getsockname(mysql_socket.fd, addr, len);
630
631 /* Instrumentation end */
632 if (locker != NULL)
633 PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
634
635 return result;
636 }
637#endif
638
639 /* Non instrumented code */
640 result= getsockname(mysql_socket.fd, addr, len);
641
642 return result;
643}
644
645/** mysql_socket_connect */
646
647static inline int
648inline_mysql_socket_connect
649(
650#ifdef HAVE_PSI_SOCKET_INTERFACE
651 const char *src_file, uint src_line,
652#endif
653 MYSQL_SOCKET mysql_socket, const struct sockaddr *addr, socklen_t len)
654{
655 int result;
656
657#ifdef HAVE_PSI_SOCKET_INTERFACE
658 if (psi_likely(mysql_socket.m_psi != NULL))
659 {
660 /* Instrumentation start */
661 PSI_socket_locker *locker;
662 PSI_socket_locker_state state;
663 locker= PSI_SOCKET_CALL(start_socket_wait)
664 (&state, mysql_socket.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line);
665
666 /* Instrumented code */
667 result= connect(mysql_socket.fd, addr, len);
668
669 /* Instrumentation end */
670 if (locker != NULL)
671 PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
672
673 return result;
674 }
675#endif
676
677 /* Non instrumented code */
678 result= connect(mysql_socket.fd, addr, len);
679
680 return result;
681}
682
683/** mysql_socket_getpeername */
684
685static inline int
686inline_mysql_socket_getpeername
687(
688#ifdef HAVE_PSI_SOCKET_INTERFACE
689 const char *src_file, uint src_line,
690#endif
691 MYSQL_SOCKET mysql_socket, struct sockaddr *addr, socklen_t *len)
692{
693 int result;
694
695#ifdef HAVE_PSI_SOCKET_INTERFACE
696 if (psi_likely(mysql_socket.m_psi != NULL))
697 {
698 /* Instrumentation start */
699 PSI_socket_locker *locker;
700 PSI_socket_locker_state state;
701 locker= PSI_SOCKET_CALL(start_socket_wait)
702 (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line);
703
704 /* Instrumented code */
705 result= getpeername(mysql_socket.fd, addr, len);
706
707 /* Instrumentation end */
708 if (locker != NULL)
709 PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
710
711 return result;
712 }
713#endif
714
715 /* Non instrumented code */
716 result= getpeername(mysql_socket.fd, addr, len);
717
718 return result;
719}
720
721/** mysql_socket_send */
722
723static inline ssize_t
724inline_mysql_socket_send
725(
726#ifdef HAVE_PSI_SOCKET_INTERFACE
727 const char *src_file, uint src_line,
728#endif
729 MYSQL_SOCKET mysql_socket, const SOCKBUF_T *buf, size_t n, int flags)
730{
731 ssize_t result;
732
733#ifdef HAVE_PSI_SOCKET_INTERFACE
734 if (psi_likely(mysql_socket.m_psi != NULL))
735 {
736 /* Instrumentation start */
737 PSI_socket_locker *locker;
738 PSI_socket_locker_state state;
739 locker= PSI_SOCKET_CALL(start_socket_wait)
740 (&state, mysql_socket.m_psi, PSI_SOCKET_SEND, n, src_file, src_line);
741
742 /* Instrumented code */
743 result= send(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
744
745 /* Instrumentation end */
746 if (locker != NULL)
747 {
748 size_t bytes_written= (result > 0) ? (size_t) result : 0;
749 PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_written);
750 }
751
752 return result;
753 }
754#endif
755
756 /* Non instrumented code */
757 result= send(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
758
759 return result;
760}
761
762/** mysql_socket_recv */
763
764static inline ssize_t
765inline_mysql_socket_recv
766(
767#ifdef HAVE_PSI_SOCKET_INTERFACE
768 const char *src_file, uint src_line,
769#endif
770 MYSQL_SOCKET mysql_socket, SOCKBUF_T *buf, size_t n, int flags)
771{
772 ssize_t result;
773
774#ifdef HAVE_PSI_SOCKET_INTERFACE
775 if (psi_likely(mysql_socket.m_psi != NULL))
776 {
777 /* Instrumentation start */
778 PSI_socket_locker *locker;
779 PSI_socket_locker_state state;
780 locker= PSI_SOCKET_CALL(start_socket_wait)
781 (&state, mysql_socket.m_psi, PSI_SOCKET_RECV, (size_t)0, src_file, src_line);
782
783 /* Instrumented code */
784 result= recv(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
785
786 /* Instrumentation end */
787 if (locker != NULL)
788 {
789 size_t bytes_read= (result > 0) ? (size_t) result : 0;
790 PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_read);
791 }
792
793 return result;
794 }
795#endif
796
797 /* Non instrumented code */
798 result= recv(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
799
800 return result;
801}
802
803/** mysql_socket_sendto */
804
805static inline ssize_t
806inline_mysql_socket_sendto
807(
808#ifdef HAVE_PSI_SOCKET_INTERFACE
809 const char *src_file, uint src_line,
810#endif
811 MYSQL_SOCKET mysql_socket, const SOCKBUF_T *buf, size_t n, int flags, const struct sockaddr *addr, socklen_t addr_len)
812{
813 ssize_t result;
814
815#ifdef HAVE_PSI_SOCKET_INTERFACE
816 if (psi_likely(mysql_socket.m_psi != NULL))
817 {
818 /* Instrumentation start */
819 PSI_socket_locker *locker;
820 PSI_socket_locker_state state;
821 locker= PSI_SOCKET_CALL(start_socket_wait)
822 (&state, mysql_socket.m_psi, PSI_SOCKET_SEND, n, src_file, src_line);
823
824 /* Instrumented code */
825 result= sendto(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len);
826
827 /* Instrumentation end */
828 if (locker != NULL)
829 {
830 size_t bytes_written = (result > 0) ? (size_t) result : 0;
831 PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_written);
832 }
833
834 return result;
835 }
836#endif
837
838 /* Non instrumented code */
839 result= sendto(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len);
840
841 return result;
842}
843
844/** mysql_socket_recvfrom */
845
846static inline ssize_t
847inline_mysql_socket_recvfrom
848(
849#ifdef HAVE_PSI_SOCKET_INTERFACE
850 const char *src_file, uint src_line,
851#endif
852 MYSQL_SOCKET mysql_socket, SOCKBUF_T *buf, size_t n, int flags,
853 struct sockaddr *addr, socklen_t *addr_len)
854{
855 ssize_t result;
856
857#ifdef HAVE_PSI_SOCKET_INTERFACE
858 if (psi_likely(mysql_socket.m_psi != NULL))
859 {
860 /* Instrumentation start */
861 PSI_socket_locker *locker;
862 PSI_socket_locker_state state;
863 locker= PSI_SOCKET_CALL(start_socket_wait)
864 (&state, mysql_socket.m_psi, PSI_SOCKET_RECV, (size_t)0, src_file, src_line);
865
866 /* Instrumented code */
867 result= recvfrom(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len);
868
869 /* Instrumentation end */
870 if (locker != NULL)
871 {
872 size_t bytes_read= (result > 0) ? (size_t) result : 0;
873 PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_read);
874 }
875
876 return result;
877 }
878#endif
879
880 /* Non instrumented code */
881 result= recvfrom(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len);
882
883 return result;
884}
885
886/** mysql_socket_getsockopt */
887
888static inline int
889inline_mysql_socket_getsockopt
890(
891#ifdef HAVE_PSI_SOCKET_INTERFACE
892 const char *src_file, uint src_line,
893#endif
894 MYSQL_SOCKET mysql_socket, int level, int optname, SOCKBUF_T *optval, socklen_t *optlen)
895{
896 int result;
897
898#ifdef HAVE_PSI_SOCKET_INTERFACE
899 if (psi_likely(mysql_socket.m_psi != NULL))
900 {
901 /* Instrumentation start */
902 PSI_socket_locker *locker;
903 PSI_socket_locker_state state;
904 locker= PSI_SOCKET_CALL(start_socket_wait)
905 (&state, mysql_socket.m_psi, PSI_SOCKET_OPT, (size_t)0, src_file, src_line);
906
907 /* Instrumented code */
908 result= getsockopt(mysql_socket.fd, level, optname, optval, optlen);
909
910 /* Instrumentation end */
911 if (locker != NULL)
912 PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
913
914 return result;
915 }
916#endif
917
918 /* Non instrumented code */
919 result= getsockopt(mysql_socket.fd, level, optname, optval, optlen);
920
921 return result;
922}
923
924/** mysql_socket_setsockopt */
925
926static inline int
927inline_mysql_socket_setsockopt
928(
929#ifdef HAVE_PSI_SOCKET_INTERFACE
930 const char *src_file, uint src_line,
931#endif
932 MYSQL_SOCKET mysql_socket, int level, int optname, const SOCKBUF_T *optval,
933 socklen_t optlen)
934{
935 int result;
936
937#ifdef HAVE_PSI_SOCKET_INTERFACE
938 if (psi_likely(mysql_socket.m_psi))
939 {
940 /* Instrumentation start */
941 PSI_socket_locker *locker;
942 PSI_socket_locker_state state;
943 locker= PSI_SOCKET_CALL(start_socket_wait)
944 (&state, mysql_socket.m_psi, PSI_SOCKET_OPT, (size_t)0, src_file, src_line);
945
946 /* Instrumented code */
947 result= setsockopt(mysql_socket.fd, level, optname, optval, optlen);
948
949 /* Instrumentation end */
950 if (locker != NULL)
951 PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
952
953 return result;
954 }
955#endif
956
957 /* Non instrumented code */
958 result= setsockopt(mysql_socket.fd, level, optname, optval, optlen);
959
960 return result;
961}
962
963/** mysql_socket_listen */
964
965static inline int
966inline_mysql_socket_listen
967(
968#ifdef HAVE_PSI_SOCKET_INTERFACE
969 const char *src_file, uint src_line,
970#endif
971 MYSQL_SOCKET mysql_socket, int backlog)
972{
973 int result;
974
975#ifdef HAVE_PSI_SOCKET_INTERFACE
976 if (psi_likely(mysql_socket.m_psi != NULL))
977 {
978 /* Instrumentation start */
979 PSI_socket_locker *locker;
980 PSI_socket_locker_state state;
981 locker= PSI_SOCKET_CALL(start_socket_wait)
982 (&state, mysql_socket.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line);
983
984 /* Instrumented code */
985 result= listen(mysql_socket.fd, backlog);
986
987 /* Instrumentation end */
988 if (locker != NULL)
989 PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
990
991 return result;
992 }
993#endif
994
995 /* Non instrumented code */
996 result= listen(mysql_socket.fd, backlog);
997
998 return result;
999}
1000
1001/** mysql_socket_accept */
1002
1003static inline MYSQL_SOCKET
1004inline_mysql_socket_accept
1005(
1006#ifdef HAVE_PSI_SOCKET_INTERFACE
1007 const char *src_file, uint src_line, PSI_socket_key key,
1008#endif
1009 MYSQL_SOCKET socket_listen, struct sockaddr *addr, socklen_t *addr_len)
1010{
1011#ifdef FD_CLOEXEC
1012 int flags __attribute__ ((unused));
1013#endif
1014
1015 MYSQL_SOCKET socket_accept= MYSQL_INVALID_SOCKET;
1016 socklen_t addr_length= (addr_len != NULL) ? *addr_len : 0;
1017
1018#ifdef HAVE_PSI_SOCKET_INTERFACE
1019 if (socket_listen.m_psi != NULL)
1020 {
1021 /* Instrumentation start */
1022 PSI_socket_locker *locker;
1023 PSI_socket_locker_state state;
1024 locker= PSI_SOCKET_CALL(start_socket_wait)
1025 (&state, socket_listen.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line);
1026
1027 /* Instrumented code */
1028#ifdef HAVE_ACCEPT4
1029 socket_accept.fd= accept4(socket_listen.fd, addr, &addr_length,
1030 SOCK_CLOEXEC);
1031#else
1032 socket_accept.fd= accept(socket_listen.fd, addr, &addr_length);
1033#ifdef FD_CLOEXEC
1034 flags= fcntl(socket_accept.fd, F_GETFD);
1035 if (flags != -1) {
1036 flags |= FD_CLOEXEC;
1037 fcntl(socket_accept.fd, F_SETFD, flags);
1038 }
1039#endif
1040#endif
1041
1042 /* Instrumentation end */
1043 if (locker != NULL)
1044 PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
1045 }
1046 else
1047#endif
1048 {
1049 /* Non instrumented code */
1050#ifdef HAVE_ACCEPT4
1051 socket_accept.fd= accept4(socket_listen.fd, addr, &addr_length,
1052 SOCK_CLOEXEC);
1053#else
1054 socket_accept.fd= accept(socket_listen.fd, addr, &addr_length);
1055#ifdef FD_CLOEXEC
1056 flags= fcntl(socket_accept.fd, F_GETFD);
1057 if (flags != -1) {
1058 flags |= FD_CLOEXEC;
1059 fcntl(socket_accept.fd, F_SETFD, flags);
1060 }
1061#endif
1062#endif
1063 }
1064
1065#ifdef HAVE_PSI_SOCKET_INTERFACE
1066 if (likely(socket_accept.fd != INVALID_SOCKET))
1067 {
1068 /* Initialize the instrument with the new socket descriptor and address */
1069 socket_accept.m_psi= PSI_SOCKET_CALL(init_socket)
1070 (key, (const my_socket*)&socket_accept.fd, addr, addr_length);
1071 }
1072#endif
1073
1074 return socket_accept;
1075}
1076
1077/** mysql_socket_close */
1078
1079static inline int
1080inline_mysql_socket_close
1081(
1082#ifdef HAVE_PSI_SOCKET_INTERFACE
1083 const char *src_file, uint src_line,
1084#endif
1085 MYSQL_SOCKET mysql_socket)
1086{
1087 int result;
1088
1089#ifdef HAVE_PSI_SOCKET_INTERFACE
1090 if (psi_likely(mysql_socket.m_psi != NULL))
1091 {
1092 /* Instrumentation start */
1093 PSI_socket_locker *locker;
1094 PSI_socket_locker_state state;
1095 locker= PSI_SOCKET_CALL(start_socket_wait)
1096 (&state, mysql_socket.m_psi, PSI_SOCKET_CLOSE, (size_t)0, src_file, src_line);
1097
1098 /* Instrumented code */
1099 result= closesocket(mysql_socket.fd);
1100
1101 /* Instrumentation end */
1102 if (locker != NULL)
1103 PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
1104 /* Remove the instrumentation for this socket. */
1105 if (mysql_socket.m_psi != NULL)
1106 PSI_SOCKET_CALL(destroy_socket)(mysql_socket.m_psi);
1107
1108 return result;
1109 }
1110#endif
1111
1112 /* Non instrumented code */
1113 result= closesocket(mysql_socket.fd);
1114
1115 return result;
1116}
1117
1118/** mysql_socket_shutdown */
1119
1120static inline int
1121inline_mysql_socket_shutdown
1122(
1123#ifdef HAVE_PSI_SOCKET_INTERFACE
1124 const char *src_file, uint src_line,
1125#endif
1126 MYSQL_SOCKET mysql_socket, int how)
1127{
1128 int result;
1129
1130#ifdef __WIN__
1131 static LPFN_DISCONNECTEX DisconnectEx = NULL;
1132 if (DisconnectEx == NULL)
1133 {
1134 DWORD dwBytesReturned;
1135 GUID guidDisconnectEx = WSAID_DISCONNECTEX;
1136 WSAIoctl(mysql_socket.fd, SIO_GET_EXTENSION_FUNCTION_POINTER,
1137 &guidDisconnectEx, sizeof(GUID),
1138 &DisconnectEx, sizeof(DisconnectEx),
1139 &dwBytesReturned, NULL, NULL);
1140 }
1141#endif
1142
1143/* Instrumentation start */
1144#ifdef HAVE_PSI_SOCKET_INTERFACE
1145 if (psi_likely(mysql_socket.m_psi != NULL))
1146 {
1147 PSI_socket_locker *locker;
1148 PSI_socket_locker_state state;
1149 locker= PSI_SOCKET_CALL(start_socket_wait)
1150 (&state, mysql_socket.m_psi, PSI_SOCKET_SHUTDOWN, (size_t)0, src_file, src_line);
1151
1152 /* Instrumented code */
1153#ifdef __WIN__
1154 if (DisconnectEx)
1155 result= (DisconnectEx(mysql_socket.fd, (LPOVERLAPPED) NULL,
1156 (DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1;
1157 else
1158#endif
1159 result= shutdown(mysql_socket.fd, how);
1160
1161 /* Instrumentation end */
1162 if (locker != NULL)
1163 PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
1164
1165 return result;
1166 }
1167#endif
1168
1169 /* Non instrumented code */
1170#ifdef __WIN__
1171 if (DisconnectEx)
1172 result= (DisconnectEx(mysql_socket.fd, (LPOVERLAPPED) NULL,
1173 (DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1;
1174 else
1175#endif
1176 result= shutdown(mysql_socket.fd, how);
1177
1178 return result;
1179}
1180
1181/** @} (end of group Socket_instrumentation) */
1182
1183#endif
1184
1185