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
1
/* Copyright (C) 2000 MySQL AB
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.
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.
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 */
17
HFTODO this must be hidden if we don't want client capabilities in
21
20
#include <drizzled/global.h>
22
#include "libdrizzle.h"
23
#include <libdrizzle/errmsg.h>
22
#include <drizzled/error.h>
23
#include <mysys/my_sys.h>
24
24
#include <vio/violite.h>
25
25
#include <signal.h>
27
27
#include <sys/poll.h>
31
30
The following handles the differences when this is linked between the
96
94
/* @todo: 1 and 2 codes are identical. */
98
net->last_errno= CR_NET_PACKET_TOO_LARGE;
96
net->last_errno= ER_NET_PACKET_TOO_LARGE;
101
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
99
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
103
101
We must allocate some extra bytes for the end 0 and to be able to
104
102
read big compressed blocks
106
if (!(buff= (uchar*) realloc((char*) net->buff, pkt_length +
107
NET_HEADER_SIZE + COMP_HEADER_SIZE)))
104
if (!(buff= (uchar*) my_realloc((char*) net->buff, pkt_length +
105
NET_HEADER_SIZE + COMP_HEADER_SIZE,
109
108
/* @todo: 1 and 2 codes are identical. */
111
net->last_errno= CR_OUT_OF_MEMORY;
110
net->last_errno= ER_OUT_OF_RESOURCES;
112
111
/* In the server the error is reported by MY_WME flag. */
149
Remove unwanted characters from connection
150
and check if disconnected.
152
Read from socket until there is nothing more to read. Discard
155
If there is anything when to read 'net_clear' is called this
156
normally indicates an error in the protocol.
158
When connection is properly closed (for TCP it means with
159
a FIN packet), then select() considers a socket "ready to read",
160
in the sense that there's EOF to read, but read() returns 0.
162
@param net NET handler
163
@param clear_buffer if <> 0, then clear all data from comm buff
148
Remove unwanted characters from connection
149
and check if disconnected.
151
Read from socket until there is nothing more to read. Discard
154
If there is anything when to read 'net_clear' is called this
155
normally indicates an error in the protocol.
157
When connection is properly closed (for TCP it means with
158
a FIN packet), then select() considers a socket "ready to read",
159
in the sense that there's EOF to read, but read() returns 0.
161
@param net NET handler
162
@param clear_buffer if <> 0, then clear all data from comm buff
166
165
void net_clear(NET *net, bool clear_buffer)
205
204
/*****************************************************************************
206
** Write something to server/client buffer
207
*****************************************************************************/
205
** Write something to server/client buffer
206
*****************************************************************************/
210
Write a logical packet with packet header.
212
Format: Packet length (3 bytes), packet number(1 byte)
213
When compression is used a 3 byte compression length is added
216
If compression is used the original package is modified!
209
Write a logical packet with packet header.
211
Format: Packet length (3 bytes), packet number(1 byte)
212
When compression is used a 3 byte compression length is added
215
If compression is used the original package is modified!
250
Send a command to the server.
252
The reason for having both header and packet is so that libdrizzle
253
can easy add a header to a special command (like prepared statements)
254
without having to re-alloc the string.
256
As the command is part of the first data packet, we have to do some data
257
juggling to put the command in there, without having to create a new
260
This function will split big packets into sub-packets if needed.
261
(Each sub packet can only be 2^24 bytes)
263
@param net NET handler
264
@param command Command in MySQL server (enum enum_server_command)
265
@param header Header to write after command
266
@param head_len Length of header
267
@param packet Query or parameter to query
268
@param len Length of packet
249
Send a command to the server.
251
The reason for having both header and packet is so that libdrizzle
252
can easy add a header to a special command (like prepared statements)
253
without having to re-alloc the string.
255
As the command is part of the first data packet, we have to do some data
256
juggling to put the command in there, without having to create a new
259
This function will split big packets into sub-packets if needed.
260
(Each sub packet can only be 2^24 bytes)
262
@param net NET handler
263
@param command Command in MySQL server (enum enum_server_command)
264
@param header Header to write after command
265
@param head_len Length of header
266
@param packet Query or parameter to query
267
@param len Length of packet
277
276
net_write_command(NET *net,uchar command,
278
const uchar *header, size_t head_len,
279
const uchar *packet, size_t len)
277
const uchar *header, size_t head_len,
278
const uchar *packet, size_t len)
281
uint32_t length=len+1+head_len; /* 1 extra byte for command */
280
uint32_t length=len+1+head_len; /* 1 extra byte for command */
282
281
uchar buff[NET_HEADER_SIZE+1];
283
282
uint header_size=NET_HEADER_SIZE+1;
285
buff[4]=command; /* For first packet */
284
buff[4]=command; /* For first packet */
287
286
if (length >= MAX_PACKET_LENGTH)
293
292
int3store(buff, MAX_PACKET_LENGTH);
294
293
buff[3]= (uchar) net->pkt_nr++;
295
294
if (net_write_buff(net, buff, header_size) ||
296
net_write_buff(net, header, head_len) ||
297
net_write_buff(net, packet, len))
295
net_write_buff(net, header, head_len) ||
296
net_write_buff(net, packet, len))
300
299
length-= MAX_PACKET_LENGTH;
301
300
len= MAX_PACKET_LENGTH;
303
302
header_size= NET_HEADER_SIZE;
304
303
} while (length >= MAX_PACKET_LENGTH);
305
len=length; /* Data left to be written */
304
len=length; /* Data left to be written */
307
306
int3store(buff,length);
308
307
buff[3]= (uchar) net->pkt_nr++;
309
308
return(test(net_write_buff(net, buff, header_size) ||
310
(head_len && net_write_buff(net, header, head_len)) ||
311
net_write_buff(net, packet, len) || net_flush(net)));
309
(head_len && net_write_buff(net, header, head_len)) ||
310
net_write_buff(net, packet, len) || net_flush(net)));
315
Caching the data in a local buffer before sending it.
314
Caching the data in a local buffer before sending it.
317
316
Fill up net->buffer and send it to the client when full.
319
If the rest of the to-be-sent-packet is bigger than buffer,
320
send it in one big block (to avoid copying to internal buffer).
321
If not, copy the rest of the data to the buffer and return without
324
@param net Network handler
325
@param packet Packet to send
326
@param len Length of packet
329
The cached buffer can be sent as it is with 'net_flush()'.
330
In this code we have to be careful to not send a packet longer than
331
MAX_PACKET_LENGTH to net_real_write() if we are using the compressed
332
protocol as we store the length of the compressed packet in 3 bytes.
318
If the rest of the to-be-sent-packet is bigger than buffer,
319
send it in one big block (to avoid copying to internal buffer).
320
If not, copy the rest of the data to the buffer and return without
323
@param net Network handler
324
@param packet Packet to send
325
@param len Length of packet
328
The cached buffer can be sent as it is with 'net_flush()'.
329
In this code we have to be careful to not send a packet longer than
330
MAX_PACKET_LENGTH to net_real_write() if we are using the compressed
331
protocol as we store the length of the compressed packet in 3 bytes.
418
417
const uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
419
if (!(b= (uchar*) malloc(len + NET_HEADER_SIZE +
418
if (!(b= (uchar*) my_malloc(len + NET_HEADER_SIZE +
419
COMP_HEADER_SIZE, MYF(MY_WME))))
423
net->last_errno= CR_OUT_OF_MEMORY;
422
net->last_errno= ER_OUT_OF_RESOURCES;
424
423
/* In the server, the error is reported by MY_WME flag. */
425
424
net->reading_or_writing= 0;
428
427
memcpy(b+header_length,packet,len);
430
complen= len * 120 / 100 + 12;
431
unsigned char * compbuf= (unsigned char *) malloc(complen);
434
uLongf tmp_complen= complen;
435
int res= compress((Bytef*) compbuf, &tmp_complen,
436
(Bytef*) (b+header_length),
438
complen= tmp_complen;
442
if ((res != Z_OK) || (complen >= len))
446
size_t tmplen= complen;
429
if (my_compress(b+header_length, &len, &complen))
455
431
int3store(&b[NET_HEADER_SIZE],complen);
456
432
int3store(b,len);
457
433
b[3]=(uchar) (net->compress_pkt_nr++);
471
447
memset(&backtime, 0, sizeof(struct timeval));
472
448
length= sizeof(struct timeval);
473
error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
449
error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
474
450
&backtime, &length);
477
453
perror("getsockopt");
478
454
assert(error == 0);
480
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
456
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
481
457
&waittime, (socklen_t)sizeof(struct timeval));
482
458
assert(error == 0);
514
490
if (retry_count++ < net->retry_count)
518
494
if (vio_errno(net->vio) == SOCKET_EINTR)
522
net->error= 2; /* Close socket */
523
net->last_errno= (interrupted ? CR_NET_WRITE_INTERRUPTED :
524
CR_NET_ERROR_ON_WRITE);
498
net->error= 2; /* Close socket */
499
net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED :
500
ER_NET_ERROR_ON_WRITE);
528
504
update_statistics(thd_increment_bytes_sent(length));
531
if ((net->compress) && (packet != NULL))
532
free((char*) packet);
508
my_free((char*) packet,MYF(0));
533
509
net->reading_or_writing=0;
535
511
if (net->write_timeout)
536
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
512
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
537
513
&backtime, (socklen_t)sizeof(struct timeval));
539
515
return(((int) (pos != end)));
582
558
memset(&backtime, 0, sizeof(struct timeval));
583
559
length= sizeof(struct timeval);
584
error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
560
error= getsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
585
561
&backtime, &length);
588
564
perror("getsockopt");
589
565
assert(error == 0);
591
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
567
error= setsockopt(net->vio->sd, SOL_SOCKET, SO_RCVTIMEO,
592
568
&waittime, (socklen_t)sizeof(struct timeval));
593
569
assert(error == 0);
676
Read a packet from the client/server and return it without the internal
679
If the packet is the first packet of a multi-packet packet
680
(which is indicated by the length of the packet = 0xffffff) then
681
all sub packets are read and concatenated.
683
If the packet was compressed, its uncompressed and the length of the
684
uncompressed packet is returned.
687
The function returns the length of the found packet or packet_error.
688
net->read_pos points to the read data.
652
Read a packet from the client/server and return it without the internal
655
If the packet is the first packet of a multi-packet packet
656
(which is indicated by the length of the packet = 0xffffff) then
657
all sub packets are read and concatenated.
659
If the packet was compressed, its uncompressed and the length of the
660
uncompressed packet is returned.
663
The function returns the length of the found packet or packet_error.
664
net->read_pos points to the read data.
745
721
if (buf_length - start_of_packet >= NET_HEADER_SIZE)
747
read_length = uint3korr(net->buff+start_of_packet);
750
/* End of multi-byte packet */
751
start_of_packet += NET_HEADER_SIZE;
754
if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
756
if (multi_byte_packet)
758
/* Remove packet header for second packet */
759
memmove(net->buff + first_packet_offset + start_of_packet,
760
net->buff + first_packet_offset + start_of_packet +
762
buf_length - start_of_packet);
763
start_of_packet += read_length;
764
buf_length -= NET_HEADER_SIZE;
767
start_of_packet+= read_length + NET_HEADER_SIZE;
723
read_length = uint3korr(net->buff+start_of_packet);
726
/* End of multi-byte packet */
727
start_of_packet += NET_HEADER_SIZE;
730
if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
732
if (multi_byte_packet)
734
/* Remove packet header for second packet */
735
memmove(net->buff + first_packet_offset + start_of_packet,
736
net->buff + first_packet_offset + start_of_packet +
738
buf_length - start_of_packet);
739
start_of_packet += read_length;
740
buf_length -= NET_HEADER_SIZE;
743
start_of_packet+= read_length + NET_HEADER_SIZE;
769
if (read_length != MAX_PACKET_LENGTH) /* last package */
771
multi_byte_packet= 0; /* No last zero len packet */
774
multi_byte_packet= NET_HEADER_SIZE;
775
/* Move data down to read next data packet after current one */
776
if (first_packet_offset)
778
memmove(net->buff,net->buff+first_packet_offset,
779
buf_length-first_packet_offset);
780
buf_length-=first_packet_offset;
781
start_of_packet -= first_packet_offset;
782
first_packet_offset=0;
745
if (read_length != MAX_PACKET_LENGTH) /* last package */
747
multi_byte_packet= 0; /* No last zero len packet */
750
multi_byte_packet= NET_HEADER_SIZE;
751
/* Move data down to read next data packet after current one */
752
if (first_packet_offset)
754
memmove(net->buff,net->buff+first_packet_offset,
755
buf_length-first_packet_offset);
756
buf_length-=first_packet_offset;
757
start_of_packet -= first_packet_offset;
758
first_packet_offset=0;
787
763
/* Move data down to read next data packet after current one */
788
764
if (first_packet_offset)
790
memmove(net->buff,net->buff+first_packet_offset,
791
buf_length-first_packet_offset);
792
buf_length-=first_packet_offset;
793
start_of_packet -= first_packet_offset;
794
first_packet_offset=0;
766
memmove(net->buff,net->buff+first_packet_offset,
767
buf_length-first_packet_offset);
768
buf_length-=first_packet_offset;
769
start_of_packet -= first_packet_offset;
770
first_packet_offset=0;
797
773
net->where_b=buf_length;
798
774
if ((packet_len = my_real_read(net,&complen)) == packet_error)
776
if (my_uncompress(net->buff + net->where_b, packet_len,
803
unsigned char * compbuf= (unsigned char *) malloc(complen);
806
uLongf tmp_complen= complen;
807
int error= uncompress((Bytef*) compbuf, &tmp_complen,
808
(Bytef*) (net->buff + net->where_b),
810
complen= tmp_complen;
814
net->error= 2; /* caller will close socket */
815
net->last_errno= CR_NET_UNCOMPRESS_ERROR;
819
memcpy((net->buff + net->where_b), compbuf, complen);
779
net->error= 2; /* caller will close socket */
780
net->last_errno= ER_NET_UNCOMPRESS_ERROR;
783
buf_length+= complen;
828
buf_length+= complen;
830
786
net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE;
831
787
net->buf_length= buf_length;
832
788
net->remain_in_buf= (uint32_t) (buf_length - start_of_packet);
833
789
len = ((uint32_t) (start_of_packet - first_packet_offset) - NET_HEADER_SIZE -
834
790
multi_byte_packet);
835
net->save_char= net->read_pos[len]; /* Must be saved */
836
net->read_pos[len]=0; /* Safeguard for drizzle_use_result */
791
net->save_char= net->read_pos[len]; /* Must be saved */
792
net->read_pos[len]=0; /* Safeguard for drizzle_use_result */
842
798
void my_net_set_read_timeout(NET *net, uint timeout)