~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/command.c

Added libdrizzle to the tree.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Drizzle Client & Protocol Library
 
3
 *
 
4
 * Copyright (C) 2008 Eric Day (eday@oddments.org)
 
5
 * All rights reserved.
 
6
 *
 
7
 * Use and distribution licensed under the BSD license.  See
 
8
 * the COPYING file in this directory for full text.
 
9
 */
 
10
 
 
11
/**
 
12
 * @file
 
13
 * @brief Command definitions
 
14
 */
 
15
 
 
16
#include "common.h"
 
17
 
 
18
/*
 
19
 * Private variables.
 
20
 */
 
21
 
 
22
static drizzle_command_drizzle_t _command_drizzle_map[]=
 
23
{
 
24
 DRIZZLE_COMMAND_DRIZZLE_END,
 
25
 DRIZZLE_COMMAND_DRIZZLE_QUIT,
 
26
 DRIZZLE_COMMAND_DRIZZLE_INIT_DB,
 
27
 DRIZZLE_COMMAND_DRIZZLE_QUERY,
 
28
 DRIZZLE_COMMAND_DRIZZLE_END,
 
29
 DRIZZLE_COMMAND_DRIZZLE_END,
 
30
 DRIZZLE_COMMAND_DRIZZLE_END,
 
31
 DRIZZLE_COMMAND_DRIZZLE_END,
 
32
 DRIZZLE_COMMAND_DRIZZLE_SHUTDOWN,
 
33
 DRIZZLE_COMMAND_DRIZZLE_END,
 
34
 DRIZZLE_COMMAND_DRIZZLE_END,
 
35
 DRIZZLE_COMMAND_DRIZZLE_END,
 
36
 DRIZZLE_COMMAND_DRIZZLE_END,
 
37
 DRIZZLE_COMMAND_DRIZZLE_END,
 
38
 DRIZZLE_COMMAND_DRIZZLE_PING,
 
39
 DRIZZLE_COMMAND_DRIZZLE_END,
 
40
 DRIZZLE_COMMAND_DRIZZLE_END,
 
41
 DRIZZLE_COMMAND_DRIZZLE_END,
 
42
 DRIZZLE_COMMAND_DRIZZLE_END,
 
43
 DRIZZLE_COMMAND_DRIZZLE_END,
 
44
 DRIZZLE_COMMAND_DRIZZLE_END,
 
45
 DRIZZLE_COMMAND_DRIZZLE_END,
 
46
 DRIZZLE_COMMAND_DRIZZLE_END,
 
47
 DRIZZLE_COMMAND_DRIZZLE_END,
 
48
 DRIZZLE_COMMAND_DRIZZLE_END,
 
49
 DRIZZLE_COMMAND_DRIZZLE_END,
 
50
 DRIZZLE_COMMAND_DRIZZLE_END,
 
51
 DRIZZLE_COMMAND_DRIZZLE_END,
 
52
 DRIZZLE_COMMAND_DRIZZLE_END,
 
53
 DRIZZLE_COMMAND_DRIZZLE_END,
 
54
 DRIZZLE_COMMAND_DRIZZLE_END
 
55
};
 
56
 
 
57
/*
 
58
 * State Definitions
 
59
 */
 
60
 
 
61
drizzle_return_t drizzle_state_command_read(drizzle_con_st *con)
 
62
{
 
63
  drizzle_log_debug(con->drizzle, "drizzle_state_command_read");
 
64
 
 
65
  if (con->buffer_size == 0)
 
66
  {
 
67
    drizzle_state_push(con, drizzle_state_read);
 
68
    return DRIZZLE_RETURN_OK;
 
69
  }
 
70
 
 
71
  if (con->command_total == 0)
 
72
  {
 
73
    con->command= (drizzle_command_t)(con->buffer_ptr[0]);
 
74
    con->buffer_ptr++;
 
75
    con->buffer_size--;
 
76
 
 
77
    con->command_total= (con->packet_size - 1);
 
78
  }
 
79
 
 
80
  if (con->buffer_size < (con->command_total - con->command_offset))
 
81
  {
 
82
    con->command_size= con->buffer_size;
 
83
    con->command_offset+= con->command_size;
 
84
  }
 
85
  else
 
86
  {
 
87
    con->command_size= (con->command_total - con->command_offset);
 
88
    con->command_offset= con->command_total;
 
89
  }
 
90
 
 
91
  con->command_data= con->buffer_ptr;
 
92
  con->buffer_ptr+= con->command_size;
 
93
  con->buffer_size-= con->command_size;
 
94
 
 
95
  if (con->command_offset == con->command_total)
 
96
    drizzle_state_pop(con);
 
97
  else
 
98
    return DRIZZLE_RETURN_PAUSE;
 
99
 
 
100
  return DRIZZLE_RETURN_OK;
 
101
}
 
