C++ Distributed Hash Table
node.h
1 /*
2  * Copyright (C) 2014-2017 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" // includes socket structures
23 #include "utils.h"
24 #include "sockaddr.h"
25 
26 #include <list>
27 #include <map>
28 
29 namespace dht {
30 
31 struct Node;
32 namespace net {
33 struct Request;
34 struct Socket;
35 struct RequestAnswer;
36 } /* namespace net */
37 
38 using Tid = uint32_t;
39 using SocketCb = std::function<void(const Sp<Node>&, net::RequestAnswer&&)>;
40 struct Socket {
41  Socket() {}
42  Socket(SocketCb&& on_receive) :
43  on_receive(std::move(on_receive)) {}
44  SocketCb on_receive {};
45 };
46 
47 struct Node {
48  const InfoHash id;
49 
50  Node(const InfoHash& id, const SockAddr& addr, bool client=false);
51  Node(const InfoHash& id, const sockaddr* sa, socklen_t salen)
52  : Node(id, SockAddr(sa, salen)) {}
53 
54  InfoHash getId() const {
55  return id;
56  }
57  const SockAddr& getAddr() const { return addr; }
58  std::string getAddrStr() const {
59  return addr.toString();
60  }
61  bool isClient() const { return is_client; }
62  bool isIncoming() { return time > reply_time; }
63 
64  const time_point& getTime() const { return time; }
65  const time_point& getReplyTime() const { return reply_time; }
66  void setTime(const time_point& t) { time = t; }
67 
73  void authError() {
74  if (++auth_errors > MAX_AUTH_ERRORS)
75  setExpired();
76  }
77  void authSuccess() { auth_errors = 0; }
78 
79  bool isExpired() const { return expired_; }
80  bool isGood(time_point now) const;
81  bool isPendingMessage() const;
82  size_t getPendingMessageCount() const;
83 
84  bool isOld(const time_point& now) const {
85  return time + NODE_EXPIRE_TIME < now;
86  }
87  bool isRemovable(const time_point& now) const {
88  return isExpired() and isOld(now);
89  }
90 
91  NodeExport exportNode() const {
92  NodeExport ne;
93  ne.id = id;
94  ne.sslen = addr.getLength();
95  std::memcpy(&ne.ss, addr.get(), ne.sslen);
96  return ne;
97  }
98  sa_family_t getFamily() const { return addr.getFamily(); }
99 
100  void update(const SockAddr&);
101 
102  void requested(const Sp<net::Request>& req);
103  void received(time_point now, const Sp<net::Request>& req);
104  Sp<net::Request> getRequest(Tid tid);
105  void cancelRequest(const Sp<net::Request>& req);
106 
107  void setExpired();
108 
118  Tid openSocket(SocketCb&& cb);
119 
120  Sp<Socket> getSocket(Tid id);
121 
127  void closeSocket(Tid id);
128 
132  void reset() { expired_ = false; reply_time = time_point::min(); }
133 
139  Tid getNewTid() {
140  ++transaction_id;
141  return transaction_id ? ++transaction_id : transaction_id;
142  }
143 
144  std::string toString() const;
145 
146  OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Node& h);
147 
148  static constexpr const std::chrono::minutes NODE_GOOD_TIME {120};
149 
150  /* The time after which we consider a node to be expirable. */
151  static constexpr const std::chrono::minutes NODE_EXPIRE_TIME {10};
152 
153  /* Time for a request to timeout */
154  static constexpr const std::chrono::seconds MAX_RESPONSE_TIME {1};
155 
156 private:
157  /* Number of times we accept authentication errors from this node. */
158  static const constexpr unsigned MAX_AUTH_ERRORS {3};
159 
160  SockAddr addr;
161  bool is_client {false};
162  time_point time {time_point::min()}; /* last time eared about */
163  time_point reply_time {time_point::min()}; /* time of last correct reply received */
164  unsigned auth_errors {0};
165  bool expired_ {false};
166  Tid transaction_id;
167  using TransactionDist = std::uniform_int_distribution<decltype(transaction_id)>;
168 
169  std::map<Tid, Sp<net::Request>> requests_ {};
170  std::map<Tid, Sp<Socket>> sockets_;
171 };
172 
173 }
void reset()
Definition: node.h:132
sa_family_t getFamily() const
Definition: sockaddr.h:121
void authError()
Definition: node.h:73
Definition: node.h:47
Tid getNewTid()
Definition: node.h:139
socklen_t getLength() const
Definition: sockaddr.h:182
void closeSocket(Tid id)
Tid openSocket(SocketCb &&cb)
Definition: callbacks.h:34
const sockaddr * get() const
Definition: sockaddr.h:195