// 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 }