From eab5fd5bdd35f27e4134bec87f6518f823565fe8 Mon Sep 17 00:00:00 2001 From: AudriusButkevicius Date: Mon, 7 Sep 2015 09:21:23 +0100 Subject: [PATCH] Join relay pool by default --- main.go | 28 ++++++++++++++++++++++++- pool.go | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 pool.go diff --git a/main.go b/main.go index c050c355d..4e7e9a137 100644 --- a/main.go +++ b/main.go @@ -5,9 +5,12 @@ package main import ( "crypto/tls" "flag" + "fmt" "log" "net" + "net/url" "path/filepath" + "strings" "time" "github.com/juju/ratelimit" @@ -32,7 +35,9 @@ var ( sessionLimiter *ratelimit.Bucket globalLimiter *ratelimit.Bucket - statusAddr string + statusAddr string + poolAddrs string + defaultPoolAddrs string = "https://relays.syncthing.net" ) func main() { @@ -47,6 +52,7 @@ func main() { flag.IntVar(&globalLimitBps, "global-rate", globalLimitBps, "Global rate limit, in bytes/s") flag.BoolVar(&debug, "debug", false, "Enable debug output") flag.StringVar(&statusAddr, "status-srv", ":22070", "Listen address for status service (blank to disable)") + flag.StringVar(&poolAddrs, "pools", defaultPoolAddrs, "Comma separated list of relau pool addresses to join") flag.Parse() @@ -101,5 +107,25 @@ func main() { go statusService(statusAddr) } + uri, err := url.Parse(fmt.Sprintf("relay://%s/?id=%s", extAddress, id)) + if err != nil { + log.Fatalln("Failed to construct URI", err) + } + + if poolAddrs == defaultPoolAddrs { + log.Println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + log.Println("!! Joining default relay pools, this relay will be available for public use. !!") + log.Println(`!! Use the -pools="" command line option to make the relay private. !!`) + log.Println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + } + + pools := strings.Split(poolAddrs, ",") + for _, pool := range pools { + pool = strings.TrimSpace(pool) + if len(pool) > 0 { + go poolHandler(pool, uri) + } + } + listener(listen, tlsCfg) } diff --git a/pool.go b/pool.go new file mode 100644 index 000000000..398b0c0a8 --- /dev/null +++ b/pool.go @@ -0,0 +1,63 @@ +// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file). + +package main + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "log" + "net/http" + "net/url" + "time" +) + +func poolHandler(pool string, uri *url.URL) { + for { + var b bytes.Buffer + json.NewEncoder(&b).Encode(struct { + URL string `json:"url"` + }{ + uri.String(), + }) + + resp, err := http.Post(pool, "application/json", &b) + if err != nil { + if debug { + log.Println("Error joining pool", pool, err) + } + } else if resp.StatusCode == 500 { + if debug { + bs, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Println("Failed to read response body for", pool, err) + } else { + log.Println("Response for", pool, string(bs)) + } + resp.Body.Close() + } + } else if resp.StatusCode == 429 { + if debug { + log.Println(pool, "under load, will retry in a minute") + } + time.Sleep(time.Minute) + continue + } else if resp.StatusCode == 200 { + var x struct { + EvictionIn time.Duration `json:"evictionIn"` + } + err := json.NewDecoder(resp.Body).Decode(&x) + if err == nil { + rejoin := x.EvictionIn - (x.EvictionIn / 5) + if debug { + log.Println("Joined", pool, "rejoining in", rejoin) + } + time.Sleep(rejoin) + continue + } else if debug { + log.Println("Failed to deserialize respnse", err) + } + } + time.Sleep(time.Hour) + } +}