@@ -580,21 +580,22 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
580
580
// attempt isn't made until either a previous attempt has *failed*,
581
581
// or the delay has passed.
582
582
// This ensures that at most *n* uncompleted connections can be
583
- // active after *n* × *delay* time has passed.
583
+ // active after *n* × *delay* time has passed.
584
584
if (host is String ) {
585
585
host = escapeLinkLocalAddress (host);
586
586
}
587
587
_throwOnBadPort (port);
588
588
_InternetAddress ? source;
589
- if (sourceAddress is _InternetAddress ) {
590
- source = sourceAddress;
591
- } else if (sourceAddress is String ) {
592
- source = new _InternetAddress .fromString (sourceAddress);
593
- }
594
- // Should we throw if sourceAddress is not one of:
595
- // null, _InternetAddress or String?
596
- // Is it somehow ensured upstream
597
- // that only those three types will reach here?
589
+ if (sourceAddress != null ) {
590
+ if (sourceAddress is _InternetAddress ) {
591
+ source = sourceAddress;
592
+ } else if (sourceAddress is String ) {
593
+ source = new _InternetAddress .fromString (sourceAddress);
594
+ } else {
595
+ throw ArgumentError .value (sourceAddress, "sourceAddress" ,
596
+ "Must be a string or native InternetAddress" );
597
+ }
598
+ }
598
599
return new Future .value (host).then <List <InternetAddress >>((host) {
599
600
if (host is _InternetAddress ) return [host];
600
601
return lookup (host).then ((addresses) {
@@ -606,7 +607,7 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
606
607
}).then ((addresses) {
607
608
assert (addresses.isNotEmpty);
608
609
// Completer for result.
609
- var completer = new Completer <_NativeSocket >();
610
+ var result = new Completer <_NativeSocket >();
610
611
// Index of next address in [addresses] to try.
611
612
var index = 0 ;
612
613
// Error, set if an error occurs.
@@ -632,43 +633,55 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
632
633
if (index >= addresses.length) {
633
634
if (connecting.isEmpty) {
634
635
assert (error != null );
635
- assert (! completer .isCompleted);
636
- completer .completeError (error);
636
+ assert (! result .isCompleted);
637
+ result .completeError (error);
637
638
}
638
639
return ;
639
640
}
640
641
final address = addresses[index++ ] as _InternetAddress ;
641
642
var socket = new _NativeSocket .normal (address);
642
- var result;
643
- if (source == null ) {
644
- if (address.type == InternetAddressType .unix) {
645
- result = socket.nativeCreateUnixDomainConnect (
643
+ // Will contain values of various types representing the result
644
+ // of trying to create a connection.
645
+ // A value of `true` means success, everything else means failure.
646
+ Object ? connectionResult;
647
+ if (address.type == InternetAddressType .unix) {
648
+ if (source == null ) {
649
+ connectionResult = socket.nativeCreateUnixDomainConnect (
646
650
address.address, _Namespace ._namespace);
647
651
} else {
648
- result = socket.nativeCreateConnect (
649
- address._in_addr, port, address._scope_id);
650
- }
651
- } else {
652
- if (address.type == InternetAddressType .unix) {
653
652
assert (source.type == InternetAddressType .unix);
654
- result = socket.nativeCreateUnixDomainBindConnect (
653
+ connectionResult = socket.nativeCreateUnixDomainBindConnect (
655
654
address.address, source.address, _Namespace ._namespace);
655
+ }
656
+ assert (connectionResult == true ||
657
+ connectionResult is Error ||
658
+ connectionResult is OSError );
659
+ } else {
660
+ if (source == null ) {
661
+ connectionResult = socket.nativeCreateConnect (
662
+ address._in_addr, port, address._scope_id);
656
663
} else {
657
- result = socket.nativeCreateBindConnect (
664
+ connectionResult = socket.nativeCreateBindConnect (
658
665
address._in_addr, port, source._in_addr, address._scope_id);
659
666
}
667
+ assert (connectionResult == true || connectionResult is OSError );
660
668
}
661
- if (result is OSError ) {
662
- // Keep first error, if present .
663
- if (error == null ) {
664
- int errorCode = result .errorCode;
669
+ if (connectionResult != true ) {
670
+ // connectionResult was not a success .
671
+ if (connectionResult is OSError ) {
672
+ int errorCode = connectionResult .errorCode;
665
673
if (source != null &&
666
674
errorCode != null &&
667
675
socket.isBindError (errorCode)) {
668
- error = createError (result , "Bind failed" , source);
676
+ error = createError (connectionResult , "Bind failed" , source);
669
677
} else {
670
- error = createError (result, "Connection failed" , address, port);
678
+ error = createError (
679
+ connectionResult, "Connection failed" , address, port);
671
680
}
681
+ } else if (connectionResult is Error ) {
682
+ error = connectionResult;
683
+ } else {
684
+ error = createError (null , "Connection failed" , address);
672
685
}
673
686
connectNext (); // Try again after failure to connect.
674
687
return ;
@@ -722,7 +735,7 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
722
735
s.setListening (read: false , write: false );
723
736
}
724
737
connecting.clear ();
725
- completer .complete (socket);
738
+ result .complete (socket);
726
739
}, error: (e, st) {
727
740
connecting.remove (socket);
728
741
socket.close ();
@@ -743,15 +756,15 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
743
756
s.setListening (read: false , write: false );
744
757
}
745
758
connecting.clear ();
746
- if (! completer .isCompleted) {
759
+ if (! result .isCompleted) {
747
760
error ?? = createError (null ,
748
761
"Connection attempt cancelled, host: ${host }, port: ${port }" );
749
- completer .completeError (error);
762
+ result .completeError (error);
750
763
}
751
764
}
752
765
753
766
connectNext ();
754
- return new ConnectionTask <_NativeSocket >._(completer .future, onCancel);
767
+ return new ConnectionTask <_NativeSocket >._(result .future, onCancel);
755
768
});
756
769
}
757
770
0 commit comments