OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 "net/socket/unix_domain_client_socket_posix.h" | |
6 | |
7 #include <sys/socket.h> | |
8 #include <sys/un.h> | |
9 | |
10 #include "base/logging.h" | |
11 #include "base/posix/eintr_wrapper.h" | |
12 #include "net/base/ip_endpoint.h" | |
13 #include "net/base/net_errors.h" | |
14 #include "net/base/net_util.h" | |
15 #include "net/socket/socket_libevent.h" | |
16 | |
17 namespace net { | |
18 | |
19 UnixDomainClientSocket::UnixDomainClientSocket(const std::string& socket_path, | |
20 bool use_abstract_namespace) | |
21 : socket_path_(socket_path), | |
22 use_abstract_namespace_(use_abstract_namespace) { | |
23 } | |
24 | |
25 UnixDomainClientSocket::UnixDomainClientSocket( | |
26 scoped_ptr<SocketLibevent> socket) | |
27 : use_abstract_namespace_(false), | |
28 socket_(socket.Pass()) { | |
29 } | |
30 | |
31 UnixDomainClientSocket::~UnixDomainClientSocket() { | |
32 Disconnect(); | |
33 } | |
34 | |
35 // static | |
36 bool UnixDomainClientSocket::FillAddress(const std::string& socket_path, | |
37 bool use_abstract_namespace, | |
38 SockaddrStorage* address) { | |
39 struct sockaddr_un* socket_addr = | |
40 reinterpret_cast<struct sockaddr_un*>(address->addr); | |
41 size_t path_max = address->addr_len - offsetof(struct sockaddr_un, sun_path); | |
42 // Non abstract namespace pathname should be null-terminated. Abstract | |
43 // namespace pathname must start with '\0'. So, the size is always greater | |
44 // than socket_path size by 1. | |
45 size_t path_size = socket_path.size() + 1; | |
46 if (path_size > path_max) | |
47 return false; | |
48 | |
49 memset(socket_addr, 0, address->addr_len); | |
50 socket_addr->sun_family = AF_UNIX; | |
51 address->addr_len = path_size + offsetof(struct sockaddr_un, sun_path); | |
52 if (!use_abstract_namespace) { | |
53 memcpy(socket_addr->sun_path, socket_path.c_str(), socket_path.size()); | |
54 return true; | |
55 } | |
56 | |
57 #if defined(OS_ANDROID) || defined(OS_LINUX) | |
58 // Convert the path given into abstract socket name. It must start with | |
59 // the '\0' character, so we are adding it. |addr_len| must specify the | |
60 // length of the structure exactly, as potentially the socket name may | |
61 // have '\0' characters embedded (although we don't support this). | |
62 // Note that addr.sun_path is already zero initialized. | |
63 memcpy(socket_addr->sun_path + 1, socket_path.c_str(), socket_path.size()); | |
64 return true; | |
65 #else | |
66 return false; | |
67 #endif | |
68 } | |
69 | |
70 int UnixDomainClientSocket::Connect(const CompletionCallback& callback) { | |
71 DCHECK(!socket_); | |
72 | |
73 if (socket_path_.empty()) | |
74 return ERR_ADDRESS_INVALID; | |
75 | |
76 SockaddrStorage address; | |
77 if (!FillAddress(socket_path_, use_abstract_namespace_, &address)) | |
78 return ERR_ADDRESS_INVALID; | |
79 | |
80 socket_.reset(new SocketLibevent); | |
81 int rv = socket_->Open(AF_UNIX); | |
82 DCHECK_NE(ERR_IO_PENDING, rv); | |
83 if (rv != OK) | |
84 return rv; | |
85 | |
86 return socket_->Connect(address, callback); | |
87 } | |
88 | |
89 void UnixDomainClientSocket::Disconnect() { | |
90 socket_.reset(); | |
91 } | |
92 | |
93 bool UnixDomainClientSocket::IsConnected() const { | |
94 return socket_ && socket_->IsConnected(); | |
95 } | |
96 | |
97 bool UnixDomainClientSocket::IsConnectedAndIdle() const { | |
98 return socket_ && socket_->IsConnectedAndIdle(); | |
99 } | |
100 | |
101 int UnixDomainClientSocket::GetPeerAddress(IPEndPoint* address) const { | |
102 // Unix domain sockets have no valid associated addr/port; | |
103 // return either not connected or address invalid. | |
104 DCHECK(address); | |
105 | |
106 if (!IsConnected()) | |
107 return ERR_SOCKET_NOT_CONNECTED; | |
108 | |
109 return ERR_ADDRESS_INVALID; | |
110 } | |
111 | |
112 int UnixDomainClientSocket::GetLocalAddress(IPEndPoint* address) const { | |
113 // Unix domain sockets have no valid associated addr/port; | |
114 // return either not connected or address invalid. | |
115 DCHECK(address); | |
116 | |
117 if (!socket_) | |
118 return ERR_SOCKET_NOT_CONNECTED; | |
119 | |
120 return ERR_ADDRESS_INVALID; | |
121 } | |
122 | |
123 const BoundNetLog& UnixDomainClientSocket::NetLog() const { | |
124 return net_log_; | |
125 } | |
126 | |
127 void UnixDomainClientSocket::SetSubresourceSpeculation() { | |
128 } | |
129 | |
130 void UnixDomainClientSocket::SetOmniboxSpeculation() { | |
131 } | |
132 | |
133 bool UnixDomainClientSocket::WasEverUsed() const { | |
134 return true; // We don't care. | |
135 } | |
136 | |
137 bool UnixDomainClientSocket::UsingTCPFastOpen() const { | |
138 return false; | |
139 } | |
140 | |
141 bool UnixDomainClientSocket::WasNpnNegotiated() const { | |
142 return false; | |
143 } | |
144 | |
145 NextProto UnixDomainClientSocket::GetNegotiatedProtocol() const { | |
146 return kProtoUnknown; | |
147 } | |
148 | |
149 bool UnixDomainClientSocket::GetSSLInfo(SSLInfo* ssl_info) { | |
150 return false; | |
151 } | |
152 | |
153 int UnixDomainClientSocket::Read(IOBuffer* buf, int buf_len, | |
154 const CompletionCallback& callback) { | |
155 DCHECK(socket_); | |
156 return socket_->Read(buf, buf_len, callback); | |
157 } | |
158 | |
159 int UnixDomainClientSocket::Write(IOBuffer* buf, int buf_len, | |
160 const CompletionCallback& callback) { | |
161 DCHECK(socket_); | |
162 return socket_->Write(buf, buf_len, callback); | |
163 } | |
164 | |
165 int UnixDomainClientSocket::SetReceiveBufferSize(int32 size) { | |
166 NOTIMPLEMENTED(); | |
167 return ERR_NOT_IMPLEMENTED; | |
168 } | |
169 | |
170 int UnixDomainClientSocket::SetSendBufferSize(int32 size) { | |
171 NOTIMPLEMENTED(); | |
172 return ERR_NOT_IMPLEMENTED; | |
173 } | |
174 | |
175 SocketDescriptor UnixDomainClientSocket::ReleaseConnectedSocket() { | |
176 DCHECK(socket_); | |
177 DCHECK(socket_->IsConnected()); | |
178 | |
179 SocketDescriptor socket_fd = socket_->ReleaseConnectedSocket(); | |
180 socket_.reset(); | |
181 return socket_fd; | |
182 } | |
183 | |
184 } // namespace net | |
OLD | NEW |