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