GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_sockaddr.cc Lines: 368 441 83.4 %
Date: 2021-04-19 04:11:46 Branches: 128 217 59.0 %

Line Branch Exec Source
1
#include "node_sockaddr-inl.h"  // NOLINT(build/include)
2
#include "env-inl.h"
3
#include "base64-inl.h"
4
#include "base_object-inl.h"
5
#include "memory_tracker-inl.h"
6
#include "node_errors.h"
7
#include "uv.h"
8
9
#include <memory>
10
#include <string>
11
#include <vector>
12
13
namespace node {
14
15
using v8::Array;
16
using v8::Context;
17
using v8::FunctionCallbackInfo;
18
using v8::FunctionTemplate;
19
using v8::Int32;
20
using v8::Local;
21
using v8::MaybeLocal;
22
using v8::Object;
23
using v8::Uint32;
24
using v8::Value;
25
26
namespace {
27
template <typename T, typename F>
28
SocketAddress FromUVHandle(F fn, const T& handle) {
29
  SocketAddress addr;
30
  int len = sizeof(sockaddr_storage);
31
  if (fn(&handle, addr.storage(), &len) == 0)
32
    CHECK_EQ(static_cast<size_t>(len), addr.length());
33
  else
34
    addr.storage()->sa_family = 0;
35
  return addr;
36
}
37
}  // namespace
38
39
200
bool SocketAddress::ToSockAddr(
40
    int32_t family,
41
    const char* host,
42
    uint32_t port,
43
    sockaddr_storage* addr) {
44
200
  switch (family) {
45
    case AF_INET:
46
120
      return uv_ip4_addr(
47
          host,
48
          port,
49
120
          reinterpret_cast<sockaddr_in*>(addr)) == 0;
50
    case AF_INET6:
51
80
      return uv_ip6_addr(
52
          host,
53
          port,
54
80
          reinterpret_cast<sockaddr_in6*>(addr)) == 0;
55
    default:
56
      UNREACHABLE();
57
  }
58
}
59
60
bool SocketAddress::New(
61
    const char* host,
62
    uint32_t port,
63
    SocketAddress* addr) {
64
  return New(AF_INET, host, port, addr) || New(AF_INET6, host, port, addr);
65
}
66
67
185
bool SocketAddress::New(
68
    int32_t family,
69
    const char* host,
70
    uint32_t port,
71
    SocketAddress* addr) {
72
  return ToSockAddr(family, host, port,
73
185
                    reinterpret_cast<sockaddr_storage*>(addr->storage()));
74
}
75
76
42
size_t SocketAddress::Hash::operator()(const SocketAddress& addr) const {
77
42
  size_t hash = 0;
78
42
  switch (addr.family()) {
79
    case AF_INET: {
80
      const sockaddr_in* ipv4 =
81
38
          reinterpret_cast<const sockaddr_in*>(addr.raw());
82
38
      hash_combine(&hash, ipv4->sin_port, ipv4->sin_addr.s_addr);
83
38
      break;
84
    }
85
    case AF_INET6: {
86
      const sockaddr_in6* ipv6 =
87
4
          reinterpret_cast<const sockaddr_in6*>(addr.raw());
88
      const uint64_t* a =
89
4
          reinterpret_cast<const uint64_t*>(&ipv6->sin6_addr);
90
4
      hash_combine(&hash, ipv6->sin6_port, a[0], a[1]);
91
4
      break;
92
    }
93
    default:
94
      UNREACHABLE();
95
  }
96
42
  return hash;
97
}
98
99
SocketAddress SocketAddress::FromSockName(const uv_tcp_t& handle) {
100
  return FromUVHandle(uv_tcp_getsockname, handle);
101
}
102
103
SocketAddress SocketAddress::FromSockName(const uv_udp_t& handle) {
104
  return FromUVHandle(uv_udp_getsockname, handle);
105
}
106
107
SocketAddress SocketAddress::FromPeerName(const uv_tcp_t& handle) {
108
  return FromUVHandle(uv_tcp_getpeername, handle);
109
}
110
111
SocketAddress SocketAddress::FromPeerName(const uv_udp_t& handle) {
112
  return FromUVHandle(uv_udp_getpeername, handle);
113
}
114
115
namespace {
116
constexpr uint8_t mask[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
117
118
15
bool is_match_ipv4(
119
    const SocketAddress& one,
120
    const SocketAddress& two) {
121
  const sockaddr_in* one_in =
122
15
      reinterpret_cast<const sockaddr_in*>(one.data());
123
  const sockaddr_in* two_in =
124
15
      reinterpret_cast<const sockaddr_in*>(two.data());
125
15
  return memcmp(&one_in->sin_addr, &two_in->sin_addr, sizeof(uint32_t)) == 0;
126
}
127
128
18
bool is_match_ipv6(
129
    const SocketAddress& one,
130
    const SocketAddress& two) {
131
  const sockaddr_in6* one_in =
132
18
      reinterpret_cast<const sockaddr_in6*>(one.data());
133
  const sockaddr_in6* two_in =
134
18
      reinterpret_cast<const sockaddr_in6*>(two.data());
135
18
  return memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16) == 0;
136
}
137
138
21
bool is_match_ipv4_ipv6(
139
    const SocketAddress& ipv4,
140
    const SocketAddress& ipv6) {
141
  const sockaddr_in* check_ipv4 =
142
21
      reinterpret_cast<const sockaddr_in*>(ipv4.data());
143
  const sockaddr_in6* check_ipv6 =
144
21
      reinterpret_cast<const sockaddr_in6*>(ipv6.data());
145
146
  const uint8_t* ptr =
147
21
      reinterpret_cast<const uint8_t*>(&check_ipv6->sin6_addr);
148
149

34
  return memcmp(ptr, mask, sizeof(mask)) == 0 &&
150
13
         memcmp(ptr + sizeof(mask),
151
13
                &check_ipv4->sin_addr,
152
21
                sizeof(uint32_t)) == 0;
153
}
154
155
65
SocketAddress::CompareResult compare_ipv4(
156
    const SocketAddress& one,
157
    const SocketAddress& two) {
158
  const sockaddr_in* one_in =
159
65
      reinterpret_cast<const sockaddr_in*>(one.data());
160
  const sockaddr_in* two_in =
161
65
      reinterpret_cast<const sockaddr_in*>(two.data());
162
163
65
  if (one_in->sin_addr.s_addr < two_in->sin_addr.s_addr)
164
28
    return SocketAddress::CompareResult::LESS_THAN;
165
37
  else if (one_in->sin_addr.s_addr == two_in->sin_addr.s_addr)
166
7
    return SocketAddress::CompareResult::SAME;
167
  else
168
30
    return SocketAddress::CompareResult::GREATER_THAN;
169
}
170
171
77
SocketAddress::CompareResult compare_ipv6(
172
    const SocketAddress& one,
173
    const SocketAddress& two) {
174
  const sockaddr_in6* one_in =
175
77
      reinterpret_cast<const sockaddr_in6*>(one.data());
176
  const sockaddr_in6* two_in =
177
77
      reinterpret_cast<const sockaddr_in6*>(two.data());
178
77
  int ret = memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16);
179
77
  if (ret < 0)
180
35
    return SocketAddress::CompareResult::LESS_THAN;
181
42
  else if (ret > 0)
182
35
    return SocketAddress::CompareResult::GREATER_THAN;
183
7
  return SocketAddress::CompareResult::SAME;
184
}
185
186
54
SocketAddress::CompareResult compare_ipv4_ipv6(
187
    const SocketAddress& ipv4,
188
    const SocketAddress& ipv6) {
189
  const sockaddr_in* ipv4_in =
190
54
      reinterpret_cast<const sockaddr_in*>(ipv4.data());
191
  const sockaddr_in6 * ipv6_in =
192
54
      reinterpret_cast<const sockaddr_in6*>(ipv6.data());
193
194
  const uint8_t* ptr =
195
54
      reinterpret_cast<const uint8_t*>(&ipv6_in->sin6_addr);
196
197
54
  if (memcmp(ptr, mask, sizeof(mask)) != 0)
198
39
    return SocketAddress::CompareResult::NOT_COMPARABLE;
199
200
  int ret = memcmp(
201
15
      &ipv4_in->sin_addr,
202
15
      ptr + sizeof(mask),
203
15
      sizeof(uint32_t));
204
205
15
  if (ret < 0)
206
9
    return SocketAddress::CompareResult::LESS_THAN;
207
6
  else if (ret > 0)
208
2
    return SocketAddress::CompareResult::GREATER_THAN;
209
4
  return SocketAddress::CompareResult::SAME;
210
}
211
212
39
bool in_network_ipv4(
213
    const SocketAddress& ip,
214
    const SocketAddress& net,
215
    int prefix) {
216
39
  uint32_t mask = ((1 << prefix) - 1) << (32 - prefix);
217
218
  const sockaddr_in* ip_in =
219
39
      reinterpret_cast<const sockaddr_in*>(ip.data());
220
  const sockaddr_in* net_in =
221
39
      reinterpret_cast<const sockaddr_in*>(net.data());
222
223
78
  return (htonl(ip_in->sin_addr.s_addr) & mask) ==
224
78
         (htonl(net_in->sin_addr.s_addr) & mask);
225
}
226
227
15
bool in_network_ipv6(
228
    const SocketAddress& ip,
229
    const SocketAddress& net,
230
    int prefix) {
231
  // Special case, if prefix == 128, then just do a
232
  // straight comparison.
233
15
  if (prefix == 128)
234
    return compare_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
235
236
15
  uint8_t r = prefix % 8;
237
15
  int len = (prefix - r) / 8;
238
15
  uint8_t mask = ((1 << r) - 1) << (8 - r);
239
240
  const sockaddr_in6* ip_in =
241
15
      reinterpret_cast<const sockaddr_in6*>(ip.data());
242
  const sockaddr_in6* net_in =
243
15
      reinterpret_cast<const sockaddr_in6*>(net.data());
244
245
15
  if (memcmp(&ip_in->sin6_addr, &net_in->sin6_addr, len) != 0)
246
7
    return false;
247
248
  const uint8_t* p1 = reinterpret_cast<const uint8_t*>(
249
8
      ip_in->sin6_addr.s6_addr);
250
  const uint8_t* p2 = reinterpret_cast<const uint8_t*>(
251
8
      net_in->sin6_addr.s6_addr);
252
253
8
  return (p1[len] & mask) == (p2[len] & mask);
254
}
255
256
42
bool in_network_ipv4_ipv6(
257
    const SocketAddress& ip,
258
    const SocketAddress& net,
259
    int prefix) {
260
261
42
  if (prefix == 128)
262
    return compare_ipv4_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
263
264
42
  uint8_t r = prefix % 8;
265
42
  int len = (prefix - r) / 8;
266
42
  uint8_t mask = ((1 << r) - 1) << (8 - r);
267
268
  const sockaddr_in* ip_in =
269
42
      reinterpret_cast<const sockaddr_in*>(ip.data());
270
  const sockaddr_in6* net_in =
271
42
      reinterpret_cast<const sockaddr_in6*>(net.data());
272
273
42
  uint8_t ip_mask[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0};
274
42
  uint8_t* ptr = ip_mask;
275
42
  memcpy(ptr + 12, &ip_in->sin_addr, 4);
276
277
42
  if (memcmp(ptr, &net_in->sin6_addr, len) != 0)
278
42
    return false;
279
280
  ptr += len;
281
  const uint8_t* p2 = reinterpret_cast<const uint8_t*>(
282
      net_in->sin6_addr.s6_addr);
283
284
  return (ptr[0] & mask) == (p2[len] & mask);
285
}
286
287
5
bool in_network_ipv6_ipv4(
288
    const SocketAddress& ip,
289
    const SocketAddress& net,
290
    int prefix) {
291
5
  if (prefix == 32)
292
    return compare_ipv4_ipv6(net, ip) == SocketAddress::CompareResult::SAME;
293
294
5
  uint32_t m = ((1 << prefix) - 1) << (32 - prefix);
295
296
  const sockaddr_in6* ip_in =
297
5
      reinterpret_cast<const sockaddr_in6*>(ip.data());
298
  const sockaddr_in* net_in =
299
5
      reinterpret_cast<const sockaddr_in*>(net.data());
300
301
  const uint8_t* ptr =
302
5
      reinterpret_cast<const uint8_t*>(&ip_in->sin6_addr);
303
304
5
  if (memcmp(ptr, mask, sizeof(mask)) != 0)
305
3
    return false;
306
307
2
  ptr += sizeof(mask);
308
2
  uint32_t check = ReadUint32BE(ptr);
309
310
2
  return (check & m) == (htonl(net_in->sin_addr.s_addr) & m);
311
}
312
}  // namespace
313
314
// TODO(@jasnell): The implementations of is_match, compare, and
315
// is_in_network have not been performance optimized and could
316
// likely benefit from work on more performant approaches.
317
318
54
bool SocketAddress::is_match(const SocketAddress& other) const {
319
54
  switch (family()) {
320
    case AF_INET:
321
23
      switch (other.family()) {
322
15
        case AF_INET: return is_match_ipv4(*this, other);
323
8
        case AF_INET6: return is_match_ipv4_ipv6(*this, other);
324
      }
325
      break;
326
    case AF_INET6:
327
31
      switch (other.family()) {
328
13
        case AF_INET: return is_match_ipv4_ipv6(other, *this);
329
18
        case AF_INET6: return is_match_ipv6(*this, other);
330
      }
331
      break;
332
  }
333
  return false;
334
}
335
336
196
SocketAddress::CompareResult SocketAddress::compare(
337
    const SocketAddress& other) const {
338
196
  switch (family()) {
339
    case AF_INET:
340
102
      switch (other.family()) {
341
65
        case AF_INET: return compare_ipv4(*this, other);
342
37
        case AF_INET6: return compare_ipv4_ipv6(*this, other);
343
      }
344
      break;
345
    case AF_INET6:
346
94
      switch (other.family()) {
347
        case AF_INET: {
348
17
          CompareResult c = compare_ipv4_ipv6(other, *this);
349

17
          switch (c) {
350
            case SocketAddress::CompareResult::NOT_COMPARABLE:
351
              // Fall through
352
            case SocketAddress::CompareResult::SAME:
353
10
              return c;
354
            case SocketAddress::CompareResult::GREATER_THAN:
355
1
              return SocketAddress::CompareResult::LESS_THAN;
356
            case SocketAddress::CompareResult::LESS_THAN:
357
6
              return SocketAddress::CompareResult::GREATER_THAN;
358
          }
359
          break;
360
        }
361
77
        case AF_INET6: return compare_ipv6(*this, other);
362
      }
363
      break;
364
  }
365
  return SocketAddress::CompareResult::NOT_COMPARABLE;
366
}
367
368
101
bool SocketAddress::is_in_network(
369
    const SocketAddress& other,
370
    int prefix) const {
371
372
101
  switch (family()) {
373
    case AF_INET:
374
81
      switch (other.family()) {
375
39
        case AF_INET: return in_network_ipv4(*this, other, prefix);
376
42
        case AF_INET6: return in_network_ipv4_ipv6(*this, other, prefix);
377
      }
378
      break;
379
    case AF_INET6:
380
20
      switch (other.family()) {
381
5
        case AF_INET: return in_network_ipv6_ipv4(*this, other, prefix);
382
15
        case AF_INET6: return in_network_ipv6(*this, other, prefix);
383
      }
384
      break;
385
  }
386
387
  return false;
388
}
389
390
16
SocketAddressBlockList::SocketAddressBlockList(
391
16
    std::shared_ptr<SocketAddressBlockList> parent)
