feat: add ICE servers and local IP address returned by the API to fix connectivity issues behind NAT (#146)

Add ICE servers and local IP address returned by the API to fix connectivity issues behind NAT
This commit is contained in:
Aveline 2025-02-11 15:45:14 +01:00 committed by GitHub
parent 15768ee0ab
commit 0d7efe5c0e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 43 additions and 9 deletions

View File

@ -7,13 +7,14 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
"github.com/coder/websocket/wsjson"
"time" "time"
"github.com/coder/websocket/wsjson"
"github.com/coreos/go-oidc/v3/oidc" "github.com/coreos/go-oidc/v3/oidc"
"github.com/gin-gonic/gin"
"github.com/coder/websocket" "github.com/coder/websocket"
"github.com/gin-gonic/gin"
) )
type CloudRegisterRequest struct { type CloudRegisterRequest struct {
@ -192,7 +193,11 @@ func handleSessionRequest(ctx context.Context, c *websocket.Conn, req WebRTCSess
return fmt.Errorf("google identity mismatch") return fmt.Errorf("google identity mismatch")
} }
session, err := newSession() session, err := newSession(SessionConfig{
ICEServers: req.ICEServers,
LocalIP: req.IP,
IsCloud: true,
})
if err != nil { if err != nil {
_ = wsjson.Write(context.Background(), c, gin.H{"error": err}) _ = wsjson.Write(context.Background(), c, gin.H{"error": err})
return err return err

8
web.go
View File

@ -17,8 +17,10 @@ import (
var staticFiles embed.FS var staticFiles embed.FS
type WebRTCSessionRequest struct { type WebRTCSessionRequest struct {
Sd string `json:"sd"` Sd string `json:"sd"`
OidcGoogle string `json:"OidcGoogle,omitempty"` OidcGoogle string `json:"OidcGoogle,omitempty"`
IP string `json:"ip,omitempty"`
ICEServers []string `json:"iceServers,omitempty"`
} }
type SetPasswordRequest struct { type SetPasswordRequest struct {
@ -116,7 +118,7 @@ func handleWebRTCSession(c *gin.Context) {
return return
} }
session, err := newSession() session, err := newSession(SessionConfig{})
if err != nil { if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err}) c.JSON(http.StatusInternalServerError, gin.H{"error": err})
return return

View File

@ -4,6 +4,7 @@ import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net"
"strings" "strings"
"github.com/pion/webrtc/v4" "github.com/pion/webrtc/v4"
@ -19,6 +20,12 @@ type Session struct {
shouldUmountVirtualMedia bool shouldUmountVirtualMedia bool
} }
type SessionConfig struct {
ICEServers []string
LocalIP string
IsCloud bool
}
func (s *Session) ExchangeOffer(offerStr string) (string, error) { func (s *Session) ExchangeOffer(offerStr string) (string, error) {
b, err := base64.StdEncoding.DecodeString(offerStr) b, err := base64.StdEncoding.DecodeString(offerStr)
if err != nil { if err != nil {
@ -61,9 +68,29 @@ func (s *Session) ExchangeOffer(offerStr string) (string, error) {
return base64.StdEncoding.EncodeToString(localDescription), nil return base64.StdEncoding.EncodeToString(localDescription), nil
} }
func newSession() (*Session, error) { func newSession(config SessionConfig) (*Session, error) {
peerConnection, err := webrtc.NewPeerConnection(webrtc.Configuration{ webrtcSettingEngine := webrtc.SettingEngine{}
ICEServers: []webrtc.ICEServer{{}}, iceServer := webrtc.ICEServer{}
if config.IsCloud {
if config.ICEServers == nil {
fmt.Printf("ICE Servers not provided by cloud")
} else {
iceServer.URLs = config.ICEServers
fmt.Printf("Using ICE Servers provided by cloud: %v\n", iceServer.URLs)
}
if config.LocalIP == "" || net.ParseIP(config.LocalIP) == nil {
fmt.Printf("Local IP address %v not provided or invalid, won't set NAT1To1IPs\n", config.LocalIP)
} else {
webrtcSettingEngine.SetNAT1To1IPs([]string{config.LocalIP}, webrtc.ICECandidateTypeSrflx)
fmt.Printf("Setting NAT1To1IPs to %s\n", config.LocalIP)
}
}
api := webrtc.NewAPI(webrtc.WithSettingEngine(webrtcSettingEngine))
peerConnection, err := api.NewPeerConnection(webrtc.Configuration{
ICEServers: []webrtc.ICEServer{iceServer},
}) })
if err != nil { if err != nil {
return nil, err return nil, err