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_SOCKET_TCP_SOCKET_H_
6 #define EXTENSIONS_BROWSER_API_SOCKET_TCP_SOCKET_H_
7 
8 #include <stdint.h>
9 
10 #include <memory>
11 #include <string>
12 
13 #include "base/memory/weak_ptr.h"
14 #include "base/sequenced_task_runner.h"
15 #include "extensions/browser/api/socket/socket.h"
16 #include "extensions/browser/api/socket/tcp_socket.h"
17 #include "extensions/common/api/socket.h"
18 #include "mojo/public/cpp/bindings/pending_receiver.h"
19 #include "mojo/public/cpp/bindings/pending_remote.h"
20 #include "mojo/public/cpp/bindings/remote.h"
21 #include "net/base/completion_once_callback.h"
22 #include "services/network/public/mojom/network_service.mojom.h"
23 #include "services/network/public/mojom/tcp_socket.mojom.h"
24 #include "services/network/public/mojom/tls_socket.mojom.h"
25 
26 namespace content {
27 class BrowserContext;
28 class StoragePartition;
29 }
30 
31 namespace extensions {
32 
33 class MojoDataPump;
34 
35 class TCPSocket : public Socket {
36  public:
37   using UpgradeToTLSCallback = base::OnceCallback<void(
38       int,
39       mojo::PendingRemote<network::mojom::TLSClientSocket>,
40       const net::IPEndPoint&,
41       const net::IPEndPoint&,
42       mojo::ScopedDataPipeConsumerHandle,
43       mojo::ScopedDataPipeProducerHandle)>;
44 
45   // Constuctor for when |socket_mode_| is unknown. The |socket_mode_| will be
46   // filled in when the consumer calls Listen/Connect.
47   TCPSocket(content::BrowserContext* browser_context,
48             const std::string& owner_extension_id);
49 
50   // Created using TCPServerSocket::Accept().
51   TCPSocket(mojo::PendingRemote<network::mojom::TCPConnectedSocket> socket,
52             mojo::ScopedDataPipeConsumerHandle receive_stream,
53             mojo::ScopedDataPipeProducerHandle send_stream,
54             const base::Optional<net::IPEndPoint>& remote_addr,
55             const std::string& owner_extension_id);
56 
57   ~TCPSocket() override;
58 
59   void Connect(const net::AddressList& address,
60                net::CompletionOnceCallback callback) override;
61   void Disconnect(bool socket_destroying) override;
62   void Bind(const std::string& address,
63             uint16_t port,
64             net::CompletionOnceCallback callback) override;
65   void Read(int count, ReadCompletionCallback callback) override;
66   void RecvFrom(int count, RecvFromCompletionCallback callback) override;
67   void SendTo(scoped_refptr<net::IOBuffer> io_buffer,
68               int byte_count,
69               const net::IPEndPoint& address,
70               net::CompletionOnceCallback callback) override;
71   void SetKeepAlive(bool enable,
72                     int delay,
73                     SetKeepAliveCallback callback) override;
74   void SetNoDelay(bool no_delay, SetNoDelayCallback callback) override;
75   void Listen(const std::string& address,
76               uint16_t port,
77               int backlog,
78               ListenCallback callback) override;
79   void Accept(AcceptCompletionCallback callback) override;
80 
81   bool IsConnected() override;
82 
83   bool GetPeerAddress(net::IPEndPoint* address) override;
84   bool GetLocalAddress(net::IPEndPoint* address) override;
85 
86   Socket::SocketType GetSocketType() const override;
87 
88   void UpgradeToTLS(api::socket::SecureOptions* options,
89                     UpgradeToTLSCallback callback);
90 
SetStoragePartitionForTest(content::StoragePartition * storage_partition)91   void SetStoragePartitionForTest(
92       content::StoragePartition* storage_partition) {
93     storage_partition_ = storage_partition;
94   }
95 
96  protected:
97   int WriteImpl(net::IOBuffer* io_buffer,
98                 int io_buffer_size,
99                 net::CompletionOnceCallback callback) override;
100 
101  private:
102   // Connects a client TCP socket. This is done on the UI thread because
103   // StoragePartition::GetNetworkContext() needs to happen on the UI thread.
104   // The completion callback is posted back to the thread on which |this| lives.
105   static void ConnectOnUIThread(
106       content::StoragePartition* storage_partition,
107       content::BrowserContext* browser_context,
108       const net::AddressList& remote_address_list,
109       mojo::PendingReceiver<network::mojom::TCPConnectedSocket> receiver,
110       network::mojom::NetworkContext::CreateTCPConnectedSocketCallback
111           callback);
112   static void OnConnectCompleteOnUIThread(
113       scoped_refptr<base::SequencedTaskRunner> original_task_runner,
114       network::mojom::NetworkContext::CreateTCPConnectedSocketCallback callback,
115       int result,
116       const base::Optional<net::IPEndPoint>& local_addr,
117       const base::Optional<net::IPEndPoint>& peer_addr,
118       mojo::ScopedDataPipeConsumerHandle receive_stream,
119       mojo::ScopedDataPipeProducerHandle send_stream);
120   void OnConnectComplete(int result,
121                          const base::Optional<net::IPEndPoint>& local_addr,
122                          const base::Optional<net::IPEndPoint>& peer_addr,
123                          mojo::ScopedDataPipeConsumerHandle receive_stream,
124                          mojo::ScopedDataPipeProducerHandle send_stream);
125 
126   // Connects a server TCP socket. This is done on the UI thread because
127   // StoragePartition::GetNetworkContext() needs to happen on the UI thread.
128   // The completion callback is posted back to the thread on which |this| lives.
129   static void ListenOnUIThread(
130       content::StoragePartition* storage_partition,
131       content::BrowserContext* browser_context,
132       const net::IPEndPoint& local_addr,
133       int backlog,
134       mojo::PendingReceiver<network::mojom::TCPServerSocket> receiver,
135       network::mojom::NetworkContext::CreateTCPServerSocketCallback callback);
136   static void OnListenCompleteOnUIThread(
137       const scoped_refptr<base::SequencedTaskRunner>& original_task_runner,
138       network::mojom::NetworkContext::CreateTCPServerSocketCallback callback,
139       int result,
140       const base::Optional<net::IPEndPoint>& local_addr);
141   void OnListenComplete(int result,
142                         const base::Optional<net::IPEndPoint>& local_addr);
143   void OnAccept(
144       int result,
145       const base::Optional<net::IPEndPoint>& remote_addr,
146       mojo::PendingRemote<network::mojom::TCPConnectedSocket> connected_socket,
147       mojo::ScopedDataPipeConsumerHandle receive_stream,
148       mojo::ScopedDataPipeProducerHandle send_stream);
149   void OnWriteComplete(net::CompletionOnceCallback callback, int result);
150   void OnReadComplete(int result, scoped_refptr<net::IOBuffer> io_buffer);
151   void OnUpgradeToTLSComplete(
152       UpgradeToTLSCallback callback,
153       mojo::PendingRemote<network::mojom::TLSClientSocket> tls_socket,
154       const net::IPEndPoint& local_addr,
155       const net::IPEndPoint& peer_addr,
156       int result,
157       mojo::ScopedDataPipeConsumerHandle receive_stream,
158       mojo::ScopedDataPipeProducerHandle send_stream,
159       const base::Optional<net::SSLInfo>& ssl_info);
160 
161   content::StoragePartition* GetStoragePartitionHelper();
162 
163   enum SocketMode {
164     UNKNOWN = 0,
165     CLIENT,
166     SERVER,
167   };
168 
169   // |this| doesn't outlive |browser_context_| because |this| is owned by
170   // ApiResourceManager which is a BrowserContextKeyedAPI.
171   content::BrowserContext* browser_context_;
172 
173   SocketMode socket_mode_;
174 
175   // CLIENT mode.
176   mojo::Remote<network::mojom::TCPConnectedSocket> client_socket_;
177   // SERVER mode.
178   mojo::Remote<network::mojom::TCPServerSocket> server_socket_;
179 
180   net::CompletionOnceCallback connect_callback_;
181   ListenCallback listen_callback_;
182   AcceptCompletionCallback accept_callback_;
183   ReadCompletionCallback read_callback_;
184 
185   std::unique_ptr<MojoDataPump> mojo_data_pump_;
186 
187   scoped_refptr<base::SequencedTaskRunner> task_runner_;
188 
189   base::Optional<net::IPEndPoint> local_addr_;
190   base::Optional<net::IPEndPoint> peer_addr_;
191 
192   // Only used in tests.
193   content::StoragePartition* storage_partition_ = nullptr;
194 
195   // WeakPtr is used when posting tasks to |task_runner_| which might outlive
196   // |this|.
197   base::WeakPtrFactory<TCPSocket> weak_factory_{this};
198 
199   DISALLOW_COPY_AND_ASSIGN(TCPSocket);
200 };
201 
202 // TCP Socket instances from the "sockets.tcp" namespace. These are regular
203 // socket objects with additional properties related to the behavior defined in
204 // the "sockets.tcp" namespace.
205 class ResumableTCPSocket : public TCPSocket {
206  public:
207   ResumableTCPSocket(content::BrowserContext* browser_context,
208                      const std::string& owner_extension_id);
209   // Created using TCPServerSocket::Accept().
210   ResumableTCPSocket(
211       mojo::PendingRemote<network::mojom::TCPConnectedSocket> socket,
212       mojo::ScopedDataPipeConsumerHandle receive_stream,
213       mojo::ScopedDataPipeProducerHandle send_stream,
214       const base::Optional<net::IPEndPoint>& remote_addr,
215       const std::string& owner_extension_id);
216 
217   ~ResumableTCPSocket() override;
218 
219   // Overriden from ApiResource
220   bool IsPersistent() const override;
221 
name()222   const std::string& name() const { return name_; }
set_name(const std::string & name)223   void set_name(const std::string& name) { name_ = name; }
224 
persistent()225   bool persistent() const { return persistent_; }
set_persistent(bool persistent)226   void set_persistent(bool persistent) { persistent_ = persistent; }
227 
buffer_size()228   int buffer_size() const { return buffer_size_; }
set_buffer_size(int buffer_size)229   void set_buffer_size(int buffer_size) { buffer_size_ = buffer_size; }
230 
paused()231   bool paused() const { return paused_; }
set_paused(bool paused)232   void set_paused(bool paused) { paused_ = paused; }
233 
234  private:
235   friend class ApiResourceManager<ResumableTCPSocket>;
service_name()236   static const char* service_name() { return "ResumableTCPSocketManager"; }
237 
238   // Application-defined string - see sockets_tcp.idl.
239   std::string name_;
240   // Flag indicating whether the socket is left open when the application is
241   // suspended - see sockets_tcp.idl.
242   bool persistent_;
243   // The size of the buffer used to receive data - see sockets_tcp.idl.
244   int buffer_size_;
245   // Flag indicating whether a connected socket blocks its peer from sending
246   // more data - see sockets_tcp.idl.
247   bool paused_;
248 };
249 
250 // TCP Socket instances from the "sockets.tcpServer" namespace. These are
251 // regular socket objects with additional properties related to the behavior
252 // defined in the "sockets.tcpServer" namespace.
253 class ResumableTCPServerSocket : public TCPSocket {
254  public:
255   ResumableTCPServerSocket(content::BrowserContext* browser_context,
256                            const std::string& owner_extension_id);
257 
258   // Overriden from ApiResource
259   bool IsPersistent() const override;
260 
name()261   const std::string& name() const { return name_; }
set_name(const std::string & name)262   void set_name(const std::string& name) { name_ = name; }
263 
persistent()264   bool persistent() const { return persistent_; }
set_persistent(bool persistent)265   void set_persistent(bool persistent) { persistent_ = persistent; }
266 
paused()267   bool paused() const { return paused_; }
set_paused(bool paused)268   void set_paused(bool paused) { paused_ = paused; }
269 
270  private:
271   friend class ApiResourceManager<ResumableTCPServerSocket>;
service_name()272   static const char* service_name() {
273     return "ResumableTCPServerSocketManager";
274   }
275 
276   // Application-defined string - see sockets_tcp_server.idl.
277   std::string name_;
278   // Flag indicating whether the socket is left open when the application is
279   // suspended - see sockets_tcp_server.idl.
280   bool persistent_;
281   // Flag indicating whether a connected socket blocks its peer from sending
282   // more data - see sockets_tcp_server.idl.
283   bool paused_;
284 };
285 
286 }  //  namespace extensions
287 
288 #endif  // EXTENSIONS_BROWSER_API_SOCKET_TCP_SOCKET_H_
289