123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- // Client handler
- package wsrpc
- import (
- "sync"
- "github.com/google/uuid"
- "golang.org/x/net/websocket"
- )
- // Call object
- type CallObj struct {
- OP string `json:"op"` // operation
- ID string `json:"id"` // Id of the call
- Method string `json:"method"` // could be param 0 instead?
- Params []interface{} `json:"params"`
- Response interface{} `json:"response"`
- }
- // 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 WsRPC client handler
- func NewHandler(id string, ws *websocket.Conn) *ClientCtx {
- var c = ClientCtx{
- WS: ws,
- listeners: map[string]ListenerFunc{},
- requests: map[string]chan interface{}{},
- }
- return &c
- }
- // Process messages
- func (c *ClientCtx) Process(data CallObj) {
- switch data.OP {
- case "call":
- params := data.Params
- var idn = data.Method
- var reqId = data.ID
- var fn, ok = c.listeners[idn]
- if !ok {
- return
- }
- go func() {
- ret := fn(params...)
- var responseObj = CallObj{
- OP: "response",
- ID: reqId,
- Response: ret,
- }
- //log.Println("Sending response")
- websocket.JSON.Send(c.WS, responseObj)
- }()
- case "response":
- c.locker.Lock()
- mchan, ok := c.requests[data.ID]
- delete(c.requests, data.ID)
- c.locker.Unlock()
- if ok {
- mchan <- data.Response
- }
- }
- }
- // Call a client method and estabilishes a request id
- func (c *ClientCtx) Call(method string, params ...interface{}) interface{} {
- u := uuid.New()
- uuidStr := u.String()
- var callObj = CallObj{
- OP: "call",
- ID: uuidStr,
- Method: method,
- Params: params,
- }
- res := make(chan interface{}, 1)
- c.locker.Lock()
- c.requests[uuidStr] = res
- c.locker.Unlock()
- websocket.JSON.Send(c.WS, &callObj)
- return <-res // Block until value
- }
- //On add a event listener on browser
- func (c *ClientCtx) Define(name string, listener ListenerFunc) {
- c.listeners[name] = listener
- }
|