12#if defined(__FreeBSD__)
13#include <sys/socket.h>
14#include <netinet/in.h>
34using namespace std::literals;
36static constexpr auto VALUE_KEY_ID(
"id");
37static const std::string VALUE_KEY_DAT(
"dat");
38static const std::string VALUE_KEY_PRIO(
"p");
39static const std::string VALUE_KEY_PUSHTYPE(
"pt");
40static const std::string VALUE_KEY_SIGNATURE(
"sig");
42static const std::string VALUE_KEY_SEQ(
"seq");
43static const std::string VALUE_KEY_DATA(
"data");
44static const std::string VALUE_KEY_OWNER(
"owner");
45static const std::string VALUE_KEY_TYPE(
"type");
46static const std::string VALUE_KEY_TO(
"to");
47static const std::string VALUE_KEY_BODY(
"body");
48static const std::string VALUE_KEY_USERTYPE(
"utype");
64 = std::function<bool(InfoHash key, std::shared_ptr<Value>& value,
const InfoHash& from,
const SockAddr& addr)>;
80using EditPolicy = std::function<bool(InfoHash key,
81 const std::shared_ptr<Value>& old_val,
82 std::shared_ptr<Value>& new_val,
86static constexpr const size_t MAX_VALUE_SIZE {1024 * 64};
87static constexpr const duration DEFAULT_VALUE_EXPIRATION {std::chrono::minutes(10)};
93 OPENDHT_PUBLIC
static bool DEFAULT_STORE_POLICY(InfoHash,
94 const std::shared_ptr<Value>& v,
97 static inline bool DEFAULT_EDIT_POLICY(
98 InfoHash,
const std::shared_ptr<Value>&, std::shared_ptr<Value>&,
const InfoHash&,
const SockAddr&)
105 ValueType(Id
id, std::string name, duration e = DEFAULT_VALUE_EXPIRATION)
119 virtual ~ValueType() {}
121 bool operator==(
const ValueType& o) {
return id == o.id; }
124 OPENDHT_PUBLIC
static const ValueType USER_DATA;
128 duration expiration {DEFAULT_VALUE_EXPIRATION};
136 void registerType(
const ValueType& type) { types[type.id] = type; }
137 const ValueType& getType(ValueType::Id type_id)
const
139 const auto& t_it = types.find(type_id);
140 return (t_it == types.end()) ? ValueType::USER_DATA : t_it->second;
144 std::map<ValueType::Id, ValueType> types {};
156struct OPENDHT_PUBLIC Value
158 enum class Field :
int {
170 static const constexpr Id INVALID_ID {0};
172 class Filter :
public std::function<bool(const Value&)>
177 template<
typename Functor>
179 : std::function<bool(
const Value&)>::function(f)
182 inline Filter chain(Filter&& f2)
185 return chain(std::move(f1), std::move(f2));
187 inline Filter chainOr(Filter&& f2)
190 return chainOr(std::move(f1), std::move(f2));
192 static inline Filter chain(Filter&& f1, Filter&& f2)
195 return std::move(f2);
197 return std::move(f1);
198 return [f1 = std::move(f1), f2 = std::move(f2)](
const Value& v) {
199 return f1(v) and f2(v);
202 static inline Filter chain(
const Filter& f1,
const Filter& f2)
208 return [f1, f2](
const Value& v) {
209 return f1(v) and f2(v);
212 static inline Filter chainAll(std::vector<Filter>&& set)
216 return [set = std::move(set)](
const Value& v) {
217 for (
const auto& f : set)
223 static inline Filter chain(std::initializer_list<Filter> l)
225 return chainAll(std::vector<Filter>(l.begin(), l.end()));
227 static inline Filter chainOr(Filter&& f1, Filter&& f2)
229 if (not f1 or not f2)
231 return [f1 = std::move(f1), f2 = std::move(f2)](
const Value& v) {
232 return f1(v) or f2(v);
235 static inline Filter notFilter(Filter&& f)
238 return [](
const Value&) {
241 return [f = std::move(f)](
const Value& v) {
245 std::vector<Sp<Value>> filter(
const std::vector<Sp<Value>>& values)
249 std::vector<Sp<Value>> ret;
250 for (
const auto& v : values)
259 static inline Filter AllFilter() {
return {}; }
261 static inline Filter TypeFilter(
const ValueType& t)
263 return [tid = t.id](
const Value& v) {
264 return v.type == tid;
267 static inline Filter TypeFilter(
const ValueType::Id& tid)
269 return [tid](
const Value& v) {
270 return v.type == tid;
274 static inline Filter IdFilter(
const Id
id)
276 return [id](
const Value& v) {
281 static inline Filter RecipientFilter(
const InfoHash& r)
283 return [r](
const Value& v) {
284 return v.recipient == r;
288 static inline Filter OwnerFilter(
const crypto::PublicKey& pk) {
return OwnerFilter(pk.getId()); }
290 static inline Filter OwnerFilter(
const InfoHash& pkh)
292 return [pkh](
const Value& v) {
293 return v.owner and v.owner->getId() == pkh;
297 static inline Filter SeqNumFilter(uint16_t seq_no)
299 return [seq_no](
const Value& v) {
300 return v.seq == seq_no;
304 static inline Filter UserTypeFilter(std::string ut)
306 return [ut = std::move(ut)](
const Value& v) {
307 return v.user_type == ut;
311 class SerializableBase
314 SerializableBase() {}
315 virtual ~SerializableBase() {};
316 virtual const ValueType& getType()
const = 0;
317 virtual void unpackValue(
const Value& v) = 0;
318 virtual Value packValue()
const = 0;
321 template<
typename Derived,
typename Base = SerializableBase>
327 virtual const ValueType& getType()
const {
return Derived::TYPE; }
329 virtual void unpackValue(
const Value& v)
331 auto msg = msgpack::unpack((
const char*) v.data.data(), v.data.size());
332 msg.get().convert(*
static_cast<Derived*
>(
this));
335 virtual Value packValue()
const {
return Value {getType(),
static_cast<const Derived&
>(*this)}; }
338 template<typename T, typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>
::type* =
nullptr>
339 static Value pack(
const T& obj)
341 return obj.packValue();
344 template<typename T, typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* =
nullptr>
345 static Value pack(
const T& obj)
347 return {ValueType::USER_DATA.id, packMsg<T>(obj)};
350 template<typename T, typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* =
nullptr>
351 static T unpack(
const Value& v)
358 template<typename T, typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* =
nullptr>
359 static T unpack(
const Value& v)
361 return unpackMsg<T>(v.data);
367 return unpack<T>(*
this);
370 inline bool isEncrypted()
const {
return not cypher.empty(); }
371 inline bool isSigned()
const {
return owner and not signature.empty(); }
386 inline std::shared_ptr<crypto::PublicKey> getOwner()
const {
return owner; }
400 Value(ValueType::Id t,
const Blob& data, Id
id = INVALID_ID)
405 Value(ValueType::Id t,
Blob&& data, Id
id = INVALID_ID)
408 , data(std::move(data))
410 Value(ValueType::Id t,
const uint8_t* dat_ptr,
size_t dat_len, Id
id = INVALID_ID)
413 , data(dat_ptr, dat_ptr + dat_len)
416#ifdef OPENDHT_JSONCPP
421 Value(
const Json::Value& json);
424 template<
typename Type>
425 Value(ValueType::Id t,
const Type& d, Id
id = INVALID_ID)
431 template<
typename Type>
432 Value(
const ValueType& t,
const Type& d, Id
id = INVALID_ID)
439 Value(
const Blob& userdata)
443 : data(std::move(userdata))
445 Value(
const uint8_t* dat_ptr,
size_t dat_len)
446 : data(dat_ptr, dat_ptr + dat_len)
449 Value(Value&& o) noexcept
451 , owner(std::move(o.owner))
452 , recipient(o.recipient)
454 , data(std::move(o.data))
455 , user_type(std::move(o.user_type))
457 , signature(std::move(o.signature))
458 , cypher(std::move(o.cypher))
459 , priority(o.priority)
460 , pushType(std::move(o.pushType))
463 template<
typename Type>
464 Value(
const Type& vs)
465 : Value(pack<Type>(vs))
471 Value(
const msgpack::object& o) { msgpack_unpack(o); }
483 inline bool operator==(
const Value& o)
const {
return id == o.id and contentEquals(o); }
484 inline bool operator!=(
const Value& o)
const {
return !(*
this == o); }
486 inline void setRecipient(
const InfoHash& r) { recipient = r; }
488 inline void setCypher(Blob&& c) { cypher = std::move(c); }
495 msgpack::sbuffer buffer;
496 msgpack::packer<msgpack::sbuffer> pk(&buffer);
497 msgpack_pack_to_sign(pk);
498 return {buffer.data(), buffer.data() + buffer.size()};
506 msgpack::sbuffer buffer;
507 msgpack::packer<msgpack::sbuffer> pk(&buffer);
508 msgpack_pack_to_encrypt(pk);
509 return {buffer.data(), buffer.data() + buffer.size()};
513 OPENDHT_PUBLIC
friend std::ostream&
operator<<(std::ostream& s,
const Value& v);
515 inline std::string toString()
const
517 std::ostringstream ss;
522#ifdef OPENDHT_JSONCPP
531 Json::Value toJson()
const;
537 template<
typename Packer>
538 void msgpack_pack_to_sign(Packer& pk)
const
543 pk.pack(VALUE_KEY_SEQ);
545 pk.pack(VALUE_KEY_OWNER);
546 owner->msgpack_pack(pk);
548 pk.pack(VALUE_KEY_TO);
552 pk.pack(VALUE_KEY_TYPE);
554 pk.pack(VALUE_KEY_DATA);
555 pk.pack_bin(data.size());
556 pk.pack_bin_body((
const char*) data.data(), data.size());
557 if (not user_type.empty()) {
558 pk.pack(VALUE_KEY_USERTYPE);
563 template<
typename Packer>
564 void msgpack_pack_to_encrypt(Packer& pk)
const
567 pk.pack_bin(cypher.size());
568 pk.pack_bin_body((
const char*) cypher.data(), cypher.size());
570 pk.pack_map(isSigned() ? 2 : 1);
571 pk.pack(VALUE_KEY_BODY);
572 msgpack_pack_to_sign(pk);
574 pk.pack(VALUE_KEY_SIGNATURE);
575 pk.pack_bin(signature.size());
576 pk.pack_bin_body((
const char*) signature.data(), signature.size());
581 template<
typename Packer>
582 void msgpack_pack(Packer& pk)
const
584 pk.pack_map(2 + (priority ? 1 : 0) + (!pushType.empty() ? 1 : 0));
585 pk.pack(VALUE_KEY_ID);
587 pk.pack(VALUE_KEY_DAT);
588 msgpack_pack_to_encrypt(pk);
590 pk.pack(VALUE_KEY_PRIO);
593 if (!pushType.empty()) {
594 pk.pack(VALUE_KEY_PUSHTYPE);
599 template<
typename Packer>
600 void msgpack_pack_fields(
const std::set<Value::Field>& fields, Packer& pk)
const
602 for (
const auto& field : fields)
604 case Value::Field::Id:
605 pk.pack(
static_cast<uint64_t
>(
id));
607 case Value::Field::ValueType:
608 pk.pack(
static_cast<uint64_t
>(type));
610 case Value::Field::OwnerPk:
612 owner->msgpack_pack(pk);
614 InfoHash().msgpack_pack(pk);
616 case Value::Field::SeqNum:
617 pk.pack(
static_cast<uint64_t
>(seq));
619 case Value::Field::UserType:
627 void msgpack_unpack(
const msgpack::object& o);
628 void msgpack_unpack_body(
const msgpack::object& o);
629 Blob getPacked()
const
631 msgpack::sbuffer buffer;
632 msgpack::packer<msgpack::sbuffer> pk(&buffer);
634 return {buffer.data(), buffer.data() + buffer.size()};
637 void msgpack_unpack_fields(
const std::set<Value::Field>& fields,
const msgpack::object& o,
unsigned offset);
644 std::shared_ptr<crypto::PublicKey>
owner {};
656 ValueType::Id
type {ValueType::USER_DATA.id};
693 inline bool isSignatureChecked()
const {
return signatureChecked; }
694 inline bool isDecrypted()
const {
return decrypted; }
695 bool checkSignature();
696 Sp<Value> decrypt(
const crypto::PrivateKey& key);
700 bool signatureChecked {
false};
701 bool signatureValid {
false};
702 bool decrypted {
false};
703 Sp<Value> decryptedValue {};
706using ValuesExport = std::pair<InfoHash, Blob>;
715struct OPENDHT_PUBLIC FieldValue
718 FieldValue(Value::Field f, uint64_t int_value)
720 , intValue(int_value)
722 FieldValue(Value::Field f, InfoHash hash_value)
724 , hashValue(hash_value)
726 FieldValue(Value::Field f,
Blob blob_value)
728 , blobValue(std::move(blob_value))
731 bool operator==(
const FieldValue& fd)
const;
734 Value::Field getField()
const {
return field; }
735 uint64_t getInt()
const {
return intValue; }
736 InfoHash getHash()
const {
return hashValue; }
737 Blob getBlob()
const {
return blobValue; }
739 template<
typename Packer>
740 void msgpack_pack(Packer& p)
const
744 p.pack(
static_cast<uint8_t
>(field));
748 case Value::Field::Id:
749 case Value::Field::ValueType:
752 case Value::Field::OwnerPk:
755 case Value::Field::UserType:
756 p.pack_bin(blobValue.size());
757 p.pack_bin_body((
const char*) blobValue.data(), blobValue.size());
760 throw msgpack::type_error();
764 void msgpack_unpack(
const msgpack::object& msg)
769 if (
auto f = findMapValue(msg,
"f"sv))
770 field = (Value::Field) f->as<
unsigned>();
772 throw msgpack::type_error();
774 auto v = findMapValue(msg,
"v"sv);
776 throw msgpack::type_error();
779 case Value::Field::Id:
780 case Value::Field::ValueType:
781 intValue = v->as<
decltype(intValue)>();
783 case Value::Field::OwnerPk:
784 hashValue = v->as<
decltype(hashValue)>();
786 case Value::Field::UserType:
790 throw msgpack::type_error();
797 Value::Field field {Value::Field::None};
799 uint64_t intValue {};
800 InfoHash hashValue {};
811struct OPENDHT_PUBLIC Select
814 Select(std::string_view q_str);
816 bool isSatisfiedBy(
const Select& os)
const;
827 if (std::find(fieldSelection_.begin(), fieldSelection_.end(),
field) == fieldSelection_.end())
828 fieldSelection_.emplace_back(
field);
837 std::set<Value::Field>
getSelection()
const {
return {fieldSelection_.begin(), fieldSelection_.end()}; }
839 template<
typename Packer>
840 void msgpack_pack(Packer& pk)
const
842 pk.pack(fieldSelection_);
844 void msgpack_unpack(
const msgpack::object& o) { fieldSelection_ = o.as<
decltype(fieldSelection_)>(); }
846 std::string toString()
const
848 std::ostringstream ss;
853 bool empty()
const {
return fieldSelection_.empty(); }
855 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& s,
const dht::Select& q);
858 std::vector<Value::Field> fieldSelection_ {};
868struct OPENDHT_PUBLIC Where
871 Where(std::string_view q_str);
873 bool isSatisfiedBy(
const Where& where)
const;
882 Where&&
id(Value::Id
id)
885 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
886 filters_.emplace_back(std::move(fv));
887 return std::move(*
this);
899 FieldValue fv {Value::Field::ValueType, type};
900 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
901 filters_.emplace_back(std::move(fv));
902 return std::move(*
this);
912 Where&&
owner(InfoHash owner_pk_hash)
914 FieldValue fv {Value::Field::OwnerPk, owner_pk_hash};
915 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
916 filters_.emplace_back(std::move(fv));
917 return std::move(*
this);
927 Where&&
seq(uint16_t seq_no)
930 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
931 filters_.emplace_back(std::move(fv));
932 return std::move(*
this);
942 Where&&
userType(std::string_view user_type)
945 Value::Field::UserType,
Blob {user_type.begin(), user_type.end()}
947 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
948 filters_.emplace_back(std::move(fv));
949 return std::move(*
this);
959 if (filters_.empty())
961 if (filters_.size() == 1)
962 return filters_[0].getLocalFilter();
963 std::vector<Value::Filter> fset;
964 fset.reserve(filters_.size());
965 for (
const auto& f : filters_) {
966 if (
auto lf = f.getLocalFilter())
967 fset.emplace_back(std::move(lf));
969 return Value::Filter::chainAll(std::move(fset));
972 template<
typename Packer>
973 void msgpack_pack(Packer& pk)
const
977 void msgpack_unpack(
const msgpack::object& o)
980 filters_ = o.as<
decltype(filters_)>();
983 std::string toString()
const
985 std::ostringstream ss;
990 bool empty()
const {
return filters_.empty(); }
992 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& s,
const dht::Where& q);
995 std::vector<FieldValue> filters_;
1006struct OPENDHT_PUBLIC Query
1008 static const std::string QUERY_PARSE_ERROR;
1010 Query(
Select s = {},
Where w = {},
bool none =
false)
1011 : select(std::move(s))
1012 , where(std::move(w))
1028 Query(std::string_view q_str)
1030 auto pos_W = q_str.find(
"WHERE");
1031 auto pos_w = q_str.find(
"where");
1032 auto pos = std::min(pos_W != std::string_view::npos ? pos_W : q_str.size(),
1033 pos_w != std::string_view::npos ? pos_w : q_str.size());
1034 select = q_str.substr(0, pos);
1035 where = q_str.substr(pos, q_str.size() - pos);
1043 template<
typename Packer>
1044 void msgpack_pack(Packer& pk)
const
1053 void msgpack_unpack(
const msgpack::object& o);
1055 std::string toString()
const
1057 std::ostringstream ss;
1062 friend std::ostream& operator<<(std::ostream& s,
const dht::Query& q)
1064 return s <<
"Query[" << q.select <<
" " << q.where <<
"]";
1079struct OPENDHT_PUBLIC FieldValueIndex
1081 FieldValueIndex() {}
1082 FieldValueIndex(
const Value& v,
const Select& s = {});
1089 bool containedIn(
const FieldValueIndex& other)
const;
1091 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& os,
const FieldValueIndex& fvi);
1093 void msgpack_unpack_fields(
const std::set<Value::Field>& fields,
const msgpack::object& o,
unsigned offset);
1095 std::map<Value::Field, FieldValue> index {};
1098template<typename T, typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
1100getFilterSet(Value::Filter f)
1102 return Value::Filter::chain({Value::TypeFilter(T::TYPE), T::getFilter(), std::move(f)});
1105template<typename T, typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
1112template<typename T, typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
1116 return Value::Filter::chain({Value::TypeFilter(T::TYPE), T::getFilter()});
1119template<typename T, typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
1128unpackVector(
const std::vector<std::shared_ptr<Value>>& vals)
1131 ret.reserve(vals.size());
1132 for (
const auto& v : vals) {
1134 ret.emplace_back(Value::unpack<T>(*v));
1135 }
catch (
const std::exception&) {
1141#ifdef OPENDHT_JSONCPP
1142uint64_t unpackId(
const Json::Value& json,
const std::string& key);
1147MSGPACK_ADD_ENUM(dht::Value::Field)
std::function< bool(InfoHash key, std::shared_ptr< Value > &value, const InfoHash &from, const SockAddr &addr)> StorePolicy
OPENDHT_PUBLIC Blob unpackBlob(const msgpack::object &o)
std::vector< uint8_t > Blob
std::function< bool(InfoHash key, const std::shared_ptr< Value > &old_val, std::shared_ptr< Value > &new_val, const InfoHash &from, const SockAddr &addr)> EditPolicy
bool containedIn(const FieldValueIndex &other) const
Describes a value filter.
Describes a query destined to another peer.
bool isSatisfiedBy(const Query &q) const
Serializable Value field selection.
std::set< Value::Field > getSelection() const
Select & field(Value::Field field)
bool contentEquals(const Value &o) const
bool checkSignature() const
std::shared_ptr< crypto::PublicKey > owner
Value encrypt(const crypto::PrivateKey &from, const crypto::PublicKey &to)
OPENDHT_PUBLIC friend std::ostream & operator<<(std::ostream &s, const Value &v)
Blob getToEncrypt() const
void sign(const crypto::PrivateKey &key)
Serializable dht::Value filter.
Value::Filter getFilter() const
Where && userType(std::string_view user_type)
Where && seq(uint16_t seq_no)
Where && id(Value::Id id)
Where && valueType(ValueType::Id type)
Where && owner(InfoHash owner_pk_hash)