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 #if defined(__FreeBSD__)
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #endif
33
34 #include <string>
35 #include <sstream>
36 #include <bitset>
37 #include <vector>
38 #include <iostream>
39 #include <algorithm>
40 #include <functional>
41 #include <memory>
42 #include <chrono>
43 #include <set>
44
45 #ifdef OPENDHT_JSONCPP
46 #include <json/json.h>
47 #endif
48
49 namespace dht {
50
51 struct Value;
52 struct Query;
53
54 /**
55 * A storage policy is applied once to every incoming value storage requests.
56 * If the policy returns false, the value is dropped.
57 *
58 * @param key: the key where the storage is requested.
59 * @param value: the value to be stored. The value can be edited by the storage policy.
60 * @param from: id of the requesting node.
61 * @param form_addr: network address of the incoming request.
62 * @param from_len: network address lendth of the incoming request.
63 */
64 using StorePolicy = std::function<bool(InfoHash key, std::shared_ptr<Value>& value, const InfoHash& from, const SockAddr& addr)>;
65
66 /**
67 * An edition policy is applied once to every incoming value storage requests,
68 * if a value already exists for this key and value id.
69 * If the policy returns false, the edition request is ignored.
70 * The default behavior is to deny edition (see {ValueType::DEFAULT_EDIT_POLICY}).
71 * Some {ValueType}s may override this behavior (e.g. SignedValue).
72 *
73 * @param key: the key where the value is stored.
74 * @param old_val: the previously stored value.
75 * @param new_val: the new value to be stored. The value can be edited by the edit policy.
76 * @param from: id of the requesting node.
77 * @param form_addr: network address of the incoming request.
78 * @param from_len: network address lendth of the incoming request.
79 */
80 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)>;
81
82 static constexpr const size_t MAX_VALUE_SIZE {1024 * 64};
83
84 struct OPENDHT_PUBLIC ValueType {
85 typedef uint16_t Id;
86
87 static bool DEFAULT_STORE_POLICY(InfoHash, const std::shared_ptr<Value>& v, const InfoHash&, const SockAddr&);
DEFAULT_EDIT_POLICYValueType88 static bool DEFAULT_EDIT_POLICY(InfoHash, const std::shared_ptr<Value>&, std::shared_ptr<Value>&, const InfoHash&, const SockAddr&) {
89 return false;
90 }
91
ValueTypeValueType92 ValueType () {}
93
94 ValueType (Id id, std::string name, duration e = std::chrono::minutes(10))
idValueType95 : id(id), name(name), expiration(e) {}
96
97 ValueType (Id id, std::string name, duration e, StorePolicy sp, EditPolicy ep = DEFAULT_EDIT_POLICY)
idValueType98 : id(id), name(name), expiration(e), storePolicy(sp), editPolicy(ep) {}
99
~ValueTypeValueType100 virtual ~ValueType() {}
101
102 bool operator==(const ValueType& o) {
103 return id == o.id;
104 }
105
106 // Generic value type
107 static const ValueType USER_DATA;
108
109
110 Id id {0};
111 std::string name {};
112 duration expiration {60 * 10};
113 StorePolicy storePolicy {DEFAULT_STORE_POLICY};
114 EditPolicy editPolicy {DEFAULT_EDIT_POLICY};
115 };
116
117 class TypeStore {
118 public:
registerType(const ValueType & type)119 void registerType(const ValueType& type) {
120 types[type.id] = type;
121 }
getType(ValueType::Id type_id)122 const ValueType& getType(ValueType::Id type_id) const {
123 const auto& t_it = types.find(type_id);
124 return (t_it == types.end()) ? ValueType::USER_DATA : t_it->second;
125 }
126 private:
127 std::map<ValueType::Id, ValueType> types {};
128 };
129
130 struct CryptoValueCache;
131
132 /**
133 * A "value" is data potentially stored on the Dht, with some metadata.
134 *
135 * It can be an IP:port announced for a service, a public key, or any kind of
136 * light user-defined data (recommended: less than 512 bytes).
137 *
138 * Values are stored at a given InfoHash in the Dht, but also have a
139 * unique ID to distinguish between values stored at the same location.
140 */
141 struct OPENDHT_PUBLIC Value
142 {
143 enum class Field : int {
144 None = 0,
145 Id, /* Value::id */
146 ValueType, /* Value::type */
147 OwnerPk, /* Value::owner */
148 SeqNum, /* Value::seq */
149 UserType, /* Value::user_type */
150
151 COUNT /* the total number of fields */
152 };
153
154 typedef uint64_t Id;
155 static const constexpr Id INVALID_ID {0};
156
157 class Filter : public std::function<bool(const Value&)> {
158 public:
FilterValue159 Filter() {}
160
161 template<typename Functor>
FilterValue162 Filter(Functor f) : std::function<bool(const Value&)>::function(f) {}
163
chainValue164 Filter chain(Filter&& f2) {
165 auto f1 = *this;
166 return chain(std::move(f1), std::move(f2));
167 }
chainOrValue168 Filter chainOr(Filter&& f2) {
169 auto f1 = *this;
170 return chainOr(std::move(f1), std::move(f2));
171 }
chainValue172 static Filter chain(Filter&& f1, Filter&& f2) {
173 if (not f1) return std::move(f2);
174 if (not f2) return std::move(f1);
175 return [f1,f2](const Value& v) {
176 return f1(v) and f2(v);
177 };
178 }
chainValue179 static Filter chain(const Filter& f1, const Filter& f2) {
180 if (not f1) return f2;
181 if (not f2) return f1;
182 return [f1,f2](const Value& v) {
183 return f1(v) and f2(v);
184 };
185 }
chainAllValue186 static Filter chainAll(std::vector<Filter>&& set) {
187 if (set.empty()) return {};
188 return std::bind([](const Value& v, std::vector<Filter>& s) {
189 for (const auto& f : s)
190 if (f and not f(v))
191 return false;
192 return true;
193 }, std::placeholders::_1, std::move(set));
194 }
chainValue195 static Filter chain(std::initializer_list<Filter> l) {
196 return chainAll(std::vector<Filter>(l.begin(), l.end()));
197 }
chainOrValue198 static Filter chainOr(Filter&& f1, Filter&& f2) {
199 if (not f1 or not f2) return {};
200 return [f1,f2](const Value& v) {
201 return f1(v) or f2(v);
202 };
203 }
notFilterValue204 static Filter notFilter(Filter&& f) {
205 if (not f) return [](const Value&) { return false; };
206 return [f](const Value& v) { return not f(v); };
207 }
filterValue208 std::vector<Sp<Value>> filter(const std::vector<Sp<Value>>& values) {
209 if (not (*this))
210 return values;
211 std::vector<Sp<Value>> ret;
212 for (const auto& v : values)
213 if ((*this)(v))
214 ret.emplace_back(v);
215 return ret;
216 }
217 };
218
219 /* Sneaky functions disguised in classes */
220
AllFilterValue221 static const Filter AllFilter() {
222 return {};
223 }
224
TypeFilterValue225 static Filter TypeFilter(const ValueType& t) {
226 const auto tid = t.id;
227 return [tid](const Value& v) {
228 return v.type == tid;
229 };
230 }
TypeFilterValue231 static Filter TypeFilter(const ValueType::Id& tid) {
232 return [tid](const Value& v) {
233 return v.type == tid;
234 };
235 }
236
IdFilterValue237 static Filter IdFilter(const Id id) {
238 return [id](const Value& v) {
239 return v.id == id;
240 };
241 }
242
RecipientFilterValue243 static Filter RecipientFilter(const InfoHash& r) {
244 return [r](const Value& v) {
245 return v.recipient == r;
246 };
247 }
248
OwnerFilterValue249 static Filter OwnerFilter(const crypto::PublicKey& pk) {
250 return OwnerFilter(pk.getId());
251 }
252
OwnerFilterValue253 static Filter OwnerFilter(const InfoHash& pkh) {
254 return [pkh](const Value& v) {
255 return v.owner and v.owner->getId() == pkh;
256 };
257 }
258
SeqNumFilterValue259 static Filter SeqNumFilter(uint16_t seq_no) {
260 return [seq_no](const Value& v) {
261 return v.seq == seq_no;
262 };
263 }
264
UserTypeFilterValue265 static Filter UserTypeFilter(const std::string& ut) {
266 return [ut](const Value& v) {
267 return v.user_type == ut;
268 };
269 }
270
271 class SerializableBase
272 {
273 public:
SerializableBaseValue274 SerializableBase() {}
~SerializableBaseValue275 virtual ~SerializableBase() {};
276 virtual const ValueType& getType() const = 0;
277 virtual void unpackValue(const Value& v) = 0;
278 virtual Value packValue() const = 0;
279 };
280
281 template <typename Derived, typename Base=SerializableBase>
282 class Serializable : public Base
283 {
284 public:
285 using Base::Base;
286
getTypeValue287 virtual const ValueType& getType() const {
288 return Derived::TYPE;
289 }
290
unpackValueValue291 virtual void unpackValue(const Value& v) {
292 auto msg = msgpack::unpack((const char*)v.data.data(), v.data.size());
293 msg.get().convert(*static_cast<Derived*>(this));
294 }
295
packValueValue296 virtual Value packValue() const {
297 return Value {getType(), static_cast<const Derived&>(*this)};
298 }
299 };
300
301 template <typename T,
302 typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
packValue303 static Value pack(const T& obj)
304 {
305 return obj.packValue();
306 }
307
308 template <typename T,
309 typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
packValue310 static Value pack(const T& obj)
311 {
312 return {ValueType::USER_DATA.id, packMsg<T>(obj)};
313 }
314
315 template <typename T,
316 typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
unpackValue317 static T unpack(const Value& v)
318 {
319 T msg;
320 msg.unpackValue(v);
321 return msg;
322 }
323
324 template <typename T,
325 typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
unpackValue326 static T unpack(const Value& v)
327 {
328 return unpackMsg<T>(v.data);
329 }
330
331 template <typename T>
unpackValue332 T unpack()
333 {
334 return unpack<T>(*this);
335 }
336
isEncryptedValue337 bool isEncrypted() const {
338 return not cypher.empty();
339 }
isSignedValue340 bool isSigned() const {
341 return owner and not signature.empty();
342 }
343
344 /**
345 * Sign the value using the provided private key.
346 * Afterward, checkSignature() will return true and owner will
347 * be set to the corresponding public key.
348 */
signValue349 void sign(const crypto::PrivateKey& key) {
350 if (isEncrypted())
351 throw DhtException("Can't sign encrypted data.");
352 owner = std::make_shared<const crypto::PublicKey>(key.getPublicKey());
353 signature = key.sign(getToSign());
354 }
355
356 /**
357 * Check that the value is signed and that the signature matches.
358 * If true, the owner field will contain the signer public key.
359 */
checkSignatureValue360 bool checkSignature() const {
361 return isSigned() and owner->checkSignature(getToSign(), signature);
362 }
363
getOwnerValue364 std::shared_ptr<const crypto::PublicKey> getOwner() const {
365 return std::static_pointer_cast<const crypto::PublicKey>(owner);
366 }
367
368 /**
369 * Sign the value with from and returns the encrypted version for to.
370 */
encryptValue371 Value encrypt(const crypto::PrivateKey& from, const crypto::PublicKey& to) {
372 if (isEncrypted())
373 throw DhtException("Data is already encrypted.");
374 setRecipient(to.getId());
375 sign(from);
376 Value nv {id};
377 nv.setCypher(to.encrypt(getToEncrypt()));
378 return nv;
379 }
380
ValueValue381 Value() {}
382
ValueValue383 Value (Id id) : id(id) {}
384
385 /** Generic constructor */
386 Value(ValueType::Id t, const Blob& data, Id id = INVALID_ID)
idValue387 : id(id), type(t), data(data) {}
388 Value(ValueType::Id t, Blob&& data, Id id = INVALID_ID)
idValue389 : id(id), type(t), data(std::move(data)) {}
390 Value(ValueType::Id t, const uint8_t* dat_ptr, size_t dat_len, Id id = INVALID_ID)
idValue391 : id(id), type(t), data(dat_ptr, dat_ptr+dat_len) {}
392
393 #ifdef OPENDHT_JSONCPP
394 /**
395 * Build a value from a json object
396 * @param json
397 */
398 Value(Json::Value& json);
399 #endif
400
401 template <typename Type>
402 Value(ValueType::Id t, const Type& d, Id id = INVALID_ID)
idValue403 : id(id), type(t), data(packMsg(d)) {}
404
405 template <typename Type>
406 Value(const ValueType& t, const Type& d, Id id = INVALID_ID)
idValue407 : id(id), type(t.id), data(packMsg(d)) {}
408
409 /** Custom user data constructor */
ValueValue410 Value(const Blob& userdata) : data(userdata) {}
ValueValue411 Value(Blob&& userdata) : data(std::move(userdata)) {}
ValueValue412 Value(const uint8_t* dat_ptr, size_t dat_len) : data(dat_ptr, dat_ptr+dat_len) {}
413
ValueValue414 Value(Value&& o) noexcept
415 : id(o.id), owner(std::move(o.owner)), recipient(o.recipient),
416 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)) {}
417
418 template <typename Type>
ValueValue419 Value(const Type& vs)
420 : Value(pack<Type>(vs)) {}
421
422 /**
423 * Unpack a serialized value
424 */
ValueValue425 Value(const msgpack::object& o) {
426 msgpack_unpack(o);
427 }
428
429 inline bool operator== (const Value& o) {
430 return id == o.id &&
431 (isEncrypted() ? cypher == o.cypher :
432 ((owner == o.owner || *owner == *o.owner) && type == o.type && data == o.data && user_type == o.user_type && signature == o.signature));
433 }
434
setRecipientValue435 void setRecipient(const InfoHash& r) {
436 recipient = r;
437 }
438
setCypherValue439 void setCypher(Blob&& c) {
440 cypher = std::move(c);
441 }
442
443 /**
444 * Pack part of the data to be signed (must always be done the same way)
445 */
getToSignValue446 Blob getToSign() const {
447 msgpack::sbuffer buffer;
448 msgpack::packer<msgpack::sbuffer> pk(&buffer);
449 msgpack_pack_to_sign(pk);
450 return {buffer.data(), buffer.data()+buffer.size()};
451 }
452
453 /**
454 * Pack part of the data to be encrypted
455 */
getToEncryptValue456 Blob getToEncrypt() const {
457 msgpack::sbuffer buffer;
458 msgpack::packer<msgpack::sbuffer> pk(&buffer);
459 msgpack_pack_to_encrypt(pk);
460 return {buffer.data(), buffer.data()+buffer.size()};
461 }
462
463 /** print value for debugging */
464 OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Value& v);
465
toStringValue466 std::string toString() const {
467 std::stringstream ss;
468 ss << *this;
469 return ss.str();
470 }
471
472 #ifdef OPENDHT_JSONCPP
473 /**
474 * Build a json object from a value
475 * Example:
476 * {
477 * "data":"base64ofdata",
478 * id":"0", "seq":0,"type":3
479 * }
480 */
481 Json::Value toJson() const;
482 #endif
483
484 /** Return the size in bytes used by this value in memory (minimum). */
485 size_t size() const;
486
487 template <typename Packer>
msgpack_pack_to_signValue488 void msgpack_pack_to_sign(Packer& pk) const
489 {
490 bool has_owner = owner && *owner;
491 pk.pack_map((user_type.empty()?0:1) + (has_owner?(recipient ? 5 : 4):2));
492 if (has_owner) { // isSigned
493 pk.pack(std::string("seq")); pk.pack(seq);
494 pk.pack(std::string("owner")); owner->msgpack_pack(pk);
495 if (recipient) {
496 pk.pack(std::string("to")); pk.pack(recipient);
497 }
498 }
499 pk.pack(std::string("type")); pk.pack(type);
500 pk.pack(std::string("data")); pk.pack_bin(data.size());
501 pk.pack_bin_body((const char*)data.data(), data.size());
502 if (not user_type.empty()) {
503 pk.pack(std::string("utype")); pk.pack(user_type);
504 }
505 }
506
507 template <typename Packer>
msgpack_pack_to_encryptValue508 void msgpack_pack_to_encrypt(Packer& pk) const
509 {
510 if (isEncrypted()) {
511 pk.pack_bin(cypher.size());
512 pk.pack_bin_body((const char*)cypher.data(), cypher.size());
513 } else {
514 pk.pack_map(isSigned() ? 2 : 1);
515 pk.pack(std::string("body")); msgpack_pack_to_sign(pk);
516 if (isSigned()) {
517 pk.pack(std::string("sig")); pk.pack_bin(signature.size());
518 pk.pack_bin_body((const char*)signature.data(), signature.size());
519 }
520 }
521 }
522
523 template <typename Packer>
msgpack_packValue524 void msgpack_pack(Packer& pk) const
525 {
526 pk.pack_map(2);
527 pk.pack(std::string("id")); pk.pack(id);
528 pk.pack(std::string("dat")); msgpack_pack_to_encrypt(pk);
529 }
530
531 template <typename Packer>
msgpack_pack_fieldsValue532 void msgpack_pack_fields(const std::set<Value::Field>& fields, Packer& pk) const
533 {
534 for (const auto& field : fields)
535 switch (field) {
536 case Value::Field::Id:
537 pk.pack(static_cast<uint64_t>(id));
538 break;
539 case Value::Field::ValueType:
540 pk.pack(static_cast<uint64_t>(type));
541 break;
542 case Value::Field::OwnerPk:
543 if (owner)
544 owner->msgpack_pack(pk);
545 else
546 InfoHash().msgpack_pack(pk);
547 break;
548 case Value::Field::SeqNum:
549 pk.pack(static_cast<uint64_t>(seq));
550 break;
551 case Value::Field::UserType:
552 pk.pack(user_type);
553 break;
554 default:
555 break;
556 }
557 }
558
559 void msgpack_unpack(msgpack::object o);
560 void msgpack_unpack_body(const msgpack::object& o);
getPackedValue561 Blob getPacked() const {
562 msgpack::sbuffer buffer;
563 msgpack::packer<msgpack::sbuffer> pk(&buffer);
564 pk.pack(*this);
565 return {buffer.data(), buffer.data()+buffer.size()};
566 }
567
568 void msgpack_unpack_fields(const std::set<Value::Field>& fields, const msgpack::object& o, unsigned offset);
569
570 Id id {INVALID_ID};
571
572 /**
573 * Public key of the signer.
574 */
575 std::shared_ptr<const crypto::PublicKey> owner {};
576
577 /**
578 * Hash of the recipient (optional).
579 * Should only be present for encrypted values.
580 * Can optionally be present for signed values.
581 */
582 InfoHash recipient {};
583
584 /**
585 * Type of data.
586 */
587 ValueType::Id type {ValueType::USER_DATA.id};
588 Blob data {};
589
590 /**
591 * Custom user-defined type
592 */
593 std::string user_type {};
594
595 /**
596 * Sequence number to avoid replay attacks
597 */
598 uint16_t seq {0};
599
600 /**
601 * Optional signature.
602 */
603 Blob signature {};
604
605 /**
606 * Hold encrypted version of the data.
607 */
608 Blob cypher {};
609
610 private:
611 friend class SecureDht;
612 /* Cache for crypto ops */
613 bool signatureChecked {false};
614 bool signatureValid {false};
615 bool decrypted {false};
616 Sp<Value> decryptedValue {};
617 };
618
619 using ValuesExport = std::pair<InfoHash, Blob>;
620
621 /**
622 * @class FieldValue
623 * @brief Describes a value filter.
624 * @details
625 * This structure holds the value for a specified field. It's type can either be
626 * uint64_t, InfoHash or Blob.
627 */
628 struct OPENDHT_PUBLIC FieldValue
629 {
FieldValueFieldValue630 FieldValue() {}
FieldValueFieldValue631 FieldValue(Value::Field f, uint64_t int_value) : field(f), intValue(int_value) {}
FieldValueFieldValue632 FieldValue(Value::Field f, InfoHash hash_value) : field(f), hashValue(hash_value) {}
FieldValueFieldValue633 FieldValue(Value::Field f, Blob blob_value) : field(f), blobValue(blob_value) {}
634
635 bool operator==(const FieldValue& fd) const;
636
637 // accessors
getFieldFieldValue638 Value::Field getField() const { return field; }
getIntFieldValue639 uint64_t getInt() const { return intValue; }
getHashFieldValue640 InfoHash getHash() const { return hashValue; }
getBlobFieldValue641 Blob getBlob() const { return blobValue; }
642
643 template <typename Packer>
msgpack_packFieldValue644 void msgpack_pack(Packer& p) const {
645 p.pack_map(2);
646 p.pack(std::string("f")); p.pack(static_cast<uint8_t>(field));
647
648 p.pack(std::string("v"));
649 switch (field) {
650 case Value::Field::Id:
651 case Value::Field::ValueType:
652 p.pack(intValue);
653 break;
654 case Value::Field::OwnerPk:
655 p.pack(hashValue);
656 break;
657 case Value::Field::UserType:
658 p.pack_bin(blobValue.size());
659 p.pack_bin_body((const char*)blobValue.data(), blobValue.size());
660 break;
661 default:
662 throw msgpack::type_error();
663 }
664 }
665
msgpack_unpackFieldValue666 void msgpack_unpack(msgpack::object msg) {
667 hashValue = {};
668 blobValue.clear();
669
670 if (auto f = findMapValue(msg, "f"))
671 field = (Value::Field)f->as<unsigned>();
672 else
673 throw msgpack::type_error();
674
675 auto v = findMapValue(msg, "v");
676 if (not v)
677 throw msgpack::type_error();
678 else
679 switch (field) {
680 case Value::Field::Id:
681 case Value::Field::ValueType:
682 intValue = v->as<decltype(intValue)>();
683 break;
684 case Value::Field::OwnerPk:
685 hashValue = v->as<decltype(hashValue)>();
686 break;
687 case Value::Field::UserType:
688 blobValue = unpackBlob(*v);
689 break;
690 default:
691 throw msgpack::type_error();
692 }
693 }
694
695 Value::Filter getLocalFilter() const;
696
697 private:
698 Value::Field field {Value::Field::None};
699 // three possible value types
700 uint64_t intValue {};
701 InfoHash hashValue {};
702 Blob blobValue {};
703 };
704
705 /**
706 * @class Select
707 * @brief Serializable Value field selection.
708 * @details
709 * This is a container for a list of FieldSelectorDescription instances. It
710 * describes a complete SELECT query for dht::Value.
711 */
712 struct OPENDHT_PUBLIC Select
713 {
SelectSelect714 Select() { }
715 Select(const std::string& q_str);
716
717 bool isSatisfiedBy(const Select& os) const;
718
719 /**
720 * Selects a field of type Value::Field.
721 *
722 * @param field the field to require.
723 *
724 * @return the resulting Select instance.
725 */
fieldSelect726 Select& field(Value::Field field) {
727 if (std::find(fieldSelection_.begin(), fieldSelection_.end(), field) == fieldSelection_.end())
728 fieldSelection_.emplace_back(field);
729 return *this;
730 }
731
732 /**
733 * Computes the set of selected fields based on previous require* calls.
734 *
735 * @return the set of fields.
736 */
getSelectionSelect737 std::set<Value::Field> getSelection() const {
738 return {fieldSelection_.begin(), fieldSelection_.end()};
739 }
740
741 template <typename Packer>
msgpack_packSelect742 void msgpack_pack(Packer& pk) const { pk.pack(fieldSelection_); }
msgpack_unpackSelect743 void msgpack_unpack(const msgpack::object& o) {
744 fieldSelection_ = o.as<decltype(fieldSelection_)>();
745 }
746
toStringSelect747 std::string toString() const {
748 std::stringstream ss;
749 ss << *this;
750 return ss.str();
751 }
752
753 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Select& q);
754 private:
755 std::vector<Value::Field> fieldSelection_ {};
756 };
757
758 /**
759 * @class Where
760 * @brief Serializable dht::Value filter.
761 * @details
762 * This is container for a list of FieldValue instances. It describes a
763 * complete WHERE query for dht::Value.
764 */
765 struct OPENDHT_PUBLIC Where
766 {
WhereWhere767 Where() { }
768 Where(const std::string& q_str);
769
770 bool isSatisfiedBy(const Where& where) const;
771
772 /**
773 * Adds restriction on Value::Id based on the id argument.
774 *
775 * @param id the id.
776 *
777 * @return the resulting Where instance.
778 */
idWhere779 Where& id(Value::Id id) {
780 FieldValue fv {Value::Field::Id, id};
781 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
782 filters_.emplace_back(std::move(fv));
783 return *this;
784 }
785
786 /**
787 * Adds restriction on Value::ValueType based on the type argument.
788 *
789 * @param type the value type.
790 *
791 * @return the resulting Where instance.
792 */
valueTypeWhere793 Where& valueType(ValueType::Id type) {
794 FieldValue fv {Value::Field::ValueType, type};
795 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
796 filters_.emplace_back(std::move(fv));
797 return *this;
798 }
799
800 /**
801 * Adds restriction on Value::OwnerPk based on the owner_pk_hash argument.
802 *
803 * @param owner_pk_hash the owner public key fingerprint.
804 *
805 * @return the resulting Where instance.
806 */
ownerWhere807 Where& owner(InfoHash owner_pk_hash) {
808 FieldValue fv {Value::Field::OwnerPk, owner_pk_hash};
809 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
810 filters_.emplace_back(std::move(fv));
811 return *this;
812 }
813
814 /**
815 * Adds restriction on Value::OwnerPk based on the owner_pk_hash argument.
816 *
817 * @param owner_pk_hash the owner public key fingerprint.
818 *
819 * @return the resulting Where instance.
820 */
seqWhere821 Where& seq(uint16_t seq_no) {
822 FieldValue fv {Value::Field::SeqNum, seq_no};
823 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
824 filters_.emplace_back(std::move(fv));
825 return *this;
826 }
827
828 /**
829 * Adds restriction on Value::UserType based on the user_type argument.
830 *
831 * @param user_type the user type.
832 *
833 * @return the resulting Where instance.
834 */
userTypeWhere835 Where& userType(std::string user_type) {
836 FieldValue fv {Value::Field::UserType, Blob {user_type.begin(), user_type.end()}};
837 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
838 filters_.emplace_back(std::move(fv));
839 return *this;
840 }
841
842 /**
843 * Computes the Value::Filter based on the list of field value set.
844 *
845 * @return the resulting Value::Filter.
846 */
getFilterWhere847 Value::Filter getFilter() const {
848 if (filters_.empty()) return {};
849 std::vector<Value::Filter> fset;
850 fset.reserve(filters_.size());
851 for (const auto& f : filters_) {
852 if (auto lf = f.getLocalFilter())
853 fset.emplace_back(std::move(lf));
854 }
855 return Value::Filter::chainAll(std::move(fset));
856 }
857
858 template <typename Packer>
msgpack_packWhere859 void msgpack_pack(Packer& pk) const { pk.pack(filters_); }
msgpack_unpackWhere860 void msgpack_unpack(const msgpack::object& o) {
861 filters_.clear();
862 filters_ = o.as<decltype(filters_)>();
863 }
864
toStringWhere865 std::string toString() const {
866 std::stringstream ss;
867 ss << *this;
868 return ss.str();
869 }
870
emptyWhere871 bool empty() const {
872 return filters_.empty();
873 }
874
875 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Where& q);
876
877 private:
878 std::vector<FieldValue> filters_;
879 };
880
881 /**
882 * @class Query
883 * @brief Describes a query destined to another peer.
884 * @details
885 * This class describes the list of filters on field values and the field
886 * itselves to include in the peer response to a GET operation. See
887 * FieldValue.
888 */
889 struct OPENDHT_PUBLIC Query
890 {
891 static const std::string QUERY_PARSE_ERROR;
892
selectQuery893 Query(Select s = {}, Where w = {}, bool none = false) : select(std::move(s)), where(std::move(w)), none(none) { };
894
895 /**
896 * Initializes a query based on a SQL-ish formatted string. The abstract
897 * form of such a string is the following:
898 *
899 * [SELECT $field$ [WHERE $field$=$value$]]
900 *
901 * where
902 *
903 * - $field$ = *|id|value_type|owner_pk|user_type
904 * - $value$ = $string$|$integer$
905 * - $string$: a simple string WITHOUT SPACES.
906 * - $integer$: a simple integer.
907 */
QueryQuery908 Query(std::string q_str) {
909 auto pos_W = q_str.find("WHERE");
910 auto pos_w = q_str.find("where");
911 auto pos = std::min(pos_W != std::string::npos ? pos_W : q_str.size(),
912 pos_w != std::string::npos ? pos_w : q_str.size());
913 select = q_str.substr(0, pos);
914 where = q_str.substr(pos, q_str.size()-pos);
915 }
916
917 /**
918 * Tell if the query is satisfied by another query.
919 */
920 bool isSatisfiedBy(const Query& q) const;
921
922 template <typename Packer>
msgpack_packQuery923 void msgpack_pack(Packer& pk) const {
924 pk.pack_map(2);
925 pk.pack(std::string("s")); pk.pack(select); /* packing field selectors */
926 pk.pack(std::string("w")); pk.pack(where); /* packing filters */
927 }
928
929 void msgpack_unpack(const msgpack::object& o);
930
toStringQuery931 std::string toString() const {
932 std::stringstream ss;
933 ss << *this;
934 return ss.str();
935 }
936
937 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Query& q) {
938 return s << "Query[" << q.select << " " << q.where << "]";
939 }
940
941 Select select {};
942 Where where {};
943 bool none {false}; /* When true, any query satisfies this. */
944 };
945
946 /*!
947 * @class FieldValueIndex
948 * @brief An index for field values.
949 * @details
950 * This structures is meant to manipulate a subset of fields normally contained
951 * in Value.
952 */
953 struct OPENDHT_PUBLIC FieldValueIndex {
FieldValueIndexFieldValueIndex954 FieldValueIndex() {}
955 FieldValueIndex(const Value& v, const Select& s = {});
956 /**
957 * Tells if all the fields of this are contained in the other
958 * FieldValueIndex with the same value.
959 *
960 * @param other The other FieldValueIndex instance.
961 */
962 bool containedIn(const FieldValueIndex& other) const;
963
964 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& os, const FieldValueIndex& fvi);
965
966 void msgpack_unpack_fields(const std::set<Value::Field>& fields,
967 const msgpack::object& o,
968 unsigned offset);
969
970 std::map<Value::Field, FieldValue> index {};
971 };
972
973 template <typename T,
974 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
975 Value::Filter
getFilterSet(Value::Filter f)976 getFilterSet(Value::Filter f)
977 {
978 return Value::Filter::chain({
979 Value::TypeFilter(T::TYPE),
980 T::getFilter(),
981 f
982 });
983 }
984
985 template <typename T,
986 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
987 Value::Filter
getFilterSet(Value::Filter f)988 getFilterSet(Value::Filter f)
989 {
990 return f;
991 }
992
993 template <typename T,
994 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
995 Value::Filter
getFilterSet()996 getFilterSet()
997 {
998 return Value::Filter::chain({
999 Value::TypeFilter(T::TYPE),
1000 T::getFilter()
1001 });
1002 }
1003
1004 template <typename T,
1005 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1006 Value::Filter
getFilterSet()1007 getFilterSet()
1008 {
1009 return {};
1010 }
1011
1012 template <class T>
1013 std::vector<T>
unpackVector(const std::vector<std::shared_ptr<Value>> & vals)1014 unpackVector(const std::vector<std::shared_ptr<Value>>& vals) {
1015 std::vector<T> ret;
1016 ret.reserve(vals.size());
1017 for (const auto& v : vals) {
1018 try {
1019 ret.emplace_back(Value::unpack<T>(*v));
1020 } catch (const std::exception&) {}
1021 }
1022 return ret;
1023 }
1024
1025 #ifdef OPENDHT_JSONCPP
1026 uint64_t unpackId(const Json::Value& json, const std::string& key);
1027 #endif
1028
1029 }
1030
1031 MSGPACK_ADD_ENUM(dht::Value::Field)
1032