Skip to content

Commit

Permalink
Refactor unix domain socket.
Browse files Browse the repository at this point in the history
This is a pre-requisite for http server refactoring,
https://codereview.chromium.org/296053012/.

1) Define UnixDomainClientSocket and UnixDomainServerSocket utilizing
   SocketLibevent.
2) Rename UnixDomainSocket to UnixDomainListenSocket to reduce confusion.
3) unittests

BUG=371906

Review URL: https://codereview.chromium.org/376323002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@285148 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
byungchul@chromium.org committed Jul 24, 2014
1 parent 960cf13 commit 518c63a
Show file tree
Hide file tree
Showing 18 changed files with 1,348 additions and 395 deletions.
4 changes: 2 additions & 2 deletions android_webview/native/aw_dev_tools_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/user_agent.h"
#include "jni/AwDevToolsServer_jni.h"
#include "net/socket/unix_domain_socket_posix.h"
#include "net/socket/unix_domain_listen_socket_posix.h"

using content::DevToolsAgentHost;
using content::RenderViewHost;
Expand Down Expand Up @@ -176,7 +176,7 @@ void AwDevToolsServer::Start() {
return;

protocol_handler_ = content::DevToolsHttpHandler::Start(
new net::UnixDomainSocketWithAbstractNamespaceFactory(
new net::deprecated::UnixDomainListenSocketWithAbstractNamespaceFactory(
base::StringPrintf(kSocketNameFormat, getpid()),
"",
base::Bind(&content::CanUserConnectToDevTools)),
Expand Down
17 changes: 9 additions & 8 deletions chrome/browser/android/dev_tools_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
#include "content/public/common/user_agent.h"
#include "grit/browser_resources.h"
#include "jni/DevToolsServer_jni.h"
#include "net/socket/unix_domain_socket_posix.h"
#include "net/socket/unix_domain_listen_socket_posix.h"
#include "net/url_request/url_request_context_getter.h"
#include "ui/base/resource/resource_bundle.h"

Expand Down Expand Up @@ -366,12 +366,13 @@ class DevToolsServerDelegate : public content::DevToolsHttpHandlerDelegate {
std::string* name) OVERRIDE {
*name = base::StringPrintf(
kTetheringSocketName, getpid(), ++last_tethering_socket_);
return net::UnixDomainSocket::CreateAndListenWithAbstractNamespace(
*name,
"",
delegate,
base::Bind(&content::CanUserConnectToDevTools))
.PassAs<net::StreamListenSocket>();
return net::deprecated::UnixDomainListenSocket::
CreateAndListenWithAbstractNamespace(
*name,
"",
delegate,
base::Bind(&content::CanUserConnectToDevTools))
.PassAs<net::StreamListenSocket>();
}

private:
Expand Down Expand Up @@ -423,7 +424,7 @@ void DevToolsServer::Start() {
return;

protocol_handler_ = content::DevToolsHttpHandler::Start(
new net::UnixDomainSocketWithAbstractNamespaceFactory(
new net::deprecated::UnixDomainListenSocketWithAbstractNamespaceFactory(
socket_name_,
base::StringPrintf("%s_%d", socket_name_.c_str(), getpid()),
base::Bind(&content::CanUserConnectToDevTools)),
Expand Down
7 changes: 4 additions & 3 deletions content/shell/browser/shell_devtools_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

#if defined(OS_ANDROID)
#include "content/public/browser/android/devtools_auth.h"
#include "net/socket/unix_domain_socket_posix.h"
#include "net/socket/unix_domain_listen_socket_posix.h"
#endif

using content::DevToolsAgentHost;
Expand All @@ -52,8 +52,9 @@ net::StreamListenSocketFactory* CreateSocketFactory() {
socket_name = command_line.GetSwitchValueASCII(
switches::kRemoteDebuggingSocketName);
}
return new net::UnixDomainSocketWithAbstractNamespaceFactory(
socket_name, "", base::Bind(&content::CanUserConnectToDevTools));
return new net::deprecated::
UnixDomainListenSocketWithAbstractNamespaceFactory(
socket_name, "", base::Bind(&content::CanUserConnectToDevTools));
#else
// See if the user specified a port on the command line (useful for
// automation). If not, use an ephemeral port by specifying 0.
Expand Down
4 changes: 3 additions & 1 deletion net/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1297,7 +1297,9 @@ test("net_unittests") {
# The following tests are disabled because they don't apply to
# iOS.
# OS is not "linux" or "freebsd" or "openbsd".
"socket/unix_domain_socket_posix_unittest.cc",
"socket/unix_domain_client_socket_posix_unittest.cc",
"socket/unix_domain_listen_socket_posix_unittest.cc",
"socket/unix_domain_server_socket_posix_unittest.cc",

# See bug http://crbug.com/344533.
"disk_cache/blockfile/index_table_v3_unittest.cc",
Expand Down
4 changes: 3 additions & 1 deletion net/net.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,9 @@
# The following tests are disabled because they don't apply to
# iOS.
# OS is not "linux" or "freebsd" or "openbsd".
'socket/unix_domain_socket_posix_unittest.cc',
'socket/unix_domain_client_socket_posix_unittest.cc',
'socket/unix_domain_listen_socket_posix_unittest.cc',
'socket/unix_domain_server_socket_posix_unittest.cc',

# See bug http://crbug.com/344533.
'disk_cache/blockfile/index_table_v3_unittest.cc',
Expand Down
12 changes: 9 additions & 3 deletions net/net.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -990,8 +990,12 @@
'socket/tcp_socket_win.h',
'socket/transport_client_socket_pool.cc',
'socket/transport_client_socket_pool.h',
'socket/unix_domain_socket_posix.cc',
'socket/unix_domain_socket_posix.h',
'socket/unix_domain_client_socket_posix.cc',
'socket/unix_domain_client_socket_posix.h',
'socket/unix_domain_listen_socket_posix.cc',
'socket/unix_domain_listen_socket_posix.h',
'socket/unix_domain_server_socket_posix.cc',
'socket/unix_domain_server_socket_posix.h',
'socket/websocket_endpoint_lock_manager.cc',
'socket/websocket_endpoint_lock_manager.h',
'socket/websocket_transport_client_socket_pool.cc',
Expand Down Expand Up @@ -1571,7 +1575,9 @@
'socket/transport_client_socket_pool_test_util.h',
'socket/transport_client_socket_pool_unittest.cc',
'socket/transport_client_socket_unittest.cc',
'socket/unix_domain_socket_posix_unittest.cc',
'socket/unix_domain_client_socket_posix_unittest.cc',
'socket/unix_domain_listen_socket_posix_unittest.cc',
'socket/unix_domain_server_socket_posix_unittest.cc',
'socket/websocket_endpoint_lock_manager_unittest.cc',
'socket/websocket_transport_client_socket_pool_unittest.cc',
'socket_stream/socket_stream_metrics_unittest.cc',
Expand Down
162 changes: 162 additions & 0 deletions net/socket/unix_domain_client_socket_posix.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// 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 <sys/socket.h>
#include <sys/un.h>

#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
#include "net/socket/socket_libevent.h"

namespace net {

UnixDomainClientSocket::UnixDomainClientSocket(const std::string& socket_path,
bool use_abstract_namespace)
: socket_path_(socket_path),
use_abstract_namespace_(use_abstract_namespace) {
}

UnixDomainClientSocket::UnixDomainClientSocket(
scoped_ptr<SocketLibevent> socket)
: use_abstract_namespace_(false),
socket_(socket.Pass()) {
}

UnixDomainClientSocket::~UnixDomainClientSocket() {
Disconnect();
}

// static
bool UnixDomainClientSocket::FillAddress(const std::string& socket_path,
bool use_abstract_namespace,
SockaddrStorage* address) {
struct sockaddr_un* socket_addr =
reinterpret_cast<struct sockaddr_un*>(address->addr);
size_t path_max = address->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, address->addr_len);
socket_addr->sun_family = AF_UNIX;
address->addr_len = path_size + offsetof(struct sockaddr_un, sun_path);
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());
return true;
#else
return false;
#endif
}

int UnixDomainClientSocket::Connect(const CompletionCallback& callback) {
DCHECK(!socket_);

if (socket_path_.empty())
return ERR_ADDRESS_INVALID;

SockaddrStorage address;
if (!FillAddress(socket_path_, use_abstract_namespace_, &address))
return ERR_ADDRESS_INVALID;

socket_.reset(new SocketLibevent);
int rv = socket_->Open(AF_UNIX);
DCHECK_NE(ERR_IO_PENDING, rv);
if (rv != OK)
return rv;

return socket_->Connect(address, callback);
}

void UnixDomainClientSocket::Disconnect() {
socket_.reset();
}

bool UnixDomainClientSocket::IsConnected() const {
return socket_ && socket_->IsConnected();
}

bool UnixDomainClientSocket::IsConnectedAndIdle() const {
return socket_ && socket_->IsConnectedAndIdle();
}

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 net_log_;
}

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(socket_);
return socket_->Read(buf, buf_len, callback);
}

int UnixDomainClientSocket::Write(IOBuffer* buf, int buf_len,
const CompletionCallback& callback) {
DCHECK(socket_);
return socket_->Write(buf, buf_len, callback);
}

int UnixDomainClientSocket::SetReceiveBufferSize(int32 size) {
NOTIMPLEMENTED();
return ERR_NOT_IMPLEMENTED;
}

int UnixDomainClientSocket::SetSendBufferSize(int32 size) {
NOTIMPLEMENTED();
return ERR_NOT_IMPLEMENTED;
}

} // namespace net
79 changes: 79 additions & 0 deletions net/socket/unix_domain_client_socket_posix.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// 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.

#ifndef NET_SOCKET_UNIX_DOMAIN_CLIENT_SOCKET_POSIX_H_
#define NET_SOCKET_UNIX_DOMAIN_CLIENT_SOCKET_POSIX_H_

#include <string>

#include "base/basictypes.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
#include "net/base/net_log.h"
#include "net/socket/stream_socket.h"

namespace net {

class SocketLibevent;
struct SockaddrStorage;

// A client socket that uses unix domain socket as the transport layer.
class NET_EXPORT UnixDomainClientSocket : public StreamSocket {
public:
// Builds a client socket with |socket_path|. The caller should call Connect()
// to connect to a server socket.
UnixDomainClientSocket(const std::string& socket_path,
bool use_abstract_namespace);
// Builds a client socket with socket libevent which is already connected.
// UnixDomainServerSocket uses this after it accepts a connection.
explicit UnixDomainClientSocket(scoped_ptr<SocketLibevent> socket);

virtual ~UnixDomainClientSocket();

// Fills |address| with |socket_path| and its length. For Android or Linux
// platform, this supports abstract namespaces.
static bool FillAddress(const std::string& socket_path,
bool use_abstract_namespace,
SockaddrStorage* address);

// StreamSocket implementation.
virtual int Connect(const CompletionCallback& callback) OVERRIDE;
virtual void Disconnect() OVERRIDE;
virtual bool IsConnected() const OVERRIDE;
virtual bool IsConnectedAndIdle() const OVERRIDE;
virtual int GetPeerAddress(IPEndPoint* address) const OVERRIDE;
virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE;
virtual const BoundNetLog& NetLog() const OVERRIDE;
virtual void SetSubresourceSpeculation() OVERRIDE;
virtual void SetOmniboxSpeculation() OVERRIDE;
virtual bool WasEverUsed() const OVERRIDE;
virtual bool UsingTCPFastOpen() const OVERRIDE;
virtual bool WasNpnNegotiated() const OVERRIDE;
virtual NextProto GetNegotiatedProtocol() const OVERRIDE;
virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE;

// Socket implementation.
virtual int Read(IOBuffer* buf, int buf_len,
const CompletionCallback& callback) OVERRIDE;
virtual int Write(IOBuffer* buf, int buf_len,
const CompletionCallback& callback) OVERRIDE;
virtual int SetReceiveBufferSize(int32 size) OVERRIDE;
virtual int SetSendBufferSize(int32 size) OVERRIDE;

private:
const std::string socket_path_;
const bool use_abstract_namespace_;
scoped_ptr<SocketLibevent> socket_;
// This net log is just to comply StreamSocket::NetLog(). It throws away
// everything.
BoundNetLog net_log_;

DISALLOW_COPY_AND_ASSIGN(UnixDomainClientSocket);
};

} // namespace net

#endif // NET_SOCKET_UNIX_DOMAIN_CLIENT_SOCKET_POSIX_H_
Loading

0 comments on commit 518c63a

Please sign in to comment.