Drizzled Public API Documentation

net_serv.cc

00001 /* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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   The following handles the differences when this is linked between the
00050   client and the server.
00051 
00052   This gives an error if a too big packet is found
00053   The server can change this with the -O switch, but because the client
00054   can't normally do this the client should have a bigger max_allowed_packet.
00055 */
00056 
00057   /* Constants when using compression */
00058 #define NET_HEADER_SIZE 4   /* standard header size */
00059 #define COMP_HEADER_SIZE 3    /* compression header extra size */
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)                    /* If real connection */
00089   {
00090     net->fd  = vio->get_fd();            /* For perl DBI/DBD */
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       /* Only delete the temporary vio if we didn't already attach it to the
00107        * NET object.
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     /* @todo: 1 and 2 codes are identical. */
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     We must allocate some extra bytes for the end 0 and to be able to
00174     read big compressed blocks
00175   */
00176   if (!(buff= (unsigned char*) realloc((char*) net->buff, pkt_length +
00177                                NET_HEADER_SIZE + COMP_HEADER_SIZE)))
00178   {
00179     /* @todo: 1 and 2 codes are identical. */
00180     net->error= 1;
00181     net->last_errno= CR_OUT_OF_MEMORY;
00182     /* In the server the error is reported by MY_WME flag. */
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       /* The socket is ready */
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;        /* Ready for new command */
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   /* Sync packet number if using compression */
00268   if (net->compress)
00269     net->pkt_nr=net->compress_pkt_nr;
00270   return(error);
00271 }
00272 
00273 
00274 /*****************************************************************************
00275  ** Write something to server/client buffer
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)) /* nowhere to write */
00293     return 0;
00294   /*
00295     Big packets are handled by splitting them in packets of MAX_PACKET_LENGTH
00296     length. The last packet is always a packet that is < MAX_PACKET_LENGTH.
00297     (The last packet may even have a length of 0)
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   /* Write last packet */
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;            /* 1 extra byte for command */
00351   unsigned char buff[NET_HEADER_SIZE+1];
00352   uint32_t header_size=NET_HEADER_SIZE+1;
00353 
00354   buff[4]=command;                /* For first packet */
00355 
00356   if (length >= MAX_PACKET_LENGTH)
00357   {
00358     /* Take into account that we have the command in the first header */
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;                    /* Data left to be written */
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       /* Fill up already used packet and write it */
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         We can't have bigger packets than 16M with compression
00435         Because the uncompressed length is stored in 3 bytes
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     /* Send out rest of the blocks as full sized blocks */
00449   }
00450   memcpy(net->write_pos,packet,len);
00451   net->write_pos+= len;
00452   return 0;
00453 }
00454 
00455 
00464 /*
00465   TODO: rewrite this in a manner to do non-block writes. If a write can not be made, and we are
00466   in the server, yield to another process and come back later.
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   /* Backup of the original SO_RCVTIMEO timeout */
00476 
00477   if (net->error == 2)
00478     return(-1);                /* socket can't be used */
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       /* In the server, the error is reported by MY_WME flag. */
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   /* Loop until we have read everything */
00532   while (pos != end)
00533   {
00534     assert(pos);
00535     // TODO - see bug comment below - will we crash now?
00536     if ((long) (length= net->vio->write( pos, (size_t) (end-pos))) <= 0)
00537     {
00538      /*
00539       * We could end up here with net->vio == NULL
00540       * See LP bug#436685
00541       * If that is the case, we exit the while loop
00542       */
00543       if (net->vio == NULL)
00544         break;
00545       
00546       const bool interrupted= net->vio->should_retry();
00547       /*
00548         If we read 0, or we were interrupted this means that
00549         we need to switch to blocking mode and wait until the timeout
00550         on the socket kicks in.
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;                     /* Close socket */
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;                /* Close socket */
00579       net->last_errno= (interrupted ? CR_NET_WRITE_INTERRUPTED :
00580                         CR_NET_ERROR_ON_WRITE);
00581       break;
00582     }
00583     pos+=length;
00584 
00585     /* If this is an error we may not have a current_session any more */
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   /* Read timeout is set in drizzleclient_net_set_read_timeout */
00621 
00622   pos = net->buff + net->where_b;        /* net->packet -4 */
00623 
00624   for (i= 0; i < 2 ; i++)
00625   {
00626     while (remain > 0)
00627     {
00628       /* First read is done with non blocking mode */
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         {                    /* Probably in MIT threads */
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;                /* Close socket */
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     {                    /* First parts is packet length */
00658       uint32_t helping;
00659 
00660       if (net->buff[net->where_b + 3] != (unsigned char) net->pkt_nr)
00661       {
00662         len= packet_error;
00663         /* Not a NET error on the client. XXX: why? */
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           If the packet is compressed then complen > 0 and contains the
00672           number of bytes in the uncompressed packet
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)                /* End of big multi-packet */
00679         goto end;
00680       helping = max(len,*complen) + net->where_b;
00681       /* The necessary size of net->buff */
00682       if (helping >= net->max_packet)
00683       {
00684         if (drizzleclient_net_realloc(net,helping))
00685         {
00686           /* Clear the buffer so libdrizzle doesn't keep retrying */
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;          /* Return error and close connection */
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       /* First packet of a multi-packet.  Concatenate the packets */
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;        /* Safeguard for drizzleclient_use_result */
00752     return len;
00753   }
00754   else
00755   {
00756     /* We are using the compressed protocol */
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;        /* Data left in old packet */
00766       first_packet_offset= start_of_packet= (net->buf_length -
00767                                              net->remain_in_buf);
00768       /* Restore the character that was overwritten by the end 0 */
00769       net->buff[start_of_packet]= net->save_char;
00770     }
00771     else
00772     {
00773       /* reuse buffer, as there is nothing in it that we need */
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           /* End of multi-byte packet */
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             /* Remove packet header for second packet */
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)    /* last package */
00805           {
00806             multi_byte_packet= 0;        /* No last zero len packet */
00807             break;
00808           }
00809           multi_byte_packet= NET_HEADER_SIZE;
00810           /* Move data down to read next data packet after current one */
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       /* Move data down to read next data packet after current one */
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;            /* caller will close socket */
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];    /* Must be saved */
00873     net->read_pos[len]=0;        /* Safeguard for drizzleclient_use_result */
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 } /* namespace drizzle_plugin */