Drizzled Public API Documentation

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  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are
00009  * met:
00010  *
00011  *     * Redistributions of source code must retain the above copyright
00012  * notice, this list of conditions and the following disclaimer.
00013  *
00014  *     * Redistributions in binary form must reproduce the above
00015  * copyright notice, this list of conditions and the following disclaimer
00016  * in the documentation and/or other materials provided with the
00017  * distribution.
00018  *
00019  *     * The names of its contributors may not be used to endorse or
00020  * promote products derived from this software without specific prior
00021  * written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00026  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00027  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  */
00036 
00037 
00043 #include "common.h"
00044 
00045 /*
00046  * Private variables.
00047  */
00048 
00049 static drizzle_command_drizzle_t _command_drizzle_map[]=
00050 {
00051  DRIZZLE_COMMAND_DRIZZLE_END,
00052  DRIZZLE_COMMAND_DRIZZLE_QUIT,
00053  DRIZZLE_COMMAND_DRIZZLE_INIT_DB,
00054  DRIZZLE_COMMAND_DRIZZLE_QUERY,
00055  DRIZZLE_COMMAND_DRIZZLE_END,
00056  DRIZZLE_COMMAND_DRIZZLE_END,
00057  DRIZZLE_COMMAND_DRIZZLE_END,
00058  DRIZZLE_COMMAND_DRIZZLE_END,
00059  DRIZZLE_COMMAND_DRIZZLE_SHUTDOWN,
00060  DRIZZLE_COMMAND_DRIZZLE_END, // STATISTICS
00061  DRIZZLE_COMMAND_DRIZZLE_END, // PROCESS_INFO
00062  DRIZZLE_COMMAND_DRIZZLE_END, // CONNECT
00063  DRIZZLE_COMMAND_DRIZZLE_KILL,// PROCESS_KILL
00064  DRIZZLE_COMMAND_DRIZZLE_END,
00065  DRIZZLE_COMMAND_DRIZZLE_PING,
00066  DRIZZLE_COMMAND_DRIZZLE_END,
00067  DRIZZLE_COMMAND_DRIZZLE_END,
00068  DRIZZLE_COMMAND_DRIZZLE_END,
00069  DRIZZLE_COMMAND_DRIZZLE_END,
00070  DRIZZLE_COMMAND_DRIZZLE_END,
00071  DRIZZLE_COMMAND_DRIZZLE_END,
00072  DRIZZLE_COMMAND_DRIZZLE_END,
00073  DRIZZLE_COMMAND_DRIZZLE_END,
00074  DRIZZLE_COMMAND_DRIZZLE_END,
00075  DRIZZLE_COMMAND_DRIZZLE_END,
00076  DRIZZLE_COMMAND_DRIZZLE_END,
00077  DRIZZLE_COMMAND_DRIZZLE_END,
00078  DRIZZLE_COMMAND_DRIZZLE_END,
00079  DRIZZLE_COMMAND_DRIZZLE_END,
00080  DRIZZLE_COMMAND_DRIZZLE_END,
00081  DRIZZLE_COMMAND_DRIZZLE_END
00082 };
00083 
00084 /*
00085  * State Definitions
00086  */
00087 
00088 drizzle_return_t drizzle_state_command_read(drizzle_con_st *con)
00089 {
00090   drizzle_log_debug(con->drizzle, "drizzle_state_command_read");
00091 
00092   if (con->buffer_size == 0)
00093   {
00094     drizzle_state_push(con, drizzle_state_read);
00095     return DRIZZLE_RETURN_OK;
00096   }
00097 
00098   if (con->command_total == 0)
00099   {
00100     con->command= (drizzle_command_t)(con->buffer_ptr[0]);
00101     con->buffer_ptr++;
00102     con->buffer_size--;
00103 
00104     con->command_total= (con->packet_size - 1);
00105   }
00106 
00107   if (con->buffer_size < (con->command_total - con->command_offset))
00108   {
00109     con->command_size= con->buffer_size;
00110     con->command_offset+= con->command_size;
00111   }
00112   else
00113   {
00114     con->command_size= (con->command_total - con->command_offset);
00115     con->command_offset= con->command_total;
00116   }
00117 
00118   con->command_data= con->buffer_ptr;
00119   con->buffer_ptr+= con->command_size;
00120   con->buffer_size-= con->command_size;
00121 
00122   if (con->command_offset == con->command_total)
00123     drizzle_state_pop(con);
00124   else
00125     return DRIZZLE_RETURN_PAUSE;
00126 
00127   return DRIZZLE_RETURN_OK;
00128 }
00129 
00130 drizzle_return_t drizzle_state_command_write(drizzle_con_st *con)
00131 {
00132   uint8_t *start;
00133   uint8_t *ptr;
00134   size_t free_size;
00135   drizzle_return_t ret;
00136 
00137   drizzle_log_debug(con->drizzle, "drizzle_state_command_write");
00138 
00139   if (con->command_data == NULL && con->command_total != 0 &&
00140       con->command != DRIZZLE_COMMAND_CHANGE_USER)
00141   {
00142     return DRIZZLE_RETURN_PAUSE;
00143   }
00144 
00145   if (con->buffer_size == 0)
00146   {
00147     con->buffer_ptr= con->buffer;
00148     start= con->buffer;
00149   }
00150   else
00151     start= con->buffer_ptr + con->buffer_size;
00152 
00153   if (con->command_offset == 0)
00154   {
00155     /* Make sure we can fit the largest non-streaming packet, currently a
00156        DRIZZLE_COMMAND_CHANGE_USER command. */
00157 
00158     con->packet_size= 1  /* Command */
00159                     + strlen(con->user) + 1
00160                     + 1  /* Scramble size */
00161                     + DRIZZLE_MAX_SCRAMBLE_SIZE
00162                     + strlen(con->db) + 1;
00163 
00164     /* Flush buffer if there is not enough room. */
00165     free_size= (size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer);
00166     if (free_size < con->packet_size)
00167     {
00168       drizzle_state_push(con, drizzle_state_write);
00169       return DRIZZLE_RETURN_OK;
00170     }
00171 
00172     /* Store packet size at the end since it may change. */
00173     con->packet_number= 1;
00174     ptr= start;
00175     ptr[3]= 0;
00176     if (con->options & DRIZZLE_CON_MYSQL)
00177       ptr[4]= (uint8_t)(con->command);
00178     else
00179       ptr[4]= (uint8_t)(_command_drizzle_map[con->command]);
00180     ptr+= 5;
00181 
00182     if (con->command == DRIZZLE_COMMAND_CHANGE_USER)
00183     {
00184       ptr= drizzle_pack_auth(con, ptr, &ret);
00185       if (ret != DRIZZLE_RETURN_OK)
00186         return ret;
00187 
00188       con->buffer_size+= (4 + con->packet_size);
00189     }
00190     else if (con->command_total == 0)
00191     {
00192       con->packet_size= 1;
00193       con->buffer_size+= 5;
00194     }
00195     else
00196     {
00197       con->packet_size= 1 + con->command_total;
00198       free_size-= 5;
00199 
00200       /* Copy as much of the data in as we can into the write buffer. */
00201       if (con->command_size <= free_size)
00202       {
00203         memcpy(ptr, con->command_data, con->command_size);
00204         con->command_offset= con->command_size;
00205         con->command_data= NULL;
00206         con->buffer_size+= 5 + con->command_size;
00207       }
00208       else
00209       {
00210         memcpy(ptr, con->command_data, free_size);
00211         con->command_offset= free_size;
00212         con->command_data+= free_size;
00213         con->command_size-= free_size;
00214         con->buffer_size+= 5 + free_size;
00215       }
00216     }
00217 
00218     /* Store packet size now. */
00219     drizzle_set_byte3(start, con->packet_size);
00220   }
00221   else
00222   {
00223     /* Write directly from the caller buffer for the rest. */
00224     con->buffer_ptr= con->command_data;
00225     con->buffer_size= con->command_size;
00226     con->command_offset+= con->command_size;
00227     con->command_data= NULL;
00228   }
00229 
00230   if (con->command_offset == con->command_total)
00231   {
00232     drizzle_state_pop(con);
00233 
00234     if (!(con->options & (DRIZZLE_CON_RAW_PACKET |
00235                           DRIZZLE_CON_NO_RESULT_READ)) &&
00236         con->command != DRIZZLE_COMMAND_FIELD_LIST)
00237     {
00238       drizzle_state_push(con, drizzle_state_result_read);
00239       drizzle_state_push(con, drizzle_state_packet_read);
00240     }
00241   }
00242 
00243   drizzle_state_push(con, drizzle_state_write);
00244 
00245   return DRIZZLE_RETURN_OK;
00246 }