392
16
    : parent_(parent) {}
393
394
11
void SocketAddressBlockList::AddSocketAddress(
395
    const std::shared_ptr<SocketAddress>& address) {
396
22
  Mutex::ScopedLock lock(mutex_);
397
  std::unique_ptr<Rule> rule =
398
22
      std::make_unique<SocketAddressRule>(address);
399
11
  rules_.emplace_front(std::move(rule));
400
11
  address_rules_[*address.get()] = rules_.begin();
401
11
}
402
403
1
void SocketAddressBlockList::RemoveSocketAddress(
404
    const std::shared_ptr<SocketAddress>& address) {
405
2
  Mutex::ScopedLock lock(mutex_);
406
1
  auto it = address_rules_.find(*address.get());
407
1
  if (it != std::end(address_rules_)) {
408
1
    rules_.erase(it->second);
409
1
    address_rules_.erase(it);
410
  }
411
1
}
412
413
5
void SocketAddressBlockList::AddSocketAddressRange(
414
    const std::shared_ptr<SocketAddress>& start,
415
    const std::shared_ptr<SocketAddress>& end) {
416
10
  Mutex::ScopedLock lock(mutex_);
417
  std::unique_ptr<Rule> rule =
418
10
      std::make_unique<SocketAddressRangeRule>(start, end);
419
5
  rules_.emplace_front(std::move(rule));
420
5
}
421
422
7
void SocketAddressBlockList::AddSocketAddressMask(
423
    const std::shared_ptr<SocketAddress>& network,
424
    int prefix) {
425
14
  Mutex::ScopedLock lock(mutex_);
426
  std::unique_ptr<Rule> rule =
427
14
      std::make_unique<SocketAddressMaskRule>(network, prefix);
428
7
  rules_.emplace_front(std::move(rule));
429
7
}
430
431
140
bool SocketAddressBlockList::Apply(
432
    const std::shared_ptr<SocketAddress>& address) {
433
280
  Mutex::ScopedLock lock(mutex_);
434
270
  for (const auto& rule : rules_) {
435
247
    if (rule->Apply(address))
436
117
      return true;
437
  }
438
23
  return parent_ ? parent_->Apply(address) : false;
439
}
440
441
11
SocketAddressBlockList::SocketAddressRule::SocketAddressRule(
442
11
    const std::shared_ptr<SocketAddress>& address_)
