From c00d7c8491fc7beae67009d739cd8a9afa40a0b9 Mon Sep 17 00:00:00 2001 From: giongto35 Date: Wed, 1 May 2019 21:06:05 +0800 Subject: [PATCH] Separate create room logic --- cmd/main_test.go | 1 - handler/browser.go | 9 ++++--- handler/handlers.go | 1 + handler/overlord.go | 19 +++++++++++--- handler/rooms.go | 59 ++++++++++++++++++++++++-------------------- handler/session.go | 60 ++++++++++++++++++++++++++++++++++++--------- 6 files changed, 103 insertions(+), 46 deletions(-) diff --git a/cmd/main_test.go b/cmd/main_test.go index 3ff088a2..1ae03a1f 100644 --- a/cmd/main_test.go +++ b/cmd/main_test.go @@ -116,7 +116,6 @@ func initClient(t *testing.T, host string) { RoomID: "", PlayerIndex: 1, }, func(resp cws.WSPacket) { - fmt.Println("Received response") fmt.Println("RoomID:", resp.RoomID) roomID <- resp.RoomID }) diff --git a/handler/browser.go b/handler/browser.go index e9b2bc04..5f7fdcb2 100644 --- a/handler/browser.go +++ b/handler/browser.go @@ -2,6 +2,7 @@ package handler import ( "encoding/json" + "fmt" "log" "github.com/giongto35/cloud-game/config" @@ -80,7 +81,6 @@ func (s *Session) RegisterBrowserClient() { s.GameName = resp.Data s.RoomID = resp.RoomID s.PlayerIndex = resp.PlayerIndex - isNewRoom := false log.Println("Starting game") // If we are connecting to overlord, request serverID from roomID @@ -94,9 +94,11 @@ func (s *Session) RegisterBrowserClient() { } } - s.RoomID, isNewRoom = startSession(s.peerconnection, s.GameName, s.RoomID, s.PlayerIndex) + room := s.handler.createNewRoom(s.GameName, s.RoomID, s.PlayerIndex) + room.addConnectionToRoom(s.peerconnection, s.PlayerIndex) + s.RoomID = room.ID // Register room to overlord if we are connecting to overlord - if isNewRoom && s.OverlordClient != nil { + if room != nil && s.OverlordClient != nil { s.OverlordClient.Send(cws.WSPacket{ ID: "registerRoom", Data: s.RoomID, @@ -105,6 +107,7 @@ func (s *Session) RegisterBrowserClient() { req.ID = "start" req.RoomID = s.RoomID req.SessionID = s.ID + fmt.Println("Response from start", req) return req }) diff --git a/handler/handlers.go b/handler/handlers.go index 918b6b47..60bbde51 100644 --- a/handler/handlers.go +++ b/handler/handlers.go @@ -97,6 +97,7 @@ func (h *Handler) WS(w http.ResponseWriter, r *http.Request) { BrowserClient: client, OverlordClient: h.oClient, peerconnection: webrtc.NewWebRTC(), + handler: h, } wssession.RegisterBrowserClient() fmt.Println("oclient : ", h.oClient) diff --git a/handler/overlord.go b/handler/overlord.go index d84411cf..62f5e4b0 100644 --- a/handler/overlord.go +++ b/handler/overlord.go @@ -9,6 +9,8 @@ import ( "github.com/gorilla/websocket" ) +// OverlordClient maintans connection to overlord +// We expect only one OverlordClient for each server type OverlordClient struct { *cws.Client peerconnections map[string]*webrtc.WebRTC @@ -26,6 +28,7 @@ func NewOverlordClient(oc *websocket.Conn) *OverlordClient { return oclient } +// RegisterOverlordClient routes overlord Client func (s *Session) RegisterOverlordClient() { oclient := s.OverlordClient @@ -64,7 +67,7 @@ func (s *Session) RegisterOverlordClient() { }, ) - // Received start from overlord. This is happens when bridging + // Received start from overlord. This happens when bridging // TODO: refactor oclient.Receive( "start", @@ -74,16 +77,24 @@ func (s *Session) RegisterOverlordClient() { peerconnection := oclient.peerconnections[resp.SessionID] log.Println("start session") - roomID, isNewRoom := startSession(peerconnection, resp.Data, resp.RoomID, resp.PlayerIndex) + + //room := s.handler.createNewRoom(s.GameName, s.RoomID, s.PlayerIndex) + room := s.handler.getRoom(s.RoomID) + if room == nil { + log.Println("Room not found", s.RoomID) + return cws.EmptyPacket + } + room.addConnectionToRoom(peerconnection, s.PlayerIndex) + //roomID, isNewRoom := startSession(peerconnection, resp.Data, resp.RoomID, resp.PlayerIndex) log.Println("Done, sending back") // Bridge always access to old room // TODO: log warn - if isNewRoom == true { + if room != nil { log.Fatal("Bridge should not spawn new room") } req.ID = "start" - req.RoomID = roomID + req.RoomID = room.ID return req }, ) diff --git a/handler/rooms.go b/handler/rooms.go index 393da503..dbd41732 100644 --- a/handler/rooms.go +++ b/handler/rooms.go @@ -14,6 +14,8 @@ import ( // Room is a game session. multi webRTC sessions can connect to a same game. // A room stores all the channel for interaction between all webRTCs session and emulator type Room struct { + ID string + imageChannel chan *image.RGBA audioChannel chan float32 inputChannel chan int @@ -36,7 +38,7 @@ func generateRoomID() string { } // init initilizes a room returns roomID -func initRoom(roomID, gameName string) string { +func (h *Handler) initRoom(roomID, gameName string) *Room { // if no roomID is given, generate it if roomID == "" { roomID = generateRoomID() @@ -50,6 +52,8 @@ func initRoom(roomID, gameName string) string { director := emulator.NewDirector(roomID, imageChannel, audioChannel, inputChannel) room := &Room{ + ID: roomID, + imageChannel: imageChannel, audioChannel: audioChannel, inputChannel: inputChannel, @@ -58,18 +62,17 @@ func initRoom(roomID, gameName string) string { director: director, Done: make(chan struct{}), } - rooms[roomID] = room go room.startVideo() go room.startAudio() - go director.Start([]string{"games/" + gameName}) + go director.Start([]string{"../games/" + gameName}) - return roomID + return room } // isRoomRunning check if there is any running sessions. // TODO: If we remove sessions from room anytime a session is closed, we can check if the sessions list is empty or not. -func isRoomRunning(roomID string) bool { +func (h *Handler) isRoomRunning(roomID string) bool { // If no roomID is registered if _, ok := rooms[roomID]; !ok { return false @@ -84,24 +87,32 @@ func isRoomRunning(roomID string) bool { return false } +func (r *Room) addConnectionToRoom(peerconnection *webrtc.WebRTC, playerIndex int) { + r.cleanSession(peerconnection) + peerconnection.AttachRoomID(r.ID) + go r.startWebRTCSession(peerconnection, playerIndex) + + r.rtcSessions = append(r.rtcSessions, peerconnection) +} + // startWebRTCSession fan-in of the same room to inputChannel -func startWebRTCSession(room *Room, webRTC *webrtc.WebRTC, playerIndex int) { - inputChannel := room.inputChannel - log.Println("room, inputChannel", room, inputChannel) +func (r *Room) startWebRTCSession(peerconnection *webrtc.WebRTC, playerIndex int) { + inputChannel := r.inputChannel + log.Println("room, inputChannel", r, inputChannel) for { select { - case <-webRTC.Done: - removeSession(webRTC, room) + case <-peerconnection.Done: + r.removeSession(peerconnection) default: } // Client stopped - if webRTC.IsClosed() { + if peerconnection.IsClosed() { return } // encode frame - if webRTC.IsConnected() { - input := <-webRTC.InputChannel + if peerconnection.IsConnected() { + input := <-peerconnection.InputChannel // the first 8 bits belong to player 1 // the next 8 belongs to player 2 ... // We standardize and put it to inputChannel (16 bits) @@ -111,26 +122,22 @@ func startWebRTCSession(room *Room, webRTC *webrtc.WebRTC, playerIndex int) { } } -func cleanSession(w *webrtc.WebRTC) { - room, ok := rooms[w.RoomID] - if !ok { - return - } - removeSession(w, room) +func (r *Room) cleanSession(peerconnection *webrtc.WebRTC) { + r.removeSession(peerconnection) } -func removeSession(w *webrtc.WebRTC, room *Room) { - room.sessionsLock.Lock() - defer room.sessionsLock.Unlock() - for i, s := range room.rtcSessions { +func (r *Room) removeSession(w *webrtc.WebRTC) { + r.sessionsLock.Lock() + defer r.sessionsLock.Unlock() + for i, s := range r.rtcSessions { if s == w { - room.rtcSessions = append(room.rtcSessions[:i], room.rtcSessions[i+1:]...) + r.rtcSessions = append(r.rtcSessions[:i], r.rtcSessions[i+1:]...) break } } // If room has no sessions, close room - if len(room.rtcSessions) == 0 { - room.Done <- struct{}{} + if len(r.rtcSessions) == 0 { + r.Done <- struct{}{} } } diff --git a/handler/session.go b/handler/session.go index cb441b32..6cfd80a7 100644 --- a/handler/session.go +++ b/handler/session.go @@ -13,30 +13,66 @@ type Session struct { OverlordClient *OverlordClient peerconnection *webrtc.WebRTC + // TODO: Decouple this + handler *Handler + ServerID string GameName string RoomID string PlayerIndex int } -// startSession handles one session call -func startSession(webRTC *webrtc.WebRTC, gameName string, roomID string, playerIndex int) (rRoomID string, isNewRoom bool) { - isNewRoom = false - cleanSession(webRTC) +// getRoom returns room from roomID +func (h *Handler) getRoom(roomID string) *Room { + room, ok := h.rooms[roomID] + if !ok { + return nil + } + + return room +} + +// createNewRoom creates a new room +// Return nil in case of room is existed +func (h *Handler) createNewRoom(gameName string, roomID string, playerIndex int) *Room { + //cleanSession(peerconnection) // If the roomID is empty, // or the roomID doesn't have any running sessions (room was closed) // we spawn a new room - if roomID == "" || !isRoomRunning(roomID) { - roomID = initRoom(roomID, gameName) - isNewRoom = true + if roomID == "" || !h.isRoomRunning(roomID) { + room := h.initRoom(roomID, gameName) + h.rooms[roomID] = room + return room } // TODO: Might have race condition - rooms[roomID].rtcSessions = append(rooms[roomID].rtcSessions, webRTC) - room := rooms[roomID] + //rooms[roomID].rtcSessions = append(rooms[roomID].rtcSessions, peerconnection) + //room := rooms[roomID] - webRTC.AttachRoomID(roomID) - go startWebRTCSession(room, webRTC, playerIndex) + //peerconnection.AttachRoomID(roomID) + //go startWebRTCSession(room, peerconnection, playerIndex) - return roomID, isNewRoom + return nil } + +// startPeerConnection handles one peerconnection call +//func (s *Handler) startPeerConnection( gameName string, roomID string, playerIndex int) (rRoomID string, isNewRoom bool) { +//isNewRoom = false +//cleanSession(peerconnection) +//// If the roomID is empty, +//// or the roomID doesn't have any running sessions (room was closed) +//// we spawn a new room +//if roomID == "" || !isRoomRunning(roomID) { +//roomID = initRoom(roomID, gameName) +//isNewRoom = true +//} + +//// TODO: Might have race condition +//rooms[roomID].rtcSessions = append(rooms[roomID].rtcSessions, peerconnection) +//room := rooms[roomID] + +//peerconnection.AttachRoomID(roomID) +//go startWebRTCSession(room, peerconnection, playerIndex) + +//return roomID, isNewRoom +//}