Home | History | Annotate | Download | only in cast_channel
      1 // Copyright 2014 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 
      5 #ifndef EXTENSIONS_BROWSER_API_CAST_CHANNEL_CAST_SOCKET_H_
      6 #define EXTENSIONS_BROWSER_API_CAST_CHANNEL_CAST_SOCKET_H_
      7 
      8 #include <queue>
      9 #include <string>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/cancelable_callback.h"
     13 #include "base/gtest_prod_util.h"
     14 #include "base/memory/ref_counted.h"
     15 #include "base/threading/thread_checker.h"
     16 #include "base/timer/timer.h"
     17 #include "extensions/browser/api/api_resource.h"
     18 #include "extensions/browser/api/api_resource_manager.h"
     19 #include "extensions/common/api/cast_channel.h"
     20 #include "extensions/common/api/cast_channel/logging.pb.h"
     21 #include "net/base/completion_callback.h"
     22 #include "net/base/io_buffer.h"
     23 #include "net/base/ip_endpoint.h"
     24 #include "net/base/net_log.h"
     25 
     26 namespace net {
     27 class AddressList;
     28 class CertVerifier;
     29 class SSLClientSocket;
     30 class StreamSocket;
     31 class TCPClientSocket;
     32 class TransportSecurityState;
     33 }
     34 
     35 namespace extensions {
     36 namespace core_api {
     37 namespace cast_channel {
     38 
     39 class CastMessage;
     40 class Logger;
     41 struct LastErrors;
     42 class MessageFramer;
     43 
     44 // This class implements a channel between Chrome and a Cast device using a TCP
     45 // socket with SSL.  The channel may authenticate that the receiver is a genuine
     46 // Cast device.  All CastSocket objects must be used only on the IO thread.
     47 //
     48 // NOTE: Not called "CastChannel" to reduce confusion with the generated API
     49 // code.
     50 // TODO(kmarshall): Inherit from CastSocket and rename to CastSocketImpl.
     51 class CastSocket : public ApiResource {
     52  public:
     53   // Object to be informed of incoming messages and errors.  The CastSocket
     54   // that owns the delegate must not be deleted by it, only by the
     55   // ApiResourceManager or in the callback to Close().
     56   class Delegate {
     57    public:
     58     // An error occurred on the channel. |last_errors| contains the last errors
     59     // logged for the channel from the implementation.
     60     virtual void OnError(const CastSocket* socket,
     61                          ChannelError error_state,
     62                          const LastErrors& last_errors) = 0;
     63     // A message was received on the channel.
     64     virtual void OnMessage(const CastSocket* socket,
     65                            const MessageInfo& message) = 0;
     66 
     67    protected:
     68     virtual ~Delegate() {}
     69   };
     70 
     71   // Creates a new CastSocket that connects to |ip_endpoint| with
     72   // |channel_auth|. |owner_extension_id| is the id of the extension that opened
     73   // the socket.  |channel_auth| must not be CHANNEL_AUTH_NONE.
     74   CastSocket(const std::string& owner_extension_id,
     75              const net::IPEndPoint& ip_endpoint,
     76              ChannelAuthType channel_auth,
     77              CastSocket::Delegate* delegate,
     78              net::NetLog* net_log,
     79              const base::TimeDelta& connect_timeout,
     80              const scoped_refptr<Logger>& logger);
     81 
     82   // Ensures that the socket is closed.
     83   virtual ~CastSocket();
     84 
     85   // The IP endpoint for the destination of the channel.
     86   const net::IPEndPoint& ip_endpoint() const { return ip_endpoint_; }
     87 
     88   // The authentication level requested for the channel.
     89   ChannelAuthType channel_auth() const { return channel_auth_; }
     90 
     91   // Returns a cast:// or casts:// URL for the channel endpoint.
     92   // For backwards compatibility.
     93   std::string CastUrl() const;
     94 
     95   // Channel id for the ApiResourceManager.
     96   int id() const { return channel_id_; }
     97 
     98   // Sets the channel id.
     99   void set_id(int channel_id) { channel_id_ = channel_id; }
    100 
    101   // Returns the state of the channel.  Virtual for testing.
    102   virtual ReadyState ready_state() const;
    103 
    104   // Returns the last error that occurred on this channel, or
    105   // CHANNEL_ERROR_NONE if no error has occurred.  Virtual for testing.
    106   virtual ChannelError error_state() const;
    107 
    108   // Connects the channel to the peer. If successful, the channel will be in
    109   // READY_STATE_OPEN.  DO NOT delete the CastSocket object in |callback|.
    110   // Instead use Close().
    111   virtual void Connect(const net::CompletionCallback& callback);
    112 
    113   // Sends a message over a connected channel. The channel must be in
    114   // READY_STATE_OPEN.
    115   //
    116   // Note that if an error occurs the following happens:
    117   // 1. Completion callbacks for all pending writes are invoked with error.
    118   // 2. Delegate::OnError is called once.
    119   // 3. CastSocket is closed.
    120   //
    121   // DO NOT delete the CastSocket object in |callback|. Instead use Close().
    122   virtual void SendMessage(const MessageInfo& message,
    123                            const net::CompletionCallback& callback);
    124 
    125   // Closes the channel if not already closed. On completion, the channel will
    126   // be in READY_STATE_CLOSED.
    127   //
    128   // It is fine to delete the CastSocket object in |callback|.
    129   virtual void Close(const net::CompletionCallback& callback);
    130 
    131  private:
    132   friend class ApiResourceManager<CastSocket>;
    133   friend class CastSocketTest;
    134   friend class TestCastSocket;
    135 
    136   static const char* service_name() { return "CastSocketManager"; }
    137 
    138   // Creates an instance of TCPClientSocket.
    139   virtual scoped_ptr<net::TCPClientSocket> CreateTcpSocket();
    140   // Creates an instance of SSLClientSocket with the given underlying |socket|.
    141   virtual scoped_ptr<net::SSLClientSocket> CreateSslSocket(
    142       scoped_ptr<net::StreamSocket> socket);
    143   // Extracts peer certificate from SSLClientSocket instance when the socket
    144   // is in cert error state.
    145   // Returns whether certificate is successfully extracted.
    146   virtual bool ExtractPeerCert(std::string* cert);
    147   // Verifies whether the challenge reply received from the peer is valid:
    148   // 1. Signature in the reply is valid.
    149   // 2. Certificate is rooted to a trusted CA.
    150   virtual bool VerifyChallengeReply();
    151 
    152   // Invoked by a cancelable closure when connection setup time
    153   // exceeds the interval specified at |connect_timeout|.
    154   void OnConnectTimeout();
    155 
    156   /////////////////////////////////////////////////////////////////////////////
    157   // Following methods work together to implement the following flow:
    158   // 1. Create a new TCP socket and connect to it
    159   // 2. Create a new SSL socket and try connecting to it
    160   // 3. If connection fails due to invalid cert authority, then extract the
    161   //    peer certificate from the error.
    162   // 4. Whitelist the peer certificate and try #1 and #2 again.
    163   // 5. If SSL socket is connected successfully, and if protocol is casts://
    164   //    then issue an auth challenge request.
    165   // 6. Validate the auth challenge response.
    166   //
    167   // Main method that performs connection state transitions.
    168   void DoConnectLoop(int result);
    169   // Each of the below Do* method is executed in the corresponding
    170   // connection state. For example when connection state is TCP_CONNECT
    171   // DoTcpConnect is called, and so on.
    172   int DoTcpConnect();
    173   int DoTcpConnectComplete(int result);
    174   int DoSslConnect();
    175   int DoSslConnectComplete(int result);
    176   int DoAuthChallengeSend();
    177   int DoAuthChallengeSendComplete(int result);
    178   void DoAuthChallengeSendWriteComplete(int result);
    179   int DoAuthChallengeReplyComplete(int result);
    180   /////////////////////////////////////////////////////////////////////////////
    181 
    182   /////////////////////////////////////////////////////////////////////////////
    183   // Following methods work together to implement write flow.
    184   //
    185   // Main method that performs write flow state transitions.
    186   void DoWriteLoop(int result);
    187   // Each of the below Do* method is executed in the corresponding
    188   // write state. For example when write state is WRITE_STATE_WRITE_COMPLETE
    189   // DowriteComplete is called, and so on.
    190   int DoWrite();
    191   int DoWriteComplete(int result);
    192   int DoWriteCallback();
    193   int DoWriteError(int result);
    194   /////////////////////////////////////////////////////////////////////////////
    195 
    196   /////////////////////////////////////////////////////////////////////////////
    197   // Following methods work together to implement read flow.
    198   //
    199   // Main method that performs write flow state transitions.
    200   void DoReadLoop(int result);
    201   // Each of the below Do* method is executed in the corresponding
    202   // write state. For example when write state is READ_STATE_READ_COMPLETE
    203   // DoReadComplete is called, and so on.
    204   int DoRead();
    205   int DoReadComplete(int result);
    206   int DoReadCallback();
    207   int DoReadError(int result);
    208   /////////////////////////////////////////////////////////////////////////////
    209 
    210   // Runs the external connection callback and resets it.
    211   void DoConnectCallback(int result);
    212   // Adds |message| to the write queue and starts the write loop if needed.
    213   void SendCastMessageInternal(const CastMessage& message,
    214                                const net::CompletionCallback& callback);
    215   void PostTaskToStartConnectLoop(int result);
    216   void PostTaskToStartReadLoop();
    217   void StartReadLoop();
    218   // Closes socket, signaling the delegate that |error| has occurred.
    219   void CloseWithError();
    220   // Frees resources and cancels pending callbacks.  |ready_state_| will be set
    221   // READY_STATE_CLOSED on completion.  A no-op if |ready_state_| is already
    222   // READY_STATE_CLOSED.
    223   void CloseInternal();
    224   // Runs pending callbacks that are passed into us to notify API clients that
    225   // pending operations will fail because the socket has been closed.
    226   void RunPendingCallbacksOnClose();
    227   // Serializes the content of message_proto (with a header) to |message_data|.
    228   static bool Serialize(const CastMessage& message_proto,
    229                         std::string* message_data);
    230 
    231   virtual bool CalledOnValidThread() const;
    232 
    233   virtual base::Timer* GetTimer();
    234 
    235   void SetConnectState(proto::ConnectionState connect_state);
    236   void SetReadyState(ReadyState ready_state);
    237   void SetErrorState(ChannelError error_state);
    238   void SetReadState(proto::ReadState read_state);
    239   void SetWriteState(proto::WriteState write_state);
    240 
    241   base::ThreadChecker thread_checker_;
    242 
    243   // The id of the channel.
    244   int channel_id_;
    245 
    246   // The IP endpoint that the the channel is connected to.
    247   net::IPEndPoint ip_endpoint_;
    248   // Receiver authentication requested for the channel.
    249   ChannelAuthType channel_auth_;
    250   // Delegate to inform of incoming messages and errors.
    251   Delegate* delegate_;
    252 
    253   // IOBuffer for reading the message header.
    254   scoped_refptr<net::GrowableIOBuffer> read_buffer_;
    255   scoped_ptr<MessageFramer> framer_;
    256 
    257   // The NetLog for this service.
    258   net::NetLog* net_log_;
    259   // The NetLog source for this service.
    260   net::NetLog::Source net_log_source_;
    261 
    262   // Logger used to track multiple CastSockets. Does NOT own this object.
    263   scoped_refptr<Logger> logger_;
    264 
    265   // CertVerifier is owned by us but should be deleted AFTER SSLClientSocket
    266   // since in some cases the destructor of SSLClientSocket may call a method
    267   // to cancel a cert verification request.
    268   scoped_ptr<net::CertVerifier> cert_verifier_;
    269   scoped_ptr<net::TransportSecurityState> transport_security_state_;
    270 
    271   // Owned ptr to the underlying TCP socket.
    272   scoped_ptr<net::TCPClientSocket> tcp_socket_;
    273   // Owned ptr to the underlying SSL socket.
    274   scoped_ptr<net::SSLClientSocket> socket_;
    275   // Certificate of the peer. This field may be empty if the peer
    276   // certificate is not yet fetched.
    277   std::string peer_cert_;
    278   // Reply received from the receiver to a challenge request.
    279   scoped_ptr<CastMessage> challenge_reply_;
    280 
    281   // Callback invoked when the socket is connected or fails to connect.
    282   net::CompletionCallback connect_callback_;
    283 
    284   // Callback invoked by |connect_timeout_timer_| to cancel the connection.
    285   base::CancelableClosure connect_timeout_callback_;
    286   // Duration to wait before timing out.
    287   base::TimeDelta connect_timeout_;
    288   // Timer invoked when the connection has timed out.
    289   scoped_ptr<base::Timer> connect_timeout_timer_;
    290   // Set when a timeout is triggered and the connection process has
    291   // canceled.
    292   bool is_canceled_;
    293 
    294   scoped_ptr<CastMessage> current_message_;
    295 
    296   // Connection flow state machine state.
    297   proto::ConnectionState connect_state_;
    298   // Write flow state machine state.
    299   proto::WriteState write_state_;
    300   // Read flow state machine state.
    301   proto::ReadState read_state_;
    302   // The last error encountered by the channel.
    303   ChannelError error_state_;
    304   // The current status of the channel.
    305   ReadyState ready_state_;
    306 
    307   // Task invoked to (re)start the connect loop.  Canceled on entry to the
    308   // connect loop.
    309   base::CancelableClosure connect_loop_callback_;
    310   // Task invoked to send the auth challenge.  Canceled when the auth challenge
    311   // has been sent.
    312   base::CancelableClosure send_auth_challenge_callback_;
    313   // Callback invoked to (re)start the read loop.  Canceled on entry to the read
    314   // loop.
    315   base::CancelableClosure read_loop_callback_;
    316 
    317   // Holds a message to be written to the socket. |callback| is invoked when the
    318   // message is fully written or an error occurrs.
    319   struct WriteRequest {
    320     explicit WriteRequest(const net::CompletionCallback& callback);
    321     ~WriteRequest();
    322     // Sets the content of the request by serializing |message| into |io_buffer|
    323     // and prepending the header.  Must only be called once.
    324     bool SetContent(const CastMessage& message_proto);
    325 
    326     net::CompletionCallback callback;
    327     std::string message_namespace;
    328     scoped_refptr<net::DrainableIOBuffer> io_buffer;
    329   };
    330   // Queue of pending writes. The message at the front of the queue is the one
    331   // being written.
    332   std::queue<WriteRequest> write_queue_;
    333 
    334   FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestFullSecureConnectionFlowAsync);
    335   FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestRead);
    336   FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestReadHeaderParseError);
    337   FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestReadMany);
    338   FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestWriteErrorLargeMessage);
    339   DISALLOW_COPY_AND_ASSIGN(CastSocket);
    340 };
    341 }  // namespace cast_channel
    342 }  // namespace core_api
    343 }  // namespace extensions
    344 
    345 #endif  // EXTENSIONS_BROWSER_API_CAST_CHANNEL_CAST_SOCKET_H_
    346