Skip to content

Commit

Permalink
add User&TrafficStats
Browse files Browse the repository at this point in the history
  • Loading branch information
Ehco1996 committed Aug 22, 2019
1 parent e637079 commit 53d963a
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 0 deletions.
29 changes: 29 additions & 0 deletions cli/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package main

import (
"context"
"fmt"
"time"

"google.golang.org/grpc"

v2scar "github.com/Ehco1996/v2scar"
)

func main() {

up := v2scar.NewUserPool()

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()

conn, _ := grpc.DialContext(ctx, "127.0.0.1:8080", grpc.WithInsecure(), grpc.WithBlock())
defer conn.Close()

v2scar.GetAndResetUserTraffic(ctx, conn, up)

for _, user := range up.GetAllUsers() {
fmt.Println(user)

}
}
6 changes: 6 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module github.com/Ehco1996/v2scar

require (
google.golang.org/grpc v1.23.0
v2ray.com/core v4.20.0+incompatible
)
49 changes: 49 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.1-0.20190205222052-c823c79ea157 h1:SdQMHsZ18/XZCHuwt3IF+dvHgYTO2XMWZjv3XBKQqAI=
github.com/golang/protobuf v1.2.1-0.20190205222052-c823c79ea157/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
go.starlark.net v0.0.0-20190225160109-1174b2613e82/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
golang.org/x/crypto v0.0.0-20190208162236-193df9c0f06f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
h12.io/socks v1.0.0/go.mod h1:MdYbo5/eB9ka7u5dzW2Qh0iSyJENwB3KI5H5ngenFGA=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
v2ray.com/core v4.15.0+incompatible h1:my1X3WD45iZIXPTz1nse9YBkZxuJzhO9F8bkPPBhO74=
v2ray.com/core v4.15.0+incompatible/go.mod h1:kCjxLuEer3COnk8YSZBx9xHnqadF1zMlaaZaKIgdEB0=
v2ray.com/core v4.20.0+incompatible h1:CMwF0n0z9Ta/nDNYuOq2LuL/WqvOapDpZzMgrFg9MSI=
v2ray.com/core v4.20.0+incompatible/go.mod h1:0yC/gG6Jd6qgp9PuaXuFE9uOi1xVYoDPexD1nlFms/w=
37 changes: 37 additions & 0 deletions services.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package v2scar

import (
"context"
"strings"

"google.golang.org/grpc"
v2stats "v2ray.com/core/app/stats/command"
)

// GetAndResetUserTraffic 统计所有user的上行下行流量
// V2ray的stats的统计模块设计的非常奇怪,具体规则如下
// 上传流量:"user>>>" + user.Email + ">>>traffic>>>uplink"
// 下载流量:"user>>>" + user.Email + ">>>traffic>>>downlink"
func GetAndResetUserTraffic(ctx context.Context, conn *grpc.ClientConn, up *UserPool) {
client := v2stats.NewStatsServiceClient(conn)
req := &v2stats.QueryStatsRequest{
Pattern: "user>>>",
Reset_: true,
}
resp, _ := client.QueryStats(ctx, req)
for _, stat := range resp.Stat {
email, trafficType := getEmailAndTrafficType(stat.Name)
user := up.GetOrCreateUser(email)
switch trafficType {
case "uplink":
user.setUploadTraffic(stat.Value)
case "downlink":
user.setDownloadTraffic(stat.Value)
}
}
}

func getEmailAndTrafficType(input string) (string, string) {
s := strings.Split(input, ">>>")
return s[1], s[len(s)-1]
}
62 changes: 62 additions & 0 deletions user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package v2scar

import (
"sync"
"sync/atomic"
)

// User V2ray User
type User struct {
Email string `json:"_"`
UploadTraffic int64 `json:"upload_traffic"`
DownloadTraffic int64 `json:"download_traffic"`
}

func (u *User) setUploadTraffic(ut int64) {
atomic.StoreInt64(&u.UploadTraffic, ut)
}

func (u *User) setDownloadTraffic(dt int64) {
atomic.StoreInt64(&u.DownloadTraffic, dt)
}

// UserPool user pool
type UserPool struct {
access sync.RWMutex
users map[string]*User
}

// NewUserPool New UserPool
func NewUserPool() *UserPool {
// map key : email
return &UserPool{
users: make(map[string]*User),
}
}

// GetOrCreateUser GetOrCreateUser
func (up *UserPool) GetOrCreateUser(email string) *User {
up.access.Lock()
defer up.access.Unlock()

if user, found := up.users[email]; found {
return user
}
user := &User{
Email: email,
}
up.users[user.Email] = user
return user
}

// GetAllUsers GetAllUsers
func (up *UserPool) GetAllUsers() []*User {
up.access.Lock()
defer up.access.Unlock()

users := make([]*User, 0, len(up.users))
for _, user := range up.users {
users = append(users, user)
}
return users
}

0 comments on commit 53d963a

Please # to comment.