443
11
    : address(address_) {}
444
445
5
SocketAddressBlockList::SocketAddressRangeRule::SocketAddressRangeRule(
446
    const std::shared_ptr<SocketAddress>& start_,
447
5
    const std::shared_ptr<SocketAddress>& end_)
448
    : start(start_),
449
5
      end(end_) {}
450
451
7
SocketAddressBlockList::SocketAddressMaskRule::SocketAddressMaskRule(
452
    const std::shared_ptr<SocketAddress>& network_,
453
7
    int prefix_)
454
    : network(network_),
455
7
      prefix(prefix_) {}
456
457
54
bool SocketAddressBlockList::SocketAddressRule::Apply(
458
    const std::shared_ptr<SocketAddress>& address) {
459
54
  return this->address->is_match(*address.get());
460
}
461
462
1
std::string SocketAddressBlockList::SocketAddressRule::ToString() {
463
1
  std::string ret = "Address: ";
464
1
  ret += address->family() == AF_INET ? "IPv4" : "IPv6";
465
1
  ret += " ";
466
1
  ret += address->address();
467
1
  return ret;
468
}
469
470
92
bool SocketAddressBlockList::SocketAddressRangeRule::Apply(
471
    const std::shared_ptr<SocketAddress>& address) {
472

151
  return *address.get() >= *start.get() &&
473
151
         *address.get() <= *end.get();
474
}
475
476
1
std::string SocketAddressBlockList::SocketAddressRangeRule::ToString() {
477
1
  std::string ret = "Range: ";
478
1
  ret += start->family() == AF_INET ? "IPv4" : "IPv6";
479
1
  ret += " ";
480
1
  ret += start->address();
481
1
  ret += "-";
482
1
  ret += end->address();
483
1
  return ret;
484
}
485
486
101
bool SocketAddressBlockList::SocketAddressMaskRule::Apply(
487
    const std::shared_ptr<SocketAddress>& address) {
488
101
  return address->is_in_network(*network.get(), prefix);
489
}
490
491
1
std::string SocketAddressBlockList::SocketAddressMaskRule::ToString() {
492
1
  std::string ret = "Subnet: ";
493
1
  ret += network->family() == AF_INET ? "IPv4" : "IPv6";
494
1
  ret += " ";
495
1
  ret += network->address();
496
1
  ret += "/" + std::to_string(prefix);
497
1
  return ret;
498
}
499
500
2
MaybeLocal<Array> SocketAddressBlockList::ListRules(Environment* env) {
501
4
  Mutex::ScopedLock lock(mutex_);
502
4
  std::vector<Local<Value>> rules;
503
2
  if (!ListRules(env, &rules))
504
    return MaybeLocal<Array>();
505
4
  return Array::New(env->isolate(), rules.data(), rules.size());
506
}
507
508
2
bool SocketAddressBlockList::ListRules(
509
    Environment* env,
510
    std::vector<v8::Local<v8::Value>>* rules) {
511

2
  if (parent_ && !parent_->ListRules(env, rules))
512
    return false;
513
5
  for (const auto& rule : rules_) {
514
    Local<Value> str;
515
6
    if (!rule->ToV8String(env).ToLocal(&str))
516
      return false;
517
3
    rules->push_back(str);
518
  }
519
2
  return true;
520
}
521
522
void SocketAddressBlockList::MemoryInfo(node::MemoryTracker* tracker) const {
523
  tracker->TrackField("rules", rules_);
524
}
525
526
void SocketAddressBlockList::SocketAddressRule::MemoryInfo(
527
    node::MemoryTracker* tracker) const {
528
  tracker->TrackField("address", address);
529
}
530
531
void SocketAddressBlockList::SocketAddressRangeRule::MemoryInfo(
532
    node::MemoryTracker* tracker) const {
533
  tracker->TrackField("start", start);
534
  tracker->TrackField("end", end);
535
}
536
537
void SocketAddressBlockList::SocketAddressMaskRule::MemoryInfo(
538
    node::MemoryTracker* tracker) const {
539
  tracker->TrackField("network", network);
540
}
541
542
16
SocketAddressBlockListWrap::SocketAddressBlockListWrap(
543
    Environment* env,
544
    Local<Object> wrap,
545
16
    std::shared_ptr<SocketAddressBlockList> blocklist)
