clientctx.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Client handler
  2. package wsrpc
  3. import (
  4. "sync"
  5. "github.com/google/uuid"
  6. "golang.org/x/net/websocket"
  7. )
  8. // DataObj common structure for dymanic json object
  9. type DataObj map[string]interface{}
  10. // ListenerFunc function type to handle browser events
  11. type ListenerFunc func(...interface{}) interface{}
  12. // Request request type for handling requests channels
  13. // ClientCtx main client struct
  14. type ClientCtx struct {
  15. locker sync.Mutex
  16. WS *websocket.Conn
  17. // stuff
  18. listeners map[string]ListenerFunc
  19. requests map[string]chan interface{}
  20. }
  21. //NewHandler creates a new handler
  22. func NewHandler(id string, ws *websocket.Conn) *ClientCtx {
  23. var c = ClientCtx{}
  24. c.WS = ws
  25. c.listeners = map[string]ListenerFunc{}
  26. c.requests = map[string]chan interface{}{}
  27. return &c
  28. }
  29. // Process messages
  30. func (c *ClientCtx) Process(data DataObj) {
  31. if data["op"].(string) == "call" {
  32. params := data["param"].([]interface{})
  33. var idn = data["method"].(string)
  34. var reqId = data["reqId"].(string)
  35. var fn, ok = c.listeners[idn]
  36. if !ok {
  37. return
  38. }
  39. go func() {
  40. ret := fn(params...)
  41. var responseObj = DataObj{
  42. "op": "response",
  43. "reqId": reqId,
  44. "data": ret,
  45. }
  46. //log.Println("Sending response")
  47. websocket.JSON.Send(c.WS, responseObj)
  48. }()
  49. }
  50. if data["op"].(string) == "response" {
  51. c.locker.Lock()
  52. mchan, ok := c.requests[data["reqId"].(string)]
  53. delete(c.requests, data["reqId"].(string))
  54. c.locker.Unlock()
  55. if ok {
  56. mchan <- data["data"]
  57. }
  58. }
  59. }
  60. // Call a client method and estabilishes a request id
  61. func (c *ClientCtx) Call(method string, params ...interface{}) chan interface{} {
  62. u := uuid.New()
  63. uuidStr := u.String()
  64. var callObj = DataObj{
  65. "op": "call",
  66. "reqId": uuidStr,
  67. "method": method,
  68. "param": params,
  69. }
  70. res := make(chan interface{}, 1)
  71. c.locker.Lock()
  72. c.requests[uuidStr] = res
  73. c.locker.Unlock()
  74. websocket.JSON.Send(c.WS, &callObj)
  75. return res
  76. }
  77. //Emit emit event listener
  78. /*func (c *ClientCtx) Emit(name string, data DataObj) (interface{}, error) {
  79. fn, ok := c.listeners[name]
  80. if !ok {
  81. return nil, fmt.Errorf("Not found") // Dont execute
  82. }
  83. return fn(data), nil
  84. }*/
  85. //On add a event listener on browser
  86. func (c *ClientCtx) Define(name string, listener ListenerFunc) {
  87. c.listeners[name] = listener
  88. }