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
#define __need_timeval 1
23
#include "libdrizzle.h"
24
#include "libdrizzle_priv.h"
25
#include <libdrizzle/errmsg.h>
26
#include <vio/violite.h>
33
#include <sys/socket.h>
38
The following handles the differences when this is linked between the
39
client and the server.
41
This gives an error if a too big packet is found
42
The server can change this with the -O switch, but because the client
43
can't normally do this the client should have a bigger max_allowed_packet.
47
#define update_statistics(A)
48
#define thd_increment_bytes_sent(N)
50
#define TEST_BLOCKING 8
51
#define MAX_PACKET_LENGTH (256L*256L*256L-1)
52
#define MIN_COMPRESS_LENGTH 50 /* Don't compress small bl. */
54
static bool net_write_buff(NET *net, const unsigned char *packet, uint32_t len);
57
/** Init with packet info. */
59
bool my_net_init(NET *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)))
66
net->buff_end=net->buff+net->max_packet;
67
net->error=0; net->return_status=0;
68
net->pkt_nr=net->compress_pkt_nr=0;
69
net->write_pos=net->read_pos = net->buff;
71
net->compress=0; net->reading_or_writing=0;
72
net->where_b = net->remain_in_buf=0;
76
if (vio != 0) /* If real connection */
78
net->fd = vio_fd(vio); /* For perl DBI/DBD */
84
bool net_init_sock(NET * net, int sock, int flags)
87
Vio *vio_tmp= vio_new(sock, VIO_TYPE_TCPIP, flags);
91
if (my_net_init(net, vio_tmp))
93
/* Only delete the temporary vio if we didn't already attach it to the
96
if (vio_tmp && (net->vio != vio_tmp))
100
(void) shutdown(sock, SHUT_RDWR);
108
void net_end(NET *net)
110
if (net->buff != NULL)
116
void net_close(NET *net)
118
if (net->vio != NULL)
120
vio_delete(net->vio);
125
bool net_peer_addr(NET *net, char *buf, uint16_t *port, size_t buflen)
127
return vio_peer_addr(net->vio, buf, port, buflen);
130
void net_keepalive(NET *net, bool flag)
132
vio_keepalive(net->vio, flag);
135
int net_get_sd(NET *net)
140
bool net_should_close(NET *net)
142
return net->error || (net->vio == 0);
145
bool net_more_data(NET *net)
147
return (net->vio == 0 || net->vio->read_pos < net->vio->read_end);
150
/** Realloc the packet buffer. */
152
bool net_realloc(NET *net, size_t length)
157
if (length >= net->max_packet_size)
159
/* @todo: 1 and 2 codes are identical. */
161
net->last_errno= CR_NET_PACKET_TOO_LARGE;
164
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
166
We must allocate some extra bytes for the end 0 and to be able to
167
read big compressed blocks
169
if (!(buff= (unsigned char*) realloc((char*) net->buff, pkt_length +
170
NET_HEADER_SIZE + COMP_HEADER_SIZE)))
172
/* @todo: 1 and 2 codes are identical. */
174
net->last_errno= CR_OUT_OF_MEMORY;
175
/* In the server the error is reported by MY_WME flag. */
178
net->buff=net->write_pos=buff;
179
net->buff_end=buff+(net->max_packet= (uint32_t) pkt_length);
185
Check if there is any data to be read from the socket.
187
@param sd socket descriptor
192
1 Data or EOF to read
194
-1 Don't know if data is ready or not
197
static bool net_data_is_ready(int sd)
203
ufds.events= POLLIN | POLLPRI;
204
if (!(res= poll(&ufds, 1, 0)))
206
if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
212
Remove unwanted characters from connection
213
and check if disconnected.
215
Read from socket until there is nothing more to read. Discard
218
If there is anything when to read 'net_clear' is called this
219
normally indicates an error in the protocol.
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.
225
@param net NET handler
226
@param clear_buffer if <> 0, then clear all data from comm buff
229
void net_clear(NET *net, bool clear_buffer)
233
while (net_data_is_ready(net->vio->sd) > 0)
235
/* The socket is ready */
236
if (vio_read(net->vio, net->buff,
237
(size_t) net->max_packet) <= 0)
244
net->pkt_nr=net->compress_pkt_nr=0; /* Ready for new command */
245
net->write_pos=net->buff;
250
/** Flush write_buffer if not empty. */
252
bool net_flush(NET *net)
255
if (net->buff != net->write_pos)
257
error=net_real_write(net, net->buff,
258
(size_t) (net->write_pos - net->buff)) ? 1 : 0;
259
net->write_pos=net->buff;
261
/* Sync packet number if using compression */
263
net->pkt_nr=net->compress_pkt_nr;
268
/*****************************************************************************
269
** Write something to server/client buffer
270
*****************************************************************************/
273
Write a logical packet with packet header.
275
Format: Packet length (3 bytes), packet number(1 byte)
276
When compression is used a 3 byte compression length is added
279
If compression is used the original package is modified!
283
my_net_write(NET *net,const unsigned char *packet,size_t len)
285
unsigned char buff[NET_HEADER_SIZE];
286
if (unlikely(!net->vio)) /* nowhere to write */
289
Big packets are handled by splitting them in packets of MAX_PACKET_LENGTH
290
length. The last packet is always a packet that is < MAX_PACKET_LENGTH.
291
(The last packet may even have a length of 0)
293
while (len >= MAX_PACKET_LENGTH)
295
const uint32_t z_size = MAX_PACKET_LENGTH;
296
int3store(buff, z_size);
297
buff[3]= (unsigned char) net->pkt_nr++;
298
if (net_write_buff(net, buff, NET_HEADER_SIZE) ||
299
net_write_buff(net, packet, z_size))
304
/* Write last packet */
306
buff[3]= (unsigned char) net->pkt_nr++;
307
if (net_write_buff(net, buff, NET_HEADER_SIZE))
309
return net_write_buff(net,packet,len) ? 1 : 0;
313
Send a command to the server.
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.
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
323
This function will split big packets into sub-packets if needed.
324
(Each sub packet can only be 2^24 bytes)
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
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)
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;
348
buff[4]=command; /* For first packet */
350
if (length >= MAX_PACKET_LENGTH)
352
/* Take into account that we have the command in the first header */
353
len= MAX_PACKET_LENGTH - 1 - head_len;
356
int3store(buff, MAX_PACKET_LENGTH);
357
buff[3]= (unsigned char) net->pkt_nr++;
358
if (net_write_buff(net, buff, header_size) ||
359
net_write_buff(net, header, head_len) ||
360
net_write_buff(net, packet, len))
363
length-= MAX_PACKET_LENGTH;
364
len= MAX_PACKET_LENGTH;
366
header_size= NET_HEADER_SIZE;
367
} while (length >= MAX_PACKET_LENGTH);
368
len=length; /* Data left to be written */
370
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 );
378
Caching the data in a local buffer before sending it.
380
Fill up net->buffer and send it to the client when full.
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
387
@param net Network handler
388
@param packet Packet to send
389
@param len Length of packet
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.
404
net_write_buff(NET *net, const unsigned char *packet, uint32_t len)
406
uint32_t left_length;
407
if (net->compress && net->max_packet > MAX_PACKET_LENGTH)
408
left_length= MAX_PACKET_LENGTH - (net->write_pos - net->buff);
410
left_length= (uint32_t) (net->buff_end - net->write_pos);
412
if (len > left_length)
414
if (net->write_pos != net->buff)
416
/* 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))
421
net->write_pos= net->buff;
422
packet+= left_length;
428
We can't have bigger packets than 16M with compression
429
Because the uncompressed length is stored in 3 bytes
431
left_length= MAX_PACKET_LENGTH;
432
while (len > left_length)
434
if (net_real_write(net, packet, left_length))
436
packet+= left_length;
440
if (len > net->max_packet)
441
return net_real_write(net, packet, len) ? 1 : 0;
442
/* Send out rest of the blocks as full sized blocks */
444
memcpy(net->write_pos,packet,len);
445
net->write_pos+= len;
451
Read and write one packet using timeouts.
452
If needed, the packet is compressed before sending.
455
- TODO is it needed to set this variable if we have no socket
459
TODO: rewrite this in a manner to do non-block writes. If a write can not be made, and we are
460
in the server, yield to another process and come back later.
463
net_real_write(NET *net,const unsigned char *packet, size_t len)
466
const unsigned char *pos,*end;
467
uint32_t retry_count= 0;
469
/* Backup of the original SO_RCVTIMEO timeout */
471
struct timespec backtime;
476
return(-1); /* socket can't be used */
478
net->reading_or_writing=2;
483
const uint32_t header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
484
if (!(b= (unsigned char*) malloc(len + NET_HEADER_SIZE +
488
net->last_errno= CR_OUT_OF_MEMORY;
489
/* In the server, the error is reported by MY_WME flag. */
490
net->reading_or_writing= 0;
493
memcpy(b+header_length,packet,len);
495
complen= len * 120 / 100 + 12;
496
unsigned char * compbuf= (unsigned char *) malloc(complen);
499
uLongf tmp_complen= complen;
500
int res= compress((Bytef*) compbuf, &tmp_complen,
501
(Bytef*) (b+header_length),
503
complen= tmp_complen;
507
if ((res != Z_OK) || (complen >= len))
511
size_t tmplen= complen;
520
int3store(&b[NET_HEADER_SIZE],complen);
522
b[3]=(unsigned char) (net->compress_pkt_nr++);
528
/* Check for error, currently assert */
529
if (net->write_timeout)
531
struct timespec waittime;
534
waittime.tv_sec= net->write_timeout;
537
memset(&backtime, 0, sizeof(struct timespec));
538
length= sizeof(struct timespec);
539
error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
543
perror("getsockopt");
546
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
547
&waittime, (socklen_t)sizeof(struct timespec));
554
/* Loop until we have read everything */
557
if ((long) (length= vio_write(net->vio,pos,(size_t) (end-pos))) <= 0)
559
const bool interrupted= vio_should_retry(net->vio);
561
If we read 0, or we were interrupted this means that
562
we need to switch to blocking mode and wait until the timeout
563
on the socket kicks in.
565
if ((interrupted || length == 0))
569
while (vio_blocking(net->vio, true, &old_mode) < 0)
571
if (vio_should_retry(net->vio) && retry_count++ < net->retry_count)
573
net->error= 2; /* Close socket */
574
net->last_errno= CR_NET_PACKET_TOO_LARGE;
582
if (retry_count++ < net->retry_count)
586
if (vio_errno(net->vio) == EINTR)
590
net->error= 2; /* Close socket */
591
net->last_errno= (interrupted ? CR_NET_WRITE_INTERRUPTED :
592
CR_NET_ERROR_ON_WRITE);
596
update_statistics(thd_increment_bytes_sent(length));
599
if ((net->compress) && (packet != NULL))
600
free((char*) packet);
601
net->reading_or_writing=0;
604
if (net->write_timeout)
605
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
606
&backtime, (socklen_t)sizeof(struct timespec));
609
return(((int) (pos != end)));
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.
619
Returns length of packet.
623
my_real_read(NET *net, size_t *complen)
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 :
633
/* Backup of the original SO_RCVTIMEO timeout */
634
struct timespec backtime;
640
net->reading_or_writing= 1;
641
/* Read timeout is set in my_net_set_read_timeout */
643
pos = net->buff + net->where_b; /* net->packet -4 */
647
/* Check for error, currently assert */
648
if (net->read_timeout)
650
struct timespec waittime;
653
waittime.tv_sec= net->read_timeout;
656
memset(&backtime, 0, sizeof(struct timespec));
657
length= sizeof(struct timespec);
658
error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
662
perror("getsockopt");
665
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
666
&waittime, (socklen_t)sizeof(struct timespec));
671
for (i= 0; i < 2 ; i++)
675
/* First read is done with non blocking mode */
676
if ((long) (length= vio_read(net->vio, pos, remain)) <= 0L)
678
const bool interrupted = vio_should_retry(net->vio);
681
{ /* Probably in MIT threads */
682
if (retry_count++ < net->retry_count)
685
if (vio_errno(net->vio) == EINTR)
690
net->error= 2; /* Close socket */
691
net->last_errno= (vio_was_interrupted(net->vio) ?
692
CR_NET_READ_INTERRUPTED :
697
remain -= (uint32_t) length;
699
update_statistics(thd_increment_bytes_received(length));
702
{ /* First parts is packet length */
705
if (net->buff[net->where_b + 3] != (unsigned char) net->pkt_nr)
708
/* Not a NET error on the client. XXX: why? */
711
net->compress_pkt_nr= ++net->pkt_nr;
715
If the packet is compressed then complen > 0 and contains the
716
number of bytes in the uncompressed packet
718
*complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
721
len=uint3korr(net->buff+net->where_b);
722
if (!len) /* End of big multi-packet */
724
helping = max(len,*complen) + net->where_b;
725
/* The necessary size of net->buff */
726
if (helping >= net->max_packet)
728
if (net_realloc(net,helping))
730
len= packet_error; /* Return error and close connection */
734
pos=net->buff + net->where_b;
735
remain = (uint32_t) len;
741
if (net->read_timeout)
742
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
743
&backtime, (socklen_t)sizeof(struct timespec));
746
net->reading_or_writing= 0;
753
Read a packet from the client/server and return it without the internal
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.
760
If the packet was compressed, its uncompressed and the length of the
761
uncompressed packet is returned.
764
The function returns the length of the found packet or packet_error.
765
net->read_pos points to the read data.
769
my_net_read(NET *net)
775
len = my_real_read(net,&complen);
776
if (len == MAX_PACKET_LENGTH)
778
/* First packet of a multi-packet. Concatenate the packets */
779
uint32_t save_pos = net->where_b;
780
size_t total_length= 0;
785
len = my_real_read(net,&complen);
786
} while (len == MAX_PACKET_LENGTH);
787
if (len != packet_error)
789
net->where_b = save_pos;
791
net->read_pos = net->buff + net->where_b;
792
if (len != packet_error)
793
net->read_pos[len]=0; /* Safeguard for drizzle_use_result */
798
/* We are using the compressed protocol */
801
uint32_t start_of_packet;
802
uint32_t first_packet_offset;
803
uint32_t read_length, multi_byte_packet=0;
805
if (net->remain_in_buf)
807
buf_length= net->buf_length; /* Data left in old packet */
808
first_packet_offset= start_of_packet= (net->buf_length -
810
/* Restore the character that was overwritten by the end 0 */
811
net->buff[start_of_packet]= net->save_char;
815
/* reuse buffer, as there is nothing in it that we need */
816
buf_length= start_of_packet= first_packet_offset= 0;
822
if (buf_length - start_of_packet >= NET_HEADER_SIZE)
824
read_length = uint3korr(net->buff+start_of_packet);
827
/* End of multi-byte packet */
828
start_of_packet += NET_HEADER_SIZE;
831
if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
833
if (multi_byte_packet)
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 +
839
buf_length - start_of_packet);
840
start_of_packet += read_length;
841
buf_length -= NET_HEADER_SIZE;
844
start_of_packet+= read_length + NET_HEADER_SIZE;
846
if (read_length != MAX_PACKET_LENGTH) /* last package */
848
multi_byte_packet= 0; /* No last zero len packet */
851
multi_byte_packet= NET_HEADER_SIZE;
852
/* Move data down to read next data packet after current one */
853
if (first_packet_offset)
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;
864
/* Move data down to read next data packet after current one */
865
if (first_packet_offset)
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;
874
net->where_b=buf_length;
875
if ((packet_len = my_real_read(net,&complen)) == packet_error)
880
unsigned char * compbuf= (unsigned char *) malloc(complen);
883
uLongf tmp_complen= complen;
884
int error= uncompress((Bytef*) compbuf, &tmp_complen,
885
(Bytef*) (net->buff + net->where_b),
887
complen= tmp_complen;
891
net->error= 2; /* caller will close socket */
892
net->last_errno= CR_NET_UNCOMPRESS_ERROR;
896
memcpy((net->buff + net->where_b), compbuf, complen);
905
buf_length+= complen;
907
net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE;
908
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 -
912
net->save_char= net->read_pos[len]; /* Must be saved */
913
net->read_pos[len]=0; /* Safeguard for drizzle_use_result */
919
void my_net_set_read_timeout(NET *net, uint32_t timeout)
921
net->read_timeout= timeout;
924
vio_timeout(net->vio, 0, timeout);
930
void my_net_set_write_timeout(NET *net, uint32_t timeout)
932
net->write_timeout= timeout;
935
vio_timeout(net->vio, 1, timeout);
940
Clear possible error state of struct NET
942
@param net clear the state of the argument
945
void net_clear_error(NET *net)
948
net->last_error[0]= '\0';
949
strcpy(net->sqlstate, sqlstate_get_not_error());