diff --git a/index_http.html b/index_http.html index 0f8d66c7..19911730 100644 --- a/index_http.html +++ b/index_http.html @@ -21,9 +21,9 @@ textarea { - + -Room ID:
+Room ID:


@@ -72,11 +72,14 @@ function postSession(session) { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { - remoteSessionDescription = this.responseText; + d = JSON.parse(this.responseText); + remoteSessionDescription = d["sdp"] + document.getElementById('roomID').value = d["room_id"] document.getElementById('playGame').disabled = false; } }; - roomID = document.getElementById('roomID').text + + roomID = document.getElementById('roomID').value xhttp.open("POST", "/session", true); xhttp.setRequestHeader("Content-type", "application/json"); xhttp.send(JSON.stringify({"game": gameOp.value, "room_id": roomID, "sdp": session})); @@ -115,6 +118,7 @@ pc.onicecandidate = event => { if (event.candidate === null) { var session = btoa(JSON.stringify(pc.localDescription)); localSessionDescription = session; + console.log("ice candidate") postSession(session) } } @@ -169,6 +173,7 @@ document.body.onkeyup = function(e){ }; window.startSession = () => { + console.log("Start session") let sd = remoteSessionDescription if (sd === '') { return alert('Session Description must not be empty') diff --git a/index_ws.html b/index_ws.html index f610881a..dca9e629 100644 --- a/index_ws.html +++ b/index_ws.html @@ -75,7 +75,8 @@ window.startGame = () => { conn.onopen = () => { log("WebSocket is opened. Send ping"); - conn.send(JSON.stringify({"id": "ping", "data": gameOp.value})); + roomID = document.getElementById('roomID').value + conn.send(JSON.stringify({"id": "ping", "data": gameOp.value, "room_id": roomID})); } conn.onerror = error => { diff --git a/main.go b/main.go index 1613d8ec..6a3134a5 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "math/rand" "os" "strconv" + "time" pionRTC "github.com/pion/webrtc" @@ -31,16 +32,18 @@ var index string = "./index_http.html" var upgrader = websocket.Upgrader{} type WSPacket struct { - ID string `json:"id"` - Data string `json:"data"` + ID string `json:"id"` + Data string `json:"data"` + RoomID string `json:"room_id"` } type Room struct { imageChannel chan *image.RGBA + inputChannel chan int rtcSessions []*webrtc.WebRTC } -var rooms map[string]Room +var rooms map[string]*Room func init() { } @@ -50,8 +53,10 @@ func startGame(path string, imageChannel chan *image.RGBA, inputChannel chan int } func main() { + rand.Seed(time.Now().UTC().UnixNano()) fmt.Printf("Usage: %s [ws]\n", os.Args[0]) fmt.Println("http://localhost:8000") + rooms = map[string]*Room{} if len(os.Args) > 1 { log.Println("Using websocket") index = "./index_ws.html" @@ -128,7 +133,7 @@ func ws(w http.ResponseWriter, r *http.Request) { res.ID = "sdp" res.Data = localSession - //res.RoomID = generateRoomID() + res.RoomID = generateRoomID() case "candidate": hi := pionRTC.ICECandidateInit{} @@ -143,7 +148,7 @@ func ws(w http.ResponseWriter, r *http.Request) { case "start": log.Println("Starting game") imageChannel := make(chan *image.RGBA, 100) - go screenshotLoop(imageChannel, webRTC) + //go screenshotLoop(imageChannel, webRTC) go startGame("games/"+gameName, imageChannel, webRTC.InputChannel, webRTC) res.ID = "start" isDone = true @@ -191,34 +196,51 @@ func postSession(w http.ResponseWriter, r *http.Request) { log.Fatalln(err) } - if postPacket.RoomID == "" { + roomID := postPacket.RoomID + fmt.Println("RoomID", roomID) + if roomID == "" { + fmt.Println("Init Room") + //generate new room + roomID = generateRoomID() + imageChannel := make(chan *image.RGBA, 100) - rooms[postPacket.RoomID] = Room{ + inputChannel := make(chan int, 100) + rooms[roomID] = &Room{ imageChannel: imageChannel, + inputChannel: inputChannel, rtcSessions: []*webrtc.WebRTC{}, } - go screenshotLoop(imageChannel, room) + go fanoutScreen(imageChannel, roomID) + go startGame("games/"+postPacket.Game, imageChannel, inputChannel, webRTC) + // fanin input channel + // fanout output channel } else { - // if there is room, reuse image channel - rooms[postPacket.RoomID] = append(rooms[postPacket.RoomID], webRTC) + // if there is room, reuse image channel, add webRTC session } - go startGame("games/"+postPacket.Game, imageChannel, webRTC.InputChannel, webRTC) + rooms[roomID].rtcSessions = append(rooms[roomID].rtcSessions, webRTC) + faninInput(rooms[roomID].inputChannel, webRTC) - w.Write([]byte(localSession)) + res := SessionPacket{ + SDP: localSession, + RoomID: roomID, + } + stRes, err := json.Marshal(res) + if err != nil { + log.Println("json marshal:", err) + } + + //w.Write([]byte(localSession)) + w.Write(stRes) } // generateRoomID generate a unique room ID containing 16 digits func generateRoomID() string { roomID := strconv.FormatInt(rand.Int63(), 16) - for len(roomID) < 16 { - roomID = "0" + roomID - } - fmt.Println(roomID) return roomID } -// func screenshotLoop(imageChannel chan *image.RGBA) { -func screenshotLoop(imageChannel chan *image.RGBA, roomID string) { +// func fanoutScreen(imageChannel chan *image.RGBA) { +func fanoutScreen(imageChannel chan *image.RGBA, roomID string) { for image := range imageChannel { yuv := util.RgbaToYuv(image) for _, webRTC := range rooms[roomID].rtcSessions { @@ -228,6 +250,7 @@ func screenshotLoop(imageChannel chan *image.RGBA, roomID string) { } // encode frame + // fanout imageChannel if webRTC.IsConnected() { webRTC.ImageChannel <- yuv } @@ -236,3 +259,23 @@ func screenshotLoop(imageChannel chan *image.RGBA, roomID string) { // time.Sleep(time.Duration(1000 / FPS) * time.Millisecond) } } + +// func faninInput(input chan int) { +func faninInput(inputChannel chan int, webRTC *webrtc.WebRTC) { + go func() { + for { + fmt.Println("spawning") + // Client stopped + if webRTC.IsClosed() { + return + } + + // encode frame + if webRTC.IsConnected() { + input := <-webRTC.InputChannel + fmt.Println("received input", input) + inputChannel <- input + } + } + }() +}