~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/net_serv.c

  • Committer: Stewart Smith
  • Date: 2008-07-13 06:56:15 UTC
  • mto: (210.1.1 drizzle)
  • mto: This revision was merged to the branch mainline in revision 211.
  • Revision ID: stewart@flamingspork.com-20080713065615-vzok75kgnnviokl9
Move MD5() into a UDF

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