Drizzled Public API Documentation

command.cc
Go to the documentation of this file.
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2  *
3  * Drizzle Client & Protocol Library
4  *
5  * Copyright (C) 2008 Eric Day (eday@oddments.org)
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following disclaimer
17  * in the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * * The names of its contributors may not be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 
44 #include <libdrizzle/common.h>
45 
46 /*
47  * Private variables.
48  */
49 
50 static drizzle_command_drizzle_t _command_drizzle_map[]=
51 {
52  DRIZZLE_COMMAND_DRIZZLE_END,
53  DRIZZLE_COMMAND_DRIZZLE_QUIT,
54  DRIZZLE_COMMAND_DRIZZLE_INIT_DB,
55  DRIZZLE_COMMAND_DRIZZLE_QUERY,
56  DRIZZLE_COMMAND_DRIZZLE_END,
57  DRIZZLE_COMMAND_DRIZZLE_END,
58  DRIZZLE_COMMAND_DRIZZLE_END,
59  DRIZZLE_COMMAND_DRIZZLE_END,
60  DRIZZLE_COMMAND_DRIZZLE_SHUTDOWN,
61  DRIZZLE_COMMAND_DRIZZLE_END, // STATISTICS
62  DRIZZLE_COMMAND_DRIZZLE_END, // PROCESS_INFO
63  DRIZZLE_COMMAND_DRIZZLE_END, // CONNECT
64  DRIZZLE_COMMAND_DRIZZLE_KILL,// PROCESS_KILL
65  DRIZZLE_COMMAND_DRIZZLE_END,
66  DRIZZLE_COMMAND_DRIZZLE_PING,
67  DRIZZLE_COMMAND_DRIZZLE_END,
68  DRIZZLE_COMMAND_DRIZZLE_END,
69  DRIZZLE_COMMAND_DRIZZLE_END,
70  DRIZZLE_COMMAND_DRIZZLE_END,
71  DRIZZLE_COMMAND_DRIZZLE_END,
72  DRIZZLE_COMMAND_DRIZZLE_END,
73  DRIZZLE_COMMAND_DRIZZLE_END,
74  DRIZZLE_COMMAND_DRIZZLE_END,
75  DRIZZLE_COMMAND_DRIZZLE_END,
76  DRIZZLE_COMMAND_DRIZZLE_END,
77  DRIZZLE_COMMAND_DRIZZLE_END,
78  DRIZZLE_COMMAND_DRIZZLE_END,
79  DRIZZLE_COMMAND_DRIZZLE_END,
80  DRIZZLE_COMMAND_DRIZZLE_END,
81  DRIZZLE_COMMAND_DRIZZLE_END,
82  DRIZZLE_COMMAND_DRIZZLE_END
83 };
84 
85 /*
86  * State Definitions
87  */
88 
89 drizzle_return_t drizzle_state_command_read(drizzle_con_st *con)
90 {
91  if (con == NULL)
92  {
93  return DRIZZLE_RETURN_INVALID_ARGUMENT;
94  }
95 
96  drizzle_log_debug(con->drizzle, "drizzle_state_command_read");
97 
98  if (con->buffer_size == 0)
99  {
100  drizzle_state_push(con, drizzle_state_read);
101  return DRIZZLE_RETURN_OK;
102  }
103 
104  if (con->command_total == 0)
105  {
106  con->command= (drizzle_command_t)(con->buffer_ptr[0]);
107  con->buffer_ptr++;
108  con->buffer_size--;
109 
110  con->command_total= (con->packet_size - 1);
111  }
112 
113  if (con->buffer_size < (con->command_total - con->command_offset))
114  {
115  con->command_size= con->buffer_size;
116  con->command_offset+= con->command_size;
117  }
118  else
119  {
120  con->command_size= (con->command_total - con->command_offset);
121  con->command_offset= con->command_total;
122  }
123 
124  con->command_data= con->buffer_ptr;
125  con->buffer_ptr+= con->command_size;
126  con->buffer_size-= con->command_size;
127 
128  if (con->command_offset == con->command_total)
129  drizzle_state_pop(con);
130  else
131  return DRIZZLE_RETURN_PAUSE;
132 
133  return DRIZZLE_RETURN_OK;
134 }
135 
136 drizzle_return_t drizzle_state_command_write(drizzle_con_st *con)
137 {
138  uint8_t *start;
139  uint8_t *ptr;
140  size_t free_size;
141  drizzle_return_t ret;
142 
143  if (con == NULL)
144  {
145  return DRIZZLE_RETURN_INVALID_ARGUMENT;
146  }
147 
148  drizzle_log_debug(con->drizzle, "drizzle_state_command_write");
149 
150  if (con->command_data == NULL && con->command_total != 0 &&
151  con->command != DRIZZLE_COMMAND_CHANGE_USER)
152  {
153  return DRIZZLE_RETURN_PAUSE;
154  }
155 
156  if (con->buffer_size == 0)
157  {
158  con->buffer_ptr= con->buffer;
159  start= con->buffer;
160  }
161  else
162  {
163  start= con->buffer_ptr + con->buffer_size;
164  }
165 
166  if (con->command_offset == 0)
167  {
168  /* Make sure we can fit the largest non-streaming packet, currently a
169  DRIZZLE_COMMAND_CHANGE_USER command. */
170 
171  con->packet_size= 1 /* Command */
172  + strlen(con->user) + 1
173  + 1 /* Scramble size */
174  + DRIZZLE_MAX_SCRAMBLE_SIZE
175  + strlen(con->db) + 1;
176 
177  /* Flush buffer if there is not enough room. */
178  free_size= (size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer);
179  if (free_size < con->packet_size)
180  {
181  drizzle_state_push(con, drizzle_state_write);
182  return DRIZZLE_RETURN_OK;
183  }
184 
185  /* Store packet size at the end since it may change. */
186  con->packet_number= 1;
187  ptr= start;
188  ptr[3]= 0;
189  if (con->options & DRIZZLE_CON_MYSQL)
190  {
191  ptr[4]= (uint8_t)(con->command);
192  }
193  else
194  {
195  ptr[4]= (uint8_t)(_command_drizzle_map[con->command]);
196  }
197  ptr+= 5;
198 
199  if (con->command == DRIZZLE_COMMAND_CHANGE_USER)
200  {
201  ptr= drizzle_pack_auth(con, ptr, &ret);
202  if (ret != DRIZZLE_RETURN_OK)
203  return ret;
204 
205  con->buffer_size+= (4 + con->packet_size);
206  }
207  else if (con->command_total == 0)
208  {
209  con->packet_size= 1;
210  con->buffer_size+= 5;
211  }
212  else
213  {
214  con->packet_size= 1 + con->command_total;
215  free_size-= 5;
216 
217  /* Copy as much of the data in as we can into the write buffer. */
218  if (con->command_size <= free_size)
219  {
220  memcpy(ptr, con->command_data, con->command_size);
221  con->command_offset= con->command_size;
222  con->command_data= NULL;
223  con->buffer_size+= 5 + con->command_size;
224  }
225  else
226  {
227  memcpy(ptr, con->command_data, free_size);
228  con->command_offset= free_size;
229  con->command_data+= free_size;
230  con->command_size-= free_size;
231  con->buffer_size+= 5 + free_size;
232  }
233  }
234 
235  /* Store packet size now. */
236  drizzle_set_byte3(start, con->packet_size);
237  }
238  else
239  {
240  /* Write directly from the caller buffer for the rest. */
241  con->buffer_ptr= con->command_data;
242  con->buffer_size= con->command_size;
243  con->command_offset+= con->command_size;
244  con->command_data= NULL;
245  }
246 
247  if (con->command_offset == con->command_total)
248  {
249  drizzle_state_pop(con);
250 
251  if (!(con->options & (DRIZZLE_CON_RAW_PACKET |
252  DRIZZLE_CON_NO_RESULT_READ)) &&
253  con->command != DRIZZLE_COMMAND_FIELD_LIST)
254  {
255  drizzle_state_push(con, drizzle_state_result_read);
256  drizzle_state_push(con, drizzle_state_packet_read);
257  }
258  }
259 
260  drizzle_state_push(con, drizzle_state_write);
261 
262  return DRIZZLE_RETURN_OK;
263 }