shadowsocks_control.go 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package inbound
  2. import (
  3. "encoding/json"
  4. "io"
  5. "net/http"
  6. C "github.com/sagernet/sing-box/constant"
  7. "github.com/sagernet/sing-box/option"
  8. "github.com/sagernet/sing/common"
  9. E "github.com/sagernet/sing/common/exceptions"
  10. F "github.com/sagernet/sing/common/format"
  11. "github.com/go-chi/chi/v5"
  12. "github.com/go-chi/render"
  13. )
  14. func (h *ShadowsocksMulti) createHandler() http.Handler {
  15. router := chi.NewRouter()
  16. router.Get("/", h.handleHello)
  17. router.Put("/users", h.handleUpdateUsers)
  18. router.Get("/traffics", h.handleReadTraffics)
  19. return router
  20. }
  21. func (h *ShadowsocksMulti) handleHello(writer http.ResponseWriter, request *http.Request) {
  22. render.JSON(writer, request, render.M{
  23. "server": "sing-box",
  24. "version": C.Version,
  25. })
  26. }
  27. func (h *ShadowsocksMulti) handleUpdateUsers(writer http.ResponseWriter, request *http.Request) {
  28. var users []option.ShadowsocksUser
  29. err := readRequest(request, &users)
  30. if err != nil {
  31. h.newError(E.Cause(err, "controller: update users: parse request"))
  32. writer.WriteHeader(http.StatusBadRequest)
  33. writer.Write([]byte(F.ToString(err)))
  34. return
  35. }
  36. users = append([]option.ShadowsocksUser{{
  37. Name: "control",
  38. Password: h.users[0].Password,
  39. }}, users...)
  40. err = h.service.UpdateUsersWithPasswords(common.MapIndexed(users, func(index int, user option.ShadowsocksUser) int {
  41. return index
  42. }), common.Map(users, func(user option.ShadowsocksUser) string {
  43. return user.Password
  44. }))
  45. if err != nil {
  46. h.newError(E.Cause(err, "controller: update users"))
  47. writer.WriteHeader(http.StatusBadRequest)
  48. writer.Write([]byte(F.ToString(err)))
  49. return
  50. }
  51. h.users = users
  52. h.trafficManager.Reset()
  53. writer.WriteHeader(http.StatusNoContent)
  54. h.logger.Info("controller: updated ", len(users)-1, " users")
  55. }
  56. type ShadowsocksUserTraffic struct {
  57. Name string `json:"name,omitempty"`
  58. Upload uint64 `json:"upload,omitempty"`
  59. Download uint64 `json:"download,omitempty"`
  60. }
  61. func (h *ShadowsocksMulti) handleReadTraffics(writer http.ResponseWriter, request *http.Request) {
  62. h.logger.Debug("controller: traffics sent")
  63. trafficMap := h.trafficManager.ReadTraffics()
  64. if len(trafficMap) == 0 {
  65. writer.WriteHeader(http.StatusNoContent)
  66. return
  67. }
  68. traffics := make([]ShadowsocksUserTraffic, 0, len(trafficMap))
  69. for user, traffic := range trafficMap {
  70. traffics = append(traffics, ShadowsocksUserTraffic{
  71. Name: h.users[user].Name,
  72. Upload: traffic.Upload,
  73. Download: traffic.Download,
  74. })
  75. }
  76. render.JSON(writer, request, traffics)
  77. }
  78. func readRequest(request *http.Request, v any) error {
  79. defer request.Body.Close()
  80. content, err := io.ReadAll(request.Body)
  81. if err != nil {
  82. return err
  83. }
  84. return json.Unmarshal(content, v)
  85. }