C++ Distributed Hash Table
default_types.h
1 /*
2  * Copyright (C) 2014-2022 Savoir-faire Linux Inc.
3  * Author : Adrien BĂ©raud <adrien.beraud@savoirfairelinux.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include "value.h"
22 #include "sockaddr.h"
23 
24 namespace dht {
25 enum class ImStatus : uint8_t {
26  NONE = 0,
27  TYPING,
28  RECEIVED,
29  READ
30 };
31 }
32 MSGPACK_ADD_ENUM(dht::ImStatus)
33 
34 namespace dht {
35 
36 class OPENDHT_PUBLIC DhtMessage : public Value::Serializable<DhtMessage>
37 {
38 public:
39  static const ValueType TYPE;
40 
41  DhtMessage(const std::string& s = {}, const Blob& msg = {}) : service(s), data(msg) {}
42 
43  std::string getService() const {
44  return service;
45  }
46 
47  static Value::Filter getFilter() { return {}; }
48 
49  static bool storePolicy(InfoHash key, std::shared_ptr<Value>& value, const InfoHash& from, const SockAddr&);
50 
51  static Value::Filter ServiceFilter(const std::string& s);
52 
54  friend std::ostream& operator<< (std::ostream&, const DhtMessage&);
55 
56  std::string service;
57  Blob data;
58  MSGPACK_DEFINE(service, data)
59 };
60 
61 template <typename T>
62 class OPENDHT_PUBLIC SignedValue : public Value::Serializable<T>
63 {
64 private:
66 
67 public:
68  virtual void unpackValue(const Value& v) override {
69  if (v.owner) {
70  owner = v.owner;
71  from = v.owner->getId();
72  }
73  BaseClass::unpackValue(v);
74  }
75 
76  static Value::Filter getFilter() {
77  return [](const Value& v){ return v.isSigned(); };
78  }
79 
80  Sp<crypto::PublicKey> owner;
81  dht::InfoHash from;
82 };
83 
84 template <typename T>
85 class OPENDHT_PUBLIC EncryptedValue : public SignedValue<T>
86 {
87 public:
88  using BaseClass = SignedValue<T>;
89 
90 public:
91  virtual void unpackValue(const Value& v) override {
92  to = v.recipient;
93  BaseClass::unpackValue(v);
94  }
95 
96  static Value::Filter getFilter() {
97  return Value::Filter::chain(
98  BaseClass::getFilter(),
99  [](const Value& v) { return static_cast<bool>(v.recipient); }
100  );
101  }
102 
103  dht::InfoHash to;
104 };
105 
106 
107 
108 
109 class OPENDHT_PUBLIC ImMessage : public SignedValue<ImMessage>
110 {
111 private:
113 
114 public:
115  static const ValueType TYPE;
116 
117  ImMessage() {}
118  ImMessage(dht::Value::Id id, std::string&& m, long d = 0)
119  : id(id), msg(std::move(m)), date(d) {}
120  ImMessage(dht::Value::Id id, std::string &&dt, std::string &&m, long d = 0)
121  : id(id), msg(std::move(m)), datatype(std::move(dt)), date(d) {}
122  ImMessage(dht::Value::Id id, std::string &&dt, std::string &&m, std::map<std::string, std::string> &&md, long d = 0)
123  : id(id), msg(std::move(m)), datatype(std::move(dt)), metadatas(std::move(md)), date(d) {}
124 
125  virtual void unpackValue(const Value& v) override {
126  to = v.recipient;
127  SignedValue::unpackValue(v);
128  }
129 
130  dht::InfoHash to;
131  dht::Value::Id id {0};
132  std::string msg;
133  std::string datatype;
134  std::map<std::string, std::string> metadatas;
135  long date {0};
136  ImStatus status {ImStatus::NONE};
137 
138  MSGPACK_DEFINE_MAP(id, msg, date, status, datatype, metadatas)
139 };
140 
141 class OPENDHT_PUBLIC TrustRequest : public EncryptedValue<TrustRequest>
142 {
143 private:
145 
146 public:
147  static const ValueType TYPE;
148 
149  TrustRequest() {}
150  TrustRequest(std::string s, std::string ci = {}) : service(s), conversationId(ci) {}
151  TrustRequest(std::string s, std::string ci, const Blob& d) : service(s), conversationId(ci), payload(d) {}
152 
153  static Value::Filter getFilter() {
154  return EncryptedValue::getFilter();
155  }
156 
157  std::string service;
158  std::string conversationId;
159  Blob payload;
160  bool confirm {false};
161  MSGPACK_DEFINE_MAP(service, conversationId, payload, confirm)
162 };
163 
164 class OPENDHT_PUBLIC IceCandidates : public EncryptedValue<IceCandidates>
165 {
166 private:
168 
169 public:
170  static const ValueType TYPE;
171 
172  IceCandidates() {}
173  IceCandidates(Value::Id msg_id, Blob ice) : id(msg_id), ice_data(ice) {}
174 
175  static Value::Filter getFilter() {
176  return EncryptedValue::getFilter();
177  }
178 
179  template <typename Packer>
180  void msgpack_pack(Packer& pk) const
181  {
182  pk.pack_array(2);
183  pk.pack(id);
184 #if 1
185  pk.pack_bin(ice_data.size());
186  pk.pack_bin_body((const char*)ice_data.data(), ice_data.size());
187 #else
188  // hack for backward compatibility with old opendht compiled with msgpack 1.0
189  // remove when enough people have moved to new versions
190  pk.pack_array(ice_data.size());
191  for (uint8_t b : ice_data)
192  pk.pack(b);
193 #endif
194  }
195 
196  virtual void msgpack_unpack(const msgpack::object& o)
197  {
198  if (o.type != msgpack::type::ARRAY) throw msgpack::type_error();
199  if (o.via.array.size < 2) throw msgpack::type_error();
200  id = o.via.array.ptr[0].as<Value::Id>();
201  ice_data = unpackBlob(o.via.array.ptr[1]);
202  }
203 
204  Value::Id id {0};
205  Blob ice_data;
206 };
207 
208 /* "Peer" announcement
209  */
210 class OPENDHT_PUBLIC IpServiceAnnouncement : public Value::Serializable<IpServiceAnnouncement>
211 {
212 private:
214 
215 public:
216  static const ValueType TYPE;
217 
218  IpServiceAnnouncement(sa_family_t family = AF_UNSPEC, in_port_t p = 0) {
219  addr.setFamily(family);
220  addr.setPort(p);
221  }
222 
223  IpServiceAnnouncement(const SockAddr& sa) : addr(sa) {}
224 
225  IpServiceAnnouncement(const Blob& b) {
226  msgpack_unpack(unpackMsg(b).get());
227  }
228 
229  template <typename Packer>
230  void msgpack_pack(Packer& pk) const
231  {
232  pk.pack_bin(addr.getLength());
233  pk.pack_bin_body((const char*)addr.get(), addr.getLength());
234  }
235 
236  virtual void msgpack_unpack(const msgpack::object& o)
237  {
238  if (o.type == msgpack::type::BIN)
239  addr = {(sockaddr*)o.via.bin.ptr, (socklen_t)o.via.bin.size};
240  else
241  throw msgpack::type_error();
242  }
243 
244  in_port_t getPort() const {
245  return addr.getPort();
246  }
247  void setPort(in_port_t p) {
248  addr.setPort(p);
249  }
250 
251  const SockAddr& getPeerAddr() const {
252  return addr;
253  }
254 
255  virtual const ValueType& getType() const {
256  return TYPE;
257  }
258 
259  static bool storePolicy(InfoHash, std::shared_ptr<Value>&, const InfoHash&, const SockAddr&);
260 
262  friend std::ostream& operator<< (std::ostream&, const IpServiceAnnouncement&);
263 
264 private:
265  SockAddr addr;
266 };
267 
268 
269 OPENDHT_PUBLIC extern const std::array<std::reference_wrapper<const ValueType>, 5> DEFAULT_TYPES;
270 
271 OPENDHT_PUBLIC extern const std::array<std::reference_wrapper<const ValueType>, 1> DEFAULT_INSECURE_TYPES;
272 
273 }
OPENDHT_PUBLIC Blob unpackBlob(const msgpack::object &o)
std::shared_ptr< crypto::PublicKey > owner
Definition: value.h:599
std::vector< uint8_t > Blob
Definition: utils.h:151
InfoHash recipient
Definition: value.h:606
Definition: callbacks.h:35