1 /*
2 * Copyright (C) 2014-2019 Savoir-faire Linux Inc.
3 * Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
4 * Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #pragma once
21
22 #include "infohash.h"
23 #include "crypto.h"
24 #include "utils.h"
25 #include "sockaddr.h"
26
27 #include <msgpack.hpp>
28
29 #include <string>
30 #include <sstream>
31 #include <bitset>
32 #include <vector>
33 #include <iostream>
34 #include <algorithm>
35 #include <functional>
36 #include <memory>
37 #include <chrono>
38 #include <set>
39
40 #ifdef OPENDHT_JSONCPP
41 #include <json/json.h>
42 #endif
43
44 namespace dht {
45
46 struct Value;
47 struct Query;
48
49 /**
50 * A storage policy is applied once to every incoming value storage requests.
51 * If the policy returns false, the value is dropped.
52 *
53 * @param key: the key where the storage is requested.
54 * @param value: the value to be stored. The value can be edited by the storage policy.
55 * @param from: id of the requesting node.
56 * @param form_addr: network address of the incoming request.
57 * @param from_len: network address lendth of the incoming request.
58 */
59 using StorePolicy = std::function<bool(InfoHash key, std::shared_ptr<Value>& value, const InfoHash& from, const SockAddr& addr)>;
60
61 /**
62 * An edition policy is applied once to every incoming value storage requests,
63 * if a value already exists for this key and value id.
64 * If the policy returns false, the edition request is ignored.
65 * The default behavior is to deny edition (see {ValueType::DEFAULT_EDIT_POLICY}).
66 * Some {ValueType}s may override this behavior (e.g. SignedValue).
67 *
68 * @param key: the key where the value is stored.
69 * @param old_val: the previously stored value.
70 * @param new_val: the new value to be stored. The value can be edited by the edit policy.
71 * @param from: id of the requesting node.
72 * @param form_addr: network address of the incoming request.
73 * @param from_len: network address lendth of the incoming request.
74 */
75 using EditPolicy = std::function<bool(InfoHash key, const std::shared_ptr<Value>& old_val, std::shared_ptr<Value>& new_val, const InfoHash& from, const SockAddr& addr)>;
76
77 static constexpr const size_t MAX_VALUE_SIZE {1024 * 64};
78
79 struct OPENDHT_PUBLIC ValueType {
80 typedef uint16_t Id;
81
82 static bool DEFAULT_STORE_POLICY(InfoHash, const std::shared_ptr<Value>& v, const InfoHash&, const SockAddr&);
DEFAULT_EDIT_POLICYValueType83 static bool DEFAULT_EDIT_POLICY(InfoHash, const std::shared_ptr<Value>&, std::shared_ptr<Value>&, const InfoHash&, const SockAddr&) {
84 return false;
85 }
86
ValueTypeValueType87 ValueType () {}
88
89 ValueType (Id id, std::string name, duration e = std::chrono::minutes(10))
idValueType90 : id(id), name(name), expiration(e) {}
91
92 ValueType (Id id, std::string name, duration e, StorePolicy sp, EditPolicy ep = DEFAULT_EDIT_POLICY)
idValueType93 : id(id), name(name), expiration(e), storePolicy(sp), editPolicy(ep) {}
94
~ValueTypeValueType95 virtual ~ValueType() {}
96
97 bool operator==(const ValueType& o) {
98 return id == o.id;
99 }
100
101 // Generic value type
102 static const ValueType USER_DATA;
103
104
105 Id id {0};
106 std::string name {};
107 duration expiration {60 * 10};
108 StorePolicy storePolicy {DEFAULT_STORE_POLICY};
109 EditPolicy editPolicy {DEFAULT_EDIT_POLICY};
110 };
111
112 class TypeStore {
113 public:
registerType(const ValueType & type)114 void registerType(const ValueType& type) {
115 types[type.id] = type;
116 }
getType(ValueType::Id type_id)117 const ValueType& getType(ValueType::Id type_id) const {
118 const auto& t_it = types.find(type_id);
119 return (t_it == types.end()) ? ValueType::USER_DATA : t_it->second;
120 }
121 private:
122 std::map<ValueType::Id, ValueType> types {};
123 };
124
125 struct CryptoValueCache;
126
127 /**
128 * A "value" is data potentially stored on the Dht, with some metadata.
129 *
130 * It can be an IP:port announced for a service, a public key, or any kind of
131 * light user-defined data (recommended: less than 512 bytes).
132 *
133 * Values are stored at a given InfoHash in the Dht, but also have a
134 * unique ID to distinguish between values stored at the same location.
135 */
136 struct OPENDHT_PUBLIC Value
137 {
138 enum class Field : int {
139 None = 0,
140 Id, /* Value::id */
141 ValueType, /* Value::type */
142 OwnerPk, /* Value::owner */
143 SeqNum, /* Value::seq */
144 UserType, /* Value::user_type */
145
146 COUNT /* the total number of fields */
147 };
148
149 typedef uint64_t Id;
150 static const constexpr Id INVALID_ID {0};
151
152 class Filter : public std::function<bool(const Value&)> {
153 public:
FilterValue154 Filter() {}
155
156 template<typename Functor>
FilterValue157 Filter(Functor f) : std::function<bool(const Value&)>::function(f) {}
158
chainValue159 Filter chain(Filter&& f2) {
160 auto f1 = *this;
161 return chain(std::move(f1), std::move(f2));
162 }
chainOrValue163 Filter chainOr(Filter&& f2) {
164 auto f1 = *this;
165 return chainOr(std::move(f1), std::move(f2));
166 }
chainValue167 static Filter chain(Filter&& f1, Filter&& f2) {
168 if (not f1) return std::move(f2);
169 if (not f2) return std::move(f1);
170 return [f1,f2](const Value& v) {
171 return f1(v) and f2(v);
172 };
173 }
chainValue174 static Filter chain(const Filter& f1, const Filter& f2) {
175 if (not f1) return f2;
176 if (not f2) return f1;
177 return [f1,f2](const Value& v) {
178 return f1(v) and f2(v);
179 };
180 }
chainAllValue181 static Filter chainAll(std::vector<Filter>&& set) {
182 if (set.empty()) return {};
183 return std::bind([](const Value& v, std::vector<Filter>& s) {
184 for (const auto& f : s)
185 if (f and not f(v))
186 return false;
187 return true;
188 }, std::placeholders::_1, std::move(set));
189 }
chainValue190 static Filter chain(std::initializer_list<Filter> l) {
191 return chainAll(std::vector<Filter>(l.begin(), l.end()));
192 }
chainOrValue193 static Filter chainOr(Filter&& f1, Filter&& f2) {
194 if (not f1 or not f2) return {};
195 return [f1,f2](const Value& v) {
196 return f1(v) or f2(v);
197 };
198 }
notFilterValue199 static Filter notFilter(Filter&& f) {
200 if (not f) return [](const Value&) { return false; };
201 return [f](const Value& v) { return not f(v); };
202 }
filterValue203 std::vector<Sp<Value>> filter(const std::vector<Sp<Value>>& values) {
204 if (not (*this))
205 return values;
206 std::vector<Sp<Value>> ret;
207 for (const auto& v : values)
208 if ((*this)(v))
209 ret.emplace_back(v);
210 return ret;
211 }
212 };
213
214 /* Sneaky functions disguised in classes */
215
AllFilterValue216 static const Filter AllFilter() {
217 return {};
218 }
219
TypeFilterValue220 static Filter TypeFilter(const ValueType& t) {
221 const auto tid = t.id;
222 return [tid](const Value& v) {
223 return v.type == tid;
224 };
225 }
TypeFilterValue226 static Filter TypeFilter(const ValueType::Id& tid) {
227 return [tid](const Value& v) {
228 return v.type == tid;
229 };
230 }
231
IdFilterValue232 static Filter IdFilter(const Id id) {
233 return [id](const Value& v) {
234 return v.id == id;
235 };
236 }
237
RecipientFilterValue238 static Filter RecipientFilter(const InfoHash& r) {
239 return [r](const Value& v) {
240 return v.recipient == r;
241 };
242 }
243
OwnerFilterValue244 static Filter OwnerFilter(const crypto::PublicKey& pk) {
245 return OwnerFilter(pk.getId());
246 }
247
OwnerFilterValue248 static Filter OwnerFilter(const InfoHash& pkh) {
249 return [pkh](const Value& v) {
250 return v.owner and v.owner->getId() == pkh;
251 };
252 }
253
SeqNumFilterValue254 static Filter SeqNumFilter(uint16_t seq_no) {
255 return [seq_no](const Value& v) {
256 return v.seq == seq_no;
257 };
258 }
259
UserTypeFilterValue260 static Filter UserTypeFilter(const std::string& ut) {
261 return [ut](const Value& v) {
262 return v.user_type == ut;
263 };
264 }
265
266 class SerializableBase
267 {
268 public:
SerializableBaseValue269 SerializableBase() {}
~SerializableBaseValue270 virtual ~SerializableBase() {};
271 virtual const ValueType& getType() const = 0;
272 virtual void unpackValue(const Value& v) = 0;
273 virtual Value packValue() const = 0;
274 };
275
276 template <typename Derived, typename Base=SerializableBase>
277 class Serializable : public Base
278 {
279 public:
280 using Base::Base;
281
getTypeValue282 virtual const ValueType& getType() const {
283 return Derived::TYPE;
284 }
285
unpackValueValue286 virtual void unpackValue(const Value& v) {
287 auto msg = msgpack::unpack((const char*)v.data.data(), v.data.size());
288 msg.get().convert(*static_cast<Derived*>(this));
289 }
290
packValueValue291 virtual Value packValue() const {
292 return Value {getType(), static_cast<const Derived&>(*this)};
293 }
294 };
295
296 template <typename T,
297 typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
packValue298 static Value pack(const T& obj)
299 {
300 return obj.packValue();
301 }
302
303 template <typename T,
304 typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
packValue305 static Value pack(const T& obj)
306 {
307 return {ValueType::USER_DATA.id, packMsg<T>(obj)};
308 }
309
310 template <typename T,
311 typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
unpackValue312 static T unpack(const Value& v)
313 {
314 T msg;
315 msg.unpackValue(v);
316 return msg;
317 }
318
319 template <typename T,
320 typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
unpackValue321 static T unpack(const Value& v)
322 {
323 return unpackMsg<T>(v.data);
324 }
325
326 template <typename T>
unpackValue327 T unpack()
328 {
329 return unpack<T>(*this);
330 }
331
isEncryptedValue332 bool isEncrypted() const {
333 return not cypher.empty();
334 }
isSignedValue335 bool isSigned() const {
336 return owner and not signature.empty();
337 }
338
339 /**
340 * Sign the value using the provided private key.
341 * Afterward, checkSignature() will return true and owner will
342 * be set to the corresponding public key.
343 */
signValue344 void sign(const crypto::PrivateKey& key) {
345 if (isEncrypted())
346 throw DhtException("Can't sign encrypted data.");
347 owner = std::make_shared<const crypto::PublicKey>(key.getPublicKey());
348 signature = key.sign(getToSign());
349 }
350
351 /**
352 * Check that the value is signed and that the signature matches.
353 * If true, the owner field will contain the signer public key.
354 */
checkSignatureValue355 bool checkSignature() const {
356 return isSigned() and owner->checkSignature(getToSign(), signature);
357 }
358
getOwnerValue359 std::shared_ptr<const crypto::PublicKey> getOwner() const {
360 return std::static_pointer_cast<const crypto::PublicKey>(owner);
361 }
362
363 /**
364 * Sign the value with from and returns the encrypted version for to.
365 */
encryptValue366 Value encrypt(const crypto::PrivateKey& from, const crypto::PublicKey& to) {
367 if (isEncrypted())
368 throw DhtException("Data is already encrypted.");
369 setRecipient(to.getId());
370 sign(from);
371 Value nv {id};
372 nv.setCypher(to.encrypt(getToEncrypt()));
373 return nv;
374 }
375
ValueValue376 Value() {}
377
ValueValue378 Value (Id id) : id(id) {}
379
380 /** Generic constructor */
381 Value(ValueType::Id t, const Blob& data, Id id = INVALID_ID)
idValue382 : id(id), type(t), data(data) {}
383 Value(ValueType::Id t, Blob&& data, Id id = INVALID_ID)
idValue384 : id(id), type(t), data(std::move(data)) {}
385 Value(ValueType::Id t, const uint8_t* dat_ptr, size_t dat_len, Id id = INVALID_ID)
idValue386 : id(id), type(t), data(dat_ptr, dat_ptr+dat_len) {}
387
388 #ifdef OPENDHT_JSONCPP
389 /**
390 * Build a value from a json object
391 * @param json
392 */
393 Value(Json::Value& json);
394 #endif
395
396 template <typename Type>
397 Value(ValueType::Id t, const Type& d, Id id = INVALID_ID)
idValue398 : id(id), type(t), data(packMsg(d)) {}
399
400 template <typename Type>
401 Value(const ValueType& t, const Type& d, Id id = INVALID_ID)
idValue402 : id(id), type(t.id), data(packMsg(d)) {}
403
404 /** Custom user data constructor */
ValueValue405 Value(const Blob& userdata) : data(userdata) {}
ValueValue406 Value(Blob&& userdata) : data(std::move(userdata)) {}
ValueValue407 Value(const uint8_t* dat_ptr, size_t dat_len) : data(dat_ptr, dat_ptr+dat_len) {}
408
ValueValue409 Value(Value&& o) noexcept
410 : id(o.id), owner(std::move(o.owner)), recipient(o.recipient),
411 type(o.type), data(std::move(o.data)), user_type(std::move(o.user_type)), seq(o.seq), signature(std::move(o.signature)), cypher(std::move(o.cypher)) {}
412
413 template <typename Type>
ValueValue414 Value(const Type& vs)
415 : Value(pack<Type>(vs)) {}
416
417 /**
418 * Unpack a serialized value
419 */
ValueValue420 Value(const msgpack::object& o) {
421 msgpack_unpack(o);
422 }
423
424 inline bool operator== (const Value& o) {
425 return id == o.id &&
426 (isEncrypted() ? cypher == o.cypher :
427 ((owner == o.owner || *owner == *o.owner) && type == o.type && data == o.data && user_type == o.user_type && signature == o.signature));
428 }
429
setRecipientValue430 void setRecipient(const InfoHash& r) {
431 recipient = r;
432 }
433
setCypherValue434 void setCypher(Blob&& c) {
435 cypher = std::move(c);
436 }
437
438 /**
439 * Pack part of the data to be signed (must always be done the same way)
440 */
getToSignValue441 Blob getToSign() const {
442 msgpack::sbuffer buffer;
443 msgpack::packer<msgpack::sbuffer> pk(&buffer);
444 msgpack_pack_to_sign(pk);
445 return {buffer.data(), buffer.data()+buffer.size()};
446 }
447
448 /**
449 * Pack part of the data to be encrypted
450 */
getToEncryptValue451 Blob getToEncrypt() const {
452 msgpack::sbuffer buffer;
453 msgpack::packer<msgpack::sbuffer> pk(&buffer);
454 msgpack_pack_to_encrypt(pk);
455 return {buffer.data(), buffer.data()+buffer.size()};
456 }
457
458 /** print value for debugging */
459 OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Value& v);
460
toStringValue461 std::string toString() const {
462 std::stringstream ss;
463 ss << *this;
464 return ss.str();
465 }
466
467 #ifdef OPENDHT_JSONCPP
468 /**
469 * Build a json object from a value
470 * Example:
471 * {
472 * "data":"base64ofdata",
473 * id":"0", "seq":0,"type":3
474 * }
475 */
476 Json::Value toJson() const;
477 #endif
478
479 /** Return the size in bytes used by this value in memory (minimum). */
480 size_t size() const;
481
482 template <typename Packer>
msgpack_pack_to_signValue483 void msgpack_pack_to_sign(Packer& pk) const
484 {
485 bool has_owner = owner && *owner;
486 pk.pack_map((user_type.empty()?0:1) + (has_owner?(recipient ? 5 : 4):2));
487 if (has_owner) { // isSigned
488 pk.pack(std::string("seq")); pk.pack(seq);
489 pk.pack(std::string("owner")); owner->msgpack_pack(pk);
490 if (recipient) {
491 pk.pack(std::string("to")); pk.pack(recipient);
492 }
493 }
494 pk.pack(std::string("type")); pk.pack(type);
495 pk.pack(std::string("data")); pk.pack_bin(data.size());
496 pk.pack_bin_body((const char*)data.data(), data.size());
497 if (not user_type.empty()) {
498 pk.pack(std::string("utype")); pk.pack(user_type);
499 }
500 }
501
502 template <typename Packer>
msgpack_pack_to_encryptValue503 void msgpack_pack_to_encrypt(Packer& pk) const
504 {
505 if (isEncrypted()) {
506 pk.pack_bin(cypher.size());
507 pk.pack_bin_body((const char*)cypher.data(), cypher.size());
508 } else {
509 pk.pack_map(isSigned() ? 2 : 1);
510 pk.pack(std::string("body")); msgpack_pack_to_sign(pk);
511 if (isSigned()) {
512 pk.pack(std::string("sig")); pk.pack_bin(signature.size());
513 pk.pack_bin_body((const char*)signature.data(), signature.size());
514 }
515 }
516 }
517
518 template <typename Packer>
msgpack_packValue519 void msgpack_pack(Packer& pk) const
520 {
521 pk.pack_map(2);
522 pk.pack(std::string("id")); pk.pack(id);
523 pk.pack(std::string("dat")); msgpack_pack_to_encrypt(pk);
524 }
525
526 template <typename Packer>
msgpack_pack_fieldsValue527 void msgpack_pack_fields(const std::set<Value::Field>& fields, Packer& pk) const
528 {
529 for (const auto& field : fields)
530 switch (field) {
531 case Value::Field::Id:
532 pk.pack(static_cast<uint64_t>(id));
533 break;
534 case Value::Field::ValueType:
535 pk.pack(static_cast<uint64_t>(type));
536 break;
537 case Value::Field::OwnerPk:
538 if (owner)
539 owner->msgpack_pack(pk);
540 else
541 InfoHash().msgpack_pack(pk);
542 break;
543 case Value::Field::SeqNum:
544 pk.pack(static_cast<uint64_t>(seq));
545 break;
546 case Value::Field::UserType:
547 pk.pack(user_type);
548 break;
549 default:
550 break;
551 }
552 }
553
554 void msgpack_unpack(msgpack::object o);
555 void msgpack_unpack_body(const msgpack::object& o);
getPackedValue556 Blob getPacked() const {
557 msgpack::sbuffer buffer;
558 msgpack::packer<msgpack::sbuffer> pk(&buffer);
559 pk.pack(*this);
560 return {buffer.data(), buffer.data()+buffer.size()};
561 }
562
563 void msgpack_unpack_fields(const std::set<Value::Field>& fields, const msgpack::object& o, unsigned offset);
564
565 Id id {INVALID_ID};
566
567 /**
568 * Public key of the signer.
569 */
570 std::shared_ptr<const crypto::PublicKey> owner {};
571
572 /**
573 * Hash of the recipient (optional).
574 * Should only be present for encrypted values.
575 * Can optionally be present for signed values.
576 */
577 InfoHash recipient {};
578
579 /**
580 * Type of data.
581 */
582 ValueType::Id type {ValueType::USER_DATA.id};
583 Blob data {};
584
585 /**
586 * Custom user-defined type
587 */
588 std::string user_type {};
589
590 /**
591 * Sequence number to avoid replay attacks
592 */
593 uint16_t seq {0};
594
595 /**
596 * Optional signature.
597 */
598 Blob signature {};
599
600 /**
601 * Hold encrypted version of the data.
602 */
603 Blob cypher {};
604
605 private:
606 friend class SecureDht;
607 /* Cache for crypto ops */
608 bool signatureChecked {false};
609 bool signatureValid {false};
610 bool decrypted {false};
611 Sp<Value> decryptedValue {};
612 };
613
614 using ValuesExport = std::pair<InfoHash, Blob>;
615
616 /**
617 * @class FieldValue
618 * @brief Describes a value filter.
619 * @details
620 * This structure holds the value for a specified field. It's type can either be
621 * uint64_t, InfoHash or Blob.
622 */
623 struct OPENDHT_PUBLIC FieldValue
624 {
FieldValueFieldValue625 FieldValue() {}
FieldValueFieldValue626 FieldValue(Value::Field f, uint64_t int_value) : field(f), intValue(int_value) {}
FieldValueFieldValue627 FieldValue(Value::Field f, InfoHash hash_value) : field(f), hashValue(hash_value) {}
FieldValueFieldValue628 FieldValue(Value::Field f, Blob blob_value) : field(f), blobValue(blob_value) {}
629
630 bool operator==(const FieldValue& fd) const;
631
632 // accessors
getFieldFieldValue633 Value::Field getField() const { return field; }
getIntFieldValue634 uint64_t getInt() const { return intValue; }
getHashFieldValue635 InfoHash getHash() const { return hashValue; }
getBlobFieldValue636 Blob getBlob() const { return blobValue; }
637
638 template <typename Packer>
msgpack_packFieldValue639 void msgpack_pack(Packer& p) const {
640 p.pack_map(2);
641 p.pack(std::string("f")); p.pack(static_cast<uint8_t>(field));
642
643 p.pack(std::string("v"));
644 switch (field) {
645 case Value::Field::Id:
646 case Value::Field::ValueType:
647 p.pack(intValue);
648 break;
649 case Value::Field::OwnerPk:
650 p.pack(hashValue);
651 break;
652 case Value::Field::UserType:
653 p.pack_bin(blobValue.size());
654 p.pack_bin_body((const char*)blobValue.data(), blobValue.size());
655 break;
656 default:
657 throw msgpack::type_error();
658 }
659 }
660
msgpack_unpackFieldValue661 void msgpack_unpack(msgpack::object msg) {
662 hashValue = {};
663 blobValue.clear();
664
665 if (auto f = findMapValue(msg, "f"))
666 field = (Value::Field)f->as<unsigned>();
667 else
668 throw msgpack::type_error();
669
670 auto v = findMapValue(msg, "v");
671 if (not v)
672 throw msgpack::type_error();
673 else
674 switch (field) {
675 case Value::Field::Id:
676 case Value::Field::ValueType:
677 intValue = v->as<decltype(intValue)>();
678 break;
679 case Value::Field::OwnerPk:
680 hashValue = v->as<decltype(hashValue)>();
681 break;
682 case Value::Field::UserType:
683 blobValue = unpackBlob(*v);
684 break;
685 default:
686 throw msgpack::type_error();
687 }
688 }
689
690 Value::Filter getLocalFilter() const;
691
692 private:
693 Value::Field field {Value::Field::None};
694 // three possible value types
695 uint64_t intValue {};
696 InfoHash hashValue {};
697 Blob blobValue {};
698 };
699
700 /**
701 * @class Select
702 * @brief Serializable Value field selection.
703 * @details
704 * This is a container for a list of FieldSelectorDescription instances. It
705 * describes a complete SELECT query for dht::Value.
706 */
707 struct OPENDHT_PUBLIC Select
708 {
SelectSelect709 Select() { }
710 Select(const std::string& q_str);
711
712 bool isSatisfiedBy(const Select& os) const;
713
714 /**
715 * Selects a field of type Value::Field.
716 *
717 * @param field the field to require.
718 *
719 * @return the resulting Select instance.
720 */
fieldSelect721 Select& field(Value::Field field) {
722 if (std::find(fieldSelection_.begin(), fieldSelection_.end(), field) == fieldSelection_.end())
723 fieldSelection_.emplace_back(field);
724 return *this;
725 }
726
727 /**
728 * Computes the set of selected fields based on previous require* calls.
729 *
730 * @return the set of fields.
731 */
getSelectionSelect732 std::set<Value::Field> getSelection() const {
733 return {fieldSelection_.begin(), fieldSelection_.end()};
734 }
735
736 template <typename Packer>
msgpack_packSelect737 void msgpack_pack(Packer& pk) const { pk.pack(fieldSelection_); }
msgpack_unpackSelect738 void msgpack_unpack(const msgpack::object& o) {
739 fieldSelection_ = o.as<decltype(fieldSelection_)>();
740 }
741
toStringSelect742 std::string toString() const {
743 std::stringstream ss;
744 ss << *this;
745 return ss.str();
746 }
747
748 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Select& q);
749 private:
750 std::vector<Value::Field> fieldSelection_ {};
751 };
752
753 /**
754 * @class Where
755 * @brief Serializable dht::Value filter.
756 * @details
757 * This is container for a list of FieldValue instances. It describes a
758 * complete WHERE query for dht::Value.
759 */
760 struct OPENDHT_PUBLIC Where
761 {
WhereWhere762 Where() { }
763 Where(const std::string& q_str);
764
765 bool isSatisfiedBy(const Where& where) const;
766
767 /**
768 * Adds restriction on Value::Id based on the id argument.
769 *
770 * @param id the id.
771 *
772 * @return the resulting Where instance.
773 */
idWhere774 Where& id(Value::Id id) {
775 FieldValue fv {Value::Field::Id, id};
776 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
777 filters_.emplace_back(std::move(fv));
778 return *this;
779 }
780
781 /**
782 * Adds restriction on Value::ValueType based on the type argument.
783 *
784 * @param type the value type.
785 *
786 * @return the resulting Where instance.
787 */
valueTypeWhere788 Where& valueType(ValueType::Id type) {
789 FieldValue fv {Value::Field::ValueType, type};
790 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
791 filters_.emplace_back(std::move(fv));
792 return *this;
793 }
794
795 /**
796 * Adds restriction on Value::OwnerPk based on the owner_pk_hash argument.
797 *
798 * @param owner_pk_hash the owner public key fingerprint.
799 *
800 * @return the resulting Where instance.
801 */
ownerWhere802 Where& owner(InfoHash owner_pk_hash) {
803 FieldValue fv {Value::Field::OwnerPk, owner_pk_hash};
804 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
805 filters_.emplace_back(std::move(fv));
806 return *this;
807 }
808
809 /**
810 * Adds restriction on Value::OwnerPk based on the owner_pk_hash argument.
811 *
812 * @param owner_pk_hash the owner public key fingerprint.
813 *
814 * @return the resulting Where instance.
815 */
seqWhere816 Where& seq(uint16_t seq_no) {
817 FieldValue fv {Value::Field::SeqNum, seq_no};
818 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
819 filters_.emplace_back(std::move(fv));
820 return *this;
821 }
822
823 /**
824 * Adds restriction on Value::UserType based on the user_type argument.
825 *
826 * @param user_type the user type.
827 *
828 * @return the resulting Where instance.
829 */
userTypeWhere830 Where& userType(std::string user_type) {
831 FieldValue fv {Value::Field::UserType, Blob {user_type.begin(), user_type.end()}};
832 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
833 filters_.emplace_back(std::move(fv));
834 return *this;
835 }
836
837 /**
838 * Computes the Value::Filter based on the list of field value set.
839 *
840 * @return the resulting Value::Filter.
841 */
getFilterWhere842 Value::Filter getFilter() const {
843 if (filters_.empty()) return {};
844 std::vector<Value::Filter> fset;
845 fset.reserve(filters_.size());
846 for (const auto& f : filters_) {
847 if (auto lf = f.getLocalFilter())
848 fset.emplace_back(std::move(lf));
849 }
850 return Value::Filter::chainAll(std::move(fset));
851 }
852
853 template <typename Packer>
msgpack_packWhere854 void msgpack_pack(Packer& pk) const { pk.pack(filters_); }
msgpack_unpackWhere855 void msgpack_unpack(const msgpack::object& o) {
856 filters_.clear();
857 filters_ = o.as<decltype(filters_)>();
858 }
859
toStringWhere860 std::string toString() const {
861 std::stringstream ss;
862 ss << *this;
863 return ss.str();
864 }
865
emptyWhere866 bool empty() const {
867 return filters_.empty();
868 }
869
870 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Where& q);
871
872 private:
873 std::vector<FieldValue> filters_;
874 };
875
876 /**
877 * @class Query
878 * @brief Describes a query destined to another peer.
879 * @details
880 * This class describes the list of filters on field values and the field
881 * itselves to include in the peer response to a GET operation. See
882 * FieldValue.
883 */
884 struct OPENDHT_PUBLIC Query
885 {
886 static const std::string QUERY_PARSE_ERROR;
887
selectQuery888 Query(Select s = {}, Where w = {}, bool none = false) : select(std::move(s)), where(std::move(w)), none(none) { };
889
890 /**
891 * Initializes a query based on a SQL-ish formatted string. The abstract
892 * form of such a string is the following:
893 *
894 * [SELECT $field$ [WHERE $field$=$value$]]
895 *
896 * where
897 *
898 * - $field$ = *|id|value_type|owner_pk|user_type
899 * - $value$ = $string$|$integer$
900 * - $string$: a simple string WITHOUT SPACES.
901 * - $integer$: a simple integer.
902 */
QueryQuery903 Query(std::string q_str) {
904 auto pos_W = q_str.find("WHERE");
905 auto pos_w = q_str.find("where");
906 auto pos = std::min(pos_W != std::string::npos ? pos_W : q_str.size(),
907 pos_w != std::string::npos ? pos_w : q_str.size());
908 select = q_str.substr(0, pos);
909 where = q_str.substr(pos, q_str.size()-pos);
910 }
911
912 /**
913 * Tell if the query is satisfied by another query.
914 */
915 bool isSatisfiedBy(const Query& q) const;
916
917 template <typename Packer>
msgpack_packQuery918 void msgpack_pack(Packer& pk) const {
919 pk.pack_map(2);
920 pk.pack(std::string("s")); pk.pack(select); /* packing field selectors */
921 pk.pack(std::string("w")); pk.pack(where); /* packing filters */
922 }
923
924 void msgpack_unpack(const msgpack::object& o);
925
toStringQuery926 std::string toString() const {
927 std::stringstream ss;
928 ss << *this;
929 return ss.str();
930 }
931
932 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Query& q) {
933 return s << "Query[" << q.select << " " << q.where << "]";
934 }
935
936 Select select {};
937 Where where {};
938 bool none {false}; /* When true, any query satisfies this. */
939 };
940
941 /*!
942 * @class FieldValueIndex
943 * @brief An index for field values.
944 * @details
945 * This structures is meant to manipulate a subset of fields normally contained
946 * in Value.
947 */
948 struct OPENDHT_PUBLIC FieldValueIndex {
FieldValueIndexFieldValueIndex949 FieldValueIndex() {}
950 FieldValueIndex(const Value& v, const Select& s = {});
951 /**
952 * Tells if all the fields of this are contained in the other
953 * FieldValueIndex with the same value.
954 *
955 * @param other The other FieldValueIndex instance.
956 */
957 bool containedIn(const FieldValueIndex& other) const;
958
959 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& os, const FieldValueIndex& fvi);
960
961 void msgpack_unpack_fields(const std::set<Value::Field>& fields,
962 const msgpack::object& o,
963 unsigned offset);
964
965 std::map<Value::Field, FieldValue> index {};
966 };
967
968 template <typename T,
969 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
970 Value::Filter
getFilterSet(Value::Filter f)971 getFilterSet(Value::Filter f)
972 {
973 return Value::Filter::chain({
974 Value::TypeFilter(T::TYPE),
975 T::getFilter(),
976 f
977 });
978 }
979
980 template <typename T,
981 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
982 Value::Filter
getFilterSet(Value::Filter f)983 getFilterSet(Value::Filter f)
984 {
985 return f;
986 }
987
988 template <typename T,
989 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
990 Value::Filter
getFilterSet()991 getFilterSet()
992 {
993 return Value::Filter::chain({
994 Value::TypeFilter(T::TYPE),
995 T::getFilter()
996 });
997 }
998
999 template <typename T,
1000 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1001 Value::Filter
getFilterSet()1002 getFilterSet()
1003 {
1004 return {};
1005 }
1006
1007 template <class T>
1008 std::vector<T>
unpackVector(const std::vector<std::shared_ptr<Value>> & vals)1009 unpackVector(const std::vector<std::shared_ptr<Value>>& vals) {
1010 std::vector<T> ret;
1011 ret.reserve(vals.size());
1012 for (const auto& v : vals) {
1013 try {
1014 ret.emplace_back(Value::unpack<T>(*v));
1015 } catch (const std::exception&) {}
1016 }
1017 return ret;
1018 }
1019
1020 #ifdef OPENDHT_JSONCPP
1021 uint64_t unpackId(const Json::Value& json, const std::string& key);
1022 #endif
1023
1024 }
1025
1026 MSGPACK_ADD_ENUM(dht::Value::Field)
1027