OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 patch class RawServerSocket { | 5 patch class RawServerSocket { |
6 /* patch */ static Future<RawServerSocket> bind(address, | 6 /* patch */ static Future<RawServerSocket> bind(address, |
7 int port, | 7 int port, |
8 {int backlog: 0, | 8 {int backlog: 0, |
9 bool v6Only: false}) { | 9 bool v6Only: false}) { |
10 return _RawServerSocket.bind(address, port, backlog, v6Only); | 10 return _RawServerSocket.bind(address, port, backlog, v6Only); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 _sockaddr_storage[_IPV4_ADDR_OFFSET] < 240; | 118 _sockaddr_storage[_IPV4_ADDR_OFFSET] < 240; |
119 | 119 |
120 case InternetAddressType.IP_V6: | 120 case InternetAddressType.IP_V6: |
121 // Checking for ff00::/8. | 121 // Checking for ff00::/8. |
122 return _sockaddr_storage[_IPV6_ADDR_OFFSET] == 0xFF; | 122 return _sockaddr_storage[_IPV6_ADDR_OFFSET] == 0xFF; |
123 } | 123 } |
124 } | 124 } |
125 | 125 |
126 Future<InternetAddress> reverse() => _NativeSocket.reverseLookup(this); | 126 Future<InternetAddress> reverse() => _NativeSocket.reverseLookup(this); |
127 | 127 |
| 128 |
128 _InternetAddress(InternetAddressType this.type, | 129 _InternetAddress(InternetAddressType this.type, |
129 String this.address, | 130 String this.address, |
130 String this._host, | 131 String this._host, |
131 List<int> this._sockaddr_storage); | 132 List<int> this._sockaddr_storage); |
132 | 133 |
133 factory _InternetAddress.parse(String address) { | 134 factory _InternetAddress.parse(String address) { |
134 var type = address.indexOf(':') == -1 | 135 var type = address.indexOf(':') == -1 |
135 ? InternetAddressType.IP_V4 | 136 ? InternetAddressType.IP_V4 |
136 : InternetAddressType.IP_V6; | 137 : InternetAddressType.IP_V6; |
137 var raw = _parse(type._value, address); | 138 var raw = _parse(type._value, address); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 int eventMask = 0; | 258 int eventMask = 0; |
258 List eventHandlers; | 259 List eventHandlers; |
259 RawReceivePort eventPort; | 260 RawReceivePort eventPort; |
260 | 261 |
261 // Indicates if native interrupts can be activated. | 262 // Indicates if native interrupts can be activated. |
262 bool canActivateEvents = true; | 263 bool canActivateEvents = true; |
263 | 264 |
264 // The type flags for this socket. | 265 // The type flags for this socket. |
265 final int typeFlags; | 266 final int typeFlags; |
266 | 267 |
267 // Holds the port of the socket, null if not known. | 268 // Holds the port of the socket, 0 if not known. |
268 int localPort; | 269 int localPort = 0; |
269 | 270 |
270 // Holds the address used to connect or bind the socket. | 271 // Holds the address used to connect or bind the socket. |
271 InternetAddress address; | 272 InternetAddress address; |
272 | 273 |
273 static Future<List<InternetAddress>> lookup( | 274 static Future<List<InternetAddress>> lookup( |
274 String host, {InternetAddressType type: InternetAddressType.ANY}) { | 275 String host, {InternetAddressType type: InternetAddressType.ANY}) { |
275 return _IOService.dispatch(_SOCKET_LOOKUP, [host, type._value]) | 276 return _IOService.dispatch(_SOCKET_LOOKUP, [host, type._value]) |
276 .then((response) { | 277 .then((response) { |
277 if (isErrorResponse(response)) { | 278 if (isErrorResponse(response)) { |
278 throw createError(response, "Failed host lookup: '$host'"); | 279 throw createError(response, "Failed host lookup: '$host'"); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 throw new SocketException("Failed to create server socket", | 393 throw new SocketException("Failed to create server socket", |
393 osError: result, | 394 osError: result, |
394 address: address, | 395 address: address, |
395 port: port); | 396 port: port); |
396 } | 397 } |
397 if (port != 0) socket.localPort = port; | 398 if (port != 0) socket.localPort = port; |
398 return socket; | 399 return socket; |
399 }); | 400 }); |
400 } | 401 } |
401 | 402 |
| 403 _NativeSocket.datagram(this.address, this.localPort) |
| 404 : typeFlags = TYPE_NORMAL_SOCKET { |
| 405 eventHandlers = new List(EVENT_COUNT + 1); |
| 406 nativeCreateBindDatagram(address._sockaddr_storage, localPort); |
| 407 } |
| 408 |
402 _NativeSocket.normal() : typeFlags = TYPE_NORMAL_SOCKET { | 409 _NativeSocket.normal() : typeFlags = TYPE_NORMAL_SOCKET { |
403 eventHandlers = new List(EVENT_COUNT + 1); | 410 eventHandlers = new List(EVENT_COUNT + 1); |
404 } | 411 } |
405 | 412 |
406 _NativeSocket.listen() : typeFlags = TYPE_LISTENING_SOCKET { | 413 _NativeSocket.listen() : typeFlags = TYPE_LISTENING_SOCKET { |
407 eventHandlers = new List(EVENT_COUNT + 1); | 414 eventHandlers = new List(EVENT_COUNT + 1); |
408 } | 415 } |
409 | 416 |
410 _NativeSocket.pipe() : typeFlags = TYPE_PIPE { | 417 _NativeSocket.pipe() : typeFlags = TYPE_PIPE { |
411 eventHandlers = new List(EVENT_COUNT + 1); | 418 eventHandlers = new List(EVENT_COUNT + 1); |
(...skipping 22 matching lines...) Expand all Loading... |
434 } | 441 } |
435 if (isClosing || isClosed) return null; | 442 if (isClosing || isClosed) return null; |
436 var result = nativeRead(len == null ? -1 : len); | 443 var result = nativeRead(len == null ? -1 : len); |
437 if (result is OSError) { | 444 if (result is OSError) { |
438 reportError(result, "Read failed"); | 445 reportError(result, "Read failed"); |
439 return null; | 446 return null; |
440 } | 447 } |
441 return result; | 448 return result; |
442 } | 449 } |
443 | 450 |
| 451 Datagram receive() { |
| 452 if (isClosing || isClosed) return null; |
| 453 var result = nativeRecvFrom(); |
| 454 if (result is OSError) { |
| 455 reportError(result, "Receive failed"); |
| 456 return null; |
| 457 } |
| 458 return result; |
| 459 } |
| 460 |
444 int write(List<int> buffer, int offset, int bytes) { | 461 int write(List<int> buffer, int offset, int bytes) { |
445 if (buffer is! List) throw new ArgumentError(); | 462 if (buffer is! List) throw new ArgumentError(); |
446 if (offset == null) offset = 0; | 463 if (offset == null) offset = 0; |
447 if (bytes == null) { | 464 if (bytes == null) { |
448 if (offset > buffer.length) { | 465 if (offset > buffer.length) { |
449 throw new RangeError.value(offset); | 466 throw new RangeError.value(offset); |
450 } | 467 } |
451 bytes = buffer.length - offset; | 468 bytes = buffer.length - offset; |
452 } | 469 } |
453 if (offset < 0) throw new RangeError.value(offset); | 470 if (offset < 0) throw new RangeError.value(offset); |
(...skipping 10 matching lines...) Expand all Loading... |
464 _ensureFastAndSerializableByteData(buffer, offset, offset + bytes); | 481 _ensureFastAndSerializableByteData(buffer, offset, offset + bytes); |
465 var result = | 482 var result = |
466 nativeWrite(bufferAndStart.buffer, bufferAndStart.start, bytes); | 483 nativeWrite(bufferAndStart.buffer, bufferAndStart.start, bytes); |
467 if (result is OSError) { | 484 if (result is OSError) { |
468 reportError(result, "Write failed"); | 485 reportError(result, "Write failed"); |
469 result = 0; | 486 result = 0; |
470 } | 487 } |
471 return result; | 488 return result; |
472 } | 489 } |
473 | 490 |
| 491 int sendTo(List<int> buffer, int offset, int bytes, |
| 492 InternetAddress address, int port) { |
| 493 if (isClosing || isClosed) return 0; |
| 494 _BufferAndStart bufferAndStart = |
| 495 _ensureFastAndSerializableByteData( |
| 496 buffer, offset, bytes); |
| 497 var result = nativeSendTo( |
| 498 bufferAndStart.buffer, bufferAndStart.start, bytes, |
| 499 address._sockaddr_storage, port); |
| 500 } |
| 501 |
474 _NativeSocket accept() { | 502 _NativeSocket accept() { |
475 // Don't issue accept if we're closing. | 503 // Don't issue accept if we're closing. |
476 if (isClosing || isClosed) return null; | 504 if (isClosing || isClosed) return null; |
477 var socket = new _NativeSocket.normal(); | 505 var socket = new _NativeSocket.normal(); |
478 if (nativeAccept(socket) != true) return null; | 506 if (nativeAccept(socket) != true) return null; |
479 socket.localPort = localPort; | 507 socket.localPort = localPort; |
480 socket.address = address; | 508 socket.address = address; |
481 return socket; | 509 return socket; |
482 } | 510 } |
483 | 511 |
484 int get port { | 512 int get port { |
485 if (localPort != null) return localPort; | 513 if (localPort != 0) return localPort; |
486 return localPort = nativeGetPort(); | 514 return localPort = nativeGetPort(); |
487 } | 515 } |
488 | 516 |
489 int get remotePort { | 517 int get remotePort { |
490 return nativeGetRemotePeer()[1]; | 518 return nativeGetRemotePeer()[1]; |
491 } | 519 } |
492 | 520 |
493 InternetAddress get remoteAddress { | 521 InternetAddress get remoteAddress { |
494 var result = nativeGetRemotePeer()[0]; | 522 var result = nativeGetRemotePeer()[0]; |
495 var type = new InternetAddressType._from(result[0]); | 523 var type = new InternetAddressType._from(result[0]); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
686 void reportError(error, String message) { | 714 void reportError(error, String message) { |
687 var e = createError(error, message, address, localPort); | 715 var e = createError(error, message, address, localPort); |
688 // Invoke the error handler if any. | 716 // Invoke the error handler if any. |
689 if (eventHandlers[ERROR_EVENT] != null) { | 717 if (eventHandlers[ERROR_EVENT] != null) { |
690 eventHandlers[ERROR_EVENT](e); | 718 eventHandlers[ERROR_EVENT](e); |
691 } | 719 } |
692 // For all errors we close the socket | 720 // For all errors we close the socket |
693 close(); | 721 close(); |
694 } | 722 } |
695 | 723 |
696 bool setOption(SocketOption option, bool enabled) { | 724 bool getOption(SocketOption option) { |
697 if (option is! SocketOption) throw new ArgumentError(options); | 725 if (option is! SocketOption) throw new ArgumentError(options); |
698 if (enabled is! bool) throw new ArgumentError(enabled); | 726 var result = nativeGetOption(option._value); |
699 return nativeSetOption(option._value, enabled); | 727 if (result is OSError) throw result; |
| 728 return result; |
| 729 } |
| 730 |
| 731 bool setOption(SocketOption option, value) { |
| 732 if (option is! SocketOption) throw new ArgumentError(options); |
| 733 var result = nativeSetOption(option._value, value); |
| 734 if (result is OSError) throw result; |
| 735 } |
| 736 |
| 737 void join(InternetAddress addr, NetworkInterface interface) { |
| 738 var result = nativeJoinMulticast(addr._sockaddr_storage, 0); |
| 739 if (result is OSError) throw result; |
| 740 } |
| 741 |
| 742 void leave(InternetAddress addr, NetworkInterface interface) { |
| 743 var result = nativeLeaveMulticast(addr._sockaddr_storage, 0); |
| 744 if (result is OSError) throw result; |
700 } | 745 } |
701 | 746 |
702 void nativeSetSocketId(int id) native "Socket_SetSocketId"; | 747 void nativeSetSocketId(int id) native "Socket_SetSocketId"; |
703 nativeAvailable() native "Socket_Available"; | 748 nativeAvailable() native "Socket_Available"; |
704 nativeRead(int len) native "Socket_Read"; | 749 nativeRead(int len) native "Socket_Read"; |
| 750 nativeRecvFrom() native "Socket_RecvFrom"; |
705 nativeWrite(List<int> buffer, int offset, int bytes) | 751 nativeWrite(List<int> buffer, int offset, int bytes) |
706 native "Socket_WriteList"; | 752 native "Socket_WriteList"; |
| 753 nativeSendTo(List<int> buffer, int offset, int bytes, |
| 754 List<int> address, int port) |
| 755 native "Socket_SendTo"; |
707 nativeCreateConnect(List<int> addr, | 756 nativeCreateConnect(List<int> addr, |
708 int port) native "Socket_CreateConnect"; | 757 int port) native "Socket_CreateConnect"; |
| 758 nativeCreateBindDatagram(List<int> addr, |
| 759 int port) native "Socket_CreateBindDatagram"; |
709 nativeCreateBindListen(List<int> addr, int port, int backlog, bool v6Only) | 760 nativeCreateBindListen(List<int> addr, int port, int backlog, bool v6Only) |
710 native "ServerSocket_CreateBindListen"; | 761 native "ServerSocket_CreateBindListen"; |
711 nativeAccept(_NativeSocket socket) native "ServerSocket_Accept"; | 762 nativeAccept(_NativeSocket socket) native "ServerSocket_Accept"; |
712 int nativeGetPort() native "Socket_GetPort"; | 763 int nativeGetPort() native "Socket_GetPort"; |
713 List nativeGetRemotePeer() native "Socket_GetRemotePeer"; | 764 List nativeGetRemotePeer() native "Socket_GetRemotePeer"; |
714 OSError nativeGetError() native "Socket_GetError"; | 765 OSError nativeGetError() native "Socket_GetError"; |
| 766 nativeGetOption(int option) native "Socket_GetOption"; |
715 bool nativeSetOption(int option, bool enabled) native "Socket_SetOption"; | 767 bool nativeSetOption(int option, bool enabled) native "Socket_SetOption"; |
| 768 bool nativeJoinMulticast(List<int> addr, int interface) |
| 769 native "Socket_JoinMulticast"; |
| 770 bool nativeLeaveMulticast(List<int> addr, int interface) |
| 771 native "Socket_LeaveMulticast"; |
716 } | 772 } |
717 | 773 |
718 | 774 |
719 class _RawServerSocket extends Stream<RawSocket> | 775 class _RawServerSocket extends Stream<RawSocket> |
720 implements RawServerSocket { | 776 implements RawServerSocket { |
721 final _NativeSocket _socket; | 777 final _NativeSocket _socket; |
722 StreamController<RawSocket> _controller; | 778 StreamController<RawSocket> _controller; |
723 | 779 |
724 static Future<_RawServerSocket> bind(address, | 780 static Future<_RawServerSocket> bind(address, |
725 int port, | 781 int port, |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1268 if (_detachReady != null) { | 1324 if (_detachReady != null) { |
1269 _detachReady.complete(null); | 1325 _detachReady.complete(null); |
1270 } else { | 1326 } else { |
1271 if (_raw != null) { | 1327 if (_raw != null) { |
1272 _raw.shutdown(SocketDirection.SEND); | 1328 _raw.shutdown(SocketDirection.SEND); |
1273 _disableWriteEvent(); | 1329 _disableWriteEvent(); |
1274 } | 1330 } |
1275 } | 1331 } |
1276 } | 1332 } |
1277 } | 1333 } |
| 1334 |
| 1335 |
| 1336 class _RawDatagramSocket extends Stream implements RawDatagramSocket { |
| 1337 _NativeSocket _socket; |
| 1338 StreamController<RawSocketEvent> _controller; |
| 1339 bool _readEventsEnabled = true; |
| 1340 bool _writeEventsEnabled = true; |
| 1341 |
| 1342 _RawDatagramSocket(InternetAddress address, int port) { |
| 1343 _socket = new _NativeSocket.datagram(address, port); |
| 1344 _controller = new StreamController(sync: true, |
| 1345 onListen: _onSubscriptionStateChange, |
| 1346 onCancel: _onSubscriptionStateChange, |
| 1347 onPause: _onPauseStateChange, |
| 1348 onResume: _onPauseStateChange); |
| 1349 _socket.closeFuture.then((_) => _controller.close()); |
| 1350 _socket.setHandlers( |
| 1351 read: () => _controller.add(RawSocketEvent.READ), |
| 1352 write: () { |
| 1353 // The write event handler is automatically disabled by the |
| 1354 // event handler when it fires. |
| 1355 _writeEventsEnabled = false; |
| 1356 _controller.add(RawSocketEvent.WRITE); |
| 1357 }, |
| 1358 closed: () => _controller.add(RawSocketEvent.READ_CLOSED), |
| 1359 destroyed: () => _controller.add(RawSocketEvent.CLOSED), |
| 1360 error: (e) { |
| 1361 _controller.addError(e); |
| 1362 close(); |
| 1363 } |
| 1364 ); |
| 1365 } |
| 1366 |
| 1367 StreamSubscription<RawSocketEvent> listen(void onData(RawSocketEvent event), |
| 1368 {Function onError, |
| 1369 void onDone(), |
| 1370 bool cancelOnError}) { |
| 1371 return _controller.stream.listen( |
| 1372 onData, |
| 1373 onError: onError, |
| 1374 onDone: onDone, |
| 1375 cancelOnError: cancelOnError); |
| 1376 } |
| 1377 |
| 1378 Future close() => _socket.close().then((_) => this); |
| 1379 |
| 1380 bool send(Datagram datagram) { |
| 1381 var result = _socket.sendTo(datagram.data, 0, datagram.data.length, |
| 1382 datagram.address, datagram.port); |
| 1383 if (result is OSError) { |
| 1384 throw result; |
| 1385 } |
| 1386 assert(result == datagram.data.length); |
| 1387 return true; |
| 1388 } |
| 1389 |
| 1390 bool sendTo(List<data> buffer, InternetAddress address, int port) { |
| 1391 var result = _socket.sendTo(buffer, 0, buffer.length, address, port); |
| 1392 if (result is OSError) { |
| 1393 throw result; |
| 1394 } |
| 1395 assert(result == buffer.length); |
| 1396 return true; |
| 1397 } |
| 1398 |
| 1399 Datagram receive() { |
| 1400 return _socket.receive(); |
| 1401 } |
| 1402 |
| 1403 void join(InternetAddress group, [NetworkInterface interface]) { |
| 1404 _socket.join(group, interface); |
| 1405 } |
| 1406 |
| 1407 void leave(InternetAddress group, [NetworkInterface interface]) { |
| 1408 _socket.leave(group, interface); |
| 1409 } |
| 1410 |
| 1411 bool get readEventsEnabled => _readEventsEnabled; |
| 1412 void set readEventsEnabled(bool value) { |
| 1413 if (value != _readEventsEnabled) { |
| 1414 _readEventsEnabled = value; |
| 1415 if (!_controller.isPaused) _resume(); |
| 1416 } |
| 1417 } |
| 1418 |
| 1419 bool get writeEventsEnabled => _writeEventsEnabled; |
| 1420 void set writeEventsEnabled(bool value) { |
| 1421 if (value != _writeEventsEnabled) { |
| 1422 _writeEventsEnabled = value; |
| 1423 if (!_controller.isPaused) _resume(); |
| 1424 } |
| 1425 } |
| 1426 |
| 1427 bool get multicastLoopback => |
| 1428 _socket.getOption(SocketOption._IP_MULTICAST_LOOP); |
| 1429 void set multicastLoopback(bool value) => |
| 1430 _socket.setOption(SocketOption._IP_MULTICAST_LOOP, value); |
| 1431 |
| 1432 int get multicastTTL => |
| 1433 _socket.getOption(SocketOption._IP_MULTICAST_TTL); |
| 1434 void set multicastTTL(int value) => |
| 1435 _socket.setOption(SocketOption._IP_MULTICAST_TTL, value); |
| 1436 |
| 1437 bool get broadcastEnabled => |
| 1438 _socket.getOption(SocketOption._IP_BROADCAST); |
| 1439 void set broadcastEnabled(bool value) => |
| 1440 _socket.setOption(SocketOption._IP_BROADCAST, value); |
| 1441 |
| 1442 int get port => _socket.port; |
| 1443 |
| 1444 InternetAddress get address => _socket.address; |
| 1445 |
| 1446 _pause() { |
| 1447 _socket.setListening(read: false, write: false); |
| 1448 } |
| 1449 |
| 1450 void _resume() { |
| 1451 _socket.setListening(read: _readEventsEnabled, write: _writeEventsEnabled); |
| 1452 } |
| 1453 |
| 1454 void _onPauseStateChange() { |
| 1455 if (_controller.isPaused) { |
| 1456 _pause(); |
| 1457 } else { |
| 1458 _resume(); |
| 1459 } |
| 1460 } |
| 1461 |
| 1462 void _onSubscriptionStateChange() { |
| 1463 if (_controller.hasListener) { |
| 1464 _resume(); |
| 1465 } else { |
| 1466 close(); |
| 1467 } |
| 1468 } |
| 1469 } |
| 1470 |
| 1471 Datagram _makeDatagram(List<int> data, |
| 1472 bool ipV6, |
| 1473 String address, |
| 1474 List<int> sockaddr_storage, |
| 1475 int port) { |
| 1476 var addressType = |
| 1477 ipV6 ? InternetAddressType.IP_V6 : InternetAddressType.IP_V4; |
| 1478 return new Datagram( |
| 1479 data, |
| 1480 new _InternetAddress(addressType, address, null, sockaddr_storage), |
| 1481 port); |
| 1482 } |
OLD | NEW |