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

Unified Diff: net/socket/unix_domain_client_socket_posix.cc

Issue 296053012: Replace StreamListenSocket with StreamSocket in HttpServer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Don't export HttpServer which is built in a static lib Created 6 years, 6 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: net/socket/unix_domain_client_socket_posix.cc
diff --git a/net/socket/unix_domain_client_socket_posix.cc b/net/socket/unix_domain_client_socket_posix.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e75e6a28c6094ff48a60c805f021cc8d44812037
--- /dev/null
+++ b/net/socket/unix_domain_client_socket_posix.cc
@@ -0,0 +1,318 @@
+// Copyright 2014 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 "net/socket/unix_domain_client_socket_posix.h"
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/posix/eintr_wrapper.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/socket/stream_socket.h"
+
+namespace net {
+
+UnixDomainClientSocket::UnixDomainClientSocket(const std::string& socket_path,
+ bool use_abstract_namespace)
+ : socket_path_(socket_path),
+ use_abstract_namespace_(use_abstract_namespace),
+ socket_fd_(kInvalidSocket),
+ waiting_connect_(true),
+ read_buf_len_(0),
+ write_buf_len_(0) {
+}
+
+UnixDomainClientSocket::UnixDomainClientSocket(SocketDescriptor socket_fd)
+ : use_abstract_namespace_(false),
+ socket_fd_(socket_fd),
+ waiting_connect_(false),
+ read_buf_len_(0),
+ write_buf_len_(0) {
+}
+
+UnixDomainClientSocket::~UnixDomainClientSocket() {
+ Disconnect();
+}
+
+// static
+bool UnixDomainClientSocket::FillAddress(const std::string& socket_path,
+ bool use_abstract_namespace,
+ sockaddr_un* socket_addr,
+ socklen_t* addr_len) {
+ size_t path_max = *addr_len - offsetof(struct sockaddr_un, sun_path);
+ // Non abstract namespace pathname should be null-terminated. Abstract
+ // namespace pathname must start with '\0'. So, the size is always greater
+ // than socket_path size by 1.
+ size_t path_size = socket_path.size() + 1;
+ if (path_size > path_max)
+ return false;
+
+ memset(socket_addr, 0, *addr_len);
+ socket_addr->sun_family = AF_UNIX;
+ if (!use_abstract_namespace) {
+ memcpy(socket_addr->sun_path, socket_path.c_str(), socket_path.size());
+ return true;
+ }
+
+#if defined(OS_ANDROID) || defined(OS_LINUX)
+ // Convert the path given into abstract socket name. It must start with
+ // the '\0' character, so we are adding it. |addr_len| must specify the
+ // length of the structure exactly, as potentially the socket name may
+ // have '\0' characters embedded (although we don't support this).
+ // Note that addr.sun_path is already zero initialized.
+ memcpy(socket_addr->sun_path + 1, socket_path.c_str(), socket_path.size());
+ *addr_len = socket_path.size() + offsetof(struct sockaddr_un, sun_path) + 1;
+ return true;
+#else
+ return false;
+#endif
+}
+
+int UnixDomainClientSocket::Connect(const CompletionCallback& callback) {
mmenke 2014/06/11 16:05:50 DCHECK(waiting_connect_)?
byungchul 2014/06/20 08:22:32 Done.
+ if (IsConnected())
+ return ERR_SOCKET_IS_CONNECTED;
mmenke 2014/06/11 16:05:50 Should we DCHECK on this instead? (I know we don'
byungchul 2014/06/20 08:22:32 Done.
+
+ if (socket_path_.empty())
+ return ERR_ADDRESS_INVALID;
+
+ DCHECK(!callback.is_null());
+ DCHECK(write_callback_.is_null());
mmenke 2014/06/11 16:05:50 Move these up before the IsConnected check?
byungchul 2014/06/20 08:22:32 Done.
+
+ int rv = DoConnect();
+ if (rv != ERR_IO_PENDING) {
+ if (rv == OK)
+ waiting_connect_ = false;
+ return rv;
+ }
+
+ if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
+ socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
+ &write_socket_watcher_, this)) {
+ PLOG(ERROR) << "WatchFileDescriptor failed on write";
+ return MapSystemError(errno);
+ }
+
+ write_callback_ = callback;
+ return ERR_IO_PENDING;
+}
+
+int UnixDomainClientSocket::DoConnect() {
+ sockaddr_un addr;
+ socklen_t addr_len = sizeof(addr);
+ if (!FillAddress(socket_path_, use_abstract_namespace_, &addr, &addr_len))
+ return ERR_ADDRESS_INVALID;
+
+ if (socket_fd_ == kInvalidSocket) {
+ SocketDescriptor s = CreatePlatformSocket(PF_UNIX, SOCK_STREAM, 0);
+ if (s == kInvalidSocket)
+ return errno ? MapSystemError(errno) : ERR_UNEXPECTED;
+
+ if (SetNonBlocking(s)) {
+ int rv = MapSystemError(errno);
+ close(s);
+ return rv;
+ }
+
+ socket_fd_ = s;
+ }
+
+ int rv = HANDLE_EINTR(connect(socket_fd_,
+ reinterpret_cast<sockaddr*>(&addr),
+ addr_len));
+ DCHECK_LE(rv, 0);
+ return rv == 0 ? OK :
+ errno == EINPROGRESS ? ERR_IO_PENDING : MapSystemError(errno);
+}
+
+void UnixDomainClientSocket::DidCompleteConnect() {
+ // Get the error that connect() completed with.
+ int os_error = 0;
+ socklen_t len = sizeof(os_error);
+ if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) < 0)
+ os_error = errno;
+
+ int rv = MapSystemError(os_error);
+ if (rv == ERR_IO_PENDING)
+ return;
+
+ write_socket_watcher_.StopWatchingFileDescriptor();
+ waiting_connect_ = false;
+ base::ResetAndReturn(&write_callback_).Run(rv);
+}
+
+void UnixDomainClientSocket::Disconnect() {
+ if (socket_fd_ == kInvalidSocket)
+ return;
+ close(socket_fd_);
+ socket_fd_ = kInvalidSocket;
+}
+
+bool UnixDomainClientSocket::IsConnected() const {
+ return socket_fd_ != kInvalidSocket && !waiting_connect_;
+}
+
+bool UnixDomainClientSocket::IsConnectedAndIdle() const {
+ return IsConnected();
+}
+
+int UnixDomainClientSocket::GetPeerAddress(IPEndPoint* address) const {
+ NOTIMPLEMENTED();
+ return ERR_NOT_IMPLEMENTED;
+}
+
+int UnixDomainClientSocket::GetLocalAddress(IPEndPoint* address) const {
+ NOTIMPLEMENTED();
+ return ERR_NOT_IMPLEMENTED;
+}
+
+const BoundNetLog& UnixDomainClientSocket::NetLog() const {
+ return netlog_;
+}
+
+void UnixDomainClientSocket::SetSubresourceSpeculation() {
+}
+
+void UnixDomainClientSocket::SetOmniboxSpeculation() {
+}
+
+bool UnixDomainClientSocket::WasEverUsed() const {
+ return true; // We don't care.
+}
+
+bool UnixDomainClientSocket::UsingTCPFastOpen() const {
+ return false;
+}
+
+bool UnixDomainClientSocket::WasNpnNegotiated() const {
+ return false;
+}
+
+NextProto UnixDomainClientSocket::GetNegotiatedProtocol() const {
+ return kProtoUnknown;
+}
+
+bool UnixDomainClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
+ return false;
+}
+
+int UnixDomainClientSocket::Read(IOBuffer* buf, int buf_len,
+ const CompletionCallback& callback) {
+ DCHECK(buf);
+ DCHECK_LT(0, buf_len);
+ DCHECK(!callback.is_null());
+ DCHECK(read_callback_.is_null());
+
+ if (!IsConnected())
+ return ERR_SOCKET_NOT_CONNECTED;
+
+ int rv = DoRead(buf, buf_len);
+ if (rv != ERR_IO_PENDING)
+ return rv;
+
+ if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
+ socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
+ &read_socket_watcher_, this)) {
+ PLOG(ERROR) << "WatchFileDescriptor failed on read";
+ return MapSystemError(errno);
+ }
+
+ read_buf_ = buf;
+ read_buf_len_ = buf_len;
+ read_callback_ = callback;
+ return ERR_IO_PENDING;
+}
+
+int UnixDomainClientSocket::DoRead(IOBuffer* buf, int buf_len) {
+ int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
+ return rv >= 0 ? rv : MapSystemError(errno);
+}
+
+void UnixDomainClientSocket::DidCompleteRead() {
+ int rv = DoRead(read_buf_, read_buf_len_);
+ if (rv == ERR_IO_PENDING)
+ return;
+
+ read_socket_watcher_.StopWatchingFileDescriptor();
+ read_buf_ = NULL;
+ read_buf_len_ = 0;
+ base::ResetAndReturn(&read_callback_).Run(rv);
+}
+
+int UnixDomainClientSocket::Write(IOBuffer* buf, int buf_len,
+ const CompletionCallback& callback) {
+ DCHECK(buf);
+ DCHECK_LT(0, buf_len);
+ DCHECK(!callback.is_null());
+ DCHECK(write_callback_.is_null());
+
+ if (!IsConnected())
+ return ERR_SOCKET_NOT_CONNECTED;
+
+ int rv = DoWrite(buf, buf_len);
+ if (rv != ERR_IO_PENDING)
+ return rv;
+
+ if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
+ socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
+ &write_socket_watcher_, this)) {
+ PLOG(ERROR) << "WatchFileDescriptor failed on write";
+ return MapSystemError(errno);
+ }
+
+ write_buf_ = buf;
+ write_buf_len_ = buf_len;
+ write_callback_ = callback;
+ return ERR_IO_PENDING;
+}
+
+int UnixDomainClientSocket::DoWrite(IOBuffer* buf, int buf_len) {
+ int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
+ return rv >= 0 ? rv : MapSystemError(errno);
+}
+
+void UnixDomainClientSocket::DidCompleteWrite() {
mmenke 2014/06/11 16:05:50 This function seems to be misnamed (As is DidCompl
byungchul 2014/06/11 17:30:28 Per your request, will try to split this change in
mmenke 2014/06/11 17:53:27 Yea, makes sense. Hrm... Since TCPSocketLibevent
byungchul 2014/06/20 08:22:32 Done. Please review https://codereview.chromium.or
+ int rv = DoWrite(write_buf_, write_buf_len_);
+ if (rv == ERR_IO_PENDING)
+ return;
+
+ write_socket_watcher_.StopWatchingFileDescriptor();
+ write_buf_ = NULL;
+ write_buf_len_ = 0;
+ base::ResetAndReturn(&write_callback_).Run(rv);
+}
+
+int UnixDomainClientSocket::SetReceiveBufferSize(int32 size) {
+ NOTIMPLEMENTED();
+ return ERR_NOT_IMPLEMENTED;
+}
+
+int UnixDomainClientSocket::SetSendBufferSize(int32 size) {
+ NOTIMPLEMENTED();
+ return ERR_NOT_IMPLEMENTED;
+}
+
+void UnixDomainClientSocket::OnFileCanReadWithoutBlocking(int fd) {
+ if (read_callback_.is_null()) {
+ NOTREACHED();
+ } else {
+ DidCompleteRead();
+ }
+}
+
+void UnixDomainClientSocket::OnFileCanWriteWithoutBlocking(int fd) {
+ if (write_callback_.is_null()) {
+ NOTREACHED();
mmenke 2014/06/11 16:05:50 Shouldn't be handling this case, should just have
byungchul 2014/06/20 08:22:32 Done.
+ } else if (waiting_connect_) {
+ DidCompleteConnect();
+ } else {
+ DidCompleteWrite();
+ }
+}
+
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698