123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- package main
- import (
- "encoding/json"
- "flag"
- "fmt"
- "log"
- "net/http"
- "github.com/google/uuid"
- "github.com/gorilla/websocket"
- )
- var wsaddr = flag.String("wsaddr", "localhost:12345", "websocket service address")
- type WSMsg struct {
- Mtype string `json:"mtype"`
- ID int `json:"id,omitempty"`
- Payload string `json:"payload,string"`
- }
- type Handler struct {
- MType string
- Callback func(WSMsg, *WSPeer) error
- }
- type WSServer struct {
- upgrader *websocket.Upgrader
- handler map[string]func(WSMsg, *WSPeer) error
- peers map[uuid.UUID]*WSPeer
- }
- func NewWSServer() *WSServer {
- upgrader := websocket.Upgrader{} // use default options
- upgrader.CheckOrigin = func(r *http.Request) bool { return true } // cors-origin '*'
- wss := WSServer{upgrader: &upgrader, peers: map[uuid.UUID]*WSPeer{}}
- return &wss
- }
- func (wss *WSServer) Write(name string, sendMsg WSMsg) {
- peers := wss.GetPeers(name)
- if len(peers) == 0 {
- log.Println("WSServer:Write - no sendChans for", name)
- return
- }
- for _, peer := range peers {
- peer.Answer(sendMsg)
- }
- }
- func (wss *WSServer) GetPeers(searchname string) []*WSPeer {
- cons := []*WSPeer{}
- for key, con := range wss.peers {
- username := key.String()
- if username == searchname {
- cons = append(cons, con)
- }
- }
- return cons
- }
- func (wss *WSServer) CleanPeer(name uuid.UUID) {
- delete(wss.peers, name)
- }
- func (wss *WSServer) RegisterHandler(handlers []Handler) {
- if wss.handler == nil {
- wss.handler = map[string]func(WSMsg, *WSPeer) error{}
- }
- for _, handler := range handlers {
- log.Println("Registrering handler for MType: ", handler.MType)
- wss.handler[handler.MType] = handler.Callback
- }
- }
- type WSPeer struct {
- uuid uuid.UUID
- conn *websocket.Conn
- answers *chan WSMsg
- }
- func (peer *WSPeer) WorkAnswers() {
- for {
- msg := WSMsg{}
- msg = <-*peer.answers
- fmt.Println("sending on: ", peer.uuid)
- peer._answer(msg)
- }
- }
- func (peer *WSPeer) Answer(msg WSMsg) {
- if peer.answers == nil {
- fmt.Println("empty chan for :", peer.uuid)
- }
- *peer.answers <- msg
- }
- func (peer *WSPeer) _answer(msg WSMsg) error {
- log.Println("sending message: ", msg)
- jsonMsg, err := json.Marshal(msg)
- if err != nil {
- log.Printf("write: err marshalling \"%s\"\n%s", msg, err.Error())
- return err
- }
- err = peer.conn.WriteMessage(websocket.BinaryMessage, jsonMsg)
- if err != nil {
- log.Println("write:", err)
- return err
- }
- return nil
- }
- func (wss WSServer) WebsocketHandler(w http.ResponseWriter, r *http.Request) {
- log.Println("request on /ws from", r.RemoteAddr)
- c, err := wss.upgrader.Upgrade(w, r, nil)
- if err != nil {
- log.Print("upgrade:", err)
- return
- }
- defer c.Close()
- peer := WSPeer{uuid: uuid.New(), conn: c}
- bla := make(chan WSMsg, 10)
- peer.answers = &bla
- go peer.WorkAnswers()
- wss.peers[peer.uuid] = &peer
- for {
- _, message, err := c.ReadMessage()
- if err != nil {
- log.Println("read:", err)
- break
- }
- var rawmsg map[string]interface{}
- err = json.Unmarshal(message, &rawmsg)
- msg := WSMsg{}
- for k, v := range rawmsg {
- switch k {
- case "id":
- id := v.(float64)
- msg.ID = int(id)
- case "mtype":
- msg.Mtype = v.(string)
- case "payload":
- payload, ok := v.(string)
- if !ok {
- payloadmap := v.(map[string]interface{})
- var payloadbyte []byte
- payloadbyte, err = json.Marshal(payloadmap)
- payload = string(payloadbyte)
- }
- msg.Payload = payload
- }
- }
- if err != nil {
- log.Println("error unmarshalling message:", err)
- log.Printf("recv: %s", message)
- return
- }
- handler, ok := wss.handler[msg.Mtype]
- if !ok {
- log.Println("unknown MType", msg.Mtype)
- keys := ""
- for k := range wss.handler {
- keys = fmt.Sprintf("%s\n%s", keys, k)
- }
- log.Println("available MTypes:\n", keys, "----")
- remsg := WSMsg{Mtype: "UNKNOWN", Payload: ""}
- peer.Answer(remsg)
- return
- }
- err = handler(msg, &peer)
- if err != nil {
- log.Println("handler failed", err.Error())
- //writeChan <- msg
- }
- log.Println("message handled")
- }
- }
|