Exemple #1
0
func (this *Pinger) sendMessage(m *icmp.Message, wh *ipv4.Header) error {
	select {
	case <-this.done:
		return nil

	default:
	}

	var (
		wb        []byte
		tempDelay time.Duration // how long to sleep on accept failure
		ticker    = time.NewTicker(this.Interval)
	)

	for i, dst := range this.IPs() {
		if i != 0 {
			<-ticker.C
		}

		binary.BigEndian.PutUint64(this.payload, uint64(time.Now().UnixNano()))

		wb, err := this.marshalMessage(m, wb)
		if err != nil {
			glog.Errorf("Error creating ICMP payload: %v", err)
			continue
		}

		wh.TotalLen = ipv4.HeaderLen + len(wb)
		wh.Dst = dst

		glog.Debugf("Pinging %s", wh.Dst)
		this.mu.Lock()
		this.results[wh.Dst.String()] = nil
		this.mu.Unlock()

		if err := this.rconn.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
			return err
		}

		if err := this.rconn.WriteTo(wh, wb, nil); err != nil {
			select {
			case <-this.done:
				return nil

			default:
			}

			// Borrowed from go1.3.3/src/pkg/net/http/server.go:1699
			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}

				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}

				glog.Errorf("write error: %v; retrying in %v", err, tempDelay)
				time.Sleep(tempDelay)
				continue // out of the IP list, wait for next tick
			}

			return err
		}
	}

	if err := this.rconn.SetReadDeadline(time.Now().Add(this.MaxRTT)); err != nil {
		return err
	}

	return nil
}