00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include <drizzled/current_session.h>
00024 #include <drizzled/error.h>
00025 #include <drizzled/session.h>
00026
00027 #include <assert.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <signal.h>
00032 #include <errno.h>
00033 #include <sys/socket.h>
00034 #include <sys/poll.h>
00035 #include <zlib.h>
00036 #include <algorithm>
00037
00038 #include "errmsg.h"
00039 #include "vio.h"
00040 #include "net_serv.h"
00041
00042 namespace drizzle_plugin
00043 {
00044
00045 using namespace std;
00046 using namespace drizzled;
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #define NET_HEADER_SIZE 4
00059 #define COMP_HEADER_SIZE 3
00060
00061 #define MAX_PACKET_LENGTH (256L*256L*256L-1)
00062 const char *not_error_sqlstate= "00000";
00063
00064 static bool net_write_buff(NET *net, const unsigned char *packet, uint32_t len);
00065 static int drizzleclient_net_real_write(NET *net, const unsigned char *packet, size_t len);
00066
00069 bool drizzleclient_net_init(NET *net, Vio* vio, uint32_t buffer_length)
00070 {
00071 net->vio = vio;
00072 net->max_packet= (uint32_t) buffer_length;
00073 net->max_packet_size= max(buffer_length, drizzled::global_system_variables.max_allowed_packet);
00074
00075 if (!(net->buff=(unsigned char*) malloc((size_t) net->max_packet+
00076 NET_HEADER_SIZE + COMP_HEADER_SIZE)))
00077 return(1);
00078 net->buff_end=net->buff+net->max_packet;
00079 net->error=0; net->return_status=0;
00080 net->pkt_nr=net->compress_pkt_nr=0;
00081 net->write_pos=net->read_pos = net->buff;
00082 net->last_error[0]=0;
00083 net->compress=0; net->reading_or_writing=0;
00084 net->where_b = net->remain_in_buf=0;
00085 net->last_errno=0;
00086 net->unused= 0;
00087
00088 if (vio != 0)
00089 {
00090 net->fd = vio->get_fd();
00091 vio->fastsend();
00092 }
00093 return(0);
00094 }
00095
00096 bool drizzleclient_net_init_sock(NET * net, int sock, uint32_t buffer_length)
00097 {
00098 Vio *vio_tmp= new Vio(sock);
00099 if (vio_tmp == NULL)
00100 {
00101 return true;
00102 }
00103 else
00104 if (drizzleclient_net_init(net, vio_tmp, buffer_length))
00105 {
00106
00107
00108
00109 if (vio_tmp && (net->vio != vio_tmp))
00110 {
00111 delete vio_tmp;
00112 }
00113 else
00114 {
00115 (void) shutdown(sock, SHUT_RDWR);
00116 (void) close(sock);
00117 }
00118 return true;
00119 }
00120 return false;
00121 }
00122
00123 void drizzleclient_net_end(NET *net)
00124 {
00125 if (net->buff != NULL)
00126 free(net->buff);
00127 net->buff= NULL;
00128 return;
00129 }
00130
00131 void drizzleclient_net_close(NET *net)
00132 {
00133 drizzled::safe_delete(net->vio);
00134 }
00135
00136 bool drizzleclient_net_peer_addr(NET *net, char *buf, uint16_t *port, size_t buflen)
00137 {
00138 return net->vio->peer_addr(buf, port, buflen);
00139 }
00140
00141 void drizzleclient_net_keepalive(NET *net, bool flag)
00142 {
00143 net->vio->keepalive(flag);
00144 }
00145
00146 int drizzleclient_net_get_sd(NET *net)
00147 {
00148 return net->vio->get_fd();
00149 }
00150
00151 bool drizzleclient_net_more_data(NET *net)
00152 {
00153 return (net->vio == 0 || net->vio->get_read_pos() < net->vio->get_read_end());
00154 }
00155
00158 static bool drizzleclient_net_realloc(NET *net, size_t length)
00159 {
00160 unsigned char *buff;
00161 size_t pkt_length;
00162
00163 if (length >= net->max_packet_size)
00164 {
00165
00166 net->error= 3;
00167 net->last_errno= ER_NET_PACKET_TOO_LARGE;
00168 my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
00169 return(1);
00170 }
00171 pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
00172
00173
00174
00175
00176 if (!(buff= (unsigned char*) realloc((char*) net->buff, pkt_length +
00177 NET_HEADER_SIZE + COMP_HEADER_SIZE)))
00178 {
00179
00180 net->error= 1;
00181 net->last_errno= CR_OUT_OF_MEMORY;
00182
00183 return(1);
00184 }
00185 net->buff=net->write_pos=buff;
00186 net->buff_end=buff+(net->max_packet= (uint32_t) pkt_length);
00187 return(0);
00188 }
00189
00190
00204 static bool net_data_is_ready(int sd)
00205 {
00206 struct pollfd ufds;
00207 int res;
00208
00209 ufds.fd= sd;
00210 ufds.events= POLLIN | POLLPRI;
00211 if (!(res= poll(&ufds, 1, 0)))
00212 return 0;
00213 if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
00214 return 0;
00215 return 1;
00216 }
00217
00236 void drizzleclient_net_clear(NET *net, bool clear_buffer)
00237 {
00238 if (clear_buffer)
00239 {
00240 while (net_data_is_ready(net->vio->get_fd()) > 0)
00241 {
00242
00243 if (net->vio->read(net->buff, (size_t) net->max_packet) <= 0)
00244 {
00245 net->error= 2;
00246 break;
00247 }
00248 }
00249 }
00250 net->pkt_nr=net->compress_pkt_nr=0;
00251 net->write_pos=net->buff;
00252 return;
00253 }
00254
00255
00258 bool drizzleclient_net_flush(NET *net)
00259 {
00260 bool error= 0;
00261 if (net->buff != net->write_pos)
00262 {
00263 error=drizzleclient_net_real_write(net, net->buff,
00264 (size_t) (net->write_pos - net->buff)) ? 1 : 0;
00265 net->write_pos=net->buff;
00266 }
00267
00268 if (net->compress)
00269 net->pkt_nr=net->compress_pkt_nr;
00270 return(error);
00271 }
00272
00273
00274
00275
00276
00277
00288 bool
00289 drizzleclient_net_write(NET *net,const unsigned char *packet,size_t len)
00290 {
00291 unsigned char buff[NET_HEADER_SIZE];
00292 if (unlikely(!net->vio))
00293 return 0;
00294
00295
00296
00297
00298
00299 while (len >= MAX_PACKET_LENGTH)
00300 {
00301 const uint32_t z_size = MAX_PACKET_LENGTH;
00302 int3store(buff, z_size);
00303 buff[3]= (unsigned char) net->pkt_nr++;
00304 if (net_write_buff(net, buff, NET_HEADER_SIZE) ||
00305 net_write_buff(net, packet, z_size))
00306 return 1;
00307 packet += z_size;
00308 len-= z_size;
00309 }
00310
00311 int3store(buff,len);
00312 buff[3]= (unsigned char) net->pkt_nr++;
00313 if (net_write_buff(net, buff, NET_HEADER_SIZE))
00314 return 1;
00315 return net_write_buff(net,packet,len) ? 1 : 0;
00316 }
00317
00345 bool
00346 drizzleclient_net_write_command(NET *net,unsigned char command,
00347 const unsigned char *header, size_t head_len,
00348 const unsigned char *packet, size_t len)
00349 {
00350 uint32_t length=len+1+head_len;
00351 unsigned char buff[NET_HEADER_SIZE+1];
00352 uint32_t header_size=NET_HEADER_SIZE+1;
00353
00354 buff[4]=command;
00355
00356 if (length >= MAX_PACKET_LENGTH)
00357 {
00358
00359 len= MAX_PACKET_LENGTH - 1 - head_len;
00360 do
00361 {
00362 int3store(buff, MAX_PACKET_LENGTH);
00363 buff[3]= (unsigned char) net->pkt_nr++;
00364 if (net_write_buff(net, buff, header_size) ||
00365 net_write_buff(net, header, head_len) ||
00366 net_write_buff(net, packet, len))
00367 return(1);
00368 packet+= len;
00369 length-= MAX_PACKET_LENGTH;
00370 len= MAX_PACKET_LENGTH;
00371 head_len= 0;
00372 header_size= NET_HEADER_SIZE;
00373 } while (length >= MAX_PACKET_LENGTH);
00374 len=length;
00375 }
00376 int3store(buff,length);
00377 buff[3]= (unsigned char) net->pkt_nr++;
00378 return((net_write_buff(net, buff, header_size) ||
00379 (head_len && net_write_buff(net, header, head_len)) ||
00380 net_write_buff(net, packet, len) || drizzleclient_net_flush(net)) ? 1 : 0 );
00381 }
00382
00409 static bool
00410 net_write_buff(NET *net, const unsigned char *packet, uint32_t len)
00411 {
00412 uint32_t left_length;
00413 if (net->compress && net->max_packet > MAX_PACKET_LENGTH)
00414 left_length= MAX_PACKET_LENGTH - (net->write_pos - net->buff);
00415 else
00416 left_length= (uint32_t) (net->buff_end - net->write_pos);
00417
00418 if (len > left_length)
00419 {
00420 if (net->write_pos != net->buff)
00421 {
00422
00423 memcpy(net->write_pos,packet,left_length);
00424 if (drizzleclient_net_real_write(net, net->buff,
00425 (size_t) (net->write_pos - net->buff) + left_length))
00426 return 1;
00427 net->write_pos= net->buff;
00428 packet+= left_length;
00429 len-= left_length;
00430 }
00431 if (net->compress)
00432 {
00433
00434
00435
00436
00437 left_length= MAX_PACKET_LENGTH;
00438 while (len > left_length)
00439 {
00440 if (drizzleclient_net_real_write(net, packet, left_length))
00441 return 1;
00442 packet+= left_length;
00443 len-= left_length;
00444 }
00445 }
00446 if (len > net->max_packet)
00447 return drizzleclient_net_real_write(net, packet, len) ? 1 : 0;
00448
00449 }
00450 memcpy(net->write_pos,packet,len);
00451 net->write_pos+= len;
00452 return 0;
00453 }
00454
00455
00464
00465
00466
00467
00468 static int
00469 drizzleclient_net_real_write(NET *net, const unsigned char *packet, size_t len)
00470 {
00471 size_t length;
00472 const unsigned char *pos, *end;
00473 uint32_t retry_count= 0;
00474
00475
00476
00477 if (net->error == 2)
00478 return(-1);
00479
00480 net->reading_or_writing=2;
00481 if (net->compress)
00482 {
00483 size_t complen;
00484 unsigned char *b;
00485 const uint32_t header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
00486 if (!(b= (unsigned char*) malloc(len + NET_HEADER_SIZE +
00487 COMP_HEADER_SIZE)))
00488 {
00489 net->error= 2;
00490 net->last_errno= CR_OUT_OF_MEMORY;
00491
00492 net->reading_or_writing= 0;
00493 return(1);
00494 }
00495 memcpy(b+header_length,packet,len);
00496
00497 complen= len * 120 / 100 + 12;
00498 unsigned char * compbuf= (unsigned char *) malloc(complen);
00499 if (compbuf != NULL)
00500 {
00501 uLongf tmp_complen= complen;
00502 int res= compress((Bytef*) compbuf, &tmp_complen,
00503 (Bytef*) (b+header_length),
00504 len);
00505 complen= tmp_complen;
00506
00507 free(compbuf);
00508
00509 if ((res != Z_OK) || (complen >= len))
00510 complen= 0;
00511 else
00512 {
00513 size_t tmplen= complen;
00514 complen= len;
00515 len= tmplen;
00516 }
00517 }
00518 else
00519 {
00520 complen=0;
00521 }
00522 int3store(&b[NET_HEADER_SIZE],complen);
00523 int3store(b,len);
00524 b[3]=(unsigned char) (net->compress_pkt_nr++);
00525 len+= header_length;
00526 packet= b;
00527 }
00528
00529 pos= packet;
00530 end=pos+len;
00531
00532 while (pos != end)
00533 {
00534 assert(pos);
00535
00536 if ((long) (length= net->vio->write( pos, (size_t) (end-pos))) <= 0)
00537 {
00538
00539
00540
00541
00542
00543 if (net->vio == NULL)
00544 break;
00545
00546 const bool interrupted= net->vio->should_retry();
00547
00548
00549
00550
00551
00552 if ((interrupted || length == 0))
00553 {
00554 bool old_mode;
00555
00556 while (net->vio->blocking(true, &old_mode) < 0)
00557 {
00558 if (net->vio->should_retry() && retry_count++ < net->retry_count)
00559 continue;
00560 net->error= 2;
00561 net->last_errno= ER_NET_PACKET_TOO_LARGE;
00562 my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
00563 goto end;
00564 }
00565 retry_count=0;
00566 continue;
00567 }
00568 else
00569 {
00570 if (retry_count++ < net->retry_count)
00571 continue;
00572 }
00573
00574 if (net->vio->get_errno() == EINTR)
00575 {
00576 continue;
00577 }
00578 net->error= 2;
00579 net->last_errno= (interrupted ? CR_NET_WRITE_INTERRUPTED :
00580 CR_NET_ERROR_ON_WRITE);
00581 break;
00582 }
00583 pos+=length;
00584
00585
00586 if (current_session)
00587 current_session->status_var.bytes_sent+= length;
00588 }
00589 end:
00590 if ((net->compress) && (packet != NULL))
00591 free((char*) packet);
00592 net->reading_or_writing=0;
00593
00594 return(((int) (pos != end)));
00595 }
00596
00597
00607 static uint32_t
00608 my_real_read(NET *net, size_t *complen)
00609 {
00610 unsigned char *pos;
00611 size_t length= 0;
00612 uint32_t i,retry_count=0;
00613 size_t len=packet_error;
00614 uint32_t remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
00615 NET_HEADER_SIZE);
00616
00617 *complen = 0;
00618
00619 net->reading_or_writing= 1;
00620
00621
00622 pos = net->buff + net->where_b;
00623
00624 for (i= 0; i < 2 ; i++)
00625 {
00626 while (remain > 0)
00627 {
00628
00629 if ((long) (length= net->vio->read(pos, remain)) <= 0L)
00630 {
00631 if (net->vio == NULL)
00632 goto end;
00633
00634 const bool interrupted = net->vio->should_retry();
00635
00636 if (interrupted)
00637 {
00638 if (retry_count++ < net->retry_count)
00639 continue;
00640 }
00641 if (net->vio->get_errno() == EINTR)
00642 {
00643 continue;
00644 }
00645 len= packet_error;
00646 net->error= 2;
00647 net->last_errno= (net->vio->was_interrupted() ?
00648 CR_NET_READ_INTERRUPTED :
00649 CR_NET_READ_ERROR);
00650 goto end;
00651 }
00652 remain -= (uint32_t) length;
00653 pos+= length;
00654 current_session->status_var.bytes_received+= length;
00655 }
00656 if (i == 0)
00657 {
00658 uint32_t helping;
00659
00660 if (net->buff[net->where_b + 3] != (unsigned char) net->pkt_nr)
00661 {
00662 len= packet_error;
00663
00664 my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0));
00665 goto end;
00666 }
00667 net->compress_pkt_nr= ++net->pkt_nr;
00668 if (net->compress)
00669 {
00670
00671
00672
00673
00674 *complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
00675 }
00676
00677 len=uint3korr(net->buff+net->where_b);
00678 if (!len)
00679 goto end;
00680 helping = max(len,*complen) + net->where_b;
00681
00682 if (helping >= net->max_packet)
00683 {
00684 if (drizzleclient_net_realloc(net,helping))
00685 {
00686
00687 while (len > 0)
00688 {
00689 length= read(net->vio->get_fd(), net->buff, min((size_t)net->max_packet, len));
00690 assert((long)length > 0L);
00691 len-= length;
00692 }
00693
00694 len= packet_error;
00695 goto end;
00696 }
00697 }
00698 pos=net->buff + net->where_b;
00699 remain = (uint32_t) len;
00700 }
00701 }
00702
00703 end:
00704 net->reading_or_writing= 0;
00705
00706 return(len);
00707 }
00708
00709
00726 uint32_t
00727 drizzleclient_net_read(NET *net)
00728 {
00729 size_t len, complen;
00730
00731 if (!net->compress)
00732 {
00733 len = my_real_read(net,&complen);
00734 if (len == MAX_PACKET_LENGTH)
00735 {
00736
00737 uint32_t save_pos = net->where_b;
00738 size_t total_length= 0;
00739 do
00740 {
00741 net->where_b += len;
00742 total_length += len;
00743 len = my_real_read(net,&complen);
00744 } while (len == MAX_PACKET_LENGTH);
00745 if (len != packet_error)
00746 len+= total_length;
00747 net->where_b = save_pos;
00748 }
00749 net->read_pos = net->buff + net->where_b;
00750 if (len != packet_error)
00751 net->read_pos[len]=0;
00752 return len;
00753 }
00754 else
00755 {
00756
00757
00758 uint32_t buf_length;
00759 uint32_t start_of_packet;
00760 uint32_t first_packet_offset;
00761 uint32_t read_length, multi_byte_packet=0;
00762
00763 if (net->remain_in_buf)
00764 {
00765 buf_length= net->buf_length;
00766 first_packet_offset= start_of_packet= (net->buf_length -
00767 net->remain_in_buf);
00768
00769 net->buff[start_of_packet]= net->save_char;
00770 }
00771 else
00772 {
00773
00774 buf_length= start_of_packet= first_packet_offset= 0;
00775 }
00776 for (;;)
00777 {
00778 uint32_t packet_len;
00779
00780 if (buf_length - start_of_packet >= NET_HEADER_SIZE)
00781 {
00782 read_length = uint3korr(net->buff+start_of_packet);
00783 if (!read_length)
00784 {
00785
00786 start_of_packet += NET_HEADER_SIZE;
00787 break;
00788 }
00789 if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
00790 {
00791 if (multi_byte_packet)
00792 {
00793
00794 memmove(net->buff + first_packet_offset + start_of_packet,
00795 net->buff + first_packet_offset + start_of_packet +
00796 NET_HEADER_SIZE,
00797 buf_length - start_of_packet);
00798 start_of_packet += read_length;
00799 buf_length -= NET_HEADER_SIZE;
00800 }
00801 else
00802 start_of_packet+= read_length + NET_HEADER_SIZE;
00803
00804 if (read_length != MAX_PACKET_LENGTH)
00805 {
00806 multi_byte_packet= 0;
00807 break;
00808 }
00809 multi_byte_packet= NET_HEADER_SIZE;
00810
00811 if (first_packet_offset)
00812 {
00813 memmove(net->buff,net->buff+first_packet_offset,
00814 buf_length-first_packet_offset);
00815 buf_length-=first_packet_offset;
00816 start_of_packet -= first_packet_offset;
00817 first_packet_offset=0;
00818 }
00819 continue;
00820 }
00821 }
00822
00823 if (first_packet_offset)
00824 {
00825 memmove(net->buff,net->buff+first_packet_offset,
00826 buf_length-first_packet_offset);
00827 buf_length-=first_packet_offset;
00828 start_of_packet -= first_packet_offset;
00829 first_packet_offset=0;
00830 }
00831
00832 net->where_b=buf_length;
00833 if ((packet_len = my_real_read(net,&complen)) == packet_error)
00834 return packet_error;
00835
00836 if (complen)
00837 {
00838 unsigned char * compbuf= (unsigned char *) malloc(complen);
00839 if (compbuf != NULL)
00840 {
00841 uLongf tmp_complen= complen;
00842 int error= uncompress((Bytef*) compbuf, &tmp_complen,
00843 (Bytef*) (net->buff + net->where_b),
00844 (uLong)packet_len);
00845 complen= tmp_complen;
00846
00847 if (error != Z_OK)
00848 {
00849 net->error= 2;
00850 net->last_errno= CR_NET_UNCOMPRESS_ERROR;
00851 }
00852 else
00853 {
00854 memcpy((net->buff + net->where_b), compbuf, complen);
00855 }
00856 free(compbuf);
00857 }
00858 }
00859 else
00860 {
00861 complen= packet_len;
00862 }
00863
00864 }
00865 buf_length+= complen;
00866
00867 net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE;
00868 net->buf_length= buf_length;
00869 net->remain_in_buf= (uint32_t) (buf_length - start_of_packet);
00870 len = ((uint32_t) (start_of_packet - first_packet_offset) - NET_HEADER_SIZE -
00871 multi_byte_packet);
00872 net->save_char= net->read_pos[len];
00873 net->read_pos[len]=0;
00874 }
00875 return len;
00876 }
00877
00878
00879 void drizzleclient_net_set_read_timeout(NET *net, uint32_t timeout)
00880 {
00881 net->read_timeout= timeout;
00882 #ifndef __sun
00883 if (net->vio)
00884 net->vio->timeout(0, timeout);
00885 #endif
00886 return;
00887 }
00888
00889
00890 void drizzleclient_net_set_write_timeout(NET *net, uint32_t timeout)
00891 {
00892 net->write_timeout= timeout;
00893 #ifndef __sun
00894 if (net->vio)
00895 net->vio->timeout(1, timeout);
00896 #endif
00897 return;
00898 }
00905 void drizzleclient_drizzleclient_net_clear_error(NET *net)
00906 {
00907 net->last_errno= 0;
00908 net->last_error[0]= '\0';
00909 strcpy(net->sqlstate, not_error_sqlstate);
00910 }
00911
00912 }