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) {
 | 
			
		||||
	type sendResult struct {
 | 
			
		||||
		addr *net.IPAddr
 | 
			
		||||
		err 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)
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
	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 cn *icmp.PacketConn
 | 
			
		||||
			if isIPv4(addr.IP) {
 | 
			
		||||
@ -525,21 +553,19 @@ func (p *Pinger) sendICMP(conn, conn6 *icmp.PacketConn) (map[string]*net.IPAddr,
 | 
			
		||||
			}).Marshal(nil)
 | 
			
		||||
			p.mu.Unlock()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
			wg.Wait()
 | 
			
		||||
			return queue, err
 | 
			
		||||
				p.debugln("sendICMP(): End sender goroutine with error")
 | 
			
		||||
				results <- sendResult{addr: nil, err: err}
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		queue[key] = addr
 | 
			
		||||
			var dst net.Addr = addr
 | 
			
		||||
			if p.network == "udp" {
 | 
			
		||||
				dst = &net.UDPAddr{IP: addr.IP, Zone: addr.Zone}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		p.debugln("sendICMP(): Invoke goroutine")
 | 
			
		||||
		wg.Add(1)
 | 
			
		||||
		go func(conn *icmp.PacketConn, ra net.Addr, b []byte) {
 | 
			
		||||
			p.debugln("sendICMP(): WriteTo Start")
 | 
			
		||||
			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.Err == syscall.ENOBUFS {
 | 
			
		||||
							continue
 | 
			
		||||
@ -549,11 +575,30 @@ func (p *Pinger) sendICMP(conn, conn6 *icmp.PacketConn) (map[string]*net.IPAddr,
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			p.debugln("sendICMP(): WriteTo End")
 | 
			
		||||
			wg.Done()
 | 
			
		||||
		}(cn, dst, bytes)
 | 
			
		||||
			results <- sendResult{addr: addr, err: nil}
 | 
			
		||||
		}
 | 
			
		||||
		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()
 | 
			
		||||
	close(results)
 | 
			
		||||
	errs := <-errors
 | 
			
		||||
 | 
			
		||||
	p.debugln("sendICMP(): End")
 | 
			
		||||
	if len(errs) > 0 {
 | 
			
		||||
		return queue, errs[0]
 | 
			
		||||
	}
 | 
			
		||||
	return queue, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user