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.
4
5#include "remoting/host/ipc_util.h"
6
7#include <fcntl.h>
8#include <sys/socket.h>
9#include <sys/types.h>
10#include <unistd.h>
11
12#include "base/logging.h"
13#include "base/posix/eintr_wrapper.h"
14#include "base/single_thread_task_runner.h"
15#include "ipc/ipc_channel.h"
16#include "ipc/ipc_channel_proxy.h"
17
18namespace remoting {
19
20bool CreateConnectedIpcChannel(
21    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
22    IPC::Listener* listener,
23    IPC::PlatformFileForTransit* client_out,
24    scoped_ptr<IPC::ChannelProxy>* server_out) {
25  // Create a socket pair.
26  int pipe_fds[2];
27  if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds) != 0) {
28    PLOG(ERROR) << "socketpair()";
29    return false;
30  }
31
32  // Set both ends to be non-blocking.
33  if (fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK) == -1 ||
34      fcntl(pipe_fds[1], F_SETFL, O_NONBLOCK) == -1) {
35    PLOG(ERROR) << "fcntl(O_NONBLOCK)";
36    if (IGNORE_EINTR(close(pipe_fds[0])) < 0)
37      PLOG(ERROR) << "close()";
38    if (IGNORE_EINTR(close(pipe_fds[1])) < 0)
39      PLOG(ERROR) << "close()";
40    return false;
41  }
42
43  std::string socket_name = "Chromoting socket";
44
45  // Wrap the pipe into an IPC channel.
46  base::FileDescriptor fd(pipe_fds[0], false);
47  IPC::ChannelHandle handle(socket_name, fd);
48  server_out->reset(new IPC::ChannelProxy(IPC::ChannelHandle(socket_name, fd),
49                                          IPC::Channel::MODE_SERVER,
50                                          listener,
51                                          io_task_runner.get()));
52
53  *client_out = base::FileDescriptor(pipe_fds[1], false);
54  return true;
55}
56
57} // namespace remoting
58