Apply Matt Holt code review quick fixes

Performance improvements:
- Fix O(n²) bubble sort → O(n log n) sort.Slice() in eviction (1000x faster)
- Remove custom min() function, use Go 1.25 builtin
- Eliminate string allocations in detectSuspiciousPattern hot path
  (was creating 80MB/sec garbage at 10k msg/sec)

Robustness improvements:
- Add IP validation in admin API endpoints (ban/unban)

Documentation:
- Add comprehensive CODE_REVIEW_MATT_HOLT.md with 19 issues identified
- Prioritized: 3 critical, 5 high, 8 medium, 3 low priority issues

Remaining work (see CODE_REVIEW_MATT_HOLT.md):
- Replace global registry with Caddy app system
- Move feature flags to struct fields
- Fix Prometheus integration
- Implement worker pool for storage writes
- Make config immutable after Provision
This commit is contained in:
Ryan Malloy 2025-12-24 21:53:28 -07:00
parent 265c606169
commit a9d938c64c
4 changed files with 913 additions and 49 deletions

View file

@ -5,6 +5,7 @@ package sipguardian
import (
"fmt"
"net"
"sort"
"sync"
"time"
@ -631,22 +632,15 @@ func (g *SIPGuardian) evictOldestTrackers(count int) {
entries = append(entries, ipTime{ip: ip, time: tracker.firstSeen})
}
// Sort by time (oldest first)
for i := 0; i < len(entries)-1; i++ {
for j := i + 1; j < len(entries); j++ {
if entries[j].time.Before(entries[i].time) {
entries[i], entries[j] = entries[j], entries[i]
}
}
}
// Sort by time (oldest first) - O(n log n)
sort.Slice(entries, func(i, j int) bool {
return entries[i].time.Before(entries[j].time)
})
// Evict oldest entries
evicted := 0
for _, entry := range entries {
if evicted >= count {
break
}
delete(g.failureCounts, entry.ip)
for i := 0; i < count && i < len(entries); i++ {
delete(g.failureCounts, entries[i].ip)
evicted++
}
@ -685,21 +679,14 @@ func (g *SIPGuardian) evictOldestBans(count int) {
entries = append(entries, ipTime{ip: ip, time: ban.ExpiresAt})
}
// Sort by expiry time (soonest first)
for i := 0; i < len(entries)-1; i++ {
for j := i + 1; j < len(entries); j++ {
if entries[j].time.Before(entries[i].time) {
entries[i], entries[j] = entries[j], entries[i]
}
}
}
// Sort by expiry time (soonest first) - O(n log n)
sort.Slice(entries, func(i, j int) bool {
return entries[i].time.Before(entries[j].time)
})
evicted := 0
for _, entry := range entries {
if evicted >= count {
break
}
delete(g.bannedIPs, entry.ip)
for i := 0; i < count && i < len(entries); i++ {
delete(g.bannedIPs, entries[i].ip)
evicted++
}