From 9ea0bf223c9178b694830daf6e8d2cff87fdcb9e Mon Sep 17 00:00:00 2001 From: giongto35 Date: Thu, 16 May 2019 01:04:54 +0800 Subject: [PATCH 1/5] Check peerconnection is in room before detach and reconn --- handler/browser.go | 16 ++++++++++++---- handler/handlers.go | 12 ++++-------- handler/room/room.go | 18 +++++++++++++----- webrtc/webrtc.go | 12 ++++++------ 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/handler/browser.go b/handler/browser.go index 6c174f5f..b76e9a55 100644 --- a/handler/browser.go +++ b/handler/browser.go @@ -46,6 +46,9 @@ func (s *Session) RouteBrowser() { req.Data = "ok" if s.RoomID != "" { room := s.handler.getRoom(s.RoomID) + if room == nil { + return + } err := room.SaveGame() if err != nil { log.Println("[!] Cannot save game state: ", err) @@ -95,17 +98,22 @@ func (s *Session) RouteBrowser() { } } - // Create new room + // Get Room in local server // TODO: check if roomID is in the current server room := s.handler.getRoom(s.RoomID) log.Println("Got Room from local ", room, " ID: ", s.RoomID) + // If room is not running if room == nil { + // Create new room room = s.handler.createNewRoom(s.GameName, s.RoomID, s.PlayerIndex) } - // Attach peerconnection to room - s.handler.detachPeerConn(s.peerconnection) - room.AddConnectionToRoom(s.peerconnection, s.PlayerIndex) + // Attach peerconnection to room. If PC is already in room, don't detach + log.Println("Is PC in room", room.IsPCInRoom(s.peerconnection)) + if !room.IsPCInRoom(s.peerconnection) { + s.handler.detachPeerConn(s.peerconnection) + room.AddConnectionToRoom(s.peerconnection, s.PlayerIndex) + } s.RoomID = room.ID // Register room to overlord if we are connecting to overlord diff --git a/handler/handlers.go b/handler/handlers.go index fd54d663..e75483f0 100644 --- a/handler/handlers.go +++ b/handler/handlers.go @@ -112,18 +112,14 @@ func (h *Handler) WS(w http.ResponseWriter, r *http.Request) { Data: gamelist.GetEncodedGameList(h.gamePath), }, nil) - wssession.BrowserClient.Listen() - - // TODO: Use callback // If peerconnection is done (client.Done is signalled), we close peerconnection go func() { - for { - <-client.Done - h.detachPeerConn(wssession.peerconnection) - return - } + <-client.Done + log.Println("Socket terminated, detach connection") + h.detachPeerConn(wssession.peerconnection) }() + wssession.BrowserClient.Listen() } // Detach peerconnection detach/remove a peerconnection from current room diff --git a/handler/room/room.go b/handler/room/room.go index a5b6f5f0..60c341cc 100644 --- a/handler/room/room.go +++ b/handler/room/room.go @@ -1,7 +1,6 @@ package room import ( - "fmt" "image" "io/ioutil" "log" @@ -147,14 +146,13 @@ func (r *Room) CleanSession(peerconnection *webrtc.WebRTC) { } func (r *Room) removeSession(w *webrtc.WebRTC) { - fmt.Println("Cleaning session: ", w) - fmt.Println("Sessions list", r.rtcSessions) + log.Println("Cleaning session: ", w.ID) // TODO: get list of r.rtcSessions in lock for i, s := range r.rtcSessions { - fmt.Println("found session: ", s, w) + log.Println("found session: ", w.ID) if s.ID == w.ID { r.rtcSessions = append(r.rtcSessions[:i], r.rtcSessions[i+1:]...) - fmt.Println("found session: ", len(r.rtcSessions)) + log.Println("Removed session ", s.ID, " from room: ", r.ID) // If room has no sessions, close room // Note: this logic cannot be brought outside of forloop because we only close room if room had at least one session @@ -169,6 +167,16 @@ func (r *Room) removeSession(w *webrtc.WebRTC) { } } +// TODO: Reuse for remove Session +func (r *Room) IsPCInRoom(w *webrtc.WebRTC) bool { + for _, s := range r.rtcSessions { + if s.ID == w.ID { + return true + } + } + return false +} + func (r *Room) Close() { if r.Done { return diff --git a/webrtc/webrtc.go b/webrtc/webrtc.go index f1b0b1cd..c7a1d98e 100644 --- a/webrtc/webrtc.go +++ b/webrtc/webrtc.go @@ -93,12 +93,12 @@ type WebRTC struct { // StartClient start webrtc func (w *WebRTC) StartClient(remoteSession string, width, height int) (string, error) { - defer func() { - if err := recover(); err != nil { - log.Println(err) - w.StopClient() - } - }() + //defer func() { + //if err := recover(); err != nil { + //log.Println(err) + //w.StopClient() + //} + //}() // reset client if w.isConnected { From 1028e871499e6054e6563afc4a53876e3c53c745 Mon Sep 17 00:00:00 2001 From: giongto35 Date: Thu, 16 May 2019 02:00:23 +0800 Subject: [PATCH 2/5] Detach room from handler --- handler/browser.go | 5 +++++ handler/handlers.go | 7 ++++++- handler/room/media.go | 4 ++-- handler/room/room.go | 16 ++++++++++------ 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/handler/browser.go b/handler/browser.go index b76e9a55..cd57bbd9 100644 --- a/handler/browser.go +++ b/handler/browser.go @@ -106,6 +106,11 @@ func (s *Session) RouteBrowser() { if room == nil { // Create new room room = s.handler.createNewRoom(s.GameName, s.RoomID, s.PlayerIndex) + // Wait for done signal from room + go func() { + <-room.Done + s.handler.detachRoom(room.ID) + }() } // Attach peerconnection to room. If PC is already in room, don't detach diff --git a/handler/handlers.go b/handler/handlers.go index e75483f0..9f9a3102 100644 --- a/handler/handlers.go +++ b/handler/handlers.go @@ -143,6 +143,11 @@ func (h *Handler) getRoom(roomID string) *room.Room { return room } +// detachRoom detach room from Handler +func (h *Handler) detachRoom(roomID string) { + delete(h.rooms, roomID) +} + // createNewRoom creates a new room // Return nil in case of room is existed func (h *Handler) createNewRoom(gameName string, roomID string, playerIndex int) *room.Room { @@ -168,5 +173,5 @@ func (h *Handler) isRoomRunning(roomID string) bool { return false } - return room.IsRunning() + return room.IsRunningSessions() } diff --git a/handler/room/media.go b/handler/room/media.go index 4daed757..1ae594ca 100644 --- a/handler/room/media.go +++ b/handler/room/media.go @@ -32,7 +32,7 @@ func (r *Room) startAudio() { log.Println("Warn: Room ", r.ID, " audio channel closed unexpectedly") return } - if r.Done { + if !r.IsRunning { log.Println("Room ", r.ID, " audio channel closed") return } @@ -85,7 +85,7 @@ func (r *Room) startVideo() { log.Println("Warn: Room ", r.ID, " video channel closed unexpectedly") return } - if r.Done { + if !r.IsRunning { log.Println("Room ", r.ID, " video channel closed") return } diff --git a/handler/room/room.go b/handler/room/room.go index 60c341cc..6bbf9a09 100644 --- a/handler/room/room.go +++ b/handler/room/room.go @@ -22,8 +22,9 @@ type Room struct { imageChannel chan *image.RGBA audioChannel chan float32 inputChannel chan int + IsRunning bool // Done channel is to fire exit event when there is no webRTC session running - Done bool + Done chan struct{} rtcSessions []*webrtc.WebRTC sessionsLock *sync.Mutex @@ -57,8 +58,10 @@ func NewRoom(roomID, gamepath, gameName string, onlineStorage *storage.Client) * rtcSessions: []*webrtc.WebRTC{}, sessionsLock: &sync.Mutex{}, director: director, - Done: false, + IsRunning: true, onlineStorage: onlineStorage, + + Done: make(chan struct{}), } go room.startVideo() @@ -121,7 +124,7 @@ func (r *Room) startWebRTCSession(peerconnection *webrtc.WebRTC, playerIndex int // might consider continue here } - if peerconnection.Done || !peerconnection.IsConnected() || r.Done { + if peerconnection.Done || !peerconnection.IsConnected() || !r.IsRunning { return } @@ -178,7 +181,7 @@ func (r *Room) IsPCInRoom(w *webrtc.WebRTC) bool { } func (r *Room) Close() { - if r.Done { + if !r.IsRunning { return } @@ -187,7 +190,8 @@ func (r *Room) Close() { close(r.director.Done) log.Println("Closing input of room ", r.ID) close(r.inputChannel) - r.Done = true + close(r.Done) + r.IsRunning = true // Close here is a bit wrong because this read channel //close(r.imageChannel) //close(r.audioChannel) @@ -231,7 +235,7 @@ func (r *Room) LoadGame() error { return err } -func (r *Room) IsRunning() bool { +func (r *Room) IsRunningSessions() bool { // If there is running session for _, s := range r.rtcSessions { if s.IsConnected() { From 8d9ee6f162bae684031a7c88bfe0dba552827fee Mon Sep 17 00:00:00 2001 From: giongto35 Date: Thu, 16 May 2019 02:20:11 +0800 Subject: [PATCH 3/5] Set IsRunning = false early --- handler/room/room.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/handler/room/room.go b/handler/room/room.go index 6bbf9a09..9a82afe2 100644 --- a/handler/room/room.go +++ b/handler/room/room.go @@ -185,13 +185,13 @@ func (r *Room) Close() { return } + r.IsRunning = false log.Println("Closing room", r.ID) log.Println("Closing director of room ", r.ID) close(r.director.Done) log.Println("Closing input of room ", r.ID) close(r.inputChannel) close(r.Done) - r.IsRunning = true // Close here is a bit wrong because this read channel //close(r.imageChannel) //close(r.audioChannel) From 2f7b7ba55e8dc73898337293500948bec6488309 Mon Sep 17 00:00:00 2001 From: giongto35 Date: Thu, 16 May 2019 02:41:54 +0800 Subject: [PATCH 4/5] Remove comments --- webrtc/webrtc.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/webrtc/webrtc.go b/webrtc/webrtc.go index c7a1d98e..cdad7be7 100644 --- a/webrtc/webrtc.go +++ b/webrtc/webrtc.go @@ -156,19 +156,13 @@ func (w *WebRTC) StartClient(remoteSession string, width, height int) (string, e // Register text message handling inputTrack.OnMessage(func(msg webrtc.DataChannelMessage) { - //layout .:= "2006-01-02T15:04:05.000Z" - //if t, err := time.Parse(layout, string(msg.Data[1])); err == nil { - //fmt.Println("Delay ", time.Now().Sub(t)) - //} else { + // TODO: Can add recover here w.InputChannel <- int(msg.Data[0]) - //} }) inputTrack.OnClose(func() { log.Println("Data channel closed") log.Println("Closed webrtc") - //close(w.Done) - //w.StopClient() }) // WebRTC state callback From 107f0b725b74ff51299df30574a426ef56de0e7a Mon Sep 17 00:00:00 2001 From: giongto35 Date: Thu, 16 May 2019 02:47:35 +0800 Subject: [PATCH 5/5] Add comments --- handler/room/room.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/handler/room/room.go b/handler/room/room.go index 9a82afe2..eedd8587 100644 --- a/handler/room/room.go +++ b/handler/room/room.go @@ -19,18 +19,22 @@ import ( type Room struct { ID string + // imageChannel is image stream from director imageChannel chan *image.RGBA + // audioChannel is audio stream from director audioChannel chan float32 + // inputChannel is input stream from websocket to room inputChannel chan int - IsRunning bool - // Done channel is to fire exit event when there is no webRTC session running + // State of room + IsRunning bool + // Done channel is to fire exit event when room is closed Done chan struct{} - - rtcSessions []*webrtc.WebRTC + // List of peerconnections in the room + rtcSessions []*webrtc.WebRTC + // NOTE: Not in use, lock rtcSessions sessionsLock *sync.Mutex - + // Director is emulator director *emulator.Director - // Cloud storage to store room state online onlineStorage *storage.Client }