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