Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Side by Side Diff: tools/android/forwarder2/socket.cc

Issue 10918057: Add forwarder2 (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/android/forwarder2/socket.h ('k') | tools/android/forwarder2/thread.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "tools/android/forwarder2/socket.h"
6
7 #include <arpa/inet.h>
8 #include <fcntl.h>
9 #include <netdb.h>
10 #include <netinet/in.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <sys/socket.h>
14 #include <sys/types.h>
15
16 #include "base/eintr_wrapper.h"
17 #include "base/logging.h"
18 #include "base/safe_strerror_posix.h"
19 #include "tools/android/common/net.h"
20
21 #define PRESERVE_ERRNO_HANDLE_EINTR(Func) \
22 do { \
23 int local_errno = errno; \
24 (void) HANDLE_EINTR(Func); \
25 errno = local_errno; \
26 } while (false);
27
28 namespace forwarder {
29
30 bool Socket::BindUnix(const string& path, bool abstract) {
31 errno = 0;
32 if (!InitUnixSocket(path, abstract) || !BindAndListen()) {
33 Close();
34 return false;
35 }
36 return true;
37 }
38
39 bool Socket::BindTcp(const string& host, int port) {
40 errno = 0;
41 if (!InitTcpSocket(host, port) || !BindAndListen()) {
42 Close();
43 return false;
44 }
45 return true;
46 }
47
48 bool Socket::ConnectUnix(const string& path, bool abstract) {
49 errno = 0;
50 if (!InitUnixSocket(path, abstract) || !Connect()) {
51 Close();
52 return false;
53 }
54 return true;
55 }
56
57 bool Socket::ConnectTcp(const string& host, int port) {
58 errno = 0;
59 if (!InitTcpSocket(host, port) || !Connect()) {
60 Close();
61 return false;
62 }
63 return true;
64 }
65
66 Socket::Socket()
67 : socket_(-1),
68 port_(0),
69 socket_error_(false),
70 family_(AF_INET),
71 abstract_(false),
72 addr_ptr_(reinterpret_cast<sockaddr*>(&addr_.addr4)),
73 addr_len_(sizeof(sockaddr)),
74 exit_notifier_fd_(-1) {
75 memset(&addr_, 0, sizeof(addr_));
76 }
77
78 Socket::~Socket() {
79 CHECK(IsClosed());
80 }
81
82 void Socket::Shutdown() {
83 if (!IsClosed()) {
84 // Preserving the errno in case we are trying to shutdown a socket that
85 // already had an error.
86 PRESERVE_ERRNO_HANDLE_EINTR(shutdown(socket_, SHUT_RDWR));
87 }
88 }
89
90 void Socket::Close() {
91 if (!IsClosed()) {
92 PRESERVE_ERRNO_HANDLE_EINTR(close(socket_));
93 socket_ = -1;
94 }
95 }
96
97 bool Socket::InitSocketInternal() {
98 socket_ = socket(family_, SOCK_STREAM, 0);
99 if (socket_ < 0)
100 return false;
101 tools::DisableNagle(socket_);
102 int reuse_addr = 1;
103 setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
104 &reuse_addr, sizeof(reuse_addr));
105 tools::DeferAccept(socket_);
106 return true;
107 }
108
109 bool Socket::InitUnixSocket(const string& path, bool abstract) {
110 static const size_t kPathMax = sizeof(addr_.addr_un.sun_path);
111 if (abstract + path.size() + 1 /* '\0' */ > kPathMax) {
112 LOG(ERROR) << "The provided path is too big to create a unix "
113 << "domain socket: " << path;
114 return false;
115 }
116 abstract_ = abstract;
117 family_ = PF_UNIX;
118 addr_.addr_un.sun_family = family_;
119
120 if (abstract) {
121 // Copied from net/base/unix_domain_socket_posix.cc
122 // Convert the path given into abstract socket name. It must start with
123 // the '\0' character, so we are adding it. |addr_len| must specify the
124 // length of the structure exactly, as potentially the socket name may
125 // have '\0' characters embedded (although we don't support this).
126 // Note that addr_.addr_un.sun_path is already zero initialized.
127 memcpy(addr_.addr_un.sun_path + 1, path.c_str(), path.size());
128 addr_len_ = path.size() + offsetof(struct sockaddr_un, sun_path) + 1;
129 } else {
130 memcpy(addr_.addr_un.sun_path, path.c_str(), path.size());
131 addr_len_ = sizeof(sockaddr_un);
132 }
133
134 addr_ptr_ = reinterpret_cast<sockaddr*>(&addr_.addr_un);
135 return InitSocketInternal();
136 }
137
138 bool Socket::InitTcpSocket(const string& host, int port) {
139 port_ = port;
140
141 if (host.empty()) {
142 // Use localhost: INADDR_LOOPBACK
143 family_ = AF_INET;
144 addr_.addr4.sin_family = family_;
145 addr_.addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
146 } else if (!Resolve(host)) {
147 return false;
148 }
149 CHECK(family_ == AF_INET || family_ == AF_INET6)
150 << "Error initializing socket.";
151 if (family_ == AF_INET) {
152 addr_.addr4.sin_port = htons(port_);
153 addr_ptr_ = reinterpret_cast<sockaddr*>(&addr_.addr4);
154 addr_len_ = sizeof(sockaddr_in);
155 } else if (family_ == AF_INET6) {
156 addr_.addr6.sin6_port = htons(port_);
157 addr_ptr_ = reinterpret_cast<sockaddr*>(&addr_.addr6);
158 addr_len_ = sizeof(sockaddr_in6);
159 }
160 return InitSocketInternal();
161 }
162
163 bool Socket::BindAndListen() {
164 errno = 0;
165 if (HANDLE_EINTR(bind(socket_, addr_ptr_, addr_len_)) < 0 ||
166 HANDLE_EINTR(listen(socket_, 5)) < 0) {
167 SetSocketError();
168 return false;
169 }
170 return true;
171 }
172
173 bool Socket::Accept(Socket* new_socket) {
174 DCHECK(new_socket != NULL);
175 if (!WaitForEvent()) {
176 SetSocketError();
177 return false;
178 }
179 errno = 0;
180 int new_socket_fd = HANDLE_EINTR(accept(socket_, NULL, NULL));
181 if (new_socket_fd < 0) {
182 SetSocketError();
183 return false;
184 }
185
186 tools::DisableNagle(new_socket_fd);
187 new_socket->socket_ = new_socket_fd;
188 return true;
189 }
190
191 bool Socket::Connect() {
192 errno = 0;
193 if (HANDLE_EINTR(connect(socket_, addr_ptr_, addr_len_)) < 0) {
194 SetSocketError();
195 return false;
196 }
197 return true;
198 }
199
200 bool Socket::Resolve(const string& host) {
201 struct addrinfo hints;
202 struct addrinfo* res;
203 memset(&hints, 0, sizeof(hints));
204 hints.ai_family = PF_UNSPEC;
205 hints.ai_socktype = SOCK_STREAM;
206 hints.ai_flags |= AI_CANONNAME;
207
208 int errcode = getaddrinfo(host.c_str(), NULL, &hints, &res);
209 if (errcode != 0) {
210 SetSocketError();
211 return false;
212 }
213 family_ = res->ai_family;
214 switch (res->ai_family) {
215 case AF_INET:
216 memcpy(&addr_.addr4,
217 reinterpret_cast<sockaddr_in*>(res->ai_addr),
218 sizeof(sockaddr_in));
219 break;
220 case AF_INET6:
221 memcpy(&addr_.addr6,
222 reinterpret_cast<sockaddr_in6*>(res->ai_addr),
223 sizeof(sockaddr_in6));
224 break;
225 }
226 return true;
227 }
228
229 bool Socket::IsFdInSet(const fd_set& fds) const {
230 if (IsClosed())
231 return false;
232 return FD_ISSET(socket_, &fds);
233 }
234
235 bool Socket::AddFdToSet(fd_set* fds) const {
236 if (IsClosed())
237 return false;
238 FD_SET(socket_, fds);
239 return true;
240 }
241
242 int Socket::ReadNumBytes(char* buffer, size_t num_bytes) {
243 int bytes_read = 0;
244 int ret = 1;
245 while (bytes_read < num_bytes && ret > 0) {
246 ret = Read(buffer + bytes_read, num_bytes - bytes_read);
247 if (ret >= 0)
248 bytes_read += ret;
249 }
250 return bytes_read;
251 }
252
253 void Socket::SetSocketError() {
254 socket_error_ = true;
255 // We never use non-blocking socket.
256 DCHECK(errno != EAGAIN && errno != EWOULDBLOCK);
257 Close();
258 }
259
260 int Socket::Read(char* buffer, size_t buffer_size) {
261 if (!WaitForEvent()) {
262 SetSocketError();
263 return 0;
264 }
265 int ret = HANDLE_EINTR(read(socket_, buffer, buffer_size));
266 if (ret < 0)
267 SetSocketError();
268 return ret;
269 }
270
271 int Socket::Write(const char* buffer, size_t count) {
272 int ret = HANDLE_EINTR(send(socket_, buffer, count, MSG_NOSIGNAL));
273 if (ret < 0)
274 SetSocketError();
275 return ret;
276 }
277
278 int Socket::WriteNumBytes(const char* buffer, size_t num_bytes) {
279 int bytes_written = 0;
280 int ret = 1;
281 while (bytes_written < num_bytes && ret > 0) {
282 ret = Write(buffer + bytes_written, num_bytes - bytes_written);
283 if (ret >= 0)
284 bytes_written += ret;
285 }
286 return bytes_written;
287 }
288
289 bool Socket::WaitForEvent() const {
290 if (exit_notifier_fd_ == -1 || socket_ == -1)
291 return true;
292 const int nfds = std::max(socket_, exit_notifier_fd_) + 1;
293 fd_set read_fds;
294 FD_ZERO(&read_fds);
295 FD_SET(socket_, &read_fds);
296 FD_SET(exit_notifier_fd_, &read_fds);
297 if (HANDLE_EINTR(select(nfds, &read_fds, NULL, NULL, NULL)) <= 0)
298 return false;
299 return !FD_ISSET(exit_notifier_fd_, &read_fds);
300 }
301
302 // static
303 int Socket::GetHighestFileDescriptor(
304 const Socket& s1, const Socket& s2) {
305 return std::max(s1.socket_, s2.socket_);
306 }
307
308 } // namespace forwarder
OLDNEW
« no previous file with comments | « tools/android/forwarder2/socket.h ('k') | tools/android/forwarder2/thread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698