SDP Exchanging

This commit is contained in:
giongto35 2019-04-20 15:25:11 +08:00
parent 73a6a0fe61
commit 80ca5bdd97
4 changed files with 163 additions and 27 deletions

95
main.go
View file

@ -168,9 +168,10 @@ func startSession(webRTC *webrtc.WebRTC, gameName string, roomID string, playerI
// Session represents a session connected from the browser to the current server
type Session struct {
client *Client
oclient *Client
ServerID string
client *Client
oclient *Client
peerconnection *webrtc.WebRTC
ServerID string
}
// Handle normal traffic (from browser to host)
@ -186,10 +187,11 @@ func ws(w http.ResponseWriter, r *http.Request) {
var playerIndex int
// Create connection to overlord
client := NewClient(c, webrtc.NewWebRTC())
client := NewClient(c)
wssession := &Session{
client: client,
client: client,
peerconnection: webrtc.NewWebRTC(),
// The server session is maintaining
}
@ -199,7 +201,7 @@ func ws(w http.ResponseWriter, r *http.Request) {
client.receive("initwebrtc", func(resp WSPacket) WSPacket {
log.Println("Received user SDP")
localSession, err := client.peerconnection.StartClient(resp.Data, width, height)
localSession, err := wssession.peerconnection.StartClient(resp.Data, width, height)
if err != nil {
log.Fatalln(err)
}
@ -252,15 +254,15 @@ func ws(w http.ResponseWriter, r *http.Request) {
//log.Println("Ping from server with game:", gameName)
//res.ID = "pong"
log.Println("Starting game")
roomServerID := GetServerIDOfRoom(wssession.oclient, roomID)
roomServerID := getServerIDOfRoom(wssession.oclient, roomID)
log.Println("Server of RoomID ", roomID, " is ", roomServerID)
if roomServerID != "" && wssession.ServerID != roomServerID {
// TODO: Re -register
bridgeConnection(wssession, roomServerID)
go bridgeConnection(wssession, roomServerID, gameName, roomID, playerIndex)
return
}
roomID, isNewRoom = startSession(client.peerconnection, gameName, roomID, playerIndex)
roomID, isNewRoom = startSession(wssession.peerconnection, gameName, roomID, playerIndex)
if isNewRoom {
wssession.oclient.send(WSPacket{
ID: "registerRoom",
@ -383,7 +385,7 @@ func removeSession(w *webrtc.WebRTC, room *Room) {
}
}
func GetServerIDOfRoom(oc *Client, roomID string) string {
func getServerIDOfRoom(oc *Client, roomID string) string {
packet := oc.syncSend(
WSPacket{
ID: "getRoom",
@ -394,8 +396,37 @@ func GetServerIDOfRoom(oc *Client, roomID string) string {
return packet.Data
}
func bridgeConnection(session *Session, serverID string) {
func bridgeConnection(session *Session, serverID string, gameName string, roomID string, playerIndex int) {
log.Println("Bridging connection to other Host ", serverID)
client := session.client
oclient := session.oclient
// Ask client to init
log.Println("Requesting offer to browser", serverID)
resp := client.syncSend(WSPacket{
ID: "requestOffer",
Data: "",
})
log.Println("Sending offer to overlord to relay message to target host", resp.TargetHostID)
// Ask overlord to relay SDP packet to serverID
resp.TargetHostID = serverID
remoteTargetSDP := oclient.syncSend(resp)
log.Println("Got back remote host SDP, sending to browser", remoteTargetSDP.Data)
// Send back remote SDP of remote server to browser
client.syncSend(WSPacket{
ID: "sdp",
Data: remoteTargetSDP.Data,
})
log.Println("Init session done, start game on target host")
oclient.syncSend(WSPacket{
ID: "start",
Data: gameName,
RoomID: roomID,
PlayerIndex: playerIndex,
})
log.Println("Game is started on remote host")
}
const overlordHost = "ws://localhost:9000/wso"
@ -415,7 +446,7 @@ func (s *Session) NewOverlordClient() {
if err != nil {
log.Println("Cannot connect to overlord")
}
oclient := NewClient(oc, webrtc.NewWebRTC())
oclient := NewClient(oc)
oclient.send(
WSPacket{
ID: "ping",
@ -437,6 +468,46 @@ func (s *Session) NewOverlordClient() {
},
)
// Received from overlord the sdp. This is happens when bridging
// TODO: refactor
oclient.receive(
"initwebrtc",
func(resp WSPacket) (req WSPacket) {
log.Println("Received a sdp request from overlord")
log.Println("Start peerconnection from the sdp")
localSession, err := s.peerconnection.StartClient(resp.Data, width, height)
if err != nil {
log.Fatalln(err)
}
return WSPacket{
ID: "sdp",
Data: localSession,
}
},
)
// Received start from overlord. This is happens when bridging
// TODO: refactor
oclient.receive(
"start",
func(resp WSPacket) (req WSPacket) {
log.Println("Received a start request from overlord")
log.Println("Add the connection to current room on the host")
roomID, isNewRoom := startSession(s.peerconnection, resp.Data, resp.RoomID, resp.PlayerIndex)
// Bridge always access to old room
// TODO: log warn
if isNewRoom == true {
log.Fatal("Bridge should not spawn new room")
}
req.ID = "start"
req.RoomID = roomID
return req
},
)
go oclient.listen()
s.oclient = oclient

View file

@ -13,7 +13,7 @@ import (
var roomToServer = map[string]string{}
// servers are the map serverID to server Client
var servers = map[string]Client{}
var servers = map[string]*Client{}
// If it's overlord, handle overlord connection (from host to overlord)
func wso(w http.ResponseWriter, r *http.Request) {
@ -29,7 +29,14 @@ func wso(w http.ResponseWriter, r *http.Request) {
serverID := strconv.Itoa(rand.Int())
log.Println("A new server connected ", serverID)
client := NewClient(c, webrtc.NewWebRTC())
client := NewClient(c)
servers[serverID] = client
wssession := &Session{
client: client,
peerconnection: webrtc.NewWebRTC(),
// The server session is maintaining
}
client.send(
WSPacket{
@ -61,5 +68,62 @@ func wso(w http.ResponseWriter, r *http.Request) {
}
})
client.receive("initwebrtc", func(resp WSPacket) WSPacket {
log.Println("Received a relay sdp request from a host")
// TODO: Abstract
if resp.TargetHostID != serverID {
log.Println("sending relay sdp to target host", resp.TargetHostID)
// relay SDP to target host and get back sdp
// TODO: Async
sdp := servers[resp.TargetHostID].syncSend(
resp,
)
return sdp
}
log.Println("Target host is overlord itself: start peerconnection")
// If the target is in master
// start by its old
localSession, err := wssession.peerconnection.StartClient(resp.Data, width, height)
if err != nil {
log.Fatalln(err)
}
return WSPacket{
ID: "sdp",
Data: localSession,
}
})
// TODO: use relay ID type
// TODO: Merge sdp and start
client.receive("start", func(resp WSPacket) WSPacket {
log.Println("Received a relay start request from a host")
// TODO: Abstract
if resp.TargetHostID != serverID {
// relay SDP to target host and get back sdp
// TODO: Async
resp := servers[resp.TargetHostID].syncSend(
resp,
)
return resp
}
log.Println("Target host is overlord itself: start game")
// If the target is in master
// start by its old
roomID, isNewRoom := startSession(wssession.peerconnection, resp.Data, resp.RoomID, resp.PlayerIndex)
// Bridge always access to old room
// TODO: log warn
if isNewRoom == true {
log.Fatal("Bridge should not spawn new room")
}
return WSPacket{
ID: "start",
RoomID: roomID,
}
})
client.listen()
}

12
static/js/ws.js vendored
View file

@ -1,4 +1,5 @@
var pc;
var curPacketID = "";
// web socket
conn = new WebSocket(`ws://${location.host}/ws`);
@ -27,10 +28,10 @@ conn.onmessage = e => {
log("Got remote sdp");
pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(d["data"]))));
break;
//case "requestOffer":
//pc.createOffer({offerToReceiveVideo: true, offerToReceiveAudio: false}).then(d => {
//pc.setLocalDescription(d).catch(log);
//})
case "requestOffer":
curPacketID = d["packet_id"];
log("Received request offer ", curPacketID)
startWebRTC();
//case "sdpremote":
//log("Got remote sdp");
@ -108,7 +109,8 @@ function startWebRTC() {
session = btoa(JSON.stringify(pc.localDescription));
localSessionDescription = session;
log("Send SDP to remote peer");
conn.send(JSON.stringify({"id": "initwebrtc", "data": session}));
// TODO: Fix curPacketID
conn.send(JSON.stringify({"id": "initwebrtc", "data": session, "packet_id": curPacketID}));
} else {
console.log(JSON.stringify(event.candidate));
}

15
ws.go
View file

@ -7,15 +7,12 @@ import (
"strconv"
"time"
"github.com/giongto35/cloud-game/webrtc"
"github.com/gorilla/websocket"
)
type Client struct {
conn *websocket.Conn
peerconnection *webrtc.WebRTC
// sendCallback is callback based on packetID
sendCallback map[string]func(req WSPacket)
// recvCallback is callback when receive based on ID of the packet
@ -30,20 +27,19 @@ type WSPacket struct {
PlayerIndex int `json:"player_index"`
TargetHostID string `json:"target_id"`
PacketID string
PacketID string `json:"packet_id"`
}
var EmptyPacket = WSPacket{}
func NewClient(conn *websocket.Conn, webrtc *webrtc.WebRTC) *Client {
func NewClient(conn *websocket.Conn) *Client {
sendCallback := map[string]func(WSPacket){}
recvCallback := map[string]func(WSPacket){}
return &Client{
conn: conn,
peerconnection: webrtc,
sendCallback: sendCallback,
recvCallback: recvCallback,
sendCallback: sendCallback,
recvCallback: recvCallback,
}
}
@ -94,6 +90,7 @@ func (c *Client) syncSend(request WSPacket) (response WSPacket) {
func (c *Client) listen() {
for {
log.Println("Waiting for message")
_, rawMsg, err := c.conn.ReadMessage()
if err != nil {
log.Println("[!] read:", err)
@ -109,6 +106,8 @@ func (c *Client) listen() {
if callback, ok := c.sendCallback[wspacket.PacketID]; ok {
callback(wspacket)
delete(c.sendCallback, wspacket.PacketID)
// Skip receiveCallback to avoid duplication
continue
}
// Check if some receiver with the ID is registered
if callback, ok := c.recvCallback[wspacket.ID]; ok {