Clean code

This commit is contained in:
giongto35 2019-05-19 05:24:58 +08:00
parent c3081ee5d9
commit 4dc55b5cdb
12 changed files with 45 additions and 317 deletions

195
' vendored
View file

@ -1,195 +0,0 @@
package handler
import (
"log"
"github.com/giongto35/cloud-game/config"
"github.com/giongto35/cloud-game/cws"
"github.com/giongto35/cloud-game/webrtc"
"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
}
// NewOverlordClient returns a client connecting to overlord for coordiation between different server
func NewOverlordClient(oc *websocket.Conn) *OverlordClient {
if oc == nil {
return nil
}
oclient := &OverlordClient{
Client: cws.NewClient(oc),
peerconnections: map[string]*webrtc.WebRTC{},
}
return oclient
}
// RouteOverlord are all routes server received from overlord
func (s *Session) RouteOverlord() {
iceCandidates := [][]byte{}
oclient := s.OverlordClient
// Received from overlord the serverID
oclient.Receive(
"serverID",
func(response cws.WSPacket) (request cws.WSPacket) {
// Stick session with serverID got from overlord
log.Println("Received serverID ", response.Data)
s.ServerID = response.Data
return cws.EmptyPacket
},
)
oclient.Receive(
"initwebrtc",
func(resp cws.WSPacket) (req cws.WSPacket) {
log.Println("Received user SDP")
localSession, err := s.peerconnection.StartClient(resp.Data, iceCandidates, config.Width, config.Height)
if err != nil {
if err != nil {
log.Println("Error: Cannot create new webrtc session", err)
return cws.EmptyPacket
}
}
return cws.WSPacket{
ID: "sdp",
Data: localSession,
SessionID: s.ID,
}
},
)
// Received start from overlord. This happens when bridging
// TODO: refactor
//oclient.Receive(
//"start",
//func(resp cws.WSPacket) (req cws.WSPacket) {
//log.Println("Received a start request from overlord")
//log.Println("Add the connection to current room on the host ", resp.SessionID)
//peerconnection := oclient.peerconnections[resp.SessionID]
//log.Println("start session")
////room := s.handler.createNewRoom(s.GameName, s.RoomID, s.PlayerIndex)
//// Request room from Server if roomID is existed on the server
//room := s.handler.getRoom(s.RoomID)
//if room == nil {
//log.Println("Room not found ", s.RoomID)
//return cws.EmptyPacket
//}
//s.handler.detachPeerConn(s.peerconnection)
//room.AddConnectionToRoom(peerconnection, s.PlayerIndex)
////roomID, isNewRoom := startSession(peerconnection, resp.Data, resp.RoomID, resp.PlayerIndex)
//log.Println("Done, sending back")
//req.ID = "start"
//req.RoomID = room.ID
//return req
//},
//)
oclient.Receive(
"start",
func(resp cws.WSPacket) (req cws.WSPacket) {
log.Println("Received a start request from overlord")
log.Println("Add the connection to current room on the host ", resp.SessionID)
s.startGameHandler(resp.Data, resp.RoomID, resp.PlayerIndex)
},
)
// heartbeat to keep pinging overlord. We not ping from server to browser, so we don't call heartbeat in browserClient
}
func getServerIDOfRoom(oc *OverlordClient, roomID string) string {
log.Println("Request overlord roomID ", roomID)
packet := oc.SyncSend(
cws.WSPacket{
ID: "getRoom",
Data: roomID,
},
)
log.Println("Received roomID from overlord ", packet.Data)
return packet.Data
}
func (s *Session) startGameHandler(gameName, roomID string, playerIndex int) cws.WSPacket {
s.GameName = gameName
s.RoomID = roomID
s.PlayerIndex = playerIndex
log.Println("Starting game")
// If we are connecting to overlord, request corresponding serverID based on roomID
// 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. 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
if room != nil && s.OverlordClient != nil {
s.OverlordClient.Send(cws.WSPacket{
ID: "registerRoom",
Data: s.RoomID,
}, nil)
}
req.ID = "start"
req.RoomID = s.RoomID
req.SessionID = s.ID
return req
}
//func (s *Session) bridgeConnection(serverID string, gameName string, roomID string, playerIndex int) {
//log.Println("Bridging connection to other Host ", serverID)
//client := s.BrowserClient
//// Ask client to init
//log.Println("Requesting offer to browser", serverID)
//resp := client.SyncSend(cws.WSPacket{
//ID: "requestOffer",
//Data: "",
//})
//// Ask overlord to relay SDP packet to serverID
//resp.TargetHostID = serverID
//log.Println("Sending offer to overlord to relay message to target host", resp.TargetHostID, "with payload")
//remoteTargetSDP := s.OverlordClient.SyncSend(resp)
//log.Println("Got back remote host SDP, sending to browser")
//// Send back remote SDP of remote server to browser
//s.BrowserClient.Send(cws.WSPacket{
//ID: "sdp",
//Data: remoteTargetSDP.Data,
//}, nil)
//log.Println("Init session done, start game on target host")
//s.OverlordClient.SyncSend(cws.WSPacket{
//ID: "start",
//Data: gameName,
//TargetHostID: serverID,
//RoomID: roomID,
//PlayerIndex: playerIndex,
//})
//log.Println("Game is started on remote host")
//}

