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_priv.h"
24
#include <libdrizzle/errmsg.h>
25
#include <libdrizzle/vio.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 */
552
if ((long) (length= vio_write(net->vio, pos, (size_t) (end-pos))) <= 0)
554
const bool interrupted= vio_should_retry(net->vio);
556
If we read 0, or we were interrupted this means that
557
we need to switch to blocking mode and wait until the timeout
558
on the socket kicks in.
560
if ((interrupted || length == 0))
564
while (vio_blocking(net->vio, true, &old_mode) < 0)
566
if (vio_should_retry(net->vio) && retry_count++ < net->retry_count)
568
net->error= 2; /* Close socket */
569
net->last_errno= CR_NET_PACKET_TOO_LARGE;
577
if (retry_count++ < net->retry_count)
581
if (vio_errno(net->vio) == EINTR)
585
net->error= 2; /* Close socket */
586
net->last_errno= (interrupted ? CR_NET_WRITE_INTERRUPTED :
587
CR_NET_ERROR_ON_WRITE);
593
if ((net->compress) && (packet != NULL))
594
free((char*) packet);
595
net->reading_or_writing=0;
598
if (net->write_timeout)
599
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
600
&backtime, (socklen_t)sizeof(struct timespec));
603
return(((int) (pos != end)));
608
Reads one packet to net->buff + net->where_b.
609
Long packets are handled by my_net_read().
610
This function reallocates the net->buff buffer if necessary.
613
Returns length of packet.
617
my_real_read(NET *net, size_t *complen)
621
uint32_t i,retry_count=0;
622
uint32_t len=packet_error;
623
uint32_t remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
627
/* Backup of the original SO_RCVTIMEO timeout */
628
struct timespec backtime;
634
net->reading_or_writing= 1;
635
/* Read timeout is set in my_net_set_read_timeout */
637
pos = net->buff + net->where_b; /* net->packet -4 */
641
/* Check for error, currently assert */
642
if (net->read_timeout)
644
struct timespec waittime;
647
waittime.tv_sec= net->read_timeout;
650
memset(&backtime, 0, sizeof(struct timespec));
651
length= sizeof(struct timespec);
652
error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
656
perror("getsockopt");
659
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
660
&waittime, (socklen_t)sizeof(struct timespec));
665
for (i= 0; i < 2 ; i++)
669
/* First read is done with non blocking mode */
670
if ((long) (length= vio_read(net->vio, pos, remain)) <= 0L)
672
const bool interrupted = vio_should_retry(net->vio);
675
{ /* Probably in MIT threads */
676
if (retry_count++ < net->retry_count)
679
if (vio_errno(net->vio) == EINTR)
684
net->error= 2; /* Close socket */
685
net->last_errno= (vio_was_interrupted(net->vio) ?
686
CR_NET_READ_INTERRUPTED :
691
remain -= (uint32_t) length;
695
{ /* First parts is packet length */
698
if (net->buff[net->where_b + 3] != (unsigned char) net->pkt_nr)
701
/* Not a NET error on the client. XXX: why? */
704
net->compress_pkt_nr= ++net->pkt_nr;
708
If the packet is compressed then complen > 0 and contains the
709
number of bytes in the uncompressed packet
711
*complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
714
len=uint3korr(net->buff+net->where_b);
715
if (!len) /* End of big multi-packet */
717
helping = max(len,*complen) + net->where_b;
718
/* The necessary size of net->buff */
719
if (helping >= net->max_packet)
721
if (net_realloc(net,helping))
723
len= packet_error; /* Return error and close connection */
727
pos=net->buff + net->where_b;
728
remain = (uint32_t) len;
734
if (net->read_timeout)
735
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
736
&backtime, (socklen_t)sizeof(struct timespec));
739
net->reading_or_writing= 0;
746
Read a packet from the client/server and return it without the internal
749
If the packet is the first packet of a multi-packet packet
750
(which is indicated by the length of the packet = 0xffffff) then
751
all sub packets are read and concatenated.
753
If the packet was compressed, its uncompressed and the length of the
754
uncompressed packet is returned.
757
The function returns the length of the found packet or packet_error.
758
net->read_pos points to the read data.
762
my_net_read(NET *net)
768
len = my_real_read(net,&complen);
769
if (len == MAX_PACKET_LENGTH)
771
/* First packet of a multi-packet. Concatenate the packets */
772
uint32_t save_pos = net->where_b;
773
size_t total_length= 0;
778
len = my_real_read(net,&complen);
779
} while (len == MAX_PACKET_LENGTH);
780
if (len != packet_error)
782
net->where_b = save_pos;
784
net->read_pos = net->buff + net->where_b;
785
if (len != packet_error)
786
net->read_pos[len]=0; /* Safeguard for drizzle_use_result */
791
/* We are using the compressed protocol */
794
uint32_t start_of_packet;
795
uint32_t first_packet_offset;
796
uint32_t read_length, multi_byte_packet=0;
798
if (net->remain_in_buf)
800
buf_length= net->buf_length; /* Data left in old packet */
801
first_packet_offset= start_of_packet= (net->buf_length -
803
/* Restore the character that was overwritten by the end 0 */
804
net->buff[start_of_packet]= net->save_char;
808
/* reuse buffer, as there is nothing in it that we need */
809
buf_length= start_of_packet= first_packet_offset= 0;
815
if (buf_length - start_of_packet >= NET_HEADER_SIZE)
817
read_length = uint3korr(net->buff+start_of_packet);
820
/* End of multi-byte packet */
821
start_of_packet += NET_HEADER_SIZE;
824
if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
826
if (multi_byte_packet)
828
/* Remove packet header for second packet */
829
memmove(net->buff + first_packet_offset + start_of_packet,
830
net->buff + first_packet_offset + start_of_packet +
832
buf_length - start_of_packet);
833
start_of_packet += read_length;
834
buf_length -= NET_HEADER_SIZE;
837
start_of_packet+= read_length + NET_HEADER_SIZE;
839
if (read_length != MAX_PACKET_LENGTH) /* last package */
841
multi_byte_packet= 0; /* No last zero len packet */
844
multi_byte_packet= NET_HEADER_SIZE;
845
/* Move data down to read next data packet after current one */
846
if (first_packet_offset)
848
memmove(net->buff,net->buff+first_packet_offset,
849
buf_length-first_packet_offset);
850
buf_length-=first_packet_offset;
851
start_of_packet -= first_packet_offset;
852
first_packet_offset=0;
857
/* Move data down to read next data packet after current one */
858
if (first_packet_offset)
860
memmove(net->buff,net->buff+first_packet_offset,
861
buf_length-first_packet_offset);
862
buf_length-=first_packet_offset;
863
start_of_packet -= first_packet_offset;
864
first_packet_offset=0;
867
net->where_b=buf_length;
868
if ((packet_len = my_real_read(net,&complen)) == packet_error)
873
unsigned char * compbuf= (unsigned char *) malloc(complen);
876
uLongf tmp_complen= complen;
877
int error= uncompress((Bytef*) compbuf, &tmp_complen,
878
(Bytef*) (net->buff + net->where_b),
880
complen= tmp_complen;
884
net->error= 2; /* caller will close socket */
885
net->last_errno= CR_NET_UNCOMPRESS_ERROR;
889
memcpy((net->buff + net->where_b), compbuf, complen);
898
buf_length+= complen;
900
net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE;
901
net->buf_length= buf_length;
902
net->remain_in_buf= (uint32_t) (buf_length - start_of_packet);
903
len = ((uint32_t) (start_of_packet - first_packet_offset) - NET_HEADER_SIZE -
905
net->save_char= net->read_pos[len]; /* Must be saved */
906
net->read_pos[len]=0; /* Safeguard for drizzle_use_result */
912
void my_net_set_read_timeout(NET *net, uint32_t timeout)
914
net->read_timeout= timeout;
917
vio_timeout(net->vio, 0, timeout);
923
void my_net_set_write_timeout(NET *net, uint32_t timeout)
925
net->write_timeout= timeout;
928
vio_timeout(net->vio, 1, timeout);
933
Clear possible error state of struct NET
935
@param net clear the state of the argument
938
void net_clear_error(NET *net)
941
net->last_error[0]= '\0';
942
strcpy(net->sqlstate, sqlstate_get_not_error());