1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "protocol_core.h"
6
7 #include <algorithm>
8 #include <cassert>
9 #include <string>
10
11 namespace v8_crdtp {
12
DeserializerState(std::vector<uint8_t> bytes)13 DeserializerState::DeserializerState(std::vector<uint8_t> bytes)
14 : storage_(new std::vector<uint8_t>(std::move(bytes))),
15 tokenizer_(span<uint8_t>(storage_->data(), storage_->size())) {}
16
DeserializerState(Storage storage,span<uint8_t> span)17 DeserializerState::DeserializerState(Storage storage, span<uint8_t> span)
18 : storage_(std::move(storage)), tokenizer_(span) {}
19
RegisterError(Error error)20 void DeserializerState::RegisterError(Error error) {
21 assert(Error::OK != error);
22 if (tokenizer_.Status().ok())
23 status_ = Status{error, tokenizer_.Status().pos};
24 }
25
RegisterFieldPath(span<char> name)26 void DeserializerState::RegisterFieldPath(span<char> name) {
27 field_path_.push_back(name);
28 }
29
ErrorMessage(span<char> message_name) const30 std::string DeserializerState::ErrorMessage(span<char> message_name) const {
31 std::string msg = "Failed to deserialize ";
32 msg.append(message_name.begin(), message_name.end());
33 for (int field = static_cast<int>(field_path_.size()) - 1; field >= 0;
34 --field) {
35 msg.append(".");
36 msg.append(field_path_[field].begin(), field_path_[field].end());
37 }
38 Status s = status();
39 if (!s.ok())
40 msg += " - " + s.ToASCIIString();
41 return msg;
42 }
43
status() const44 Status DeserializerState::status() const {
45 if (!tokenizer_.Status().ok())
46 return tokenizer_.Status();
47 return status_;
48 }
49
50 namespace {
GetMandatoryFieldMask(const DeserializerDescriptor::Field * fields,size_t count)51 constexpr int32_t GetMandatoryFieldMask(
52 const DeserializerDescriptor::Field* fields,
53 size_t count) {
54 int32_t mask = 0;
55 for (size_t i = 0; i < count; ++i) {
56 if (!fields[i].is_optional)
57 mask |= (1 << i);
58 }
59 return mask;
60 }
61 } // namespace
62
DeserializerDescriptor(const Field * fields,size_t field_count)63 DeserializerDescriptor::DeserializerDescriptor(const Field* fields,
64 size_t field_count)
65 : fields_(fields),
66 field_count_(field_count),
67 mandatory_field_mask_(GetMandatoryFieldMask(fields, field_count)) {}
68
Deserialize(DeserializerState * state,void * obj) const69 bool DeserializerDescriptor::Deserialize(DeserializerState* state,
70 void* obj) const {
71 auto* tokenizer = state->tokenizer();
72
73 // As a special compatibility quirk, allow empty objects if
74 // no mandatory fields are required.
75 if (tokenizer->TokenTag() == cbor::CBORTokenTag::DONE &&
76 !mandatory_field_mask_) {
77 return true;
78 }
79 if (tokenizer->TokenTag() == cbor::CBORTokenTag::ENVELOPE)
80 tokenizer->EnterEnvelope();
81 if (tokenizer->TokenTag() != cbor::CBORTokenTag::MAP_START) {
82 state->RegisterError(Error::CBOR_MAP_START_EXPECTED);
83 return false;
84 }
85 tokenizer->Next();
86 int32_t seen_mandatory_fields = 0;
87 for (; tokenizer->TokenTag() != cbor::CBORTokenTag::STOP; tokenizer->Next()) {
88 if (tokenizer->TokenTag() != cbor::CBORTokenTag::STRING8) {
89 state->RegisterError(Error::CBOR_INVALID_MAP_KEY);
90 return false;
91 }
92 span<uint8_t> u_key = tokenizer->GetString8();
93 span<char> key(reinterpret_cast<const char*>(u_key.data()), u_key.size());
94 tokenizer->Next();
95 if (!DeserializeField(state, key, &seen_mandatory_fields, obj))
96 return false;
97 }
98 // Only compute mandatory fields once per type.
99 int32_t missing_fields = seen_mandatory_fields ^ mandatory_field_mask_;
100 if (missing_fields) {
101 int32_t idx = 0;
102 while ((missing_fields & 1) == 0) {
103 missing_fields >>= 1;
104 ++idx;
105 }
106 state->RegisterError(Error::BINDINGS_MANDATORY_FIELD_MISSING);
107 state->RegisterFieldPath(fields_[idx].name);
108 return false;
109 }
110 return true;
111 }
112
DeserializeField(DeserializerState * state,span<char> name,int * seen_mandatory_fields,void * obj) const113 bool DeserializerDescriptor::DeserializeField(DeserializerState* state,
114 span<char> name,
115 int* seen_mandatory_fields,
116 void* obj) const {
117 // TODO(caseq): consider checking if the sought field is the one
118 // after the last deserialized.
119 const auto* begin = fields_;
120 const auto* end = fields_ + field_count_;
121 auto entry = std::lower_bound(
122 begin, end, name, [](const Field& field_desc, span<char> field_name) {
123 return SpanLessThan(field_desc.name, field_name);
124 });
125 // Unknown field is not an error -- we may be working against an
126 // implementation of a later version of the protocol.
127 // TODO(caseq): support unknown arrays and maps not enclosed by an envelope.
128 if (entry == end || !SpanEquals(entry->name, name))
129 return true;
130 if (!entry->deserializer(state, obj)) {
131 state->RegisterFieldPath(name);
132 return false;
133 }
134 if (!entry->is_optional)
135 *seen_mandatory_fields |= 1 << (entry - begin);
136 return true;
137 }
138
Deserialize(DeserializerState * state,bool * value)139 bool ProtocolTypeTraits<bool>::Deserialize(DeserializerState* state,
140 bool* value) {
141 const auto tag = state->tokenizer()->TokenTag();
142 if (tag == cbor::CBORTokenTag::TRUE_VALUE) {
143 *value = true;
144 return true;
145 }
146 if (tag == cbor::CBORTokenTag::FALSE_VALUE) {
147 *value = false;
148 return true;
149 }
150 state->RegisterError(Error::BINDINGS_BOOL_VALUE_EXPECTED);
151 return false;
152 }
153
Serialize(bool value,std::vector<uint8_t> * bytes)154 void ProtocolTypeTraits<bool>::Serialize(bool value,
155 std::vector<uint8_t>* bytes) {
156 bytes->push_back(value ? cbor::EncodeTrue() : cbor::EncodeFalse());
157 }
158
Deserialize(DeserializerState * state,int32_t * value)159 bool ProtocolTypeTraits<int32_t>::Deserialize(DeserializerState* state,
160 int32_t* value) {
161 if (state->tokenizer()->TokenTag() != cbor::CBORTokenTag::INT32) {
162 state->RegisterError(Error::BINDINGS_INT32_VALUE_EXPECTED);
163 return false;
164 }
165 *value = state->tokenizer()->GetInt32();
166 return true;
167 }
168
Serialize(int32_t value,std::vector<uint8_t> * bytes)169 void ProtocolTypeTraits<int32_t>::Serialize(int32_t value,
170 std::vector<uint8_t>* bytes) {
171 cbor::EncodeInt32(value, bytes);
172 }
173
ContainerSerializer(std::vector<uint8_t> * bytes,uint8_t tag)174 ContainerSerializer::ContainerSerializer(std::vector<uint8_t>* bytes,
175 uint8_t tag)
176 : bytes_(bytes) {
177 envelope_.EncodeStart(bytes_);
178 bytes_->push_back(tag);
179 }
180
EncodeStop()181 void ContainerSerializer::EncodeStop() {
182 bytes_->push_back(cbor::EncodeStop());
183 envelope_.EncodeStop(bytes_);
184 }
185
ObjectSerializer()186 ObjectSerializer::ObjectSerializer()
187 : serializer_(&owned_bytes_, cbor::EncodeIndefiniteLengthMapStart()) {}
188
189 ObjectSerializer::~ObjectSerializer() = default;
190
Finish()191 std::unique_ptr<Serializable> ObjectSerializer::Finish() {
192 serializer_.EncodeStop();
193 return Serializable::From(std::move(owned_bytes_));
194 }
195
Deserialize(DeserializerState * state,double * value)196 bool ProtocolTypeTraits<double>::Deserialize(DeserializerState* state,
197 double* value) {
198 // Double values that round-trip through JSON may end up getting represented
199 // as an int32 (SIGNED, UNSIGNED) on the wire in CBOR. Therefore, we also
200 // accept an INT32 here.
201 if (state->tokenizer()->TokenTag() == cbor::CBORTokenTag::INT32) {
202 *value = state->tokenizer()->GetInt32();
203 return true;
204 }
205 if (state->tokenizer()->TokenTag() != cbor::CBORTokenTag::DOUBLE) {
206 state->RegisterError(Error::BINDINGS_DOUBLE_VALUE_EXPECTED);
207 return false;
208 }
209 *value = state->tokenizer()->GetDouble();
210 return true;
211 }
212
Serialize(double value,std::vector<uint8_t> * bytes)213 void ProtocolTypeTraits<double>::Serialize(double value,
214 std::vector<uint8_t>* bytes) {
215 cbor::EncodeDouble(value, bytes);
216 }
217
218 class IncomingDeferredMessage : public DeferredMessage {
219 public:
220 // Creates the state from the part of another message.
221 // Note storage is opaque and is mostly to retain ownership.
222 // It may be null in case caller owns the memory and will dispose
223 // of the message synchronously.
IncomingDeferredMessage(DeserializerState::Storage storage,span<uint8_t> span)224 IncomingDeferredMessage(DeserializerState::Storage storage,
225 span<uint8_t> span)
226 : storage_(storage), span_(span) {}
227
228 private:
MakeDeserializer() const229 DeserializerState MakeDeserializer() const override {
230 return DeserializerState(storage_, span_);
231 }
AppendSerialized(std::vector<uint8_t> * out) const232 void AppendSerialized(std::vector<uint8_t>* out) const override {
233 out->insert(out->end(), span_.begin(), span_.end());
234 }
235
236 DeserializerState::Storage storage_;
237 span<uint8_t> span_;
238 };
239
240 class OutgoingDeferredMessage : public DeferredMessage {
241 public:
242 OutgoingDeferredMessage() = default;
OutgoingDeferredMessage(std::unique_ptr<Serializable> serializable)243 explicit OutgoingDeferredMessage(std::unique_ptr<Serializable> serializable)
244 : serializable_(std::move(serializable)) {
245 assert(!!serializable_);
246 }
247
248 private:
MakeDeserializer() const249 DeserializerState MakeDeserializer() const override {
250 return DeserializerState(serializable_->Serialize());
251 }
AppendSerialized(std::vector<uint8_t> * out) const252 void AppendSerialized(std::vector<uint8_t>* out) const override {
253 serializable_->AppendSerialized(out);
254 }
255
256 std::unique_ptr<Serializable> serializable_;
257 };
258
259 // static
FromSerializable(std::unique_ptr<Serializable> serializeable)260 std::unique_ptr<DeferredMessage> DeferredMessage::FromSerializable(
261 std::unique_ptr<Serializable> serializeable) {
262 return std::make_unique<OutgoingDeferredMessage>(std::move(serializeable));
263 }
264
265 // static
FromSpan(span<uint8_t> bytes)266 std::unique_ptr<DeferredMessage> DeferredMessage::FromSpan(
267 span<uint8_t> bytes) {
268 return std::make_unique<IncomingDeferredMessage>(nullptr, bytes);
269 }
270
Deserialize(DeserializerState * state,std::unique_ptr<DeferredMessage> * value)271 bool ProtocolTypeTraits<std::unique_ptr<DeferredMessage>>::Deserialize(
272 DeserializerState* state,
273 std::unique_ptr<DeferredMessage>* value) {
274 if (state->tokenizer()->TokenTag() != cbor::CBORTokenTag::ENVELOPE) {
275 state->RegisterError(Error::CBOR_INVALID_ENVELOPE);
276 return false;
277 }
278 *value = std::make_unique<IncomingDeferredMessage>(
279 state->storage(), state->tokenizer()->GetEnvelope());
280 return true;
281 }
282
Serialize(const std::unique_ptr<DeferredMessage> & value,std::vector<uint8_t> * bytes)283 void ProtocolTypeTraits<std::unique_ptr<DeferredMessage>>::Serialize(
284 const std::unique_ptr<DeferredMessage>& value,
285 std::vector<uint8_t>* bytes) {
286 value->AppendSerialized(bytes);
287 }
288
289 } // namespace v8_crdtp
290