gui.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package main
  2. import (
  3. "encoding/json"
  4. "log"
  5. "net/http"
  6. "runtime"
  7. "sync"
  8. "github.com/calmh/syncthing/model"
  9. "github.com/codegangsta/martini"
  10. )
  11. func startGUI(addr string, m *model.Model) {
  12. router := martini.NewRouter()
  13. router.Get("/", getRoot)
  14. router.Get("/rest/version", restGetVersion)
  15. router.Get("/rest/model", restGetModel)
  16. router.Get("/rest/connections", restGetConnections)
  17. router.Get("/rest/config", restGetConfig)
  18. router.Get("/rest/need", restGetNeed)
  19. router.Get("/rest/system", restGetSystem)
  20. router.Post("/rest/config", restPostConfig)
  21. go func() {
  22. mr := martini.New()
  23. mr.Use(embeddedStatic())
  24. mr.Use(martini.Recovery())
  25. mr.Action(router.Handle)
  26. mr.Map(m)
  27. err := http.ListenAndServe(addr, mr)
  28. if err != nil {
  29. warnln("GUI not possible:", err)
  30. }
  31. }()
  32. }
  33. func getRoot(w http.ResponseWriter, r *http.Request) {
  34. http.Redirect(w, r, "/index.html", 302)
  35. }
  36. func restGetVersion() string {
  37. return Version
  38. }
  39. func restGetModel(m *model.Model, w http.ResponseWriter) {
  40. var res = make(map[string]interface{})
  41. globalFiles, globalDeleted, globalBytes := m.GlobalSize()
  42. res["globalFiles"], res["globalDeleted"], res["globalBytes"] = globalFiles, globalDeleted, globalBytes
  43. localFiles, localDeleted, localBytes := m.LocalSize()
  44. res["localFiles"], res["localDeleted"], res["localBytes"] = localFiles, localDeleted, localBytes
  45. inSyncFiles, inSyncBytes := m.InSyncSize()
  46. res["inSyncFiles"], res["inSyncBytes"] = inSyncFiles, inSyncBytes
  47. files, total := m.NeedFiles()
  48. res["needFiles"], res["needBytes"] = len(files), total
  49. w.Header().Set("Content-Type", "application/json")
  50. json.NewEncoder(w).Encode(res)
  51. }
  52. func restGetConnections(m *model.Model, w http.ResponseWriter) {
  53. var res = m.ConnectionStats()
  54. w.Header().Set("Content-Type", "application/json")
  55. json.NewEncoder(w).Encode(res)
  56. }
  57. func restGetConfig(w http.ResponseWriter) {
  58. json.NewEncoder(w).Encode(cfg)
  59. }
  60. func restPostConfig(req *http.Request) {
  61. err := json.NewDecoder(req.Body).Decode(&cfg)
  62. if err != nil {
  63. log.Println(err)
  64. } else {
  65. saveConfig()
  66. }
  67. }
  68. type guiFile model.File
  69. func (f guiFile) MarshalJSON() ([]byte, error) {
  70. type t struct {
  71. Name string
  72. Size int
  73. }
  74. return json.Marshal(t{
  75. Name: f.Name,
  76. Size: model.File(f).Size(),
  77. })
  78. }
  79. func restGetNeed(m *model.Model, w http.ResponseWriter) {
  80. files, _ := m.NeedFiles()
  81. gfs := make([]guiFile, len(files))
  82. for i, f := range files {
  83. gfs[i] = guiFile(f)
  84. }
  85. w.Header().Set("Content-Type", "application/json")
  86. json.NewEncoder(w).Encode(gfs)
  87. }
  88. var cpuUsagePercent float64
  89. var cpuUsageLock sync.RWMutex
  90. func restGetSystem(w http.ResponseWriter) {
  91. var m runtime.MemStats
  92. runtime.ReadMemStats(&m)
  93. res := make(map[string]interface{})
  94. res["myID"] = myID
  95. res["goroutines"] = runtime.NumGoroutine()
  96. res["alloc"] = m.Alloc
  97. res["sys"] = m.Sys
  98. cpuUsageLock.RLock()
  99. res["cpuPercent"] = cpuUsagePercent
  100. cpuUsageLock.RUnlock()
  101. w.Header().Set("Content-Type", "application/json")
  102. json.NewEncoder(w).Encode(res)
  103. }