~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/net_serv.c

  • Committer: Brian Aker
  • Date: 2008-07-13 21:20:24 UTC
  • Revision ID: brian@tangent.org-20080713212024-o6263c1vha7yxdeu
More bool removal. More cow bell!

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