~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/net_serv.c

  • Committer: Jay Pipes
  • Date: 2008-08-25 16:51:53 UTC
  • mfrom: (370.1.1 tests-fixups)
  • Revision ID: jay@mysql.com-20080825165153-vq7wmr23x1yr503j
Merge from Arjen.  Fixes some stuff in the test suite

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
 
1
/* Copyright (C) 2000 MySQL AB
 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
/*
 
17
  HFTODO this must be hidden if we don't want client capabilities in 
 
18
  embedded library
19
19
 */
20
 
 
21
20
#include <drizzled/global.h>
22
 
#include "libdrizzle.h"
23
 
#include <libdrizzle/errmsg.h>
 
21
#include <drizzle.h>
 
22
#include <drizzled/error.h>
 
23
#include <mysys/my_sys.h>
24
24
#include <vio/violite.h>
25
25
#include <signal.h>
26
26
#include <errno.h>
27
27
#include <sys/poll.h>
28
 
#include <zlib.h>
29
28
 
30
29
/*
31
30
  The following handles the differences when this is linked between the
40
39
#define update_statistics(A)
41
40
#define thd_increment_bytes_sent(N)
42
41
 
43
 
#define TEST_BLOCKING        8
 
42
#define TEST_BLOCKING           8
44
43
#define MAX_PACKET_LENGTH (256L*256L*256L-1)
45
 
#define MIN_COMPRESS_LENGTH             50      /* Don't compress small bl. */
46
44
 
47
45
static bool net_write_buff(NET *net, const unsigned char *packet, uint32_t len);
48
46
 
52
50
bool my_net_init(NET *net, Vio* vio)
53
51
{
54
52
  net->vio = vio;
55
 
  my_net_local_init(net);            /* Set some limits */
56
 
  if (!(net->buff=(uchar*) malloc((size_t) net->max_packet+
57
 
                                  NET_HEADER_SIZE + COMP_HEADER_SIZE)))
 
53
  my_net_local_init(net);                       /* Set some limits */
 
54
  if (!(net->buff=(uchar*) my_malloc((size_t) net->max_packet+
 
55
                                     NET_HEADER_SIZE + COMP_HEADER_SIZE,
 
56
                                     MYF(MY_WME))))
58
57
    return(1);
59
58
  net->buff_end=net->buff+net->max_packet;
60
59
  net->error=0; net->return_status=0;
66
65
  net->last_errno=0;
67
66
  net->unused= 0;
68
67
 
69
 
  if (vio != 0)                    /* If real connection */
 
68
  if (vio != 0)                                 /* If real connection */
70
69
  {
71
 
    net->fd  = vio_fd(vio);            /* For perl DBI/DBD */
 
70
    net->fd  = vio_fd(vio);                     /* For perl DBI/DBD */
72
71
    vio_fastsend(vio);
73
72
  }
74
73
  return(0);
77
76
 
78
77
void net_end(NET *net)
79
78
{
80
 
  if (net->buff != NULL)
81
 
    free(net->buff);
 
79
  my_free(net->buff,MYF(MY_ALLOW_ZERO_PTR));
82
80
  net->buff=0;
83
81
  return;
84
82
}
95
93
  {
96
94
    /* @todo: 1 and 2 codes are identical. */
97
95
    net->error= 1;
98
 
    net->last_errno= CR_NET_PACKET_TOO_LARGE;
 
96
    net->last_errno= ER_NET_PACKET_TOO_LARGE;
99
97
    return(1);
100
98
  }
101
 
  pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
 
99
  pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1); 
102
100
  /*
103
101
    We must allocate some extra bytes for the end 0 and to be able to
104
102
    read big compressed blocks
105
103
  */
106
 
  if (!(buff= (uchar*) realloc((char*) net->buff, pkt_length +
107
 
                               NET_HEADER_SIZE + COMP_HEADER_SIZE)))
 
104
  if (!(buff= (uchar*) my_realloc((char*) net->buff, pkt_length +
 
105
                                  NET_HEADER_SIZE + COMP_HEADER_SIZE,
 
106
                                  MYF(MY_WME))))
108
107
  {
109
108
    /* @todo: 1 and 2 codes are identical. */
110
109
    net->error= 1;
111
 
    net->last_errno= CR_OUT_OF_MEMORY;
 
110
    net->last_errno= ER_OUT_OF_RESOURCES;
112
111
    /* In the server the error is reported by MY_WME flag. */
113
112
    return(1);
114
113
  }
