~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/net_serv.cc

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

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