~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/net_serv.c

  • Committer: Monty
  • Date: 2008-10-02 05:41:33 UTC
  • mfrom: (398.1.10 codestyle)
  • Revision ID: mordred@scylla.inaugust.com-20081002054133-tyxv5bmqpazfaqqi
Merged up to 408 of stdint-includes-fix.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 */
 
20
 
 
21
#include "libdrizzle.h"
 
22
#include "libdrizzle_priv.h"
 
23
#include <libdrizzle/errmsg.h>
 
24
#include <vio/violite.h>
 
25
#include <assert.h>
 
26
#include <stdio.h>
 
27
#include <stdlib.h>
 
28
#include <string.h>
 
29
#include <signal.h>
 
30
#include <errno.h>
 
31
#include <sys/socket.h>
 
32
#include <sys/poll.h>
 
33
#include <zlib.h>
 
34
 
 
35
/*
 
36
  The following handles the differences when this is linked between the
 
37
  client and the server.
 
38
 
 
39
  This gives an error if a too big packet is found
 
40
  The server can change this with the -O switch, but because the client
 
41
  can't normally do this the client should have a bigger max_allowed_packet.
 
42
*/
 
43
 
 
44
 
 
45
#define update_statistics(A)
 
46
#define thd_increment_bytes_sent(N)
 
47
 
 
48
#define TEST_BLOCKING        8
 
49
#define MAX_PACKET_LENGTH (256L*256L*256L-1)
 
50
#define MIN_COMPRESS_LENGTH             50      /* Don't compress small bl. */
 
51
 
 
52
static bool net_write_buff(NET *net, const unsigned char *packet, uint32_t len);
 
53
 
 
54
 
 
55
/** Init with packet info. */
 
56
 
 
57
bool my_net_init(NET *net, Vio* vio)
 
58
{
 
59
  net->vio = vio;
 
60
  my_net_local_init(net);            /* Set some limits */
 
61
  if (!(net->buff=(unsigned char*) malloc((size_t) net->max_packet+
 
62
                                  NET_HEADER_SIZE + COMP_HEADER_SIZE)))
 
63
    return(1);
 
64
  net->buff_end=net->buff+net->max_packet;
 
65
  net->error=0; net->return_status=0;
 
66
  net->pkt_nr=net->compress_pkt_nr=0;
 
67
  net->write_pos=net->read_pos = net->buff;
 
68
  net->last_error[0]=0;
 
69
  net->compress=0; net->reading_or_writing=0;
 
70
  net->where_b = net->remain_in_buf=0;
 
71
  net->last_errno=0;
 
72
  net->unused= 0;
 
73
 
 
74
  if (vio != 0)                    /* If real connection */
 
75
  {
 
76
    net->fd  = vio_fd(vio);            /* For perl DBI/DBD */
 
77
    vio_fastsend(vio);
 
78
  }
 
79
  return(0);
 
80
}
 
81
 
 
82
bool net_init_sock(NET * net, int sock, int flags)
 
83
{
 
84
 
 
85
  Vio *vio_tmp= vio_new(sock, VIO_TYPE_TCPIP, flags);
 
86
  if (vio_tmp == NULL)
 
87
    return true;
 
88
  else
 
89
    if (my_net_init(net, vio_tmp))
 
90
    {
 
91
      /* Only delete the temporary vio if we didn't already attach it to the
 
92
       * NET object.
 
93
       */
 
94
      if (vio_tmp && (net->vio != vio_tmp))
 
95
        vio_delete(vio_tmp);
 
96
      else
 
97
      {
 
98
        (void) shutdown(sock, SHUT_RDWR);
 
99
        (void) close(sock);
 
100
      }
 
101
      return true;
 
102
    }
 
103
  return false;
 
104
}
 
105
 
 
106
void net_end(NET *net)
 
107
{
 
108
  if (net->buff != NULL)
 
109
    free(net->buff);
 
110
  net->buff=0;
 
111
  return;
 
112
}
 
113
 
 
114
void net_close(NET *net)
 
115
{
 
116
  if (net->vio != NULL)
 
117
  {
 
118
    vio_delete(net->vio);
 
119
    net->vio= 0;
 
120
  }
 
121
}
 
122
 
 
123
bool net_peer_addr(NET *net, char *buf, uint16_t *port, size_t buflen)
 
