Zippytal-Node/webrtcFsManager.go

450 lines
15 KiB
Go

package localserver
// import (
// context "context"
// "encoding/json"
// "fmt"
// "io"
// sync "sync"
// "github.com/pion/webrtc/v3"
// )
// type WebrtcFsManager struct {
// stream SignalingService_LinkClient
// DatachannelManager DataChannelManager
// LocalSD map[string]*webrtc.SessionDescription
// RTCPeerConnections map[string]*webrtc.PeerConnection
// DataChannels map[string]*webrtc.DataChannel
// PendingCandidates map[string][]*webrtc.ICECandidate
// CandidateChannel chan *IncomingCandidate
// CandidateMux *sync.RWMutex
// RTCPeerConnectionMapMux *sync.RWMutex
// DataChannelMapMux *sync.RWMutex
// LocalSDMapMux *sync.RWMutex
// }
// func NewWebrtcFsManager(dataChannelManager DataChannelManager) (webrtcFsManager *WebrtcFsManager, err error) {
// webrtcFsManager = &WebrtcFsManager{
// DatachannelManager: dataChannelManager,
// DataChannels: make(map[string]*webrtc.DataChannel),
// PendingCandidates: make(map[string][]*webrtc.ICECandidate),
// LocalSD: make(map[string]*webrtc.SessionDescription),
// RTCPeerConnections: make(map[string]*webrtc.PeerConnection),
// RTCPeerConnectionMapMux: &sync.RWMutex{},
// LocalSDMapMux: &sync.RWMutex{},
// CandidateMux: &sync.RWMutex{},
// DataChannelMapMux: &sync.RWMutex{},
// }
// return
// }
// func (wf *WebrtcFsManager) sendSignalingMessage(messageType, from, to string, payload map[string]interface{}) (err error) {
// bs, err := json.Marshal(payload)
// if err != nil {
// return
// }
// err = wf.stream.Send(&SignalingMessage{
// Type: messageType,
// From: from,
// To: to,
// Payload: bs,
// })
// return
// }
// func (wf *WebrtcFsManager) CreateOffer(ctx context.Context, target string, from string, cb OnICECandidateFunc) (err error) {
// peerConnection, err := wf.createPeerConnection(target, from, webrtc.SDPTypeOffer, cb)
// if err != nil {
// return
// }
// rawOffer, err := peerConnection.CreateOffer(nil)
// if err != nil {
// return
// }
// if err = peerConnection.SetLocalDescription(rawOffer); err != nil {
// return
// }
// wf.RTCPeerConnectionMapMux.Lock()
// logger.Println("adding for target", target)
// wf.RTCPeerConnections[target] = peerConnection
// wf.RTCPeerConnectionMapMux.Unlock()
// err = wf.sendSignalingMessage(string(WEBRTC_OFFER_FS), "lolo_local_serv", target, map[string]any{
// "to": target,
// "from": "lolo_local_serv",
// "sdp": rawOffer.SDP,
// })
// return
// }
// func (wf *WebrtcFsManager) HandleOffer(ctx context.Context, req map[string]string, cb OnICECandidateFunc) (err error) {
// done, errCh := make(chan struct{}), make(chan error)
// go func() {
// peerConnection, err := wf.createPeerConnection(req[FROM], req[TO], webrtc.SDPTypeAnswer, cb)
// if err != nil {
// errCh <- err
// return
// }
// wf.RTCPeerConnectionMapMux.Lock()
// wf.RTCPeerConnections[req[FROM]] = peerConnection
// wf.RTCPeerConnectionMapMux.Unlock()
// offer := webrtc.SessionDescription{
// Type: webrtc.SDPTypeOffer,
// SDP: req[SDP],
// }
// if err = peerConnection.SetRemoteDescription(offer); err != nil {
// errCh <- err
// return
// }
// rawAnswer, err := peerConnection.CreateAnswer(nil)
// if err != nil {
// errCh <- err
// return
// }
// wf.LocalSDMapMux.Lock()
// wf.LocalSD[req[FROM]] = &rawAnswer
// wf.LocalSDMapMux.Unlock()
// // if err = wf.stream.Send(&Request{
// // Type: string(WEBRTC_ANSWER_FS),
// // From: "lolo_local_serv",
// // Token: "none",
// // Payload: map[string]string{
// // "to": req[FROM],
// // "from": "lolo_local_serv",
// // "sdp": rawAnswer.SDP,
// // },
// // }); err != nil {
// // errCh <- err
// // return
// // }
// done <- struct{}{}
// }()
// select {
// case <-done:
// return
// case err = <-errCh:
// return
// case <-ctx.Done():
// err = ctx.Err()
// return
// }
// }
// func (wf *WebrtcFsManager) HandleAnswer(ctx context.Context, req map[string]string) (err error) {
// wf.RTCPeerConnectionMapMux.RLock()
// defer wf.RTCPeerConnectionMapMux.RUnlock()
// defer func() {
// if r := recover(); err != nil {
// logger.Printf("recover from panic : %v\n", r)
// }
// }()
// if _, ok := wf.RTCPeerConnections[req[FROM]]; !ok {
// err = fmt.Errorf("no corresponding peer connection for id : %s", req[FROM])
// return
// }
// peerConnnection := wf.RTCPeerConnections[req[FROM]]
// if err = peerConnnection.SetRemoteDescription(webrtc.SessionDescription{
// Type: webrtc.SDPTypeAnswer,
// SDP: req[SDP],
// }); err != nil {
// return
// }
// // if err = wf.stream.Send(&Request{
// // Type: string(WEBRTC_COUNTER_OFFER_FS),
// // From: "lolo_local_serv",
// // Token: "none",
// // Payload: map[string]string{
// // "from": "lolo_local_serv",
// // "to": req[FROM],
// // },
// // }); err != nil {
// // return
// // }
// wf.CandidateMux.RLock()
// for range wf.PendingCandidates[req[FROM]] {
// logger.Println("sending candidate to", req[FROM])
// // if err = wf.stream.Send(&Request{
// // Type: string(WEBRTC_CANDIDATE_FS),
// // From: "lolo_local_serv",
// // Token: "none",
// // Payload: map[string]string{
// // "from": "lolo_local_serv",
// // "to": req[FROM],
// // "candidate": candidate.ToJSON().Candidate,
// // "sdpMid": *candidate.ToJSON().SDPMid,
// // "sdpMLineIndex": strconv.Itoa(int(*candidate.ToJSON().SDPMLineIndex)),
// // },
// // }); err != nil {
// // return
// // }
// }
// wf.CandidateMux.RUnlock()
// wf.CandidateMux.Lock()
// delete(wf.PendingCandidates, req[FROM])
// wf.CandidateMux.Unlock()
// wf.LocalSDMapMux.Lock()
// delete(wf.LocalSD, req[FROM])
// wf.LocalSDMapMux.Unlock()
// return
// }
// func (wf *WebrtcFsManager) HandleCounterOffer(ctx context.Context, req map[string]string) (err error) {
// wf.RTCPeerConnectionMapMux.RLock()
// if _, ok := wf.RTCPeerConnections[req[FROM]]; !ok {
// err = fmt.Errorf("no field corresponding peer connection for id %s", req[FROM])
// return
// }
// connection := wf.RTCPeerConnections[req[FROM]]
// wf.RTCPeerConnectionMapMux.RUnlock()
// wf.LocalSDMapMux.RLock()
// if err = connection.SetLocalDescription(*wf.LocalSD[req[FROM]]); err != nil {
// return
// }
// wf.LocalSDMapMux.RUnlock()
// wf.CandidateMux.RLock()
// for range wf.PendingCandidates[req[FROM]] {
// // logger.Println("sending candidate to", req[FROM])
// // if err = wf.stream.Send(&Request{
// // Type: string(WEBRTC_CANDIDATE_FS),
// // From: "lolo_local_serv",
// // Token: "none",
// // Payload: map[string]string{
// // "from": "lolo_local_serv",
// // "to": req[FROM],
// // "candidate": candidate.ToJSON().Candidate,
// // "sdpMid": *candidate.ToJSON().SDPMid,
// // "sdpMLineIndex": strconv.Itoa(int(*candidate.ToJSON().SDPMLineIndex)),
// // },
// // }); err != nil {
// // return
// // }
// }
// wf.CandidateMux.RUnlock()
// return
// }
// func (wf *WebrtcFsManager) createPeerConnection(target string, from string, peerType webrtc.SDPType, cb OnICECandidateFunc) (peerConnection *webrtc.PeerConnection, err error) {
// defer func() {
// if r := recover(); err != nil {
// logger.Printf("recover from panic : %v\n", r)
// }
// }()
// s := webrtc.SettingEngine{}
// s.DetachDataChannels()
// api := webrtc.NewAPI(webrtc.WithSettingEngine(s))
// config := webrtc.Configuration{
// ICEServers: []webrtc.ICEServer{
// {
// URLs: []string{"stun:stun.l.google.com:19302", "stun:stun.l.google.com:19302", "stun:stun.l.google.com:19302?transport=tcp"},
// },
// },
// SDPSemantics: webrtc.SDPSemanticsUnifiedPlan,
// }
// peerConnection, err = api.NewPeerConnection(config)
// if err != nil {
// return
// }
// if peerType == webrtc.SDPTypeOffer {
// maxRetransmits := uint16(100)
// channel, err := peerConnection.CreateDataChannel("data", &webrtc.DataChannelInit{
// MaxRetransmits: &maxRetransmits,
// })
// if err != nil {
// return nil, err
// }
// channel.OnOpen(func() {
// logger.Println("channel opened")
// if chanErr := channel.SendText("yooo man this is open"); chanErr != nil {
// logger.Println(chanErr)
// }
// })
// channel.OnMessage(func(msg webrtc.DataChannelMessage) {
// logger.Printf("new message %s\n", string(msg.Data))
// done, errCh := wf.DatachannelManager.HandleMessage(&DatachannelMessage{
// From: target,
// Type: "test",
// Payload: &DatachannelMessagePayload{},
// }, channel)
// select {
// case <-done:
// //logger.Println("done with success")
// case e := <-errCh:
// logger.Println(e)
// logger.Println("this is impossible")
// }
// })
// wf.DataChannelMapMux.Lock()
// wf.DataChannels[target] = channel
// wf.DataChannelMapMux.Unlock()
// }
// peerConnection.OnICEConnectionStateChange(func(is webrtc.ICEConnectionState) {
// logger.Printf("ICE connection state has changed %s\n", is.String())
// if is == webrtc.ICEConnectionStateDisconnected || is == webrtc.ICEConnectionStateFailed {
// logger.Println(is)
// }
// })
// peerConnection.OnDataChannel(func(dc *webrtc.DataChannel) {
// dc.OnOpen(func() {
// logger.Printf("got a new open datachannel %s\n", dc.Label())
// dataChann, err := dc.Detach()
// if err != nil {
// logger.Println(err)
// return
// }
// for {
// var x []byte = make([]byte, 2<<15)
// n, _, err := dataChann.ReadDataChannel(x)
// if err != nil {
// logger.Println(err)
// if err == io.EOF {
// return
// }
// continue
// }
// go func(msg []byte) {
// var dataChannelMessage DatachannelMessage
// if unmarshalErr := json.Unmarshal(msg, &dataChannelMessage); unmarshalErr != nil {
// logger.Println(unmarshalErr)
// return
// }
// done, errCh := wf.DatachannelManager.HandleMessage(&DatachannelMessage{
// From: dataChannelMessage.From,
// Type: dataChannelMessage.Type,
// Payload: dataChannelMessage.Payload,
// }, dc)
// select {
// case <-done:
// //logger.Println("done with success")
// case e := <-errCh:
// logger.Println(e)
// logger.Println("this is impossible")
// }
// }(x[:n])
// }
// })
// // dc.OnMessage(func(msg webrtc.DataChannelMessage) {
// // var dataChannelMessage DatachannelMessage
// // if unmarshalErr := json.Unmarshal(msg.Data, &dataChannelMessage); unmarshalErr != nil {
// // logger.Println(unmarshalErr)
// // return
// // }
// // done, errCh := wf.DatachannelManager.HandleMessage(&DatachannelMessage{
// // From: dataChannelMessage.From,
// // Type: dataChannelMessage.Type,
// // Payload: dataChannelMessage.Payload,
// // }, dc)
// // select {
// // case <-done:
// // //logger.Println("done with success")
// // case e := <-errCh:
// // logger.Println(e)
// // logger.Println("this is impossible")
// // }
// // })
// })
// peerConnection.OnICECandidate(func(i *webrtc.ICECandidate) {
// if i == nil {
// return
// }
// wf.CandidateMux.Lock()
// defer wf.CandidateMux.Unlock()
// desc := peerConnection.RemoteDescription()
// if desc == nil {
// wf.PendingCandidates[target] = append(wf.PendingCandidates[target], i)
// } else {
// logger.Println(i)
// if iceCandidateErr := cb(target, i); iceCandidateErr != nil {
// logger.Println(iceCandidateErr)
// }
// }
// })
// peerConnection.OnNegotiationNeeded(func() {
// if peerConnection.SignalingState() != webrtc.SignalingStateHaveLocalOffer && peerConnection.SignalingState() != webrtc.SignalingStateHaveRemoteOffer {
// wf.RTCPeerConnectionMapMux.Lock()
// defer wf.RTCPeerConnectionMapMux.Unlock()
// for _, connection := range wf.RTCPeerConnections {
// if connection.SignalingState() != webrtc.SignalingStateHaveLocalOffer && connection.SignalingState() != webrtc.SignalingStateHaveRemoteOffer {
// localSd, err := connection.CreateOffer(nil)
// if err != nil {
// logger.Println(err)
// return
// }
// if err = connection.SetLocalDescription(localSd); err != nil {
// logger.Println(err)
// return
// }
// // if err = wf.stream.Send(&Request{
// // Type: string(WEBRTC_RENNEGOTIATION_OFFER_FS),
// // From: "lolo_local_serv",
// // Token: "",
// // Payload: map[string]string{
// // "to": id,
// // "sdp": localSd.SDP,
// // },
// // }); err != nil {
// // logger.Println(err)
// // return
// // }
// }
// }
// }
// })
// return
// }
// func (wf *WebrtcFsManager) HandleRennegotiationOffer(from string, dst string, sdp string) (err error) {
// wf.RTCPeerConnectionMapMux.Lock()
// defer wf.RTCPeerConnectionMapMux.Unlock()
// if _, ok := wf.RTCPeerConnections[from]; !ok {
// err = fmt.Errorf("no corresponding peer connection for id %s", from)
// return
// }
// if wf.RTCPeerConnections[from].SignalingState() != webrtc.SignalingStateStable {
// err = fmt.Errorf("rennego called in wrong state")
// return
// }
// if err = wf.RTCPeerConnections[from].SetRemoteDescription(webrtc.SessionDescription{SDP: sdp, Type: webrtc.SDPTypeOffer}); err != nil {
// return
// }
// localSd, err := wf.RTCPeerConnections[from].CreateAnswer(nil)
// if err != nil {
// return
// }
// if err = wf.RTCPeerConnections[from].SetLocalDescription(localSd); err != nil {
// return
// }
// // if err = wf.stream.Send(&Request{
// // Type: string(WEBRTC_RENNEGOTIATION_ANSWER_FS),
// // From: "lolo_local_serv",
// // Token: "",
// // Payload: map[string]string{
// // "to": from,
// // "sdp": localSd.SDP,
// // },
// // }); err != nil {
// // logger.Println(err)
// // return
// // }
// return
// }
// func (wf *WebrtcFsManager) HandleRennegotiationAnswer(from string, dst string, sdp string) (err error) {
// wf.RTCPeerConnectionMapMux.Lock()
// defer wf.RTCPeerConnectionMapMux.Unlock()
// if _, ok := wf.RTCPeerConnections[from]; !ok {
// err = fmt.Errorf("no corresponding peer connection for id %s", from)
// return
// }
// err = wf.RTCPeerConnections[from].SetRemoteDescription(webrtc.SessionDescription{SDP: sdp, Type: webrtc.SDPTypeAnswer})
// return
// }
// func (wf *WebrtcFsManager) AddCandidate(candidate *webrtc.ICECandidateInit, from string) (err error) {
// wf.RTCPeerConnectionMapMux.Lock()
// defer wf.RTCPeerConnectionMapMux.Unlock()
// err = wf.RTCPeerConnections[from].AddICECandidate(*candidate)
// return
// }