102
 
 
103
drizzle_return_t drizzle_state_command_write(drizzle_con_st *con)
 
104
{
 
105
  uint8_t *start;
 
106
  uint8_t *ptr;
 
107
  size_t free_size;
 
108
  drizzle_return_t ret;
 
109
 
 
110
  drizzle_log_debug(con->drizzle, "drizzle_state_command_write");
 
111
 
 
112
  if (con->command_data == NULL && con->command_total != 0 &&
 
113
      con->command != DRIZZLE_COMMAND_CHANGE_USER)
 
114
  {
 
115
    return DRIZZLE_RETURN_PAUSE;
 
116
  }
 
117
 
 
118
  if (con->buffer_size == 0)
 
119
  {
 
120
    con->buffer_ptr= con->buffer;
 
121
    start= con->buffer;
 
122
  }
 
123
  else
 
124
    start= con->buffer_ptr + con->buffer_size;
 
125
 
 
126
  if (con->command_offset == 0)
 
127
  {
 
128
    /* Make sure we can fit the largest non-streaming packet, currently a
 
129
       DRIZZLE_COMMAND_CHANGE_USER command. */
 
130
 
 
131
    con->packet_size= 1  /* Command */
 
132
                    + strlen(con->user) + 1
 
133
                    + 1  /* Scramble size */
 
134
                    + DRIZZLE_MAX_SCRAMBLE_SIZE
 
135
                    + strlen(con->db) + 1;
 
136
 
 
137
    /* Flush buffer if there is not enough room. */
 
138
    free_size= (size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer);
 
139
    if (free_size < con->packet_size)
 
140
    {
 
141
      drizzle_state_push(con, drizzle_state_write);
 
142
      return DRIZZLE_RETURN_OK;
 
143
    }
 
144
 
 
145
    /* Store packet size at the end since it may change. */
 
146
    con->packet_number= 1;
 
147
    ptr= start;
 
148
    ptr[3]= 0;
 
149
    if (con->options & DRIZZLE_CON_MYSQL)
 
150
      ptr[4]= (uint8_t)(con->command);
 
151
    else
 
152
      ptr[4]= (uint8_t)(_command_drizzle_map[con->command]);
 
153
    ptr+= 5;
 
154
 
 
155
    if (con->command == DRIZZLE_COMMAND_CHANGE_USER)
 
156
    {
 
157
      ptr= drizzle_pack_auth(con, ptr, &ret);
 
158
      if (ret != DRIZZLE_RETURN_OK)
 
159
        return ret;
 
160
 
 
161
      con->buffer_size+= (4 + con->packet_size);
 
162
    }
 
163
    else if (con->command_total == 0)
 
164
    {
 
165
      con->packet_size= 1;
 
166
      con->buffer_size+= 5;
 
167
    }
 
168
    else
 
169
    {
 
170
      con->packet_size= 1 + con->command_total;
 
171
      free_size-= 5;
 
172
 
 
173
      /* Copy as much of the data in as we can into the write buffer. */
 
174
      if (con->command_size <= free_size)
 
175
      {
 
176
        memcpy(ptr, con->command_data, con->command_size);
 
177
        con->command_offset= con->command_size;
 
178
        con->command_data= NULL;
 
179
        con->buffer_size+= 5 + con->command_size;
 
180
      }
 
181
      else
 
182
      {
 
183
        memcpy(ptr, con->command_data, free_size);
 
184
        con->command_offset= free_size;
 
185
        con->command_data+= free_size;
 
186
        con->command_size-= free_size;
 
187
        con->buffer_size+= 5 + free_size;
 
188
      }
 
189
    }
 
190
 
 
191
    /* Store packet size now. */
 
192
    drizzle_set_byte3(start, con->packet_size);
 
193
  }
 
194
  else
 
195
  {
 
196
    /* Write directly from the caller buffer for the rest. */
 
197
    con->buffer_ptr= con->command_data;
 
198
    con->buffer_size= con->command_size;
 
199
    con->command_offset+= con->command_size;
 
200
    con->command_data= NULL;
 
201
  }
 
202
 
 
203
  if (con->command_offset == con->command_total)
 
204
  {
 
205
    drizzle_state_pop(con);
 
206
 
 
207
    if (!(con->options & (DRIZZLE_CON_RAW_PACKET |
 
208
                          DRIZZLE_CON_NO_RESULT_READ)) &&
 
209
        con->command != DRIZZLE_COMMAND_FIELD_LIST)
 
210
    {
 
211
      drizzle_state_push(con, drizzle_state_result_read);
 
212
      drizzle_state_push(con, drizzle_state_packet_read);
 
213
    }
 
214
  }
 
215
 
 
216
  drizzle_state_push(con, drizzle_state_write);
 
217
 
 
218
  return DRIZZLE_RETURN_OK;
 
219
}