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