546
    : BaseObject(env, wrap),
547
16
      blocklist_(std::move(blocklist)) {
548
16
  MakeWeak();
549
16
}
550
551
BaseObjectPtr<SocketAddressBlockListWrap> SocketAddressBlockListWrap::New(
552
    Environment* env) {
553
  Local<Object> obj;
554
  if (!env->blocklist_constructor_template()
555
          ->InstanceTemplate()
556
          ->NewInstance(env->context()).ToLocal(&obj)) {
557
    return BaseObjectPtr<SocketAddressBlockListWrap>();
558
  }
559
  BaseObjectPtr<SocketAddressBlockListWrap> wrap =
560
      MakeBaseObject<SocketAddressBlockListWrap>(env, obj);
561
  CHECK(wrap);
562
  return wrap;
563
}
564
565
1
BaseObjectPtr<SocketAddressBlockListWrap> SocketAddressBlockListWrap::New(
566
    Environment* env,
567
    std::shared_ptr<SocketAddressBlockList> blocklist) {
568
  Local<Object> obj;
569
3
  if (!env->blocklist_constructor_template()
570
2
          ->InstanceTemplate()
571
4
          ->NewInstance(env->context()).ToLocal(&obj)) {
572
    return BaseObjectPtr<SocketAddressBlockListWrap>();
573
  }
574
  BaseObjectPtr<SocketAddressBlockListWrap> wrap =
575
      MakeBaseObject<SocketAddressBlockListWrap>(
576
          env,
577
          obj,
578
2
          std::move(blocklist));
579
1
  CHECK(wrap);
580
1
  return wrap;
581
}
582
583
15
void SocketAddressBlockListWrap::New(
584
    const FunctionCallbackInfo<Value>& args) {
585
15
  CHECK(args.IsConstructCall());
586
15
  Environment* env = Environment::GetCurrent(args);
587
15
  new SocketAddressBlockListWrap(env, args.This());
588
15
}
589
590
9
void SocketAddressBlockListWrap::AddAddress(
591
    const FunctionCallbackInfo<Value>& args) {
592
9
  Environment* env = Environment::GetCurrent(args);
593
  SocketAddressBlockListWrap* wrap;
594
9
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
595
596
9
  CHECK(SocketAddressBase::HasInstance(env, args[0]));
597
  SocketAddressBase* addr;
598
9
  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
599
600
9
  wrap->blocklist_->AddSocketAddress(addr->address());
601
602
18
  args.GetReturnValue().Set(true);
603
}
604
605
6
void SocketAddressBlockListWrap::AddRange(
606
    const FunctionCallbackInfo<Value>& args) {
607
6
  Environment* env = Environment::GetCurrent(args);
608
  SocketAddressBlockListWrap* wrap;
609
7
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
610
611
6
  CHECK(SocketAddressBase::HasInstance(env, args[0]));
612
6
  CHECK(SocketAddressBase::HasInstance(env, args[1]));
613
614
  SocketAddressBase* start_addr;
615
  SocketAddressBase* end_addr;
616
6
  ASSIGN_OR_RETURN_UNWRAP(&start_addr, args[0]);
617
6
  ASSIGN_OR_RETURN_UNWRAP(&end_addr, args[1]);
618
619
  // Starting address must come before the end address
620
6
  if (*start_addr->address().get() > *end_addr->address().get())
621
2
    return args.GetReturnValue().Set(false);
622
623
5
  wrap->blocklist_->AddSocketAddressRange(
624
      start_addr->address(),
625
5
      end_addr->address());
626
627
10
  args.GetReturnValue().Set(true);
628
}
629
630
7
void SocketAddressBlockListWrap::AddSubnet(
631
    const FunctionCallbackInfo<Value>& args) {
632
7
  Environment* env = Environment::GetCurrent(args);
633
  SocketAddressBlockListWrap* wrap;
634
7
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
635
636
7
  CHECK(SocketAddressBase::HasInstance(env, args[0]));
637
14
  CHECK(args[1]->IsInt32());
638
639
  SocketAddressBase* addr;
640
7
  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
641
642
  int32_t prefix;
643
28
  if (!args[1]->Int32Value(env->context()).To(&prefix)) {
644
    return;
645
  }
646
647

7
  CHECK_IMPLIES(addr->address()->family() == AF_INET, prefix <= 32);
648

7
  CHECK_IMPLIES(addr->address()->family() == AF_INET6, prefix <= 128);
649
7
  CHECK_GE(prefix, 0);
650
651
7
  wrap->blocklist_->AddSocketAddressMask(addr->address(), prefix);
652
653
14
  args.GetReturnValue().Set(true);
654
}
655
656
136
void SocketAddressBlockListWrap::Check(
657
    const FunctionCallbackInfo<Value>& args) {
658
136
  Environment* env = Environment::GetCurrent(args);
659
  SocketAddressBlockListWrap* wrap;
660
136
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
661
662
136
  CHECK(SocketAddressBase::HasInstance(env, args[0]));
663
  SocketAddressBase* addr;
664
136
  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
665
666
408
  args.GetReturnValue().Set(wrap->blocklist_->Apply(addr->address()));
667
}
668
669
2
void SocketAddressBlockListWrap::GetRules(
670
    const FunctionCallbackInfo<Value>& args) {
671
2
  Environment* env = Environment::GetCurrent(args);
672
  SocketAddressBlockListWrap* wrap;
673
2
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
674
  Local<Array> rules;
675
4
  if (wrap->blocklist_->ListRules(env).ToLocal(&rules))
676
4
    args.GetReturnValue().Set(rules);
677
}
678
679
void SocketAddressBlockListWrap::MemoryInfo(MemoryTracker* tracker) const {
680
  blocklist_->MemoryInfo(tracker);
681
}
682
683
std::unique_ptr<worker::TransferData>
684
1
SocketAddressBlockListWrap::CloneForMessaging() const {
685
1
  return std::make_unique<TransferData>(this);
686
}
687
688
bool SocketAddressBlockListWrap::HasInstance(
689
    Environment* env,
690
    Local<Value> value) {
691
  return GetConstructorTemplate(env)->HasInstance(value);
692
}
693
694
457
Local<FunctionTemplate> SocketAddressBlockListWrap::GetConstructorTemplate(
695
    Environment* env) {
696
457
  Local<FunctionTemplate> tmpl = env->blocklist_constructor_template();
697
457
  if (tmpl.IsEmpty()) {
698
457
    tmpl = env->NewFunctionTemplate(SocketAddressBlockListWrap::New);
699
914
    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "BlockList"));
