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