Files
netris-nestri/packages/relay/internal/common/common.go
Kristian Ollikainen d87a0b35dd feat: Fully use protobuf, fix controller issues and cleanup (#305)
## Description
### First commit
Restructured protobuf schemas to make them easier to use across
languages, switched to using them in-place of JSON for signaling as
well, so there's no 2 different message formats flying about. Few new
message types to deal with clients and nestri-servers better (not final
format, may see changes still).

General cleanup of dead/unused code along some bug squashing and package
updates.

TODO for future commits:
- [x] Fix additional controllers not doing inputs (possibly needs
vimputti changes)
- [x] ~~Restructure relay protocols code a bit, to reduce bloatiness of
the currently single file for them, more code re-use.~~
- Gonna keep this PR somewhat manageable without poking more at relay..
- [x] ~~Try to fix issue where with multiple clients, static stream
content causes video to freeze until there's some movement.~~
- Was caused by server tuned profile being `throughput-performance`,
causing CPU latency to be too high.
- [x] Ponder the orb


### Second + third commit
Redid the controller polling handling and fixed multi-controller
handling in vimputti and nestri code sides. Remove some dead relay code
as well to clean up the protocol source file, we'll revisit the meshing
functionality later.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added software rendering option and MangoHud runtime config;
controller sessions now support reconnection and batched state updates
with persistent session IDs.

* **Bug Fixes**
* Restored previously-filtered NES-like gamepads so they connect
correctly.

* **Chores**
* Modernized dependencies and protobuf tooling, migrated to
protobuf-based messaging and streaming, and removed obsolete CUDA build
steps.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com>
2025-11-08 13:10:28 +02:00

116 lines
3.3 KiB
Go

package common
import (
"fmt"
"log/slog"
"strconv"
"github.com/libp2p/go-reuseport"
"github.com/pion/ice/v4"
"github.com/pion/interceptor"
"github.com/pion/webrtc/v4"
)
var globalWebRTCAPI *webrtc.API
var globalWebRTCConfig = webrtc.Configuration{
ICETransportPolicy: webrtc.ICETransportPolicyAll,
BundlePolicy: webrtc.BundlePolicyBalanced,
SDPSemantics: webrtc.SDPSemanticsUnifiedPlan,
}
func InitWebRTCAPI() error {
var err error
flags := GetFlags()
// Media engine
mediaEngine := &webrtc.MediaEngine{}
// Register our extensions
if err = RegisterExtensions(mediaEngine); err != nil {
return fmt.Errorf("failed to register extensions: %w", err)
}
// Default codecs cover our needs
err = mediaEngine.RegisterDefaultCodecs()
if err != nil {
return err
}
// Interceptor registry
interceptorRegistry := &interceptor.Registry{}
// Use default set
err = webrtc.RegisterDefaultInterceptors(mediaEngine, interceptorRegistry)
if err != nil {
return err
}
// Setting engine
settingEngine := webrtc.SettingEngine{}
// New in v4, reduces CPU usage and latency when enabled
settingEngine.EnableSCTPZeroChecksum(true)
nat11IP := GetFlags().NAT11IP
if len(nat11IP) > 0 {
settingEngine.SetNAT1To1IPs([]string{nat11IP}, webrtc.ICECandidateTypeSrflx)
slog.Info("Using NAT 1:1 IP for WebRTC", "nat11_ip", nat11IP)
}
muxPort := GetFlags().UDPMuxPort
if muxPort > 0 {
// Use reuseport to allow multiple listeners on the same port
pktListener, err := reuseport.ListenPacket("udp", ":"+strconv.Itoa(muxPort))
if err != nil {
return fmt.Errorf("failed to create WebRTC muxed UDP listener: %w", err)
}
mux := ice.NewMultiUDPMuxDefault(ice.NewUDPMuxDefault(ice.UDPMuxParams{
UDPConn: pktListener,
}))
slog.Info("Using UDP Mux for WebRTC", "port", muxPort)
settingEngine.SetICEUDPMux(mux)
}
if flags.WebRTCUDPStart > 0 && flags.WebRTCUDPEnd > 0 && flags.WebRTCUDPStart < flags.WebRTCUDPEnd {
// Set the UDP port range used by WebRTC
err = settingEngine.SetEphemeralUDPPortRange(uint16(flags.WebRTCUDPStart), uint16(flags.WebRTCUDPEnd))
if err != nil {
return err
}
slog.Info("Using WebRTC UDP Port Range", "start", flags.WebRTCUDPStart, "end", flags.WebRTCUDPEnd)
}
// Improves speed when sending offers to browsers (https://github.com/pion/webrtc/issues/3174)
settingEngine.SetIncludeLoopbackCandidate(true)
// Create a new API object with our customized settings
globalWebRTCAPI = webrtc.NewAPI(webrtc.WithMediaEngine(mediaEngine), webrtc.WithSettingEngine(settingEngine), webrtc.WithInterceptorRegistry(interceptorRegistry))
return nil
}
// CreatePeerConnection sets up a new peer connection
func CreatePeerConnection(onClose func()) (*webrtc.PeerConnection, error) {
pc, err := globalWebRTCAPI.NewPeerConnection(globalWebRTCConfig)
if err != nil {
return nil, err
}
// Log connection state changes and handle failed/disconnected connections
pc.OnConnectionStateChange(func(connectionState webrtc.PeerConnectionState) {
// Close PeerConnection in cases
if connectionState == webrtc.PeerConnectionStateFailed ||
connectionState == webrtc.PeerConnectionStateDisconnected ||
connectionState == webrtc.PeerConnectionStateClosed {
err = pc.Close()
if err != nil {
slog.Error("Failed to close PeerConnection", "err", err)
}
onClose()
}
})
return pc, nil
}