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.

226 lines
5.2 KiB

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