700
914
    tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
701
914
    tmpl->InstanceTemplate()->SetInternalFieldCount(kInternalFieldCount);
702
457
    env->SetProtoMethod(tmpl, "addAddress", AddAddress);
703
457
    env->SetProtoMethod(tmpl, "addRange", AddRange);
704
457
    env->SetProtoMethod(tmpl, "addSubnet", AddSubnet);
705
457
    env->SetProtoMethod(tmpl, "check", Check);
706
457
    env->SetProtoMethod(tmpl, "getRules", GetRules);
707
457
    env->set_blocklist_constructor_template(tmpl);
708
  }
709
457
  return tmpl;
710
}
711
712
457
void SocketAddressBlockListWrap::Initialize(
713
    Local<Object> target,
714
    Local<Value> unused,
715
    Local<Context> context,
716
    void* priv) {
717
457
  Environment* env = Environment::GetCurrent(context);
718
719
457
  env->SetConstructorFunction(
720
      target,
721
      "BlockList",
722
      GetConstructorTemplate(env),
723
457
      Environment::SetConstructorFunctionFlag::NONE);
724
725
457
  SocketAddressBase::Initialize(env, target);
726
727
1828
  NODE_DEFINE_CONSTANT(target, AF_INET);
728
1828
  NODE_DEFINE_CONSTANT(target, AF_INET6);
729
457
}
730
731
1
BaseObjectPtr<BaseObject> SocketAddressBlockListWrap::TransferData::Deserialize(
732
    Environment* env,
733
    Local<Context> context,
734
    std::unique_ptr<worker::TransferData> self) {
735
1
  return New(env, std::move(blocklist_));
736
}
737
738
void SocketAddressBlockListWrap::TransferData::MemoryInfo(
739
    MemoryTracker* tracker) const {
740
  blocklist_->MemoryInfo(tracker);
741
}
742
743
164
bool SocketAddressBase::HasInstance(Environment* env, Local<Value> value) {
744
328
  return GetConstructorTemplate(env)->HasInstance(value);
745
}
746
747
622
Local<FunctionTemplate> SocketAddressBase::GetConstructorTemplate(
748
    Environment* env) {
749
622
  Local<FunctionTemplate> tmpl = env->socketaddress_constructor_template();
750
622
  if (tmpl.IsEmpty()) {
751
457
    tmpl = env->NewFunctionTemplate(New);
752
914
    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "SocketAddress"));
