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