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