Files
pilens/internal/capture/hub.go
T
Andy Dixon 5dbf85f84e Phase 4: authorised HTTPS interception (Mode B)
Toggleable transparent interception via mitmdump in a venv. Own RSA CA generated
in-app, downloadable (public cert only, key never leaves the box), with per-OS
install guide and fingerprint. nftables redirect accepts only dnat'd connections
(never an open proxy). HTTP Explorer with headers and opt-in body viewers (JSON/
text/hex/image, sandboxed). Honest status: pinned/untrusting = reported errors,
excluded hosts pass through, bodies off by default. Helper op + systemd unit +
installer venv build + boot restore.
2026-10-10 08:05:42 +01:00

55 lines
896 B
Go

package capture
import (
"sync"
"sync/atomic"
)
// Hub fans out live events to browser subscribers. A subscriber that cannot
// keep up loses events (counted) and is told to resync; capture never waits.
type Hub struct {
mu sync.Mutex
subs map[*Sub]struct{}
}
type Event struct {
Type string // SSE event name
Data []byte // JSON
}
type Sub struct {
C chan Event
Dropped atomic.Int64
Resync atomic.Bool
}
func NewHub() *Hub { return &Hub{subs: map[*Sub]struct{}{}} }
func (h *Hub) Subscribe() *Sub {
s := &Sub{C: make(chan Event, 64)}
h.mu.Lock()
h.subs[s] = struct{}{}
h.mu.Unlock()
return s
}
func (h *Hub) Unsubscribe(s *Sub) {
h.mu.Lock()
delete(h.subs, s)
h.mu.Unlock()
}
func (h *Hub) Publish(e Event) {
h.mu.Lock()
defer h.mu.Unlock()
for s := range h.subs {
select {
case s.C <- e:
default:
s.Dropped.Add(1)
s.Resync.Store(true)
}
}
}