⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.19
Server IP:
178.33.27.10
Server:
Linux cpanel.dev-unit.com 3.10.0-1160.108.1.el7.x86_64 #1 SMP Thu Jan 25 16:17:31 UTC 2024 x86_64
Server Software:
Apache/2.4.57 (Unix) OpenSSL/1.0.2k-fips
PHP Version:
8.2.11
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
proc
/
self
/
root
/
usr
/
local
/
src
/
memcache-8.0
/
src
/
View File Name :
memcache_binary_protocol.c
/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Antony Dovgal <tony2001@phpclub.net> | | Mikael Johansson <mikael AT synd DOT info> | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define MMC_DEBUG 0 #ifdef PHP_WIN32 #include <win32/php_stdint.h> #include <winsock2.h> #else #include <stdint.h> #include <arpa/inet.h> #include <netinet/in.h> #endif #include "memcache_pool.h" #include "ext/standard/php_smart_string.h" #ifdef htonll #undef htonll #endif #ifdef ntohll #undef ntohll #endif #ifndef PHP_WIN32 #if __BYTE_ORDER == __BIG_ENDIAN # define ntohll(x) (x) # define htonll(x) (x) #elif __BYTE_ORDER == __LITTLE_ENDIAN # include <byteswap.h> # define ntohll(x) bswap_64(x) # define htonll(x) bswap_64(x) #else # error "Could not determine byte order: __BYTE_ORDER uncorrectly defined" #endif #else uint64_t mmc_htonll(uint64_t value); # define ntohll mmc_htonll # define htonll mmc_htonll #endif #ifdef __GNUC__ # define MMC_ATTR_PACKED __attribute__((packed)) #else # define MMC_ATTR_PACKED #endif /* UD_ATTR_PACKED */ #define MMC_REQUEST_MAGIC 0x80 #define MMC_RESPONSE_MAGIC 0x81 #define MMC_OP_GET 0x00 #define MMC_OP_SET 0x01 #define MMC_OP_ADD 0x02 #define MMC_OP_REPLACE 0x03 #define MMC_OP_DELETE 0x04 #define MMC_OP_INCR 0x05 #define MMC_OP_DECR 0x06 #define MMC_OP_QUIT 0x07 #define MMC_OP_FLUSH 0x08 #define MMC_OP_GETQ 0x09 #define MMC_OP_NOOP 0x0a #define MMC_OP_VERSION 0x0b #define MMC_BIN_OP_APPEND 0x0e #define MMC_BIN_OP_PREPEND 0x0f #define MMC_BINARY_STATUS_OK 0x00 #define MMC_BINARY_STATUS_KEY_NOT_FOUND 0x01 #define MMC_BINARY_STATUS_KEY_EXISTS 0x02 #define MMC_BINARY_STATUS_VALUE_TOO_LARGE 0x03 #define MMC_BINARY_STATUS_INVALID_ARGS 0x04 #define MMC_BINARY_STATUS_ITEM_NOT_STORED 0x05 #define MMC_BINARY_STATUS_INCR_DECR_ERROR 0x06 /* Incr/Decr on non-numeric value */ #define MMC_BINARY_STATUS_UNKNOWN_COMMAND 0x81 #define MMC_BINARY_STATUS_OUT_OF_MEMORY 0x82 #define MMC_OP_SASL_LIST 0x20 #define MMC_OP_SASL_AUTH 0x21 #define MMC_OP_SASL_AUTH_STEP 0x21 typedef struct mmc_binary_request { mmc_request_t base; /* enable cast to mmc_request_t */ mmc_request_parser next_parse_handler; /* next payload parser state */ mmc_queue_t keys; /* mmc_queue_t<zval *>, reqid -> key mappings */ struct { uint8_t opcode; uint16_t error; /* error received in current request */ uint32_t reqid; /* current reqid being processed */ } command; struct { /* stores value info while the body is being read */ unsigned int flags; unsigned long length; uint64_t cas; /* CAS counter */ } value; } mmc_binary_request_t; typedef struct mmc_request_header { uint8_t magic; uint8_t opcode; uint16_t key_len; uint8_t extras_len; uint8_t datatype; uint16_t _reserved; uint32_t length; /* trailing body total_body_length (not including this header) */ uint32_t reqid; /* opaque request id */ uint64_t cas; } MMC_ATTR_PACKED mmc_request_header_t; typedef struct mmc_get_request_header { mmc_request_header_t base; } MMC_ATTR_PACKED mmc_get_request_header_t; typedef struct mmc_version_request_header { mmc_request_header_t base; } MMC_ATTR_PACKED mmc_version_request_header_t; typedef struct mmc_store_request_header { mmc_request_header_t base; uint32_t flags; uint32_t exptime; } MMC_ATTR_PACKED mmc_store_request_header_t; typedef struct mmc_store_append_header { mmc_request_header_t base; } MMC_ATTR_PACKED mmc_store_append_header_t; typedef struct mmc_delete_request_header { mmc_request_header_t base; } MMC_ATTR_PACKED mmc_delete_request_header_t; typedef struct mmc_mutate_request_header { mmc_request_header_t base; uint64_t delta; uint64_t initial; uint32_t expiration; } MMC_ATTR_PACKED mmc_mutate_request_header_t; typedef struct mmc_sasl_request_header { mmc_request_header_t base; } MMC_ATTR_PACKED mmc_sasl_request_header; typedef struct mmc_response_header { uint8_t magic; uint8_t opcode; uint16_t key_len; uint8_t extras_len; uint8_t datatype; uint16_t status; uint32_t total_body_length; /* trailing body total_body_length (not including this header) */ uint32_t reqid; /* echo'ed from request */ uint64_t cas; } MMC_ATTR_PACKED mmc_response_header_t; typedef struct mmc_get_response_header { uint32_t flags; } MMC_ATTR_PACKED mmc_get_response_header_t; typedef struct mmc_mutate_response_header { uint64_t value; } MMC_ATTR_PACKED mmc_mutate_response_header_t; static int mmc_request_read_response(mmc_t *, mmc_request_t *); static int mmc_request_parse_value(mmc_t *, mmc_request_t *); static int mmc_request_read_value(mmc_t *, mmc_request_t *); void mmc_binary_hexdump(void *mem, unsigned int len) { # define HEXDUMP_COLS 4 unsigned int i, j; for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++) { if(i % HEXDUMP_COLS == 0) { printf("%06i: ", i); } if(i < len) { printf("%02x ", 0xFF & ((char*)mem)[i]); } else { printf(" "); } if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1)) { for(j = i - (HEXDUMP_COLS - 1); j <= i; j++) { if(j >= len) { putchar(' '); } else if(isprint(((char*)mem)[j])) { putchar(0xFF & ((char*)mem)[j]); } else { putchar('.'); } } putchar('\n'); } } } #ifdef PHP_WIN32 uint64_t mmc_htonll(uint64_t value) { if (value == 0) { return 0x0LL; } else { static const int num = 42; // Check the endianness if (*(const char *)(&num) == num) { const uint32_t high_part = htonl((uint32_t)(value >> 32)); const uint32_t low_part = htonl((uint32_t)(value & 0xFFFFFFFFLL)); return ((uint64_t)(low_part) << 32) | high_part; } else { return value; } } } #endif static inline char *mmc_stream_get(mmc_stream_t *io, size_t bytes) /* attempts to read a number of bytes from server, returns the a pointer to the buffer on success, NULL if the complete number of bytes could not be read {{{ */ { io->input.idx += io->read(io, io->input.value + io->input.idx, bytes - io->input.idx); if (io->input.idx >= bytes) { io->input.idx = 0; return io->input.value; } return NULL; } /* }}} */ static int mmc_request_parse_response(mmc_t *mmc, mmc_request_t *request) /* reads a generic response header and reads the response body {{{ */ { mmc_response_header_t *header; mmc_binary_request_t *req = (mmc_binary_request_t *)request; header = (mmc_response_header_t *)mmc_stream_get(request->io, sizeof(mmc_response_header_t)); if (header != NULL) { if (header->magic != MMC_RESPONSE_MAGIC) { return mmc_server_failure(mmc, request->io, "Malformed server response (invalid magic byte)", 0); } if (header->opcode == MMC_OP_NOOP) { return MMC_REQUEST_DONE; } req->command.opcode = header->opcode; switch (ntohs(header->status)) { case MMC_BINARY_STATUS_OK: req->command.error = MMC_OK; break; case MMC_BINARY_STATUS_KEY_NOT_FOUND: req->command.error = MMC_RESPONSE_NOT_FOUND; break; case MMC_BINARY_STATUS_KEY_EXISTS: req->command.error = MMC_RESPONSE_EXISTS; break; case MMC_BINARY_STATUS_VALUE_TOO_LARGE: req->command.error = MMC_RESPONSE_TOO_LARGE; break; case MMC_BINARY_STATUS_INVALID_ARGS: case MMC_BINARY_STATUS_INCR_DECR_ERROR: req->command.error = MMC_RESPONSE_CLIENT_ERROR; break; case MMC_BINARY_STATUS_ITEM_NOT_STORED: req->command.error = MMC_RESPONSE_NOT_STORED; break; case MMC_BINARY_STATUS_UNKNOWN_COMMAND: req->command.error = MMC_RESPONSE_UNKNOWN_CMD; break; case MMC_BINARY_STATUS_OUT_OF_MEMORY: req->command.error = MMC_RESPONSE_OUT_OF_MEMORY; break; default: req->command.error = MMC_RESPONSE_UNKNOWN; break; } req->command.reqid = ntohl(header->reqid); req->value.length = ntohl(header->total_body_length); req->value.cas = ntohll(header->cas); if (req->value.length == 0) { return request->response_handler(mmc, request, req->command.error, "", 0, request->response_handler_param); } /* allow read_response handler to read the response body */ if (req->command.error) { request->parse = mmc_request_read_response; mmc_buffer_alloc(&(request->readbuf), req->value.length + 1); } else { request->parse = req->next_parse_handler; if (req->value.length >= header->extras_len) { req->value.length -= header->extras_len; } mmc_buffer_alloc(&(request->readbuf), req->value.length + 1); } /* read more, php streams buffer input which must be read if available */ return MMC_REQUEST_AGAIN; } return MMC_REQUEST_MORE; } /* }}}*/ static int mmc_request_parse_null(mmc_t *mmc, mmc_request_t *request) /* always returns MMC_REQUEST_DONE {{{ */ { return MMC_REQUEST_DONE; } static int mmc_request_read_response(mmc_t *mmc, mmc_request_t *request) /* read the response body into the buffer and delegates to response_handler {{{ */ { mmc_binary_request_t *req = (mmc_binary_request_t *)request; request->readbuf.idx += request->io->read(request->io, request->readbuf.value.c + request->readbuf.idx, req->value.length - request->readbuf.idx); /* done reading? */ if (request->readbuf.idx >= req->value.length) { request->readbuf.value.c[req->value.length] = '\0'; return request->response_handler(mmc, request, req->command.error, request->readbuf.value.c, req->value.length, request->response_handler_param); } return MMC_REQUEST_MORE; } /* }}}*/ static int mmc_request_read_mutate(mmc_t *mmc, mmc_request_t *request) /* reads and parses the mutate response header {{{ */ { mmc_mutate_response_header_t *header; mmc_binary_request_t *req = (mmc_binary_request_t *)request; header = (mmc_mutate_response_header_t *)mmc_stream_get(request->io, sizeof(*header)); if (header != NULL) { int result; zval *key, value; /* convert remembered key to string and unpack value */ key = (zval *)mmc_queue_item(&(req->keys), req->command.reqid); ZVAL_LONG(&value, ntohll(header->value)); if (Z_TYPE_P(key) != IS_STRING) { zval keytmp = *key; zval_copy_ctor(&keytmp); convert_to_string(&keytmp); result = request->value_handler( Z_STRVAL(keytmp), Z_STRLEN(keytmp), &value, req->value.flags, req->value.cas, request->value_handler_param); zval_dtor(&keytmp); } else { result = request->value_handler( Z_STRVAL_P(key), Z_STRLEN_P(key), &value, req->value.flags, req->value.cas, request->value_handler_param); } return result; } return MMC_REQUEST_MORE; } /* }}}*/ static int mmc_request_parse_value(mmc_t *mmc, mmc_request_t *request) /* reads and parses the value response header and then reads the value body {{{ */ { mmc_get_response_header_t *header; mmc_binary_request_t *req = (mmc_binary_request_t *)request; header = (mmc_get_response_header_t *)mmc_stream_get(request->io, sizeof(mmc_get_response_header_t)); if (header != NULL) { //req->value.cas = ntohll(header->cas); req->value.flags = ntohl(header->flags); /* allow read_value handler to read the value body */ request->parse = mmc_request_read_value; /* read more, php streams buffer input which must be read if available */ return MMC_REQUEST_AGAIN; } return MMC_REQUEST_MORE; } /* }}}*/ static int mmc_request_read_value(mmc_t *mmc, mmc_request_t *request) /* read the value body into the buffer {{{ */ { mmc_binary_request_t *req = (mmc_binary_request_t *)request; request->readbuf.idx += request->io->read(request->io, request->readbuf.value.c + request->readbuf.idx, req->value.length - request->readbuf.idx); /* done reading? */ if (request->readbuf.idx >= req->value.length) { zval *key; int result; /* allow parse_value to read next VALUE or NOOP, done here to ensure reentrancy */ if (req->command.opcode == MMC_OP_GET) { request->parse = mmc_request_parse_null; } else { request->parse = mmc_request_parse_response; } mmc_buffer_reset(&(request->readbuf)); /* convert remembered key to string and unpack value */ key = (zval *)mmc_queue_item(&(req->keys), req->command.reqid); if (Z_TYPE_P(key) != IS_STRING) { zval keytmp = *key; zval_copy_ctor(&keytmp); convert_to_string(&keytmp); result = mmc_unpack_value( mmc, request, &(request->readbuf), Z_STRVAL(keytmp), Z_STRLEN(keytmp), req->value.flags, req->value.cas, req->value.length); zval_dtor(&keytmp); } else { result = mmc_unpack_value( mmc, request, &(request->readbuf), Z_STRVAL_P(key), Z_STRLEN_P(key), req->value.flags, req->value.cas, req->value.length); } if (result == MMC_REQUEST_DONE && (req->command.opcode == MMC_OP_GET || req->command.reqid >= req->keys.len)) { return MMC_REQUEST_DONE; } return MMC_REQUEST_AGAIN; } return MMC_REQUEST_MORE; } /* }}}*/ static inline void mmc_pack_header(mmc_request_header_t *header, uint8_t opcode, unsigned int reqid, unsigned int key_len, unsigned int extras_len, unsigned int length) /* {{{ */ { header->magic = MMC_REQUEST_MAGIC; header->opcode = opcode; header->key_len = htons(key_len); header->extras_len = extras_len; header->datatype = 0; header->_reserved = 0; header->length = htonl(key_len + extras_len + length); header->reqid = htonl(reqid); header->cas = 0; } /* }}} */ static mmc_request_t *mmc_binary_create_request() /* {{{ */ { mmc_binary_request_t *request = emalloc(sizeof(mmc_binary_request_t)); ZEND_SECURE_ZERO(request, sizeof(mmc_binary_request_t)); return (mmc_request_t *)request; } /* }}} */ static void mmc_binary_clone_request(mmc_request_t *clone, mmc_request_t *request) /* {{{ */ { mmc_binary_request_t *rcl = (mmc_binary_request_t *)clone; mmc_binary_request_t *req = (mmc_binary_request_t *)request; rcl->next_parse_handler = req->next_parse_handler; mmc_queue_copy(&(rcl->keys), &(req->keys)); } /* }}} */ static void mmc_binary_reset_request(mmc_request_t *request) /* {{{ */ { mmc_binary_request_t *req = (mmc_binary_request_t *)request; mmc_queue_reset(&(req->keys)); req->value.cas = 0; mmc_request_reset(request); } /* }}} */ static void mmc_binary_free_request(mmc_request_t *request) /* {{{ */ { mmc_binary_request_t *req = (mmc_binary_request_t *)request; mmc_queue_free(&(req->keys)); mmc_request_free(request); } /* }}} */ static void mmc_binary_begin_get(mmc_request_t *request, int op) /* {{{ */ { mmc_binary_request_t *req = (mmc_binary_request_t *)request; request->parse = mmc_request_parse_response; req->next_parse_handler = mmc_request_parse_value; } /* }}} */ static void mmc_binary_append_get(mmc_request_t *request, zval *zkey, const char *key, unsigned int key_len) /* {{{ */ { mmc_request_header_t header; mmc_binary_request_t *req = (mmc_binary_request_t *)request; /* reqid/opaque is the index into the collection of key pointers */ mmc_pack_header(&header, MMC_OP_GETQ, req->keys.len, key_len, 0, 0); smart_string_appendl(&(request->sendbuf.value), (const char *)&header, sizeof(mmc_request_header_t)); smart_string_appendl(&(request->sendbuf.value), key, key_len); /* store key to be used by the response handler */ mmc_queue_push(&(req->keys), zkey); } /* }}} */ static void mmc_binary_end_get(mmc_request_t *request) /* {{{ */ { mmc_request_header_t header; mmc_binary_request_t *req = (mmc_binary_request_t *)request; mmc_pack_header(&header, MMC_OP_NOOP, req->keys.len, 0, 0, 0); smart_string_appendl(&(request->sendbuf.value), (const char *)&header, sizeof(header)); } /* }}} */ static void mmc_binary_get(mmc_request_t *request, int op, zval *zkey, const char *key, unsigned int key_len) /* {{{ */ { mmc_get_request_header_t header; mmc_binary_request_t *req = (mmc_binary_request_t *)request; request->parse = mmc_request_parse_response; req->next_parse_handler = mmc_request_parse_value; /* reqid/opaque is the index into the collection of key pointers */ mmc_pack_header(&(header.base), MMC_OP_GET, req->keys.len, key_len, 0, 0); header.base.cas = 0x0; smart_string_appendl(&(request->sendbuf.value), (const char *)&header, sizeof(mmc_get_request_header_t)); smart_string_appendl(&(request->sendbuf.value), key, key_len); #if MMC_DEBUG mmc_binary_hexdump(request->sendbuf.value.c, request->sendbuf.value.len); #endif /* store key to be used by the response handler */ mmc_queue_push(&(req->keys), zkey); } /* }}} */ static int mmc_binary_store( mmc_pool_t *pool, mmc_request_t *request, int op, const char *key, unsigned int key_len, unsigned int flags, unsigned int exptime, unsigned long cas, zval *value) /* {{{ */ { mmc_binary_request_t *req = (mmc_binary_request_t *)request; int status, prevlen, valuelen; request->parse = mmc_request_parse_response; req->next_parse_handler = mmc_request_read_response; prevlen = request->sendbuf.value.len; /* placeholder for upcoming append/prepend support */ #if 1 if (op == MMC_OP_APPEND || op == MMC_OP_PREPEND) { mmc_store_append_header_t *header; if (op == MMC_OP_APPEND) { op = MMC_BIN_OP_APPEND; } else { op = MMC_BIN_OP_PREPEND; } /* allocate space for header */ mmc_buffer_alloc(&(request->sendbuf), sizeof(mmc_store_append_header_t)); request->sendbuf.value.len += sizeof(mmc_store_append_header_t); /* append key and data */ smart_string_appendl(&(request->sendbuf.value), key, key_len); valuelen = request->sendbuf.value.len; status = mmc_pack_value(pool, &(request->sendbuf), value, &flags); if (status != MMC_OK) { return status; } header = (mmc_store_append_header_t *)(request->sendbuf.value.c + prevlen); mmc_pack_header(&(header->base), op, 0, key_len, sizeof(mmc_store_append_header_t) - sizeof(mmc_request_header_t), request->sendbuf.value.len - valuelen); header->base.cas = htonll(cas); #if MMC_DEBUG mmc_binary_hexdump(request->sendbuf.value.c, request->sendbuf.value.len); #endif /* todo */ return MMC_OK; } else #endif { mmc_store_request_header_t *header; /* allocate space for header */ mmc_buffer_alloc(&(request->sendbuf), sizeof(mmc_store_request_header_t)); request->sendbuf.value.len += sizeof(mmc_store_request_header_t); /* append key and data */ smart_string_appendl(&(request->sendbuf.value), key, key_len); valuelen = request->sendbuf.value.len; status = mmc_pack_value(pool, &(request->sendbuf), value, &flags); if (status != MMC_OK) { return status; } /* initialize header */ header = (mmc_store_request_header_t *)(request->sendbuf.value.c + prevlen); if (op == MMC_OP_CAS) { op = MMC_OP_SET; } mmc_pack_header(&(header->base), op, 0, key_len, sizeof(mmc_store_request_header_t) - sizeof(mmc_request_header_t), request->sendbuf.value.len - valuelen); header->base.cas = htonll(cas); header->flags = htonl(flags); header->exptime = htonl(exptime); return MMC_OK; } } /* }}} */ static void mmc_binary_delete(mmc_request_t *request, const char *key, unsigned int key_len, unsigned int exptime) /* {{{ */ { mmc_delete_request_header_t header; mmc_binary_request_t *req = (mmc_binary_request_t *)request; request->parse = mmc_request_parse_response; req->next_parse_handler = mmc_request_read_response; mmc_pack_header(&(header.base), MMC_OP_DELETE, 0, key_len, 0, 0); smart_string_appendl(&(request->sendbuf.value), (const char *)&header, sizeof(header)); smart_string_appendl(&(request->sendbuf.value), key, key_len); } /* }}} */ static void mmc_binary_mutate(mmc_request_t *request, zval *zkey, const char *key, unsigned int key_len, long value, long defval, int defval_used, unsigned int exptime) /* {{{ */ { mmc_mutate_request_header_t header; mmc_binary_request_t *req = (mmc_binary_request_t *)request; uint8_t op; request->parse = mmc_request_parse_response; req->next_parse_handler = mmc_request_read_mutate; if (value >= 0) { op = MMC_OP_INCR; header.delta = htonll((uint64_t)value); //header.delta = (uint64_t)value; } else { op = MMC_OP_DECR; header.delta = htonll((uint64_t)-value); } /* extra is always 20 bytes https://code.google.com/p/memcached/wiki/BinaryProtocolRevamped#Increment,_Decrement TODO: add flags to do not force alignments so we can rely on sizeof instead of fixed sizes, safer&cleaner */ mmc_pack_header(&(header.base), op, req->keys.len, key_len, 20, 0); header.base.cas = 0x0; header.initial = htonll((int64_t)defval); if (defval_used) { /* server inserts defval if key doesn't exist */ header.expiration = htonl(exptime); } else { /* server replies with NOT_FOUND if exptime ~0 and key doesn't exist */ header.expiration = ~(uint32_t)0; } /* mutate request is 43 bytes */ smart_string_appendl(&(request->sendbuf.value), (const char *)&header, 44); smart_string_appendl(&(request->sendbuf.value), key, key_len); #if MMC_DEBUG mmc_binary_hexdump(request->sendbuf.value.c, request->sendbuf.value.len); #endif /* store key to be used by the response handler */ mmc_queue_push(&(req->keys), zkey); } /* }}} */ static void mmc_binary_flush(mmc_request_t *request, unsigned int exptime) /* {{{ */ { mmc_request_header_t header; mmc_binary_request_t *req = (mmc_binary_request_t *)request; request->parse = mmc_request_parse_response; req->next_parse_handler = mmc_request_read_response; mmc_pack_header(&header, MMC_OP_FLUSH, 0, 0, 0, 0); smart_string_appendl(&(request->sendbuf.value), (const char *)&header, sizeof(header)); } /* }}} */ static void mmc_binary_version(mmc_request_t *request) /* {{{ */ { mmc_version_request_header_t header; mmc_binary_request_t *req = (mmc_binary_request_t *)request; request->parse = mmc_request_parse_response; req->next_parse_handler = mmc_request_read_response; mmc_pack_header(&(header.base), MMC_OP_VERSION, 0, 0, 0, 0); header.base.cas = 0x0; smart_string_appendl(&(request->sendbuf.value), (const char *)&header, sizeof(header)); } /* }}} */ static void mmc_binary_stats(mmc_request_t *request, const char *type, long slabid, long limit) /* {{{ */ { /* stats not supported */ mmc_request_header_t header; mmc_binary_request_t *req = (mmc_binary_request_t *)request; request->parse = mmc_request_parse_response; req->next_parse_handler = mmc_request_read_response; mmc_pack_header(&header, MMC_OP_NOOP, 0, 0, 0, 0); smart_string_appendl(&(request->sendbuf.value), (const char *)&header, sizeof(header)); } /* }}} */ static void mmc_set_sasl_auth_data(mmc_pool_t *pool, mmc_request_t *request, const char *user, const char *password) /* {{{ */ { const unsigned int key_len = 5; int prevlen; mmc_sasl_request_header *header; mmc_binary_request_t *req = (mmc_binary_request_t *)request; request->parse = mmc_request_parse_response; req->next_parse_handler = mmc_request_read_response; memcpy(request->key, "PLAIN", 5 + 1); prevlen = request->sendbuf.value.len; /* allocate space for header */ mmc_buffer_alloc(&(request->sendbuf), sizeof(*header)); request->sendbuf.value.len += sizeof(*header); /* append key and data */ smart_string_appendl(&(request->sendbuf.value), "PLAIN", 5); /* initialize header */ header = (mmc_sasl_request_header *)(request->sendbuf.value.c + prevlen); (header->base).magic = MMC_REQUEST_MAGIC; (header->base).opcode = MMC_OP_SASL_AUTH; (header->base).key_len = htons(key_len); (header->base).extras_len = 0x0; (header->base).datatype = 0x0; (header->base)._reserved = 0x0; (header->base).length = htonl(strlen(user) + strlen(password) + key_len + 2); (header->base).reqid = htonl(0); header->base.cas = 0x0; smart_string_appendl(&(request->sendbuf.value), "\0", 1); smart_string_appendl(&(request->sendbuf.value), user, strlen(user)); smart_string_appendl(&(request->sendbuf.value), "\0", 1); smart_string_appendl(&(request->sendbuf.value), password, strlen(password)); #if MMC_DEBUG mmc_binary_hexdump(request->sendbuf.value.c, request->sendbuf.value.len); #endif return; } /* }}} */ mmc_protocol_t mmc_binary_protocol = { mmc_binary_create_request, mmc_binary_clone_request, mmc_binary_reset_request, mmc_binary_free_request, mmc_binary_get, mmc_binary_begin_get, mmc_binary_append_get, mmc_binary_end_get, mmc_binary_store, mmc_binary_delete, mmc_binary_mutate, mmc_binary_flush, mmc_binary_version, mmc_binary_stats, mmc_set_sasl_auth_data }; /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */