Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding models pkg #83

Merged
merged 1 commit into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions pkg/agent/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package agent

import "errors"

var (
errGrpcAddressRequired = errors.New("address is required for gRPC checker")
errUnknownCheckerType = errors.New("unknown checker type")
errGrpcMissingConfig = errors.New("no configuration or address provided for gRPC checker")
errNoLocalConfig = errors.New("no local config found")
errShutdown = errors.New("error while shutting down")
errServiceStartup = errors.New("error while starting services")
)
13 changes: 2 additions & 11 deletions pkg/agent/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"time"

"github.com/mfreeman451/serviceradar/pkg/checker"
"github.com/mfreeman451/serviceradar/pkg/sweeper"
"github.com/mfreeman451/serviceradar/pkg/models"
"github.com/mfreeman451/serviceradar/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
Expand All @@ -25,15 +25,6 @@ const (
processConfigurationName = "process"
)

var (
errGrpcAddressRequired = errors.New("address is required for gRPC checker")
errUnknownCheckerType = errors.New("unknown checker type")
errGrpcMissingConfig = errors.New("no configuration or address provided for gRPC checker")
errNoLocalConfig = errors.New("no local config found")
errShutdown = errors.New("error while shutting down")
errServiceStartup = errors.New("error while starting services")
)

type Duration time.Duration

// SweepConfig represents sweep service configuration from JSON.
Expand Down Expand Up @@ -153,7 +144,7 @@ func loadSweepService(configDir string) (Service, error) {
}

