commit 678cf454cd51ab9c749ffd70debaec177e2bed54 Author: Serene Han keroserene+git@gmail.com Date: Sun Jan 31 21:42:53 2016 -0800
s/MeekChannel/BrokerChannel (close #14) and more informative TODOs --- client/meek-webrtc.go | 74 -------------------------------------------------- client/rendezvous.go | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ client/snowflake.go | 31 ++++++++++++--------- 3 files changed, 94 insertions(+), 86 deletions(-)
diff --git a/client/meek-webrtc.go b/client/meek-webrtc.go deleted file mode 100644 index 34ff185..0000000 --- a/client/meek-webrtc.go +++ /dev/null @@ -1,74 +0,0 @@ -// Exchange WebRTC SessionDescriptions over a domain-fronted HTTP -// signaling channel. -package main - -import ( - "bytes" - "io/ioutil" - "log" - "net/http" - "net/url" - - "github.com/keroserene/go-webrtc" -) - -// Meek Signalling Channel. -type MeekChannel struct { - // The Host header to put in the HTTP request (optional and may be - // different from the host name in URL). - Host string - url *url.URL - transport http.Transport // Used to make all requests. -} - -// Construct a new MeekChannel, where: -// |broker| is the full URL of the facilitating program which assigns proxies -// to clients, and |front| is the option fronting domain. -func NewMeekChannel(broker string, front string) *MeekChannel { - targetURL, err := url.Parse(broker) - if nil != err { - return nil - } - mc := new(MeekChannel) - mc.url = targetURL - if "" != front { // Optional front domain. - mc.Host = mc.url.Host - mc.url.Host = front - } - - // We make a copy of DefaultTransport because we want the default Dial - // and TLSHandshakeTimeout settings. But we want to disable the default - // ProxyFromEnvironment setting. - mc.transport = *http.DefaultTransport.(*http.Transport) - mc.transport.Proxy = nil - return mc -} - -// Roundtrip HTTP POST using WebRTC SessionDescriptions. -// -// Sends an SDP offer to the meek broker, which assigns a proxy and responds -// with an SDP answer from a designated remote WebRTC peer. -func (mc *MeekChannel) Negotiate(offer *webrtc.SessionDescription) ( - *webrtc.SessionDescription, error) { - data := bytes.NewReader([]byte(offer.Serialize())) - // Suffix with broker's client registration handler. - request, err := http.NewRequest("POST", mc.url.String()+"client", data) - if nil != err { - return nil, err - } - if "" != mc.Host { // Set true host if necessary. - request.Host = mc.Host - } - resp, err := mc.transport.RoundTrip(request) - if nil != err { - return nil, err - } - defer resp.Body.Close() - log.Printf("MeekChannel Response:\n%s\n\n", resp.Status) - body, err := ioutil.ReadAll(resp.Body) - if nil != err { - return nil, err - } - answer := webrtc.DeserializeSessionDescription(string(body)) - return answer, nil -} diff --git a/client/rendezvous.go b/client/rendezvous.go new file mode 100644 index 0000000..ea0b338 --- /dev/null +++ b/client/rendezvous.go @@ -0,0 +1,75 @@ +// WebRTC Rendezvous requires the exchange of SessionDescriptions between +// peers. This file contains the domain-fronted HTTP signaling mechanism +// between the client and a desired Broker. +package main + +import ( + "bytes" + "io/ioutil" + "log" + "net/http" + "net/url" + + "github.com/keroserene/go-webrtc" +) + +// Signalling Channel to the Broker. +type BrokerChannel struct { + // The Host header to put in the HTTP request (optional and may be + // different from the host name in URL). + Host string + url *url.URL + transport http.Transport // Used to make all requests. +} + +// 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) *BrokerChannel { + targetURL, err := url.Parse(broker) + if nil != err { + return nil + } + bc := new(BrokerChannel) + bc.url = targetURL + if "" != front { // Optional front domain. + bc.Host = bc.url.Host + bc.url.Host = front + } + + // We make a copy of DefaultTransport because we want the default Dial + // and TLSHandshakeTimeout settings. But we want to disable the default + // ProxyFromEnvironment setting. + bc.transport = *http.DefaultTransport.(*http.Transport) + bc.transport.Proxy = nil + return bc +} + +// Roundtrip HTTP POST using WebRTC SessionDescriptions. +// +// Send an SDP offer to the broker, which assigns a proxy and responds +// with an SDP answer from a designated remote WebRTC peer. +func (bc *BrokerChannel) Negotiate(offer *webrtc.SessionDescription) ( + *webrtc.SessionDescription, error) { + data := bytes.NewReader([]byte(offer.Serialize())) + // Suffix with broker's client registration handler. + request, err := http.NewRequest("POST", bc.url.String()+"client", data) + if nil != err { + return nil, err + } + if "" != bc.Host { // Set true host if necessary. + request.Host = bc.Host + } + resp, err := bc.transport.RoundTrip(request) + if nil != err { + return nil, err + } + defer resp.Body.Close() + log.Printf("BrokerChannel Response:\n%s\n\n", resp.Status) + body, err := ioutil.ReadAll(resp.Body) + if nil != err { + return nil, err + } + answer := webrtc.DeserializeSessionDescription(string(body)) + return answer, nil +} diff --git a/client/snowflake.go b/client/snowflake.go index 83179a3..486e602 100644 --- a/client/snowflake.go +++ b/client/snowflake.go @@ -1,10 +1,9 @@ -// Client transport plugin for the snowflake pluggable transport. -// -// TODO: Use meek for signalling. +// Client transport plugin for the Snowflake pluggable transport. package main
import ( "bufio" + "errors" "flag" "fmt" "io" @@ -16,10 +15,9 @@ import ( "syscall" "time"
+ "git.torproject.org/pluggable-transports/goptlib.git" "github.com/keroserene/go-webrtc" "github.com/keroserene/go-webrtc/data" - - "git.torproject.org/pluggable-transports/goptlib.git" )
var ptInfo pt.ClientInfo @@ -93,7 +91,7 @@ func (c *webRTCConn) SetWriteDeadline(t time.Time) error { return fmt.Errorf("SetWriteDeadline not implemented") }
-func dialWebRTC(config *webrtc.Configuration, meek *MeekChannel) ( +func dialWebRTC(config *webrtc.Configuration, broker *BrokerChannel) ( *webRTCConn, error) {
offerChan := make(chan *webrtc.SessionDescription) @@ -131,6 +129,8 @@ func dialWebRTC(config *webrtc.Configuration, meek *MeekChannel) ( log.Printf("OnIceComplete") offerChan <- pc.LocalDescription() } + // This callback is not expected, as the Client initiates the creation + // of the data channel, not the remote peer. pc.OnDataChannel = func(channel *data.Channel) { log.Println("OnDataChannel") panic("OnDataChannel") @@ -151,6 +151,7 @@ func dialWebRTC(config *webrtc.Configuration, meek *MeekChannel) ( log.Println("OnClose channel") pw.Close() close(openChan) + // TODO: (Issue #12) Should attempt to renegotiate at this point. } dc.OnMessage = func(msg []byte) { log.Printf("OnMessage <--- %d bytes", len(msg)) @@ -173,14 +174,14 @@ func dialWebRTC(config *webrtc.Configuration, meek *MeekChannel) ( log.Printf("----------------") go func() { if "" != brokerURL { - log.Println("Sending offer via meek channel...\nTarget URL: ", brokerURL, + log.Println("Sending offer via BrokerChannel...\nTarget URL: ", brokerURL, "\nFront URL: ", frontDomain) - answer, err := meek.Negotiate(pc.LocalDescription()) + answer, err := broker.Negotiate(pc.LocalDescription()) if nil != err { - log.Printf("MeekChannel signaling error: %s", err) + log.Printf("BrokerChannel signaling error: %s", err) } if nil == answer { - log.Printf("MeekChannel: No answer received.") + log.Printf("BrokerChannel: No answer received.") } else { signalChan <- answer } @@ -236,10 +237,16 @@ func handler(conn *pt.SocksConn) error { }() defer conn.Close()
+ // TODO: [#3] Fetch ICE server information from Broker. + // TODO: [#18] Consider TURN servers here too. config := webrtc.NewConfiguration( webrtc.OptionIceServer("stun:stun.l.google.com:19302")) - meek := NewMeekChannel(brokerURL, frontDomain) - remote, err := dialWebRTC(config, meek) + broker := NewBrokerChannel(brokerURL, frontDomain) + if nil == broker { + conn.Reject() + return errors.New("Failed to prepare BrokerChannel") + } + remote, err := dialWebRTC(config, broker) if err != nil { conn.Reject() return err