func sendPing(conn *net.IPConn, addr *net.IPAddr, id, seq int) { bytes, err := (&icmpMessage{ Type: icmpv4EchoRequest, Code: 0, Body: &icmpEcho{ ID: id, Seq: seq, Data: timeToBytes(time.Now()), }, }).Marshal() if err != nil { panic(err) } for { if _, _, err := conn.WriteMsgIP(bytes, nil, addr); err != nil { if neterr, ok := err.(*net.OpError); ok { if neterr.Err == syscall.ENOBUFS { // creating a busy loop? continue } } } fmt.Printf("ICMP: Ping sent: %s, id=%d.\n", addr.String(), id) break } }
func (p *Pinger) sendICMP(conn, conn6 *net.IPConn) (map[string]*net.IPAddr, error) { p.debugln("sendICMP(): Start") p.mu.Lock() p.id = rand.Intn(0xffff) p.seq = rand.Intn(0xffff) p.mu.Unlock() queue := make(map[string]*net.IPAddr) wg := new(sync.WaitGroup) for key, addr := range p.addrs { var typ int var cn *net.IPConn if isIPv4(addr.IP) { typ = icmpv4EchoRequest cn = conn } else if isIPv6(addr.IP) { typ = icmpv6EchoRequest cn = conn6 } else { continue } if cn == nil { continue } t := timeToBytes(time.Now()) if p.Size-TimeSliceLength != 0 { t = append(t, byteSliceOfSize(p.Size-TimeSliceLength)...) } p.mu.Lock() bytes, err := (&icmpMessage{ Type: typ, Code: 0, Body: &icmpEcho{ ID: p.id, Seq: p.seq, Data: t, }, }).Marshal() p.mu.Unlock() if err != nil { wg.Wait() return queue, err } queue[key] = addr p.debugln("sendICMP(): Invoke goroutine") wg.Add(1) go func(conn *net.IPConn, ra *net.IPAddr, b []byte) { for { if _, _, err := conn.WriteMsgIP(bytes, nil, ra); err != nil { if neterr, ok := err.(*net.OpError); ok { if neterr.Err == syscall.ENOBUFS { continue } } } break } p.debugln("sendICMP(): WriteMsgIP End") wg.Done() }(cn, addr, bytes) } wg.Wait() p.debugln("sendICMP(): End") return queue, nil }