mirror of
https://github.com/giongto35/cloud-game.git
synced 2026-07-21 17:18:47 +00:00
170 lines
4 KiB
Go
170 lines
4 KiB
Go
package handler
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
|
|
"github.com/giongto35/cloud-game/cws"
|
|
storage "github.com/giongto35/cloud-game/handler/cloud-storage"
|
|
"github.com/giongto35/cloud-game/handler/gamelist"
|
|
"github.com/giongto35/cloud-game/handler/room"
|
|
"github.com/giongto35/cloud-game/webrtc"
|
|
"github.com/gorilla/websocket"
|
|
uuid "github.com/satori/go.uuid"
|
|
)
|
|
|
|
const (
|
|
gameboyIndex = "./static/gameboy.html"
|
|
debugIndex = "./static/index_ws.html"
|
|
)
|
|
|
|
// Flag to determine if the server is overlord or not
|
|
var upgrader = websocket.Upgrader{}
|
|
|
|
type Handler struct {
|
|
// Client that connects to overlord
|
|
oClient *OverlordClient
|
|
// Rooms map : RoomID -> Room
|
|
rooms map[string]*room.Room
|
|
// ID of the current server globalwise
|
|
serverID string
|
|
// isDebug determines the mode handler is running
|
|
isDebug bool
|
|
// Path to game list
|
|
gamePath string
|
|
// All webrtc peerconnections are handled by the server
|
|
// ID -> peerconnections
|
|
peerconnections map[string]*webrtc.WebRTC
|
|
// onlineStorage is client accessing to online storage (GCP)
|
|
onlineStorage *storage.Client
|
|
}
|
|
|
|
// NewHandler returns a new server
|
|
func NewHandler(overlordConn *websocket.Conn, isDebug bool, gamePath string) *Handler {
|
|
onlineStorage := storage.NewInitClient()
|
|
|
|
return &Handler{
|
|
oClient: NewOverlordClient(overlordConn),
|
|
rooms: map[string]*room.Room{},
|
|
peerconnections: map[string]*webrtc.WebRTC{},
|
|
|
|
isDebug: isDebug,
|
|
gamePath: gamePath,
|
|
|
|
onlineStorage: onlineStorage,
|
|
}
|
|
}
|
|
|
|
// GetWeb returns web frontend
|
|
func (h *Handler) GetWeb(w http.ResponseWriter, r *http.Request) {
|
|
indexFN := ""
|
|
if h.isDebug {
|
|
indexFN = debugIndex
|
|
} else {
|
|
indexFN = gameboyIndex
|
|
}
|
|
|
|
bs, err := ioutil.ReadFile(indexFN)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
w.Write(bs)
|
|
}
|
|
|
|
// WS handles normal traffic (from browser to host)
|
|
func (h *Handler) WS(w http.ResponseWriter, r *http.Request) {
|
|
c, err := upgrader.Upgrade(w, r, nil)
|
|
if err != nil {
|
|
log.Print("[!] WS upgrade:", err)
|
|
return
|
|
}
|
|
defer c.Close()
|
|
|
|
client := NewBrowserClient(c)
|
|
sessionID := uuid.Must(uuid.NewV4()).String()
|
|
wssession := &Session{
|
|
ID: sessionID,
|
|
BrowserClient: client,
|
|
OverlordClient: h.oClient,
|
|
peerconnection: webrtc.NewWebRTC(),
|
|
handler: h,
|
|
}
|
|
defer wssession.Close()
|
|
|
|
if wssession.OverlordClient != nil {
|
|
wssession.RouteOverlord()
|
|
go wssession.OverlordClient.Heartbeat()
|
|
go wssession.OverlordClient.Listen()
|
|
}
|
|
|
|
wssession.RouteBrowser()
|
|
log.Println("oclient : ", h.oClient)
|
|
|
|
wssession.BrowserClient.Send(cws.WSPacket{
|
|
ID: "gamelist",
|
|
Data: gamelist.GetEncodedGameList(h.gamePath),
|
|
}, nil)
|
|
|
|
wssession.BrowserClient.Listen()
|
|
|
|
// TODO: Use callback
|
|
// listen to socket done to close peerconnection
|
|
go func() {
|
|
for {
|
|
<-client.Done
|
|
h.detachPeerConn(wssession.peerconnection)
|
|
return
|
|
}
|
|
}()
|
|
|
|
}
|
|
|
|
// Detach peerconnection detach/remove a peerconnection from current room
|
|
func (h *Handler) detachPeerConn(pc *webrtc.WebRTC) {
|
|
log.Println("Detach peerconnection")
|
|
roomID := pc.RoomID
|
|
room := h.getRoom(roomID)
|
|
if room == nil {
|
|
return
|
|
}
|
|
room.CleanSession(pc)
|
|
}
|
|
|
|
// getRoom returns room from roomID
|
|
func (h *Handler) getRoom(roomID string) *room.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.Room {
|
|
// If the roomID is empty,
|
|
// or the roomID doesn't have any running sessions (room was closed)
|
|
// we spawn a new room
|
|
if roomID == "" || !h.isRoomRunning(roomID) {
|
|
room := room.NewRoom(roomID, h.gamePath, gameName, h.onlineStorage)
|
|
// TODO: Might have race condition
|
|
h.rooms[room.ID] = room
|
|
return room
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// 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 (h *Handler) isRoomRunning(roomID string) bool {
|
|
// If no roomID is registered
|
|
room, ok := h.rooms[roomID]
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
return room.IsRunning()
|
|
}
|