OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 patch class RawServerSocket { | 5 patch class RawServerSocket { |
6 /* patch */ static Future<RawServerSocket> bind(address, | 6 /* patch */ static Future<RawServerSocket> bind(address, |
7 int port, | 7 int port, |
8 {int backlog: 0, | 8 {int backlog: 0, |
9 bool v6Only: false}) { | 9 bool v6Only: false}) { |
10 return _RawServerSocket.bind(address, port, backlog, v6Only); | 10 return _RawServerSocket.bind(address, port, backlog, v6Only); |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
266 static const LIST_INTERFACES = 1; | 266 static const LIST_INTERFACES = 1; |
267 static const REVERSE_LOOKUP = 2; | 267 static const REVERSE_LOOKUP = 2; |
268 | 268 |
269 // Protocol flags. | 269 // Protocol flags. |
270 static const int PROTOCOL_IPV4 = 1 << 0; | 270 static const int PROTOCOL_IPV4 = 1 << 0; |
271 static const int PROTOCOL_IPV6 = 1 << 1; | 271 static const int PROTOCOL_IPV6 = 1 << 1; |
272 | 272 |
273 static const int NORMAL_TOKEN_BATCH_SIZE = 8; | 273 static const int NORMAL_TOKEN_BATCH_SIZE = 8; |
274 static const int LISTENING_TOKEN_BATCH_SIZE = 2; | 274 static const int LISTENING_TOKEN_BATCH_SIZE = 2; |
275 | 275 |
276 static const Duration _RETRY_DURATION = const Duration(milliseconds: 250); | |
277 static const Duration _RETRY_DURATION_LOOPBACK = | |
278 const Duration(milliseconds: 25); | |
279 | |
276 // Use default Map so we keep order. | 280 // Use default Map so we keep order. |
277 static Map<int, _NativeSocket> _sockets = new Map<int, _NativeSocket>(); | 281 static Map<int, _NativeSocket> _sockets = new Map<int, _NativeSocket>(); |
278 | 282 |
279 // Socket close state | 283 // Socket close state |
280 bool isClosed = false; | 284 bool isClosed = false; |
281 bool isClosing = false; | 285 bool isClosing = false; |
282 bool isClosedRead = false; | 286 bool isClosedRead = false; |
283 bool isClosedWrite = false; | 287 bool isClosedWrite = false; |
284 Completer closeCompleter = new Completer.sync(); | 288 Completer closeCompleter = new Completer.sync(); |
285 | 289 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
374 return map.values.toList(); | 378 return map.values.toList(); |
375 } | 379 } |
376 }); | 380 }); |
377 } | 381 } |
378 | 382 |
379 static Future<_NativeSocket> connect(host, int port) { | 383 static Future<_NativeSocket> connect(host, int port) { |
380 return new Future.value(host) | 384 return new Future.value(host) |
381 .then((host) { | 385 .then((host) { |
382 if (host is _InternetAddress) return [host]; | 386 if (host is _InternetAddress) return [host]; |
383 return lookup(host) | 387 return lookup(host) |
384 .then((list) { | 388 .then((addresses) { |
385 if (list.length == 0) { | 389 if (addresses.isEmpty) { |
386 throw createError(response, "Failed host lookup: '$host'"); | 390 throw createError(response, "Failed host lookup: '$host'"); |
387 } | 391 } |
388 return list; | 392 return addresses; |
389 }); | 393 }); |
390 }) | 394 }) |
391 .then((addresses) { | 395 .then((addresses) { |
392 assert(addresses is List); | 396 assert(addresses is List); |
393 var completer = new Completer(); | 397 var completer = new Completer(); |
394 var it = addresses.iterator; | 398 var it = addresses.iterator; |
395 void run(error) { | 399 var error = null; |
400 var connecting = new HashMap(); | |
401 void connectNext() { | |
396 if (!it.moveNext()) { | 402 if (!it.moveNext()) { |
397 assert(error != null); | 403 if (connecting.isEmpty) { |
398 completer.completeError(error); | 404 assert(error != null); |
405 completer.completeError(error); | |
406 } | |
399 return; | 407 return; |
400 } | 408 } |
401 var address = it.current; | 409 var address = it.current; |
402 var socket = new _NativeSocket.normal(); | 410 var socket = new _NativeSocket.normal(); |
403 socket.address = address; | 411 socket.address = address; |
404 var result = socket.nativeCreateConnect(address._in_addr, port); | 412 var result = socket.nativeCreateConnect(address._in_addr, port); |
405 if (result is OSError) { | 413 if (result is OSError) { |
406 // Keep first error, if present. | 414 // Keep first error, if present. |
407 run(error != null ? error : | 415 if (error == null) { |
408 createError(result, "Connection failed", address, port)); | 416 error = createError(result, "Connection failed", address, port); |
417 } | |
418 connectNext(); | |
409 } else { | 419 } else { |
410 socket.port; // Query the local port, for error messages. | 420 socket.port; // Query the local port, for error messages. |
421 // Set up timer for when we should retry the next address (if any) . | |
Søren Gjesse
2014/08/04 09:21:37
Long line.
Anders Johnsen
2014/08/05 09:14:55
Done.
| |
422 var duration = address.isLoopback ? | |
423 _RETRY_DURATION_LOOPBACK : | |
424 _RETRY_DURATION; | |
425 var timer = new Timer(duration, connectNext); | |
426 connecting[socket] = timer; | |
411 // Setup handlers for receiving the first write event which | 427 // Setup handlers for receiving the first write event which |
412 // indicate that the socket is fully connected. | 428 // indicate that the socket is fully connected. |
413 socket.setHandlers( | 429 socket.setHandlers( |
414 write: () { | 430 write: () { |
431 timer.cancel(); | |
415 socket.setListening(read: false, write: false); | 432 socket.setListening(read: false, write: false); |
416 completer.complete(socket); | 433 completer.complete(socket); |
434 connecting.remove(socket); | |
435 connecting.forEach((s, t) { | |
436 t.cancel(); | |
437 s.close(); | |
Søren Gjesse
2014/08/04 09:21:37
Shouldn't s.destroy() be enough?
Anders Johnsen
2014/08/05 09:14:55
There is no destroy on _NativeSocket. We need to c
| |
438 s.setHandlers(); | |
439 s.setListening(read: false, write: false); | |
440 }); | |
417 }, | 441 }, |
418 error: (e) { | 442 error: (e) { |
443 timer.cancel(); | |
419 socket.close(); | 444 socket.close(); |
420 // Keep first error, if present. | 445 // Keep first error, if present. |
421 run(error != null ? error : e); | 446 if (error == null) error = e; |
422 } | 447 connecting.remove(socket); |
423 ); | 448 if (connecting.isEmpty) connectNext(); |
449 }); | |
424 socket.setListening(read: false, write: true); | 450 socket.setListening(read: false, write: true); |
425 } | 451 } |
426 } | 452 } |
427 run(null); | 453 connectNext(); |
428 return completer.future; | 454 return completer.future; |
429 }); | 455 }); |
430 } | 456 } |
431 | 457 |
432 static Future<_NativeSocket> bind(host, | 458 static Future<_NativeSocket> bind(host, |
433 int port, | 459 int port, |
434 int backlog, | 460 int backlog, |
435 bool v6Only) { | 461 bool v6Only) { |
436 return new Future.value(host) | 462 return new Future.value(host) |
437 .then((host) { | 463 .then((host) { |
(...skipping 1464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1902 String address, | 1928 String address, |
1903 List<int> in_addr, | 1929 List<int> in_addr, |
1904 int port) { | 1930 int port) { |
1905 return new Datagram( | 1931 return new Datagram( |
1906 data, | 1932 data, |
1907 new _InternetAddress(address, null, in_addr), | 1933 new _InternetAddress(address, null, in_addr), |
1908 port); | 1934 port); |
1909 } | 1935 } |
1910 | 1936 |
1911 String _socketsStats() => _SocketsObservatory.toJSON(); | 1937 String _socketsStats() => _SocketsObservatory.toJSON(); |
OLD | NEW |