summaryrefslogtreecommitdiffstats
path: root/base/sync_socket_posix.cc
diff options
context:
space:
mode:
authorsehr@google.com <sehr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-26 00:28:02 +0000
committersehr@google.com <sehr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-26 00:28:02 +0000
commit182c44faa58c15e474682f2ad349eca5a6a2235f (patch)
tree183ecce85bf6f84b4b9ed77ae358103ede765864 /base/sync_socket_posix.cc
parent4ebb4f136e3e5040351b4e29ca79fe1153ce606d (diff)
downloadchromium_src-182c44faa58c15e474682f2ad349eca5a6a2235f.zip
chromium_src-182c44faa58c15e474682f2ad349eca5a6a2235f.tar.gz
chromium_src-182c44faa58c15e474682f2ad349eca5a6a2235f.tar.bz2
Implement SyncSocket class for Posix targets (Linux, Mac), and enable the
corresponding unittest. This feature, as a reminder, allows low-latency (blocking) send/receive between processes, and will be used for real-time thread synchronization for Pepper audio and for direct synchronization for 3D video. Review URL: http://codereview.chromium.org/431043 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33161 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/sync_socket_posix.cc')
-rw-r--r--base/sync_socket_posix.cc101
1 files changed, 101 insertions, 0 deletions
diff --git a/base/sync_socket_posix.cc b/base/sync_socket_posix.cc
new file mode 100644
index 0000000..35d53b2
--- /dev/null
+++ b/base/sync_socket_posix.cc
@@ -0,0 +1,101 @@
+// Copyright (c) 2009 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 "base/sync_socket.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "base/atomicops.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+
+
+namespace base {
+
+namespace {
+// To avoid users sending negative message lengths to Send/Receive
+// we clamp message lengths, which are size_t, to no more than INT_MAX.
+const size_t kMaxMessageLength = static_cast<size_t>(INT_MAX);
+
+static const SyncSocket::Handle kInvalidHandle = -1;
+
+} // namespace
+
+bool SyncSocket::CreatePair(SyncSocket* pair[2]) {
+ Handle handles[2] = { kInvalidHandle, kInvalidHandle };
+ SyncSocket* tmp_sockets[2] = { NULL, NULL };
+#if defined(OS_MACOSX)
+ int nosigpipe = 1;
+#endif // defined(OS_MACOSX)
+
+ // Create the two SyncSocket objects first to avoid ugly cleanup issues.
+ tmp_sockets[0] = new SyncSocket(kInvalidHandle);
+ if (tmp_sockets[0] == NULL) {
+ goto cleanup;
+ }
+ tmp_sockets[1] = new SyncSocket(kInvalidHandle);
+ if (tmp_sockets[1] == NULL) {
+ goto cleanup;
+ }
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, handles) != 0) {
+ goto cleanup;
+ }
+#if defined(OS_MACOSX)
+ // On OSX an attempt to read or write to a closed socket may generate a
+ // SIGPIPE rather than returning -1. setsockopt will shut this off.
+ if (0 != setsockopt(handles[0], SOL_SOCKET, SO_NOSIGPIPE,
+ &nosigpipe, sizeof nosigpipe) ||
+ 0 != setsockopt(handles[1], SOL_SOCKET, SO_NOSIGPIPE,
+ &nosigpipe, sizeof nosigpipe)) {
+ goto cleanup;
+ }
+#endif
+ // Copy the handles out for successful return.
+ tmp_sockets[0]->handle_ = handles[0];
+ pair[0] = tmp_sockets[0];
+ tmp_sockets[1]->handle_ = handles[1];
+ pair[1] = tmp_sockets[1];
+ return true;
+
+cleanup:
+ if (handles[0] != kInvalidHandle)
+ (void) close(handles[0]);
+ if (handles[1] != kInvalidHandle)
+ (void) close(handles[1]);
+ delete tmp_sockets[0];
+ delete tmp_sockets[1];
+ return false;
+}
+
+bool SyncSocket::Close() {
+ if (handle_ == kInvalidHandle) {
+ return false;
+ }
+ int retval = close(handle_);
+ handle_ = kInvalidHandle;
+ return (retval == 0);
+}
+
+size_t SyncSocket::Send(const void* buffer, size_t length) {
+ DCHECK(length <= kMaxMessageLength);
+ const char* charbuffer = static_cast<const char*>(buffer);
+ int len = file_util::WriteFileDescriptor(handle_, charbuffer, length);
+ return static_cast<size_t>(len);
+}
+
+size_t SyncSocket::Receive(void* buffer, size_t length) {
+ DCHECK(length <= kMaxMessageLength);
+ char* charbuffer = static_cast<char*>(buffer);
+ if (file_util::ReadFromFD(handle_, charbuffer, length)) {
+ return length;
+ } else {
+ return -1;
+ }
+}
+
+} // namespace base