Skip to content

Commit

Permalink
Add v2ray user stats api
Browse files Browse the repository at this point in the history
  • Loading branch information
nekohasekai committed Feb 8, 2023
1 parent 7ea9d48 commit 39514b3
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 8 deletions.
4 changes: 2 additions & 2 deletions adapter/experimental.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ type V2RayServer interface {
}

type V2RayStatsService interface {
RoutedConnection(inbound string, outbound string, conn net.Conn) net.Conn
RoutedPacketConnection(inbound string, outbound string, conn N.PacketConn) N.PacketConn
RoutedConnection(inbound string, outbound string, user string, conn net.Conn) net.Conn
RoutedPacketConnection(inbound string, outbound string, user string, conn N.PacketConn) N.PacketConn
}
7 changes: 7 additions & 0 deletions docs/configuration/experimental/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
"outbounds": [
"proxy",
"direct"
],
"users": [
"sekai"
]
}
}
Expand Down Expand Up @@ -109,3 +112,7 @@ Inbound list to count traffic.
#### stats.outbounds

Outbound list to count traffic.

#### stats.users

User list to count traffic.
7 changes: 7 additions & 0 deletions docs/configuration/experimental/index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
"outbounds": [
"proxy",
"direct"
],
"users": [
"sekai"
]
}
}
Expand Down Expand Up @@ -107,3 +110,7 @@ gRPC API 监听地址。如果为空,则禁用 V2Ray API。
#### stats.outbounds

统计流量的出站列表。

#### stats.users

统计流量的用户列表。
24 changes: 20 additions & 4 deletions experimental/v2rayapi/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type StatsService struct {
createdAt time.Time
inbounds map[string]bool
outbounds map[string]bool
users map[string]bool
access sync.Mutex
counters map[string]*atomic.Int64
}
Expand All @@ -41,26 +42,32 @@ func NewStatsService(options option.V2RayStatsServiceOptions) *StatsService {
}
inbounds := make(map[string]bool)
outbounds := make(map[string]bool)
users := make(map[string]bool)
for _, inbound := range options.Inbounds {
inbounds[inbound] = true
}
for _, outbound := range options.Outbounds {
outbounds[outbound] = true
}
for _, user := range options.Users {
users[user] = true
}
return &StatsService{
createdAt: time.Now(),
inbounds: inbounds,
outbounds: outbounds,
users: users,
counters: make(map[string]*atomic.Int64),
}
}

func (s *StatsService) RoutedConnection(inbound string, outbound string, conn net.Conn) net.Conn {
func (s *StatsService) RoutedConnection(inbound string, outbound string, user string, conn net.Conn) net.Conn {
var readCounter []*atomic.Int64
var writeCounter []*atomic.Int64
countInbound := inbound != "" && s.inbounds[inbound]
countOutbound := outbound != "" && s.outbounds[outbound]
if !countInbound && !countOutbound {
countUser := user != "" && s.users[user]
if !countInbound && !countOutbound && !countUser {
return conn
}
s.access.Lock()
Expand All @@ -72,16 +79,21 @@ func (s *StatsService) RoutedConnection(inbound string, outbound string, conn ne
readCounter = append(readCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>uplink"))
writeCounter = append(writeCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>downlink"))
}
if countUser {
readCounter = append(readCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>uplink"))
writeCounter = append(writeCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>downlink"))
}
s.access.Unlock()
return trackerconn.New(conn, readCounter, writeCounter)
}

func (s *StatsService) RoutedPacketConnection(inbound string, outbound string, conn N.PacketConn) N.PacketConn {
func (s *StatsService) RoutedPacketConnection(inbound string, outbound string, user string, conn N.PacketConn) N.PacketConn {
var readCounter []*atomic.Int64
var writeCounter []*atomic.Int64
countInbound := inbound != "" && s.inbounds[inbound]
countOutbound := outbound != "" && s.outbounds[outbound]
if !countInbound && !countOutbound {
countUser := user != "" && s.users[user]
if !countInbound && !countOutbound && !countUser {
return conn
}
s.access.Lock()
Expand All @@ -93,6 +105,10 @@ func (s *StatsService) RoutedPacketConnection(inbound string, outbound string, c
readCounter = append(readCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>uplink"))
writeCounter = append(writeCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>downlink"))
}
if countUser {
readCounter = append(readCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>uplink"))
writeCounter = append(writeCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>downlink"))
}
s.access.Unlock()
return trackerconn.NewPacket(conn, readCounter, writeCounter)
}
Expand Down
1 change: 1 addition & 0 deletions option/v2ray.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ type V2RayStatsServiceOptions struct {
Enabled bool `json:"enabled,omitempty"`
Inbounds []string `json:"inbounds,omitempty"`
Outbounds []string `json:"outbounds,omitempty"`
Users []string `json:"users,omitempty"`
}
4 changes: 2 additions & 2 deletions route/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
}
if r.v2rayServer != nil {
if statsService := r.v2rayServer.StatsService(); statsService != nil {
conn = statsService.RoutedConnection(metadata.Inbound, detour.Tag(), conn)
conn = statsService.RoutedConnection(metadata.Inbound, detour.Tag(), metadata.User, conn)
}
}
return detour.NewConnection(ctx, conn, metadata)
Expand Down Expand Up @@ -678,7 +678,7 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
}
if r.v2rayServer != nil {
if statsService := r.v2rayServer.StatsService(); statsService != nil {
conn = statsService.RoutedPacketConnection(metadata.Inbound, detour.Tag(), conn)
conn = statsService.RoutedPacketConnection(metadata.Inbound, detour.Tag(), metadata.User, conn)
}
}
return detour.NewPacketConnection(ctx, conn, metadata)
Expand Down

0 comments on commit 39514b3

Please sign in to comment.