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

Side by Side Diff: runtime/bin/socket_base_android.cc

Issue 2791163004: Reverting until bots clear up. (Closed)
Patch Set: Created 3 years, 8 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 | « runtime/bin/socket_base_android.h ('k') | runtime/bin/socket_base_fuchsia.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 Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #if !defined(DART_IO_DISABLED)
6
7 #include "platform/globals.h"
8 #if defined(HOST_OS_ANDROID)
9
10 #include "bin/socket_base.h"
11
12 #include <errno.h> // NOLINT
13 #include <netinet/tcp.h> // NOLINT
14 #include <stdio.h> // NOLINT
15 #include <stdlib.h> // NOLINT
16 #include <string.h> // NOLINT
17 #include <sys/stat.h> // NOLINT
18 #include <unistd.h> // NOLINT
19
20 #include "bin/fdutils.h"
21 #include "bin/file.h"
22 #include "bin/socket_base_android.h"
23 #include "platform/signal_blocker.h"
24
25 namespace dart {
26 namespace bin {
27
28 SocketAddress::SocketAddress(struct sockaddr* sa) {
29 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
30 if (!SocketBase::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa),
31 as_string_, INET6_ADDRSTRLEN)) {
32 as_string_[0] = 0;
33 }
34 socklen_t salen = GetAddrLength(*reinterpret_cast<RawAddr*>(sa));
35 memmove(reinterpret_cast<void*>(&addr_), sa, salen);
36 }
37
38
39 bool SocketBase::FormatNumericAddress(const RawAddr& addr,
40 char* address,
41 int len) {
42 socklen_t salen = SocketAddress::GetAddrLength(addr);
43 return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, salen, address, len, NULL,
44 0, NI_NUMERICHOST)) == 0);
45 }
46
47
48 bool SocketBase::IsBindError(intptr_t error_number) {
49 return error_number == EADDRINUSE || error_number == EADDRNOTAVAIL ||
50 error_number == EINVAL;
51 }
52
53
54 intptr_t SocketBase::Available(intptr_t fd) {
55 return FDUtils::AvailableBytes(fd);
56 }
57
58
59 intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
60 ASSERT(fd >= 0);
61 ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
62 ASSERT(EAGAIN == EWOULDBLOCK);
63 if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
64 // If the read would block we need to retry and therefore return 0
65 // as the number of bytes written.
66 read_bytes = 0;
67 }
68 return read_bytes;
69 }
70
71
72 intptr_t SocketBase::RecvFrom(intptr_t fd,
73 void* buffer,
74 intptr_t num_bytes,
75 RawAddr* addr) {
76 ASSERT(fd >= 0);
77 socklen_t addr_len = sizeof(addr->ss);
78 ssize_t read_bytes = TEMP_FAILURE_RETRY(
79 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
80 if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
81 // If the read would block we need to retry and therefore return 0
82 // as the number of bytes written.
83 read_bytes = 0;
84 }
85 return read_bytes;
86 }
87
88
89 intptr_t SocketBase::Write(intptr_t fd,
90 const void* buffer,
91 intptr_t num_bytes) {
92 ASSERT(fd >= 0);
93 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
94 ASSERT(EAGAIN == EWOULDBLOCK);
95 if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
96 // If the would block we need to retry and therefore return 0 as
97 // the number of bytes written.
98 written_bytes = 0;
99 }
100 return written_bytes;
101 }
102
103
104 intptr_t SocketBase::SendTo(intptr_t fd,
105 const void* buffer,
106 intptr_t num_bytes,
107 const RawAddr& addr) {
108 ASSERT(fd >= 0);
109 ssize_t written_bytes =
110 TEMP_FAILURE_RETRY(sendto(fd, buffer, num_bytes, 0, &addr.addr,
111 SocketAddress::GetAddrLength(addr)));
112 ASSERT(EAGAIN == EWOULDBLOCK);
113 if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
114 // If the would block we need to retry and therefore return 0 as
115 // the number of bytes written.
116 written_bytes = 0;
117 }
118 return written_bytes;
119 }
120
121
122 intptr_t SocketBase::GetPort(intptr_t fd) {
123 ASSERT(fd >= 0);
124 RawAddr raw;
125 socklen_t size = sizeof(raw);
126 if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &size))) {
127 return 0;
128 }
129 return SocketAddress::GetAddrPort(raw);
130 }
131
132
133 SocketAddress* SocketBase::GetRemotePeer(intptr_t fd, intptr_t* port) {
134 ASSERT(fd >= 0);
135 RawAddr raw;
136 socklen_t size = sizeof(raw);
137 if (NO_RETRY_EXPECTED(getpeername(fd, &raw.addr, &size))) {
138 return NULL;
139 }
140 *port = SocketAddress::GetAddrPort(raw);
141 return new SocketAddress(&raw.addr);
142 }
143
144
145 void SocketBase::GetError(intptr_t fd, OSError* os_error) {
146 int errorNumber;
147 socklen_t len = sizeof(errorNumber);
148 getsockopt(fd, SOL_SOCKET, SO_ERROR, reinterpret_cast<void*>(&errorNumber),
149 &len);
150 os_error->SetCodeAndMessage(OSError::kSystem, errorNumber);
151 }
152
153
154 int SocketBase::GetType(intptr_t fd) {
155 struct stat buf;
156 int result = fstat(fd, &buf);
157 if (result == -1) {
158 return -1;
159 }
160 if (S_ISCHR(buf.st_mode)) {
161 return File::kTerminal;
162 }
163 if (S_ISFIFO(buf.st_mode)) {
164 return File::kPipe;
165 }
166 if (S_ISREG(buf.st_mode)) {
167 return File::kFile;
168 }
169 return File::kOther;
170 }
171
172
173 intptr_t SocketBase::GetStdioHandle(intptr_t num) {
174 return num;
175 }
176
177
178 AddressList<SocketAddress>* SocketBase::LookupAddress(const char* host,
179 int type,
180 OSError** os_error) {
181 // Perform a name lookup for a host name.
182 struct addrinfo hints;
183 memset(&hints, 0, sizeof(hints));
184 hints.ai_family = SocketAddress::FromType(type);
185 hints.ai_socktype = SOCK_STREAM;
186 hints.ai_flags = AI_ADDRCONFIG;
187 hints.ai_protocol = IPPROTO_TCP;
188 struct addrinfo* info = NULL;
189 int status = getaddrinfo(host, 0, &hints, &info);
190 if (status != 0) {
191 // We failed, try without AI_ADDRCONFIG. This can happen when looking up
192 // e.g. '::1', when there are no IPv6 addresses.
193 hints.ai_flags = 0;
194 status = getaddrinfo(host, 0, &hints, &info);
195 if (status != 0) {
196 ASSERT(*os_error == NULL);
197 *os_error =
198 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
199 return NULL;
200 }
201 }
202 intptr_t count = 0;
203 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
204 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
205 count++;
206 }
207 }
208 intptr_t i = 0;
209 AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
210 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
211 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
212 addresses->SetAt(i, new SocketAddress(c->ai_addr));
213 i++;
214 }
215 }
216 freeaddrinfo(info);
217 return addresses;
218 }
219
220
221 bool SocketBase::ReverseLookup(const RawAddr& addr,
222 char* host,
223 intptr_t host_len,
224 OSError** os_error) {
225 ASSERT(host_len >= NI_MAXHOST);
226 int status = NO_RETRY_EXPECTED(
227 getnameinfo(&addr.addr, SocketAddress::GetAddrLength(addr), host,
228 host_len, NULL, 0, NI_NAMEREQD));
229 if (status != 0) {
230 ASSERT(*os_error == NULL);
231 *os_error =
232 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
233 return false;
234 }
235 return true;
236 }
237
238
239 bool SocketBase::ParseAddress(int type, const char* address, RawAddr* addr) {
240 int result;
241 if (type == SocketAddress::TYPE_IPV4) {
242 result = inet_pton(AF_INET, address, &addr->in.sin_addr);
243 } else {
244 ASSERT(type == SocketAddress::TYPE_IPV6);
245 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr);
246 }
247 return (result == 1);
248 }
249
250
251 bool SocketBase::ListInterfacesSupported() {
252 return false;
253 }
254
255
256 AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces(
257 int type,
258 OSError** os_error) {
259 // The ifaddrs.h header is not provided on Android. An Android
260 // implementation would have to use IOCTL or netlink.
261 ASSERT(*os_error == NULL);
262 *os_error = new OSError(-1,
263 "Listing interfaces is not supported "
264 "on this platform",
265 OSError::kSystem);
266 return NULL;
267 }
268
269
270 void SocketBase::Close(intptr_t fd) {
271 ASSERT(fd >= 0);
272 VOID_TEMP_FAILURE_RETRY(close(fd));
273 }
274
275
276 bool SocketBase::GetNoDelay(intptr_t fd, bool* enabled) {
277 int on;
278 socklen_t len = sizeof(on);
279 int err = NO_RETRY_EXPECTED(getsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
280 reinterpret_cast<void*>(&on), &len));
281 if (err == 0) {
282 *enabled = (on == 1);
283 }
284 return (err == 0);
285 }
286
287
288 bool SocketBase::SetNoDelay(intptr_t fd, bool enabled) {
289 int on = enabled ? 1 : 0;
290 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
291 reinterpret_cast<char*>(&on),
292 sizeof(on))) == 0;
293 }
294
295
296 bool SocketBase::GetMulticastLoop(intptr_t fd,
297 intptr_t protocol,
298 bool* enabled) {
299 uint8_t on;
300 socklen_t len = sizeof(on);
301 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
302 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP
303 : IPV6_MULTICAST_LOOP;
304 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname,
305 reinterpret_cast<char*>(&on), &len)) == 0) {
306 *enabled = (on == 1);
307 return true;
308 }
309 return false;
310 }
311
312
313 bool SocketBase::SetMulticastLoop(intptr_t fd,
314 intptr_t protocol,
315 bool enabled) {
316 int on = enabled ? 1 : 0;
317 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
318 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP
319 : IPV6_MULTICAST_LOOP;
320 return NO_RETRY_EXPECTED(setsockopt(
321 fd, level, optname, reinterpret_cast<char*>(&on), sizeof(on))) ==
322 0;
323 }
324
325 bool SocketBase::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) {
326 uint8_t v;
327 socklen_t len = sizeof(v);
328 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
329 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL
330 : IPV6_MULTICAST_HOPS;
331 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname,
332 reinterpret_cast<char*>(&v), &len)) == 0) {
333 *value = v;
334 return true;
335 }
336 return false;
337 }
338
339
340 bool SocketBase::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) {
341 int v = value;
342 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
343 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL
344 : IPV6_MULTICAST_HOPS;
345 return NO_RETRY_EXPECTED(setsockopt(
346 fd, level, optname, reinterpret_cast<char*>(&v), sizeof(v))) == 0;
347 }
348
349
350 bool SocketBase::GetBroadcast(intptr_t fd, bool* enabled) {
351 int on;
352 socklen_t len = sizeof(on);
353 int err = NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_BROADCAST,
354 reinterpret_cast<char*>(&on), &len));
355 if (err == 0) {
356 *enabled = (on == 1);
357 }
358 return (err == 0);
359 }
360
361
362 bool SocketBase::SetBroadcast(intptr_t fd, bool enabled) {
363 int on = enabled ? 1 : 0;
364 return NO_RETRY_EXPECTED(setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
365 reinterpret_cast<char*>(&on),
366 sizeof(on))) == 0;
367 }
368
369
370 bool SocketBase::JoinMulticast(intptr_t fd,
371 const RawAddr& addr,
372 const RawAddr&,
373 int interfaceIndex) {
374 int proto = (addr.addr.sa_family == AF_INET) ? IPPROTO_IP : IPPROTO_IPV6;
375 struct group_req mreq;
376 mreq.gr_interface = interfaceIndex;
377 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
378 return NO_RETRY_EXPECTED(
379 setsockopt(fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0;
380 }
381
382
383 bool SocketBase::LeaveMulticast(intptr_t fd,
384 const RawAddr& addr,
385 const RawAddr&,
386 int interfaceIndex) {
387 int proto = (addr.addr.sa_family == AF_INET) ? IPPROTO_IP : IPPROTO_IPV6;
388 struct group_req mreq;
389 mreq.gr_interface = interfaceIndex;
390 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
391 return NO_RETRY_EXPECTED(setsockopt(fd, proto, MCAST_LEAVE_GROUP, &mreq,
392 sizeof(mreq))) == 0;
393 }
394
395 } // namespace bin
396 } // namespace dart
397
398 #endif // defined(HOST_OS_ANDROID)
399
400 #endif // !defined(DART_IO_DISABLED)
OLDNEW
« no previous file with comments | « runtime/bin/socket_base_android.h ('k') | runtime/bin/socket_base_fuchsia.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698