123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- // Client handler
- package wsrpc
- import (
- "sync"
- "github.com/google/uuid"
- "golang.org/x/net/websocket"
- )
- // DataObj common structure for dymanic json object
- type DataObj map[string]interface{}
- // ListenerFunc function type to handle browser events
- type ListenerFunc func(...interface{}) interface{}
- // Request request type for handling requests channels
- // ClientCtx main client struct
- type ClientCtx struct {
- locker sync.Mutex
- WS *websocket.Conn
- // stuff
- listeners map[string]ListenerFunc
- requests map[string]chan interface{}
- }
- //NewHandler creates a new handler
- func NewHandler(id string, ws *websocket.Conn) *ClientCtx {
- var c = ClientCtx{}
- c.WS = ws
- c.listeners = map[string]ListenerFunc{}
- c.requests = map[string]chan interface{}{}
- return &c
- }
- // Process messages
- func (c *ClientCtx) Process(data DataObj) {
- if data["op"].(string) == "call" {
- params := data["param"].([]interface{})
- var idn = data["method"].(string)
- var reqId = data["reqId"].(string)
- var fn, ok = c.listeners[idn]
- if !ok {
- return
- }
- go func() {
- ret := fn(params...)
- var responseObj = DataObj{
- "op": "response",
- "reqId": reqId,
- "data": ret,
- }
- //log.Println("Sending response")
- websocket.JSON.Send(c.WS, responseObj)
- }()
- }
- if data["op"].(string) == "response" {
- c.locker.Lock()
- mchan, ok := c.requests[data["reqId"].(string)]
- delete(c.requests, data["reqId"].(string))
- c.locker.Unlock()
- if ok {
- mchan <- data["data"]
- }
- }
- }
- // Call a client method and estabilishes a request id
- func (c *ClientCtx) Call(method string, params ...interface{}) chan interface{} {
- u := uuid.New()
- uuidStr := u.String()
- var callObj = DataObj{
- "op": "call",
- "reqId": uuidStr,
- "method": method,
- "param": params,
- }
- res := make(chan interface{}, 1)
- c.locker.Lock()
- c.requests[uuidStr] = res
- c.locker.Unlock()
- websocket.JSON.Send(c.WS, &callObj)
- return res
- }
- //Emit emit event listener
- /*func (c *ClientCtx) Emit(name string, data DataObj) (interface{}, error) {
- fn, ok := c.listeners[name]
- if !ok {
- return nil, fmt.Errorf("Not found") // Dont execute
- }
- return fn(data), nil
- }*/
- //On add a event listener on browser
- func (c *ClientCtx) Define(name string, listener ListenerFunc) {
- c.listeners[name] = listener
- }
|