GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_sockaddr-inl.h Lines: 112 116 96.6 %
Date: 2022-04-05 04:14:57 Branches: 35 42 83.3 %

Line Branch Exec Source
1
#ifndef SRC_NODE_SOCKADDR_INL_H_
2
#define SRC_NODE_SOCKADDR_INL_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "node.h"
7
#include "env-inl.h"
8
#include "node_internals.h"
9
#include "node_sockaddr.h"
10
#include "util-inl.h"
11
#include "memory_tracker-inl.h"
12
13
#include <string>
14
15
namespace node {
16
17
static constexpr uint32_t kLabelMask = 0xFFFFF;
18
19
5605
inline void hash_combine(size_t* seed) { }
20
21
template <typename T, typename... Args>
22
33554
inline void hash_combine(size_t* seed, const T& value, Args... rest) {
23
33554
    *seed ^= std::hash<T>{}(value) + 0x9e3779b9 + (*seed << 6) + (*seed >> 2);
24
33554
    hash_combine(seed, rest...);
25
33554
}
26
27
2
bool SocketAddress::is_numeric_host(const char* hostname) {
28

3
  return is_numeric_host(hostname, AF_INET) ||
29
3
         is_numeric_host(hostname, AF_INET6);
30
}
31
32
3
bool SocketAddress::is_numeric_host(const char* hostname, int family) {
33
  in6_addr dst;
34
3
  return inet_pton(family, hostname, &dst) == 1;
35
}
36
37
16924
int SocketAddress::GetPort(const sockaddr* addr) {
38

16924
  CHECK(addr->sa_family == AF_INET || addr->sa_family == AF_INET6);
39
16924
  return ntohs(addr->sa_family == AF_INET ?
40
11258
      reinterpret_cast<const sockaddr_in*>(addr)->sin_port :
41
16924
      reinterpret_cast<const sockaddr_in6*>(addr)->sin6_port);
42
}
43
44
16924
int SocketAddress::GetPort(const sockaddr_storage* addr) {
45
16924
  return GetPort(reinterpret_cast<const sockaddr*>(addr));
46
}
47
48
16928
std::string SocketAddress::GetAddress(const sockaddr* addr) {
49

16928
  CHECK(addr->sa_family == AF_INET || addr->sa_family == AF_INET6);
50
  char host[INET6_ADDRSTRLEN];
51
16928
  const void* src = addr->sa_family == AF_INET ?
52
      static_cast<const void*>(
53
          &(reinterpret_cast<const sockaddr_in*>(addr)->sin_addr)) :
54
      static_cast<const void*>(
55
          &(reinterpret_cast<const sockaddr_in6*>(addr)->sin6_addr));
56
16928
  uv_inet_ntop(addr->sa_family, src, host, INET6_ADDRSTRLEN);
57
16928
  return std::string(host);
58
}
59
60
16928
std::string SocketAddress::GetAddress(const sockaddr_storage* addr) {
61
16928
  return GetAddress(reinterpret_cast<const sockaddr*>(addr));
62
}
63
64
5622
size_t SocketAddress::GetLength(const sockaddr* addr) {
65
5622
  return addr->sa_family == AF_INET ?
66
5622
      sizeof(sockaddr_in) : sizeof(sockaddr_in6);
67
}
68
69
5607
size_t SocketAddress::GetLength(const sockaddr_storage* addr) {
70
5607
  return GetLength(reinterpret_cast<const sockaddr*>(addr));
71
}
72
73
15
SocketAddress::SocketAddress(const sockaddr* addr) {
74
15
  memcpy(&address_, addr, GetLength(addr));
75
15
}
76
77
5584
SocketAddress::SocketAddress(const SocketAddress& addr) {
78
5584
  memcpy(&address_, &addr.address_, addr.length());
79
5584
}
80
81
SocketAddress& SocketAddress::operator=(const sockaddr* addr) {
82
  memcpy(&address_, addr, GetLength(addr));
83
  return *this;
84
}
85
86
SocketAddress& SocketAddress::operator=(const SocketAddress& addr) {
87
  memcpy(&address_, &addr.address_, addr.length());
88
  return *this;
89
}
90
91
const sockaddr& SocketAddress::operator*() const {
92
  return *data();
93
}
94
95
const sockaddr* SocketAddress::operator->() const {
96
  return data();
97
}
98
99
5607
size_t SocketAddress::length() const {
100
5607
  return GetLength(&address_);
101
}
102
103
17686
const sockaddr* SocketAddress::data() const {
104
17686
  return reinterpret_cast<const sockaddr*>(&address_);
105
}
106
107
5645
const uint8_t* SocketAddress::raw() const {
108
5645
  return reinterpret_cast<const uint8_t*>(&address_);
109
}
110
111
16924
sockaddr* SocketAddress::storage() {
112
16924
  return reinterpret_cast<sockaddr*>(&address_);
113
}
114
115
68457
int SocketAddress::family() const {
116
68457
  return address_.ss_family;
117
}
118
119
16928
std::string SocketAddress::address() const {
120
16928
  return GetAddress(&address_);
121
}
122
123
16924
int SocketAddress::port() const {
124
16924
  return GetPort(&address_);
125
}
126
127
16931
uint32_t SocketAddress::flow_label() const {
128
16931
  if (family() != AF_INET6)
129
11263
    return 0;
130
5668
  const sockaddr_in6* in = reinterpret_cast<const sockaddr_in6*>(data());
131
5668
  return in->sin6_flowinfo;
132
}
133
134
16922
void SocketAddress::set_flow_label(uint32_t label) {
135
16922
  if (family() != AF_INET6)
136
11256
    return;
137
5666
  CHECK_LE(label, kLabelMask);
138
5666
  sockaddr_in6* in = reinterpret_cast<sockaddr_in6*>(&address_);
139
5666
  in->sin6_flowinfo = label;
140
}
141
142
std::string SocketAddress::ToString() const {
143
  if (family() != AF_INET && family() != AF_INET6) return "";
144
  return (family() == AF_INET6 ?
145
              std::string("[") + address() + "]:" :
146
              address() + ":") +
147
      std::to_string(port());
148
}
149
150
1
void SocketAddress::Update(uint8_t* data, size_t len) {
151
1
  CHECK_LE(len, sizeof(address_));
152
1
  memcpy(&address_, data, len);
153
1
}
154
155
void SocketAddress::Update(const sockaddr* data, size_t len) {
156
  CHECK_LE(len, sizeof(address_));
157
  memcpy(&address_, data, len);
158
}
159
160
v8::MaybeLocal<v8::Object> SocketAddress::ToJS(
161
    Environment* env,
162
    v8::Local<v8::Object> info) const {
163
  return AddressToJS(env, data(), info);
164
}
165
166
20
bool SocketAddress::operator==(const SocketAddress& other) const {
167
20
  if (family() != other.family()) return false;
168
20
  return memcmp(raw(), other.raw(), length()) == 0;
169
}
170
171
1
bool SocketAddress::operator!=(const SocketAddress& other) const {
172
1
  return !(*this == other);
173
}
174
175
5
bool SocketAddress::operator<(const SocketAddress& other) const {
176
5
  return compare(other) == CompareResult::LESS_THAN;
177
}
178
179
5575
bool SocketAddress::operator>(const SocketAddress& other) const {
180
5575
  return compare(other) == CompareResult::GREATER_THAN;
181
}
182
183
86
bool SocketAddress::operator<=(const SocketAddress& other) const {
184
86
  CompareResult c = compare(other);
185

86
  return c == CompareResult::NOT_COMPARABLE ? false :
186
86
              c <= CompareResult::SAME;
187
}
188
189
149
bool SocketAddress::operator>=(const SocketAddress& other) const {
190
149
  return compare(other) >= CompareResult::SAME;
191
}
192
193
template <typename T>
194
1
SocketAddressLRU<T>::SocketAddressLRU(
195
    size_t max_size)
196
1
    : max_size_(max_size) {}
197
198
template <typename T>
199
11
typename T::Type* SocketAddressLRU<T>::Peek(
200
    const SocketAddress& address) const {
201
11
  auto it = map_.find(address);
202
11
  return it == std::end(map_) ? nullptr : &it->second->second;
203
}
204
205
template <typename T>
206
4
void SocketAddressLRU<T>::CheckExpired() {
207
4
  auto it = list_.rbegin();
208
5
  while (it != list_.rend()) {
209
5
    if (T::CheckExpired(it->first, it->second)) {
210
1
      map_.erase(it->first);
211
1
      list_.pop_back();
212
1
      it = list_.rbegin();
213
1
      continue;
214
    } else {
215
4
      break;
216
    }
217
  }
218
4
}
219
220
template <typename T>
221
void SocketAddressLRU<T>::MemoryInfo(MemoryTracker* tracker) const {
222
  tracker->TrackFieldWithSize("list", size() * sizeof(Pair));
223
}
224
225
// If an item already exists for the given address, bump up it's
226
// position in the LRU list and return it. If the item does not
227
// exist, create it. If an item is created, check the size of the
228
// cache and adjust if necessary. Whether the item exists or not,
229
// purge expired items.
230
template <typename T>
231
4
typename T::Type* SocketAddressLRU<T>::Upsert(
232
    const SocketAddress& address) {
233
234
12
  auto on_exit = OnScopeLeave([&]() { CheckExpired(); });
235
236
4
  auto it = map_.find(address);
237
4
  if (it != std::end(map_)) {
238
1
    list_.splice(list_.begin(), list_, it->second);
239
1
    T::Touch(it->first, &it->second->second);
240
1
    return &it->second->second;
241
  }
242
243
3
  list_.push_front(Pair(address, { }));
244
3
  map_[address] = list_.begin();
245
3
  T::Touch(list_.begin()->first, &list_.begin()->second);
246
247
  // Drop the last item in the list if we are
248
  // over the size limit...
249
3
  if (map_.size() > max_size_) {
250
1
    auto last = list_.end();
251
1
    map_.erase((--last)->first);
252
1
    list_.pop_back();
253
  }
254
255
3
  return &map_[address]->second;
256
}
257
258
3
v8::MaybeLocal<v8::Value> SocketAddressBlockList::Rule::ToV8String(
259
    Environment* env) {
260
6
  std::string str = ToString();
261
3
  return ToV8Value(env->context(), str);
262
}
263
}  // namespace node
264
265
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
266
#endif  // SRC_NODE_SOCKADDR_INL_H_