Merge pull request #28 from giongto35/fix-closed-channel-bug

Fix closed channel bug
This commit is contained in:
giongto35 2019-05-16 02:50:24 +08:00 committed by GitHub
commit ea020bd7ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 68 additions and 44 deletions

View file

@ -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,27 @@ 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)
// Wait for done signal from room
go func() {
<-room.Done
s.handler.detachRoom(room.ID)
}()
}
// 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

View file

@ -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
@ -147,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 {
@ -172,5 +173,5 @@ func (h *Handler) isRoomRunning(roomID string) bool {
return false
}
return room.IsRunning()
return room.IsRunningSessions()
}

View file

@ -33,7 +33,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
}
@ -88,7 +88,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
}

View file

@ -1,7 +1,6 @@
package room
import (
"fmt"
"image"
"io/ioutil"
"log"
@ -20,17 +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
// Done channel is to fire exit event when there is no webRTC session running
Done bool
rtcSessions []*webrtc.WebRTC
// State of room
IsRunning bool
// Done channel is to fire exit event when room is closed
Done chan struct{}
// 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
}
@ -58,8 +62,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()
@ -122,7 +128,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
}
@ -147,14 +153,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,17 +174,28 @@ 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 {
if !r.IsRunning {
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)
r.Done = true
close(r.Done)
// Close here is a bit wrong because this read channel
//close(r.imageChannel)
//close(r.audioChannel)
@ -223,7 +239,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() {

View file

@ -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 {
@ -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