| // Copyright 2022 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 LIB_ZXIO_SOCKET_ADDRESS_H_ |
| #define LIB_ZXIO_SOCKET_ADDRESS_H_ |
| |
| #include <fidl/fuchsia.net/cpp/wire.h> |
| #include <fidl/fuchsia.posix.socket.packet/cpp/wire.h> |
| #include <lib/fidl/cpp/wire/object_view.h> |
| #include <netinet/in.h> |
| #include <sys/socket.h> |
| #include <zircon/types.h> |
| |
| #include <functional> |
| #include <optional> |
| #include <type_traits> |
| #include <variant> |
| |
| #include <netpacket/packet.h> |
| |
| // A helper structure to keep a socket address and the variants allocations on the stack. |
| class SocketAddress { |
| public: |
| static std::optional<SocketAddress> FromFidl(const fuchsia_net::wire::SocketAddress& from_addr); |
| |
| zx_status_t LoadSockAddr(const struct sockaddr* addr, size_t addr_len); |
| |
| bool operator==(const SocketAddress& o) const; |
| bool operator!=(const SocketAddress& o) const; |
| |
| size_t hash() const; |
| |
| // Helpers from the reference documentation for std::visit<>, to allow |
| // visit-by-overload of the std::variant<> below: |
| template <class... Ts> |
| struct overloaded : Ts... { |
| using Ts::operator()...; |
| }; |
| |
| // explicit deduction guide (not needed as of C++20) |
| template <class... Ts> |
| overloaded(Ts...) -> overloaded<Ts...>; |
| |
| template <typename F> |
| std::invoke_result_t<F, fuchsia_net::wire::SocketAddress> WithFIDL(F fn) { |
| return fn([this]() -> fuchsia_net::wire::SocketAddress { |
| if (storage_.has_value()) { |
| return std::visit( |
| overloaded{ |
| [](fuchsia_net::wire::Ipv4SocketAddress& ipv4) { |
| return fuchsia_net::wire::SocketAddress::WithIpv4( |
| fidl::ObjectView<fuchsia_net::wire::Ipv4SocketAddress>::FromExternal(&ipv4)); |
| }, |
| [](fuchsia_net::wire::Ipv6SocketAddress& ipv6) { |
| return fuchsia_net::wire::SocketAddress::WithIpv6( |
| fidl::ObjectView<fuchsia_net::wire::Ipv6SocketAddress>::FromExternal(&ipv6)); |
| }, |
| }, |
| storage_.value()); |
| } |
| return {}; |
| }()); |
| } |
| |
| private: |
| std::optional< |
| std::variant<fuchsia_net::wire::Ipv4SocketAddress, fuchsia_net::wire::Ipv6SocketAddress>> |
| storage_; |
| }; |
| |
| #endif // LIB_ZXIO_SOCKET_ADDRESS_H_ |