| 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 |
| 6 @patch static Future<RawServerSocket> bind(address, | 6 class RawServerSocket { |
| 7 int port, | 7 @patch |
| 8 {int backlog: 0, | 8 static Future<RawServerSocket> bind(address, int port, |
| 9 bool v6Only: false, | 9 {int backlog: 0, bool v6Only: false, bool shared: false}) { |
| 10 bool shared: false}) { | |
| 11 return _RawServerSocket.bind(address, port, backlog, v6Only, shared); | 10 return _RawServerSocket.bind(address, port, backlog, v6Only, shared); |
| 12 } | 11 } |
| 13 } | 12 } |
| 14 | 13 |
| 15 | 14 @patch |
| 16 @patch class RawSocket { | 15 class RawSocket { |
| 17 @patch static Future<RawSocket> connect( | 16 @patch |
| 18 host, int port, {sourceAddress}) { | 17 static Future<RawSocket> connect(host, int port, {sourceAddress}) { |
| 19 return _RawSocket.connect(host, port, sourceAddress); | 18 return _RawSocket.connect(host, port, sourceAddress); |
| 20 } | 19 } |
| 21 } | 20 } |
| 22 | 21 |
| 23 | 22 @patch |
| 24 @patch class InternetAddress { | 23 class InternetAddress { |
| 25 @patch static InternetAddress get LOOPBACK_IP_V4 { | 24 @patch |
| 25 static InternetAddress get LOOPBACK_IP_V4 { |
| 26 return _InternetAddress.LOOPBACK_IP_V4; | 26 return _InternetAddress.LOOPBACK_IP_V4; |
| 27 } | 27 } |
| 28 | 28 |
| 29 @patch static InternetAddress get LOOPBACK_IP_V6 { | 29 @patch |
| 30 static InternetAddress get LOOPBACK_IP_V6 { |
| 30 return _InternetAddress.LOOPBACK_IP_V6; | 31 return _InternetAddress.LOOPBACK_IP_V6; |
| 31 } | 32 } |
| 32 | 33 |
| 33 @patch static InternetAddress get ANY_IP_V4 { | 34 @patch |
| 35 static InternetAddress get ANY_IP_V4 { |
| 34 return _InternetAddress.ANY_IP_V4; | 36 return _InternetAddress.ANY_IP_V4; |
| 35 } | 37 } |
| 36 | 38 |
| 37 @patch static InternetAddress get ANY_IP_V6 { | 39 @patch |
| 40 static InternetAddress get ANY_IP_V6 { |
| 38 return _InternetAddress.ANY_IP_V6; | 41 return _InternetAddress.ANY_IP_V6; |
| 39 } | 42 } |
| 40 | 43 |
| 41 @patch factory InternetAddress(String address) { | 44 @patch |
| 45 factory InternetAddress(String address) { |
| 42 return new _InternetAddress.parse(address); | 46 return new _InternetAddress.parse(address); |
| 43 } | 47 } |
| 44 | 48 |
| 45 @patch static Future<List<InternetAddress>> lookup( | 49 @patch |
| 46 String host, {InternetAddressType type: InternetAddressType.ANY}) { | 50 static Future<List<InternetAddress>> lookup(String host, |
| 51 {InternetAddressType type: InternetAddressType.ANY}) { |
| 47 return _NativeSocket.lookup(host, type: type); | 52 return _NativeSocket.lookup(host, type: type); |
| 48 } | 53 } |
| 49 | 54 |
| 50 @patch static InternetAddress _cloneWithNewHost( | 55 @patch |
| 56 static InternetAddress _cloneWithNewHost( |
| 51 InternetAddress address, String host) { | 57 InternetAddress address, String host) { |
| 52 return (address as _InternetAddress)._cloneWithNewHost(host); | 58 return (address as _InternetAddress)._cloneWithNewHost(host); |
| 53 } | 59 } |
| 54 } | 60 } |
| 55 | 61 |
| 56 @patch class NetworkInterface { | 62 @patch |
| 57 @patch static bool get listSupported { | 63 class NetworkInterface { |
| 64 @patch |
| 65 static bool get listSupported { |
| 58 return _listSupported(); | 66 return _listSupported(); |
| 59 } | 67 } |
| 60 | 68 |
| 61 @patch static Future<List<NetworkInterface>> list({ | 69 @patch |
| 62 bool includeLoopback: false, | 70 static Future<List<NetworkInterface>> list( |
| 71 {bool includeLoopback: false, |
| 63 bool includeLinkLocal: false, | 72 bool includeLinkLocal: false, |
| 64 InternetAddressType type: InternetAddressType.ANY}) { | 73 InternetAddressType type: InternetAddressType.ANY}) { |
| 65 return _NativeSocket.listInterfaces(includeLoopback: includeLoopback, | 74 return _NativeSocket.listInterfaces( |
| 66 includeLinkLocal: includeLinkLocal, | 75 includeLoopback: includeLoopback, |
| 67 type: type); | 76 includeLinkLocal: includeLinkLocal, |
| 77 type: type); |
| 68 } | 78 } |
| 69 | 79 |
| 70 static bool _listSupported() native "NetworkInterface_ListSupported"; | 80 static bool _listSupported() native "NetworkInterface_ListSupported"; |
| 71 } | 81 } |
| 72 | 82 |
| 73 void _throwOnBadPort(int port) { | 83 void _throwOnBadPort(int port) { |
| 74 if ((port == null) || (port < 0) || (port > 0xFFFF)) { | 84 if ((port == null) || (port < 0) || (port > 0xFFFF)) { |
| 75 throw new ArgumentError("Invalid port $port"); | 85 throw new ArgumentError("Invalid port $port"); |
| 76 } | 86 } |
| 77 } | 87 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 90 new _InternetAddress.fixed(_ADDRESS_LOOPBACK_IP_V6); | 100 new _InternetAddress.fixed(_ADDRESS_LOOPBACK_IP_V6); |
| 91 static _InternetAddress ANY_IP_V4 = | 101 static _InternetAddress ANY_IP_V4 = |
| 92 new _InternetAddress.fixed(_ADDRESS_ANY_IP_V4); | 102 new _InternetAddress.fixed(_ADDRESS_ANY_IP_V4); |
| 93 static _InternetAddress ANY_IP_V6 = | 103 static _InternetAddress ANY_IP_V6 = |
| 94 new _InternetAddress.fixed(_ADDRESS_ANY_IP_V6); | 104 new _InternetAddress.fixed(_ADDRESS_ANY_IP_V6); |
| 95 | 105 |
| 96 final String address; | 106 final String address; |
| 97 final String _host; | 107 final String _host; |
| 98 final Uint8List _in_addr; | 108 final Uint8List _in_addr; |
| 99 | 109 |
| 100 InternetAddressType get type => | 110 InternetAddressType get type => _in_addr.length == _IPV4_ADDR_LENGTH |
| 101 _in_addr.length == _IPV4_ADDR_LENGTH ? InternetAddressType.IP_V4 | 111 ? InternetAddressType.IP_V4 |
| 102 : InternetAddressType.IP_V6; | 112 : InternetAddressType.IP_V6; |
| 103 | 113 |
| 104 String get host => _host != null ? _host : address; | 114 String get host => _host != null ? _host : address; |
| 105 | 115 |
| 106 List<int> get rawAddress => new Uint8List.fromList(_in_addr); | 116 List<int> get rawAddress => new Uint8List.fromList(_in_addr); |
| 107 | 117 |
| 108 bool get isLoopback { | 118 bool get isLoopback { |
| 109 switch (type) { | 119 switch (type) { |
| 110 case InternetAddressType.IP_V4: | 120 case InternetAddressType.IP_V4: |
| 111 return _in_addr[0] == 127; | 121 return _in_addr[0] == 127; |
| 112 | 122 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 140 // Checking for ff00::/8. | 150 // Checking for ff00::/8. |
| 141 return _in_addr[0] == 0xFF; | 151 return _in_addr[0] == 0xFF; |
| 142 } | 152 } |
| 143 } | 153 } |
| 144 | 154 |
| 145 Future<InternetAddress> reverse() => _NativeSocket.reverseLookup(this); | 155 Future<InternetAddress> reverse() => _NativeSocket.reverseLookup(this); |
| 146 | 156 |
| 147 _InternetAddress(this.address, this._host, this._in_addr); | 157 _InternetAddress(this.address, this._host, this._in_addr); |
| 148 | 158 |
| 149 factory _InternetAddress.parse(String address) { | 159 factory _InternetAddress.parse(String address) { |
| 150 if (address is !String) { | 160 if (address is! String) { |
| 151 throw new ArgumentError("Invalid internet address $address"); | 161 throw new ArgumentError("Invalid internet address $address"); |
| 152 } | 162 } |
| 153 var in_addr = _parse(address); | 163 var in_addr = _parse(address); |
| 154 if (in_addr == null) { | 164 if (in_addr == null) { |
| 155 throw new ArgumentError("Invalid internet address $address"); | 165 throw new ArgumentError("Invalid internet address $address"); |
| 156 } | 166 } |
| 157 return new _InternetAddress(address, null, in_addr); | 167 return new _InternetAddress(address, null, in_addr); |
| 158 } | 168 } |
| 159 | 169 |
| 160 factory _InternetAddress.fixed(int id) { | 170 factory _InternetAddress.fixed(int id) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 final int index; | 226 final int index; |
| 217 final List<InternetAddress> addresses = []; | 227 final List<InternetAddress> addresses = []; |
| 218 | 228 |
| 219 _NetworkInterface(this.name, this.index); | 229 _NetworkInterface(this.name, this.index); |
| 220 | 230 |
| 221 String toString() { | 231 String toString() { |
| 222 return "NetworkInterface('$name', $addresses)"; | 232 return "NetworkInterface('$name', $addresses)"; |
| 223 } | 233 } |
| 224 } | 234 } |
| 225 | 235 |
| 226 | |
| 227 // The NativeFieldWrapperClass1 can not be used with a mixin, due to missing | 236 // The NativeFieldWrapperClass1 can not be used with a mixin, due to missing |
| 228 // implicit constructor. | 237 // implicit constructor. |
| 229 class _NativeSocketNativeWrapper extends NativeFieldWrapperClass1 {} | 238 class _NativeSocketNativeWrapper extends NativeFieldWrapperClass1 {} |
| 230 | 239 |
| 231 | |
| 232 // The _NativeSocket class encapsulates an OS socket. | 240 // The _NativeSocket class encapsulates an OS socket. |
| 233 class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { | 241 class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { |
| 234 // Bit flags used when communicating between the eventhandler and | 242 // Bit flags used when communicating between the eventhandler and |
| 235 // dart code. The EVENT flags are used to indicate events of | 243 // dart code. The EVENT flags are used to indicate events of |
| 236 // interest when sending a message from dart code to the | 244 // interest when sending a message from dart code to the |
| 237 // eventhandler. When receiving a message from the eventhandler the | 245 // eventhandler. When receiving a message from the eventhandler the |
| 238 // EVENT flags indicate the events that actually happened. The | 246 // EVENT flags indicate the events that actually happened. The |
| 239 // COMMAND flags are used to send commands from dart to the | 247 // COMMAND flags are used to send commands from dart to the |
| 240 // eventhandler. COMMAND flags are never received from the | 248 // eventhandler. COMMAND flags are never received from the |
| 241 // eventhandler. Additional flags are used to communicate other | 249 // eventhandler. Additional flags are used to communicate other |
| (...skipping 29 matching lines...) Expand all Loading... |
| 271 // Protocol flags. | 279 // Protocol flags. |
| 272 static const int TCP_SOCKET = 18; | 280 static const int TCP_SOCKET = 18; |
| 273 static const int UDP_SOCKET = 19; | 281 static const int UDP_SOCKET = 19; |
| 274 static const int INTERNAL_SOCKET = 20; | 282 static const int INTERNAL_SOCKET = 20; |
| 275 static const int TYPE_TCP_SOCKET = 1 << TCP_SOCKET; | 283 static const int TYPE_TCP_SOCKET = 1 << TCP_SOCKET; |
| 276 static const int TYPE_UDP_SOCKET = 1 << UDP_SOCKET; | 284 static const int TYPE_UDP_SOCKET = 1 << UDP_SOCKET; |
| 277 static const int TYPE_INTERNAL_SOCKET = 1 << INTERNAL_SOCKET; | 285 static const int TYPE_INTERNAL_SOCKET = 1 << INTERNAL_SOCKET; |
| 278 static const int TYPE_PROTOCOL_MASK = | 286 static const int TYPE_PROTOCOL_MASK = |
| 279 TYPE_TCP_SOCKET | TYPE_UDP_SOCKET | TYPE_INTERNAL_SOCKET; | 287 TYPE_TCP_SOCKET | TYPE_UDP_SOCKET | TYPE_INTERNAL_SOCKET; |
| 280 | 288 |
| 281 | |
| 282 // Native port messages. | 289 // Native port messages. |
| 283 static const HOST_NAME_LOOKUP = 0; | 290 static const HOST_NAME_LOOKUP = 0; |
| 284 static const LIST_INTERFACES = 1; | 291 static const LIST_INTERFACES = 1; |
| 285 static const REVERSE_LOOKUP = 2; | 292 static const REVERSE_LOOKUP = 2; |
| 286 | 293 |
| 287 // Protocol flags. | 294 // Protocol flags. |
| 288 static const int PROTOCOL_IPV4 = 1 << 0; | 295 static const int PROTOCOL_IPV4 = 1 << 0; |
| 289 static const int PROTOCOL_IPV6 = 1 << 1; | 296 static const int PROTOCOL_IPV6 = 1 << 1; |
| 290 | 297 |
| 291 static const int NORMAL_TOKEN_BATCH_SIZE = 8; | 298 static const int NORMAL_TOKEN_BATCH_SIZE = 8; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 bool writeEventIssued = false; | 335 bool writeEventIssued = false; |
| 329 bool writeAvailable = false; | 336 bool writeAvailable = false; |
| 330 | 337 |
| 331 static bool connectedResourceHandler = false; | 338 static bool connectedResourceHandler = false; |
| 332 _ReadWriteResourceInfo resourceInfo; | 339 _ReadWriteResourceInfo resourceInfo; |
| 333 | 340 |
| 334 // The owner object is the object that the Socket is being used by, e.g. | 341 // The owner object is the object that the Socket is being used by, e.g. |
| 335 // a HttpServer, a WebSocket connection, a process pipe, etc. | 342 // a HttpServer, a WebSocket connection, a process pipe, etc. |
| 336 Object owner; | 343 Object owner; |
| 337 | 344 |
| 338 static Future<List<InternetAddress>> lookup( | 345 static Future<List<InternetAddress>> lookup(String host, |
| 339 String host, {InternetAddressType type: InternetAddressType.ANY}) { | 346 {InternetAddressType type: InternetAddressType.ANY}) { |
| 340 return _IOService._dispatch(_SOCKET_LOOKUP, [host, type._value]) | 347 return _IOService |
| 341 .then((response) { | 348 ._dispatch(_SOCKET_LOOKUP, [host, type._value]).then((response) { |
| 342 if (isErrorResponse(response)) { | 349 if (isErrorResponse(response)) { |
| 343 throw createError(response, "Failed host lookup: '$host'"); | 350 throw createError(response, "Failed host lookup: '$host'"); |
| 344 } else { | 351 } else { |
| 345 return response.skip(1).map((result) { | 352 return response.skip(1).map((result) { |
| 346 var type = new InternetAddressType._from(result[0]); | 353 var type = new InternetAddressType._from(result[0]); |
| 347 return new _InternetAddress(result[1], host, result[2]); | 354 return new _InternetAddress(result[1], host, result[2]); |
| 348 }).toList(); | 355 }).toList(); |
| 349 } | 356 } |
| 350 }); | 357 }); |
| 351 } | 358 } |
| 352 | 359 |
| 353 static Future<InternetAddress> reverseLookup(InternetAddress addr) { | 360 static Future<InternetAddress> reverseLookup(InternetAddress addr) { |
| 354 return _IOService._dispatch(_SOCKET_REVERSE_LOOKUP, [addr._in_addr]) | 361 return _IOService |
| 355 .then((response) { | 362 ._dispatch(_SOCKET_REVERSE_LOOKUP, [addr._in_addr]).then((response) { |
| 356 if (isErrorResponse(response)) { | 363 if (isErrorResponse(response)) { |
| 357 throw createError(response, "Failed reverse host lookup", addr); | 364 throw createError(response, "Failed reverse host lookup", addr); |
| 358 } else { | 365 } else { |
| 359 return addr._cloneWithNewHost(response); | 366 return addr._cloneWithNewHost(response); |
| 360 } | 367 } |
| 361 }); | 368 }); |
| 362 } | 369 } |
| 363 | 370 |
| 364 static Future<List<NetworkInterface>> listInterfaces({ | 371 static Future<List<NetworkInterface>> listInterfaces( |
| 365 bool includeLoopback: false, | 372 {bool includeLoopback: false, |
| 366 bool includeLinkLocal: false, | 373 bool includeLinkLocal: false, |
| 367 InternetAddressType type: InternetAddressType.ANY}) { | 374 InternetAddressType type: InternetAddressType.ANY}) { |
| 368 return _IOService._dispatch(_SOCKET_LIST_INTERFACES, [type._value]) | 375 return _IOService |
| 369 .then((response) { | 376 ._dispatch(_SOCKET_LIST_INTERFACES, [type._value]).then((response) { |
| 370 if (isErrorResponse(response)) { | 377 if (isErrorResponse(response)) { |
| 371 throw createError(response, "Failed listing interfaces"); | 378 throw createError(response, "Failed listing interfaces"); |
| 372 } else { | 379 } else { |
| 373 var map = response.skip(1) | 380 var map = response.skip(1).fold(new Map<String, NetworkInterface>(), |
| 374 .fold(new Map<String, NetworkInterface>(), (map, result) { | 381 (map, result) { |
| 375 var type = new InternetAddressType._from(result[0]); | 382 var type = new InternetAddressType._from(result[0]); |
| 376 var name = result[3]; | 383 var name = result[3]; |
| 377 var index = result[4]; | 384 var index = result[4]; |
| 378 var address = new _InternetAddress(result[1], "", result[2]); | 385 var address = new _InternetAddress(result[1], "", result[2]); |
| 379 if (!includeLinkLocal && address.isLinkLocal) return map; | 386 if (!includeLinkLocal && address.isLinkLocal) return map; |
| 380 if (!includeLoopback && address.isLoopback) return map; | 387 if (!includeLoopback && address.isLoopback) return map; |
| 381 map.putIfAbsent( | 388 map.putIfAbsent(name, () => new _NetworkInterface(name, index)); |
| 382 name, () => new _NetworkInterface(name, index)); | 389 map[name].addresses.add(address); |
| 383 map[name].addresses.add(address); | 390 return map; |
| 384 return map; | |
| 385 }); | |
| 386 return map.values.toList(); | |
| 387 } | |
| 388 }); | 391 }); |
| 392 return map.values.toList(); |
| 393 } |
| 394 }); |
| 389 } | 395 } |
| 390 | 396 |
| 391 static Future<_NativeSocket> connect(host, int port, sourceAddress) { | 397 static Future<_NativeSocket> connect(host, int port, sourceAddress) { |
| 392 _throwOnBadPort(port); | 398 _throwOnBadPort(port); |
| 393 if (sourceAddress != null && sourceAddress is! _InternetAddress) { | 399 if (sourceAddress != null && sourceAddress is! _InternetAddress) { |
| 394 if (sourceAddress is String) { | 400 if (sourceAddress is String) { |
| 395 sourceAddress = new InternetAddress(sourceAddress); | 401 sourceAddress = new InternetAddress(sourceAddress); |
| 396 } | 402 } |
| 397 } | 403 } |
| 398 return new Future.value(host) | 404 return new Future.value(host).then((host) { |
| 399 .then((host) { | 405 if (host is _InternetAddress) return [host]; |
| 400 if (host is _InternetAddress) return [host]; | 406 return lookup(host).then((addresses) { |
| 401 return lookup(host) | 407 if (addresses.isEmpty) { |
| 402 .then((addresses) { | 408 throw createError(null, "Failed host lookup: '$host'"); |
| 403 if (addresses.isEmpty) { | 409 } |
| 404 throw createError(null, "Failed host lookup: '$host'"); | 410 return addresses; |
| 405 } | 411 }); |
| 406 return addresses; | 412 }).then((addresses) { |
| 407 }); | 413 assert(addresses is List); |
| 408 }) | 414 var completer = new Completer(); |
| 409 .then((addresses) { | 415 var it = addresses.iterator; |
| 410 assert(addresses is List); | 416 var error = null; |
| 411 var completer = new Completer(); | 417 var connecting = new HashMap(); |
| 412 var it = addresses.iterator; | 418 void connectNext() { |
| 413 var error = null; | 419 if (!it.moveNext()) { |
| 414 var connecting = new HashMap(); | 420 if (connecting.isEmpty) { |
| 415 void connectNext() { | 421 assert(error != null); |
| 416 if (!it.moveNext()) { | 422 completer.completeError(error); |
| 417 if (connecting.isEmpty) { | 423 } |
| 418 assert(error != null); | 424 return; |
| 419 completer.completeError(error); | 425 } |
| 420 } | 426 var address = it.current; |
| 421 return; | 427 var socket = new _NativeSocket.normal(); |
| 422 } | 428 socket.localAddress = address; |
| 423 var address = it.current; | 429 var result; |
| 424 var socket = new _NativeSocket.normal(); | 430 if (sourceAddress == null) { |
| 425 socket.localAddress = address; | 431 result = socket.nativeCreateConnect(address._in_addr, port); |
| 426 var result; | 432 } else { |
| 427 if (sourceAddress == null) { | 433 assert(sourceAddress is _InternetAddress); |
| 428 result = socket.nativeCreateConnect(address._in_addr, port); | 434 result = socket.nativeCreateBindConnect( |
| 435 address._in_addr, port, sourceAddress._in_addr); |
| 436 } |
| 437 if (result is OSError) { |
| 438 // Keep first error, if present. |
| 439 if (error == null) { |
| 440 int errorCode = result.errorCode; |
| 441 if (errorCode != null && socket.isBindError(errorCode)) { |
| 442 error = createError(result, "Bind failed", sourceAddress); |
| 429 } else { | 443 } else { |
| 430 assert(sourceAddress is _InternetAddress); | 444 error = createError(result, "Connection failed", address, port); |
| 431 result = socket.nativeCreateBindConnect( | |
| 432 address._in_addr, port, sourceAddress._in_addr); | |
| 433 } | |
| 434 if (result is OSError) { | |
| 435 // Keep first error, if present. | |
| 436 if (error == null) { | |
| 437 int errorCode = result.errorCode; | |
| 438 if (errorCode != null && socket.isBindError(errorCode)) { | |
| 439 error = createError(result, "Bind failed", sourceAddress); | |
| 440 } else { | |
| 441 error = | |
| 442 createError(result, "Connection failed", address, port); | |
| 443 } | |
| 444 } | |
| 445 connectNext(); | |
| 446 } else { | |
| 447 // Query the local port, for error messages. | |
| 448 try { | |
| 449 socket.port; | |
| 450 } catch (e) { | |
| 451 error = createError(e, "Connection failed", address, port); | |
| 452 connectNext(); | |
| 453 } | |
| 454 // Set up timer for when we should retry the next address | |
| 455 // (if any). | |
| 456 var duration = address.isLoopback ? | |
| 457 _RETRY_DURATION_LOOPBACK : | |
| 458 _RETRY_DURATION; | |
| 459 var timer = new Timer(duration, connectNext); | |
| 460 setupResourceInfo(socket); | |
| 461 | |
| 462 connecting[socket] = timer; | |
| 463 // Setup handlers for receiving the first write event which | |
| 464 // indicate that the socket is fully connected. | |
| 465 socket.setHandlers( | |
| 466 write: () { | |
| 467 timer.cancel(); | |
| 468 socket.setListening(read: false, write: false); | |
| 469 completer.complete(socket); | |
| 470 connecting.remove(socket); | |
| 471 connecting.forEach((s, t) { | |
| 472 t.cancel(); | |
| 473 s.close(); | |
| 474 s.setHandlers(); | |
| 475 s.setListening(read: false, write: false); | |
| 476 }); | |
| 477 }, | |
| 478 error: (e) { | |
| 479 timer.cancel(); | |
| 480 socket.close(); | |
| 481 // Keep first error, if present. | |
| 482 if (error == null) error = e; | |
| 483 connecting.remove(socket); | |
| 484 if (connecting.isEmpty) connectNext(); | |
| 485 }); | |
| 486 socket.setListening(read: false, write: true); | |
| 487 } | 445 } |
| 488 } | 446 } |
| 489 connectNext(); | 447 connectNext(); |
| 490 return completer.future; | 448 } else { |
| 491 }); | 449 // Query the local port, for error messages. |
| 450 try { |
| 451 socket.port; |
| 452 } catch (e) { |
| 453 error = createError(e, "Connection failed", address, port); |
| 454 connectNext(); |
| 455 } |
| 456 // Set up timer for when we should retry the next address |
| 457 // (if any). |
| 458 var duration = |
| 459 address.isLoopback ? _RETRY_DURATION_LOOPBACK : _RETRY_DURATION; |
| 460 var timer = new Timer(duration, connectNext); |
| 461 setupResourceInfo(socket); |
| 462 |
| 463 connecting[socket] = timer; |
| 464 // Setup handlers for receiving the first write event which |
| 465 // indicate that the socket is fully connected. |
| 466 socket.setHandlers(write: () { |
| 467 timer.cancel(); |
| 468 socket.setListening(read: false, write: false); |
| 469 completer.complete(socket); |
| 470 connecting.remove(socket); |
| 471 connecting.forEach((s, t) { |
| 472 t.cancel(); |
| 473 s.close(); |
| 474 s.setHandlers(); |
| 475 s.setListening(read: false, write: false); |
| 476 }); |
| 477 }, error: (e) { |
| 478 timer.cancel(); |
| 479 socket.close(); |
| 480 // Keep first error, if present. |
| 481 if (error == null) error = e; |
| 482 connecting.remove(socket); |
| 483 if (connecting.isEmpty) connectNext(); |
| 484 }); |
| 485 socket.setListening(read: false, write: true); |
| 486 } |
| 487 } |
| 488 |
| 489 connectNext(); |
| 490 return completer.future; |
| 491 }); |
| 492 } | 492 } |
| 493 | 493 |
| 494 static Future<_NativeSocket> bind(host, | 494 static Future<_NativeSocket> bind( |
| 495 int port, | 495 host, int port, int backlog, bool v6Only, bool shared) { |
| 496 int backlog, | |
| 497 bool v6Only, | |
| 498 bool shared) { | |
| 499 _throwOnBadPort(port); | 496 _throwOnBadPort(port); |
| 500 return new Future.value(host) | 497 return new Future.value(host).then((host) { |
| 501 .then((host) { | 498 if (host is _InternetAddress) return host; |
| 502 if (host is _InternetAddress) return host; | 499 return lookup(host).then((list) { |
| 503 return lookup(host) | 500 if (list.length == 0) { |
| 504 .then((list) { | 501 throw createError(null, "Failed host lookup: '$host'"); |
| 505 if (list.length == 0) { | 502 } |
| 506 throw createError(null, "Failed host lookup: '$host'"); | 503 return list[0]; |
| 507 } | 504 }); |
| 508 return list[0]; | 505 }).then((address) { |
| 509 }); | 506 var socket = new _NativeSocket.listen(); |
| 510 }) | 507 socket.localAddress = address; |
| 511 .then((address) { | 508 var result = socket.nativeCreateBindListen( |
| 512 var socket = new _NativeSocket.listen(); | 509 address._in_addr, port, backlog, v6Only, shared); |
| 513 socket.localAddress = address; | 510 if (result is OSError) { |
| 514 var result = socket.nativeCreateBindListen(address._in_addr, | 511 throw new SocketException("Failed to create server socket", |
| 515 port, | 512 osError: result, address: address, port: port); |
| 516 backlog, | 513 } |
| 517 v6Only, | 514 if (port != 0) socket.localPort = port; |
| 518 shared); | 515 setupResourceInfo(socket); |
| 519 if (result is OSError) { | 516 socket.connectToEventHandler(); |
| 520 throw new SocketException("Failed to create server socket", | 517 return socket; |
| 521 osError: result, | 518 }); |
| 522 address: address, | |
| 523 port: port); | |
| 524 } | |
| 525 if (port != 0) socket.localPort = port; | |
| 526 setupResourceInfo(socket); | |
| 527 socket.connectToEventHandler(); | |
| 528 return socket; | |
| 529 }); | |
| 530 } | 519 } |
| 531 | 520 |
| 532 static void setupResourceInfo(_NativeSocket socket) { | 521 static void setupResourceInfo(_NativeSocket socket) { |
| 533 socket.resourceInfo = new _SocketResourceInfo(socket); | 522 socket.resourceInfo = new _SocketResourceInfo(socket); |
| 534 } | 523 } |
| 535 | 524 |
| 536 static Future<_NativeSocket> bindDatagram( | 525 static Future<_NativeSocket> bindDatagram(host, int port, bool reuseAddress) { |
| 537 host, int port, bool reuseAddress) { | |
| 538 _throwOnBadPort(port); | 526 _throwOnBadPort(port); |
| 539 return new Future.value(host) | 527 return new Future.value(host).then((host) { |
| 540 .then((host) { | 528 if (host is _InternetAddress) return host; |
| 541 if (host is _InternetAddress) return host; | 529 return lookup(host).then((list) { |
| 542 return lookup(host) | 530 if (list.length == 0) { |
| 543 .then((list) { | 531 throw createError(null, "Failed host lookup: '$host'"); |
| 544 if (list.length == 0) { | 532 } |
| 545 throw createError(null, "Failed host lookup: '$host'"); | 533 return list[0]; |
| 546 } | 534 }); |
| 547 return list[0]; | 535 }).then((address) { |
| 548 }); | 536 var socket = new _NativeSocket.datagram(address); |
| 549 }) | 537 var result = |
| 550 .then((address) { | 538 socket.nativeCreateBindDatagram(address._in_addr, port, reuseAddress); |
| 551 var socket = new _NativeSocket.datagram(address); | 539 if (result is OSError) { |
| 552 var result = socket.nativeCreateBindDatagram( | 540 throw new SocketException("Failed to create datagram socket", |
| 553 address._in_addr, port, reuseAddress); | 541 osError: result, address: address, port: port); |
| 554 if (result is OSError) { | 542 } |
| 555 throw new SocketException("Failed to create datagram socket", | 543 if (port != 0) socket.localPort = port; |
| 556 osError: result, | 544 setupResourceInfo(socket); |
| 557 address: address, | 545 return socket; |
| 558 port: port); | 546 }); |
| 559 } | |
| 560 if (port != 0) socket.localPort = port; | |
| 561 setupResourceInfo(socket); | |
| 562 return socket; | |
| 563 }); | |
| 564 } | 547 } |
| 565 | 548 |
| 566 _NativeSocket.datagram(this.localAddress) | 549 _NativeSocket.datagram(this.localAddress) |
| 567 : typeFlags = TYPE_NORMAL_SOCKET | TYPE_UDP_SOCKET; | 550 : typeFlags = TYPE_NORMAL_SOCKET | TYPE_UDP_SOCKET; |
| 568 | 551 |
| 569 _NativeSocket.normal() : typeFlags = TYPE_NORMAL_SOCKET | TYPE_TCP_SOCKET; | 552 _NativeSocket.normal() : typeFlags = TYPE_NORMAL_SOCKET | TYPE_TCP_SOCKET; |
| 570 | 553 |
| 571 _NativeSocket.listen() : typeFlags = TYPE_LISTENING_SOCKET | TYPE_TCP_SOCKET { | 554 _NativeSocket.listen() : typeFlags = TYPE_LISTENING_SOCKET | TYPE_TCP_SOCKET { |
| 572 isClosedWrite = true; | 555 isClosedWrite = true; |
| 573 } | 556 } |
| 574 | 557 |
| 575 _NativeSocket.pipe() : typeFlags = TYPE_PIPE; | 558 _NativeSocket.pipe() : typeFlags = TYPE_PIPE; |
| 576 | 559 |
| 577 _NativeSocket.watch(int id) | 560 _NativeSocket.watch(int id) |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 // Negate the result, as stated above. | 661 // Negate the result, as stated above. |
| 679 if (result < 0) result = -result; | 662 if (result < 0) result = -result; |
| 680 // TODO(ricow): Remove when we track internal and pipe uses. | 663 // TODO(ricow): Remove when we track internal and pipe uses. |
| 681 assert(resourceInfo != null || isPipe || isInternal); | 664 assert(resourceInfo != null || isPipe || isInternal); |
| 682 if (resourceInfo != null) { | 665 if (resourceInfo != null) { |
| 683 resourceInfo.addWrite(result); | 666 resourceInfo.addWrite(result); |
| 684 } | 667 } |
| 685 return result; | 668 return result; |
| 686 } | 669 } |
| 687 | 670 |
| 688 int send(List<int> buffer, int offset, int bytes, | 671 int send(List<int> buffer, int offset, int bytes, InternetAddress address, |
| 689 InternetAddress address, int port) { | 672 int port) { |
| 690 _throwOnBadPort(port); | 673 _throwOnBadPort(port); |
| 691 if (isClosing || isClosed) return 0; | 674 if (isClosing || isClosed) return 0; |
| 692 _BufferAndStart bufferAndStart = | 675 _BufferAndStart bufferAndStart = |
| 693 _ensureFastAndSerializableByteData( | 676 _ensureFastAndSerializableByteData(buffer, offset, bytes); |
| 694 buffer, offset, bytes); | 677 var result = nativeSendTo(bufferAndStart.buffer, bufferAndStart.start, |
| 695 var result = nativeSendTo( | 678 bytes, address._in_addr, port); |
| 696 bufferAndStart.buffer, bufferAndStart.start, bytes, | |
| 697 address._in_addr, port); | |
| 698 if (result is OSError) { | 679 if (result is OSError) { |
| 699 OSError osError = result; | 680 OSError osError = result; |
| 700 scheduleMicrotask(() => reportError(osError, "Send failed")); | 681 scheduleMicrotask(() => reportError(osError, "Send failed")); |
| 701 result = 0; | 682 result = 0; |
| 702 } | 683 } |
| 703 // TODO(ricow): Remove when we track internal and pipe uses. | 684 // TODO(ricow): Remove when we track internal and pipe uses. |
| 704 assert(resourceInfo != null || isPipe || isInternal); | 685 assert(resourceInfo != null || isPipe || isInternal); |
| 705 if (resourceInfo != null) { | 686 if (resourceInfo != null) { |
| 706 resourceInfo.addWrite(result); | 687 resourceInfo.addWrite(result); |
| 707 } | 688 } |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 772 handler(); | 753 handler(); |
| 773 } | 754 } |
| 774 return; | 755 return; |
| 775 } | 756 } |
| 776 var handler = eventHandlers[READ_EVENT]; | 757 var handler = eventHandlers[READ_EVENT]; |
| 777 if (handler == null) return; | 758 if (handler == null) return; |
| 778 readEventIssued = true; | 759 readEventIssued = true; |
| 779 handler(); | 760 handler(); |
| 780 scheduleMicrotask(issue); | 761 scheduleMicrotask(issue); |
| 781 } | 762 } |
| 763 |
| 782 scheduleMicrotask(issue); | 764 scheduleMicrotask(issue); |
| 783 } | 765 } |
| 784 | 766 |
| 785 void issueWriteEvent({bool delayed: true}) { | 767 void issueWriteEvent({bool delayed: true}) { |
| 786 if (writeEventIssued) return; | 768 if (writeEventIssued) return; |
| 787 if (!writeAvailable) return; | 769 if (!writeAvailable) return; |
| 788 void issue() { | 770 void issue() { |
| 789 writeEventIssued = false; | 771 writeEventIssued = false; |
| 790 if (!writeAvailable) return; | 772 if (!writeAvailable) return; |
| 791 if (isClosing) return; | 773 if (isClosing) return; |
| 792 if (!sendWriteEvents) return; | 774 if (!sendWriteEvents) return; |
| 793 sendWriteEvents = false; | 775 sendWriteEvents = false; |
| 794 var handler = eventHandlers[WRITE_EVENT]; | 776 var handler = eventHandlers[WRITE_EVENT]; |
| 795 if (handler == null) return; | 777 if (handler == null) return; |
| 796 handler(); | 778 handler(); |
| 797 } | 779 } |
| 780 |
| 798 if (delayed) { | 781 if (delayed) { |
| 799 writeEventIssued = true; | 782 writeEventIssued = true; |
| 800 scheduleMicrotask(issue); | 783 scheduleMicrotask(issue); |
| 801 } else { | 784 } else { |
| 802 issue(); | 785 issue(); |
| 803 } | 786 } |
| 804 } | 787 } |
| 805 | 788 |
| 806 // Multiplexes socket events to the socket handlers. | 789 // Multiplexes socket events to the socket handlers. |
| 807 void multiplex(int events) { | 790 void multiplex(int events) { |
| 808 for (int i = FIRST_EVENT; i <= LAST_EVENT; i++) { | 791 for (int i = FIRST_EVENT; i <= LAST_EVENT; i++) { |
| 809 if (((events & (1 << i)) != 0)) { | 792 if (((events & (1 << i)) != 0)) { |
| 810 if ((i == CLOSED_EVENT || i == READ_EVENT) && isClosedRead) continue; | 793 if ((i == CLOSED_EVENT || i == READ_EVENT) && isClosedRead) continue; |
| 811 if (isClosing && i != DESTROYED_EVENT) continue; | 794 if (isClosing && i != DESTROYED_EVENT) continue; |
| 812 if (i == CLOSED_EVENT && | 795 if (i == CLOSED_EVENT && !isListening && !isClosing && !isClosed) { |
| 813 !isListening && | |
| 814 !isClosing && | |
| 815 !isClosed) { | |
| 816 isClosedRead = true; | 796 isClosedRead = true; |
| 817 issueReadEvent(); | 797 issueReadEvent(); |
| 818 continue; | 798 continue; |
| 819 } | 799 } |
| 820 | 800 |
| 821 if (i == WRITE_EVENT) { | 801 if (i == WRITE_EVENT) { |
| 822 writeAvailable = true; | 802 writeAvailable = true; |
| 823 issueWriteEvent(delayed: false); | 803 issueWriteEvent(delayed: false); |
| 824 continue; | 804 continue; |
| 825 } | 805 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 955 connectToEventHandler(); | 935 connectToEventHandler(); |
| 956 _EventHandler._sendData(this, eventPort.sendPort, fullData); | 936 _EventHandler._sendData(this, eventPort.sendPort, fullData); |
| 957 } | 937 } |
| 958 | 938 |
| 959 void connectToEventHandler() { | 939 void connectToEventHandler() { |
| 960 assert(!isClosed); | 940 assert(!isClosed); |
| 961 if (eventPort == null) { | 941 if (eventPort == null) { |
| 962 eventPort = new RawReceivePort(multiplex); | 942 eventPort = new RawReceivePort(multiplex); |
| 963 } | 943 } |
| 964 if (!connectedResourceHandler) { | 944 if (!connectedResourceHandler) { |
| 965 registerExtension('ext.dart.io.getOpenSockets', | 945 registerExtension( |
| 966 _SocketResourceInfo.getOpenSockets); | 946 'ext.dart.io.getOpenSockets', _SocketResourceInfo.getOpenSockets); |
| 967 registerExtension('ext.dart.io.getSocketByID', | 947 registerExtension('ext.dart.io.getSocketByID', |
| 968 _SocketResourceInfo.getSocketInfoMapByID); | 948 _SocketResourceInfo.getSocketInfoMapByID); |
| 969 | 949 |
| 970 connectedResourceHandler = true; | 950 connectedResourceHandler = true; |
| 971 } | 951 } |
| 972 } | 952 } |
| 973 | 953 |
| 974 void disconnectFromEventHandler() { | 954 void disconnectFromEventHandler() { |
| 975 assert(eventPort != null); | 955 assert(eventPort != null); |
| 976 eventPort.close(); | 956 eventPort.close(); |
| 977 eventPort = null; | 957 eventPort = null; |
| 978 // Now that we don't track this Socket anymore, we can clear the owner | 958 // Now that we don't track this Socket anymore, we can clear the owner |
| 979 // field. | 959 // field. |
| 980 owner = null; | 960 owner = null; |
| 981 } | 961 } |
| 982 | 962 |
| 983 // Check whether this is an error response from a native port call. | 963 // Check whether this is an error response from a native port call. |
| 984 static bool isErrorResponse(response) { | 964 static bool isErrorResponse(response) { |
| 985 return response is List && response[0] != _SUCCESS_RESPONSE; | 965 return response is List && response[0] != _SUCCESS_RESPONSE; |
| 986 } | 966 } |
| 987 | 967 |
| 988 // Create the appropriate error/exception from different returned | 968 // Create the appropriate error/exception from different returned |
| 989 // error objects. | 969 // error objects. |
| 990 static createError(error, | 970 static createError(error, String message, |
| 991 String message, | 971 [InternetAddress address, int port]) { |
| 992 [InternetAddress address, | |
| 993 int port]) { | |
| 994 if (error is OSError) { | 972 if (error is OSError) { |
| 995 return new SocketException( | 973 return new SocketException(message, |
| 996 message, osError: error, address: address, port: port); | 974 osError: error, address: address, port: port); |
| 997 } else if (error is List) { | 975 } else if (error is List) { |
| 998 assert(isErrorResponse(error)); | 976 assert(isErrorResponse(error)); |
| 999 switch (error[0]) { | 977 switch (error[0]) { |
| 1000 case _ILLEGAL_ARGUMENT_RESPONSE: | 978 case _ILLEGAL_ARGUMENT_RESPONSE: |
| 1001 return new ArgumentError(); | 979 return new ArgumentError(); |
| 1002 case _OSERROR_RESPONSE: | 980 case _OSERROR_RESPONSE: |
| 1003 return new SocketException(message, | 981 return new SocketException(message, |
| 1004 osError: new OSError(error[2], error[1]), | 982 osError: new OSError(error[2], error[1]), |
| 1005 address: address, | 983 address: address, |
| 1006 port: port); | 984 port: port); |
| 1007 default: | 985 default: |
| 1008 return new Exception("Unknown error"); | 986 return new Exception("Unknown error"); |
| 1009 } | 987 } |
| 1010 } else { | 988 } else { |
| 1011 return new SocketException(message, address: address, port: port); | 989 return new SocketException(message, address: address, port: port); |
| 1012 } | 990 } |
| 1013 } | 991 } |
| 1014 | 992 |
| 1015 void reportError(error, String message) { | 993 void reportError(error, String message) { |
| 1016 var e = createError(error, message, address, localPort); | 994 var e = createError(error, message, address, localPort); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 return InternetAddress.ANY_IP_V4; | 1033 return InternetAddress.ANY_IP_V4; |
| 1056 } | 1034 } |
| 1057 } else { | 1035 } else { |
| 1058 return null; | 1036 return null; |
| 1059 } | 1037 } |
| 1060 } | 1038 } |
| 1061 | 1039 |
| 1062 void joinMulticast(InternetAddress addr, NetworkInterface interface) { | 1040 void joinMulticast(InternetAddress addr, NetworkInterface interface) { |
| 1063 var interfaceAddr = multicastAddress(addr, interface); | 1041 var interfaceAddr = multicastAddress(addr, interface); |
| 1064 var interfaceIndex = interface == null ? 0 : interface.index; | 1042 var interfaceIndex = interface == null ? 0 : interface.index; |
| 1065 var result = nativeJoinMulticast( | 1043 var result = nativeJoinMulticast(addr._in_addr, |
| 1066 addr._in_addr, | 1044 interfaceAddr == null ? null : interfaceAddr._in_addr, interfaceIndex); |
| 1067 interfaceAddr == null ? null : interfaceAddr._in_addr, | |
| 1068 interfaceIndex); | |
| 1069 if (result is OSError) throw result; | 1045 if (result is OSError) throw result; |
| 1070 } | 1046 } |
| 1071 | 1047 |
| 1072 void leaveMulticast(InternetAddress addr, NetworkInterface interface) { | 1048 void leaveMulticast(InternetAddress addr, NetworkInterface interface) { |
| 1073 var interfaceAddr = multicastAddress(addr, interface); | 1049 var interfaceAddr = multicastAddress(addr, interface); |
| 1074 var interfaceIndex = interface == null ? 0 : interface.index; | 1050 var interfaceIndex = interface == null ? 0 : interface.index; |
| 1075 var result = nativeLeaveMulticast( | 1051 var result = nativeLeaveMulticast(addr._in_addr, |
| 1076 addr._in_addr, | 1052 interfaceAddr == null ? null : interfaceAddr._in_addr, interfaceIndex); |
| 1077 interfaceAddr == null ? null : interfaceAddr._in_addr, | |
| 1078 interfaceIndex); | |
| 1079 if (result is OSError) throw result; | 1053 if (result is OSError) throw result; |
| 1080 } | 1054 } |
| 1081 | 1055 |
| 1082 | |
| 1083 void nativeSetSocketId(int id) native "Socket_SetSocketId"; | 1056 void nativeSetSocketId(int id) native "Socket_SetSocketId"; |
| 1084 nativeAvailable() native "Socket_Available"; | 1057 nativeAvailable() native "Socket_Available"; |
| 1085 nativeRead(int len) native "Socket_Read"; | 1058 nativeRead(int len) native "Socket_Read"; |
| 1086 nativeRecvFrom() native "Socket_RecvFrom"; | 1059 nativeRecvFrom() native "Socket_RecvFrom"; |
| 1087 nativeWrite(List<int> buffer, int offset, int bytes) | 1060 nativeWrite(List<int> buffer, int offset, int bytes) |
| 1088 native "Socket_WriteList"; | 1061 native "Socket_WriteList"; |
| 1089 nativeSendTo(List<int> buffer, int offset, int bytes, | 1062 nativeSendTo(List<int> buffer, int offset, int bytes, List<int> address, |
| 1090 List<int> address, int port) | 1063 int port) native "Socket_SendTo"; |
| 1091 native "Socket_SendTo"; | 1064 nativeCreateConnect(List<int> addr, int port) native "Socket_CreateConnect"; |
| 1092 nativeCreateConnect(List<int> addr, | 1065 nativeCreateBindConnect(List<int> addr, int port, List<int> sourceAddr) |
| 1093 int port) native "Socket_CreateConnect"; | |
| 1094 nativeCreateBindConnect( | |
| 1095 List<int> addr, int port, List<int> sourceAddr) | |
| 1096 native "Socket_CreateBindConnect"; | 1066 native "Socket_CreateBindConnect"; |
| 1097 bool isBindError(int errorNumber) native "Socket_IsBindError"; | 1067 bool isBindError(int errorNumber) native "Socket_IsBindError"; |
| 1098 nativeCreateBindListen(List<int> addr, int port, int backlog, bool v6Only, | 1068 nativeCreateBindListen(List<int> addr, int port, int backlog, bool v6Only, |
| 1099 bool shared) | 1069 bool shared) native "ServerSocket_CreateBindListen"; |
| 1100 native "ServerSocket_CreateBindListen"; | |
| 1101 nativeCreateBindDatagram(List<int> addr, int port, bool reuseAddress) | 1070 nativeCreateBindDatagram(List<int> addr, int port, bool reuseAddress) |
| 1102 native "Socket_CreateBindDatagram"; | 1071 native "Socket_CreateBindDatagram"; |
| 1103 nativeAccept(_NativeSocket socket) native "ServerSocket_Accept"; | 1072 nativeAccept(_NativeSocket socket) native "ServerSocket_Accept"; |
| 1104 int nativeGetPort() native "Socket_GetPort"; | 1073 int nativeGetPort() native "Socket_GetPort"; |
| 1105 List nativeGetRemotePeer() native "Socket_GetRemotePeer"; | 1074 List nativeGetRemotePeer() native "Socket_GetRemotePeer"; |
| 1106 int nativeGetSocketId() native "Socket_GetSocketId"; | 1075 int nativeGetSocketId() native "Socket_GetSocketId"; |
| 1107 OSError nativeGetError() native "Socket_GetError"; | 1076 OSError nativeGetError() native "Socket_GetError"; |
| 1108 nativeGetOption(int option, int protocol) native "Socket_GetOption"; | 1077 nativeGetOption(int option, int protocol) native "Socket_GetOption"; |
| 1109 bool nativeSetOption(int option, int protocol, value) | 1078 bool nativeSetOption(int option, int protocol, value) |
| 1110 native "Socket_SetOption"; | 1079 native "Socket_SetOption"; |
| 1111 OSError nativeJoinMulticast( | 1080 OSError nativeJoinMulticast(List<int> addr, List<int> interfaceAddr, |
| 1112 List<int> addr, List<int> interfaceAddr, int interfaceIndex) | 1081 int interfaceIndex) native "Socket_JoinMulticast"; |
| 1113 native "Socket_JoinMulticast"; | 1082 bool nativeLeaveMulticast(List<int> addr, List<int> interfaceAddr, |
| 1114 bool nativeLeaveMulticast( | 1083 int interfaceIndex) native "Socket_LeaveMulticast"; |
| 1115 List<int> addr, List<int> interfaceAddr, int interfaceIndex) | |
| 1116 native "Socket_LeaveMulticast"; | |
| 1117 } | 1084 } |
| 1118 | 1085 |
| 1119 | 1086 class _RawServerSocket extends Stream<RawSocket> implements RawServerSocket { |
| 1120 class _RawServerSocket extends Stream<RawSocket> | |
| 1121 implements RawServerSocket { | |
| 1122 final _NativeSocket _socket; | 1087 final _NativeSocket _socket; |
| 1123 StreamController<RawSocket> _controller; | 1088 StreamController<RawSocket> _controller; |
| 1124 ReceivePort _referencePort; | 1089 ReceivePort _referencePort; |
| 1125 bool _v6Only; | 1090 bool _v6Only; |
| 1126 | 1091 |
| 1127 static Future<_RawServerSocket> bind(address, | 1092 static Future<_RawServerSocket> bind( |
| 1128 int port, | 1093 address, int port, int backlog, bool v6Only, bool shared) { |
| 1129 int backlog, | |
| 1130 bool v6Only, | |
| 1131 bool shared) { | |
| 1132 _throwOnBadPort(port); | 1094 _throwOnBadPort(port); |
| 1133 if (backlog < 0) throw new ArgumentError("Invalid backlog $backlog"); | 1095 if (backlog < 0) throw new ArgumentError("Invalid backlog $backlog"); |
| 1134 return _NativeSocket.bind(address, port, backlog, v6Only, shared) | 1096 return _NativeSocket |
| 1097 .bind(address, port, backlog, v6Only, shared) |
| 1135 .then((socket) => new _RawServerSocket(socket, v6Only)); | 1098 .then((socket) => new _RawServerSocket(socket, v6Only)); |
| 1136 } | 1099 } |
| 1137 | 1100 |
| 1138 _RawServerSocket(this._socket, this._v6Only); | 1101 _RawServerSocket(this._socket, this._v6Only); |
| 1139 | 1102 |
| 1140 StreamSubscription<RawSocket> listen(void onData(RawSocket event), | 1103 StreamSubscription<RawSocket> listen(void onData(RawSocket event), |
| 1141 {Function onError, | 1104 {Function onError, void onDone(), bool cancelOnError}) { |
| 1142 void onDone(), | |
| 1143 bool cancelOnError}) { | |
| 1144 if (_controller != null) { | 1105 if (_controller != null) { |
| 1145 throw new StateError("Stream was already listened to"); | 1106 throw new StateError("Stream was already listened to"); |
| 1146 } | 1107 } |
| 1147 var zone = Zone.current; | 1108 var zone = Zone.current; |
| 1148 _controller = new StreamController(sync: true, | 1109 _controller = new StreamController( |
| 1110 sync: true, |
| 1149 onListen: _onSubscriptionStateChange, | 1111 onListen: _onSubscriptionStateChange, |
| 1150 onCancel: _onSubscriptionStateChange, | 1112 onCancel: _onSubscriptionStateChange, |
| 1151 onPause: _onPauseStateChange, | 1113 onPause: _onPauseStateChange, |
| 1152 onResume: _onPauseStateChange); | 1114 onResume: _onPauseStateChange); |
| 1153 _socket.setHandlers( | 1115 _socket.setHandlers(read: zone.bindCallback(() { |
| 1154 read: zone.bindCallback(() { | 1116 while (_socket.available > 0) { |
| 1155 while (_socket.available > 0) { | 1117 var socket = _socket.accept(); |
| 1156 var socket = _socket.accept(); | 1118 if (socket == null) return; |
| 1157 if (socket == null) return; | 1119 _controller.add(new _RawSocket(socket)); |
| 1158 _controller.add(new _RawSocket(socket)); | 1120 if (_controller.isPaused) return; |
| 1159 if (_controller.isPaused) return; | 1121 } |
| 1160 } | 1122 }), error: zone.bindUnaryCallback((e) { |
| 1161 }), | 1123 _controller.addError(e); |
| 1162 error: zone.bindUnaryCallback((e) { | 1124 _controller.close(); |
| 1163 _controller.addError(e); | 1125 }), destroyed: () { |
| 1164 _controller.close(); | 1126 _controller.close(); |
| 1165 }), | 1127 if (_referencePort != null) { |
| 1166 destroyed: () { | 1128 _referencePort.close(); |
| 1167 _controller.close(); | 1129 _referencePort = null; |
| 1168 if (_referencePort != null) { | 1130 } |
| 1169 _referencePort.close(); | 1131 }); |
| 1170 _referencePort = null; | 1132 return _controller.stream.listen(onData, |
| 1171 } | 1133 onError: onError, onDone: onDone, cancelOnError: cancelOnError); |
| 1172 }); | |
| 1173 return _controller.stream.listen( | |
| 1174 onData, | |
| 1175 onError: onError, | |
| 1176 onDone: onDone, | |
| 1177 cancelOnError: cancelOnError); | |
| 1178 } | 1134 } |
| 1179 | 1135 |
| 1180 int get port => _socket.port; | 1136 int get port => _socket.port; |
| 1181 | 1137 |
| 1182 InternetAddress get address => _socket.address; | 1138 InternetAddress get address => _socket.address; |
| 1183 | 1139 |
| 1184 Future close() { | 1140 Future close() { |
| 1185 return _socket.close().then((_) { | 1141 return _socket.close().then((_) { |
| 1186 if (_referencePort != null) { | 1142 if (_referencePort != null) { |
| 1187 _referencePort.close(); | 1143 _referencePort.close(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1208 } | 1164 } |
| 1209 | 1165 |
| 1210 void _onPauseStateChange() { | 1166 void _onPauseStateChange() { |
| 1211 if (_controller.isPaused) { | 1167 if (_controller.isPaused) { |
| 1212 _pause(); | 1168 _pause(); |
| 1213 } else { | 1169 } else { |
| 1214 _resume(); | 1170 _resume(); |
| 1215 } | 1171 } |
| 1216 } | 1172 } |
| 1217 | 1173 |
| 1218 void set _owner(owner) { _socket.owner = owner; } | 1174 void set _owner(owner) { |
| 1175 _socket.owner = owner; |
| 1176 } |
| 1219 } | 1177 } |
| 1220 | 1178 |
| 1221 | 1179 class _RawSocket extends Stream<RawSocketEvent> implements RawSocket { |
| 1222 class _RawSocket extends Stream<RawSocketEvent> | |
| 1223 implements RawSocket { | |
| 1224 final _NativeSocket _socket; | 1180 final _NativeSocket _socket; |
| 1225 StreamController<RawSocketEvent> _controller; | 1181 StreamController<RawSocketEvent> _controller; |
| 1226 bool _readEventsEnabled = true; | 1182 bool _readEventsEnabled = true; |
| 1227 bool _writeEventsEnabled = true; | 1183 bool _writeEventsEnabled = true; |
| 1228 | 1184 |
| 1229 // Flag to handle Ctrl-D closing of stdio on Mac OS. | 1185 // Flag to handle Ctrl-D closing of stdio on Mac OS. |
| 1230 bool _isMacOSTerminalInput = false; | 1186 bool _isMacOSTerminalInput = false; |
| 1231 | 1187 |
| 1232 static Future<RawSocket> connect(host, int port, sourceAddress) { | 1188 static Future<RawSocket> connect(host, int port, sourceAddress) { |
| 1233 return _NativeSocket.connect(host, port, sourceAddress) | 1189 return _NativeSocket |
| 1190 .connect(host, port, sourceAddress) |
| 1234 .then((socket) => new _RawSocket(socket)); | 1191 .then((socket) => new _RawSocket(socket)); |
| 1235 } | 1192 } |
| 1236 | 1193 |
| 1237 _RawSocket(this._socket) { | 1194 _RawSocket(this._socket) { |
| 1238 var zone = Zone.current; | 1195 var zone = Zone.current; |
| 1239 _controller = new StreamController(sync: true, | 1196 _controller = new StreamController( |
| 1197 sync: true, |
| 1240 onListen: _onSubscriptionStateChange, | 1198 onListen: _onSubscriptionStateChange, |
| 1241 onCancel: _onSubscriptionStateChange, | 1199 onCancel: _onSubscriptionStateChange, |
| 1242 onPause: _onPauseStateChange, | 1200 onPause: _onPauseStateChange, |
| 1243 onResume: _onPauseStateChange); | 1201 onResume: _onPauseStateChange); |
| 1244 _socket.setHandlers( | 1202 _socket.setHandlers( |
| 1245 read: () => _controller.add(RawSocketEvent.READ), | 1203 read: () => _controller.add(RawSocketEvent.READ), |
| 1246 write: () { | 1204 write: () { |
| 1247 // The write event handler is automatically disabled by the | 1205 // The write event handler is automatically disabled by the |
| 1248 // event handler when it fires. | 1206 // event handler when it fires. |
| 1249 _writeEventsEnabled = false; | 1207 _writeEventsEnabled = false; |
| 1250 _controller.add(RawSocketEvent.WRITE); | 1208 _controller.add(RawSocketEvent.WRITE); |
| 1251 }, | 1209 }, |
| 1252 closed: () => _controller.add(RawSocketEvent.READ_CLOSED), | 1210 closed: () => _controller.add(RawSocketEvent.READ_CLOSED), |
| 1253 destroyed: () { | 1211 destroyed: () { |
| 1254 _controller.add(RawSocketEvent.CLOSED); | 1212 _controller.add(RawSocketEvent.CLOSED); |
| 1255 _controller.close(); | 1213 _controller.close(); |
| 1256 }, | 1214 }, |
| 1257 error: zone.bindUnaryCallback((e) { | 1215 error: zone.bindUnaryCallback((e) { |
| 1258 _controller.addError(e); | 1216 _controller.addError(e); |
| 1259 _socket.close(); | 1217 _socket.close(); |
| 1260 }) | 1218 })); |
| 1261 ); | |
| 1262 } | 1219 } |
| 1263 | 1220 |
| 1264 factory _RawSocket._writePipe() { | 1221 factory _RawSocket._writePipe() { |
| 1265 var native = new _NativeSocket.pipe(); | 1222 var native = new _NativeSocket.pipe(); |
| 1266 native.isClosedRead = true; | 1223 native.isClosedRead = true; |
| 1267 native.closedReadEventSent = true; | 1224 native.closedReadEventSent = true; |
| 1268 return new _RawSocket(native); | 1225 return new _RawSocket(native); |
| 1269 } | 1226 } |
| 1270 | 1227 |
| 1271 factory _RawSocket._readPipe(int fd) { | 1228 factory _RawSocket._readPipe(int fd) { |
| 1272 var native = new _NativeSocket.pipe(); | 1229 var native = new _NativeSocket.pipe(); |
| 1273 native.isClosedWrite = true; | 1230 native.isClosedWrite = true; |
| 1274 if (fd != null) _getStdioHandle(native, fd); | 1231 if (fd != null) _getStdioHandle(native, fd); |
| 1275 var result = new _RawSocket(native); | 1232 var result = new _RawSocket(native); |
| 1276 if (fd != null) { | 1233 if (fd != null) { |
| 1277 var socketType = _StdIOUtils._nativeSocketType(result._socket); | 1234 var socketType = _StdIOUtils._nativeSocketType(result._socket); |
| 1278 result._isMacOSTerminalInput = | 1235 result._isMacOSTerminalInput = |
| 1279 Platform.isMacOS && socketType == _STDIO_HANDLE_TYPE_TERMINAL; | 1236 Platform.isMacOS && socketType == _STDIO_HANDLE_TYPE_TERMINAL; |
| 1280 } | 1237 } |
| 1281 return result; | 1238 return result; |
| 1282 } | 1239 } |
| 1283 | 1240 |
| 1284 StreamSubscription<RawSocketEvent> listen(void onData(RawSocketEvent event), | 1241 StreamSubscription<RawSocketEvent> listen(void onData(RawSocketEvent event), |
| 1285 {Function onError, | 1242 {Function onError, void onDone(), bool cancelOnError}) { |
| 1286 void onDone(), | 1243 return _controller.stream.listen(onData, |
| 1287 bool cancelOnError}) { | 1244 onError: onError, onDone: onDone, cancelOnError: cancelOnError); |
| 1288 return _controller.stream.listen( | |
| 1289 onData, | |
| 1290 onError: onError, | |
| 1291 onDone: onDone, | |
| 1292 cancelOnError: cancelOnError); | |
| 1293 } | 1245 } |
| 1294 | 1246 |
| 1295 int available() => _socket.available; | 1247 int available() => _socket.available; |
| 1296 | 1248 |
| 1297 List<int> read([int len]) { | 1249 List<int> read([int len]) { |
| 1298 if (_isMacOSTerminalInput) { | 1250 if (_isMacOSTerminalInput) { |
| 1299 var available = this.available(); | 1251 var available = this.available(); |
| 1300 if (available == 0) return null; | 1252 if (available == 0) return null; |
| 1301 var data = _socket.read(len); | 1253 var data = _socket.read(len); |
| 1302 if (data == null || data.length < available) { | 1254 if (data == null || data.length < available) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1361 } | 1313 } |
| 1362 | 1314 |
| 1363 void _onSubscriptionStateChange() { | 1315 void _onSubscriptionStateChange() { |
| 1364 if (_controller.hasListener) { | 1316 if (_controller.hasListener) { |
| 1365 _resume(); | 1317 _resume(); |
| 1366 } else { | 1318 } else { |
| 1367 _socket.close(); | 1319 _socket.close(); |
| 1368 } | 1320 } |
| 1369 } | 1321 } |
| 1370 | 1322 |
| 1371 void set _owner(owner) { _socket.owner = owner; } | 1323 void set _owner(owner) { |
| 1324 _socket.owner = owner; |
| 1325 } |
| 1372 } | 1326 } |
| 1373 | 1327 |
| 1374 | 1328 @patch |
| 1375 @patch class ServerSocket { | 1329 class ServerSocket { |
| 1376 @patch static Future<ServerSocket> bind(address, | 1330 @patch |
| 1377 int port, | 1331 static Future<ServerSocket> bind(address, int port, |
| 1378 {int backlog: 0, | 1332 {int backlog: 0, bool v6Only: false, bool shared: false}) { |
| 1379 bool v6Only: false, | |
| 1380 bool shared: false}) { | |
| 1381 return _ServerSocket.bind(address, port, backlog, v6Only, shared); | 1333 return _ServerSocket.bind(address, port, backlog, v6Only, shared); |
| 1382 } | 1334 } |
| 1383 } | 1335 } |
| 1384 | 1336 |
| 1385 | 1337 class _ServerSocket extends Stream<Socket> implements ServerSocket { |
| 1386 class _ServerSocket extends Stream<Socket> | |
| 1387 implements ServerSocket { | |
| 1388 final _socket; | 1338 final _socket; |
| 1389 | 1339 |
| 1390 static Future<_ServerSocket> bind(address, | 1340 static Future<_ServerSocket> bind( |
| 1391 int port, | 1341 address, int port, int backlog, bool v6Only, bool shared) { |
| 1392 int backlog, | 1342 return _RawServerSocket |
| 1393 bool v6Only, | 1343 .bind(address, port, backlog, v6Only, shared) |
| 1394 bool shared) { | |
| 1395 return _RawServerSocket.bind(address, port, backlog, v6Only, shared) | |
| 1396 .then((socket) => new _ServerSocket(socket)); | 1344 .then((socket) => new _ServerSocket(socket)); |
| 1397 } | 1345 } |
| 1398 | 1346 |
| 1399 _ServerSocket(this._socket); | 1347 _ServerSocket(this._socket); |
| 1400 | 1348 |
| 1401 StreamSubscription<Socket> listen(void onData(Socket event), | 1349 StreamSubscription<Socket> listen(void onData(Socket event), |
| 1402 {Function onError, | 1350 {Function onError, void onDone(), bool cancelOnError}) { |
| 1403 void onDone(), | 1351 return _socket.map((rawSocket) => new _Socket(rawSocket)).listen(onData, |
| 1404 bool cancelOnError}) { | 1352 onError: onError, onDone: onDone, cancelOnError: cancelOnError); |
| 1405 return _socket.map((rawSocket) => new _Socket(rawSocket)).listen( | |
| 1406 onData, | |
| 1407 onError: onError, | |
| 1408 onDone: onDone, | |
| 1409 cancelOnError: cancelOnError); | |
| 1410 } | 1353 } |
| 1411 | 1354 |
| 1412 int get port => _socket.port; | 1355 int get port => _socket.port; |
| 1413 | 1356 |
| 1414 InternetAddress get address => _socket.address; | 1357 InternetAddress get address => _socket.address; |
| 1415 | 1358 |
| 1416 Future close() => _socket.close().then((_) => this); | 1359 Future close() => _socket.close().then((_) => this); |
| 1417 | 1360 |
| 1418 void set _owner(owner) { _socket._owner = owner; } | 1361 void set _owner(owner) { |
| 1419 } | 1362 _socket._owner = owner; |
| 1420 | |
| 1421 | |
| 1422 @patch class Socket { | |
| 1423 @patch static Future<Socket> connect(host, int port, {sourceAddress}) { | |
| 1424 return RawSocket.connect(host, port, sourceAddress: sourceAddress).then( | |
| 1425 (socket) => new _Socket(socket)); | |
| 1426 } | 1363 } |
| 1427 } | 1364 } |
| 1428 | 1365 |
| 1366 @patch |
| 1367 class Socket { |
| 1368 @patch |
| 1369 static Future<Socket> connect(host, int port, {sourceAddress}) { |
| 1370 return RawSocket |
| 1371 .connect(host, port, sourceAddress: sourceAddress) |
| 1372 .then((socket) => new _Socket(socket)); |
| 1373 } |
| 1374 } |
| 1429 | 1375 |
| 1430 class _SocketStreamConsumer extends StreamConsumer<List<int>> { | 1376 class _SocketStreamConsumer extends StreamConsumer<List<int>> { |
| 1431 StreamSubscription subscription; | 1377 StreamSubscription subscription; |
| 1432 final _Socket socket; | 1378 final _Socket socket; |
| 1433 int offset; | 1379 int offset; |
| 1434 List<int> buffer; | 1380 List<int> buffer; |
| 1435 bool paused = false; | 1381 bool paused = false; |
| 1436 Completer streamCompleter; | 1382 Completer streamCompleter; |
| 1437 | 1383 |
| 1438 _SocketStreamConsumer(this.socket); | 1384 _SocketStreamConsumer(this.socket); |
| 1439 | 1385 |
| 1440 Future<Socket> addStream(Stream<List<int>> stream) { | 1386 Future<Socket> addStream(Stream<List<int>> stream) { |
| 1441 socket._ensureRawSocketSubscription(); | 1387 socket._ensureRawSocketSubscription(); |
| 1442 streamCompleter = new Completer<Socket>(); | 1388 streamCompleter = new Completer<Socket>(); |
| 1443 if (socket._raw != null) { | 1389 if (socket._raw != null) { |
| 1444 subscription = stream.listen( | 1390 subscription = stream.listen((data) { |
| 1445 (data) { | 1391 assert(!paused); |
| 1446 assert(!paused); | 1392 assert(buffer == null); |
| 1447 assert(buffer == null); | 1393 buffer = data; |
| 1448 buffer = data; | 1394 offset = 0; |
| 1449 offset = 0; | 1395 try { |
| 1450 try { | 1396 write(); |
| 1451 write(); | 1397 } catch (e) { |
| 1452 } catch (e) { | 1398 socket.destroy(); |
| 1453 socket.destroy(); | 1399 stop(); |
| 1454 stop(); | 1400 done(e); |
| 1455 done(e); | 1401 } |
| 1456 } | 1402 }, onError: (error, [stackTrace]) { |
| 1457 }, | 1403 socket.destroy(); |
| 1458 onError: (error, [stackTrace]) { | 1404 done(error, stackTrace); |
| 1459 socket.destroy(); | 1405 }, onDone: () { |
| 1460 done(error, stackTrace); | 1406 done(); |
| 1461 }, | 1407 }, cancelOnError: true); |
| 1462 onDone: () { | |
| 1463 done(); | |
| 1464 }, | |
| 1465 cancelOnError: true); | |
| 1466 } | 1408 } |
| 1467 return streamCompleter.future; | 1409 return streamCompleter.future; |
| 1468 } | 1410 } |
| 1469 | 1411 |
| 1470 Future<Socket> close() { | 1412 Future<Socket> close() { |
| 1471 socket._consumerDone(); | 1413 socket._consumerDone(); |
| 1472 return new Future.value(socket); | 1414 return new Future.value(socket); |
| 1473 } | 1415 } |
| 1474 | 1416 |
| 1475 void write() { | 1417 void write() { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1505 | 1447 |
| 1506 void stop() { | 1448 void stop() { |
| 1507 if (subscription == null) return; | 1449 if (subscription == null) return; |
| 1508 subscription.cancel(); | 1450 subscription.cancel(); |
| 1509 subscription = null; | 1451 subscription = null; |
| 1510 paused = false; | 1452 paused = false; |
| 1511 socket._disableWriteEvent(); | 1453 socket._disableWriteEvent(); |
| 1512 } | 1454 } |
| 1513 } | 1455 } |
| 1514 | 1456 |
| 1515 | |
| 1516 class _Socket extends Stream<List<int>> implements Socket { | 1457 class _Socket extends Stream<List<int>> implements Socket { |
| 1517 RawSocket _raw; // Set to null when the raw socket is closed. | 1458 RawSocket _raw; // Set to null when the raw socket is closed. |
| 1518 bool _closed = false; // Set to true when the raw socket is closed. | 1459 bool _closed = false; // Set to true when the raw socket is closed. |
| 1519 StreamController _controller; | 1460 StreamController _controller; |
| 1520 bool _controllerClosed = false; | 1461 bool _controllerClosed = false; |
| 1521 _SocketStreamConsumer _consumer; | 1462 _SocketStreamConsumer _consumer; |
| 1522 IOSink _sink; | 1463 IOSink _sink; |
| 1523 var _subscription; | 1464 var _subscription; |
| 1524 var _detachReady; | 1465 var _detachReady; |
| 1525 | 1466 |
| 1526 _Socket(this._raw) { | 1467 _Socket(this._raw) { |
| 1527 _controller = new StreamController<List<int>>(sync: true, | 1468 _controller = new StreamController<List<int>>( |
| 1469 sync: true, |
| 1528 onListen: _onSubscriptionStateChange, | 1470 onListen: _onSubscriptionStateChange, |
| 1529 onCancel: _onSubscriptionStateChange, | 1471 onCancel: _onSubscriptionStateChange, |
| 1530 onPause: _onPauseStateChange, | 1472 onPause: _onPauseStateChange, |
| 1531 onResume: _onPauseStateChange); | 1473 onResume: _onPauseStateChange); |
| 1532 _consumer = new _SocketStreamConsumer(this); | 1474 _consumer = new _SocketStreamConsumer(this); |
| 1533 _sink = new IOSink(_consumer); | 1475 _sink = new IOSink(_consumer); |
| 1534 | 1476 |
| 1535 // Disable read events until there is a subscription. | 1477 // Disable read events until there is a subscription. |
| 1536 _raw.readEventsEnabled = false; | 1478 _raw.readEventsEnabled = false; |
| 1537 | 1479 |
| 1538 // Disable write events until the consumer needs it for pending writes. | 1480 // Disable write events until the consumer needs it for pending writes. |
| 1539 _raw.writeEventsEnabled = false; | 1481 _raw.writeEventsEnabled = false; |
| 1540 } | 1482 } |
| 1541 | 1483 |
| 1542 factory _Socket._writePipe() { | 1484 factory _Socket._writePipe() { |
| 1543 return new _Socket(new _RawSocket._writePipe()); | 1485 return new _Socket(new _RawSocket._writePipe()); |
| 1544 } | 1486 } |
| 1545 | 1487 |
| 1546 factory _Socket._readPipe([int fd]) { | 1488 factory _Socket._readPipe([int fd]) { |
| 1547 return new _Socket(new _RawSocket._readPipe(fd)); | 1489 return new _Socket(new _RawSocket._readPipe(fd)); |
| 1548 } | 1490 } |
| 1549 | 1491 |
| 1550 _NativeSocket get _nativeSocket => _raw._socket; | 1492 _NativeSocket get _nativeSocket => _raw._socket; |
| 1551 | 1493 |
| 1552 StreamSubscription<List<int>> listen(void onData(List<int> event), | 1494 StreamSubscription<List<int>> listen(void onData(List<int> event), |
| 1553 {Function onError, | 1495 {Function onError, void onDone(), bool cancelOnError}) { |
| 1554 void onDone(), | 1496 return _controller.stream.listen(onData, |
| 1555 bool cancelOnError}) { | 1497 onError: onError, onDone: onDone, cancelOnError: cancelOnError); |
| 1556 return _controller.stream.listen( | |
| 1557 onData, | |
| 1558 onError: onError, | |
| 1559 onDone: onDone, | |
| 1560 cancelOnError: cancelOnError); | |
| 1561 } | 1498 } |
| 1562 | 1499 |
| 1563 Encoding get encoding => _sink.encoding; | 1500 Encoding get encoding => _sink.encoding; |
| 1564 | 1501 |
| 1565 void set encoding(Encoding value) { | 1502 void set encoding(Encoding value) { |
| 1566 _sink.encoding = value; | 1503 _sink.encoding = value; |
| 1567 } | 1504 } |
| 1568 | 1505 |
| 1569 void write(Object obj) => _sink.write(obj); | 1506 void write(Object obj) => _sink.write(obj); |
| 1570 | 1507 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1594 _controllerClosed = true; | 1531 _controllerClosed = true; |
| 1595 _controller.close(); | 1532 _controller.close(); |
| 1596 } | 1533 } |
| 1597 | 1534 |
| 1598 bool setOption(SocketOption option, bool enabled) { | 1535 bool setOption(SocketOption option, bool enabled) { |
| 1599 if (_raw == null) return false; | 1536 if (_raw == null) return false; |
| 1600 return _raw.setOption(option, enabled); | 1537 return _raw.setOption(option, enabled); |
| 1601 } | 1538 } |
| 1602 | 1539 |
| 1603 int get port { | 1540 int get port { |
| 1604 if (_raw == null) throw const SocketException.closed();; | 1541 if (_raw == null) throw const SocketException.closed(); |
| 1542 ; |
| 1605 return _raw.port; | 1543 return _raw.port; |
| 1606 } | 1544 } |
| 1607 | 1545 |
| 1608 InternetAddress get address { | 1546 InternetAddress get address { |
| 1609 if (_raw == null) throw const SocketException.closed();; | 1547 if (_raw == null) throw const SocketException.closed(); |
| 1548 ; |
| 1610 return _raw.address; | 1549 return _raw.address; |
| 1611 } | 1550 } |
| 1612 | 1551 |
| 1613 int get remotePort { | 1552 int get remotePort { |
| 1614 if (_raw == null) throw const SocketException.closed();; | 1553 if (_raw == null) throw const SocketException.closed(); |
| 1554 ; |
| 1615 return _raw.remotePort; | 1555 return _raw.remotePort; |
| 1616 } | 1556 } |
| 1617 | 1557 |
| 1618 InternetAddress get remoteAddress { | 1558 InternetAddress get remoteAddress { |
| 1619 if (_raw == null) throw const SocketException.closed();; | 1559 if (_raw == null) throw const SocketException.closed(); |
| 1560 ; |
| 1620 return _raw.remoteAddress; | 1561 return _raw.remoteAddress; |
| 1621 } | 1562 } |
| 1622 | 1563 |
| 1623 Future _detachRaw() { | 1564 Future _detachRaw() { |
| 1624 _detachReady = new Completer(); | 1565 _detachReady = new Completer(); |
| 1625 _sink.close(); | 1566 _sink.close(); |
| 1626 return _detachReady.future.then((_) { | 1567 return _detachReady.future.then((_) { |
| 1627 assert(_consumer.buffer == null); | 1568 assert(_consumer.buffer == null); |
| 1628 var raw = _raw; | 1569 var raw = _raw; |
| 1629 _raw = null; | 1570 _raw = null; |
| 1630 return [raw, _subscription]; | 1571 return [raw, _subscription]; |
| 1631 }); | 1572 }); |
| 1632 } | 1573 } |
| 1633 | 1574 |
| 1634 // Ensure a subscription on the raw socket. Both the stream and the | 1575 // Ensure a subscription on the raw socket. Both the stream and the |
| 1635 // consumer needs a subscription as they share the error and done | 1576 // consumer needs a subscription as they share the error and done |
| 1636 // events from the raw socket. | 1577 // events from the raw socket. |
| 1637 void _ensureRawSocketSubscription() { | 1578 void _ensureRawSocketSubscription() { |
| 1638 if (_subscription == null && _raw != null) { | 1579 if (_subscription == null && _raw != null) { |
| 1639 _subscription = _raw.listen(_onData, | 1580 _subscription = _raw.listen(_onData, |
| 1640 onError: _onError, | 1581 onError: _onError, onDone: _onDone, cancelOnError: true); |
| 1641 onDone: _onDone, | |
| 1642 cancelOnError: true); | |
| 1643 } | 1582 } |
| 1644 } | 1583 } |
| 1645 | 1584 |
| 1646 _closeRawSocket() { | 1585 _closeRawSocket() { |
| 1647 var tmp = _raw; | 1586 var tmp = _raw; |
| 1648 _raw = null; | 1587 _raw = null; |
| 1649 _closed = true; | 1588 _closed = true; |
| 1650 tmp.close(); | 1589 tmp.close(); |
| 1651 } | 1590 } |
| 1652 | 1591 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1721 if (_detachReady != null) { | 1660 if (_detachReady != null) { |
| 1722 _detachReady.complete(null); | 1661 _detachReady.complete(null); |
| 1723 } else { | 1662 } else { |
| 1724 if (_raw != null) { | 1663 if (_raw != null) { |
| 1725 _raw.shutdown(SocketDirection.SEND); | 1664 _raw.shutdown(SocketDirection.SEND); |
| 1726 _disableWriteEvent(); | 1665 _disableWriteEvent(); |
| 1727 } | 1666 } |
| 1728 } | 1667 } |
| 1729 } | 1668 } |
| 1730 | 1669 |
| 1731 void set _owner(owner) { _raw._owner = owner; } | 1670 void set _owner(owner) { |
| 1671 _raw._owner = owner; |
| 1672 } |
| 1732 } | 1673 } |
| 1733 | 1674 |
| 1734 | 1675 @patch |
| 1735 @patch class RawDatagramSocket { | 1676 class RawDatagramSocket { |
| 1736 @patch static Future<RawDatagramSocket> bind( | 1677 @patch |
| 1737 host, int port, {bool reuseAddress: true}) { | 1678 static Future<RawDatagramSocket> bind(host, int port, |
| 1679 {bool reuseAddress: true}) { |
| 1738 return _RawDatagramSocket.bind(host, port, reuseAddress); | 1680 return _RawDatagramSocket.bind(host, port, reuseAddress); |
| 1739 } | 1681 } |
| 1740 } | 1682 } |
| 1741 | 1683 |
| 1742 class _RawDatagramSocket extends Stream implements RawDatagramSocket { | 1684 class _RawDatagramSocket extends Stream implements RawDatagramSocket { |
| 1743 _NativeSocket _socket; | 1685 _NativeSocket _socket; |
| 1744 StreamController<RawSocketEvent> _controller; | 1686 StreamController<RawSocketEvent> _controller; |
| 1745 bool _readEventsEnabled = true; | 1687 bool _readEventsEnabled = true; |
| 1746 bool _writeEventsEnabled = true; | 1688 bool _writeEventsEnabled = true; |
| 1747 | 1689 |
| 1748 _RawDatagramSocket(this._socket) { | 1690 _RawDatagramSocket(this._socket) { |
| 1749 var zone = Zone.current; | 1691 var zone = Zone.current; |
| 1750 _controller = new StreamController(sync: true, | 1692 _controller = new StreamController( |
| 1693 sync: true, |
| 1751 onListen: _onSubscriptionStateChange, | 1694 onListen: _onSubscriptionStateChange, |
| 1752 onCancel: _onSubscriptionStateChange, | 1695 onCancel: _onSubscriptionStateChange, |
| 1753 onPause: _onPauseStateChange, | 1696 onPause: _onPauseStateChange, |
| 1754 onResume: _onPauseStateChange); | 1697 onResume: _onPauseStateChange); |
| 1755 _socket.setHandlers( | 1698 _socket.setHandlers( |
| 1756 read: () => _controller.add(RawSocketEvent.READ), | 1699 read: () => _controller.add(RawSocketEvent.READ), |
| 1757 write: () { | 1700 write: () { |
| 1758 // The write event handler is automatically disabled by the | 1701 // The write event handler is automatically disabled by the |
| 1759 // event handler when it fires. | 1702 // event handler when it fires. |
| 1760 _writeEventsEnabled = false; | 1703 _writeEventsEnabled = false; |
| 1761 _controller.add(RawSocketEvent.WRITE); | 1704 _controller.add(RawSocketEvent.WRITE); |
| 1762 }, | 1705 }, |
| 1763 closed: () => _controller.add(RawSocketEvent.READ_CLOSED), | 1706 closed: () => _controller.add(RawSocketEvent.READ_CLOSED), |
| 1764 destroyed: () { | 1707 destroyed: () { |
| 1765 _controller.add(RawSocketEvent.CLOSED); | 1708 _controller.add(RawSocketEvent.CLOSED); |
| 1766 _controller.close(); | 1709 _controller.close(); |
| 1767 }, | 1710 }, |
| 1768 error: zone.bindUnaryCallback((e) { | 1711 error: zone.bindUnaryCallback((e) { |
| 1769 _controller.addError(e); | 1712 _controller.addError(e); |
| 1770 _socket.close(); | 1713 _socket.close(); |
| 1771 }) | 1714 })); |
| 1772 ); | |
| 1773 } | 1715 } |
| 1774 | 1716 |
| 1775 static Future<RawDatagramSocket> bind( | 1717 static Future<RawDatagramSocket> bind(host, int port, bool reuseAddress) { |
| 1776 host, int port, bool reuseAddress) { | |
| 1777 _throwOnBadPort(port); | 1718 _throwOnBadPort(port); |
| 1778 return _NativeSocket.bindDatagram(host, port, reuseAddress) | 1719 return _NativeSocket |
| 1720 .bindDatagram(host, port, reuseAddress) |
| 1779 .then((socket) => new _RawDatagramSocket(socket)); | 1721 .then((socket) => new _RawDatagramSocket(socket)); |
| 1780 } | 1722 } |
| 1781 | 1723 |
| 1782 StreamSubscription<RawSocketEvent> listen(void onData(RawSocketEvent event), | 1724 StreamSubscription<RawSocketEvent> listen(void onData(RawSocketEvent event), |
| 1783 {Function onError, | 1725 {Function onError, void onDone(), bool cancelOnError}) { |
| 1784 void onDone(), | 1726 return _controller.stream.listen(onData, |
| 1785 bool cancelOnError}) { | 1727 onError: onError, onDone: onDone, cancelOnError: cancelOnError); |
| 1786 return _controller.stream.listen( | |
| 1787 onData, | |
| 1788 onError: onError, | |
| 1789 onDone: onDone, | |
| 1790 cancelOnError: cancelOnError); | |
| 1791 } | 1728 } |
| 1792 | 1729 |
| 1793 Future close() => _socket.close().then((_) => this); | 1730 Future close() => _socket.close().then((_) => this); |
| 1794 | 1731 |
| 1795 int send(List<int> buffer, InternetAddress address, int port) => | 1732 int send(List<int> buffer, InternetAddress address, int port) => |
| 1796 _socket.send(buffer, 0, buffer.length, address, port); | 1733 _socket.send(buffer, 0, buffer.length, address, port); |
| 1797 | 1734 |
| 1798 Datagram receive() { | 1735 Datagram receive() { |
| 1799 return _socket.receive(); | 1736 return _socket.receive(); |
| 1800 } | 1737 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1821 _writeEventsEnabled = value; | 1758 _writeEventsEnabled = value; |
| 1822 if (!_controller.isPaused) _resume(); | 1759 if (!_controller.isPaused) _resume(); |
| 1823 } | 1760 } |
| 1824 } | 1761 } |
| 1825 | 1762 |
| 1826 bool get multicastLoopback => | 1763 bool get multicastLoopback => |
| 1827 _socket.getOption(SocketOption._IP_MULTICAST_LOOP); | 1764 _socket.getOption(SocketOption._IP_MULTICAST_LOOP); |
| 1828 void set multicastLoopback(bool value) => | 1765 void set multicastLoopback(bool value) => |
| 1829 _socket.setOption(SocketOption._IP_MULTICAST_LOOP, value); | 1766 _socket.setOption(SocketOption._IP_MULTICAST_LOOP, value); |
| 1830 | 1767 |
| 1831 int get multicastHops => | 1768 int get multicastHops => _socket.getOption(SocketOption._IP_MULTICAST_HOPS); |
| 1832 _socket.getOption(SocketOption._IP_MULTICAST_HOPS); | |
| 1833 void set multicastHops(int value) => | 1769 void set multicastHops(int value) => |
| 1834 _socket.setOption(SocketOption._IP_MULTICAST_HOPS, value); | 1770 _socket.setOption(SocketOption._IP_MULTICAST_HOPS, value); |
| 1835 | 1771 |
| 1836 NetworkInterface get multicastInterface => | 1772 NetworkInterface get multicastInterface => throw "Not implemented"; |
| 1837 throw "Not implemented"; | |
| 1838 void set multicastInterface(NetworkInterface value) => | 1773 void set multicastInterface(NetworkInterface value) => |
| 1839 throw "Not implemented"; | 1774 throw "Not implemented"; |
| 1840 | 1775 |
| 1841 bool get broadcastEnabled => | 1776 bool get broadcastEnabled => _socket.getOption(SocketOption._IP_BROADCAST); |
| 1842 _socket.getOption(SocketOption._IP_BROADCAST); | |
| 1843 void set broadcastEnabled(bool value) => | 1777 void set broadcastEnabled(bool value) => |
| 1844 _socket.setOption(SocketOption._IP_BROADCAST, value); | 1778 _socket.setOption(SocketOption._IP_BROADCAST, value); |
| 1845 | 1779 |
| 1846 int get port => _socket.port; | 1780 int get port => _socket.port; |
| 1847 | 1781 |
| 1848 InternetAddress get address => _socket.address; | 1782 InternetAddress get address => _socket.address; |
| 1849 | 1783 |
| 1850 _pause() { | 1784 _pause() { |
| 1851 _socket.setListening(read: false, write: false); | 1785 _socket.setListening(read: false, write: false); |
| 1852 } | 1786 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1865 | 1799 |
| 1866 void _onSubscriptionStateChange() { | 1800 void _onSubscriptionStateChange() { |
| 1867 if (_controller.hasListener) { | 1801 if (_controller.hasListener) { |
| 1868 _resume(); | 1802 _resume(); |
| 1869 } else { | 1803 } else { |
| 1870 _socket.close(); | 1804 _socket.close(); |
| 1871 } | 1805 } |
| 1872 } | 1806 } |
| 1873 } | 1807 } |
| 1874 | 1808 |
| 1875 Datagram _makeDatagram(List<int> data, | 1809 Datagram _makeDatagram( |
| 1876 String address, | 1810 List<int> data, String address, List<int> in_addr, int port) { |
| 1877 List<int> in_addr, | 1811 return new Datagram(data, new _InternetAddress(address, null, in_addr), port); |
| 1878 int port) { | |
| 1879 return new Datagram( | |
| 1880 data, | |
| 1881 new _InternetAddress(address, null, in_addr), | |
| 1882 port); | |
| 1883 } | 1812 } |
| 1884 | |
| OLD | NEW |