~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/drizzle_protocol/net_serv.cc

  • Committer: Brian Aker
  • Date: 2009-12-29 01:38:38 UTC
  • mfrom: (1251.1.1 drizzle)
  • Revision ID: brian@gaz-20091229013838-03kb2z5xbqw03ddt
Merge of Diego fix.

Show diffs side-by-side

added added

removed removed

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