OLD | NEW |
1 // Copyright 2010 The Go Authors. All rights reserved. | 1 // Copyright 2010 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package net | 5 package net |
6 | 6 |
7 import ( | 7 import ( |
8 "time" | 8 "time" |
9 ) | 9 ) |
10 | 10 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 // | 86 // |
87 // Examples: | 87 // Examples: |
88 // Dial("ip4:1", "127.0.0.1") | 88 // Dial("ip4:1", "127.0.0.1") |
89 // Dial("ip6:ospf", "::1") | 89 // Dial("ip6:ospf", "::1") |
90 // | 90 // |
91 func Dial(net, addr string) (Conn, error) { | 91 func Dial(net, addr string) (Conn, error) { |
92 _, addri, err := resolveNetAddr("dial", net, addr) | 92 _, addri, err := resolveNetAddr("dial", net, addr) |
93 if err != nil { | 93 if err != nil { |
94 return nil, err | 94 return nil, err |
95 } | 95 } |
96 » return dialAddr(net, addr, addri) | 96 » return dialAddr(net, addr, addri, nil) |
97 } | 97 } |
98 | 98 |
99 func dialAddr(net, addr string, addri Addr) (c Conn, err error) { | 99 func dialAddr(net, addr string, addri Addr, beforeConnect chan<- *netFD) (c Conn
, err error) { |
100 switch ra := addri.(type) { | 100 switch ra := addri.(type) { |
101 case *TCPAddr: | 101 case *TCPAddr: |
102 » » c, err = DialTCP(net, nil, ra) | 102 » » c, err = dialTCP(net, nil, ra, beforeConnect) |
103 case *UDPAddr: | 103 case *UDPAddr: |
104 c, err = DialUDP(net, nil, ra) | 104 c, err = DialUDP(net, nil, ra) |
105 case *IPAddr: | 105 case *IPAddr: |
106 c, err = DialIP(net, nil, ra) | 106 c, err = DialIP(net, nil, ra) |
107 case *UnixAddr: | 107 case *UnixAddr: |
108 c, err = DialUnix(net, nil, ra) | 108 c, err = DialUnix(net, nil, ra) |
109 default: | 109 default: |
110 err = &OpError{"dial", net + " " + addr, nil, UnknownNetworkErro
r(net)} | 110 err = &OpError{"dial", net + " " + addr, nil, UnknownNetworkErro
r(net)} |
111 } | 111 } |
112 if err != nil { | 112 if err != nil { |
(...skipping 10 matching lines...) Expand all Loading... |
123 // don't have a goroutine sticking around for the default of | 123 // don't have a goroutine sticking around for the default of |
124 // ~3 minutes. | 124 // ~3 minutes. |
125 t := time.NewTimer(timeout) | 125 t := time.NewTimer(timeout) |
126 defer t.Stop() | 126 defer t.Stop() |
127 type pair struct { | 127 type pair struct { |
128 Conn | 128 Conn |
129 error | 129 error |
130 } | 130 } |
131 ch := make(chan pair, 1) | 131 ch := make(chan pair, 1) |
132 resolvedAddr := make(chan Addr, 1) | 132 resolvedAddr := make(chan Addr, 1) |
| 133 fdc := make(chan *netFD, 1) |
133 go func() { | 134 go func() { |
134 _, addri, err := resolveNetAddr("dial", net, addr) | 135 _, addri, err := resolveNetAddr("dial", net, addr) |
135 if err != nil { | 136 if err != nil { |
136 ch <- pair{nil, err} | 137 ch <- pair{nil, err} |
137 return | 138 return |
138 } | 139 } |
139 resolvedAddr <- addri // in case we need it for OpError | 140 resolvedAddr <- addri // in case we need it for OpError |
140 » » c, err := dialAddr(net, addr, addri) | 141 » » c, err := dialAddr(net, addr, addri, fdc) |
141 ch <- pair{c, err} | 142 ch <- pair{c, err} |
142 }() | 143 }() |
143 select { | 144 select { |
144 case <-t.C: | 145 case <-t.C: |
145 // Try to use the real Addr in our OpError, if we resolved it | 146 // Try to use the real Addr in our OpError, if we resolved it |
146 // before the timeout. Otherwise we just use stringAddr. | 147 // before the timeout. Otherwise we just use stringAddr. |
147 var addri Addr | 148 var addri Addr |
148 select { | 149 select { |
149 case a := <-resolvedAddr: | 150 case a := <-resolvedAddr: |
150 addri = a | 151 addri = a |
151 default: | 152 default: |
152 addri = &stringAddr{net, addr} | 153 addri = &stringAddr{net, addr} |
153 } | 154 } |
154 err := &OpError{ | 155 err := &OpError{ |
155 Op: "dial", | 156 Op: "dial", |
156 Net: net, | 157 Net: net, |
157 Addr: addri, | 158 Addr: addri, |
158 Err: &timeoutError{}, | 159 Err: &timeoutError{}, |
159 } | 160 } |
| 161 |
| 162 // Try to close the *netFD, if it was sent. |
| 163 select { |
| 164 case fd := <-fdc: |
| 165 fd.Close() |
| 166 default: |
| 167 } |
| 168 |
160 return nil, err | 169 return nil, err |
161 case p := <-ch: | 170 case p := <-ch: |
162 return p.Conn, p.error | 171 return p.Conn, p.error |
163 } | 172 } |
164 panic("unreachable") | 173 panic("unreachable") |
165 } | 174 } |
166 | 175 |
167 type stringAddr struct { | 176 type stringAddr struct { |
168 net, addr string | 177 net, addr string |
169 } | 178 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 return ListenIP(net, la) | 228 return ListenIP(net, la) |
220 case "unixgram": | 229 case "unixgram": |
221 var la *UnixAddr | 230 var la *UnixAddr |
222 if a != nil { | 231 if a != nil { |
223 la = a.(*UnixAddr) | 232 la = a.(*UnixAddr) |
224 } | 233 } |
225 return DialUnix(net, la, nil) | 234 return DialUnix(net, la, nil) |
226 } | 235 } |
227 return nil, UnknownNetworkError(net) | 236 return nil, UnknownNetworkError(net) |
228 } | 237 } |
OLD | NEW |