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