Guard room creation with a mutex

Possible fix for the concurrent room creation while other is not destroyed properly.
This commit is contained in:
Sergey Stepanov 2023-10-06 13:30:10 +03:00
parent cddf081b8f
commit f875d3fc42
No known key found for this signature in database
GPG key ID: A56B4929BAA8556B
2 changed files with 30 additions and 19 deletions

View file

@ -50,9 +50,7 @@ func (c *coordinator) HandleWebrtcInit(rq api.WebrtcInitRequest[com.Uid], w *Wor
user := room.NewGameSession(rq.Id, peer) // use user uid from the coordinator
c.log.Info().Msgf("Peer connection: %s", user.Id())
c.log.Debug().Msgf("Users before add: %v", w.router.Users())
w.router.AddUser(user)
c.log.Debug().Msgf("Users after add: %v", w.router.Users())
return api.Out{Payload: sdp}
}
@ -83,11 +81,23 @@ func (c *coordinator) HandleGameStart(rq api.StartGameRequest[com.Uid], w *Worke
r := w.router.FindRoom(rq.Rid)
if r == nil {
if r == nil { // new room
uid := rq.Room.Rid
if uid == "" {
uid = games.GenerateRoomID(rq.Game.Name)
}
game := games.GameMetadata(rq.Game)
r = room.NewRoom[*room.GameSession](uid, nil, w.router.Users(), nil)
r.HandleClose = func() { c.CloseRoom(uid) }
if other := w.router.Room(); other != nil {
c.log.Error().Msgf("concurrent room creation: %v", uid)
return api.EmptyPacket
}
w.router.SetRoom(r)
c.log.Info().Str("room", r.Id()).Str("game", game.Name).Msg("New room")
// start the emulator
app := room.WithEmulator(w.mana.Get(caged.Libretro))
@ -97,13 +107,14 @@ func (c *coordinator) HandleGameStart(rq api.StartGameRequest[com.Uid], w *Worke
app.EnableCloudStorage(uid, w.storage)
app.EnableRecording(rq.Record, rq.RecordUser, rq.Game.Name)
w.log.Info().Msgf("Starting game: %v", rq.Game.Name)
game := games.GameMetadata(rq.Game)
w.log.Info().Msgf("Starting the game: %v", rq.Game.Name)
if err := app.Load(game, w.conf.Worker.Library.BasePath); err != nil {
c.log.Error().Err(err).Msgf("couldn't load the game %v", game)
app.Close()
w.router.SetRoom(nil)
return api.EmptyPacket
}
r.SetApp(app)
m := media.NewWebRtcMediaPipe(w.conf.Encoder.Audio, w.conf.Encoder.Video, w.log)
m.AudioSrcHz = app.AudioSampleRate()
@ -112,19 +123,15 @@ func (c *coordinator) HandleGameStart(rq api.StartGameRequest[com.Uid], w *Worke
if err := m.Init(); err != nil {
c.log.Error().Err(err).Msgf("couldn't init the media")
app.Close()
w.router.SetRoom(nil)
return api.EmptyPacket
}
if app.Flipped() {
m.SetVideoFlip(true)
}
r.SetMedia(m)
// make the room
r = room.NewRoom[*room.GameSession](uid, app, w.router.Users(), m)
r.HandleClose = func() { c.CloseRoom(uid) }
w.router.SetRoom(r)
c.log.Info().Str("room", r.Id()).Str("game", game.Name).Msg("New room")
r.BindAppMedia()
r.StartApp()
}
@ -146,10 +153,8 @@ func (c *coordinator) HandleTerminateSession(rq api.TerminateSessionRequest[com.
// HandleQuitGame handles cases when a user manually exits the game.
func (c *coordinator) HandleQuitGame(rq api.GameQuitRequest[com.Uid], w *Worker) {
w.log.Debug().Msgf("Users before remove: %v", w.router.Users())
if user := w.router.FindUser(rq.Id); user != nil {
w.router.Remove(user)
w.log.Debug().Msgf("Users after remove: %v", w.router.Users())
}
}

View file

@ -53,8 +53,10 @@ type Room[T Session] struct {
func NewRoom[T Session](id string, app app.App, um SessionManager[T], media MediaPipe) *Room[T] {
room := &Room[T]{id: id, app: app, users: um, media: media}
room.InitVideo()
room.InitAudio()
if app != nil && media != nil {
room.InitVideo()
room.InitAudio()
}
return room
}
@ -70,9 +72,12 @@ func (r *Room[T]) InitVideo() {
})
}
func (r *Room[T]) App() app.App { return r.app }
func (r *Room[T]) Id() string { return r.id }
func (r *Room[T]) StartApp() { r.app.Start() }
func (r *Room[T]) App() app.App { return r.app }
func (r *Room[T]) BindAppMedia() { r.InitAudio(); r.InitVideo() }
func (r *Room[T]) Id() string { return r.id }
func (r *Room[T]) SetApp(app app.App) { r.app = app }
func (r *Room[T]) SetMedia(m MediaPipe) { r.media = m }
func (r *Room[T]) StartApp() { r.app.Start() }
func (r *Room[T]) Close() {
if r.closed {
@ -124,6 +129,7 @@ func (r *Router[T]) Remove(user T) {
r.Close()
}
}
func (r *Router[T]) Room() *Room[T] { r.mu.Lock(); defer r.mu.Unlock(); return r.room }
func (r *Router[T]) FindUser(uid Uid) T { return r.users.Find(uid.Id()) }
func (r *Router[T]) SetRoom(room *Room[T]) { r.mu.Lock(); r.room = room; r.mu.Unlock() }
func (r *Router[T]) Users() SessionManager[T] { return r.users }