119
118
 
120
119
 
121
120
/**
122
 
   Check if there is any data to be read from the socket.
123
 
 
124
 
   @param sd   socket descriptor
125
 
 
126
 
   @retval
127
 
   0  No data to read
128
 
   @retval
129
 
   1  Data or EOF to read
130
 
   @retval
131
 
   -1   Don't know if data is ready or not
 
121
  Check if there is any data to be read from the socket.
 
122
 
 
123
  @param sd   socket descriptor
 
124
 
 
125
  @retval
 
126
    0  No data to read
 
127
  @retval
 
128
    1  Data or EOF to read
 
129
  @retval
 
130
    -1   Don't know if data is ready or not
132
131
*/
133
132
 
134
133
static bool net_data_is_ready(int sd)
146
145
}
147
146
 
148
147
/**
149
 
   Remove unwanted characters from connection
150
 
   and check if disconnected.
151
 
 
152
 
   Read from socket until there is nothing more to read. Discard
153
 
   what is read.
154
 
 
155
 
   If there is anything when to read 'net_clear' is called this
156
 
   normally indicates an error in the protocol.
157
 
 
158
 
   When connection is properly closed (for TCP it means with
159
 
   a FIN packet), then select() considers a socket "ready to read",
160
 
   in the sense that there's EOF to read, but read() returns 0.
161
 
 
162
 
   @param net            NET handler
163
 
   @param clear_buffer           if <> 0, then clear all data from comm buff
 
148
  Remove unwanted characters from connection
 
149
  and check if disconnected.
 
150
 
 
151
    Read from socket until there is nothing more to read. Discard
 
152
    what is read.
 
153
 
 
154
    If there is anything when to read 'net_clear' is called this
 
155
    normally indicates an error in the protocol.
 
156
 
 
157
    When connection is properly closed (for TCP it means with
 
158
    a FIN packet), then select() considers a socket "ready to read",
 
159
    in the sense that there's EOF to read, but read() returns 0.
 
160
 
 
161
  @param net                    NET handler
 
162
  @param clear_buffer           if <> 0, then clear all data from comm buff
164
163
*/
165
164
 
166
165
void net_clear(NET *net, bool clear_buffer)
171
170
    {
172
171
      /* The socket is ready */
173
172
      if (vio_read(net->vio, net->buff,
174
 
                   (size_t) net->max_packet) <= 0)
 
173
                                  (size_t) net->max_packet) <= 0)
175
174
      {
176
175
        net->error= 2;
177
176
        break;
178
177
      }
179
178
    }
180
179
  }
181
 
  net->pkt_nr=net->compress_pkt_nr=0;        /* Ready for new command */
 
180
  net->pkt_nr=net->compress_pkt_nr=0;           /* Ready for new command */
182
181
  net->write_pos=net->buff;
183
182
  return;
184
183
}
192
191
  if (net->buff != net->write_pos)
193
192
  {
194
193
    error=test(net_real_write(net, net->buff,
195
 
                              (size_t) (net->write_pos - net->buff)));
 
194
                              (size_t) (net->write_pos - net->buff)));
196
195
    net->write_pos=net->buff;
197
196
  }
198
197
  /* Sync packet number if using compression */
203
202
 
204
203
 
205
204
/*****************************************************************************
206
 
 ** Write something to server/client buffer
207
 
 *****************************************************************************/
 
205
** Write something to server/client buffer
 
206
*****************************************************************************/
208
207
 
209
208
/**
210
 
   Write a logical packet with packet header.
211
 
 
212
 
   Format: Packet length (3 bytes), packet number(1 byte)
213
 
   When compression is used a 3 byte compression length is added
214
 
 
215
 
   @note
216
 
   If compression is used the original package is modified!
 
209
  Write a logical packet with packet header.
 
210
 
 
211
  Format: Packet length (3 bytes), packet number(1 byte)
 
212
  When compression is used a 3 byte compression length is added
 
213
 
 
214
  @note
 
215
    If compression is used the original package is modified!
217
216
*/
218
217
 
219
218
bool
233
232
    int3store(buff, z_size);
234
233
    buff[3]= (uchar) net->pkt_nr++;
