diff --git a/README.md b/README.md index 20c42679..d38cd1b1 100644 --- a/README.md +++ b/README.md @@ -278,7 +278,16 @@ NEKO_CERT: NEKO_KEY: - Path to the SSL-Certificate private key - e.g. '/certs/key.pem' - +NEKO_ICELITE: + - Use the ice lite protocol + - e.g. false +NEKO_ICESERVER: + - Describes a single STUN and TURN server that can be used by the ICEAgent to establish a connection with a peer (deprecated) + - e.g. 'stun:stun.l.google.com:19302' +NEKO_ICESERVERS: + - Describes multiple STUN and TURN server that can be used by the ICEAgent to establish a connection with a peer + - e.g. '[{"urls": ["turn:turn.example.com:19302", "stun:stun.example.com:19302"], "username": "name", "credential": "password"}, {"urls": ["stun:stun.example2.com:19302"]}]' + - [More information](https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer) ``` # How to contribute? diff --git a/client/src/neko/base.ts b/client/src/neko/base.ts index c50066c8..5aa98895 100644 --- a/client/src/neko/base.ts +++ b/client/src/neko/base.ts @@ -183,7 +183,7 @@ export abstract class BaseClient extends EventEmitter { this._ws!.send(JSON.stringify({ event, ...payload })) } - public createPeer(sdp: string, lite: boolean, servers: string[]) { + public createPeer(sdp: string, lite: boolean, servers: string) { this.emit('debug', `creating peer`) if (!this.socketOpen) { this.emit( @@ -202,7 +202,7 @@ export abstract class BaseClient extends EventEmitter { this._peer = new RTCPeerConnection() if (lite !== true) { this._peer = new RTCPeerConnection({ - iceServers: [{ urls: servers }], + iceServers: JSON.parse(servers), }) } diff --git a/client/src/neko/messages.ts b/client/src/neko/messages.ts index 276ddf75..a476262f 100644 --- a/client/src/neko/messages.ts +++ b/client/src/neko/messages.ts @@ -67,7 +67,7 @@ export interface SignalProvideMessage extends WebSocketMessage, SignalProvidePay export interface SignalProvidePayload { id: string lite: boolean - ice: string[] + ice: string sdp: string } diff --git a/server/internal/types/config/webrtc.go b/server/internal/types/config/webrtc.go index 5d76832c..4c6d727e 100644 --- a/server/internal/types/config/webrtc.go +++ b/server/internal/types/config/webrtc.go @@ -3,15 +3,18 @@ package config import ( "strconv" "strings" + "encoding/json" "github.com/spf13/cobra" "github.com/spf13/viper" "n.eko.moe/neko/internal/utils" + + "github.com/pion/webrtc/v3" ) type WebRTC struct { ICELite bool - ICEServers []string + ICEServers []webrtc.ICEServer EphemeralMin uint16 EphemeralMax uint16 NAT1To1IPs []string @@ -38,12 +41,24 @@ func (WebRTC) Init(cmd *cobra.Command) error { return err } + cmd.PersistentFlags().String("iceservers", "", "describes a single STUN and TURN server that can be used by the ICEAgent to establish a connection with a peer") + if err := viper.BindPFlag("iceservers", cmd.PersistentFlags().Lookup("iceservers")); err != nil { + return err + } + + return nil } func (s *WebRTC) Set() { s.ICELite = viper.GetBool("icelite") - s.ICEServers = viper.GetStringSlice("iceserver") + s.ICEServers = []webrtc.ICEServer{{URLs: viper.GetStringSlice("iceserver")}} + if (viper.GetString("iceservers") != "") { + errj := json.Unmarshal([]byte(viper.GetString("iceservers")), &s.ICEServers) + if (errj != nil) { + panic(errj) + } + } s.NAT1To1IPs = viper.GetStringSlice("nat1to1") if len(s.NAT1To1IPs) == 0 { diff --git a/server/internal/types/message/messages.go b/server/internal/types/message/messages.go index 56d116e7..62195ce0 100644 --- a/server/internal/types/message/messages.go +++ b/server/internal/types/message/messages.go @@ -18,7 +18,7 @@ type SignalProvide struct { ID string `json:"id"` SDP string `json:"sdp"` Lite bool `json:"lite"` - ICE []string `json:"ice"` + ICE string `json:"ice"` } type SignalAnswer struct { diff --git a/server/internal/types/webrtc.go b/server/internal/types/webrtc.go index 80c2f1a1..82f57eed 100644 --- a/server/internal/types/webrtc.go +++ b/server/internal/types/webrtc.go @@ -2,6 +2,8 @@ package types import ( "time" + + "github.com/pion/webrtc/v3" ) type Sample struct { @@ -13,7 +15,7 @@ type Sample struct { type WebRTCManager interface { Start() Shutdown() error - CreatePeer(id string, session Session) (string, bool, []string, error) + CreatePeer(id string, session Session) (string, bool, []webrtc.ICEServer, error) } type Peer interface { diff --git a/server/internal/webrtc/webrtc.go b/server/internal/webrtc/webrtc.go index b1feeee6..555f88e9 100644 --- a/server/internal/webrtc/webrtc.go +++ b/server/internal/webrtc/webrtc.go @@ -63,7 +63,7 @@ func (manager *WebRTCManager) Start() { manager.logger.Info(). Str("ice_lite", fmt.Sprintf("%t", manager.config.ICELite)). - Str("ice_servers", strings.Join(manager.config.ICEServers, ",")). + Str("ice_servers", fmt.Sprintf("%+v", manager.config.ICEServers)). Str("ephemeral_port_range", fmt.Sprintf("%d-%d", manager.config.EphemeralMin, manager.config.EphemeralMax)). Str("nat_ips", strings.Join(manager.config.NAT1To1IPs, ",")). Msgf("webrtc starting") @@ -74,13 +74,9 @@ func (manager *WebRTCManager) Shutdown() error { return nil } -func (manager *WebRTCManager) CreatePeer(id string, session types.Session) (string, bool, []string, error) { +func (manager *WebRTCManager) CreatePeer(id string, session types.Session) (string, bool, []webrtc.ICEServer, error) { configuration := &webrtc.Configuration{ - ICEServers: []webrtc.ICEServer{ - { - URLs: manager.config.ICEServers, - }, - }, + ICEServers: manager.config.ICEServers, SDPSemantics: webrtc.SDPSemanticsUnifiedPlanWithFallback, } diff --git a/server/internal/websocket/signal.go b/server/internal/websocket/signal.go index e24db554..1059c10a 100644 --- a/server/internal/websocket/signal.go +++ b/server/internal/websocket/signal.go @@ -1,6 +1,8 @@ package websocket import ( + "encoding/json" + "n.eko.moe/neko/internal/types" "n.eko.moe/neko/internal/types/event" "n.eko.moe/neko/internal/types/message" @@ -12,12 +14,17 @@ func (h *MessageHandler) signalProvide(id string, session types.Session) error { return err } + tmp, err := json.Marshal(ice) + if (err != nil) { + panic(err) + } + if err := session.Send(message.SignalProvide{ Event: event.SIGNAL_PROVIDE, ID: id, SDP: sdp, Lite: lite, - ICE: ice, + ICE: string(tmp), }); err != nil { return err }