1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
// Copyright 2020 The Chromium 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 DEVICE_FIDO_CABLE_WEBSOCKET_ADAPTER_H_
#define DEVICE_FIDO_CABLE_WEBSOCKET_ADAPTER_H_
#include <vector>
#include "base/callback_forward.h"
#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/optional.h"
#include "base/sequence_checker.h"
#include "device/fido/cable/v2_handshake.h"
#include "services/network/public/mojom/network_context.mojom.h"
namespace device {
namespace cablev2 {
// WebSocketAdapter implements several network::mojom interfaces needed to
// create a WebSocket connection and translates the Mojo interface into a
// callback-based one.
class COMPONENT_EXPORT(DEVICE_FIDO) WebSocketAdapter
: public network::mojom::WebSocketHandshakeClient,
network::mojom::WebSocketClient {
public:
using TunnelReadyCallback = base::OnceCallback<
void(bool, base::Optional<std::array<uint8_t, kRoutingIdSize>>)>;
using TunnelDataCallback =
base::RepeatingCallback<void(base::Optional<base::span<const uint8_t>>)>;
WebSocketAdapter(
// on_tunnel_ready is called once with a boolean that indicates whether
// the WebSocket successfully connected and an optional routing ID.
TunnelReadyCallback on_tunnel_ready,
// on_tunnel_ready is called repeatedly, after successful connection, with
// the contents of WebSocket messages. Framing is preserved so a single
// message written by the server will result in a single callback.
TunnelDataCallback on_tunnel_data);
~WebSocketAdapter() override;
WebSocketAdapter(const WebSocketAdapter&) = delete;
WebSocketAdapter& operator=(const WebSocketAdapter&) = delete;
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
BindNewHandshakeClientPipe();
// Write writes data to the WebSocket server. The amount of data that can be
// written at once is limited by the size of an internal Mojo buffer which
// defaults to 64KiB. Exceeding that will cause the function to return false.
bool Write(base::span<const uint8_t> data);
// WebSocketHandshakeClient:
void OnOpeningHandshakeStarted(
network::mojom::WebSocketHandshakeRequestPtr request) override;
void OnConnectionEstablished(
mojo::PendingRemote<network::mojom::WebSocket> socket,
mojo::PendingReceiver<network::mojom::WebSocketClient> client_receiver,
network::mojom::WebSocketHandshakeResponsePtr response,
mojo::ScopedDataPipeConsumerHandle readable,
mojo::ScopedDataPipeProducerHandle writable) override;
// WebSocketClient:
void OnDataFrame(bool finish,
network::mojom::WebSocketMessageType type,
uint64_t data_len) override;
void OnDropChannel(bool was_clean,
uint16_t code,
const std::string& reason) override;
void OnClosingHandshake() override;
private:
void OnMojoPipeDisconnect();
void OnDataPipeReady(MojoResult result,
const mojo::HandleSignalsState& state);
void Close();
void FlushPendingMessage();
bool closed_ = false;
// pending_message_ contains a partial message that is being reassembled.
std::vector<uint8_t> pending_message_;
// pending_message_i_ contains the number of valid bytes of
// |pending_message_|.
size_t pending_message_i_ = 0;
// pending_message_finished_ is true if |pending_message_| is the full size of
// an application frame and thus should be passed up once filled with bytes.
bool pending_message_finished_ = false;
TunnelReadyCallback on_tunnel_ready_;
const TunnelDataCallback on_tunnel_data_;
mojo::Receiver<network::mojom::WebSocketHandshakeClient> handshake_receiver_{
this};
mojo::Receiver<network::mojom::WebSocketClient> client_receiver_{this};
mojo::Remote<network::mojom::WebSocket> socket_remote_;
mojo::ScopedDataPipeConsumerHandle read_pipe_;
mojo::SimpleWatcher read_pipe_watcher_;
mojo::ScopedDataPipeProducerHandle write_pipe_;
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace cablev2
} // namespace device
#endif // DEVICE_FIDO_CABLE_WEBSOCKET_ADAPTER_H_
|