Guest User

Untitled

a guest
Feb 19th, 2018
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.53 KB | None | 0 0
  1. /* <MYSQL_ROOT>/vio/viosocket.c */
  2.  
  3. /* Copyright (C) 2000 MySQL AB
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; version 2 of the License.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
  17.  
  18. /*
  19. Note that we can't have assertion on file descriptors; The reason for
  20. this is that during mysql shutdown, another thread can close a file
  21. we are working on. In this case we should just return read errors from
  22. the file descriptior.
  23. */
  24.  
  25. #include "vio_priv.h"
  26.  
  27. int vio_errno(Vio *vio __attribute__((unused)))
  28. {
  29. return socket_errno; /* On Win32 this mapped to WSAGetLastError() */
  30. }
  31.  
  32.  
  33. int vio_read(Vio * vio, gptr buf, int size)
  34. {
  35. int r;
  36. DBUG_ENTER("vio_read");
  37. DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size));
  38.  
  39. /* Ensure nobody uses vio_read_buff and vio_read simultaneously */
  40. DBUG_ASSERT(vio->read_end == vio->read_pos);
  41. #ifdef __WIN__
  42. r = recv(vio->sd, buf, size,0);
  43. #else
  44. errno=0; /* For linux */
  45. r = read(vio->sd, buf, size);
  46. #endif /* __WIN__ */
  47. #ifndef DBUG_OFF
  48. if (r < 0)
  49. {
  50. DBUG_PRINT("vio_error", ("Got error %d during read",errno));
  51. }
  52. #endif /* DBUG_OFF */
  53. DBUG_PRINT("exit", ("%d", r));
  54. DBUG_RETURN(r);
  55. }
  56.  
  57.  
  58. /*
  59. Buffered read: if average read size is small it may
  60. reduce number of syscalls.
  61. */
  62.  
  63. int vio_read_buff(Vio *vio, gptr buf, int size)
  64. {
  65. int rc;
  66. #define VIO_UNBUFFERED_READ_MIN_SIZE 2048
  67. DBUG_ENTER("vio_read_buff");
  68. DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size));
  69.  
  70. if (vio->read_pos < vio->read_end)
  71. {
  72. rc= min(vio->read_end - vio->read_pos, size);
  73. memcpy(buf, vio->read_pos, rc);
  74. vio->read_pos+= rc;
  75. /*
  76. Do not try to read from the socket now even if rc < size:
  77. vio_read can return -1 due to an error or non-blocking mode, and
  78. the safest way to handle it is to move to a separate branch.
  79. */
  80. }
  81. else if (size < VIO_UNBUFFERED_READ_MIN_SIZE)
  82. {
  83. rc= vio_read(vio, vio->read_buffer, VIO_READ_BUFFER_SIZE);
  84. if (rc > 0)
  85. {
  86. if (rc > size)
  87. {
  88. vio->read_pos= vio->read_buffer + size;
  89. vio->read_end= vio->read_buffer + rc;
  90. rc= size;
  91. }
  92. memcpy(buf, vio->read_buffer, rc);
  93. }
  94. }
  95. else
  96. rc= vio_read(vio, buf, size);
  97. DBUG_RETURN(rc);
  98. #undef VIO_UNBUFFERED_READ_MIN_SIZE
  99. }
  100.  
  101.  
  102. int vio_write(Vio * vio, const gptr buf, int size)
  103. {
  104. int r;
  105. DBUG_ENTER("vio_write");
  106. DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size));
  107. #ifdef __WIN__
  108. r = send(vio->sd, buf, size,0);
  109. #else
  110. r = write(vio->sd, buf, size);
  111. #endif /* __WIN__ */
  112. #ifndef DBUG_OFF
  113. if (r < 0)
  114. {
  115. DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno));
  116. }
  117. #endif /* DBUG_OFF */
  118. DBUG_PRINT("exit", ("%d", r));
  119. DBUG_RETURN(r);
  120. }
  121.  
  122. int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode,
  123. my_bool *old_mode)
  124. {
  125. int r=0;
  126. DBUG_ENTER("vio_blocking");
  127.  
  128. *old_mode= test(!(vio->fcntl_mode & O_NONBLOCK));
  129. DBUG_PRINT("enter", ("set_blocking_mode: %d old_mode: %d",
  130. (int) set_blocking_mode, (int) *old_mode));
  131.  
  132. #if !defined(__WIN__) && !defined(__EMX__)
  133. #if !defined(NO_FCNTL_NONBLOCK)
  134. if (vio->sd >= 0)
  135. {
  136. int old_fcntl=vio->fcntl_mode;
  137. if (set_blocking_mode)
  138. vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
  139. else
  140. vio->fcntl_mode |= O_NONBLOCK; /* set bit */
  141. if (old_fcntl != vio->fcntl_mode)
  142. {
  143. r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
  144. if (r == -1)
  145. {
  146. DBUG_PRINT("info", ("fcntl failed, errno %d", errno));
  147. vio->fcntl_mode= old_fcntl;
  148. }
  149. }
  150. }
  151. #else
  152. r= set_blocking_mode ? 0 : 1;
  153. #endif /* !defined(NO_FCNTL_NONBLOCK) */
  154. #else /* !defined(__WIN__) && !defined(__EMX__) */
  155. #ifndef __EMX__
  156. if (vio->type != VIO_TYPE_NAMEDPIPE && vio->type != VIO_TYPE_SHARED_MEMORY)
  157. #endif
  158. {
  159. ulong arg;
  160. int old_fcntl=vio->fcntl_mode;
  161. if (set_blocking_mode)
  162. {
  163. arg = 0;
  164. vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
  165. }
  166. else
  167. {
  168. arg = 1;
  169. vio->fcntl_mode |= O_NONBLOCK; /* set bit */
  170. }
  171. if (old_fcntl != vio->fcntl_mode)
  172. r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg);
  173. }
  174. #ifndef __EMX__
  175. else
  176. r= test(!(vio->fcntl_mode & O_NONBLOCK)) != set_blocking_mode;
  177. #endif /* __EMX__ */
  178. #endif /* !defined(__WIN__) && !defined(__EMX__) */
  179. DBUG_PRINT("exit", ("%d", r));
  180. DBUG_RETURN(r);
  181. }
  182.  
  183. my_bool
  184. vio_is_blocking(Vio * vio)
  185. {
  186. my_bool r;
  187. DBUG_ENTER("vio_is_blocking");
  188. r = !(vio->fcntl_mode & O_NONBLOCK);
  189. DBUG_PRINT("exit", ("%d", (int) r));
  190. DBUG_RETURN(r);
  191. }
  192.  
  193.  
  194. int vio_fastsend(Vio * vio __attribute__((unused)))
  195. {
  196. int r=0;
  197. DBUG_ENTER("vio_fastsend");
  198.  
  199. #if defined(IPTOS_THROUGHPUT) && !defined(__EMX__)
  200. {
  201. int tos = IPTOS_THROUGHPUT;
  202. r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos));
  203. }
  204. #endif /* IPTOS_THROUGHPUT && !__EMX__ */
  205. if (!r)
  206. {
  207. #ifdef __WIN__
  208. BOOL nodelay= 1;
  209. #else
  210. int nodelay = 1;
  211. #endif
  212.  
  213. r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
  214. IF_WIN(const char*, void*) &nodelay,
  215. sizeof(nodelay));
  216.  
  217. }
  218. if (r)
  219. {
  220. DBUG_PRINT("warning", ("Couldn't set socket option for fast send"));
  221. r= -1;
  222. }
  223. DBUG_PRINT("exit", ("%d", r));
  224. DBUG_RETURN(r);
  225. }
  226.  
  227. int vio_keepalive(Vio* vio, my_bool set_keep_alive)
  228. {
  229. int r=0;
  230. uint opt = 0;
  231. DBUG_ENTER("vio_keepalive");
  232. DBUG_PRINT("enter", ("sd: %d set_keep_alive: %d", vio->sd, (int)
  233. set_keep_alive));
  234. if (vio->type != VIO_TYPE_NAMEDPIPE)
  235. {
  236. if (set_keep_alive)
  237. opt = 1;
  238. r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
  239. sizeof(opt));
  240. }
  241. DBUG_RETURN(r);
  242. }
  243.  
  244.  
  245. my_bool
  246. vio_should_retry(Vio * vio __attribute__((unused)))
  247. {
  248. int en = socket_errno;
  249. return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
  250. en == SOCKET_EWOULDBLOCK);
  251. }
  252.  
  253.  
  254. my_bool
  255. vio_was_interrupted(Vio *vio __attribute__((unused)))
  256. {
  257. int en= socket_errno;
  258. return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
  259. en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
  260. }
  261.  
  262.  
  263. int vio_close(Vio * vio)
  264. {
  265. int r=0;
  266. DBUG_ENTER("vio_close");
  267. #ifdef __WIN__
  268. if (vio->type == VIO_TYPE_NAMEDPIPE)
  269. {
  270. #if defined(__NT__) && defined(MYSQL_SERVER)
  271. CancelIo(vio->hPipe);
  272. DisconnectNamedPipe(vio->hPipe);
  273. #endif
  274. r=CloseHandle(vio->hPipe);
  275. }
  276. else
  277. #endif /* __WIN__ */
  278. if (vio->type != VIO_CLOSED)
  279. {
  280. DBUG_ASSERT(vio->sd >= 0);
  281. if (shutdown(vio->sd, SHUT_RDWR))
  282. r= -1;
  283. if (closesocket(vio->sd))
  284. r= -1;
  285. }
  286. if (r)
  287. {
  288. DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno));
  289. /* FIXME: error handling (not critical for MySQL) */
  290. }
  291. vio->type= VIO_CLOSED;
  292. vio->sd= -1;
  293. DBUG_RETURN(r);
  294. }
  295.  
  296.  
  297. const char *vio_description(Vio * vio)
  298. {
  299. return vio->desc;
  300. }
  301.  
  302. enum enum_vio_type vio_type(Vio* vio)
  303. {
  304. return vio->type;
  305. }
  306.  
  307. my_socket vio_fd(Vio* vio)
  308. {
  309. return vio->sd;
  310. }
  311.  
  312.  
  313. my_bool vio_peer_addr(Vio * vio, char *buf, uint16 *port)
  314. {
  315. DBUG_ENTER("vio_peer_addr");
  316. DBUG_PRINT("enter", ("sd: %d", vio->sd));
  317. if (vio->localhost)
  318. {
  319. strmov(buf,"127.0.0.1");
  320. *port= 0;
  321. }
  322. else
  323. {
  324. size_socket addrLen = sizeof(vio->remote);
  325. if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
  326. &addrLen) != 0)
  327. {
  328. DBUG_PRINT("exit", ("getpeername gave error: %d", socket_errno));
  329. DBUG_RETURN(1);
  330. }
  331. my_inet_ntoa(vio->remote.sin_addr,buf);
  332. *port= ntohs(vio->remote.sin_port);
  333. }
  334. DBUG_PRINT("exit", ("addr: %s", buf));
  335. DBUG_RETURN(0);
  336. }
  337.  
  338.  
  339. /*
  340. Get in_addr for a TCP/IP connection
  341.  
  342. SYNOPSIS
  343. vio_in_addr()
  344. vio vio handle
  345. in put in_addr here
  346.  
  347. NOTES
  348. one must call vio_peer_addr() before calling this one
  349. */
  350.  
  351. void vio_in_addr(Vio *vio, struct in_addr *in)
  352. {
  353. DBUG_ENTER("vio_in_addr");
  354. if (vio->localhost)
  355. bzero((char*) in, sizeof(*in));
  356. else
  357. *in=vio->remote.sin_addr;
  358. DBUG_VOID_RETURN;
  359. }
  360.  
  361.  
  362. /* Return 0 if there is data to be read */
  363.  
  364. my_bool vio_poll_read(Vio *vio,uint timeout)
  365. {
  366. #ifndef HAVE_POLL
  367. return 0;
  368. #else
  369. struct pollfd fds;
  370. int res;
  371. DBUG_ENTER("vio_poll");
  372. fds.fd=vio->sd;
  373. fds.events=POLLIN;
  374. fds.revents=0;
  375. if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
  376. {
  377. DBUG_RETURN(res < 0 ? 0 : 1); /* Don't return 1 on errors */
  378. }
  379. DBUG_RETURN(fds.revents & POLLIN ? 0 : 1);
  380. #endif
  381. }
  382.  
  383.  
  384. void vio_timeout(Vio *vio, uint which, uint timeout)
  385. {
  386. #if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)
  387. int r;
  388. DBUG_ENTER("vio_timeout");
  389.  
  390. {
  391. #ifdef __WIN__
  392. /* Windows expects time in milliseconds as int */
  393. int wait_timeout= (int) timeout * 1000;
  394. #else
  395. /* POSIX specifies time as struct timeval. */
  396. struct timeval wait_timeout;
  397. wait_timeout.tv_sec= timeout;
  398. wait_timeout.tv_usec= 0;
  399. #endif
  400.  
  401. r= setsockopt(vio->sd, SOL_SOCKET, which ? SO_SNDTIMEO : SO_RCVTIMEO,
  402. IF_WIN(const char*, const void*)&wait_timeout,
  403. sizeof(wait_timeout));
  404.  
  405. }
  406.  
  407. #ifndef DBUG_OFF
  408. if (r != 0)
  409. DBUG_PRINT("error", ("setsockopt failed: %d, errno: %d", r, socket_errno));
  410. #endif
  411.  
  412. DBUG_VOID_RETURN;
  413. #else
  414. /*
  415. Platforms not suporting setting of socket timeout should either use
  416. thr_alarm or just run without read/write timeout(s)
  417. */
  418. #endif
  419. }
  420.  
  421.  
  422. #ifdef __WIN__
  423. int vio_read_pipe(Vio * vio, gptr buf, int size)
  424. {
  425. DWORD length;
  426. DBUG_ENTER("vio_read_pipe");
  427. DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size));
  428.  
  429. if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
  430. DBUG_RETURN(-1);
  431.  
  432. DBUG_PRINT("exit", ("%d", length));
  433. DBUG_RETURN(length);
  434. }
  435.  
  436.  
  437. int vio_write_pipe(Vio * vio, const gptr buf, int size)
  438. {
  439. DWORD length;
  440. DBUG_ENTER("vio_write_pipe");
  441. DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size));
  442.  
  443. if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
  444. DBUG_RETURN(-1);
  445.  
  446. DBUG_PRINT("exit", ("%d", length));
  447. DBUG_RETURN(length);
  448. }
  449.  
  450. int vio_close_pipe(Vio * vio)
  451. {
  452. int r;
  453. DBUG_ENTER("vio_close_pipe");
  454. #if defined(__NT__) && defined(MYSQL_SERVER)
  455. CancelIo(vio->hPipe);
  456. DisconnectNamedPipe(vio->hPipe);
  457. #endif
  458. r=CloseHandle(vio->hPipe);
  459. if (r)
  460. {
  461. DBUG_PRINT("vio_error", ("close() failed, error: %d",GetLastError()));
  462. /* FIXME: error handling (not critical for MySQL) */
  463. }
  464. vio->type= VIO_CLOSED;
  465. vio->sd= -1;
  466. DBUG_RETURN(r);
  467. }
  468.  
  469.  
  470. void vio_ignore_timeout(Vio *vio __attribute__((unused)),
  471. uint which __attribute__((unused)),
  472. uint timeout __attribute__((unused)))
  473. {
  474. }
  475.  
  476.  
  477. #ifdef HAVE_SMEM
  478.  
  479. int vio_read_shared_memory(Vio * vio, gptr buf, int size)
  480. {
  481. int length;
  482. int remain_local;
  483. char *current_postion;
  484.  
  485. DBUG_ENTER("vio_read_shared_memory");
  486. DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size));
  487.  
  488. remain_local = size;
  489. current_postion=buf;
  490. do
  491. {
  492. if (vio->shared_memory_remain == 0)
  493. {
  494. HANDLE events[2];
  495. events[0]= vio->event_server_wrote;
  496. events[1]= vio->event_conn_closed;
  497. /*
  498. WaitForMultipleObjects can return next values:
  499. WAIT_OBJECT_0+0 - event from vio->event_server_wrote
  500. WAIT_OBJECT_0+1 - event from vio->event_conn_closed. We can't read anything
  501. WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail. We can't read anything
  502. */
  503. if (WaitForMultipleObjects(2, (HANDLE*)&events,FALSE,
  504. vio->net->read_timeout*1000) != WAIT_OBJECT_0)
  505. {
  506. DBUG_RETURN(-1);
  507. };
  508.  
  509. vio->shared_memory_pos = vio->handle_map;
  510. vio->shared_memory_remain = uint4korr((ulong*)vio->shared_memory_pos);
  511. vio->shared_memory_pos+=4;
  512. }
  513.  
  514. length = size;
  515.  
  516. if (vio->shared_memory_remain < length)
  517. length = vio->shared_memory_remain;
  518. if (length > remain_local)
  519. length = remain_local;
  520.  
  521. memcpy(current_postion,vio->shared_memory_pos,length);
  522.  
  523. vio->shared_memory_remain-=length;
  524. vio->shared_memory_pos+=length;
  525. current_postion+=length;
  526. remain_local-=length;
  527.  
  528. if (!vio->shared_memory_remain)
  529. if (!SetEvent(vio->event_client_read)) DBUG_RETURN(-1);
  530. } while (remain_local);
  531. length = size;
  532.  
  533. DBUG_PRINT("exit", ("%d", length));
  534. DBUG_RETURN(length);
  535. }
  536.  
  537.  
  538. int vio_write_shared_memory(Vio * vio, const gptr buf, int size)
  539. {
  540. int length;
  541. uint remain;
  542. HANDLE pos;
  543. int sz;
  544. char *current_postion;
  545.  
  546. DBUG_ENTER("vio_write_shared_memory");
  547. DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size));
  548.  
  549. remain = size;
  550. current_postion = buf;
  551. while (remain != 0)
  552. {
  553. if (WaitForSingleObject(vio->event_server_read, vio->net->write_timeout*1000)
  554. != WAIT_OBJECT_0)
  555. {
  556. DBUG_RETURN(-1);
  557. };
  558.  
  559. sz = remain > shared_memory_buffer_length ? shared_memory_buffer_length: remain;
  560.  
  561. int4store(vio->handle_map,sz);
  562. pos = vio->handle_map + 4;
  563. memcpy(pos,current_postion,sz);
  564. remain-=sz;
  565. current_postion+=sz;
  566. if (!SetEvent(vio->event_client_wrote)) DBUG_RETURN(-1);
  567. }
  568. length = size;
  569.  
  570. DBUG_PRINT("exit", ("%d", length));
  571. DBUG_RETURN(length);
  572. }
  573.  
  574.  
  575. /**
  576. Close shared memory and DBUG_PRINT any errors that happen on closing.
  577. @return Zero if all closing functions succeed, and nonzero otherwise.
  578. */
  579. int vio_close_shared_memory(Vio * vio)
  580. {
  581. int error_count= 0;
  582. DBUG_ENTER("vio_close_shared_memory");
  583. if (vio->type != VIO_CLOSED)
  584. {
  585. /*
  586. Set event_conn_closed for notification of both client and server that
  587. connection is closed
  588. */
  589. SetEvent(vio->event_conn_closed);
  590. /*
  591. Close all handlers. UnmapViewOfFile and CloseHandle return non-zero
  592. result if they are success.
  593. */
  594. if (UnmapViewOfFile(vio->handle_map) == 0)
  595. {
  596. error_count++;
  597. DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed"));
  598. }
  599. if (CloseHandle(vio->event_server_wrote) == 0)
  600. {
  601. error_count++;
  602. DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed"));
  603. }
  604. if (CloseHandle(vio->event_server_read) == 0)
  605. {
  606. error_count++;
  607. DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed"));
  608. }
  609. if (CloseHandle(vio->event_client_wrote) == 0)
  610. {
  611. error_count++;
  612. DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed"));
  613. }
  614. if (CloseHandle(vio->event_client_read) == 0)
  615. {
  616. error_count++;
  617. DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed"));
  618. }
  619. if (CloseHandle(vio->handle_file_map) == 0)
  620. {
  621. error_count++;
  622. DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed"));
  623. }
  624. if (CloseHandle(vio->event_conn_closed) == 0)
  625. {
  626. error_count++;
  627. DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed"));
  628. }
  629. }
  630. vio->type= VIO_CLOSED;
  631. vio->sd= -1;
  632. DBUG_RETURN(error_count);
  633. }
  634. #endif /* HAVE_SMEM */
  635. #endif /* __WIN__ */
Add Comment
Please, Sign In to add comment