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.
5 #ifndef EXTENSIONS_BROWSER_API_CAST_CHANNEL_CAST_SOCKET_H_
6 #define EXTENSIONS_BROWSER_API_CAST_CHANNEL_CAST_SOCKET_H_
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 "net/base/completion_callback.h"
21 #include "net/base/io_buffer.h"
22 #include "net/base/ip_endpoint.h"
23 #include "net/base/net_log.h"
28 class SSLClientSocket;
30 class TCPClientSocket;
31 class TransportSecurityState;
34 namespace extensions {
36 namespace cast_channel {
42 // This class implements a channel between Chrome and a Cast device using a TCP
43 // socket with SSL. The channel may authenticate that the receiver is a genuine
44 // Cast device. All CastSocket objects must be used only on the IO thread.
46 // NOTE: Not called "CastChannel" to reduce confusion with the generated API
48 class CastSocket : public ApiResource {
50 // Object to be informed of incoming messages and errors. The CastSocket that
51 // owns the delegate must not be deleted by it, only by the ApiResourceManager
52 // or in the callback to Close().
55 // An error occurred on the channel. |last_errors| contains the last errors
56 // logged for the channel from the implementation.
57 virtual void OnError(const CastSocket* socket,
58 ChannelError error_state,
59 const LastErrors& last_errors) = 0;
60 // A message was received on the channel.
61 virtual void OnMessage(const CastSocket* socket,
62 const MessageInfo& message) = 0;
65 virtual ~Delegate() {}
68 // Creates a new CastSocket that connects to |ip_endpoint| with
69 // |channel_auth|. |owner_extension_id| is the id of the extension that opened
70 // the socket. |channel_auth| must not be CHANNEL_AUTH_NONE.
71 CastSocket(const std::string& owner_extension_id,
72 const net::IPEndPoint& ip_endpoint,
73 ChannelAuthType channel_auth,
74 CastSocket::Delegate* delegate,
76 const base::TimeDelta& connect_timeout,
77 const scoped_refptr<Logger>& logger);
79 // Ensures that the socket is closed.
80 virtual ~CastSocket();
82 // The IP endpoint for the destination of the channel.
83 const net::IPEndPoint& ip_endpoint() const { return ip_endpoint_; }
85 // The authentication level requested for the channel.
86 ChannelAuthType channel_auth() const { return channel_auth_; }
88 // Returns a cast:// or casts:// URL for the channel endpoint.
89 // For backwards compatibility.
90 std::string CastUrl() const;
92 // Channel id for the ApiResourceManager.
93 int id() const { return channel_id_; }
95 // Sets the channel id.
96 void set_id(int channel_id) { channel_id_ = channel_id; }
98 // Returns the state of the channel. Virtual for testing.
99 virtual ReadyState ready_state() const;
101 // Returns the last error that occurred on this channel, or
102 // CHANNEL_ERROR_NONE if no error has occurred. Virtual for testing.
103 virtual ChannelError error_state() const;
105 // Connects the channel to the peer. If successful, the channel will be in
106 // READY_STATE_OPEN. DO NOT delete the CastSocket object in |callback|.
107 // Instead use Close().
108 virtual void Connect(const net::CompletionCallback& callback);
110 // Sends a message over a connected channel. The channel must be in
113 // Note that if an error occurs the following happens:
114 // 1. Completion callbacks for all pending writes are invoked with error.
115 // 2. Delegate::OnError is called once.
116 // 3. CastSocket is closed.
118 // DO NOT delete the CastSocket object in |callback|. Instead use Close().
119 virtual void SendMessage(const MessageInfo& message,
120 const net::CompletionCallback& callback);
122 // Closes the channel if not already closed. On completion, the channel will
123 // be in READY_STATE_CLOSED.
125 // It is fine to delete the CastSocket object in |callback|.
126 virtual void Close(const net::CompletionCallback& callback);
128 // Internal connection states.
129 enum ConnectionState {
131 CONN_STATE_TCP_CONNECT,
132 CONN_STATE_TCP_CONNECT_COMPLETE,
133 CONN_STATE_SSL_CONNECT,
134 CONN_STATE_SSL_CONNECT_COMPLETE,
135 CONN_STATE_AUTH_CHALLENGE_SEND,
136 CONN_STATE_AUTH_CHALLENGE_SEND_COMPLETE,
137 CONN_STATE_AUTH_CHALLENGE_REPLY_COMPLETE,
140 // Internal write states.
144 WRITE_STATE_WRITE_COMPLETE,
145 WRITE_STATE_DO_CALLBACK,
149 // Internal read states.
153 READ_STATE_READ_COMPLETE,
154 READ_STATE_DO_CALLBACK,
159 // Message header struct. If fields are added, be sure to update
160 // header_size(). Protected to allow use of *_size() methods in unit tests.
161 struct MessageHeader {
163 // Sets the message size.
164 void SetMessageSize(size_t message_size);
165 // Prepends this header to |str|.
166 void PrependToString(std::string* str);
167 // Reads |header| from the beginning of |buffer|.
168 static void ReadFromIOBuffer(net::GrowableIOBuffer* buffer,
169 MessageHeader* header);
170 // Size (in bytes) of the message header.
171 static uint32 header_size() { return sizeof(uint32); }
173 // Maximum size (in bytes) of a message payload on the wire (does not
175 static uint32 max_message_size() { return 65536; }
177 std::string ToString();
178 // The size of the following protocol message in bytes, in host byte order.
183 friend class ApiResourceManager<CastSocket>;
184 friend class CastSocketTest;
185 friend class TestCastSocket;
187 static const char* service_name() { return "CastSocketManager"; }
189 // Creates an instance of TCPClientSocket.
190 virtual scoped_ptr<net::TCPClientSocket> CreateTcpSocket();
191 // Creates an instance of SSLClientSocket with the given underlying |socket|.
192 virtual scoped_ptr<net::SSLClientSocket> CreateSslSocket(
193 scoped_ptr<net::StreamSocket> socket);
194 // Extracts peer certificate from SSLClientSocket instance when the socket
195 // is in cert error state.
196 // Returns whether certificate is successfully extracted.
197 virtual bool ExtractPeerCert(std::string* cert);
198 // Verifies whether the challenge reply received from the peer is valid:
199 // 1. Signature in the reply is valid.
200 // 2. Certificate is rooted to a trusted CA.
201 virtual bool VerifyChallengeReply();
203 // Invoked by a cancelable closure when connection setup time
204 // exceeds the interval specified at |connect_timeout|.
205 void OnConnectTimeout();
207 /////////////////////////////////////////////////////////////////////////////
208 // Following methods work together to implement the following flow:
209 // 1. Create a new TCP socket and connect to it
210 // 2. Create a new SSL socket and try connecting to it
211 // 3. If connection fails due to invalid cert authority, then extract the
212 // peer certificate from the error.
213 // 4. Whitelist the peer certificate and try #1 and #2 again.
214 // 5. If SSL socket is connected successfully, and if protocol is casts://
215 // then issue an auth challenge request.
216 // 6. Validate the auth challenge response.
218 // Main method that performs connection state transitions.
219 void DoConnectLoop(int result);
220 // Each of the below Do* method is executed in the corresponding
221 // connection state. For example when connection state is TCP_CONNECT
222 // DoTcpConnect is called, and so on.
224 int DoTcpConnectComplete(int result);
226 int DoSslConnectComplete(int result);
227 int DoAuthChallengeSend();
228 int DoAuthChallengeSendComplete(int result);
229 void DoAuthChallengeSendWriteComplete(int result);
230 int DoAuthChallengeReplyComplete(int result);
231 /////////////////////////////////////////////////////////////////////////////
233 /////////////////////////////////////////////////////////////////////////////
234 // Following methods work together to implement write flow.
236 // Main method that performs write flow state transitions.
237 void DoWriteLoop(int result);
238 // Each of the below Do* method is executed in the corresponding
239 // write state. For example when write state is WRITE_STATE_WRITE_COMPLETE
240 // DowriteComplete is called, and so on.
242 int DoWriteComplete(int result);
243 int DoWriteCallback();
244 int DoWriteError(int result);
245 /////////////////////////////////////////////////////////////////////////////
247 /////////////////////////////////////////////////////////////////////////////
248 // Following methods work together to implement read flow.
250 // Main method that performs write flow state transitions.
251 void DoReadLoop(int result);
252 // Each of the below Do* method is executed in the corresponding
253 // write state. For example when write state is READ_STATE_READ_COMPLETE
254 // DoReadComplete is called, and so on.
256 int DoReadComplete(int result);
257 int DoReadCallback();
258 int DoReadError(int result);
259 /////////////////////////////////////////////////////////////////////////////
261 // Runs the external connection callback and resets it.
262 void DoConnectCallback(int result);
263 // Adds |message| to the write queue and starts the write loop if needed.
264 void SendCastMessageInternal(const CastMessage& message,
265 const net::CompletionCallback& callback);
266 void PostTaskToStartConnectLoop(int result);
267 void PostTaskToStartReadLoop();
268 void StartReadLoop();
269 // Parses the contents of header_read_buffer_ and sets current_message_size_
270 // to the size of the body of the message.
271 bool ProcessHeader();
272 // Parses the contents of body_read_buffer_ and sets current_message_ to
273 // the message received.
275 // Closes socket, signaling the delegate that |error| has occurred.
276 void CloseWithError();
277 // Frees resources and cancels pending callbacks. |ready_state_| will be set
278 // READY_STATE_CLOSED on completion. A no-op if |ready_state_| is already
279 // READY_STATE_CLOSED.
280 void CloseInternal();
281 // Runs pending callbacks that are passed into us to notify API clients that
282 // pending operations will fail because the socket has been closed.
283 void RunPendingCallbacksOnClose();
284 // Serializes the content of message_proto (with a header) to |message_data|.
285 static bool Serialize(const CastMessage& message_proto,
286 std::string* message_data);
288 virtual bool CalledOnValidThread() const;
290 virtual base::Timer* GetTimer();
292 void SetConnectState(ConnectionState connect_state);
293 void SetReadyState(ReadyState ready_state);
294 void SetErrorState(ChannelError error_state);
295 void SetReadState(ReadState read_state);
296 void SetWriteState(WriteState write_state);
298 base::ThreadChecker thread_checker_;
300 // The id of the channel.
303 // The IP endpoint that the the channel is connected to.
304 net::IPEndPoint ip_endpoint_;
305 // Receiver authentication requested for the channel.
306 ChannelAuthType channel_auth_;
307 // Delegate to inform of incoming messages and errors.
310 // IOBuffer for reading the message header.
311 scoped_refptr<net::GrowableIOBuffer> header_read_buffer_;
312 // IOBuffer for reading the message body.
313 scoped_refptr<net::GrowableIOBuffer> body_read_buffer_;
314 // IOBuffer to currently read into.
315 scoped_refptr<net::GrowableIOBuffer> current_read_buffer_;
316 // The number of bytes in the current message body.
317 uint32 current_message_size_;
318 // Last message received on the socket.
319 scoped_ptr<CastMessage> current_message_;
321 // The NetLog for this service.
322 net::NetLog* net_log_;
323 // The NetLog source for this service.
324 net::NetLog::Source net_log_source_;
326 // Logger used to track multiple CastSockets. Does NOT own this object.
327 scoped_refptr<Logger> logger_;
329 // CertVerifier is owned by us but should be deleted AFTER SSLClientSocket
330 // since in some cases the destructor of SSLClientSocket may call a method
331 // to cancel a cert verification request.
332 scoped_ptr<net::CertVerifier> cert_verifier_;
333 scoped_ptr<net::TransportSecurityState> transport_security_state_;
335 // Owned ptr to the underlying TCP socket.
336 scoped_ptr<net::TCPClientSocket> tcp_socket_;
337 // Owned ptr to the underlying SSL socket.
338 scoped_ptr<net::SSLClientSocket> socket_;
339 // Certificate of the peer. This field may be empty if the peer
340 // certificate is not yet fetched.
341 std::string peer_cert_;
342 // Reply received from the receiver to a challenge request.
343 scoped_ptr<CastMessage> challenge_reply_;
345 // Callback invoked when the socket is connected or fails to connect.
346 net::CompletionCallback connect_callback_;
348 // Callback invoked by |connect_timeout_timer_| to cancel the connection.
349 base::CancelableClosure connect_timeout_callback_;
350 // Duration to wait before timing out.
351 base::TimeDelta connect_timeout_;
352 // Timer invoked when the connection has timed out.
353 scoped_ptr<base::Timer> connect_timeout_timer_;
354 // Set when a timeout is triggered and the connection process has
358 // Connection flow state machine state.
359 ConnectionState connect_state_;
360 // Write flow state machine state.
361 WriteState write_state_;
362 // Read flow state machine state.
363 ReadState read_state_;
364 // The last error encountered by the channel.
365 ChannelError error_state_;
366 // The current status of the channel.
367 ReadyState ready_state_;
369 // Task invoked to (re)start the connect loop. Canceled on entry to the
371 base::CancelableClosure connect_loop_callback_;
372 // Task invoked to send the auth challenge. Canceled when the auth challenge
374 base::CancelableClosure send_auth_challenge_callback_;
375 // Callback invoked to (re)start the read loop. Canceled on entry to the read
377 base::CancelableClosure read_loop_callback_;
379 // Holds a message to be written to the socket. |callback| is invoked when the
380 // message is fully written or an error occurrs.
381 struct WriteRequest {
382 explicit WriteRequest(const net::CompletionCallback& callback);
384 // Sets the content of the request by serializing |message| into |io_buffer|
385 // and prepending the header. Must only be called once.
386 bool SetContent(const CastMessage& message_proto);
388 net::CompletionCallback callback;
389 std::string message_namespace;
390 scoped_refptr<net::DrainableIOBuffer> io_buffer;
392 // Queue of pending writes. The message at the front of the queue is the one
394 std::queue<WriteRequest> write_queue_;
396 FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestFullSecureConnectionFlowAsync);
397 FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestRead);
398 FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestReadHeaderParseError);
399 FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestReadMany);
400 FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestWriteErrorLargeMessage);
401 DISALLOW_COPY_AND_ASSIGN(CastSocket);
404 } // namespace cast_channel
405 } // namespace core_api
406 } // namespace extensions
408 #endif // EXTENSIONS_BROWSER_API_CAST_CHANNEL_CAST_SOCKET_H_