Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
2.5 kB · 102 lines
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103package rtmps
import ( "context" "crypto/tls" "errors" "fmt" "io" "net" "sync"
"stream.place/streamplace/pkg/config" "stream.place/streamplace/pkg/log")
// passthrough RTMPS TLS terminator to external RTMP server// tlsConfig may be nil, in which case the certificate files from the CLI// are used; the ACME manager passes its own.func ServeRTMPSAddon(ctx context.Context, cli *config.CLI, tlsConfig *tls.Config) error { if cli.RTMPServerAddon == "" { return fmt.Errorf("RTMP server address not configured") }
if tlsConfig == nil { cert, err := tls.LoadX509KeyPair(cli.TLSCertPath, cli.TLSKeyPath) if err != nil { return fmt.Errorf("failed to load TLS certificate: %w", err) } tlsConfig = &tls.Config{ Certificates: []tls.Certificate{cert}, MinVersion: tls.VersionTLS12, } }
listener, err := tls.Listen("tcp", cli.RTMPSAddonAddr, tlsConfig) if err != nil { return fmt.Errorf("failed to create RTMPS listener: %w", err) }
log.Log(ctx, "rtmps server starting", "addr", cli.RTMPSAddonAddr, "forwarding_to", cli.RTMPServerAddon)
go func() { <-ctx.Done() listener.Close() }()
for { conn, err := listener.Accept() if err != nil { // Check if the context was canceled, which means we're shutting down select { case <-ctx.Done(): return nil default: log.Error(ctx, "error accepting RTMPS connection", "error", err) continue } }
go func(clientConn net.Conn) { defer clientConn.Close()
rtmpConn, err := net.Dial("tcp", cli.RTMPServerAddon) if err != nil { log.Error(ctx, "failed to connect to RTMP server", "error", err) return } defer rtmpConn.Close()
// Create a wait group to wait for both copy operations to complete var wg sync.WaitGroup wg.Add(2)
// Copy from client to RTMP server go func() { defer wg.Done() _, err := io.Copy(rtmpConn, clientConn) if err != nil && !errors.Is(err, io.EOF) { log.Error(ctx, "error copying from client to RTMP server", "error", err) } // Signal the other goroutine to stop by closing the connection rtmpConn.Close() }()
// Copy from RTMP server to client go func() { defer wg.Done() _, err := io.Copy(clientConn, rtmpConn) if err != nil && !errors.Is(err, io.EOF) { log.Error(ctx, "error copying from RTMP server to client", "error", err) } // Signal the other goroutine to stop by closing the connection clientConn.Close() }()
// Wait for both copy operations to complete wg.Wait() }(conn) }}