X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=src%2Flibmemcachedprotocol%2Fascii_handler.c;h=52db79223b7d87ee4285498bfe8041fbeedffed9;hb=808f81dba2553a1e552e8f3cea3ee376ad7d3558;hp=449b650d7e8e9f5b46fd2373c98b705f6b82254d;hpb=5e760300d15ef4c5b7eed3fb9f37920ebca2f6ec;p=m6w6%2Flibmemcached diff --git a/src/libmemcachedprotocol/ascii_handler.c b/src/libmemcachedprotocol/ascii_handler.c index 449b650d..52db7922 100644 --- a/src/libmemcachedprotocol/ascii_handler.c +++ b/src/libmemcachedprotocol/ascii_handler.c @@ -1,54 +1,30 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * - * Libmemcached library - * - * Copyright (C) 2011 Data Differential, http://datadifferential.com/ - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * The names of its contributors may not be used to endorse or - * promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include +/* + +--------------------------------------------------------------------+ + | libmemcached - C/C++ Client Library for memcached | + +--------------------------------------------------------------------+ + | Redistribution and use in source and binary forms, with or without | + | modification, are permitted under the terms of the BSD license. | + | You should have received a copy of the license in a bundled file | + | named LICENSE; in case you did not receive a copy you can review | + | the terms online at: https://opensource.org/licenses/BSD-3-Clause | + +--------------------------------------------------------------------+ + | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ | + | Copyright (c) 2020 Michael Wallner | + +--------------------------------------------------------------------+ +*/ + +#include "libmemcachedprotocol/common.h" #include #include #include #include #include +#include - -static void print_ascii_command(memcached_protocol_client_st *client) -{ - if (client->is_verbose) - { - switch (client->ascii_command) - { +static void print_ascii_command(memcached_protocol_client_st *client) { + if (client->is_verbose) { + switch (client->ascii_command) { case SET_CMD: fprintf(stderr, "%s:%d SET_CMD\n", __FILE__, __LINE__); break; @@ -117,7 +93,6 @@ static void print_ascii_command(memcached_protocol_client_st *client) case UNKNOWN_CMD: fprintf(stderr, "%s:%d UNKNOWN_CMD\n", __FILE__, __LINE__); break; - } } } @@ -129,27 +104,22 @@ static void print_ascii_command(memcached_protocol_client_st *client) * characters or invalid length) * @todo add length! */ -static uint16_t parse_ascii_key(char **start) -{ - uint16_t len= 0; - char *c= *start; +static uint16_t parse_ascii_key(char **start) { + uint16_t len = 0; + char *c = *start; /* Strip leading whitespaces */ - while (isspace(*c)) - { + while (isspace(*c)) { ++c; } - *start= c; + *start = c; - while (*c != '\0' && !isspace(*c) && !iscntrl(*c)) - { + while (*c != '\0' && !isspace(*c) && !iscntrl(*c)) { ++c; ++len; } - - if (len == 0 || len > 240 || (*c != '\0' && *c != '\r' && iscntrl(*c))) - { + if (len == 0 || len > 240 || (*c != '\0' && *c != '\r' && iscntrl(*c))) { return 0; } @@ -162,19 +132,17 @@ static uint16_t parse_ascii_key(char **start) * @param text the text to spool * @return status of the spool operation */ -static protocol_binary_response_status raw_response_handler(memcached_protocol_client_st *client, const char *text) -{ - if (client->is_verbose) - { +static protocol_binary_response_status +ascii_raw_response_handler(memcached_protocol_client_st *client, const char *text) { + if (client->is_verbose) { fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, text); } - if (client->root->drain(client) == false) - { + if (client->root->drain(client) == false) { return PROTOCOL_BINARY_RESPONSE_EINTERNAL; } - assert(client->output != NULL); + assert(client->output); #if 0 if (client->output == NULL) { @@ -214,31 +182,34 @@ static protocol_binary_response_status raw_response_handler(memcached_protocol_c * format of the command being sent * @param client the client to send the message to */ -static void send_command_usage(memcached_protocol_client_st *client) -{ - const char *errmsg[]= { - [GET_CMD]= "CLIENT_ERROR: Syntax error: get *\r\n", - [GETS_CMD]= "CLIENT_ERROR: Syntax error: gets *\r\n", - [SET_CMD]= "CLIENT_ERROR: Syntax error: set [noreply]\r\n", - [ADD_CMD]= "CLIENT_ERROR: Syntax error: add [noreply]\r\n", - [REPLACE_CMD]= "CLIENT_ERROR: Syntax error: replace [noreply]\r\n", - [CAS_CMD]= "CLIENT_ERROR: Syntax error: cas [noreply]\r\n", - [APPEND_CMD]= "CLIENT_ERROR: Syntax error: append [noreply]\r\n", - [PREPEND_CMD]= "CLIENT_ERROR: Syntax error: prepend [noreply]\r\n", - [DELETE_CMD]= "CLIENT_ERROR: Syntax error: delete_object [noreply]\r\n", - [INCR_CMD]= "CLIENT_ERROR: Syntax error: incr [noreply]\r\n", - [DECR_CMD]= "CLIENT_ERROR: Syntax error: decr [noreply]\r\n", - [STATS_CMD]= "CLIENT_ERROR: Syntax error: stats [key]\r\n", - [FLUSH_ALL_CMD]= "CLIENT_ERROR: Syntax error: flush_all [timeout] [noreply]\r\n", - [VERSION_CMD]= "CLIENT_ERROR: Syntax error: version\r\n", - [QUIT_CMD]="CLIENT_ERROR: Syntax error: quit\r\n", - - [VERBOSITY_CMD]= "CLIENT_ERROR: Syntax error: verbosity \r\n", - [UNKNOWN_CMD]= "CLIENT_ERROR: Unknown command\r\n", +static void send_command_usage(memcached_protocol_client_st *client) { + const char *errmsg[] = { + [GET_CMD] = "CLIENT_ERROR: Syntax error: get *\r\n", + [GETS_CMD] = "CLIENT_ERROR: Syntax error: gets *\r\n", + [SET_CMD] = "CLIENT_ERROR: Syntax error: set [noreply]\r\n", + [ADD_CMD] = "CLIENT_ERROR: Syntax error: add [noreply]\r\n", + [REPLACE_CMD] = + "CLIENT_ERROR: Syntax error: replace [noreply]\r\n", + [CAS_CMD] = + "CLIENT_ERROR: Syntax error: cas [noreply]\r\n", + [APPEND_CMD] = + "CLIENT_ERROR: Syntax error: append [noreply]\r\n", + [PREPEND_CMD] = + "CLIENT_ERROR: Syntax error: prepend [noreply]\r\n", + [DELETE_CMD] = "CLIENT_ERROR: Syntax error: delete_object [noreply]\r\n", + [INCR_CMD] = "CLIENT_ERROR: Syntax error: incr [noreply]\r\n", + [DECR_CMD] = "CLIENT_ERROR: Syntax error: decr [noreply]\r\n", + [STATS_CMD] = "CLIENT_ERROR: Syntax error: stats [key]\r\n", + [FLUSH_ALL_CMD] = "CLIENT_ERROR: Syntax error: flush_all [timeout] [noreply]\r\n", + [VERSION_CMD] = "CLIENT_ERROR: Syntax error: version\r\n", + [QUIT_CMD] = "CLIENT_ERROR: Syntax error: quit\r\n", + + [VERBOSITY_CMD] = "CLIENT_ERROR: Syntax error: verbosity \r\n", + [UNKNOWN_CMD] = "CLIENT_ERROR: Unknown command\r\n", }; client->mute = false; - raw_response_handler(client, errmsg[client->ascii_command]); + ascii_raw_response_handler(client, errmsg[client->ascii_command]); } /** @@ -247,14 +218,12 @@ static void send_command_usage(memcached_protocol_client_st *client) * @param text the length of the body * @param textlen the length of the body */ -static protocol_binary_response_status ascii_version_response_handler(const void *cookie, - const void *text, - uint32_t textlen) -{ - memcached_protocol_client_st *client= (memcached_protocol_client_st*)cookie; - raw_response_handler(client, "VERSION "); +static protocol_binary_response_status +ascii_version_response_handler(const void *cookie, const void *text, uint32_t textlen) { + memcached_protocol_client_st *client = (memcached_protocol_client_st *) cookie; + ascii_raw_response_handler(client, "VERSION "); client->root->spool(client, text, textlen); - raw_response_handler(client, "\r\n"); + ascii_raw_response_handler(client, "\r\n"); return PROTOCOL_BINARY_RESPONSE_SUCCESS; } @@ -269,28 +238,18 @@ static protocol_binary_response_status ascii_version_response_handler(const void * @param cas the CAS id for the item */ static protocol_binary_response_status -ascii_get_response_handler(const void *cookie, - const void *key, - uint16_t keylen, - const void *body, - uint32_t bodylen, - uint32_t flags, - uint64_t cas) -{ - memcached_protocol_client_st *client= (void*)cookie; +ascii_get_response_handler(const void *cookie, const void *key, uint16_t keylen, const void *body, + uint32_t bodylen, uint32_t flags, uint64_t cas) { + memcached_protocol_client_st *client = (void *) cookie; char buffer[300]; strcpy(buffer, "VALUE "); - const char *source= key; - char *dest= buffer + 6; + const char *source = key; + char *dest = buffer + 6; - for (int x= 0; x < keylen; ++x) - { - if (*source != '\0' && !isspace(*source) && !iscntrl(*source)) - { - *dest= *source; - } - else - { + for (int x = 0; x < keylen; ++x) { + if (*source != '\0' && !isspace(*source) && !iscntrl(*source)) { + *dest = *source; + } else { return PROTOCOL_BINARY_RESPONSE_EINVAL; /* key constraints in ascii */ } @@ -298,15 +257,11 @@ ascii_get_response_handler(const void *cookie, ++source; } - size_t used= (size_t)(dest - buffer); + size_t used = (size_t)(dest - buffer); - if (client->ascii_command == GETS_CMD) - { - snprintf(dest, sizeof(buffer) - used, " %u %u %" PRIu64 "\r\n", flags, - bodylen, cas); - } - else - { + if (client->ascii_command == GETS_CMD) { + snprintf(dest, sizeof(buffer) - used, " %u %u %" PRIu64 "\r\n", flags, bodylen, cas); + } else { snprintf(dest, sizeof(buffer) - used, " %u %u\r\n", flags, bodylen); } @@ -326,25 +281,19 @@ ascii_get_response_handler(const void *cookie, * @param bodylen the length of the body */ static protocol_binary_response_status ascii_stat_response_handler(const void *cookie, - const void *key, - uint16_t keylen, + const void *key, uint16_t keylen, const void *body, - uint32_t bodylen) -{ - - memcached_protocol_client_st *client= (void*)cookie; + uint32_t bodylen) { + memcached_protocol_client_st *client = (void *) cookie; - if (key != NULL) - { - raw_response_handler(client, "STAT "); + if (key) { + ascii_raw_response_handler(client, "STAT "); client->root->spool(client, key, keylen); - raw_response_handler(client, " "); + ascii_raw_response_handler(client, " "); client->root->spool(client, body, bodylen); - raw_response_handler(client, "\r\n"); - } - else - { - raw_response_handler(client, "END\r\n"); + ascii_raw_response_handler(client, "\r\n"); + } else { + ascii_raw_response_handler(client, "END\r\n"); } return PROTOCOL_BINARY_RESPONSE_SUCCESS; @@ -356,35 +305,27 @@ static protocol_binary_response_status ascii_stat_response_handler(const void *c * @param buffer the complete get(s) command * @param end the last character in the command */ -static void ascii_process_gets(memcached_protocol_client_st *client, - char *buffer, char *end) -{ - char *key= buffer; +static void ascii_process_gets(memcached_protocol_client_st *client, char *buffer, char *end) { + char *key = buffer; /* Skip command */ key += (client->ascii_command == GETS_CMD) ? 5 : 4; - int num_keys= 0; - while (key < end) - { - uint16_t nkey= parse_ascii_key(&key); - if (nkey == 0) /* Invalid key... stop processing this line */ - { + int num_keys = 0; + while (key < end) { + uint16_t nkey = parse_ascii_key(&key); + if (nkey == 0) /* Invalid key... stop processing this line */ { break; } - (void)client->root->callback->interface.v1.get(client, key, nkey, - ascii_get_response_handler); + (void) client->root->callback->interface.v1.get(client, key, nkey, ascii_get_response_handler); key += nkey; ++num_keys; } - if (num_keys == 0) - { + if (num_keys == 0) { send_command_usage(client); - } - else - { + } else { client->root->spool(client, "END\r\n", 5); } } @@ -398,37 +339,31 @@ static void ascii_process_gets(memcached_protocol_client_st *client, * @size the number of elements in the vector * @return the number of tokens in the vector */ -static int ascii_tokenize_command(char *str, char *end, char **vec, int size) -{ - int elem= 0; +static int ascii_tokenize_command(char *str, char *end, char **vec, int size) { + int elem = 0; - while (str < end) - { + while (str < end) { /* Skip leading blanks */ - while (str < end && isspace(*str)) - { + while (str < end && isspace(*str)) { ++str; } - if (str == end) - { + if (str == end) { return elem; } - vec[elem++]= str; + vec[elem++] = str; /* find the next non-blank field */ - while (str < end && !isspace(*str)) - { + while (str < end && !isspace(*str)) { ++str; } /* zero-terminate it for easier parsing later on */ - *str= '\0'; + *str = '\0'; ++str; /* Is the vector full? */ - if (elem == size) - { + if (elem == size) { break; } } @@ -445,55 +380,48 @@ static int ascii_tokenize_command(char *str, char *end, char **vec, int size) * @param start pointer to the first character in the buffer to recover * @param end pointer to the last character in the buffer to recover */ -static void recover_tokenize_command(char *start, char *end) -{ - while (start < end) - { +static void recover_tokenize_command(char *start, char *end) { + while (start < end) { if (*start == '\0') - *start= ' '; + *start = ' '; ++start; } - *end= '\n'; + *end = '\n'; } /** * Convert the textual command into a comcode */ -static enum ascii_cmd ascii_to_cmd(char *start, size_t length) -{ +static enum ascii_cmd ascii_to_cmd(char *start, size_t length) { struct { const char *cmd; size_t len; enum ascii_cmd cc; - } commands[]= { - { .cmd= "get", .len= 3, .cc= GET_CMD }, - { .cmd= "gets", .len= 4, .cc= GETS_CMD }, - { .cmd= "set", .len= 3, .cc= SET_CMD }, - { .cmd= "add", .len= 3, .cc= ADD_CMD }, - { .cmd= "replace", .len= 7, .cc= REPLACE_CMD }, - { .cmd= "cas", .len= 3, .cc= CAS_CMD }, - { .cmd= "append", .len= 6, .cc= APPEND_CMD }, - { .cmd= "prepend", .len= 7, .cc= PREPEND_CMD }, - { .cmd= "delete_object", .len= 6, .cc= DELETE_CMD }, - { .cmd= "incr", .len= 4, .cc= INCR_CMD }, - { .cmd= "decr", .len= 4, .cc= DECR_CMD }, - { .cmd= "stats", .len= 5, .cc= STATS_CMD }, - { .cmd= "flush_all", .len= 9, .cc= FLUSH_ALL_CMD }, - { .cmd= "version", .len= 7, .cc= VERSION_CMD }, - { .cmd= "quit", .len= 4, .cc= QUIT_CMD }, - { .cmd= "verbosity", .len= 9, .cc= VERBOSITY_CMD }, - { .cmd= NULL, .len= 0, .cc= UNKNOWN_CMD }}; - - int x= 0; + } commands[] = {{.cmd = "get", .len = 3, .cc = GET_CMD}, + {.cmd = "gets", .len = 4, .cc = GETS_CMD}, + {.cmd = "set", .len = 3, .cc = SET_CMD}, + {.cmd = "add", .len = 3, .cc = ADD_CMD}, + {.cmd = "replace", .len = 7, .cc = REPLACE_CMD}, + {.cmd = "cas", .len = 3, .cc = CAS_CMD}, + {.cmd = "append", .len = 6, .cc = APPEND_CMD}, + {.cmd = "prepend", .len = 7, .cc = PREPEND_CMD}, + {.cmd = "delete_object", .len = 6, .cc = DELETE_CMD}, + {.cmd = "incr", .len = 4, .cc = INCR_CMD}, + {.cmd = "decr", .len = 4, .cc = DECR_CMD}, + {.cmd = "stats", .len = 5, .cc = STATS_CMD}, + {.cmd = "flush_all", .len = 9, .cc = FLUSH_ALL_CMD}, + {.cmd = "version", .len = 7, .cc = VERSION_CMD}, + {.cmd = "quit", .len = 4, .cc = QUIT_CMD}, + {.cmd = "verbosity", .len = 9, .cc = VERBOSITY_CMD}, + {.cmd = NULL, .len = 0, .cc = UNKNOWN_CMD}}; + + int x = 0; while (commands[x].len > 0) { - if (length >= commands[x].len) - { - if (strncmp(start, commands[x].cmd, commands[x].len) == 0) - { + if (length >= commands[x].len) { + if (strncmp(start, commands[x].cmd, commands[x].len) == 0) { /* Potential hit */ - if (length == commands[x].len || isspace(*(start + commands[x].len))) - { + if (length == commands[x].len || isspace(*(start + commands[x].len))) { return commands[x].cc; } } @@ -511,102 +439,74 @@ static enum ascii_cmd ascii_to_cmd(char *start, size_t length) * @param tokens the command as a vector * @param ntokens the number of items in the vector */ -static void process_delete(memcached_protocol_client_st *client, - char **tokens, int ntokens) -{ - char *key= tokens[1]; +static void process_delete(memcached_protocol_client_st *client, char **tokens, int ntokens) { + char *key = tokens[1]; uint16_t nkey; - if (ntokens != 2 || (nkey= parse_ascii_key(&key)) == 0) - { + if (ntokens != 2 || (nkey = parse_ascii_key(&key)) == 0) { send_command_usage(client); return; } - if (client->root->callback->interface.v1.delete_object == NULL) - { - raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); + if (client->root->callback->interface.v1.delete_object == NULL) { + ascii_raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); return; } - protocol_binary_response_status rval= client->root->callback->interface.v1.delete_object(client, key, nkey, 0); + protocol_binary_response_status rval = + client->root->callback->interface.v1.delete_object(client, key, nkey, 0); - if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS) - { - raw_response_handler(client, "DELETED\r\n"); - } - else if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT) - { - raw_response_handler(client, "NOT_FOUND\r\n"); - } - else - { + if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { + ascii_raw_response_handler(client, "DELETED\r\n"); + } else if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT) { + ascii_raw_response_handler(client, "NOT_FOUND\r\n"); + } else { char msg[80]; - snprintf(msg, sizeof(msg), "SERVER_ERROR: delete_object failed %u\r\n",(uint32_t)rval); - raw_response_handler(client, msg); + snprintf(msg, sizeof(msg), "SERVER_ERROR: delete_object failed %u\r\n", (uint32_t) rval); + ascii_raw_response_handler(client, msg); } } -static void process_arithmetic(memcached_protocol_client_st *client, - char **tokens, int ntokens) -{ - char *key= tokens[1]; +static void process_arithmetic(memcached_protocol_client_st *client, char **tokens, int ntokens) { + char *key = tokens[1]; uint16_t nkey; - if (ntokens != 3 || (nkey= parse_ascii_key(&key)) == 0) - { + if (ntokens != 3 || (nkey = parse_ascii_key(&key)) == 0) { send_command_usage(client); return; } uint64_t cas; uint64_t result; - errno= 0; - uint64_t delta= strtoull(tokens[2], NULL, 10); - if (errno != 0) - { + errno = 0; + uint64_t delta = strtoull(tokens[2], NULL, 10); + if (errno) { return; // Error } protocol_binary_response_status rval; - if (client->ascii_command == INCR_CMD) - { - if (client->root->callback->interface.v1.increment == NULL) - { - raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); + if (client->ascii_command == INCR_CMD) { + if (client->root->callback->interface.v1.increment == NULL) { + ascii_raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); return; } - rval= client->root->callback->interface.v1.increment(client, - key, nkey, - delta, 0, - 0, - &result, - &cas); - } - else - { - if (client->root->callback->interface.v1.decrement == NULL) - { - raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); + rval = client->root->callback->interface.v1.increment(client, key, nkey, delta, 0, 0, &result, + &cas); + } else { + if (client->root->callback->interface.v1.decrement == NULL) { + ascii_raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); return; } - rval= client->root->callback->interface.v1.decrement(client, - key, nkey, - delta, 0, - 0, - &result, - &cas); + rval = client->root->callback->interface.v1.decrement(client, key, nkey, delta, 0, 0, &result, + &cas); } - if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS) - { + if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { char buffer[80]; - snprintf(buffer, sizeof(buffer), "%"PRIu64"\r\n", result); - raw_response_handler(client, buffer); - } - else - { - raw_response_handler(client, "NOT_FOUND\r\n"); + snprintf(buffer, sizeof(buffer), "%" PRIu64 "\r\n", result); + ascii_raw_response_handler(client, buffer); + } else { + ascii_raw_response_handler(client, "NOT_FOUND\r\n"); } } @@ -615,77 +515,61 @@ static void process_arithmetic(memcached_protocol_client_st *client, * @param key pointer to the first character after "stats" * @param end pointer to the "\n" */ -static void process_stats(memcached_protocol_client_st *client, - char *key, char *end) -{ - if (client->root->callback->interface.v1.stat == NULL) - { - raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); +static void process_stats(memcached_protocol_client_st *client, char *key, char *end) { + if (client->root->callback->interface.v1.stat == NULL) { + ascii_raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); return; } - while (isspace(*key)) - { + while (isspace(*key)) { key++; } - uint16_t nkey= (uint16_t)(end - key); - (void)client->root->callback->interface.v1.stat(client, key, nkey, - ascii_stat_response_handler); + uint16_t nkey = (uint16_t)(end - key); + (void) client->root->callback->interface.v1.stat(client, key, nkey, ascii_stat_response_handler); } -static void process_version(memcached_protocol_client_st *client, - char **tokens, int ntokens) -{ - (void)tokens; - if (ntokens != 1) - { +static void process_version(memcached_protocol_client_st *client, char **tokens, int ntokens) { + (void) tokens; + if (ntokens != 1) { send_command_usage(client); return; } - if (client->root->callback->interface.v1.version == NULL) - { - raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); + if (client->root->callback->interface.v1.version == NULL) { + ascii_raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); return; } - client->root->callback->interface.v1.version(client, - ascii_version_response_handler); + client->root->callback->interface.v1.version(client, ascii_version_response_handler); } -static void process_flush(memcached_protocol_client_st *client, - char **tokens, int ntokens) -{ - if (ntokens > 2) - { +static void process_flush(memcached_protocol_client_st *client, char **tokens, int ntokens) { + if (ntokens > 2) { send_command_usage(client); return; } - if (client->root->callback->interface.v1.flush_object == NULL) - { - raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); + if (client->root->callback->interface.v1.flush_object == NULL) { + ascii_raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); return; } - uint32_t timeout= 0; - if (ntokens == 2) - { - errno= 0; - timeout= (uint32_t)strtoul(tokens[1], NULL, 10); - if (errno != 0) - { + uint32_t timeout = 0; + if (ntokens == 2) { + errno = 0; + timeout = (uint32_t) strtoul(tokens[1], NULL, 10); + if (errno) { return; // Error } } protocol_binary_response_status rval; - rval= client->root->callback->interface.v1.flush_object(client, timeout); + rval = client->root->callback->interface.v1.flush_object(client, timeout); if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS) - raw_response_handler(client, "OK\r\n"); + ascii_raw_response_handler(client, "OK\r\n"); else - raw_response_handler(client, "SERVER_ERROR: internal error\r\n"); + ascii_raw_response_handler(client, "SERVER_ERROR: internal error\r\n"); } /** @@ -702,111 +586,80 @@ static void process_flush(memcached_protocol_client_st *client, * 0 storage command completed, continue processing * 1 We need more data, so just go ahead and wait for more! */ -static inline int process_storage_command(memcached_protocol_client_st *client, - char **tokens, int ntokens, char *start, - char **end, ssize_t length) -{ - (void)ntokens; /* already checked */ - char *key= tokens[1]; - uint16_t nkey= parse_ascii_key(&key); - if (nkey == 0) - { +static inline int process_storage_command(memcached_protocol_client_st *client, char **tokens, + int ntokens, char *start, char **end, ssize_t length) { + (void) ntokens; /* already checked */ + char *key = tokens[1]; + uint16_t nkey = parse_ascii_key(&key); + if (nkey == 0) { /* return error */ - raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); + ascii_raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); return -1; } - errno= 0; - uint32_t flags= (uint32_t)strtoul(tokens[2], NULL, 10); - if (errno != 0) - { + errno = 0; + uint32_t flags = (uint32_t) strtoul(tokens[2], NULL, 10); + if (errno) { /* return error */ - raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); + ascii_raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); return -1; } - uint32_t timeout= (uint32_t)strtoul(tokens[3], NULL, 10); - if (errno != 0) - { + uint32_t timeout = (uint32_t) strtoul(tokens[3], NULL, 10); + if (errno) { /* return error */ - raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); + ascii_raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); return -1; } - unsigned long nbytes= strtoul(tokens[4], NULL, 10); - if (errno != 0) - { + unsigned long nbytes = strtoul(tokens[4], NULL, 10); + if (errno) { /* return error */ - raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); + ascii_raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); return -1; } /* Do we have all data? */ - unsigned long need= nbytes + (unsigned long)((*end - start) + 1) + 2; /* \n\r\n */ - if ((ssize_t)need > length) - { + unsigned long need = nbytes + (unsigned long) ((*end - start) + 1) + 2; /* \n\r\n */ + if ((ssize_t) need > length) { /* Keep on reading */ recover_tokenize_command(start, *end); return 1; } - void *data= (*end) + 1; - uint64_t cas= 0; + void *data = (*end) + 1; + uint64_t cas = 0; uint64_t result_cas; protocol_binary_response_status rval; - switch (client->ascii_command) - { + switch (client->ascii_command) { case SET_CMD: - rval= client->root->callback->interface.v1.set(client, key, - (uint16_t)nkey, - data, - (uint32_t)nbytes, - flags, - timeout, cas, - &result_cas); + rval = client->root->callback->interface.v1.set( + client, key, (uint16_t) nkey, data, (uint32_t) nbytes, flags, timeout, cas, &result_cas); break; case ADD_CMD: - rval= client->root->callback->interface.v1.add(client, key, - (uint16_t)nkey, - data, - (uint32_t)nbytes, - flags, - timeout, &result_cas); + rval = client->root->callback->interface.v1.add(client, key, (uint16_t) nkey, data, + (uint32_t) nbytes, flags, timeout, &result_cas); break; case CAS_CMD: - errno= 0; - cas= strtoull(tokens[5], NULL, 10); - if (errno != 0) - { + errno = 0; + cas = strtoull(tokens[5], NULL, 10); + if (errno) { /* return error */ - raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); + ascii_raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); return -1; } /* FALLTHROUGH */ case REPLACE_CMD: - rval= client->root->callback->interface.v1.replace(client, key, - (uint16_t)nkey, - data, - (uint32_t)nbytes, - flags, - timeout, cas, - &result_cas); + rval = client->root->callback->interface.v1.replace( + client, key, (uint16_t) nkey, data, (uint32_t) nbytes, flags, timeout, cas, &result_cas); break; case APPEND_CMD: - rval= client->root->callback->interface.v1.append(client, key, - (uint16_t)nkey, - data, - (uint32_t)nbytes, - cas, - &result_cas); + rval = client->root->callback->interface.v1.append(client, key, (uint16_t) nkey, data, + (uint32_t) nbytes, cas, &result_cas); break; case PREPEND_CMD: - rval= client->root->callback->interface.v1.prepend(client, key, - (uint16_t)nkey, - data, - (uint32_t)nbytes, - cas, - &result_cas); + rval = client->root->callback->interface.v1.prepend(client, key, (uint16_t) nkey, data, + (uint32_t) nbytes, cas, &result_cas); break; /* gcc complains if I don't put all of the enums in here.. */ @@ -825,30 +678,19 @@ static inline int process_storage_command(memcached_protocol_client_st *client, abort(); /* impossible */ } - if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS) - { - raw_response_handler(client, "STORED\r\n"); - } - else - { - if (client->ascii_command == CAS_CMD) - { - if (rval == PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS) - { - raw_response_handler(client, "EXISTS\r\n"); - } - else if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT) - { - raw_response_handler(client, "NOT_FOUND\r\n"); - } - else - { - raw_response_handler(client, "NOT_STORED\r\n"); + if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { + ascii_raw_response_handler(client, "STORED\r\n"); + } else { + if (client->ascii_command == CAS_CMD) { + if (rval == PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS) { + ascii_raw_response_handler(client, "EXISTS\r\n"); + } else if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT) { + ascii_raw_response_handler(client, "NOT_FOUND\r\n"); + } else { + ascii_raw_response_handler(client, "NOT_STORED\r\n"); } - } - else - { - raw_response_handler(client, "NOT_STORED\r\n"); + } else { + ascii_raw_response_handler(client, "NOT_STORED\r\n"); } } @@ -857,114 +699,90 @@ static inline int process_storage_command(memcached_protocol_client_st *client, return 0; } -static int process_cas_command(memcached_protocol_client_st *client, - char **tokens, int ntokens, char *start, - char **end, ssize_t length) -{ - if (ntokens != 6) - { +static int process_cas_command(memcached_protocol_client_st *client, char **tokens, int ntokens, + char *start, char **end, ssize_t length) { + if (ntokens != 6) { send_command_usage(client); return false; } - if (client->root->callback->interface.v1.replace == NULL) - { - raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); + if (client->root->callback->interface.v1.replace == NULL) { + ascii_raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); return false; } return process_storage_command(client, tokens, ntokens, start, end, length); } -static int process_set_command(memcached_protocol_client_st *client, - char **tokens, int ntokens, char *start, - char **end, ssize_t length) -{ - if (ntokens != 5) - { +static int process_set_command(memcached_protocol_client_st *client, char **tokens, int ntokens, + char *start, char **end, ssize_t length) { + if (ntokens != 5) { send_command_usage(client); return false; } - if (client->root->callback->interface.v1.set == NULL) - { - raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); + if (client->root->callback->interface.v1.set == NULL) { + ascii_raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); return false; } return process_storage_command(client, tokens, ntokens, start, end, length); } -static int process_add_command(memcached_protocol_client_st *client, - char **tokens, int ntokens, char *start, - char **end, ssize_t length) -{ - if (ntokens != 5) - { +static int process_add_command(memcached_protocol_client_st *client, char **tokens, int ntokens, + char *start, char **end, ssize_t length) { + if (ntokens != 5) { send_command_usage(client); return false; } - if (client->root->callback->interface.v1.add == NULL) - { - raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); + if (client->root->callback->interface.v1.add == NULL) { + ascii_raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); return false; } return process_storage_command(client, tokens, ntokens, start, end, length); } -static int process_replace_command(memcached_protocol_client_st *client, - char **tokens, int ntokens, char *start, - char **end, ssize_t length) -{ - if (ntokens != 5) - { +static int process_replace_command(memcached_protocol_client_st *client, char **tokens, int ntokens, + char *start, char **end, ssize_t length) { + if (ntokens != 5) { send_command_usage(client); return false; } - if (client->root->callback->interface.v1.replace == NULL) - { - raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); + if (client->root->callback->interface.v1.replace == NULL) { + ascii_raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); return false; } return process_storage_command(client, tokens, ntokens, start, end, length); } -static int process_append_command(memcached_protocol_client_st *client, - char **tokens, int ntokens, char *start, - char **end, ssize_t length) -{ - if (ntokens != 5) - { +static int process_append_command(memcached_protocol_client_st *client, char **tokens, int ntokens, + char *start, char **end, ssize_t length) { + if (ntokens != 5) { send_command_usage(client); return false; } - if (client->root->callback->interface.v1.append == NULL) - { - raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); + if (client->root->callback->interface.v1.append == NULL) { + ascii_raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); return false; } return process_storage_command(client, tokens, ntokens, start, end, length); } -static int process_prepend_command(memcached_protocol_client_st *client, - char **tokens, int ntokens, char *start, - char **end, ssize_t length) -{ - if (ntokens != 5) - { +static int process_prepend_command(memcached_protocol_client_st *client, char **tokens, int ntokens, + char *start, char **end, ssize_t length) { + if (ntokens != 5) { send_command_usage(client); return false; } - if (client->root->callback->interface.v1.prepend == NULL) - { - raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); + if (client->root->callback->interface.v1.prepend == NULL) { + ascii_raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n"); return false; } @@ -976,89 +794,77 @@ static int process_prepend_command(memcached_protocol_client_st *client, * a optimal ascii support, I just convert the ASCII commands to the binary * protocol and calls back into the command handlers for the binary protocol ;) */ -memcached_protocol_event_t memcached_ascii_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr) -{ - char *ptr= (char*)client->root->input_buffer; - *endptr= ptr; +memcached_protocol_event_t +memcached_ascii_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, + void **endptr) { + char *ptr = (char *) client->root->input_buffer; + *endptr = ptr; do { /* Do we have \n (indicating the command preamble)*/ - char *end= memchr(ptr, '\n', (size_t)*length); - if (end == NULL) - { - *endptr= ptr; + char *end = memchr(ptr, '\n', (size_t) *length); + if (end == NULL) { + *endptr = ptr; return MEMCACHED_PROTOCOL_READ_EVENT; } - client->ascii_command= ascii_to_cmd(ptr, (size_t)(*length)); + client->ascii_command = ascii_to_cmd(ptr, (size_t)(*length)); /* we got all data available, execute the callback! */ - if (client->root->callback->pre_execute != NULL) - { + if (client->root->callback->pre_execute) { client->root->callback->pre_execute(client, NULL); } - /* A multiget lists all of the keys, and I don't want to have an * avector of let's say 512 pointers to tokenize all of them, so let's * just handle them immediately */ - if (client->ascii_command == GET_CMD || - client->ascii_command == GETS_CMD) - { - if (client->root->callback->interface.v1.get != NULL) - { + if (client->ascii_command == GET_CMD || client->ascii_command == GETS_CMD) { + if (client->root->callback->interface.v1.get) { ascii_process_gets(client, ptr, end); + } else { + ascii_raw_response_handler(client, "SERVER_ERROR: Command not implemented\n"); } - else - { - raw_response_handler(client, "SERVER_ERROR: Command not implemented\n"); - } - } - else - { + } else { /* None of the defined commands takes 10 parameters, so lets just use * that as a maximum limit. - */ + */ char *tokens[10]; - int ntokens= ascii_tokenize_command(ptr, end, tokens, 10); + int ntokens = ascii_tokenize_command(ptr, end, tokens, 10); - if (ntokens < 10) - { - client->mute= strcmp(tokens[ntokens - 1], "noreply") == 0; - if (client->mute) - { + if (ntokens < 10) { + client->mute = strcmp(tokens[ntokens - 1], "noreply") == 0; + if (client->mute) { --ntokens; /* processed noreply token*/ } } - int error= 0; + int error = 0; print_ascii_command(client); - switch (client->ascii_command) - { + switch (client->ascii_command) { case SET_CMD: - error= process_set_command(client, tokens, ntokens, ptr, &end, *length); + error = process_set_command(client, tokens, ntokens, ptr, &end, *length); break; case ADD_CMD: - error= process_add_command(client, tokens, ntokens, ptr, &end, *length); + error = process_add_command(client, tokens, ntokens, ptr, &end, *length); break; case REPLACE_CMD: - error= process_replace_command(client, tokens, ntokens, ptr, &end, *length); + error = process_replace_command(client, tokens, ntokens, ptr, &end, *length); break; case CAS_CMD: - error= process_cas_command(client, tokens, ntokens, ptr, &end, *length); + error = process_cas_command(client, tokens, ntokens, ptr, &end, *length); break; case APPEND_CMD: - error= process_append_command(client, tokens, ntokens, ptr, &end, *length); + error = process_append_command(client, tokens, ntokens, ptr, &end, *length); break; case PREPEND_CMD: - error= process_prepend_command(client, tokens, ntokens, ptr, &end, *length); + error = process_prepend_command(client, tokens, ntokens, ptr, &end, *length); break; case DELETE_CMD: @@ -1071,12 +877,9 @@ memcached_protocol_event_t memcached_ascii_protocol_process_data(memcached_proto break; case STATS_CMD: - if (client->mute) - { + if (client->mute) { send_command_usage(client); - } - else - { + } else { recover_tokenize_command(ptr, end); process_stats(client, ptr + 6, end); } @@ -1087,25 +890,18 @@ memcached_protocol_event_t memcached_ascii_protocol_process_data(memcached_proto break; case VERSION_CMD: - if (client->mute) - { + if (client->mute) { send_command_usage(client); - } - else - { + } else { process_version(client, tokens, ntokens); } break; case QUIT_CMD: - if (ntokens != 1 || client->mute) - { + if (ntokens != 1 || client->mute) { send_command_usage(client); - } - else - { - if (client->root->callback->interface.v1.quit != NULL) - { + } else { + if (client->root->callback->interface.v1.quit) { client->root->callback->interface.v1.quit(client); } @@ -1114,13 +910,10 @@ memcached_protocol_event_t memcached_ascii_protocol_process_data(memcached_proto break; case VERBOSITY_CMD: - if (ntokens != 2) - { + if (ntokens != 2) { send_command_usage(client); - } - else - { - raw_response_handler(client, "OK\r\n"); + } else { + ascii_raw_response_handler(client, "OK\r\n"); } break; @@ -1135,27 +928,23 @@ memcached_protocol_event_t memcached_ascii_protocol_process_data(memcached_proto abort(); } - if (error == -1) - { + if (error == -1) { return MEMCACHED_PROTOCOL_ERROR_EVENT; - } - else if (error == 1) - { + } else if (error == 1) { return MEMCACHED_PROTOCOL_READ_EVENT; } } - if (client->root->callback->post_execute != NULL) - { + if (client->root->callback->post_execute) { client->root->callback->post_execute(client, NULL); } /* Move past \n */ ++end; *length -= end - ptr; - ptr= end; + ptr = end; } while (*length > 0); - *endptr= ptr; + *endptr = ptr; return MEMCACHED_PROTOCOL_READ_EVENT; }