~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/net_serv.c

  • Committer: Jay Pipes
  • Date: 2008-07-17 17:54:00 UTC
  • mto: This revision was merged to the branch mainline in revision 182.
  • Revision ID: jay@mysql.com-20080717175400-xm2aazihjra8mdzq
Removal of DBUG from libdrizzle/ - Round 2

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