package collector // Query combines filtering, sorting, and limiting into a single operation type Query struct { Filter FilterOptions Sort SortOptions Limit int } // NewQuery creates a query with sensible defaults func NewQuery() *Query { return &Query{ Filter: FilterOptions{}, Sort: SortOptions{Field: SortByLport, Direction: SortAsc}, Limit: 0, } } // WithFilter sets the filter options func (q *Query) WithFilter(f FilterOptions) *Query { q.Filter = f return q } // WithSort sets the sort options func (q *Query) WithSort(s SortOptions) *Query { q.Sort = s return q } // WithSortString parses and sets sort options from a string like "pid:desc" func (q *Query) WithSortString(s string) *Query { q.Sort = ParseSortOptions(s) return q } // WithLimit sets the maximum number of results func (q *Query) WithLimit(n int) *Query { q.Limit = n return q } // Proto filters by protocol func (q *Query) Proto(proto string) *Query { q.Filter.Proto = proto return q } // State filters by connection state func (q *Query) State(state string) *Query { q.Filter.State = state return q } // Process filters by process name (substring match) func (q *Query) Process(proc string) *Query { q.Filter.Proc = proc return q } // PID filters by process ID func (q *Query) PID(pid int) *Query { q.Filter.Pid = pid return q } // LocalPort filters by local port func (q *Query) LocalPort(port int) *Query { q.Filter.Lport = port return q } // RemotePort filters by remote port func (q *Query) RemotePort(port int) *Query { q.Filter.Rport = port return q } // IPv4Only filters to only IPv4 connections func (q *Query) IPv4Only() *Query { q.Filter.IPv4 = true q.Filter.IPv6 = false return q } // IPv6Only filters to only IPv6 connections func (q *Query) IPv6Only() *Query { q.Filter.IPv4 = false q.Filter.IPv6 = true return q } // Listening filters to only listening sockets func (q *Query) Listening() *Query { q.Filter.State = "LISTEN" return q } // Established filters to only established connections func (q *Query) Established() *Query { q.Filter.State = "ESTABLISHED" return q } // Contains filters by substring in process, local addr, or remote addr func (q *Query) Contains(s string) *Query { q.Filter.Contains = s return q } // Execute runs the query and returns results func (q *Query) Execute() ([]Connection, error) { conns, err := GetConnections() if err != nil { return nil, err } return q.Apply(conns), nil } // Apply applies the query to a slice of connections func (q *Query) Apply(conns []Connection) []Connection { result := FilterConnections(conns, q.Filter) SortConnections(result, q.Sort) if q.Limit > 0 && len(result) > q.Limit { result = result[:q.Limit] } return result } // common pre-built queries // ListeningTCP returns a query for TCP listeners func ListeningTCP() *Query { return NewQuery().Proto("tcp").Listening() } // ListeningAll returns a query for all listeners func ListeningAll() *Query { return NewQuery().Listening() } // EstablishedTCP returns a query for established TCP connections func EstablishedTCP() *Query { return NewQuery().Proto("tcp").Established() } // ByProcess returns a query filtered by process name func ByProcess(name string) *Query { return NewQuery().Process(name) } // ByPort returns a query filtered by local port func ByPort(port int) *Query { return NewQuery().LocalPort(port) }