124
{
 
125
  return vio_peer_addr(net->vio, buf, port, buflen);
 
126
}
 
127
 
 
128
void net_keepalive(NET *net, bool flag)
 
129
{
 
130
  vio_keepalive(net->vio, flag);
 
131
}
 
132
 
 
133
int net_get_sd(NET *net)
 
134
{
 
135
  return net->vio->sd;
 
136
}
 
137
 
 
138
bool net_should_close(NET *net)
 
139
{
 
140
  return net->error || (net->vio == 0);
 
141
}
 
142
 
 
143
bool net_more_data(NET *net)
 
144
{
 
145
  return (net->vio == 0 || net->vio->read_pos < net->vio->read_end);
 
146
}
 
147
 
 
148
/** Realloc the packet buffer. */
 
149
 
 
150
bool net_realloc(NET *net, size_t length)
 
151
{
 
152
  unsigned char *buff;
 
153
  size_t pkt_length;
 
154
 
 
155
  if (length >= net->max_packet_size)
 
156
  {
 
157
    /* @todo: 1 and 2 codes are identical. */
 
158
    net->error= 1;
 
159
    net->last_errno= CR_NET_PACKET_TOO_LARGE;
 
160
    return(1);
 
161
  }
 
162
  pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
 
163
  /*
 
164
    We must allocate some extra bytes for the end 0 and to be able to
 
165
    read big compressed blocks
 
166
  */
 
167
  if (!(buff= (unsigned char*) realloc((char*) net->buff, pkt_length +
 
168
                               NET_HEADER_SIZE + COMP_HEADER_SIZE)))
 
169
  {
 
170
    /* @todo: 1 and 2 codes are identical. */
 
171
    net->error= 1;
 
172
    net->last_errno= CR_OUT_OF_MEMORY;
 
173
    /* In the server the error is reported by MY_WME flag. */
 
174
    return(1);
 
175
  }
 
176
  net->buff=net->write_pos=buff;
 
177
  net->buff_end=buff+(net->max_packet= (uint32_t) pkt_length);
 
178
  return(0);
 
179
}
 
180
 
 
181
 
 
182
/**
 
183
   Check if there is any data to be read from the socket.
 
184
 
 
185
   @param sd   socket descriptor
 
186
 
 
187
   @retval
 
188
   0  No data to read
 
189
   @retval
 
190
   1  Data or EOF to read
 
191
   @retval
 
192
   -1   Don't know if data is ready or not
 
193
*/
 
194
 
 
195
static bool net_data_is_ready(int sd)
 
196
{
 
197
  struct pollfd ufds;
 
198
  int res;
 
199
 
 
200
  ufds.fd= sd;
 
201
  ufds.events= POLLIN | POLLPRI;
 
202
  if (!(res= poll(&ufds, 1, 0)))
 
203
    return 0;
 
204
  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
 
205
    return 0;
 
206
  return 1;
 
207
}
 
208
 
 
209
/**
 
210
   Remove unwanted characters from connection
 
211
   and check if disconnected.
 
212
 
 
213
   Read from socket until there is nothing more to read. Discard
 
214
   what is read.
 
215
 
 
216
   If there is anything when to read 'net_clear' is called this
 
217
   normally indicates an error in the protocol.
 
218
 
 
219
   When connection is properly closed (for TCP it means with
 
220
   a FIN packet), then select() considers a socket "ready to read",
 
221
   in the sense that there's EOF to read, but read() returns 0.
 
222
 
 
223
   @param net            NET handler
 
224
   @param clear_buffer           if <> 0, then clear all data from comm buff
 
225
*/
 
226
 
 
227
void net_clear(NET *net, bool clear_buffer)
 
228
{
 
229
  if (clear_buffer)
 
230
  {
 
231
    while (net_data_is_ready(net->vio->sd) > 0)
 
232
    {
 
233
      /* The socket is ready */
 
234
      if (vio_read(net->vio, net->buff,
 
235
                   (size_t) net->max_packet) <= 0)
 
236
      {
 
237
        net->error= 2;
 
238
        break;
 
239
      }
 
240
    }
 
241
  }
 
242
  net->pkt_nr=net->compress_pkt_nr=0;        /* Ready for new command */
 
243
  net->write_pos=net->buff;
 
244
  return;
 
245
}
 
246
 
 
247
 
 
248
/** Flush write_buffer if not empty. */
 
249
 
 
250
bool net_flush(NET *net)
 
