~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/net_serv.c

  • Committer: Brian Aker
  • Date: 2008-10-12 01:59:02 UTC
  • Revision ID: brian@tangent.org-20081012015902-prhy6wsimdqr28om
Dead code around unsigned (first pass)

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