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 |