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 addres 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 128 static SocketAddress FromSockName(const uv_udp_t& handle); 129 static SocketAddress FromSockName(const uv_tcp_t& handle); 130 static SocketAddress FromPeerName(const uv_udp_t& handle); 131 static SocketAddress FromPeerName(const uv_tcp_t& handle); 132 133 inline v8::Local<v8::Object> ToJS( 134 Environment* env, 135 v8::Local<v8::Object> obj = v8::Local<v8::Object>()) const; 136 137 inline std::string ToString() const; 138 139 SET_NO_MEMORY_INFO() 140 SET_MEMORY_INFO_NAME(SocketAddress) 141 SET_SELF_SIZE(SocketAddress) 142 143 template <typename T> 144 using Map = std::unordered_map<SocketAddress, T, Hash>; 145 146 private: 147 sockaddr_storage address_; 148 }; 149 150 class SocketAddressBase : public BaseObject { 151 public: 152 static bool HasInstance(Environment* env, v8::Local<v8::Value> value); 153 static v8::Local<v8::FunctionTemplate> GetConstructorTemplate( 154 Environment* env); 155 static void Initialize(Environment* env, v8::Local<v8::Object> target); 156 static BaseObjectPtr<SocketAddressBase> Create( 157 Environment* env, 158 std::shared_ptr<SocketAddress> address); 159 160 static void New(const v8::FunctionCallbackInfo<v8::Value>& args); 161 static void Detail(const v8::FunctionCallbackInfo<v8::Value>& args); 162 static void LegacyDetail(const v8::FunctionCallbackInfo<v8::Value>& args); 163 static void GetFlowLabel(const v8::FunctionCallbackInfo<v8::Value>& args); 164 165 SocketAddressBase( 166 Environment* env, 167 v8::Local<v8::Object> wrap, 168 std::shared_ptr<SocketAddress> address); 169 address()170 inline const std::shared_ptr<SocketAddress>& address() const { 171 return address_; 172 } 173 174 void MemoryInfo(MemoryTracker* tracker) const override; 175 SET_MEMORY_INFO_NAME(SocketAddressBase) SET_SELF_SIZE(SocketAddressBase)176 SET_SELF_SIZE(SocketAddressBase) 177 178 TransferMode GetTransferMode() const override { 179 return TransferMode::kCloneable; 180 } 181 std::unique_ptr<worker::TransferData> CloneForMessaging() const override; 182 183 class TransferData : public worker::TransferData { 184 public: TransferData(const SocketAddressBase * wrap)185 inline explicit TransferData(const SocketAddressBase* wrap) 186 : address_(wrap->address_) {} 187 TransferData(std::shared_ptr<SocketAddress> address)188 inline explicit TransferData(std::shared_ptr<SocketAddress> address) 189 : address_(std::move(address)) {} 190 191 BaseObjectPtr<BaseObject> Deserialize( 192 Environment* env, 193 v8::Local<v8::Context> context, 194 std::unique_ptr<worker::TransferData> self) override; 195 196 void MemoryInfo(MemoryTracker* tracker) const override; 197 SET_MEMORY_INFO_NAME(SocketAddressBase::TransferData) 198 SET_SELF_SIZE(TransferData) 199 200 private: 201 std::shared_ptr<SocketAddress> address_; 202 }; 203 204 private: 205 std::shared_ptr<SocketAddress> address_; 206 }; 207 208 template <typename T> 209 class SocketAddressLRU : public MemoryRetainer { 210 public: 211 using Type = typename T::Type; 212 213 inline explicit SocketAddressLRU(size_t max_size); 214 215 // If the item already exists, returns a reference to 216 // the existing item, adjusting items position in the 217 // LRU. If the item does not exist, emplaces the item 218 // and returns the new item. 219 Type* Upsert(const SocketAddress& address); 220 221 // Returns a reference to the item if it exists, or 222 // nullptr. The position in the LRU is not modified. 223 Type* Peek(const SocketAddress& address) const; 224 size()225 size_t size() const { return map_.size(); } max_size()226 size_t max_size() const { return max_size_; } 227 228 void MemoryInfo(MemoryTracker* tracker) const override; 229 SET_MEMORY_INFO_NAME(SocketAddressLRU) 230 SET_SELF_SIZE(SocketAddressLRU) 231 232 private: 233 using Pair = std::pair<SocketAddress, Type>; 234 using Iterator = typename std::list<Pair>::iterator; 235 236 void CheckExpired(); 237 238 std::list<Pair> list_; 239 SocketAddress::Map<Iterator> map_; 240 size_t max_size_; 241 }; 242 243 // A BlockList is used to evaluate whether a given 244 // SocketAddress should be accepted for inbound or 245 // outbound network activity. 246 class SocketAddressBlockList : public MemoryRetainer { 247 public: 248 explicit SocketAddressBlockList( 249 std::shared_ptr<SocketAddressBlockList> parent = {}); 250 ~SocketAddressBlockList() = default; 251 252 void AddSocketAddress(const std::shared_ptr<SocketAddress>& address); 253 254 void RemoveSocketAddress(const std::shared_ptr<SocketAddress>& address); 255 256 void AddSocketAddressRange( 257 const std::shared_ptr<SocketAddress>& start, 258 const std::shared_ptr<SocketAddress>& end); 259 260 void AddSocketAddressMask( 261 const std::shared_ptr<SocketAddress>& address, 262 int prefix); 263 264 bool Apply(const std::shared_ptr<SocketAddress>& address); 265 size()266 size_t size() const { return rules_.size(); } 267 268 v8::MaybeLocal<v8::Array> ListRules(Environment* env); 269 270 struct Rule : public MemoryRetainer { 271 virtual bool Apply(const std::shared_ptr<SocketAddress>& address) = 0; 272 inline v8::MaybeLocal<v8::Value> ToV8String(Environment* env); 273 virtual std::string ToString() = 0; 274 }; 275 276 struct SocketAddressRule final : Rule { 277 std::shared_ptr<SocketAddress> address; 278 279 explicit SocketAddressRule(const std::shared_ptr<SocketAddress>& address); 280 281 bool Apply(const std::shared_ptr<SocketAddress>& address) override; 282 std::string ToString() override; 283 284 void MemoryInfo(node::MemoryTracker* tracker) const override; 285 SET_MEMORY_INFO_NAME(SocketAddressRule) 286 SET_SELF_SIZE(SocketAddressRule) 287 }; 288 289 struct SocketAddressRangeRule final : Rule { 290 std::shared_ptr<SocketAddress> start; 291 std::shared_ptr<SocketAddress> end; 292 293 SocketAddressRangeRule( 294 const std::shared_ptr<SocketAddress>& start, 295 const std::shared_ptr<SocketAddress>& end); 296 297 bool Apply(const std::shared_ptr<SocketAddress>& address) override; 298 std::string ToString() override; 299 300 void MemoryInfo(node::MemoryTracker* tracker) const override; 301 SET_MEMORY_INFO_NAME(SocketAddressRangeRule) 302 SET_SELF_SIZE(SocketAddressRangeRule) 303 }; 304 305 struct SocketAddressMaskRule final : Rule { 306 std::shared_ptr<SocketAddress> network; 307 int prefix; 308 309 SocketAddressMaskRule( 310 const std::shared_ptr<SocketAddress>& address, 311 int prefix); 312 313 bool Apply(const std::shared_ptr<SocketAddress>& address) override; 314 std::string ToString() override; 315 316 void MemoryInfo(node::MemoryTracker* tracker) const override; 317 SET_MEMORY_INFO_NAME(SocketAddressMaskRule) 318 SET_SELF_SIZE(SocketAddressMaskRule) 319 }; 320 321 void MemoryInfo(node::MemoryTracker* tracker) const override; 322 SET_MEMORY_INFO_NAME(SocketAddressBlockList) 323 SET_SELF_SIZE(SocketAddressBlockList) 324 325 private: 326 bool ListRules( 327 Environment* env, 328 std::vector<v8::Local<v8::Value>>* vec); 329 330 std::shared_ptr<SocketAddressBlockList> parent_; 331 std::list<std::unique_ptr<Rule>> rules_; 332 SocketAddress::Map<std::list<std::unique_ptr<Rule>>::iterator> address_rules_; 333 334 Mutex mutex_; 335 }; 336 337 class SocketAddressBlockListWrap : public BaseObject { 338 public: 339 static bool HasInstance(Environment* env, v8::Local<v8::Value> value); 340 static v8::Local<v8::FunctionTemplate> GetConstructorTemplate( 341 Environment* env); 342 static void Initialize(v8::Local<v8::Object> target, 343 v8::Local<v8::Value> unused, 344 v8::Local<v8::Context> context, 345 void* priv); 346 347 static BaseObjectPtr<SocketAddressBlockListWrap> New(Environment* env); 348 static BaseObjectPtr<SocketAddressBlockListWrap> New( 349 Environment* env, 350 std::shared_ptr<SocketAddressBlockList> blocklist); 351 352 static void New(const v8::FunctionCallbackInfo<v8::Value>& args); 353 static void AddAddress(const v8::FunctionCallbackInfo<v8::Value>& args); 354 static void AddRange(const v8::FunctionCallbackInfo<v8::Value>& args); 355 static void AddSubnet(const v8::FunctionCallbackInfo<v8::Value>& args); 356 static void Check(const v8::FunctionCallbackInfo<v8::Value>& args); 357 static void GetRules(const v8::FunctionCallbackInfo<v8::Value>& args); 358 359 SocketAddressBlockListWrap( 360 Environment* env, 361 v8::Local<v8::Object> wrap, 362 std::shared_ptr<SocketAddressBlockList> blocklist = 363 std::make_shared<SocketAddressBlockList>()); 364 365 void MemoryInfo(node::MemoryTracker* tracker) const override; 366 SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap) SET_SELF_SIZE(SocketAddressBlockListWrap)367 SET_SELF_SIZE(SocketAddressBlockListWrap) 368 369 TransferMode GetTransferMode() const override { 370 return TransferMode::kCloneable; 371 } 372 std::unique_ptr<worker::TransferData> CloneForMessaging() const override; 373 374 class TransferData : public worker::TransferData { 375 public: TransferData(const SocketAddressBlockListWrap * wrap)376 inline explicit TransferData(const SocketAddressBlockListWrap* wrap) 377 : blocklist_(wrap->blocklist_) {} 378 TransferData(std::shared_ptr<SocketAddressBlockList> blocklist)379 inline explicit TransferData( 380 std::shared_ptr<SocketAddressBlockList> blocklist) 381 : blocklist_(std::move(blocklist)) {} 382 383 BaseObjectPtr<BaseObject> Deserialize( 384 Environment* env, 385 v8::Local<v8::Context> context, 386 std::unique_ptr<worker::TransferData> self) override; 387 388 void MemoryInfo(MemoryTracker* tracker) const override; 389 SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap::TransferData) 390 SET_SELF_SIZE(TransferData) 391 392 private: 393 std::shared_ptr<SocketAddressBlockList> blocklist_; 394 }; 395 396 private: 397 std::shared_ptr<SocketAddressBlockList> blocklist_; 398 }; 399 400 } // namespace node 401 402 #endif // NOE_WANT_INTERNALS 403 404 #endif // SRC_NODE_SOCKADDR_H_ 405