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 }