View file

@ -11,8 +11,8 @@ import (
"time"
"github.com/giongto35/cloud-game/config"
"github.com/giongto35/cloud-game/handler"
"github.com/giongto35/cloud-game/overlord"
"github.com/giongto35/cloud-game/worker"
"github.com/gorilla/websocket"
)
@ -60,7 +60,7 @@ func initializeWorker() {
log.Println("Run as a single server")
}
handler := handler.NewHandler(conn, *config.IsDebug, gamePath)
handler := worker.NewHandler(conn, *config.IsDebug, gamePath)
handler.Run()

View file

@ -11,7 +11,7 @@ type BrowserClient struct {
*cws.Client
}
// RouteBrowser are all routes server received from browser
// RouteBrowser are all routes server accepts for browser
func (s *Session) RouteBrowser() {
iceCandidates := [][]byte{}
@ -23,6 +23,7 @@ func (s *Session) RouteBrowser() {
browserClient.Receive("icecandidate", func(resp cws.WSPacket) cws.WSPacket {
log.Println("Received candidates ", resp.Data)
iceCandidates = append(iceCandidates, []byte(resp.Data))
return cws.EmptyPacket
})
@ -30,6 +31,7 @@ func (s *Session) RouteBrowser() {
browserClient.Receive("initwebrtc", func(resp cws.WSPacket) cws.WSPacket {
log.Println("Overlord: Received a sdp request from a browser")
log.Println("Overlord: Relay sdp request from a browser to worker")
// relay SDP to target worker and get back SDP of the worker
// TODO: Async
log.Println("Overlord: serverID: ", s.ServerID)
@ -42,16 +44,9 @@ func (s *Session) RouteBrowser() {
browserClient.Receive("quit", func(resp cws.WSPacket) (req cws.WSPacket) {
log.Println("Overlord: Received a relay quit request from a browser")
//s.GameName = resp.Data
//s.RoomID = resp.RoomID
//s.PlayerIndex = resp.PlayerIndex
//room := s.handler.getRoom(s.RoomID)
//if room.IsPCInRoom(s.peerconnection) {
//s.handler.detachPeerConn(s.peerconnection)
//}
log.Println("Sending to target host", s.ServerID, " ", resp)
log.Println("Overlord: Relay quit request from a browser to worker")
// TODO: Async
resp = s.handler.servers[s.ServerID].SyncSend(
resp,
)
@ -61,10 +56,7 @@ func (s *Session) RouteBrowser() {
browserClient.Receive("start", func(resp cws.WSPacket) cws.WSPacket {
log.Println("Overlord: Received a relay start request from a browser")
// TODO: Abstract
// TODO: if resp.TargetHostID != ""c:w {
// relay start to target host
log.Println("Sending to target host", s.ServerID, " ", resp)
log.Println("Overlord: Relay start request from a browser to worker")
// TODO: Async
resp = s.handler.servers[s.ServerID].SyncSend(
resp,
@ -73,23 +65,6 @@ func (s *Session) RouteBrowser() {
return resp
})
//browserClient.Receive("initwebrtc", func(resp cws.WSPacket) cws.WSPacket {
//log.Println("Received user SDP")
//localSession, err := s.peerconnection.StartClient(resp.Data, iceCandidates, config.Width, config.Height)
//if err != nil {
//if err != nil {
//log.Println("Error: Cannot create new webrtc session", err)
//return cws.EmptyPacket
//}
//}
//return cws.WSPacket{
//ID: "sdp",
//Data: localSession,
//SessionID: s.ID,
//}
//})
// TODO: Add save and load
//browserClient.Receive("save", func(resp cws.WSPacket) (req cws.WSPacket) {
//log.Println("Saving game state")

View file

@ -7,7 +7,6 @@ import (
"log"
"math/rand"
"net/http"
"strconv"
"github.com/giongto35/cloud-game/cws"
"github.com/giongto35/cloud-game/overlord/gamelist"
@ -41,12 +40,7 @@ func NewServer() *Server {
// GetWeb returns web frontend
func (o *Server) GetWeb(w http.ResponseWriter, r *http.Request) {
indexFN := ""
//if h.isDebug {
//indexFN = debugIndex
//} else {
indexFN = gameboyIndex
//}
indexFN := gameboyIndex
bs, err := ioutil.ReadFile(indexFN)
if err != nil {
@ -55,7 +49,7 @@ func (o *Server) GetWeb(w http.ResponseWriter, r *http.Request) {
w.Write(bs)
}
// If it's overlord, handle overlord connection (from host to overlord)
// WSO handles all connections from a new worker to overlord
func (o *Server) WSO(w http.ResponseWriter, r *http.Request) {
fmt.Println("Connected")
c, err := upgrader.Upgrade(w, r, nil)
@ -64,7 +58,7 @@ func (o *Server) WSO(w http.ResponseWriter, r *http.Request) {
return
}
// Register new server
serverID := strconv.Itoa(rand.Int())
serverID := uuid.Must(uuid.NewV4()).String()
log.Println("Overlord: A new server connected to Overlord", serverID)
// Register to servers map the client connection
@ -100,9 +94,11 @@ func (o *Server) WSO(w http.ResponseWriter, r *http.Request) {
Data: o.roomToServer[resp.Data],
}
})
client.Listen()
}
// WSO handles all connections from frontend to overlord
func (o *Server) WS(w http.ResponseWriter, r *http.Request) {
log.Println("Browser connected to overlord")
//TODO: Add it back
@ -145,6 +141,7 @@ func (o *Server) WS(w http.ResponseWriter, r *http.Request) {
wssession.BrowserClient.Listen()
}
// findBestServer returns the best server for a session
func (o *Server) findBestServer() (string, error) {
// TODO: Find best Server by latency, currently return by ping
if len(o.servers) == 0 {

View file

@ -35,40 +35,24 @@ func (s *Session) RouteWorker() {
return cws.EmptyPacket
})
workerClient.Receive("quit", func(resp cws.WSPacket) (req cws.WSPacket) {
log.Println("Received quit", req)
s.GameName = resp.Data
s.RoomID = resp.RoomID
s.PlayerIndex = resp.PlayerIndex
//workerClient.Receive("quit", func(resp cws.WSPacket) (req cws.WSPacket) {
//log.Println("Overlord: Received quit request from a worker")
//log.Println("Overlord: Sending back sdp to browser")
//s.GameName = resp.Data
//s.RoomID = resp.RoomID
//s.PlayerIndex = resp.PlayerIndex
// TODO:
//room := s.handler.getRoom(s.RoomID)
//if room.IsPCInRoom(s.peerconnection) {
//s.handler.detachPeerConn(s.peerconnection)
//}
log.Println("Sending to target host", resp.TargetHostID, " ", resp)
resp = s.handler.servers[resp.TargetHostID].SyncSend(
resp,
)
//// TODO:
////room := s.handler.getRoom(s.RoomID)
////if room.IsPCInRoom(s.peerconnection) {
////s.handler.detachPeerConn(s.peerconnection)
////}
//log.Println("Sending to target host", resp.TargetHostID, " ", resp)
//resp = s.handler.servers[resp.TargetHostID].SyncSend(
//resp,
//)
return cws.EmptyPacket
})
//browserClient.Receive("initwebrtc", func(resp cws.WSPacket) cws.WSPacket {
//log.Println("Received user SDP")
//localSession, err := s.peerconnection.StartClient(resp.Data, iceCandidates, config.Width, config.Height)
//if err != nil {
//if err != nil {
//log.Println("Error: Cannot create new webrtc session", err)
//return cws.EmptyPacket
//}
//}
//return cws.WSPacket{
//ID: "sdp",
//Data: localSession,
//SessionID: s.ID,
//}
//})
// TODO: Add save and load

View file

@ -1,13 +1,11 @@
package handler
package worker
import (
"io/ioutil"
"log"
"net/http"
storage "github.com/giongto35/cloud-game/handler/cloud-storage"
"github.com/giongto35/cloud-game/handler/room"
"github.com/giongto35/cloud-game/webrtc"
storage "github.com/giongto35/cloud-game/worker/cloud-storage"
"github.com/giongto35/cloud-game/worker/room"
"github.com/gorilla/websocket"
)
@ -26,13 +24,8 @@ type Handler struct {
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
// sessions handles all sessions server is handler (key is sessionID)
@ -42,21 +35,18 @@ type Handler struct {
// NewHandler returns a new server
func NewHandler(overlordConn *websocket.Conn, isDebug bool, gamePath string) *Handler {
onlineStorage := storage.NewInitClient()
oClient := NewOverlordClient(overlordConn)
return &Handler{
oClient: oClient,
rooms: map[string]*room.Room{},
peerconnections: map[string]*webrtc.WebRTC{},
sessions: map[string]*Session{},
//isDebug: isDebug,
gamePath: gamePath,
oClient: oClient,
rooms: map[string]*room.Room{},
sessions: map[string]*Session{},
gamePath: gamePath,
onlineStorage: onlineStorage,
}
}
// Run starts a Handler running logic
func (h *Handler) Run() {
go h.oClient.Heartbeat()
@ -64,23 +54,7 @@ func (h *Handler) Run() {
h.oClient.Listen()
}
// 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)
}
// Detach peerconnection detach/remove a peerconnection from current room
// detachPeerConn detach/remove a peerconnection from current room
func (h *Handler) detachPeerConn(pc *webrtc.WebRTC) {
log.Println("Detach peerconnection")
roomID := pc.RoomID

View file

@ -1,12 +1,12 @@
package handler
package worker
import (
"log"
"github.com/giongto35/cloud-game/config"
"github.com/giongto35/cloud-game/cws"
"github.com/giongto35/cloud-game/handler/room"
"github.com/giongto35/cloud-game/webrtc"
"github.com/giongto35/cloud-game/worker/room"
"github.com/gorilla/websocket"
)

View file

@ -10,8 +10,8 @@ import (
"sync"
emulator "github.com/giongto35/cloud-game/emulator"
storage "github.com/giongto35/cloud-game/handler/cloud-storage"
"github.com/giongto35/cloud-game/webrtc"
storage "github.com/giongto35/cloud-game/worker/cloud-storage"
)
// Room is a game session. multi webRTC sessions can connect to a same game.

View file

@ -1,4 +1,4 @@
package handler
package worker
import "github.com/giongto35/cloud-game/webrtc"
@ -7,16 +7,9 @@ import "github.com/giongto35/cloud-game/webrtc"
// connection to browser is 1-1. connection to overlord is n - 1
// Peerconnection can be from other server to ensure better latency
type Session struct {
ID string
//BrowserClient *BrowserClient
//OverlordClient *OverlordClient
ID string
peerconnection *webrtc.WebRTC
// TODO: Decouple this
//handler *Handler
//ServerID string
//GameName string
// Should I make direct reference
RoomID string
//PlayerIndex int
}