func (d *dialer) defaultCheck() bool { client := &http.Client{ Transport: &http.Transport{ DisableKeepAlives: true, Dial: d.Dial, }, } ok, timedOut, _ := withtimeout.Do(60*time.Second, func() (interface{}, error) { req, err := http.NewRequest("GET", "http://www.google.com/humans.txt", nil) if err != nil { log.Errorf("Could not create HTTP request?") return false, nil } req.Header.Set("X-LANTERN-AUTH-TOKEN", d.AuthToken) resp, err := client.Do(req) if err != nil { log.Debugf("Error testing dialer %s to humans.txt: %s", d.Label, err) return false, nil } if err := resp.Body.Close(); err != nil { log.Debugf("Unable to close response body: %v", err) } log.Tracef("Tested dialer %s to humans.txt, status code %d", d.Label, resp.StatusCode) return resp.StatusCode == 200, nil }) if timedOut { log.Errorf("Timed out checking dialer at: %v", d.Label) } return !timedOut && ok.(bool) }
func execTimeout(timeout time.Duration, cmd *exec.Cmd) ([]byte, error) { stdout, err := cmd.StdoutPipe() if err != nil { return nil, err } stderr, err := cmd.StderrPipe() if err != nil { return nil, err } err = cmd.Start() if err != nil { return nil, err } b := bytes.NewBuffer([]byte{}) go io.Copy(b, stdout) go io.Copy(b, stderr) _, timedOut, err := withtimeout.Do(timeout, func() (interface{}, error) { return nil, cmd.Wait() }) if err != nil { if timedOut { go cmd.Process.Kill() } return nil, err } return b.Bytes(), nil }
func (igd *natpmpIGD) RemovePortMapping(proto protocol, externalPort int) error { _, _, err := withtimeout.Do(opTimeout, func() (interface{}, error) { someInternalPort := 15670 // actual value doesn't matter _, err := igd.client.AddPortMapping(natpmpProtoFor(proto), someInternalPort, externalPort, 0) if err != nil { return nil, fmt.Errorf("Unable to remove port mapping: %s", err) } return nil, nil }) return err }
func (igd *natpmpIGD) GetExternalIP() (ip string, err error) { result, _, err := withtimeout.Do(opTimeout, func() (interface{}, error) { response, err := igd.client.GetExternalAddress() if err != nil { return "", fmt.Errorf("Unable to get external address: %s", err) } ip = net.IPv4(response.ExternalIPAddress[0], response.ExternalIPAddress[1], response.ExternalIPAddress[2], response.ExternalIPAddress[3]).String() return ip, err }) return result.(string), err }
func (igd *natpmpIGD) AddPortMapping(proto protocol, internalIP string, internalPort int, externalPort int, expiration time.Duration) error { _, _, err := withtimeout.Do(opTimeout, func() (interface{}, error) { expirationInSeconds := int(expiration.Seconds()) if expirationInSeconds == 0 { expirationInSeconds = int(math.MaxInt32) } result, err := igd.client.AddPortMapping(natpmpProtoFor(proto), internalPort, externalPort, expirationInSeconds) if err != nil { return nil, fmt.Errorf("Unable to add port mapping: %s", err) } if int(result.MappedExternalPort) != externalPort { igd.RemovePortMapping(proto, externalPort) return nil, fmt.Errorf("Mapped port didn't match requested") } return nil, nil }) return err }
func (d *dialer) defaultCheck() bool { client := &http.Client{ Transport: &http.Transport{ Dial: d.Dial, }, } ok, timedOut, _ := withtimeout.Do(60*time.Second, func() (interface{}, error) { resp, err := client.Get("http://www.google.com/humans.txt") if err != nil { log.Debugf("Error testing dialer %s to humans.txt: %s", d.Label, err) return false, nil } resp.Body.Close() log.Tracef("Tested dialer %s to humans.txt, status code %d", d.Label, resp.StatusCode) return resp.StatusCode == 200, nil }) if timedOut { log.Errorf("Timed out checking dialer at: %v", d.Label) } return !timedOut && ok.(bool) }
// run is the main run loop for this host func (h *host) run() { checkImmediately := true h.lastSuccess = time.Now() h.lastTest = time.Now() periodTimer := time.NewTimer(0) pauseTimer := time.NewTimer(0) for { if !checkImmediately { // Limit the rate at which we run tests waitTime := h.lastTest.Add(testPeriod).Sub(time.Now()) log.Tracef("Waiting %v until testing %v", waitTime, h) periodTimer.Reset(waitTime) } // Pause run loop after some largish amount of time pauseTimer.Reset(h.lastSuccess.Add(pauseAfter).Sub(time.Now())) select { case newName := <-h.resetCh: h.doReset(newName) case <-h.unregisterCh: log.Debugf("Unregistering %v and pausing", h) h.pause() checkImmediately = true /* Temporarily disable CloudFront/DNSimple. case <-h.initCfrCh: h.doInitCfrDist() */ case <-pauseTimer.C: log.Debugf("%v had no successful checks or resets in %v, pausing", h, pauseAfter) h.pause() checkImmediately = true case <-periodTimer.C: log.Tracef("Testing %v", h) _s, timedOut, err := withtimeout.Do(ttl, func() (interface{}, error) { online, connectionRefused, err := h.isAbleToProxy() return &status{online, connectionRefused}, err }) s := &status{false, false} if timedOut { log.Debugf("Testing %v timed out unexpectedly", h) } if _s != nil { s = _s.(*status) } h.reportStatus(s) h.lastTest = time.Now() checkImmediately = false if s.online { log.Tracef("Test for %v successful", h) h.lastSuccess = time.Now() err := h.register() if err != nil { log.Errorf("Error registering %v: %v", h, err) } } else { log.Tracef("Test for %v failed with error: %v", h, err) // Deregister this host from its rotations. We leave the host // itself registered to support continued sticky routing in case // any clients still have connections open to it. h.deregisterFromRotations() } } } }