blob: 5eb00f9e6cd28294a891ef0286fd5290dca55e17 [file] [log] [blame]
// 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_DGRAM_CACHE_H_
#define LIB_ZXIO_DGRAM_CACHE_H_
#include <fidl/fuchsia.posix.socket/cpp/wire.h>
#include <lib/fit/result.h>
#include <lib/zx/eventpair.h>
#include <zircon/types.h>
#include <list>
#include <mutex>
#include <optional>
#include <unordered_map>
#include "socket_address.h"
using ErrOrOutCode = zx::result<int16_t>;
namespace std {
template <>
struct hash<SocketAddress> {
size_t operator()(const SocketAddress& k) const { return k.hash(); }
};
} // namespace std
class RequestedCmsgSet {
public:
explicit RequestedCmsgSet(
const fuchsia_posix_socket::wire::DatagramSocketRecvMsgPostflightResponse& response);
constexpr static RequestedCmsgSet AllRequestedCmsgSet() {
RequestedCmsgSet cmsg_set;
cmsg_set.requests_ |= fuchsia_posix_socket::wire::CmsgRequests::kMask;
return cmsg_set;
}
std::optional<fuchsia_posix_socket::wire::TimestampOption> so_timestamp() const;
bool ip_tos() const;
bool ip_ttl() const;
bool ip_recvorigdstaddr() const;
bool ipv6_tclass() const;
bool ipv6_hoplimit() const;
bool ipv6_pktinfo() const;
private:
RequestedCmsgSet() = default;
fuchsia_posix_socket::wire::CmsgRequests requests_;
std::optional<fuchsia_posix_socket::wire::TimestampOption> so_timestamp_filter_;
};
class RequestedCmsgCache {
public:
using Result = fit::result<ErrOrOutCode, std::optional<RequestedCmsgSet>>;
Result Get(zx_wait_item_t err_wait_item, bool get_requested_cmsg_set,
fidl::WireSyncClient<fuchsia_posix_socket::DatagramSocket>& client);
private:
struct Value {
zx::eventpair validity;
RequestedCmsgSet requested_cmsg_set;
};
std::optional<Value> cache_ __TA_GUARDED(lock_);
std::mutex lock_;
};
class RouteCache {
public:
using Result = fit::result<ErrOrOutCode, uint32_t>;
Result Get(std::optional<SocketAddress>& remote_addr,
const std::optional<std::pair<uint64_t, fuchsia_net::wire::Ipv6Address>>&
local_iface_and_addr,
const zx_wait_item_t& err_wait_item,
fidl::WireSyncClient<fuchsia_posix_socket::DatagramSocket>& client);
// Chosen to be arbitrarily large enough for the cache to be useful for most
// clients, while preventing unbounded memory growth.
static constexpr size_t kMaxEntries = 512;
private:
struct Key {
SocketAddress remote_addr;
std::optional<std::pair<uint64_t, fuchsia_net::wire::Ipv6Address>> local_iface_and_addr;
bool operator==(const Key& o) const;
};
struct KeyHasher {
size_t operator()(const Key& k) const;
};
struct Value {
std::vector<zx::eventpair> eventpairs;
uint32_t maximum_size;
std::list<Key>::iterator lru;
};
void LruAddToFront(const Key& k, std::list<Key>::iterator& lru) __TA_REQUIRES(lock_);
void LruMoveToFront(const Key& k, std::list<Key>::iterator& lru) __TA_REQUIRES(lock_);
std::unordered_map<Key, Value, KeyHasher> cache_ __TA_GUARDED(lock_);
std::list<Key> lru_ __TA_GUARDED(lock_);
std::optional<SocketAddress> connected_ __TA_GUARDED(lock_);
std::mutex lock_;
};
std::optional<ErrOrOutCode> GetErrorWithClient(
fidl::WireSyncClient<fuchsia_posix_socket::DatagramSocket>& client);
#endif // LIB_ZXIO_DGRAM_CACHE_H_