feat(sense): complete T-006 five-stream integration
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
listenAddress := flag.String("listen", "127.0.0.1:10554", "local listen address")
|
||||
upstreamAddress := flag.String("upstream", "", "upstream host:port")
|
||||
flag.Parse()
|
||||
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
|
||||
if *upstreamAddress == "" {
|
||||
logger.Error("upstream is required")
|
||||
os.Exit(2)
|
||||
}
|
||||
if _, _, err := net.SplitHostPort(*upstreamAddress); err != nil {
|
||||
logger.Error("upstream must be host:port")
|
||||
os.Exit(2)
|
||||
}
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
defer stop()
|
||||
if err := serve(ctx, *listenAddress, *upstreamAddress); err != nil {
|
||||
logger.Error("RTSP fault proxy stopped", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func serve(ctx context.Context, listenAddress, upstreamAddress string) error {
|
||||
listener, err := net.Listen("tcp", listenAddress)
|
||||
if err != nil {
|
||||
return fmt.Errorf("listen: %w", err)
|
||||
}
|
||||
defer listener.Close()
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
_ = listener.Close()
|
||||
}()
|
||||
var connections sync.WaitGroup
|
||||
defer connections.Wait()
|
||||
for {
|
||||
client, acceptErr := listener.Accept()
|
||||
if acceptErr != nil {
|
||||
if ctx.Err() != nil {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("accept: %w", acceptErr)
|
||||
}
|
||||
connections.Add(1)
|
||||
go func() {
|
||||
defer connections.Done()
|
||||
proxy(client, upstreamAddress)
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func proxy(client net.Conn, upstreamAddress string) {
|
||||
defer client.Close()
|
||||
upstream, err := net.DialTimeout("tcp", upstreamAddress, 5*time.Second)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer upstream.Close()
|
||||
done := make(chan struct{}, 2)
|
||||
copyOneWay := func(destination, source net.Conn) {
|
||||
_, _ = io.Copy(destination, source)
|
||||
done <- struct{}{}
|
||||
}
|
||||
go copyOneWay(upstream, client)
|
||||
go copyOneWay(client, upstream)
|
||||
<-done
|
||||
}
|
||||
Reference in New Issue
Block a user