Files
oko_public/mofin/main.go
T
2026-09-09 21:44:05 -05:00

173 lines
4.4 KiB
Go

package main
import (
"context"
"flag"
"log"
"net"
"os"
"os/signal"
"sync"
"syscall"
"time"
"frame"
)
const (
workerCount = 4
// connLimit bounds concurrent inbound connections so a connection flood
// (auth handshake parked, or clips queued behind busy workers) cannot
// exhaust goroutines or file descriptors.
connLimit = 16
// clipChanCap gives in-flight ingest handlers somewhere to park a decoded
// clip without holding the connection's socket open for the workers.
clipChanCap = 32
shutdownGrace = 5 * time.Second
)
func main() {
var (
listenAddr string
terpAddr string
threshold int
passphrase string
authToken string
pbkdf2Iter int
)
flag.StringVar(&listenAddr, "listen", ":8083", "address to listen for incoming clips")
flag.StringVar(&terpAddr, "terp", "localhost:8081", "address to forward clips with motion to terp")
flag.IntVar(&threshold, "threshold", 30, "pixel-value sensitivity (0-255) for motion detection comparison")
flag.StringVar(&passphrase, "passphrase", "", "decryption passphrase (empty = no encryption)")
flag.StringVar(&authToken, "auth-token", "", "shared pipeline auth token (or OKO_AUTH_TOKEN)")
flag.IntVar(&pbkdf2Iter, "pbkdf2-iters", frame.DefaultPBKDF2Iter, "PBKDF2 iterations for clip encryption (1..1000000)")
flag.Parse()
if threshold < 0 || threshold > 255 {
log.Fatalf("threshold must be in [0, 255], got %d", threshold)
}
if pbkdf2Iter < 1 || pbkdf2Iter > frame.MaxPBKDF2Iter {
log.Fatalf("pbkdf2-iters must be in [1, %d], got %d", frame.MaxPBKDF2Iter, pbkdf2Iter)
}
frame.SetDefaultPBKDF2Iter(pbkdf2Iter)
tok := authToken
if tok == "" {
tok = os.Getenv("OKO_AUTH_TOKEN")
}
if tok == "" {
log.Fatal("authentication required: set -auth-token or OKO_AUTH_TOKEN")
}
frame.SetAuthToken(tok)
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
clipChan := make(chan frame.Clip, clipChanCap)
connSem := make(chan struct{}, connLimit)
ln, err := net.Listen("tcp", listenAddr)
if err != nil {
log.Fatalf("Listen %s: %v", listenAddr, err)
}
log.Printf("Listening on %s", listenAddr)
var acceptWg sync.WaitGroup
rejected := frame.NewMalformedAttempts()
go func() {
<-ctx.Done()
ln.Close()
}()
go func() {
for {
conn, err := ln.Accept()
if err != nil {
if ctx.Err() != nil {
return
}
log.Printf("Accept error: %v", err)
continue
}
select {
case connSem <- struct{}{}:
default:
log.Printf("Rejecting connection from %s: too many concurrent connections", conn.RemoteAddr())
conn.Close()
continue
}
acceptWg.Add(1)
go func(c net.Conn) {
defer func() { <-connSem }()
defer acceptWg.Done()
frame.HandleClipConn(c, rejected, func(clp frame.Clip) {
clipChan <- clp
})
}(conn)
}
}()
// Bounded worker pool, so a burst of clips cannot spin up unbounded
// goroutines or saturate every core with motion passes.
var procWg sync.WaitGroup
procWg.Add(workerCount)
for w := 0; w < workerCount; w++ {
go func() {
defer procWg.Done()
for clp := range clipChan {
processClip(clp, terpAddr, threshold, passphrase)
}
}()
}
<-ctx.Done()
log.Println("Shutting down...")
ln.Close()
if !frame.WaitGroupTimeout(&acceptWg, shutdownGrace) {
log.Println("Inbound handlers did not drain; closing channel anyway")
}
close(clipChan)
if !frame.WaitGroupTimeout(&procWg, shutdownGrace) {
log.Println("Workers still busy (downstream retry?); exiting anyway")
}
if n := rejected.Total(); n > 0 {
log.Printf("Rejected %d malformed clips from the network", n)
}
log.Println("Exiting")
}
// processClip decrypts, drops clips with no motion, re-encrypts, and forwards
// survivors to terp.
func processClip(clp frame.Clip, terpAddr string, threshold int, passphrase string) {
if passphrase != "" {
if err := clp.Decrypt(passphrase); err != nil {
log.Printf("Decrypt error: %v", err)
return
}
}
if err := clp.CountChangedPixels(uint8(threshold)); err != nil {
log.Printf("CountChangedPixels: %v", err)
return
}
if clp.GetHighestMotion() == 0 {
log.Printf("Dropped no-motion clip (source %s)", clp.SourceData)
return
}
if passphrase != "" {
if err := clp.Encrypt(passphrase); err != nil {
log.Printf("Encrypt error: %v", err)
return
}
}
if err := clp.SendClipRetry(terpAddr, 6); err != nil {
log.Printf("Forward to terp failed, clip dropped: %v", err)
return
}
log.Printf("Forwarded clip to terp (motion: %d%%)", clp.GetHighestMotion())
}