GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_sockaddr-inl.h Lines: 112 116 96.6 %
Date: 2022-06-12 04:16:28 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
6056
inline void hash_combine(size_t* seed) { }
20
21
template <typename T, typename... Args>
22
36260
inline void hash_combine(size_t* seed, const T& value, Args... rest) {
23
36260
    *seed ^= std::hash<T>{}(value) + 0x9e3779b9 + (*seed << 6) + (*seed >> 2);
24
36260
    hash_combine(seed, rest...);
25
36260
}
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
18277
int SocketAddress::GetPort(const sockaddr* addr) {
38

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

18281
  CHECK(addr->sa_family == AF_INET || addr->sa_family == AF_INET6);
50
  char host[INET6_ADDRSTRLEN];
51
18281
  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
18281
  uv_inet_ntop(addr->sa_family, src, host, INET6_ADDRSTRLEN);
57
18281
  return std::string(host);
58
}
59
60
18281
std::string SocketAddress::GetAddress(const sockaddr_storage* addr) {
61
18281
  return GetAddress(reinterpret_cast<const sockaddr*>(addr));
62
}
63
64
6073
size_t SocketAddress::GetLength(const sockaddr* addr) {
65
6073
  return addr->sa_family == AF_INET ?
66
6073
      sizeof(sockaddr_in) : sizeof(sockaddr_in6);
67
}
68
69
6058
size_t SocketAddress::GetLength(const sockaddr_storage* addr) {
70
6058
  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
6035
SocketAddress::SocketAddress(const SocketAddress& addr) {
78
6035
  memcpy(&address_, &addr.address_, addr.length());
79
6035
}
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
6058
size_t SocketAddress::length() const {
100
6058
  return GetLength(&address_);
101
}
102
103
19039
const sockaddr* SocketAddress::data() const {
104
19039
  return reinterpret_cast<const sockaddr*>(&address_);
105
}
106
107
6096
const uint8_t* SocketAddress::raw() const {
108
6096
  return reinterpret_cast<const uint8_t*>(&address_);
109
}
110
111
18277
sockaddr* SocketAddress::storage() {
112
18277
  return reinterpret_cast<sockaddr*>(&address_);
113
}
114
115
73869
int SocketAddress::family() const {
116
73869
  return address_.ss_family;
117
}
118
119
18281
std::string SocketAddress::address() const {
120
18281
  return GetAddress(&address_);
121
}
122
123
18277
int SocketAddress::port() const {
124
18277
  return GetPort(&address_);
125
}
126
127
18284
uint32_t SocketAddress::flow_label() const {
128
18284
  if (family() != AF_INET6)
129
12165
    return 0;
130
6119
  const sockaddr_in6* in = reinterpret_cast<const sockaddr_in6*>(data());
131
6119
  return in->sin6_flowinfo;
132
}
133
134
18275
void SocketAddress::set_flow_label(uint32_t label) {
135
18275
  if (family() != AF_INET6)
136
12158
    return;
137
6117
  CHECK_LE(label, kLabelMask);
138
6117
  sockaddr_in6* in = reinterpret_cast<sockaddr_in6*>(&address_);
139
6117
  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
6026
bool SocketAddress::operator>(const SocketAddress& other) const {
180
6026
  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_