1/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (c) <2008>, Sun Microsystems, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *     * Redistributions of source code must retain the above copyright
9 *       notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above copyright
11 *       notice, this list of conditions and the following disclaimer in the
12 *       documentation and/or other materials provided with the distribution.
13 *     * Neither the name of the  nor the
14 *       names of its contributors may be used to endorse or promote products
15 *       derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY SUN MICROSYSTEMS, INC. ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28/*
29 * Summary: Constants used by to implement the binary protocol.
30 *
31 * Copy: See Copyright for the status of this software.
32 *
33 * Author: Trond Norbye <trond.norbye@sun.com>
34 */
35#pragma once
36
37#include "config.h"
38
39#include <memcached/vbucket.h>
40
41#include <cstdint>
42#include <gsl/gsl>
43#include <sstream>
44#include <stdexcept>
45#include <string>
46
47/**
48 * \addtogroup Protocol
49 * @{
50 */
51
52/**
53 * This file contains definitions of the constants and packet formats
54 * defined in the binary specification. Please note that you _MUST_ remember
55 * to convert each multibyte field to / from network byte order to / from
56 * host order.
57 */
58
59#include <mcbp/protocol/datatype.h>
60#include <mcbp/protocol/feature.h>
61#include <mcbp/protocol/magic.h>
62#include <mcbp/protocol/opcode.h>
63#include <mcbp/protocol/request.h>
64#include <mcbp/protocol/response.h>
65#include <mcbp/protocol/status.h>
66
67// For backward compatibility with old sources
68
69// Magic
70const uint8_t PROTOCOL_BINARY_REQ = uint8_t(cb::mcbp::Magic::ClientRequest);
71const uint8_t PROTOCOL_BINARY_RES = uint8_t(cb::mcbp::Magic::ClientResponse);
72
73// Status codes
74using protocol_binary_response_status = uint16_t;
75
76const uint16_t PROTOCOL_BINARY_RESPONSE_SUCCESS =
77        uint16_t(cb::mcbp::Status::Success);
78const uint16_t PROTOCOL_BINARY_RESPONSE_KEY_ENOENT =
79        uint16_t(cb::mcbp::Status::KeyEnoent);
80const uint16_t PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS =
81        uint16_t(cb::mcbp::Status::KeyEexists);
82const uint16_t PROTOCOL_BINARY_RESPONSE_E2BIG = uint16_t(cb::mcbp::Status::E2big);
83const uint16_t PROTOCOL_BINARY_RESPONSE_EINVAL =
84        uint16_t(cb::mcbp::Status::Einval);
85const uint16_t PROTOCOL_BINARY_RESPONSE_NOT_STORED =
86        uint16_t(cb::mcbp::Status::NotStored);
87const uint16_t PROTOCOL_BINARY_RESPONSE_DELTA_BADVAL =
88        uint16_t(cb::mcbp::Status::DeltaBadval);
89const uint16_t PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET =
90        uint16_t(cb::mcbp::Status::NotMyVbucket);
91const uint16_t PROTOCOL_BINARY_RESPONSE_NO_BUCKET =
92        uint16_t(cb::mcbp::Status::NoBucket);
93const uint16_t PROTOCOL_BINARY_RESPONSE_LOCKED =
94        uint16_t(cb::mcbp::Status::Locked);
95const uint16_t PROTOCOL_BINARY_RESPONSE_AUTH_STALE =
96        uint16_t(cb::mcbp::Status::AuthStale);
97const uint16_t PROTOCOL_BINARY_RESPONSE_AUTH_ERROR =
98        uint16_t(cb::mcbp::Status::AuthError);
99const uint16_t PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE =
100        uint16_t(cb::mcbp::Status::AuthContinue);
101const uint16_t PROTOCOL_BINARY_RESPONSE_ERANGE =
102        uint16_t(cb::mcbp::Status::Erange);
103const uint16_t PROTOCOL_BINARY_RESPONSE_ROLLBACK =
104        uint16_t(cb::mcbp::Status::Rollback);
105const uint16_t PROTOCOL_BINARY_RESPONSE_EACCESS =
106        uint16_t(cb::mcbp::Status::Eaccess);
107const uint16_t PROTOCOL_BINARY_RESPONSE_NOT_INITIALIZED =
108        uint16_t(cb::mcbp::Status::NotInitialized);
109const uint16_t PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND =
110        uint16_t(cb::mcbp::Status::UnknownCommand);
111const uint16_t PROTOCOL_BINARY_RESPONSE_ENOMEM =
112        uint16_t(cb::mcbp::Status::Enomem);
113const uint16_t PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED =
114        uint16_t(cb::mcbp::Status::NotSupported);
115const uint16_t PROTOCOL_BINARY_RESPONSE_EINTERNAL =
116        uint16_t(cb::mcbp::Status::Einternal);
117const uint16_t PROTOCOL_BINARY_RESPONSE_EBUSY = uint16_t(cb::mcbp::Status::Ebusy);
118const uint16_t PROTOCOL_BINARY_RESPONSE_ETMPFAIL =
119        uint16_t(cb::mcbp::Status::Etmpfail);
120const uint16_t PROTOCOL_BINARY_RESPONSE_XATTR_EINVAL =
121        uint16_t(cb::mcbp::Status::XattrEinval);
122const uint16_t PROTOCOL_BINARY_RESPONSE_UNKNOWN_COLLECTION =
123        uint16_t(cb::mcbp::Status::UnknownCollection);
124const uint16_t PROTOCOL_BINARY_RESPONSE_NO_COLLECTIONS_MANIFEST =
125        uint16_t(cb::mcbp::Status::NoCollectionsManifest);
126const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_ENOENT =
127        uint16_t(cb::mcbp::Status::SubdocPathEnoent);
128const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_MISMATCH =
129        uint16_t(cb::mcbp::Status::SubdocPathMismatch);
130const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_EINVAL =
131        uint16_t(cb::mcbp::Status::SubdocPathEinval);
132const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_E2BIG =
133        uint16_t(cb::mcbp::Status::SubdocPathE2big);
134const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_DOC_E2DEEP =
135        uint16_t(cb::mcbp::Status::SubdocDocE2deep);
136const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_VALUE_CANTINSERT =
137        uint16_t(cb::mcbp::Status::SubdocValueCantinsert);
138const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_DOC_NOTJSON =
139        uint16_t(cb::mcbp::Status::SubdocDocNotJson);
140const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_NUM_ERANGE =
141        uint16_t(cb::mcbp::Status::SubdocNumErange);
142const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_DELTA_EINVAL =
143        uint16_t(cb::mcbp::Status::SubdocDeltaEinval);
144const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_EEXISTS =
145        uint16_t(cb::mcbp::Status::SubdocPathEexists);
146const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_VALUE_ETOODEEP =
147        uint16_t(cb::mcbp::Status::SubdocValueEtoodeep);
148const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_INVALID_COMBO =
149        uint16_t(cb::mcbp::Status::SubdocInvalidCombo);
150const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_MULTI_PATH_FAILURE =
151        uint16_t(cb::mcbp::Status::SubdocMultiPathFailure);
152const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_SUCCESS_DELETED =
153        uint16_t(cb::mcbp::Status::SubdocSuccessDeleted);
154const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_XATTR_INVALID_FLAG_COMBO =
155        uint16_t(cb::mcbp::Status::SubdocXattrInvalidFlagCombo);
156const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_XATTR_INVALID_KEY_COMBO =
157        uint16_t(cb::mcbp::Status::SubdocXattrInvalidKeyCombo);
158const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_XATTR_UNKNOWN_MACRO =
159        uint16_t(cb::mcbp::Status::SubdocXattrUnknownMacro);
160const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_XATTR_UNKNOWN_VATTR =
161        uint16_t(cb::mcbp::Status::SubdocXattrUnknownVattr);
162const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_XATTR_CANT_MODIFY_VATTR =
163        uint16_t(cb::mcbp::Status::SubdocXattrCantModifyVattr);
164const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_MULTI_PATH_FAILURE_DELETED =
165        uint16_t(cb::mcbp::Status::SubdocMultiPathFailureDeleted);
166const uint16_t PROTOCOL_BINARY_RESPONSE_SUBDOC_INVALID_XATTR_ORDER =
167        uint16_t(cb::mcbp::Status::SubdocInvalidXattrOrder);
168
169using protocol_binary_command = uint8_t;
170
171const uint8_t PROTOCOL_BINARY_CMD_GET = uint8_t(cb::mcbp::ClientOpcode::Get);
172const uint8_t PROTOCOL_BINARY_CMD_SET = uint8_t(cb::mcbp::ClientOpcode::Set);
173const uint8_t PROTOCOL_BINARY_CMD_ADD = uint8_t(cb::mcbp::ClientOpcode::Add);
174const uint8_t PROTOCOL_BINARY_CMD_REPLACE =
175        uint8_t(cb::mcbp::ClientOpcode::Replace);
176const uint8_t PROTOCOL_BINARY_CMD_DELETE =
177        uint8_t(cb::mcbp::ClientOpcode::Delete);
178const uint8_t PROTOCOL_BINARY_CMD_INCREMENT =
179        uint8_t(cb::mcbp::ClientOpcode::Increment);
180const uint8_t PROTOCOL_BINARY_CMD_DECREMENT =
181        uint8_t(cb::mcbp::ClientOpcode::Decrement);
182const uint8_t PROTOCOL_BINARY_CMD_QUIT = uint8_t(cb::mcbp::ClientOpcode::Quit);
183const uint8_t PROTOCOL_BINARY_CMD_FLUSH =
184        uint8_t(cb::mcbp::ClientOpcode::Flush);
185const uint8_t PROTOCOL_BINARY_CMD_GETQ = uint8_t(cb::mcbp::ClientOpcode::Getq);
186const uint8_t PROTOCOL_BINARY_CMD_NOOP = uint8_t(cb::mcbp::ClientOpcode::Noop);
187const uint8_t PROTOCOL_BINARY_CMD_VERSION =
188        uint8_t(cb::mcbp::ClientOpcode::Version);
189const uint8_t PROTOCOL_BINARY_CMD_GETK = uint8_t(cb::mcbp::ClientOpcode::Getk);
190const uint8_t PROTOCOL_BINARY_CMD_GETKQ =
191        uint8_t(cb::mcbp::ClientOpcode::Getkq);
192const uint8_t PROTOCOL_BINARY_CMD_APPEND =
193        uint8_t(cb::mcbp::ClientOpcode::Append);
194const uint8_t PROTOCOL_BINARY_CMD_PREPEND =
195        uint8_t(cb::mcbp::ClientOpcode::Prepend);
196const uint8_t PROTOCOL_BINARY_CMD_STAT = uint8_t(cb::mcbp::ClientOpcode::Stat);
197const uint8_t PROTOCOL_BINARY_CMD_SETQ = uint8_t(cb::mcbp::ClientOpcode::Setq);
198const uint8_t PROTOCOL_BINARY_CMD_ADDQ = uint8_t(cb::mcbp::ClientOpcode::Addq);
199const uint8_t PROTOCOL_BINARY_CMD_REPLACEQ =
200        uint8_t(cb::mcbp::ClientOpcode::Replaceq);
201const uint8_t PROTOCOL_BINARY_CMD_DELETEQ =
202        uint8_t(cb::mcbp::ClientOpcode::Deleteq);
203const uint8_t PROTOCOL_BINARY_CMD_INCREMENTQ =
204        uint8_t(cb::mcbp::ClientOpcode::Incrementq);
205const uint8_t PROTOCOL_BINARY_CMD_DECREMENTQ =
206        uint8_t(cb::mcbp::ClientOpcode::Decrementq);
207const uint8_t PROTOCOL_BINARY_CMD_QUITQ =
208        uint8_t(cb::mcbp::ClientOpcode::Quitq);
209const uint8_t PROTOCOL_BINARY_CMD_FLUSHQ =
210        uint8_t(cb::mcbp::ClientOpcode::Flushq);
211const uint8_t PROTOCOL_BINARY_CMD_APPENDQ =
212        uint8_t(cb::mcbp::ClientOpcode::Appendq);
213const uint8_t PROTOCOL_BINARY_CMD_PREPENDQ =
214        uint8_t(cb::mcbp::ClientOpcode::Prependq);
215const uint8_t PROTOCOL_BINARY_CMD_VERBOSITY =
216        uint8_t(cb::mcbp::ClientOpcode::Verbosity);
217const uint8_t PROTOCOL_BINARY_CMD_TOUCH =
218        uint8_t(cb::mcbp::ClientOpcode::Touch);
219const uint8_t PROTOCOL_BINARY_CMD_GAT = uint8_t(cb::mcbp::ClientOpcode::Gat);
220const uint8_t PROTOCOL_BINARY_CMD_GATQ = uint8_t(cb::mcbp::ClientOpcode::Gatq);
221const uint8_t PROTOCOL_BINARY_CMD_HELLO =
222        uint8_t(cb::mcbp::ClientOpcode::Hello);
223const uint8_t PROTOCOL_BINARY_CMD_SASL_LIST_MECHS =
224        uint8_t(cb::mcbp::ClientOpcode::SaslListMechs);
225const uint8_t PROTOCOL_BINARY_CMD_SASL_AUTH =
226        uint8_t(cb::mcbp::ClientOpcode::SaslAuth);
227const uint8_t PROTOCOL_BINARY_CMD_SASL_STEP =
228        uint8_t(cb::mcbp::ClientOpcode::SaslStep);
229const uint8_t PROTOCOL_BINARY_CMD_IOCTL_GET =
230        uint8_t(cb::mcbp::ClientOpcode::IoctlGet);
231const uint8_t PROTOCOL_BINARY_CMD_IOCTL_SET =
232        uint8_t(cb::mcbp::ClientOpcode::IoctlSet);
233const uint8_t PROTOCOL_BINARY_CMD_CONFIG_VALIDATE =
234        uint8_t(cb::mcbp::ClientOpcode::ConfigValidate);
235const uint8_t PROTOCOL_BINARY_CMD_CONFIG_RELOAD =
236        uint8_t(cb::mcbp::ClientOpcode::ConfigReload);
237const uint8_t PROTOCOL_BINARY_CMD_AUDIT_PUT =
238        uint8_t(cb::mcbp::ClientOpcode::AuditPut);
239const uint8_t PROTOCOL_BINARY_CMD_AUDIT_CONFIG_RELOAD =
240        uint8_t(cb::mcbp::ClientOpcode::AuditConfigReload);
241const uint8_t PROTOCOL_BINARY_CMD_SHUTDOWN =
242        uint8_t(cb::mcbp::ClientOpcode::Shutdown);
243const uint8_t PROTOCOL_BINARY_CMD_RGET = uint8_t(cb::mcbp::ClientOpcode::Rget);
244const uint8_t PROTOCOL_BINARY_CMD_RSET = uint8_t(cb::mcbp::ClientOpcode::Rset);
245const uint8_t PROTOCOL_BINARY_CMD_RSETQ =
246        uint8_t(cb::mcbp::ClientOpcode::Rsetq);
247const uint8_t PROTOCOL_BINARY_CMD_RAPPEND =
248        uint8_t(cb::mcbp::ClientOpcode::Rappend);
249const uint8_t PROTOCOL_BINARY_CMD_RAPPENDQ =
250        uint8_t(cb::mcbp::ClientOpcode::Rappendq);
251const uint8_t PROTOCOL_BINARY_CMD_RPREPEND =
252        uint8_t(cb::mcbp::ClientOpcode::Rprepend);
253const uint8_t PROTOCOL_BINARY_CMD_RPREPENDQ =
254        uint8_t(cb::mcbp::ClientOpcode::Rprependq);
255const uint8_t PROTOCOL_BINARY_CMD_RDELETE =
256        uint8_t(cb::mcbp::ClientOpcode::Rdelete);
257const uint8_t PROTOCOL_BINARY_CMD_RDELETEQ =
258        uint8_t(cb::mcbp::ClientOpcode::Rdeleteq);
259const uint8_t PROTOCOL_BINARY_CMD_RINCR =
260        uint8_t(cb::mcbp::ClientOpcode::Rincr);
261const uint8_t PROTOCOL_BINARY_CMD_RINCRQ =
262        uint8_t(cb::mcbp::ClientOpcode::Rincrq);
263const uint8_t PROTOCOL_BINARY_CMD_RDECR =
264        uint8_t(cb::mcbp::ClientOpcode::Rdecr);
265const uint8_t PROTOCOL_BINARY_CMD_RDECRQ =
266        uint8_t(cb::mcbp::ClientOpcode::Rdecrq);
267const uint8_t PROTOCOL_BINARY_CMD_SET_VBUCKET =
268        uint8_t(cb::mcbp::ClientOpcode::SetVbucket);
269const uint8_t PROTOCOL_BINARY_CMD_GET_VBUCKET =
270        uint8_t(cb::mcbp::ClientOpcode::GetVbucket);
271const uint8_t PROTOCOL_BINARY_CMD_DEL_VBUCKET =
272        uint8_t(cb::mcbp::ClientOpcode::DelVbucket);
273const uint8_t PROTOCOL_BINARY_CMD_TAP_CONNECT =
274        uint8_t(cb::mcbp::ClientOpcode::TapConnect);
275const uint8_t PROTOCOL_BINARY_CMD_TAP_MUTATION =
276        uint8_t(cb::mcbp::ClientOpcode::TapMutation);
277const uint8_t PROTOCOL_BINARY_CMD_TAP_DELETE =
278        uint8_t(cb::mcbp::ClientOpcode::TapDelete);
279const uint8_t PROTOCOL_BINARY_CMD_TAP_FLUSH =
280        uint8_t(cb::mcbp::ClientOpcode::TapFlush);
281const uint8_t PROTOCOL_BINARY_CMD_TAP_OPAQUE =
282        uint8_t(cb::mcbp::ClientOpcode::TapOpaque);
283const uint8_t PROTOCOL_BINARY_CMD_TAP_VBUCKET_SET =
284        uint8_t(cb::mcbp::ClientOpcode::TapVbucketSet);
285const uint8_t PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_START =
286        uint8_t(cb::mcbp::ClientOpcode::TapCheckpointStart);
287const uint8_t PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_END =
288        uint8_t(cb::mcbp::ClientOpcode::TapCheckpointEnd);
289const uint8_t PROTOCOL_BINARY_CMD_GET_ALL_VB_SEQNOS =
290        uint8_t(cb::mcbp::ClientOpcode::GetAllVbSeqnos);
291const uint8_t PROTOCOL_BINARY_CMD_DCP_OPEN =
292        uint8_t(cb::mcbp::ClientOpcode::DcpOpen);
293const uint8_t PROTOCOL_BINARY_CMD_DCP_ADD_STREAM =
294        uint8_t(cb::mcbp::ClientOpcode::DcpAddStream);
295const uint8_t PROTOCOL_BINARY_CMD_DCP_CLOSE_STREAM =
296        uint8_t(cb::mcbp::ClientOpcode::DcpCloseStream);
297const uint8_t PROTOCOL_BINARY_CMD_DCP_STREAM_REQ =
298        uint8_t(cb::mcbp::ClientOpcode::DcpStreamReq);
299const uint8_t PROTOCOL_BINARY_CMD_DCP_GET_FAILOVER_LOG =
300        uint8_t(cb::mcbp::ClientOpcode::DcpGetFailoverLog);
301const uint8_t PROTOCOL_BINARY_CMD_DCP_STREAM_END =
302        uint8_t(cb::mcbp::ClientOpcode::DcpStreamEnd);
303const uint8_t PROTOCOL_BINARY_CMD_DCP_SNAPSHOT_MARKER =
304        uint8_t(cb::mcbp::ClientOpcode::DcpSnapshotMarker);
305const uint8_t PROTOCOL_BINARY_CMD_DCP_MUTATION =
306        uint8_t(cb::mcbp::ClientOpcode::DcpMutation);
307const uint8_t PROTOCOL_BINARY_CMD_DCP_DELETION =
308        uint8_t(cb::mcbp::ClientOpcode::DcpDeletion);
309const uint8_t PROTOCOL_BINARY_CMD_DCP_EXPIRATION =
310        uint8_t(cb::mcbp::ClientOpcode::DcpExpiration);
311const uint8_t PROTOCOL_BINARY_CMD_DCP_FLUSH =
312        uint8_t(cb::mcbp::ClientOpcode::DcpFlush);
313const uint8_t PROTOCOL_BINARY_CMD_DCP_SET_VBUCKET_STATE =
314        uint8_t(cb::mcbp::ClientOpcode::DcpSetVbucketState);
315const uint8_t PROTOCOL_BINARY_CMD_DCP_NOOP =
316        uint8_t(cb::mcbp::ClientOpcode::DcpNoop);
317const uint8_t PROTOCOL_BINARY_CMD_DCP_BUFFER_ACKNOWLEDGEMENT =
318        uint8_t(cb::mcbp::ClientOpcode::DcpBufferAcknowledgement);
319const uint8_t PROTOCOL_BINARY_CMD_DCP_CONTROL =
320        uint8_t(cb::mcbp::ClientOpcode::DcpControl);
321const uint8_t PROTOCOL_BINARY_CMD_DCP_SYSTEM_EVENT =
322        uint8_t(cb::mcbp::ClientOpcode::DcpSystemEvent);
323const uint8_t PROTOCOL_BINARY_CMD_STOP_PERSISTENCE =
324        uint8_t(cb::mcbp::ClientOpcode::StopPersistence);
325const uint8_t PROTOCOL_BINARY_CMD_START_PERSISTENCE =
326        uint8_t(cb::mcbp::ClientOpcode::StartPersistence);
327const uint8_t PROTOCOL_BINARY_CMD_SET_PARAM =
328        uint8_t(cb::mcbp::ClientOpcode::SetParam);
329const uint8_t PROTOCOL_BINARY_CMD_GET_REPLICA =
330        uint8_t(cb::mcbp::ClientOpcode::GetReplica);
331const uint8_t PROTOCOL_BINARY_CMD_CREATE_BUCKET =
332        uint8_t(cb::mcbp::ClientOpcode::CreateBucket);
333const uint8_t PROTOCOL_BINARY_CMD_DELETE_BUCKET =
334        uint8_t(cb::mcbp::ClientOpcode::DeleteBucket);
335const uint8_t PROTOCOL_BINARY_CMD_LIST_BUCKETS =
336        uint8_t(cb::mcbp::ClientOpcode::ListBuckets);
337const uint8_t PROTOCOL_BINARY_CMD_SELECT_BUCKET =
338        uint8_t(cb::mcbp::ClientOpcode::SelectBucket);
339const uint8_t PROTOCOL_BINARY_CMD_OBSERVE_SEQNO =
340        uint8_t(cb::mcbp::ClientOpcode::ObserveSeqno);
341const uint8_t PROTOCOL_BINARY_CMD_OBSERVE =
342        uint8_t(cb::mcbp::ClientOpcode::Observe);
343const uint8_t PROTOCOL_BINARY_CMD_EVICT_KEY =
344        uint8_t(cb::mcbp::ClientOpcode::EvictKey);
345const uint8_t PROTOCOL_BINARY_CMD_GET_LOCKED =
346        uint8_t(cb::mcbp::ClientOpcode::GetLocked);
347const uint8_t PROTOCOL_BINARY_CMD_UNLOCK_KEY =
348        uint8_t(cb::mcbp::ClientOpcode::UnlockKey);
349const uint8_t PROTOCOL_BINARY_CMD_GET_FAILOVER_LOG =
350        uint8_t(cb::mcbp::ClientOpcode::GetFailoverLog);
351const uint8_t PROTOCOL_BINARY_CMD_LAST_CLOSED_CHECKPOINT =
352        uint8_t(cb::mcbp::ClientOpcode::LastClosedCheckpoint);
353const uint8_t PROTOCOL_BINARY_CMD_GET_META =
354        uint8_t(cb::mcbp::ClientOpcode::GetMeta);
355const uint8_t PROTOCOL_BINARY_CMD_GETQ_META =
356        uint8_t(cb::mcbp::ClientOpcode::GetqMeta);
357const uint8_t PROTOCOL_BINARY_CMD_SET_WITH_META =
358        uint8_t(cb::mcbp::ClientOpcode::SetWithMeta);
359const uint8_t PROTOCOL_BINARY_CMD_SETQ_WITH_META =
360        uint8_t(cb::mcbp::ClientOpcode::SetqWithMeta);
361const uint8_t PROTOCOL_BINARY_CMD_ADD_WITH_META =
362        uint8_t(cb::mcbp::ClientOpcode::AddWithMeta);
363const uint8_t PROTOCOL_BINARY_CMD_ADDQ_WITH_META =
364        uint8_t(cb::mcbp::ClientOpcode::AddqWithMeta);
365const uint8_t PROTOCOL_BINARY_CMD_SNAPSHOT_VB_STATES =
366        uint8_t(cb::mcbp::ClientOpcode::SnapshotVbStates);
367const uint8_t PROTOCOL_BINARY_CMD_VBUCKET_BATCH_COUNT =
368        uint8_t(cb::mcbp::ClientOpcode::VbucketBatchCount);
369const uint8_t PROTOCOL_BINARY_CMD_DEL_WITH_META =
370        uint8_t(cb::mcbp::ClientOpcode::DelWithMeta);
371const uint8_t PROTOCOL_BINARY_CMD_DELQ_WITH_META =
372        uint8_t(cb::mcbp::ClientOpcode::DelqWithMeta);
373const uint8_t PROTOCOL_BINARY_CMD_CREATE_CHECKPOINT =
374        uint8_t(cb::mcbp::ClientOpcode::CreateCheckpoint);
375const uint8_t PROTOCOL_BINARY_CMD_NOTIFY_VBUCKET_UPDATE =
376        uint8_t(cb::mcbp::ClientOpcode::NotifyVbucketUpdate);
377const uint8_t PROTOCOL_BINARY_CMD_ENABLE_TRAFFIC =
378        uint8_t(cb::mcbp::ClientOpcode::EnableTraffic);
379const uint8_t PROTOCOL_BINARY_CMD_DISABLE_TRAFFIC =
380        uint8_t(cb::mcbp::ClientOpcode::DisableTraffic);
381const uint8_t PROTOCOL_BINARY_CMD_CHECKPOINT_PERSISTENCE =
382        uint8_t(cb::mcbp::ClientOpcode::CheckpointPersistence);
383const uint8_t PROTOCOL_BINARY_CMD_RETURN_META =
384        uint8_t(cb::mcbp::ClientOpcode::ReturnMeta);
385const uint8_t PROTOCOL_BINARY_CMD_COMPACT_DB =
386        uint8_t(cb::mcbp::ClientOpcode::CompactDb);
387const uint8_t PROTOCOL_BINARY_CMD_SET_CLUSTER_CONFIG =
388        uint8_t(cb::mcbp::ClientOpcode::SetClusterConfig);
389const uint8_t PROTOCOL_BINARY_CMD_GET_CLUSTER_CONFIG =
390        uint8_t(cb::mcbp::ClientOpcode::GetClusterConfig);
391const uint8_t PROTOCOL_BINARY_CMD_GET_RANDOM_KEY =
392        uint8_t(cb::mcbp::ClientOpcode::GetRandomKey);
393const uint8_t PROTOCOL_BINARY_CMD_SEQNO_PERSISTENCE =
394        uint8_t(cb::mcbp::ClientOpcode::SeqnoPersistence);
395const uint8_t PROTOCOL_BINARY_CMD_GET_KEYS =
396        uint8_t(cb::mcbp::ClientOpcode::GetKeys);
397const uint8_t PROTOCOL_BINARY_CMD_COLLECTIONS_SET_MANIFEST =
398        uint8_t(cb::mcbp::ClientOpcode::CollectionsSetManifest);
399const uint8_t PROTOCOL_BINARY_CMD_COLLECTIONS_GET_MANIFEST =
400        uint8_t(cb::mcbp::ClientOpcode::CollectionsGetManifest);
401const uint8_t PROTOCOL_BINARY_CMD_SET_DRIFT_COUNTER_STATE =
402        uint8_t(cb::mcbp::ClientOpcode::SetDriftCounterState);
403const uint8_t PROTOCOL_BINARY_CMD_GET_ADJUSTED_TIME =
404        uint8_t(cb::mcbp::ClientOpcode::GetAdjustedTime);
405const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_GET =
406        uint8_t(cb::mcbp::ClientOpcode::SubdocGet);
407const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_EXISTS =
408        uint8_t(cb::mcbp::ClientOpcode::SubdocExists);
409const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_DICT_ADD =
410        uint8_t(cb::mcbp::ClientOpcode::SubdocDictAdd);
411const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_DICT_UPSERT =
412        uint8_t(cb::mcbp::ClientOpcode::SubdocDictUpsert);
413const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_DELETE =
414        uint8_t(cb::mcbp::ClientOpcode::SubdocDelete);
415const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_REPLACE =
416        uint8_t(cb::mcbp::ClientOpcode::SubdocReplace);
417const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_ARRAY_PUSH_LAST =
418        uint8_t(cb::mcbp::ClientOpcode::SubdocArrayPushLast);
419const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_ARRAY_PUSH_FIRST =
420        uint8_t(cb::mcbp::ClientOpcode::SubdocArrayPushFirst);
421const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_ARRAY_INSERT =
422        uint8_t(cb::mcbp::ClientOpcode::SubdocArrayInsert);
423const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_ARRAY_ADD_UNIQUE =
424        uint8_t(cb::mcbp::ClientOpcode::SubdocArrayAddUnique);
425const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_COUNTER =
426        uint8_t(cb::mcbp::ClientOpcode::SubdocCounter);
427const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_MULTI_LOOKUP =
428        uint8_t(cb::mcbp::ClientOpcode::SubdocMultiLookup);
429const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_MULTI_MUTATION =
430        uint8_t(cb::mcbp::ClientOpcode::SubdocMultiMutation);
431const uint8_t PROTOCOL_BINARY_CMD_SUBDOC_GET_COUNT =
432        uint8_t(cb::mcbp::ClientOpcode::SubdocGetCount);
433const uint8_t PROTOCOL_BINARY_CMD_SCRUB =
434        uint8_t(cb::mcbp::ClientOpcode::Scrub);
435const uint8_t PROTOCOL_BINARY_CMD_ISASL_REFRESH =
436        uint8_t(cb::mcbp::ClientOpcode::IsaslRefresh);
437const uint8_t PROTOCOL_BINARY_CMD_SSL_CERTS_REFRESH =
438        uint8_t(cb::mcbp::ClientOpcode::SslCertsRefresh);
439const uint8_t PROTOCOL_BINARY_CMD_GET_CMD_TIMER =
440        uint8_t(cb::mcbp::ClientOpcode::GetCmdTimer);
441const uint8_t PROTOCOL_BINARY_CMD_SET_CTRL_TOKEN =
442        uint8_t(cb::mcbp::ClientOpcode::SetCtrlToken);
443const uint8_t PROTOCOL_BINARY_CMD_GET_CTRL_TOKEN =
444        uint8_t(cb::mcbp::ClientOpcode::GetCtrlToken);
445const uint8_t PROTOCOL_BINARY_CMD_RBAC_REFRESH =
446        uint8_t(cb::mcbp::ClientOpcode::RbacRefresh);
447const uint8_t PROTOCOL_BINARY_CMD_ADJUST_TIMEOFDAY =
448        uint8_t(cb::mcbp::ClientOpcode::AdjustTimeofday);
449const uint8_t PROTOCOL_BINARY_CMD_EWOULDBLOCK_CTL =
450        uint8_t(cb::mcbp::ClientOpcode::EwouldblockCtl);
451const uint8_t PROTOCOL_BINARY_CMD_GET_ERROR_MAP =
452        uint8_t(cb::mcbp::ClientOpcode::GetErrorMap);
453const uint8_t PROTOCOL_BINARY_CMD_DROP_PRIVILEGE =
454        uint8_t(cb::mcbp::ClientOpcode::DropPrivilege);
455const uint8_t PROTOCOL_BINARY_CMD_INVALID =
456        uint8_t(cb::mcbp::ClientOpcode::Invalid);
457
458using protocol_binary_datatype_t = uint8_t;
459#define PROTOCOL_BINARY_RAW_BYTES uint8_t(cb::mcbp::Datatype::Raw)
460#define PROTOCOL_BINARY_DATATYPE_JSON uint8_t(cb::mcbp::Datatype::JSON)
461#define PROTOCOL_BINARY_DATATYPE_SNAPPY uint8_t(cb::mcbp::Datatype::Snappy)
462#define PROTOCOL_BINARY_DATATYPE_XATTR uint8_t(cb::mcbp::Datatype::Xattr)
463
464/*
465 * Bitmask that defines datatypes that can only be valid when a document body
466 * exists. i.e. When the document is not soft-deleted
467 */
468#define BODY_ONLY_DATATYPE_MASK \
469    uint8_t(PROTOCOL_BINARY_DATATYPE_JSON | PROTOCOL_BINARY_DATATYPE_SNAPPY);
470
471/*
472 * Bitmask that defines the datatypes that can be resident in memory. For
473 * example, DATATYPE_COMPRESSED is excluded as resident items are not
474 * compressed.
475 * This is useful for efficiently storing statistics about datatypes.
476 */
477#define RESIDENT_DATATYPE_MASK uint8_t(5);
478
479
480/**
481 * Definition of the header structure for a request packet.
482 * See section 2
483 */
484typedef union {
485    cb::mcbp::Request request;
486    uint8_t bytes[24];
487} protocol_binary_request_header;
488
489/**
490 * Definition of the header structure for a response packet.
491 * See section 2
492 */
493typedef union {
494    cb::mcbp::Response response;
495    uint8_t bytes[24];
496} protocol_binary_response_header;
497
498/**
499 * Definition of a request-packet containing no extras
500 */
501typedef union {
502    struct {
503        protocol_binary_request_header header;
504    } message;
505    uint8_t bytes[sizeof(protocol_binary_request_header)];
506} protocol_binary_request_no_extras;
507
508/**
509 * Definition of a response-packet containing no extras
510 */
511typedef union {
512    struct {
513        protocol_binary_response_header header;
514    } message;
515    uint8_t bytes[sizeof(protocol_binary_response_header)];
516} protocol_binary_response_no_extras;
517
518/**
519 * Definition of the packet used by the get, getq, getk and getkq command.
520 * See section 4
521 */
522typedef protocol_binary_request_no_extras protocol_binary_request_get;
523typedef protocol_binary_request_no_extras protocol_binary_request_getq;
524typedef protocol_binary_request_no_extras protocol_binary_request_getk;
525typedef protocol_binary_request_no_extras protocol_binary_request_getkq;
526
527/**
528 * Definition of the packet returned from a successful get, getq, getk and
529 * getkq.
530 * See section 4
531 */
532typedef union {
533    struct {
534        protocol_binary_response_header header;
535        struct {
536            uint32_t flags;
537        } body;
538    } message;
539    uint8_t bytes[sizeof(protocol_binary_response_header) + 4];
540} protocol_binary_response_get;
541
542typedef protocol_binary_response_get protocol_binary_response_getq;
543typedef protocol_binary_response_get protocol_binary_response_getk;
544typedef protocol_binary_response_get protocol_binary_response_getkq;
545
546/**
547 * Definition of the packet used by the delete command
548 * See section 4
549 */
550typedef protocol_binary_request_no_extras protocol_binary_request_delete;
551
552/**
553 * Definition of the packet returned by the delete command
554 * See section 4
555 *
556 * extlen should be either zero, or 16 if the client has enabled the
557 * MUTATION_SEQNO feature, with the following format:
558 *
559 *   Header:           (0-23): <protocol_binary_response_header>
560 *   Extras:
561 *     Vbucket UUID   (24-31): 0x0000000000003039
562 *     Seqno          (32-39): 0x000000000000002D
563 */
564typedef protocol_binary_response_no_extras protocol_binary_response_delete;
565
566/**
567 * Definition of the packet used by the flush command
568 * See section 4
569 * Please note that the expiration field is optional, so remember to see
570 * check the header.bodysize to see if it is present.
571 */
572typedef union {
573    struct {
574        protocol_binary_request_header header;
575        struct {
576            /*
577             * Specifying a non-null expiration time is no longer
578             * supported
579             */
580            uint32_t expiration;
581        } body;
582    } message;
583    uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
584} protocol_binary_request_flush;
585
586/**
587 * Definition of the packet returned by the flush command
588 * See section 4
589 */
590typedef protocol_binary_response_no_extras protocol_binary_response_flush;
591
592/**
593 * Definition of the packet used by set, add and replace
594 * See section 4
595 */
596typedef union {
597    struct {
598        protocol_binary_request_header header;
599        struct {
600            uint32_t flags;
601            uint32_t expiration;
602        } body;
603    } message;
604    uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
605} protocol_binary_request_set;
606typedef protocol_binary_request_set protocol_binary_request_add;
607typedef protocol_binary_request_set protocol_binary_request_replace;
608
609/**
610 * Definition of the packet returned by set, add and replace
611 * See section 4
612 */
613typedef protocol_binary_response_no_extras protocol_binary_response_set;
614typedef protocol_binary_response_no_extras protocol_binary_response_add;
615typedef protocol_binary_response_no_extras protocol_binary_response_replace;
616
617/**
618 * Definition of the noop packet
619 * See section 4
620 */
621typedef protocol_binary_request_no_extras protocol_binary_request_noop;
622
623/**
624 * Definition of the packet returned by the noop command
625 * See section 4
626 */
627typedef protocol_binary_response_no_extras protocol_binary_response_noop;
628
629/**
630 * Definition of the structure used by the increment and decrement
631 * command.
632 * See section 4
633 */
634typedef union {
635    struct {
636        protocol_binary_request_header header;
637        struct {
638            uint64_t delta;
639            uint64_t initial;
640            uint32_t expiration;
641        } body;
642    } message;
643    uint8_t bytes[sizeof(protocol_binary_request_header) + 20];
644} protocol_binary_request_incr;
645typedef protocol_binary_request_incr protocol_binary_request_decr;
646
647/**
648 * Definition of the response from an incr or decr command
649 * command.
650 *
651 * The result of the incr/decr is a uint64_t placed at header + extlen.
652 *
653 * extlen should be either zero, or 16 if the client has enabled the
654 * MUTATION_SEQNO feature, with the following format:
655 *
656 *   Header:           (0-23): <protocol_binary_response_header>
657 *   Extras:
658 *     Vbucket UUID   (24-31): 0x0000000000003039
659 *     Seqno          (32-39): 0x000000000000002D
660 *   Value:           (40-47): ....
661 *
662 */
663typedef protocol_binary_response_no_extras protocol_binary_response_incr;
664typedef protocol_binary_response_no_extras protocol_binary_response_decr;
665
666/**
667 * Definition of the quit
668 * See section 4
669 */
670typedef protocol_binary_request_no_extras protocol_binary_request_quit;
671
672/**
673 * Definition of the packet returned by the quit command
674 * See section 4
675 */
676typedef protocol_binary_response_no_extras protocol_binary_response_quit;
677
678/**
679 * Definition of the packet used by append and prepend command
680 * See section 4
681 */
682typedef protocol_binary_request_no_extras protocol_binary_request_append;
683typedef protocol_binary_request_no_extras protocol_binary_request_prepend;
684
685/**
686 * Definition of the packet returned from a successful append or prepend
687 * See section 4
688 */
689typedef protocol_binary_response_no_extras protocol_binary_response_append;
690typedef protocol_binary_response_no_extras protocol_binary_response_prepend;
691
692/**
693 * Definition of the packet used by the version command
694 * See section 4
695 */
696typedef protocol_binary_request_no_extras protocol_binary_request_version;
697
698/**
699 * Definition of the packet returned from a successful version command
700 * See section 4
701 */
702typedef protocol_binary_response_no_extras protocol_binary_response_version;
703
704/**
705 * Definition of the packet used by the stats command.
706 * See section 4
707 */
708typedef protocol_binary_request_no_extras protocol_binary_request_stats;
709
710/**
711 * Definition of the packet returned from a successful stats command
712 * See section 4
713 */
714typedef protocol_binary_response_no_extras protocol_binary_response_stats;
715
716/**
717 * Definition of the packet used by the verbosity command
718 */
719typedef union {
720    struct {
721        protocol_binary_request_header header;
722        struct {
723            uint32_t level;
724        } body;
725    } message;
726    uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
727} protocol_binary_request_verbosity;
728
729/**
730 * Definition of the packet returned from the verbosity command
731 */
732typedef protocol_binary_response_no_extras protocol_binary_response_verbosity;
733
734/**
735 * Definition of the packet used by the touch command.
736 */
737typedef union {
738    struct {
739        protocol_binary_request_header header;
740        struct {
741            uint32_t expiration;
742        } body;
743    } message;
744    uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
745} protocol_binary_request_touch;
746
747/**
748 * Definition of the packet returned from the touch command
749 */
750typedef protocol_binary_response_no_extras protocol_binary_response_touch;
751
752/**
753 * Definition of the packet used by the GAT(Q) command.
754 */
755typedef union {
756    struct {
757        protocol_binary_request_header header;
758        struct {
759            uint32_t expiration;
760        } body;
761    } message;
762    uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
763} protocol_binary_request_gat;
764
765typedef protocol_binary_request_gat protocol_binary_request_gatq;
766
767/**
768 * Definition of the packet returned from the GAT(Q)
769 */
770typedef protocol_binary_response_get protocol_binary_response_gat;
771typedef protocol_binary_response_get protocol_binary_response_gatq;
772
773
774/**
775 * Definitions for extended (flexible) metadata
776 *
777 * @1: Flex Code to identify the number of extended metadata fields
778 * @2: Size of the Flex Code, set to 1 byte
779 * @3: Current size of extended metadata
780 */
781typedef enum {
782    FLEX_META_CODE = 0x01,
783    FLEX_DATA_OFFSET = 1,
784    EXT_META_LEN = 1
785} protocol_binary_flexmeta;
786
787/**
788 * Definitions of sub-document path flags (this is a bitmap)
789 */
790typedef enum : uint8_t {
791    /** No flags set */
792    SUBDOC_FLAG_NONE = 0x0,
793
794    /** (Mutation) Should non-existent intermediate paths be created? */
795    SUBDOC_FLAG_MKDIR_P = 0x01,
796
797    /**
798     * 0x02 is unused
799     */
800
801    /**
802     * If set, the path refers to an Extended Attribute (XATTR).
803     * If clear, the path refers to a path inside the document body.
804     */
805    SUBDOC_FLAG_XATTR_PATH = 0x04,
806
807    /**
808     * 0x08 is unused
809     */
810
811    /**
812     * Expand macro values inside extended attributes. The request is
813     * invalid if this flag is set without SUBDOC_FLAG_XATTR_PATH being
814     * set.
815     */
816    SUBDOC_FLAG_EXPAND_MACROS = 0x10,
817
818} protocol_binary_subdoc_flag;
819
820namespace mcbp {
821namespace subdoc {
822/**
823 * Definitions of sub-document doc flags (this is a bitmap).
824 */
825
826enum class doc_flag : uint8_t {
827    None = 0x0,
828
829    /**
830     * (Mutation) Create the document if it does not exist. Implies
831     * SUBDOC_FLAG_MKDIR_P and Set (upsert) mutation semantics. Not valid
832     * with Add.
833     */
834        Mkdoc = 0x1,
835
836    /**
837     * (Mutation) Add the document only if it does not exist. Implies
838     * SUBDOC_FLAG_MKDIR_P. Not valid with Mkdoc.
839     */
840        Add = 0x02,
841
842    /**
843     * Allow access to XATTRs for deleted documents (instead of
844     * returning KEY_ENOENT).
845     */
846        AccessDeleted = 0x04,
847
848};
849} // namespace subdoc
850} // namespace mcbp
851
852
853
854
855/**
856 * Definition of the packet used by SUBDOCUMENT single-path commands.
857 *
858 * The path, which is always required, is in the Body, after the Key.
859 *
860 *   Header:                        24 @0: <protocol_binary_request_header>
861 *   Extras:
862 *     Sub-document pathlen          2 @24: <variable>
863 *     Sub-document flags            1 @26: <protocol_binary_subdoc_flag>
864 *     Expiry                        4 @27: (Optional) Mutations only. The
865 *                                          ttl
866 *     Sub-document doc flags        1 @27: (Optional) @31 if expiry is
867 *                                          set. Note these are the
868 *                                          subdocument doc flags not the
869 *                                          flag section in the document.
870 *   Body:
871 *     Key                      keylen @27: <variable>
872 *     Path                    pathlen @27+keylen: <variable>
873 *     Value to insert/replace
874 *               vallen-keylen-pathlen @27+keylen+pathlen: [variable]
875 */
876typedef union {
877    struct {
878        protocol_binary_request_header header;
879        struct {
880            uint16_t pathlen; // Length in bytes of the sub-doc path.
881            uint8_t subdoc_flags; // See protocol_binary_subdoc_flag
882            /* uint32_t expiry     (optional for mutations only - present
883                                    if extlen == 7 or extlen == 8) */
884            /* uint8_t doc_flags   (optional - present if extlen == 4 or
885                                    extlen == 8)  Note these are the
886                                    subdocument doc flags not the flag
887                                    \section in the document. */
888        } extras;
889    } message;
890    uint8_t bytes[sizeof(protocol_binary_request_header) + 3];
891} protocol_binary_request_subdocument;
892
893/** Definition of the packet used by SUBDOCUMENT responses.
894 */
895typedef union {
896    struct {
897        protocol_binary_response_header header;
898    } message;
899    uint8_t bytes[sizeof(protocol_binary_response_header)];
900} protocol_binary_response_subdocument;
901
902/**
903 * Definition of the request packets used by SUBDOCUMENT multi-path commands.
904 *
905 * Multi-path sub-document commands differ from single-path in that they
906 * encode a series of multiple paths to operate on (from a single key).
907 * There are two multi-path commands - MULTI_LOOKUP and MULTI_MUTATION.
908 * - MULTI_LOOKUP consists of variable number of subdoc lookup commands
909 *                (SUBDOC_GET or SUBDOC_EXISTS).
910 * - MULTI_MUTATION consists of a variable number of subdoc mutation
911 *                  commands (i.e. all subdoc commands apart from
912 *                  SUBDOC_{GET,EXISTS}).
913 *
914 * Each path to be operated on is specified by an Operation Spec, which are
915 * contained in the body. This defines the opcode, path, and value
916 * (for mutations).
917 *
918 * A maximum of MULTI_MAX_PATHS paths (operations) can be encoded in a
919 * single multi-path command.
920 *
921 *  SUBDOC_MULTI_LOOKUP:
922 *    Header:                24 @0:  <protocol_binary_request_header>
923 *    Extras:            0 or 1 @24: (optional) doc_flags. Note these are
924 *                                   the subdocument doc flags not the flag
925 *                                   section in the document.
926 *    Body:         <variable>  @24:
927 *        Key            keylen @24: <variable>
928 *        1..MULTI_MAX_PATHS [Lookup Operation Spec]
929 *
930 *        Lookup Operation Spec:
931 *                            1 @0 : Opcode
932 *                            1 @1 : Flags
933 *                            2 @2 : Path Length
934 *                      pathlen @4 : Path
935 */
936static const int PROTOCOL_BINARY_SUBDOC_MULTI_MAX_PATHS = 16;
937
938typedef struct {
939    uint8_t opcode;
940    uint8_t flags;
941    uint16_t pathlen;
942    /* uint8_t path[pathlen] */
943} protocol_binary_subdoc_multi_lookup_spec;
944
945typedef protocol_binary_request_no_extras
946        protocol_binary_request_subdocument_multi_lookup;
947
948/*
949 *
950 * SUBDOC_MULTI_MUTATION
951 *    Header:                24 @0:  <protocol_binary_request_header>
952 *    Extras:            0 OR 4 @24: (optional) expiration
953 *                       0 OR 1 @24: (optional) doc_flags. Note these are
954 *                                   the subdocument doc flags not the
955 *                                   flag section in the document.
956 *    Body:           variable  @24 + extlen:
957 *        Key            keylen @24: <variable>
958 *        1..MULTI_MAX_PATHS [Mutation Operation Spec]
959 *
960 *        Mutation Operation Spec:
961 *                            1 @0         : Opcode
962 *                            1 @1         : Flags
963 *                            2 @2         : Path Length
964 *                            4 @4         : Value Length
965 *                      pathlen @8         : Path
966 *                       vallen @8+pathlen : Value
967 */
968typedef struct {
969    uint8_t opcode;
970    uint8_t flags;
971    uint16_t pathlen;
972    uint32_t valuelen;
973    /* uint8_t path[pathlen] */
974    /* uint8_t value[valuelen]  */
975} protocol_binary_subdoc_multi_mutation_spec;
976
977typedef protocol_binary_request_no_extras
978        protocol_binary_request_subdocument_multi_mutation;
979
980/**
981 * Definition of the response packets used by SUBDOCUMENT multi-path
982 * commands.
983 *
984 * SUBDOC_MULTI_LOOKUP - Body consists of a series of lookup_result structs,
985 *                       one per lookup_spec in the request.
986 *
987 * Lookup Result:
988 *                            2 @0 : status
989 *                            4 @2 : resultlen
990 *                    resultlen @6 : result
991 */
992typedef struct {
993    protocol_binary_request_header header;
994    /* Variable-length 1..PROTOCOL_BINARY_SUBDOC_MULTI_MAX_PATHS */
995    protocol_binary_subdoc_multi_lookup_spec body[1];
996} protocol_binary_response_subdoc_multi_lookup;
997
998/**
999 * SUBDOC_MULTI_MUTATION response
1000 *
1001 * Extras is either 0 or 16 if MUTATION_SEQNO is enabled.
1002 *
1003 * Body consists of a variable number of subdoc_multi_mutation_result_spec
1004 * structs:
1005 *
1006 * On success (header.status == SUCCESS), zero or more result specs, one for
1007 * each multi_mutation_spec which wishes to return a value.
1008 *
1009 * Mutation Result (success):
1010 *   [0..N] of:
1011 *                   1 @0 : index - Index of multi_mutation spec this result
1012 *                          corresponds to.
1013 *                   2 @1 : status - Status of the mutation (should always
1014 *                          be SUCCESS for successful multi-mutation
1015 *                          requests).
1016 *                   4 @3 : resultlen - Result value length
1017 *           resultlen @7 : Value payload
1018 *
1019
1020 * On one of more of the mutation specs failing, there is exactly one
1021 * result spec, specifying the index and status code of the first failing
1022 * mutation spec.
1023 *
1024 * Mutation Result (failure):
1025 *   1 of:
1026 *                   1 @0 : index - Index of multi_mutation spec this result
1027 *                          corresponds to.
1028 *                   2 @1 : status - Status of the mutation (should always be
1029 *                          !SUCCESS for failures).
1030 *
1031 * (Note: On failure the multi_mutation_result_spec only includes the
1032 *        first two fields).
1033 */
1034typedef union {
1035    struct {
1036        protocol_binary_response_header header;
1037    } message;
1038    uint8_t bytes[sizeof(protocol_binary_response_header)];
1039} protocol_binary_response_subdoc_multi_mutation;
1040
1041/**
1042 * Definition of a request for a range operation.
1043 * See http://code.google.com/p/memcached/wiki/RangeOps
1044 *
1045 * These types are used for range operations and exist within
1046 * this header for use in other projects.  Range operations are
1047 * not expected to be implemented in the memcached server itself.
1048 */
1049typedef union {
1050    struct {
1051        protocol_binary_response_header header;
1052        struct {
1053            uint16_t size;
1054            uint8_t reserved;
1055            uint8_t flags;
1056            uint32_t max_results;
1057        } body;
1058    } message;
1059    uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
1060} protocol_binary_request_rangeop;
1061
1062typedef protocol_binary_request_rangeop protocol_binary_request_rget;
1063typedef protocol_binary_request_rangeop protocol_binary_request_rset;
1064typedef protocol_binary_request_rangeop protocol_binary_request_rsetq;
1065typedef protocol_binary_request_rangeop protocol_binary_request_rappend;
1066typedef protocol_binary_request_rangeop protocol_binary_request_rappendq;
1067typedef protocol_binary_request_rangeop protocol_binary_request_rprepend;
1068typedef protocol_binary_request_rangeop protocol_binary_request_rprependq;
1069typedef protocol_binary_request_rangeop protocol_binary_request_rdelete;
1070typedef protocol_binary_request_rangeop protocol_binary_request_rdeleteq;
1071typedef protocol_binary_request_rangeop protocol_binary_request_rincr;
1072typedef protocol_binary_request_rangeop protocol_binary_request_rincrq;
1073typedef protocol_binary_request_rangeop protocol_binary_request_rdecr;
1074typedef protocol_binary_request_rangeop protocol_binary_request_rdecrq;
1075
1076/**
1077 * Definition of tap commands
1078 * See To be written
1079 *
1080 */
1081
1082typedef union {
1083    struct {
1084        protocol_binary_request_header header;
1085        struct {
1086            /**
1087             * flags is a bitmask used to set properties for the
1088             * the connection. Please In order to be forward compatible
1089             * you should set all undefined bits to 0.
1090             *
1091             * If the bit require extra userdata, it will be stored
1092             * in the user-data field of the body (passed to the engine
1093             * as enginespeciffic). That means that when you parse the
1094             * flags and the engine-specific data, you have to work your
1095             * way from bit 0 and upwards to find the correct offset for
1096             * the data.
1097             *
1098             */
1099            uint32_t flags;
1100
1101/**
1102 * Backfill age
1103 *
1104 * By using this flag you can limit the amount of data being
1105 * transmitted. If you don't specify a backfill age, the
1106 * server will transmit everything it contains.
1107 *
1108 * The first 8 bytes in the engine specific data contains
1109 * the oldest entry (from epoc) you're interested in.
1110 * Specifying a time in the future (for the server you are
1111 * connecting to), will cause it to start streaming current
1112 * changes.
1113 */
1114#define TAP_CONNECT_FLAG_BACKFILL 0x01
1115/**
1116 * Dump will cause the server to send the data stored on the
1117 * server, but disconnect when the keys stored in the server
1118 * are transmitted.
1119 */
1120#define TAP_CONNECT_FLAG_DUMP 0x02
1121/**
1122 * The body contains a list of 16 bits words in network byte
1123 * order specifying the vbucket ids to monitor. The first 16
1124 * bit word contains the number of buckets. The number of 0
1125 * means "all buckets"
1126 */
1127#define TAP_CONNECT_FLAG_LIST_VBUCKETS 0x04
1128/**
1129 * The responsibility of the vbuckets is to be transferred
1130 * over to the caller when all items are transferred.
1131 */
1132#define TAP_CONNECT_FLAG_TAKEOVER_VBUCKETS 0x08
1133/**
1134 * The tap consumer supports ack'ing of tap messages
1135 */
1136#define TAP_CONNECT_SUPPORT_ACK 0x10
1137/**
1138 * The tap consumer would prefer to just get the keys
1139 * back. If the engine supports this it will set
1140 * the TAP_FLAG_NO_VALUE flag in each of the
1141 * tap packets returned.
1142 */
1143#define TAP_CONNECT_REQUEST_KEYS_ONLY 0x20
1144/**
1145 * The body contains a list of (vbucket_id, last_checkpoint_id)
1146 * pairs. This provides the checkpoint support in TAP streams.
1147 * The last checkpoint id represents the last checkpoint that
1148 * was successfully persisted.
1149 */
1150#define TAP_CONNECT_CHECKPOINT 0x40
1151/**
1152 * The tap consumer is a registered tap client, which means that
1153 * the tap server will maintain its checkpoint cursor permanently.
1154 */
1155#define TAP_CONNECT_REGISTERED_CLIENT 0x80
1156
1157/**
1158 * The initial TAP implementation convert flags to/from network
1159 * byte order, but the values isn't stored in host local order
1160 * causing them to change if you mix platforms..
1161 */
1162#define TAP_CONNECT_TAP_FIX_FLAG_BYTEORDER 0x100
1163
1164        } body;
1165    } message;
1166    uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
1167} protocol_binary_request_tap_connect;
1168
1169typedef union {
1170    struct {
1171        protocol_binary_request_header header;
1172        struct {
1173            struct {
1174                uint16_t enginespecific_length;
1175/*
1176 * The flag section support the following flags
1177 */
1178/**
1179 * Request that the consumer send a response packet
1180 * for this packet. The opaque field must be preserved
1181 * in the response.
1182 */
1183#define TAP_FLAG_ACK 0x01
1184/**
1185 * The value for the key is not included in the packet
1186 */
1187#define TAP_FLAG_NO_VALUE 0x02
1188/**
1189 * The flags are in network byte order
1190 */
1191#define TAP_FLAG_NETWORK_BYTE_ORDER 0x04
1192
1193                uint16_t flags;
1194                uint8_t ttl;
1195                uint8_t res1;
1196                uint8_t res2;
1197                uint8_t res3;
1198            } tap;
1199            struct {
1200                uint32_t flags;
1201                uint32_t expiration;
1202            } item;
1203        } body;
1204    } message;
1205    uint8_t bytes[sizeof(protocol_binary_request_header) + 16];
1206} protocol_binary_request_tap_mutation;
1207
1208typedef union {
1209    struct {
1210        protocol_binary_request_header header;
1211        struct {
1212            struct {
1213                uint16_t enginespecific_length;
1214                /**
1215                 * See the definition of the flags for
1216                 * protocol_binary_request_tap_mutation for a description
1217                 * of the available flags.
1218                 */
1219                uint16_t flags;
1220                uint8_t ttl;
1221                uint8_t res1;
1222                uint8_t res2;
1223                uint8_t res3;
1224            } tap;
1225        } body;
1226    } message;
1227    uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
1228} protocol_binary_request_tap_no_extras;
1229
1230typedef protocol_binary_request_tap_no_extras
1231        protocol_binary_request_tap_delete;
1232typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_flush;
1233
1234/**
1235 * TAP OPAQUE command list
1236 */
1237#define TAP_OPAQUE_ENABLE_AUTO_NACK 0
1238#define TAP_OPAQUE_INITIAL_VBUCKET_STREAM 1
1239#define TAP_OPAQUE_ENABLE_CHECKPOINT_SYNC 2
1240#define TAP_OPAQUE_OPEN_CHECKPOINT 3
1241#define TAP_OPAQUE_COMPLETE_VB_FILTER_CHANGE 4
1242#define TAP_OPAQUE_CLOSE_TAP_STREAM 7
1243#define TAP_OPAQUE_CLOSE_BACKFILL 8
1244
1245typedef protocol_binary_request_tap_no_extras
1246        protocol_binary_request_tap_opaque;
1247typedef protocol_binary_request_tap_no_extras
1248        protocol_binary_request_tap_vbucket_set;
1249
1250/**
1251 * Definition of the packet used by the scrub.
1252 */
1253typedef protocol_binary_request_no_extras protocol_binary_request_scrub;
1254
1255/**
1256 * Definition of the packet returned from scrub.
1257 */
1258typedef protocol_binary_response_no_extras protocol_binary_response_scrub;
1259
1260/**
1261 * Definition of the packet used by set vbucket
1262 */
1263typedef union {
1264    struct {
1265        protocol_binary_request_header header;
1266        struct {
1267            vbucket_state_t state;
1268        } body;
1269    } message;
1270    uint8_t bytes[sizeof(protocol_binary_request_header) +
1271                  sizeof(vbucket_state_t)];
1272} protocol_binary_request_set_vbucket;
1273/**
1274 * Definition of the packet returned from set vbucket
1275 */
1276typedef protocol_binary_response_no_extras protocol_binary_response_set_vbucket;
1277/**
1278 * Definition of the packet used by del vbucket
1279 */
1280typedef protocol_binary_request_no_extras protocol_binary_request_del_vbucket;
1281/**
1282 * Definition of the packet returned from del vbucket
1283 */
1284typedef protocol_binary_response_no_extras protocol_binary_response_del_vbucket;
1285
1286/**
1287 * Definition of the packet used by get vbucket
1288 */
1289typedef protocol_binary_request_no_extras protocol_binary_request_get_vbucket;
1290
1291/**
1292 * Definition of the packet returned from get vbucket
1293 */
1294typedef union {
1295    struct {
1296        protocol_binary_response_header header;
1297        struct {
1298            vbucket_state_t state;
1299        } body;
1300    } message;
1301    uint8_t bytes[sizeof(protocol_binary_response_header) +
1302                  sizeof(vbucket_state_t)];
1303} protocol_binary_response_get_vbucket;
1304
1305/**
1306 * The HELLO command is used by the client and the server to agree
1307 * upon the set of features the other end supports. It is initiated
1308 * by the client by sending its agent string and the list of features
1309 * it would like to use. The server will then reply with the list
1310 * of the requested features it supports.
1311 *
1312 * ex:
1313 * Client ->  HELLO [myclient 2.0] datatype, tls
1314 * Server ->  HELLO SUCCESS datatype
1315 *
1316 * In this example the server responds that it allows the client to
1317 * use the datatype extension, but not the tls extension.
1318 */
1319
1320/**
1321 * Definition of the packet requested by hello cmd.
1322 * Key: This is a client-specific identifier (not really used by
1323 *      the server, except for logging the HELLO and may therefore
1324 *      be used to identify the client at a later time)
1325 * Body: Contains all features supported by client. Each feature is
1326 *       specified as an uint16_t in network byte order.
1327 */
1328typedef protocol_binary_request_no_extras protocol_binary_request_hello;
1329
1330/**
1331 * Definition of the packet returned by hello cmd.
1332 * Body: Contains all features requested by the client that the
1333 *       server agrees to ssupport. Each feature is
1334 *       specified as an uint16_t in network byte order.
1335 */
1336typedef protocol_binary_response_no_extras protocol_binary_response_hello;
1337
1338/**
1339 * The SET_CTRL_TOKEN command will be used by ns_server and ns_server alone
1340 * to set the session cas token in memcached which will be used to
1341 * recognize the particular instance on ns_server. The previous token will
1342 * be passed in the cas section of the request header for the CAS operation,
1343 * and the new token will be part of ext (8B).
1344 *
1345 * The response to this request will include the cas as it were set,
1346 * and a SUCCESS as status, or a KEY_EEXISTS with the existing token in
1347 * memcached if the CAS operation were to fail.
1348 */
1349
1350/**
1351 * Definition of the request packet for SET_CTRL_TOKEN.
1352 * Body: new session_cas_token of uint64_t type.
1353 */
1354typedef union {
1355    struct {
1356        protocol_binary_request_header header;
1357        struct {
1358            uint64_t new_cas;
1359        } body;
1360    } message;
1361    uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
1362} protocol_binary_request_set_ctrl_token;
1363
1364/**
1365 * Definition of the response packet for SET_CTRL_TOKEN
1366 */
1367typedef protocol_binary_response_no_extras
1368        protocol_binary_response_set_ctrl_token;
1369
1370/**
1371 * The GET_CTRL_TOKEN command will be used by ns_server to fetch the current
1372 * session cas token held in memcached.
1373 *
1374 * The response to this request will include the token currently held in
1375 * memcached in the cas field of the header.
1376 */
1377
1378/**
1379 * Definition of the request packet for GET_CTRL_TOKEN.
1380 */
1381typedef protocol_binary_request_no_extras
1382        protocol_binary_request_get_ctrl_token;
1383
1384/**
1385 * Definition of the response packet for GET_CTRL_TOKEN
1386 */
1387typedef protocol_binary_response_no_extras
1388        protocol_binary_response_get_ctrl_token;
1389
1390/* DCP related stuff */
1391typedef union {
1392    struct {
1393        protocol_binary_request_header header;
1394        struct {
1395            uint32_t seqno;
1396/*
1397 * The following flags are defined
1398 */
1399#define DCP_OPEN_PRODUCER 1
1400#define DCP_OPEN_NOTIFIER 2
1401
1402/**
1403 * Indicate that the server include the documents' XATTRs
1404 * within mutation and deletion bodies.
1405 */
1406#define DCP_OPEN_INCLUDE_XATTRS 4
1407
1408/**
1409 * Indicate that the server should strip off the values (note,
1410 * if you add INCLUDE_XATTR those will be present)
1411 */
1412#define DCP_OPEN_NO_VALUE 8
1413
1414/**
1415 * Indicate that the server should send collection data
1416 * and this request can also optionally include a collection
1417 * filter in the body (no filter = all data)
1418 */
1419#define DCP_OPEN_COLLECTIONS 16
1420
1421/**
1422 * Request that DCP delete message include the time the a delete was persisted.
1423 * This only applies to deletes being backfilled from storage, in-memory deletes
1424 * will have a delete time of 0
1425 */
1426#define DCP_OPEN_INCLUDE_DELETE_TIMES 32
1427
1428/**
1429 * Indicates that the server should strip off the values, but return the
1430 * datatype of the underlying document (note, if you add
1431 * INCLUDE_XATTR those will be present).
1432 * Note this differs from DCP_OPEN_NO_VALUE in that the datatype field will
1433 * contain the underlying datatype of the document; not the datatype of the
1434 * transmitted payload.
1435 * This flag can be used to obtain the full, original datatype for a document
1436 * without the user's value.
1437 * Not valid to specify with DCP_OPEN_NO_VALUE.
1438 */
1439#define DCP_OPEN_NO_VALUE_WITH_UNDERLYING_DATATYPE 64
1440
1441            uint32_t flags;
1442        } body;
1443    } message;
1444    uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
1445} protocol_binary_request_dcp_open;
1446
1447typedef protocol_binary_response_no_extras protocol_binary_response_dcp_open;
1448
1449typedef union {
1450    struct {
1451        protocol_binary_request_header header;
1452        struct {
1453/*
1454 * The following flags are defined
1455 */
1456#define DCP_ADD_STREAM_FLAG_TAKEOVER 1
1457#define DCP_ADD_STREAM_FLAG_DISKONLY 2
1458#define DCP_ADD_STREAM_FLAG_LATEST 4
1459/**
1460 * This flag is not used anymore, and should NOT be
1461 * set. It is replaced by DCP_OPEN_NO_VALUE.
1462 */
1463#define DCP_ADD_STREAM_FLAG_NO_VALUE 8
1464/**
1465 * Indicate the server to add stream only if the vbucket
1466 * is active.
1467 * If the vbucket is not active, the stream request fails with
1468 * error ENGINE_NOT_MY_VBUCKET
1469 */
1470#define DCP_ADD_STREAM_ACTIVE_VB_ONLY 16
1471/**
1472 * Indicate the server to check for vb_uuid match even at start_seqno 0 before
1473 * adding the stream successfully.
1474 * If the flag is set and there is a vb_uuid mismatch at start_seqno 0, then
1475 * the server returns ENGINE_ROLLBACK error.
1476 */
1477#define DCP_ADD_STREAM_STRICT_VBUUID 32
1478            uint32_t flags;
1479        } body;
1480    } message;
1481    uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
1482} protocol_binary_request_dcp_add_stream;
1483
1484typedef union {
1485    struct {
1486        protocol_binary_response_header header;
1487        struct {
1488            uint32_t opaque;
1489        } body;
1490    } message;
1491    uint8_t bytes[sizeof(protocol_binary_response_header) + 4];
1492} protocol_binary_response_dcp_add_stream;
1493
1494typedef protocol_binary_request_no_extras
1495        protocol_binary_request_dcp_close_stream;
1496typedef protocol_binary_response_no_extras
1497        protocol_binary_response_dcp_close_stream;
1498
1499typedef union {
1500    struct {
1501        protocol_binary_request_header header;
1502        struct {
1503            uint32_t flags;
1504            uint32_t reserved;
1505            uint64_t start_seqno;
1506            uint64_t end_seqno;
1507            uint64_t vbucket_uuid;
1508            uint64_t snap_start_seqno;
1509            uint64_t snap_end_seqno;
1510        } body;
1511        /* Group ID is specified in the key */
1512    } message;
1513    uint8_t bytes[sizeof(protocol_binary_request_header) + 48];
1514} protocol_binary_request_dcp_stream_req;
1515
1516typedef union {
1517    struct {
1518        protocol_binary_response_header header;
1519    } message;
1520    /*
1521    ** In case of PROTOCOL_BINARY_RESPONSE_ROLLBACK the body contains
1522    ** the rollback sequence number (uint64_t)
1523    */
1524    uint8_t bytes[sizeof(protocol_binary_request_header)];
1525} protocol_binary_response_dcp_stream_req;
1526
1527typedef protocol_binary_request_no_extras
1528        protocol_binary_request_dcp_get_failover_log;
1529
1530/* The body of the message contains UUID/SEQNO pairs */
1531typedef protocol_binary_response_no_extras
1532        protocol_binary_response_dcp_get_failover_log;
1533
1534typedef union {
1535    struct {
1536        protocol_binary_request_header header;
1537        struct {
1538            /**
1539             * All flags set to 0 == OK,
1540             * 1: state changed
1541             */
1542            uint32_t flags;
1543        } body;
1544    } message;
1545    uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
1546} protocol_binary_request_dcp_stream_end;
1547typedef protocol_binary_response_no_extras
1548        protocol_binary_response_dcp_stream_end;
1549
1550typedef union {
1551    struct {
1552        protocol_binary_request_header header;
1553        struct {
1554            uint64_t start_seqno;
1555            uint64_t end_seqno;
1556            uint32_t flags;
1557        } body;
1558    } message;
1559    uint8_t bytes[sizeof(protocol_binary_request_header) + 20];
1560} protocol_binary_request_dcp_snapshot_marker;
1561
1562typedef protocol_binary_response_no_extras
1563        protocol_binary_response_dcp_snapshot_marker;
1564
1565union protocol_binary_request_dcp_mutation {
1566    protocol_binary_request_dcp_mutation(bool collectionsAware,
1567                                         uint32_t opaque,
1568                                         uint16_t vbucket,
1569                                         uint64_t cas,
1570                                         uint16_t keyLen,
1571                                         uint32_t valueLen,
1572                                         protocol_binary_datatype_t datatype,
1573                                         uint64_t bySeqno,
1574                                         uint64_t revSeqno,
1575                                         uint32_t flags,
1576                                         uint32_t expiration,
1577                                         uint32_t lockTime,
1578                                         uint16_t nmeta,
1579                                         uint8_t nru,
1580                                         uint8_t collectionLen) {
1581        auto& req = message.header.request;
1582        req.magic = (uint8_t)PROTOCOL_BINARY_REQ;
1583        req.opcode = (uint8_t)PROTOCOL_BINARY_CMD_DCP_MUTATION;
1584        req.opaque = opaque;
1585        req.vbucket = htons(vbucket);
1586        req.cas = htonll(cas);
1587        req.keylen = htons(keyLen);
1588        req.extlen = gsl::narrow<uint8_t>(getExtrasLength(collectionsAware));
1589        req.bodylen = ntohl(req.extlen + keyLen + nmeta + valueLen);
1590        req.datatype = datatype;
1591
1592        auto& body = message.body;
1593        body.by_seqno = htonll(bySeqno);
1594        body.rev_seqno = htonll(revSeqno);
1595        body.flags = flags;
1596        body.expiration = htonl(expiration);
1597        body.lock_time = htonl(lockTime);
1598        body.nmeta = htons(nmeta);
1599        body.nru = nru;
1600        body.collection_len = collectionLen;
1601    }
1602
1603    struct {
1604        protocol_binary_request_header header;
1605        struct {
1606            uint64_t by_seqno;
1607            uint64_t rev_seqno;
1608            uint32_t flags;
1609            uint32_t expiration;
1610            uint32_t lock_time;
1611            uint16_t nmeta;
1612            uint8_t nru;
1613            uint8_t collection_len;
1614        } body;
1615    } message;
1616    uint8_t bytes[sizeof(protocol_binary_request_header) + 32];
1617
1618    static uint8_t getExtrasLength(bool collectionAware) {
1619        if (collectionAware) {
1620            return (2 * sizeof(uint64_t)) + (3 * sizeof(uint32_t)) +
1621                   sizeof(uint16_t) + (2 * sizeof(uint8_t));
1622        } else {
1623            return (2 * sizeof(uint64_t)) + (3 * sizeof(uint32_t)) +
1624                   sizeof(uint16_t) + sizeof(uint8_t);
1625        }
1626    }
1627
1628    static size_t getHeaderLength(bool collectionAware) {
1629        return sizeof(protocol_binary_request_header) +
1630               getExtrasLength(collectionAware);
1631    }
1632};
1633
1634union protocol_binary_request_dcp_deletion {
1635    static constexpr size_t extlen = 18;
1636    protocol_binary_request_dcp_deletion(uint32_t opaque,
1637                                         uint16_t vbucket,
1638                                         uint64_t cas,
1639                                         uint16_t keyLen,
1640                                         uint32_t valueLen,
1641                                         protocol_binary_datatype_t datatype,
1642                                         uint64_t bySeqno,
1643                                         uint64_t revSeqno,
1644                                         uint16_t nmeta) {
1645        auto& req = message.header.request;
1646        req.magic = (uint8_t)PROTOCOL_BINARY_REQ;
1647        req.opcode = (uint8_t)PROTOCOL_BINARY_CMD_DCP_DELETION;
1648        req.opaque = opaque;
1649        req.vbucket = htons(vbucket);
1650        req.cas = htonll(cas);
1651        req.keylen = htons(keyLen);
1652        req.extlen = extlen;
1653        req.bodylen = ntohl(req.extlen + keyLen + nmeta + valueLen);
1654        req.datatype = datatype;
1655
1656        auto& body = message.body;
1657        body.by_seqno = htonll(bySeqno);
1658        body.rev_seqno = htonll(revSeqno);
1659        body.nmeta = htons(nmeta);
1660    }
1661    struct {
1662        protocol_binary_request_header header;
1663        struct {
1664            uint64_t by_seqno;
1665            uint64_t rev_seqno;
1666            uint16_t nmeta;
1667        } body;
1668    } message;
1669    uint8_t bytes[sizeof(protocol_binary_request_header) + extlen];
1670};
1671
1672union protocol_binary_request_dcp_deletion_v2 {
1673    static constexpr size_t extlen = 21;
1674    protocol_binary_request_dcp_deletion_v2(uint32_t opaque,
1675                                            uint16_t vbucket,
1676                                            uint64_t cas,
1677                                            uint16_t keyLen,
1678                                            uint32_t valueLen,
1679                                            protocol_binary_datatype_t datatype,
1680                                            uint64_t bySeqno,
1681                                            uint64_t revSeqno,
1682                                            uint32_t deleteTime,
1683                                            uint8_t collectionLen) {
1684        auto& req = message.header.request;
1685        req.magic = (uint8_t)PROTOCOL_BINARY_REQ;
1686        req.opcode = (uint8_t)PROTOCOL_BINARY_CMD_DCP_DELETION;
1687        req.opaque = opaque;
1688        req.vbucket = htons(vbucket);
1689        req.cas = htonll(cas);
1690        req.keylen = htons(keyLen);
1691        req.extlen = extlen;
1692        req.bodylen = ntohl(req.extlen + keyLen + valueLen);
1693        req.datatype = datatype;
1694
1695        auto& body = message.body;
1696        body.by_seqno = htonll(bySeqno);
1697        body.rev_seqno = htonll(revSeqno);
1698        body.delete_time = htonl(deleteTime);
1699        body.collection_len = collectionLen;
1700    }
1701
1702    struct {
1703        protocol_binary_request_header header;
1704        struct {
1705            uint64_t by_seqno;
1706            uint64_t rev_seqno;
1707            uint32_t delete_time;
1708            uint8_t collection_len;
1709        } body;
1710    } message;
1711    uint8_t bytes[sizeof(protocol_binary_request_header) + extlen];
1712};
1713
1714union protocol_binary_request_dcp_expiration {
1715    protocol_binary_request_dcp_expiration(bool collectionsAware,
1716                                           uint32_t opaque,
1717                                           uint16_t vbucket,
1718                                           uint64_t cas,
1719                                           uint16_t keyLen,
1720                                           uint32_t valueLen,
1721                                           protocol_binary_datatype_t datatype,
1722                                           uint64_t bySeqno,
1723                                           uint64_t revSeqno,
1724                                           uint16_t nmeta,
1725                                           uint8_t collectionLen) {
1726        auto& req = message.header.request;
1727        req.magic = (uint8_t)PROTOCOL_BINARY_REQ;
1728        req.opcode = (uint8_t)PROTOCOL_BINARY_CMD_DCP_EXPIRATION;
1729        req.opaque = opaque;
1730        req.vbucket = htons(vbucket);
1731        req.cas = htonll(cas);
1732        req.keylen = htons(keyLen);
1733        req.extlen = gsl::narrow<uint8_t>(getExtrasLength(collectionsAware));
1734        req.bodylen = ntohl(req.extlen + keyLen + nmeta + valueLen);
1735        req.datatype = datatype;
1736
1737        auto& body = message.body;
1738        body.by_seqno = htonll(bySeqno);
1739        body.rev_seqno = htonll(revSeqno);
1740        body.nmeta = htons(nmeta);
1741        body.collection_len = collectionLen;
1742    }
1743
1744    struct {
1745        protocol_binary_request_header header;
1746        struct {
1747            uint64_t by_seqno;
1748            uint64_t rev_seqno;
1749            uint16_t nmeta;
1750            uint8_t collection_len;
1751        } body;
1752    } message;
1753    uint8_t bytes[sizeof(protocol_binary_request_header) + 19];
1754
1755    static size_t getExtrasLength(bool collectionsAware) {
1756        if (collectionsAware) {
1757            return (2 * sizeof(uint64_t)) + sizeof(uint16_t) +
1758                   (1 * sizeof(uint8_t));
1759        } else {
1760            return (2 * sizeof(uint64_t)) + sizeof(uint16_t);
1761        }
1762    }
1763
1764    /**
1765     * Retrieve the size of a DCP expiration header - all the non variable
1766     * data of the packet. The size of a collectionAware DCP stream expiration
1767     * differs to that of legacy DCP streams.
1768     */
1769    static size_t getHeaderLength(bool collectionsAware) {
1770        return sizeof(protocol_binary_request_header) +
1771               getExtrasLength(collectionsAware);
1772    }
1773};
1774
1775typedef protocol_binary_request_no_extras protocol_binary_request_dcp_flush;
1776
1777typedef union {
1778    struct {
1779        protocol_binary_request_header header;
1780        struct {
1781            /**
1782             * 0x01 - Active
1783             * 0x02 - Replica
1784             * 0x03 - Pending
1785             * 0x04 - Dead
1786             */
1787            uint8_t state;
1788        } body;
1789    } message;
1790    uint8_t bytes[sizeof(protocol_binary_request_header) + 1];
1791} protocol_binary_request_dcp_set_vbucket_state;
1792typedef protocol_binary_response_no_extras
1793        protocol_binary_response_dcp_set_vbucket_state;
1794
1795typedef protocol_binary_request_no_extras protocol_binary_request_dcp_noop;
1796typedef protocol_binary_response_no_extras protocol_binary_response_dcp_noop;
1797
1798typedef union {
1799    struct {
1800        protocol_binary_request_header header;
1801        struct {
1802            uint32_t buffer_bytes;
1803        } body;
1804    } message;
1805    uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
1806} protocol_binary_request_dcp_buffer_acknowledgement;
1807typedef protocol_binary_response_no_extras
1808        protocol_binary_response_dcp_buffer_acknowledgement;
1809
1810typedef protocol_binary_request_no_extras protocol_binary_request_dcp_control;
1811typedef protocol_binary_response_no_extras protocol_binary_response_dcp_control;
1812
1813/**
1814 * Events that the system may send
1815 */
1816namespace mcbp {
1817namespace systemevent {
1818
1819enum class id : uint32_t {
1820    CreateCollection = 0,
1821    DeleteCollection = 1,
1822    CollectionsSeparatorChanged = 2
1823};
1824
1825/**
1826 * Validate that the uint32_t represents a valid systemevent::id
1827 */
1828static inline bool validate(uint32_t event) {
1829    switch (id(event)) {
1830        case id::CreateCollection:
1831        case id::DeleteCollection:
1832        case id::CollectionsSeparatorChanged:
1833            return true;
1834    }
1835    return false;
1836}
1837
1838}
1839}
1840
1841/**
1842 * Format for a DCP_SYSTEM_EVENT packet. Encodes a sequence number for the
1843 * event and the event's identifier.
1844 */
1845union protocol_binary_request_dcp_system_event {
1846    protocol_binary_request_dcp_system_event(uint32_t opaque,
1847                                             uint16_t vbucket,
1848                                             uint16_t keyLen,
1849                                             size_t valueLen,
1850                                             mcbp::systemevent::id event,
1851                                             uint64_t bySeqno) {
1852        auto& req = message.header.request;
1853        req.magic = (uint8_t)PROTOCOL_BINARY_REQ;
1854        req.opcode = (uint8_t)PROTOCOL_BINARY_CMD_DCP_SYSTEM_EVENT;
1855        req.opaque = opaque;
1856        req.vbucket = htons(vbucket);
1857        req.keylen = htons(keyLen);
1858        req.extlen = getExtrasLength();
1859        req.bodylen =
1860                htonl(gsl::narrow<uint32_t>(req.extlen + valueLen + keyLen));
1861        req.datatype = PROTOCOL_BINARY_RAW_BYTES;
1862        message.body.event = htonl(uint32_t(event));
1863        message.body.by_seqno = htonll(bySeqno);
1864    }
1865    struct {
1866        protocol_binary_request_header header;
1867        struct {
1868            uint64_t by_seqno;
1869            uint32_t event;
1870        } body;
1871    } message;
1872    uint8_t bytes[sizeof(protocol_binary_request_header) + 12];
1873
1874    /**
1875     * @returns the extlen value that a system_event packet should encode.
1876     */
1877    static inline uint8_t getExtrasLength() {
1878        return sizeof(uint64_t) + sizeof(uint32_t);
1879    }
1880};
1881
1882/**
1883 * IOCTL_GET command message to get/set control parameters.
1884 */
1885typedef protocol_binary_request_no_extras protocol_binary_request_ioctl_get;
1886typedef protocol_binary_request_no_extras protocol_binary_request_ioctl_set;
1887
1888typedef protocol_binary_request_no_extras
1889        protocol_binary_request_config_validate;
1890typedef protocol_binary_request_no_extras protocol_binary_request_config_reload;
1891
1892typedef protocol_binary_request_no_extras protocol_binary_request_ssl_refresh;
1893typedef protocol_binary_response_no_extras protocol_binary_response_ssl_refresh;
1894
1895/**
1896 * Request command timings for a bucket from memcached. Privileged
1897 * connections may specify the name of the bucket in the "key" field,
1898 * or the aggregated timings for the entire server by using the
1899 * special name <code>/all/</code>.
1900 *
1901 * The returned payload is a json document of the following format:
1902 *    { "us" : [ x, x, x, x, ... ],
1903 *      "ms" : [ y, y, y, ...],
1904 *      "500ms" : [ z, z, z, ...],
1905 *      "wayout" : nnn
1906 *    }
1907 */
1908typedef union {
1909    struct {
1910        protocol_binary_request_header header;
1911        struct {
1912            uint8_t opcode;
1913        } body;
1914    } message;
1915    uint8_t bytes[sizeof(protocol_binary_request_header) + 1];
1916} protocol_binary_request_get_cmd_timer;
1917
1918typedef protocol_binary_response_no_extras
1919        protocol_binary_response_get_cmd_timer;
1920
1921typedef protocol_binary_request_no_extras protocol_binary_request_create_bucket;
1922typedef protocol_binary_request_no_extras protocol_binary_request_delete_bucket;
1923typedef protocol_binary_request_no_extras protocol_binary_request_list_buckets;
1924typedef protocol_binary_request_no_extras protocol_binary_request_select_bucket;
1925
1926/*
1927 * Parameter types of CMD_SET_PARAM command.
1928 */
1929typedef enum : int {
1930    protocol_binary_engine_param_flush = 1, /* flusher-related param type */
1931    protocol_binary_engine_param_replication, /* replication param type */
1932    protocol_binary_engine_param_checkpoint, /* checkpoint-related param type */
1933    protocol_binary_engine_param_dcp, /* dcp param type */
1934    protocol_binary_engine_param_vbucket /* vbucket param type */
1935} protocol_binary_engine_param_t;
1936
1937/**
1938 * CMD_SET_PARAM command message to set engine parameters.
1939 * flush, tap, checkpoint, dcp and vbucket parameter types are currently
1940 * supported.
1941 */
1942typedef union {
1943    struct {
1944        protocol_binary_request_header header;
1945        struct {
1946            protocol_binary_engine_param_t param_type;
1947        } body;
1948    } message;
1949    uint8_t bytes[sizeof(protocol_binary_request_header) +
1950                  sizeof(protocol_binary_engine_param_t)];
1951} protocol_binary_request_set_param;
1952
1953typedef union {
1954    struct {
1955        protocol_binary_request_header header;
1956        struct {
1957            uint32_t size;
1958        } body;
1959    } message;
1960    uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
1961} protocol_binary_request_set_batch_count;
1962
1963/**
1964 * This flag is used by the setWithMeta/addWithMeta/deleteWithMeta packets
1965 * to specify that the operation should be forced. The update will not
1966 * be subject to conflict resolution and the target vb can be active/pending or
1967 * replica.
1968 */
1969#define FORCE_WITH_META_OP 0x01
1970
1971/**
1972 * This flag is used to indicate that the *_with_meta should be accepted
1973 * regardless of the bucket config. LWW buckets require this flag.
1974 */
1975#define FORCE_ACCEPT_WITH_META_OPS 0x02
1976
1977/**
1978 * This flag asks that the server regenerates the CAS. The server requires
1979 * that SKIP_CONFLICT_RESOLUTION_FLAG is set along with this option.
1980 */
1981#define REGENERATE_CAS 0x04
1982
1983/**
1984 * This flag is used by the setWithMeta/addWithMeta/deleteWithMeta packets
1985 * to specify that the conflict resolution mechanism should be skipped for
1986 * this operation.
1987 */
1988#define SKIP_CONFLICT_RESOLUTION_FLAG 0x08
1989
1990#define SET_RET_META 1
1991#define ADD_RET_META 2
1992#define DEL_RET_META 3
1993
1994/**
1995 * This flag is used with the get meta response packet. If set it
1996 * specifies that the item recieved has been deleted, but that the
1997 * items meta data is still contained in ep-engine. Eg. the item
1998 * has been soft deleted.
1999 */
2000#define GET_META_ITEM_DELETED_FLAG 0x01
2001
2002/**
2003 * The physical layout for the CMD_SET_WITH_META looks like the the normal
2004 * set request with the addition of a bulk of extra meta data stored
2005 * at the <b>end</b> of the package.
2006 */
2007typedef union {
2008    struct {
2009        protocol_binary_request_header header;
2010        struct {
2011            uint32_t flags;
2012            uint32_t expiration;
2013            uint64_t seqno;
2014            uint64_t cas;
2015        } body;
2016    } message;
2017    uint8_t bytes[sizeof(protocol_binary_request_header) + 24];
2018} protocol_binary_request_set_with_meta;
2019
2020typedef union {
2021    struct {
2022        protocol_binary_request_header header;
2023        struct {
2024            uint32_t flags;
2025            uint32_t delete_time;
2026            uint64_t seqno;
2027            uint64_t cas;
2028        } body;
2029    } message;
2030    uint8_t bytes[sizeof(protocol_binary_request_header) + 24];
2031} protocol_binary_request_delete_with_meta;
2032
2033/**
2034 * The message format for getLocked engine API
2035 */
2036typedef protocol_binary_request_gat protocol_binary_request_getl;
2037
2038/**
2039 * The physical layout for a CMD_GET_META command returns the meta-data
2040 * section for an item:
2041 */
2042typedef protocol_binary_request_no_extras protocol_binary_request_get_meta;
2043
2044/**
2045 * Structure holding getMeta command response fields
2046 */
2047#pragma pack(1)
2048
2049struct GetMetaResponse {
2050    uint32_t deleted;
2051    uint32_t flags;
2052    uint32_t expiry;
2053    uint64_t seqno;
2054    uint8_t datatype;
2055
2056    GetMetaResponse() : deleted(0), flags(0), expiry(0), seqno(0), datatype(0) {
2057    }
2058
2059    GetMetaResponse(uint32_t deleted,
2060                    uint32_t flags,
2061                    uint32_t expiry,
2062                    uint64_t seqno,
2063                    uint8_t datatype)
2064        : deleted(deleted),
2065          flags(flags),
2066          expiry(expiry),
2067          seqno(seqno),
2068          datatype(datatype) {
2069    }
2070};
2071
2072#pragma pack()
2073
2074static_assert(sizeof(GetMetaResponse) == 21, "Incorrect compiler padding");
2075
2076/* Meta data versions for GET_META */
2077enum class GetMetaVersion : uint8_t {
2078    V1 = 1, // returns deleted, flags, expiry and seqno
2079    V2 = 2, // The 'spock' version returns V1 + the datatype
2080};
2081
2082/**
2083 * The response for CMD_SET_WITH_META does not carry any user-data and the
2084 * status of the operation is signalled in the status bits.
2085 */
2086typedef protocol_binary_response_no_extras
2087        protocol_binary_response_set_with_meta;
2088
2089typedef union {
2090    struct {
2091        protocol_binary_request_header header;
2092        struct {
2093            uint64_t file_version;
2094            uint64_t header_offset;
2095            uint32_t vbucket_state_updated;
2096            uint32_t state;
2097            uint64_t checkpoint;
2098        } body;
2099    } message;
2100    uint8_t bytes[sizeof(protocol_binary_request_header) + 32];
2101} protocol_binary_request_notify_vbucket_update;
2102typedef protocol_binary_response_no_extras
2103        protocol_binary_response_notify_vbucket_update;
2104
2105/**
2106 * The physical layout for the CMD_RETURN_META
2107 */
2108typedef union {
2109    struct {
2110        protocol_binary_request_header header;
2111        struct {
2112            uint32_t mutation_type;
2113            uint32_t flags;
2114            uint32_t expiration;
2115        } body;
2116    } message;
2117    uint8_t bytes[sizeof(protocol_binary_request_header) + 12];
2118} protocol_binary_request_return_meta;
2119
2120/**
2121 * Message format for CMD_SET_CONFIG
2122 */
2123typedef protocol_binary_request_no_extras
2124        protocol_binary_request_set_cluster_config;
2125
2126/**
2127 * Message format for CMD_GET_CONFIG
2128 */
2129typedef protocol_binary_request_no_extras
2130        protocol_binary_request_get_cluster_config;
2131
2132/**
2133 * Message format for CMD_GET_ADJUSTED_TIME
2134 *
2135 * The PROTOCOL_BINARY_CMD_GET_ADJUSTED_TIME command will be
2136 * used by XDCR to retrieve the vbucket's latest adjusted_time
2137 * which is calculated based on the driftCounter if timeSync
2138 * has been enabled.
2139 *
2140 * Request:-
2141 *
2142 * Header: Contains a vbucket id.
2143 *
2144 * Response:-
2145 *
2146 * The response will contain the adjusted_time (type: int64_t)
2147 * as part of the body if in case of a SUCCESS, or else a NOTSUP
2148 * in case of timeSync not being enabled.
2149 *
2150 * The request packet's header will contain the vbucket_id.
2151 */
2152typedef protocol_binary_request_no_extras
2153        protocol_binary_request_get_adjusted_time;
2154
2155/**
2156 * Message format for CMD_SET_DRIFT_COUNTER_STATE
2157 *
2158 * The PROTOCOL_BINARY_CMD_SET_DRIFT_COUNTER_STATE command will be
2159 * used by GO-XDCR to set the initial drift counter and enable/disable
2160 * the time synchronization for the vbucket.
2161 *
2162 * Request:-
2163 *
2164 * Header: Contains a vbucket id.
2165 * Extras: Contains the initial drift value which is of type int64_t and
2166 * the time sync state (0x00 for disable, 0x01 for enable),
2167 *
2168 * Response:-
2169 *
2170 * The response will return a SUCCESS after saving the settings, the
2171 * body will contain the vbucket uuid (type: uint64_t) and the vbucket
2172 * high seqno (type: int64_t).
2173 * A NOT_MY_VBUCKET (along with cluster config) is returned if the
2174 * vbucket isn't found.
2175 */
2176typedef union {
2177    struct {
2178        protocol_binary_request_header header;
2179        struct {
2180            int64_t initial_drift;
2181            uint8_t time_sync;
2182        } body;
2183    } message;
2184    uint8_t bytes[sizeof(protocol_binary_request_header) + 9];
2185} protocol_binary_request_set_drift_counter_state;
2186
2187/**
2188 * Message format for CMD_COMPACT_DB
2189 *
2190 * The PROTOCOL_BINARY_CMD_COMPACT_DB is used by ns_server to
2191 * issue a compaction request to ep-engine to compact the
2192 * underlying store's database files
2193 *
2194 * Request:
2195 *
2196 * Header: Contains the vbucket id. The vbucket id will be used
2197 *         to identify the database file if the backend is
2198 *         couchstore. If the vbucket id is set to 0xFFFF, then
2199 *         the db_file_id field will be used for compaction.
2200 * Body:
2201 * - purge_before_ts:  Deleted items whose expiry timestamp is less
2202 *                     than purge_before_ts will be purged.
2203 * - purge_before_seq: Deleted items whose sequence number is less
2204 *                     than purge_before_seq will be purged.
2205 * - drop_deletes:     whether to purge deleted items or not.
2206 * - db_file_id  :     Database file id for the underlying store.
2207 *
2208 * Response:
2209 *
2210 * The response will return a SUCCESS after compaction is done
2211 * successfully and a NOT_MY_VBUCKET (along with cluster config)
2212 * if the vbucket isn't found.
2213 */
2214typedef union {
2215    struct {
2216        protocol_binary_request_header header;
2217        struct {
2218            uint64_t purge_before_ts;
2219            uint64_t purge_before_seq;
2220            uint8_t drop_deletes;
2221            uint8_t align_pad1;
2222            uint16_t db_file_id;
2223            uint32_t align_pad3;
2224        } body;
2225    } message;
2226    uint8_t bytes[sizeof(protocol_binary_request_header) + 24];
2227} protocol_binary_request_compact_db;
2228
2229typedef protocol_binary_request_get protocol_binary_request_get_random;
2230
2231#define OBS_STATE_NOT_PERSISTED 0x00
2232#define OBS_STATE_PERSISTED 0x01
2233#define OBS_STATE_NOT_FOUND 0x80
2234#define OBS_STATE_LOGICAL_DEL 0x81
2235
2236/**
2237 * The physical layout for the PROTOCOL_BINARY_CMD_AUDIT_PUT
2238 */
2239typedef union {
2240    struct {
2241        protocol_binary_request_header header;
2242        struct {
2243            uint32_t id;
2244        } body;
2245    } message;
2246    uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
2247} protocol_binary_request_audit_put;
2248
2249typedef protocol_binary_response_no_extras protocol_binary_response_audit_put;
2250
2251/**
2252 * The shutdown message is sent from ns_server to memcached to tell
2253 * memcached to initiate a clean shutdown. This is a privileged
2254 * command and carries no payload, but the CAS field needs to be
2255 * set to the current session token (see GET/SET_CTRL_TOKEN)
2256 */
2257typedef protocol_binary_request_no_extras protocol_binary_request_shutdown;
2258typedef protocol_binary_response_no_extras protocol_binary_response_shutdown;
2259
2260/**
2261 * The rbac_refresh message is sent from ns_server to memcached to tell
2262 * memcached to reload the RBAC configuration file. This is a privileged
2263 * command and carries no payload.
2264 */
2265typedef protocol_binary_request_no_extras protocol_binary_request_rbac_refresh;
2266typedef protocol_binary_response_no_extras
2267        protocol_binary_response_rbac_refresh;
2268
2269/**
2270 * The PROTOCOL_BINARY_CMD_OBSERVE_SEQNO command is used by the
2271 * client to retrieve information about the vbucket in order to
2272 * find out if a particular mutation has been persisted or
2273 * replicated at the server side. In order to do so, the client
2274 * would pass the vbucket uuid of the vbucket that it wishes to
2275 * observe to the serve.  The response would contain the last
2276 * persisted sequence number and the latest sequence number in the
2277 * vbucket. For example, if a client sends a request to observe
2278 * the vbucket 0 with uuid 12345 and if the response contains the
2279 * values <58, 65> and then the client can infer that sequence
2280 * number 56 has been persisted, 60 has only been replicated and
2281 * not been persisted yet and 68 has not been replicated yet.
2282 */
2283
2284/**
2285 * Definition of the request packet for the observe_seqno command.
2286 *
2287 * Header: Contains the vbucket id of the vbucket that the client
2288 *         wants to observe.
2289 *
2290 * Body: Contains the vbucket uuid of the vbucket that the client
2291 *       wants to observe. The vbucket uuid is of type uint64_t.
2292 *
2293 */
2294typedef union {
2295    struct {
2296        protocol_binary_request_header header;
2297        struct {
2298            uint64_t uuid;
2299        } body;
2300    } message;
2301    uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
2302} protocol_binary_request_observe_seqno;
2303
2304/**
2305 * Definition of the response packet for the observe_seqno command.
2306 * Body: Contains a tuple of the form
2307 *       <format_type, vbucket id, vbucket uuid, last_persisted_seqno,
2308 * current_seqno>
2309 *
2310 *       - format_type is of type uint8_t and it describes whether
2311 *         the vbucket has failed over or not. 1 indicates a hard
2312 *         failover, 0 indicates otherwise.
2313 *       - vbucket id is of type uint16_t and it is the identifier for
2314 *         the vbucket.
2315 *       - vbucket uuid is of type uint64_t and it represents a UUID for
2316 *          the vbucket.
2317 *       - last_persisted_seqno is of type uint64_t and it is the
2318 *         last sequence number that was persisted for this
2319 *         vbucket.
2320 *       - current_seqno is of the type uint64_t and it is the
2321 *         sequence number of the latest mutation in the vbucket.
2322 *
2323 *       In the case of a hard failover, the tuple is of the form
2324 *       <format_type, vbucket id, vbucket uuid, last_persisted_seqno,
2325 * current_seqno, old vbucket uuid, last_received_seqno>
2326 *
2327 *       - old vbucket uuid is of type uint64_t and it is the
2328 *         vbucket UUID of the vbucket prior to the hard failover.
2329 *
2330 *       - last_received_seqno is of type uint64_t and it is the
2331 *         last received sequence number in the old vbucket uuid.
2332 *
2333 *       The other fields are the same as that mentioned in the normal case.
2334 */
2335typedef protocol_binary_response_no_extras
2336        protocol_binary_response_observe_seqno;
2337
2338/**
2339 * Definition of the request packet for the command
2340 * PROTOCOL_BINARY_CMD_GET_ALL_VB_SEQNOS
2341 *
2342 * Header: Only opcode field is used.
2343 *
2344 * Body: Contains the vbucket state for which the vb sequence numbers are
2345 *       requested.
2346 *       Please note that this field is optional, header.request.extlen is
2347 *       checked to see if it is present. If not present, it implies request
2348 *       is for all vbucket states.
2349 */
2350typedef union {
2351    struct {
2352        protocol_binary_request_header header;
2353        struct {
2354            vbucket_state_t state;
2355        } body;
2356    } message;
2357    uint8_t bytes[sizeof(protocol_binary_request_header) +
2358                  sizeof(vbucket_state_t)];
2359} protocol_binary_request_get_all_vb_seqnos;
2360
2361/**
2362 * Definition of the payload in the PROTOCOL_BINARY_CMD_GET_ALL_VB_SEQNOS
2363 * response.
2364 *
2365 * The body contains a "list" of "vbucket id - seqno pairs" for all
2366 * active and replica buckets on the node in network byte order.
2367 *
2368 *
2369 *    Byte/     0       |       1       |       2       |       3       |
2370 *       /              |               |               |               |
2371 *      |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
2372 *      +---------------+---------------+---------------+---------------+
2373 *     0| VBID          | VBID          | SEQNO         | SEQNO         |
2374 *      +---------------+---------------+---------------+---------------+
2375 *     4| SEQNO         | SEQNO         | SEQNO         | SEQNO         |
2376 *      +---------------+---------------+---------------+---------------+
2377 *     4| SEQNO         | SEQNO         |
2378 *      +---------------+---------------+
2379 */
2380typedef protocol_binary_response_no_extras
2381        protocol_binary_response_get_all_vb_seqnos;
2382
2383/**
2384 * Message format for PROTOCOL_BINARY_CMD_GET_KEYS
2385 *
2386 * The extras field may contain a 32 bit integer specifying the number
2387 * of keys to fetch. If no value specified 1000 keys is transmitted.
2388 *
2389 * Key is mandatory and specifies the starting key
2390 *
2391 * Get keys is used to fetch a sequence of keys from the server starting
2392 * at the specified key.
2393 */
2394typedef protocol_binary_request_no_extras protocol_binary_request_get_keys;
2395
2396
2397enum class TimeType : uint8_t {
2398    TimeOfDay,
2399    Uptime
2400};
2401/**
2402 * Definition of the packet used to adjust timeofday and memcached uptime
2403 */
2404typedef union {
2405    struct {
2406        protocol_binary_request_header header;
2407        struct {
2408            uint64_t offset;
2409            TimeType timeType;
2410        } body;
2411    } message;
2412    uint8_t bytes[sizeof(protocol_binary_request_header) + sizeof(uint64_t) + sizeof(TimeType)];
2413} protocol_binary_adjust_time;
2414
2415/**
2416 * Definition of the packet returned by adjust_timeofday
2417 */
2418typedef protocol_binary_response_no_extras protocol_binary_adjust_time_response;
2419
2420/**
2421 * Message format for PROTOCOL_BINARY_CMD_EWOULDBLOCK_CTL
2422 *
2423 * See engines/ewouldblock_engine for more information.
2424 */
2425typedef union {
2426    struct {
2427        protocol_binary_request_header header;
2428        struct {
2429            uint32_t mode; // See EWB_Engine_Mode
2430            uint32_t value;
2431            uint32_t inject_error; // ENGINE_ERROR_CODE to inject.
2432        } body;
2433    } message;
2434    uint8_t bytes[sizeof(protocol_binary_request_header) + sizeof(uint32_t) +
2435                  sizeof(uint32_t) + sizeof(uint32_t)];
2436} protocol_binary_request_ewb_ctl;
2437typedef protocol_binary_response_no_extras protocol_binary_response_ewb_ctl;
2438
2439/**
2440 * Message format for PROTOCOL_BINARY_CMD_GET_ERRORMAP
2441 *
2442 * The payload (*not* specified as extras) contains a 2 byte payload
2443 * containing a 16 bit encoded version number. This version number should
2444 * indicate the highest version number of the error map the client is able
2445 * to understand. The server will return a JSON-formatted error map
2446 * which is formatted to either the version requested by the client, or
2447 * a lower version (thus, clients must be ready to parse lower version
2448 * formats).
2449 */
2450typedef union {
2451    struct {
2452        protocol_binary_request_header header;
2453        struct {
2454            uint16_t version;
2455        } body;
2456    } message;
2457    uint8_t bytes[sizeof(protocol_binary_request_header) + 2];
2458} protocol_binary_request_get_errmap;
2459
2460typedef protocol_binary_response_no_extras protocol_binary_response_get_errmap;
2461
2462/**
2463 * Message format for PROTOCOL_BINARY_CMD_COLLECTIONS_SET_MANIFEST
2464 *
2465 * The body contains a JSON collections manifest.
2466 * No key and no extras
2467 */
2468typedef union {
2469    struct {
2470        protocol_binary_request_header header;
2471    } message;
2472    uint8_t bytes[sizeof(protocol_binary_request_header)];
2473} protocol_binary_collections_set_manifest;
2474
2475typedef protocol_binary_response_no_extras
2476        protocol_binary_response_collections_set_manifest;
2477
2478/**
2479 * @}
2480 */
2481inline protocol_binary_subdoc_flag operator|(protocol_binary_subdoc_flag a,
2482                                             protocol_binary_subdoc_flag b) {
2483    return protocol_binary_subdoc_flag(static_cast<uint8_t>(a) |
2484                                       static_cast<uint8_t>(b));
2485}
2486
2487namespace mcbp {
2488namespace subdoc {
2489inline mcbp::subdoc::doc_flag operator|(mcbp::subdoc::doc_flag a,
2490                                        mcbp::subdoc::doc_flag b) {
2491    return mcbp::subdoc::doc_flag(static_cast<uint8_t>(a) |
2492                                  static_cast<uint8_t>(b));
2493}
2494
2495inline mcbp::subdoc::doc_flag operator&(mcbp::subdoc::doc_flag a,
2496                                        mcbp::subdoc::doc_flag b) {
2497    return mcbp::subdoc::doc_flag(static_cast<uint8_t>(a) &
2498                                  static_cast<uint8_t>(b));
2499}
2500
2501inline mcbp::subdoc::doc_flag operator~(mcbp::subdoc::doc_flag a) {
2502    return mcbp::subdoc::doc_flag(~static_cast<uint8_t>(a));
2503}
2504
2505inline std::string to_string(mcbp::subdoc::doc_flag a) {
2506    switch (a) {
2507    case mcbp::subdoc::doc_flag::None:
2508        return "None";
2509    case mcbp::subdoc::doc_flag::Mkdoc:
2510        return "Mkdoc";
2511    case mcbp::subdoc::doc_flag::AccessDeleted:
2512        return "AccessDeleted";
2513    case mcbp::subdoc::doc_flag::Add:
2514        return "Add";
2515    }
2516    return std::to_string(static_cast<uint8_t>(a));
2517}
2518
2519inline bool hasAccessDeleted(mcbp::subdoc::doc_flag a) {
2520    return (a & mcbp::subdoc::doc_flag::AccessDeleted) !=
2521           mcbp::subdoc::doc_flag::None;
2522}
2523
2524inline bool hasMkdoc(mcbp::subdoc::doc_flag a) {
2525    return (a & mcbp::subdoc::doc_flag::Mkdoc) != mcbp::subdoc::doc_flag::None;
2526}
2527
2528inline bool hasAdd(mcbp::subdoc::doc_flag a) {
2529    return (a & mcbp::subdoc::doc_flag::Add) != mcbp::subdoc::doc_flag::None;
2530}
2531
2532inline bool isNone(mcbp::subdoc::doc_flag a) {
2533    return a == mcbp::subdoc::doc_flag::None;
2534}
2535inline bool impliesMkdir_p(mcbp::subdoc::doc_flag a) {
2536    return hasAdd(a) || hasMkdoc(a);
2537}
2538} // namespace subdoc
2539} // namespace mcbp
2540
2541// Create a namespace to handle the Datatypes
2542namespace mcbp {
2543namespace datatype {
2544const uint8_t highest = PROTOCOL_BINARY_DATATYPE_XATTR |
2545                        PROTOCOL_BINARY_DATATYPE_SNAPPY |
2546                        PROTOCOL_BINARY_DATATYPE_JSON;
2547inline bool is_raw(const protocol_binary_datatype_t datatype) {
2548    return datatype == PROTOCOL_BINARY_RAW_BYTES;
2549}
2550
2551inline bool is_json(const protocol_binary_datatype_t datatype) {
2552    return (datatype & PROTOCOL_BINARY_DATATYPE_JSON) ==
2553           PROTOCOL_BINARY_DATATYPE_JSON;
2554}
2555
2556inline bool is_snappy(const protocol_binary_datatype_t datatype) {
2557    return (datatype & PROTOCOL_BINARY_DATATYPE_SNAPPY) ==
2558           PROTOCOL_BINARY_DATATYPE_SNAPPY;
2559}
2560
2561inline bool is_xattr(const protocol_binary_datatype_t datatype) {
2562    return (datatype & PROTOCOL_BINARY_DATATYPE_XATTR) ==
2563           PROTOCOL_BINARY_DATATYPE_XATTR;
2564}
2565
2566inline bool is_valid(const protocol_binary_datatype_t datatype) {
2567    return datatype <= highest;
2568}
2569
2570inline std::string to_string(const protocol_binary_datatype_t datatype) {
2571    if (is_valid(datatype)) {
2572        if (is_raw(datatype)) {
2573            return std::string{"raw"};
2574        } else {
2575            std::stringstream ss;
2576            if (is_snappy(datatype)) {
2577                ss << "snappy,";
2578            }
2579            if (is_json(datatype)) {
2580                ss << "json,";
2581            }
2582            if (is_xattr(datatype)) {
2583                ss << "xattr,";
2584            }
2585
2586            // remove the last ','
2587            std::string ret = ss.str();
2588            ret.resize(ret.size() - 1);
2589            return ret;
2590        }
2591    } else {
2592        return std::string{"invalid"};
2593    }
2594}
2595} // namespace datatype
2596} // namespace mcbp
2597
2598namespace mcbp {
2599
2600namespace cas {
2601/**
2602 * The special value used as a wildcard and match all CAS values
2603 */
2604const uint64_t Wildcard = 0x0;
2605} // namespace cas
2606} // namespace mcbp
2607