~drizzle-trunk/drizzle/development

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