github.com/Psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/upstreamproxy/upstreamproxy.go (about) 1 /* 2 * Copyright (c) 2015, Psiphon Inc. 3 * All rights reserved. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package upstreamproxy 21 22 import ( 23 "fmt" 24 "net" 25 "net/http" 26 27 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common" 28 "golang.org/x/net/proxy" 29 ) 30 31 type DialFunc func(string, string) (net.Conn, error) 32 33 type Error struct { 34 error 35 } 36 37 func proxyError(err error) error { 38 // Avoid multiple upstream.Error wrapping 39 if _, ok := err.(*Error); ok { 40 return err 41 } 42 return &Error{error: fmt.Errorf("upstreamproxy error: %s", err)} 43 } 44 45 type UpstreamProxyConfig struct { 46 ForwardDialFunc DialFunc 47 ProxyURIString string 48 CustomHeaders http.Header 49 } 50 51 // Dial implements the proxy.Dialer interface, allowing a UpstreamProxyConfig 52 // to be passed to proxy.FromURL. 53 func (u *UpstreamProxyConfig) Dial(network, addr string) (net.Conn, error) { 54 return u.ForwardDialFunc(network, addr) 55 } 56 57 func NewProxyDialFunc(config *UpstreamProxyConfig) DialFunc { 58 if config.ProxyURIString == "" { 59 return config.ForwardDialFunc 60 } 61 proxyURI, err := common.SafeParseURL(config.ProxyURIString) 62 if err != nil { 63 return func(network, addr string) (net.Conn, error) { 64 return nil, proxyError(fmt.Errorf("NewProxyDialFunc: SafeParseURL failed: %v", err)) 65 } 66 } 67 68 dialer, err := proxy.FromURL(proxyURI, config) 69 if err != nil { 70 return func(network, addr string) (net.Conn, error) { 71 return nil, proxyError(fmt.Errorf("NewProxyDialFunc: proxy.FromURL: %v", err)) 72 } 73 } 74 return dialer.Dial 75 }