[tor-commits] [meek/master] Add some proxy support functions.

dcf at torproject.org dcf at torproject.org
Wed May 28 07:03:21 UTC 2014


commit daab1193f4234bd23e26f7a525356b67630c6ba2
Author: David Fifield <david at bamsoftware.com>
Date:   Sat May 24 20:25:49 2014 -0700

    Add some proxy support functions.
    
    These are candidates to move to goptlib for proposal 232 support.
    
    I assumed that you should be able to give a proxy host as a domain name,
    but it turns out that proposal 232 doesn't actually say that
    (https://trac.torproject.org/projects/tor/ticket/12125#comment:3). Some
    of the tests use IP addresses and some use host names.
---
 meek-client/proxy.go      |   53 ++++++++++++++++++++++++++++++++++
 meek-client/proxy_test.go |   69 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 122 insertions(+)

diff --git a/meek-client/proxy.go b/meek-client/proxy.go
new file mode 100644
index 0000000..56717a3
--- /dev/null
+++ b/meek-client/proxy.go
@@ -0,0 +1,53 @@
+package main
+
+import (
+	"errors"
+	"fmt"
+	"net/url"
+	"os"
+)
+
+import "git.torproject.org/pluggable-transports/goptlib.git"
+
+// The code in this file has to do with configuring an upstream proxy, whether
+// through the command line or the managed interface of proposal 232
+// (TOR_PT_PROXY).
+//
+// https://gitweb.torproject.org/torspec.git/blob/HEAD:/proposals/232-pluggable-transports-through-proxy.txt
+
+// Get the upstream proxy URL. Returns nil if no proxy is requested. The
+// function ensures that the Scheme and Host fields are set; i.e., that the URL
+// is absolute. This function reads the environment variable TOR_PT_PROXY.
+//
+// This function doesn't check that the scheme is one of Tor's supported proxy
+// schemes; that is, one of "http", "socks5", or "socks4a". The caller must be
+// able to handle any returned scheme (which may be by calling PtProxyError if
+// it doesn't know how to handle the scheme).
+func PtGetProxyURL() (*url.URL, error) {
+	rawurl := os.Getenv("TOR_PT_PROXY")
+	if rawurl == "" {
+		return nil, nil
+	}
+	u, err := url.Parse(rawurl)
+	if err != nil {
+		return nil, err
+	}
+	if u.Scheme == "" {
+		return nil, errors.New("missing scheme")
+	}
+	if u.Host == "" {
+		return nil, errors.New("missing host")
+	}
+	return u, nil
+}
+
+// Emit a PROXY-ERROR line with explanation text.
+func PtProxyError(msg string) {
+	fmt.Fprintf(pt.Stdout, "PROXY-ERROR %s\n", msg)
+}
+
+// Emit a PROXY DONE line. Call this after parsing the return value of
+// PtGetProxyURL.
+func PtProxyDone() {
+	fmt.Fprintf(pt.Stdout, "PROXY DONE\n")
+}
diff --git a/meek-client/proxy_test.go b/meek-client/proxy_test.go
new file mode 100644
index 0000000..9565101
--- /dev/null
+++ b/meek-client/proxy_test.go
@@ -0,0 +1,69 @@
+package main
+
+import (
+	"os"
+	"testing"
+)
+
+func TestGetProxyURL(t *testing.T) {
+	badTests := [...]string{
+		"bogus",
+		"http:",
+		"://127.0.0.1",
+		"//127.0.0.1",
+		"http:127.0.0.1",
+		"://[::1]",
+		"//[::1]",
+		"http:[::1]",
+		"://localhost",
+		"//localhost",
+		"http:localhost",
+	}
+	goodTests := [...]struct {
+		input, expected string
+	}{
+		{"http://127.0.0.1", "http://127.0.0.1"},
+		{"http://127.0.0.1:8080", "http://127.0.0.1:8080"},
+		{"http://127.0.0.1:8080/", "http://127.0.0.1:8080/"},
+		{"http://127.0.0.1:8080/path", "http://127.0.0.1:8080/path"},
+		{"http://[::1]", "http://[::1]"},
+		{"http://[::1]:8080", "http://[::1]:8080"},
+		{"http://[::1]:8080/", "http://[::1]:8080/"},
+		{"http://[::1]:8080/path", "http://[::1]:8080/path"},
+		{"http://localhost", "http://localhost"},
+		{"http://localhost:8080", "http://localhost:8080"},
+		{"http://localhost:8080/", "http://localhost:8080/"},
+		{"http://localhost:8080/path", "http://localhost:8080/path"},
+		{"http://user@localhost:8080", "http://user@localhost:8080"},
+		{"http://user:password@localhost:8080", "http://user:password@localhost:8080"},
+		{"unknown://localhost/whatever", "unknown://localhost/whatever"},
+	}
+
+	os.Clearenv()
+	u, err := PtGetProxyURL()
+	if err != nil {
+		t.Errorf("empty environment unexpectedly returned an error: %s", err)
+	}
+	if u != nil {
+		t.Errorf("empty environment returned %q", u)
+	}
+
+	for _, input := range badTests {
+		os.Setenv("TOR_PT_PROXY", input)
+		u, err = PtGetProxyURL()
+		if err == nil {
+			t.Errorf("TOR_PT_PROXY=%q unexpectedly succeeded and returned %q", input, u)
+		}
+	}
+
+	for _, test := range goodTests {
+		os.Setenv("TOR_PT_PROXY", test.input)
+		u, err := PtGetProxyURL()
+		if err != nil {
+			t.Errorf("TOR_PT_PROXY=%q unexpectedly returned an error: %s", test.input, err)
+		}
+		if u == nil || u.String() != test.expected {
+			t.Errorf("TOR_PT_PROXY=%q → %q (expected %q)", test.input, u, test.expected)
+		}
+	}
+}





More information about the tor-commits mailing list