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.

154 lines
3.5 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "io/ioutil"
  6. "net/http"
  7. "os"
  8. "sync"
  9. acm "github.com/tendermint/tendermint/account"
  10. "github.com/tendermint/tendermint/binary"
  11. . "github.com/tendermint/tendermint/common"
  12. pcm "github.com/tendermint/tendermint/process"
  13. "github.com/tendermint/tendermint/rpc"
  14. )
  15. var Routes = map[string]*rpc.RPCFunc{
  16. "RunProcess": rpc.NewRPCFunc(RunProcess, []string{"wait", "label", "execPath", "args"}),
  17. "ListProcesses": rpc.NewRPCFunc(ListProcesses, []string{}),
  18. "StopProcess": rpc.NewRPCFunc(StopProcess, []string{"label", "kill"}),
  19. // NOTE: also, two special non-JSONRPC routes called
  20. // "download" and "upload".
  21. }
  22. type Validator struct {
  23. VotingPower uint64
  24. PubKey acm.PubKey
  25. }
  26. type Options struct {
  27. Validators []Validator
  28. ListenAddress string
  29. }
  30. // Global instance
  31. var debora = struct {
  32. mtx sync.Mutex
  33. processes map[string]*pcm.Process
  34. }{sync.Mutex{}, make(map[string]*pcm.Process)}
  35. func main() {
  36. // read options from stdin.
  37. var err error
  38. optionsBytes, err := ioutil.ReadAll(os.Stdin)
  39. if err != nil {
  40. panic(Fmt("Error reading input: %v", err))
  41. }
  42. options := binary.ReadJSON(&Options{}, optionsBytes, &err).(*Options)
  43. if err != nil {
  44. panic(Fmt("Error parsing input: %v", err))
  45. }
  46. // Debug.
  47. fmt.Printf("Validators: %v\n", options.Validators)
  48. // start rpc server.
  49. mux := http.NewServeMux()
  50. mux.HandleFunc("/download", ServeFile)
  51. // TODO: mux.HandleFunc("/upload", UploadFile)
  52. rpc.RegisterRPCFuncs(mux, Routes)
  53. rpc.StartHTTPServer(options.ListenAddress, mux)
  54. TrapSignal(func() {
  55. fmt.Println("Debora shutting down")
  56. })
  57. }
  58. //------------------------------------------------------------------------------
  59. // RPC functions
  60. type ResponseRunProcess struct {
  61. }
  62. func RunProcess(wait bool, label string, execPath string, args []string, input string) (*ResponseRunProcess, error) {
  63. debora.mtx.Lock()
  64. // First, see if there already is a process labeled 'label'
  65. existing := debora.processes[label]
  66. if existing != nil {
  67. debora.mtx.Unlock()
  68. return nil, Errorf("Process already exists: %v", label)
  69. }
  70. // Otherwise, create one.
  71. proc := pcm.Create(pcm.ProcessModeDaemon, label, execPath, args, input)
  72. debora.processes[label] = proc
  73. debora.mtx.Unlock()
  74. if wait {
  75. exitErr := pcm.Wait(proc)
  76. return nil, exitErr
  77. } else {
  78. return &ResponseRunProcess{}, nil
  79. }
  80. }
  81. //--------------------------------------
  82. type ResponseListProcesses struct {
  83. Processes []*pcm.Process
  84. }
  85. func ListProcesses() (*ResponseListProcesses, error) {
  86. var procs = []*pcm.Process{}
  87. debora.mtx.Lock()
  88. for _, proc := range debora.processes {
  89. procs = append(procs, proc)
  90. }
  91. debora.mtx.Unlock()
  92. return &ResponseListProcesses{
  93. Processes: procs,
  94. }, nil
  95. }
  96. //--------------------------------------
  97. type ResponseStopProcess struct {
  98. }
  99. func StopProcess(label string, kill bool) (*ResponseStopProcess, error) {
  100. debora.mtx.Lock()
  101. proc := debora.processes[label]
  102. debora.mtx.Unlock()
  103. if proc == nil {
  104. return nil, Errorf("Process does not exist: %v", label)
  105. }
  106. err := pcm.Stop(proc, kill)
  107. return &ResponseStopProcess{}, err
  108. }
  109. //------------------------------------------------------------------------------
  110. func ServeFile(w http.ResponseWriter, req *http.Request) {
  111. path := req.FormValue("path")
  112. if path == "" {
  113. http.Error(w, "Must specify path", 400)
  114. return
  115. }
  116. file, err := os.Open(path)
  117. if err != nil {
  118. http.Error(w, Fmt("Error opening file: %v. %v", path, err), 400)
  119. return
  120. }
  121. _, err = io.Copy(w, file)
  122. if err != nil {
  123. fmt.Fprintf(os.Stderr, Fmt("Error serving file: %v. %v", path, err))
  124. return
  125. }
  126. }