This is an automated email from the git hooks/post-receive script.
arlo pushed a change to branch main in repository pluggable-transports/snowflake.
from 6e29dc6 Add document for NewUTLSHTTPRoundTripper new 6fd0f1a Rename *PollRequest methods to distinguish client/proxy new 829caca Parse ClientPollRequest version in DecodeClientPollRequest new bd636a1 Introduce an unexported newBrokerChannelFromConfig
The 3 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "add" were already present in the repository and have only been added to this reference.
Summary of changes: broker/http.go | 7 +++--- broker/ipc.go | 47 ++++++++++------------------------------ client/lib/rendezvous.go | 45 +++++++++++++++++--------------------- client/lib/rendezvous_test.go | 7 +++--- client/lib/snowflake.go | 4 +--- common/messages/client.go | 30 ++++++++++++++++++++----- common/messages/messages_test.go | 29 ++++++++++++------------- common/messages/proxy.go | 4 ++-- proxy/lib/snowflake.go | 2 +- 9 files changed, 81 insertions(+), 94 deletions(-)
This is an automated email from the git hooks/post-receive script.
arlo pushed a commit to branch main in repository pluggable-transports/snowflake.
commit 6fd0f1ae5dd22bb30100353d80f681b70d879d92 Author: Arlo Breault arlolra@gmail.com AuthorDate: Tue Mar 8 17:49:28 2022 -0500
Rename *PollRequest methods to distinguish client/proxy --- broker/http.go | 2 +- broker/ipc.go | 2 +- client/lib/rendezvous.go | 2 +- client/lib/rendezvous_test.go | 2 +- common/messages/client.go | 2 +- common/messages/messages_test.go | 8 ++++---- common/messages/proxy.go | 4 ++-- proxy/lib/snowflake.go | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/broker/http.go b/broker/http.go index 9ec95d8..3b0ba1f 100644 --- a/broker/http.go +++ b/broker/http.go @@ -149,7 +149,7 @@ func clientOffers(i *IPC, w http.ResponseWriter, r *http.Request) { Offer: string(body), NAT: r.Header.Get("Snowflake-NAT-Type"), } - body, err = req.EncodePollRequest() + body, err = req.EncodeClientPollRequest() if err != nil { log.Printf("Error shimming the legacy request: %s", err.Error()) w.WriteHeader(http.StatusInternalServerError) diff --git a/broker/ipc.go b/broker/ipc.go index c5d66e8..b8359f6 100644 --- a/broker/ipc.go +++ b/broker/ipc.go @@ -75,7 +75,7 @@ func (i *IPC) Debug(_ interface{}, response *string) error { }
func (i *IPC) ProxyPolls(arg messages.Arg, response *[]byte) error { - sid, proxyType, natType, clients, err := messages.DecodePollRequest(arg.Body) + sid, proxyType, natType, clients, err := messages.DecodeProxyPollRequest(arg.Body) if err != nil { return messages.ErrBadRequest } diff --git a/client/lib/rendezvous.go b/client/lib/rendezvous.go index 1fc2a69..0ce2744 100644 --- a/client/lib/rendezvous.go +++ b/client/lib/rendezvous.go @@ -125,7 +125,7 @@ func (bc *BrokerChannel) Negotiate(offer *webrtc.SessionDescription) ( Offer: offerSDP, NAT: bc.natType, } - encReq, err := req.EncodePollRequest() + encReq, err := req.EncodeClientPollRequest() bc.lock.Unlock() if err != nil { return nil, err diff --git a/client/lib/rendezvous_test.go b/client/lib/rendezvous_test.go index 582a979..21b9f57 100644 --- a/client/lib/rendezvous_test.go +++ b/client/lib/rendezvous_test.go @@ -45,7 +45,7 @@ func makeEncPollReq(offer string) []byte { encPollReq, err := (&messages.ClientPollRequest{ Offer: offer, NAT: nat.NATUnknown, - }).EncodePollRequest() + }).EncodeClientPollRequest() if err != nil { panic(err) } diff --git a/common/messages/client.go b/common/messages/client.go index edb7115..5a7d73b 100644 --- a/common/messages/client.go +++ b/common/messages/client.go @@ -54,7 +54,7 @@ type ClientPollRequest struct { }
// Encodes a poll message from a snowflake client -func (req *ClientPollRequest) EncodePollRequest() ([]byte, error) { +func (req *ClientPollRequest) EncodeClientPollRequest() ([]byte, error) { body, err := json.Marshal(req) if err != nil { return nil, err diff --git a/common/messages/messages_test.go b/common/messages/messages_test.go index a38746b..0d8b450 100644 --- a/common/messages/messages_test.go +++ b/common/messages/messages_test.go @@ -97,7 +97,7 @@ func TestDecodeProxyPollRequest(t *testing.T) { fmt.Errorf(""), }, } { - sid, proxyType, natType, clients, err := DecodePollRequest([]byte(test.data)) + sid, proxyType, natType, clients, err := DecodeProxyPollRequest([]byte(test.data)) So(sid, ShouldResemble, test.sid) So(proxyType, ShouldResemble, test.proxyType) So(natType, ShouldResemble, test.natType) @@ -110,9 +110,9 @@ func TestDecodeProxyPollRequest(t *testing.T) {
func TestEncodeProxyPollRequests(t *testing.T) { Convey("Context", t, func() { - b, err := EncodePollRequest("ymbcCMto7KHNGYlp", "standalone", "unknown", 16) + b, err := EncodeProxyPollRequest("ymbcCMto7KHNGYlp", "standalone", "unknown", 16) So(err, ShouldEqual, nil) - sid, proxyType, natType, clients, err := DecodePollRequest(b) + sid, proxyType, natType, clients, err := DecodeProxyPollRequest(b) So(sid, ShouldEqual, "ymbcCMto7KHNGYlp") So(proxyType, ShouldEqual, "standalone") So(natType, ShouldEqual, "unknown") @@ -328,7 +328,7 @@ func TestEncodeClientPollRequests(t *testing.T) { NAT: "unknown", Offer: "fake", } - b, err := req1.EncodePollRequest() + b, err := req1.EncodeClientPollRequest() So(err, ShouldEqual, nil) fmt.Println(string(b)) parts := bytes.SplitN(b, []byte("\n"), 2) diff --git a/common/messages/proxy.go b/common/messages/proxy.go index 83606d3..64f139b 100644 --- a/common/messages/proxy.go +++ b/common/messages/proxy.go @@ -92,7 +92,7 @@ type ProxyPollRequest struct { Clients int }
-func EncodePollRequest(sid string, proxyType string, natType string, clients int) ([]byte, error) { +func EncodeProxyPollRequest(sid string, proxyType string, natType string, clients int) ([]byte, error) { return json.Marshal(ProxyPollRequest{ Sid: sid, Version: version, @@ -105,7 +105,7 @@ func EncodePollRequest(sid string, proxyType string, natType string, clients int // Decodes a poll message from a snowflake proxy and returns the // sid, proxy type, nat type and clients of the proxy on success // and an error if it failed -func DecodePollRequest(data []byte) (sid string, proxyType string, natType string, clients int, err error) { +func DecodeProxyPollRequest(data []byte) (sid string, proxyType string, natType string, clients int, err error) { var message ProxyPollRequest
err = json.Unmarshal(data, &message) diff --git a/proxy/lib/snowflake.go b/proxy/lib/snowflake.go index 8747f66..ae9d5bf 100644 --- a/proxy/lib/snowflake.go +++ b/proxy/lib/snowflake.go @@ -199,7 +199,7 @@ func (s *SignalingServer) pollOffer(sid string, shutdown chan struct{}) *webrtc. default: numClients := int((tokens.count() / 8) * 8) // Round down to 8 currentNATTypeLoaded := getCurrentNATType() - body, err := messages.EncodePollRequest(sid, "standalone", currentNATTypeLoaded, numClients) + body, err := messages.EncodeProxyPollRequest(sid, "standalone", currentNATTypeLoaded, numClients) if err != nil { log.Printf("Error encoding poll message: %s", err.Error()) return nil
This is an automated email from the git hooks/post-receive script.
arlo pushed a commit to branch main in repository pluggable-transports/snowflake.
commit 829cacac5f7ecb2cc701a24061679814fc1841bc Author: Arlo Breault arlolra@gmail.com AuthorDate: Wed Mar 9 19:48:16 2022 -0500
Parse ClientPollRequest version in DecodeClientPollRequest
Instead of IPC.ClientOffers. This makes things consistent with EncodeClientPollRequest which adds the version while serializing. --- broker/http.go | 5 +++-- broker/ipc.go | 45 +++++++++------------------------------- client/lib/rendezvous.go | 5 +++-- client/lib/rendezvous_test.go | 5 +++-- common/messages/client.go | 28 ++++++++++++++++++++----- common/messages/messages_test.go | 21 +++++++++---------- 6 files changed, 52 insertions(+), 57 deletions(-)
diff --git a/broker/http.go b/broker/http.go index 3b0ba1f..7acc465 100644 --- a/broker/http.go +++ b/broker/http.go @@ -146,8 +146,9 @@ func clientOffers(i *IPC, w http.ResponseWriter, r *http.Request) { if len(body) > 0 && body[0] == '{' { isLegacy = true req := messages.ClientPollRequest{ - Offer: string(body), - NAT: r.Header.Get("Snowflake-NAT-Type"), + Offer: string(body), + NAT: r.Header.Get("Snowflake-NAT-Type"), + Version: messages.ClientVersion1_0, } body, err = req.EncodeClientPollRequest() if err != nil { diff --git a/broker/ipc.go b/broker/ipc.go index b8359f6..768c0b7 100644 --- a/broker/ipc.go +++ b/broker/ipc.go @@ -1,7 +1,6 @@ package main
import ( - "bytes" "container/heap" "fmt" "log" @@ -21,12 +20,6 @@ const ( NATUnrestricted = "unrestricted" )
-type clientVersion int - -const ( - v1 clientVersion = iota -) - type IPC struct { ctx *BrokerContext } @@ -132,32 +125,16 @@ func sendClientResponse(resp *messages.ClientPollResponse, response *[]byte) err }
func (i *IPC) ClientOffers(arg messages.Arg, response *[]byte) error { - var version clientVersion - startTime := time.Now() - body := arg.Body
- parts := bytes.SplitN(body, []byte("\n"), 2) - if len(parts) < 2 { - // no version number found - err := fmt.Errorf("unsupported message version") - return sendClientResponse(&messages.ClientPollResponse{Error: err.Error()}, response) - } - body = parts[1] - if string(parts[0]) == "1.0" { - version = v1 - } else { - err := fmt.Errorf("unsupported message version") + req, err := messages.DecodeClientPollRequest(arg.Body) + if err != nil { return sendClientResponse(&messages.ClientPollResponse{Error: err.Error()}, response) }
var offer *ClientOffer - switch version { - case v1: - req, err := messages.DecodeClientPollRequest(body) - if err != nil { - return sendClientResponse(&messages.ClientPollResponse{Error: err.Error()}, response) - } + switch req.Version { + case messages.ClientVersion1_0: offer = &ClientOffer{ natType: req.NAT, sdp: []byte(req.Offer), @@ -188,8 +165,8 @@ func (i *IPC) ClientOffers(arg messages.Arg, response *[]byte) error { i.ctx.metrics.clientRestrictedDeniedCount++ } i.ctx.metrics.lock.Unlock() - switch version { - case v1: + switch req.Version { + case messages.ClientVersion1_0: resp := &messages.ClientPollResponse{Error: messages.StrNoProxies} return sendClientResponse(resp, response) default: @@ -204,8 +181,6 @@ func (i *IPC) ClientOffers(arg messages.Arg, response *[]byte) error { i.ctx.snowflakeLock.Unlock() snowflake.offerChannel <- offer
- var err error - // Wait for the answer to be returned on the channel or timeout. select { case answer := <-snowflake.answerChannel: @@ -213,8 +188,8 @@ func (i *IPC) ClientOffers(arg messages.Arg, response *[]byte) error { i.ctx.metrics.clientProxyMatchCount++ i.ctx.metrics.promMetrics.ClientPollTotal.With(prometheus.Labels{"nat": offer.natType, "status": "matched"}).Inc() i.ctx.metrics.lock.Unlock() - switch version { - case v1: + switch req.Version { + case messages.ClientVersion1_0: resp := &messages.ClientPollResponse{Answer: answer} err = sendClientResponse(resp, response) default: @@ -224,8 +199,8 @@ func (i *IPC) ClientOffers(arg messages.Arg, response *[]byte) error { i.ctx.metrics.clientRoundtripEstimate = time.Since(startTime) / time.Millisecond case <-time.After(time.Second * ClientTimeout): log.Println("Client: Timed out.") - switch version { - case v1: + switch req.Version { + case messages.ClientVersion1_0: resp := &messages.ClientPollResponse{Error: messages.StrTimedOut} err = sendClientResponse(resp, response) default: diff --git a/client/lib/rendezvous.go b/client/lib/rendezvous.go index 0ce2744..e7543ad 100644 --- a/client/lib/rendezvous.go +++ b/client/lib/rendezvous.go @@ -122,8 +122,9 @@ func (bc *BrokerChannel) Negotiate(offer *webrtc.SessionDescription) ( // Encode the client poll request. bc.lock.Lock() req := &messages.ClientPollRequest{ - Offer: offerSDP, - NAT: bc.natType, + Offer: offerSDP, + NAT: bc.natType, + Version: messages.ClientVersion1_0, } encReq, err := req.EncodeClientPollRequest() bc.lock.Unlock() diff --git a/client/lib/rendezvous_test.go b/client/lib/rendezvous_test.go index 21b9f57..a233e7d 100644 --- a/client/lib/rendezvous_test.go +++ b/client/lib/rendezvous_test.go @@ -43,8 +43,9 @@ func (t errorTransport) RoundTrip(req *http.Request) (*http.Response, error) { // offer. func makeEncPollReq(offer string) []byte { encPollReq, err := (&messages.ClientPollRequest{ - Offer: offer, - NAT: nat.NATUnknown, + Offer: offer, + NAT: nat.NATUnknown, + Version: messages.ClientVersion1_0, }).EncodeClientPollRequest() if err != nil { panic(err) diff --git a/common/messages/client.go b/common/messages/client.go index 5a7d73b..2a35594 100644 --- a/common/messages/client.go +++ b/common/messages/client.go @@ -4,13 +4,14 @@ package messages
import ( + "bytes" "encoding/json" "fmt"
"git.torproject.org/pluggable-transports/snowflake.git/v2/common/nat" )
-const ClientVersion = "1.0" +const ClientVersion1_0 = "1.0"
/* Client--Broker protocol v1.x specification:
@@ -49,24 +50,41 @@ for the error. */
type ClientPollRequest struct { - Offer string `json:"offer"` - NAT string `json:"nat"` + Offer string `json:"offer"` + NAT string `json:"nat"` + Version string `json:"-"` }
// Encodes a poll message from a snowflake client func (req *ClientPollRequest) EncodeClientPollRequest() ([]byte, error) { + if req.Version != ClientVersion1_0 { + return nil, fmt.Errorf("unsupported message version") + } body, err := json.Marshal(req) if err != nil { return nil, err } - return append([]byte(ClientVersion+"\n"), body...), nil + return append([]byte(req.Version+"\n"), body...), nil }
// Decodes a poll message from a snowflake client func DecodeClientPollRequest(data []byte) (*ClientPollRequest, error) { + parts := bytes.SplitN(data, []byte("\n"), 2) + + if len(parts) < 2 { + // no version number found + return nil, fmt.Errorf("unsupported message version") + } + var message ClientPollRequest
- err := json.Unmarshal(data, &message) + if string(parts[0]) == ClientVersion1_0 { + message.Version = ClientVersion1_0 + } else { + return nil, fmt.Errorf("unsupported message version") + } + + err := json.Unmarshal(parts[1], &message) if err != nil { return nil, err } diff --git a/common/messages/messages_test.go b/common/messages/messages_test.go index 0d8b450..e0aa2a8 100644 --- a/common/messages/messages_test.go +++ b/common/messages/messages_test.go @@ -1,7 +1,6 @@ package messages
import ( - "bytes" "encoding/json" "fmt" "testing" @@ -286,14 +285,16 @@ func TestDecodeClientPollRequest(t *testing.T) { //version 1.0 client message "unknown", "fake", - `{"nat":"unknown","offer":"fake"}`, + `1.0 +{"nat":"unknown","offer":"fake"}`, nil, }, { //version 1.0 client message "unknown", "fake", - `{"offer":"fake"}`, + `1.0 +{"offer":"fake"}`, nil, }, { @@ -307,16 +308,17 @@ func TestDecodeClientPollRequest(t *testing.T) { //no offer "", "", - `{"nat":"unknown"}`, + `1.0 +{"nat":"unknown"}`, fmt.Errorf(""), }, } { req, err := DecodeClientPollRequest([]byte(test.data)) + So(err, ShouldHaveSameTypeAs, test.err) if test.err == nil { So(req.NAT, ShouldResemble, test.natType) So(req.Offer, ShouldResemble, test.offer) } - So(err, ShouldHaveSameTypeAs, test.err) }
}) @@ -325,15 +327,12 @@ func TestDecodeClientPollRequest(t *testing.T) { func TestEncodeClientPollRequests(t *testing.T) { Convey("Context", t, func() { req1 := &ClientPollRequest{ - NAT: "unknown", - Offer: "fake", + NAT: "unknown", + Offer: "fake", + Version: ClientVersion1_0, } b, err := req1.EncodeClientPollRequest() So(err, ShouldEqual, nil) - fmt.Println(string(b)) - parts := bytes.SplitN(b, []byte("\n"), 2) - So(string(parts[0]), ShouldEqual, "1.0") - b = parts[1] req2, err := DecodeClientPollRequest(b) So(err, ShouldEqual, nil) So(req2, ShouldResemble, req1)
This is an automated email from the git hooks/post-receive script.
arlo pushed a commit to branch main in repository pluggable-transports/snowflake.
commit bd636a1374efb514bbc40acbd1dcaf0ecec26916 Author: Arlo Breault arlolra@gmail.com AuthorDate: Thu Mar 10 14:13:35 2022 -0500
Introduce an unexported newBrokerChannelFromConfig
A follow-up wants to pass in a new property from the ClientConfig but it would be an API breaking change to NewBrokerChannel.
However, it's unclear why NewBrokerChannel is exported at all. No other package in the repo depends on it and the known users of the library probably wouldn't be construct them.
While this patch was being reviewed, a new constructor was added, NewBrokerChannelWithUTLSSettings, with effectively the same issue. Both of those exported ones are deleted here. --- client/lib/rendezvous.go | 38 ++++++++++++++++---------------------- client/lib/snowflake.go | 4 +--- 2 files changed, 17 insertions(+), 25 deletions(-)
diff --git a/client/lib/rendezvous.go b/client/lib/rendezvous.go index e7543ad..73c62ed 100644 --- a/client/lib/rendezvous.go +++ b/client/lib/rendezvous.go @@ -55,40 +55,34 @@ func createBrokerTransport() http.RoundTripper { return transport }
-func NewBrokerChannel(broker, ampCache, front string, keepLocalAddresses bool) (*BrokerChannel, error) { - return NewBrokerChannelWithUTLSSettings(broker, ampCache, front, keepLocalAddresses, "", false) -} +func newBrokerChannelFromConfig(config ClientConfig) (*BrokerChannel, error) { + log.Println("Rendezvous using Broker at:", config.BrokerURL)
-// NewBrokerChannelWithUTLSSettings 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 NewBrokerChannelWithUTLSSettings(broker, ampCache, front string, keepLocalAddresses bool, - uTLSClientID string, removeSNI 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) + if config.FrontDomain != "" { + log.Println("Domain fronting using:", config.FrontDomain) }
brokerTransport := createBrokerTransport()
- if uTLSClientID != "" { - utlsClientHelloID, err := utlsutil.NameToUTLSID(uTLSClientID) + if config.UTLSClientID != "" { + utlsClientHelloID, err := utlsutil.NameToUTLSID(config.UTLSClientID) if err != nil { return nil, fmt.Errorf("unable to create broker channel: %v", err) } - config := &utls.Config{} - brokerTransport = utlsutil.NewUTLSHTTPRoundTripper(utlsClientHelloID, config, brokerTransport, removeSNI) + utlsConfig := &utls.Config{} + brokerTransport = utlsutil.NewUTLSHTTPRoundTripper(utlsClientHelloID, utlsConfig, brokerTransport, config.UTLSRemoveSNI) }
var rendezvous RendezvousMethod var err error - if ampCache != "" { - rendezvous, err = newAMPCacheRendezvous(broker, ampCache, front, brokerTransport) + if config.AmpCacheURL != "" { + log.Println("Through AMP cache at:", config.AmpCacheURL) + rendezvous, err = newAMPCacheRendezvous( + config.BrokerURL, config.AmpCacheURL, config.FrontDomain, + brokerTransport) } else { - rendezvous, err = newHTTPRendezvous(broker, front, brokerTransport) + rendezvous, err = newHTTPRendezvous( + config.BrokerURL, config.FrontDomain, brokerTransport) } if err != nil { return nil, err @@ -96,7 +90,7 @@ func NewBrokerChannelWithUTLSSettings(broker, ampCache, front string, keepLocalA
return &BrokerChannel{ Rendezvous: rendezvous, - keepLocalAddresses: keepLocalAddresses, + keepLocalAddresses: config.KeepLocalAddresses, natType: nat.NATUnknown, }, nil } diff --git a/client/lib/snowflake.go b/client/lib/snowflake.go index 1c6c381..1b236a6 100644 --- a/client/lib/snowflake.go +++ b/client/lib/snowflake.go @@ -131,9 +131,7 @@ func NewSnowflakeClient(config ClientConfig) (*Transport, error) { }
// Rendezvous with broker using the given parameters. - broker, err := NewBrokerChannelWithUTLSSettings( - config.BrokerURL, config.AmpCacheURL, config.FrontDomain, - config.KeepLocalAddresses, config.UTLSClientID, config.UTLSRemoveSNI) + broker, err := newBrokerChannelFromConfig(config) if err != nil { return nil, err }
tor-commits@lists.torproject.org