MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
net_serv.cc
Go to the documentation of this file.
1 /* Copyright (c) 2000, 2013, 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 as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
32 /*
33  HFTODO this must be hidden if we don't want client capabilities in
34  embedded library
35  */
36 #include <my_global.h>
37 #include <mysql.h>
38 #include <mysql_com.h>
39 #include <mysqld_error.h>
40 #include <my_sys.h>
41 #include <m_string.h>
42 #include <my_net.h>
43 #include <violite.h>
44 #include <signal.h>
45 #include <errno.h>
46 #include "probes_mysql.h"
47 
48 #include <algorithm>
49 
50 using std::min;
51 using std::max;
52 
53 #ifdef EMBEDDED_LIBRARY
54 #undef MYSQL_SERVER
55 #undef MYSQL_CLIENT
56 #define MYSQL_CLIENT
57 #endif /*EMBEDDED_LIBRARY */
58 
59 
60 /*
61  The following handles the differences when this is linked between the
62  client and the server.
63 
64  This gives an error if a too big packet is found.
65  The server can change this, but because the client can't normally do this
66  the client should have a bigger max_allowed_packet.
67 */
68 
69 #ifdef MYSQL_SERVER
70 /*
71  The following variables/functions should really not be declared
72  extern, but as it's hard to include sql_priv.h here, we have to
73  live with this for a while.
74 */
75 #ifdef HAVE_QUERY_CACHE
76 #define USE_QUERY_CACHE
77 extern void query_cache_insert(const char *packet, ulong length,
78  unsigned pkt_nr);
79 #endif /* HAVE_QUERY_CACHE */
80 #define update_statistics(A) A
81 #else /* MYSQL_SERVER */
82 #define update_statistics(A)
83 #define thd_increment_bytes_sent(N)
84 #endif
85 
86 #ifdef MYSQL_SERVER
87 /* Additional instrumentation hooks for the server */
88 #include "mysql_com_server.h"
89 #endif
90 
91 #define VIO_SOCKET_ERROR ((size_t) -1)
92 #define MAX_PACKET_LENGTH (256L*256L*256L-1)
93 
94 static my_bool net_write_buff(NET *, const uchar *, ulong);
95 
98 my_bool my_net_init(NET *net, Vio* vio)
99 {
100  DBUG_ENTER("my_net_init");
101  net->vio = vio;
102  my_net_local_init(net); /* Set some limits */
103  if (!(net->buff=(uchar*) my_malloc((size_t) net->max_packet+
104  NET_HEADER_SIZE + COMP_HEADER_SIZE,
105  MYF(MY_WME))))
106  DBUG_RETURN(1);
107  net->buff_end=net->buff+net->max_packet;
108  net->error=0; net->return_status=0;
109  net->pkt_nr=net->compress_pkt_nr=0;
110  net->write_pos=net->read_pos = net->buff;
111  net->last_error[0]=0;
112  net->compress=0; net->reading_or_writing=0;
113  net->where_b = net->remain_in_buf=0;
114  net->last_errno=0;
115  net->unused= 0;
116 #ifdef MYSQL_SERVER
117  net->extension= NULL;
118 #endif
119 
120  if (vio)
121  {
122  /* For perl DBI/DBD. */
123  net->fd= vio_fd(vio);
124  vio_fastsend(vio);
125  }
126  DBUG_RETURN(0);
127 }
128 
129 
130 void net_end(NET *net)
131 {
132  DBUG_ENTER("net_end");
133  my_free(net->buff);
134  net->buff=0;
135  DBUG_VOID_RETURN;
136 }
137 
138 
141 my_bool net_realloc(NET *net, size_t length)
142 {
143  uchar *buff;
144  size_t pkt_length;
145  DBUG_ENTER("net_realloc");
146  DBUG_PRINT("enter",("length: %lu", (ulong) length));
147 
148  if (length >= net->max_packet_size)
149  {
150  DBUG_PRINT("error", ("Packet too large. Max size: %lu",
151  net->max_packet_size));
152  /* @todo: 1 and 2 codes are identical. */
153  net->error= 1;
154  net->last_errno= ER_NET_PACKET_TOO_LARGE;
155 #ifdef MYSQL_SERVER
156  my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
157 #endif
158  DBUG_RETURN(1);
159  }
160  pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
161  /*
162  We must allocate some extra bytes for the end 0 and to be able to
163  read big compressed blocks + 1 safety byte since uint3korr() in
164  net_read_packet() may actually read 4 bytes depending on build flags and
165  platform.
166  */
167  if (!(buff= (uchar*) my_realloc((char*) net->buff, pkt_length +
168  NET_HEADER_SIZE + COMP_HEADER_SIZE + 1,
169  MYF(MY_WME))))
170  {
171  /* @todo: 1 and 2 codes are identical. */
172  net->error= 1;
173  net->last_errno= ER_OUT_OF_RESOURCES;
174  /* In the server the error is reported by MY_WME flag. */
175  DBUG_RETURN(1);
176  }
177  net->buff=net->write_pos=buff;
178  net->buff_end=buff+(net->max_packet= (ulong) pkt_length);
179  DBUG_RETURN(0);
180 }
181 
182 
193 void net_clear(NET *net,
194  my_bool check_buffer __attribute__((unused)))
195 {
196  DBUG_ENTER("net_clear");
197 
198 #if !defined(EMBEDDED_LIBRARY)
199  /* Ensure the socket buffer is empty, except for an EOF (at least 1). */
200  DBUG_ASSERT(!check_buffer || (vio_pending(net->vio) <= 1));
201 #endif
202 
203  /* Ready for new command */
204  net->pkt_nr= net->compress_pkt_nr= 0;
205  net->write_pos= net->buff;
206 
207  DBUG_VOID_RETURN;
208 }
209 
210 
213 my_bool net_flush(NET *net)
214 {
215  my_bool error= 0;
216  DBUG_ENTER("net_flush");
217  if (net->buff != net->write_pos)
218  {
219  error= net_write_packet(net, net->buff,
220  (size_t) (net->write_pos - net->buff));
221  net->write_pos= net->buff;
222  }
223  /* Sync packet number if using compression */
224  if (net->compress)
225  net->pkt_nr=net->compress_pkt_nr;
226  DBUG_RETURN(error);
227 }
228 
229 
240 static my_bool
241 net_should_retry(NET *net, uint *retry_count __attribute__((unused)))
242 {
243  my_bool retry;
244 
245 #if !defined(MYSQL_SERVER) && defined(THREAD_SAFE_CLIENT)
246  /*
247  In the thread safe client library, interrupted I/O operations
248  are always retried. Otherwise, its either a timeout or a
249  unrecoverable error.
250  */
251  retry= vio_should_retry(net->vio);
252 #else
253  /*
254  In the non-thread safe client library, or in the server,
255  interrupted I/O operations are retried up to a limit.
256  In this scenario, pthread_kill can be used to wake up
257  (interrupt) threads waiting for I/O.
258  */
259  retry= vio_should_retry(net->vio) && ((*retry_count)++ < net->retry_count);
260 #endif
261 
262  return retry;
263 }
264 
265 
266 /*****************************************************************************
267 ** Write something to server/client buffer
268 *****************************************************************************/
269 
279 my_bool my_net_write(NET *net, const uchar *packet, size_t len)
280 {
281  uchar buff[NET_HEADER_SIZE];
282  int rc;
283 
284  if (unlikely(!net->vio)) /* nowhere to write */
285  return 0;
286 
287  MYSQL_NET_WRITE_START(len);
288 
289  /*
290  Big packets are handled by splitting them in packets of MAX_PACKET_LENGTH
291  length. The last packet is always a packet that is < MAX_PACKET_LENGTH.
292  (The last packet may even have a length of 0)
293  */
294  while (len >= MAX_PACKET_LENGTH)
295  {
296  const ulong z_size = MAX_PACKET_LENGTH;
297  int3store(buff, z_size);
298  buff[3]= (uchar) net->pkt_nr++;
299  if (net_write_buff(net, buff, NET_HEADER_SIZE) ||
300  net_write_buff(net, packet, z_size))
301  {
302  MYSQL_NET_WRITE_DONE(1);
303  return 1;
304  }
305  packet += z_size;
306  len-= z_size;
307  }
308  /* Write last packet */
309  int3store(buff,len);
310  buff[3]= (uchar) net->pkt_nr++;
311  if (net_write_buff(net, buff, NET_HEADER_SIZE))
312  {
313  MYSQL_NET_WRITE_DONE(1);
314  return 1;
315  }
316 #ifndef DEBUG_DATA_PACKETS
317  DBUG_DUMP("packet_header", buff, NET_HEADER_SIZE);
318 #endif
319  rc= test(net_write_buff(net,packet,len));
320  MYSQL_NET_WRITE_DONE(rc);
321  return rc;
322 }
323 
324 
352 my_bool
353 net_write_command(NET *net,uchar command,
354  const uchar *header, size_t head_len,
355  const uchar *packet, size_t len)
356 {
357  size_t length=len+1+head_len; /* 1 extra byte for command */
358  uchar buff[NET_HEADER_SIZE+1];
359  uint header_size=NET_HEADER_SIZE+1;
360  int rc;
361  DBUG_ENTER("net_write_command");
362  DBUG_PRINT("enter",("length: %lu", (ulong) len));
363 
364  MYSQL_NET_WRITE_START(length);
365 
366  buff[4]=command; /* For first packet */
367 
368  if (length >= MAX_PACKET_LENGTH)
369  {
370  /* Take into account that we have the command in the first header */
371  len= MAX_PACKET_LENGTH - 1 - head_len;
372  do
373  {
374  int3store(buff, MAX_PACKET_LENGTH);
375  buff[3]= (uchar) net->pkt_nr++;
376  if (net_write_buff(net, buff, header_size) ||
377  net_write_buff(net, header, head_len) ||
378  net_write_buff(net, packet, len))
379  {
380  MYSQL_NET_WRITE_DONE(1);
381  DBUG_RETURN(1);
382  }
383  packet+= len;
384  length-= MAX_PACKET_LENGTH;
385  len= MAX_PACKET_LENGTH;
386  head_len= 0;
387  header_size= NET_HEADER_SIZE;
388  } while (length >= MAX_PACKET_LENGTH);
389  len=length; /* Data left to be written */
390  }
391  int3store(buff,length);
392  buff[3]= (uchar) net->pkt_nr++;
393  rc= test(net_write_buff(net, buff, header_size) ||
394  (head_len && net_write_buff(net, header, head_len)) ||
395  net_write_buff(net, packet, len) || net_flush(net));
396  MYSQL_NET_WRITE_DONE(rc);
397  DBUG_RETURN(rc);
398 }
399 
400 
427 static my_bool
428 net_write_buff(NET *net, const uchar *packet, ulong len)
429 {
430  ulong left_length;
431  if (net->compress && net->max_packet > MAX_PACKET_LENGTH)
432  left_length= (ulong) (MAX_PACKET_LENGTH - (net->write_pos - net->buff));
433  else
434  left_length= (ulong) (net->buff_end - net->write_pos);
435 
436 #ifdef DEBUG_DATA_PACKETS
437  DBUG_DUMP("data", packet, len);
438 #endif
439  if (len > left_length)
440  {
441  if (net->write_pos != net->buff)
442  {
443  /* Fill up already used packet and write it */
444  memcpy(net->write_pos, packet, left_length);
445  if (net_write_packet(net, net->buff,
446  (size_t) (net->write_pos - net->buff) + left_length))
447  return 1;
448  net->write_pos= net->buff;
449  packet+= left_length;
450  len-= left_length;
451  }
452  if (net->compress)
453  {
454  /*
455  We can't have bigger packets than 16M with compression
456  Because the uncompressed length is stored in 3 bytes
457  */
458  left_length= MAX_PACKET_LENGTH;
459  while (len > left_length)
460  {
461  if (net_write_packet(net, packet, left_length))
462  return 1;
463  packet+= left_length;
464  len-= left_length;
465  }
466  }
467  if (len > net->max_packet)
468  return net_write_packet(net, packet, len);
469  /* Send out rest of the blocks as full sized blocks */
470  }
471  memcpy(net->write_pos, packet, len);
472  net->write_pos+= len;
473  return 0;
474 }
475 
476 
487 static my_bool
488 net_write_raw_loop(NET *net, const uchar *buf, size_t count)
489 {
490  unsigned int retry_count= 0;
491 
492  while (count)
493  {
494  size_t sentcnt= vio_write(net->vio, buf, count);
495 
496  /* VIO_SOCKET_ERROR (-1) indicates an error. */
497  if (sentcnt == VIO_SOCKET_ERROR)
498  {
499  /* A recoverable I/O error occurred? */
500  if (net_should_retry(net, &retry_count))
501  continue;
502  else
503  break;
504  }
505 
506  count-= sentcnt;
507  buf+= sentcnt;
508  update_statistics(thd_increment_bytes_sent(sentcnt));
509  }
510 
511  /* On failure, propagate the error code. */
512  if (count)
513  {
514  /* Socket should be closed. */
515  net->error= 2;
516 
517  /* Interrupted by a timeout? */
518  if (vio_was_timeout(net->vio))
519  net->last_errno= ER_NET_WRITE_INTERRUPTED;
520  else
521  net->last_errno= ER_NET_ERROR_ON_WRITE;
522 
523 #ifdef MYSQL_SERVER
524  my_error(net->last_errno, MYF(0));
525 #endif
526  }
527 
528  return test(count);
529 }
530 
531 
546 static uchar *
547 compress_packet(NET *net, const uchar *packet, size_t *length)
548 {
549  uchar *compr_packet;
550  size_t compr_length;
551  const uint header_length= NET_HEADER_SIZE + COMP_HEADER_SIZE;
552 
553  compr_packet= (uchar *) my_malloc(*length + header_length, MYF(MY_WME));
554 
555  if (compr_packet == NULL)
556  return NULL;
557 
558  memcpy(compr_packet + header_length, packet, *length);
559 
560  /* Compress the encapsulated packet. */
561  if (my_compress(compr_packet + header_length, length, &compr_length))
562  {
563  /*
564  If the length of the compressed packet is larger than the
565  original packet, the original packet is sent uncompressed.
566  */
567  compr_length= 0;
568  }
569 
570  /* Length of the compressed (original) packet. */
571  int3store(&compr_packet[NET_HEADER_SIZE], compr_length);
572  /* Length of this packet. */
573  int3store(compr_packet, *length);
574  /* Packet number. */
575  compr_packet[3]= (uchar) (net->compress_pkt_nr++);
576 
577  *length+= header_length;
578 
579  return compr_packet;
580 }
581 
582 
595 my_bool
596 net_write_packet(NET *net, const uchar *packet, size_t length)
597 {
598  my_bool res;
599  DBUG_ENTER("net_write_packet");
600 
601 #if defined(MYSQL_SERVER) && defined(USE_QUERY_CACHE)
602  query_cache_insert((char*) packet, length, net->pkt_nr);
603 #endif
604 
605  /* Socket can't be used */
606  if (net->error == 2)
607  DBUG_RETURN(TRUE);
608 
609  net->reading_or_writing= 2;
610 
611 #ifdef HAVE_COMPRESS
612  const bool do_compress= net->compress;
613  if (do_compress)
614  {
615  if ((packet= compress_packet(net, packet, &length)) == NULL)
616  {
617  net->error= 2;
618  net->last_errno= ER_OUT_OF_RESOURCES;
619  /* In the server, allocation failure raises a error. */
620  net->reading_or_writing= 0;
621  DBUG_RETURN(TRUE);
622  }
623  }
624 #endif /* HAVE_COMPRESS */
625 
626 #ifdef DEBUG_DATA_PACKETS
627  DBUG_DUMP("data", packet, length);
628 #endif
629 
630  res= net_write_raw_loop(net, packet, length);
631 
632 #ifdef HAVE_COMPRESS
633  if (do_compress)
634  my_free((void *) packet);
635 #endif
636 
637  net->reading_or_writing= 0;
638 
639  DBUG_RETURN(res);
640 }
641 
642 /*****************************************************************************
643 ** Read something from server/clinet
644 *****************************************************************************/
645 
655 static my_bool net_read_raw_loop(NET *net, size_t count)
656 {
657  bool eof= false;
658  unsigned int retry_count= 0;
659  uchar *buf= net->buff + net->where_b;
660 
661  while (count)
662  {
663  size_t recvcnt= vio_read(net->vio, buf, count);
664 
665  /* VIO_SOCKET_ERROR (-1) indicates an error. */
666  if (recvcnt == VIO_SOCKET_ERROR)
667  {
668  /* A recoverable I/O error occurred? */
669  if (net_should_retry(net, &retry_count))
670  continue;
671  else
672  break;
673  }
674  /* Zero indicates end of file. */
675  else if (!recvcnt)
676  {
677  eof= true;
678  break;
679  }
680 
681  count-= recvcnt;
682  buf+= recvcnt;
683  update_statistics(thd_increment_bytes_received(recvcnt));
684  }
685 
686  /* On failure, propagate the error code. */
687  if (count)
688  {
689  /* Socket should be closed. */
690  net->error= 2;
691 
692  /* Interrupted by a timeout? */
693  if (!eof && vio_was_timeout(net->vio))
694  net->last_errno= ER_NET_READ_INTERRUPTED;
695  else
696  net->last_errno= ER_NET_READ_ERROR;
697 
698 #ifdef MYSQL_SERVER
699  my_error(net->last_errno, MYF(0));
700 #endif
701  }
702 
703  return test(count);
704 }
705 
706 
724 static my_bool net_read_packet_header(NET *net)
725 {
726  uchar pkt_nr;
727  size_t count= NET_HEADER_SIZE;
728  my_bool rc;
729 
730  if (net->compress)
731  count+= COMP_HEADER_SIZE;
732 
733 #ifdef MYSQL_SERVER
734  struct st_net_server *server_extension;
735 
736  server_extension= static_cast<st_net_server*> (net->extension);
737 
738  if (server_extension != NULL)
739  {
740  void *user_data= server_extension->m_user_data;
741  DBUG_ASSERT(server_extension->m_before_header != NULL);
742  DBUG_ASSERT(server_extension->m_after_header != NULL);
743 
744  server_extension->m_before_header(net, user_data, count);
745  rc= net_read_raw_loop(net, count);
746  server_extension->m_after_header(net, user_data, count, rc);
747  }
748  else
749 #endif
750  {
751  rc= net_read_raw_loop(net, count);
752  }
753 
754  if (rc)
755  return TRUE;
756 
757  DBUG_DUMP("packet_header", net->buff + net->where_b, NET_HEADER_SIZE);
758 
759  pkt_nr= net->buff[net->where_b + 3];
760 
761  /*
762  Verify packet serial number against the truncated packet counter.
763  The local packet counter must be truncated since its not reset.
764  */
765  if (pkt_nr != (uchar) net->pkt_nr)
766  {
767  /* Not a NET error on the client. XXX: why? */
768 #if defined(MYSQL_SERVER)
769  my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0));
770 #elif defined(EXTRA_DEBUG)
771  /*
772  We don't make noise server side, since the client is expected
773  to break the protocol for e.g. --send LOAD DATA .. LOCAL where
774  the server expects the client to send a file, but the client
775  may reply with a new command instead.
776  */
777  fprintf(stderr, "Error: packets out of order (found %u, expected %u)\n",
778  (uint) pkt_nr, net->pkt_nr);
779  DBUG_ASSERT(pkt_nr == net->pkt_nr);
780 #endif
781  return TRUE;
782  }
783 
784  net->pkt_nr++;
785 
786  return FALSE;
787 }
788 
789 
801 static ulong net_read_packet(NET *net, size_t *complen)
802 {
803  size_t pkt_len, pkt_data_len;
804 
805  *complen= 0;
806 
807  net->reading_or_writing= 1;
808 
809  /* Retrieve packet length and number. */
810  if (net_read_packet_header(net))
811  goto error;
812 
813  net->compress_pkt_nr= net->pkt_nr;
814 
815 #ifdef HAVE_COMPRESS
816  if (net->compress)
817  {
818  /*
819  The following uint3korr() may read 4 bytes, so make sure we don't
820  read unallocated or uninitialized memory. The right-hand expression
821  must match the size of the buffer allocated in net_realloc().
822  */
823  DBUG_ASSERT(net->where_b + NET_HEADER_SIZE + sizeof(uint32) <=
824  net->max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1);
825 
826  /*
827  If the packet is compressed then complen > 0 and contains the
828  number of bytes in the uncompressed packet.
829  */
830  *complen= uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
831  }
832 #endif
833 
834  /* The length of the packet that follows. */
835  pkt_len= uint3korr(net->buff+net->where_b);
836 
837  /* End of big multi-packet. */
838  if (!pkt_len)
839  goto end;
840 
841  pkt_data_len = max(pkt_len, *complen) + net->where_b;
842 
843  /* Expand packet buffer if necessary. */
844  if ((pkt_data_len >= net->max_packet) && net_realloc(net, pkt_data_len))
845  goto error;
846 
847  /* Read the packet data (payload). */
848  if (net_read_raw_loop(net, pkt_len))
849  goto error;
850 
851 end:
852  net->reading_or_writing= 0;
853  return pkt_len;
854 
855 error:
856  net->reading_or_writing= 0;
857  return packet_error;
858 }
859 
860 
877 ulong
879 {
880  size_t len, complen;
881 
882  MYSQL_NET_READ_START();
883 
884 #ifdef HAVE_COMPRESS
885  if (!net->compress)
886  {
887 #endif
888  len= net_read_packet(net, &complen);
889  if (len == MAX_PACKET_LENGTH)
890  {
891  /* First packet of a multi-packet. Concatenate the packets */
892  ulong save_pos = net->where_b;
893  size_t total_length= 0;
894  do
895  {
896  net->where_b += len;
897  total_length += len;
898  len= net_read_packet(net, &complen);
899  } while (len == MAX_PACKET_LENGTH);
900  if (len != packet_error)
901  len+= total_length;
902  net->where_b = save_pos;
903  }
904  net->read_pos = net->buff + net->where_b;
905  if (len != packet_error)
906  net->read_pos[len]=0; /* Safeguard for mysql_use_result */
907  MYSQL_NET_READ_DONE(0, len);
908  return len;
909 #ifdef HAVE_COMPRESS
910  }
911  else
912  {
913  /* We are using the compressed protocol */
914 
915  ulong buf_length;
916  ulong start_of_packet;
917  ulong first_packet_offset;
918  uint read_length, multi_byte_packet=0;
919 
920  if (net->remain_in_buf)
921  {
922  buf_length= net->buf_length; /* Data left in old packet */
923  first_packet_offset= start_of_packet= (net->buf_length -
924  net->remain_in_buf);
925  /* Restore the character that was overwritten by the end 0 */
926  net->buff[start_of_packet]= net->save_char;
927  }
928  else
929  {
930  /* reuse buffer, as there is nothing in it that we need */
931  buf_length= start_of_packet= first_packet_offset= 0;
932  }
933  for (;;)
934  {
935  ulong packet_len;
936 
937  if (buf_length - start_of_packet >= NET_HEADER_SIZE)
938  {
939  read_length = uint3korr(net->buff+start_of_packet);
940  if (!read_length)
941  {
942  /* End of multi-byte packet */
943  start_of_packet += NET_HEADER_SIZE;
944  break;
945  }
946  if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
947  {
948  if (multi_byte_packet)
949  {
950  /* Remove packet header for second packet */
951  memmove(net->buff + first_packet_offset + start_of_packet,
952  net->buff + first_packet_offset + start_of_packet +
953  NET_HEADER_SIZE,
954  buf_length - start_of_packet);
955  start_of_packet += read_length;
956  buf_length -= NET_HEADER_SIZE;
957  }
958  else
959  start_of_packet+= read_length + NET_HEADER_SIZE;
960 
961  if (read_length != MAX_PACKET_LENGTH) /* last package */
962  {
963  multi_byte_packet= 0; /* No last zero len packet */
964  break;
965  }
966  multi_byte_packet= NET_HEADER_SIZE;
967  /* Move data down to read next data packet after current one */
968  if (first_packet_offset)
969  {
970  memmove(net->buff,net->buff+first_packet_offset,
971  buf_length-first_packet_offset);
972  buf_length-=first_packet_offset;
973  start_of_packet -= first_packet_offset;
974  first_packet_offset=0;
975  }
976  continue;
977  }
978  }
979  /* Move data down to read next data packet after current one */
980  if (first_packet_offset)
981  {
982  memmove(net->buff,net->buff+first_packet_offset,
983  buf_length-first_packet_offset);
984  buf_length-=first_packet_offset;
985  start_of_packet -= first_packet_offset;
986  first_packet_offset=0;
987  }
988 
989  net->where_b=buf_length;
990  if ((packet_len= net_read_packet(net, &complen)) == packet_error)
991  {
992  MYSQL_NET_READ_DONE(1, 0);
993  return packet_error;
994  }
995  if (my_uncompress(net->buff + net->where_b, packet_len,
996  &complen))
997  {
998  net->error= 2; /* caller will close socket */
999  net->last_errno= ER_NET_UNCOMPRESS_ERROR;
1000 #ifdef MYSQL_SERVER
1001  my_error(ER_NET_UNCOMPRESS_ERROR, MYF(0));
1002 #endif
1003  MYSQL_NET_READ_DONE(1, 0);
1004  return packet_error;
1005  }
1006  buf_length+= complen;
1007  }
1008 
1009  net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE;
1010  net->buf_length= buf_length;
1011  net->remain_in_buf= (ulong) (buf_length - start_of_packet);
1012  len = ((ulong) (start_of_packet - first_packet_offset) - NET_HEADER_SIZE -
1013  multi_byte_packet);
1014  net->save_char= net->read_pos[len]; /* Must be saved */
1015  net->read_pos[len]=0; /* Safeguard for mysql_use_result */
1016  }
1017 #endif /* HAVE_COMPRESS */
1018  MYSQL_NET_READ_DONE(0, len);
1019  return len;
1020 }
1021 
1022 
1023 void my_net_set_read_timeout(NET *net, uint timeout)
1024 {
1025  DBUG_ENTER("my_net_set_read_timeout");
1026  DBUG_PRINT("enter", ("timeout: %d", timeout));
1027  net->read_timeout= timeout;
1028  if (net->vio)
1029  vio_timeout(net->vio, 0, timeout);
1030  DBUG_VOID_RETURN;
1031 }
1032 
1033 
1034 void my_net_set_write_timeout(NET *net, uint timeout)
1035 {
1036  DBUG_ENTER("my_net_set_write_timeout");
1037  DBUG_PRINT("enter", ("timeout: %d", timeout));
1038  net->write_timeout= timeout;
1039  if (net->vio)
1040  vio_timeout(net->vio, 1, timeout);
1041  DBUG_VOID_RETURN;
1042 }
1043