github.com/chwjbn/xclash@v0.2.0/tunnel/statistic/tracker.go (about) 1 package statistic 2 3 import ( 4 "net" 5 "time" 6 7 C "github.com/chwjbn/xclash/constant" 8 9 "github.com/gofrs/uuid" 10 "go.uber.org/atomic" 11 ) 12 13 type tracker interface { 14 ID() string 15 Close() error 16 } 17 18 type trackerInfo struct { 19 UUID uuid.UUID `json:"id"` 20 Metadata *C.Metadata `json:"metadata"` 21 UploadTotal *atomic.Int64 `json:"upload"` 22 DownloadTotal *atomic.Int64 `json:"download"` 23 Start time.Time `json:"start"` 24 Chain C.Chain `json:"chains"` 25 Rule string `json:"rule"` 26 RulePayload string `json:"rulePayload"` 27 } 28 29 type tcpTracker struct { 30 C.Conn `json:"-"` 31 *trackerInfo 32 manager *Manager 33 } 34 35 func (tt *tcpTracker) ID() string { 36 return tt.UUID.String() 37 } 38 39 func (tt *tcpTracker) Read(b []byte) (int, error) { 40 n, err := tt.Conn.Read(b) 41 download := int64(n) 42 tt.manager.PushDownloaded(download) 43 tt.DownloadTotal.Add(download) 44 return n, err 45 } 46 47 func (tt *tcpTracker) Write(b []byte) (int, error) { 48 n, err := tt.Conn.Write(b) 49 upload := int64(n) 50 tt.manager.PushUploaded(upload) 51 tt.UploadTotal.Add(upload) 52 return n, err 53 } 54 55 func (tt *tcpTracker) Close() error { 56 tt.manager.Leave(tt) 57 return tt.Conn.Close() 58 } 59 60 func NewTCPTracker(conn C.Conn, manager *Manager, metadata *C.Metadata, rule C.Rule) *tcpTracker { 61 uuid, _ := uuid.NewV4() 62 63 t := &tcpTracker{ 64 Conn: conn, 65 manager: manager, 66 trackerInfo: &trackerInfo{ 67 UUID: uuid, 68 Start: time.Now(), 69 Metadata: metadata, 70 Chain: conn.Chains(), 71 Rule: "", 72 UploadTotal: atomic.NewInt64(0), 73 DownloadTotal: atomic.NewInt64(0), 74 }, 75 } 76 77 if rule != nil { 78 t.trackerInfo.Rule = rule.RuleType().String() 79 t.trackerInfo.RulePayload = rule.Payload() 80 } 81 82 manager.Join(t) 83 return t 84 } 85 86 type udpTracker struct { 87 C.PacketConn `json:"-"` 88 *trackerInfo 89 manager *Manager 90 } 91 92 func (ut *udpTracker) ID() string { 93 return ut.UUID.String() 94 } 95 96 func (ut *udpTracker) ReadFrom(b []byte) (int, net.Addr, error) { 97 n, addr, err := ut.PacketConn.ReadFrom(b) 98 download := int64(n) 99 ut.manager.PushDownloaded(download) 100 ut.DownloadTotal.Add(download) 101 return n, addr, err 102 } 103 104 func (ut *udpTracker) WriteTo(b []byte, addr net.Addr) (int, error) { 105 n, err := ut.PacketConn.WriteTo(b, addr) 106 upload := int64(n) 107 ut.manager.PushUploaded(upload) 108 ut.UploadTotal.Add(upload) 109 return n, err 110 } 111 112 func (ut *udpTracker) Close() error { 113 ut.manager.Leave(ut) 114 return ut.PacketConn.Close() 115 } 116 117 func NewUDPTracker(conn C.PacketConn, manager *Manager, metadata *C.Metadata, rule C.Rule) *udpTracker { 118 uuid, _ := uuid.NewV4() 119 120 ut := &udpTracker{ 121 PacketConn: conn, 122 manager: manager, 123 trackerInfo: &trackerInfo{ 124 UUID: uuid, 125 Start: time.Now(), 126 Metadata: metadata, 127 Chain: conn.Chains(), 128 Rule: "", 129 UploadTotal: atomic.NewInt64(0), 130 DownloadTotal: atomic.NewInt64(0), 131 }, 132 } 133 134 if rule != nil { 135 ut.trackerInfo.Rule = rule.RuleType().String() 136 ut.trackerInfo.RulePayload = rule.Payload() 137 } 138 139 manager.Join(ut) 140 return ut 141 }