net.c
上传用户:jmzj888
上传日期:2007-01-02
资源大小:220k
文件大小:13k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
  2.    This file is public domain and comes with NO WARRANTY of any kind */
  3. /* Write and read of logical packets to/from socket
  4. ** Writes are cached into net_buffer_length big packets.
  5. ** Read packets are reallocated dynamicly when reading big packets.
  6. ** Each logical packet has the following pre-info:
  7. ** 3 byte length & 1 byte package-number.
  8. */
  9. #ifdef _WIN32
  10. #include <winsock.h>
  11. #endif
  12. #include <global.h>
  13. #include <my_sys.h>
  14. #include <m_string.h>
  15. #include "mysql.h"
  16. #include <signal.h>
  17. #include <errno.h>
  18. #include <sys/types.h>
  19. #if !defined(__WIN32__) && !defined(MSDOS)
  20. #include <sys/socket.h>
  21. #endif
  22. #if !defined(MSDOS) && !defined(__WIN32__) && !defined(HAVE_BROKEN_NETINET_INCLUDES)
  23. #include <netinet/in_systm.h>
  24. #include <netinet/in.h>
  25. #include <netinet/ip.h>
  26. #include <netinet/tcp.h>
  27. #endif
  28. #ifdef MYSQL_SERVER
  29. #include "my_pthread.h"
  30. #include "thr_alarm.h"
  31. #endif
  32. #if defined(MSDOS) || defined(__WIN32__)
  33. #define raw_net_read(A,B,C) recv((A),(B),(C),0)
  34. #define raw_net_write(A,B,C) send((A),(B),(C),0)
  35. #ifdef __WIN32__
  36. #undef errno
  37. #undef EINTR
  38. #undef EAGAIN
  39. #define errno WSAGetLastError()
  40. #define EINTR  WSAEINTR
  41. #define EAGAIN WSAEINPROGRESS
  42. #endif
  43. #else /* unix */
  44. #define raw_net_read(A,B,C) read((A),(B),(C))
  45. #define raw_net_write(A,B,C) write((A),(B),(C))
  46. #endif
  47. #ifndef EWOULDBLOCK
  48. #define EWOULDBLOCK EAGAIN
  49. #endif
  50. /*
  51. ** Give error if a too big packet is found
  52. ** The server can change this with the -O switch, but because the client
  53. ** can't normally do this the client should have a bigger max-buffer.
  54. */
  55. #ifdef MYSQL_SERVER
  56. ulong max_allowed_packet=65536;
  57. #else
  58. ulong max_allowed_packet=1024*1024L;
  59. #endif
  60. ulong net_buffer_length=8192; /* Default length. Enlarged if necessary */
  61. static int net_write_buff(NET *net,const byte *packet,uint len);
  62. /* Init with packet info */
  63. int my_net_init(NET *net,Socket fd)
  64. {
  65.   if (!(net->buff=(uchar*) my_malloc(net_buffer_length,MYF(MY_WME))))
  66.     return 1;
  67.   if (net_buffer_length > max_allowed_packet)
  68.     max_allowed_packet=net_buffer_length;
  69.   net->buff_end=net->buff+(net->max_packet=net_buffer_length);
  70.   net->fd=fd;
  71.   net->error=net->return_errno=0;
  72.   net->timeout=30; /* Timeout for read */
  73.   net->pkt_nr=0;
  74.   net->write_pos=net->buff;
  75.   net->last_error[0]=0;
  76. #if defined(MYSQL_SERVER) && !defined(__WIN32__)
  77.   if (fd)
  78.   {
  79.     extern uint test_flags; /* QQ */
  80.     net->fcntl=(fcntl(net->fd, F_GETFL) |
  81. (!(test_flags & 8) ? O_NONBLOCK : 0));
  82.     (void) fcntl(net->fd, F_SETFL, net->fcntl);
  83.   }
  84. #endif
  85. #ifdef IPTOS_THROUGHPUT /* For FreeBSD */
  86.   {
  87.     int tos = IPTOS_THROUGHPUT;
  88.     if (!setsockopt(fd, IPPROTO_IP, IP_TOS, (void*) &tos, sizeof(tos)))
  89.     {
  90.       int nodelay = 1;
  91.       if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay,
  92.      sizeof(nodelay)))
  93.       {
  94. DBUG_PRINT("warning",("Couldn't set socket option for fast send"));
  95.       }
  96.     }
  97.   }
  98. #endif
  99.   return 0;
  100. }
  101. void net_end(NET *net)
  102. {
  103.   if (net->buff)
  104.   {
  105.     my_free((gptr) net->buff,MYF(0));
  106.     net->buff=0;
  107.   }
  108. }
  109. /* Remove unwanted characters from connection */
  110. #ifndef MYSQL_SERVER
  111. void net_clear(NET *net)
  112. {
  113. #if !defined(MSDOS) && !defined(__WIN32__)
  114.   int old_fcntl=fcntl(net->fd, F_GETFL);
  115.   int count;
  116.   if (!(old_fcntl & O_NONBLOCK))
  117.     (void) fcntl(net->fd, F_SETFL, old_fcntl | O_NONBLOCK);
  118.   while ((count=(int) raw_net_read(net->fd,net->buff,net->max_packet)) > 0)
  119.   {
  120.     DBUG_PRINT("info",("skipped %d bytes from file: %d",count,net->fd));
  121.   }
  122.   if (!(old_fcntl & O_NONBLOCK))
  123.     (void) fcntl(net->fd, F_SETFL, old_fcntl);
  124. #else
  125.   ulong arg;
  126.   arg=1; ioctlsocket(net->fd,FIONBIO,&arg);
  127.   while ((int) raw_net_read(net->fd,net->buff,net->max_packet) > 0) ;
  128.   arg=0; ioctlsocket(net->fd,FIONBIO,&arg);
  129. #endif
  130.   net->pkt_nr=0; /* Ready for new command */
  131.   net->write_pos=net->buff;
  132. }
  133. #endif
  134. /* Flush write_buffer if not empty. */
  135. int net_flush(NET *net)
  136. {
  137.   int error=0;
  138.   if (net->buff != net->write_pos)
  139.   {
  140.     error=net_real_write(net,(byte*) net->buff,
  141.  (uint) (net->write_pos - net->buff));
  142.     net->write_pos=net->buff;
  143.   }
  144.   return error;
  145. }
  146. /*****************************************************************************
  147. ** Write something to server/clinet buffer
  148. *****************************************************************************/
  149. /*
  150. ** Write a logical packet with packet header
  151. ** Format: Packet length (3 bytes), packet number(1 byte)
  152. */
  153. int
  154. my_net_write(NET *net,const byte *packet,uint len)
  155. {
  156.   uchar buff[4];
  157.   int3store(buff,len);
  158.   buff[3]=(uchar) (net->pkt_nr++);
  159.   if (net_write_buff(net,(char*) buff,4))
  160.     return 1;
  161.   return net_write_buff(net,packet,len);
  162. }
  163. int
  164. net_write_command(NET *net,uchar command,const byte *packet,uint len)
  165. {
  166.   uchar buff[5];
  167.   uint length=len+1; /* One extra byte for command */
  168.   int3store(buff,length);
  169.   buff[3]=(uchar) (net->pkt_nr++);
  170.   buff[4]=command;
  171.   if (!net->buff)
  172.   { /* If net not initiated */
  173.     return test(net_real_write(net,(byte*) buff,5) ||
  174. net_real_write(net,packet,len));
  175.   }
  176.   if (net_write_buff(net,(char*) buff,5))
  177.     return 1;
  178.   return test(net_write_buff(net,packet,len) || net_flush(net));
  179. }
  180. static int
  181. net_write_buff(NET *net,const byte *packet,uint len)
  182. {
  183.   uint left_length=(uint) (net->buff_end - net->write_pos);
  184.   while (len > left_length)
  185.   {
  186.     memcpy((byte*) net->write_pos,packet,left_length);
  187.     if (net_real_write(net,(byte*) net->buff,net->max_packet))
  188.       return 1;
  189.     net->write_pos=net->buff;
  190.     packet+=left_length;
  191.     len-=left_length;
  192.     left_length=net->max_packet;
  193.   }
  194.   memcpy((byte*) net->write_pos,packet,len);
  195.   net->write_pos+=len;
  196.   return 0;
  197. }
  198. #ifdef MYSQL_SERVER
  199. /*  Read and write using timeouts */
  200. int
  201. net_real_write(NET *net,const byte *packet,uint len)
  202. {
  203.   int length;
  204.   byte *pos,*end;
  205.   thr_alarm_t alarmed;
  206.   uint retry_count=0;
  207. #ifdef __WIN32__
  208.   alarmed=thr_alarm(60); /* blocking read */
  209. #else
  210.   thr_alarm_init(&alarmed);
  211. #endif
  212.   pos=(byte*) packet; end=pos+len;
  213.   while (pos != end)
  214.   {
  215.     if ((int) (length=raw_net_write(net->fd,pos,(size_t) (end-pos))) <= 0)
  216.     {
  217. #ifndef __WIN32__
  218.       if ((errno == EAGAIN || errno == EWOULDBLOCK || length == 0)
  219.   && !thr_alarm_in_use(alarmed))
  220.       {
  221. if (!thr_alarm(&alarmed,60)) /* Don't wait too long */
  222. {
  223.   while (fcntl(net->fd, F_SETFL, net->fcntl & ~ O_NONBLOCK) < 0)
  224.   {
  225.     if (errno == EINTR && retry_count++ < 10)
  226.       continue;
  227.     fprintf(stderr,
  228.     "%s: my_net_write: fcntl returned error %d, aborting threadn",
  229.     my_progname,errno);
  230.     net->error=1; /* Close socket */
  231.     goto end;
  232.   }
  233.   retry_count=0;
  234.   continue;
  235. }
  236.       }
  237.       else
  238. #endif
  239. if (thr_alarm_in_use(alarmed) && !thr_got_alarm(alarmed) &&
  240.     (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
  241.       {
  242. if (retry_count++ < 10)
  243.     continue;
  244.   fprintf(stderr, "%s: net_real_write looped, aborting threadn",
  245.   my_progname);
  246.       }
  247.       net->error=1; /* Close socket */
  248.       break;
  249.     }
  250.     pos+=length;
  251.   }
  252.  end:
  253.   if (thr_alarm_in_use(alarmed))
  254.   {
  255.     thr_end_alarm(&alarmed);
  256. #ifdef HAVE_FCNTL
  257.     (void) fcntl(net->fd, F_SETFL, net->fcntl);
  258. #endif
  259.   }
  260.   return (int) (pos != end);
  261. }
  262. #else
  263. int
  264. net_real_write(NET *net,const byte *packet,uint len)
  265. {
  266.   int length;
  267.   byte *pos,*end;
  268.   bool alarmed=0;
  269.   pos=(byte*) packet; end=pos+len;
  270.   while (pos != end)
  271.   {
  272.     if ((int) (length=raw_net_write(net->fd,pos,(size_t) (end-pos))) <= 0)
  273.     {
  274.       if ((errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK ||
  275.    length == 0) && !alarmed)
  276.       {
  277. alarmed=1;
  278. #ifdef HAVE_FCNTL
  279. (void) fcntl(net->fd, F_SETFL, net->fcntl & ~ O_NONBLOCK);
  280. #endif
  281. continue;
  282.       }
  283. #ifdef THREAD_SAFE_CLIENT
  284.       if (errno == EINTR)
  285.       {
  286. DBUG_PRINT("warning",("Interrupted write. Retrying..."));
  287. continue;
  288.       }
  289. #endif
  290.       break;
  291.     }
  292.     pos+=length;
  293.   }
  294. #ifdef HAVE_FCNTL
  295.   if (alarmed)
  296.     (void) fcntl(net->fd, F_SETFL, net->fcntl);
  297. #endif
  298.   return (int) (pos != end);
  299. }
  300. #endif
  301. /*****************************************************************************
  302. ** Read something from server/clinet
  303. *****************************************************************************/
  304. #ifdef MYSQL_SERVER
  305. uint
  306. my_net_read(NET *net)
  307. {
  308.   uchar *pos;
  309.   ulong len,remain;
  310.   long length;
  311.   uint i,retry_count=0;
  312.   thr_alarm_t alarmed;
  313.   len=packet_error;
  314.   remain = 4;
  315.   pos=net->buff;
  316. #ifdef __WIN32__
  317.   alarmed=thr_alarm(net->timeout); /* blocking read */
  318. #else
  319.   thr_alarm_init(&alarmed);
  320. #endif
  321.   for (i=0 ; i < 2 ; i++)
  322.   {
  323.     while (remain > 0)
  324.     {
  325.       errno=0; /* For linux */
  326.       if ((int) (length=raw_net_read(net->fd,(char*) pos,remain)) <= 0)
  327.       {
  328. #ifndef __WIN32__
  329. if ((errno == EAGAIN || errno == EWOULDBLOCK || length == 0)
  330.     && !thr_alarm_in_use(alarmed))
  331. {
  332.   if (!thr_alarm(&alarmed,net->timeout)) /* Don't wait too long */
  333.   {
  334.     while (fcntl(net->fd, F_SETFL, net->fcntl & ~ O_NONBLOCK) < 0)
  335.     {
  336.       if (errno == EINTR && retry_count++ < 10)
  337. continue;
  338.       DBUG_PRINT("error",("fcntl returned error %d, aborting thread",
  339.   errno));
  340.       fprintf(stderr,
  341.       "%s: my_net_read: fcntl returned error %d, aborting threadn",
  342.       my_progname,errno);
  343.       len= packet_error;
  344.       net->error=1; /* Close socket */
  345.       goto end;
  346.     }
  347.     retry_count=0;
  348.     continue;
  349.   }
  350. }
  351. #endif
  352. if (thr_alarm_in_use(alarmed) && !thr_got_alarm(alarmed) &&
  353.     (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
  354. { /* Probably in MIT threads */
  355.   if (retry_count++ < 10)
  356.     continue;
  357.   fprintf(stderr, "%s: my_net_read: looped with error %d, aborting threadn",
  358.   my_progname,errno);
  359. }
  360. DBUG_PRINT("error",("Got error %d reading socket",errno));
  361. len= packet_error;
  362. net->error=1; /* Close socket */
  363. goto end;
  364.       }
  365.       remain -= (ulong) length;
  366.       pos+= (ulong) length;
  367.     }
  368.     if (i == 0)
  369.     { /* First parts is packet length */
  370.       if ((len=uint3korr(net->buff)) >= max_allowed_packet)
  371.       {
  372. DBUG_PRINT("error",("Packet too large (%ld)", len));
  373. fprintf(stderr,"Packet too large (%ld)n", len);
  374. len= packet_error; /* Return error */
  375. goto end;
  376.       }
  377.       if (net->buff[3] != (uchar) net->pkt_nr)
  378.       {
  379. DBUG_PRINT("error",("Packets out of order (Found: %d, expected %d)",
  380.     (int) net->buff[3],net->pkt_nr));
  381. fprintf(stderr,"Packets out of order (Found: %d, expected %d)n",
  382. (int) net->buff[3],net->pkt_nr);
  383. len= packet_error;
  384. goto end;
  385.       }
  386.       net->pkt_nr++;
  387.       if (len >= net->max_packet)
  388.       { /* Alloc bigger package */
  389. uint pkt_length=(len+IO_SIZE) & ~(IO_SIZE-1);
  390. uchar *buff=(uchar*) my_realloc((char*) net->buff,pkt_length,
  391. MYF(MY_WME));
  392. if (!buff)
  393. {
  394.   len=packet_error;
  395.   goto end;
  396. }
  397. net->buff=net->write_pos=buff;
  398. net->buff_end=buff+(net->max_packet=pkt_length);
  399.       }
  400.       pos=net->buff;
  401.       remain = len;
  402.     }
  403.   }
  404.   *pos = 0; /* Safeguard */
  405. end:
  406.   if (thr_alarm_in_use(alarmed))
  407.   {
  408.     thr_end_alarm(&alarmed);
  409. #ifdef HAVE_FCNTL
  410.     (void) fcntl(net->fd, F_SETFL, net->fcntl);
  411. #endif
  412.   }
  413.   return(len);
  414. }
  415. #else /* !MYSQL_SERVER */
  416. uint my_net_read(NET *net)
  417. {
  418.   uchar *pos,wrong_packet_nr;
  419.   ulong len,remain;
  420.   long length;
  421.   uint i;
  422.   bool alarmed=0,error_packet=0;
  423.   len= packet_error;
  424.   remain = 4;
  425.   pos=net->buff; /* net->packet -4 */
  426.   for (i=0 ; i < 2 ; i++)
  427.   {
  428.     while (remain > 0)
  429.     {
  430.       if ((int) (length=raw_net_read(net->fd,pos,remain)) <= 0)
  431.       {
  432. if ((errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK ||
  433.      length == 0) && !alarmed)
  434. {
  435.   alarmed=1;
  436. #ifdef HAVE_FCNTL
  437.   (void) fcntl(net->fd, F_SETFL, net->fcntl & ~ O_NONBLOCK);
  438. #endif
  439.   continue;
  440. }
  441. #ifdef THREAD_SAFE_CLIENT
  442. if (errno == EINTR)
  443. {
  444.   DBUG_PRINT("warning",("Interrupted read. Retrying..."));
  445.   continue;
  446. }
  447. #endif
  448. DBUG_PRINT("error",("Couldn't read packet: remain: %d  errno: %d  length: %d  alarmed: %d", remain,errno,length,alarmed));
  449. len= packet_error;
  450. goto end;
  451.       }
  452.       remain -= (ulong) length;
  453.       pos+= (ulong) length;
  454.     }
  455.     if (i == 0)
  456.     { /* First parts is packet length */
  457.       if ((len=uint3korr(net->buff)) >= max_allowed_packet)
  458.       {
  459. DBUG_PRINT("error",("Packet too large (%ld)",len));
  460. fprintf(stderr,"Packet too large (%ld)n", len);
  461. return packet_error; /* Return error */
  462.       }
  463.       if (net->buff[3] != (uchar) net->pkt_nr)
  464.       {
  465. error_packet=1; /* Probably error out of sync */
  466. wrong_packet_nr=net->pkt_nr;
  467. net->pkt_nr=net->buff[3];
  468.       }
  469.       else
  470. net->pkt_nr++;
  471.       if (len >= net->max_packet)
  472.       { /* Alloc bigger package */
  473. uint pkt_length=(len+IO_SIZE) & ~(IO_SIZE-1);
  474. uchar *buff=(uchar*) my_realloc((char*) net->buff,pkt_length,
  475. MYF(MY_WME));
  476. if (!buff)
  477. {
  478.   len=packet_error;
  479.   break;
  480. }
  481. net->buff=net->write_pos=buff;
  482. net->buff_end=buff+(net->max_packet=pkt_length);
  483.       }
  484.       pos=net->buff;
  485.       remain = len;
  486.     }
  487.   }
  488.   if (error_packet && net->buff[0] != (uchar) 255)
  489.   {
  490.     DBUG_PRINT("error",("Packets out of order (Found: %d, expected %d)n",
  491. (int) (uchar) net->pkt_nr,(int) wrong_packet_nr));
  492.     fprintf(stderr,"Packets out of order (Found: %d, expected %d)n",
  493.     (int) (uchar) net->pkt_nr,(int) wrong_packet_nr);
  494.     len=packet_error;
  495.   }
  496. end:
  497. #ifdef HAVE_FCNTL
  498.   if (alarmed)
  499.     (void) fcntl(net->fd, F_SETFL, net->fcntl);
  500. #endif
  501.   *pos = 0; /* Safeguard */
  502.   return(len);
  503. }
  504. #endif