251
{
 
252
  bool error= 0;
 
253
  if (net->buff != net->write_pos)
 
254
  {
 
255
    error=net_real_write(net, net->buff,
 
256
                         (size_t) (net->write_pos - net->buff)) ? 1 : 0;
 
257
    net->write_pos=net->buff;
 
258
  }
 
259
  /* Sync packet number if using compression */
 
260
  if (net->compress)
 
261
    net->pkt_nr=net->compress_pkt_nr;
 
262
  return(error);
 
263
}
 
264
 
 
265
 
 
266
/*****************************************************************************
 
267
 ** Write something to server/client buffer
 
268
 *****************************************************************************/
 
269
 
 
270
/**
 
271
   Write a logical packet with packet header.
 
272
 
 
273
   Format: Packet length (3 bytes), packet number(1 byte)
 
274
   When compression is used a 3 byte compression length is added
 
275
 
 
276
   @note
 
277
   If compression is used the original package is modified!
 
278
*/
 
279
 
 
280
bool
 
281
my_net_write(NET *net,const unsigned char *packet,size_t len)
 
282
{
 
283
  unsigned char buff[NET_HEADER_SIZE];
 
284
  if (unlikely(!net->vio)) /* nowhere to write */
 
285
    return 0;
 
286
  /*
 
287
    Big packets are handled by splitting them in packets of MAX_PACKET_LENGTH
 
288
    length. The last packet is always a packet that is < MAX_PACKET_LENGTH.
 
289
    (The last packet may even have a length of 0)
 
290
  */
 
291
  while (len >= MAX_PACKET_LENGTH)
 
292
  {
 
293
    const uint32_t z_size = MAX_PACKET_LENGTH;
 
294
    int3store(buff, z_size);
 
295
    buff[3]= (unsigned char) net->pkt_nr++;
 
296
    if (net_write_buff(net, buff, NET_HEADER_SIZE) ||
 
297
        net_write_buff(net, packet, z_size))
 
298
      return 1;
 
299
    packet += z_size;
 
300
    len-=     z_size;
 
301
  }
 
302
  /* Write last packet */
 
303
  int3store(buff,len);
 
304
  buff[3]= (unsigned char) net->pkt_nr++;
 
305
  if (net_write_buff(net, buff, NET_HEADER_SIZE))
 
306
    return 1;
 
307
  return net_write_buff(net,packet,len) ? 1 : 0;
 
308
}
 
309
 
 
310
/**
 
311
   Send a command to the server.
 
312
 
 
313
   The reason for having both header and packet is so that libdrizzle
 
314
   can easy add a header to a special command (like prepared statements)
 
315
   without having to re-alloc the string.
 
316
 
 
317
   As the command is part of the first data packet, we have to do some data
 
318
   juggling to put the command in there, without having to create a new
 
319
   packet.
 
320
 
 
321
   This function will split big packets into sub-packets if needed.
 
322
   (Each sub packet can only be 2^24 bytes)
 
323
 
 
324
   @param net        NET handler
 
325
   @param command    Command in MySQL server (enum enum_server_command)
 
326
   @param header    Header to write after command
 
327
   @param head_len    Length of header
 
328
   @param packet    Query or parameter to query
 
329
   @param len        Length of packet
 
330
 
 
331
   @retval
 
332
   0    ok
 
333
   @retval
 
334
   1    error
 
335
*/
 
336
 
 
337
bool
 
338
net_write_command(NET *net,unsigned char command,
 
339
                  const unsigned char *header, size_t head_len,
 
340
                  const unsigned char *packet, size_t len)
 
