blob: 467be89af985521d0056102fb12088134bf833fa [file] [log] [blame]
[email protected]bdf9bdc2013-03-13 04:23:101// 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.
4
danakj03de39b22016-04-23 04:21:095#include "ipc/unix_domain_socket_util.h"
6
avi246998d82015-12-22 02:39:047#include <stddef.h>
[email protected]bdf9bdc2013-03-13 04:23:108#include <sys/socket.h>
9
danakj03de39b22016-04-23 04:21:0910#include <memory>
11
[email protected]bdf9bdc2013-03-13 04:23:1012#include "base/bind.h"
[email protected]bdf9bdc2013-03-13 04:23:1013#include "base/files/file_path.h"
skyostile687bdff2015-05-12 11:29:2114#include "base/location.h"
avi246998d82015-12-22 02:39:0415#include "base/macros.h"
[email protected]bdf9bdc2013-03-13 04:23:1016#include "base/path_service.h"
[email protected]47163d42013-05-16 02:37:5017#include "base/posix/eintr_wrapper.h"
skyostile687bdff2015-05-12 11:29:2118#include "base/single_thread_task_runner.h"
[email protected]bdf9bdc2013-03-13 04:23:1019#include "base/synchronization/waitable_event.h"
20#include "base/threading/thread.h"
21#include "base/threading/thread_restrictions.h"
[email protected]bdf9bdc2013-03-13 04:23:1022#include "testing/gtest/include/gtest/gtest.h"
23
24namespace {
25
[email protected]fd0a773a2013-04-30 20:55:0326class SocketAcceptor : public base::MessageLoopForIO::Watcher {
[email protected]bdf9bdc2013-03-13 04:23:1027 public:
skyostile687bdff2015-05-12 11:29:2128 SocketAcceptor(int fd, base::SingleThreadTaskRunner* target_thread)
[email protected]bdf9bdc2013-03-13 04:23:1029 : server_fd_(-1),
30 target_thread_(target_thread),
gab90c2c5c2016-06-01 20:34:0631 started_watching_event_(
32 base::WaitableEvent::ResetPolicy::AUTOMATIC,
33 base::WaitableEvent::InitialState::NOT_SIGNALED),
34 accepted_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
35 base::WaitableEvent::InitialState::NOT_SIGNALED) {
[email protected]bdf9bdc2013-03-13 04:23:1036 target_thread->PostTask(FROM_HERE,
37 base::Bind(&SocketAcceptor::StartWatching, base::Unretained(this), fd));
38 }
39
dchengfe61fca2014-10-22 02:29:5240 ~SocketAcceptor() override {
dchengf3076af2014-10-21 18:02:4241 Close();
42 }
[email protected]bdf9bdc2013-03-13 04:23:1043
44 int server_fd() const { return server_fd_; }
45
46 void WaitUntilReady() {
47 started_watching_event_.Wait();
48 }
49
50 void WaitForAccept() {
51 accepted_event_.Wait();
52 }
53
54 void Close() {
55 if (watcher_.get()) {
56 target_thread_->PostTask(FROM_HERE,
57 base::Bind(&SocketAcceptor::StopWatching, base::Unretained(this),
58 watcher_.release()));
59 }
60 }
61
62 private:
63 void StartWatching(int fd) {
[email protected]fd0a773a2013-04-30 20:55:0364 watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher);
65 base::MessageLoopForIO::current()->WatchFileDescriptor(
66 fd, true, base::MessageLoopForIO::WATCH_READ, watcher_.get(), this);
[email protected]bdf9bdc2013-03-13 04:23:1067 started_watching_event_.Signal();
68 }
[email protected]fd0a773a2013-04-30 20:55:0369 void StopWatching(base::MessageLoopForIO::FileDescriptorWatcher* watcher) {
[email protected]bdf9bdc2013-03-13 04:23:1070 watcher->StopWatchingFileDescriptor();
71 delete watcher;
72 }
dchengfe61fca2014-10-22 02:29:5273 void OnFileCanReadWithoutBlocking(int fd) override {
[email protected]bdf9bdc2013-03-13 04:23:1074 ASSERT_EQ(-1, server_fd_);
bene1bbc002016-07-05 16:04:3675 IPC::ServerOnConnect(fd, &server_fd_);
[email protected]bdf9bdc2013-03-13 04:23:1076 watcher_->StopWatchingFileDescriptor();
77 accepted_event_.Signal();
78 }
dchengfe61fca2014-10-22 02:29:5279 void OnFileCanWriteWithoutBlocking(int fd) override {}
[email protected]bdf9bdc2013-03-13 04:23:1080
81 int server_fd_;
skyostile687bdff2015-05-12 11:29:2182 base::SingleThreadTaskRunner* target_thread_;
danakj03de39b22016-04-23 04:21:0983 std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> watcher_;
[email protected]bdf9bdc2013-03-13 04:23:1084 base::WaitableEvent started_watching_event_;
85 base::WaitableEvent accepted_event_;
86
87 DISALLOW_COPY_AND_ASSIGN(SocketAcceptor);
88};
89
90const base::FilePath GetChannelDir() {
[email protected]bdf9bdc2013-03-13 04:23:1091 base::FilePath tmp_dir;
byungchule2295eb2015-01-22 17:43:5992 PathService::Get(base::DIR_TEMP, &tmp_dir);
[email protected]bdf9bdc2013-03-13 04:23:1093 return tmp_dir;
[email protected]bdf9bdc2013-03-13 04:23:1094}
95
96class TestUnixSocketConnection {
97 public:
98 TestUnixSocketConnection()
99 : worker_("WorkerThread"),
100 server_listen_fd_(-1),
101 server_fd_(-1),
102 client_fd_(-1) {
103 socket_name_ = GetChannelDir().Append("TestSocket");
104 base::Thread::Options options;
[email protected]fd0a773a2013-04-30 20:55:03105 options.message_loop_type = base::MessageLoop::TYPE_IO;
[email protected]bdf9bdc2013-03-13 04:23:10106 worker_.StartWithOptions(options);
107 }
108
109 bool CreateServerSocket() {
110 IPC::CreateServerUnixDomainSocket(socket_name_, &server_listen_fd_);
111 if (server_listen_fd_ < 0)
112 return false;
113 struct stat socket_stat;
114 stat(socket_name_.value().c_str(), &socket_stat);
115 EXPECT_TRUE(S_ISSOCK(socket_stat.st_mode));
skyostile687bdff2015-05-12 11:29:21116 acceptor_.reset(
117 new SocketAcceptor(server_listen_fd_, worker_.task_runner().get()));
[email protected]bdf9bdc2013-03-13 04:23:10118 acceptor_->WaitUntilReady();
119 return true;
120 }
121
122 bool CreateClientSocket() {
123 DCHECK(server_listen_fd_ >= 0);
124 IPC::CreateClientUnixDomainSocket(socket_name_, &client_fd_);
125 if (client_fd_ < 0)
126 return false;
127 acceptor_->WaitForAccept();
128 server_fd_ = acceptor_->server_fd();
129 return server_fd_ >= 0;
130 }
131
132 virtual ~TestUnixSocketConnection() {
133 if (client_fd_ >= 0)
134 close(client_fd_);
135 if (server_fd_ >= 0)
136 close(server_fd_);
137 if (server_listen_fd_ >= 0) {
138 close(server_listen_fd_);
139 unlink(socket_name_.value().c_str());
140 }
141 }
142
143 int client_fd() const { return client_fd_; }
144 int server_fd() const { return server_fd_; }
145
146 private:
147 base::Thread worker_;
148 base::FilePath socket_name_;
149 int server_listen_fd_;
150 int server_fd_;
151 int client_fd_;
danakj03de39b22016-04-23 04:21:09152 std::unique_ptr<SocketAcceptor> acceptor_;
[email protected]bdf9bdc2013-03-13 04:23:10153};
154
155// Ensure that IPC::CreateServerUnixDomainSocket creates a socket that
156// IPC::CreateClientUnixDomainSocket can successfully connect to.
157TEST(UnixDomainSocketUtil, Connect) {
158 TestUnixSocketConnection connection;
159 ASSERT_TRUE(connection.CreateServerSocket());
160 ASSERT_TRUE(connection.CreateClientSocket());
161}
162
163// Ensure that messages can be sent across the resulting socket.
164TEST(UnixDomainSocketUtil, SendReceive) {
165 TestUnixSocketConnection connection;
166 ASSERT_TRUE(connection.CreateServerSocket());
167 ASSERT_TRUE(connection.CreateClientSocket());
168
169 const char buffer[] = "Hello, server!";
170 size_t buf_len = sizeof(buffer);
171 size_t sent_bytes =
172 HANDLE_EINTR(send(connection.client_fd(), buffer, buf_len, 0));
173 ASSERT_EQ(buf_len, sent_bytes);
174 char recv_buf[sizeof(buffer)];
175 size_t received_bytes =
176 HANDLE_EINTR(recv(connection.server_fd(), recv_buf, buf_len, 0));
177 ASSERT_EQ(buf_len, received_bytes);
178 ASSERT_EQ(0, memcmp(recv_buf, buffer, buf_len));
179}
180
181} // namespace