36b3af2e3d
PR Check / Code Quality: Format (push) Failing after 1s
PR Check / Code Quality: Lint (darwin) (push) Failing after 0s
PR Check / Code Quality: Lint (freebsd) (push) Failing after 1s
PR Check / Code Quality: Lint (windows) (push) Failing after 1s
PR Check / Code Quality: Lint (linux) (push) Failing after 1s
PR Check / Security: Vulnerability Scan (push) Failing after 0s
Update Documentation / update-docs (push) Failing after 2s
PR Check / Code Quality: Vendor (push) Failing after 1s
PR Check / Code Quality: Coverage (push) Failing after 0s
PR Check / Tests: Unit (macos-latest) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04-arm) (push) Has been cancelled
PR Check / Tests: Unit (windows-latest) (push) Has been cancelled
62 lines
1.4 KiB
Go
62 lines
1.4 KiB
Go
//go:build darwin
|
|
|
|
package proc
|
|
|
|
import (
|
|
"strconv"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/pranshuparmar/witr/pkg/model"
|
|
)
|
|
|
|
// Cached results of ListOpenPorts to avoid running lsof multiple times during
|
|
// an ancestry walk (typically 5-10 ReadProcess calls within milliseconds).
|
|
var (
|
|
openPortsCache []model.OpenPort
|
|
openPortsCacheTime time.Time
|
|
openPortsCacheMu sync.Mutex
|
|
openPortsCacheTTL = 2 * time.Second
|
|
)
|
|
|
|
func listOpenPortsCached() []model.OpenPort {
|
|
openPortsCacheMu.Lock()
|
|
defer openPortsCacheMu.Unlock()
|
|
|
|
if openPortsCache != nil && time.Since(openPortsCacheTime) < openPortsCacheTTL {
|
|
return openPortsCache
|
|
}
|
|
ports, err := ListOpenPorts()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
openPortsCache = ports
|
|
openPortsCacheTime = time.Now()
|
|
return ports
|
|
}
|
|
|
|
// socketsForPID returns every IP socket owned by a PID, including non-listening
|
|
// sockets. Backed by `lsof -i -P -n` via ListOpenPorts.
|
|
func socketsForPID(pid int) []model.Socket {
|
|
all := listOpenPortsCached()
|
|
var sockets []model.Socket
|
|
seen := make(map[string]bool)
|
|
for _, p := range all {
|
|
if p.PID != pid {
|
|
continue
|
|
}
|
|
key := p.Protocol + "|" + p.Address + "|" + strconv.Itoa(p.Port) + "|" + p.State
|
|
if seen[key] {
|
|
continue
|
|
}
|
|
seen[key] = true
|
|
sockets = append(sockets, model.Socket{
|
|
Port: p.Port,
|
|
Address: p.Address,
|
|
Protocol: p.Protocol,
|
|
State: p.State,
|
|
})
|
|
}
|
|
return sockets
|
|
}
|