235
234
    if (net_write_buff(net, buff, NET_HEADER_SIZE) ||
236
 
        net_write_buff(net, packet, z_size))
 
235
        net_write_buff(net, packet, z_size))
237
236
      return 1;
238
237
    packet += z_size;
239
238
    len-=     z_size;
247
246
}
248
247
 
249
248
/**
250
 
   Send a command to the server.
251
 
 
252
 
   The reason for having both header and packet is so that libdrizzle
253
 
   can easy add a header to a special command (like prepared statements)
254
 
   without having to re-alloc the string.
255
 
 
256
 
   As the command is part of the first data packet, we have to do some data
257
 
   juggling to put the command in there, without having to create a new
258
 
   packet.
259
 
 
260
 
   This function will split big packets into sub-packets if needed.
261
 
   (Each sub packet can only be 2^24 bytes)
262
 
 
263
 
   @param net        NET handler
264
 
   @param command    Command in MySQL server (enum enum_server_command)
265
 
   @param header    Header to write after command
266
 
   @param head_len    Length of header
267
 
   @param packet    Query or parameter to query
268
 
   @param len        Length of packet
269
 
 
270
 
   @retval
271
 
   0    ok
272
 
   @retval
273
 
   1    error
 
249
  Send a command to the server.
 
250
 
 
251
    The reason for having both header and packet is so that libdrizzle
 
252
    can easy add a header to a special command (like prepared statements)
 
253
    without having to re-alloc the string.
 
254
 
 
255
    As the command is part of the first data packet, we have to do some data
 
256
    juggling to put the command in there, without having to create a new
 
257
    packet.
 
258
  
 
259
    This function will split big packets into sub-packets if needed.
 
260
    (Each sub packet can only be 2^24 bytes)
 
261
 
 
262
  @param net            NET handler
 
263
  @param command        Command in MySQL server (enum enum_server_command)
 
264
  @param header Header to write after command
 
265
  @param head_len       Length of header
 
266
  @param packet Query or parameter to query
 
267
  @param len            Length of packet
 
268
 
 
269
  @retval
 
270
    0   ok
 
271
  @retval
 
272
    1   error
274
273
*/
275
274
 
276
275
bool
277
276
net_write_command(NET *net,uchar command,
278
 
                  const uchar *header, size_t head_len,
279
 
                  const uchar *packet, size_t len)
 
277
                  const uchar *header, size_t head_len,
 
278
                  const uchar *packet, size_t len)
280
279
{
281
 
  uint32_t length=len+1+head_len;            /* 1 extra byte for command */
 
280
  uint32_t length=len+1+head_len;                       /* 1 extra byte for command */
282
281
  uchar buff[NET_HEADER_SIZE+1];
283
282
  uint header_size=NET_HEADER_SIZE+1;
284
283
 
285
 
  buff[4]=command;                /* For first packet */
 
284
  buff[4]=command;                              /* For first packet */
286
285
 
287
286
  if (length >= MAX_PACKET_LENGTH)
288
287
  {
293
292
      int3store(buff, MAX_PACKET_LENGTH);
294
293
      buff[3]= (uchar) net->pkt_nr++;
295
294
      if (net_write_buff(net, buff, header_size) ||
296
 
          net_write_buff(net, header, head_len) ||
297
 
          net_write_buff(net, packet, len))
298
 
        return(1);
 
295
          net_write_buff(net, header, head_len) ||
 
296
          net_write_buff(net, packet, len))
 
297
        return(1);
299
298
      packet+= len;
300
299
      length-= MAX_PACKET_LENGTH;
301
300
      len= MAX_PACKET_LENGTH;
302
301
      head_len= 0;
303
302
      header_size= NET_HEADER_SIZE;
304
303
    } while (length >= MAX_PACKET_LENGTH);
305
 
    len=length;                    /* Data left to be written */
 
304
    len=length;                                 /* Data left to be written */
306
305
  }
307
306
  int3store(buff,length);
308
307
  buff[3]= (uchar) net->pkt_nr++;
309
308
  return(test(net_write_buff(net, buff, header_size) ||
310
 
              (head_len && net_write_buff(net, header, head_len)) ||
311
 
              net_write_buff(net, packet, len) || net_flush(net)));
 
309
                   (head_len && net_write_buff(net, header, head_len)) ||
 
310
                   net_write_buff(net, packet, len) || net_flush(net)));
