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 #include <drizzled/statistics_variables.h>
00027 #include <drizzled/system_variables.h>
00028
00029 #include <assert.h>
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <signal.h>
00034 #include <errno.h>
00035 #include <sys/socket.h>
00036 #include <sys/poll.h>
00037 #include <zlib.h>
00038 #include <algorithm>
00039
00040 #include "errmsg.h"
00041 #include "vio.h"
00042 #include "net_serv.h"
00043
00044 namespace drizzle_plugin {
00045
00046 using namespace std;
00047 using namespace drizzled;
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #define NET_HEADER_SIZE 4
00060 #define COMP_HEADER_SIZE 3
00061
00062 #define MAX_PACKET_LENGTH (256L*256L*256L-1)
00063
00064 static bool net_write_buff(NET*, const void*, uint32_t len);
00065 static int drizzleclient_net_real_write(NET *net, const unsigned char *packet, size_t len);
00066
00069 void NET::init(int sock, uint32_t buffer_length)
00070 {
00071 vio= new Vio(sock);
00072 max_packet= (uint32_t) buffer_length;
00073 max_packet_size= max(buffer_length, drizzled::global_system_variables.max_allowed_packet);
00074
00075 buff= (unsigned char*) malloc((size_t) max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE);
00076 buff_end= buff + max_packet;
00077 error_= 0;
00078 pkt_nr= compress_pkt_nr= 0;
00079 write_pos= read_pos= buff;
00080 compress= 0;
00081 where_b= remain_in_buf= 0;
00082 last_errno= 0;
00083 vio->fastsend();
00084 }
00085
00086 void NET::end()
00087 {
00088 free(buff);
00089 buff= NULL;
00090 }
00091
00092 void NET::close()
00093 {
00094 drizzled::safe_delete(vio);
00095 }
00096
00097 bool NET::peer_addr(char *buf, size_t buflen, uint16_t& port)
00098 {
00099 return vio->peer_addr(buf, buflen, port);
00100 }
00101
00102 void NET::keepalive(bool flag)
00103 {
00104 vio->keepalive(flag);
00105 }
00106
00107 int NET::get_sd() const
00108 {
00109 return vio->get_fd();
00110 }
00111
00114 static bool drizzleclient_net_realloc(NET *net, size_t length)
00115 {
00116 if (length >= net->max_packet_size)
00117 {
00118
00119 net->error_= 3;
00120 net->last_errno= ER_NET_PACKET_TOO_LARGE;
00121 my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
00122 return 1;
00123 }
00124 size_t pkt_length = (length + IO_SIZE - 1) & ~(IO_SIZE - 1);
00125
00126
00127
00128
00129 unsigned char* buff= (unsigned char*)realloc((char*) net->buff, pkt_length + NET_HEADER_SIZE + COMP_HEADER_SIZE);
00130 net->buff=net->write_pos= buff;
00131 net->buff_end= buff + (net->max_packet= (uint32_t) pkt_length);
00132 return 0;
00133 }
00134
00135 bool NET::flush()
00136 {
00137 bool error= false;
00138 if (buff != write_pos)
00139 {
00140 error= drizzleclient_net_real_write(this, buff, write_pos - buff) ? true : false;
00141 write_pos= buff;
00142 }
00143
00144 if (compress)
00145 pkt_nr= compress_pkt_nr;
00146 return error;
00147 }
00148
00149
00150
00151
00152
00153
00164 static bool
00165 drizzleclient_net_write(NET* net, const void* packet0, size_t len)
00166 {
00167 const unsigned char* packet= reinterpret_cast<const unsigned char*>(packet0);
00168 unsigned char buff[NET_HEADER_SIZE];
00169 if (unlikely(!net->vio))
00170 return 0;
00171
00172
00173
00174
00175
00176 while (len >= MAX_PACKET_LENGTH)
00177 {
00178 const uint32_t z_size = MAX_PACKET_LENGTH;
00179 int3store(buff, z_size);
00180 buff[3]= (unsigned char) net->pkt_nr++;
00181 if (net_write_buff(net, buff, NET_HEADER_SIZE) || net_write_buff(net, packet, z_size))
00182 return 1;
00183 packet += z_size;
00184 len-= z_size;
00185 }
00186
00187 int3store(buff,len);
00188 buff[3]= (unsigned char) net->pkt_nr++;
00189 return net_write_buff(net, buff, NET_HEADER_SIZE) || net_write_buff(net, packet, len);
00190 }
00191
00219 static bool
00220 drizzleclient_net_write_command(NET *net,unsigned char command,
00221 const unsigned char *header, size_t head_len,
00222 const unsigned char *packet, size_t len)
00223 {
00224 uint32_t length=len+1+head_len;
00225 unsigned char buff[NET_HEADER_SIZE+1];
00226 uint32_t header_size=NET_HEADER_SIZE+1;
00227
00228 buff[4]=command;
00229
00230 if (length >= MAX_PACKET_LENGTH)
00231 {
00232
00233 len= MAX_PACKET_LENGTH - 1 - head_len;
00234 do
00235 {
00236 int3store(buff, MAX_PACKET_LENGTH);
00237 buff[3]= (unsigned char) net->pkt_nr++;
00238 if (net_write_buff(net, buff, header_size) ||
00239 net_write_buff(net, header, head_len) ||
00240 net_write_buff(net, packet, len))
00241 return(1);
00242 packet+= len;
00243 length-= MAX_PACKET_LENGTH;
00244 len= MAX_PACKET_LENGTH;
00245 head_len= 0;
00246 header_size= NET_HEADER_SIZE;
00247 } while (length >= MAX_PACKET_LENGTH);
00248 len=length;
00249 }
00250 int3store(buff,length);
00251 buff[3]= (unsigned char) net->pkt_nr++;
00252 return (net_write_buff(net, buff, header_size) ||
00253 (head_len && net_write_buff(net, header, head_len)) ||
00254 net_write_buff(net, packet, len) || net->flush());
00255 }
00256
00283 static bool
00284 net_write_buff(NET* net, const void* packet0, uint32_t len)
00285 {
00286 const unsigned char* packet= reinterpret_cast<const unsigned char*>(packet0);
00287 uint32_t left_length;
00288 if (net->compress && net->max_packet > MAX_PACKET_LENGTH)
00289 left_length= MAX_PACKET_LENGTH - (net->write_pos - net->buff);
00290 else
00291 left_length= (uint32_t) (net->buff_end - net->write_pos);
00292
00293 if (len > left_length)
00294 {
00295 if (net->write_pos != net->buff)
00296 {
00297
00298 memcpy(net->write_pos,packet,left_length);
00299 if (drizzleclient_net_real_write(net, net->buff,
00300 (size_t) (net->write_pos - net->buff) + left_length))
00301 return 1;
00302 net->write_pos= net->buff;
00303 packet+= left_length;
00304 len-= left_length;
00305 }
00306 if (net->compress)
00307 {
00308
00309
00310
00311
00312 left_length= MAX_PACKET_LENGTH;
00313 while (len > left_length)
00314 {
00315 if (drizzleclient_net_real_write(net, packet, left_length))
00316 return 1;
00317 packet+= left_length;
00318 len-= left_length;
00319 }
00320 }
00321 if (len > net->max_packet)
00322 return drizzleclient_net_real_write(net, packet, len) ? 1 : 0;
00323
00324 }
00325 memcpy(net->write_pos,packet,len);
00326 net->write_pos+= len;
00327 return 0;
00328 }
00329
00330
00339
00340
00341
00342
00343 static int
00344 drizzleclient_net_real_write(NET *net, const unsigned char *packet, size_t len)
00345 {
00346
00347
00348 if (net->error_ == 2)
00349 return(-1);
00350
00351 if (net->compress)
00352 {
00353 const uint32_t header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
00354 unsigned char* b= (unsigned char*) malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE);
00355 memcpy(b+header_length,packet,len);
00356
00357 size_t complen= len * 120 / 100 + 12;
00358 unsigned char* compbuf= new unsigned char[complen];
00359 uLongf tmp_complen= complen;
00360 int res= compress((Bytef*) compbuf, &tmp_complen,
00361 (Bytef*) (b+header_length),
00362 len);
00363 complen= tmp_complen;
00364
00365 delete[] compbuf;
00366
00367 if (res != Z_OK || complen >= len)
00368 complen= 0;
00369 else
00370 {
00371 size_t tmplen= complen;
00372 complen= len;
00373 len= tmplen;
00374 }
00375 int3store(&b[NET_HEADER_SIZE],complen);
00376 int3store(b,len);
00377 b[3]=(unsigned char) (net->compress_pkt_nr++);
00378 len+= header_length;
00379 packet= b;
00380 }
00381
00382 uint32_t retry_count= 0;
00383 const unsigned char* pos= packet;
00384 const unsigned char* end= pos + len;
00385
00386 while (pos != end)
00387 {
00388 assert(pos);
00389
00390 size_t length;
00391 if ((long) (length= net->vio->write( pos, (size_t) (end-pos))) <= 0)
00392 {
00393
00394
00395
00396
00397
00398 if (net->vio == NULL)
00399 break;
00400
00401 const bool interrupted= net->vio->should_retry();
00402
00403
00404
00405
00406
00407 if (interrupted || length == 0)
00408 {
00409 bool old_mode;
00410 while (net->vio->blocking(true, &old_mode) < 0)
00411 {
00412 if (net->vio->should_retry() && retry_count++ < net->retry_count)
00413 continue;
00414 net->error_= 2;
00415 net->last_errno= ER_NET_PACKET_TOO_LARGE;
00416 my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
00417 goto end;
00418 }
00419 retry_count=0;
00420 continue;
00421 }
00422 else
00423 {
00424 if (retry_count++ < net->retry_count)
00425 continue;
00426 }
00427
00428 if (net->vio->get_errno() == EINTR)
00429 {
00430 continue;
00431 }
00432 net->error_= 2;
00433 net->last_errno= interrupted ? CR_NET_WRITE_INTERRUPTED : CR_NET_ERROR_ON_WRITE;
00434 break;
00435 }
00436 pos+= length;
00437
00438
00439 if (current_session)
00440 current_session->status_var.bytes_sent+= length;
00441 }
00442 end:
00443 if (net->compress)
00444 free((char*)packet);
00445
00446 return (int) (pos != end);
00447 }
00448
00449
00459 static uint32_t
00460 my_real_read(NET *net, size_t *complen)
00461 {
00462 size_t length= 0;
00463 uint32_t retry_count=0;
00464 size_t len=packet_error;
00465 uint32_t remain= net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE : NET_HEADER_SIZE;
00466
00467 *complen = 0;
00468
00469
00470
00471 unsigned char* pos = net->buff + net->where_b;
00472
00473 for (uint32_t i= 0; i < 2 ; i++)
00474 {
00475 while (remain > 0)
00476 {
00477
00478 if ((long) (length= net->vio->read(pos, remain)) <= 0L)
00479 {
00480 if (net->vio == NULL)
00481 goto end;
00482
00483 const bool interrupted = net->vio->should_retry();
00484
00485 if (interrupted)
00486 {
00487 if (retry_count++ < net->retry_count)
00488 continue;
00489 }
00490 if (net->vio->get_errno() == EINTR)
00491 {
00492 continue;
00493 }
00494 len= packet_error;
00495 net->error_= 2;
00496 net->last_errno= net->vio->was_interrupted() ? CR_NET_READ_INTERRUPTED : CR_NET_READ_ERROR;
00497 goto end;
00498 }
00499 remain -= (uint32_t) length;
00500 pos+= length;
00501 current_session->status_var.bytes_received+= length;
00502 }
00503 if (i == 0)
00504 {
00505 uint32_t helping;
00506
00507 if (net->buff[net->where_b + 3] != (unsigned char) net->pkt_nr)
00508 {
00509 len= packet_error;
00510
00511 my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0));
00512 goto end;
00513 }
00514 net->compress_pkt_nr= ++net->pkt_nr;
00515 if (net->compress)
00516 {
00517
00518
00519
00520
00521 *complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
00522 }
00523
00524 len=uint3korr(net->buff+net->where_b);
00525 if (!len)
00526 goto end;
00527 helping = max(len,*complen) + net->where_b;
00528
00529 if (helping >= net->max_packet)
00530 {
00531 if (drizzleclient_net_realloc(net,helping))
00532 {
00533
00534 while (len > 0)
00535 {
00536 length= read(net->vio->get_fd(), net->buff, min((size_t)net->max_packet, len));
00537 assert((long)length > 0L);
00538 len-= length;
00539 }
00540
00541 len= packet_error;
00542 goto end;
00543 }
00544 }
00545 pos=net->buff + net->where_b;
00546 remain = (uint32_t) len;
00547 }
00548 }
00549
00550 end:
00551 return len;
00552 }
00553
00554
00571 static uint32_t
00572 drizzleclient_net_read(NET *net)
00573 {
00574 size_t len, complen;
00575
00576 if (not net->compress)
00577 {
00578 len = my_real_read(net,&complen);
00579 if (len == MAX_PACKET_LENGTH)
00580 {
00581
00582 uint32_t save_pos = net->where_b;
00583 size_t total_length= 0;
00584
00585 do
00586 {
00587 net->where_b += len;
00588 total_length += len;
00589 len = my_real_read(net,&complen);
00590 } while (len == MAX_PACKET_LENGTH);
00591
00592 if (len != packet_error)
00593 {
00594 len+= total_length;
00595 }
00596 net->where_b = save_pos;
00597 }
00598 net->read_pos = net->buff + net->where_b;
00599
00600 if (len != packet_error)
00601 net->read_pos[len]=0;
00602
00603 return len;
00604 }
00605 else
00606 {
00607
00608
00609 uint32_t buf_length;
00610 uint32_t start_of_packet;
00611 uint32_t first_packet_offset;
00612 uint32_t read_length, multi_byte_packet=0;
00613
00614 if (net->remain_in_buf)
00615 {
00616 buf_length= net->buf_length;
00617 first_packet_offset= start_of_packet= (net->buf_length -
00618 net->remain_in_buf);
00619
00620 net->buff[start_of_packet]= net->save_char;
00621 }
00622 else
00623 {
00624
00625 buf_length= start_of_packet= first_packet_offset= 0;
00626 }
00627 for (;;)
00628 {
00629 uint32_t packet_len;
00630
00631 if (buf_length - start_of_packet >= NET_HEADER_SIZE)
00632 {
00633 read_length = uint3korr(net->buff+start_of_packet);
00634 if (!read_length)
00635 {
00636
00637 start_of_packet += NET_HEADER_SIZE;
00638 break;
00639 }
00640 if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
00641 {
00642 if (multi_byte_packet)
00643 {
00644
00645 memmove(net->buff + first_packet_offset + start_of_packet,
00646 net->buff + first_packet_offset + start_of_packet +
00647 NET_HEADER_SIZE,
00648 buf_length - start_of_packet);
00649 start_of_packet += read_length;
00650 buf_length -= NET_HEADER_SIZE;
00651 }
00652 else
00653 start_of_packet+= read_length + NET_HEADER_SIZE;
00654
00655 if (read_length != MAX_PACKET_LENGTH)
00656 {
00657 multi_byte_packet= 0;
00658 break;
00659 }
00660 multi_byte_packet= NET_HEADER_SIZE;
00661
00662 if (first_packet_offset)
00663 {
00664 memmove(net->buff,net->buff+first_packet_offset,
00665 buf_length-first_packet_offset);
00666 buf_length-=first_packet_offset;
00667 start_of_packet -= first_packet_offset;
00668 first_packet_offset=0;
00669 }
00670 continue;
00671 }
00672 }
00673
00674 if (first_packet_offset)
00675 {
00676 memmove(net->buff,net->buff+first_packet_offset,
00677 buf_length-first_packet_offset);
00678 buf_length-=first_packet_offset;
00679 start_of_packet -= first_packet_offset;
00680 first_packet_offset=0;
00681 }
00682
00683 net->where_b=buf_length;
00684 if ((packet_len = my_real_read(net,&complen)) == packet_error)
00685 return packet_error;
00686
00687 if (complen)
00688 {
00689 unsigned char * compbuf= (unsigned char *) malloc(complen);
00690 if (compbuf != NULL)
00691 {
00692 uLongf tmp_complen= complen;
00693 int error= uncompress((Bytef*) compbuf, &tmp_complen,
00694 (Bytef*) (net->buff + net->where_b),
00695 (uLong)packet_len);
00696 complen= tmp_complen;
00697
00698 if (error != Z_OK)
00699 {
00700 net->error_= 2;
00701 net->last_errno= CR_NET_UNCOMPRESS_ERROR;
00702 }
00703 else
00704 {
00705 memcpy((net->buff + net->where_b), compbuf, complen);
00706 }
00707 free(compbuf);
00708 }
00709 }
00710 else
00711 {
00712 complen= packet_len;
00713 }
00714
00715 }
00716 buf_length+= complen;
00717
00718 net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE;
00719 net->buf_length= buf_length;
00720 net->remain_in_buf= (uint32_t) (buf_length - start_of_packet);
00721 len = ((uint32_t) (start_of_packet - first_packet_offset) - NET_HEADER_SIZE -
00722 multi_byte_packet);
00723 net->save_char= net->read_pos[len];
00724 net->read_pos[len]=0;
00725 }
00726 return len;
00727 }
00728
00729 void NET::set_read_timeout(uint32_t timeout)
00730 {
00731 read_timeout_= timeout;
00732 #ifndef __sun
00733 if (vio)
00734 vio->timeout(0, timeout);
00735 #endif
00736 return;
00737 }
00738
00739 void NET::set_write_timeout(uint32_t timeout)
00740 {
00741 write_timeout_= timeout;
00742 #ifndef __sun
00743 if (vio)
00744 vio->timeout(1, timeout);
00745 #endif
00746 return;
00747 }
00748
00749 bool NET::write(const void* data, size_t size)
00750 {
00751 return drizzleclient_net_write(this, data, size);
00752 }
00753
00754 bool NET::write_command(unsigned char command, data_ref header, data_ref body)
00755 {
00756 return drizzleclient_net_write_command(this, command, header.data(), header.size(), body.data(), body.size());
00757 }
00758
00759 uint32_t NET::read()
00760 {
00761 return drizzleclient_net_read(this);
00762 }
00763
00764 }