341
{
 
342
  uint32_t length=len+1+head_len;            /* 1 extra byte for command */
 
343
  unsigned char buff[NET_HEADER_SIZE+1];
 
344
  uint header_size=NET_HEADER_SIZE+1;
 
345
 
 
346
  buff[4]=command;                /* For first packet */
 
347
 
 
348
  if (length >= MAX_PACKET_LENGTH)
 
349
  {
 
350
    /* Take into account that we have the command in the first header */
 
351
    len= MAX_PACKET_LENGTH - 1 - head_len;
 
352
    do
 
353
    {
 
354
      int3store(buff, MAX_PACKET_LENGTH);
 
355
      buff[3]= (unsigned char) net->pkt_nr++;
 
356
      if (net_write_buff(net, buff, header_size) ||
 
357
          net_write_buff(net, header, head_len) ||
 
358
          net_write_buff(net, packet, len))
 
359
        return(1);
 
360
      packet+= len;
 
361
      length-= MAX_PACKET_LENGTH;
 
362
      len= MAX_PACKET_LENGTH;
 
363
      head_len= 0;
 
364
      header_size= NET_HEADER_SIZE;
 
365
    } while (length >= MAX_PACKET_LENGTH);
 
366
    len=length;                    /* Data left to be written */
 
367
  }
 
368
  int3store(buff,length);
 
369
  buff[3]= (unsigned char) net->pkt_nr++;
 
370
  return((net_write_buff(net, buff, header_size) ||
 
371
          (head_len && net_write_buff(net, header, head_len)) ||
 
372
          net_write_buff(net, packet, len) || net_flush(net)) ? 1 : 0 );
 
373
}
 
374
 
 
375
/**
 
376
   Caching the data in a local buffer before sending it.
 
377
 
 
378
   Fill up net->buffer and send it to the client when full.
 
379
 
 
380
   If the rest of the to-be-sent-packet is bigger than buffer,
 
381
   send it in one big block (to avoid copying to internal buffer).
 
382
   If not, copy the rest of the data to the buffer and return without
 
383
   sending data.
 
384
 
 
385
   @param net        Network handler
 
386
   @param packet    Packet to send
 
387
   @param len        Length of packet
 
388
 
 
389
   @note
 
390
   The cached buffer can be sent as it is with 'net_flush()'.
 
391
   In this code we have to be careful to not send a packet longer than
 
392
   MAX_PACKET_LENGTH to net_real_write() if we are using the compressed
 
393
   protocol as we store the length of the compressed packet in 3 bytes.
 
394
 
 
395
   @retval
 
396
   0    ok
 
397
   @retval
 
398
   1
 
399
*/
 
400
 
 
401
static bool
 
402
net_write_buff(NET *net, const unsigned char *packet, uint32_t len)
 
403
{
 
404
  uint32_t left_length;
 
405
  if (net->compress && net->max_packet > MAX_PACKET_LENGTH)
 
406
    left_length= MAX_PACKET_LENGTH - (net->write_pos - net->buff);
 
407
  else
 
408
    left_length= (uint32_t) (net->buff_end - net->write_pos);
 
409
 
 
410
  if (len > left_length)
 
411
  {
 
412
    if (net->write_pos != net->buff)
 
413
    {
 
414
      /* Fill up already used packet and write it */
 
415
      memcpy(net->write_pos,packet,left_length);
 
416
      if (net_real_write(net, net->buff,
 
417
                         (size_t) (net->write_pos - net->buff) + left_length))
 
418
        return 1;
 
419
      net->write_pos= net->buff;
 
420
      packet+= left_length;
 
421
      len-= left_length;
 
422
    }
 
423
    if (net->compress)
 
424
    {
 
425
      /*
 
426
        We can't have bigger packets than 16M with compression
 
427
        Because the uncompressed length is stored in 3 bytes
 
428
      */
 
429
      left_length= MAX_PACKET_LENGTH;
 
430
      while (len > left_length)
 
431
      {
 
432
        if (net_real_write(net, packet, left_length))
 
433
          return 1;
 
434
        packet+= left_length;
 
435
        len-= left_length;
 
436
      }
 
437
    }
 
438
    if (len > net->max_packet)
 
439
      return net_real_write(net, packet, len) ? 1 : 0;
 
440
    /* Send out rest of the blocks as full sized blocks */
 
441
  }
 
442
  memcpy(net->write_pos,packet,len);
 
443
  net->write_pos+= len;
 
444
  return 0;
 
445
}
 
446
 
 
447
 
 
448
/**
 
449
   Read and write one packet using timeouts.
 
450
   If needed, the packet is compressed before sending.
 
451
 
 
452
   @todo
 
453
   - TODO is it needed to set this variable if we have no socket
 
454
*/
 
455
 
 
456
/*
 
457
  TODO: rewrite this in a manner to do non-block writes. If a write can not be made, and we are
 
458
  in the server, yield to another process and come back later.
 
459
*/
 
460
int
 
461
net_real_write(NET *net,const unsigned char *packet, size_t len)
 
