Beispiel #1
0
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)
}
Beispiel #2
0
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
}
Beispiel #3
0
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
}
Beispiel #4
0
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
}
Beispiel #5
0
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
}
Beispiel #6
0
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)
}
Beispiel #7
0
// 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()
			}
		}
	}
}