@@ -29,41 +29,54 @@ do_connect(Hostname, Port, Opts, Timeout) when is_tuple(Hostname) ->
29
29
end
30
30
end ;
31
31
do_connect (Hostname , Port , Opts , Timeout ) ->
32
- ? report_debug (" happy eyeballs, try to connect using IPv6" , [{hostname , Hostname }, {port , Port }]),
32
+ ? report_debug (" happy eyeballs, try to connect using IPv6" , [{hostname , Hostname }, {port , Port }, { timeout , Timeout } ]),
33
33
Self = self (),
34
- {Ipv6Addrs , IPv4Addrs } = getaddrs (Hostname ),
35
- {Pid6 , MRef6 } = spawn_monitor (fun () -> try_connect (Ipv6Addrs , Port , Opts , Self ) end ),
36
- TRef = erlang :start_timer (? TIMEOUT , self (), try_ipv4 ),
37
- receive
38
- {'DOWN' , MRef6 , _Type , _Pid , {happy_connect , OK }} ->
39
- _ = erlang :cancel_timer (TRef , []),
40
- OK ;
41
- {'DOWN' , MRef6 , _Type , _Pid , _Info } ->
42
- _ = erlang :cancel_timer (TRef , []),
43
- {Pid4 , MRef4 } = spawn_monitor (fun () -> try_connect (IPv4Addrs , Port , Opts , Self ) end ),
34
+ case getaddrs (Hostname ) of
35
+ {[], []} -> {error , nxdomain };
36
+ {[], IPv4Addrs } ->
37
+ ? report_trace (" happy connect: try IPv4 only" , []),
38
+ {Pid4 , MRef4 } = spawn_monitor (fun () -> try_connect (IPv4Addrs , Port , Opts , Timeout , Self ) end ),
44
39
do_connect_2 (Pid4 , MRef4 , Timeout );
45
- {timeout , TRef , try_ipv4 } ->
46
- PidRef4 = spawn_monitor (fun () -> try_connect (IPv4Addrs , Port , Opts , Self ) end ),
47
- do_connect_1 (PidRef4 , {Pid6 , MRef6 }, Timeout )
48
- after Timeout ->
40
+ {Ipv6Addrs , []} ->
41
+ ? report_trace (" happy connect: try IPv6 only" , []),
42
+ {Pid6 , MRef6 } = spawn_monitor (fun () -> try_connect (Ipv6Addrs , Port , Opts , Timeout , Self ) end ),
43
+ do_connect_2 (Pid6 , MRef6 , Timeout );
44
+ {Ipv6Addrs , IPv4Addrs } ->
45
+ {Pid6 , MRef6 } = spawn_monitor (fun () -> try_connect (Ipv6Addrs , Port , Opts , Timeout , Self ) end ),
46
+ TRef = erlang :start_timer (? TIMEOUT , self (), try_ipv4 ),
47
+ receive
48
+ {'DOWN' , MRef6 , _Type , _Pid , {happy_connect , OK }} ->
49
49
_ = erlang :cancel_timer (TRef , []),
50
- erlang :demonitor (MRef6 , [flush ]),
51
- {error , connect_timeout }
50
+ OK ;
51
+ {'DOWN' , MRef6 , _Type , _Pid , _Info } ->
52
+ _ = erlang :cancel_timer (TRef , []),
53
+ {Pid4 , MRef4 } = spawn_monitor (fun () -> try_connect (IPv4Addrs , Port , Opts , Timeout , Self ) end ),
54
+ do_connect_2 (Pid4 , MRef4 , Timeout );
55
+ {timeout , TRef , try_ipv4 } ->
56
+ ? report_trace (" happy connect: try IPv4" , []),
57
+ PidRef4 = spawn_monitor (fun () -> try_connect (IPv4Addrs , Port , Opts , Timeout , Self ) end ),
58
+ do_connect_1 (PidRef4 , {Pid6 , MRef6 }, Timeout )
59
+ after Timeout ->
60
+ ? report_trace (" happy, connect timeout" , []),
61
+ _ = erlang :cancel_timer (TRef , []),
62
+ erlang :demonitor (MRef6 , [flush ]),
63
+ {error , connect_timeout }
64
+ end
52
65
end .
53
66
54
67
55
68
do_connect_1 ({Pid4 , MRef4 }, {Pid6 , MRef6 }, Timeout ) ->
56
69
receive
57
70
{'DOWN' , MRef4 , _Type , _Pid , {happy_connect , OK }} ->
58
- ? report_trace (" happy_connect ~p " , [OK ]),
71
+ ? report_trace (" happy_connect: ~p " , [OK ]),
59
72
connect_gc (Pid6 , MRef6 ),
60
73
OK ;
61
- {'DOWN' , MRef4 , _Type , _Pid , _Info } ->
62
- do_connect_2 (Pid6 , MRef6 , Timeout );
63
- {'DOWN' , MRef6 , _Type , _Pid , {happy_connect , OK }} ->
74
+ {'DOWN' , MRef6 , _Type , _Pid , {happy_connect , OK }} ->
64
75
? report_trace (" happy_connect ~p " , [OK ]),
65
76
connect_gc (Pid4 , MRef4 ),
66
77
OK ;
78
+ {'DOWN' , MRef4 , _Type , _Pid , _Info } ->
79
+ do_connect_2 (Pid6 , MRef6 , Timeout );
67
80
{'DOWN' , MRef6 , _Type , _Pid , _Info } ->
68
81
do_connect_2 (Pid4 , MRef4 , Timeout )
69
82
after Timeout ->
@@ -122,19 +135,19 @@ getbyname(Hostname, Type) ->
122
135
[]
123
136
end .
124
137
125
- try_connect (Ipv6Addrs , Port , Opts , Self ) ->
126
- try_connect (Ipv6Addrs , Port , Opts , Self , {error , nxdomain }).
138
+ try_connect (Ipv6Addrs , Port , Opts , Timeout , Self ) ->
139
+ try_connect (Ipv6Addrs , Port , Opts , Timeout , Self , {error , nxdomain }).
127
140
128
- try_connect ([], _Port , _Opts , _ServerPid , LastError ) ->
141
+ try_connect ([], _Port , _Opts , _Timeout , _ServerPid , LastError ) ->
129
142
? report_trace (" happy eyeball: failed to connect" , [{error , LastError }]),
130
143
exit (LastError );
131
- try_connect ([{IP , Type } | Rest ], Port , Opts , ServerPid , _LastError ) ->
144
+ try_connect ([{IP , Type } | Rest ], Port , Opts , Timeout , ServerPid , _LastError ) ->
132
145
? report_trace (" try to connect" , [{ip , IP }, {type , Type }]),
133
- case gen_tcp :connect (IP , Port , [Type | Opts ], ? TIMEOUT ) of
146
+ case gen_tcp :connect (IP , Port , [Type | Opts ], Timeout ) of
134
147
{ok , Socket } = OK ->
135
148
? report_trace (" success to connect" , [{ip , IP }, {type , Type }]),
136
149
ok = gen_tcp :controlling_process (Socket , ServerPid ),
137
150
exit ({happy_connect , OK });
138
151
Error ->
139
- try_connect (Rest , Port , Opts , ServerPid , Error )
152
+ try_connect (Rest , Port , Opts , Timeout , ServerPid , Error )
140
153
end .
0 commit comments