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 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 SET_NO_MEMORY_INFO() 141 SET_MEMORY_INFO_NAME(SocketAddress) 142 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 address()171 inline const std::shared_ptr<SocketAddress>& address() const { 172 return address_; 173 } 174 175 void MemoryInfo(MemoryTracker* tracker) const override; 176 SET_MEMORY_INFO_NAME(SocketAddressBase) SET_SELF_SIZE(SocketAddressBase)177 SET_SELF_SIZE(SocketAddressBase) 178 179 TransferMode GetTransferMode() const override { 180 return TransferMode::kCloneable; 181 } 182 std::unique_ptr<worker::TransferData> CloneForMessaging() const override; 183 184 class TransferData : public worker::TransferData { 185 public: TransferData(const SocketAddressBase * wrap)186 inline explicit TransferData(const SocketAddressBase* wrap) 187 : address_(wrap->address_) {} 188 TransferData(std::shared_ptr<SocketAddress> address)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 size()226 size_t size() const { return map_.size(); } max_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 ~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 size()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 SET_MEMORY_INFO_NAME(SocketAddressRule) 287 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 SET_MEMORY_INFO_NAME(SocketAddressRangeRule) 303 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 SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap) SET_SELF_SIZE(SocketAddressBlockListWrap)368 SET_SELF_SIZE(SocketAddressBlockListWrap) 369 370 TransferMode GetTransferMode() const override { 371 return TransferMode::kCloneable; 372 } 373 std::unique_ptr<worker::TransferData> CloneForMessaging() const override; 374 375 class TransferData : public worker::TransferData { 376 public: TransferData(const SocketAddressBlockListWrap * wrap)377 inline explicit TransferData(const SocketAddressBlockListWrap* wrap) 378 : blocklist_(wrap->blocklist_) {} 379 TransferData(std::shared_ptr<SocketAddressBlockList> blocklist)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_ 406