312
311
}
313
312
 
314
313
/**
315
 
   Caching the data in a local buffer before sending it.
 
314
  Caching the data in a local buffer before sending it.
316
315
 
317
316
   Fill up net->buffer and send it to the client when full.
318
317
 
319
 
   If the rest of the to-be-sent-packet is bigger than buffer,
320
 
   send it in one big block (to avoid copying to internal buffer).
321
 
   If not, copy the rest of the data to the buffer and return without
322
 
   sending data.
323
 
 
324
 
   @param net        Network handler
325
 
   @param packet    Packet to send
326
 
   @param len        Length of packet
327
 
 
328
 
   @note
329
 
   The cached buffer can be sent as it is with 'net_flush()'.
330
 
   In this code we have to be careful to not send a packet longer than
331
 
   MAX_PACKET_LENGTH to net_real_write() if we are using the compressed
332
 
   protocol as we store the length of the compressed packet in 3 bytes.
333
 
 
334
 
   @retval
335
 
   0    ok
336
 
   @retval
337
 
   1
 
318
    If the rest of the to-be-sent-packet is bigger than buffer,
 
319
    send it in one big block (to avoid copying to internal buffer).
 
320
    If not, copy the rest of the data to the buffer and return without
 
321
    sending data.
 
322
 
 
323
  @param net            Network handler
 
324
  @param packet Packet to send
 
325
  @param len            Length of packet
 
326
 
 
327
  @note
 
328
    The cached buffer can be sent as it is with 'net_flush()'.
 
329
    In this code we have to be careful to not send a packet longer than
 
330
    MAX_PACKET_LENGTH to net_real_write() if we are using the compressed
 
331
    protocol as we store the length of the compressed packet in 3 bytes.
 
332
 
 
333
  @retval
 
334
    0   ok
 
335
  @retval
 
336
    1
338
337
*/
339
338
 
340
339
static bool
352
351
    {
353
352
      /* Fill up already used packet and write it */
354
353
      memcpy(net->write_pos,packet,left_length);
355
 
      if (net_real_write(net, net->buff,
356
 
                         (size_t) (net->write_pos - net->buff) + left_length))
357
 
        return 1;
 
354
      if (net_real_write(net, net->buff, 
 
355
                         (size_t) (net->write_pos - net->buff) + left_length))
 
356
        return 1;
358
357
      net->write_pos= net->buff;
359
358
      packet+= left_length;
360
359
      len-= left_length;
362
361
    if (net->compress)
363
362
    {
364
363
      /*
365
 
        We can't have bigger packets than 16M with compression
366
 
        Because the uncompressed length is stored in 3 bytes
 
364
        We can't have bigger packets than 16M with compression
 
365
        Because the uncompressed length is stored in 3 bytes
367
366
      */
368
367
      left_length= MAX_PACKET_LENGTH;
369
368
      while (len > left_length)
370
369
      {
371
 
        if (net_real_write(net, packet, left_length))
372
 
          return 1;
373
 
        packet+= left_length;
374
 
        len-= left_length;
 
370
        if (net_real_write(net, packet, left_length))
 
371
          return 1;
 
372
        packet+= left_length;
 
373
        len-= left_length;
375
374
      }
376
375
    }
377
376
    if (len > net->max_packet)
385
384
 
386
385
 
387
386
/**
388
 
   Read and write one packet using timeouts.
389
 
   If needed, the packet is compressed before sending.
 
387
  Read and write one packet using timeouts.
 
388
  If needed, the packet is compressed before sending.
390
389
 
391
 
   @todo
392
 
   - TODO is it needed to set this variable if we have no socket
 
390
  @todo
 
391
    - TODO is it needed to set this variable if we have no socket
393
392
*/
394
393
 
395
394
/*
408
407
  int error;
409
408
 
410
409
  if (net->error == 2)
411
 
    return(-1);                /* socket can't be used */
 
410
    return(-1);                         /* socket can't be used */
412
411
 
413
412
  net->reading_or_writing=2;
414
413
  if (net->compress)
416
415
    size_t complen;
417
416
    uchar *b;
418
417
    const uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
419
 
    if (!(b= (uchar*) malloc(len + NET_HEADER_SIZE +
420
 
                             COMP_HEADER_SIZE)))
 
418
    if (!(b= (uchar*) my_malloc(len + NET_HEADER_SIZE +
 
419
                                COMP_HEADER_SIZE, MYF(MY_WME))))
421
420
    {
422
421
      net->error= 2;
423
 
      net->last_errno= CR_OUT_OF_MEMORY;
 
422
      net->last_errno= ER_OUT_OF_RESOURCES;
424
423
      /* In the server, the error is reported by MY_WME flag. */
425
424
      net->reading_or_writing= 0;
426
425
      return(1);
427
426
    }
428
427
    memcpy(b+header_length,packet,len);
429
428
 
430
 
    complen= len * 120 / 100 + 12;
431
 
    unsigned char * compbuf= (unsigned char *) malloc(complen);
432
 
    if (compbuf != NULL)
433
 
    {
434
 
      uLongf tmp_complen= complen;
435
 
      int res= compress((Bytef*) compbuf, &tmp_complen,
436
 
                        (Bytef*) (b+header_length),
437
 
                        len);
438
 
      complen= tmp_complen;
439
 
 
440
 
      free(compbuf);
441
 
 
442
 
      if ((res != Z_OK) || (complen >= len))
443
 
        complen= 0;
444
 
      else
445
 
      {
446
 
        size_t tmplen= complen;
447
 
        complen= len;
448
 
        len= tmplen;
449
 
      }
450
 
    }
451
 
    else
452
 
    {
 
429
    if (my_compress(b+header_length, &len, &complen))
453
430
      complen=0;
454
 
    }
455
431
    int3store(&b[NET_HEADER_SIZE],complen);
456
432
    int3store(b,len);
457
433
    b[3]=(uchar) (net->compress_pkt_nr++);
470
446
 
471
447
    memset(&backtime, 0, sizeof(struct timeval));
472
448
    length= sizeof(struct timeval);
473
 
    error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
 
449
    error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO, 
474
450
                      &backtime, &length);
