blob: 2de569b3d2e71d33d3d3e0fe26dcf919a900e224 [file] [log] [blame]
// Copyright 2018 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_LEDGER_BIN_P2P_PROVIDER_IMPL_P2P_PROVIDER_IMPL_H_
#define SRC_LEDGER_BIN_P2P_PROVIDER_IMPL_P2P_PROVIDER_IMPL_H_
#include <fuchsia/overnet/cpp/fidl.h>
#include <memory>
#include <set>
#include <string>
#include "lib/fidl/cpp/binding.h"
#include "peridot/lib/rng/random.h"
#include "src/ledger/bin/environment/environment.h"
#include "src/ledger/bin/p2p_provider/impl/make_client_id.h"
#include "src/ledger/bin/p2p_provider/impl/remote_connection.h"
#include "src/ledger/bin/p2p_provider/public/p2p_provider.h"
#include "src/ledger/bin/p2p_provider/public/user_id_provider.h"
#include "src/ledger/lib/convert/convert.h"
#include "src/lib/callback/auto_cleanable.h"
namespace p2p_provider {
struct OvernetNodeIdComparator {
bool operator()(const fuchsia::overnet::protocol::NodeId& left,
const fuchsia::overnet::protocol::NodeId& right) const {
return (left.id > right.id);
}
};
// P2PProviderImpl provides the peer-to-peer communication abstraction for the
// Ledger, using Overnet.
//
// We deploy a number of strategies to provide a consistent communication layer
// using Overnet:
// - Overnet exposes services to other devices, and allows one to connect
// to other devices services. We thus expose a service whose name is
// ledger-specific, and also depends on the user id and the ledger version.
// This ensures that only compatible Ledgers of the same user communicate.
// - Overnet provides a list of peers, each with a unique overnet ID and the list
// of services they expose. A given device only initiates connections to peers
// that have the relevant service, and whose overnet ID is greater than their own.
// This ensures that there is only one communication channel between devices.
class P2PProviderImpl : public P2PProvider, public fuchsia::overnet::ServiceProvider {
public:
P2PProviderImpl(fuchsia::overnet::OvernetPtr overnet,
std::unique_ptr<p2p_provider::UserIdProvider> user_id_provider,
rng::Random* random);
P2PProviderImpl(const P2PProviderImpl&) = delete;
P2PProviderImpl& operator=(const P2PProviderImpl&) = delete;
~P2PProviderImpl() override;
// P2PProvider:
void Start(Client* client) override;
bool SendMessage(const P2PClientId& destination, convert::ExtendedStringView data) override;
// Overnet.ServiceProvider
void ConnectToService(zx::channel chan,
fuchsia::overnet::ConnectionInfo connection_info) override;
private:
// Starts the listening mDNS service.
void StartService();
// Retrieves and processes the current devices list
void ListenForNewDevices();
// Creates a RemoteConnection from |chan| and associated with |id|.
void AddConnectionFromChannel(zx::channel chan,
std::optional<fuchsia::overnet::protocol::NodeId> overnet_id);
// Dispatches an incoming message to the relevant page, or sends an error
// back.
void Dispatch(P2PClientId source, std::vector<uint8_t> data);
// Callback when we establish a new device connection, or a device breaks its
// connection.
void OnDeviceChange(P2PClientId remote_device, DeviceChangeType change_type);
// The name of the service exposed by Overnet.
std::string OvernetServiceName();
Client* client_ = nullptr;
// ID of the user, used to ensure all connected Ledgers are for the same user.
std::string user_id_;
// Holds the connections and the IDs used to identify them.
std::map<P2PClientId, RemoteConnection> connections_;
// The peers that we have initiated a connection to.
std::set<fuchsia::overnet::protocol::NodeId, OvernetNodeIdComparator> contacted_peers_;
std::optional<fuchsia::overnet::protocol::NodeId> self_client_id_;
fidl::Binding<fuchsia::overnet::ServiceProvider> service_binding_;
fuchsia::overnet::OvernetPtr const overnet_;
std::unique_ptr<p2p_provider::UserIdProvider> const user_id_provider_;
rng::Random* random_;
};
} // namespace p2p_provider
#endif // SRC_LEDGER_BIN_P2P_PROVIDER_IMPL_P2P_PROVIDER_IMPL_H_