command_types.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. package libbox
  2. import (
  3. "slices"
  4. "strings"
  5. "github.com/sagernet/sing-box/daemon"
  6. M "github.com/sagernet/sing/common/metadata"
  7. )
  8. type StatusMessage struct {
  9. Memory int64
  10. Goroutines int32
  11. ConnectionsIn int32
  12. ConnectionsOut int32
  13. TrafficAvailable bool
  14. Uplink int64
  15. Downlink int64
  16. UplinkTotal int64
  17. DownlinkTotal int64
  18. }
  19. type SystemProxyStatus struct {
  20. Available bool
  21. Enabled bool
  22. }
  23. type OutboundGroup struct {
  24. Tag string
  25. Type string
  26. Selectable bool
  27. Selected string
  28. IsExpand bool
  29. ItemList []*OutboundGroupItem
  30. }
  31. func (g *OutboundGroup) GetItems() OutboundGroupItemIterator {
  32. return newIterator(g.ItemList)
  33. }
  34. type OutboundGroupIterator interface {
  35. Next() *OutboundGroup
  36. HasNext() bool
  37. }
  38. type OutboundGroupItem struct {
  39. Tag string
  40. Type string
  41. URLTestTime int64
  42. URLTestDelay int32
  43. }
  44. type OutboundGroupItemIterator interface {
  45. Next() *OutboundGroupItem
  46. HasNext() bool
  47. }
  48. const (
  49. ConnectionStateAll = iota
  50. ConnectionStateActive
  51. ConnectionStateClosed
  52. )
  53. type Connections struct {
  54. input []Connection
  55. filtered []Connection
  56. }
  57. func (c *Connections) FilterState(state int32) {
  58. c.filtered = c.filtered[:0]
  59. switch state {
  60. case ConnectionStateAll:
  61. c.filtered = append(c.filtered, c.input...)
  62. case ConnectionStateActive:
  63. for _, connection := range c.input {
  64. if connection.ClosedAt == 0 {
  65. c.filtered = append(c.filtered, connection)
  66. }
  67. }
  68. case ConnectionStateClosed:
  69. for _, connection := range c.input {
  70. if connection.ClosedAt != 0 {
  71. c.filtered = append(c.filtered, connection)
  72. }
  73. }
  74. }
  75. }
  76. func (c *Connections) SortByDate() {
  77. slices.SortStableFunc(c.filtered, func(x, y Connection) int {
  78. if x.CreatedAt < y.CreatedAt {
  79. return 1
  80. } else if x.CreatedAt > y.CreatedAt {
  81. return -1
  82. } else {
  83. return strings.Compare(y.ID, x.ID)
  84. }
  85. })
  86. }
  87. func (c *Connections) SortByTraffic() {
  88. slices.SortStableFunc(c.filtered, func(x, y Connection) int {
  89. xTraffic := x.Uplink + x.Downlink
  90. yTraffic := y.Uplink + y.Downlink
  91. if xTraffic < yTraffic {
  92. return 1
  93. } else if xTraffic > yTraffic {
  94. return -1
  95. } else {
  96. return strings.Compare(y.ID, x.ID)
  97. }
  98. })
  99. }
  100. func (c *Connections) SortByTrafficTotal() {
  101. slices.SortStableFunc(c.filtered, func(x, y Connection) int {
  102. xTraffic := x.UplinkTotal + x.DownlinkTotal
  103. yTraffic := y.UplinkTotal + y.DownlinkTotal
  104. if xTraffic < yTraffic {
  105. return 1
  106. } else if xTraffic > yTraffic {
  107. return -1
  108. } else {
  109. return strings.Compare(y.ID, x.ID)
  110. }
  111. })
  112. }
  113. func (c *Connections) Iterator() ConnectionIterator {
  114. return newPtrIterator(c.filtered)
  115. }
  116. type ProcessInfo struct {
  117. ProcessID int64
  118. UserID int32
  119. UserName string
  120. ProcessPath string
  121. PackageName string
  122. }
  123. type Connection struct {
  124. ID string
  125. Inbound string
  126. InboundType string
  127. IPVersion int32
  128. Network string
  129. Source string
  130. Destination string
  131. Domain string
  132. Protocol string
  133. User string
  134. FromOutbound string
  135. CreatedAt int64
  136. ClosedAt int64
  137. Uplink int64
  138. Downlink int64
  139. UplinkTotal int64
  140. DownlinkTotal int64
  141. Rule string
  142. Outbound string
  143. OutboundType string
  144. ChainList []string
  145. ProcessInfo *ProcessInfo
  146. }
  147. func (c *Connection) Chain() StringIterator {
  148. return newIterator(c.ChainList)
  149. }
  150. func (c *Connection) DisplayDestination() string {
  151. destination := M.ParseSocksaddr(c.Destination)
  152. if destination.IsIP() && c.Domain != "" {
  153. destination = M.Socksaddr{
  154. Fqdn: c.Domain,
  155. Port: destination.Port,
  156. }
  157. return destination.String()
  158. }
  159. return c.Destination
  160. }
  161. type ConnectionIterator interface {
  162. Next() *Connection
  163. HasNext() bool
  164. }
  165. func StatusMessageFromGRPC(status *daemon.Status) *StatusMessage {
  166. if status == nil {
  167. return nil
  168. }
  169. return &StatusMessage{
  170. Memory: int64(status.Memory),
  171. Goroutines: status.Goroutines,
  172. ConnectionsIn: status.ConnectionsIn,
  173. ConnectionsOut: status.ConnectionsOut,
  174. TrafficAvailable: status.TrafficAvailable,
  175. Uplink: status.Uplink,
  176. Downlink: status.Downlink,
  177. UplinkTotal: status.UplinkTotal,
  178. DownlinkTotal: status.DownlinkTotal,
  179. }
  180. }
  181. func OutboundGroupIteratorFromGRPC(groups *daemon.Groups) OutboundGroupIterator {
  182. if groups == nil || len(groups.Group) == 0 {
  183. return newIterator([]*OutboundGroup{})
  184. }
  185. var libboxGroups []*OutboundGroup
  186. for _, g := range groups.Group {
  187. libboxGroup := &OutboundGroup{
  188. Tag: g.Tag,
  189. Type: g.Type,
  190. Selectable: g.Selectable,
  191. Selected: g.Selected,
  192. IsExpand: g.IsExpand,
  193. }
  194. for _, item := range g.Items {
  195. libboxGroup.ItemList = append(libboxGroup.ItemList, &OutboundGroupItem{
  196. Tag: item.Tag,
  197. Type: item.Type,
  198. URLTestTime: item.UrlTestTime,
  199. URLTestDelay: item.UrlTestDelay,
  200. })
  201. }
  202. libboxGroups = append(libboxGroups, libboxGroup)
  203. }
  204. return newIterator(libboxGroups)
  205. }
  206. func ConnectionFromGRPC(conn *daemon.Connection) Connection {
  207. var processInfo *ProcessInfo
  208. if conn.ProcessInfo != nil {
  209. processInfo = &ProcessInfo{
  210. ProcessID: int64(conn.ProcessInfo.ProcessId),
  211. UserID: conn.ProcessInfo.UserId,
  212. UserName: conn.ProcessInfo.UserName,
  213. ProcessPath: conn.ProcessInfo.ProcessPath,
  214. PackageName: conn.ProcessInfo.PackageName,
  215. }
  216. }
  217. return Connection{
  218. ID: conn.Id,
  219. Inbound: conn.Inbound,
  220. InboundType: conn.InboundType,
  221. IPVersion: conn.IpVersion,
  222. Network: conn.Network,
  223. Source: conn.Source,
  224. Destination: conn.Destination,
  225. Domain: conn.Domain,
  226. Protocol: conn.Protocol,
  227. User: conn.User,
  228. FromOutbound: conn.FromOutbound,
  229. CreatedAt: conn.CreatedAt,
  230. ClosedAt: conn.ClosedAt,
  231. Uplink: conn.Uplink,
  232. Downlink: conn.Downlink,
  233. UplinkTotal: conn.UplinkTotal,
  234. DownlinkTotal: conn.DownlinkTotal,
  235. Rule: conn.Rule,
  236. Outbound: conn.Outbound,
  237. OutboundType: conn.OutboundType,
  238. ChainList: conn.ChainList,
  239. ProcessInfo: processInfo,
  240. }
  241. }
  242. func ConnectionsFromGRPC(connections *daemon.Connections) []Connection {
  243. if connections == nil || len(connections.Connections) == 0 {
  244. return nil
  245. }
  246. var libboxConnections []Connection
  247. for _, conn := range connections.Connections {
  248. libboxConnections = append(libboxConnections, ConnectionFromGRPC(conn))
  249. }
  250. return libboxConnections
  251. }
  252. func SystemProxyStatusFromGRPC(status *daemon.SystemProxyStatus) *SystemProxyStatus {
  253. if status == nil {
  254. return nil
  255. }
  256. return &SystemProxyStatus{
  257. Available: status.Available,
  258. Enabled: status.Enabled,
  259. }
  260. }
  261. func SystemProxyStatusToGRPC(status *SystemProxyStatus) *daemon.SystemProxyStatus {
  262. if status == nil {
  263. return nil
  264. }
  265. return &daemon.SystemProxyStatus{
  266. Available: status.Available,
  267. Enabled: status.Enabled,
  268. }
  269. }