475
451
    if (error != 0)
476
452
    {
477
453
      perror("getsockopt");
478
454
      assert(error == 0);
479
455
    }
480
 
    error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
 
456
    error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO, 
481
457
                      &waittime, (socklen_t)sizeof(struct timeval));
482
458
    assert(error == 0);
483
459
  }
489
465
    if ((long) (length= vio_write(net->vio,pos,(size_t) (end-pos))) <= 0)
490
466
    {
491
467
      const bool interrupted= vio_should_retry(net->vio);
492
 
      /*
493
 
        If we read 0, or we were interrupted this means that
494
 
        we need to switch to blocking mode and wait until the timeout
 
468
      /* 
 
469
        If we read 0, or we were interrupted this means that 
 
470
        we need to switch to blocking mode and wait until the timeout 
495
471
        on the socket kicks in.
496
472
      */
497
473
      if ((interrupted || length == 0))
503
479
          if (vio_should_retry(net->vio) && retry_count++ < net->retry_count)
504
480
            continue;
505
481
          net->error= 2;                     /* Close socket */
506
 
          net->last_errno= CR_NET_PACKET_TOO_LARGE;
 
482
          net->last_errno= ER_NET_PACKET_TOO_LARGE;
507
483
          goto end;
508
484
        }
509
485
        retry_count=0;
514
490
        if (retry_count++ < net->retry_count)
515
491
          continue;
516
492
      }
517
 
 
 
493
      
518
494
      if (vio_errno(net->vio) == SOCKET_EINTR)
519
495
      {
520
496
        continue;
521
497
      }
522
 
      net->error= 2;                /* Close socket */
523
 
      net->last_errno= (interrupted ? CR_NET_WRITE_INTERRUPTED :
524
 
                        CR_NET_ERROR_ON_WRITE);
 
498
      net->error= 2;                            /* Close socket */
 
499
      net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED :
 
500
                        ER_NET_ERROR_ON_WRITE);
525
501
      break;
526
502
    }
527
503
    pos+=length;
528
504
    update_statistics(thd_increment_bytes_sent(length));
529
505
  }
530
 
end:
531
 
  if ((net->compress) && (packet != NULL))
532
 
    free((char*) packet);
 
506
 end:
 
507
  if (net->compress)
 
508
    my_free((char*) packet,MYF(0));
533
509
  net->reading_or_writing=0;
534
510
 
535
511
  if (net->write_timeout)
536
 
    error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
 
512
    error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO, 
