1 /*
2  *     Copyright 2019 Couchbase, Inc.
3  *
4  *   Licensed under the Apache License, Version 2.0 (the "License");
5  *   you may not use this file except in compliance with the License.
6  *   You may obtain a copy of the License at
7  *
8  *       http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *   Unless required by applicable law or agreed to in writing, software
11  *   distributed under the License is distributed on an "AS IS" BASIS,
12  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *   See the License for the specific language governing permissions and
14  *   limitations under the License.
15  */
16 
17 #include "frameinfo.h"
18 
19 #include <gsl.h>
20 #include <mcbp/protocol/request.h>
21 
22 FrameInfo::~FrameInfo() = default;
23 BarrierFrameInfo::~BarrierFrameInfo() = default;
24 DurabilityFrameInfo::~DurabilityFrameInfo() = default;
25 DcpStreamIdFrameInfo::~DcpStreamIdFrameInfo() = default;
26 OpenTracingContextFrameInfo::~OpenTracingContextFrameInfo() = default;
27 
28 using cb::mcbp::request::FrameInfoId;
29 
encode() const30 std::vector<uint8_t> BarrierFrameInfo::encode() const {
31     std::vector<uint8_t> ret;
32     ret.push_back(uint8_t(FrameInfoId::Barrier) << 0x04U);
33     return ret;
34 }
35 
encode() const36 std::vector<uint8_t> DurabilityFrameInfo::encode() const {
37     using cb::durability::Level;
38     using cb::durability::Timeout;
39 
40     if (level == Level::None) {
41         return {};
42     }
43 
44     std::vector<uint8_t> ret(2);
45     ret[0] = uint8_t(FrameInfoId::DurabilityRequirement) << 0x04U;
46     ret[1] = (uint8_t(0x0f) & uint8_t(level));
47 
48     if (timeout.isDefault()) {
49         // Level is the only byte
50         ret[0] |= uint8_t(0x01);
51     } else {
52         // Level and timeout is present
53         ret[0] |= uint8_t(0x03);
54         auto value = htons(timeout.get());
55         const auto* ptr = reinterpret_cast<const char*>(&value);
56         ret.insert(ret.end(), ptr, ptr + sizeof(value));
57     }
58 
59     return ret;
60 }
61 
encode() const62 std::vector<uint8_t> DcpStreamIdFrameInfo::encode() const {
63     std::vector<uint8_t> ret(1);
64     ret[0] = uint8_t(FrameInfoId::DcpStreamId) << 0x04U;
65     ret[0] |= sizeof(id);
66     auto value = htons(id);
67     const auto* ptr = reinterpret_cast<const char*>(&value);
68     ret.insert(ret.end(), ptr, ptr + sizeof(value));
69 
70     return ret;
71 }
72 
encode() const73 std::vector<uint8_t> OpenTracingContextFrameInfo::encode() const {
74     std::vector<uint8_t> ret(1);
75     ret[0] = uint8_t(FrameInfoId::OpenTracingContext) << 0x04U;
76     if (ctx.size() < 0x0fU) {
77         // We may fit in a single byte
78         ret[0] |= uint8_t(ctx.size());
79     } else {
80         // we need an extra length byte to set the length
81         ret[0] |= 0x0fU;
82         ret.push_back(gsl::narrow<uint8_t>(ctx.size()));
83     }
84     ret.insert(ret.end(), ctx.cbegin(), ctx.cend());
85 
86     return ret;
87 }
88