OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "tools/android/forwarder2/socket.h" | 5 #include "tools/android/forwarder2/socket.h" |
6 | 6 |
7 #include <arpa/inet.h> | 7 #include <arpa/inet.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <netdb.h> | 9 #include <netdb.h> |
10 #include <netinet/in.h> | 10 #include <netinet/in.h> |
11 #include <stdio.h> | 11 #include <stdio.h> |
12 #include <string.h> | 12 #include <string.h> |
13 #include <sys/socket.h> | 13 #include <sys/socket.h> |
14 #include <sys/types.h> | 14 #include <sys/types.h> |
15 | 15 |
16 #include "base/eintr_wrapper.h" | 16 #include "base/eintr_wrapper.h" |
17 #include "base/logging.h" | 17 #include "base/logging.h" |
18 #include "base/safe_strerror_posix.h" | 18 #include "base/safe_strerror_posix.h" |
19 #include "tools/android/common/net.h" | 19 #include "tools/android/common/net.h" |
20 | 20 #include "tools/android/forwarder2/common.h" |
21 // This is used in Close and Shutdown. | |
22 // Preserving errno for Close() is important because the function is very often | |
23 // used in cleanup code, after an error occurred, and it is very easy to pass an | |
24 // invalid file descriptor to close() in this context, or more rarely, a | |
25 // spurious signal might make close() return -1 + setting errno to EINTR, | |
26 // masking the real reason for the original error. This leads to very unpleasant | |
27 // debugging sessions. | |
28 #define PRESERVE_ERRNO_HANDLE_EINTR(Func) \ | |
29 do { \ | |
30 int local_errno = errno; \ | |
31 (void) HANDLE_EINTR(Func); \ | |
32 errno = local_errno; \ | |
33 } while (false); | |
34 | |
35 | 21 |
36 namespace { | 22 namespace { |
37 const int kNoTimeout = -1; | 23 const int kNoTimeout = -1; |
38 const int kConnectTimeOut = 10; // Seconds. | 24 const int kConnectTimeOut = 10; // Seconds. |
39 | 25 |
40 bool FamilyIsTCP(int family) { | 26 bool FamilyIsTCP(int family) { |
41 return family == AF_INET || family == AF_INET6; | 27 return family == AF_INET || family == AF_INET6; |
42 } | 28 } |
43 } // namespace | 29 } // namespace |
44 | 30 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
81 } | 67 } |
82 | 68 |
83 Socket::Socket() | 69 Socket::Socket() |
84 : socket_(-1), | 70 : socket_(-1), |
85 port_(0), | 71 port_(0), |
86 socket_error_(false), | 72 socket_error_(false), |
87 family_(AF_INET), | 73 family_(AF_INET), |
88 abstract_(false), | 74 abstract_(false), |
89 addr_ptr_(reinterpret_cast<sockaddr*>(&addr_.addr4)), | 75 addr_ptr_(reinterpret_cast<sockaddr*>(&addr_.addr4)), |
90 addr_len_(sizeof(sockaddr)), | 76 addr_len_(sizeof(sockaddr)), |
91 exit_notifier_fd_(-1) { | 77 exit_notifier_fd_(-1), |
78 exited_(false) { | |
92 memset(&addr_, 0, sizeof(addr_)); | 79 memset(&addr_, 0, sizeof(addr_)); |
93 } | 80 } |
94 | 81 |
95 Socket::~Socket() { | 82 Socket::~Socket() { |
96 CHECK(IsClosed()); | 83 Close(); |
97 } | 84 } |
98 | 85 |
99 void Socket::Shutdown() { | 86 void Socket::Shutdown() { |
100 if (!IsClosed()) { | 87 if (!IsClosed()) { |
101 PRESERVE_ERRNO_HANDLE_EINTR(shutdown(socket_, SHUT_RDWR)); | 88 PRESERVE_ERRNO_HANDLE_EINTR(shutdown(socket_, SHUT_RDWR)); |
102 } | 89 } |
103 } | 90 } |
104 | 91 |
105 void Socket::Close() { | 92 void Socket::Close() { |
106 if (!IsClosed()) { | 93 if (!IsClosed()) { |
107 PRESERVE_ERRNO_HANDLE_EINTR(close(socket_)); | 94 CloseFD(socket_); |
108 socket_ = -1; | 95 socket_ = -1; |
109 } | 96 } |
110 } | 97 } |
111 | 98 |
112 bool Socket::InitSocketInternal() { | 99 bool Socket::InitSocketInternal() { |
113 socket_ = socket(family_, SOCK_STREAM, 0); | 100 socket_ = socket(family_, SOCK_STREAM, 0); |
114 if (socket_ < 0) | 101 if (socket_ < 0) |
115 return false; | 102 return false; |
116 tools::DisableNagle(socket_); | 103 tools::DisableNagle(socket_); |
117 int reuse_addr = 1; | 104 int reuse_addr = 1; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
235 SetSocketError(); | 222 SetSocketError(); |
236 PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); | 223 PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); |
237 return false; | 224 return false; |
238 } | 225 } |
239 // Wait for connection to complete, or receive a notification. | 226 // Wait for connection to complete, or receive a notification. |
240 if (!WaitForEvent(WRITE, kConnectTimeOut)) { | 227 if (!WaitForEvent(WRITE, kConnectTimeOut)) { |
241 SetSocketError(); | 228 SetSocketError(); |
242 PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); | 229 PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); |
243 return false; | 230 return false; |
244 } | 231 } |
245 // Disable non-block since our code assumes blocking semantics. | 232 int socket_errno; |
233 socklen_t opt_len = sizeof(socket_errno); | |
234 if (!getsockopt(socket_, SOL_SOCKET, SO_ERROR, &socket_errno, &opt_len) < 0) { | |
Nico
2013/07/02 01:07:22
The "!" here is wrong, right?
Philippe
2013/07/02 09:35:38
Yeah, good catch!
| |
235 LOG(ERROR) << "getsockopt(): " << safe_strerror(errno); | |
236 SetSocketError(); | |
237 PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); | |
238 return false; | |
239 } | |
240 if (socket_errno != 0) { | |
241 LOG(ERROR) << "Could not connect to host: " << safe_strerror(socket_errno); | |
242 SetSocketError(); | |
243 PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); | |
244 return false; | |
245 } | |
246 fcntl(socket_, F_SETFL, kFlags); | 246 fcntl(socket_, F_SETFL, kFlags); |
247 return true; | 247 return true; |
248 } | 248 } |
249 | 249 |
250 bool Socket::Resolve(const std::string& host) { | 250 bool Socket::Resolve(const std::string& host) { |
251 struct addrinfo hints; | 251 struct addrinfo hints; |
252 struct addrinfo* res; | 252 struct addrinfo* res; |
253 memset(&hints, 0, sizeof(hints)); | 253 memset(&hints, 0, sizeof(hints)); |
254 hints.ai_family = AF_UNSPEC; | 254 hints.ai_family = AF_UNSPEC; |
255 hints.ai_socktype = SOCK_STREAM; | 255 hints.ai_socktype = SOCK_STREAM; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
290 return FD_ISSET(socket_, &fds); | 290 return FD_ISSET(socket_, &fds); |
291 } | 291 } |
292 | 292 |
293 bool Socket::AddFdToSet(fd_set* fds) const { | 293 bool Socket::AddFdToSet(fd_set* fds) const { |
294 if (IsClosed()) | 294 if (IsClosed()) |
295 return false; | 295 return false; |
296 FD_SET(socket_, fds); | 296 FD_SET(socket_, fds); |
297 return true; | 297 return true; |
298 } | 298 } |
299 | 299 |
300 int Socket::ReadNumBytes(char* buffer, size_t num_bytes) { | 300 int Socket::ReadNumBytes(void* buffer, size_t num_bytes) { |
301 int bytes_read = 0; | 301 int bytes_read = 0; |
302 int ret = 1; | 302 int ret = 1; |
303 while (bytes_read < num_bytes && ret > 0) { | 303 while (bytes_read < num_bytes && ret > 0) { |
304 ret = Read(buffer + bytes_read, num_bytes - bytes_read); | 304 ret = Read(static_cast<char*>(buffer) + bytes_read, num_bytes - bytes_read); |
305 if (ret >= 0) | 305 if (ret >= 0) |
306 bytes_read += ret; | 306 bytes_read += ret; |
307 } | 307 } |
308 return bytes_read; | 308 return bytes_read; |
309 } | 309 } |
310 | 310 |
311 void Socket::SetSocketError() { | 311 void Socket::SetSocketError() { |
312 socket_error_ = true; | 312 socket_error_ = true; |
313 // We never use non-blocking socket. | 313 // We never use non-blocking socket. |
314 DCHECK(errno != EAGAIN && errno != EWOULDBLOCK); | 314 DCHECK(errno != EAGAIN && errno != EWOULDBLOCK); |
315 Close(); | 315 Close(); |
316 } | 316 } |
317 | 317 |
318 int Socket::Read(char* buffer, size_t buffer_size) { | 318 int Socket::Read(void* buffer, size_t buffer_size) { |
319 if (!WaitForEvent(READ, kNoTimeout)) { | 319 if (!WaitForEvent(READ, kNoTimeout)) { |
320 SetSocketError(); | 320 SetSocketError(); |
321 return 0; | 321 return 0; |
322 } | 322 } |
323 int ret = HANDLE_EINTR(read(socket_, buffer, buffer_size)); | 323 int ret = HANDLE_EINTR(read(socket_, buffer, buffer_size)); |
324 if (ret < 0) | 324 if (ret < 0) |
325 SetSocketError(); | 325 SetSocketError(); |
326 return ret; | 326 return ret; |
327 } | 327 } |
328 | 328 |
329 int Socket::Write(const char* buffer, size_t count) { | 329 int Socket::Write(const void* buffer, size_t count) { |
330 int ret = HANDLE_EINTR(send(socket_, buffer, count, MSG_NOSIGNAL)); | 330 int ret = HANDLE_EINTR(send(socket_, buffer, count, MSG_NOSIGNAL)); |
331 if (ret < 0) | 331 if (ret < 0) |
332 SetSocketError(); | 332 SetSocketError(); |
333 return ret; | 333 return ret; |
334 } | 334 } |
335 | 335 |
336 int Socket::WriteString(const std::string& buffer) { | 336 int Socket::WriteString(const std::string& buffer) { |
337 return WriteNumBytes(buffer.c_str(), buffer.size()); | 337 return WriteNumBytes(buffer.c_str(), buffer.size()); |
338 } | 338 } |
339 | 339 |
340 int Socket::WriteNumBytes(const char* buffer, size_t num_bytes) { | 340 int Socket::WriteNumBytes(const void* buffer, size_t num_bytes) { |
341 int bytes_written = 0; | 341 int bytes_written = 0; |
342 int ret = 1; | 342 int ret = 1; |
343 while (bytes_written < num_bytes && ret > 0) { | 343 while (bytes_written < num_bytes && ret > 0) { |
344 ret = Write(buffer + bytes_written, num_bytes - bytes_written); | 344 ret = Write(static_cast<const char*>(buffer) + bytes_written, |
345 num_bytes - bytes_written); | |
345 if (ret >= 0) | 346 if (ret >= 0) |
346 bytes_written += ret; | 347 bytes_written += ret; |
347 } | 348 } |
348 return bytes_written; | 349 return bytes_written; |
349 } | 350 } |
350 | 351 |
351 bool Socket::WaitForEvent(EventType type, int timeout_secs) const { | 352 bool Socket::WaitForEvent(EventType type, int timeout_secs) { |
352 if (exit_notifier_fd_ == -1 || socket_ == -1) | 353 if (exit_notifier_fd_ == -1 || socket_ == -1) |
353 return true; | 354 return true; |
354 const int nfds = std::max(socket_, exit_notifier_fd_) + 1; | 355 const int nfds = std::max(socket_, exit_notifier_fd_) + 1; |
355 fd_set read_fds; | 356 fd_set read_fds; |
356 fd_set write_fds; | 357 fd_set write_fds; |
357 FD_ZERO(&read_fds); | 358 FD_ZERO(&read_fds); |
358 FD_ZERO(&write_fds); | 359 FD_ZERO(&write_fds); |
359 if (type == READ) | 360 if (type == READ) |
360 FD_SET(socket_, &read_fds); | 361 FD_SET(socket_, &read_fds); |
361 else | 362 else |
362 FD_SET(socket_, &write_fds); | 363 FD_SET(socket_, &write_fds); |
363 FD_SET(exit_notifier_fd_, &read_fds); | 364 FD_SET(exit_notifier_fd_, &read_fds); |
364 | 365 |
365 timeval tv = {}; | 366 timeval tv = {}; |
366 timeval* tv_ptr = NULL; | 367 timeval* tv_ptr = NULL; |
367 if (timeout_secs > 0) { | 368 if (timeout_secs > 0) { |
368 tv.tv_sec = timeout_secs; | 369 tv.tv_sec = timeout_secs; |
369 tv.tv_usec = 0; | 370 tv.tv_usec = 0; |
370 tv_ptr = &tv; | 371 tv_ptr = &tv; |
371 } | 372 } |
372 if (HANDLE_EINTR(select(nfds, &read_fds, &write_fds, NULL, tv_ptr)) <= 0) | 373 if (HANDLE_EINTR(select(nfds, &read_fds, &write_fds, NULL, tv_ptr)) <= 0) |
373 return false; | 374 return false; |
374 return !FD_ISSET(exit_notifier_fd_, &read_fds); | 375 if (FD_ISSET(exit_notifier_fd_, &read_fds)) { |
376 exited_ = true; | |
377 return false; | |
378 } | |
379 return true; | |
375 } | 380 } |
376 | 381 |
377 // static | 382 // static |
378 int Socket::GetHighestFileDescriptor( | 383 int Socket::GetHighestFileDescriptor( |
379 const Socket& s1, const Socket& s2) { | 384 const Socket& s1, const Socket& s2) { |
380 return std::max(s1.socket_, s2.socket_); | 385 return std::max(s1.socket_, s2.socket_); |
381 } | 386 } |
382 | 387 |
383 } // namespace forwarder | 388 } // namespace forwarder |
OLD | NEW |