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
22
#include "libdrizzle.h"
23
#include "libdrizzle_priv.h"
24
#include <libdrizzle/errmsg.h>
25
#include <vio/violite.h>
32
#include <sys/socket.h>
37
The following handles the differences when this is linked between the
38
client and the server.
40
This gives an error if a too big packet is found
41
The server can change this with the -O switch, but because the client
42
can't normally do this the client should have a bigger max_allowed_packet.
46
#define MAX_PACKET_LENGTH (256L*256L*256L-1)
48
static bool net_write_buff(NET *net, const unsigned char *packet, uint32_t len);
51
/** Init with packet info. */
53
bool my_net_init(NET *net, Vio* vio)
56
my_net_local_init(net); /* Set some limits */
57
if (!(net->buff=(unsigned char*) malloc((size_t) net->max_packet+
58
NET_HEADER_SIZE + COMP_HEADER_SIZE)))
60
net->buff_end=net->buff+net->max_packet;
61
net->error=0; net->return_status=0;
62
net->pkt_nr=net->compress_pkt_nr=0;
63
net->write_pos=net->read_pos = net->buff;
65
net->compress=0; net->reading_or_writing=0;
66
net->where_b = net->remain_in_buf=0;
70
if (vio != 0) /* If real connection */
72
net->fd = vio_fd(vio); /* For perl DBI/DBD */
78
bool net_init_sock(NET * net, int sock, int flags)
81
Vio *vio_tmp= vio_new(sock, VIO_TYPE_TCPIP, flags);
85
if (my_net_init(net, vio_tmp))
87
/* Only delete the temporary vio if we didn't already attach it to the
90
if (vio_tmp && (net->vio != vio_tmp))
94
(void) shutdown(sock, SHUT_RDWR);
102
void net_end(NET *net)
104
if (net->buff != NULL)
110
void net_close(NET *net)
112
if (net->vio != NULL)
114
vio_delete(net->vio);
119
bool net_peer_addr(NET *net, char *buf, uint16_t *port, size_t buflen)
121
return vio_peer_addr(net->vio, buf, port, buflen);
124
void net_keepalive(NET *net, bool flag)
126
vio_keepalive(net->vio, flag);
129
int net_get_sd(NET *net)
134
bool net_should_close(NET *net)
136
return net->error || (net->vio == 0);
139
bool net_more_data(NET *net)
141
return (net->vio == 0 || net->vio->read_pos < net->vio->read_end);
144
/** Realloc the packet buffer. */
146
bool net_realloc(NET *net, size_t length)
151
if (length >= net->max_packet_size)
153
/* @todo: 1 and 2 codes are identical. */
155
net->last_errno= CR_NET_PACKET_TOO_LARGE;
158
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
160
We must allocate some extra bytes for the end 0 and to be able to
161
read big compressed blocks
163
if (!(buff= (unsigned char*) realloc((char*) net->buff, pkt_length +
164
NET_HEADER_SIZE + COMP_HEADER_SIZE)))
166
/* @todo: 1 and 2 codes are identical. */
168
net->last_errno= CR_OUT_OF_MEMORY;
169
/* In the server the error is reported by MY_WME flag. */
172
net->buff=net->write_pos=buff;
173
net->buff_end=buff+(net->max_packet= (uint32_t) pkt_length);
179
Check if there is any data to be read from the socket.
181
@param sd socket descriptor
186
1 Data or EOF to read
188
-1 Don't know if data is ready or not
191
static bool net_data_is_ready(int sd)
197
ufds.events= POLLIN | POLLPRI;
198
if (!(res= poll(&ufds, 1, 0)))
200
if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
206
Remove unwanted characters from connection
207
and check if disconnected.
209
Read from socket until there is nothing more to read. Discard
212
If there is anything when to read 'net_clear' is called this
213
normally indicates an error in the protocol.
215
When connection is properly closed (for TCP it means with
216
a FIN packet), then select() considers a socket "ready to read",
217
in the sense that there's EOF to read, but read() returns 0.
219
@param net NET handler
220
@param clear_buffer if <> 0, then clear all data from comm buff
223
void net_clear(NET *net, bool clear_buffer)
227
while (net_data_is_ready(net->vio->sd) > 0)
229
/* The socket is ready */
230
if (vio_read(net->vio, net->buff,
231
(size_t) net->max_packet) <= 0)
238
net->pkt_nr=net->compress_pkt_nr=0; /* Ready for new command */
239
net->write_pos=net->buff;
244
/** Flush write_buffer if not empty. */
246
bool net_flush(NET *net)
249
if (net->buff != net->write_pos)
251
error=net_real_write(net, net->buff,
252
(size_t) (net->write_pos - net->buff)) ? 1 : 0;
253
net->write_pos=net->buff;
255
/* Sync packet number if using compression */
257
net->pkt_nr=net->compress_pkt_nr;
262
/*****************************************************************************
263
** Write something to server/client buffer
264
*****************************************************************************/
267
Write a logical packet with packet header.
269
Format: Packet length (3 bytes), packet number(1 byte)
270
When compression is used a 3 byte compression length is added
273
If compression is used the original package is modified!
277
my_net_write(NET *net,const unsigned char *packet,size_t len)
279
unsigned char buff[NET_HEADER_SIZE];
280
if (unlikely(!net->vio)) /* nowhere to write */
283
Big packets are handled by splitting them in packets of MAX_PACKET_LENGTH
284
length. The last packet is always a packet that is < MAX_PACKET_LENGTH.
285
(The last packet may even have a length of 0)
287
while (len >= MAX_PACKET_LENGTH)
289
const uint32_t z_size = MAX_PACKET_LENGTH;
290
int3store(buff, z_size);
291
buff[3]= (unsigned char) net->pkt_nr++;
292
if (net_write_buff(net, buff, NET_HEADER_SIZE) ||
293
net_write_buff(net, packet, z_size))
298
/* Write last packet */
300
buff[3]= (unsigned char) net->pkt_nr++;
301
if (net_write_buff(net, buff, NET_HEADER_SIZE))
303
return net_write_buff(net,packet,len) ? 1 : 0;
307
Send a command to the server.
309
The reason for having both header and packet is so that libdrizzle
310
can easy add a header to a special command (like prepared statements)
311
without having to re-alloc the string.
313
As the command is part of the first data packet, we have to do some data
314
juggling to put the command in there, without having to create a new
317
This function will split big packets into sub-packets if needed.
318
(Each sub packet can only be 2^24 bytes)
320
@param net NET handler
321
@param command Command in MySQL server (enum enum_server_command)
322
@param header Header to write after command
323
@param head_len Length of header
324
@param packet Query or parameter to query
325
@param len Length of packet
334
net_write_command(NET *net,unsigned char command,
335
const unsigned char *header, size_t head_len,
336
const unsigned char *packet, size_t len)
338
uint32_t length=len+1+head_len; /* 1 extra byte for command */
339
unsigned char buff[NET_HEADER_SIZE+1];
340
uint32_t header_size=NET_HEADER_SIZE+1;
342
buff[4]=command; /* For first packet */
344
if (length >= MAX_PACKET_LENGTH)
346
/* Take into account that we have the command in the first header */
347
len= MAX_PACKET_LENGTH - 1 - head_len;
350
int3store(buff, MAX_PACKET_LENGTH);
351
buff[3]= (unsigned char) net->pkt_nr++;
352
if (net_write_buff(net, buff, header_size) ||
353
net_write_buff(net, header, head_len) ||
354
net_write_buff(net, packet, len))
357
length-= MAX_PACKET_LENGTH;
358
len= MAX_PACKET_LENGTH;
360
header_size= NET_HEADER_SIZE;
361
} while (length >= MAX_PACKET_LENGTH);
362
len=length; /* Data left to be written */
364
int3store(buff,length);
365
buff[3]= (unsigned char) net->pkt_nr++;
366
return((net_write_buff(net, buff, header_size) ||
367
(head_len && net_write_buff(net, header, head_len)) ||
368
net_write_buff(net, packet, len) || net_flush(net)) ? 1 : 0 );
372
Caching the data in a local buffer before sending it.
374
Fill up net->buffer and send it to the client when full.
376
If the rest of the to-be-sent-packet is bigger than buffer,
377
send it in one big block (to avoid copying to internal buffer).
378
If not, copy the rest of the data to the buffer and return without
381
@param net Network handler
382
@param packet Packet to send
383
@param len Length of packet
386
The cached buffer can be sent as it is with 'net_flush()'.
387
In this code we have to be careful to not send a packet longer than
388
MAX_PACKET_LENGTH to net_real_write() if we are using the compressed
389
protocol as we store the length of the compressed packet in 3 bytes.
398
net_write_buff(NET *net, const unsigned char *packet, uint32_t len)
400
uint32_t left_length;
401
if (net->compress && net->max_packet > MAX_PACKET_LENGTH)
402
left_length= MAX_PACKET_LENGTH - (net->write_pos - net->buff);
404
left_length= (uint32_t) (net->buff_end - net->write_pos);
406
if (len > left_length)
408
if (net->write_pos != net->buff)
410
/* Fill up already used packet and write it */
411
memcpy(net->write_pos,packet,left_length);
412
if (net_real_write(net, net->buff,
413
(size_t) (net->write_pos - net->buff) + left_length))
415
net->write_pos= net->buff;
416
packet+= left_length;
422
We can't have bigger packets than 16M with compression
423
Because the uncompressed length is stored in 3 bytes
425
left_length= MAX_PACKET_LENGTH;
426
while (len > left_length)
428
if (net_real_write(net, packet, left_length))
430
packet+= left_length;
434
if (len > net->max_packet)
435
return net_real_write(net, packet, len) ? 1 : 0;
436
/* Send out rest of the blocks as full sized blocks */
438
memcpy(net->write_pos,packet,len);
439
net->write_pos+= len;
445
Read and write one packet using timeouts.
446
If needed, the packet is compressed before sending.
449
- TODO is it needed to set this variable if we have no socket
453
TODO: rewrite this in a manner to do non-block writes. If a write can not be made, and we are
454
in the server, yield to another process and come back later.
457
net_real_write(NET *net,const unsigned char *packet, size_t len)
460
const unsigned char *pos,*end;
461
uint32_t retry_count= 0;
463
/* Backup of the original SO_RCVTIMEO timeout */
465
struct timespec backtime;
470
return(-1); /* socket can't be used */
472
net->reading_or_writing=2;
477
const uint32_t header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
478
if (!(b= (unsigned char*) malloc(len + NET_HEADER_SIZE +
482
net->last_errno= CR_OUT_OF_MEMORY;
483
/* In the server, the error is reported by MY_WME flag. */
484
net->reading_or_writing= 0;
487
memcpy(b+header_length,packet,len);
489
complen= len * 120 / 100 + 12;
490
unsigned char * compbuf= (unsigned char *) malloc(complen);
493
uLongf tmp_complen= complen;
494
int res= compress((Bytef*) compbuf, &tmp_complen,
495
(Bytef*) (b+header_length),
497
complen= tmp_complen;
501
if ((res != Z_OK) || (complen >= len))
505
size_t tmplen= complen;
514
int3store(&b[NET_HEADER_SIZE],complen);
516
b[3]=(unsigned char) (net->compress_pkt_nr++);
522
/* Check for error, currently assert */
523
if (net->write_timeout)
525
struct timespec waittime;
528
waittime.tv_sec= net->write_timeout;
531
memset(&backtime, 0, sizeof(struct timespec));
532
length= sizeof(struct timespec);
533
error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
537
perror("getsockopt");
540
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
541
&waittime, (socklen_t)sizeof(struct timespec));
548
/* Loop until we have read everything */
551
if ((long) (length= vio_write(net->vio,pos,(size_t) (end-pos))) <= 0)
553
const bool interrupted= vio_should_retry(net->vio);
555
If we read 0, or we were interrupted this means that
556
we need to switch to blocking mode and wait until the timeout
557
on the socket kicks in.
559
if ((interrupted || length == 0))
563
while (vio_blocking(net->vio, true, &old_mode) < 0)
565
if (vio_should_retry(net->vio) && retry_count++ < net->retry_count)
567
net->error= 2; /* Close socket */
568
net->last_errno= CR_NET_PACKET_TOO_LARGE;
576
if (retry_count++ < net->retry_count)
580
if (vio_errno(net->vio) == EINTR)
584
net->error= 2; /* Close socket */
585
net->last_errno= (interrupted ? CR_NET_WRITE_INTERRUPTED :
586
CR_NET_ERROR_ON_WRITE);
592
if ((net->compress) && (packet != NULL))
593
free((char*) packet);
594
net->reading_or_writing=0;
597
if (net->write_timeout)
598
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
599
&backtime, (socklen_t)sizeof(struct timespec));
602
return(((int) (pos != end)));
607
Reads one packet to net->buff + net->where_b.
608
Long packets are handled by my_net_read().
609
This function reallocates the net->buff buffer if necessary.
612
Returns length of packet.
616
my_real_read(NET *net, size_t *complen)
620
uint32_t i,retry_count=0;
621
uint32_t len=packet_error;
622
uint32_t remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
626
/* Backup of the original SO_RCVTIMEO timeout */
627
struct timespec backtime;
633
net->reading_or_writing= 1;
634
/* Read timeout is set in my_net_set_read_timeout */
636
pos = net->buff + net->where_b; /* net->packet -4 */
640
/* Check for error, currently assert */
641
if (net->read_timeout)
643
struct timespec waittime;
646
waittime.tv_sec= net->read_timeout;
649
memset(&backtime, 0, sizeof(struct timespec));
650
length= sizeof(struct timespec);
651
error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
655
perror("getsockopt");
658
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
659
&waittime, (socklen_t)sizeof(struct timespec));
664
for (i= 0; i < 2 ; i++)
668
/* First read is done with non blocking mode */
669
if ((long) (length= vio_read(net->vio, pos, remain)) <= 0L)
671
const bool interrupted = vio_should_retry(net->vio);
674
{ /* Probably in MIT threads */
675
if (retry_count++ < net->retry_count)
678
if (vio_errno(net->vio) == EINTR)
683
net->error= 2; /* Close socket */
684
net->last_errno= (vio_was_interrupted(net->vio) ?
685
CR_NET_READ_INTERRUPTED :
690
remain -= (uint32_t) length;
694
{ /* First parts is packet length */
697
if (net->buff[net->where_b + 3] != (unsigned char) net->pkt_nr)
700
/* Not a NET error on the client. XXX: why? */
703
net->compress_pkt_nr= ++net->pkt_nr;
707
If the packet is compressed then complen > 0 and contains the
708
number of bytes in the uncompressed packet
710
*complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
713
len=uint3korr(net->buff+net->where_b);
714
if (!len) /* End of big multi-packet */
716
helping = max(len,*complen) + net->where_b;
717
/* The necessary size of net->buff */
718
if (helping >= net->max_packet)
720
if (net_realloc(net,helping))
722
len= packet_error; /* Return error and close connection */
726
pos=net->buff + net->where_b;
727
remain = (uint32_t) len;
733
if (net->read_timeout)
734
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
735
&backtime, (socklen_t)sizeof(struct timespec));
738
net->reading_or_writing= 0;
745
Read a packet from the client/server and return it without the internal
748
If the packet is the first packet of a multi-packet packet
749
(which is indicated by the length of the packet = 0xffffff) then
750
all sub packets are read and concatenated.
752
If the packet was compressed, its uncompressed and the length of the
753
uncompressed packet is returned.
756
The function returns the length of the found packet or packet_error.
757
net->read_pos points to the read data.
761
my_net_read(NET *net)
767
len = my_real_read(net,&complen);
768
if (len == MAX_PACKET_LENGTH)
770
/* First packet of a multi-packet. Concatenate the packets */
771
uint32_t save_pos = net->where_b;
772
size_t total_length= 0;
777
len = my_real_read(net,&complen);
778
} while (len == MAX_PACKET_LENGTH);
779
if (len != packet_error)
781
net->where_b = save_pos;
783
net->read_pos = net->buff + net->where_b;
784
if (len != packet_error)
785
net->read_pos[len]=0; /* Safeguard for drizzle_use_result */
790
/* We are using the compressed protocol */
793
uint32_t start_of_packet;
794
uint32_t first_packet_offset;
795
uint32_t read_length, multi_byte_packet=0;
797
if (net->remain_in_buf)
799
buf_length= net->buf_length; /* Data left in old packet */
800
first_packet_offset= start_of_packet= (net->buf_length -
802
/* Restore the character that was overwritten by the end 0 */
803
net->buff[start_of_packet]= net->save_char;
807
/* reuse buffer, as there is nothing in it that we need */
808
buf_length= start_of_packet= first_packet_offset= 0;
814
if (buf_length - start_of_packet >= NET_HEADER_SIZE)
816
read_length = uint3korr(net->buff+start_of_packet);
819
/* End of multi-byte packet */
820
start_of_packet += NET_HEADER_SIZE;
823
if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
825
if (multi_byte_packet)
827
/* Remove packet header for second packet */
828
memmove(net->buff + first_packet_offset + start_of_packet,
829
net->buff + first_packet_offset + start_of_packet +
831
buf_length - start_of_packet);
832
start_of_packet += read_length;
833
buf_length -= NET_HEADER_SIZE;
836
start_of_packet+= read_length + NET_HEADER_SIZE;
838
if (read_length != MAX_PACKET_LENGTH) /* last package */
840
multi_byte_packet= 0; /* No last zero len packet */
843
multi_byte_packet= NET_HEADER_SIZE;
844
/* Move data down to read next data packet after current one */
845
if (first_packet_offset)
847
memmove(net->buff,net->buff+first_packet_offset,
848
buf_length-first_packet_offset);
849
buf_length-=first_packet_offset;
850
start_of_packet -= first_packet_offset;
851
first_packet_offset=0;
856
/* Move data down to read next data packet after current one */
857
if (first_packet_offset)
859
memmove(net->buff,net->buff+first_packet_offset,
860
buf_length-first_packet_offset);
861
buf_length-=first_packet_offset;
862
start_of_packet -= first_packet_offset;
863
first_packet_offset=0;
866
net->where_b=buf_length;
867
if ((packet_len = my_real_read(net,&complen)) == packet_error)
872
unsigned char * compbuf= (unsigned char *) malloc(complen);
875
uLongf tmp_complen= complen;
876
int error= uncompress((Bytef*) compbuf, &tmp_complen,
877
(Bytef*) (net->buff + net->where_b),
879
complen= tmp_complen;
883
net->error= 2; /* caller will close socket */
884
net->last_errno= CR_NET_UNCOMPRESS_ERROR;
888
memcpy((net->buff + net->where_b), compbuf, complen);
897
buf_length+= complen;
899
net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE;
900
net->buf_length= buf_length;
901
net->remain_in_buf= (uint32_t) (buf_length - start_of_packet);
902
len = ((uint32_t) (start_of_packet - first_packet_offset) - NET_HEADER_SIZE -
904
net->save_char= net->read_pos[len]; /* Must be saved */
905
net->read_pos[len]=0; /* Safeguard for drizzle_use_result */
911
void my_net_set_read_timeout(NET *net, uint32_t timeout)
913
net->read_timeout= timeout;
916
vio_timeout(net->vio, 0, timeout);
922
void my_net_set_write_timeout(NET *net, uint32_t timeout)
924
net->write_timeout= timeout;
927
vio_timeout(net->vio, 1, timeout);
932
Clear possible error state of struct NET
934
@param net clear the state of the argument
937
void net_clear_error(NET *net)
940
net->last_error[0]= '\0';
941
strcpy(net->sqlstate, sqlstate_get_not_error());