1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * Copyright 2016 Couchbase, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 #pragma once 18 #include "client_connection.h" 19 #include <boost/optional/optional_fwd.hpp> 20 #include <mcbp/protocol/header.h> 21 #include <mcbp/protocol/response.h> 22 #include <memcached/durability_spec.h> 23 #include <nlohmann/json.hpp> 24 #include <platform/sized_buffer.h> 25 #include <unordered_set> 26 27 class FrameInfo; 28 29 /** 30 * This is the base class used for binary protocol commands. You probably 31 * want to use one of the subclasses. Do not subclass this class directly, 32 * rather, instantiate/derive from BinprotCommandT or BinprotGenericCommand 33 */ 34 class BinprotCommand { 35 public: 36 BinprotCommand() = default; 37 38 virtual ~BinprotCommand() = default; 39 40 cb::mcbp::ClientOpcode getOp() const; 41 42 const std::string& getKey() const; 43 44 uint64_t getCas() const; 45 46 virtual void clear(); 47 48 BinprotCommand& setKey(std::string key_); 49 50 BinprotCommand& setCas(uint64_t cas_); 51 52 BinprotCommand& setOp(cb::mcbp::ClientOpcode cmd_); 53 54 BinprotCommand& setVBucket(Vbid vbid); 55 56 BinprotCommand& setOpaque(uint32_t opaq); 57 58 /// Add a frame info object to the stream 59 BinprotCommand& addFrameInfo(const FrameInfo& fi); 60 61 /// Add something you want to put into the frame info section of the 62 /// packet (in the case you want to create illegal frame encodings 63 /// to make sure that the server handle them correctly) 64 BinprotCommand& addFrameInfo(cb::const_byte_buffer section); 65 66 /** 67 * Encode the command to a buffer. 68 * @param buf The buffer 69 * @note the buffer's contents are _not_ reset, and the encoded command 70 * is simply appended to it. 71 * 72 * The default implementation is to encode the standard header fields. 73 * The key itself is not added to the buffer. 74 */ 75 virtual void encode(std::vector<uint8_t>& buf) const; 76 77 struct Encoded { 78 /** 79 * 'scratch' space for data which isn't owned by anything and is 80 * generated on demand. Any data here is sent before the data in the 81 * buffers. 82 */ 83 std::vector<uint8_t> header; 84 85 /** The actual buffers to be sent */ 86 std::vector<cb::const_byte_buffer> bufs; 87 }; 88 89 /** 90 * Encode data into an 'Encoded' object. 91 * @return an `Encoded` object which may be sent on the wire. 92 * 93 * Note that unlike the vector<uint8_t> variant, the actual buffers 94 * are not copied into the new structure, so ensure the command object 95 * (which owns the buffers), or the original buffers (if the command object 96 * doesn't own the buffers either; see e.g. 97 * BinprotMutationCommand::setValueBuffers()) remain in tact between this 98 * call and actually sending it. 99 * 100 * The default implementation simply copies what encode(vector<uint8_t>) 101 * does into Encoded::header, and Encoded::bufs contains a single 102 * element. 103 */ 104 virtual Encoded encode() const; 105 protected: 106 /** 107 * This class exposes a tri-state expiry object, to allow for a 0-value 108 * expiry. This is not used directly by this class, but is used a bit in 109 * subclasses 110 */ 111 class ExpiryValue { 112 public: 113 void assign(uint32_t value_); 114 void clear(); 115 bool isSet() const; 116 uint32_t getValue() const; 117 118 private: 119 bool set = false; 120 uint32_t value = 0; 121 }; 122 123 /** 124 * Writes the header to the buffer 125 * @param buf Buffer to write to 126 * @param payload_len Payload length (excluding keylen and extlen) 127 * @param extlen Length of extras 128 */ 129 void writeHeader(std::vector<uint8_t>& buf, 130 size_t payload_len = 0, 131 size_t extlen = 0) const; 132 133 cb::mcbp::ClientOpcode opcode = cb::mcbp::ClientOpcode::Invalid; 134 std::string key; 135 uint64_t cas = 0; 136 Vbid vbucket = Vbid(0); 137 uint32_t opaque{0xdeadbeef}; 138 139 /// The frame info sections to inject into the packet 140 std::vector<uint8_t> frame_info; 141 142 private: 143 /** 144 * Fills the header with the current fields. 145 * 146 * @param[out] header header to write to 147 * @param payload_len length of the "value" of the payload 148 * @param extlen extras length. 149 */ 150 void fillHeader(cb::mcbp::Request& header, 151 size_t payload_len = 0, 152 size_t extlen = 0) const; 153 }; 154 155 /** 156 * For use with subclasses of @class MemcachedCommand. This installs setter 157 * methods which 158 * return the actual class rather than TestCmd. 159 * 160 * @code{.c++} 161 * class SomeCmd : public MemcachedCommandT<SomeCmd> { 162 * // ... 163 * }; 164 * @endcode 165 * 166 * And therefore allows subclasses to be used like so: 167 * 168 * @code{.c++} 169 * MyCommand cmd; 170 * cmd.setKey("foo"). 171 * setExpiry(300). 172 * setCas(0xdeadbeef); 173 * 174 * @endcode 175 */ 176 template <typename T, 177 cb::mcbp::ClientOpcode OpCode = cb::mcbp::ClientOpcode::Invalid> 178 class BinprotCommandT : public BinprotCommand { 179 public: BinprotCommandT()180 BinprotCommandT() { 181 setOp(OpCode); 182 } 183 }; 184 185 /** 186 * Convenience class for constructing ad-hoc commands with no special semantics. 187 * Ideally, you should use another class which provides nicer wrapper functions. 188 */ 189 class BinprotGenericCommand : public BinprotCommandT<BinprotGenericCommand> { 190 public: 191 BinprotGenericCommand(cb::mcbp::ClientOpcode opcode, 192 const std::string& key_, 193 const std::string& value_); 194 BinprotGenericCommand(cb::mcbp::ClientOpcode opcode, 195 const std::string& key_); 196 BinprotGenericCommand(cb::mcbp::ClientOpcode opcode); 197 BinprotGenericCommand(); 198 BinprotGenericCommand& setValue(std::string value_); 199 BinprotGenericCommand& setExtras(const std::vector<uint8_t>& buf); 200 201 // Use for setting a simple value as an extras 202 template <typename T> setExtrasValue(T value)203 BinprotGenericCommand& setExtrasValue(T value) { 204 std::vector<uint8_t> buf; 205 buf.resize(sizeof(T)); 206 memcpy(buf.data(), &value, sizeof(T)); 207 return setExtras(buf); 208 } 209 210 void clear() override; 211 212 void encode(std::vector<uint8_t>& buf) const override; 213 214 protected: 215 std::string value; 216 std::vector<uint8_t> extras; 217 }; 218 219 class BinprotResponse { 220 public: 221 bool isSuccess() const; 222 223 /** Get the opcode for the response */ 224 cb::mcbp::ClientOpcode getOp() const; 225 226 /** Get the status code for the response */ 227 cb::mcbp::Status getStatus() const; 228 229 size_t getExtlen() const; 230 231 /** Get the length of packet (minus the header) */ 232 size_t getBodylen() const; 233 234 size_t getFramingExtraslen() const; 235 236 /** 237 * Get the length of the header. This is a static function as it is 238 * always 24 239 */ 240 static size_t getHeaderLen(); 241 uint64_t getCas() const; 242 protocol_binary_datatype_t getDatatype() const; 243 244 /** 245 * Get a pointer to the key returned in the packet, if a key is present. 246 * Use #getKeyLen() to determine this. 247 */ 248 cb::const_char_buffer getKey() const; 249 250 std::string getKeyString() const; 251 252 /** 253 * Get a pointer to the "data" or "value" part of the response. This is 254 * any payload content _after_ the key and extras (if present 255 */ 256 cb::const_byte_buffer getData() const; 257 258 std::string getDataString() const; 259 260 const cb::mcbp::Response& getResponse() const; 261 262 /** 263 * Retrieve the approximate time spent on the server 264 */ 265 boost::optional<std::chrono::microseconds> getTracingData() const; 266 267 /** 268 * Populate this response from a response 269 * @param srcbuf The buffer containing the response. 270 * 271 * The input parameter here is forced to be an rvalue reference because 272 * we don't want careless copying of potentially large payloads. 273 */ 274 virtual void assign(std::vector<uint8_t>&& srcbuf); 275 276 virtual void clear(); 277 278 virtual ~BinprotResponse() = default; 279 280 protected: 281 const cb::mcbp::Header& getHeader() const; 282 std::vector<uint8_t> payload; 283 }; 284 285 class BinprotSubdocCommand : public BinprotCommandT<BinprotSubdocCommand> { 286 public: 287 BinprotSubdocCommand(); 288 289 explicit BinprotSubdocCommand(cb::mcbp::ClientOpcode cmd_); 290 291 // Old-style constructors. These are all used by testapp_subdoc. 292 BinprotSubdocCommand(cb::mcbp::ClientOpcode cmd_, 293 const std::string& key_, 294 const std::string& path_); 295 296 BinprotSubdocCommand( 297 cb::mcbp::ClientOpcode cmd, 298 const std::string& key, 299 const std::string& path, 300 const std::string& value, 301 protocol_binary_subdoc_flag flags = SUBDOC_FLAG_NONE, 302 mcbp::subdoc::doc_flag docFlags = mcbp::subdoc::doc_flag::None, 303 uint64_t cas = 0); 304 305 BinprotSubdocCommand& setPath(std::string path_); 306 BinprotSubdocCommand& setValue(std::string value_); 307 BinprotSubdocCommand& addPathFlags(protocol_binary_subdoc_flag flags_); 308 BinprotSubdocCommand& addDocFlags(mcbp::subdoc::doc_flag flags_); 309 BinprotSubdocCommand& setExpiry(uint32_t value_); 310 const std::string& getPath() const; 311 const std::string& getValue() const; 312 protocol_binary_subdoc_flag getFlags() const; 313 314 void encode(std::vector<uint8_t>& buf) const override; 315 316 private: 317 std::string path; 318 std::string value; 319 BinprotCommand::ExpiryValue expiry; 320 protocol_binary_subdoc_flag flags = SUBDOC_FLAG_NONE; 321 mcbp::subdoc::doc_flag doc_flags = mcbp::subdoc::doc_flag::None; 322 }; 323 324 class BinprotSubdocResponse : public BinprotResponse { 325 public: 326 const std::string& getValue() const; 327 328 void clear() override; 329 330 void assign(std::vector<uint8_t>&& srcbuf) override; 331 332 bool operator==(const BinprotSubdocResponse& other) const; 333 334 private: 335 std::string value; 336 }; 337 338 class BinprotSubdocMultiMutationCommand 339 : public BinprotCommandT<BinprotSubdocMultiMutationCommand, 340 cb::mcbp::ClientOpcode::SubdocMultiMutation> { 341 public: 342 BinprotSubdocMultiMutationCommand(); 343 344 struct MutationSpecifier { 345 cb::mcbp::ClientOpcode opcode; 346 protocol_binary_subdoc_flag flags; 347 std::string path; 348 std::string value; 349 }; 350 351 BinprotSubdocMultiMutationCommand( 352 std::string key, 353 std::vector<MutationSpecifier> specs, 354 mcbp::subdoc::doc_flag docFlags, 355 const boost::optional<cb::durability::Requirements>& durReqs = {}); 356 357 void encode(std::vector<uint8_t>& buf) const override; 358 359 BinprotSubdocMultiMutationCommand& addDocFlag( 360 mcbp::subdoc::doc_flag docFlag); 361 362 BinprotSubdocMultiMutationCommand& addMutation( 363 const MutationSpecifier& spec); 364 365 BinprotSubdocMultiMutationCommand& addMutation( 366 cb::mcbp::ClientOpcode opcode, 367 protocol_binary_subdoc_flag flags, 368 const std::string& path, 369 const std::string& value); 370 371 BinprotSubdocMultiMutationCommand& setExpiry(uint32_t expiry_); 372 373 BinprotSubdocMultiMutationCommand& setDurabilityReqs( 374 const cb::durability::Requirements& durReqs); 375 376 MutationSpecifier& at(size_t index); 377 378 MutationSpecifier& operator[](size_t index); 379 380 bool empty() const; 381 382 size_t size() const; 383 384 void clearMutations(); 385 386 void clearDocFlags(); 387 388 protected: 389 std::vector<MutationSpecifier> specs; 390 ExpiryValue expiry; 391 mcbp::subdoc::doc_flag docFlags; 392 }; 393 394 class BinprotSubdocMultiMutationResponse : public BinprotResponse { 395 public: 396 struct MutationResult { 397 uint8_t index; 398 cb::mcbp::Status status; 399 std::string value; 400 }; 401 402 void assign(std::vector<uint8_t>&& buf) override; 403 404 void clear() override; 405 406 const std::vector<MutationResult>& getResults() const; 407 408 protected: 409 std::vector<MutationResult> results; 410 }; 411 412 class BinprotSubdocMultiLookupCommand 413 : public BinprotCommandT<BinprotSubdocMultiLookupCommand, 414 cb::mcbp::ClientOpcode::SubdocMultiLookup> { 415 public: 416 BinprotSubdocMultiLookupCommand(); 417 418 struct LookupSpecifier { 419 cb::mcbp::ClientOpcode opcode; 420 protocol_binary_subdoc_flag flags; 421 std::string path; 422 }; 423 424 BinprotSubdocMultiLookupCommand(std::string key, 425 std::vector<LookupSpecifier> specs, 426 mcbp::subdoc::doc_flag docFlags); 427 428 void encode(std::vector<uint8_t>& buf) const override; 429 430 BinprotSubdocMultiLookupCommand& addLookup(const LookupSpecifier& spec); 431 432 BinprotSubdocMultiLookupCommand& addLookup( 433 const std::string& path, 434 cb::mcbp::ClientOpcode opcode = cb::mcbp::ClientOpcode::SubdocGet, 435 protocol_binary_subdoc_flag flags = SUBDOC_FLAG_NONE); 436 437 BinprotSubdocMultiLookupCommand& addGet( 438 const std::string& path, 439 protocol_binary_subdoc_flag flags = SUBDOC_FLAG_NONE); 440 BinprotSubdocMultiLookupCommand& addExists( 441 const std::string& path, 442 protocol_binary_subdoc_flag flags = SUBDOC_FLAG_NONE); 443 BinprotSubdocMultiLookupCommand& addGetcount( 444 const std::string& path, 445 protocol_binary_subdoc_flag flags = SUBDOC_FLAG_NONE); 446 BinprotSubdocMultiLookupCommand& addDocFlag(mcbp::subdoc::doc_flag docFlag); 447 448 void clearLookups(); 449 450 LookupSpecifier& at(size_t index); 451 452 LookupSpecifier& operator[](size_t index); 453 454 bool empty() const; 455 456 size_t size() const; 457 458 void clearDocFlags(); 459 460 /** 461 * This is used for testing only! 462 */ 463 BinprotSubdocMultiLookupCommand& setExpiry_Unsupported(uint32_t expiry_); 464 465 protected: 466 std::vector<LookupSpecifier> specs; 467 ExpiryValue expiry; 468 mcbp::subdoc::doc_flag docFlags; 469 }; 470 471 class BinprotSubdocMultiLookupResponse : public BinprotResponse { 472 public: 473 BinprotSubdocMultiLookupResponse() = default; 474 explicit BinprotSubdocMultiLookupResponse(BinprotResponse&& other); 475 476 struct LookupResult { 477 cb::mcbp::Status status; 478 std::string value; 479 }; 480 481 const std::vector<LookupResult>& getResults() const; 482 483 void clear() override; 484 485 void assign(std::vector<uint8_t>&& srcbuf) override; 486 487 protected: 488 void decode(); 489 std::vector<LookupResult> results; 490 }; 491 492 class BinprotSaslAuthCommand 493 : public BinprotCommandT<BinprotSaslAuthCommand, 494 cb::mcbp::ClientOpcode::SaslAuth> { 495 public: 496 void setMechanism(const std::string& mech_); 497 498 void setChallenge(cb::const_char_buffer data); 499 500 void encode(std::vector<uint8_t>&) const override; 501 502 private: 503 std::string challenge; 504 }; 505 506 class BinprotSaslStepCommand 507 : public BinprotCommandT<BinprotSaslStepCommand, 508 cb::mcbp::ClientOpcode::SaslStep> { 509 public: 510 void setMechanism(const std::string& mech); 511 512 void setChallenge(cb::const_char_buffer data); 513 514 void encode(std::vector<uint8_t>&) const override; 515 516 private: 517 std::string challenge; 518 }; 519 520 class BinprotHelloCommand 521 : public BinprotCommandT<BinprotHelloCommand, 522 cb::mcbp::ClientOpcode::Hello> { 523 public: 524 explicit BinprotHelloCommand(const std::string& client_id); 525 BinprotHelloCommand& enableFeature(cb::mcbp::Feature feature, 526 bool enabled = true); 527 528 void encode(std::vector<uint8_t>& buf) const override; 529 530 private: 531 std::unordered_set<uint16_t> features; 532 }; 533 534 class BinprotHelloResponse : public BinprotResponse { 535 public: 536 BinprotHelloResponse() = default; 537 explicit BinprotHelloResponse(BinprotResponse&& other); 538 539 void assign(std::vector<uint8_t>&& buf) override; 540 const std::vector<cb::mcbp::Feature>& getFeatures() const; 541 542 protected: 543 void decode(); 544 std::vector<cb::mcbp::Feature> features; 545 }; 546 547 class BinprotCreateBucketCommand 548 : public BinprotCommandT<BinprotCreateBucketCommand, 549 cb::mcbp::ClientOpcode::CreateBucket> { 550 public: 551 explicit BinprotCreateBucketCommand(const char* name); 552 553 void setConfig(const std::string& module, const std::string& config); 554 void encode(std::vector<uint8_t>& buf) const override; 555 556 private: 557 std::vector<uint8_t> module_config; 558 }; 559 560 class BinprotGetCommand 561 : public BinprotCommandT<BinprotGetCommand, cb::mcbp::ClientOpcode::Get> { 562 public: 563 void encode(std::vector<uint8_t>& buf) const override; 564 }; 565 566 class BinprotGetAndLockCommand 567 : public BinprotCommandT<BinprotGetAndLockCommand, 568 cb::mcbp::ClientOpcode::GetLocked> { 569 public: 570 BinprotGetAndLockCommand(); 571 572 void encode(std::vector<uint8_t>& buf) const override; 573 574 BinprotGetAndLockCommand& setLockTimeout(uint32_t timeout); 575 576 protected: 577 uint32_t lock_timeout; 578 }; 579 580 class BinprotGetAndTouchCommand 581 : public BinprotCommandT<BinprotGetAndTouchCommand, 582 cb::mcbp::ClientOpcode::Gat> { 583 public: 584 explicit BinprotGetAndTouchCommand(std::string key = {}, uint32_t exp = 0); 585 586 void encode(std::vector<uint8_t>& buf) const override; 587 588 bool isQuiet() const; 589 590 BinprotGetAndTouchCommand& setQuiet(bool quiet = true); 591 592 BinprotGetAndTouchCommand& setExpirytime(uint32_t timeout); 593 594 protected: 595 uint32_t expirytime; 596 }; 597 598 class BinprotGetResponse : public BinprotResponse { 599 public: 600 BinprotGetResponse() = default; BinprotGetResponse(BinprotResponse&& other)601 explicit BinprotGetResponse(BinprotResponse&& other) 602 : BinprotResponse(other) { 603 } 604 uint32_t getDocumentFlags() const; 605 }; 606 607 using BinprotGetAndLockResponse = BinprotGetResponse; 608 using BinprotGetAndTouchResponse = BinprotGetResponse; 609 610 class BinprotUnlockCommand 611 : public BinprotCommandT<BinprotGetCommand, 612 cb::mcbp::ClientOpcode::UnlockKey> { 613 public: 614 void encode(std::vector<uint8_t>& buf) const override; 615 }; 616 617 using BinprotUnlockResponse = BinprotResponse; 618 619 class BinprotTouchCommand 620 : public BinprotCommandT<BinprotGetAndTouchCommand, 621 cb::mcbp::ClientOpcode::Touch> { 622 public: 623 explicit BinprotTouchCommand(std::string key = {}, uint32_t exp = 0); 624 void encode(std::vector<uint8_t>& buf) const override; 625 626 BinprotTouchCommand& setExpirytime(uint32_t timeout); 627 628 protected: 629 uint32_t expirytime = 0; 630 }; 631 632 using BinprotTouchResponse = BinprotResponse; 633 634 class BinprotGetCmdTimerCommand 635 : public BinprotCommandT<BinprotGetCmdTimerCommand, 636 cb::mcbp::ClientOpcode::GetCmdTimer> { 637 public: 638 BinprotGetCmdTimerCommand() = default; 639 explicit BinprotGetCmdTimerCommand(cb::mcbp::ClientOpcode opcode); 640 BinprotGetCmdTimerCommand(const std::string& bucket, 641 cb::mcbp::ClientOpcode opcode); 642 643 void encode(std::vector<uint8_t>& buf) const override; 644 645 void setOpcode(cb::mcbp::ClientOpcode opcode); 646 647 void setBucket(const std::string& bucket); 648 649 protected: 650 cb::mcbp::ClientOpcode opcode = cb::mcbp::ClientOpcode::Invalid; 651 }; 652 653 class BinprotGetCmdTimerResponse : public BinprotResponse { 654 public: 655 void assign(std::vector<uint8_t>&& buf) override; 656 657 nlohmann::json getTimings() const; 658 659 private: 660 nlohmann::json timings; 661 }; 662 663 class BinprotVerbosityCommand 664 : public BinprotCommandT<BinprotVerbosityCommand, 665 cb::mcbp::ClientOpcode::Verbosity> { 666 public: 667 void encode(std::vector<uint8_t>& buf) const override; 668 669 void setLevel(int level); 670 671 protected: 672 int level; 673 }; 674 675 using BinprotVerbosityResponse = BinprotResponse; 676 677 using BinprotIsaslRefreshCommand = 678 BinprotCommandT<BinprotGenericCommand, 679 cb::mcbp::ClientOpcode::IsaslRefresh>; 680 681 using BinprotIsaslRefreshResponse = BinprotResponse; 682 683 class BinprotMutationCommand : public BinprotCommandT<BinprotMutationCommand> { 684 public: 685 BinprotMutationCommand& setMutationType(MutationType); 686 BinprotMutationCommand& setDocumentInfo(const DocumentInfo& info); 687 688 BinprotMutationCommand& setValue(std::vector<uint8_t>&& value_); 689 690 template <typename T> 691 BinprotMutationCommand& setValue(const T& value_); 692 693 BinprotMutationCommand& addValueBuffer(cb::const_byte_buffer buf); 694 695 BinprotMutationCommand& setDatatype(uint8_t datatype_); 696 BinprotMutationCommand& setDatatype(cb::mcbp::Datatype datatype_); 697 BinprotMutationCommand& setDocumentFlags(uint32_t flags_); 698 BinprotMutationCommand& setExpiry(uint32_t expiry_); 699 700 void encode(std::vector<uint8_t>& buf) const override; 701 Encoded encode() const override; 702 703 private: 704 void encodeHeader(std::vector<uint8_t>& buf) const; 705 706 /** This contains our copied value (i.e. setValue) */ 707 std::vector<uint8_t> value; 708 /** This contains value references (e.g. addValueBuffer/setValueBuffers) */ 709 std::vector<cb::const_byte_buffer> value_refs; 710 711 BinprotCommand::ExpiryValue expiry; 712 uint32_t flags = 0; 713 uint8_t datatype = 0; 714 }; 715 716 class BinprotMutationResponse : public BinprotResponse { 717 public: 718 BinprotMutationResponse() = default; 719 explicit BinprotMutationResponse(BinprotResponse&& other); 720 721 void assign(std::vector<uint8_t>&& buf) override; 722 723 const MutationInfo& getMutationInfo() const; 724 725 protected: 726 void decode(); 727 MutationInfo mutation_info; 728 }; 729 730 class BinprotIncrDecrCommand : public BinprotCommandT<BinprotIncrDecrCommand> { 731 public: 732 BinprotIncrDecrCommand& setDelta(uint64_t delta_); 733 734 BinprotIncrDecrCommand& setInitialValue(uint64_t initial_); 735 736 BinprotIncrDecrCommand& setExpiry(uint32_t expiry_); 737 738 void encode(std::vector<uint8_t>& buf) const override; 739 740 private: 741 uint64_t delta = 0; 742 uint64_t initial = 0; 743 BinprotCommand::ExpiryValue expiry; 744 }; 745 746 class BinprotIncrDecrResponse : public BinprotMutationResponse { 747 public: 748 BinprotIncrDecrResponse() = default; 749 explicit BinprotIncrDecrResponse(BinprotResponse&& other); 750 uint64_t getValue() const; 751 752 void assign(std::vector<uint8_t>&& buf) override; 753 754 protected: 755 void decode(); 756 uint64_t value = 0; 757 }; 758 759 class BinprotRemoveCommand 760 : public BinprotCommandT<BinprotRemoveCommand, 761 cb::mcbp::ClientOpcode::Delete> { 762 public: 763 void encode(std::vector<uint8_t>& buf) const override; 764 }; 765 766 using BinprotRemoveResponse = BinprotMutationResponse; 767 768 class BinprotGetErrorMapCommand 769 : public BinprotCommandT<BinprotGetErrorMapCommand, 770 cb::mcbp::ClientOpcode::GetErrorMap> { 771 public: 772 void setVersion(uint16_t version_); 773 774 void encode(std::vector<uint8_t>& buf) const override; 775 private: 776 uint16_t version = 0; 777 }; 778 779 using BinprotGetErrorMapResponse = BinprotResponse; 780 781 class BinprotDcpOpenCommand : public BinprotGenericCommand { 782 public: 783 /** 784 * DCP Open 785 * 786 * @param name the name of the DCP stream to create 787 * @param seqno_ the sequence number for the stream 788 * @param flags_ the open flags 789 */ 790 explicit BinprotDcpOpenCommand(const std::string& name, 791 uint32_t seqno_ = 0, 792 uint32_t flags_ = 0); 793 794 void setConsumerName(std::string name); 795 796 /** 797 * Make this a producer stream 798 * 799 * @return this 800 */ 801 BinprotDcpOpenCommand& makeProducer(); 802 803 /** 804 * Make this a consumer stream 805 * 806 * @return this 807 */ 808 BinprotDcpOpenCommand& makeConsumer(); 809 810 /** 811 * Let the stream include xattrs (if any) 812 * 813 * @return this 814 */ 815 BinprotDcpOpenCommand& makeIncludeXattr(); 816 817 /** 818 * Don't add any values into the stream 819 * 820 * @return this 821 */ 822 BinprotDcpOpenCommand& makeNoValue(); 823 824 /** 825 * Set an arbitrary flag value. This may be used in order to test 826 * the sanity checks on the server 827 * 828 * @param flags the raw 32 bit flag section to inject 829 * @return this 830 */ 831 BinprotDcpOpenCommand& setFlags(uint32_t flags); 832 833 void encode(std::vector<uint8_t>& buf) const override; 834 835 private: 836 uint32_t seqno; 837 uint32_t flags; 838 nlohmann::json payload; 839 }; 840 841 class BinprotDcpStreamRequestCommand : public BinprotGenericCommand { 842 public: 843 BinprotDcpStreamRequestCommand(); 844 845 BinprotDcpStreamRequestCommand& setDcpFlags(uint32_t value); 846 847 BinprotDcpStreamRequestCommand& setDcpReserved(uint32_t value); 848 849 BinprotDcpStreamRequestCommand& setDcpStartSeqno(uint64_t value); 850 851 BinprotDcpStreamRequestCommand& setDcpEndSeqno(uint64_t value); 852 853 BinprotDcpStreamRequestCommand& setDcpVbucketUuid(uint64_t value); 854 855 BinprotDcpStreamRequestCommand& setDcpSnapStartSeqno(uint64_t value); 856 857 BinprotDcpStreamRequestCommand& setDcpSnapEndSeqno(uint64_t value); 858 859 void encode(std::vector<uint8_t>& buf) const override; 860 861 private: 862 // The byteorder is fixed when we append the members to the packet 863 uint32_t dcp_flags; 864 uint32_t dcp_reserved; 865 uint64_t dcp_start_seqno; 866 uint64_t dcp_end_seqno; 867 uint64_t dcp_vbucket_uuid; 868 uint64_t dcp_snap_start_seqno; 869 uint64_t dcp_snap_end_seqno; 870 }; 871 872 class BinprotDcpAddStreamCommand : public BinprotGenericCommand { 873 public: 874 explicit BinprotDcpAddStreamCommand(uint32_t flags); 875 void encode(std::vector<uint8_t>& buf) const override; 876 877 protected: 878 uint32_t flags; 879 }; 880 881 class BinprotGetFailoverLogCommand : public BinprotGenericCommand { 882 public: BinprotGetFailoverLogCommand()883 BinprotGetFailoverLogCommand() 884 : BinprotGenericCommand(cb::mcbp::ClientOpcode::GetFailoverLog){}; 885 }; 886 887 class BinprotSetParamCommand 888 : public BinprotGenericCommand { 889 public: 890 BinprotSetParamCommand(cb::mcbp::request::SetParamPayload::Type type_, 891 const std::string& key_, 892 const std::string& value_); 893 894 void encode(std::vector<uint8_t>& buf) const override; 895 896 protected: 897 const cb::mcbp::request::SetParamPayload::Type type; 898 const std::string value; 899 }; 900 901 class BinprotSetWithMetaCommand 902 : public BinprotGenericCommand { 903 public: 904 BinprotSetWithMetaCommand(const Document& doc, 905 Vbid vbucket, 906 uint64_t operationCas, 907 uint64_t seqno, 908 uint32_t options, 909 std::vector<uint8_t>& meta); 910 911 BinprotSetWithMetaCommand& setQuiet(bool quiet); 912 913 uint32_t getFlags() const; 914 915 BinprotSetWithMetaCommand& setFlags(uint32_t flags); 916 917 uint32_t getExptime() const; 918 919 BinprotSetWithMetaCommand& setExptime(uint32_t exptime); 920 921 uint64_t getSeqno() const; 922 923 BinprotSetWithMetaCommand& setSeqno(uint64_t seqno); 924 925 uint64_t getMetaCas() const; 926 927 BinprotSetWithMetaCommand& setMetaCas(uint64_t cas); 928 929 const std::vector<uint8_t>& getMeta(); 930 931 BinprotSetWithMetaCommand& setMeta(const std::vector<uint8_t>& meta); 932 933 void encode(std::vector<uint8_t>& buf) const override; 934 935 protected: 936 Document doc; 937 uint64_t seqno; 938 uint64_t operationCas; 939 uint32_t options; 940 std::vector<uint8_t> meta; 941 }; 942 943 class BinprotDelWithMetaCommand : public BinprotGenericCommand { 944 public: 945 BinprotDelWithMetaCommand(Document doc, 946 Vbid vbucket, 947 uint32_t flags, 948 uint32_t delete_time, 949 uint64_t seqno, 950 uint64_t operationCas, 951 bool quiet = false); 952 953 void encode(std::vector<uint8_t>& buf) const override; 954 955 protected: 956 const Document doc; 957 const uint32_t flags; 958 const uint32_t delete_time; 959 const uint64_t seqno; 960 const uint64_t operationCas; 961 }; 962 963 class BinprotSetControlTokenCommand : public BinprotGenericCommand { 964 public: 965 BinprotSetControlTokenCommand(uint64_t token_, uint64_t oldtoken); 966 967 void encode(std::vector<uint8_t>& buf) const override; 968 969 protected: 970 const uint64_t token; 971 }; 972 973 class BinprotSetClusterConfigCommand : public BinprotGenericCommand { 974 public: 975 BinprotSetClusterConfigCommand(uint64_t token_, 976 std::string config, 977 int revision = -1, 978 const std::string& bucket = {}); 979 980 void encode(std::vector<uint8_t>& buf) const override; 981 982 protected: 983 const std::string config; 984 int revision; 985 }; 986 987 class BinprotObserveSeqnoCommand : public BinprotGenericCommand { 988 public: 989 BinprotObserveSeqnoCommand(Vbid vbid, uint64_t uuid); 990 991 void encode(std::vector<uint8_t>& buf) const override; 992 993 private: 994 uint64_t uuid; 995 }; 996 997 class BinprotObserveSeqnoResponse : public BinprotResponse { 998 public: 999 BinprotObserveSeqnoResponse() = default; 1000 explicit BinprotObserveSeqnoResponse(BinprotResponse&& other); 1001 void assign(std::vector<uint8_t>&& buf) override; 1002 1003 ObserveInfo info; 1004 1005 protected: 1006 void decode(); 1007 }; 1008 1009 class BinprotUpdateUserPermissionsCommand : public BinprotGenericCommand { 1010 public: 1011 BinprotUpdateUserPermissionsCommand(std::string payload); 1012 1013 void encode(std::vector<uint8_t>& buf) const override; 1014 1015 protected: 1016 const std::string payload; 1017 }; 1018 1019 using BinprotAuthProviderCommand = 1020 BinprotCommandT<BinprotGenericCommand, 1021 cb::mcbp::ClientOpcode::AuthProvider>; 1022 1023 using BinprotRbacRefreshCommand = 1024 BinprotCommandT<BinprotGenericCommand, 1025 cb::mcbp::ClientOpcode::RbacRefresh>; 1026 1027 class BinprotAuditPutCommand : public BinprotGenericCommand { 1028 public: 1029 BinprotAuditPutCommand(uint32_t id, std::string payload); 1030 1031 void encode(std::vector<uint8_t>& buf) const override; 1032 1033 protected: 1034 const uint32_t id; 1035 const std::string payload; 1036 }; 1037 1038 class BinprotSetVbucketCommand : public BinprotGenericCommand { 1039 public: 1040 BinprotSetVbucketCommand(Vbid vbid, 1041 vbucket_state_t state, 1042 nlohmann::json payload); 1043 1044 void encode(std::vector<uint8_t>& buf) const override; 1045 1046 protected: 1047 const vbucket_state_t state; 1048 const nlohmann::json payload; 1049 }; 1050