462
{
 
463
  size_t length;
 
464
  const unsigned char *pos,*end;
 
465
  uint retry_count= 0;
 
466
 
 
467
  /* Backup of the original SO_RCVTIMEO timeout */
 
468
  struct timeval backtime;
 
469
  int error;
 
470
 
 
471
  if (net->error == 2)
 
472
    return(-1);                /* socket can't be used */
 
473
 
 
474
  net->reading_or_writing=2;
 
475
  if (net->compress)
 
476
  {
 
477
    size_t complen;
 
478
    unsigned char *b;
 
479
    const uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
 
480
    if (!(b= (unsigned char*) malloc(len + NET_HEADER_SIZE +
 
481
                             COMP_HEADER_SIZE)))
 
482
    {
 
483
      net->error= 2;
 
484
      net->last_errno= CR_OUT_OF_MEMORY;
 
485
      /* In the server, the error is reported by MY_WME flag. */
 
486
      net->reading_or_writing= 0;
 
487
      return(1);
 
488
    }
 
489
    memcpy(b+header_length,packet,len);
 
490
 
 
491
    complen= len * 120 / 100 + 12;
 
492
    unsigned char * compbuf= (unsigned char *) malloc(complen);
 
493
    if (compbuf != NULL)
 
494
    {
 
495
      uLongf tmp_complen= complen;
 
496
      int res= compress((Bytef*) compbuf, &tmp_complen,
 
497
                        (Bytef*) (b+header_length),
 
498
                        len);
 
499
      complen= tmp_complen;
 
500
 
 
501
      free(compbuf);
 
502
 
 
503
      if ((res != Z_OK) || (complen >= len))
 
504
        complen= 0;
 
505
      else
 
506
      {
 
507
        size_t tmplen= complen;
 
508
        complen= len;
 
509
        len= tmplen;
 
510
      }
 
511
    }
 
512
    else
 
513
    {
 
514
      complen=0;
 
515
    }
 
516
    int3store(&b[NET_HEADER_SIZE],complen);
 
517
    int3store(b,len);
 
518
    b[3]=(unsigned char) (net->compress_pkt_nr++);
 
519
    len+= header_length;
 
520
    packet= b;
 
521
  }
 
522
 
 
523
  /* Check for error, currently assert */
 
524
  if (net->write_timeout)
 
525
  {
 
526
    struct timeval waittime;
 
527
    socklen_t length;
 
528
 
 
529
    waittime.tv_sec= net->write_timeout;
 
530
    waittime.tv_usec= 0;
 
531
 
 
532
    memset(&backtime, 0, sizeof(struct timeval));
 
533
    length= sizeof(struct timeval);
 
534
    error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
 
535
                      &backtime, &length);
 
536
    if (error != 0)
 
537
    {
 
538
      perror("getsockopt");
 
539
      assert(error == 0);
 
540
    }
 
541
    error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
 
542
                      &waittime, (socklen_t)sizeof(struct timeval));
 
543
    assert(error == 0);
 
544
  }
 
545
  pos= packet;
 
546
  end=pos+len;
 
547
  /* Loop until we have read everything */
 
548
  while (pos != end)
 
549
  {
 
550
    if ((long) (length= vio_write(net->vio,pos,(size_t) (end-pos))) <= 0)
 
551
    {
 
552
      const bool interrupted= vio_should_retry(net->vio);
 
553
      /*
 
554
        If we read 0, or we were interrupted this means that
 
555
        we need to switch to blocking mode and wait until the timeout
 
556
        on the socket kicks in.
 
557
      */
 
558
      if ((interrupted || length == 0))
 
559
      {
 
560
        bool old_mode;
 
561
 
 
562
        while (vio_blocking(net->vio, true, &old_mode) < 0)
 
563
        {
 
564
          if (vio_should_retry(net->vio) && retry_count++ < net->retry_count)
 
565
            continue;
 
566
          net->error= 2;                     /* Close socket */
 
567
          net->last_errno= CR_NET_PACKET_TOO_LARGE;
 
568
          goto end;
 
569
        }
 
570
        retry_count=0;
 
571
        continue;
 
572
      }
 
573
      else
 
574
      {
 
575
        if (retry_count++ < net->retry_count)
 
576
          continue;
 
577
      }
 
578
 
 
579
      if (vio_errno(net->vio) == EINTR)
 
580
      {
 
581
        continue;
 
582
      }
 
583
      net->error= 2;                /* Close socket */
 
584
      net->last_errno= (interrupted ? CR_NET_WRITE_INTERRUPTED :
 
585
                        CR_NET_ERROR_ON_WRITE);
 
586
      break;
 
587
    }
 
588
    pos+=length;
 
589
    update_statistics(thd_increment_bytes_sent(length));
 
590
  }
 
