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