blob: 63653acf774f2cf589d549c605f1da78bc4fe72b [file] [log] [blame]
// 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 <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.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_