1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: 2 * 3 * Libmemcached library 4 * 5 * Copyright (C) 2011 Data Differential, http://datadifferential.com/ 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * * Redistributions in binary form must reproduce the above 15 * copyright notice, this list of conditions and the following disclaimer 16 * in the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * * The names of its contributors may not be used to endorse or 20 * promote products derived from this software without specific prior 21 * written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 * 35 */ 36 37 #pragma once 38 39 #include "mem_config.h" 40 #include <assert.h> 41 42 #include <libmemcachedprotocol-0.0/handler.h> 43 #include <libmemcachedprotocol/cache.h> 44 #include <libmemcached/byteorder.h> 45 #include <libmemcached/socket.hpp> 46 47 /* 48 * I don't really need the following two functions as function pointers 49 * in the instance handle, but I don't want to put them in the global 50 * namespace for those linking statically (personally I don't like that, 51 * but some people still do). If it ever shows up as a performance thing 52 * I'll look into optimizing this ;-) 53 */ 54 typedef bool (*drain_func)(memcached_protocol_client_st *client); 55 typedef protocol_binary_response_status (*spool_func)(memcached_protocol_client_st *client, 56 const void *data, 57 size_t length); 58 59 /** 60 * Definition of the per instance structure. 61 */ 62 struct memcached_protocol_st { 63 memcached_binary_protocol_callback_st *callback; 64 memcached_protocol_recv_func recv; 65 memcached_protocol_send_func send; 66 67 /* 68 * I really don't need these as funciton pointers, but I don't want 69 * to clutter the namespace if someone links statically. 70 */ 71 drain_func drain; 72 spool_func spool; 73 74 /* 75 * To avoid keeping a buffer in each client all the time I have a 76 * bigger buffer in the instance that I read to initially, and then 77 * I try to parse and execute as much from the buffer. If I wasn't able 78 * to process all data I'll keep that in a per-connection buffer until 79 * the next time I can read from the socket. 80 */ 81 uint8_t *input_buffer; 82 size_t input_buffer_size; 83 84 bool pedantic; 85 /* @todo use multiple sized buffers */ 86 cache_t *buffer_cache; 87 }; 88 89 struct chunk_st { 90 /* Pointer to the data */ 91 char *data; 92 /* The offset to the first byte into the buffer that is used */ 93 size_t offset; 94 /* The offset into the buffer for the first free byte */ 95 size_t nbytes; 96 /* The number of bytes in the buffer */ 97 size_t size; 98 /* Pointer to the next buffer in the chain */ 99 struct chunk_st *next; 100 }; 101 102 #define CHUNK_BUFFERSIZE 2048 103 104 typedef memcached_protocol_event_t (*process_data)(struct memcached_protocol_client_st *client, ssize_t *length, void **endptr); 105 106 enum ascii_cmd { 107 GET_CMD, 108 GETS_CMD, 109 SET_CMD, 110 ADD_CMD, 111 REPLACE_CMD, 112 CAS_CMD, 113 APPEND_CMD, 114 PREPEND_CMD, 115 DELETE_CMD, 116 INCR_CMD, 117 DECR_CMD, 118 STATS_CMD, 119 FLUSH_ALL_CMD, 120 VERSION_CMD, 121 QUIT_CMD, 122 VERBOSITY_CMD, 123 UNKNOWN_CMD 124 }; 125 126 struct memcached_protocol_client_st { 127 bool is_verbose; 128 memcached_protocol_st *root; 129 memcached_socket_t sock; 130 int error; 131 132 /* Linked list of data to send */ 133 struct chunk_st *output; 134 struct chunk_st *output_tail; 135 136 /* 137 * While we process input data, this is where we spool incomplete commands 138 * if we need to receive more data.... 139 * @todo use the buffercace 140 */ 141 uint8_t *input_buffer; 142 size_t input_buffer_size; 143 size_t input_buffer_offset; 144 145 /* The callback to the protocol handler to use (ascii or binary) */ 146 process_data work; 147 148 /* 149 * Should the spool data discard the data to send or not? (aka noreply in 150 * the ascii protocol.. 151 */ 152 bool mute; 153 154 /* Members used by the binary protocol */ 155 protocol_binary_request_header *current_command; 156 157 /* Members used by the ascii protocol */ 158 enum ascii_cmd ascii_command; 159 }; 160 161 #include "ascii_handler.h" 162 #include "binary_handler.h" 163