viosocket.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:13k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /*
  14.   Note that we can't have assertion on file descriptors;  The reason for
  15.   this is that during mysql shutdown, another thread can close a file
  16.   we are working on.  In this case we should just return read errors from
  17.   the file descriptior.
  18. */
  19. #include "vio_priv.h"
  20. int vio_errno(Vio *vio __attribute__((unused)))
  21. {
  22.   return socket_errno; /* On Win32 this mapped to WSAGetLastError() */
  23. }
  24. int vio_read(Vio * vio, gptr buf, int size)
  25. {
  26.   int r;
  27.   DBUG_ENTER("vio_read");
  28.   DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
  29. #ifdef __WIN__
  30.   r = recv(vio->sd, buf, size,0);
  31. #else
  32.   errno=0; /* For linux */
  33.   r = read(vio->sd, buf, size);
  34. #endif /* __WIN__ */
  35. #ifndef DBUG_OFF
  36.   if (r < 0)
  37.   {
  38.     DBUG_PRINT("vio_error", ("Got error %d during read",errno));
  39.   }
  40. #endif /* DBUG_OFF */
  41.   DBUG_PRINT("exit", ("%d", r));
  42.   DBUG_RETURN(r);
  43. }
  44. int vio_write(Vio * vio, const gptr buf, int size)
  45. {
  46.   int r;
  47.   DBUG_ENTER("vio_write");
  48.   DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
  49. #ifdef __WIN__
  50.   r = send(vio->sd, buf, size,0);
  51. #else
  52.   r = write(vio->sd, buf, size);
  53. #endif /* __WIN__ */
  54. #ifndef DBUG_OFF
  55.   if (r < 0)
  56.   {
  57.     DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno));
  58.   }
  59. #endif /* DBUG_OFF */
  60.   DBUG_PRINT("exit", ("%d", r));
  61.   DBUG_RETURN(r);
  62. }
  63. int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode,
  64.  my_bool *old_mode)
  65. {
  66.   int r=0;
  67.   DBUG_ENTER("vio_blocking");
  68.   *old_mode= test(!(vio->fcntl_mode & O_NONBLOCK));
  69.   DBUG_PRINT("enter", ("set_blocking_mode: %d  old_mode: %d",
  70.        (int) set_blocking_mode, (int) *old_mode));
  71. #if !defined(__WIN__) && !defined(__EMX__)
  72. #if !defined(NO_FCNTL_NONBLOCK)
  73.   if (vio->sd >= 0)
  74.   {
  75.     int old_fcntl=vio->fcntl_mode;
  76.     if (set_blocking_mode)
  77.       vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
  78.     else
  79.       vio->fcntl_mode |= O_NONBLOCK; /* set bit */
  80.     if (old_fcntl != vio->fcntl_mode)
  81.     {
  82.       r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
  83.       if (r == -1)
  84.       {
  85.         DBUG_PRINT("info", ("fcntl failed, errno %d", errno));
  86.         vio->fcntl_mode= old_fcntl;
  87.       }
  88.     }
  89.   }
  90. #else
  91.   r= set_blocking_mode ? 0 : 1;
  92. #endif /* !defined(NO_FCNTL_NONBLOCK) */
  93. #else /* !defined(__WIN__) && !defined(__EMX__) */
  94. #ifndef __EMX__
  95.   if (vio->type != VIO_TYPE_NAMEDPIPE && vio->type != VIO_TYPE_SHARED_MEMORY)
  96. #endif
  97.   { 
  98.     ulong arg;
  99.     int old_fcntl=vio->fcntl_mode;
  100.     if (set_blocking_mode)
  101.     {
  102.       arg = 0;
  103.       vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
  104.     }
  105.     else
  106.     {
  107.       arg = 1;
  108.       vio->fcntl_mode |= O_NONBLOCK; /* set bit */
  109.     }
  110.     if (old_fcntl != vio->fcntl_mode)
  111.       r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg);
  112.   }
  113. #ifndef __EMX__
  114.   else
  115.     r=  test(!(vio->fcntl_mode & O_NONBLOCK)) != set_blocking_mode;
  116. #endif /* __EMX__ */
  117. #endif /* !defined(__WIN__) && !defined(__EMX__) */
  118.   DBUG_PRINT("exit", ("%d", r));
  119.   DBUG_RETURN(r);
  120. }
  121. my_bool
  122. vio_is_blocking(Vio * vio)
  123. {
  124.   my_bool r;
  125.   DBUG_ENTER("vio_is_blocking");
  126.   r = !(vio->fcntl_mode & O_NONBLOCK);
  127.   DBUG_PRINT("exit", ("%d", (int) r));
  128.   DBUG_RETURN(r);
  129. }
  130. int vio_fastsend(Vio * vio __attribute__((unused)))
  131. {
  132.   int r=0;
  133.   DBUG_ENTER("vio_fastsend");
  134. #if defined(IPTOS_THROUGHPUT) && !defined(__EMX__)
  135.   {
  136.     int tos = IPTOS_THROUGHPUT;
  137.     r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos));
  138.   }
  139. #endif                                    /* IPTOS_THROUGHPUT && !__EMX__ */
  140.   if (!r)
  141.   {
  142. #ifdef __WIN__
  143.     BOOL nodelay= 1;
  144.     r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (const char*) &nodelay,
  145.                   sizeof(nodelay));
  146. #else
  147.     int nodelay = 1;
  148.     r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay,
  149.                   sizeof(nodelay));
  150. #endif                                          /* __WIN__ */
  151.   }
  152.   if (r)
  153.   {
  154.     DBUG_PRINT("warning", ("Couldn't set socket option for fast send"));
  155.     r= -1;
  156.   }
  157.   DBUG_PRINT("exit", ("%d", r));
  158.   DBUG_RETURN(r);
  159. }
  160. int vio_keepalive(Vio* vio, my_bool set_keep_alive)
  161. {
  162.   int r=0;
  163.   uint opt = 0;
  164.   DBUG_ENTER("vio_keepalive");
  165.   DBUG_PRINT("enter", ("sd=%d, set_keep_alive=%d", vio->sd, (int)
  166.        set_keep_alive));
  167.   if (vio->type != VIO_TYPE_NAMEDPIPE)
  168.   {
  169.     if (set_keep_alive)
  170.       opt = 1;
  171.     r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
  172.    sizeof(opt));
  173.   }
  174.   DBUG_RETURN(r);
  175. }
  176. my_bool
  177. vio_should_retry(Vio * vio __attribute__((unused)))
  178. {
  179.   int en = socket_errno;
  180.   return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
  181.   en == SOCKET_EWOULDBLOCK);
  182. }
  183. my_bool
  184. vio_was_interrupted(Vio *vio __attribute__((unused)))
  185. {
  186.   int en= socket_errno;
  187.   return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
  188.   en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
  189. }
  190. int vio_close(Vio * vio)
  191. {
  192.   int r=0;
  193.   DBUG_ENTER("vio_close");
  194. #ifdef __WIN__
  195.   if (vio->type == VIO_TYPE_NAMEDPIPE)
  196.   {
  197. #if defined(__NT__) && defined(MYSQL_SERVER)
  198.     CancelIo(vio->hPipe);
  199.     DisconnectNamedPipe(vio->hPipe);
  200. #endif
  201.     r=CloseHandle(vio->hPipe);
  202.   }
  203.   else
  204. #endif /* __WIN__ */
  205.  if (vio->type != VIO_CLOSED)
  206.   {
  207.     DBUG_ASSERT(vio->sd >= 0);
  208.     if (shutdown(vio->sd,2))
  209.       r= -1;
  210.     if (closesocket(vio->sd))
  211.       r= -1;
  212.   }
  213.   if (r)
  214.   {
  215.     DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno));
  216.     /* FIXME: error handling (not critical for MySQL) */
  217.   }
  218.   vio->type= VIO_CLOSED;
  219.   vio->sd=   -1;
  220.   DBUG_RETURN(r);
  221. }
  222. const char *vio_description(Vio * vio)
  223. {
  224.   return vio->desc;
  225. }
  226. enum enum_vio_type vio_type(Vio* vio)
  227. {
  228.   return vio->type;
  229. }
  230. my_socket vio_fd(Vio* vio)
  231. {
  232.   return vio->sd;
  233. }
  234. my_bool vio_peer_addr(Vio * vio, char *buf, uint16 *port)
  235. {
  236.   DBUG_ENTER("vio_peer_addr");
  237.   DBUG_PRINT("enter", ("sd: %d", vio->sd));
  238.   if (vio->localhost)
  239.   {
  240.     strmov(buf,"127.0.0.1");
  241.     *port= 0;
  242.   }
  243.   else
  244.   {
  245.     size_socket addrLen = sizeof(vio->remote);
  246.     if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
  247.     &addrLen) != 0)
  248.     {
  249.       DBUG_PRINT("exit", ("getpeername gave error: %d", socket_errno));
  250.       DBUG_RETURN(1);
  251.     }
  252.     my_inet_ntoa(vio->remote.sin_addr,buf);
  253.     *port= ntohs(vio->remote.sin_port);
  254.   }
  255.   DBUG_PRINT("exit", ("addr: %s", buf));
  256.   DBUG_RETURN(0);
  257. }
  258. /*
  259.   Get in_addr for a TCP/IP connection
  260.   SYNOPSIS
  261.     vio_in_addr()
  262.     vio vio handle
  263.     in put in_addr here
  264.   NOTES
  265.     one must call vio_peer_addr() before calling this one
  266. */
  267. void vio_in_addr(Vio *vio, struct in_addr *in)
  268. {
  269.   DBUG_ENTER("vio_in_addr");
  270.   if (vio->localhost)
  271.     bzero((char*) in, sizeof(*in));
  272.   else
  273.     *in=vio->remote.sin_addr;
  274.   DBUG_VOID_RETURN;
  275. }
  276. /* Return 0 if there is data to be read */
  277. my_bool vio_poll_read(Vio *vio,uint timeout)
  278. {
  279. #ifndef HAVE_POLL
  280.   return 0;
  281. #else
  282.   struct pollfd fds;
  283.   int res;
  284.   DBUG_ENTER("vio_poll");
  285.   fds.fd=vio->sd;
  286.   fds.events=POLLIN;
  287.   fds.revents=0;
  288.   if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
  289.   {
  290.     DBUG_RETURN(res < 0 ? 0 : 1); /* Don't return 1 on errors */
  291.   }
  292.   DBUG_RETURN(fds.revents & POLLIN ? 0 : 1);
  293. #endif
  294. }
  295. void vio_timeout(Vio *vio __attribute__((unused)),
  296.  uint which __attribute__((unused)),
  297.                  uint timeout __attribute__((unused)))
  298. {
  299. #ifdef __WIN__
  300.   ulong wait_timeout= (ulong) timeout * 1000;
  301.   (void) setsockopt(vio->sd, SOL_SOCKET, 
  302. which ? SO_SNDTIMEO : SO_RCVTIMEO, (char*) &wait_timeout,
  303.         sizeof(wait_timeout));
  304. #endif /* __WIN__ */
  305. }
  306. #ifdef __WIN__
  307. int vio_read_pipe(Vio * vio, gptr buf, int size)
  308. {
  309.   DWORD length;
  310.   DBUG_ENTER("vio_read_pipe");
  311.   DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
  312.   if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
  313.     DBUG_RETURN(-1);
  314.   DBUG_PRINT("exit", ("%d", length));
  315.   DBUG_RETURN(length);
  316. }
  317. int vio_write_pipe(Vio * vio, const gptr buf, int size)
  318. {
  319.   DWORD length;
  320.   DBUG_ENTER("vio_write_pipe");
  321.   DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
  322.   if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
  323.     DBUG_RETURN(-1);
  324.   DBUG_PRINT("exit", ("%d", length));
  325.   DBUG_RETURN(length);
  326. }
  327. int vio_close_pipe(Vio * vio)
  328. {
  329.   int r;
  330.   DBUG_ENTER("vio_close_pipe");
  331. #if defined(__NT__) && defined(MYSQL_SERVER)
  332.   CancelIo(vio->hPipe);
  333.   DisconnectNamedPipe(vio->hPipe);
  334. #endif
  335.   r=CloseHandle(vio->hPipe);
  336.   if (r)
  337.   {
  338.     DBUG_PRINT("vio_error", ("close() failed, error: %d",GetLastError()));
  339.     /* FIXME: error handling (not critical for MySQL) */
  340.   }
  341.   vio->type= VIO_CLOSED;
  342.   vio->sd=   -1;
  343.   DBUG_RETURN(r);
  344. }
  345. void vio_ignore_timeout(Vio *vio __attribute__((unused)),
  346. uint which __attribute__((unused)),
  347. uint timeout __attribute__((unused)))
  348. {
  349. }
  350. #ifdef HAVE_SMEM
  351. int vio_read_shared_memory(Vio * vio, gptr buf, int size)
  352. {
  353.   int length;
  354.   int remain_local;
  355.   char *current_postion;
  356.   DBUG_ENTER("vio_read_shared_memory");
  357.   DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
  358.   remain_local = size;
  359.   current_postion=buf;
  360.   do
  361.   {
  362.     if (vio->shared_memory_remain == 0)
  363.     {
  364.       HANDLE events[2];
  365.       events[0]= vio->event_server_wrote;
  366.       events[1]= vio->event_conn_closed;
  367.       /*
  368.         WaitForMultipleObjects can return next values:
  369.          WAIT_OBJECT_0+0 - event from vio->event_server_wrote
  370.          WAIT_OBJECT_0+1 - event from vio->event_conn_closed. We can't read anything
  371.          WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail.  We can't read anything
  372.       */
  373.       if (WaitForMultipleObjects(2, (HANDLE*)&events,FALSE,
  374.                                  vio->net->read_timeout*1000) != WAIT_OBJECT_0)
  375.       {
  376.         DBUG_RETURN(-1);
  377.       };
  378.       vio->shared_memory_pos = vio->handle_map;
  379.       vio->shared_memory_remain = uint4korr((ulong*)vio->shared_memory_pos);
  380.       vio->shared_memory_pos+=4;
  381.     }
  382.     length = size;
  383.     if (vio->shared_memory_remain < length)
  384.        length = vio->shared_memory_remain;
  385.     if (length > remain_local)
  386.        length = remain_local;
  387.     memcpy(current_postion,vio->shared_memory_pos,length);
  388.     vio->shared_memory_remain-=length;
  389.     vio->shared_memory_pos+=length;
  390.     current_postion+=length;
  391.     remain_local-=length;
  392.     if (!vio->shared_memory_remain)
  393.       if (!SetEvent(vio->event_client_read)) DBUG_RETURN(-1);
  394.   } while (remain_local);
  395.   length = size;
  396.   DBUG_PRINT("exit", ("%d", length));
  397.   DBUG_RETURN(length);
  398. }
  399. int vio_write_shared_memory(Vio * vio, const gptr buf, int size)
  400. {
  401.   int length;
  402.   uint remain;
  403.   HANDLE pos;
  404.   int sz;
  405.   char *current_postion;
  406.   DBUG_ENTER("vio_write_shared_memory");
  407.   DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
  408.   remain = size;
  409.   current_postion = buf;
  410.   while (remain != 0)
  411.   {
  412.     if (WaitForSingleObject(vio->event_server_read, vio->net->write_timeout*1000) 
  413.                             != WAIT_OBJECT_0)
  414.     {
  415.       DBUG_RETURN(-1);
  416.     };
  417.     sz = remain > shared_memory_buffer_length ? shared_memory_buffer_length: remain;
  418.     int4store(vio->handle_map,sz);
  419.     pos = vio->handle_map + 4;
  420.     memcpy(pos,current_postion,sz);
  421.     remain-=sz;
  422.     current_postion+=sz;
  423.     if (!SetEvent(vio->event_client_wrote)) DBUG_RETURN(-1);
  424.   }
  425.   length = size;
  426.   DBUG_PRINT("exit", ("%d", length));
  427.   DBUG_RETURN(length);
  428. }
  429. int vio_close_shared_memory(Vio * vio)
  430. {
  431.   int r;
  432.   DBUG_ENTER("vio_close_shared_memory");
  433.   if (vio->type != VIO_CLOSED)
  434.   {
  435.     /*
  436.       Set event_conn_closed for notification of both client and server that
  437.       connection is closed
  438.     */
  439.     SetEvent(vio->event_conn_closed);
  440.     /*
  441.       Close all handlers. UnmapViewOfFile and CloseHandle return non-zero
  442.       result if they are success.
  443.     */
  444.     r= UnmapViewOfFile(vio->handle_map) || CloseHandle(vio->event_server_wrote) ||
  445.        CloseHandle(vio->event_server_read) || CloseHandle(vio->event_client_wrote) ||
  446.        CloseHandle(vio->event_client_read) || CloseHandle(vio->handle_file_map);
  447.     if (!r)
  448.     {
  449.       DBUG_PRINT("vio_error", ("close() failed, error: %d",r));
  450.       /* FIXME: error handling (not critical for MySQL) */
  451.     }
  452.   }
  453.   vio->type= VIO_CLOSED;
  454.   vio->sd=   -1;
  455.   DBUG_RETURN(!r);
  456. }
  457. #endif /* HAVE_SMEM */
  458. #endif /* __WIN__ */