feat(stream): UPnP-map the HTTPS port for remote direct-TLS (best-effort)
UPnP previously published only the HTTP stream port (11818). The remote per-agent direct-TLS path (https://<pubip>.<hash>.agent.unarr.app:<port>) needs the HTTPS port (11819) reachable from the WAN, so map it too — inside listenTLS after the actual bound port is known, so the router and the web (which encodes the reported httpsPort) agree. Best-effort: if UPnP/NAT-PMP isn't available the remote path just falls back to the CloudFlare funnel; the LAN direct path is unaffected. Opt-in via downloads.enable_upnp (unchanged default: false).
This commit is contained in:
parent
3fcfaaf234
commit
e4170af604
1 changed files with 22 additions and 5 deletions
|
|
@ -67,11 +67,12 @@ type StreamServer struct {
|
||||||
growing GrowingSource // set instead of provider for the progressive-remux path (3b)
|
growing GrowingSource // set instead of provider for the progressive-remux path (3b)
|
||||||
taskID string // current task being streamed
|
taskID string // current task being streamed
|
||||||
|
|
||||||
server *http.Server
|
server *http.Server
|
||||||
port int
|
port int
|
||||||
url string // best single URL (backward compat)
|
url string // best single URL (backward compat)
|
||||||
urls StreamURLs // all available URLs by network type
|
urls StreamURLs // all available URLs by network type
|
||||||
upnpMapping *UPnPMapping
|
upnpMapping *UPnPMapping
|
||||||
|
httpsUpnpMapping *UPnPMapping // WAN mapping for the direct-TLS HTTPS port
|
||||||
|
|
||||||
// TLS — optional HTTPS listener for direct, valid-cert browser playback
|
// TLS — optional HTTPS listener for direct, valid-cert browser playback
|
||||||
// (agent-TLS feature). httpsPort 0 = disabled. tlsCert holds the current
|
// (agent-TLS feature). httpsPort 0 = disabled. tlsCert holds the current
|
||||||
|
|
@ -461,6 +462,21 @@ func (ss *StreamServer) listenTLS(ctx context.Context, mux http.Handler) error {
|
||||||
}
|
}
|
||||||
ss.httpsPort = listener.Addr().(*net.TCPAddr).Port
|
ss.httpsPort = listener.Addr().(*net.TCPAddr).Port
|
||||||
|
|
||||||
|
// Best-effort: publish the HTTPS port to the WAN so a remote browser can hit
|
||||||
|
// the per-agent direct-TLS host (https://<pubip>.<hash>.agent.unarr.app:<port>)
|
||||||
|
// without a manual port-forward. Mapped here — after the actual bound port is
|
||||||
|
// known — so the web (which encodes the reported httpsPort) and the router
|
||||||
|
// agree. If UPnP/NAT-PMP isn't available the remote path just falls back to
|
||||||
|
// the CloudFlare funnel; the LAN direct path is unaffected.
|
||||||
|
if ss.enableUPnP {
|
||||||
|
if m, err := SetupUPnP(ss.httpsPort); err != nil {
|
||||||
|
log.Printf("[stream] HTTPS UPnP failed: %v (remote direct-TLS falls back to the funnel)", err)
|
||||||
|
} else {
|
||||||
|
ss.httpsUpnpMapping = m
|
||||||
|
log.Printf("[stream] HTTPS UPnP: published port %d to WAN via %s:%d", ss.httpsPort, m.ExternalIP, m.ExternalPort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tlsCfg := &tls.Config{
|
tlsCfg := &tls.Config{
|
||||||
MinVersion: tls.VersionTLS12,
|
MinVersion: tls.VersionTLS12,
|
||||||
NextProtos: []string{"h2", "http/1.1"},
|
NextProtos: []string{"h2", "http/1.1"},
|
||||||
|
|
@ -634,6 +650,7 @@ func (ss *StreamServer) IdleSince() time.Duration {
|
||||||
// Call only at daemon shutdown — NOT between file swaps.
|
// Call only at daemon shutdown — NOT between file swaps.
|
||||||
func (ss *StreamServer) Shutdown(ctx context.Context) error {
|
func (ss *StreamServer) Shutdown(ctx context.Context) error {
|
||||||
ss.upnpMapping.Remove()
|
ss.upnpMapping.Remove()
|
||||||
|
ss.httpsUpnpMapping.Remove()
|
||||||
if ss.hls != nil {
|
if ss.hls != nil {
|
||||||
ss.hls.CloseAll()
|
ss.hls.CloseAll()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue