libdrizzle Developer Documentation

libdrizzle/command.c
Go to the documentation of this file.
00001 /*
00002  * Drizzle Client & Protocol Library
00003  *
00004  * Copyright (C) 2008 Eric Day (eday@oddments.org)
00005  * All rights reserved.
00006  *
00007  * Use and distribution licensed under the BSD license.  See
00008  * the COPYING file in this directory for full text.
00009  */
00010 
00016 #include "common.h"
00017 
00018 /*
00019  * Private variables.
00020  */
00021 
00022 static drizzle_command_drizzle_t _command_drizzle_map[]=
00023 {
00024  DRIZZLE_COMMAND_DRIZZLE_END,
00025  DRIZZLE_COMMAND_DRIZZLE_QUIT,
00026  DRIZZLE_COMMAND_DRIZZLE_INIT_DB,
00027  DRIZZLE_COMMAND_DRIZZLE_QUERY,
00028  DRIZZLE_COMMAND_DRIZZLE_END,
00029  DRIZZLE_COMMAND_DRIZZLE_END,
00030  DRIZZLE_COMMAND_DRIZZLE_END,
00031  DRIZZLE_COMMAND_DRIZZLE_END,
00032  DRIZZLE_COMMAND_DRIZZLE_SHUTDOWN,
00033  DRIZZLE_COMMAND_DRIZZLE_END,
00034  DRIZZLE_COMMAND_DRIZZLE_END,
00035  DRIZZLE_COMMAND_DRIZZLE_END,
00036  DRIZZLE_COMMAND_DRIZZLE_END,
00037  DRIZZLE_COMMAND_DRIZZLE_END,
00038  DRIZZLE_COMMAND_DRIZZLE_PING,
00039  DRIZZLE_COMMAND_DRIZZLE_END,
00040  DRIZZLE_COMMAND_DRIZZLE_END,
00041  DRIZZLE_COMMAND_DRIZZLE_END,
00042  DRIZZLE_COMMAND_DRIZZLE_END,
00043  DRIZZLE_COMMAND_DRIZZLE_END,
00044  DRIZZLE_COMMAND_DRIZZLE_END,
00045  DRIZZLE_COMMAND_DRIZZLE_END,
00046  DRIZZLE_COMMAND_DRIZZLE_END,
00047  DRIZZLE_COMMAND_DRIZZLE_END,
00048  DRIZZLE_COMMAND_DRIZZLE_END,
00049  DRIZZLE_COMMAND_DRIZZLE_END,
00050  DRIZZLE_COMMAND_DRIZZLE_END,
00051  DRIZZLE_COMMAND_DRIZZLE_END,
00052  DRIZZLE_COMMAND_DRIZZLE_END,
00053  DRIZZLE_COMMAND_DRIZZLE_END,
00054  DRIZZLE_COMMAND_DRIZZLE_END
00055 };
00056 
00057 /*
00058  * State Definitions
00059  */
00060 
00061 drizzle_return_t drizzle_state_command_read(drizzle_con_st *con)
00062 {
00063   drizzle_log_debug(con->drizzle, "drizzle_state_command_read");
00064 
00065   if (con->buffer_size == 0)
00066   {
00067     drizzle_state_push(con, drizzle_state_read);
00068     return DRIZZLE_RETURN_OK;
00069   }
00070 
00071   if (con->command_total == 0)
00072   {
00073     con->command= (drizzle_command_t)(con->buffer_ptr[0]);
00074     con->buffer_ptr++;
00075     con->buffer_size--;
00076 
00077     con->command_total= (con->packet_size - 1);
00078   }
00079 
00080   if (con->buffer_size < (con->command_total - con->command_offset))
00081   {
00082     con->command_size= con->buffer_size;
00083     con->command_offset+= con->command_size;
00084   }
00085   else
00086   {
00087     con->command_size= (con->command_total - con->command_offset);
00088     con->command_offset= con->command_total;
00089   }
00090 
00091   con->command_data= con->buffer_ptr;
00092   con->buffer_ptr+= con->command_size;
00093   con->buffer_size-= con->command_size;
00094 
00095   if (con->command_offset == con->command_total)
00096     drizzle_state_pop(con);
00097   else
00098     return DRIZZLE_RETURN_PAUSE;
00099 
00100   return DRIZZLE_RETURN_OK;
00101 }
00102 
00103 drizzle_return_t drizzle_state_command_write(drizzle_con_st *con)
00104 {
00105   uint8_t *start;
00106   uint8_t *ptr;
00107   size_t free_size;
00108   drizzle_return_t ret;
00109 
00110   drizzle_log_debug(con->drizzle, "drizzle_state_command_write");
00111 
00112   if (con->command_data == NULL && con->command_total != 0 &&
00113       con->command != DRIZZLE_COMMAND_CHANGE_USER)
00114   {
00115     return DRIZZLE_RETURN_PAUSE;
00116   }
00117 
00118   if (con->buffer_size == 0)
00119   {
00120     con->buffer_ptr= con->buffer;
00121     start= con->buffer;
00122   }
00123   else
00124     start= con->buffer_ptr + con->buffer_size;
00125 
00126   if (con->command_offset == 0)
00127   {
00128     /* Make sure we can fit the largest non-streaming packet, currently a
00129        DRIZZLE_COMMAND_CHANGE_USER command. */
00130 
00131     con->packet_size= 1  /* Command */
00132                     + strlen(con->user) + 1
00133                     + 1  /* Scramble size */
00134                     + DRIZZLE_MAX_SCRAMBLE_SIZE
00135                     + strlen(con->db) + 1;
00136 
00137     /* Flush buffer if there is not enough room. */
00138     free_size= (size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer);
00139     if (free_size < con->packet_size)
00140     {
00141       drizzle_state_push(con, drizzle_state_write);
00142       return DRIZZLE_RETURN_OK;
00143     }
00144 
00145     /* Store packet size at the end since it may change. */
00146     con->packet_number= 1;
00147     ptr= start;
00148     ptr[3]= 0;
00149     if (con->options & DRIZZLE_CON_MYSQL)
00150       ptr[4]= (uint8_t)(con->command);
00151     else
00152       ptr[4]= (uint8_t)(_command_drizzle_map[con->command]);
00153     ptr+= 5;
00154 
00155     if (con->command == DRIZZLE_COMMAND_CHANGE_USER)
00156     {
00157       ptr= drizzle_pack_auth(con, ptr, &ret);
00158       if (ret != DRIZZLE_RETURN_OK)
00159         return ret;
00160 
00161       con->buffer_size+= (4 + con->packet_size);
00162     }
00163     else if (con->command_total == 0)
00164     {
00165       con->packet_size= 1;
00166       con->buffer_size+= 5;
00167     }
00168     else
00169     {
00170       con->packet_size= 1 + con->command_total;
00171       free_size-= 5;
00172 
00173       /* Copy as much of the data in as we can into the write buffer. */
00174       if (con->command_size <= free_size)
00175       {
00176         memcpy(ptr, con->command_data, con->command_size);
00177         con->command_offset= con->command_size;
00178         con->command_data= NULL;
00179         con->buffer_size+= 5 + con->command_size;
00180       }
00181       else
00182       {
00183         memcpy(ptr, con->command_data, free_size);
00184         con->command_offset= free_size;
00185         con->command_data+= free_size;
00186         con->command_size-= free_size;
00187         con->buffer_size+= 5 + free_size;
00188       }
00189     }
00190 
00191     /* Store packet size now. */
00192     drizzle_set_byte3(start, con->packet_size);
00193   }
00194   else
00195   {
00196     /* Write directly from the caller buffer for the rest. */
00197     con->buffer_ptr= con->command_data;
00198     con->buffer_size= con->command_size;
00199     con->command_offset+= con->command_size;
00200     con->command_data= NULL;
00201   }
00202 
00203   if (con->command_offset == con->command_total)
00204   {
00205     drizzle_state_pop(con);
00206 
00207     if (!(con->options & (DRIZZLE_CON_RAW_PACKET |
00208                           DRIZZLE_CON_NO_RESULT_READ)) &&
00209         con->command != DRIZZLE_COMMAND_FIELD_LIST)
00210     {
00211       drizzle_state_push(con, drizzle_state_result_read);
00212       drizzle_state_push(con, drizzle_state_packet_read);
00213     }
00214   }
00215 
00216   drizzle_state_push(con, drizzle_state_write);
00217 
00218   return DRIZZLE_RETURN_OK;
00219 }