fix webrtc client gathering, #259.
This commit is contained in:
parent
0cebe465a2
commit
9daf83cc52
@ -203,11 +203,12 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this._peer = new RTCPeerConnection()
|
|
||||||
if (lite !== true) {
|
if (lite !== true) {
|
||||||
this._peer = new RTCPeerConnection({
|
this._peer = new RTCPeerConnection({
|
||||||
iceServers: servers,
|
iceServers: servers,
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
this._peer = new RTCPeerConnection()
|
||||||
}
|
}
|
||||||
|
|
||||||
this._peer.onconnectionstatechange = () => {
|
this._peer.onconnectionstatechange = () => {
|
||||||
@ -251,11 +252,28 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
|
|||||||
|
|
||||||
this._peer.ontrack = this.onTrack.bind(this)
|
this._peer.ontrack = this.onTrack.bind(this)
|
||||||
|
|
||||||
|
this._peer.onicecandidate = (event: RTCPeerConnectionIceEvent) => {
|
||||||
|
if (!event.candidate) {
|
||||||
|
this.emit('debug', `sent all local ICE candidates`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const init = event.candidate.toJSON()
|
||||||
|
this.emit('debug', `sending local ICE candidate`, init)
|
||||||
|
|
||||||
|
this._ws!.send(
|
||||||
|
JSON.stringify({
|
||||||
|
event: EVENT.SIGNAL.CANDIDATE,
|
||||||
|
data: JSON.stringify(init),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
this._peer.onnegotiationneeded = async () => {
|
this._peer.onnegotiationneeded = async () => {
|
||||||
this.emit('warn', `negotiation is needed`)
|
this.emit('warn', `negotiation is needed`)
|
||||||
|
|
||||||
const d = await this._peer!.createOffer()
|
const d = await this._peer!.createOffer()
|
||||||
this._peer!.setLocalDescription(d)
|
await this._peer!.setLocalDescription(d)
|
||||||
|
|
||||||
this._ws!.send(
|
this._ws!.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
@ -277,10 +295,10 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this._peer.setRemoteDescription({ type: 'offer', sdp })
|
await this._peer.setRemoteDescription({ type: 'offer', sdp })
|
||||||
|
|
||||||
for (const candidate of this._candidates) {
|
for (const candidate of this._candidates) {
|
||||||
this._peer.addIceCandidate(candidate)
|
await this._peer.addIceCandidate(candidate)
|
||||||
}
|
}
|
||||||
this._candidates = []
|
this._candidates = []
|
||||||
|
|
||||||
@ -310,7 +328,7 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this._peer.setRemoteDescription({ type: 'answer', sdp })
|
await this._peer.setRemoteDescription({ type: 'answer', sdp })
|
||||||
}
|
}
|
||||||
|
|
||||||
private async onMessage(e: MessageEvent) {
|
private async onMessage(e: MessageEvent) {
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
- Fixed stereo problem in chromium-based browsers, where it was only as mono by adding `stereo=1` to opus SDP to clients answer.
|
- Fixed stereo problem in chromium-based browsers, where it was only as mono by adding `stereo=1` to opus SDP to clients answer.
|
||||||
- Fixed keysym mapping for unknown keycodes, which was causing some key combinations to not work on some keyboards.
|
- Fixed keysym mapping for unknown keycodes, which was causing some key combinations to not work on some keyboards.
|
||||||
- Fixed a bug where `max_fps=0` would lead to an invalid pipeline.
|
- Fixed a bug where `max_fps=0` would lead to an invalid pipeline.
|
||||||
|
- Fixed client side webrtc ICE gathering, so that neko can be used without exposed ports, only with STUN and TURN servers.
|
||||||
|
|
||||||
### Misc
|
### Misc
|
||||||
- Updated to go 1.19 and Node 18, removed go-events as dependency (by @mbattista).
|
- Updated to go 1.19 and Node 18, removed go-events as dependency (by @mbattista).
|
||||||
|
@ -131,6 +131,17 @@ func (session *Session) SignalLocalAnswer(sdp string) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (session *Session) SignalLocalCandidate(data string) error {
|
||||||
|
if session.socket == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
session.peer.SetCandidate(data)
|
||||||
|
return session.socket.Send(&message.SignalCandidate{
|
||||||
|
Event: event.SIGNAL_CANDIDATE,
|
||||||
|
Data: data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (session *Session) SignalRemoteOffer(sdp string) error {
|
func (session *Session) SignalRemoteOffer(sdp string) error {
|
||||||
if session.peer == nil {
|
if session.peer == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -154,14 +165,12 @@ func (session *Session) SignalRemoteAnswer(sdp string) error {
|
|||||||
return session.peer.SetAnswer(sdp)
|
return session.peer.SetAnswer(sdp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) SignalCandidate(data string) error {
|
func (session *Session) SignalRemoteCandidate(data string) error {
|
||||||
if session.socket == nil {
|
if session.socket == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return session.socket.Send(&message.SignalCandidate{
|
session.logger.Info().Msg("signal update - RemoteCandidate")
|
||||||
Event: event.SIGNAL_CANDIDATE,
|
return session.peer.SetCandidate(data)
|
||||||
Data: data,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) destroy() error {
|
func (session *Session) destroy() error {
|
||||||
|
@ -40,9 +40,10 @@ type Session interface {
|
|||||||
Send(v interface{}) error
|
Send(v interface{}) error
|
||||||
SignalLocalOffer(sdp string) error
|
SignalLocalOffer(sdp string) error
|
||||||
SignalLocalAnswer(sdp string) error
|
SignalLocalAnswer(sdp string) error
|
||||||
|
SignalLocalCandidate(data string) error
|
||||||
SignalRemoteOffer(sdp string) error
|
SignalRemoteOffer(sdp string) error
|
||||||
SignalRemoteAnswer(sdp string) error
|
SignalRemoteAnswer(sdp string) error
|
||||||
SignalCandidate(data string) error
|
SignalRemoteCandidate(data string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type SessionManager interface {
|
type SessionManager interface {
|
||||||
|
@ -21,6 +21,7 @@ type Peer interface {
|
|||||||
CreateAnswer() (string, error)
|
CreateAnswer() (string, error)
|
||||||
SetOffer(sdp string) error
|
SetOffer(sdp string) error
|
||||||
SetAnswer(sdp string) error
|
SetAnswer(sdp string) error
|
||||||
|
SetCandidate(candidateString string) error
|
||||||
WriteData(v interface{}) error
|
WriteData(v interface{}) error
|
||||||
Destroy() error
|
Destroy() error
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package webrtc
|
package webrtc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/pion/webrtc/v3"
|
"github.com/pion/webrtc/v3"
|
||||||
@ -49,6 +50,16 @@ func (peer *Peer) SetAnswer(sdp string) error {
|
|||||||
return peer.connection.SetRemoteDescription(webrtc.SessionDescription{SDP: sdp, Type: webrtc.SDPTypeAnswer})
|
return peer.connection.SetRemoteDescription(webrtc.SessionDescription{SDP: sdp, Type: webrtc.SDPTypeAnswer})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (peer *Peer) SetCandidate(candidateString string) error {
|
||||||
|
var candidate webrtc.ICECandidateInit
|
||||||
|
err := json.Unmarshal([]byte(candidateString), &candidate)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return peer.connection.AddICECandidate(candidate)
|
||||||
|
}
|
||||||
|
|
||||||
func (peer *Peer) WriteData(v interface{}) error {
|
func (peer *Peer) WriteData(v interface{}) error {
|
||||||
peer.mu.Lock()
|
peer.mu.Lock()
|
||||||
defer peer.mu.Unlock()
|
defer peer.mu.Unlock()
|
||||||
|
@ -123,7 +123,6 @@ func (manager *WebRTCManager) initAPI() error {
|
|||||||
LoggerFactory: logger,
|
LoggerFactory: logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = settings.SetEphemeralUDPPortRange(manager.config.EphemeralMin, manager.config.EphemeralMax)
|
|
||||||
settings.SetNAT1To1IPs(manager.config.NAT1To1IPs, webrtc.ICECandidateTypeHost)
|
settings.SetNAT1To1IPs(manager.config.NAT1To1IPs, webrtc.ICECandidateTypeHost)
|
||||||
settings.SetICETimeouts(6*time.Second, 6*time.Second, 3*time.Second)
|
settings.SetICETimeouts(6*time.Second, 6*time.Second, 3*time.Second)
|
||||||
settings.SetSRTPReplayProtectionWindow(512)
|
settings.SetSRTPReplayProtectionWindow(512)
|
||||||
@ -168,12 +167,15 @@ func (manager *WebRTCManager) initAPI() error {
|
|||||||
|
|
||||||
networkType = append(networkType, webrtc.NetworkTypeUDP4)
|
networkType = append(networkType, webrtc.NetworkTypeUDP4)
|
||||||
manager.logger.Info().Int("port", manager.config.UDPMUX).Msg("using UDP MUX")
|
manager.logger.Info().Int("port", manager.config.UDPMUX).Msg("using UDP MUX")
|
||||||
|
} else if manager.config.EphemeralMax != 0 {
|
||||||
|
_ = settings.SetEphemeralUDPPortRange(manager.config.EphemeralMin, manager.config.EphemeralMax)
|
||||||
|
networkType = append(networkType,
|
||||||
|
webrtc.NetworkTypeUDP4,
|
||||||
|
webrtc.NetworkTypeUDP6,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable support for TCP and UDP ICE candidates
|
|
||||||
if len(networkType) > 0 {
|
|
||||||
settings.SetNetworkTypes(networkType)
|
settings.SetNetworkTypes(networkType)
|
||||||
}
|
|
||||||
|
|
||||||
// Create MediaEngine with selected codecs
|
// Create MediaEngine with selected codecs
|
||||||
engine := webrtc.MediaEngine{}
|
engine := webrtc.MediaEngine{}
|
||||||
@ -299,7 +301,7 @@ func (manager *WebRTCManager) CreatePeer(id string, session types.Session) (type
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := session.SignalCandidate(string(candidateString)); err != nil {
|
if err := session.SignalLocalCandidate(string(candidateString)); err != nil {
|
||||||
manager.logger.Warn().Err(err).Msg("sending SignalCandidate failed")
|
manager.logger.Warn().Err(err).Msg("sending SignalCandidate failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,12 @@ func (h *MessageHandler) Message(id string, raw []byte) error {
|
|||||||
utils.Unmarshal(payload, raw, func() error {
|
utils.Unmarshal(payload, raw, func() error {
|
||||||
return h.signalRemoteAnswer(id, session, payload)
|
return h.signalRemoteAnswer(id, session, payload)
|
||||||
}), "%s failed", header.Event)
|
}), "%s failed", header.Event)
|
||||||
|
case event.SIGNAL_CANDIDATE:
|
||||||
|
payload := &message.SignalCandidate{}
|
||||||
|
return errors.Wrapf(
|
||||||
|
utils.Unmarshal(payload, raw, func() error {
|
||||||
|
return h.signalRemoteCandidate(id, session, payload)
|
||||||
|
}), "%s failed", header.Event)
|
||||||
|
|
||||||
// Control Events
|
// Control Events
|
||||||
case event.CONTROL_RELEASE:
|
case event.CONTROL_RELEASE:
|
||||||
|
@ -45,3 +45,7 @@ func (h *MessageHandler) signalRemoteAnswer(id string, session types.Session, pa
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *MessageHandler) signalRemoteCandidate(id string, session types.Session, payload *message.SignalCandidate) error {
|
||||||
|
return session.SignalRemoteCandidate(payload.Data)
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user