// Convert to sweeper.Config
config := &sweeper.Config{
config := &models.Config{
Networks: sweepConfig.Networks,
Ports: sweepConfig.Ports,
Interval: time.Duration(sweepConfig.Interval),
Expand Down
31 changes: 16 additions & 15 deletions pkg/agent/sweep_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"sync"
"time"

"github.com/mfreeman451/serviceradar/pkg/models"
"github.com/mfreeman451/serviceradar/pkg/sweeper"
"github.com/mfreeman451/serviceradar/proto"
)
Expand All @@ -20,11 +21,11 @@ type SweepService struct {
processor sweeper.ResultProcessor
mu sync.RWMutex
closed chan struct{}
config *sweeper.Config
config *models.Config
}

// NewSweepService creates a new sweep service with default configuration.
func NewSweepService(config *sweeper.Config) (*SweepService, error) {
func NewSweepService(config *models.Config) (*SweepService, error) {
// Apply default configuration
config = applyDefaultConfig(config)

Expand All @@ -44,12 +45,12 @@ func NewSweepService(config *sweeper.Config) (*SweepService, error) {
}, nil
}

func applyDefaultConfig(config *sweeper.Config) *sweeper.Config {
func applyDefaultConfig(config *models.Config) *models.Config {
// Ensure we have default sweep modes
if len(config.SweepModes) == 0 {
config.SweepModes = []sweeper.SweepMode{
sweeper.ModeTCP,
sweeper.ModeICMP,
config.SweepModes = []models.SweepMode{
models.ModeTCP,
models.ModeICMP,
}
}

Expand Down Expand Up @@ -200,7 +201,7 @@ func (s *SweepService) GetStatus(_ context.Context) (*proto.StatusResponse, erro
}

// UpdateConfig updates the sweep configuration.
func (s *SweepService) UpdateConfig(config *sweeper.Config) error {
func (s *SweepService) UpdateConfig(config *models.Config) error {
s.mu.Lock()
defer s.mu.Unlock()

Expand All @@ -216,8 +217,8 @@ func (s *SweepService) Close() error {
return s.Stop()
}

func generateTargets(config *sweeper.Config) ([]sweeper.Target, error) {
var targets []sweeper.Target
func generateTargets(config *models.Config) ([]models.Target, error) {
var targets []models.Target

// For each network
for _, network := range config.Networks {
Expand All @@ -230,20 +231,20 @@ func generateTargets(config *sweeper.Config) ([]sweeper.Target, error) {
// For each IP, create appropriate targets
for _, ip := range ips {
// Add ICMP target if enabled
if sweeper.ContainsMode(config.SweepModes, sweeper.ModeICMP) {
targets = append(targets, sweeper.Target{
if models.ContainsMode(config.SweepModes, models.ModeICMP) {
targets = append(targets, models.Target{
Host: ip.String(),
Mode: sweeper.ModeICMP,
Mode: models.ModeICMP,
})
}

// Add TCP targets if enabled
if sweeper.ContainsMode(config.SweepModes, sweeper.ModeTCP) {
if models.ContainsMode(config.SweepModes, models.ModeTCP) {
for _, port := range config.Ports {
targets = append(targets, sweeper.Target{
targets = append(targets, models.Target{
Host: ip.String(),
Port: port,
Mode: sweeper.ModeTCP,
Mode: models.ModeTCP,
})
}
}
Expand Down
74 changes: 74 additions & 0 deletions pkg/models/sweeper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package models

import "time"

// SweepData represents network sweep results.
type SweepData struct {
Network string `json:"network"`
TotalHosts int32 `json:"total_hosts"`
AvailableHosts int32 `json:"available_hosts"`
LastSweep int64 `json:"last_sweep"`
Ports []PortStatus `json:"ports"`
}

// PortStatus represents port availability information.
type PortStatus struct {
Port int32 `json:"port"`
Available int32 `json:"available"`
}

// Config defines sweeper configuration.
type Config struct {
Networks []string `json:"networks"`
Ports []int `json:"ports"`
SweepModes []SweepMode `json:"sweep_modes"`
Interval time.Duration `json:"interval"`
Concurrency int `json:"concurrency"`
Timeout time.Duration `json:"timeout"`
ICMPCount int `json:"icmp_count"`
}

type SweepMode string

const (
ModeTCP SweepMode = "tcp"
ModeICMP SweepMode = "icmp"
)

// Target represents a network target to be scanned.
type Target struct {
Host string
Port int
Mode SweepMode
}

// Result represents the outcome of a sweep against a target.
type Result struct {
Target Target
Available bool
FirstSeen time.Time
LastSeen time.Time
RespTime time.Duration
PacketLoss float64
Error error
}

// ResultFilter defines criteria for retrieving results.
type ResultFilter struct {
Host string
Port int
StartTime time.Time
EndTime time.Time
Available *bool
}

// ContainsMode checks if a mode is in a list of modes.
func ContainsMode(modes []SweepMode, mode SweepMode) bool {
for _, m := range modes {
if m == mode {
return true
}
}

return false
}
3 changes: 2 additions & 1 deletion pkg/poller/poller.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"

"github.com/mfreeman451/serviceradar/pkg/grpc"
"github.com/mfreeman451/serviceradar/pkg/models"
"github.com/mfreeman451/serviceradar/proto"
)

Expand Down Expand Up @@ -75,7 +76,7 @@ func (p *Poller) ensureAgentHealth(ctx context.Context, agentName string, config

// processSweepStatus handles sweep status processing.
func (*Poller) processSweepStatus(status *proto.ServiceStatus) error {
var sweepData SweepData
var sweepData models.SweepData
if err := json.Unmarshal([]byte(status.Message), &sweepData); err != nil {
return fmt.Errorf("failed to parse sweep data: %w", err)
}
Expand Down
15 changes: 0 additions & 15 deletions pkg/poller/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,6 @@ type Poller struct {
agents map[string]*AgentConnection
}

// SweepData represents network sweep results.
type SweepData struct {
Network string `json:"network"`
TotalHosts int32 `json:"total_hosts"`
AvailableHosts int32 `json:"available_hosts"`
LastSweep int64 `json:"last_sweep"`
Ports []PortStatus `json:"ports"`
}

// PortStatus represents port availability information.
type PortStatus struct {
Port int32 `json:"port"`
Available int32 `json:"available"`
}

// Duration is a wrapper around time.Duration for JSON unmarshaling.
type Duration time.Duration

Expand Down
24 changes: 13 additions & 11 deletions pkg/sweeper/combined_scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"log"
"sync"
"time"

"github.com/mfreeman451/serviceradar/pkg/models"
)

type CombinedScanner struct {
Expand All @@ -30,12 +32,12 @@ func (s *CombinedScanner) Stop() error {
}

type scanTargets struct {
tcp []Target
icmp []Target
tcp []models.Target
icmp []models.Target
}

func (s *CombinedScanner) Scan(ctx context.Context, targets []Target) (<-chan Result, error) {
results := make(chan Result)
func (s *CombinedScanner) Scan(ctx context.Context, targets []models.Target) (<-chan models.Result, error) {
results := make(chan models.Result)
separated := s.separateTargets(targets)

var wg sync.WaitGroup
Expand All @@ -50,14 +52,14 @@ func (s *CombinedScanner) Scan(ctx context.Context, targets []Target) (<-chan Re
return results, nil
}

func (*CombinedScanner) separateTargets(targets []Target) scanTargets {
func (*CombinedScanner) separateTargets(targets []models.Target) scanTargets {
var separated scanTargets

for _, target := range targets {
switch target.Mode {
case ModeTCP:
case models.ModeTCP:
separated.tcp = append(separated.tcp, target)
case ModeICMP:
case models.ModeICMP:
separated.icmp = append(separated.icmp, target)
default:
log.Printf("Unknown scan mode for target %v: %v", target, target.Mode)
Expand All @@ -67,7 +69,7 @@ func (*CombinedScanner) separateTargets(targets []Target) scanTargets {
return separated
}

func (s *CombinedScanner) startScanners(ctx context.Context, wg *sync.WaitGroup, targets scanTargets, results chan<- Result) {
func (s *CombinedScanner) startScanners(ctx context.Context, wg *sync.WaitGroup, targets scanTargets, results chan<- models.Result) {
if len(targets.tcp) > 0 {
wg.Add(1)

Expand All @@ -81,7 +83,7 @@ func (s *CombinedScanner) startScanners(ctx context.Context, wg *sync.WaitGroup,
}
}

func (s *CombinedScanner) runTCPScanner(ctx context.Context, wg *sync.WaitGroup, targets []Target, results chan<- Result) {
func (s *CombinedScanner) runTCPScanner(ctx context.Context, wg *sync.WaitGroup, targets []models.Target, results chan<- models.Result) {
defer wg.Done()

tcpResults, err := s.tcpScanner.Scan(ctx, targets)
Expand All @@ -93,7 +95,7 @@ func (s *CombinedScanner) runTCPScanner(ctx context.Context, wg *sync.WaitGroup,
s.processResults(ctx, tcpResults, results)
}

func (s *CombinedScanner) runICMPScanner(ctx context.Context, wg *sync.WaitGroup, targets []Target, results chan<- Result) {
func (s *CombinedScanner) runICMPScanner(ctx context.Context, wg *sync.WaitGroup, targets []models.Target, results chan<- models.Result) {
defer wg.Done()

icmpResults, err := s.icmpScanner.Scan(ctx, targets)
Expand All @@ -105,7 +107,7 @@ func (s *CombinedScanner) runICMPScanner(ctx context.Context, wg *sync.WaitGroup
s.processResults(ctx, icmpResults, results)
}

func (s *CombinedScanner) processResults(ctx context.Context, scanResults <-chan Result, results chan<- Result) {
func (s *CombinedScanner) processResults(ctx context.Context, scanResults <-chan models.Result, results chan<- models.Result) {
for result := range scanResults {
select {
case <-ctx.Done():
Expand Down
23 changes: 12 additions & 11 deletions pkg/sweeper/icmp_scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"sync"
"time"

"github.com/mfreeman451/serviceradar/pkg/models"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
)
Expand All @@ -30,7 +31,7 @@ type ICMPScanner struct {

type ICMPWorkerConfig struct {
conn *icmp.PacketConn
target Target
target models.Target
attempts int
timeout time.Duration
}
Expand All @@ -54,9 +55,9 @@ func (s *ICMPScanner) Stop() error {
return nil
}

func (s *ICMPScanner) Scan(ctx context.Context, targets []Target) (<-chan Result, error) {
results := make(chan Result)
targetChan := make(chan Target)
func (s *ICMPScanner) Scan(ctx context.Context, targets []models.Target) (<-chan models.Result, error) {
results := make(chan models.Result)
targetChan := make(chan models.Target)

conn, err := s.createICMPConnection()
if err != nil {
Expand Down Expand Up @@ -116,7 +117,7 @@ func (*ICMPScanner) createICMPConnection() (*icmp.PacketConn, error) {
return icmp.ListenPacket("ip4:icmp", "0.0.0.0")
}

func (s *ICMPScanner) worker(ctx context.Context, config *ICMPWorkerConfig, targets <-chan Target, results chan<- Result) {
func (s *ICMPScanner) worker(ctx context.Context, config *ICMPWorkerConfig, targets <-chan models.Target, results chan<- models.Result) {
for {
select {
case <-ctx.Done():
Expand All @@ -142,9 +143,9 @@ func (s *ICMPScanner) worker(ctx context.Context, config *ICMPWorkerConfig, targ
}
}

func (s *ICMPScanner) pingHost(ctx context.Context, config *ICMPWorkerConfig) Result {
func (s *ICMPScanner) pingHost(ctx context.Context, config *ICMPWorkerConfig) models.Result {
start := time.Now()
result := Result{
result := models.Result{
Target: config.target,
FirstSeen: start,
LastSeen: start,
Expand Down Expand Up @@ -255,15 +256,15 @@ func (*ICMPScanner) sendPing(_ context.Context, config *ICMPWorkerConfig) (bool,
return success, elapsed
}

func (s *ICMPScanner) fallbackScan(ctx context.Context, targets []Target) (<-chan Result, error) {
func (s *ICMPScanner) fallbackScan(ctx context.Context, targets []models.Target) (<-chan models.Result, error) {
// Convert ICMP targets to TCP targets
tcpTargets := make([]Target, len(targets))
tcpTargets := make([]models.Target, len(targets))

for i, target := range targets {
tcpTargets[i] = Target{
tcpTargets[i] = models.Target{
Host: target.Host,
Port: 80, // Try a common port for host discovery
Mode: ModeTCP,
Mode: models.ModeTCP,
}
}

Expand Down
Loading
Loading