#ifndef SRC_NODE_SOCKADDR_H_ #define SRC_NODE_SOCKADDR_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "env.h" #include "memory_tracker.h" #include "base_object.h" #include "node.h" #include "uv.h" #include "v8.h" #include #include #include #include namespace node { class Environment; class SocketAddress : public MemoryRetainer { public: enum class CompareResult { NOT_COMPARABLE = -2, LESS_THAN, SAME, GREATER_THAN }; struct Hash { size_t operator()(const SocketAddress& addr) const; }; inline bool operator==(const SocketAddress& other) const; inline bool operator!=(const SocketAddress& other) const; inline bool operator<(const SocketAddress& other) const; inline bool operator>(const SocketAddress& other) const; inline bool operator<=(const SocketAddress& other) const; inline bool operator>=(const SocketAddress& other) const; inline static bool is_numeric_host(const char* hostname); inline static bool is_numeric_host(const char* hostname, int family); // Returns true if converting {family, host, port} to *addr succeeded. static bool ToSockAddr( int32_t family, const char* host, uint32_t port, sockaddr_storage* addr); // Returns true if converting {family, host, port} to *addr succeeded. static bool New( int32_t family, const char* host, uint32_t port, SocketAddress* addr); static bool New( const char* host, uint32_t port, SocketAddress* addr); // Returns the port for an IPv4 or IPv6 address. inline static int GetPort(const sockaddr* addr); inline static int GetPort(const sockaddr_storage* addr); // Returns the numeric host as a string for an IPv4 or IPv6 address. inline static std::string GetAddress(const sockaddr* addr); inline static std::string GetAddress(const sockaddr_storage* addr); // Returns the struct length for an IPv4, IPv6 or UNIX domain. inline static size_t GetLength(const sockaddr* addr); inline static size_t GetLength(const sockaddr_storage* addr); SocketAddress() = default; inline explicit SocketAddress(const sockaddr* addr); inline SocketAddress(const SocketAddress& addr); inline SocketAddress& operator=(const sockaddr* other); inline SocketAddress& operator=(const SocketAddress& other); inline const sockaddr& operator*() const; inline const sockaddr* operator->() const; inline const sockaddr* data() const; inline const uint8_t* raw() const; inline sockaddr* storage(); inline size_t length() const; inline int family() const; inline std::string address() const; inline int port() const; // Returns true if the given other SocketAddress is a match // for this one. The addresses are a match if: // 1. They are the same family and match identically // 2. They are different family but match semantically ( // for instance, an IPv4 addres in IPv6 notation) bool is_match(const SocketAddress& other) const; // Compares this SocketAddress to the given other SocketAddress. CompareResult compare(const SocketAddress& other) const; // Returns true if this SocketAddress is within the subnet // identified by the given network address and CIDR prefix. bool is_in_network(const SocketAddress& network, int prefix) const; // If the SocketAddress is an IPv6 address, returns the // current value of the IPv6 flow label, if set. Otherwise // returns 0. inline uint32_t flow_label() const; // If the SocketAddress is an IPv6 address, sets the // current value of the IPv6 flow label. If not an // IPv6 address, set_flow_label is a non-op. It // is important to note that the flow label, // while represented as an uint32_t, the flow // label is strictly limited to 20 bits, and // this will assert if any value larger than // 20-bits is specified. inline void set_flow_label(uint32_t label = 0); inline void Update(uint8_t* data, size_t len); inline void Update(const sockaddr* data, size_t len); static SocketAddress FromSockName(const uv_udp_t& handle); static SocketAddress FromSockName(const uv_tcp_t& handle); static SocketAddress FromPeerName(const uv_udp_t& handle); static SocketAddress FromPeerName(const uv_tcp_t& handle); inline v8::Local ToJS( Environment* env, v8::Local obj = v8::Local()) const; inline std::string ToString() const; SET_NO_MEMORY_INFO() SET_MEMORY_INFO_NAME(SocketAddress) SET_SELF_SIZE(SocketAddress) template using Map = std::unordered_map; private: sockaddr_storage address_; }; template class SocketAddressLRU : public MemoryRetainer { public: using Type = typename T::Type; inline explicit SocketAddressLRU(size_t max_size); // If the item already exists, returns a reference to // the existing item, adjusting items position in the // LRU. If the item does not exist, emplaces the item // and returns the new item. Type* Upsert(const SocketAddress& address); // Returns a reference to the item if it exists, or // nullptr. The position in the LRU is not modified. Type* Peek(const SocketAddress& address) const; size_t size() const { return map_.size(); } size_t max_size() const { return max_size_; } void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(SocketAddressLRU) SET_SELF_SIZE(SocketAddressLRU) private: using Pair = std::pair; using Iterator = typename std::list::iterator; void CheckExpired(); std::list list_; SocketAddress::Map map_; size_t max_size_; }; // A BlockList is used to evaluate whether a given // SocketAddress should be accepted for inbound or // outbound network activity. class SocketAddressBlockList : public MemoryRetainer { public: explicit SocketAddressBlockList( std::shared_ptr parent = {}); ~SocketAddressBlockList() = default; void AddSocketAddress( const SocketAddress& address); void RemoveSocketAddress( const SocketAddress& address); void AddSocketAddressRange( const SocketAddress& start, const SocketAddress& end); void AddSocketAddressMask( const SocketAddress& address, int prefix); bool Apply(const SocketAddress& address); size_t size() const { return rules_.size(); } v8::MaybeLocal ListRules(Environment* env); struct Rule : public MemoryRetainer { virtual bool Apply(const SocketAddress& address) = 0; inline v8::MaybeLocal ToV8String(Environment* env); virtual std::string ToString() = 0; }; struct SocketAddressRule final : Rule { SocketAddress address; explicit SocketAddressRule(const SocketAddress& address); bool Apply(const SocketAddress& address) override; std::string ToString() override; void MemoryInfo(node::MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(SocketAddressRule) SET_SELF_SIZE(SocketAddressRule) }; struct SocketAddressRangeRule final : Rule { SocketAddress start; SocketAddress end; SocketAddressRangeRule( const SocketAddress& start, const SocketAddress& end); bool Apply(const SocketAddress& address) override; std::string ToString() override; void MemoryInfo(node::MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(SocketAddressRangeRule) SET_SELF_SIZE(SocketAddressRangeRule) }; struct SocketAddressMaskRule final : Rule { SocketAddress network; int prefix; SocketAddressMaskRule( const SocketAddress& address, int prefix); bool Apply(const SocketAddress& address) override; std::string ToString() override; void MemoryInfo(node::MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(SocketAddressMaskRule) SET_SELF_SIZE(SocketAddressMaskRule) }; void MemoryInfo(node::MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(SocketAddressBlockList) SET_SELF_SIZE(SocketAddressBlockList) private: std::shared_ptr parent_; std::list> rules_; SocketAddress::Map>::iterator> address_rules_; }; class SocketAddressBlockListWrap : public BaseObject, public SocketAddressBlockList { public: static void Initialize(v8::Local target, v8::Local unused, v8::Local context, void* priv); static BaseObjectPtr New(Environment* env); static void New(const v8::FunctionCallbackInfo& args); static void AddAddress(const v8::FunctionCallbackInfo& args); static void AddRange(const v8::FunctionCallbackInfo& args); static void AddSubnet(const v8::FunctionCallbackInfo& args); static void Check(const v8::FunctionCallbackInfo& args); static void GetRules(const v8::FunctionCallbackInfo& args); SocketAddressBlockListWrap( Environment* env, v8::Local wrap); void MemoryInfo(node::MemoryTracker* tracker) const override { SocketAddressBlockList::MemoryInfo(tracker); } SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap) SET_SELF_SIZE(SocketAddressBlockListWrap) }; } // namespace node #endif // NOE_WANT_INTERNALS #endif // SRC_NODE_SOCKADDR_H_