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

Unified 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, 4 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 side-by-side diff with in-line comments
Download patch
Index: mojo/edk/embedder/named_platform_handle_utils_posix.cc
diff --git a/mojo/edk/embedder/named_platform_handle_utils_posix.cc b/mojo/edk/embedder/named_platform_handle_utils_posix.cc
new file mode 100644
index 0000000000000000000000000000000000000000..97572c0590377b89a1128d55c904923ec0be1865
--- /dev/null
+++ b/mojo/edk/embedder/named_platform_handle_utils_posix.cc
@@ -0,0 +1,147 @@
+// Copyright 2016 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 "mojo/edk/embedder/named_platform_handle_utils.h"
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "mojo/edk/embedder/named_platform_handle.h"
+
+namespace mojo {
+namespace edk {
+namespace {
+
+// The maximum length of the name of a socket for MODE_NAMED_SERVER or
+// MODE_NAMED_CLIENT if you want to pass in your own socket.
+// The standard size on linux is 108, mac is 104. To maintain consistency
+// across platforms we standardize on the smaller value.
+const size_t kMaxSocketNameLength = 104;
+
+// This function fills in |unix_addr| with the appropriate data for the socket,
+// and sets |unix_addr_len| to the length of the data therein.
+// Returns true on success, or false on failure (typically because |handle.name|
+// violated the naming rules).
+bool MakeUnixAddr(const NamedPlatformHandle& handle,
+ struct sockaddr_un* unix_addr,
+ size_t* unix_addr_len) {
+ DCHECK(unix_addr);
+ DCHECK(unix_addr_len);
+ DCHECK(handle.is_valid());
+
+ // We reject handle.name.length() == kMaxSocketNameLength to make room for the
+ // NUL terminator at the end of the string.
+ if (handle.name.length() >= kMaxSocketNameLength) {
+ LOG(ERROR) << "Socket name too long: " << handle.name;
+ return false;
+ }
+
+ // Create unix_addr structure.
+ memset(unix_addr, 0, sizeof(struct sockaddr_un));
+ unix_addr->sun_family = AF_UNIX;
+ strncpy(unix_addr->sun_path, handle.name.c_str(), kMaxSocketNameLength);
+ *unix_addr_len =
+ offsetof(struct sockaddr_un, sun_path) + handle.name.length();
+ return true;
+}
+
+// This function creates a unix domain socket, and set it as non-blocking.
+// If successful, this returns a ScopedPlatformHandle containing the socket.
+// Otherwise, this returns an invalid ScopedPlatformHandle.
+ScopedPlatformHandle CreateUnixDomainSocket(bool needs_connection) {
+ // Create the unix domain socket.
+ PlatformHandle socket_handle(socket(AF_UNIX, SOCK_STREAM, 0));
+ socket_handle.needs_connection = needs_connection;
+ ScopedPlatformHandle handle(socket_handle);
+ if (!handle.is_valid()) {
+ PLOG(ERROR) << "Failed to create AF_UNIX socket.";
+ return ScopedPlatformHandle();
+ }
+
+ // Now set it as non-blocking.
+ if (!base::SetNonBlocking(handle.get().handle)) {
+ PLOG(ERROR) << "base::SetNonBlocking() failed " << handle.get().handle;
+ return ScopedPlatformHandle();
+ }
+ return handle;
+}
+
+} // namespace
+
+ScopedPlatformHandle CreateClientHandle(
+ const NamedPlatformHandle& named_handle) {
+ if (!named_handle.is_valid())
+ return ScopedPlatformHandle();
+
+ struct sockaddr_un unix_addr;
+ size_t unix_addr_len;
+ if (!MakeUnixAddr(named_handle, &unix_addr, &unix_addr_len))
+ return ScopedPlatformHandle();
+
+ ScopedPlatformHandle handle = CreateUnixDomainSocket(false);
+ if (!handle.is_valid())
+ return ScopedPlatformHandle();
+
+ if (HANDLE_EINTR(connect(handle.get().handle,
+ reinterpret_cast<sockaddr*>(&unix_addr),
+ unix_addr_len)) < 0) {
+ PLOG(ERROR) << "connect " << named_handle.name;
+ return ScopedPlatformHandle();
+ }
+
+ return handle;
+}
+
+ScopedPlatformHandle CreateServerHandle(const NamedPlatformHandle& named_handle,
+ bool enforce_uniqueness) {
+ CHECK(!enforce_uniqueness);
+ if (!named_handle.is_valid())
+ return ScopedPlatformHandle();
+
+ // Make sure the path we need exists.
+ base::FilePath socket_dir = base::FilePath(named_handle.name).DirName();
+ if (!base::CreateDirectory(socket_dir)) {
+ LOG(ERROR) << "Couldn't create directory: " << socket_dir.value();
+ return ScopedPlatformHandle();
+ }
+
+ // Delete any old FS instances.
+ if (unlink(named_handle.name.c_str()) < 0 && errno != ENOENT) {
+ PLOG(ERROR) << "unlink " << named_handle.name;
+ return ScopedPlatformHandle();
+ }
+
+ struct sockaddr_un unix_addr;
+ size_t unix_addr_len;
+ if (!MakeUnixAddr(named_handle, &unix_addr, &unix_addr_len))
+ return ScopedPlatformHandle();
+
+ ScopedPlatformHandle handle = CreateUnixDomainSocket(true);
+ if (!handle.is_valid())
+ return ScopedPlatformHandle();
+
+ // Bind the socket.
+ if (bind(handle.get().handle, reinterpret_cast<const sockaddr*>(&unix_addr),
+ unix_addr_len) < 0) {
+ PLOG(ERROR) << "bind " << named_handle.name;
+ return ScopedPlatformHandle();
+ }
+
+ // Start listening on the socket.
+ if (listen(handle.get().handle, SOMAXCONN) < 0) {
+ PLOG(ERROR) << "listen " << named_handle.name;
+ unlink(named_handle.name.c_str());
+ return ScopedPlatformHandle();
+ }
+ return handle;
+}
+
+} // namespace edk
+} // namespace mojo
« 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