From a625817cacc768646180bae26bbb2c925ebbe784 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 6 Apr 2019 01:51:24 +0800 Subject: [PATCH] fix websocket, time frame on each stage --- index.html | 63 +++++++++++++++++++++++++++++------------------ main.go | 64 ++++++++++++++++++++++++------------------------ webrtc/webrtc.go | 30 ++++++++++++----------- 3 files changed, 87 insertions(+), 70 deletions(-) diff --git a/index.html b/index.html index 46ade8a8..36cd866b 100644 --- a/index.html +++ b/index.html @@ -43,7 +43,8 @@ var remoteSessionDescription = "" var conn = new WebSocket(`ws://${location.host}/ws`); conn.onopen = () => { - log("WebSocket is opened"); + log("WebSocket is opened. Send ping"); + conn.send(JSON.stringify({"id": "ping", "data": ""})); } conn.onerror = error => { @@ -51,10 +52,30 @@ conn.onerror = error => { } conn.onmessage = e => { - console.log(e.data); - // e.data in json + d = JSON.parse(e.data); + switch (d["id"]) { + case "pong": + log("Recv pong. Start webrtc"); + startWebRTC(); + break; + case "sdp": + pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(d["data"])))); + break; + } } +window.startSession = () => { + let sd = remoteSessionDescription + if (sd === '') { + return alert('Session Description must not be empty') + } + + try { + pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd)))); + } catch (e) { + alert(e); + } +} function postSession(session) { if (session == "") { @@ -184,6 +205,7 @@ function endInput() { pc.oniceconnectionstatechange = e => { log(pc.iceConnectionState); if (pc.iceConnectionState === "connected") { + conn.send(JSON.stringify({"id": "start", "data": ""})); startInput(); } else if (pc.iceConnectionState === "disconnected") { @@ -205,40 +227,33 @@ pc.ontrack = function (event) { } + // candidate packet from STUN pc.onicecandidate = event => { if (event.candidate === null) { // var session = btoa(JSON.stringify(pc.localDescription)); // localSessionDescription = session; // postSession(session) + } else { + console.log(JSON.stringify(event.candidate)); } } -// create SDP -pc.createOffer({offerToReceiveVideo: true, offerToReceiveAudio: true}).then(d => { - pc.setLocalDescription(d, () => { - // send to ws - session = btoa(JSON.stringify(pc.localDescription)); - localSessionDescription = session; - conn.send(JSON.stringify({"id": "sdp", "data": session})); - }); +function startWebRTC() { + // create SDP + pc.createOffer({offerToReceiveVideo: true, offerToReceiveAudio: true}).then(d => { + pc.setLocalDescription(d, () => { + // send to ws + session = btoa(JSON.stringify(pc.localDescription)); + localSessionDescription = session; + conn.send(JSON.stringify({"id": "sdp", "data": session})); + }); -}).catch(log); + }).catch(log); - -window.startSession = () => { - let sd = remoteSessionDescription - if (sd === '') { - return alert('Session Description must not be empty') - } - - try { - pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd)))); - } catch (e) { - alert(e); - } } + diff --git a/main.go b/main.go index f514176a..06f16f50 100644 --- a/main.go +++ b/main.go @@ -41,9 +41,7 @@ func startGame(path string, imageChannel chan *image.RGBA, inputChannel chan int } func main() { - // imageChannel := make(chan *image.RGBA, 100) fmt.Println("http://localhost:8000") - // webRTC = webrtc.NewWebRTC() // router := mux.NewRouter() // router.HandleFunc("/", getWeb).Methods("GET") @@ -77,20 +75,13 @@ func ws(w http.ResponseWriter, r *http.Request) { log.Println("new connection") webRTC := webrtc.NewWebRTC() - localSession, err := webRTC.StartClient(width, height) - if err != nil { - log.Fatalln(err) - } - - log.Println("new connection2") - + // streaming game - // imageChannel := make(chan *image.RGBA, 100) - // go screenshotLoop(imageChannel, webRTC) - // go startGame("games/" + gameName, imageChannel, webRTC.InputChannel, webRTC) // start new games and webrtc stuff? - for { + isDone := false + + for !isDone { mt, message, err := c.ReadMessage() if err != nil { log.Println("read:", err) @@ -112,12 +103,23 @@ func ws(w http.ResponseWriter, r *http.Request) { res.ID = "pong" case "sdp": - webRTC.SetRemoteSession(res.Data) + localSession, err := webRTC.StartClient(req.Data, width, height) + if err != nil { + log.Fatalln(err) + } + res.ID = "sdp" res.Data = localSession case "candidate": res.ID = "candidate" + + case "start": + imageChannel := make(chan *image.RGBA, 100) + go screenshotLoop(imageChannel, webRTC) + go startGame("games/" + gameName, imageChannel, webRTC.InputChannel, webRTC) + res.ID = "start" + isDone = true } stRes, err := json.Marshal(res) @@ -134,26 +136,26 @@ func ws(w http.ResponseWriter, r *http.Request) { } } -// func postSession(w http.ResponseWriter, r *http.Request) { -// bs, err := ioutil.ReadAll(r.Body) -// if err != nil { -// log.Fatal(err) -// } -// r.Body.Close() +func postSession(w http.ResponseWriter, r *http.Request) { + bs, err := ioutil.ReadAll(r.Body) + if err != nil { + log.Fatal(err) + } + r.Body.Close() -// webRTC := webrtc.NewWebRTC() + webRTC := webrtc.NewWebRTC() -// localSession, err := webRTC.StartClient(string(bs), width, height) -// if err != nil { -// log.Fatalln(err) -// } + localSession, err := webRTC.StartClient(string(bs), width, height) + if err != nil { + log.Fatalln(err) + } -// imageChannel := make(chan *image.RGBA, 100) -// go screenshotLoop(imageChannel, webRTC) -// go startGame("games/"+gameName, imageChannel, webRTC.InputChannel, webRTC) + imageChannel := make(chan *image.RGBA, 100) + go screenshotLoop(imageChannel, webRTC) + go startGame("games/"+gameName, imageChannel, webRTC.InputChannel, webRTC) -// w.Write([]byte(localSession)) -// } + w.Write([]byte(localSession)) +} // func screenshotLoop(imageChannel chan *image.RGBA) { func screenshotLoop(imageChannel chan *image.RGBA, webRTC *webrtc.WebRTC) { @@ -168,7 +170,5 @@ func screenshotLoop(imageChannel chan *image.RGBA, webRTC *webrtc.WebRTC) { yuv := util.RgbaToYuv(image) webRTC.ImageChannel <- yuv } - // time.Sleep(10 * time.Millisecond) - // time.Sleep(time.Duration(1000 / FPS) * time.Millisecond) } } diff --git a/webrtc/webrtc.go b/webrtc/webrtc.go index a529f0bf..82545ecd 100644 --- a/webrtc/webrtc.go +++ b/webrtc/webrtc.go @@ -115,7 +115,7 @@ type WebRTC struct { } // StartClient start webrtc -func (w *WebRTC) StartClient(width, height int) (string, error) { +func (w *WebRTC) StartClient(remoteSession string, width, height int) (string, error) { defer func() { if err := recover(); err != nil { fmt.Println(err) @@ -151,6 +151,7 @@ func (w *WebRTC) StartClient(width, height int) (string, error) { return "", err } + // WebRTC state callback w.connection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) { fmt.Printf("ICE Connection State has changed: %s\n", connectionState.String()) @@ -167,6 +168,11 @@ func (w *WebRTC) StartClient(width, height int) (string, error) { } }) + w.connection.OnICECandidate(func(iceCandidate *webrtc.ICECandidate) { + fmt.Println(iceCandidate) + }) + + // Data channel callback w.connection.OnDataChannel(func(d *webrtc.DataChannel) { fmt.Printf("New DataChannel %s %d\n", d.Label(), d.ID()) @@ -184,6 +190,15 @@ func (w *WebRTC) StartClient(width, height int) (string, error) { }) }) + offer := webrtc.SessionDescription{} + + Decode(remoteSession, &offer) + + err = w.connection.SetRemoteDescription(offer) + if err != nil { + return "", err + } + answer, err := w.connection.CreateAnswer(nil) if err != nil { return "", err @@ -193,19 +208,6 @@ func (w *WebRTC) StartClient(width, height int) (string, error) { return localSession, nil } -func (w *WebRTC) SetRemoteSession(remoteSession string) error { - offer := webrtc.SessionDescription{} - - Decode(remoteSession, &offer) - - err := w.connection.SetRemoteDescription(offer) - if err != nil { - return err - } - - return nil -} - // StopClient disconnect func (w *WebRTC) StopClient() { fmt.Println("===StopClient===")