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

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

Issue 2780063002: Pulled a significant portion of Socket implementation into BaseSocket in order to prepare for the s… (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
OLDNEW
(Empty)
1 // Copyright (c) 2013, 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(TARGET_OS_WINDOWS)
9
10 #include "bin/socket.h"
11 #include "bin/socket_win.h"
12
13 #include "bin/builtin.h"
14 #include "bin/eventhandler.h"
15 #include "bin/file.h"
16 #include "bin/lockers.h"
17 #include "bin/log.h"
18 #include "bin/thread.h"
19 #include "bin/utils.h"
20 #include "bin/utils_win.h"
21
22 namespace dart {
23 namespace bin {
24
25 SocketAddress::SocketAddress(struct sockaddr* sockaddr) {
26 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
27 RawAddr* raw = reinterpret_cast<RawAddr*>(sockaddr);
28
29 // Clear the port before calling WSAAddressToString as WSAAddressToString
30 // includes the port in the formatted string.
31 int err = Socket::FormatNumericAddress(*raw, as_string_, INET6_ADDRSTRLEN);
32
33 if (err != 0) {
34 as_string_[0] = 0;
35 }
36 memmove(reinterpret_cast<void*>(&addr_), sockaddr,
37 SocketAddress::GetAddrLength(*raw));
38 }
39
40
41 bool Socket::FormatNumericAddress(const RawAddr& addr, char* address, int len) {
42 socklen_t salen = SocketAddress::GetAddrLength(addr);
43 DWORD l = len;
44 RawAddr& raw = const_cast<RawAddr&>(addr);
45 return WSAAddressToStringA(&raw.addr, salen, NULL, address, &l) != 0;
46 }
47
48
49 static Mutex* init_mutex = new Mutex();
50 static bool socket_initialized = false;
51
52 bool Socket::Initialize() {
53 MutexLocker lock(init_mutex);
54 if (socket_initialized) {
55 return true;
56 }
57 int err;
58 WSADATA winsock_data;
59 WORD version_requested = MAKEWORD(2, 2);
60 err = WSAStartup(version_requested, &winsock_data);
61 if (err == 0) {
62 socket_initialized = true;
63 } else {
64 Log::PrintErr("Unable to initialize Winsock: %d\n", WSAGetLastError());
65 }
66 return (err == 0);
67 }
68
69 intptr_t Socket::Available(intptr_t fd) {
70 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(fd);
71 return client_socket->Available();
72 }
73
74
75 intptr_t Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
76 Handle* handle = reinterpret_cast<Handle*>(fd);
77 return handle->Read(buffer, num_bytes);
78 }
79
80
81 intptr_t Socket::RecvFrom(intptr_t fd,
82 void* buffer,
83 intptr_t num_bytes,
84 RawAddr* addr) {
85 Handle* handle = reinterpret_cast<Handle*>(fd);
86 socklen_t addr_len = sizeof(addr->ss);
87 return handle->RecvFrom(buffer, num_bytes, &addr->addr, addr_len);
88 }
89
90
91 intptr_t Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
92 Handle* handle = reinterpret_cast<Handle*>(fd);
93 return handle->Write(buffer, num_bytes);
94 }
95
96
97 intptr_t Socket::SendTo(intptr_t fd,
98 const void* buffer,
99 intptr_t num_bytes,
100 const RawAddr& addr) {
101 Handle* handle = reinterpret_cast<Handle*>(fd);
102 RawAddr& raw = const_cast<RawAddr&>(addr);
103 return handle->SendTo(buffer, num_bytes, &raw.addr,
104 SocketAddress::GetAddrLength(addr));
105 }
106
107
108 intptr_t Socket::GetPort(intptr_t fd) {
109 ASSERT(reinterpret_cast<Handle*>(fd)->is_socket());
110 SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd);
111 RawAddr raw;
112 socklen_t size = sizeof(raw);
113 if (getsockname(socket_handle->socket(), &raw.addr, &size) == SOCKET_ERROR) {
114 return 0;
115 }
116 return SocketAddress::GetAddrPort(raw);
117 }
118
119
120 SocketAddress* Socket::GetRemotePeer(intptr_t fd, intptr_t* port) {
121 ASSERT(reinterpret_cast<Handle*>(fd)->is_socket());
122 SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd);
123 RawAddr raw;
124 socklen_t size = sizeof(raw);
125 if (getpeername(socket_handle->socket(), &raw.addr, &size)) {
126 return NULL;
127 }
128 *port = SocketAddress::GetAddrPort(raw);
129 // Clear the port before calling WSAAddressToString as WSAAddressToString
130 // includes the port in the formatted string.
131 SocketAddress::SetAddrPort(&raw, 0);
132 return new SocketAddress(&raw.addr);
133 }
134
135
136 static intptr_t Create(const RawAddr& addr) {
137 SOCKET s = socket(addr.ss.ss_family, SOCK_STREAM, 0);
138 if (s == INVALID_SOCKET) {
139 return -1;
140 }
141
142 linger l;
143 l.l_onoff = 1;
144 l.l_linger = 10;
145 int status = setsockopt(s, SOL_SOCKET, SO_LINGER, reinterpret_cast<char*>(&l),
146 sizeof(l));
147 if (status != NO_ERROR) {
148 FATAL("Failed setting SO_LINGER on socket");
149 }
150
151 ClientSocket* client_socket = new ClientSocket(s);
152 return reinterpret_cast<intptr_t>(client_socket);
153 }
154
155
156 static intptr_t Connect(intptr_t fd,
157 const RawAddr& addr,
158 const RawAddr& bind_addr) {
159 ASSERT(reinterpret_cast<Handle*>(fd)->is_client_socket());
160 ClientSocket* handle = reinterpret_cast<ClientSocket*>(fd);
161 SOCKET s = handle->socket();
162
163 int status =
164 bind(s, &bind_addr.addr, SocketAddress::GetAddrLength(bind_addr));
165 if (status != NO_ERROR) {
166 int rc = WSAGetLastError();
167 handle->mark_closed(); // Destructor asserts that socket is marked closed.
168 delete handle;
169 closesocket(s);
170 SetLastError(rc);
171 return -1;
172 }
173
174 LPFN_CONNECTEX connectEx = NULL;
175 GUID guid_connect_ex = WSAID_CONNECTEX;
176 DWORD bytes;
177 status = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid_connect_ex,
178 sizeof(guid_connect_ex), &connectEx, sizeof(connectEx),
179 &bytes, NULL, NULL);
180 DWORD rc;
181 if (status != SOCKET_ERROR) {
182 handle->EnsureInitialized(EventHandler::delegate());
183
184 OverlappedBuffer* overlapped = OverlappedBuffer::AllocateConnectBuffer();
185
186 status = connectEx(s, &addr.addr, SocketAddress::GetAddrLength(addr), NULL,
187 0, NULL, overlapped->GetCleanOverlapped());
188
189
190 if (status == TRUE) {
191 handle->ConnectComplete(overlapped);
192 return fd;
193 } else if (WSAGetLastError() == ERROR_IO_PENDING) {
194 return fd;
195 }
196 rc = WSAGetLastError();
197 // Cleanup in case of error.
198 OverlappedBuffer::DisposeBuffer(overlapped);
199 } else {
200 rc = WSAGetLastError();
201 }
202 handle->Close();
203 delete handle;
204 SetLastError(rc);
205 return -1;
206 }
207
208
209 intptr_t Socket::CreateConnect(const RawAddr& addr) {
210 intptr_t fd = Create(addr);
211 if (fd < 0) {
212 return fd;
213 }
214
215 RawAddr bind_addr;
216 memset(&bind_addr, 0, sizeof(bind_addr));
217 bind_addr.ss.ss_family = addr.ss.ss_family;
218 if (addr.ss.ss_family == AF_INET) {
219 bind_addr.in.sin_addr.s_addr = INADDR_ANY;
220 } else {
221 bind_addr.in6.sin6_addr = in6addr_any;
222 }
223
224 return Connect(fd, addr, bind_addr);
225 }
226
227
228 intptr_t Socket::CreateBindConnect(const RawAddr& addr,
229 const RawAddr& source_addr) {
230 intptr_t fd = Create(addr);
231 if (fd < 0) {
232 return fd;
233 }
234
235 return Connect(fd, addr, source_addr);
236 }
237
238
239 bool Socket::IsBindError(intptr_t error_number) {
240 return error_number == WSAEADDRINUSE || error_number == WSAEADDRNOTAVAIL ||
241 error_number == WSAEINVAL;
242 }
243
244
245 void Socket::GetError(intptr_t fd, OSError* os_error) {
246 Handle* handle = reinterpret_cast<Handle*>(fd);
247 os_error->SetCodeAndMessage(OSError::kSystem, handle->last_error());
248 }
249
250
251 int Socket::GetType(intptr_t fd) {
252 Handle* handle = reinterpret_cast<Handle*>(fd);
253 switch (GetFileType(handle->handle())) {
254 case FILE_TYPE_CHAR:
255 return File::kTerminal;
256 case FILE_TYPE_PIPE:
257 return File::kPipe;
258 case FILE_TYPE_DISK:
259 return File::kFile;
260 default:
261 return GetLastError == NO_ERROR ? File::kOther : -1;
262 }
263 }
264
265
266 intptr_t Socket::GetStdioHandle(intptr_t num) {
267 if (num != 0) {
268 return -1;
269 }
270 HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
271 if (handle == INVALID_HANDLE_VALUE) {
272 return -1;
273 }
274 StdHandle* std_handle = new StdHandle(handle);
275 std_handle->MarkDoesNotSupportOverlappedIO();
276 std_handle->EnsureInitialized(EventHandler::delegate());
277 return reinterpret_cast<intptr_t>(std_handle);
278 }
279
280
281 intptr_t ServerSocket::Accept(intptr_t fd) {
282 ListenSocket* listen_socket = reinterpret_cast<ListenSocket*>(fd);
283 ClientSocket* client_socket = listen_socket->Accept();
284 if (client_socket != NULL) {
285 return reinterpret_cast<intptr_t>(client_socket);
286 } else {
287 return -1;
288 }
289 }
290
291
292 AddressList<SocketAddress>* Socket::LookupAddress(const char* host,
293 int type,
294 OSError** os_error) {
295 Initialize();
296
297 // Perform a name lookup for a host name.
298 struct addrinfo hints;
299 memset(&hints, 0, sizeof(hints));
300 hints.ai_family = SocketAddress::FromType(type);
301 hints.ai_socktype = SOCK_STREAM;
302 hints.ai_flags = AI_ADDRCONFIG;
303 hints.ai_protocol = IPPROTO_TCP;
304 struct addrinfo* info = NULL;
305 int status = getaddrinfo(host, 0, &hints, &info);
306 if (status != 0) {
307 // We failed, try without AI_ADDRCONFIG. This can happen when looking up
308 // e.g. '::1', when there are no global IPv6 addresses.
309 hints.ai_flags = 0;
310 status = getaddrinfo(host, 0, &hints, &info);
311 }
312 if (status != 0) {
313 ASSERT(*os_error == NULL);
314 DWORD error_code = WSAGetLastError();
315 SetLastError(error_code);
316 *os_error = new OSError();
317 return NULL;
318 }
319 intptr_t count = 0;
320 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
321 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
322 count++;
323 }
324 }
325 AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
326 intptr_t i = 0;
327 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
328 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
329 addresses->SetAt(i, new SocketAddress(c->ai_addr));
330 i++;
331 }
332 }
333 freeaddrinfo(info);
334 return addresses;
335 }
336
337
338 bool Socket::ReverseLookup(const RawAddr& addr,
339 char* host,
340 intptr_t host_len,
341 OSError** os_error) {
342 ASSERT(host_len >= NI_MAXHOST);
343 int status = getnameinfo(&addr.addr, SocketAddress::GetAddrLength(addr), host,
344 host_len, NULL, 0, NI_NAMEREQD);
345 if (status != 0) {
346 ASSERT(*os_error == NULL);
347 DWORD error_code = WSAGetLastError();
348 SetLastError(error_code);
349 *os_error = new OSError();
350 return false;
351 }
352 return true;
353 }
354
355
356 bool Socket::ParseAddress(int type, const char* address, RawAddr* addr) {
357 int result;
358 Utf8ToWideScope system_address(address);
359 if (type == SocketAddress::TYPE_IPV4) {
360 result = InetPton(AF_INET, system_address.wide(), &addr->in.sin_addr);
361 } else {
362 ASSERT(type == SocketAddress::TYPE_IPV6);
363 result = InetPton(AF_INET6, system_address.wide(), &addr->in6.sin6_addr);
364 }
365 return result == 1;
366 }
367
368
369 intptr_t Socket::CreateBindDatagram(const RawAddr& addr, bool reuseAddress) {
370 SOCKET s = socket(addr.ss.ss_family, SOCK_DGRAM, IPPROTO_UDP);
371 if (s == INVALID_SOCKET) {
372 return -1;
373 }
374
375 int status;
376 if (reuseAddress) {
377 BOOL optval = true;
378 status = setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
379 reinterpret_cast<const char*>(&optval), sizeof(optval));
380 if (status == SOCKET_ERROR) {
381 DWORD rc = WSAGetLastError();
382 closesocket(s);
383 SetLastError(rc);
384 return -1;
385 }
386 }
387
388 status = bind(s, &addr.addr, SocketAddress::GetAddrLength(addr));
389 if (status == SOCKET_ERROR) {
390 DWORD rc = WSAGetLastError();
391 closesocket(s);
392 SetLastError(rc);
393 return -1;
394 }
395
396 DatagramSocket* datagram_socket = new DatagramSocket(s);
397 datagram_socket->EnsureInitialized(EventHandler::delegate());
398 return reinterpret_cast<intptr_t>(datagram_socket);
399 }
400
401
402 bool Socket::ListInterfacesSupported() {
403 return true;
404 }
405
406
407 AddressList<InterfaceSocketAddress>* Socket::ListInterfaces(
408 int type,
409 OSError** os_error) {
410 Initialize();
411
412 ULONG size = 0;
413 DWORD flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
414 GAA_FLAG_SKIP_DNS_SERVER;
415 // Query the size needed.
416 int status = GetAdaptersAddresses(SocketAddress::FromType(type), flags, NULL,
417 NULL, &size);
418 IP_ADAPTER_ADDRESSES* addrs = NULL;
419 if (status == ERROR_BUFFER_OVERFLOW) {
420 addrs = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(size));
421 // Get the addresses now we have the right buffer.
422 status = GetAdaptersAddresses(SocketAddress::FromType(type), flags, NULL,
423 addrs, &size);
424 }
425 if (status != NO_ERROR) {
426 ASSERT(*os_error == NULL);
427 DWORD error_code = WSAGetLastError();
428 SetLastError(error_code);
429 *os_error = new OSError();
430 return NULL;
431 }
432 intptr_t count = 0;
433 for (IP_ADAPTER_ADDRESSES* a = addrs; a != NULL; a = a->Next) {
434 for (IP_ADAPTER_UNICAST_ADDRESS* u = a->FirstUnicastAddress; u != NULL;
435 u = u->Next) {
436 count++;
437 }
438 }
439 AddressList<InterfaceSocketAddress>* addresses =
440 new AddressList<InterfaceSocketAddress>(count);
441 intptr_t i = 0;
442 for (IP_ADAPTER_ADDRESSES* a = addrs; a != NULL; a = a->Next) {
443 for (IP_ADAPTER_UNICAST_ADDRESS* u = a->FirstUnicastAddress; u != NULL;
444 u = u->Next) {
445 addresses->SetAt(
446 i, new InterfaceSocketAddress(
447 u->Address.lpSockaddr,
448 StringUtilsWin::WideToUtf8(a->FriendlyName), a->Ipv6IfIndex));
449 i++;
450 }
451 }
452 free(addrs);
453 return addresses;
454 }
455
456
457 intptr_t ServerSocket::CreateBindListen(const RawAddr& addr,
458 intptr_t backlog,
459 bool v6_only) {
460 SOCKET s = socket(addr.ss.ss_family, SOCK_STREAM, IPPROTO_TCP);
461 if (s == INVALID_SOCKET) {
462 return -1;
463 }
464
465 BOOL optval = true;
466 int status =
467 setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
468 reinterpret_cast<const char*>(&optval), sizeof(optval));
469 if (status == SOCKET_ERROR) {
470 DWORD rc = WSAGetLastError();
471 closesocket(s);
472 SetLastError(rc);
473 return -1;
474 }
475
476 if (addr.ss.ss_family == AF_INET6) {
477 optval = v6_only;
478 setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
479 reinterpret_cast<const char*>(&optval), sizeof(optval));
480 }
481
482 status = bind(s, &addr.addr, SocketAddress::GetAddrLength(addr));
483 if (status == SOCKET_ERROR) {
484 DWORD rc = WSAGetLastError();
485 closesocket(s);
486 SetLastError(rc);
487 return -1;
488 }
489
490 ListenSocket* listen_socket = new ListenSocket(s);
491
492 // Test for invalid socket port 65535 (some browsers disallow it).
493 if ((SocketAddress::GetAddrPort(addr) == 0) &&
494 (Socket::GetPort(reinterpret_cast<intptr_t>(listen_socket)) == 65535)) {
495 // Don't close fd until we have created new. By doing that we ensure another
496 // port.
497 intptr_t new_s = CreateBindListen(addr, backlog, v6_only);
498 DWORD rc = WSAGetLastError();
499 closesocket(s);
500 delete listen_socket;
501 SetLastError(rc);
502 return new_s;
503 }
504
505 status = listen(s, backlog > 0 ? backlog : SOMAXCONN);
506 if (status == SOCKET_ERROR) {
507 DWORD rc = WSAGetLastError();
508 closesocket(s);
509 delete listen_socket;
510 SetLastError(rc);
511 return -1;
512 }
513
514 return reinterpret_cast<intptr_t>(listen_socket);
515 }
516
517
518 bool ServerSocket::StartAccept(intptr_t fd) {
519 ListenSocket* listen_socket = reinterpret_cast<ListenSocket*>(fd);
520 listen_socket->EnsureInitialized(EventHandler::delegate());
521 // Always keep 5 outstanding accepts going, to enhance performance.
522 for (int i = 0; i < 5; i++) {
523 if (!listen_socket->IssueAccept()) {
524 DWORD rc = WSAGetLastError();
525 listen_socket->Close();
526 if (!listen_socket->HasPendingAccept()) {
527 // Delete socket now, if there are no pending accepts. Otherwise,
528 // the event-handler will take care of deleting it.
529 delete listen_socket;
530 }
531 SetLastError(rc);
532 return false;
533 }
534 }
535 return true;
536 }
537
538
539 void Socket::Close(intptr_t fd) {
540 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(fd);
541 client_socket->Close();
542 }
543
544
545 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) {
546 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
547 int on;
548 socklen_t len = sizeof(on);
549 int err = getsockopt(handle->socket(), IPPROTO_TCP, TCP_NODELAY,
550 reinterpret_cast<char*>(&on), &len);
551 if (err == 0) {
552 *enabled = (on == 1);
553 }
554 return (err == 0);
555 }
556
557
558 bool Socket::SetNoDelay(intptr_t fd, bool enabled) {
559 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
560 int on = enabled ? 1 : 0;
561 return setsockopt(handle->socket(), IPPROTO_TCP, TCP_NODELAY,
562 reinterpret_cast<char*>(&on), sizeof(on)) == 0;
563 }
564
565
566 bool Socket::GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled) {
567 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
568 uint8_t on;
569 socklen_t len = sizeof(on);
570 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
571 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP
572 : IPV6_MULTICAST_LOOP;
573 if (getsockopt(handle->socket(), level, optname, reinterpret_cast<char*>(&on),
574 &len) == 0) {
575 *enabled = (on == 1);
576 return true;
577 }
578 return false;
579 }
580
581
582 bool Socket::SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled) {
583 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
584 int on = enabled ? 1 : 0;
585 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
586 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP
587 : IPV6_MULTICAST_LOOP;
588 return setsockopt(handle->socket(), level, optname,
589 reinterpret_cast<char*>(&on), sizeof(on)) == 0;
590 }
591
592
593 bool Socket::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) {
594 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
595 uint8_t v;
596 socklen_t len = sizeof(v);
597 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
598 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL
599 : IPV6_MULTICAST_HOPS;
600 if (getsockopt(handle->socket(), level, optname, reinterpret_cast<char*>(&v),
601 &len) == 0) {
602 *value = v;
603 return true;
604 }
605 return false;
606 }
607
608
609 bool Socket::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) {
610 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
611 int v = value;
612 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
613 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL
614 : IPV6_MULTICAST_HOPS;
615 return setsockopt(handle->socket(), level, optname,
616 reinterpret_cast<char*>(&v), sizeof(v)) == 0;
617 }
618
619
620 bool Socket::GetBroadcast(intptr_t fd, bool* enabled) {
621 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
622 int on;
623 socklen_t len = sizeof(on);
624 int err = getsockopt(handle->socket(), SOL_SOCKET, SO_BROADCAST,
625 reinterpret_cast<char*>(&on), &len);
626 if (err == 0) {
627 *enabled = (on == 1);
628 }
629 return (err == 0);
630 }
631
632
633 bool Socket::SetBroadcast(intptr_t fd, bool enabled) {
634 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
635 int on = enabled ? 1 : 0;
636 return setsockopt(handle->socket(), SOL_SOCKET, SO_BROADCAST,
637 reinterpret_cast<char*>(&on), sizeof(on)) == 0;
638 }
639
640
641 bool Socket::JoinMulticast(intptr_t fd,
642 const RawAddr& addr,
643 const RawAddr&,
644 int interfaceIndex) {
645 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
646 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
647 struct group_req mreq;
648 mreq.gr_interface = interfaceIndex;
649 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
650 return setsockopt(handle->socket(), proto, MCAST_JOIN_GROUP,
651 reinterpret_cast<char*>(&mreq), sizeof(mreq)) == 0;
652 }
653
654
655 bool Socket::LeaveMulticast(intptr_t fd,
656 const RawAddr& addr,
657 const RawAddr&,
658 int interfaceIndex) {
659 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
660 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
661 struct group_req mreq;
662 mreq.gr_interface = interfaceIndex;
663 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
664 return setsockopt(handle->socket(), proto, MCAST_LEAVE_GROUP,
665 reinterpret_cast<char*>(&mreq), sizeof(mreq)) == 0;
666 }
667
668 } // namespace bin
669 } // namespace dart
670
671 #endif // defined(TARGET_OS_WINDOWS)
672
673 #endif // !defined(DART_IO_DISABLED)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698