GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_sockaddr.h Lines: 22 34 64.7 %
Date: 2022-05-21 04:15:56 Branches: 0 0 - %

Line Branch Exec Source
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_