591
end:
 
592
  if ((net->compress) && (packet != NULL))
 
593
    free((char*) packet);
 
594
  net->reading_or_writing=0;
 
595
 
 
596
  if (net->write_timeout)
 
597
    error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
 
598
                      &backtime, (socklen_t)sizeof(struct timeval));
 
599
 
 
600
  return(((int) (pos != end)));
 
601
}
 
602
 
 
603
 
 
604
/**
 
605
   Reads one packet to net->buff + net->where_b.
 
606
   Long packets are handled by my_net_read().
 
607
   This function reallocates the net->buff buffer if necessary.
 
608
 
 
609
   @return
 
610
   Returns length of packet.
 
611
*/
 
612
 
 
613
static uint32_t
 
614
my_real_read(NET *net, size_t *complen)
 
615
{
 
616
  unsigned char *pos;
 
617
  size_t length;
 
618
  uint i,retry_count=0;
 
619
  uint32_t len=packet_error;
 
620
  uint32_t remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
 
621
                    NET_HEADER_SIZE);
 
622
  /* Backup of the original SO_RCVTIMEO timeout */
 
623
  struct timeval backtime;
 
624
  int error= 0;
 
625
 
 
626
  *complen = 0;
 
627
 
 
628
  net->reading_or_writing= 1;
 
629
  /* Read timeout is set in my_net_set_read_timeout */
 
630
 
 
631
  pos = net->buff + net->where_b;        /* net->packet -4 */
 
632
 
 
633
 
 
634
  /* Check for error, currently assert */
 
635
  if (net->read_timeout)
 
636
  {
 
637
    struct timeval waittime;
 
638
    socklen_t length;
 
639
 
 
640
    waittime.tv_sec= net->read_timeout;
 
641
    waittime.tv_usec= 0;
 
642
 
 
643
    memset(&backtime, 0, sizeof(struct timeval));
 
644
    length= sizeof(struct timeval);
 
645
    error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
 
646
                      &backtime, &length);
 
647
    if (error != 0)
 
648
    {
 
649
      perror("getsockopt");
 
650
      assert(error == 0);
 
651
    }
 
652
    error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
 
653
                      &waittime, (socklen_t)sizeof(struct timeval));
 
654
    assert(error == 0);
 
655
  }
 
656
 
 
657
  for (i= 0; i < 2 ; i++)
 
658
  {
 
659
    while (remain > 0)
 
660
    {
 
661
      /* First read is done with non blocking mode */
 
662
      if ((long) (length= vio_read(net->vio, pos, remain)) <= 0L)
 
663
      {
 
664
        const bool interrupted = vio_should_retry(net->vio);
 
665
 
 
666
        if (interrupted)
 
667
        {                    /* Probably in MIT threads */
 
668
          if (retry_count++ < net->retry_count)
 
669
            continue;
 
670
        }
 
671
        if (vio_errno(net->vio) == EINTR)
 
672
        {
 
673
          continue;
 
674
        }
 
675
        len= packet_error;
 
676
        net->error= 2;                /* Close socket */
 
677
        net->last_errno= (vio_was_interrupted(net->vio) ?
 
678
                          CR_NET_READ_INTERRUPTED :
 
679
                          CR_NET_READ_ERROR);
 
680
        ER(net->last_errno);
 
681
        goto end;
 
682
      }
 
683
      remain -= (uint32_t) length;
 
684
      pos+= length;
 
685
      update_statistics(thd_increment_bytes_received(length));
 
686
    }
 
687
    if (i == 0)
 
688
    {                    /* First parts is packet length */
 
689
      uint32_t helping;
 
690
 
 
691
      if (net->buff[net->where_b + 3] != (unsigned char) net->pkt_nr)
 
692
      {
 
693
        len= packet_error;
 
694
        /* Not a NET error on the client. XXX: why? */
 
695
        goto end;
 
696
      }
 
697
      net->compress_pkt_nr= ++net->pkt_nr;
 
698
      if (net->compress)
 
699
      {
 
700
        /*
 
701
          If the packet is compressed then complen > 0 and contains the
 
702
          number of bytes in the uncompressed packet
 
703
        */
 
704
        *complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
 
705
      }
 
706
 
 
707
      len=uint3korr(net->buff+net->where_b);
 
708
      if (!len)                /* End of big multi-packet */
 
709
        goto end;
 
710
      helping = max(len,*complen) + net->where_b;
 
711
      /* The necessary size of net->buff */
 
712
      if (helping >= net->max_packet)
 
713
      {
 
714
        if (net_realloc(net,helping))
 
715
        {
 
716
          len= packet_error;          /* Return error and close connection */
 
717
          goto end;
 
718
        }
 
719
      }
 
720
      pos=net->buff + net->where_b;
 
721
      remain = (uint32_t) len;
 
722
    }
 
723
  }
 
