tracker.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. package statistic
  2. import (
  3. "io"
  4. "net"
  5. "net/netip"
  6. "time"
  7. "github.com/metacubex/mihomo/common/atomic"
  8. "github.com/metacubex/mihomo/common/buf"
  9. N "github.com/metacubex/mihomo/common/net"
  10. "github.com/metacubex/mihomo/common/utils"
  11. C "github.com/metacubex/mihomo/constant"
  12. "github.com/gofrs/uuid/v5"
  13. )
  14. type Tracker interface {
  15. ID() string
  16. Close() error
  17. Info() *TrackerInfo
  18. C.Connection
  19. }
  20. type TrackerInfo struct {
  21. UUID uuid.UUID `json:"id"`
  22. Metadata *C.Metadata `json:"metadata"`
  23. UploadTotal atomic.Int64 `json:"upload"`
  24. DownloadTotal atomic.Int64 `json:"download"`
  25. Start time.Time `json:"start"`
  26. Chain C.Chain `json:"chains"`
  27. Rule string `json:"rule"`
  28. RulePayload string `json:"rulePayload"`
  29. }
  30. type tcpTracker struct {
  31. C.Conn `json:"-"`
  32. *TrackerInfo
  33. manager *Manager
  34. pushToManager bool `json:"-"`
  35. }
  36. func (tt *tcpTracker) ID() string {
  37. return tt.UUID.String()
  38. }
  39. func (tt *tcpTracker) Info() *TrackerInfo {
  40. return tt.TrackerInfo
  41. }
  42. func (tt *tcpTracker) Read(b []byte) (int, error) {
  43. n, err := tt.Conn.Read(b)
  44. download := int64(n)
  45. if tt.pushToManager {
  46. tt.manager.PushDownloaded(tt.Conn.Chains().Last(), download)
  47. }
  48. tt.DownloadTotal.Add(download)
  49. return n, err
  50. }
  51. func (tt *tcpTracker) ReadBuffer(buffer *buf.Buffer) (err error) {
  52. err = tt.Conn.ReadBuffer(buffer)
  53. download := int64(buffer.Len())
  54. if tt.pushToManager {
  55. tt.manager.PushDownloaded(tt.Chains().Last(), download)
  56. }
  57. tt.DownloadTotal.Add(download)
  58. return
  59. }
  60. func (tt *tcpTracker) UnwrapReader() (io.Reader, []N.CountFunc) {
  61. return tt.Conn, []N.CountFunc{func(download int64) {
  62. if tt.pushToManager {
  63. tt.manager.PushDownloaded(tt.Chains().Last(), download)
  64. }
  65. tt.DownloadTotal.Add(download)
  66. }}
  67. }
  68. func (tt *tcpTracker) Write(b []byte) (int, error) {
  69. n, err := tt.Conn.Write(b)
  70. upload := int64(n)
  71. if tt.pushToManager {
  72. tt.manager.PushUploaded(tt.Chains().Last(), upload)
  73. }
  74. tt.UploadTotal.Add(upload)
  75. return n, err
  76. }
  77. func (tt *tcpTracker) WriteBuffer(buffer *buf.Buffer) (err error) {
  78. upload := int64(buffer.Len())
  79. err = tt.Conn.WriteBuffer(buffer)
  80. if tt.pushToManager {
  81. tt.manager.PushUploaded(tt.Chains().Last(), upload)
  82. }
  83. tt.UploadTotal.Add(upload)
  84. return
  85. }
  86. func (tt *tcpTracker) UnwrapWriter() (io.Writer, []N.CountFunc) {
  87. return tt.Conn, []N.CountFunc{func(upload int64) {
  88. if tt.pushToManager {
  89. tt.manager.PushUploaded(tt.Chains().Last(), upload)
  90. }
  91. tt.UploadTotal.Add(upload)
  92. }}
  93. }
  94. func (tt *tcpTracker) Close() error {
  95. tt.manager.Leave(tt)
  96. return tt.Conn.Close()
  97. }
  98. func (tt *tcpTracker) Upstream() any {
  99. return tt.Conn
  100. }
  101. func parseRemoteDestination(addr net.Addr, conn C.Connection) string {
  102. if addr == nil && conn != nil {
  103. return conn.RemoteDestination()
  104. }
  105. if addrPort, err := netip.ParseAddrPort(addr.String()); err == nil && addrPort.Addr().IsValid() {
  106. return addrPort.Addr().String()
  107. } else {
  108. if conn != nil {
  109. return conn.RemoteDestination()
  110. } else {
  111. return ""
  112. }
  113. }
  114. }
  115. func NewTCPTracker(conn C.Conn, manager *Manager, metadata *C.Metadata, rule C.Rule, uploadTotal int64, downloadTotal int64, pushToManager bool) *tcpTracker {
  116. if conn != nil {
  117. metadata.RemoteDst = parseRemoteDestination(conn.RemoteAddr(), conn)
  118. }
  119. tt := &tcpTracker{
  120. Conn: conn,
  121. manager: manager,
  122. TrackerInfo: &TrackerInfo{
  123. UUID: utils.NewUUIDV4(),
  124. Start: time.Now(),
  125. Metadata: metadata,
  126. Chain: conn.Chains(),
  127. Rule: "",
  128. UploadTotal: atomic.NewInt64(uploadTotal),
  129. DownloadTotal: atomic.NewInt64(downloadTotal),
  130. },
  131. pushToManager: pushToManager,
  132. }
  133. if pushToManager {
  134. if uploadTotal > 0 {
  135. manager.PushUploaded(tt.Chains().Last(), uploadTotal)
  136. }
  137. if downloadTotal > 0 {
  138. manager.PushDownloaded(tt.Chains().Last(), downloadTotal)
  139. }
  140. }
  141. if rule != nil {
  142. tt.TrackerInfo.Rule = rule.RuleType().String()
  143. tt.TrackerInfo.RulePayload = rule.Payload()
  144. }
  145. manager.Join(tt)
  146. return tt
  147. }
  148. type udpTracker struct {
  149. C.PacketConn `json:"-"`
  150. *TrackerInfo
  151. manager *Manager
  152. pushToManager bool `json:"-"`
  153. }
  154. func (ut *udpTracker) ID() string {
  155. return ut.UUID.String()
  156. }
  157. func (ut *udpTracker) Info() *TrackerInfo {
  158. return ut.TrackerInfo
  159. }
  160. func (ut *udpTracker) ReadFrom(b []byte) (int, net.Addr, error) {
  161. n, addr, err := ut.PacketConn.ReadFrom(b)
  162. download := int64(n)
  163. if ut.pushToManager {
  164. ut.manager.PushDownloaded(ut.Chains().Last(), download)
  165. }
  166. ut.DownloadTotal.Add(download)
  167. return n, addr, err
  168. }
  169. func (ut *udpTracker) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) {
  170. data, put, addr, err = ut.PacketConn.WaitReadFrom()
  171. download := int64(len(data))
  172. if ut.pushToManager {
  173. ut.manager.PushDownloaded(ut.Chains().Last(), download)
  174. }
  175. ut.DownloadTotal.Add(download)
  176. return
  177. }
  178. func (ut *udpTracker) WriteTo(b []byte, addr net.Addr) (int, error) {
  179. n, err := ut.PacketConn.WriteTo(b, addr)
  180. upload := int64(n)
  181. if ut.pushToManager {
  182. ut.manager.PushUploaded(ut.Chains().Last(), upload)
  183. }
  184. ut.UploadTotal.Add(upload)
  185. return n, err
  186. }
  187. func (ut *udpTracker) Close() error {
  188. ut.manager.Leave(ut)
  189. return ut.PacketConn.Close()
  190. }
  191. func (ut *udpTracker) Upstream() any {
  192. return ut.PacketConn
  193. }
  194. func NewUDPTracker(conn C.PacketConn, manager *Manager, metadata *C.Metadata, rule C.Rule, uploadTotal int64, downloadTotal int64, pushToManager bool) *udpTracker {
  195. metadata.RemoteDst = parseRemoteDestination(nil, conn)
  196. ut := &udpTracker{
  197. PacketConn: conn,
  198. manager: manager,
  199. TrackerInfo: &TrackerInfo{
  200. UUID: utils.NewUUIDV4(),
  201. Start: time.Now(),
  202. Metadata: metadata,
  203. Chain: conn.Chains(),
  204. Rule: "",
  205. UploadTotal: atomic.NewInt64(uploadTotal),
  206. DownloadTotal: atomic.NewInt64(downloadTotal),
  207. },
  208. pushToManager: pushToManager,
  209. }
  210. if pushToManager {
  211. if uploadTotal > 0 {
  212. manager.PushUploaded(ut.Chains().Last(), uploadTotal)
  213. }
  214. if downloadTotal > 0 {
  215. manager.PushDownloaded(ut.Chains().Last(), downloadTotal)
  216. }
  217. }
  218. if rule != nil {
  219. ut.TrackerInfo.Rule = rule.RuleType().String()
  220. ut.TrackerInfo.RulePayload = rule.Payload()
  221. }
  222. manager.Join(ut)
  223. return ut
  224. }