537
513
                      &backtime, (socklen_t)sizeof(struct timeval));
538
514
 
539
515
  return(((int) (pos != end)));
541
517
 
542
518
 
543
519
/**
544
 
   Reads one packet to net->buff + net->where_b.
545
 
   Long packets are handled by my_net_read().
546
 
   This function reallocates the net->buff buffer if necessary.
 
520
  Reads one packet to net->buff + net->where_b.
 
521
  Long packets are handled by my_net_read().
 
522
  This function reallocates the net->buff buffer if necessary.
547
523
 
548
 
   @return
549
 
   Returns length of packet.
 
524
  @return
 
525
    Returns length of packet.
550
526
*/
551
527
 
552
528
static uint32_t
557
533
  uint i,retry_count=0;
558
534
  uint32_t len=packet_error;
559
535
  uint32_t remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
560
 
                    NET_HEADER_SIZE);
 
536
                  NET_HEADER_SIZE);
561
537
  /* Backup of the original SO_RCVTIMEO timeout */
562
538
  struct timeval backtime;
563
539
  int error= 0;
567
543
  net->reading_or_writing= 1;
568
544
  /* Read timeout is set in my_net_set_read_timeout */
569
545
 
570
 
  pos = net->buff + net->where_b;        /* net->packet -4 */
 
546
  pos = net->buff + net->where_b;               /* net->packet -4 */
571
547
 
572
548
 
573
549
  /* Check for error, currently assert */
581
557
 
582
558
    memset(&backtime, 0, sizeof(struct timeval));
583
559
    length= sizeof(struct timeval);
584
 
    error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
 
560
    error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO, 
585
561
                      &backtime, &length);
586
562
    if (error != 0)
587
563
    {
588
564
      perror("getsockopt");
589
565
      assert(error == 0);
590
566
    }
591
 
    error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
 
567
    error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO, 
592
568
                      &waittime, (socklen_t)sizeof(struct timeval));
593
569
    assert(error == 0);
594
570
  }
603
579
        const bool interrupted = vio_should_retry(net->vio);
604
580
 
605
581
        if (interrupted)
606
 
        {                    /* Probably in MIT threads */
 
582
        {                                       /* Probably in MIT threads */
607
583
          if (retry_count++ < net->retry_count)
608
584
            continue;
609
585
        }
612
588
          continue;
613
589
        }
614
590
        len= packet_error;
615
 
        net->error= 2;                /* Close socket */
 
591
        net->error= 2;                          /* Close socket */
616
592
        net->last_errno= (vio_was_interrupted(net->vio) ?
617
 
                          CR_NET_READ_INTERRUPTED :
618
 
                          CR_NET_READ_ERROR);
619
 
        ER(net->last_errno);
 
593
                          ER_NET_READ_INTERRUPTED :
 
594
                          ER_NET_READ_ERROR);
 
595
        my_error(net->last_errno, MYF(0));
620
596
        goto end;
621
597
      }
622
598
      remain -= (uint32_t) length;
624
600
      update_statistics(thd_increment_bytes_received(length));
625
601
    }
626
602
    if (i == 0)
627
 
    {                    /* First parts is packet length */
 
603
    {                                   /* First parts is packet length */
628
604
      uint32_t helping;
629
605
 
630
606
      if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr)
644
620
      }
645
621
 
646
622
      len=uint3korr(net->buff+net->where_b);
647
 
      if (!len)                /* End of big multi-packet */
 
623
      if (!len)                         /* End of big multi-packet */
648
624
        goto end;
649
625
      helping = max(len,*complen) + net->where_b;
650
626
      /* The necessary size of net->buff */
663
639
 
664
640
end:
665
641
  if  (net->read_timeout)
666
 
    error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
 
642
    error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO, 
667
643
                      &backtime, (socklen_t)sizeof(struct timeval));
668
644
  assert(error == 0);
669
645
  net->reading_or_writing= 0;
673
649
 
674
650
 
