Beispiel #1
0
// makeTCPDialer creates a custom dialer which creates TCPConn. An upstream
// proxy is used when specified.
func makeTCPDialer(config *DialConfig) func(network, addr string) (net.Conn, error) {

	dialer := func(network, addr string) (net.Conn, error) {
		if network != "tcp" {
			return nil, errors.New("unsupported network type in TCPConn dialer")
		}
		conn, err := interruptibleTCPDial(addr, config)
		if err != nil {
			return nil, ContextError(err)
		}
		return conn, nil
	}

	if config.UpstreamProxyUrl != "" {

		upstreamDialer := upstreamproxy.NewProxyDialFunc(
			&upstreamproxy.UpstreamProxyConfig{
				ForwardDialFunc: dialer,
				ProxyURIString:  config.UpstreamProxyUrl,
			})

		dialer = func(network, addr string) (conn net.Conn, err error) {

			// The entire upstream dial is wrapped in an explicit timeout. This
			// may include network connection read and writes when proxy auth negotation
			// is performed.

			type upstreamDialResult struct {
				conn net.Conn
				err  error
			}
			if config.ConnectTimeout != 0 {
				resultChannel := make(chan *upstreamDialResult, 2)
				time.AfterFunc(config.ConnectTimeout, func() {
					// TODO: we could "interrupt" the underlying TCPConn at this point, as
					// it's being abandoned. But we don't have a reference to it. It's left
					// to the outer DialConfig.PendingConns to track and clean up that TCPConn.
					resultChannel <- &upstreamDialResult{nil, errors.New("upstreamproxy dial timeout")}
				})
				go func() {
					conn, err := upstreamDialer(network, addr)
					resultChannel <- &upstreamDialResult{conn, err}
				}()
				result := <-resultChannel

				conn, err = result.conn, result.err
			} else {
				conn, err = upstreamDialer(network, addr)
			}

			if _, ok := err.(*upstreamproxy.Error); ok {
				NoticeUpstreamProxyError(err)
			}
			return conn, err
		}
	}

	return dialer
}
Beispiel #2
0
// proxiedTcpDial wraps a tcpDial call in an upstreamproxy dial.
func proxiedTcpDial(
	addr string, config *DialConfig, dialResult chan error) (net.Conn, error) {
	dialer := func(network, addr string) (net.Conn, error) {
		return tcpDial(addr, config, dialResult)
	}
	upstreamDialer := upstreamproxy.NewProxyDialFunc(
		&upstreamproxy.UpstreamProxyConfig{
			ForwardDialFunc: dialer,
			ProxyURIString:  config.UpstreamProxyUrl,
		})
	netConn, err := upstreamDialer("tcp", addr)
	if _, ok := err.(*upstreamproxy.Error); ok {
		NoticeUpstreamProxyError(err)
	}
	return netConn, err
}