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

Side by Side 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 unified diff | Download patch
OLDNEW
(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 <errno.h>
8 #include <sys/socket.h>
9 #include <unistd.h>
10
11 #include "base/callback.h"
12 #include "base/callback_helpers.h"
13 #include "base/posix/eintr_wrapper.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/net_errors.h"
16 #include "net/base/net_util.h"
17 #include "net/socket/stream_socket.h"
18
19 namespace net {
20
21 UnixDomainClientSocket::UnixDomainClientSocket(const std::string& socket_path,
22 bool use_abstract_namespace)
23 : socket_path_(socket_path),
24 use_abstract_namespace_(use_abstract_namespace),
25 socket_fd_(kInvalidSocket),
26 waiting_connect_(true),
27 read_buf_len_(0),
28 write_buf_len_(0) {
29 }
30
31 UnixDomainClientSocket::UnixDomainClientSocket(SocketDescriptor socket_fd)
32 : use_abstract_namespace_(false),
33 socket_fd_(socket_fd),
34 waiting_connect_(false),
35 read_buf_len_(0),
36 write_buf_len_(0) {
37 }
38
39 UnixDomainClientSocket::~UnixDomainClientSocket() {
40 Disconnect();
41 }
42
43 // static
44 bool UnixDomainClientSocket::FillAddress(const std::string& socket_path,
45 bool use_abstract_namespace,
46 sockaddr_un* socket_addr,
47 socklen_t* addr_len) {
48 size_t path_max = *addr_len - offsetof(struct sockaddr_un, sun_path);
49 // Non abstract namespace pathname should be null-terminated. Abstract
50 // namespace pathname must start with '\0'. So, the size is always greater
51 // than socket_path size by 1.
52 size_t path_size = socket_path.size() + 1;
53 if (path_size > path_max)
54 return false;
55
56 memset(socket_addr, 0, *addr_len);
57 socket_addr->sun_family = AF_UNIX;
58 if (!use_abstract_namespace) {
59 memcpy(socket_addr->sun_path, socket_path.c_str(), socket_path.size());
60 return true;
61 }
62
63 #if defined(OS_ANDROID) || defined(OS_LINUX)
64 // Convert the path given into abstract socket name. It must start with
65 // the '\0' character, so we are adding it. |addr_len| must specify the
66 // length of the structure exactly, as potentially the socket name may
67 // have '\0' characters embedded (although we don't support this).
68 // Note that addr.sun_path is already zero initialized.
69 memcpy(socket_addr->sun_path + 1, socket_path.c_str(), socket_path.size());
70 *addr_len = socket_path.size() + offsetof(struct sockaddr_un, sun_path) + 1;
71 return true;
72 #else
73 return false;
74 #endif
75 }
76
77 int UnixDomainClientSocket::Connect(const CompletionCallback& callback) {
mmenke 2014/06/11 16:05:50 DCHECK(waiting_connect_)?
byungchul 2014/06/20 08:22:32 Done.
78 if (IsConnected())
79 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.
80
81 if (socket_path_.empty())
82 return ERR_ADDRESS_INVALID;
83
84 DCHECK(!callback.is_null());
85 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.
86
87 int rv = DoConnect();
88 if (rv != ERR_IO_PENDING) {
89 if (rv == OK)
90 waiting_connect_ = false;
91 return rv;
92 }
93
94 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
95 socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
96 &write_socket_watcher_, this)) {
97 PLOG(ERROR) << "WatchFileDescriptor failed on write";
98 return MapSystemError(errno);
99 }
100
101 write_callback_ = callback;
102 return ERR_IO_PENDING;
103 }
104
105 int UnixDomainClientSocket::DoConnect() {
106 sockaddr_un addr;
107 socklen_t addr_len = sizeof(addr);
108 if (!FillAddress(socket_path_, use_abstract_namespace_, &addr, &addr_len))
109 return ERR_ADDRESS_INVALID;
110
111 if (socket_fd_ == kInvalidSocket) {
112 SocketDescriptor s = CreatePlatformSocket(PF_UNIX, SOCK_STREAM, 0);
113 if (s == kInvalidSocket)
114 return errno ? MapSystemError(errno) : ERR_UNEXPECTED;
115
116 if (SetNonBlocking(s)) {
117 int rv = MapSystemError(errno);
118 close(s);
119 return rv;
120 }
121
122 socket_fd_ = s;
123 }
124
125 int rv = HANDLE_EINTR(connect(socket_fd_,
126 reinterpret_cast<sockaddr*>(&addr),
127 addr_len));
128 DCHECK_LE(rv, 0);
129 return rv == 0 ? OK :
130 errno == EINPROGRESS ? ERR_IO_PENDING : MapSystemError(errno);
131 }
132
133 void UnixDomainClientSocket::DidCompleteConnect() {
134 // Get the error that connect() completed with.
135 int os_error = 0;
136 socklen_t len = sizeof(os_error);
137 if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) < 0)
138 os_error = errno;
139
140 int rv = MapSystemError(os_error);
141 if (rv == ERR_IO_PENDING)
142 return;
143
144 write_socket_watcher_.StopWatchingFileDescriptor();
145 waiting_connect_ = false;
146 base::ResetAndReturn(&write_callback_).Run(rv);
147 }
148
149 void UnixDomainClientSocket::Disconnect() {
150 if (socket_fd_ == kInvalidSocket)
151 return;
152 close(socket_fd_);
153 socket_fd_ = kInvalidSocket;
154 }
155
156 bool UnixDomainClientSocket::IsConnected() const {
157 return socket_fd_ != kInvalidSocket && !waiting_connect_;
158 }
159
160 bool UnixDomainClientSocket::IsConnectedAndIdle() const {
161 return IsConnected();
162 }
163
164 int UnixDomainClientSocket::GetPeerAddress(IPEndPoint* address) const {
165 NOTIMPLEMENTED();
166 return ERR_NOT_IMPLEMENTED;
167 }
168
169 int UnixDomainClientSocket::GetLocalAddress(IPEndPoint* address) const {
170 NOTIMPLEMENTED();
171 return ERR_NOT_IMPLEMENTED;
172 }
173
174 const BoundNetLog& UnixDomainClientSocket::NetLog() const {
175 return netlog_;
176 }
177
178 void UnixDomainClientSocket::SetSubresourceSpeculation() {
179 }
180
181 void UnixDomainClientSocket::SetOmniboxSpeculation() {
182 }
183
184 bool UnixDomainClientSocket::WasEverUsed() const {
185 return true; // We don't care.
186 }
187
188 bool UnixDomainClientSocket::UsingTCPFastOpen() const {
189 return false;
190 }
191
192 bool UnixDomainClientSocket::WasNpnNegotiated() const {
193 return false;
194 }
195
196 NextProto UnixDomainClientSocket::GetNegotiatedProtocol() const {
197 return kProtoUnknown;
198 }
199
200 bool UnixDomainClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
201 return false;
202 }
203
204 int UnixDomainClientSocket::Read(IOBuffer* buf, int buf_len,
205 const CompletionCallback& callback) {
206 DCHECK(buf);
207 DCHECK_LT(0, buf_len);
208 DCHECK(!callback.is_null());
209 DCHECK(read_callback_.is_null());
210
211 if (!IsConnected())
212 return ERR_SOCKET_NOT_CONNECTED;
213
214 int rv = DoRead(buf, buf_len);
215 if (rv != ERR_IO_PENDING)
216 return rv;
217
218 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
219 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
220 &read_socket_watcher_, this)) {
221 PLOG(ERROR) << "WatchFileDescriptor failed on read";
222 return MapSystemError(errno);
223 }
224
225 read_buf_ = buf;
226 read_buf_len_ = buf_len;
227 read_callback_ = callback;
228 return ERR_IO_PENDING;
229 }
230
231 int UnixDomainClientSocket::DoRead(IOBuffer* buf, int buf_len) {
232 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
233 return rv >= 0 ? rv : MapSystemError(errno);
234 }
235
236 void UnixDomainClientSocket::DidCompleteRead() {
237 int rv = DoRead(read_buf_, read_buf_len_);
238 if (rv == ERR_IO_PENDING)
239 return;
240
241 read_socket_watcher_.StopWatchingFileDescriptor();
242 read_buf_ = NULL;
243 read_buf_len_ = 0;
244 base::ResetAndReturn(&read_callback_).Run(rv);
245 }
246
247 int UnixDomainClientSocket::Write(IOBuffer* buf, int buf_len,
248 const CompletionCallback& callback) {
249 DCHECK(buf);
250 DCHECK_LT(0, buf_len);
251 DCHECK(!callback.is_null());
252 DCHECK(write_callback_.is_null());
253
254 if (!IsConnected())
255 return ERR_SOCKET_NOT_CONNECTED;
256
257 int rv = DoWrite(buf, buf_len);
258 if (rv != ERR_IO_PENDING)
259 return rv;
260
261 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
262 socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
263 &write_socket_watcher_, this)) {
264 PLOG(ERROR) << "WatchFileDescriptor failed on write";
265 return MapSystemError(errno);
266 }
267
268 write_buf_ = buf;
269 write_buf_len_ = buf_len;
270 write_callback_ = callback;
271 return ERR_IO_PENDING;
272 }
273
274 int UnixDomainClientSocket::DoWrite(IOBuffer* buf, int buf_len) {
275 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
276 return rv >= 0 ? rv : MapSystemError(errno);
277 }
278
279 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
280 int rv = DoWrite(write_buf_, write_buf_len_);
281 if (rv == ERR_IO_PENDING)
282 return;
283
284 write_socket_watcher_.StopWatchingFileDescriptor();
285 write_buf_ = NULL;
286 write_buf_len_ = 0;
287 base::ResetAndReturn(&write_callback_).Run(rv);
288 }
289
290 int UnixDomainClientSocket::SetReceiveBufferSize(int32 size) {
291 NOTIMPLEMENTED();
292 return ERR_NOT_IMPLEMENTED;
293 }
294
295 int UnixDomainClientSocket::SetSendBufferSize(int32 size) {
296 NOTIMPLEMENTED();
297 return ERR_NOT_IMPLEMENTED;
298 }
299
300 void UnixDomainClientSocket::OnFileCanReadWithoutBlocking(int fd) {
301 if (read_callback_.is_null()) {
302 NOTREACHED();
303 } else {
304 DidCompleteRead();
305 }
306 }
307
308 void UnixDomainClientSocket::OnFileCanWriteWithoutBlocking(int fd) {
309 if (write_callback_.is_null()) {
310 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.
311 } else if (waiting_connect_) {
312 DidCompleteConnect();
313 } else {
314 DidCompleteWrite();
315 }
316 }
317
318 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698