| // Copyright 2012 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // +build windows plan9 |
| |
| package net |
| |
| import ( |
| "time" |
| ) |
| |
| // resolveAndDialChannel is the simple pure-Go implementation of |
| // resolveAndDial, still used on operating systems where the deadline |
| // hasn't been pushed down into the pollserver. (Plan 9 and some old |
| // versions of Windows) |
| func resolveAndDialChannel(net, addr string, localAddr Addr, deadline time.Time) (Conn, error) { |
| timeout := deadline.Sub(time.Now()) |
| if timeout < 0 { |
| timeout = 0 |
| } |
| t := time.NewTimer(timeout) |
| defer t.Stop() |
| type pair struct { |
| Conn |
| error |
| } |
| ch := make(chan pair, 1) |
| resolvedAddr := make(chan Addr, 1) |
| go func() { |
| ra, err := resolveAddr("dial", net, addr, noDeadline) |
| if err != nil { |
| ch <- pair{nil, err} |
| return |
| } |
| resolvedAddr <- ra // in case we need it for OpError |
| c, err := dial(net, addr, localAddr, ra, noDeadline) |
| ch <- pair{c, err} |
| }() |
| select { |
| case <-t.C: |
| // Try to use the real Addr in our OpError, if we resolved it |
| // before the timeout. Otherwise we just use stringAddr. |
| var ra Addr |
| select { |
| case a := <-resolvedAddr: |
| ra = a |
| default: |
| ra = &stringAddr{net, addr} |
| } |
| err := &OpError{ |
| Op: "dial", |
| Net: net, |
| Addr: ra, |
| Err: &timeoutError{}, |
| } |
| return nil, err |
| case p := <-ch: |
| return p.Conn, p.error |
| } |
| } |