1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems, Inc.
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.
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.
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
21
#include <drizzled/global.h>
22
#include "libdrizzle.h"
23
#include <libdrizzle/errmsg.h>
24
#include <vio/violite.h>
31
The following handles the differences when this is linked between the
32
client and the server.
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.
40
#define update_statistics(A)
41
#define thd_increment_bytes_sent(N)
43
#define TEST_BLOCKING 8
44
#define MAX_PACKET_LENGTH (256L*256L*256L-1)
45
#define MIN_COMPRESS_LENGTH 50 /* Don't compress small bl. */
47
static bool net_write_buff(NET *net, const unsigned char *packet, uint32_t len);
50
/** Init with packet info. */
52
bool my_net_init(NET *net, Vio* vio)
55
my_net_local_init(net); /* Set some limits */
56
if (!(net->buff=(uchar*) malloc((size_t) net->max_packet+
57
NET_HEADER_SIZE + COMP_HEADER_SIZE)))
59
net->buff_end=net->buff+net->max_packet;
60
net->error=0; net->return_status=0;
61
net->pkt_nr=net->compress_pkt_nr=0;
62
net->write_pos=net->read_pos = net->buff;
64
net->compress=0; net->reading_or_writing=0;
65
net->where_b = net->remain_in_buf=0;
69
if (vio != 0) /* If real connection */
71
net->fd = vio_fd(vio); /* For perl DBI/DBD */
77
bool net_init_sock(NET * net, int sock, int flags)
80
Vio *vio_tmp= vio_new(sock, VIO_TYPE_TCPIP, flags);
84
if (my_net_init(net, vio_tmp))
86
/* Only delete the temporary vio if we didn't already attach it to the
89
if (vio_tmp && (net->vio != vio_tmp))
93
(void) shutdown(sock, SHUT_RDWR);
101
void net_end(NET *net)
103
if (net->buff != NULL)
109
void net_close(NET *net)
111
if (net->vio != NULL)
113
vio_delete(net->vio);
118
bool net_peer_addr(NET *net, char *buf, uint16_t *port, size_t buflen)
120
return vio_peer_addr(net->vio, buf, port, buflen);
123
void net_keepalive(NET *net, bool flag)
125
vio_keepalive(net->vio, flag);
128
int net_get_sd(NET *net)
133
bool net_should_close(NET *net)
135
return net->error || (net->vio == 0);
138
bool net_more_data(NET *net)
140
return (net->vio == 0 || net->vio->read_pos < net->vio->read_end);
143
/** Realloc the packet buffer. */
145
bool net_realloc(NET *net, size_t length)
150
if (length >= net->max_packet_size)
152
/* @todo: 1 and 2 codes are identical. */
154
net->last_errno= CR_NET_PACKET_TOO_LARGE;
157
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
159
We must allocate some extra bytes for the end 0 and to be able to
160
read big compressed blocks
162
if (!(buff= (uchar*) realloc((char*) net->buff, pkt_length +
163
NET_HEADER_SIZE + COMP_HEADER_SIZE)))
165
/* @todo: 1 and 2 codes are identical. */
167
net->last_errno= CR_OUT_OF_MEMORY;
168
/* In the server the error is reported by MY_WME flag. */
171
net->buff=net->write_pos=buff;
172
net->buff_end=buff+(net->max_packet= (uint32_t) pkt_length);
178
Check if there is any data to be read from the socket.
180
@param sd socket descriptor
185
1 Data or EOF to read
187
-1 Don't know if data is ready or not
190
static bool net_data_is_ready(int sd)
196
ufds.events= POLLIN | POLLPRI;
197
if (!(res= poll(&ufds, 1, 0)))
199
if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
205
Remove unwanted characters from connection
206
and check if disconnected.
208
Read from socket until there is nothing more to read. Discard
211
If there is anything when to read 'net_clear' is called this
212
normally indicates an error in the protocol.
214
When connection is properly closed (for TCP it means with
215
a FIN packet), then select() considers a socket "ready to read",
216
in the sense that there's EOF to read, but read() returns 0.
218
@param net NET handler
219
@param clear_buffer if <> 0, then clear all data from comm buff
222
void net_clear(NET *net, bool clear_buffer)
226
while (net_data_is_ready(net->vio->sd) > 0)
228
/* The socket is ready */
229
if (vio_read(net->vio, net->buff,
230
(size_t) net->max_packet) <= 0)
237
net->pkt_nr=net->compress_pkt_nr=0; /* Ready for new command */
238
net->write_pos=net->buff;
243
/** Flush write_buffer if not empty. */
245
bool net_flush(NET *net)
248
if (net->buff != net->write_pos)
250
error=test(net_real_write(net, net->buff,
251
(size_t) (net->write_pos - net->buff)));
252
net->write_pos=net->buff;
254
/* Sync packet number if using compression */
256
net->pkt_nr=net->compress_pkt_nr;
261
/*****************************************************************************
262
** Write something to server/client buffer
263
*****************************************************************************/
266
Write a logical packet with packet header.
268
Format: Packet length (3 bytes), packet number(1 byte)
269
When compression is used a 3 byte compression length is added
272
If compression is used the original package is modified!
276
my_net_write(NET *net,const uchar *packet,size_t len)
278
uchar buff[NET_HEADER_SIZE];
279
if (unlikely(!net->vio)) /* nowhere to write */
282
Big packets are handled by splitting them in packets of MAX_PACKET_LENGTH
283
length. The last packet is always a packet that is < MAX_PACKET_LENGTH.
284
(The last packet may even have a length of 0)
286
while (len >= MAX_PACKET_LENGTH)
288
const uint32_t z_size = MAX_PACKET_LENGTH;
289
int3store(buff, z_size);
290
buff[3]= (uchar) net->pkt_nr++;
291
if (net_write_buff(net, buff, NET_HEADER_SIZE) ||
292
net_write_buff(net, packet, z_size))
297
/* Write last packet */
299
buff[3]= (uchar) net->pkt_nr++;
300
if (net_write_buff(net, buff, NET_HEADER_SIZE))
302
return test(net_write_buff(net,packet,len));
306
Send a command to the server.
308
The reason for having both header and packet is so that libdrizzle
309
can easy add a header to a special command (like prepared statements)
310
without having to re-alloc the string.
312
As the command is part of the first data packet, we have to do some data
313
juggling to put the command in there, without having to create a new
316
This function will split big packets into sub-packets if needed.
317
(Each sub packet can only be 2^24 bytes)
319
@param net NET handler
320
@param command Command in MySQL server (enum enum_server_command)
321
@param header Header to write after command
322
@param head_len Length of header
323
@param packet Query or parameter to query
324
@param len Length of packet
333
net_write_command(NET *net,uchar command,
334
const uchar *header, size_t head_len,
335
const uchar *packet, size_t len)
337
uint32_t length=len+1+head_len; /* 1 extra byte for command */
338
uchar buff[NET_HEADER_SIZE+1];
339
uint header_size=NET_HEADER_SIZE+1;
341
buff[4]=command; /* For first packet */
343
if (length >= MAX_PACKET_LENGTH)
345
/* Take into account that we have the command in the first header */
346
len= MAX_PACKET_LENGTH - 1 - head_len;
349
int3store(buff, MAX_PACKET_LENGTH);
350
buff[3]= (uchar) net->pkt_nr++;
351
if (net_write_buff(net, buff, header_size) ||
352
net_write_buff(net, header, head_len) ||
353
net_write_buff(net, packet, len))
356
length-= MAX_PACKET_LENGTH;
357
len= MAX_PACKET_LENGTH;
359
header_size= NET_HEADER_SIZE;
360
} while (length >= MAX_PACKET_LENGTH);
361
len=length; /* Data left to be written */
363
int3store(buff,length);
364
buff[3]= (uchar) net->pkt_nr++;
365
return(test(net_write_buff(net, buff, header_size) ||
366
(head_len && net_write_buff(net, header, head_len)) ||
367
net_write_buff(net, packet, len) || net_flush(net)));
371
Caching the data in a local buffer before sending it.
373
Fill up net->buffer and send it to the client when full.
375
If the rest of the to-be-sent-packet is bigger than buffer,
376
send it in one big block (to avoid copying to internal buffer).
377
If not, copy the rest of the data to the buffer and return without
380
@param net Network handler
381
@param packet Packet to send
382
@param len Length of packet
385
The cached buffer can be sent as it is with 'net_flush()'.
386
In this code we have to be careful to not send a packet longer than
387
MAX_PACKET_LENGTH to net_real_write() if we are using the compressed
388
protocol as we store the length of the compressed packet in 3 bytes.
397
net_write_buff(NET *net, const unsigned char *packet, uint32_t len)
399
uint32_t left_length;
400
if (net->compress && net->max_packet > MAX_PACKET_LENGTH)
401
left_length= MAX_PACKET_LENGTH - (net->write_pos - net->buff);
403
left_length= (uint32_t) (net->buff_end - net->write_pos);
405
if (len > left_length)
407
if (net->write_pos != net->buff)
409
/* Fill up already used packet and write it */
410
memcpy(net->write_pos,packet,left_length);
411
if (net_real_write(net, net->buff,
412
(size_t) (net->write_pos - net->buff) + left_length))
414
net->write_pos= net->buff;
415
packet+= left_length;
421
We can't have bigger packets than 16M with compression
422
Because the uncompressed length is stored in 3 bytes
424
left_length= MAX_PACKET_LENGTH;
425
while (len > left_length)
427
if (net_real_write(net, packet, left_length))
429
packet+= left_length;
433
if (len > net->max_packet)
434
return net_real_write(net, packet, len) ? 1 : 0;
435
/* Send out rest of the blocks as full sized blocks */
437
memcpy(net->write_pos,packet,len);
438
net->write_pos+= len;
444
Read and write one packet using timeouts.
445
If needed, the packet is compressed before sending.
448
- TODO is it needed to set this variable if we have no socket
452
TODO: rewrite this in a manner to do non-block writes. If a write can not be made, and we are
453
in the server, yield to another process and come back later.
456
net_real_write(NET *net,const uchar *packet, size_t len)
459
const uchar *pos,*end;
462
/* Backup of the original SO_RCVTIMEO timeout */
463
struct timeval backtime;
467
return(-1); /* socket can't be used */
469
net->reading_or_writing=2;
474
const uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
475
if (!(b= (uchar*) malloc(len + NET_HEADER_SIZE +
479
net->last_errno= CR_OUT_OF_MEMORY;
480
/* In the server, the error is reported by MY_WME flag. */
481
net->reading_or_writing= 0;
484
memcpy(b+header_length,packet,len);
486
complen= len * 120 / 100 + 12;
487
unsigned char * compbuf= (unsigned char *) malloc(complen);
490
uLongf tmp_complen= complen;
491
int res= compress((Bytef*) compbuf, &tmp_complen,
492
(Bytef*) (b+header_length),
494
complen= tmp_complen;
498
if ((res != Z_OK) || (complen >= len))
502
size_t tmplen= complen;
511
int3store(&b[NET_HEADER_SIZE],complen);
513
b[3]=(uchar) (net->compress_pkt_nr++);
518
/* Check for error, currently assert */
519
if (net->write_timeout)
521
struct timeval waittime;
524
waittime.tv_sec= net->write_timeout;
527
memset(&backtime, 0, sizeof(struct timeval));
528
length= sizeof(struct timeval);
529
error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
533
perror("getsockopt");
536
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
537
&waittime, (socklen_t)sizeof(struct timeval));
542
/* Loop until we have read everything */
545
if ((long) (length= vio_write(net->vio,pos,(size_t) (end-pos))) <= 0)
547
const bool interrupted= vio_should_retry(net->vio);
549
If we read 0, or we were interrupted this means that
550
we need to switch to blocking mode and wait until the timeout
551
on the socket kicks in.
553
if ((interrupted || length == 0))
557
while (vio_blocking(net->vio, true, &old_mode) < 0)
559
if (vio_should_retry(net->vio) && retry_count++ < net->retry_count)
561
net->error= 2; /* Close socket */
562
net->last_errno= CR_NET_PACKET_TOO_LARGE;
570
if (retry_count++ < net->retry_count)
574
if (vio_errno(net->vio) == SOCKET_EINTR)
578
net->error= 2; /* Close socket */
579
net->last_errno= (interrupted ? CR_NET_WRITE_INTERRUPTED :
580
CR_NET_ERROR_ON_WRITE);
584
update_statistics(thd_increment_bytes_sent(length));
587
if ((net->compress) && (packet != NULL))
588
free((char*) packet);
589
net->reading_or_writing=0;
591
if (net->write_timeout)
592
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
593
&backtime, (socklen_t)sizeof(struct timeval));
595
return(((int) (pos != end)));
600
Reads one packet to net->buff + net->where_b.
601
Long packets are handled by my_net_read().
602
This function reallocates the net->buff buffer if necessary.
605
Returns length of packet.
609
my_real_read(NET *net, size_t *complen)
613
uint i,retry_count=0;
614
uint32_t len=packet_error;
615
uint32_t remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
617
/* Backup of the original SO_RCVTIMEO timeout */
618
struct timeval backtime;
623
net->reading_or_writing= 1;
624
/* Read timeout is set in my_net_set_read_timeout */
626
pos = net->buff + net->where_b; /* net->packet -4 */
629
/* Check for error, currently assert */
630
if (net->read_timeout)
632
struct timeval waittime;
635
waittime.tv_sec= net->read_timeout;
638
memset(&backtime, 0, sizeof(struct timeval));
639
length= sizeof(struct timeval);
640
error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
644
perror("getsockopt");
647
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
648
&waittime, (socklen_t)sizeof(struct timeval));
652
for (i= 0; i < 2 ; i++)
656
/* First read is done with non blocking mode */
657
if ((long) (length= vio_read(net->vio, pos, remain)) <= 0L)
659
const bool interrupted = vio_should_retry(net->vio);
662
{ /* Probably in MIT threads */
663
if (retry_count++ < net->retry_count)
666
if (vio_errno(net->vio) == SOCKET_EINTR)
671
net->error= 2; /* Close socket */
672
net->last_errno= (vio_was_interrupted(net->vio) ?
673
CR_NET_READ_INTERRUPTED :
678
remain -= (uint32_t) length;
680
update_statistics(thd_increment_bytes_received(length));
683
{ /* First parts is packet length */
686
if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr)
689
/* Not a NET error on the client. XXX: why? */
692
net->compress_pkt_nr= ++net->pkt_nr;
696
If the packet is compressed then complen > 0 and contains the
697
number of bytes in the uncompressed packet
699
*complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
702
len=uint3korr(net->buff+net->where_b);
703
if (!len) /* End of big multi-packet */
705
helping = max(len,*complen) + net->where_b;
706
/* The necessary size of net->buff */
707
if (helping >= net->max_packet)
709
if (net_realloc(net,helping))
711
len= packet_error; /* Return error and close connection */
715
pos=net->buff + net->where_b;
716
remain = (uint32_t) len;
721
if (net->read_timeout)
722
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
723
&backtime, (socklen_t)sizeof(struct timeval));
725
net->reading_or_writing= 0;
732
Read a packet from the client/server and return it without the internal
735
If the packet is the first packet of a multi-packet packet
736
(which is indicated by the length of the packet = 0xffffff) then
737
all sub packets are read and concatenated.
739
If the packet was compressed, its uncompressed and the length of the
740
uncompressed packet is returned.
743
The function returns the length of the found packet or packet_error.
744
net->read_pos points to the read data.
748
my_net_read(NET *net)
754
len = my_real_read(net,&complen);
755
if (len == MAX_PACKET_LENGTH)
757
/* First packet of a multi-packet. Concatenate the packets */
758
uint32_t save_pos = net->where_b;
759
size_t total_length= 0;
764
len = my_real_read(net,&complen);
765
} while (len == MAX_PACKET_LENGTH);
766
if (len != packet_error)
768
net->where_b = save_pos;
770
net->read_pos = net->buff + net->where_b;
771
if (len != packet_error)
772
net->read_pos[len]=0; /* Safeguard for drizzle_use_result */
777
/* We are using the compressed protocol */
780
uint32_t start_of_packet;
781
uint32_t first_packet_offset;
782
uint read_length, multi_byte_packet=0;
784
if (net->remain_in_buf)
786
buf_length= net->buf_length; /* Data left in old packet */
787
first_packet_offset= start_of_packet= (net->buf_length -
789
/* Restore the character that was overwritten by the end 0 */
790
net->buff[start_of_packet]= net->save_char;
794
/* reuse buffer, as there is nothing in it that we need */
795
buf_length= start_of_packet= first_packet_offset= 0;
801
if (buf_length - start_of_packet >= NET_HEADER_SIZE)
803
read_length = uint3korr(net->buff+start_of_packet);
806
/* End of multi-byte packet */
807
start_of_packet += NET_HEADER_SIZE;
810
if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
812
if (multi_byte_packet)
814
/* Remove packet header for second packet */
815
memmove(net->buff + first_packet_offset + start_of_packet,
816
net->buff + first_packet_offset + start_of_packet +
818
buf_length - start_of_packet);
819
start_of_packet += read_length;
820
buf_length -= NET_HEADER_SIZE;
823
start_of_packet+= read_length + NET_HEADER_SIZE;
825
if (read_length != MAX_PACKET_LENGTH) /* last package */
827
multi_byte_packet= 0; /* No last zero len packet */
830
multi_byte_packet= NET_HEADER_SIZE;
831
/* Move data down to read next data packet after current one */
832
if (first_packet_offset)
834
memmove(net->buff,net->buff+first_packet_offset,
835
buf_length-first_packet_offset);
836
buf_length-=first_packet_offset;
837
start_of_packet -= first_packet_offset;
838
first_packet_offset=0;
843
/* Move data down to read next data packet after current one */
844
if (first_packet_offset)
846
memmove(net->buff,net->buff+first_packet_offset,
847
buf_length-first_packet_offset);
848
buf_length-=first_packet_offset;
849
start_of_packet -= first_packet_offset;
850
first_packet_offset=0;
853
net->where_b=buf_length;
854
if ((packet_len = my_real_read(net,&complen)) == packet_error)
859
unsigned char * compbuf= (unsigned char *) malloc(complen);
862
uLongf tmp_complen= complen;
863
int error= uncompress((Bytef*) compbuf, &tmp_complen,
864
(Bytef*) (net->buff + net->where_b),
866
complen= tmp_complen;
870
net->error= 2; /* caller will close socket */
871
net->last_errno= CR_NET_UNCOMPRESS_ERROR;
875
memcpy((net->buff + net->where_b), compbuf, complen);
884
buf_length+= complen;
886
net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE;
887
net->buf_length= buf_length;
888
net->remain_in_buf= (uint32_t) (buf_length - start_of_packet);
889
len = ((uint32_t) (start_of_packet - first_packet_offset) - NET_HEADER_SIZE -
891
net->save_char= net->read_pos[len]; /* Must be saved */
892
net->read_pos[len]=0; /* Safeguard for drizzle_use_result */
898
void my_net_set_read_timeout(NET *net, uint timeout)
900
net->read_timeout= timeout;
902
vio_timeout(net->vio, 0, timeout);
907
void my_net_set_write_timeout(NET *net, uint timeout)
909
net->write_timeout= timeout;
911
vio_timeout(net->vio, 1, timeout);