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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 122 // For abstract sockets we need one extra byte for the leading zero. | 122 // For abstract sockets we need one extra byte for the leading zero. |
| 123 if ((abstract && path.size() + 2 /* '\0' */ > kPathMax) || | 123 if ((abstract && path.size() + 2 /* '\0' */ > kPathMax) || |
| 124 (!abstract && path.size() + 1 /* '\0' */ > kPathMax)) { | 124 (!abstract && path.size() + 1 /* '\0' */ > kPathMax)) { |
| 125 LOG(ERROR) << "The provided path is too big to create a unix " | 125 LOG(ERROR) << "The provided path is too big to create a unix " |
| 126 << "domain socket: " << path; | 126 << "domain socket: " << path; |
| 127 return false; | 127 return false; |
| 128 } | 128 } |
| 129 abstract_ = abstract; | 129 abstract_ = abstract; |
| 130 family_ = PF_UNIX; | 130 family_ = PF_UNIX; |
| 131 addr_.addr_un.sun_family = family_; | 131 addr_.addr_un.sun_family = family_; |
| 132 | |
| 133 if (abstract) { | 132 if (abstract) { |
| 134 // Copied from net/base/unix_domain_socket_posix.cc | 133 // Copied from net/base/unix_domain_socket_posix.cc |
| 135 // Convert the path given into abstract socket name. It must start with | 134 // Convert the path given into abstract socket name. It must start with |
| 136 // the '\0' character, so we are adding it. |addr_len| must specify the | 135 // the '\0' character, so we are adding it. |addr_len| must specify the |
| 137 // length of the structure exactly, as potentially the socket name may | 136 // length of the structure exactly, as potentially the socket name may |
| 138 // have '\0' characters embedded (although we don't support this). | 137 // have '\0' characters embedded (although we don't support this). |
| 139 // Note that addr_.addr_un.sun_path is already zero initialized. | 138 // Note that addr_.addr_un.sun_path is already zero initialized. |
| 140 memcpy(addr_.addr_un.sun_path + 1, path.c_str(), path.size()); | 139 memcpy(addr_.addr_un.sun_path + 1, path.c_str(), path.size()); |
| 141 addr_len_ = path.size() + offsetof(struct sockaddr_un, sun_path) + 1; | 140 addr_len_ = path.size() + offsetof(struct sockaddr_un, sun_path) + 1; |
| 142 } else { | 141 } else { |
| 143 memcpy(addr_.addr_un.sun_path, path.c_str(), path.size()); | 142 memcpy(addr_.addr_un.sun_path, path.c_str(), path.size()); |
| 144 addr_len_ = sizeof(sockaddr_un); | 143 addr_len_ = sizeof(sockaddr_un); |
| 145 } | 144 } |
| 146 | |
| 147 addr_ptr_ = reinterpret_cast<sockaddr*>(&addr_.addr_un); | 145 addr_ptr_ = reinterpret_cast<sockaddr*>(&addr_.addr_un); |
| 148 return InitSocketInternal(); | 146 return InitSocketInternal(); |
| 149 } | 147 } |
| 150 | 148 |
| 151 bool Socket::InitTcpSocket(const std::string& host, int port) { | 149 bool Socket::InitTcpSocket(const std::string& host, int port) { |
| 152 port_ = port; | 150 port_ = port; |
| 153 | |
| 154 if (host.empty()) { | 151 if (host.empty()) { |
| 155 // Use localhost: INADDR_LOOPBACK | 152 // Use localhost: INADDR_LOOPBACK |
| 156 family_ = AF_INET; | 153 family_ = AF_INET; |
| 157 addr_.addr4.sin_family = family_; | 154 addr_.addr4.sin_family = family_; |
| 158 addr_.addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | 155 addr_.addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 159 } else if (!Resolve(host)) { | 156 } else if (!Resolve(host)) { |
| 160 return false; | 157 return false; |
| 161 } | 158 } |
| 162 CHECK(family_ == AF_INET || family_ == AF_INET6) | 159 CHECK(family_ == AF_INET || family_ == AF_INET6) |
| 163 << "Invalid socket family."; | 160 << "Invalid socket family."; |
| 164 if (family_ == AF_INET) { | 161 if (family_ == AF_INET) { |
| 165 addr_.addr4.sin_port = htons(port_); | 162 addr_.addr4.sin_port = htons(port_); |
| 166 addr_ptr_ = reinterpret_cast<sockaddr*>(&addr_.addr4); | 163 addr_ptr_ = reinterpret_cast<sockaddr*>(&addr_.addr4); |
| 167 addr_len_ = sizeof(addr_.addr4); | 164 addr_len_ = sizeof(addr_.addr4); |
| 168 } else if (family_ == AF_INET6) { | 165 } else if (family_ == AF_INET6) { |
| 169 addr_.addr6.sin6_port = htons(port_); | 166 addr_.addr6.sin6_port = htons(port_); |
| 170 addr_ptr_ = reinterpret_cast<sockaddr*>(&addr_.addr6); | 167 addr_ptr_ = reinterpret_cast<sockaddr*>(&addr_.addr6); |
| 171 addr_len_ = sizeof(addr_.addr6); | 168 addr_len_ = sizeof(addr_.addr6); |
| 172 } | 169 } |
| 173 return InitSocketInternal(); | 170 return InitSocketInternal(); |
| 174 } | 171 } |
| 175 | 172 |
| 176 bool Socket::BindAndListen() { | 173 bool Socket::BindAndListen() { |
| 177 errno = 0; | 174 errno = 0; |
| 178 if (HANDLE_EINTR(bind(socket_, addr_ptr_, addr_len_)) < 0 || | 175 if (HANDLE_EINTR(bind(socket_, addr_ptr_, addr_len_)) < 0 || |
| 179 HANDLE_EINTR(listen(socket_, 5)) < 0) { | 176 HANDLE_EINTR(listen(socket_, 5)) < 0) { |
| 180 SetSocketError(); | 177 SetSocketError(); |
| 181 return false; | 178 return false; |
| 182 } | 179 } |
| 183 if (port_ == 0) { | 180 if (port_ == 0 && (family_ == AF_INET || family_ == AF_INET6)) { |
|
Philippe
2012/09/26 00:15:46
Nit: I think that this could be factored out into
felipeg
2012/09/26 00:34:28
Done.
| |
| 184 SockAddr addr; | 181 SockAddr addr; |
| 185 memset(&addr, 0, sizeof(addr)); | 182 memset(&addr, 0, sizeof(addr)); |
| 186 socklen_t addrlen = 0; | 183 socklen_t addrlen = 0; |
| 187 sockaddr* addr_ptr = NULL; | 184 sockaddr* addr_ptr = NULL; |
| 188 uint16* port_ptr = NULL; | 185 uint16* port_ptr = NULL; |
| 189 if (family_ == AF_INET) { | 186 if (family_ == AF_INET) { |
| 190 addr_ptr = reinterpret_cast<sockaddr*>(&addr.addr4); | 187 addr_ptr = reinterpret_cast<sockaddr*>(&addr.addr4); |
| 191 port_ptr = &addr.addr4.sin_port; | 188 port_ptr = &addr.addr4.sin_port; |
| 192 addrlen = sizeof(addr.addr4); | 189 addrlen = sizeof(addr.addr4); |
| 193 } else if (family_ == AF_INET6) { | 190 } else if (family_ == AF_INET6) { |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 218 SetSocketError(); | 215 SetSocketError(); |
| 219 return false; | 216 return false; |
| 220 } | 217 } |
| 221 | 218 |
| 222 tools::DisableNagle(new_socket_fd); | 219 tools::DisableNagle(new_socket_fd); |
| 223 new_socket->socket_ = new_socket_fd; | 220 new_socket->socket_ = new_socket_fd; |
| 224 return true; | 221 return true; |
| 225 } | 222 } |
| 226 | 223 |
| 227 bool Socket::Connect() { | 224 bool Socket::Connect() { |
| 228 // Set non-block because we use select. | 225 // Set non-block because we use select for connect. |
| 229 fcntl(socket_, F_SETFL, fcntl(socket_, F_GETFL) | O_NONBLOCK); | 226 fcntl(socket_, F_SETFL, fcntl(socket_, F_GETFL) | O_NONBLOCK); |
|
Philippe
2012/09/26 00:15:46
Nit: maybe store the result of fcntl() into a cons
felipeg
2012/09/26 00:34:28
Done.
| |
| 230 errno = 0; | 227 errno = 0; |
| 231 if (HANDLE_EINTR(connect(socket_, addr_ptr_, addr_len_)) < 0 && | 228 if (HANDLE_EINTR(connect(socket_, addr_ptr_, addr_len_)) < 0 && |
| 232 errno != EINPROGRESS) { | 229 errno != EINPROGRESS) { |
| 233 SetSocketError(); | 230 SetSocketError(); |
| 234 return false; | 231 return false; |
|
digit1
2012/09/26 00:19:04
you should restore the flags before returning.
Philippe
2012/09/26 00:30:10
Good point.
This might be a good opportunity to u
felipeg
2012/09/26 00:34:28
Done.
| |
| 235 } | 232 } |
| 236 // Wait for connection to complete, or receive a notification. | 233 // Wait for connection to complete, or receive a notification. |
| 237 if (!WaitForEvent(WRITE, kConnectTimeOut)) { | 234 if (!WaitForEvent(WRITE, kConnectTimeOut)) { |
| 238 SetSocketError(); | 235 SetSocketError(); |
| 239 return false; | 236 return false; |
| 240 } | 237 } |
| 238 // Disable non-block since our code assumes blocking semantics. | |
| 239 fcntl(socket_, F_SETFL, fcntl(socket_, F_GETFL) & ~O_NONBLOCK); | |
|
digit1
2012/09/26 00:19:04
I agree with Philippe that this kind of assumption
felipeg
2012/09/26 00:34:28
Done.
| |
| 241 return true; | 240 return true; |
| 242 } | 241 } |
| 243 | 242 |
| 244 bool Socket::Resolve(const std::string& host) { | 243 bool Socket::Resolve(const std::string& host) { |
| 245 struct addrinfo hints; | 244 struct addrinfo hints; |
| 246 struct addrinfo* res; | 245 struct addrinfo* res; |
| 247 memset(&hints, 0, sizeof(hints)); | 246 memset(&hints, 0, sizeof(hints)); |
| 248 hints.ai_family = AF_UNSPEC; | 247 hints.ai_family = AF_UNSPEC; |
| 249 hints.ai_socktype = SOCK_STREAM; | 248 hints.ai_socktype = SOCK_STREAM; |
| 250 hints.ai_flags |= AI_CANONNAME; | 249 hints.ai_flags |= AI_CANONNAME; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 368 return !FD_ISSET(exit_notifier_fd_, &read_fds); | 367 return !FD_ISSET(exit_notifier_fd_, &read_fds); |
| 369 } | 368 } |
| 370 | 369 |
| 371 // static | 370 // static |
| 372 int Socket::GetHighestFileDescriptor( | 371 int Socket::GetHighestFileDescriptor( |
| 373 const Socket& s1, const Socket& s2) { | 372 const Socket& s1, const Socket& s2) { |
| 374 return std::max(s1.socket_, s2.socket_); | 373 return std::max(s1.socket_, s2.socket_); |
| 375 } | 374 } |
| 376 | 375 |
| 377 } // namespace forwarder | 376 } // namespace forwarder |
| OLD | NEW |