My Project 3.7.1
C++ Distributed Hash Table
Loading...
Searching...
No Matches
node.h
1// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
2// SPDX-License-Identifier: MIT
3#pragma once
4
5#include "infohash.h" // includes socket structures
6#include "utils.h"
7#include "sockaddr.h"
8#include "node_export.h"
9
10#include <list>
11#include <map>
12
13namespace dht {
14
15struct Node;
16namespace net {
17struct Request;
18struct Socket;
19struct RequestAnswer;
20} /* namespace net */
21
22using Tid = uint32_t;
23using SocketCb = std::function<void(const Sp<Node>&, net::RequestAnswer&&)>;
24struct Socket
25{
26 Socket() {}
27 Socket(SocketCb&& on_receive)
28 : on_receive(std::move(on_receive))
29 {}
30 SocketCb on_receive {};
31};
32
33struct Node
34{
35 const InfoHash id;
36
37 Node(const InfoHash& id, const SockAddr& addr, std::mt19937_64& rd, bool client = false);
38 Node(const InfoHash& id, SockAddr&& addr, std::mt19937_64& rd, bool client = false);
39 Node(const InfoHash& id, const sockaddr* sa, socklen_t salen, std::mt19937_64& rd)
40 : Node(id, SockAddr(sa, salen), rd)
41 {}
42
43 const InfoHash& getId() const { return id; }
44 const SockAddr& getAddr() const { return addr; }
45 std::string getAddrStr() const { return addr.toString(); }
46 bool isClient() const { return is_client; }
47 bool isIncoming() { return time > reply_time; }
48
49 const time_point& getTime() const { return time; }
50 const time_point& getReplyTime() const { return reply_time; }
51 void setTime(const time_point& t) { time = t; }
52
58 void authError()
59 {
60 if (++auth_errors > MAX_AUTH_ERRORS)
61 setExpired();
62 }
63 void authSuccess() { auth_errors = 0; }
64
65 bool isExpired() const { return expired_; }
66 bool isGood(time_point now) const;
67 bool isPendingMessage() const;
68 size_t getPendingMessageCount() const;
69
70 bool isOld(const time_point& now) const { return time + NODE_EXPIRE_TIME < now; }
71 bool isRemovable(const time_point& now) const { return isExpired() and isOld(now); }
72
73 NodeExport exportNode() const
74 {
75 NodeExport ne;
76 ne.id = id;
77 ne.addr = addr;
78 return ne;
79 }
80 sa_family_t getFamily() const { return addr.getFamily(); }
81
82 void update(const SockAddr&);
83
84 void requested(const Sp<net::Request>& req);
85 void received(time_point now, const Sp<net::Request>& req);
86 Sp<net::Request> getRequest(Tid tid);
87 void cancelRequest(const Sp<net::Request>& req);
88
89 void setExpired();
90
100 Tid openSocket(SocketCb&& cb);
101
102 Sp<Socket> getSocket(Tid id);
103
109 void closeSocket(Tid id);
110
114 void reset()
115 {
116 expired_ = false;
117 reply_time = time_point::min();
118 }
119
126 {
127 ++transaction_id;
128 return transaction_id ? transaction_id : ++transaction_id;
129 }
130
131 std::string toString() const;
132
133 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const Node& h);
134
135 static constexpr const std::chrono::minutes NODE_GOOD_TIME {120};
136
137 /* The time after which we consider a node to be expirable. */
138 static constexpr const std::chrono::minutes NODE_EXPIRE_TIME {10};
139
140 /* Time for a request to timeout */
141 static constexpr const std::chrono::seconds MAX_RESPONSE_TIME {1};
142
143private:
144 /* Number of times we accept authentication errors from this node. */
145 static const constexpr unsigned MAX_AUTH_ERRORS {3};
146
147 SockAddr addr;
148 bool is_client {false};
149 time_point time {time_point::min()}; /* last time eared about */
150 time_point reply_time {time_point::min()}; /* time of last correct reply received */
151 unsigned auth_errors {0};
152 bool expired_ {false};
153 Tid transaction_id;
154 using TransactionDist = std::uniform_int_distribution<decltype(transaction_id)>;
155
156 std::map<Tid, Sp<net::Request>> requests_ {};
157 std::map<Tid, Sp<Socket>> sockets_;
158};
159
160} // namespace dht
Tid getNewTid()
Definition node.h:125
void closeSocket(Tid id)
void reset()
Definition node.h:114
Tid openSocket(SocketCb &&cb)
void authError()
Definition node.h:58