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 |