1 /* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
3 * This file contains an implementation of the callback interface for level 0
4 * in the protocol library. You might want to have your copy of the protocol
5 * specification next to your coffee ;-)
17 #include <libmemcached/protocol_handler.h>
18 #include <libmemcached/byteorder.h>
20 #include "memcached_light.h"
22 static protocol_binary_response_status
noop_command_handler(const void *cookie
,
23 protocol_binary_request_header
*header
,
24 memcached_binary_protocol_raw_response_handler response_handler
)
26 protocol_binary_response_no_extras response
= {
27 .message
.header
.response
= {
28 .magic
= PROTOCOL_BINARY_RES
,
29 .opcode
= PROTOCOL_BINARY_CMD_NOOP
,
30 .status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
),
31 .opaque
= header
->request
.opaque
35 return response_handler(cookie
, header
, (void*)&response
);
38 static protocol_binary_response_status
quit_command_handler(const void *cookie
,
39 protocol_binary_request_header
*header
,
40 memcached_binary_protocol_raw_response_handler response_handler
)
42 protocol_binary_response_no_extras response
= {
43 .message
.header
.response
= {
44 .magic
= PROTOCOL_BINARY_RES
,
45 .opcode
= PROTOCOL_BINARY_CMD_QUIT
,
46 .status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
),
47 .opaque
= header
->request
.opaque
51 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_QUIT
)
52 response_handler(cookie
, header
, (void*)&response
);
54 /* I need a better way to signal to close the connection */
55 return PROTOCOL_BINARY_RESPONSE_EINTERNAL
;
58 static protocol_binary_response_status
get_command_handler(const void *cookie
,
59 protocol_binary_request_header
*header
,
60 memcached_binary_protocol_raw_response_handler response_handler
)
62 uint8_t opcode
= header
->request
.opcode
;
64 protocol_binary_response_get response
;
67 .response
.message
.header
.response
= {
68 .magic
= PROTOCOL_BINARY_RES
,
70 .status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
),
71 .opaque
= header
->request
.opaque
75 struct item
*item
= get_item(header
+ 1, ntohs(header
->request
.keylen
));
78 msg
.response
.message
.body
.flags
= htonl(item
->flags
);
79 char *ptr
= (char*)(msg
.response
.bytes
+ sizeof(*header
) + 4);
81 msg
.response
.message
.header
.response
.cas
= memcached_htonll(item
->cas
);
82 if (opcode
== PROTOCOL_BINARY_CMD_GETK
|| opcode
== PROTOCOL_BINARY_CMD_GETKQ
)
84 memcpy(ptr
, item
->key
, item
->nkey
);
85 msg
.response
.message
.header
.response
.keylen
= htons((uint16_t)item
->nkey
);
87 bodysize
+= (uint32_t)item
->nkey
;
89 memcpy(ptr
, item
->data
, item
->size
);
90 bodysize
+= (uint32_t)item
->size
;
91 msg
.response
.message
.header
.response
.bodylen
= htonl(bodysize
);
92 msg
.response
.message
.header
.response
.extlen
= 4;
95 return response_handler(cookie
, header
, (void*)&msg
);
97 else if (opcode
== PROTOCOL_BINARY_CMD_GET
|| opcode
== PROTOCOL_BINARY_CMD_GETK
)
99 msg
.response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
);
100 return response_handler(cookie
, header
, (void*)&msg
);
103 /* Q shouldn't report a miss ;-) */
104 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
107 static protocol_binary_response_status
delete_command_handler(const void *cookie
,
108 protocol_binary_request_header
*header
,
109 memcached_binary_protocol_raw_response_handler response_handler
)
111 size_t keylen
= ntohs(header
->request
.keylen
);
112 char *key
= ((char*)header
) + sizeof(*header
);
113 protocol_binary_response_no_extras response
= {
114 .message
.header
.response
= {
115 .magic
= PROTOCOL_BINARY_RES
,
116 .opcode
= header
->request
.opcode
,
117 .opaque
= header
->request
.opaque
121 if (!delete_item(key
, keylen
))
123 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
);
124 return response_handler(cookie
, header
, (void*)&response
);
126 else if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_DELETE
)
128 /* DELETEQ doesn't want success response */
129 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
);
130 return response_handler(cookie
, header
, (void*)&response
);
133 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
136 static protocol_binary_response_status
flush_command_handler(const void *cookie
,
137 protocol_binary_request_header
*header
,
138 memcached_binary_protocol_raw_response_handler response_handler
)
140 uint8_t opcode
= header
->request
.opcode
;
142 /* @fixme sett inn when! */
145 if (opcode
== PROTOCOL_BINARY_CMD_FLUSH
)
147 protocol_binary_response_no_extras response
= {
148 .message
.header
.response
= {
149 .magic
= PROTOCOL_BINARY_RES
,
151 .status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
),
152 .opaque
= header
->request
.opaque
155 return response_handler(cookie
, header
, (void*)&response
);
158 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
161 static protocol_binary_response_status
arithmetic_command_handler(const void *cookie
,
162 protocol_binary_request_header
*header
,
163 memcached_binary_protocol_raw_response_handler response_handler
)
165 protocol_binary_request_incr
*req
= (void*)header
;
166 protocol_binary_response_incr response
= {
167 .message
.header
.response
= {
168 .magic
= PROTOCOL_BINARY_RES
,
169 .opcode
= header
->request
.opcode
,
170 .opaque
= header
->request
.opaque
,
174 uint16_t keylen
= ntohs(header
->request
.keylen
);
175 uint64_t initial
= memcached_ntohll(req
->message
.body
.initial
);
176 uint64_t delta
= memcached_ntohll(req
->message
.body
.delta
);
177 uint32_t expiration
= ntohl(req
->message
.body
.expiration
);
179 void *key
= req
->bytes
+ sizeof(req
->bytes
);
180 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
182 uint64_t value
= initial
;
184 struct item
*item
= get_item(key
, keylen
);
187 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_INCREMENT
||
188 header
->request
.opcode
== PROTOCOL_BINARY_CMD_INCREMENTQ
)
190 value
= (*(uint64_t*)item
->data
) + delta
;
194 if (delta
> *(uint64_t*)item
->data
)
200 value
= *(uint64_t*)item
->data
- delta
;
203 expiration
= (uint32_t)item
->exp
;
207 delete_item(key
, keylen
);
210 item
= create_item(key
, keylen
, NULL
, sizeof(value
), flags
, (time_t)expiration
);
213 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
217 memcpy(item
->data
, &value
, sizeof(value
));
221 response
.message
.header
.response
.status
= htons(rval
);
222 if (rval
== PROTOCOL_BINARY_RESPONSE_SUCCESS
)
224 response
.message
.header
.response
.bodylen
= ntohl(8);
225 response
.message
.body
.value
= memcached_ntohll((*(uint64_t*)item
->data
));
226 response
.message
.header
.response
.cas
= memcached_ntohll(item
->cas
);
229 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_INCREMENTQ
||
230 header
->request
.opcode
== PROTOCOL_BINARY_CMD_DECREMENTQ
)
232 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
236 return response_handler(cookie
, header
, (void*)&response
);
239 static protocol_binary_response_status
version_command_handler(const void *cookie
,
240 protocol_binary_request_header
*header
,
241 memcached_binary_protocol_raw_response_handler response_handler
)
243 const char *versionstring
= "1.0.0";
245 protocol_binary_response_header packet
;
249 .magic
= PROTOCOL_BINARY_RES
,
250 .opcode
= PROTOCOL_BINARY_CMD_VERSION
,
251 .status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
),
252 .opaque
= header
->request
.opaque
,
254 .bodylen
= htonl((uint32_t)strlen(versionstring
))
258 memcpy(response
.buffer
+ sizeof(response
.packet
), versionstring
, strlen(versionstring
));
260 return response_handler(cookie
, header
, (void*)&response
);
263 static protocol_binary_response_status
concat_command_handler(const void *cookie
,
264 protocol_binary_request_header
*header
,
265 memcached_binary_protocol_raw_response_handler response_handler
)
267 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
268 uint16_t keylen
= ntohs(header
->request
.keylen
);
269 uint64_t cas
= memcached_ntohll(header
->request
.cas
);
270 void *key
= header
+ 1;
271 uint32_t vallen
= ntohl(header
->request
.bodylen
) - keylen
;
272 void *val
= (char*)key
+ keylen
;
274 struct item
*item
= get_item(key
, keylen
);
275 struct item
*nitem
= NULL
;
279 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
281 else if (cas
!= 0 && cas
!= item
->cas
)
283 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
285 else if ((nitem
= create_item(key
, keylen
, NULL
, item
->size
+ vallen
,
286 item
->flags
, item
->exp
)) == NULL
)
289 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
293 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_APPEND
||
294 header
->request
.opcode
== PROTOCOL_BINARY_CMD_APPENDQ
)
296 memcpy(nitem
->data
, item
->data
, item
->size
);
297 memcpy(((char*)(nitem
->data
)) + item
->size
, val
, vallen
);
301 memcpy(nitem
->data
, val
, vallen
);
302 memcpy(((char*)(nitem
->data
)) + vallen
, item
->data
, item
->size
);
305 delete_item(key
, keylen
);
310 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_APPEND
||
311 header
->request
.opcode
== PROTOCOL_BINARY_CMD_PREPEND
)
313 protocol_binary_response_no_extras response
= {
316 .magic
= PROTOCOL_BINARY_RES
,
317 .opcode
= header
->request
.opcode
,
318 .status
= htons(rval
),
319 .opaque
= header
->request
.opaque
,
320 .cas
= memcached_htonll(cas
),
324 return response_handler(cookie
, header
, (void*)&response
);
331 static protocol_binary_response_status
set_command_handler(const void *cookie
,
332 protocol_binary_request_header
*header
,
333 memcached_binary_protocol_raw_response_handler response_handler
)
335 size_t keylen
= ntohs(header
->request
.keylen
);
336 size_t datalen
= ntohl(header
->request
.bodylen
) - keylen
- 8;
337 protocol_binary_request_replace
*request
= (void*)header
;
338 uint32_t flags
= ntohl(request
->message
.body
.flags
);
339 time_t timeout
= (time_t)ntohl(request
->message
.body
.expiration
);
340 char *key
= ((char*)header
) + sizeof(*header
) + 8;
341 char *data
= key
+ keylen
;
343 protocol_binary_response_no_extras response
= {
346 .magic
= PROTOCOL_BINARY_RES
,
347 .opcode
= header
->request
.opcode
,
348 .status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
),
349 .opaque
= header
->request
.opaque
354 if (header
->request
.cas
!= 0)
357 struct item
* item
= get_item(key
, keylen
);
360 if (item
->cas
!= memcached_ntohll(header
->request
.cas
))
363 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
);
364 return response_handler(cookie
, header
, (void*)&response
);
370 delete_item(key
, keylen
);
371 struct item
* item
= create_item(key
, keylen
, data
, datalen
, flags
, timeout
);
374 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_ENOMEM
);
379 /* SETQ shouldn't return a message */
380 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_SET
)
382 response
.message
.header
.response
.cas
= memcached_htonll(item
->cas
);
384 return response_handler(cookie
, header
, (void*)&response
);
388 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
391 return response_handler(cookie
, header
, (void*)&response
);
394 static protocol_binary_response_status
add_command_handler(const void *cookie
,
395 protocol_binary_request_header
*header
,
396 memcached_binary_protocol_raw_response_handler response_handler
)
398 size_t keylen
= ntohs(header
->request
.keylen
);
399 size_t datalen
= ntohl(header
->request
.bodylen
) - keylen
- 8;
400 protocol_binary_request_add
*request
= (void*)header
;
401 uint32_t flags
= ntohl(request
->message
.body
.flags
);
402 time_t timeout
= (time_t)ntohl(request
->message
.body
.expiration
);
403 char *key
= ((char*)header
) + sizeof(*header
) + 8;
404 char *data
= key
+ keylen
;
406 protocol_binary_response_no_extras response
= {
409 .magic
= PROTOCOL_BINARY_RES
,
410 .opcode
= header
->request
.opcode
,
411 .status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
),
412 .opaque
= header
->request
.opaque
417 struct item
* item
= get_item(key
, keylen
);
420 item
= create_item(key
, keylen
, data
, datalen
, flags
, timeout
);
422 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_ENOMEM
);
426 /* ADDQ shouldn't return a message */
427 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_ADD
)
429 response
.message
.header
.response
.cas
= memcached_htonll(item
->cas
);
431 return response_handler(cookie
, header
, (void*)&response
);
434 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
440 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
);
443 return response_handler(cookie
, header
, (void*)&response
);
446 static protocol_binary_response_status
replace_command_handler(const void *cookie
,
447 protocol_binary_request_header
*header
,
448 memcached_binary_protocol_raw_response_handler response_handler
)
450 size_t keylen
= ntohs(header
->request
.keylen
);
451 size_t datalen
= ntohl(header
->request
.bodylen
) - keylen
- 8;
452 protocol_binary_request_replace
*request
= (void*)header
;
453 uint32_t flags
= ntohl(request
->message
.body
.flags
);
454 time_t timeout
= (time_t)ntohl(request
->message
.body
.expiration
);
455 char *key
= ((char*)header
) + sizeof(*header
) + 8;
456 char *data
= key
+ keylen
;
458 protocol_binary_response_no_extras response
= {
461 .magic
= PROTOCOL_BINARY_RES
,
462 .opcode
= header
->request
.opcode
,
463 .status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
),
464 .opaque
= header
->request
.opaque
469 struct item
* item
= get_item(key
, keylen
);
472 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
);
474 else if (header
->request
.cas
== 0 || memcached_ntohll(header
->request
.cas
) == item
->cas
)
477 delete_item(key
, keylen
);
478 item
= create_item(key
, keylen
, data
, datalen
, flags
, timeout
);
482 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_ENOMEM
);
487 /* REPLACEQ shouldn't return a message */
488 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_REPLACE
)
490 response
.message
.header
.response
.cas
= memcached_htonll(item
->cas
);
492 return response_handler(cookie
, header
, (void*)&response
);
495 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
500 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
);
504 return response_handler(cookie
, header
, (void*)&response
);
507 static protocol_binary_response_status
stat_command_handler(const void *cookie
,
508 protocol_binary_request_header
*header
,
509 memcached_binary_protocol_raw_response_handler response_handler
)
511 /* Just send the terminating packet*/
512 protocol_binary_response_no_extras response
= {
515 .magic
= PROTOCOL_BINARY_RES
,
516 .opcode
= PROTOCOL_BINARY_CMD_STAT
,
517 .status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
),
518 .opaque
= header
->request
.opaque
523 return response_handler(cookie
, header
, (void*)&response
);
526 memcached_binary_protocol_callback_st interface_v0_impl
= {
527 .interface_version
= MEMCACHED_PROTOCOL_HANDLER_V0
,
530 ** There is a number of bugs in the extra options for gcc causing
531 ** warning on these struct initializers. It hurts my heart to remove
532 ** it so I'll just leave it in here so that we can enable it when
533 ** we can drop support for the broken compilers
535 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_GET
]= get_command_handler
,
536 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_SET
]= set_command_handler
,
537 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_ADD
]= add_command_handler
,
538 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_REPLACE
]= replace_command_handler
,
539 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_DELETE
]= delete_command_handler
,
540 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_INCREMENT
]= arithmetic_command_handler
,
541 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_DECREMENT
]= arithmetic_command_handler
,
542 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_QUIT
]= quit_command_handler
,
543 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_FLUSH
]= flush_command_handler
,
544 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_GETQ
]= get_command_handler
,
545 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_NOOP
]= noop_command_handler
,
546 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_VERSION
]= version_command_handler
,
547 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_GETK
]= get_command_handler
,
548 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_GETKQ
]= get_command_handler
,
549 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_APPEND
]= concat_command_handler
,
550 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_PREPEND
]= concat_command_handler
,
551 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_STAT
]= stat_command_handler
,
552 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_SETQ
]= set_command_handler
,
553 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_ADDQ
]= add_command_handler
,
554 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_REPLACEQ
]= replace_command_handler
,
555 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_DELETEQ
]= delete_command_handler
,
556 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_INCREMENTQ
]= arithmetic_command_handler
,
557 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_DECREMENTQ
]= arithmetic_command_handler
,
558 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_QUITQ
]= quit_command_handler
,
559 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_FLUSHQ
]= flush_command_handler
,
560 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_APPENDQ
]= concat_command_handler
,
561 .interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_PREPENDQ
]= concat_command_handler
,
565 void initialize_interface_v0_handler(void)
567 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_GET
]= get_command_handler
;
568 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_SET
]= set_command_handler
;
569 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_ADD
]= add_command_handler
;
570 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_REPLACE
]= replace_command_handler
;
571 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_DELETE
]= delete_command_handler
;
572 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_INCREMENT
]= arithmetic_command_handler
;
573 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_DECREMENT
]= arithmetic_command_handler
;
574 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_QUIT
]= quit_command_handler
;
575 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_FLUSH
]= flush_command_handler
;
576 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_GETQ
]= get_command_handler
;
577 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_NOOP
]= noop_command_handler
;
578 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_VERSION
]= version_command_handler
;
579 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_GETK
]= get_command_handler
;
580 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_GETKQ
]= get_command_handler
;
581 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_APPEND
]= concat_command_handler
;
582 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_PREPEND
]= concat_command_handler
;
583 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_STAT
]= stat_command_handler
;
584 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_SETQ
]= set_command_handler
;
585 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_ADDQ
]= add_command_handler
;
586 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_REPLACEQ
]= replace_command_handler
;
587 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_DELETEQ
]= delete_command_handler
;
588 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_INCREMENTQ
]= arithmetic_command_handler
;
589 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_DECREMENTQ
]= arithmetic_command_handler
;
590 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_QUITQ
]= quit_command_handler
;
591 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_FLUSHQ
]= flush_command_handler
;
592 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_APPENDQ
]= concat_command_handler
;
593 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_PREPENDQ
]= concat_command_handler
;