commit e4e068640f26bc070199bc9d7ba661bb14d2e25a Author: Serene Han keroserene+git@gmail.com Date: Mon Jan 18 10:53:22 2016 -0800
begin appengine rendezvous component - domain fronting works, although it just reflects the offer. next step is to retrieve browser proxy answer (#1) --- client/meek-webrtc.go | 19 +++++++++---- client/snowflake.go | 13 ++++++--- rendezvous/app.yaml | 10 +++++++ rendezvous/config.go | 16 +++++++++++ rendezvous/snowflake-reg.go | 65 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 113 insertions(+), 10 deletions(-)
diff --git a/client/meek-webrtc.go b/client/meek-webrtc.go index d783781..927d4bf 100644 --- a/client/meek-webrtc.go +++ b/client/meek-webrtc.go @@ -5,6 +5,7 @@ package main import ( "bytes" "io/ioutil" + "log" "net/http" "net/url"
@@ -31,8 +32,9 @@ func NewRequestInfo(meekUrl string, front string) *RequestInfo { return nil } info.URL = requestUrl - info.Host = info.URL.Host - info.URL.Host = front + info.Host = front + // info.URL.Host = front + // info.Host = info.URL.Host return info }
@@ -57,13 +59,13 @@ func NewMeekChannel(info *RequestInfo) *MeekChannel {
// Do an HTTP roundtrip using the payload data in buf. func (m *MeekChannel) roundTripHTTP(buf []byte) (*http.Response, error) { - req, err := http.NewRequest("POST", m.info.URL.String(), bytes.NewReader(buf)) + // Compose an innocent looking request. + req, err := http.NewRequest("POST", m.info.Host+"/reg/123", bytes.NewReader(buf)) if nil != err { return nil, err } - if "" != m.info.Host { - req.Host = m.info.Host - } + // Set actually desired target host. + req.Host = m.info.URL.String() // req.Header.Set("X-Session-Id", m.info.SessionID) return m.transport.RoundTrip(req) } @@ -78,7 +80,12 @@ func (m *MeekChannel) Negotiate(offer *webrtc.SessionDescription) ( return nil, err } defer resp.Body.Close() + log.Println("MeekChannel Response: ", resp) body, err := ioutil.ReadAll(resp.Body) + if nil != err { + return nil, err + } + log.Println("MeekChannel Body: ", string(body)) answer := webrtc.DeserializeSessionDescription(string(body)) return answer, nil } diff --git a/client/snowflake.go b/client/snowflake.go index b42b17d..7da1e15 100644 --- a/client/snowflake.go +++ b/client/snowflake.go @@ -25,8 +25,9 @@ import ( // Hard-coded meek signalling channel for now. // TODO: expose as param const ( - MEEK_URL = "not implemented yet" - FRONT_DOMAIN = "www.google.com" + MEEK_URL = "snowflake-reg.appspot.com" + FRONT_DOMAIN = "https://www.google.com" + // FRONT_DOMAIN = "https://www.google.com" )
var ptInfo pt.ClientInfo @@ -187,7 +188,11 @@ func dialWebRTC(config *webrtc.Configuration, meek *MeekChannel) ( // if nil == answer { // log.Printf("No answer received from meek channel.") // } else { - // signalChan <- answer + // // TODO: Once this is correct, uncomment and remove copy-paste + // // signalling. + // log.Println("Recieved answer from Meek channel: \n", + // answer.Serialize()) + // // signalChan <- answer // } if offerURL != "" { answer, err := sendOfferHTTP(offerURL, offer) @@ -207,7 +212,7 @@ func dialWebRTC(config *webrtc.Configuration, meek *MeekChannel) ( pc.Close() return nil, fmt.Errorf("no answer received") } - log.Printf("got answer %s", answer.Serialize()) + log.Printf("Received Answer: %s", answer.Serialize()) err = pc.SetRemoteDescription(answer) if err != nil { pc.Close() diff --git a/rendezvous/README.md b/rendezvous/README.md new file mode 100644 index 0000000..e69de29 diff --git a/rendezvous/app.yaml b/rendezvous/app.yaml new file mode 100644 index 0000000..14fcf0a --- /dev/null +++ b/rendezvous/app.yaml @@ -0,0 +1,10 @@ +# override this with appcfg.py -A $YOUR_APP_ID +application: snowflake-reg +version: 1 +runtime: go +api_version: go1 + +handlers: +- url: /.* + script: _go_app + secure: always diff --git a/rendezvous/config.go b/rendezvous/config.go new file mode 100644 index 0000000..eabbe65 --- /dev/null +++ b/rendezvous/config.go @@ -0,0 +1,16 @@ +/* +This is the server-side code that runs on Google App Engine for the +"appspot" registration method. + +See doc/appspot-howto.txt for more details about setting up an +application, and advice on running one. + +To upload a new version: +$ torify ~/go_appengine/appcfg.py --no_cookies -A $YOUR_APP_ID update . +*/ +package snowflake_reg + +// host:port/basepath of the facilitator you want to register with +// for example, fp-facilitator.org or example.com:12345/facilitator +// https:// and /reg/ will be prepended and appended respectively. +const SNOWFLAKE_FACILITATOR = "" diff --git a/rendezvous/snowflake-reg.go b/rendezvous/snowflake-reg.go new file mode 100644 index 0000000..094612d --- /dev/null +++ b/rendezvous/snowflake-reg.go @@ -0,0 +1,65 @@ +package snowflake_reg + +import ( + // "io" + "io/ioutil" + "log" + "net" + "net/http" + "path" + + // "appengine" + // "appengine/urlfetch" +) + +// This is an intermediate step - a basic hardcoded appengine rendezvous +// to a single browser snowflake. + +var snowflakeProxy = "" + +func robotsTxtHandler(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.Write([]byte("User-agent: *\nDisallow:\n")) +} + +func ipHandler(w http.ResponseWriter, r *http.Request) { + remoteAddr := r.RemoteAddr + if net.ParseIP(remoteAddr).To4() == nil { + remoteAddr = "[" + remoteAddr + "]" + } + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.Write([]byte(remoteAddr)) +} + +/* +Expects a WebRTC SDP offer in the Request to give to an assigned +snowflake proxy, which responds with the SDP answer to be sent in +the HTTP response back to the client. +*/ +func regHandler(w http.ResponseWriter, r *http.Request) { + // TODO: Maybe don't pass anything on path, since it will always be bidirectional + dir, _ := path.Split(path.Clean(r.URL.Path)) + if dir != "/reg/" { + http.NotFound(w, r) + return + } + body, err := ioutil.ReadAll(r.Body) + if nil != err { + return + log.Println("Invalid data.") + } + + // TODO: Get browser snowflake to talkto this appengine instance + // so it can reply with an answer, and not just the offer again :) + // TODO: Real facilitator which matches clients and snowflake proxies. + w.Write(body) +} + +func init() { + http.HandleFunc("/robots.txt", robotsTxtHandler) + http.HandleFunc("/ip", ipHandler) + http.HandleFunc("/reg/", regHandler) + // if SNOWFLAKE_FACILITATOR == "" { + // panic("SNOWFLAKE_FACILITATOR empty; did you forget to edit config.go?") + // } +}