mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
add Trickle ICE support.
This commit is contained in:
parent
dd4c67a6c4
commit
cae8201908
@ -2,6 +2,7 @@ package session
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/pion/webrtc/v3"
|
||||||
|
|
||||||
"demodesk/neko/internal/types"
|
"demodesk/neko/internal/types"
|
||||||
"demodesk/neko/internal/types/event"
|
"demodesk/neko/internal/types/event"
|
||||||
@ -195,3 +196,11 @@ func (session *SessionCtx) SignalAnswer(sdp string) error {
|
|||||||
|
|
||||||
return session.webrtc_peer.SignalAnswer(sdp)
|
return session.webrtc_peer.SignalAnswer(sdp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (session *SessionCtx) SignalCandidate(candidate webrtc.ICECandidateInit) error {
|
||||||
|
if session.webrtc_peer == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return session.webrtc_peer.SignalCandidate(candidate)
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@ const (
|
|||||||
SIGNAL_REQUEST = "signal/request"
|
SIGNAL_REQUEST = "signal/request"
|
||||||
SIGNAL_ANSWER = "signal/answer"
|
SIGNAL_ANSWER = "signal/answer"
|
||||||
SIGNAL_PROVIDE = "signal/provide"
|
SIGNAL_PROVIDE = "signal/provide"
|
||||||
|
SIGNAL_CANDIDATE = "signal/candidate"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package message
|
package message
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/pion/webrtc/v3"
|
||||||
|
|
||||||
"demodesk/neko/internal/types"
|
"demodesk/neko/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -45,6 +47,11 @@ type SignalProvide struct {
|
|||||||
ICE []string `json:"ice"`
|
ICE []string `json:"ice"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SignalCandidate struct {
|
||||||
|
Event string `json:"event,omitempty"`
|
||||||
|
*webrtc.ICECandidateInit
|
||||||
|
}
|
||||||
|
|
||||||
type SignalAnswer struct {
|
type SignalAnswer struct {
|
||||||
Event string `json:"event,omitempty"`
|
Event string `json:"event,omitempty"`
|
||||||
SDP string `json:"sdp"`
|
SDP string `json:"sdp"`
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import "net/http"
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/pion/webrtc/v3"
|
||||||
|
)
|
||||||
|
|
||||||
type MemberProfile struct {
|
type MemberProfile struct {
|
||||||
Secret string `json:"secret,omitempty"`
|
Secret string `json:"secret,omitempty"`
|
||||||
@ -58,6 +62,7 @@ type Session interface {
|
|||||||
SetWebRTCPeer(webrtc_peer WebRTCPeer)
|
SetWebRTCPeer(webrtc_peer WebRTCPeer)
|
||||||
SetWebRTCConnected(connected bool)
|
SetWebRTCConnected(connected bool)
|
||||||
SignalAnswer(sdp string) error
|
SignalAnswer(sdp string) error
|
||||||
|
SignalCandidate(candidate webrtc.ICECandidateInit) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type SessionManager interface {
|
type SessionManager interface {
|
||||||
|
@ -4,6 +4,8 @@ import "github.com/pion/webrtc/v3"
|
|||||||
|
|
||||||
type WebRTCPeer interface {
|
type WebRTCPeer interface {
|
||||||
SignalAnswer(sdp string) error
|
SignalAnswer(sdp string) error
|
||||||
|
SignalCandidate(candidate webrtc.ICECandidateInit) error
|
||||||
|
|
||||||
Destroy() error
|
Destroy() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ import (
|
|||||||
|
|
||||||
"demodesk/neko/internal/types"
|
"demodesk/neko/internal/types"
|
||||||
"demodesk/neko/internal/types/codec"
|
"demodesk/neko/internal/types/codec"
|
||||||
|
"demodesk/neko/internal/types/event"
|
||||||
|
"demodesk/neko/internal/types/message"
|
||||||
"demodesk/neko/internal/config"
|
"demodesk/neko/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -86,45 +88,57 @@ func (manager *WebRTCManagerCtx) ICEServers() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (manager *WebRTCManagerCtx) CreatePeer(session types.Session) (*webrtc.SessionDescription, error) {
|
func (manager *WebRTCManagerCtx) CreatePeer(session types.Session) (*webrtc.SessionDescription, error) {
|
||||||
// Create MediaEngine
|
logger := manager.logger.With().Str("id", session.ID()).Logger()
|
||||||
|
|
||||||
engine, err := manager.mediaEngine()
|
engine, err := manager.mediaEngine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom settings & configuration
|
// Custom settings & configuration
|
||||||
settings := manager.apiSettings(session)
|
settings := manager.apiSettings(logger)
|
||||||
configuration := manager.apiConfiguration()
|
configuration := manager.apiConfiguration()
|
||||||
|
|
||||||
// Create NewAPI with MediaEngine and SettingEngine
|
// Create NewAPI with MediaEngine and SettingEngine
|
||||||
api := webrtc.NewAPI(webrtc.WithMediaEngine(engine), webrtc.WithSettingEngine(*settings))
|
api := webrtc.NewAPI(webrtc.WithMediaEngine(engine), webrtc.WithSettingEngine(*settings))
|
||||||
|
|
||||||
// Create NewPeerConnection
|
|
||||||
connection, err := api.NewPeerConnection(*configuration)
|
connection, err := api.NewPeerConnection(*configuration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register video, audio & data tracks
|
// Asynchronously send local ICE Candidates
|
||||||
|
connection.OnICECandidate(func(candidate *webrtc.ICECandidate) {
|
||||||
|
if candidate == nil {
|
||||||
|
logger.Debug().Msg("all local ice candidates sent")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ICECandidateInit := candidate.ToJSON()
|
||||||
|
err := session.Send(
|
||||||
|
message.SignalCandidate{
|
||||||
|
Event: event.SIGNAL_CANDIDATE,
|
||||||
|
ICECandidateInit: &ICECandidateInit,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Warn().Err(err).Msg("sending ice candidate failed")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if err := manager.registerTracks(connection); err != nil {
|
if err := manager.registerTracks(connection); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Offer
|
|
||||||
offer, err := connection.CreateOffer(nil)
|
offer, err := connection.CreateOffer(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Refactor, send request to client.
|
|
||||||
gatherComplete := webrtc.GatheringCompletePromise(connection)
|
|
||||||
|
|
||||||
if err := connection.SetLocalDescription(offer); err != nil {
|
if err := connection.SetLocalDescription(offer); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
<-gatherComplete
|
|
||||||
|
|
||||||
connection.OnConnectionStateChange(func(state webrtc.PeerConnectionState) {
|
connection.OnConnectionStateChange(func(state webrtc.PeerConnectionState) {
|
||||||
switch state {
|
switch state {
|
||||||
case webrtc.PeerConnectionStateConnected:
|
case webrtc.PeerConnectionStateConnected:
|
||||||
@ -145,7 +159,7 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session) (*webrtc.Sess
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err = manager.handle(message); err != nil {
|
if err = manager.handle(message); err != nil {
|
||||||
manager.logger.Warn().Err(err).Msg("data handle failed")
|
logger.Warn().Err(err).Msg("data handle failed")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -176,10 +190,10 @@ func (manager *WebRTCManagerCtx) mediaEngine() (*webrtc.MediaEngine, error) {
|
|||||||
return engine, nil
|
return engine, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *WebRTCManagerCtx) apiSettings(session types.Session) *webrtc.SettingEngine {
|
func (manager *WebRTCManagerCtx) apiSettings(logger zerolog.Logger) *webrtc.SettingEngine {
|
||||||
settings := &webrtc.SettingEngine{
|
settings := &webrtc.SettingEngine{
|
||||||
LoggerFactory: loggerFactory{
|
LoggerFactory: loggerFactory{
|
||||||
logger: manager.logger.With().Str("id", session.ID()).Logger(),
|
logger: logger,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,10 @@ func (webrtc_peer *WebRTCPeerCtx) SignalAnswer(sdp string) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (webrtc_peer *WebRTCPeerCtx) SignalCandidate(candidate webrtc.ICECandidateInit) error {
|
||||||
|
return webrtc_peer.connection.AddICECandidate(candidate)
|
||||||
|
}
|
||||||
|
|
||||||
func (webrtc_peer *WebRTCPeerCtx) Destroy() error {
|
func (webrtc_peer *WebRTCPeerCtx) Destroy() error {
|
||||||
if webrtc_peer.connection == nil || webrtc_peer.connection.ConnectionState() != webrtc.PeerConnectionStateConnected {
|
if webrtc_peer.connection == nil || webrtc_peer.connection.ConnectionState() != webrtc.PeerConnectionStateConnected {
|
||||||
return nil
|
return nil
|
||||||
|
@ -54,6 +54,11 @@ func (h *MessageHandlerCtx) Message(session types.Session, raw []byte) bool {
|
|||||||
err = utils.Unmarshal(payload, raw, func() error {
|
err = utils.Unmarshal(payload, raw, func() error {
|
||||||
return h.signalAnswer(session, payload)
|
return h.signalAnswer(session, payload)
|
||||||
})
|
})
|
||||||
|
case event.SIGNAL_CANDIDATE:
|
||||||
|
payload := &message.SignalCandidate{}
|
||||||
|
err = utils.Unmarshal(payload, raw, func() error {
|
||||||
|
return h.signalCandidate(session, payload)
|
||||||
|
})
|
||||||
|
|
||||||
// Control Events
|
// Control Events
|
||||||
case event.CONTROL_RELEASE:
|
case event.CONTROL_RELEASE:
|
||||||
|
@ -28,3 +28,7 @@ func (h *MessageHandlerCtx) signalRequest(session types.Session) error {
|
|||||||
func (h *MessageHandlerCtx) signalAnswer(session types.Session, payload *message.SignalAnswer) error {
|
func (h *MessageHandlerCtx) signalAnswer(session types.Session, payload *message.SignalAnswer) error {
|
||||||
return session.SignalAnswer(payload.SDP)
|
return session.SignalAnswer(payload.SDP)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *MessageHandlerCtx) signalCandidate(session types.Session, payload *message.SignalCandidate) error {
|
||||||
|
return session.SignalCandidate(*payload.ICECandidateInit)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user