mirror of
https://github.com/taigrr/go-fastping
synced 2025-01-18 05:03:15 -08:00
Send ICMP from routines in multiples of GOMAXPROCS
This commit is contained in:
parent
d36728c9f3
commit
04c22ac9c6
65
fastping.go
65
fastping.go
@ -486,14 +486,42 @@ mainloop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pinger) sendICMP(conn, conn6 *icmp.PacketConn) (map[string]*net.IPAddr, error) {
|
func (p *Pinger) sendICMP(conn, conn6 *icmp.PacketConn) (map[string]*net.IPAddr, error) {
|
||||||
|
type sendResult struct {
|
||||||
|
addr *net.IPAddr
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
p.debugln("sendICMP(): Start")
|
p.debugln("sendICMP(): Start")
|
||||||
|
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
p.id = rand.Intn(0xffff)
|
p.id = rand.Intn(0xffff)
|
||||||
p.seq = rand.Intn(0xffff)
|
p.seq = rand.Intn(0xffff)
|
||||||
p.mu.Unlock()
|
p.mu.Unlock()
|
||||||
|
|
||||||
queue := make(map[string]*net.IPAddr)
|
queue := make(map[string]*net.IPAddr)
|
||||||
|
|
||||||
|
addrs := make(chan *net.IPAddr)
|
||||||
|
results := make(chan sendResult, 1)
|
||||||
|
errors := make(chan []error)
|
||||||
|
|
||||||
|
collectResult := func (results <-chan sendResult, errors chan<- []error) {
|
||||||
|
var errs []error
|
||||||
|
for r := range results {
|
||||||
|
if r.err != nil {
|
||||||
|
errs = append(errs, r.err)
|
||||||
|
} else {
|
||||||
|
queue[r.addr.String()] = r.addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errors <- errs
|
||||||
|
}
|
||||||
|
go collectResult(results, errors)
|
||||||
|
|
||||||
wg := new(sync.WaitGroup)
|
wg := new(sync.WaitGroup)
|
||||||
for key, addr := range p.addrs {
|
sendPacket := func (addrs <-chan *net.IPAddr, results chan<- sendResult) {
|
||||||
|
defer wg.Done()
|
||||||
|
p.debugln("sendICMP(): Invoke sender goroutine")
|
||||||
|
for addr := range addrs {
|
||||||
var typ icmp.Type
|
var typ icmp.Type
|
||||||
var cn *icmp.PacketConn
|
var cn *icmp.PacketConn
|
||||||
if isIPv4(addr.IP) {
|
if isIPv4(addr.IP) {
|
||||||
@ -525,21 +553,19 @@ func (p *Pinger) sendICMP(conn, conn6 *icmp.PacketConn) (map[string]*net.IPAddr,
|
|||||||
}).Marshal(nil)
|
}).Marshal(nil)
|
||||||
p.mu.Unlock()
|
p.mu.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wg.Wait()
|
p.debugln("sendICMP(): End sender goroutine with error")
|
||||||
return queue, err
|
results <- sendResult{addr: nil, err: err}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
queue[key] = addr
|
|
||||||
var dst net.Addr = addr
|
var dst net.Addr = addr
|
||||||
if p.network == "udp" {
|
if p.network == "udp" {
|
||||||
dst = &net.UDPAddr{IP: addr.IP, Zone: addr.Zone}
|
dst = &net.UDPAddr{IP: addr.IP, Zone: addr.Zone}
|
||||||
}
|
}
|
||||||
|
|
||||||
p.debugln("sendICMP(): Invoke goroutine")
|
p.debugln("sendICMP(): WriteTo Start")
|
||||||
wg.Add(1)
|
|
||||||
go func(conn *icmp.PacketConn, ra net.Addr, b []byte) {
|
|
||||||
for {
|
for {
|
||||||
if _, err := conn.WriteTo(bytes, ra); err != nil {
|
if _, err := cn.WriteTo(bytes, dst); err != nil {
|
||||||
if neterr, ok := err.(*net.OpError); ok {
|
if neterr, ok := err.(*net.OpError); ok {
|
||||||
if neterr.Err == syscall.ENOBUFS {
|
if neterr.Err == syscall.ENOBUFS {
|
||||||
continue
|
continue
|
||||||
@ -549,11 +575,30 @@ func (p *Pinger) sendICMP(conn, conn6 *icmp.PacketConn) (map[string]*net.IPAddr,
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
p.debugln("sendICMP(): WriteTo End")
|
p.debugln("sendICMP(): WriteTo End")
|
||||||
wg.Done()
|
results <- sendResult{addr: addr, err: nil}
|
||||||
}(cn, dst, bytes)
|
|
||||||
}
|
}
|
||||||
|
p.debugln("sendICMP(): End sender goroutine")
|
||||||
|
}
|
||||||
|
|
||||||
|
routines := numGoRoutines()
|
||||||
|
wg.Add(routines)
|
||||||
|
for i := 0; i < routines; i++ {
|
||||||
|
go sendPacket(addrs, results)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range p.addrs {
|
||||||
|
addrs <- addr
|
||||||
|
}
|
||||||
|
|
||||||
|
close(addrs)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
close(results)
|
||||||
|
errs := <-errors
|
||||||
|
|
||||||
p.debugln("sendICMP(): End")
|
p.debugln("sendICMP(): End")
|
||||||
|
if len(errs) > 0 {
|
||||||
|
return queue, errs[0]
|
||||||
|
}
|
||||||
return queue, nil
|
return queue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user