[tor-commits] [snowflake/main] Skeleton of ampCacheRendezvous.

dcf at torproject.org dcf at torproject.org
Thu Aug 5 22:18:28 UTC 2021


commit c13810192d243690dab4c0e890a1f50273a22ca1
Author: David Fifield <david at bamsoftware.com>
Date:   Sun Jul 18 14:18:32 2021 -0600

    Skeleton of ampCacheRendezvous.
    
    Currently the same as httpRendezvous, but activated using the -ampcache
    command-line option.
---
 client/lib/rendezvous.go          | 13 ++++++-
 client/lib/rendezvous_ampcache.go | 78 +++++++++++++++++++++++++++++++++++++++
 client/lib/snowflake.go           |  7 ++--
 client/snowflake.go               |  3 +-
 4 files changed, 95 insertions(+), 6 deletions(-)

diff --git a/client/lib/rendezvous.go b/client/lib/rendezvous.go
index 8568120..8af638f 100644
--- a/client/lib/rendezvous.go
+++ b/client/lib/rendezvous.go
@@ -59,13 +59,22 @@ func CreateBrokerTransport() http.RoundTripper {
 // Construct a new BrokerChannel, where:
 // |broker| is the full URL of the facilitating program which assigns proxies
 // to clients, and |front| is the option fronting domain.
-func NewBrokerChannel(broker string, front string, transport http.RoundTripper, keepLocalAddresses bool) (*BrokerChannel, error) {
+func NewBrokerChannel(broker, ampCache, front string, transport http.RoundTripper, keepLocalAddresses bool) (*BrokerChannel, error) {
 	log.Println("Rendezvous using Broker at:", broker)
+	if ampCache != "" {
+		log.Println("Through AMP cache at:", ampCache)
+	}
 	if front != "" {
 		log.Println("Domain fronting using:", front)
 	}
 
-	rendezvous, err := newHTTPRendezvous(broker, front, transport)
+	var rendezvous rendezvousMethod
+	var err error
+	if ampCache != "" {
+		rendezvous, err = newAMPCacheRendezvous(broker, ampCache, front, transport)
+	} else {
+		rendezvous, err = newHTTPRendezvous(broker, front, transport)
+	}
 	if err != nil {
 		return nil, err
 	}
diff --git a/client/lib/rendezvous_ampcache.go b/client/lib/rendezvous_ampcache.go
new file mode 100644
index 0000000..89745f4
--- /dev/null
+++ b/client/lib/rendezvous_ampcache.go
@@ -0,0 +1,78 @@
+package lib
+
+import (
+	"bytes"
+	"errors"
+	"log"
+	"net/http"
+	"net/url"
+)
+
+// ampCacheRendezvous is a rendezvousMethod that communicates with the
+// .../amp/client route of the broker, optionally over an AMP cache proxy, and
+// with optional domain fronting.
+type ampCacheRendezvous struct {
+	brokerURL *url.URL
+	cacheURL  *url.URL          // Optional AMP cache URL.
+	front     string            // Optional front domain to replace url.Host in requests.
+	transport http.RoundTripper // Used to make all requests.
+}
+
+// newAMPCacheRendezvous creates a new ampCacheRendezvous that contacts the
+// broker at the given URL, optionally proxying through an AMP cache, and with
+// an optional front domain. transport is the http.RoundTripper used to make all
+// requests.
+func newAMPCacheRendezvous(broker, cache, front string, transport http.RoundTripper) (*ampCacheRendezvous, error) {
+	brokerURL, err := url.Parse(broker)
+	if err != nil {
+		return nil, err
+	}
+	var cacheURL *url.URL
+	if cache != "" {
+		var err error
+		cacheURL, err = url.Parse(cache)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return &ampCacheRendezvous{
+		brokerURL: brokerURL,
+		cacheURL:  cacheURL,
+		front:     front,
+		transport: transport,
+	}, nil
+}
+
+func (r *ampCacheRendezvous) Exchange(encPollReq []byte) ([]byte, error) {
+	log.Println("Negotiating via AMP cache rendezvous...")
+	log.Println("Broker URL:", r.brokerURL)
+	log.Println("AMP cache URL:", r.cacheURL)
+	log.Println("Front domain:", r.front)
+
+	// Suffix the path with the broker's client registration handler.
+	reqURL := r.brokerURL.ResolveReference(&url.URL{Path: "client"})
+	req, err := http.NewRequest("POST", reqURL.String(), bytes.NewReader(encPollReq))
+	if err != nil {
+		return nil, err
+	}
+
+	if r.front != "" {
+		// Do domain fronting. Replace the domain in the URL's with the
+		// front, and store the original domain the HTTP Host header.
+		req.Host = req.URL.Host
+		req.URL.Host = r.front
+	}
+
+	resp, err := r.transport.RoundTrip(req)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+
+	log.Printf("AMP cache rendezvous response: %s", resp.Status)
+	if resp.StatusCode != http.StatusOK {
+		return nil, errors.New(BrokerErrorUnexpected)
+	}
+
+	return limitedRead(resp.Body, readLimit)
+}
diff --git a/client/lib/snowflake.go b/client/lib/snowflake.go
index f643c0a..0fc7671 100644
--- a/client/lib/snowflake.go
+++ b/client/lib/snowflake.go
@@ -39,7 +39,8 @@ type Transport struct {
 // iceAddresses are the STUN/TURN urls needed for WebRTC negotiation
 // keepLocalAddresses is a flag to enable sending local network addresses (for testing purposes)
 // max is the maximum number of snowflakes the client should gather for each SOCKS connection
-func NewSnowflakeClient(brokerURL, frontDomain string, iceAddresses []string, keepLocalAddresses bool, max int) (*Transport, error) {
+func NewSnowflakeClient(brokerURL, ampCacheURL, frontDomain string,
+	iceAddresses []string, keepLocalAddresses bool, max int) (*Transport, error) {
 
 	log.Println("\n\n\n --- Starting Snowflake Client ---")
 
@@ -57,9 +58,9 @@ func NewSnowflakeClient(brokerURL, frontDomain string, iceAddresses []string, ke
 		log.Printf("url: %v", strings.Join(server.URLs, " "))
 	}
 
-	// Use potentially domain-fronting broker to rendezvous.
+	// Rendezvous with broker using the given parameters.
 	broker, err := NewBrokerChannel(
-		brokerURL, frontDomain, CreateBrokerTransport(),
+		brokerURL, ampCacheURL, frontDomain, CreateBrokerTransport(),
 		keepLocalAddresses)
 	if err != nil {
 		return nil, err
diff --git a/client/snowflake.go b/client/snowflake.go
index af9c2e4..ef06a2d 100644
--- a/client/snowflake.go
+++ b/client/snowflake.go
@@ -94,6 +94,7 @@ func main() {
 	iceServersCommas := flag.String("ice", "", "comma-separated list of ICE servers")
 	brokerURL := flag.String("url", "", "URL of signaling broker")
 	frontDomain := flag.String("front", "", "front domain")
+	ampCacheURL := flag.String("ampcache", "", "URL of AMP cache to use as a proxy for signaling")
 	logFilename := flag.String("log", "", "name of log file")
 	logToStateDir := flag.Bool("log-to-state-dir", false, "resolve the log file relative to tor's pt state dir")
 	keepLocalAddresses := flag.Bool("keep-local-addresses", false, "keep local LAN address ICE candidates")
@@ -140,7 +141,7 @@ func main() {
 
 	iceAddresses := strings.Split(strings.TrimSpace(*iceServersCommas), ",")
 
-	transport, err := sf.NewSnowflakeClient(*brokerURL, *frontDomain, iceAddresses,
+	transport, err := sf.NewSnowflakeClient(*brokerURL, *ampCacheURL, *frontDomain, iceAddresses,
 		*keepLocalAddresses || *oldKeepLocalAddresses, *max)
 	if err != nil {
 		log.Fatal("Failed to start snowflake transport: ", err)





More information about the tor-commits mailing list