From 8ebaec2ee24eb8a2e3c59826e5770863b0a00c39 Mon Sep 17 00:00:00 2001 From: Allen Lee Date: Sun, 2 Jun 2013 02:12:44 +0800 Subject: [PATCH 1/3] Fix ip and tcp header length calculation --- src/net/memcache_command.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/net/memcache_command.cpp b/src/net/memcache_command.cpp index 106079e..e927bf3 100644 --- a/src/net/memcache_command.cpp +++ b/src/net/memcache_command.cpp @@ -27,14 +27,6 @@ using namespace std; MemcacheCommand MemcacheCommand::create(const Packet& pkt, const bpf_u_int32 captureAddress) { - static ssize_t ether_header_sz = sizeof(struct ether_header); - static ssize_t ip_sz = sizeof(struct ip); - static ssize_t tcphdr_sz = sizeof(struct tcphdr); - - const struct ether_header* ethernetHeader; - const struct ip* ipHeader; - const struct tcphdr* tcpHeader; - const Packet::Header* pkthdr = &pkt.getHeader(); const Packet::Data* packet = pkt.getData(); @@ -46,14 +38,16 @@ MemcacheCommand MemcacheCommand::create(const Packet& pkt, // must be an IP packet // TODO add support for dumping localhost - ethernetHeader = (struct ether_header*)packet; + const struct ether_header* ethernetHeader = (struct ether_header*)packet; + ssize_t ethernetHeaderSize = sizeof(struct ether_header); //14 bytes auto etype = ntohs(ethernetHeader->ether_type); if (etype != ETHERTYPE_IP) { return MemcacheCommand(); } // must be TCP - TODO add support for UDP - ipHeader = (struct ip*)(packet + ether_header_sz); + const struct ip* ipHeader = (struct ip*)(packet + ethernetHeaderSize); + ssize_t ipHeaderSize = ipHeader->ip_hl * 4; auto itype = ipHeader->ip_p; if (itype != IPPROTO_TCP) { return MemcacheCommand(); @@ -69,15 +63,20 @@ MemcacheCommand MemcacheCommand::create(const Packet& pkt, // FIXME will remove once we add back the direction parsing (void)possible_request; - tcpHeader = (struct tcphdr*)(packet + ether_header_sz + ip_sz); + const struct tcphdr* tcpHeader = (struct tcphdr*)(packet + ethernetHeaderSize + + ipHeaderSize); + ssize_t tcpHeaderSize = tcpHeader->doff * 4; (void)tcpHeader; - data = (u_char*)(packet + ether_header_sz + ip_sz + tcphdr_sz); - dataLength = pkthdr->len - (ether_header_sz + ip_sz + tcphdr_sz); + data = (u_char*)(packet + ethernetHeaderSize + ipHeaderSize + tcpHeaderSize); + dataLength = pkthdr->len - (ethernetHeaderSize + ipHeaderSize + tcpHeaderSize); if (dataLength > pkthdr->caplen) { dataLength = pkthdr->caplen; } // TODO revert to detecting request/response and doing the right thing + if (dataLength <= 0) { + return MemcacheCommand(); + } return MemcacheCommand::makeResponse(data, dataLength, sourceAddress); } From a76a1a663f01713324d1e3f2b8fc93857e28141d Mon Sep 17 00:00:00 2001 From: Allen Lee Date: Sun, 2 Jun 2013 12:11:03 +0800 Subject: [PATCH 2/3] Support multi-key get reponse --- src/net/capture_engine.cpp | 16 +++++----- src/net/memcache_command.cpp | 60 ++++++++++++++++++++++++------------ src/net/memcache_command.h | 20 +++++++++--- 3 files changed, 66 insertions(+), 30 deletions(-) diff --git a/src/net/capture_engine.cpp b/src/net/capture_engine.cpp index c9d55da..fac89cb 100644 --- a/src/net/capture_engine.cpp +++ b/src/net/capture_engine.cpp @@ -116,7 +116,7 @@ void CaptureEngine::processPackets(int worker_id, mqueue* work_queue) { MemcacheCommand mc = parse(packet); if (mc.isResponse()) { enqueue(mc); - resCount += 1; + resCount += mc.getObjectNumber(); #ifdef _DEBUG logger->trace(CONTEXT, "worker %d, packet %ld, key %s", worker_id, packet.id(), @@ -172,14 +172,16 @@ MemcacheCommand CaptureEngine::parse(const Packet& packet) const */ void CaptureEngine::enqueue(const MemcacheCommand& mc) { - Elem e(mc.getObjectKey(), mc.getObjectSize()); + for (uint32_t idx = 0; idx < mc.getObjectNumber(); ++idx) { + Elem e(mc.getObjectKey(idx), mc.getObjectSize(idx)); #ifdef _DEBUG - logger->trace(CONTEXT, - "Produced stat: %s, %d", e.first.c_str(), e.second); + logger->trace(CONTEXT, + "Produced stat: %s, %d", e.first.c_str(), e.second); #endif - barrier_lock.lock(); - barrier->produce(e); - barrier_lock.unlock(); + barrier_lock.lock(); + barrier->produce(e); + barrier_lock.unlock(); + } } } // end namespace diff --git a/src/net/memcache_command.cpp b/src/net/memcache_command.cpp index e927bf3..f39da51 100644 --- a/src/net/memcache_command.cpp +++ b/src/net/memcache_command.cpp @@ -84,12 +84,18 @@ MemcacheCommand MemcacheCommand::create(const Packet& pkt, MemcacheCommand::MemcacheCommand() : cmdType_(MC_UNKNOWN), sourceAddress_(), - commandName_(), - objectKey_(), - objectSize_(0) + commandName_() {} // protected constructor +MemcacheCommand::MemcacheCommand(const memcache_command_t cmdType, + const string sourceAddress, + const string commandName) + : cmdType_(cmdType), + sourceAddress_(sourceAddress), + commandName_(commandName) +{} + MemcacheCommand::MemcacheCommand(const memcache_command_t cmdType, const string sourceAddress, const string commandName, @@ -97,10 +103,16 @@ MemcacheCommand::MemcacheCommand(const memcache_command_t cmdType, uint32_t objectSize) : cmdType_(cmdType), sourceAddress_(sourceAddress), - commandName_(commandName), - objectKey_(objectKey), - objectSize_(objectSize) -{} + commandName_(commandName) +{ + pushObject(objectKey, objectSize); +} + +void MemcacheCommand::pushObject(const std::string objectKey, uint32_t objectSize) +{ + objectKeyList_.push_back(objectKey); + objectSizeList_.push_back(objectSize); +} // static protected MemcacheCommand MemcacheCommand::makeRequest(u_char*, int, string) @@ -113,23 +125,33 @@ MemcacheCommand MemcacheCommand::makeRequest(u_char*, int, string) MemcacheCommand MemcacheCommand::makeResponse(u_char *data, int length, string sourceAddress) { - static pcrecpp::RE re("VALUE (\\S+) \\d+ (\\d+)", + static pcrecpp::RE re("(VALUE (\\S+) \\d+ (\\d+))", pcrecpp::RE_Options(PCRE_MULTILINE)); + static int minimum_length = 11; // 'VALUE a 0 1' + + string whole; string key; int size = -1; - string input = ""; - for (int i = 0; i < length; i++) { - int cid = (int)data[i]; - if (isprint(cid) || cid == 10 || cid == 13) { - input += (char)data[i]; + + MemcacheCommand mc(MC_RESPONSE, sourceAddress, ""); + int offset = 0; + while (length - offset >= minimum_length) { + //Logger::getLogger("command")->debug(CONTEXT, "%.*s", length, data + offset); + if (!re.PartialMatch(data + offset, &whole, &key, &size)) { + break; + } + //Logger::getLogger("command")->debug(whole); + //Logger::getLogger("command")->debug(key); + if (size >= 0) { + mc.pushObject(key, size); + offset += whole.length() + 2 + size + 2; // 2 for '\r\n', 2 for '\r\n' + } else { + break; } } - if (input.length() < 11) { - return MemcacheCommand(); - } - re.PartialMatch(input, &key, &size); - if (size >= 0) { - return MemcacheCommand(MC_RESPONSE, sourceAddress, "", key, size); + + if (mc.getObjectNumber() > 0) { + return mc; } else { return MemcacheCommand(); } diff --git a/src/net/memcache_command.h b/src/net/memcache_command.h index ef9d56b..56f7003 100644 --- a/src/net/memcache_command.h +++ b/src/net/memcache_command.h @@ -31,11 +31,17 @@ class MemcacheCommand // only when isRequest is true std::string getCommandName() const { return commandName_; } + ssize_t getObjectNumber() const { return objectKeyList_.size(); } + // sometimes when isResponse is true, sometimes when isRequest is true - std::string getObjectKey() const { return objectKey_; } + std::string getObjectKey(uint32_t idx = 0) const { + return (idx < objectKeyList_.size() ? objectKeyList_[idx] : ""); + } // only when isResponse is true - uint32_t getObjectSize() const { return objectSize_; } + uint32_t getObjectSize(uint32_t idx = 0) const { + return (idx < objectSizeList_.size() ? objectSizeList_[idx] : 0); + } // source address for request std::string getSourceAddress() const { return sourceAddress_; } @@ -47,12 +53,18 @@ class MemcacheCommand // Default constructor is protected MemcacheCommand(); + MemcacheCommand(const memcache_command_t cmdType, + const std::string sourceAddress, + const std::string commandName); + MemcacheCommand(const memcache_command_t cmdType, const std::string sourceAddress, const std::string commandName, const std::string objectKey, uint32_t objectSize); + void pushObject(const std::string objectKey, uint32_t objectSize); + static MemcacheCommand makeRequest(u_char *data, int dataLength, std::string sourceAddress); @@ -63,8 +75,8 @@ class MemcacheCommand const memcache_command_t cmdType_; const std::string sourceAddress_; const std::string commandName_; - const std::string objectKey_; - const uint32_t objectSize_; + std::vector objectKeyList_; + std::vector objectSizeList_; }; } // end namespace From 279195c2e91addab7fd3068081c9465c2dce84a5 Mon Sep 17 00:00:00 2001 From: Allen Lee Date: Sun, 2 Jun 2013 22:00:55 +0800 Subject: [PATCH 3/3] Support binary protocol --- src/net/memcache_command.cpp | 70 +++++- src/net/memcache_command.h | 4 + src/net/protocol_binary.h | 470 +++++++++++++++++++++++++++++++++++ 3 files changed, 538 insertions(+), 6 deletions(-) create mode 100644 src/net/protocol_binary.h diff --git a/src/net/memcache_command.cpp b/src/net/memcache_command.cpp index f39da51..0656447 100644 --- a/src/net/memcache_command.cpp +++ b/src/net/memcache_command.cpp @@ -11,6 +11,7 @@ extern "C" { #include #include #include +#include "protocol_binary.h" } static inline std::string ipv4addressToString(const void * src) { @@ -121,9 +122,8 @@ MemcacheCommand MemcacheCommand::makeRequest(u_char*, int, string) return MemcacheCommand(); } -// static protected -MemcacheCommand MemcacheCommand::makeResponse(u_char *data, int length, - string sourceAddress) +MemcacheCommand MemcacheCommand::parseAsciiResponse(u_char *data, int length, + string sourceAddress) { static pcrecpp::RE re("(VALUE (\\S+) \\d+ (\\d+))", pcrecpp::RE_Options(PCRE_MULTILINE)); @@ -136,12 +136,9 @@ MemcacheCommand MemcacheCommand::makeResponse(u_char *data, int length, MemcacheCommand mc(MC_RESPONSE, sourceAddress, ""); int offset = 0; while (length - offset >= minimum_length) { - //Logger::getLogger("command")->debug(CONTEXT, "%.*s", length, data + offset); if (!re.PartialMatch(data + offset, &whole, &key, &size)) { break; } - //Logger::getLogger("command")->debug(whole); - //Logger::getLogger("command")->debug(key); if (size >= 0) { mc.pushObject(key, size); offset += whole.length() + 2 + size + 2; // 2 for '\r\n', 2 for '\r\n' @@ -157,4 +154,65 @@ MemcacheCommand MemcacheCommand::makeResponse(u_char *data, int length, } } +MemcacheCommand MemcacheCommand::parseBinaryResponse(u_char *data, int length, + string sourceAddress) +{ + static const int HEADER_LENGTH = sizeof(protocol_binary_response_header); + static const int MINIMUM_LENGTH = HEADER_LENGTH; + + string key; + int valuelen = 0; + MemcacheCommand mc(MC_RESPONSE, sourceAddress, ""); + int offset = 0; + while (length - offset >= MINIMUM_LENGTH) { + protocol_binary_response_header header; + memcpy((char*)&header, data + offset, HEADER_LENGTH); + header.response.status = ntohs(header.response.status); + header.response.keylen = ntohs(header.response.keylen); + header.response.bodylen = ntohl(header.response.bodylen); + valuelen = header.response.bodylen - header.response.extlen + - header.response.keylen; + + if (header.response.status == PROTOCOL_BINARY_RESPONSE_SUCCESS || + header.response.status == PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE) { + switch (header.response.opcode) { + case PROTOCOL_BINARY_CMD_GET: + case PROTOCOL_BINARY_CMD_GETQ: + Logger::getLogger("command")->debug(CONTEXT, "get reponse without key"); + break; + case PROTOCOL_BINARY_CMD_GETK: + case PROTOCOL_BINARY_CMD_GETKQ: + key.assign((char*)data + offset + HEADER_LENGTH + header.response.extlen, + header.response.keylen); + mc.pushObject(key, valuelen); + break; + default: + break; + } + } + + offset += HEADER_LENGTH + header.response.bodylen; + } + + if (mc.getObjectNumber() > 0) { + return mc; + } else { + return MemcacheCommand(); + } +} + +// static protected +MemcacheCommand MemcacheCommand::makeResponse(u_char *data, int length, + string sourceAddress) +{ + if (length < 1) { + return MemcacheCommand(); + } + if (data[0] == PROTOCOL_BINARY_RES) { + return parseBinaryResponse(data, length, sourceAddress); + } else { + return parseAsciiResponse(data, length, sourceAddress); + } +} + } // end namespace diff --git a/src/net/memcache_command.h b/src/net/memcache_command.h index 56f7003..0755384 100644 --- a/src/net/memcache_command.h +++ b/src/net/memcache_command.h @@ -71,6 +71,10 @@ class MemcacheCommand static MemcacheCommand makeResponse(u_char *data, int dataLength, std::string sourceAddress); + static MemcacheCommand parseAsciiResponse(u_char *data, int length, + std::string sourceAddress); + static MemcacheCommand parseBinaryResponse(u_char *data, int length, + std::string sourceAddress); const memcache_command_t cmdType_; const std::string sourceAddress_; diff --git a/src/net/protocol_binary.h b/src/net/protocol_binary.h new file mode 100644 index 0000000..dfc59c8 --- /dev/null +++ b/src/net/protocol_binary.h @@ -0,0 +1,470 @@ +/* + * Copyright (c) <2008>, Sun Microsystems, Inc. + * All rights reserved. + * + * 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. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY SUN MICROSYSTEMS, INC. ``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 SUN MICROSYSTEMS, INC. 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. + */ +/* + * Summary: Constants used by to implement the binary protocol. + * + * Copy: See Copyright for the status of this software. + * + * Author: Trond Norbye + */ + +#ifndef PROTOCOL_BINARY_H +#define PROTOCOL_BINARY_H + +/** + * This file contains definitions of the constants and packet formats + * defined in the binary specification. Please note that you _MUST_ remember + * to convert each multibyte field to / from network byte order to / from + * host order. + */ +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * Definition of the legal "magic" values used in a packet. + * See section 3.1 Magic byte + */ + typedef enum { + PROTOCOL_BINARY_REQ = 0x80, + PROTOCOL_BINARY_RES = 0x81 + } protocol_binary_magic; + + /** + * Definition of the valid response status numbers. + * See section 3.2 Response Status + */ + typedef enum { + PROTOCOL_BINARY_RESPONSE_SUCCESS = 0x00, + PROTOCOL_BINARY_RESPONSE_KEY_ENOENT = 0x01, + PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS = 0x02, + PROTOCOL_BINARY_RESPONSE_E2BIG = 0x03, + PROTOCOL_BINARY_RESPONSE_EINVAL = 0x04, + PROTOCOL_BINARY_RESPONSE_NOT_STORED = 0x05, + PROTOCOL_BINARY_RESPONSE_DELTA_BADVAL = 0x06, + PROTOCOL_BINARY_RESPONSE_AUTH_ERROR = 0x20, + PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE = 0x21, + PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND = 0x81, + PROTOCOL_BINARY_RESPONSE_ENOMEM = 0x82 + } protocol_binary_response_status; + + /** + * Defintion of the different command opcodes. + * See section 3.3 Command Opcodes + */ + typedef enum { + PROTOCOL_BINARY_CMD_GET = 0x00, + PROTOCOL_BINARY_CMD_SET = 0x01, + PROTOCOL_BINARY_CMD_ADD = 0x02, + PROTOCOL_BINARY_CMD_REPLACE = 0x03, + PROTOCOL_BINARY_CMD_DELETE = 0x04, + PROTOCOL_BINARY_CMD_INCREMENT = 0x05, + PROTOCOL_BINARY_CMD_DECREMENT = 0x06, + PROTOCOL_BINARY_CMD_QUIT = 0x07, + PROTOCOL_BINARY_CMD_FLUSH = 0x08, + PROTOCOL_BINARY_CMD_GETQ = 0x09, + PROTOCOL_BINARY_CMD_NOOP = 0x0a, + PROTOCOL_BINARY_CMD_VERSION = 0x0b, + PROTOCOL_BINARY_CMD_GETK = 0x0c, + PROTOCOL_BINARY_CMD_GETKQ = 0x0d, + PROTOCOL_BINARY_CMD_APPEND = 0x0e, + PROTOCOL_BINARY_CMD_PREPEND = 0x0f, + PROTOCOL_BINARY_CMD_STAT = 0x10, + PROTOCOL_BINARY_CMD_SETQ = 0x11, + PROTOCOL_BINARY_CMD_ADDQ = 0x12, + PROTOCOL_BINARY_CMD_REPLACEQ = 0x13, + PROTOCOL_BINARY_CMD_DELETEQ = 0x14, + PROTOCOL_BINARY_CMD_INCREMENTQ = 0x15, + PROTOCOL_BINARY_CMD_DECREMENTQ = 0x16, + PROTOCOL_BINARY_CMD_QUITQ = 0x17, + PROTOCOL_BINARY_CMD_FLUSHQ = 0x18, + PROTOCOL_BINARY_CMD_APPENDQ = 0x19, + PROTOCOL_BINARY_CMD_PREPENDQ = 0x1a, + PROTOCOL_BINARY_CMD_TOUCH = 0x1c, + PROTOCOL_BINARY_CMD_GAT = 0x1d, + PROTOCOL_BINARY_CMD_GATQ = 0x1e, + PROTOCOL_BINARY_CMD_GATK = 0x23, + PROTOCOL_BINARY_CMD_GATKQ = 0x24, + + PROTOCOL_BINARY_CMD_SASL_LIST_MECHS = 0x20, + PROTOCOL_BINARY_CMD_SASL_AUTH = 0x21, + PROTOCOL_BINARY_CMD_SASL_STEP = 0x22, + + /* These commands are used for range operations and exist within + * this header for use in other projects. Range operations are + * not expected to be implemented in the memcached server itself. + */ + PROTOCOL_BINARY_CMD_RGET = 0x30, + PROTOCOL_BINARY_CMD_RSET = 0x31, + PROTOCOL_BINARY_CMD_RSETQ = 0x32, + PROTOCOL_BINARY_CMD_RAPPEND = 0x33, + PROTOCOL_BINARY_CMD_RAPPENDQ = 0x34, + PROTOCOL_BINARY_CMD_RPREPEND = 0x35, + PROTOCOL_BINARY_CMD_RPREPENDQ = 0x36, + PROTOCOL_BINARY_CMD_RDELETE = 0x37, + PROTOCOL_BINARY_CMD_RDELETEQ = 0x38, + PROTOCOL_BINARY_CMD_RINCR = 0x39, + PROTOCOL_BINARY_CMD_RINCRQ = 0x3a, + PROTOCOL_BINARY_CMD_RDECR = 0x3b, + PROTOCOL_BINARY_CMD_RDECRQ = 0x3c + /* End Range operations */ + + } protocol_binary_command; + + /** + * Definition of the data types in the packet + * See section 3.4 Data Types + */ + typedef enum { + PROTOCOL_BINARY_RAW_BYTES = 0x00 + } protocol_binary_datatypes; + + /** + * Definition of the header structure for a request packet. + * See section 2 + */ + typedef union { + struct { + uint8_t magic; + uint8_t opcode; + uint16_t keylen; + uint8_t extlen; + uint8_t datatype; + uint16_t reserved; + uint32_t bodylen; + uint32_t opaque; + uint64_t cas; + } request; + uint8_t bytes[24]; + } protocol_binary_request_header; + + /** + * Definition of the header structure for a response packet. + * See section 2 + */ + typedef union { + struct { + uint8_t magic; + uint8_t opcode; + uint16_t keylen; + uint8_t extlen; + uint8_t datatype; + uint16_t status; + uint32_t bodylen; + uint32_t opaque; + uint64_t cas; + } response; + uint8_t bytes[24]; + } protocol_binary_response_header; + + /** + * Definition of a request-packet containing no extras + */ + typedef union { + struct { + protocol_binary_request_header header; + } message; + uint8_t bytes[sizeof(protocol_binary_request_header)]; + } protocol_binary_request_no_extras; + + /** + * Definition of a response-packet containing no extras + */ + typedef union { + struct { + protocol_binary_response_header header; + } message; + uint8_t bytes[sizeof(protocol_binary_response_header)]; + } protocol_binary_response_no_extras; + + /** + * Definition of the packet used by the get, getq, getk and getkq command. + * See section 4 + */ + typedef protocol_binary_request_no_extras protocol_binary_request_get; + typedef protocol_binary_request_no_extras protocol_binary_request_getq; + typedef protocol_binary_request_no_extras protocol_binary_request_getk; + typedef protocol_binary_request_no_extras protocol_binary_request_getkq; + + /** + * Definition of the packet returned from a successful get, getq, getk and + * getkq. + * See section 4 + */ + typedef union { + struct { + protocol_binary_response_header header; + struct { + uint32_t flags; + } body; + } message; + uint8_t bytes[sizeof(protocol_binary_response_header) + 4]; + } protocol_binary_response_get; + + typedef protocol_binary_response_get protocol_binary_response_getq; + typedef protocol_binary_response_get protocol_binary_response_getk; + typedef protocol_binary_response_get protocol_binary_response_getkq; + + /** + * Definition of the packet used by the delete command + * See section 4 + */ + typedef protocol_binary_request_no_extras protocol_binary_request_delete; + + /** + * Definition of the packet returned by the delete command + * See section 4 + */ + typedef protocol_binary_response_no_extras protocol_binary_response_delete; + + /** + * Definition of the packet used by the flush command + * See section 4 + * Please note that the expiration field is optional, so remember to see + * check the header.bodysize to see if it is present. + */ + typedef union { + struct { + protocol_binary_request_header header; + struct { + uint32_t expiration; + } body; + } message; + uint8_t bytes[sizeof(protocol_binary_request_header) + 4]; + } protocol_binary_request_flush; + + /** + * Definition of the packet returned by the flush command + * See section 4 + */ + typedef protocol_binary_response_no_extras protocol_binary_response_flush; + + /** + * Definition of the packet used by set, add and replace + * See section 4 + */ + typedef union { + struct { + protocol_binary_request_header header; + struct { + uint32_t flags; + uint32_t expiration; + } body; + } message; + uint8_t bytes[sizeof(protocol_binary_request_header) + 8]; + } protocol_binary_request_set; + typedef protocol_binary_request_set protocol_binary_request_add; + typedef protocol_binary_request_set protocol_binary_request_replace; + + /** + * Definition of the packet returned by set, add and replace + * See section 4 + */ + typedef protocol_binary_response_no_extras protocol_binary_response_set; + typedef protocol_binary_response_no_extras protocol_binary_response_add; + typedef protocol_binary_response_no_extras protocol_binary_response_replace; + + /** + * Definition of the noop packet + * See section 4 + */ + typedef protocol_binary_request_no_extras protocol_binary_request_noop; + + /** + * Definition of the packet returned by the noop command + * See section 4 + */ + typedef protocol_binary_response_no_extras protocol_binary_response_noop; + + /** + * Definition of the structure used by the increment and decrement + * command. + * See section 4 + */ + typedef union { + struct { + protocol_binary_request_header header; + struct { + uint64_t delta; + uint64_t initial; + uint32_t expiration; + } body; + } message; + uint8_t bytes[sizeof(protocol_binary_request_header) + 20]; + } protocol_binary_request_incr; + typedef protocol_binary_request_incr protocol_binary_request_decr; + + /** + * Definition of the response from an incr or decr command + * command. + * See section 4 + */ + typedef union { + struct { + protocol_binary_response_header header; + struct { + uint64_t value; + } body; + } message; + uint8_t bytes[sizeof(protocol_binary_response_header) + 8]; + } protocol_binary_response_incr; + typedef protocol_binary_response_incr protocol_binary_response_decr; + + /** + * Definition of the quit + * See section 4 + */ + typedef protocol_binary_request_no_extras protocol_binary_request_quit; + + /** + * Definition of the packet returned by the quit command + * See section 4 + */ + typedef protocol_binary_response_no_extras protocol_binary_response_quit; + + /** + * Definition of the packet used by append and prepend command + * See section 4 + */ + typedef protocol_binary_request_no_extras protocol_binary_request_append; + typedef protocol_binary_request_no_extras protocol_binary_request_prepend; + + /** + * Definition of the packet returned from a successful append or prepend + * See section 4 + */ + typedef protocol_binary_response_no_extras protocol_binary_response_append; + typedef protocol_binary_response_no_extras protocol_binary_response_prepend; + + /** + * Definition of the packet used by the version command + * See section 4 + */ + typedef protocol_binary_request_no_extras protocol_binary_request_version; + + /** + * Definition of the packet returned from a successful version command + * See section 4 + */ + typedef protocol_binary_response_no_extras protocol_binary_response_version; + + + /** + * Definition of the packet used by the stats command. + * See section 4 + */ + typedef protocol_binary_request_no_extras protocol_binary_request_stats; + + /** + * Definition of the packet returned from a successful stats command + * See section 4 + */ + typedef protocol_binary_response_no_extras protocol_binary_response_stats; + + /** + * Definition of the packet used by the touch command. + */ + typedef union { + struct { + protocol_binary_request_header header; + struct { + uint32_t expiration; + } body; + } message; + uint8_t bytes[sizeof(protocol_binary_request_header) + 4]; + } protocol_binary_request_touch; + + /** + * Definition of the packet returned from the touch command + */ + typedef protocol_binary_response_no_extras protocol_binary_response_touch; + + /** + * Definition of the packet used by the GAT(Q) command. + */ + typedef union { + struct { + protocol_binary_request_header header; + struct { + uint32_t expiration; + } body; + } message; + uint8_t bytes[sizeof(protocol_binary_request_header) + 4]; + } protocol_binary_request_gat; + + typedef protocol_binary_request_gat protocol_binary_request_gatq; + typedef protocol_binary_request_gat protocol_binary_request_gatk; + typedef protocol_binary_request_gat protocol_binary_request_gatkq; + + /** + * Definition of the packet returned from the GAT(Q) + */ + typedef protocol_binary_response_get protocol_binary_response_gat; + typedef protocol_binary_response_get protocol_binary_response_gatq; + typedef protocol_binary_response_get protocol_binary_response_gatk; + typedef protocol_binary_response_get protocol_binary_response_gatkq; + + /** + * Definition of a request for a range operation. + * See http://code.google.com/p/memcached/wiki/RangeOps + * + * These types are used for range operations and exist within + * this header for use in other projects. Range operations are + * not expected to be implemented in the memcached server itself. + */ + typedef union { + struct { + protocol_binary_response_header header; + struct { + uint16_t size; + uint8_t reserved; + uint8_t flags; + uint32_t max_results; + } body; + } message; + uint8_t bytes[sizeof(protocol_binary_request_header) + 4]; + } protocol_binary_request_rangeop; + + typedef protocol_binary_request_rangeop protocol_binary_request_rget; + typedef protocol_binary_request_rangeop protocol_binary_request_rset; + typedef protocol_binary_request_rangeop protocol_binary_request_rsetq; + typedef protocol_binary_request_rangeop protocol_binary_request_rappend; + typedef protocol_binary_request_rangeop protocol_binary_request_rappendq; + typedef protocol_binary_request_rangeop protocol_binary_request_rprepend; + typedef protocol_binary_request_rangeop protocol_binary_request_rprependq; + typedef protocol_binary_request_rangeop protocol_binary_request_rdelete; + typedef protocol_binary_request_rangeop protocol_binary_request_rdeleteq; + typedef protocol_binary_request_rangeop protocol_binary_request_rincr; + typedef protocol_binary_request_rangeop protocol_binary_request_rincrq; + typedef protocol_binary_request_rangeop protocol_binary_request_rdecr; + typedef protocol_binary_request_rangeop protocol_binary_request_rdecrq; + +#ifdef __cplusplus +} +#endif +#endif /* PROTOCOL_BINARY_H */