4 memcached_response() is used to determine the return result
5 from an issued command.
9 #include "memcached_io.h"
11 static memcached_return
binary_response(memcached_server_st
*ptr
,
12 char *buffer
, size_t buffer_length
,
13 memcached_result_st
*result
);
15 memcached_return
memcached_response(memcached_server_st
*ptr
,
16 char *buffer
, size_t buffer_length
,
17 memcached_result_st
*result
)
22 unsigned int max_messages
;
26 /* UDP at the moment is odd...*/
27 if (ptr
->type
== MEMCACHED_CONNECTION_UDP
)
32 return MEMCACHED_SUCCESS
;
34 read_length
= memcached_io_read(ptr
, buffer
, 8);
37 /* We may have old commands in the buffer not set, first purge */
38 if (ptr
->root
->flags
& MEM_NO_BLOCK
)
39 (void)memcached_io_write(ptr
, NULL
, 0, 1);
41 if (ptr
->root
->flags
& MEM_BINARY_PROTOCOL
)
42 return binary_response(ptr
, buffer
, buffer_length
, result
);
44 max_messages
= memcached_server_response_count(ptr
);
45 for (x
= 0; x
< max_messages
; x
++)
47 size_t total_length
= 0;
55 read_length
= memcached_io_read(ptr
, buffer_ptr
, 1);
56 WATCHPOINT_ASSERT(isgraph(*buffer_ptr
) || isspace(*buffer_ptr
));
60 memcached_io_reset(ptr
);
61 return MEMCACHED_UNKNOWN_READ_FAILURE
;
64 if (*buffer_ptr
== '\n')
70 WATCHPOINT_ASSERT(total_length
<= buffer_length
);
72 if (total_length
>= buffer_length
)
74 memcached_io_reset(ptr
);
75 return MEMCACHED_PROTOCOL_ERROR
;
81 memcached_server_response_decrement(ptr
);
86 case 'V': /* VALUE || VERSION */
87 if (buffer
[1] == 'A') /* VALUE */
91 /* We add back in one because we will need to search for END */
92 memcached_server_response_increment(ptr
);
94 rc
= value_fetch(ptr
, buffer
, result
);
96 rc
= value_fetch(ptr
, buffer
, &ptr
->root
->result
);
100 else if (buffer
[1] == 'E') /* VERSION */
102 return MEMCACHED_SUCCESS
;
106 WATCHPOINT_STRING(buffer
);
107 WATCHPOINT_ASSERT(0);
108 memcached_io_reset(ptr
);
109 return MEMCACHED_UNKNOWN_READ_FAILURE
;
112 return MEMCACHED_SUCCESS
;
113 case 'S': /* STORED STATS SERVER_ERROR */
115 if (buffer
[2] == 'A') /* STORED STATS */
117 memcached_server_response_increment(ptr
);
118 return MEMCACHED_STAT
;
120 else if (buffer
[1] == 'E')
121 return MEMCACHED_SERVER_ERROR
;
122 else if (buffer
[1] == 'T')
123 return MEMCACHED_STORED
;
126 WATCHPOINT_STRING(buffer
);
127 WATCHPOINT_ASSERT(0);
128 memcached_io_reset(ptr
);
129 return MEMCACHED_UNKNOWN_READ_FAILURE
;
132 case 'D': /* DELETED */
133 return MEMCACHED_DELETED
;
134 case 'N': /* NOT_FOUND */
136 if (buffer
[4] == 'F')
137 return MEMCACHED_NOTFOUND
;
138 else if (buffer
[4] == 'S')
139 return MEMCACHED_NOTSTORED
;
142 memcached_io_reset(ptr
);
143 return MEMCACHED_UNKNOWN_READ_FAILURE
;
146 case 'E': /* PROTOCOL ERROR or END */
148 if (buffer
[1] == 'N')
149 return MEMCACHED_END
;
150 else if (buffer
[1] == 'R')
152 memcached_io_reset(ptr
);
153 return MEMCACHED_PROTOCOL_ERROR
;
155 else if (buffer
[1] == 'X')
157 memcached_io_reset(ptr
);
158 return MEMCACHED_DATA_EXISTS
;
162 memcached_io_reset(ptr
);
163 return MEMCACHED_UNKNOWN_READ_FAILURE
;
166 case 'C': /* CLIENT ERROR */
167 memcached_io_reset(ptr
);
168 return MEMCACHED_CLIENT_ERROR
;
170 memcached_io_reset(ptr
);
171 return MEMCACHED_UNKNOWN_READ_FAILURE
;
175 return MEMCACHED_SUCCESS
;
178 char *memcached_result_value(memcached_result_st
*ptr
)
180 memcached_string_st
*sptr
= &ptr
->value
;
181 return memcached_string_value(sptr
);
184 size_t memcached_result_length(memcached_result_st
*ptr
)
186 memcached_string_st
*sptr
= &ptr
->value
;
187 return memcached_string_length(sptr
);
191 * Read a given number of bytes from the server and place it into a specific
192 * buffer. Reset the IO channel or this server if an error occurs.
194 static memcached_return
safe_read(memcached_server_st
*ptr
, void *dta
,
199 while (offset
< size
)
201 ssize_t nread
= memcached_io_read(ptr
, data
+ offset
, size
- offset
);
204 memcached_io_reset(ptr
);
205 return MEMCACHED_UNKNOWN_READ_FAILURE
;
210 return MEMCACHED_SUCCESS
;
213 static memcached_return
binary_response(memcached_server_st
*ptr
,
215 size_t buffer_length
,
216 memcached_result_st
*result
)
218 protocol_binary_response_header header
;
219 memcached_server_response_decrement(ptr
);
221 unlikely (safe_read(ptr
, &header
.bytes
,
222 sizeof(header
.bytes
)) != MEMCACHED_SUCCESS
)
223 return MEMCACHED_UNKNOWN_READ_FAILURE
;
225 unlikely (header
.response
.magic
!= PROTOCOL_BINARY_RES
)
227 memcached_io_reset(ptr
);
228 return MEMCACHED_PROTOCOL_ERROR
;
232 ** Convert the header to host local endian!
234 header
.response
.keylen
= ntohs(header
.response
.keylen
);
235 header
.response
.status
= ntohs(header
.response
.status
);
236 header
.response
.bodylen
= ntohl(header
.response
.bodylen
);
237 header
.response
.cas
= ntohll(header
.response
.cas
);
238 uint32_t bodylen
= header
.response
.bodylen
;
240 if (header
.response
.status
== 0)
242 if ((header
.response
.opcode
== PROTOCOL_BINARY_CMD_GETK
) ||
243 (header
.response
.opcode
== PROTOCOL_BINARY_CMD_GETKQ
))
245 uint16_t keylen
= header
.response
.keylen
;
246 memcached_result_reset(result
);
247 result
->cas
= header
.response
.cas
;
249 if (safe_read(ptr
, &result
->flags
,
250 sizeof(result
->flags
)) != MEMCACHED_SUCCESS
)
252 return MEMCACHED_UNKNOWN_READ_FAILURE
;
254 result
->flags
= ntohl(result
->flags
);
255 bodylen
-= header
.response
.extlen
;
257 result
->key_length
= keylen
;
258 if (safe_read(ptr
, result
->key
, keylen
) != MEMCACHED_SUCCESS
)
260 return MEMCACHED_UNKNOWN_READ_FAILURE
;
264 if (memcached_string_check(&result
->value
,
265 bodylen
) != MEMCACHED_SUCCESS
)
267 memcached_io_reset(ptr
);
268 return MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
271 char *vptr
= memcached_string_value(&result
->value
);
272 if (safe_read(ptr
, vptr
, bodylen
) != MEMCACHED_SUCCESS
)
274 return MEMCACHED_UNKNOWN_READ_FAILURE
;
277 memcached_string_set_length(&result
->value
, bodylen
);
279 else if ((header
.response
.opcode
== PROTOCOL_BINARY_CMD_INCREMENT
) ||
280 (header
.response
.opcode
== PROTOCOL_BINARY_CMD_DECREMENT
))
282 if (bodylen
!= sizeof(uint64_t) || buffer_length
!= sizeof(uint64_t))
284 return MEMCACHED_PROTOCOL_ERROR
;
287 WATCHPOINT_ASSERT(bodylen
== buffer_length
);
289 if (safe_read(ptr
, &val
, sizeof(val
)) != MEMCACHED_SUCCESS
)
291 return MEMCACHED_UNKNOWN_READ_FAILURE
;
295 memcpy(buffer
, &val
, sizeof(val
));
297 else if (header
.response
.opcode
== PROTOCOL_BINARY_CMD_VERSION
)
299 memset(buffer
, 0, buffer_length
);
300 if (bodylen
>= buffer_length
)
301 /* not enough space in buffer.. should not happen... */
302 return MEMCACHED_UNKNOWN_READ_FAILURE
;
304 safe_read(ptr
, buffer
, bodylen
);
306 else if ((header
.response
.opcode
== PROTOCOL_BINARY_CMD_FLUSH
) ||
307 (header
.response
.opcode
== PROTOCOL_BINARY_CMD_QUIT
) ||
308 (header
.response
.opcode
== PROTOCOL_BINARY_CMD_SET
) ||
309 (header
.response
.opcode
== PROTOCOL_BINARY_CMD_ADD
) ||
310 (header
.response
.opcode
== PROTOCOL_BINARY_CMD_REPLACE
) ||
311 (header
.response
.opcode
== PROTOCOL_BINARY_CMD_APPEND
) ||
312 (header
.response
.opcode
== PROTOCOL_BINARY_CMD_PREPEND
) ||
313 (header
.response
.opcode
== PROTOCOL_BINARY_CMD_DELETE
))
315 WATCHPOINT_ASSERT(bodylen
== 0);
316 return MEMCACHED_SUCCESS
;
318 else if (header
.response
.opcode
== PROTOCOL_BINARY_CMD_NOOP
)
320 WATCHPOINT_ASSERT(bodylen
== 0);
321 return MEMCACHED_END
;
323 else if (header
.response
.opcode
== PROTOCOL_BINARY_CMD_STAT
)
326 return MEMCACHED_END
;
327 else if (bodylen
+ 1 > buffer_length
)
328 /* not enough space in buffer.. should not happen... */
329 return MEMCACHED_UNKNOWN_READ_FAILURE
;
332 size_t keylen
= header
.response
.keylen
;
333 memset(buffer
, 0, buffer_length
);
334 safe_read(ptr
, buffer
, keylen
);
335 safe_read(ptr
, buffer
+ keylen
+ 1, bodylen
- keylen
);
340 /* Command not implemented yet! */
341 WATCHPOINT_ASSERT(0);
342 memcached_io_reset(ptr
);
343 return MEMCACHED_PROTOCOL_ERROR
;
346 else if (header
.response
.bodylen
)
348 /* What should I do with the error message??? just discard it for now */
352 size_t nr
= (bodylen
> sizeof(hole
)) ? sizeof(hole
) : bodylen
;
353 safe_read(ptr
, hole
, nr
);
358 memcached_return rc
= MEMCACHED_SUCCESS
;
359 unlikely(header
.response
.status
!= 0)
360 switch (header
.response
.status
)
362 case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
:
363 rc
= MEMCACHED_NOTFOUND
;
365 case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
:
366 rc
= MEMCACHED_DATA_EXISTS
;
368 case PROTOCOL_BINARY_RESPONSE_E2BIG
:
369 case PROTOCOL_BINARY_RESPONSE_EINVAL
:
370 case PROTOCOL_BINARY_RESPONSE_NOT_STORED
:
371 case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND
:
372 case PROTOCOL_BINARY_RESPONSE_ENOMEM
:
374 /* @todo fix the error mappings */
375 rc
= MEMCACHED_PROTOCOL_ERROR
;