123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- // Copyright (C) 2015 Audrius Butkevicius and Contributors.
- package main
- import (
- "bytes"
- "crypto/tls"
- "encoding/json"
- "io/ioutil"
- "log"
- "net/http"
- "net/url"
- "time"
- )
- const (
- httpStatusEnhanceYourCalm = 429
- )
- func poolHandler(pool string, uri *url.URL, mapping mapping, ownCert tls.Certificate) {
- if debug {
- log.Println("Joining", pool)
- }
- for {
- uriCopy := *uri
- uriCopy.Host = mapping.Address().String()
- var b bytes.Buffer
- json.NewEncoder(&b).Encode(struct {
- URL string `json:"url"`
- }{
- uriCopy.String(),
- })
- poolUrl, err := url.Parse(pool)
- if err != nil {
- log.Printf("Could not parse pool url '%s': %v", pool, err)
- }
- client := http.DefaultClient
- if poolUrl.Scheme == "https" {
- // Sent our certificate in join request
- client = &http.Client{
- Transport: &http.Transport{
- TLSClientConfig: &tls.Config{
- Certificates: []tls.Certificate{ownCert},
- },
- },
- }
- }
- resp, err := client.Post(pool, "application/json", &b)
- if err != nil {
- log.Printf("Error joining pool %v: HTTP request: %v", pool, err)
- time.Sleep(time.Minute)
- continue
- }
- bs, err := ioutil.ReadAll(resp.Body)
- resp.Body.Close()
- if err != nil {
- log.Printf("Error joining pool %v: reading response: %v", pool, err)
- time.Sleep(time.Minute)
- continue
- }
- switch resp.StatusCode {
- case http.StatusOK:
- var x struct {
- EvictionIn time.Duration `json:"evictionIn"`
- }
- if err := json.Unmarshal(bs, &x); err == nil {
- rejoin := x.EvictionIn - (x.EvictionIn / 5)
- log.Printf("Joined pool %s, rejoining in %v", pool, rejoin)
- time.Sleep(rejoin)
- continue
- } else {
- log.Printf("Joined pool %s, failed to deserialize response: %v", pool, err)
- }
- case http.StatusInternalServerError:
- log.Printf("Failed to join %v: server error", pool)
- log.Printf("Response data: %s", bs)
- time.Sleep(time.Minute)
- continue
- case http.StatusBadRequest:
- log.Printf("Failed to join %v: request or check error", pool)
- log.Printf("Response data: %s", bs)
- time.Sleep(time.Minute)
- continue
- case httpStatusEnhanceYourCalm:
- log.Printf("Failed to join %v: under load (rate limiting)", pool)
- time.Sleep(time.Minute)
- continue
- case http.StatusUnauthorized:
- log.Printf("Failed to join %v: IP address not matching external address", pool)
- log.Println("Aborting")
- return
- default:
- log.Printf("Failed to join %v: unexpected status code from server: %d", pool, resp.StatusCode)
- log.Printf("Response data: %s", bs)
- time.Sleep(time.Minute)
- continue
- }
- time.Sleep(time.Hour)
- }
- }
|