1 |
|
|
#ifndef SRC_NODE_SOCKADDR_H_ |
2 |
|
|
#define SRC_NODE_SOCKADDR_H_ |
3 |
|
|
|
4 |
|
|
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
5 |
|
|
|
6 |
|
|
#include "env.h" |
7 |
|
|
#include "memory_tracker.h" |
8 |
|
|
#include "base_object.h" |
9 |
|
|
#include "node.h" |
10 |
|
|
#include "node_worker.h" |
11 |
|
|
#include "uv.h" |
12 |
|
|
#include "v8.h" |
13 |
|
|
|
14 |
|
|
#include <memory> |
15 |
|
|
#include <string> |
16 |
|
|
#include <list> |
17 |
|
|
#include <unordered_map> |
18 |
|
|
|
19 |
|
|
namespace node { |
20 |
|
|
|
21 |
|
|
class Environment; |
22 |
|
|
|
23 |
|
|
class SocketAddress : public MemoryRetainer { |
24 |
|
|
public: |
25 |
|
|
enum class CompareResult { |
26 |
|
|
NOT_COMPARABLE = -2, |
27 |
|
|
LESS_THAN, |
28 |
|
|
SAME, |
29 |
|
|
GREATER_THAN |
30 |
|
|
}; |
31 |
|
|
|
32 |
|
|
struct Hash { |
33 |
|
|
size_t operator()(const SocketAddress& addr) const; |
34 |
|
|
}; |
35 |
|
|
|
36 |
|
|
inline bool operator==(const SocketAddress& other) const; |
37 |
|
|
inline bool operator!=(const SocketAddress& other) const; |
38 |
|
|
|
39 |
|
|
inline bool operator<(const SocketAddress& other) const; |
40 |
|
|
inline bool operator>(const SocketAddress& other) const; |
41 |
|
|
inline bool operator<=(const SocketAddress& other) const; |
42 |
|
|
inline bool operator>=(const SocketAddress& other) const; |
43 |
|
|
|
44 |
|
|
inline static bool is_numeric_host(const char* hostname); |
45 |
|
|
inline static bool is_numeric_host(const char* hostname, int family); |
46 |
|
|
|
47 |
|
|
// Returns true if converting {family, host, port} to *addr succeeded. |
48 |
|
|
static bool ToSockAddr( |
49 |
|
|
int32_t family, |
50 |
|
|
const char* host, |
51 |
|
|
uint32_t port, |
52 |
|
|
sockaddr_storage* addr); |
53 |
|
|
|
54 |
|
|
// Returns true if converting {family, host, port} to *addr succeeded. |
55 |
|
|
static bool New( |
56 |
|
|
int32_t family, |
57 |
|
|
const char* host, |
58 |
|
|
uint32_t port, |
59 |
|
|
SocketAddress* addr); |
60 |
|
|
|
61 |
|
|
static bool New( |
62 |
|
|
const char* host, |
63 |
|
|
uint32_t port, |
64 |
|
|
SocketAddress* addr); |
65 |
|
|
|
66 |
|
|
// Returns the port for an IPv4 or IPv6 address. |
67 |
|
|
inline static int GetPort(const sockaddr* addr); |
68 |
|
|
inline static int GetPort(const sockaddr_storage* addr); |
69 |
|
|
|
70 |
|
|
// Returns the numeric host as a string for an IPv4 or IPv6 address. |
71 |
|
|
inline static std::string GetAddress(const sockaddr* addr); |
72 |
|
|
inline static std::string GetAddress(const sockaddr_storage* addr); |
73 |
|
|
|
74 |
|
|
// Returns the struct length for an IPv4, IPv6 or UNIX domain. |
75 |
|
|
inline static size_t GetLength(const sockaddr* addr); |
76 |
|
|
inline static size_t GetLength(const sockaddr_storage* addr); |
77 |
|
|
|
78 |
|
18226 |
SocketAddress() = default; |
79 |
|
|
|
80 |
|
|
inline explicit SocketAddress(const sockaddr* addr); |
81 |
|
|
inline SocketAddress(const SocketAddress& addr); |
82 |
|
|
inline SocketAddress& operator=(const sockaddr* other); |
83 |
|
|
inline SocketAddress& operator=(const SocketAddress& other); |
84 |
|
|
|
85 |
|
|
inline const sockaddr& operator*() const; |
86 |
|
|
inline const sockaddr* operator->() const; |
87 |
|
|
|
88 |
|
|
inline const sockaddr* data() const; |
89 |
|
|
inline const uint8_t* raw() const; |
90 |
|
|
inline sockaddr* storage(); |
91 |
|
|
inline size_t length() const; |
92 |
|
|
|
93 |
|
|
inline int family() const; |
94 |
|
|
inline std::string address() const; |
95 |
|
|
inline int port() const; |
96 |
|
|
|
97 |
|
|
// Returns true if the given other SocketAddress is a match |
98 |
|
|
// for this one. The addresses are a match if: |
99 |
|
|
// 1. They are the same family and match identically |
100 |
|
|
// 2. They are different family but match semantically ( |
101 |
|
|
// for instance, an IPv4 address in IPv6 notation) |
102 |
|
|
bool is_match(const SocketAddress& other) const; |
103 |
|
|
|
104 |
|
|
// Compares this SocketAddress to the given other SocketAddress. |
105 |
|
|
CompareResult compare(const SocketAddress& other) const; |
106 |
|
|
|
107 |
|
|
// Returns true if this SocketAddress is within the subnet |
108 |
|
|
// identified by the given network address and CIDR prefix. |
109 |
|
|
bool is_in_network(const SocketAddress& network, int prefix) const; |
110 |
|
|
|
111 |
|
|
// If the SocketAddress is an IPv6 address, returns the |
112 |
|
|
// current value of the IPv6 flow label, if set. Otherwise |
113 |
|
|
// returns 0. |
114 |
|
|
inline uint32_t flow_label() const; |
115 |
|
|
|
116 |
|
|
// If the SocketAddress is an IPv6 address, sets the |
117 |
|
|
// current value of the IPv6 flow label. If not an |
118 |
|
|
// IPv6 address, set_flow_label is a non-op. It |
119 |
|
|
// is important to note that the flow label, |
120 |
|
|
// while represented as an uint32_t, the flow |
121 |
|
|
// label is strictly limited to 20 bits, and |
122 |
|
|
// this will assert if any value larger than |
123 |
|
|
// 20-bits is specified. |
124 |
|
|
inline void set_flow_label(uint32_t label = 0); |
125 |
|
|
|
126 |
|
|
inline void Update(uint8_t* data, size_t len); |
127 |
|
|
inline void Update(const sockaddr* data, size_t len); |
128 |
|
|
|
129 |
|
|
static SocketAddress FromSockName(const uv_udp_t& handle); |
130 |
|
|
static SocketAddress FromSockName(const uv_tcp_t& handle); |
131 |
|
|
static SocketAddress FromPeerName(const uv_udp_t& handle); |
132 |
|
|
static SocketAddress FromPeerName(const uv_tcp_t& handle); |
133 |
|
|
|
134 |
|
|
inline v8::MaybeLocal<v8::Object> ToJS( |
135 |
|
|
Environment* env, |
136 |
|
|
v8::Local<v8::Object> obj = v8::Local<v8::Object>()) const; |
137 |
|
|
|
138 |
|
|
inline std::string ToString() const; |
139 |
|
|
|
140 |
|
72 |
SET_NO_MEMORY_INFO() |
141 |
|
72 |
SET_MEMORY_INFO_NAME(SocketAddress) |
142 |
|
72 |
SET_SELF_SIZE(SocketAddress) |
143 |
|
|
|
144 |
|
|
template <typename T> |
145 |
|
|
using Map = std::unordered_map<SocketAddress, T, Hash>; |
146 |
|
|
|
147 |
|
|
private: |
148 |
|
|
sockaddr_storage address_; |
149 |
|
|
}; |
150 |
|
|
|
151 |
|
|
class SocketAddressBase : public BaseObject { |
152 |
|
|
public: |
153 |
|
|
static bool HasInstance(Environment* env, v8::Local<v8::Value> value); |
154 |
|
|
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate( |
155 |
|
|
Environment* env); |
156 |
|
|
static void Initialize(Environment* env, v8::Local<v8::Object> target); |
157 |
|
|
static BaseObjectPtr<SocketAddressBase> Create( |
158 |
|
|
Environment* env, |
159 |
|
|
std::shared_ptr<SocketAddress> address); |
160 |
|
|
|
161 |
|
|
static void New(const v8::FunctionCallbackInfo<v8::Value>& args); |
162 |
|
|
static void Detail(const v8::FunctionCallbackInfo<v8::Value>& args); |
163 |
|
|
static void LegacyDetail(const v8::FunctionCallbackInfo<v8::Value>& args); |
164 |
|
|
static void GetFlowLabel(const v8::FunctionCallbackInfo<v8::Value>& args); |
165 |
|
|
|
166 |
|
|
SocketAddressBase( |
167 |
|
|
Environment* env, |
168 |
|
|
v8::Local<v8::Object> wrap, |
169 |
|
|
std::shared_ptr<SocketAddress> address); |
170 |
|
|
|
171 |
|
30225 |
inline const std::shared_ptr<SocketAddress>& address() const { |
172 |
|
30225 |
return address_; |
173 |
|
|
} |
174 |
|
|
|
175 |
|
|
void MemoryInfo(MemoryTracker* tracker) const override; |
176 |
|
|
SET_MEMORY_INFO_NAME(SocketAddressBase) |
177 |
|
|
SET_SELF_SIZE(SocketAddressBase) |
178 |
|
|
|
179 |
|
1 |
TransferMode GetTransferMode() const override { |
180 |
|
1 |
return TransferMode::kCloneable; |
181 |
|
|
} |
182 |
|
|
std::unique_ptr<worker::TransferData> CloneForMessaging() const override; |
183 |
|
|
|
184 |
|
|
class TransferData : public worker::TransferData { |
185 |
|
|
public: |
186 |
|
1 |
inline explicit TransferData(const SocketAddressBase* wrap) |
187 |
|
1 |
: address_(wrap->address_) {} |
188 |
|
|
|
189 |
|
|
inline explicit TransferData(std::shared_ptr<SocketAddress> address) |
190 |
|
|
: address_(std::move(address)) {} |
191 |
|
|
|
192 |
|
|
BaseObjectPtr<BaseObject> Deserialize( |
193 |
|
|
Environment* env, |
194 |
|
|
v8::Local<v8::Context> context, |
195 |
|
|
std::unique_ptr<worker::TransferData> self) override; |
196 |
|
|
|
197 |
|
|
void MemoryInfo(MemoryTracker* tracker) const override; |
198 |
|
|
SET_MEMORY_INFO_NAME(SocketAddressBase::TransferData) |
199 |
|
|
SET_SELF_SIZE(TransferData) |
200 |
|
|
|
201 |
|
|
private: |
202 |
|
|
std::shared_ptr<SocketAddress> address_; |
203 |
|
|
}; |
204 |
|
|
|
205 |
|
|
private: |
206 |
|
|
std::shared_ptr<SocketAddress> address_; |
207 |
|
|
}; |
208 |
|
|
|
209 |
|
|
template <typename T> |
210 |
|
|
class SocketAddressLRU : public MemoryRetainer { |
211 |
|
|
public: |
212 |
|
|
using Type = typename T::Type; |
213 |
|
|
|
214 |
|
|
inline explicit SocketAddressLRU(size_t max_size); |
215 |
|
|
|
216 |
|
|
// If the item already exists, returns a reference to |
217 |
|
|
// the existing item, adjusting items position in the |
218 |
|
|
// LRU. If the item does not exist, emplaces the item |
219 |
|
|
// and returns the new item. |
220 |
|
|
Type* Upsert(const SocketAddress& address); |
221 |
|
|
|
222 |
|
|
// Returns a reference to the item if it exists, or |
223 |
|
|
// nullptr. The position in the LRU is not modified. |
224 |
|
|
Type* Peek(const SocketAddress& address) const; |
225 |
|
|
|
226 |
|
3 |
size_t size() const { return map_.size(); } |
227 |
|
|
size_t max_size() const { return max_size_; } |
228 |
|
|
|
229 |
|
|
void MemoryInfo(MemoryTracker* tracker) const override; |
230 |
|
|
SET_MEMORY_INFO_NAME(SocketAddressLRU) |
231 |
|
|
SET_SELF_SIZE(SocketAddressLRU) |
232 |
|
|
|
233 |
|
|
private: |
234 |
|
|
using Pair = std::pair<SocketAddress, Type>; |
235 |
|
|
using Iterator = typename std::list<Pair>::iterator; |
236 |
|
|
|
237 |
|
|
void CheckExpired(); |
238 |
|
|
|
239 |
|
|
std::list<Pair> list_; |
240 |
|
|
SocketAddress::Map<Iterator> map_; |
241 |
|
|
size_t max_size_; |
242 |
|
|
}; |
243 |
|
|
|
244 |
|
|
// A BlockList is used to evaluate whether a given |
245 |
|
|
// SocketAddress should be accepted for inbound or |
246 |
|
|
// outbound network activity. |
247 |
|
|
class SocketAddressBlockList : public MemoryRetainer { |
248 |
|
|
public: |
249 |
|
|
explicit SocketAddressBlockList( |
250 |
|
|
std::shared_ptr<SocketAddressBlockList> parent = {}); |
251 |
|
11016 |
~SocketAddressBlockList() = default; |
252 |
|
|
|
253 |
|
|
void AddSocketAddress(const std::shared_ptr<SocketAddress>& address); |
254 |
|
|
|
255 |
|
|
void RemoveSocketAddress(const std::shared_ptr<SocketAddress>& address); |
256 |
|
|
|
257 |
|
|
void AddSocketAddressRange( |
258 |
|
|
const std::shared_ptr<SocketAddress>& start, |
259 |
|
|
const std::shared_ptr<SocketAddress>& end); |
260 |
|
|
|
261 |
|
|
void AddSocketAddressMask( |
262 |
|
|
const std::shared_ptr<SocketAddress>& address, |
263 |
|
|
int prefix); |
264 |
|
|
|
265 |
|
|
bool Apply(const std::shared_ptr<SocketAddress>& address); |
266 |
|
|
|
267 |
|
|
size_t size() const { return rules_.size(); } |
268 |
|
|
|
269 |
|
|
v8::MaybeLocal<v8::Array> ListRules(Environment* env); |
270 |
|
|
|
271 |
|
|
struct Rule : public MemoryRetainer { |
272 |
|
|
virtual bool Apply(const std::shared_ptr<SocketAddress>& address) = 0; |
273 |
|
|
inline v8::MaybeLocal<v8::Value> ToV8String(Environment* env); |
274 |
|
|
virtual std::string ToString() = 0; |
275 |
|
|
}; |
276 |
|
|
|
277 |
|
|
struct SocketAddressRule final : Rule { |
278 |
|
|
std::shared_ptr<SocketAddress> address; |
279 |
|
|
|
280 |
|
|
explicit SocketAddressRule(const std::shared_ptr<SocketAddress>& address); |
281 |
|
|
|
282 |
|
|
bool Apply(const std::shared_ptr<SocketAddress>& address) override; |
283 |
|
|
std::string ToString() override; |
284 |
|
|
|
285 |
|
|
void MemoryInfo(node::MemoryTracker* tracker) const override; |
286 |
|
24 |
SET_MEMORY_INFO_NAME(SocketAddressRule) |
287 |
|
24 |
SET_SELF_SIZE(SocketAddressRule) |
288 |
|
|
}; |
289 |
|
|
|
290 |
|
|
struct SocketAddressRangeRule final : Rule { |
291 |
|
|
std::shared_ptr<SocketAddress> start; |
292 |
|
|
std::shared_ptr<SocketAddress> end; |
293 |
|
|
|
294 |
|
|
SocketAddressRangeRule( |
295 |
|
|
const std::shared_ptr<SocketAddress>& start, |
296 |
|
|
const std::shared_ptr<SocketAddress>& end); |
297 |
|
|
|
298 |
|
|
bool Apply(const std::shared_ptr<SocketAddress>& address) override; |
299 |
|
|
std::string ToString() override; |
300 |
|
|
|
301 |
|
|
void MemoryInfo(node::MemoryTracker* tracker) const override; |
302 |
|
24 |
SET_MEMORY_INFO_NAME(SocketAddressRangeRule) |
303 |
|
24 |
SET_SELF_SIZE(SocketAddressRangeRule) |
304 |
|
|
}; |
305 |
|
|
|
306 |
|
|
struct SocketAddressMaskRule final : Rule { |
307 |
|
|
std::shared_ptr<SocketAddress> network; |
308 |
|
|
int prefix; |
309 |
|
|
|
310 |
|
|
SocketAddressMaskRule( |
311 |
|
|
const std::shared_ptr<SocketAddress>& address, |
312 |
|
|
int prefix); |
313 |
|
|
|
314 |
|
|
bool Apply(const std::shared_ptr<SocketAddress>& address) override; |
315 |
|
|
std::string ToString() override; |
316 |
|
|
|
317 |
|
|
void MemoryInfo(node::MemoryTracker* tracker) const override; |
318 |
|
|
SET_MEMORY_INFO_NAME(SocketAddressMaskRule) |
319 |
|
|
SET_SELF_SIZE(SocketAddressMaskRule) |
320 |
|
|
}; |
321 |
|
|
|
322 |
|
|
void MemoryInfo(node::MemoryTracker* tracker) const override; |
323 |
|
|
SET_MEMORY_INFO_NAME(SocketAddressBlockList) |
324 |
|
|
SET_SELF_SIZE(SocketAddressBlockList) |
325 |
|
|
|
326 |
|
|
private: |
327 |
|
|
bool ListRules( |
328 |
|
|
Environment* env, |
329 |
|
|
std::vector<v8::Local<v8::Value>>* vec); |
330 |
|
|
|
331 |
|
|
std::shared_ptr<SocketAddressBlockList> parent_; |
332 |
|
|
std::list<std::unique_ptr<Rule>> rules_; |
333 |
|
|
SocketAddress::Map<std::list<std::unique_ptr<Rule>>::iterator> address_rules_; |
334 |
|
|
|
335 |
|
|
Mutex mutex_; |
336 |
|
|
}; |
337 |
|
|
|
338 |
|
|
class SocketAddressBlockListWrap : public BaseObject { |
339 |
|
|
public: |
340 |
|
|
static bool HasInstance(Environment* env, v8::Local<v8::Value> value); |
341 |
|
|
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate( |
342 |
|
|
Environment* env); |
343 |
|
|
static void Initialize(v8::Local<v8::Object> target, |
344 |
|
|
v8::Local<v8::Value> unused, |
345 |
|
|
v8::Local<v8::Context> context, |
346 |
|
|
void* priv); |
347 |
|
|
|
348 |
|
|
static BaseObjectPtr<SocketAddressBlockListWrap> New(Environment* env); |
349 |
|
|
static BaseObjectPtr<SocketAddressBlockListWrap> New( |
350 |
|
|
Environment* env, |
351 |
|
|
std::shared_ptr<SocketAddressBlockList> blocklist); |
352 |
|
|
|
353 |
|
|
static void New(const v8::FunctionCallbackInfo<v8::Value>& args); |
354 |
|
|
static void AddAddress(const v8::FunctionCallbackInfo<v8::Value>& args); |
355 |
|
|
static void AddRange(const v8::FunctionCallbackInfo<v8::Value>& args); |
356 |
|
|
static void AddSubnet(const v8::FunctionCallbackInfo<v8::Value>& args); |
357 |
|
|
static void Check(const v8::FunctionCallbackInfo<v8::Value>& args); |
358 |
|
|
static void GetRules(const v8::FunctionCallbackInfo<v8::Value>& args); |
359 |
|
|
|
360 |
|
|
SocketAddressBlockListWrap( |
361 |
|
|
Environment* env, |
362 |
|
|
v8::Local<v8::Object> wrap, |
363 |
|
|
std::shared_ptr<SocketAddressBlockList> blocklist = |
364 |
|
|
std::make_shared<SocketAddressBlockList>()); |
365 |
|
|
|
366 |
|
|
void MemoryInfo(node::MemoryTracker* tracker) const override; |
367 |
|
24 |
SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap) |
368 |
|
24 |
SET_SELF_SIZE(SocketAddressBlockListWrap) |
369 |
|
|
|
370 |
|
1 |
TransferMode GetTransferMode() const override { |
371 |
|
1 |
return TransferMode::kCloneable; |
372 |
|
|
} |
373 |
|
|
std::unique_ptr<worker::TransferData> CloneForMessaging() const override; |
374 |
|
|
|
375 |
|
|
class TransferData : public worker::TransferData { |
376 |
|
|
public: |
377 |
|
1 |
inline explicit TransferData(const SocketAddressBlockListWrap* wrap) |
378 |
|
1 |
: blocklist_(wrap->blocklist_) {} |
379 |
|
|
|
380 |
|
|
inline explicit TransferData( |
381 |
|
|
std::shared_ptr<SocketAddressBlockList> blocklist) |
382 |
|
|
: blocklist_(std::move(blocklist)) {} |
383 |
|
|
|
384 |
|
|
BaseObjectPtr<BaseObject> Deserialize( |
385 |
|
|
Environment* env, |
386 |
|
|
v8::Local<v8::Context> context, |
387 |
|
|
std::unique_ptr<worker::TransferData> self) override; |
388 |
|
|
|
389 |
|
|
void MemoryInfo(MemoryTracker* tracker) const override; |
390 |
|
|
SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap::TransferData) |
391 |
|
|
SET_SELF_SIZE(TransferData) |
392 |
|
|
|
393 |
|
|
private: |
394 |
|
|
std::shared_ptr<SocketAddressBlockList> blocklist_; |
395 |
|
|
}; |
396 |
|
|
|
397 |
|
|
private: |
398 |
|
|
std::shared_ptr<SocketAddressBlockList> blocklist_; |
399 |
|
|
}; |
400 |
|
|
|
401 |
|
|
} // namespace node |
402 |
|
|
|
403 |
|
|
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
404 |
|
|
|
405 |
|
|
#endif // SRC_NODE_SOCKADDR_H_ |