blob: e346bae049786d0b8289e88f5ff8d985876f57af [file] [log] [blame]
[email protected]532e9bd2012-01-25 12:04:171// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]0840cc72009-11-24 16:14:532// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]22b42c52010-12-20 06:59:235#include "base/sync_socket.h"
6
avi246998d82015-12-22 02:39:047#include <stddef.h>
[email protected]0840cc72009-11-24 16:14:538#include <stdio.h>
danakj03de39b22016-04-23 04:21:099#include <memory>
[email protected]0840cc72009-11-24 16:14:5310#include <sstream>
skyostile687bdff2015-05-12 11:29:2111#include <string>
[email protected]0840cc72009-11-24 16:14:5312
[email protected]532e9bd2012-01-25 12:04:1713#include "base/bind.h"
skyostile687bdff2015-05-12 11:29:2114#include "base/location.h"
fdoray8e32586852016-06-22 19:56:1615#include "base/run_loop.h"
skyostile687bdff2015-05-12 11:29:2116#include "base/single_thread_task_runner.h"
Avi Drissman118cee82018-12-26 17:07:1617#include "base/stl_util.h"
[email protected]532e9bd2012-01-25 12:04:1718#include "base/threading/thread.h"
avi246998d82015-12-22 02:39:0419#include "build/build_config.h"
[email protected]0cb7d8c82013-01-11 15:13:3720#include "ipc/ipc_test_base.h"
[email protected]0840cc72009-11-24 16:14:5321#include "testing/gtest/include/gtest/gtest.h"
[email protected]0840cc72009-11-24 16:14:5322
[email protected]23f771162011-06-02 18:37:5123#if defined(OS_POSIX)
[email protected]f214f8792011-01-01 02:17:0824#include "base/file_descriptor_posix.h"
[email protected]23f771162011-06-02 18:37:5125#endif
[email protected]0840cc72009-11-24 16:14:5326
[email protected]2a3aa7b52013-01-11 20:56:2227// IPC messages for testing ----------------------------------------------------
[email protected]1d4ecf42011-08-26 21:27:3028
29#define IPC_MESSAGE_IMPL
30#include "ipc/ipc_message_macros.h"
31
32#define IPC_MESSAGE_START TestMsgStart
33
34// Message class to pass a base::SyncSocket::Handle to another process. This
35// is not as easy as it sounds, because of the differences in transferring
36// Windows HANDLEs versus posix file descriptors.
37#if defined(OS_WIN)
38IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::SyncSocket::Handle)
39#elif defined(OS_POSIX)
40IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::FileDescriptor)
41#endif
42
43// Message class to pass a response to the server.
44IPC_MESSAGE_CONTROL1(MsgClassResponse, std::string)
45
46// Message class to tell the server to shut down.
47IPC_MESSAGE_CONTROL0(MsgClassShutdown)
48
[email protected]2a3aa7b52013-01-11 20:56:2249// -----------------------------------------------------------------------------
[email protected]0840cc72009-11-24 16:14:5350
51namespace {
[email protected]2a3aa7b52013-01-11 20:56:2252
[email protected]0840cc72009-11-24 16:14:5353const char kHelloString[] = "Hello, SyncSocket Client";
Avi Drissman118cee82018-12-26 17:07:1654const size_t kHelloStringLength = base::size(kHelloString);
[email protected]0840cc72009-11-24 16:14:5355
[email protected]0840cc72009-11-24 16:14:5356// The SyncSocket server listener class processes two sorts of
57// messages from the client.
[email protected]b7f59e822012-06-29 22:05:2658class SyncSocketServerListener : public IPC::Listener {
[email protected]0840cc72009-11-24 16:14:5359 public:
[email protected]532e9bd2012-01-25 12:04:1760 SyncSocketServerListener() : chan_(NULL) {
[email protected]0840cc72009-11-24 16:14:5361 }
62
63 void Init(IPC::Channel* chan) {
64 chan_ = chan;
65 }
66
dchengfe61fca2014-10-22 02:29:5267 bool OnMessageReceived(const IPC::Message& msg) override {
[email protected]0840cc72009-11-24 16:14:5368 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
69 IPC_BEGIN_MESSAGE_MAP(SyncSocketServerListener, msg)
70 IPC_MESSAGE_HANDLER(MsgClassSetHandle, OnMsgClassSetHandle)
71 IPC_MESSAGE_HANDLER(MsgClassShutdown, OnMsgClassShutdown)
72 IPC_END_MESSAGE_MAP()
73 }
[email protected]a95986a82010-12-24 06:19:2874 return true;
[email protected]0840cc72009-11-24 16:14:5375 }
76
77 private:
78 // This sort of message is sent first, causing the transfer of
79 // the handle for the SyncSocket. This message sends a buffer
80 // on the SyncSocket and then sends a response to the client.
[email protected]182c44fa2009-11-26 00:28:0281#if defined(OS_WIN)
[email protected]0840cc72009-11-24 16:14:5382 void OnMsgClassSetHandle(const base::SyncSocket::Handle handle) {
[email protected]182c44fa2009-11-26 00:28:0283 SetHandle(handle);
84 }
85#elif defined(OS_POSIX)
86 void OnMsgClassSetHandle(const base::FileDescriptor& fd_struct) {
87 SetHandle(fd_struct.fd);
88 }
89#else
90# error "What platform?"
91#endif // defined(OS_WIN)
92
93 void SetHandle(base::SyncSocket::Handle handle) {
[email protected]0840cc72009-11-24 16:14:5394 base::SyncSocket sync_socket(handle);
[email protected]5d272092012-04-19 10:23:0395 EXPECT_EQ(sync_socket.Send(kHelloString, kHelloStringLength),
96 kHelloStringLength);
[email protected]0840cc72009-11-24 16:14:5397 IPC::Message* msg = new MsgClassResponse(kHelloString);
[email protected]0840cc72009-11-24 16:14:5398 EXPECT_TRUE(chan_->Send(msg));
99 }
100
101 // When the client responds, it sends back a shutdown message,
102 // which causes the message loop to exit.
Gabriel Charette53a9ef812017-07-26 12:36:23103 void OnMsgClassShutdown() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
[email protected]0840cc72009-11-24 16:14:53104
105 IPC::Channel* chan_;
106
107 DISALLOW_COPY_AND_ASSIGN(SyncSocketServerListener);
108};
109
[email protected]3c788582013-01-25 21:51:35110// Runs the fuzzing server child mode. Returns when the preset number of
111// messages have been received.
sammc4bcc4ed62016-10-27 10:13:59112DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(SyncSocketServerClient) {
[email protected]0840cc72009-11-24 16:14:53113 SyncSocketServerListener listener;
sammc4bcc4ed62016-10-27 10:13:59114 Connect(&listener);
115 listener.Init(channel());
fdoray8e32586852016-06-22 19:56:16116 base::RunLoop().Run();
sammc4bcc4ed62016-10-27 10:13:59117 Close();
[email protected]0840cc72009-11-24 16:14:53118}
119
120// The SyncSocket client listener only processes one sort of message,
121// a response from the server.
[email protected]b7f59e822012-06-29 22:05:26122class SyncSocketClientListener : public IPC::Listener {
[email protected]0840cc72009-11-24 16:14:53123 public:
Chris Watkins2d879af2017-11-30 02:11:59124 SyncSocketClientListener() = default;
[email protected]0840cc72009-11-24 16:14:53125
126 void Init(base::SyncSocket* socket, IPC::Channel* chan) {
127 socket_ = socket;
128 chan_ = chan;
129 }
130
dchengfe61fca2014-10-22 02:29:52131 bool OnMessageReceived(const IPC::Message& msg) override {
[email protected]0840cc72009-11-24 16:14:53132 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
133 IPC_BEGIN_MESSAGE_MAP(SyncSocketClientListener, msg)
134 IPC_MESSAGE_HANDLER(MsgClassResponse, OnMsgClassResponse)
135 IPC_END_MESSAGE_MAP()
136 }
[email protected]a95986a82010-12-24 06:19:28137 return true;
[email protected]0840cc72009-11-24 16:14:53138 }
139
140 private:
141 // When a response is received from the server, it sends the same
142 // string as was written on the SyncSocket. These are compared
143 // and a shutdown message is sent back to the server.
144 void OnMsgClassResponse(const std::string& str) {
[email protected]d8b65912009-12-04 22:53:22145 // We rely on the order of sync_socket.Send() and chan_->Send() in
146 // the SyncSocketServerListener object.
147 EXPECT_EQ(kHelloStringLength, socket_->Peek());
[email protected]0840cc72009-11-24 16:14:53148 char buf[kHelloStringLength];
149 socket_->Receive(static_cast<void*>(buf), kHelloStringLength);
150 EXPECT_EQ(strcmp(str.c_str(), buf), 0);
[email protected]1e1f1a72009-12-06 19:45:08151 // After receiving from the socket there should be no bytes left.
[email protected]7ee1a44c2010-07-23 14:18:59152 EXPECT_EQ(0U, socket_->Peek());
[email protected]0840cc72009-11-24 16:14:53153 IPC::Message* msg = new MsgClassShutdown();
[email protected]0840cc72009-11-24 16:14:53154 EXPECT_TRUE(chan_->Send(msg));
Gabriel Charette53a9ef812017-07-26 12:36:23155 base::RunLoop::QuitCurrentWhenIdleDeprecated();
[email protected]0840cc72009-11-24 16:14:53156 }
157
158 base::SyncSocket* socket_;
159 IPC::Channel* chan_;
160
161 DISALLOW_COPY_AND_ASSIGN(SyncSocketClientListener);
162};
163
sammc4bcc4ed62016-10-27 10:13:59164using SyncSocketTest = IPCChannelMojoTestBase;
[email protected]0840cc72009-11-24 16:14:53165
amistry6de2ee4f2016-05-05 05:12:09166TEST_F(SyncSocketTest, SanityTest) {
[email protected]3c788582013-01-25 21:51:35167 Init("SyncSocketServerClient");
168
[email protected]0840cc72009-11-24 16:14:53169 SyncSocketClientListener listener;
[email protected]3c788582013-01-25 21:51:35170 CreateChannel(&listener);
[email protected]0840cc72009-11-24 16:14:53171 // Create a pair of SyncSockets.
[email protected]532e9bd2012-01-25 12:04:17172 base::SyncSocket pair[2];
173 base::SyncSocket::CreatePair(&pair[0], &pair[1]);
[email protected]1e1f1a72009-12-06 19:45:08174 // Immediately after creation there should be no pending bytes.
[email protected]532e9bd2012-01-25 12:04:17175 EXPECT_EQ(0U, pair[0].Peek());
176 EXPECT_EQ(0U, pair[1].Peek());
[email protected]0840cc72009-11-24 16:14:53177 base::SyncSocket::Handle target_handle;
[email protected]182c44fa2009-11-26 00:28:02178 // Connect the channel and listener.
[email protected]3c788582013-01-25 21:51:35179 ASSERT_TRUE(ConnectChannel());
180 listener.Init(&pair[0], channel());
[email protected]0840cc72009-11-24 16:14:53181#if defined(OS_WIN)
182 // On windows we need to duplicate the handle into the server process.
[email protected]532e9bd2012-01-25 12:04:17183 BOOL retval = DuplicateHandle(GetCurrentProcess(), pair[1].handle(),
rvargas07b589c2015-01-12 22:23:23184 client_process().Handle(), &target_handle,
[email protected]0840cc72009-11-24 16:14:53185 0, FALSE, DUPLICATE_SAME_ACCESS);
186 EXPECT_TRUE(retval);
[email protected]0840cc72009-11-24 16:14:53187 // Set up a message to pass the handle to the server.
188 IPC::Message* msg = new MsgClassSetHandle(target_handle);
[email protected]182c44fa2009-11-26 00:28:02189#else
[email protected]532e9bd2012-01-25 12:04:17190 target_handle = pair[1].handle();
[email protected]182c44fa2009-11-26 00:28:02191 // Set up a message to pass the handle to the server.
192 base::FileDescriptor filedesc(target_handle, false);
193 IPC::Message* msg = new MsgClassSetHandle(filedesc);
194#endif // defined(OS_WIN)
[email protected]3c788582013-01-25 21:51:35195 EXPECT_TRUE(sender()->Send(msg));
[email protected]0840cc72009-11-24 16:14:53196 // Use the current thread as the I/O thread.
fdoray8e32586852016-06-22 19:56:16197 base::RunLoop().Run();
[email protected]0840cc72009-11-24 16:14:53198 // Shut down.
[email protected]532e9bd2012-01-25 12:04:17199 pair[0].Close();
200 pair[1].Close();
[email protected]3c788582013-01-25 21:51:35201 EXPECT_TRUE(WaitForClientShutdown());
202 DestroyChannel();
[email protected]0840cc72009-11-24 16:14:53203}
[email protected]532e9bd2012-01-25 12:04:17204
[email protected]5d272092012-04-19 10:23:03205// A blocking read operation that will block the thread until it receives
206// |length| bytes of packets or Shutdown() is called on another thread.
207static void BlockingRead(base::SyncSocket* socket, char* buf,
208 size_t length, size_t* received) {
209 DCHECK(buf != NULL);
[email protected]532e9bd2012-01-25 12:04:17210 // Notify the parent thread that we're up and running.
211 socket->Send(kHelloString, kHelloStringLength);
[email protected]5d272092012-04-19 10:23:03212 *received = socket->Receive(buf, length);
[email protected]532e9bd2012-01-25 12:04:17213}
214
215// Tests that we can safely end a blocking Receive operation on one thread
216// from another thread by disconnecting (but not closing) the socket.
217TEST_F(SyncSocketTest, DisconnectTest) {
218 base::CancelableSyncSocket pair[2];
219 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
220
221 base::Thread worker("BlockingThread");
222 worker.Start();
223
224 // Try to do a blocking read from one of the sockets on the worker thread.
[email protected]5d272092012-04-19 10:23:03225 char buf[0xff];
[email protected]532e9bd2012-01-25 12:04:17226 size_t received = 1U; // Initialize to an unexpected value.
skyostile687bdff2015-05-12 11:29:21227 worker.task_runner()->PostTask(
kylecharf448cc92019-02-19 20:28:09228 FROM_HERE, base::BindOnce(&BlockingRead, &pair[0], &buf[0],
229 base::size(buf), &received));
[email protected]532e9bd2012-01-25 12:04:17230
231 // Wait for the worker thread to say hello.
232 char hello[kHelloStringLength] = {0};
233 pair[1].Receive(&hello[0], sizeof(hello));
[email protected]5d272092012-04-19 10:23:03234 EXPECT_EQ(0, strcmp(hello, kHelloString));
[email protected]532e9bd2012-01-25 12:04:17235 // Give the worker a chance to start Receive().
236 base::PlatformThread::YieldCurrentThread();
237
238 // Now shut down the socket that the thread is issuing a blocking read on
239 // which should cause Receive to return with an error.
240 pair[0].Shutdown();
241
242 worker.Stop();
243
244 EXPECT_EQ(0U, received);
245}
[email protected]5d272092012-04-19 10:23:03246
247// Tests that read is a blocking operation.
amistry6de2ee4f2016-05-05 05:12:09248TEST_F(SyncSocketTest, BlockingReceiveTest) {
[email protected]5d272092012-04-19 10:23:03249 base::CancelableSyncSocket pair[2];
250 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
251
252 base::Thread worker("BlockingThread");
253 worker.Start();
254
255 // Try to do a blocking read from one of the sockets on the worker thread.
256 char buf[kHelloStringLength] = {0};
257 size_t received = 1U; // Initialize to an unexpected value.
kylecharf448cc92019-02-19 20:28:09258 worker.task_runner()->PostTask(
259 FROM_HERE, base::BindOnce(&BlockingRead, &pair[0], &buf[0],
260 kHelloStringLength, &received));
[email protected]5d272092012-04-19 10:23:03261
262 // Wait for the worker thread to say hello.
263 char hello[kHelloStringLength] = {0};
264 pair[1].Receive(&hello[0], sizeof(hello));
265 EXPECT_EQ(0, strcmp(hello, kHelloString));
266 // Give the worker a chance to start Receive().
267 base::PlatformThread::YieldCurrentThread();
268
269 // Send a message to the socket on the blocking thead, it should free the
270 // socket from Receive().
271 pair[1].Send(kHelloString, kHelloStringLength);
272 worker.Stop();
273
274 // Verify the socket has received the message.
275 EXPECT_TRUE(strcmp(buf, kHelloString) == 0);
276 EXPECT_EQ(kHelloStringLength, received);
277}
278
279// Tests that the write operation is non-blocking and returns immediately
280// when there is insufficient space in the socket's buffer.
281TEST_F(SyncSocketTest, NonBlockingWriteTest) {
282 base::CancelableSyncSocket pair[2];
283 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
284
285 // Fill up the buffer for one of the socket, Send() should not block the
286 // thread even when the buffer is full.
287 while (pair[0].Send(kHelloString, kHelloStringLength) != 0) {}
288
289 // Data should be avialble on another socket.
290 size_t bytes_in_buffer = pair[1].Peek();
291 EXPECT_NE(bytes_in_buffer, 0U);
292
293 // No more data can be written to the buffer since socket has been full,
294 // verify that the amount of avialble data on another socket is unchanged.
295 EXPECT_EQ(0U, pair[0].Send(kHelloString, kHelloStringLength));
296 EXPECT_EQ(bytes_in_buffer, pair[1].Peek());
297
298 // Read from another socket to free some space for a new write.
299 char hello[kHelloStringLength] = {0};
300 pair[1].Receive(&hello[0], sizeof(hello));
301
302 // Should be able to write more data to the buffer now.
303 EXPECT_EQ(kHelloStringLength, pair[0].Send(kHelloString, kHelloStringLength));
304}
[email protected]2a3aa7b52013-01-11 20:56:22305
306} // namespace