|  | // Copyright 2017 The Fuchsia Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef SRC_LIB_INET_SOCKET_ADDRESS_H_ | 
|  | #define SRC_LIB_INET_SOCKET_ADDRESS_H_ | 
|  |  | 
|  | #include <arpa/inet.h> | 
|  | #include <fuchsia/net/cpp/fidl.h> | 
|  | #include <fuchsia/netstack/cpp/fidl.h> | 
|  | #include <lib/syslog/cpp/macros.h> | 
|  | #include <sys/socket.h> | 
|  |  | 
|  | #include <ostream> | 
|  |  | 
|  | #include "src/lib/inet/ip_address.h" | 
|  | #include "src/lib/inet/ip_port.h" | 
|  |  | 
|  | namespace inet { | 
|  |  | 
|  | // Represents a V4 or V6 socket address. | 
|  | class SocketAddress { | 
|  | public: | 
|  | static const SocketAddress kInvalid; | 
|  |  | 
|  | // Creates an invalid socket. | 
|  | SocketAddress(); | 
|  |  | 
|  | // Creates an IPV4 socket address from four address bytes and an IpPort. | 
|  | SocketAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, IpPort port); | 
|  |  | 
|  | // Creates an IPV4 socket address from an in_addr_t and an IpPort. | 
|  | SocketAddress(in_addr_t addr, IpPort port); | 
|  |  | 
|  | // Creates an IPV4 socket address from an sockaddr_in struct. | 
|  | explicit SocketAddress(const sockaddr_in& addr); | 
|  |  | 
|  | // Creates an IPV6 socket address from eight address words and an IpPort. | 
|  | SocketAddress(uint16_t w0, uint16_t w1, uint16_t w2, uint16_t w3, uint16_t w4, uint16_t w5, | 
|  | uint16_t w6, uint16_t w7, IpPort port); | 
|  |  | 
|  | // Creates an IPV6 socket address from two address words and an IpPort. | 
|  | SocketAddress(uint16_t w0, uint16_t w7, IpPort port); | 
|  |  | 
|  | // Creates an IPV6 socket address from an in6_addr struct and an IpPort. | 
|  | SocketAddress(const in6_addr& addr, IpPort port); | 
|  |  | 
|  | // Creates an IPV6 socket address from an sockaddr_in6 struct. | 
|  | explicit SocketAddress(const sockaddr_in6& addr); | 
|  |  | 
|  | // Creates a socket address from a IpAddress and an IpPort. | 
|  | SocketAddress(const IpAddress& addr, IpPort port, uint32_t scope_id = 0); | 
|  |  | 
|  | // Creates a socket address from an sockaddr_storage struct. | 
|  | explicit SocketAddress(const sockaddr_storage& addr); | 
|  |  | 
|  | // Creates a socket address from a fuchsia.netstack SocketAddress struct. | 
|  | explicit SocketAddress(const fuchsia::netstack::SocketAddress* addr); | 
|  |  | 
|  | // Creates a socket address from a fuchsia.net SocketAddress struct. | 
|  | explicit SocketAddress(const fuchsia::net::SocketAddress* addr); | 
|  |  | 
|  | // Creates a socket address from a fuchsia.net Ipv4SocketAddress struct. | 
|  | explicit SocketAddress(const fuchsia::net::Ipv4SocketAddress* addr); | 
|  |  | 
|  | // Creates a socket address from a fuchsia.net Ipv6SocketAddress struct. | 
|  | explicit SocketAddress(const fuchsia::net::Ipv6SocketAddress* addr); | 
|  |  | 
|  | bool is_valid() const { return family() != AF_UNSPEC; } | 
|  |  | 
|  | sa_family_t family() const { return v4_.sin_family; } | 
|  |  | 
|  | bool is_v4() const { return family() == AF_INET; } | 
|  |  | 
|  | bool is_v6() const { return family() == AF_INET6; } | 
|  |  | 
|  | IpAddress address() const { return is_v4() ? IpAddress(v4_.sin_addr) : IpAddress(v6_.sin6_addr); } | 
|  |  | 
|  | IpPort port() const { return IpPort::From_in_port_t(v4_.sin_port); } | 
|  |  | 
|  | uint32_t scope_id() const { return as_sockaddr_in6().sin6_scope_id; } | 
|  |  | 
|  | const sockaddr_in& as_sockaddr_in() const { | 
|  | FX_DCHECK(is_v4()); | 
|  | return v4_; | 
|  | } | 
|  |  | 
|  | const sockaddr_in6& as_sockaddr_in6() const { | 
|  | FX_DCHECK(is_v6()); | 
|  | return v6_; | 
|  | } | 
|  |  | 
|  | const sockaddr* as_sockaddr() const { return reinterpret_cast<const sockaddr*>(&v4_); } | 
|  |  | 
|  | socklen_t socklen() const { return is_v4() ? sizeof(v4_) : sizeof(v6_); } | 
|  |  | 
|  | std::string ToString() const; | 
|  |  | 
|  | explicit operator bool() const { return is_valid(); } | 
|  |  | 
|  | bool operator==(const SocketAddress& other) const { | 
|  | return is_v4() == other.is_v4() && | 
|  | std::memcmp(as_sockaddr(), other.as_sockaddr(), socklen()) == 0; | 
|  | } | 
|  |  | 
|  | bool operator!=(const SocketAddress& other) const { return !(*this == other); } | 
|  |  | 
|  | private: | 
|  | void Build(const IpAddress& address, IpPort port, uint32_t scope_id); | 
|  |  | 
|  | union { | 
|  | sockaddr_in v4_; | 
|  | sockaddr_in6 v6_; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | std::ostream& operator<<(std::ostream& os, const SocketAddress& value); | 
|  |  | 
|  | }  // namespace inet | 
|  |  | 
|  | template <> | 
|  | struct std::hash<inet::SocketAddress> { | 
|  | std::size_t operator()(const inet::SocketAddress& address) const noexcept { | 
|  | return std::hash<inet::IpAddress>{}(address.address()) ^ | 
|  | (std::hash<uint16_t>{}(address.port().as_uint16_t()) << 1); | 
|  | } | 
|  | }; | 
|  |  | 
|  | #endif  // SRC_LIB_INET_SOCKET_ADDRESS_H_ |