Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Side by Side Diff: mojo/edk/embedder/named_platform_handle_utils_posix.cc

Issue 2282413004: Support creating mojo peer connections from named pipes. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "mojo/edk/embedder/named_platform_handle_utils.h"
6
7 #include <errno.h>
8 #include <sys/socket.h>
9 #include <sys/un.h>
10 #include <unistd.h>
11
12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h"
14 #include "base/logging.h"
15 #include "base/posix/eintr_wrapper.h"
16 #include "mojo/edk/embedder/named_platform_handle.h"
17
18 namespace mojo {
19 namespace edk {
20 namespace {
21
22 // The maximum length of the name of a socket for MODE_NAMED_SERVER or
23 // MODE_NAMED_CLIENT if you want to pass in your own socket.
24 // The standard size on linux is 108, mac is 104. To maintain consistency
25 // across platforms we standardize on the smaller value.
26 const size_t kMaxSocketNameLength = 104;
27
28 // This function fills in |unix_addr| with the appropriate data for the socket,
29 // and sets |unix_addr_len| to the length of the data therein.
30 // Returns true on success, or false on failure (typically because |handle.name|
31 // violated the naming rules).
32 bool MakeUnixAddr(const NamedPlatformHandle& handle,
33 struct sockaddr_un* unix_addr,
34 size_t* unix_addr_len) {
35 DCHECK(unix_addr);
36 DCHECK(unix_addr_len);
37 DCHECK(handle.is_valid());
38
39 // We reject handle.name.length() == kMaxSocketNameLength to make room for the
40 // NUL terminator at the end of the string.
41 if (handle.name.length() >= kMaxSocketNameLength) {
42 LOG(ERROR) << "Socket name too long: " << handle.name;
43 return false;
44 }
45
46 // Create unix_addr structure.
47 memset(unix_addr, 0, sizeof(struct sockaddr_un));
48 unix_addr->sun_family = AF_UNIX;
49 strncpy(unix_addr->sun_path, handle.name.c_str(), kMaxSocketNameLength);
50 *unix_addr_len =
51 offsetof(struct sockaddr_un, sun_path) + handle.name.length();
52 return true;
53 }
54
55 // This function creates a unix domain socket, and set it as non-blocking.
56 // If successful, this returns a ScopedPlatformHandle containing the socket.
57 // Otherwise, this returns an invalid ScopedPlatformHandle.
58 ScopedPlatformHandle CreateUnixDomainSocket(bool needs_connection) {
59 // Create the unix domain socket.
60 PlatformHandle socket_handle(socket(AF_UNIX, SOCK_STREAM, 0));
61 socket_handle.needs_connection = needs_connection;
62 ScopedPlatformHandle handle(socket_handle);
63 if (!handle.is_valid()) {
64 PLOG(ERROR) << "Failed to create AF_UNIX socket.";
65 return ScopedPlatformHandle();
66 }
67
68 // Now set it as non-blocking.
69 if (!base::SetNonBlocking(handle.get().handle)) {
70 PLOG(ERROR) << "base::SetNonBlocking() failed " << handle.get().handle;
71 return ScopedPlatformHandle();
72 }
73 return handle;
74 }
75
76 } // namespace
77
78 ScopedPlatformHandle CreateClientHandle(
79 const NamedPlatformHandle& named_handle) {
80 if (!named_handle.is_valid())
81 return ScopedPlatformHandle();
82
83 struct sockaddr_un unix_addr;
84 size_t unix_addr_len;
85 if (!MakeUnixAddr(named_handle, &unix_addr, &unix_addr_len))
86 return ScopedPlatformHandle();
87
88 ScopedPlatformHandle handle = CreateUnixDomainSocket(false);
89 if (!handle.is_valid())
90 return ScopedPlatformHandle();
91
92 if (HANDLE_EINTR(connect(handle.get().handle,
93 reinterpret_cast<sockaddr*>(&unix_addr),
94 unix_addr_len)) < 0) {
95 PLOG(ERROR) << "connect " << named_handle.name;
96 return ScopedPlatformHandle();
97 }
98
99 return handle;
100 }
101
102 ScopedPlatformHandle CreateServerHandle(const NamedPlatformHandle& named_handle,
103 bool enforce_uniqueness) {
104 CHECK(!enforce_uniqueness);
105 if (!named_handle.is_valid())
106 return ScopedPlatformHandle();
107
108 // Make sure the path we need exists.
109 base::FilePath socket_dir = base::FilePath(named_handle.name).DirName();
110 if (!base::CreateDirectory(socket_dir)) {
111 LOG(ERROR) << "Couldn't create directory: " << socket_dir.value();
112 return ScopedPlatformHandle();
113 }
114
115 // Delete any old FS instances.
116 if (unlink(named_handle.name.c_str()) < 0 && errno != ENOENT) {
117 PLOG(ERROR) << "unlink " << named_handle.name;
118 return ScopedPlatformHandle();
119 }
120
121 struct sockaddr_un unix_addr;
122 size_t unix_addr_len;
123 if (!MakeUnixAddr(named_handle, &unix_addr, &unix_addr_len))
124 return ScopedPlatformHandle();
125
126 ScopedPlatformHandle handle = CreateUnixDomainSocket(true);
127 if (!handle.is_valid())
128 return ScopedPlatformHandle();
129
130 // Bind the socket.
131 if (bind(handle.get().handle, reinterpret_cast<const sockaddr*>(&unix_addr),
132 unix_addr_len) < 0) {
133 PLOG(ERROR) << "bind " << named_handle.name;
134 return ScopedPlatformHandle();
135 }
136
137 // Start listening on the socket.
138 if (listen(handle.get().handle, SOMAXCONN) < 0) {
139 PLOG(ERROR) << "listen " << named_handle.name;
140 unlink(named_handle.name.c_str());
141 return ScopedPlatformHandle();
142 }
143 return handle;
144 }
145
146 } // namespace edk
147 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/embedder/named_platform_handle_utils.h ('k') | mojo/edk/embedder/named_platform_handle_utils_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698