Improve parser error messages.
[m6w6/libmemcached] / libmemcachedprotocol / common.h
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 "config.h"
40 #if !defined(__cplusplus)
41 # include <stdbool.h>
42 #endif
43 #include <assert.h>
44
45 #include <libmemcachedprotocol-0.0/handler.h>
46 #include <libmemcachedprotocol/cache.h>
47 #include <libmemcached/byteorder.h>
48 #include <libmemcached/close_socket.hpp>
49
50 /*
51 * I don't really need the following two functions as function pointers
52 * in the instance handle, but I don't want to put them in the global
53 * namespace for those linking statically (personally I don't like that,
54 * but some people still do). If it ever shows up as a performance thing
55 * I'll look into optimizing this ;-)
56 */
57 typedef bool (*drain_func)(memcached_protocol_client_st *client);
58 typedef protocol_binary_response_status (*spool_func)(memcached_protocol_client_st *client,
59 const void *data,
60 size_t length);
61
62 /**
63 * Definition of the per instance structure.
64 */
65 struct memcached_protocol_st {
66 memcached_binary_protocol_callback_st *callback;
67 memcached_protocol_recv_func recv;
68 memcached_protocol_send_func send;
69
70 /*
71 * I really don't need these as funciton pointers, but I don't want
72 * to clutter the namespace if someone links statically.
73 */
74 drain_func drain;
75 spool_func spool;
76
77 /*
78 * To avoid keeping a buffer in each client all the time I have a
79 * bigger buffer in the instance that I read to initially, and then
80 * I try to parse and execute as much from the buffer. If I wasn't able
81 * to process all data I'll keep that in a per-connection buffer until
82 * the next time I can read from the socket.
83 */
84 uint8_t *input_buffer;
85 size_t input_buffer_size;
86
87 bool pedantic;
88 /* @todo use multiple sized buffers */
89 cache_t *buffer_cache;
90 };
91
92 struct chunk_st {
93 /* Pointer to the data */
94 char *data;
95 /* The offset to the first byte into the buffer that is used */
96 size_t offset;
97 /* The offset into the buffer for the first free byte */
98 size_t nbytes;
99 /* The number of bytes in the buffer */
100 size_t size;
101 /* Pointer to the next buffer in the chain */
102 struct chunk_st *next;
103 };
104
105 #define CHUNK_BUFFERSIZE 2048
106
107 typedef memcached_protocol_event_t (*process_data)(struct memcached_protocol_client_st *client, ssize_t *length, void **endptr);
108
109 enum ascii_cmd {
110 GET_CMD,
111 GETS_CMD,
112 SET_CMD,
113 ADD_CMD,
114 REPLACE_CMD,
115 CAS_CMD,
116 APPEND_CMD,
117 PREPEND_CMD,
118 DELETE_CMD,
119 INCR_CMD,
120 DECR_CMD,
121 STATS_CMD,
122 FLUSH_ALL_CMD,
123 VERSION_CMD,
124 QUIT_CMD,
125 VERBOSITY_CMD,
126 UNKNOWN_CMD
127 };
128
129 struct memcached_protocol_client_st {
130 memcached_protocol_st *root;
131 memcached_socket_t sock;
132 int error;
133
134 /* Linked list of data to send */
135 struct chunk_st *output;
136 struct chunk_st *output_tail;
137
138 /*
139 * While we process input data, this is where we spool incomplete commands
140 * if we need to receive more data....
141 * @todo use the buffercace
142 */
143 uint8_t *input_buffer;
144 size_t input_buffer_size;
145 size_t input_buffer_offset;
146
147 /* The callback to the protocol handler to use (ascii or binary) */
148 process_data work;
149
150 /*
151 * Should the spool data discard the data to send or not? (aka noreply in
152 * the ascii protocol..
153 */
154 bool mute;
155
156 /* Members used by the binary protocol */
157 protocol_binary_request_header *current_command;
158
159 /* Members used by the ascii protocol */
160 enum ascii_cmd ascii_command;
161 };
162
163 #include "ascii_handler.h"
164 #include "binary_handler.h"