summaryrefslogtreecommitdiffstats
path: root/remoting/host/ipc_util_posix.cc
blob: b7c5277e22cf712881db3a15234e4912c4ebb177 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/ipc_util.h"

#include <fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#include "base/files/file.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/single_thread_task_runner.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_channel_proxy.h"

namespace remoting {

bool CreateConnectedIpcChannel(
    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
    IPC::Listener* listener,
    base::File* client_out,
    scoped_ptr<IPC::ChannelProxy>* server_out) {
  // Create a socket pair.
  int pipe_fds[2];
  if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds) != 0) {
    PLOG(ERROR) << "socketpair()";
    return false;
  }

  // Set both ends to be non-blocking.
  if (fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK) == -1 ||
      fcntl(pipe_fds[1], F_SETFL, O_NONBLOCK) == -1) {
    PLOG(ERROR) << "fcntl(O_NONBLOCK)";
    if (IGNORE_EINTR(close(pipe_fds[0])) < 0)
      PLOG(ERROR) << "close()";
    if (IGNORE_EINTR(close(pipe_fds[1])) < 0)
      PLOG(ERROR) << "close()";
    return false;
  }

  std::string socket_name = "Chromoting socket";

  // Wrap the pipe into an IPC channel.
  base::FileDescriptor fd(pipe_fds[0], false);
  IPC::ChannelHandle handle(socket_name, fd);
  *server_out = IPC::ChannelProxy::Create(IPC::ChannelHandle(socket_name, fd),
                                          IPC::Channel::MODE_SERVER, listener,
                                          io_task_runner.get());

  *client_out = base::File(pipe_fds[1]);
  return true;
}

} // namespace remoting