Chromium Code Reviews| 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 |