724
 
 
725
end:
 
726
  if  (net->read_timeout)
 
727
    error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
 
728
                      &backtime, (socklen_t)sizeof(struct timeval));
 
729
  assert(error == 0);
 
730
  net->reading_or_writing= 0;
 
731
 
 
732
  return(len);
 
733
}
 
734
 
 
735
 
 
736
/**
 
737
   Read a packet from the client/server and return it without the internal
 
738
   package header.
 
739
 
 
740
   If the packet is the first packet of a multi-packet packet
 
741
   (which is indicated by the length of the packet = 0xffffff) then
 
742
   all sub packets are read and concatenated.
 
743
 
 
744
   If the packet was compressed, its uncompressed and the length of the
 
745
   uncompressed packet is returned.
 
746
 
 
747
   @return
 
748
   The function returns the length of the found packet or packet_error.
 
749
   net->read_pos points to the read data.
 
750
*/
 
751
 
 
752
uint32_t
 
753
my_net_read(NET *net)
 
754
{
 
755
  size_t len, complen;
 
756
 
 
757
  if (!net->compress)
 
758
  {
 
759
    len = my_real_read(net,&complen);
 
760
    if (len == MAX_PACKET_LENGTH)
 
761
    {
 
762
      /* First packet of a multi-packet.  Concatenate the packets */
 
763
      uint32_t save_pos = net->where_b;
 
764
      size_t total_length= 0;
 
765
      do
 
766
      {
 
767
        net->where_b += len;
 
768
        total_length += len;
 
769
        len = my_real_read(net,&complen);
 
770
      } while (len == MAX_PACKET_LENGTH);
 
771
      if (len != packet_error)
 
772
        len+= total_length;
 
773
      net->where_b = save_pos;
 
774
    }
 
775
    net->read_pos = net->buff + net->where_b;
 
776
    if (len != packet_error)
 
777
      net->read_pos[len]=0;        /* Safeguard for drizzle_use_result */
 
778
    return len;
 
779
  }
 
780
  else
 
781
  {
 
782
    /* We are using the compressed protocol */
 
783
 
 
784
    uint32_t buf_length;
 
785
    uint32_t start_of_packet;
 
786
    uint32_t first_packet_offset;
 
787
    uint read_length, multi_byte_packet=0;
 
788
 
 
789
    if (net->remain_in_buf)
 
790
    {
 
791
      buf_length= net->buf_length;        /* Data left in old packet */
 
792
      first_packet_offset= start_of_packet= (net->buf_length -
 
793
                                             net->remain_in_buf);
 
794
      /* Restore the character that was overwritten by the end 0 */
 
795
      net->buff[start_of_packet]= net->save_char;
 
796
    }
 
797
    else
 
798
    {
 
799
      /* reuse buffer, as there is nothing in it that we need */
 
800
      buf_length= start_of_packet= first_packet_offset= 0;
 
801
    }
 
802
    for (;;)
 
803
    {
 
804
      uint32_t packet_len;
 
805
 
 
806
      if (buf_length - start_of_packet >= NET_HEADER_SIZE)
 
807
      {
 
808
        read_length = uint3korr(net->buff+start_of_packet);
 
809
        if (!read_length)
 
810
        {
 
811
          /* End of multi-byte packet */
 
812
          start_of_packet += NET_HEADER_SIZE;
 
813
          break;
 
814
        }
 
815
        if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
 
816
        {
 
817
          if (multi_byte_packet)
 
818
          {
 
819
            /* Remove packet header for second packet */
 
820
            memmove(net->buff + first_packet_offset + start_of_packet,
 
821
                    net->buff + first_packet_offset + start_of_packet +
 
822
                    NET_HEADER_SIZE,
 
823
                    buf_length - start_of_packet);
 
824
            start_of_packet += read_length;
 
825
            buf_length -= NET_HEADER_SIZE;
 
826
          }
 
827
          else
 
828
            start_of_packet+= read_length + NET_HEADER_SIZE;
 
829
 
 
830
          if (read_length != MAX_PACKET_LENGTH)    /* last package */
 
831
          {
 
832
            multi_byte_packet= 0;        /* No last zero len packet */
 
833
            break;
 
834
          }
 
835
          multi_byte_packet= NET_HEADER_SIZE;
 
836
          /* Move data down to read next data packet after current one */
 
837
          if (first_packet_offset)
 
838
          {
 
839
            memmove(net->buff,net->buff+first_packet_offset,
 
840
                    buf_length-first_packet_offset);
 
841
            buf_length-=first_packet_offset;
 
842
            start_of_packet -= first_packet_offset;
 
843
            first_packet_offset=0;
 
844
          }
 
845
          continue;
 
846
        }
 
847
      }
 
848
      /* Move data down to read next data packet after current one */
 
849
      if (first_packet_offset)
 
850
      {
 
851
        memmove(net->buff,net->buff+first_packet_offset,
 
852
                buf_length-first_packet_offset);
 
853
        buf_length-=first_packet_offset;
 
854
        start_of_packet -= first_packet_offset;
 
855
        first_packet_offset=0;
 
856
      }
 
857
 
 
858
      net->where_b=buf_length;
 
859
      if ((packet_len = my_real_read(net,&complen)) == packet_error)
 
860
        return packet_error;
 
861
 
 
862
      if (complen)
 
863
      {
 
864
        unsigned char * compbuf= (unsigned char *) malloc(complen);
 
865
        if (compbuf != NULL)
 
866
        {
 
867
          uLongf tmp_complen= complen;
 
868
          int error= uncompress((Bytef*) compbuf, &tmp_complen,
 
869
                                (Bytef*) (net->buff + net->where_b),
 
870
                                (uLong)packet_len);
 
871
          complen= tmp_complen;
 
872
 
 
873
          if (error != Z_OK)
 
874
          {
 
875
            net->error= 2;            /* caller will close socket */
 
876
            net->last_errno= CR_NET_UNCOMPRESS_ERROR;
 
877
          }
 
878
          else
 
879
          {
 
880
            memcpy((net->buff + net->where_b), compbuf, complen);
 
881
          }
 
882
          free(compbuf);
 
883
        }
 
884
      }
 
885
      else
 
886
        complen= packet_len;
 
887
 
 
888
    }
 
889
    buf_length+= complen;
 
890
 
 
891
    net->read_pos=      net->buff+ first_packet_offset + NET_HEADER_SIZE;
 
892
    net->buf_length=    buf_length;
 
893
    net->remain_in_buf= (uint32_t) (buf_length - start_of_packet);
 
894
    len = ((uint32_t) (start_of_packet - first_packet_offset) - NET_HEADER_SIZE -
 
895
           multi_byte_packet);
 
896
    net->save_char= net->read_pos[len];    /* Must be saved */
 
897
    net->read_pos[len]=0;        /* Safeguard for drizzle_use_result */
 
898
  }
 
899
  return len;
 
900
  }
 
901
 
 
902
 
 
903
void my_net_set_read_timeout(NET *net, uint timeout)
 
904
{
 
905
  net->read_timeout= timeout;
 
906
  if (net->vio)
 
907
    vio_timeout(net->vio, 0, timeout);
 
908
  return;
 
909
}
 
910
 
 
911
 
 
912
void my_net_set_write_timeout(NET *net, uint timeout)
 
913
{
 
914
  net->write_timeout= timeout;
 
915
  if (net->vio)
 
916
    vio_timeout(net->vio, 1, timeout);
 
917
  return;
 
918
}
 
919
/**
 
920
  Clear possible error state of struct NET
 
921
 
 
922
  @param net  clear the state of the argument
 
923
*/
 
924
 
 
925
void net_clear_error(NET *net)
 
926
{
 
927
  net->last_errno= 0;
 
928
  net->last_error[0]= '\0';
 
929
  strcpy(net->sqlstate, sqlstate_get_not_error());
 
930
}
 
931