package main import ( "errors" "flag" "fmt" "log" "net/http" "strconv" "time" //wss "git.alfi.li/gamelang/frontend/wsserver" ) type ExampleConfig struct { Http struct { Listen string // ip:port } Kafka struct { Enabled bool UserManagerBroker string WorldManagerBroker string } } func DefaultConfig() ExampleConfig { config := ExampleConfig{} config.Http.Listen = "0.0.0.0:8080" config.Kafka.Enabled = false return config } type WebRTCPeer struct { id int ws *WSPeer } type exampleWSServer struct { wsserver *WSServer peers map[int]*WebRTCPeer removeChan *chan *WSPeer } func NewexampleWSServer(removechan *chan *WSPeer, wsserver *WSServer) *exampleWSServer { peers := map[int]*WebRTCPeer{} ewss := exampleWSServer{wsserver: wsserver, peers: peers, removeChan: removechan} go ewss.Housekeeping() //wss := exampleWSServer{upgrader: &upgrader, peers: map[uuid.UUID]*WSPeer{}, removeChan: removechan} return &ewss } func (ewss *exampleWSServer) broadcast(msg WSMsg) { for _, peer := range ewss.peers { go peer.ws.Answer(msg) } } func (ewss *exampleWSServer) register(peer *WSPeer) *WebRTCPeer { fmt.Println("finding id") id := 1 _, ok := ewss.peers[1] if ok { log.Printf("id 1 exists, wspeers connected: %i, webrtcpeers: %i\n", ewss.wsserver.GetPeercount(), len(ewss.peers)) if ewss.wsserver.GetPeercount() > 1 { id = 2 for i := 2; i <= len(ewss.peers)+1; i++ { _, ok := ewss.peers[i] if !ok { id = i fmt.Println("free id", id) break } else { fmt.Println("peer exists", i) } } } } log.Println("registering peer", id) wrtcPeer, ok := ewss.peers[id] if ok { wrtcPeer.ws = peer } else { wrtcPeer = &WebRTCPeer{id: id, ws: peer} ewss.peers[id] = wrtcPeer } msg := WSMsg{ID: id, Mtype: "I", Payload: strconv.Itoa(id)} peer.Answer(msg) return wrtcPeer } func (ewss *exampleWSServer) unregister(peer *WebRTCPeer) { if peer == nil { log.Print("peer pointer already gone") return } _, ok := ewss.peers[peer.id] if !ok { log.Print("peer already gone") return } delete(ewss.peers, peer.id) log.Println("removed peer: ", peer.id) if peer.id == 1 { go ewss.reassign_id1() } msg := WSMsg{ID: peer.id, Mtype: "D"} ewss.broadcast(msg) } func (ewss *exampleWSServer) reassign_id1() { for peerID, peer := range ewss.peers { if peerID == 1 { break } ewss.unregister(peer) ewss.register(peer.ws) break } } func (ewss *exampleWSServer) Housekeeping() { removechan := ewss.removeChan for { // TODO: why is removechan nil if removechan == nil { time.Sleep(time.Second) continue } wspeer := <-*removechan ewss.unregister(ewss.getWebRTCPeerFromWSPeer(wspeer)) /* select { case wspeer := <-*ewss.removeChan: ewss.unregister(ewss.getWebRTCPeerFromWSPeer(wspeer)) //case <-time.After(3 * time.Second): } */ } } func (ewss exampleWSServer) getWebRTCPeerFromWSPeer(wspeer *WSPeer) *WebRTCPeer { for _, webRTCPeer := range ewss.peers { if wspeer.uuid == webRTCPeer.ws.uuid { return webRTCPeer } } return nil } func (ewss exampleWSServer) RenderHandler() []Handler { handler := []Handler{} handler = append(handler, Handler{MType: "echo", Callback: func(msg WSMsg, peer *WSPeer) error { log.Printf("echo from \"%s\"", peer.uuid.String()) remsg := WSMsg{Mtype: "echo", Payload: msg.Payload} peer.Answer(remsg) return nil }}) handler = append(handler, Handler{MType: "J", Callback: func(msg WSMsg, peer *WSPeer) error { peer.Answer(WSMsg{Mtype: "J", Payload: "default"}) log.Printf("join from \"%s\"", peer.uuid.String()) webRTCPeer := ewss.register(peer) for otherPeerID, _ := range ewss.peers { if otherPeerID == webRTCPeer.id { continue } go ewss.peers[otherPeerID].ws.Answer(WSMsg{Mtype: "N", Payload: strconv.Itoa(webRTCPeer.id)}) go peer.Answer(WSMsg{Mtype: "N", Payload: strconv.Itoa(otherPeerID)}) } return nil }}) handler = append(handler, Handler{MType: "O", Callback: func(msg WSMsg, peer *WSPeer) error { log.Printf("offer from \"%s\" for \"%d\"", peer.uuid.String(), msg.ID) otherPeer, ok := ewss.peers[msg.ID] if !ok { return errors.New(fmt.Sprintf("Peer with id \"%d\" not found", msg.ID)) } otherPeer.ws.Answer(WSMsg{Mtype: "O", Payload: msg.Payload, ID: ewss.getWebRTCPeerFromWSPeer(peer).id}) return nil }}) handler = append(handler, Handler{MType: "A", Callback: func(msg WSMsg, peer *WSPeer) error { log.Printf("answer from \"%s\"", peer.uuid.String()) otherPeer := ewss.peers[msg.ID] otherPeer.ws.Answer(WSMsg{Mtype: "A", Payload: msg.Payload, ID: ewss.getWebRTCPeerFromWSPeer(peer).id}) return nil }}) handler = append(handler, Handler{MType: "C", Callback: func(msg WSMsg, peer *WSPeer) error { log.Printf("candidate from \"%s\"", peer.uuid.String()) otherPeer := ewss.peers[msg.ID] otherPeer.ws.Answer(WSMsg{Mtype: "C", Payload: msg.Payload, ID: ewss.getWebRTCPeerFromWSPeer(peer).id}) return nil }}) return handler } func main() { wsPtr := flag.String("ws", ":8080", "websocket listen port") wssPtr := flag.String("wss", ":8443", "wesocker secure listen port") certPtr := flag.String("cert", "", "wesocker secure server certificate") keyPtr := flag.String("key", "", "wesocker secure server key") flag.Parse() removeChan := make(chan *WSPeer, 10) wsserver := NewWSServer(&removeChan) ewss := NewexampleWSServer(&removeChan, wsserver) ewss.wsserver.RegisterHandler(ewss.RenderHandler()) http.HandleFunc("/play", ewss.wsserver.WebsocketHandler) log.Println("websocket listening on", *wsPtr) go http.ListenAndServe(*wsPtr, nil) log.Println("websocket listening on", *wssPtr) err := http.ListenAndServeTLS(*wssPtr, *certPtr, *keyPtr, nil) if err != nil { fmt.Println(err.Error()) } }