My Project 1.7.4
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
29namespace dht {
30
31struct Node;
32namespace net {
33struct Request;
34struct Socket;
35struct RequestAnswer;
36} /* namespace net */
37
38using Tid = uint32_t;
39using SocketCb = std::function<void(const Sp<Node>&, net::RequestAnswer&&)>;
40struct Socket {
41 Socket() {}
42 Socket(SocketCb&& on_receive) :
43 on_receive(std::move(on_receive)) {}
44 SocketCb on_receive {};
45};
46
47struct 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
156private:
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}
const sockaddr * get() const
Definition: sockaddr.h:195
socklen_t getLength() const
Definition: sockaddr.h:182
sa_family_t getFamily() const
Definition: sockaddr.h:121
Definition: callbacks.h:34
Definition: node.h:47
Tid getNewTid()
Definition: node.h:139
void closeSocket(Tid id)
void reset()
Definition: node.h:132
Tid openSocket(SocketCb &&cb)
void authError()
Definition: node.h:73