675
651
/**
676
 
   Read a packet from the client/server and return it without the internal
677
 
   package header.
678
 
 
679
 
   If the packet is the first packet of a multi-packet packet
680
 
   (which is indicated by the length of the packet = 0xffffff) then
681
 
   all sub packets are read and concatenated.
682
 
 
683
 
   If the packet was compressed, its uncompressed and the length of the
684
 
   uncompressed packet is returned.
685
 
 
686
 
   @return
687
 
   The function returns the length of the found packet or packet_error.
688
 
   net->read_pos points to the read data.
 
652
  Read a packet from the client/server and return it without the internal
 
653
  package header.
 
654
 
 
655
  If the packet is the first packet of a multi-packet packet
 
656
  (which is indicated by the length of the packet = 0xffffff) then
 
657
  all sub packets are read and concatenated.
 
658
 
 
659
  If the packet was compressed, its uncompressed and the length of the
 
660
  uncompressed packet is returned.
 
661
 
 
662
  @return
 
663
  The function returns the length of the found packet or packet_error.
 
664
  net->read_pos points to the read data.
689
665
*/
690
666
 
691
667
uint32_t
703
679
      size_t total_length= 0;
704
680
      do
705
681
      {
706
 
        net->where_b += len;
707
 
        total_length += len;
708
 
        len = my_real_read(net,&complen);
 
682
        net->where_b += len;
 
683
        total_length += len;
 
684
        len = my_real_read(net,&complen);
709
685
      } while (len == MAX_PACKET_LENGTH);
710
686
      if (len != packet_error)
711
 
        len+= total_length;
 
687
        len+= total_length;
712
688
      net->where_b = save_pos;
713
689
    }
714
690
    net->read_pos = net->buff + net->where_b;
715
691
    if (len != packet_error)
716
 
      net->read_pos[len]=0;        /* Safeguard for drizzle_use_result */
 
692
      net->read_pos[len]=0;             /* Safeguard for drizzle_use_result */
717
693
    return len;
718
694
  }
719
695
  else
727
703
 
728
704
    if (net->remain_in_buf)
729
705
    {
730
 
      buf_length= net->buf_length;        /* Data left in old packet */
 
706
      buf_length= net->buf_length;              /* Data left in old packet */
731
707
      first_packet_offset= start_of_packet= (net->buf_length -
732
 
                                             net->remain_in_buf);
 
708
                                             net->remain_in_buf);
733
709
      /* Restore the character that was overwritten by the end 0 */
734
710
      net->buff[start_of_packet]= net->save_char;
735
711
    }
744
720
 
745
721
      if (buf_length - start_of_packet >= NET_HEADER_SIZE)
746
722
      {
747
 
        read_length = uint3korr(net->buff+start_of_packet);
748
 
        if (!read_length)
749
 
        {
750
 
          /* End of multi-byte packet */
751
 
          start_of_packet += NET_HEADER_SIZE;
752
 
          break;
753
 
        }
754
 
        if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
755
 
        {
756
 
          if (multi_byte_packet)
757
 
          {
758
 
            /* Remove packet header for second packet */
759
 
            memmove(net->buff + first_packet_offset + start_of_packet,
760
 
                    net->buff + first_packet_offset + start_of_packet +
761
 
                    NET_HEADER_SIZE,
762
 
                    buf_length - start_of_packet);
763
 
            start_of_packet += read_length;
764
 
            buf_length -= NET_HEADER_SIZE;
765
 
          }
766
 
          else
767
 
            start_of_packet+= read_length + NET_HEADER_SIZE;
 
723
        read_length = uint3korr(net->buff+start_of_packet);
 
724
        if (!read_length)
 
725
        { 
 
726
          /* End of multi-byte packet */
 
727
          start_of_packet += NET_HEADER_SIZE;
 
728
          break;
 
729
        }
 
730
        if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
 
731
        {
 
732
          if (multi_byte_packet)
 
733
          {
 
734
            /* Remove packet header for second packet */
 
735
            memmove(net->buff + first_packet_offset + start_of_packet,
 
736
                    net->buff + first_packet_offset + start_of_packet +
 
737
                    NET_HEADER_SIZE,
 
738
                    buf_length - start_of_packet);
 
739
            start_of_packet += read_length;
 
740
            buf_length -= NET_HEADER_SIZE;
 
741
          }
 
742
          else
 
743
            start_of_packet+= read_length + NET_HEADER_SIZE;
768
744
 
769
 
          if (read_length != MAX_PACKET_LENGTH)    /* last package */
770
 
          {
771
 
            multi_byte_packet= 0;        /* No last zero len packet */
772
 
            break;
773
 
          }
774
 
          multi_byte_packet= NET_HEADER_SIZE;
775
 
          /* Move data down to read next data packet after current one */
776
 
          if (first_packet_offset)
777
 
          {
778
 
            memmove(net->buff,net->buff+first_packet_offset,
779
 
                    buf_length-first_packet_offset);
780
 
            buf_length-=first_packet_offset;
781
 
            start_of_packet -= first_packet_offset;
782
 
            first_packet_offset=0;
783
 
          }
784
 
          continue;
785
 
        }
 
745
          if (read_length != MAX_PACKET_LENGTH) /* last package */
 
746
          {
 
747
            multi_byte_packet= 0;               /* No last zero len packet */
 
748
            break;
 
749
          }
 
750
          multi_byte_packet= NET_HEADER_SIZE;
 
751
          /* Move data down to read next data packet after current one */
 
752
          if (first_packet_offset)
 
753
          {
 
754
            memmove(net->buff,net->buff+first_packet_offset,
 
755
                    buf_length-first_packet_offset);
 
756
            buf_length-=first_packet_offset;
 
757
            start_of_packet -= first_packet_offset;
 
758
            first_packet_offset=0;
 
759
          }
 
760
          continue;
 
761
        }
786
762
      }
