1 // Copyright 2013 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 CHROME_BROWSER_EXTENSIONS_API_CAST_CHANNEL_CAST_SOCKET_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_CAST_CHANNEL_CAST_SOCKET_H_
11 #include "base/basictypes.h"
12 #include "base/callback.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/threading/thread_checker.h"
17 #include "chrome/browser/extensions/api/api_resource.h"
18 #include "chrome/browser/extensions/api/api_resource_manager.h"
19 #include "chrome/common/extensions/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"
29 class SSLClientSocket;
30 class TCPClientSocket;
31 class TransportSecurityState;
34 namespace extensions {
36 namespace cast_channel {
40 // Size, in bytes, of the largest allowed message payload on the wire (without
42 extern const uint32 kMaxMessageSize;
44 // This class implements a channel between Chrome and a Cast device using a TCP
45 // socket. The channel may be unauthenticated (cast://) or authenticated
46 // (casts://). All CastSocket objects must be used only on the IO thread.
48 // NOTE: Not called "CastChannel" to reduce confusion with the generated API
50 class CastSocket : public ApiResource,
51 public base::SupportsWeakPtr<CastSocket> {
53 // Object to be informed of incoming messages and errors.
56 // An error occurred on the channel.
57 virtual void OnError(const CastSocket* socket,
58 ChannelError error) = 0;
59 // A string message was received on the channel.
60 virtual void OnMessage(const CastSocket* socket,
61 const MessageInfo& message) = 0;
63 virtual ~Delegate() {}
66 // Creates a new CastSocket to |url|. |owner_extension_id| is the id of the
67 // extension that opened the socket.
68 CastSocket(const std::string& owner_extension_id,
70 CastSocket::Delegate* delegate,
71 net::NetLog* net_log);
72 virtual ~CastSocket();
74 // The URL for the channel.
75 const GURL& url() const;
77 // Whether to perform receiver authentication.
78 bool auth_required() const { return auth_required_; }
80 // Channel id for the ApiResourceManager.
81 int id() const { return channel_id_; }
83 // Sets the channel id.
84 void set_id(int channel_id) { channel_id_ = channel_id; }
86 // Returns the state of the channel.
87 ReadyState ready_state() const { return ready_state_; }
89 // Returns the last error that occurred on this channel, or CHANNEL_ERROR_NONE
90 // if no error has occurred.
91 ChannelError error_state() const { return error_state_; }
93 // Connects the channel to the peer. If successful, the channel will be in
95 virtual void Connect(const net::CompletionCallback& callback);
97 // Sends a message over a connected channel. The channel must be in
99 virtual void SendMessage(const MessageInfo& message,
100 const net::CompletionCallback& callback);
102 // Closes the channel. On completion, the channel will be in
103 // READY_STATE_CLOSED.
104 virtual void Close(const net::CompletionCallback& callback);
106 // Fills |channel_info| with the status of this channel.
107 virtual void FillChannelInfo(ChannelInfo* channel_info) const;
110 // Creates an instance of TCPClientSocket.
111 virtual scoped_ptr<net::TCPClientSocket> CreateTcpSocket();
112 // Creates an instance of SSLClientSocket.
113 virtual scoped_ptr<net::SSLClientSocket> CreateSslSocket();
114 // Extracts peer certificate from SSLClientSocket instance when the socket
115 // is in cert error state.
116 // Returns whether certificate is successfully extracted.
117 virtual bool ExtractPeerCert(std::string* cert);
118 // Sends a challenge request to the receiver.
119 virtual int SendAuthChallenge();
120 // Reads auth challenge reply from the receiver.
121 virtual int ReadAuthChallengeReply();
122 // Verifies whether the challenge reply received from the peer is valid:
123 // 1. Signature in the reply is valid.
124 // 2. Certificate is rooted to a trusted CA.
125 virtual bool VerifyChallengeReply();
127 // Returns whether we are executing in a valid thread.
128 virtual bool CalledOnValidThread() const;
131 friend class ApiResourceManager<CastSocket>;
132 friend class CastSocketTest;
134 static const char* service_name() {
135 return "CastSocketManager";
138 // Internal connection states.
139 enum ConnectionState {
141 CONN_STATE_TCP_CONNECT,
142 CONN_STATE_TCP_CONNECT_COMPLETE,
143 CONN_STATE_SSL_CONNECT,
144 CONN_STATE_SSL_CONNECT_COMPLETE,
145 CONN_STATE_AUTH_CHALLENGE_SEND,
146 CONN_STATE_AUTH_CHALLENGE_SEND_COMPLETE,
147 CONN_STATE_AUTH_CHALLENGE_REPLY_COMPLETE,
150 /////////////////////////////////////////////////////////////////////////////
151 // Following methods work together to implement the following flow:
152 // 1. Create a new TCP socket and connect to it
153 // 2. Create a new SSL socket and try connecting to it
154 // 3. If connection fails due to invalid cert authority, then extract the
155 // peer certificate from the error.
156 // 4. Whitelist the peer certificate and try #1 and #2 again.
157 // 5. If SSL socket is connected successfully, and if protocol is casts://
158 // then issue an auth challenge request.
159 // 6. Validate the auth challenge response.
161 // Main method that performs connection state transitions.
162 int DoConnectLoop(int result);
163 // Each of the below Do* method is executed in the corresponding
164 // connection state. For e.g. when connection state is TCP_CONNECT
165 // DoTcpConnect is called, and so on.
167 int DoTcpConnectComplete(int result);
169 int DoSslConnectComplete(int result);
170 int DoAuthChallengeSend();
171 int DoAuthChallengeSendComplete(int result);
172 int DoAuthChallengeReplyComplete(int result);
173 /////////////////////////////////////////////////////////////////////////////
175 // Callback method for callbacks from underlying sockets.
176 void OnConnectComplete(int result);
178 // Callback method when a challenge request is sent or a reply is received.
179 void OnChallengeEvent(int result);
181 // Runs the external connection callback and resets it.
182 void DoConnectCallback(int result);
184 // Verifies that the URL is a valid cast:// or casts:// URL and sets url_ to
186 bool ParseChannelUrl(const GURL& url);
188 // Sends the given |message| and invokes the given callback when done.
189 int SendMessageInternal(const CastMessage& message,
190 const net::CompletionCallback& callback);
192 // Writes data to the socket from the WriteRequest at the head of the queue.
193 // Calls OnWriteData() on completion.
195 void OnWriteData(int result);
197 // Reads data from the socket into one of the read buffers. Calls
198 // OnReadData() on completion.
200 void OnReadData(int result);
202 // Processes the contents of header_read_buffer_ and returns true on success.
203 bool ProcessHeader();
204 // Processes the contents of body_read_buffer_ and returns true on success.
206 // Parses the message held in body_read_buffer_ and notifies |delegate_| if a
207 // message was extracted from the buffer. Returns true on success.
208 bool ParseMessageFromBody();
210 // Serializes the content of message_proto (with a header) to |message_data|.
211 static bool Serialize(const CastMessage& message_proto,
212 std::string* message_data);
214 // Closes the socket and sets |error_state_|. Also signals |error| via
216 void CloseWithError(ChannelError error);
218 base::ThreadChecker thread_checker_;
220 // The id of the channel.
223 // The URL of the peer (cast:// or casts://).
225 // Delegate to inform of incoming messages and errors.
227 // True if we should perform receiver authentication.
229 // The IP endpoint of the peer.
230 net::IPEndPoint ip_endpoint_;
231 // The last error encountered by the channel.
232 ChannelError error_state_;
233 // The current status of the channel.
234 ReadyState ready_state_;
236 // True when there is a write callback pending.
237 bool write_callback_pending_;
238 // True when there is a read callback pending.
239 bool read_callback_pending_;
241 // IOBuffer for reading the message header.
242 scoped_refptr<net::GrowableIOBuffer> header_read_buffer_;
243 // IOBuffer for reading the message body.
244 scoped_refptr<net::GrowableIOBuffer> body_read_buffer_;
245 // IOBuffer we are currently reading into.
246 scoped_refptr<net::GrowableIOBuffer> current_read_buffer_;
247 // The number of bytes in the current message body.
248 uint32 current_message_size_;
250 // The NetLog for this service.
251 net::NetLog* net_log_;
252 // The NetLog source for this service.
253 net::NetLog::Source net_log_source_;
255 // Next connection state to transition to.
256 ConnectionState next_state_;
257 // Owned ptr to the underlying TCP socket.
258 scoped_ptr<net::TCPClientSocket> tcp_socket_;
259 // Owned ptr to the underlying SSL socket.
260 scoped_ptr<net::SSLClientSocket> socket_;
261 // Certificate of the peer. This field may be empty if the peer
262 // certificate is not yet fetched.
263 std::string peer_cert_;
264 scoped_ptr<net::CertVerifier> cert_verifier_;
265 scoped_ptr<net::TransportSecurityState> transport_security_state_;
266 // Reply received from the receiver to a challenge request.
267 scoped_ptr<CastMessage> challenge_reply_;
269 // Callback invoked when the socket is connected.
270 net::CompletionCallback connect_callback_;
272 // Message header struct. If fields are added, be sure to update
273 // kMessageHeaderSize in the .cc.
274 struct MessageHeader {
276 // Sets the message size.
277 void SetMessageSize(size_t message_size);
278 // Prepends this header to |str|.
279 void PrependToString(std::string* str);
280 // Reads |header| from the beginning of |buffer|.
281 static void ReadFromIOBuffer(net::GrowableIOBuffer* buffer,
282 MessageHeader* header);
283 std::string ToString();
284 // The size of the following protocol message in bytes, in host byte order.
288 // Holds a message to be written to the socket. |callback| is invoked when the
289 // message is fully written or an error occurrs.
290 struct WriteRequest {
291 explicit WriteRequest(const net::CompletionCallback& callback);
293 // Sets the content of the request by serializing |message| into |io_buffer|
294 // and prepending the header. Must only be called once.
295 bool SetContent(const CastMessage& message_proto);
297 net::CompletionCallback callback;
298 scoped_refptr<net::DrainableIOBuffer> io_buffer;
300 // Queue of pending writes. The message at the front of the queue is the one
302 std::queue<WriteRequest> write_queue_;
304 FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestCastURLs);
305 FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestRead);
306 FRIEND_TEST_ALL_PREFIXES(CastSocketTest, TestReadMany);
307 DISALLOW_COPY_AND_ASSIGN(CastSocket);
310 } // namespace cast_channel
312 } // namespace extensions
314 #endif // CHROME_BROWSER_EXTENSIONS_API_CAST_CHANNEL_CAST_SOCKET_H_