websocket_adapter.h 4.9 KB

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