~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/net_serv.c

MergingĀ mainline

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