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
26namespace net {
27class AddressList;
28class CertVerifier;
29class SSLClientSocket;
30class StreamSocket;
31class TCPClientSocket;
32class TransportSecurityState;
33}
34
35namespace extensions {
36namespace core_api {
37namespace cast_channel {
38
39class CastMessage;
40class Logger;
41struct LastErrors;
42class 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.
51class 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