1 /* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2 #include "libmemcached/protocol/common.h"
7 #define ensure(a) if (!(a)) { return false; }
9 bool memcached_binary_protocol_pedantic_check_request(const protocol_binary_request_header
*request
)
11 ensure(request
->request
.magic
== PROTOCOL_BINARY_REQ
);
12 ensure(request
->request
.datatype
== PROTOCOL_BINARY_RAW_BYTES
);
14 ensure(request
->bytes
[6] == 0);
15 ensure(request
->bytes
[7] == 0);
17 uint8_t opcode
= request
->request
.opcode
;
18 uint16_t keylen
= ntohs(request
->request
.keylen
);
19 uint8_t extlen
= request
->request
.extlen
;
20 uint32_t bodylen
= ntohl(request
->request
.bodylen
);
22 ensure(bodylen
>= (keylen
+ extlen
));
25 case PROTOCOL_BINARY_CMD_GET
:
26 case PROTOCOL_BINARY_CMD_GETK
:
27 case PROTOCOL_BINARY_CMD_GETKQ
:
28 case PROTOCOL_BINARY_CMD_GETQ
:
31 ensure(keylen
== bodylen
);
32 ensure(request
->request
.cas
== 0);
35 case PROTOCOL_BINARY_CMD_ADD
:
36 case PROTOCOL_BINARY_CMD_ADDQ
:
37 /* it makes no sense to run add with a cas value */
38 ensure(request
->request
.cas
== 0);
40 case PROTOCOL_BINARY_CMD_SET
:
41 case PROTOCOL_BINARY_CMD_SETQ
:
42 case PROTOCOL_BINARY_CMD_REPLACE
:
43 case PROTOCOL_BINARY_CMD_REPLACEQ
:
48 case PROTOCOL_BINARY_CMD_DELETE
:
49 case PROTOCOL_BINARY_CMD_DELETEQ
:
52 ensure(keylen
== bodylen
);
55 case PROTOCOL_BINARY_CMD_INCREMENT
:
56 case PROTOCOL_BINARY_CMD_INCREMENTQ
:
57 case PROTOCOL_BINARY_CMD_DECREMENT
:
58 case PROTOCOL_BINARY_CMD_DECREMENTQ
:
61 ensure(keylen
+ extlen
== bodylen
);
64 case PROTOCOL_BINARY_CMD_QUIT
:
65 case PROTOCOL_BINARY_CMD_QUITQ
:
66 case PROTOCOL_BINARY_CMD_NOOP
:
67 case PROTOCOL_BINARY_CMD_VERSION
:
73 case PROTOCOL_BINARY_CMD_FLUSH
:
74 case PROTOCOL_BINARY_CMD_FLUSHQ
:
75 ensure(extlen
== 0 || extlen
== 4);
77 ensure(bodylen
== extlen
);
80 case PROTOCOL_BINARY_CMD_STAT
:
82 /* May have key, but not value */
83 ensure(keylen
== bodylen
);
86 case PROTOCOL_BINARY_CMD_APPEND
:
87 case PROTOCOL_BINARY_CMD_APPENDQ
:
88 case PROTOCOL_BINARY_CMD_PREPEND
:
89 case PROTOCOL_BINARY_CMD_PREPENDQ
:
101 bool memcached_binary_protocol_pedantic_check_response(const protocol_binary_request_header
*request
,
102 const protocol_binary_response_header
*response
)
104 ensure(response
->response
.magic
== PROTOCOL_BINARY_RES
);
105 ensure(response
->response
.datatype
== PROTOCOL_BINARY_RAW_BYTES
);
106 ensure(response
->response
.opaque
== request
->request
.opaque
);
108 uint16_t status
= ntohs(response
->response
.status
);
109 uint8_t opcode
= response
->response
.opcode
;
111 if (status
== PROTOCOL_BINARY_RESPONSE_SUCCESS
)
114 case PROTOCOL_BINARY_CMD_ADDQ
:
115 case PROTOCOL_BINARY_CMD_APPENDQ
:
116 case PROTOCOL_BINARY_CMD_DECREMENTQ
:
117 case PROTOCOL_BINARY_CMD_DELETEQ
:
118 case PROTOCOL_BINARY_CMD_FLUSHQ
:
119 case PROTOCOL_BINARY_CMD_INCREMENTQ
:
120 case PROTOCOL_BINARY_CMD_PREPENDQ
:
121 case PROTOCOL_BINARY_CMD_QUITQ
:
122 case PROTOCOL_BINARY_CMD_REPLACEQ
:
123 case PROTOCOL_BINARY_CMD_SETQ
:
124 /* Quiet command shouldn't return on success */
131 case PROTOCOL_BINARY_CMD_ADD
:
132 case PROTOCOL_BINARY_CMD_REPLACE
:
133 case PROTOCOL_BINARY_CMD_SET
:
134 case PROTOCOL_BINARY_CMD_APPEND
:
135 case PROTOCOL_BINARY_CMD_PREPEND
:
136 ensure(response
->response
.keylen
== 0);
137 ensure(response
->response
.extlen
== 0);
138 ensure(response
->response
.bodylen
== 0);
139 ensure(response
->response
.cas
!= 0);
141 case PROTOCOL_BINARY_CMD_FLUSH
:
142 case PROTOCOL_BINARY_CMD_NOOP
:
143 case PROTOCOL_BINARY_CMD_QUIT
:
144 case PROTOCOL_BINARY_CMD_DELETE
:
145 ensure(response
->response
.keylen
== 0);
146 ensure(response
->response
.extlen
== 0);
147 ensure(response
->response
.bodylen
== 0);
148 ensure(response
->response
.cas
== 0);
151 case PROTOCOL_BINARY_CMD_DECREMENT
:
152 case PROTOCOL_BINARY_CMD_INCREMENT
:
153 ensure(response
->response
.keylen
== 0);
154 ensure(response
->response
.extlen
== 0);
155 ensure(ntohl(response
->response
.bodylen
) == 8);
156 ensure(response
->response
.cas
!= 0);
159 case PROTOCOL_BINARY_CMD_STAT
:
160 ensure(response
->response
.extlen
== 0);
161 /* key and value exists in all packets except in the terminating */
162 ensure(response
->response
.cas
== 0);
165 case PROTOCOL_BINARY_CMD_VERSION
:
166 ensure(response
->response
.keylen
== 0);
167 ensure(response
->response
.extlen
== 0);
168 ensure(response
->response
.bodylen
!= 0);
169 ensure(response
->response
.cas
== 0);
172 case PROTOCOL_BINARY_CMD_GET
:
173 case PROTOCOL_BINARY_CMD_GETQ
:
174 ensure(response
->response
.keylen
== 0);
175 ensure(response
->response
.extlen
== 4);
176 ensure(response
->response
.cas
!= 0);
179 case PROTOCOL_BINARY_CMD_GETK
:
180 case PROTOCOL_BINARY_CMD_GETKQ
:
181 ensure(response
->response
.keylen
!= 0);
182 ensure(response
->response
.extlen
== 4);
183 ensure(response
->response
.cas
!= 0);
187 /* Undefined command code */
193 ensure(response
->response
.cas
== 0);
194 ensure(response
->response
.extlen
== 0);
195 if (opcode
!= PROTOCOL_BINARY_CMD_GETK
)
197 ensure(response
->response
.keylen
== 0);