787
763
      /* Move data down to read next data packet after current one */
788
764
      if (first_packet_offset)
789
765
      {
790
 
        memmove(net->buff,net->buff+first_packet_offset,
791
 
                buf_length-first_packet_offset);
792
 
        buf_length-=first_packet_offset;
793
 
        start_of_packet -= first_packet_offset;
794
 
        first_packet_offset=0;
 
766
        memmove(net->buff,net->buff+first_packet_offset,
 
767
                buf_length-first_packet_offset);
 
768
        buf_length-=first_packet_offset;
 
769
        start_of_packet -= first_packet_offset;
 
770
        first_packet_offset=0;
795
771
      }
796
772
 
797
773
      net->where_b=buf_length;
798
774
      if ((packet_len = my_real_read(net,&complen)) == packet_error)
799
 
        return packet_error;
800
 
 
801
 
      if (complen)
 
775
        return packet_error;
 
776
      if (my_uncompress(net->buff + net->where_b, packet_len,
 
777
                        &complen))
802
778
      {
803
 
        unsigned char * compbuf= (unsigned char *) malloc(complen);
804
 
        if (compbuf != NULL)
805
 
        {
806
 
          uLongf tmp_complen= complen;
807
 
          int error= uncompress((Bytef*) compbuf, &tmp_complen,
808
 
                                (Bytef*) (net->buff + net->where_b),
809
 
                                (uLong)packet_len);
810
 
          complen= tmp_complen;
811
 
 
812
 
          if (error != Z_OK)
813
 
          {
814
 
            net->error= 2;            /* caller will close socket */
815
 
            net->last_errno= CR_NET_UNCOMPRESS_ERROR;
816
 
          }
817
 
          else
818
 
          {
819
 
            memcpy((net->buff + net->where_b), compbuf, complen);
820
 
          }
821
 
          free(compbuf);
822
 
        }
 
779
        net->error= 2;                  /* caller will close socket */
 
780
        net->last_errno= ER_NET_UNCOMPRESS_ERROR;
 
781
        return packet_error;
823
782
      }
824
 
      else
825
 
        complen= packet_len;
826
 
 
 
783
      buf_length+= complen;
827
784
    }
828
 
    buf_length+= complen;
829
785
 
830
786
    net->read_pos=      net->buff+ first_packet_offset + NET_HEADER_SIZE;
831
787
    net->buf_length=    buf_length;
832
788
    net->remain_in_buf= (uint32_t) (buf_length - start_of_packet);
833
789
    len = ((uint32_t) (start_of_packet - first_packet_offset) - NET_HEADER_SIZE -
834
790
           multi_byte_packet);
835
 
    net->save_char= net->read_pos[len];    /* Must be saved */
836
 
    net->read_pos[len]=0;        /* Safeguard for drizzle_use_result */
 
791
    net->save_char= net->read_pos[len]; /* Must be saved */
 
792
    net->read_pos[len]=0;               /* Safeguard for drizzle_use_result */
837
793
  }
838
794
  return len;
839
 
  }
 
795
}
840
796
 
841
797
 
842
798
void my_net_set_read_timeout(NET *net, uint timeout)