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> |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 socket_ = -1; | 93 socket_ = -1; |
| 94 } | 94 } |
| 95 } | 95 } |
| 96 | 96 |
| 97 bool Socket::InitSocketInternal() { | 97 bool Socket::InitSocketInternal() { |
| 98 socket_ = socket(family_, SOCK_STREAM, 0); | 98 socket_ = socket(family_, SOCK_STREAM, 0); |
| 99 if (socket_ < 0) | 99 if (socket_ < 0) |
| 100 return false; | 100 return false; |
| 101 tools::DisableNagle(socket_); | 101 tools::DisableNagle(socket_); |
| 102 int reuse_addr = 1; | 102 int reuse_addr = 1; |
| 103 setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, | 103 setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, |
| 104 &reuse_addr, sizeof(reuse_addr)); | 104 sizeof(reuse_addr)); |
| 105 if (!SetNonBlocking()) | |
| 106 return false; | |
| 105 return true; | 107 return true; |
| 106 } | 108 } |
| 107 | 109 |
| 110 bool Socket::SetNonBlocking() { | |
| 111 const int flags = fcntl(socket_, F_GETFL); | |
| 112 if (flags < 0) { | |
| 113 PLOG(ERROR) << "fcntl"; | |
| 114 return false; | |
| 115 } | |
| 116 if (flags & O_NONBLOCK) | |
| 117 return true; | |
| 118 if (fcntl(socket_, F_SETFL, flags | O_NONBLOCK) < 0) { | |
| 119 PLOG(ERROR) << "fcntl"; | |
| 120 return false; | |
| 121 } | |
| 122 return true; | |
| 123 } | |
| 124 | |
| 108 bool Socket::InitUnixSocket(const std::string& path) { | 125 bool Socket::InitUnixSocket(const std::string& path) { |
| 109 static const size_t kPathMax = sizeof(addr_.addr_un.sun_path); | 126 static const size_t kPathMax = sizeof(addr_.addr_un.sun_path); |
| 110 // For abstract sockets we need one extra byte for the leading zero. | 127 // For abstract sockets we need one extra byte for the leading zero. |
| 111 if (path.size() + 2 /* '\0' */ > kPathMax) { | 128 if (path.size() + 2 /* '\0' */ > kPathMax) { |
| 112 LOG(ERROR) << "The provided path is too big to create a unix " | 129 LOG(ERROR) << "The provided path is too big to create a unix " |
| 113 << "domain socket: " << path; | 130 << "domain socket: " << path; |
| 114 return false; | 131 return false; |
| 115 } | 132 } |
| 116 family_ = PF_UNIX; | 133 family_ = PF_UNIX; |
| 117 addr_.addr_un.sun_family = family_; | 134 addr_.addr_un.sun_family = family_; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 167 addr_ptr = reinterpret_cast<sockaddr*>(&addr.addr4); | 184 addr_ptr = reinterpret_cast<sockaddr*>(&addr.addr4); |
| 168 port_ptr = &addr.addr4.sin_port; | 185 port_ptr = &addr.addr4.sin_port; |
| 169 addrlen = sizeof(addr.addr4); | 186 addrlen = sizeof(addr.addr4); |
| 170 } else if (family_ == AF_INET6) { | 187 } else if (family_ == AF_INET6) { |
| 171 addr_ptr = reinterpret_cast<sockaddr*>(&addr.addr6); | 188 addr_ptr = reinterpret_cast<sockaddr*>(&addr.addr6); |
| 172 port_ptr = &addr.addr6.sin6_port; | 189 port_ptr = &addr.addr6.sin6_port; |
| 173 addrlen = sizeof(addr.addr6); | 190 addrlen = sizeof(addr.addr6); |
| 174 } | 191 } |
| 175 errno = 0; | 192 errno = 0; |
| 176 if (getsockname(socket_, addr_ptr, &addrlen) != 0) { | 193 if (getsockname(socket_, addr_ptr, &addrlen) != 0) { |
| 177 LOG(ERROR) << "getsockname error: " << safe_strerror(errno);; | 194 PLOG(ERROR) << "getsockname"; |
| 178 SetSocketError(); | 195 SetSocketError(); |
| 179 return false; | 196 return false; |
| 180 } | 197 } |
| 181 port_ = ntohs(*port_ptr); | 198 port_ = ntohs(*port_ptr); |
| 182 } | 199 } |
| 183 return true; | 200 return true; |
| 184 } | 201 } |
| 185 | 202 |
| 186 bool Socket::Accept(Socket* new_socket) { | 203 bool Socket::Accept(Socket* new_socket) { |
| 187 DCHECK(new_socket != NULL); | 204 DCHECK(new_socket != NULL); |
| 188 if (!WaitForEvent(READ, kNoTimeout)) { | 205 if (!WaitForEvent(READ, kNoTimeout)) { |
| 189 SetSocketError(); | 206 SetSocketError(); |
| 190 return false; | 207 return false; |
| 191 } | 208 } |
| 192 errno = 0; | 209 errno = 0; |
| 193 int new_socket_fd = HANDLE_EINTR(accept(socket_, NULL, NULL)); | 210 int new_socket_fd = HANDLE_EINTR(accept(socket_, NULL, NULL)); |
| 194 if (new_socket_fd < 0) { | 211 if (new_socket_fd < 0) { |
| 195 SetSocketError(); | 212 SetSocketError(); |
| 196 return false; | 213 return false; |
| 197 } | 214 } |
| 198 | |
| 199 tools::DisableNagle(new_socket_fd); | 215 tools::DisableNagle(new_socket_fd); |
| 200 new_socket->socket_ = new_socket_fd; | 216 new_socket->socket_ = new_socket_fd; |
| 217 if (!new_socket->SetNonBlocking()) | |
| 218 return false; | |
| 201 return true; | 219 return true; |
| 202 } | 220 } |
| 203 | 221 |
| 204 bool Socket::Connect() { | 222 bool Socket::Connect() { |
| 205 // Set non-block because we use select for connect. | 223 DCHECK(fcntl(socket_, F_GETFL) & O_NONBLOCK); |
| 206 const int kFlags = fcntl(socket_, F_GETFL); | |
| 207 DCHECK(!(kFlags & O_NONBLOCK)); | |
| 208 fcntl(socket_, F_SETFL, kFlags | O_NONBLOCK); | |
| 209 errno = 0; | 224 errno = 0; |
| 210 if (HANDLE_EINTR(connect(socket_, addr_ptr_, addr_len_)) < 0 && | 225 if (HANDLE_EINTR(connect(socket_, addr_ptr_, addr_len_)) < 0 && |
| 211 errno != EINPROGRESS) { | 226 errno != EINPROGRESS) { |
| 212 SetSocketError(); | 227 SetSocketError(); |
| 213 PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); | |
| 214 return false; | 228 return false; |
| 215 } | 229 } |
| 216 // Wait for connection to complete, or receive a notification. | 230 // Wait for connection to complete, or receive a notification. |
| 217 if (!WaitForEvent(WRITE, kConnectTimeOut)) { | 231 if (!WaitForEvent(WRITE, kConnectTimeOut)) { |
| 218 SetSocketError(); | 232 SetSocketError(); |
| 219 PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); | |
| 220 return false; | 233 return false; |
| 221 } | 234 } |
| 222 int socket_errno; | 235 int socket_errno; |
| 223 socklen_t opt_len = sizeof(socket_errno); | 236 socklen_t opt_len = sizeof(socket_errno); |
| 224 if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &socket_errno, &opt_len) < 0) { | 237 if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &socket_errno, &opt_len) < 0) { |
| 225 LOG(ERROR) << "getsockopt(): " << safe_strerror(errno); | 238 PLOG(ERROR) << "getsockopt()"; |
| 226 SetSocketError(); | 239 SetSocketError(); |
| 227 PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); | |
| 228 return false; | 240 return false; |
| 229 } | 241 } |
| 230 if (socket_errno != 0) { | 242 if (socket_errno != 0) { |
| 231 LOG(ERROR) << "Could not connect to host: " << safe_strerror(socket_errno); | 243 LOG(ERROR) << "Could not connect to host: " << safe_strerror(socket_errno); |
| 232 SetSocketError(); | 244 SetSocketError(); |
| 233 PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); | |
| 234 return false; | 245 return false; |
| 235 } | 246 } |
| 236 fcntl(socket_, F_SETFL, kFlags); | |
| 237 return true; | 247 return true; |
| 238 } | 248 } |
| 239 | 249 |
| 240 bool Socket::Resolve(const std::string& host) { | 250 bool Socket::Resolve(const std::string& host) { |
| 241 struct addrinfo hints; | 251 struct addrinfo hints; |
| 242 struct addrinfo* res; | 252 struct addrinfo* res; |
| 243 memset(&hints, 0, sizeof(hints)); | 253 memset(&hints, 0, sizeof(hints)); |
| 244 hints.ai_family = AF_UNSPEC; | 254 hints.ai_family = AF_UNSPEC; |
| 245 hints.ai_socktype = SOCK_STREAM; | 255 hints.ai_socktype = SOCK_STREAM; |
| 246 hints.ai_flags |= AI_CANONNAME; | 256 hints.ai_flags |= AI_CANONNAME; |
| 247 | 257 |
| 248 int errcode = getaddrinfo(host.c_str(), NULL, &hints, &res); | 258 int errcode = getaddrinfo(host.c_str(), NULL, &hints, &res); |
| 249 if (errcode != 0) { | 259 if (errcode != 0) { |
| 260 errno = 0; | |
| 250 SetSocketError(); | 261 SetSocketError(); |
| 251 freeaddrinfo(res); | 262 freeaddrinfo(res); |
| 252 return false; | 263 return false; |
| 253 } | 264 } |
| 254 family_ = res->ai_family; | 265 family_ = res->ai_family; |
| 255 switch (res->ai_family) { | 266 switch (res->ai_family) { |
| 256 case AF_INET: | 267 case AF_INET: |
| 257 memcpy(&addr_.addr4, | 268 memcpy(&addr_.addr4, |
| 258 reinterpret_cast<sockaddr_in*>(res->ai_addr), | 269 reinterpret_cast<sockaddr_in*>(res->ai_addr), |
| 259 sizeof(sockaddr_in)); | 270 sizeof(sockaddr_in)); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 295 while (bytes_read < num_bytes && ret > 0) { | 306 while (bytes_read < num_bytes && ret > 0) { |
| 296 ret = Read(static_cast<char*>(buffer) + bytes_read, num_bytes - bytes_read); | 307 ret = Read(static_cast<char*>(buffer) + bytes_read, num_bytes - bytes_read); |
| 297 if (ret >= 0) | 308 if (ret >= 0) |
| 298 bytes_read += ret; | 309 bytes_read += ret; |
| 299 } | 310 } |
| 300 return bytes_read; | 311 return bytes_read; |
| 301 } | 312 } |
| 302 | 313 |
| 303 void Socket::SetSocketError() { | 314 void Socket::SetSocketError() { |
| 304 socket_error_ = true; | 315 socket_error_ = true; |
| 305 // We never use non-blocking socket. | 316 DCHECK_NE(EAGAIN, errno); |
| 306 DCHECK(errno != EAGAIN && errno != EWOULDBLOCK); | 317 DCHECK_NE(EWOULDBLOCK, errno); |
| 307 Close(); | 318 Close(); |
| 308 } | 319 } |
| 309 | 320 |
| 310 int Socket::Read(void* buffer, size_t buffer_size) { | 321 int Socket::Read(void* buffer, size_t buffer_size) { |
| 311 if (!WaitForEvent(READ, kNoTimeout)) { | 322 if (!WaitForEvent(READ, kNoTimeout)) { |
| 312 SetSocketError(); | 323 SetSocketError(); |
| 313 return 0; | 324 return 0; |
| 314 } | 325 } |
| 315 int ret = HANDLE_EINTR(read(socket_, buffer, buffer_size)); | 326 int ret = HANDLE_EINTR(read(socket_, buffer, buffer_size)); |
| 316 if (ret < 0) | 327 if (ret < 0) { |
| 328 PLOG(ERROR) << "read"; | |
| 317 SetSocketError(); | 329 SetSocketError(); |
| 330 } | |
| 331 return ret; | |
| 332 } | |
| 333 | |
| 334 int Socket::NonBlockingRead(void* buffer, size_t buffer_size) { | |
| 335 DCHECK(fcntl(socket_, F_GETFL) & O_NONBLOCK); | |
|
digit1
2013/11/13 10:28:42
I really like this DCHECK(), thanks :)
| |
| 336 int ret = HANDLE_EINTR(read(socket_, buffer, buffer_size)); | |
| 337 if (ret < 0) { | |
| 338 PLOG(ERROR) << "read"; | |
| 339 SetSocketError(); | |
| 340 } | |
| 318 return ret; | 341 return ret; |
| 319 } | 342 } |
| 320 | 343 |
| 321 int Socket::Write(const void* buffer, size_t count) { | 344 int Socket::Write(const void* buffer, size_t count) { |
| 345 if (!WaitForEvent(WRITE, kNoTimeout)) { | |
| 346 SetSocketError(); | |
| 347 return 0; | |
| 348 } | |
| 322 int ret = HANDLE_EINTR(send(socket_, buffer, count, MSG_NOSIGNAL)); | 349 int ret = HANDLE_EINTR(send(socket_, buffer, count, MSG_NOSIGNAL)); |
| 323 if (ret < 0) | 350 if (ret < 0) { |
| 351 PLOG(ERROR) << "send"; | |
| 324 SetSocketError(); | 352 SetSocketError(); |
| 353 } | |
| 325 return ret; | 354 return ret; |
| 326 } | 355 } |
| 327 | 356 |
| 357 int Socket::NonBlockingWrite(const void* buffer, size_t count) { | |
| 358 DCHECK(fcntl(socket_, F_GETFL) & O_NONBLOCK); | |
| 359 int ret = HANDLE_EINTR(send(socket_, buffer, count, MSG_NOSIGNAL)); | |
| 360 if (ret < 0) { | |
| 361 PLOG(ERROR) << "send"; | |
| 362 SetSocketError(); | |
| 363 } | |
| 364 return ret; | |
| 365 } | |
| 366 | |
| 328 int Socket::WriteString(const std::string& buffer) { | 367 int Socket::WriteString(const std::string& buffer) { |
| 329 return WriteNumBytes(buffer.c_str(), buffer.size()); | 368 return WriteNumBytes(buffer.c_str(), buffer.size()); |
| 330 } | 369 } |
| 331 | 370 |
| 332 void Socket::AddEventFd(int event_fd) { | 371 void Socket::AddEventFd(int event_fd) { |
| 333 Event event; | 372 Event event; |
| 334 event.fd = event_fd; | 373 event.fd = event_fd; |
| 335 event.was_fired = false; | 374 event.was_fired = false; |
| 336 events_.push_back(event); | 375 events_.push_back(event); |
| 337 } | 376 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 356 while (bytes_written < num_bytes && ret > 0) { | 395 while (bytes_written < num_bytes && ret > 0) { |
| 357 ret = Write(static_cast<const char*>(buffer) + bytes_written, | 396 ret = Write(static_cast<const char*>(buffer) + bytes_written, |
| 358 num_bytes - bytes_written); | 397 num_bytes - bytes_written); |
| 359 if (ret >= 0) | 398 if (ret >= 0) |
| 360 bytes_written += ret; | 399 bytes_written += ret; |
| 361 } | 400 } |
| 362 return bytes_written; | 401 return bytes_written; |
| 363 } | 402 } |
| 364 | 403 |
| 365 bool Socket::WaitForEvent(EventType type, int timeout_secs) { | 404 bool Socket::WaitForEvent(EventType type, int timeout_secs) { |
| 366 if (events_.empty() || socket_ == -1) | 405 if (socket_ == -1) |
| 367 return true; | 406 return true; |
| 407 DCHECK(fcntl(socket_, F_GETFL) & O_NONBLOCK); | |
| 368 fd_set read_fds; | 408 fd_set read_fds; |
| 369 fd_set write_fds; | 409 fd_set write_fds; |
| 370 FD_ZERO(&read_fds); | 410 FD_ZERO(&read_fds); |
| 371 FD_ZERO(&write_fds); | 411 FD_ZERO(&write_fds); |
| 372 if (type == READ) | 412 if (type == READ) |
| 373 FD_SET(socket_, &read_fds); | 413 FD_SET(socket_, &read_fds); |
| 374 else | 414 else |
| 375 FD_SET(socket_, &write_fds); | 415 FD_SET(socket_, &write_fds); |
| 376 for (size_t i = 0; i < events_.size(); ++i) | 416 for (size_t i = 0; i < events_.size(); ++i) |
| 377 FD_SET(events_[i].fd, &read_fds); | 417 FD_SET(events_[i].fd, &read_fds); |
| 378 timeval tv = {}; | 418 timeval tv = {}; |
| 379 timeval* tv_ptr = NULL; | 419 timeval* tv_ptr = NULL; |
| 380 if (timeout_secs > 0) { | 420 if (timeout_secs > 0) { |
| 381 tv.tv_sec = timeout_secs; | 421 tv.tv_sec = timeout_secs; |
| 382 tv.tv_usec = 0; | 422 tv.tv_usec = 0; |
| 383 tv_ptr = &tv; | 423 tv_ptr = &tv; |
| 384 } | 424 } |
| 385 int max_fd = socket_; | 425 int max_fd = socket_; |
| 386 for (size_t i = 0; i < events_.size(); ++i) | 426 for (size_t i = 0; i < events_.size(); ++i) |
| 387 if (events_[i].fd > max_fd) | 427 if (events_[i].fd > max_fd) |
| 388 max_fd = events_[i].fd; | 428 max_fd = events_[i].fd; |
| 389 if (HANDLE_EINTR( | 429 if (HANDLE_EINTR( |
| 390 select(max_fd + 1, &read_fds, &write_fds, NULL, tv_ptr)) <= 0) { | 430 select(max_fd + 1, &read_fds, &write_fds, NULL, tv_ptr)) <= 0) { |
| 431 PLOG(ERROR) << "select"; | |
| 391 return false; | 432 return false; |
| 392 } | 433 } |
| 393 bool event_was_fired = false; | 434 bool event_was_fired = false; |
| 394 for (size_t i = 0; i < events_.size(); ++i) { | 435 for (size_t i = 0; i < events_.size(); ++i) { |
| 395 if (FD_ISSET(events_[i].fd, &read_fds)) { | 436 if (FD_ISSET(events_[i].fd, &read_fds)) { |
| 396 events_[i].was_fired = true; | 437 events_[i].was_fired = true; |
| 397 event_was_fired = true; | 438 event_was_fired = true; |
| 398 } | 439 } |
| 399 } | 440 } |
| 400 return !event_was_fired; | 441 return !event_was_fired; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 413 ucred ucred; | 454 ucred ucred; |
| 414 socklen_t len = sizeof(ucred); | 455 socklen_t len = sizeof(ucred); |
| 415 if (getsockopt(socket.socket_, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) { | 456 if (getsockopt(socket.socket_, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) { |
| 416 CHECK_NE(ENOPROTOOPT, errno); | 457 CHECK_NE(ENOPROTOOPT, errno); |
| 417 return -1; | 458 return -1; |
| 418 } | 459 } |
| 419 return ucred.pid; | 460 return ucred.pid; |
| 420 } | 461 } |
| 421 | 462 |
| 422 } // namespace forwarder2 | 463 } // namespace forwarder2 |
| OLD | NEW |