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.

338 lines
6.8 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package main
  2. import (
  3. "bufio"
  4. "encoding/hex"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "net"
  9. "os"
  10. "strings"
  11. "github.com/codegangsta/cli"
  12. . "github.com/tendermint/go-common"
  13. "github.com/tendermint/tmsp/types"
  14. )
  15. // connection is a global variable so it can be reused by the console
  16. var conn net.Conn
  17. func main() {
  18. app := cli.NewApp()
  19. app.Name = "tmsp-cli"
  20. app.Usage = "tmsp-cli [command] [args...]"
  21. app.Flags = []cli.Flag{
  22. cli.StringFlag{
  23. Name: "address",
  24. Value: "tcp://127.0.0.1:46658",
  25. Usage: "address of application socket",
  26. },
  27. }
  28. app.Commands = []cli.Command{
  29. {
  30. Name: "batch",
  31. Usage: "Run a batch of tmsp commands against an application",
  32. Action: func(c *cli.Context) {
  33. cmdBatch(app, c)
  34. },
  35. },
  36. {
  37. Name: "console",
  38. Usage: "Start an interactive tmsp console for multiple commands",
  39. Action: func(c *cli.Context) {
  40. cmdConsole(app, c)
  41. },
  42. },
  43. {
  44. Name: "echo",
  45. Usage: "Have the application echo a message",
  46. Action: func(c *cli.Context) {
  47. cmdEcho(c)
  48. },
  49. },
  50. {
  51. Name: "info",
  52. Usage: "Get some info about the application",
  53. Action: func(c *cli.Context) {
  54. cmdInfo(c)
  55. },
  56. },
  57. {
  58. Name: "set_option",
  59. Usage: "Set an option on the application",
  60. Action: func(c *cli.Context) {
  61. cmdSetOption(c)
  62. },
  63. },
  64. {
  65. Name: "append_tx",
  66. Usage: "Append a new tx to application",
  67. Action: func(c *cli.Context) {
  68. cmdAppendTx(c)
  69. },
  70. },
  71. {
  72. Name: "check_tx",
  73. Usage: "Validate a tx",
  74. Action: func(c *cli.Context) {
  75. cmdCheckTx(c)
  76. },
  77. },
  78. {
  79. Name: "get_hash",
  80. Usage: "Get application Merkle root hash",
  81. Action: func(c *cli.Context) {
  82. cmdGetHash(c)
  83. },
  84. },
  85. {
  86. Name: "query",
  87. Usage: "Query application state",
  88. Action: func(c *cli.Context) {
  89. cmdQuery(c)
  90. },
  91. },
  92. }
  93. app.Before = before
  94. app.Run(os.Args)
  95. }
  96. func before(c *cli.Context) error {
  97. if conn == nil {
  98. var err error
  99. conn, err = Connect(c.GlobalString("address"))
  100. if err != nil {
  101. Exit(err.Error())
  102. }
  103. }
  104. return nil
  105. }
  106. //--------------------------------------------------------------------------------
  107. func cmdBatch(app *cli.App, c *cli.Context) {
  108. bufReader := bufio.NewReader(os.Stdin)
  109. for {
  110. line, more, err := bufReader.ReadLine()
  111. if more {
  112. fmt.Println("input line is too long")
  113. return
  114. } else if err == io.EOF {
  115. break
  116. } else if len(line) == 0 {
  117. continue
  118. } else if err != nil {
  119. fmt.Println(err.Error())
  120. return
  121. }
  122. args := []string{"tmsp"}
  123. args = append(args, strings.Split(string(line), " ")...)
  124. app.Run(args)
  125. }
  126. }
  127. func cmdConsole(app *cli.App, c *cli.Context) {
  128. for {
  129. fmt.Printf("\n> ")
  130. bufReader := bufio.NewReader(os.Stdin)
  131. line, more, err := bufReader.ReadLine()
  132. if more {
  133. fmt.Println("input is too long")
  134. return
  135. } else if err != nil {
  136. fmt.Println(err.Error())
  137. return
  138. }
  139. args := []string{"tmsp"}
  140. args = append(args, strings.Split(string(line), " ")...)
  141. app.Run(args)
  142. }
  143. }
  144. // Have the application echo a message
  145. func cmdEcho(c *cli.Context) {
  146. args := c.Args()
  147. if len(args) != 1 {
  148. fmt.Println("echo takes 1 argument")
  149. return
  150. }
  151. res, err := makeRequest(conn, types.RequestEcho(args[0]))
  152. if err != nil {
  153. fmt.Println(err.Error())
  154. return
  155. }
  156. printResponse(res, string(res.Data))
  157. }
  158. // Get some info from the application
  159. func cmdInfo(c *cli.Context) {
  160. res, err := makeRequest(conn, types.RequestInfo())
  161. if err != nil {
  162. fmt.Println(err.Error())
  163. return
  164. }
  165. printResponse(res, string(res.Data))
  166. }
  167. // Set an option on the application
  168. func cmdSetOption(c *cli.Context) {
  169. args := c.Args()
  170. if len(args) != 2 {
  171. fmt.Println("set_option takes 2 arguments (key, value)")
  172. return
  173. }
  174. res, err := makeRequest(conn, types.RequestSetOption(args[0], args[1]))
  175. if err != nil {
  176. fmt.Println(err.Error())
  177. return
  178. }
  179. printResponse(res, Fmt("%s=%s", args[0], args[1]))
  180. }
  181. // Append a new tx to application
  182. func cmdAppendTx(c *cli.Context) {
  183. args := c.Args()
  184. if len(args) != 1 {
  185. fmt.Println("append_tx takes 1 argument")
  186. return
  187. }
  188. txString := args[0]
  189. tx := []byte(txString)
  190. if len(txString) > 2 && strings.HasPrefix(txString, "0x") {
  191. var err error
  192. tx, err = hex.DecodeString(txString[2:])
  193. if err != nil {
  194. fmt.Println(err.Error())
  195. return
  196. }
  197. }
  198. res, err := makeRequest(conn, types.RequestAppendTx(tx))
  199. if err != nil {
  200. fmt.Println(err.Error())
  201. return
  202. }
  203. printResponse(res, string(res.Data))
  204. }
  205. // Validate a tx
  206. func cmdCheckTx(c *cli.Context) {
  207. args := c.Args()
  208. if len(args) != 1 {
  209. fmt.Println("check_tx takes 1 argument")
  210. return
  211. }
  212. txString := args[0]
  213. tx := []byte(txString)
  214. if len(txString) > 2 && strings.HasPrefix(txString, "0x") {
  215. var err error
  216. tx, err = hex.DecodeString(txString[2:])
  217. if err != nil {
  218. fmt.Println(err.Error())
  219. return
  220. }
  221. }
  222. res, err := makeRequest(conn, types.RequestCheckTx(tx))
  223. if err != nil {
  224. fmt.Println(err.Error())
  225. return
  226. }
  227. printResponse(res, string(res.Data))
  228. }
  229. // Get application Merkle root hash
  230. func cmdGetHash(c *cli.Context) {
  231. res, err := makeRequest(conn, types.RequestGetHash())
  232. if err != nil {
  233. fmt.Println(err.Error())
  234. return
  235. }
  236. printResponse(res, Fmt("%X", res.Data))
  237. }
  238. // Query application state
  239. func cmdQuery(c *cli.Context) {
  240. args := c.Args()
  241. if len(args) != 1 {
  242. fmt.Println("query takes 1 argument")
  243. return
  244. }
  245. queryString := args[0]
  246. query := []byte(queryString)
  247. if len(queryString) > 2 && strings.HasPrefix(queryString, "0x") {
  248. var err error
  249. query, err = hex.DecodeString(queryString[2:])
  250. if err != nil {
  251. fmt.Println(err.Error())
  252. return
  253. }
  254. }
  255. res, err := makeRequest(conn, types.RequestQuery(query))
  256. if err != nil {
  257. fmt.Println(err.Error())
  258. return
  259. }
  260. printResponse(res, string(res.Data))
  261. }
  262. //--------------------------------------------------------------------------------
  263. func printResponse(res *types.Response, s string) {
  264. fmt.Printf("-> ")
  265. if res.Error != "" {
  266. fmt.Printf("error: %s\t", res.Error)
  267. }
  268. if res.Code != types.CodeType_OK {
  269. fmt.Printf("code: %s", res.Code.String())
  270. }
  271. if s != "" {
  272. fmt.Printf("data: {%s}", s)
  273. }
  274. if res.Log != "" {
  275. fmt.Printf("log: %s", res.Log)
  276. }
  277. fmt.Printf("\n")
  278. }
  279. func responseString(res *types.Response) string {
  280. return Fmt("type: %v\tdata: %v\tcode: %v", res.Type, res.Data, res.Code)
  281. }
  282. func makeRequest(conn net.Conn, req *types.Request) (*types.Response, error) {
  283. // Write desired request
  284. err := types.WriteMessage(req, conn)
  285. if err != nil {
  286. return nil, err
  287. }
  288. // Write flush request
  289. err = types.WriteMessage(types.RequestFlush(), conn)
  290. if err != nil {
  291. return nil, err
  292. }
  293. // Read desired response
  294. var res = &types.Response{}
  295. err = types.ReadMessage(conn, res)
  296. if err != nil {
  297. return nil, err
  298. }
  299. // Read flush response
  300. var resFlush = &types.Response{}
  301. err = types.ReadMessage(conn, resFlush)
  302. if err != nil {
  303. return nil, err
  304. }
  305. if resFlush.Type != types.MessageType_Flush {
  306. return nil, errors.New(Fmt("Expected types.MessageType_Flush but got %v instead", resFlush.Type))
  307. }
  308. return res, nil
  309. }