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  }