753
1371
    tmpl->InstanceTemplate()->SetInternalFieldCount(
754
457
        SocketAddressBase::kInternalFieldCount);
755
914
    tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
756
457
    env->SetProtoMethod(tmpl, "detail", Detail);
757
457
    env->SetProtoMethod(tmpl, "legacyDetail", LegacyDetail);
758
457
    env->SetProtoMethodNoSideEffect(tmpl, "flowlabel", GetFlowLabel);
759
457
    env->set_socketaddress_constructor_template(tmpl);
760
  }
761
622
  return tmpl;
762
}
763
764
457
void SocketAddressBase::Initialize(Environment* env, Local<Object> target) {
765
457
  env->SetConstructorFunction(
766
      target,
767
      "SocketAddress",
768
      GetConstructorTemplate(env),
769
457
      Environment::SetConstructorFunctionFlag::NONE);
770
457
}
771
772
1
BaseObjectPtr<SocketAddressBase> SocketAddressBase::Create(
773
    Environment* env,
774
    std::shared_ptr<SocketAddress> address) {
775
  Local<Object> obj;
776
3
  if (!GetConstructorTemplate(env)
777
2
          ->InstanceTemplate()
778
4
          ->NewInstance(env->context()).ToLocal(&obj)) {
779
    return BaseObjectPtr<SocketAddressBase>();
780
  }
781
782
1
  return MakeBaseObject<SocketAddressBase>(env, obj, std::move(address));
783
}
784
785
185
void SocketAddressBase::New(const FunctionCallbackInfo<Value>& args) {
786
185
  Environment* env = Environment::GetCurrent(args);
787
185
  CHECK(args.IsConstructCall());
788
555
  CHECK(args[0]->IsString());  // address
789
370
  CHECK(args[1]->IsInt32());  // port
790
370
  CHECK(args[2]->IsInt32());  // family
791
370
  CHECK(args[3]->IsUint32());  // flow label
792
793
366
  Utf8Value address(env->isolate(), args[0]);
794
555
  int32_t port = args[1].As<Int32>()->Value();
795
555
  int32_t family = args[2].As<Int32>()->Value();
796
555
  uint32_t flow_label = args[3].As<Uint32>()->Value();
797
798
366
  std::shared_ptr<SocketAddress> addr = std::make_shared<SocketAddress>();
799
800
185
  if (!SocketAddress::New(family, *address, port, addr.get()))
801
4
    return THROW_ERR_INVALID_ADDRESS(env);
802
803
181
  addr->set_flow_label(flow_label);
804
805
181
  new SocketAddressBase(env, args.This(), std::move(addr));
806
}
807
808
182
void SocketAddressBase::Detail(const FunctionCallbackInfo<Value>& args) {
809
182
  Environment* env = Environment::GetCurrent(args);
810
364
  CHECK(args[0]->IsObject());
811
364
  Local<Object> detail = args[0].As<Object>();
812
813
  SocketAddressBase* base;
814
182
  ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
815
816
  Local<Value> address;
817
364
  if (!ToV8Value(env->context(), base->address_->address()).ToLocal(&address))
818
    return;
819
820

1274
  if (detail->Set(env->context(), env->address_string(), address).IsJust() &&
821
364
      detail->Set(
822
          env->context(),
823
          env->port_string(),
824
1274
          Int32::New(env->isolate(), base->address_->port())).IsJust() &&
825
364
      detail->Set(
826
          env->context(),
827
          env->family_string(),
828

1456
          Int32::New(env->isolate(), base->address_->family())).IsJust() &&
829
364
      detail->Set(
830
          env->context(),
831
          env->flowlabel_string(),
832
910
          Uint32::New(env->isolate(), base->address_->flow_label()))
833
182
              .IsJust()) {
834
364
    args.GetReturnValue().Set(detail);
835
  }
836
}
837
838
8
void SocketAddressBase::GetFlowLabel(const FunctionCallbackInfo<Value>& args) {
839
  SocketAddressBase* base;
840
8
  ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
841
24
  args.GetReturnValue().Set(base->address_->flow_label());
842
}
843
844
void SocketAddressBase::LegacyDetail(const FunctionCallbackInfo<Value>& args) {
845
  Environment* env = Environment::GetCurrent(args);
846
  SocketAddressBase* base;
847
  ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
848
  args.GetReturnValue().Set(base->address_->ToJS(env));
849
}
850
851
182
SocketAddressBase::SocketAddressBase(
852
    Environment* env,
853
    Local<Object> wrap,
854
182
    std::shared_ptr<SocketAddress> address)
855
    : BaseObject(env, wrap),
856
182
      address_(std::move(address)) {
857
182
  MakeWeak();
858
182
}
859
860
void SocketAddressBase::MemoryInfo(MemoryTracker* tracker) const {
861
  tracker->TrackField("address", address_);
862
}
863
864
std::unique_ptr<worker::TransferData>
865
1
SocketAddressBase::CloneForMessaging() const {
866
1
  return std::make_unique<TransferData>(this);
867
}
868
869
void SocketAddressBase::TransferData::MemoryInfo(MemoryTracker* tracker) const {
870
  tracker->TrackField("address", address_);
871
}
872
873
1
BaseObjectPtr<BaseObject> SocketAddressBase::TransferData::Deserialize(
874
    Environment* env,
875
    v8::Local<v8::Context> context,
876
    std::unique_ptr<worker::TransferData> self) {
877
1
  return SocketAddressBase::Create(env, std::move(address_));
878
}
879
880
}  // namespace node
881
882

19072
NODE_MODULE_CONTEXT_AWARE_INTERNAL(
883
    block_list,
884
    node::SocketAddressBlockListWrap::Initialize)