You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
5.1 KiB

  1. package core_client
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/tendermint/tendermint/binary"
  6. rpctypes "github.com/tendermint/tendermint/rpc/types"
  7. // NOTE: do not import rpc/core.
  8. // What kind of client imports all of core logic? :P
  9. "io/ioutil"
  10. "net/http"
  11. "net/url"
  12. //"reflect"
  13. // Uncomment to use go:generate
  14. // _ "github.com/tendermint/go-rpc-gen"
  15. )
  16. // maps camel-case function names to lower case rpc version
  17. var reverseFuncMap = map[string]string{
  18. "Status": "status",
  19. "NetInfo": "net_info",
  20. "BlockchainInfo": "blockchain",
  21. "GetBlock": "get_block",
  22. "GetAccount": "get_account",
  23. "GetStorage": "get_storage",
  24. "Call": "call",
  25. "CallCode": "call_code",
  26. "ListValidators": "list_validators",
  27. "DumpStorage": "dump_storage",
  28. "BroadcastTx": "broadcast_tx",
  29. "ListAccounts": "list_accounts",
  30. "GenPrivAccount": "unsafe/gen_priv_account",
  31. "SignTx": "unsafe/sign_tx",
  32. }
  33. /*
  34. // fill the map from camelcase to lowercase
  35. func fillReverseFuncMap() map[string]string {
  36. fMap := make(map[string]string)
  37. for name, f := range core.Routes {
  38. camelName := runtime.FuncForPC(f.f.Pointer()).Name()
  39. spl := strings.Split(camelName, ".")
  40. if len(spl) > 1 {
  41. camelName = spl[len(spl)-1]
  42. }
  43. fMap[camelName] = name
  44. }
  45. return fMap
  46. }
  47. */
  48. type Response struct {
  49. Status string
  50. Data interface{}
  51. Error string
  52. }
  53. //go:generate go-rpc-gen -interface Client -dir ../core -pkg core -type *ClientHTTP,*ClientJSON -exclude pipe.go -out-pkg core_client
  54. type ClientJSON struct {
  55. addr string
  56. }
  57. type ClientHTTP struct {
  58. addr string
  59. }
  60. func NewClient(addr, typ string) Client {
  61. switch typ {
  62. case "HTTP":
  63. return &ClientHTTP{addr}
  64. case "JSONRPC":
  65. return &ClientJSON{addr}
  66. }
  67. return nil
  68. }
  69. func argsToJson(args ...interface{}) ([]string, error) {
  70. l := len(args)
  71. jsons := make([]string, l)
  72. n, err := new(int64), new(error)
  73. for i, a := range args {
  74. buf := new(bytes.Buffer)
  75. binary.WriteJSON(a, buf, n, err)
  76. if *err != nil {
  77. return nil, *err
  78. }
  79. jsons[i] = string(buf.Bytes())
  80. }
  81. return jsons, nil
  82. }
  83. func (c *ClientJSON) RequestResponse(s rpctypes.RPCRequest) (b []byte, err error) {
  84. b = binary.JSONBytes(s)
  85. buf := bytes.NewBuffer(b)
  86. resp, err := http.Post(c.addr, "text/json", buf)
  87. if err != nil {
  88. return nil, err
  89. }
  90. defer resp.Body.Close()
  91. return ioutil.ReadAll(resp.Body)
  92. }
  93. /*
  94. What follows is used by `rpc-gen` when `go generate` is called
  95. to populate the rpc client methods
  96. */
  97. // first we define the base interface, which rpc-gen will further populate with generated methods
  98. /*rpc-gen:define-interface Client
  99. type Client interface {
  100. Address() string // returns the remote address
  101. }
  102. */
  103. // encoding functions
  104. func binaryWriter(args ...interface{}) ([]interface{}, error) {
  105. list := []interface{}{}
  106. for _, a := range args {
  107. buf, n, err := new(bytes.Buffer), new(int64), new(error)
  108. binary.WriteJSON(a, buf, n, err)
  109. if *err != nil {
  110. return nil, *err
  111. }
  112. list = append(list, buf.Bytes())
  113. }
  114. return list, nil
  115. }
  116. func argsToURLValues(argNames []string, args ...interface{}) (url.Values, error) {
  117. values := make(url.Values)
  118. if len(argNames) == 0 {
  119. return values, nil
  120. }
  121. if len(argNames) != len(args) {
  122. return nil, fmt.Errorf("argNames and args have different lengths: %d, %d", len(argNames), len(args))
  123. }
  124. slice, err := argsToJson(args...)
  125. if err != nil {
  126. return nil, err
  127. }
  128. for i, name := range argNames {
  129. s := slice[i]
  130. values.Set(name, s) // s[0]
  131. /*for j := 1; j < len(s); j++ {
  132. values.Add(name, s[j])
  133. }*/
  134. }
  135. return values, nil
  136. }
  137. // import statements we will need for the templates
  138. /*rpc-gen:imports:
  139. github.com/tendermint/tendermint/binary
  140. rpctypes github.com/tendermint/tendermint/rpc/types
  141. net/http
  142. io/ioutil
  143. fmt
  144. */
  145. // Template functions to be filled in
  146. /*rpc-gen:template:*ClientJSON func (c *ClientJSON) {{name}}({{args.def}}) ({{response}}) {
  147. request := rpctypes.RPCRequest{
  148. JSONRPC: "2.0",
  149. Method: reverseFuncMap["{{name}}"],
  150. Params: []interface{}{ {{args.ident}} },
  151. Id: 0,
  152. }
  153. body, err := c.RequestResponse(request)
  154. if err != nil{
  155. return nil, err
  156. }
  157. var response struct {
  158. Result {{response.0}} `json:"result"`
  159. Error string `json:"error"`
  160. Id string `json:"id"`
  161. JSONRPC string `json:"jsonrpc"`
  162. }
  163. binary.ReadJSON(&response, body, &err)
  164. if err != nil {
  165. return nil, err
  166. }
  167. if response.Error != ""{
  168. return nil, fmt.Errorf(response.Error)
  169. }
  170. return response.Result, nil
  171. }*/
  172. /*rpc-gen:template:*ClientHTTP func (c *ClientHTTP) {{name}}({{args.def}}) ({{response}}){
  173. values, err := argsToURLValues({{args.name}}, {{args.ident}})
  174. if err != nil{
  175. return nil, err
  176. }
  177. resp, err := http.PostForm(c.addr+reverseFuncMap["{{name}}"], values)
  178. if err != nil {
  179. return nil, err
  180. }
  181. defer resp.Body.Close()
  182. body, err := ioutil.ReadAll(resp.Body)
  183. if err != nil {
  184. return nil, err
  185. }
  186. var response struct {
  187. Result {{response.0}} `json:"result"`
  188. Error string `json:"error"`
  189. Id string `json:"id"`
  190. JSONRPC string `json:"jsonrpc"`
  191. }
  192. binary.ReadJSON(&response, body, &err)
  193. if err != nil {
  194. return nil, err
  195. }
  196. if response.Error != ""{
  197. return nil, fmt.Errorf(response.Error)
  198. }
  199. return response.Result, nil
  200. }*/