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 |