| Index: extensions/browser/api/cast_channel/cast_socket.h
|
| diff --git a/extensions/browser/api/cast_channel/cast_socket.h b/extensions/browser/api/cast_channel/cast_socket.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..242508f2ae76c8c7db56a7c869efd7c99ad9e24d
|
| --- /dev/null
|
| +++ b/extensions/browser/api/cast_channel/cast_socket.h
|
| @@ -0,0 +1,402 @@
|
| +// Copyright 2014 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 EXTENSIONS_BROWSER_API_CAST_CHANNEL_CAST_SOCKET_H_
|
| +#define EXTENSIONS_BROWSER_API_CAST_CHANNEL_CAST_SOCKET_H_
|
| +
|
| +#include <stdint.h>
|
| +
|
| +#include <queue>
|
| +#include <string>
|
| +
|
| +#include "base/cancelable_callback.h"
|
| +#include "base/gtest_prod_util.h"
|
| +#include "base/macros.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/threading/thread_checker.h"
|
| +#include "base/timer/timer.h"
|
| +#include "components/cast_channel/cast_channel_enum.h"
|
| +#include "extensions/browser/api/api_resource.h"
|
| +#include "extensions/browser/api/api_resource_manager.h"
|
| +#include "extensions/browser/api/cast_channel/cast_auth_util.h"
|
| +#include "extensions/browser/api/cast_channel/cast_socket.h"
|
| +#include "extensions/browser/api/cast_channel/cast_transport.h"
|
| +#include "extensions/common/api/cast_channel/logging.pb.h"
|
| +#include "net/base/completion_callback.h"
|
| +#include "net/base/io_buffer.h"
|
| +#include "net/base/ip_endpoint.h"
|
| +#include "net/log/net_log_source.h"
|
| +
|
| +namespace net {
|
| +class CertVerifier;
|
| +class CTPolicyEnforcer;
|
| +class CTVerifier;
|
| +class NetLog;
|
| +class SSLClientSocket;
|
| +class StreamSocket;
|
| +class TCPClientSocket;
|
| +class TransportSecurityState;
|
| +class X509Certificate;
|
| +}
|
| +
|
| +namespace extensions {
|
| +namespace api {
|
| +namespace cast_channel {
|
| +class CastMessage;
|
| +class Logger;
|
| +struct LastErrors;
|
| +
|
| +// Cast device capabilities.
|
| +enum CastDeviceCapability {
|
| + NONE = 0,
|
| + VIDEO_OUT = 1 << 0,
|
| + VIDEO_IN = 1 << 1,
|
| + AUDIO_OUT = 1 << 2,
|
| + AUDIO_IN = 1 << 3,
|
| + DEV_MODE = 1 << 4
|
| +};
|
| +
|
| +// Public interface of the CastSocket class.
|
| +class CastSocket {
|
| + public:
|
| + using ChannelError = ::cast_channel::ChannelError;
|
| + using ChannelAuthType = ::cast_channel::ChannelAuthType;
|
| + using ReadyState = ::cast_channel::ReadyState;
|
| +
|
| + virtual ~CastSocket() {}
|
| +
|
| + // Used by BrowserContextKeyedAPIFactory.
|
| + static const char* service_name() { return "CastSocketImplManager"; }
|
| +
|
| + // Connects the channel to the peer. If successful, the channel will be in
|
| + // READY_STATE_OPEN. DO NOT delete the CastSocket object in |callback|.
|
| + // Instead use Close().
|
| + // |callback| will be invoked with any ChannelError that occurred, or
|
| + // CHANNEL_ERROR_NONE if successful.
|
| + // If the CastSocket is destroyed while the connection is pending, |callback|
|
| + // will be invoked with CHANNEL_ERROR_UNKNOWN. In this case, invoking
|
| + // |callback| must not result in any re-entrancy behavior.
|
| + // |delegate| receives message receipt and error events.
|
| + // Ownership of |delegate| is transferred to this CastSocket.
|
| + virtual void Connect(std::unique_ptr<CastTransport::Delegate> delegate,
|
| + base::Callback<void(ChannelError)> callback) = 0;
|
| +
|
| + // Closes the channel if not already closed. On completion, the channel will
|
| + // be in READY_STATE_CLOSED.
|
| + //
|
| + // It is fine to delete this object in |callback|.
|
| + virtual void Close(const net::CompletionCallback& callback) = 0;
|
| +
|
| + // The IP endpoint for the destination of the channel.
|
| + virtual const net::IPEndPoint& ip_endpoint() const = 0;
|
| +
|
| + // Channel id generated by the CastChannelService.
|
| + virtual int id() const = 0;
|
| +
|
| + // Sets the channel id generated by CastChannelService.
|
| + virtual void set_id(int id) = 0;
|
| +
|
| + // The authentication level requested for the channel.
|
| + virtual ChannelAuthType channel_auth() const = 0;
|
| +
|
| + // The ready state of the channel.
|
| + virtual ReadyState ready_state() const = 0;
|
| +
|
| + // Returns the last error that occurred on this channel, or
|
| + // CHANNEL_ERROR_NONE if no error has occurred.
|
| + virtual ChannelError error_state() const = 0;
|
| +
|
| + // True when keep-alive signaling is handled for this socket.
|
| + virtual bool keep_alive() const = 0;
|
| +
|
| + // Whether the channel is audio only as identified by the device
|
| + // certificate during channel authentication.
|
| + virtual bool audio_only() const = 0;
|
| +
|
| + // Marks a socket as invalid due to an error, and sends an OnError
|
| + // event to |delegate_|.
|
| + // The OnError event receipient is responsible for closing the socket in the
|
| + // event of an error.
|
| + // Setting the error state does not close the socket if it is open.
|
| + virtual void SetErrorState(ChannelError error_state) = 0;
|
| +
|
| + // Returns a pointer to the socket's message transport layer. Can be used to
|
| + // send and receive CastMessages over the socket.
|
| + virtual CastTransport* transport() const = 0;
|
| +};
|
| +
|
| +// This class implements a channel between Chrome and a Cast device using a TCP
|
| +// socket with SSL. The channel may authenticate that the receiver is a genuine
|
| +// Cast device. All CastSocketImpl objects must be used only on the IO thread.
|
| +//
|
| +// NOTE: Not called "CastChannel" to reduce confusion with the generated API
|
| +// code.
|
| +class CastSocketImpl : public CastSocket {
|
| + public:
|
| + // Creates a new CastSocket that connects to |ip_endpoint| with
|
| + // |channel_auth|. |owner_extension_id| is the id of the extension that opened
|
| + // the socket. |channel_auth| must not be CHANNEL_AUTH_NONE.
|
| + // Parameters:
|
| + // |owner_extension_id|: ID of the extension calling the API.
|
| + // |ip_endpoint|: IP address of the remote host.
|
| + // |channel_auth|: Authentication method used for connecting to a Cast
|
| + // receiver.
|
| + // |net_log|: Log of socket events.
|
| + // |connect_timeout|: Connection timeout interval.
|
| + // |logger|: Log of cast channel events.
|
| + CastSocketImpl(const std::string& owner_extension_id,
|
| + const net::IPEndPoint& ip_endpoint,
|
| + ChannelAuthType channel_auth,
|
| + net::NetLog* net_log,
|
| + const base::TimeDelta& connect_timeout,
|
| + bool keep_alive,
|
| + const scoped_refptr<Logger>& logger,
|
| + uint64_t device_capabilities);
|
| +
|
| + // For test-only.
|
| + // This constructor allows for setting a custom AuthContext.
|
| + CastSocketImpl(const std::string& owner_extension_id,
|
| + const net::IPEndPoint& ip_endpoint,
|
| + ChannelAuthType channel_auth,
|
| + net::NetLog* net_log,
|
| + const base::TimeDelta& connect_timeout,
|
| + bool keep_alive,
|
| + const scoped_refptr<Logger>& logger,
|
| + uint64_t device_capabilities,
|
| + const AuthContext& auth_context);
|
| +
|
| + // Ensures that the socket is closed.
|
| + ~CastSocketImpl() override;
|
| +
|
| + // CastSocket interface.
|
| + void Connect(std::unique_ptr<CastTransport::Delegate> delegate,
|
| + base::Callback<void(ChannelError)> callback) override;
|
| + CastTransport* transport() const override;
|
| + void Close(const net::CompletionCallback& callback) override;
|
| + const net::IPEndPoint& ip_endpoint() const override;
|
| + int id() const override;
|
| + void set_id(int channel_id) override;
|
| + ChannelAuthType channel_auth() const override;
|
| + ReadyState ready_state() const override;
|
| + ChannelError error_state() const override;
|
| + bool keep_alive() const override;
|
| + bool audio_only() const override;
|
| +
|
| + protected:
|
| + // CastTransport::Delegate methods for receiving handshake messages.
|
| + class AuthTransportDelegate : public CastTransport::Delegate {
|
| + public:
|
| + explicit AuthTransportDelegate(CastSocketImpl* socket);
|
| +
|
| + // Gets the error state of the channel.
|
| + // Returns CHANNEL_ERROR_NONE if no errors are present.
|
| + ChannelError error_state() const;
|
| +
|
| + // Gets recorded error details.
|
| + LastErrors last_errors() const;
|
| +
|
| + // CastTransport::Delegate interface.
|
| + void OnError(ChannelError error_state) override;
|
| + void OnMessage(const CastMessage& message) override;
|
| + void Start() override;
|
| +
|
| + private:
|
| + CastSocketImpl* socket_;
|
| + ChannelError error_state_;
|
| + LastErrors last_errors_;
|
| + };
|
| +
|
| + // Replaces the internally-constructed transport object with one provided
|
| + // by the caller (e.g. a mock).
|
| + void SetTransportForTesting(std::unique_ptr<CastTransport> transport);
|
| +
|
| + // Verifies whether the socket complies with cast channel policy.
|
| + // Audio only channel policy mandates that a device declaring a video out
|
| + // capability must not have a certificate with audio only policy.
|
| + bool VerifyChannelPolicy(const AuthResult& result);
|
| +
|
| + private:
|
| + FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestConnectAuthMessageCorrupted);
|
| + FRIEND_TEST_ALL_PREFIXES(CastSocketTest,
|
| + TestConnectChallengeReplyReceiveError);
|
| + FRIEND_TEST_ALL_PREFIXES(CastSocketTest,
|
| + TestConnectChallengeVerificationFails);
|
| + friend class AuthTransportDelegate;
|
| + friend class CastSocketTest;
|
| + friend class TestCastSocket;
|
| +
|
| + void SetErrorState(ChannelError error_state) override;
|
| +
|
| + // Frees resources and cancels pending callbacks. |ready_state_| will be set
|
| + // READY_STATE_CLOSED on completion. A no-op if |ready_state_| is already
|
| + // READY_STATE_CLOSED.
|
| + void CloseInternal();
|
| +
|
| + // Creates an instance of TCPClientSocket.
|
| + virtual std::unique_ptr<net::TCPClientSocket> CreateTcpSocket();
|
| + // Creates an instance of SSLClientSocket with the given underlying |socket|.
|
| + virtual std::unique_ptr<net::SSLClientSocket> CreateSslSocket(
|
| + std::unique_ptr<net::StreamSocket> socket);
|
| + // Extracts peer certificate from SSLClientSocket instance when the socket
|
| + // is in cert error state.
|
| + // Returns null if the certificate could not be extracted.
|
| + // TODO(kmarshall): Use MockSSLClientSocket for tests instead of overriding
|
| + // this function.
|
| + virtual scoped_refptr<net::X509Certificate> ExtractPeerCert();
|
| + // Verifies whether the challenge reply received from the peer is valid:
|
| + // 1. Signature in the reply is valid.
|
| + // 2. Certificate is rooted to a trusted CA.
|
| + virtual bool VerifyChallengeReply();
|
| +
|
| + // Invoked by a cancelable closure when connection setup time
|
| + // exceeds the interval specified at |connect_timeout|.
|
| + void OnConnectTimeout();
|
| +
|
| + /////////////////////////////////////////////////////////////////////////////
|
| + // Following methods work together to implement the following flow:
|
| + // 1. Create a new TCP socket and connect to it
|
| + // 2. Create a new SSL socket and try connecting to it
|
| + // 3. If connection fails due to invalid cert authority, then extract the
|
| + // peer certificate from the error.
|
| + // 4. Whitelist the peer certificate and try #1 and #2 again.
|
| + // 5. If SSL socket is connected successfully, and if protocol is casts://
|
| + // then issue an auth challenge request.
|
| + // 6. Validate the auth challenge response.
|
| + //
|
| + // Main method that performs connection state transitions.
|
| + void DoConnectLoop(int result);
|
| + // Each of the below Do* method is executed in the corresponding
|
| + // connection state. For example when connection state is TCP_CONNECT
|
| + // DoTcpConnect is called, and so on.
|
| + int DoTcpConnect();
|
| + int DoTcpConnectComplete(int result);
|
| + int DoSslConnect();
|
| + int DoSslConnectComplete(int result);
|
| + int DoAuthChallengeSend();
|
| + int DoAuthChallengeSendComplete(int result);
|
| + int DoAuthChallengeReplyComplete(int result);
|
| + /////////////////////////////////////////////////////////////////////////////
|
| +
|
| + // Resets the cancellable callback used for async invocations of
|
| + // DoConnectLoop.
|
| + void ResetConnectLoopCallback();
|
| +
|
| + // Posts a task to invoke |connect_loop_callback_| with |result| on the
|
| + // current message loop.
|
| + void PostTaskToStartConnectLoop(int result);
|
| +
|
| + // Runs the external connection callback and resets it.
|
| + void DoConnectCallback();
|
| +
|
| + virtual bool CalledOnValidThread() const;
|
| +
|
| + virtual base::Timer* GetTimer();
|
| +
|
| + void SetConnectState(proto::ConnectionState connect_state);
|
| + void SetReadyState(ReadyState ready_state);
|
| +
|
| + base::ThreadChecker thread_checker_;
|
| +
|
| + // The id of the channel.
|
| + int channel_id_;
|
| + // The IP endpoint that the the channel is connected to.
|
| + net::IPEndPoint ip_endpoint_;
|
| + // Receiver authentication requested for the channel.
|
| + ChannelAuthType channel_auth_;
|
| + // The NetLog for this service.
|
| + net::NetLog* net_log_;
|
| + // The NetLog source for this service.
|
| + net::NetLogSource net_log_source_;
|
| + // True when keep-alive signaling should be handled for this socket.
|
| + bool keep_alive_;
|
| +
|
| + // Shared logging object, used to log CastSocket events for diagnostics.
|
| + scoped_refptr<Logger> logger_;
|
| +
|
| + // CertVerifier is owned by us but should be deleted AFTER SSLClientSocket
|
| + // since in some cases the destructor of SSLClientSocket may call a method
|
| + // to cancel a cert verification request.
|
| + std::unique_ptr<net::CertVerifier> cert_verifier_;
|
| + std::unique_ptr<net::TransportSecurityState> transport_security_state_;
|
| + std::unique_ptr<net::CTVerifier> cert_transparency_verifier_;
|
| + std::unique_ptr<net::CTPolicyEnforcer> ct_policy_enforcer_;
|
| +
|
| + // Owned ptr to the underlying TCP socket.
|
| + std::unique_ptr<net::TCPClientSocket> tcp_socket_;
|
| +
|
| + // Owned ptr to the underlying SSL socket.
|
| + std::unique_ptr<net::SSLClientSocket> socket_;
|
| +
|
| + // Certificate of the peer. This field may be empty if the peer
|
| + // certificate is not yet fetched.
|
| + scoped_refptr<net::X509Certificate> peer_cert_;
|
| +
|
| + // The challenge context for the current connection.
|
| + const AuthContext auth_context_;
|
| +
|
| + // Reply received from the receiver to a challenge request.
|
| + std::unique_ptr<CastMessage> challenge_reply_;
|
| +
|
| + // Callback invoked when the socket is connected or fails to connect.
|
| + base::Callback<void(ChannelError)> connect_callback_;
|
| +
|
| + // Callback invoked by |connect_timeout_timer_| to cancel the connection.
|
| + base::CancelableClosure connect_timeout_callback_;
|
| +
|
| + // Duration to wait before timing out.
|
| + base::TimeDelta connect_timeout_;
|
| +
|
| + // Timer invoked when the connection has timed out.
|
| + std::unique_ptr<base::Timer> connect_timeout_timer_;
|
| +
|
| + // Set when a timeout is triggered and the connection process has
|
| + // canceled.
|
| + bool is_canceled_;
|
| +
|
| + // Capabilities declared by the cast device.
|
| + uint64_t device_capabilities_;
|
| +
|
| + // Whether the channel is audio only as identified by the device
|
| + // certificate during channel authentication.
|
| + bool audio_only_;
|
| +
|
| + // Connection flow state machine state.
|
| + proto::ConnectionState connect_state_;
|
| +
|
| + // Write flow state machine state.
|
| + proto::WriteState write_state_;
|
| +
|
| + // Read flow state machine state.
|
| + proto::ReadState read_state_;
|
| +
|
| + // The last error encountered by the channel.
|
| + ChannelError error_state_;
|
| +
|
| + // The current status of the channel.
|
| + ReadyState ready_state_;
|
| +
|
| + // Callback which, when invoked, will re-enter the connection state machine.
|
| + // Oustanding callbacks will be cancelled when |this| is destroyed.
|
| + // The callback signature is based on net::CompletionCallback, which passes
|
| + // operation result codes as byte counts in the success case, or as
|
| + // net::Error enum values for error cases.
|
| + base::CancelableCallback<void(int)> connect_loop_callback_;
|
| +
|
| + // Cast message formatting and parsing layer.
|
| + std::unique_ptr<CastTransport> transport_;
|
| +
|
| + // Caller's message read and error handling delegate.
|
| + std::unique_ptr<CastTransport::Delegate> delegate_;
|
| +
|
| + // Raw pointer to the auth handshake delegate. Used to get detailed error
|
| + // information.
|
| + AuthTransportDelegate* auth_delegate_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(CastSocketImpl);
|
| +};
|
| +} // namespace cast_channel
|
| +} // namespace api
|
| +} // namespace extensions
|
| +
|
| +#endif // EXTENSIONS_BROWSER_API_CAST_CHANNEL_CAST_SOCKET_H_
|
|
|