mirror of https://github.com/v2ray/v2ray-core
stats counter for inbound traffic
parent
3e8da9e540
commit
c76d492c0f
|
@ -52,18 +52,6 @@ func (*DefaultDispatcher) Start() error {
|
||||||
// Close implements common.Closable.
|
// Close implements common.Closable.
|
||||||
func (*DefaultDispatcher) Close() error { return nil }
|
func (*DefaultDispatcher) Close() error { return nil }
|
||||||
|
|
||||||
func (d *DefaultDispatcher) getStatCounter(name string) core.StatCounter {
|
|
||||||
c := d.stats.GetCounter(name)
|
|
||||||
if c != nil {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
c, err := d.stats.RegisterCounter(name)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DefaultDispatcher) getRayOption(user *protocol.User) []ray.Option {
|
func (d *DefaultDispatcher) getRayOption(user *protocol.User) []ray.Option {
|
||||||
var rayOptions []ray.Option
|
var rayOptions []ray.Option
|
||||||
|
|
||||||
|
@ -71,13 +59,13 @@ func (d *DefaultDispatcher) getRayOption(user *protocol.User) []ray.Option {
|
||||||
p := d.policy.ForLevel(user.Level)
|
p := d.policy.ForLevel(user.Level)
|
||||||
if p.Stats.UserUplink {
|
if p.Stats.UserUplink {
|
||||||
name := "user>>>" + user.Email + ">>>traffic>>>uplink"
|
name := "user>>>" + user.Email + ">>>traffic>>>uplink"
|
||||||
if c := d.getStatCounter(name); c != nil {
|
if c, _ := core.GetOrRegisterStatCounter(d.stats, name); c != nil {
|
||||||
rayOptions = append(rayOptions, ray.WithUplinkStatCounter(c))
|
rayOptions = append(rayOptions, ray.WithUplinkStatCounter(c))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.Stats.UserDownlink {
|
if p.Stats.UserDownlink {
|
||||||
name := "user>>>" + user.Email + ">>>traffic>>>downlink"
|
name := "user>>>" + user.Email + ">>>traffic>>>downlink"
|
||||||
if c := d.getStatCounter(name); c != nil {
|
if c, _ := core.GetOrRegisterStatCounter(d.stats, name); c != nil {
|
||||||
rayOptions = append(rayOptions, ray.WithDownlinkStatCounter(c))
|
rayOptions = append(rayOptions, ray.WithDownlinkStatCounter(c))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,3 +67,12 @@ func (p *Policy) ToCorePolicy() core.Policy {
|
||||||
}
|
}
|
||||||
return cp
|
return cp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *SystemPolicy) ToCorePolicy() core.SystemPolicy {
|
||||||
|
return core.SystemPolicy{
|
||||||
|
Stats: core.SystemStatsPolicy{
|
||||||
|
InboundUplink: p.Stats.InboundUplink,
|
||||||
|
InboundDownlink: p.Stats.InboundDownlink,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -120,14 +120,55 @@ func (m *Policy_Stats) GetUserDownlink() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SystemPolicy struct {
|
||||||
|
Stats *SystemPolicy_Stats `protobuf:"bytes,1,opt,name=stats" json:"stats,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SystemPolicy) Reset() { *m = SystemPolicy{} }
|
||||||
|
func (m *SystemPolicy) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*SystemPolicy) ProtoMessage() {}
|
||||||
|
func (*SystemPolicy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||||
|
|
||||||
|
func (m *SystemPolicy) GetStats() *SystemPolicy_Stats {
|
||||||
|
if m != nil {
|
||||||
|
return m.Stats
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type SystemPolicy_Stats struct {
|
||||||
|
InboundUplink bool `protobuf:"varint,1,opt,name=inbound_uplink,json=inboundUplink" json:"inbound_uplink,omitempty"`
|
||||||
|
InboundDownlink bool `protobuf:"varint,2,opt,name=inbound_downlink,json=inboundDownlink" json:"inbound_downlink,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SystemPolicy_Stats) Reset() { *m = SystemPolicy_Stats{} }
|
||||||
|
func (m *SystemPolicy_Stats) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*SystemPolicy_Stats) ProtoMessage() {}
|
||||||
|
func (*SystemPolicy_Stats) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} }
|
||||||
|
|
||||||
|
func (m *SystemPolicy_Stats) GetInboundUplink() bool {
|
||||||
|
if m != nil {
|
||||||
|
return m.InboundUplink
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SystemPolicy_Stats) GetInboundDownlink() bool {
|
||||||
|
if m != nil {
|
||||||
|
return m.InboundDownlink
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Level map[uint32]*Policy `protobuf:"bytes,1,rep,name=level" json:"level,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
Level map[uint32]*Policy `protobuf:"bytes,1,rep,name=level" json:"level,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||||
|
System *SystemPolicy `protobuf:"bytes,2,opt,name=system" json:"system,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Config) Reset() { *m = Config{} }
|
func (m *Config) Reset() { *m = Config{} }
|
||||||
func (m *Config) String() string { return proto.CompactTextString(m) }
|
func (m *Config) String() string { return proto.CompactTextString(m) }
|
||||||
func (*Config) ProtoMessage() {}
|
func (*Config) ProtoMessage() {}
|
||||||
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||||
|
|
||||||
func (m *Config) GetLevel() map[uint32]*Policy {
|
func (m *Config) GetLevel() map[uint32]*Policy {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -136,42 +177,55 @@ func (m *Config) GetLevel() map[uint32]*Policy {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Config) GetSystem() *SystemPolicy {
|
||||||
|
if m != nil {
|
||||||
|
return m.System
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterType((*Second)(nil), "v2ray.core.app.policy.Second")
|
proto.RegisterType((*Second)(nil), "v2ray.core.app.policy.Second")
|
||||||
proto.RegisterType((*Policy)(nil), "v2ray.core.app.policy.Policy")
|
proto.RegisterType((*Policy)(nil), "v2ray.core.app.policy.Policy")
|
||||||
proto.RegisterType((*Policy_Timeout)(nil), "v2ray.core.app.policy.Policy.Timeout")
|
proto.RegisterType((*Policy_Timeout)(nil), "v2ray.core.app.policy.Policy.Timeout")
|
||||||
proto.RegisterType((*Policy_Stats)(nil), "v2ray.core.app.policy.Policy.Stats")
|
proto.RegisterType((*Policy_Stats)(nil), "v2ray.core.app.policy.Policy.Stats")
|
||||||
|
proto.RegisterType((*SystemPolicy)(nil), "v2ray.core.app.policy.SystemPolicy")
|
||||||
|
proto.RegisterType((*SystemPolicy_Stats)(nil), "v2ray.core.app.policy.SystemPolicy.Stats")
|
||||||
proto.RegisterType((*Config)(nil), "v2ray.core.app.policy.Config")
|
proto.RegisterType((*Config)(nil), "v2ray.core.app.policy.Config")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { proto.RegisterFile("v2ray.com/core/app/policy/config.proto", fileDescriptor0) }
|
func init() { proto.RegisterFile("v2ray.com/core/app/policy/config.proto", fileDescriptor0) }
|
||||||
|
|
||||||
var fileDescriptor0 = []byte{
|
var fileDescriptor0 = []byte{
|
||||||
// 410 bytes of a gzipped FileDescriptorProto
|
// 478 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x5d, 0xab, 0xd3, 0x30,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0xdf, 0x6e, 0xd3, 0x30,
|
||||||
0x18, 0xc7, 0x69, 0x6b, 0x7b, 0x8e, 0x4f, 0xcf, 0x54, 0x82, 0x07, 0xea, 0x40, 0x3d, 0x6c, 0x28,
|
0x18, 0xc5, 0x95, 0x96, 0x66, 0xe3, 0x6b, 0xbb, 0x4d, 0x16, 0x93, 0x4a, 0x25, 0x60, 0xea, 0x34,
|
||||||
0xbb, 0x4a, 0xa1, 0xbb, 0xf1, 0x05, 0x27, 0xce, 0x17, 0x10, 0x14, 0x47, 0xe6, 0x0b, 0x78, 0x33,
|
0xd4, 0xdd, 0xb8, 0x52, 0x76, 0x03, 0x4c, 0x0c, 0x31, 0xfe, 0x48, 0x48, 0x20, 0x26, 0x97, 0x3f,
|
||||||
0x62, 0x1a, 0x5d, 0x59, 0x96, 0x84, 0xbe, 0x4c, 0xfa, 0x35, 0xfc, 0x06, 0xde, 0xfa, 0xc9, 0xfc,
|
0x82, 0x9b, 0xca, 0x73, 0x0c, 0x8b, 0xea, 0xd8, 0x56, 0xe2, 0x14, 0xe5, 0x35, 0x78, 0x8c, 0x3d,
|
||||||
0x18, 0xd2, 0xa4, 0xa5, 0x37, 0xdb, 0xdc, 0x5d, 0xfa, 0xf0, 0xfb, 0xff, 0x78, 0x12, 0xfe, 0x85,
|
0x14, 0xd7, 0x3c, 0x06, 0x8a, 0xed, 0x2c, 0x1b, 0x5a, 0xb7, 0xde, 0x25, 0x47, 0xbf, 0x73, 0x74,
|
||||||
0x87, 0xbb, 0x24, 0xa7, 0x35, 0x66, 0x6a, 0x1b, 0x33, 0x95, 0xf3, 0x98, 0x6a, 0x1d, 0x6b, 0x25,
|
0x3e, 0xdb, 0x1f, 0x3c, 0x5e, 0x44, 0x19, 0x2d, 0x31, 0x53, 0xe9, 0x84, 0xa9, 0x8c, 0x4f, 0xa8,
|
||||||
0x32, 0x56, 0xc7, 0x4c, 0xc9, 0xef, 0xd9, 0x0f, 0xac, 0x73, 0x55, 0x2a, 0x74, 0xd9, 0x71, 0x39,
|
0xd6, 0x13, 0xad, 0x44, 0xc2, 0xca, 0x09, 0x53, 0xf2, 0x47, 0xf2, 0x13, 0xeb, 0x4c, 0x19, 0x85,
|
||||||
0xc7, 0x54, 0x6b, 0x6c, 0x99, 0xd1, 0x3d, 0x08, 0x96, 0x9c, 0x29, 0x99, 0xa2, 0xdb, 0xe0, 0xef,
|
0xb6, 0x6b, 0x2e, 0xe3, 0x98, 0x6a, 0x8d, 0x1d, 0x33, 0x7a, 0x08, 0xe1, 0x94, 0x33, 0x25, 0x63,
|
||||||
0xa8, 0xa8, 0x78, 0xe4, 0x5c, 0x39, 0x93, 0x01, 0xb1, 0x1f, 0xa3, 0xbf, 0x1e, 0x04, 0x0b, 0x83,
|
0x74, 0x0f, 0x3a, 0x0b, 0x2a, 0x0a, 0x3e, 0x08, 0x76, 0x82, 0x71, 0x9f, 0xb8, 0x9f, 0xd1, 0xdf,
|
||||||
0xa2, 0xe7, 0x70, 0x56, 0x66, 0x5b, 0xae, 0xaa, 0xd2, 0x20, 0x61, 0xf2, 0x00, 0xef, 0x75, 0x62,
|
0x36, 0x84, 0x27, 0x16, 0x45, 0x2f, 0x60, 0xcd, 0x24, 0x29, 0x57, 0x85, 0xb1, 0x48, 0x37, 0xda,
|
||||||
0xcb, 0xe3, 0x8f, 0x16, 0x26, 0x5d, 0x0a, 0x3d, 0x06, 0xbf, 0x28, 0x69, 0x59, 0x44, 0xae, 0x89,
|
0xc3, 0xd7, 0x66, 0x62, 0xc7, 0xe3, 0x4f, 0x0e, 0x26, 0xb5, 0x0b, 0x3d, 0x85, 0x4e, 0x6e, 0xa8,
|
||||||
0x8f, 0x8f, 0xc7, 0x97, 0x0d, 0x4a, 0x6c, 0x62, 0xf8, 0xcb, 0x85, 0xb3, 0xd6, 0x87, 0x9e, 0xc2,
|
0xc9, 0x07, 0x2d, 0x6b, 0xdf, 0xbd, 0xd9, 0x3e, 0xad, 0x50, 0xe2, 0x1c, 0xc3, 0xdf, 0x2d, 0x58,
|
||||||
0xf5, 0x35, 0x95, 0x69, 0xb1, 0xa6, 0x1b, 0xde, 0x6e, 0x72, 0xf7, 0x80, 0xca, 0x5e, 0x8d, 0xf4,
|
0xf3, 0x79, 0xe8, 0x10, 0xee, 0x9e, 0x51, 0x19, 0xe7, 0x67, 0x74, 0xce, 0x7d, 0x93, 0x07, 0x4b,
|
||||||
0x3c, 0x7a, 0x03, 0x37, 0x99, 0x92, 0x92, 0xb3, 0x32, 0x53, 0x72, 0x95, 0xa5, 0x82, 0xb7, 0xdb,
|
0xa2, 0xdc, 0x68, 0xa4, 0xe1, 0xd1, 0x5b, 0xd8, 0x64, 0x4a, 0x4a, 0xce, 0x4c, 0xa2, 0xe4, 0x2c,
|
||||||
0xfc, 0x47, 0x71, 0xa3, 0x4f, 0xbd, 0x4d, 0x05, 0x47, 0x33, 0x08, 0x2b, 0x2d, 0x32, 0xb9, 0x59,
|
0x89, 0x05, 0xf7, 0x6d, 0x6e, 0x89, 0xd8, 0x68, 0x5c, 0xef, 0x62, 0xc1, 0xd1, 0x11, 0x74, 0x0b,
|
||||||
0x29, 0x29, 0xea, 0xc8, 0x3b, 0xc5, 0x01, 0x36, 0xf1, 0x41, 0x8a, 0x1a, 0xcd, 0x61, 0x90, 0xaa,
|
0x2d, 0x12, 0x39, 0x9f, 0x29, 0x29, 0xca, 0x41, 0x7b, 0x95, 0x0c, 0x70, 0x8e, 0x8f, 0x52, 0x94,
|
||||||
0x9f, 0xb2, 0x37, 0x5c, 0x3b, 0xc5, 0x70, 0xd1, 0x65, 0x1a, 0xc7, 0xf0, 0x3d, 0xf8, 0xe6, 0x91,
|
0xe8, 0x18, 0xfa, 0xb1, 0xfa, 0x25, 0x9b, 0x84, 0x3b, 0xab, 0x24, 0xf4, 0x6a, 0x4f, 0x95, 0x31,
|
||||||
0xd0, 0x7d, 0x08, 0xab, 0x82, 0xe7, 0x2b, 0xeb, 0x37, 0x6f, 0x72, 0x4e, 0xa0, 0x19, 0x7d, 0x32,
|
0xfc, 0x00, 0x1d, 0x7b, 0x48, 0xe8, 0x11, 0x74, 0x8b, 0x9c, 0x67, 0x33, 0x97, 0x6f, 0xcf, 0x64,
|
||||||
0x13, 0x34, 0x86, 0x81, 0x01, 0xba, 0xb8, 0xb9, 0xf3, 0x39, 0xb9, 0x68, 0x86, 0xaf, 0xda, 0xd9,
|
0x9d, 0x40, 0x25, 0x7d, 0xb6, 0x0a, 0xda, 0x85, 0xbe, 0x05, 0x6a, 0xbb, 0x9d, 0x79, 0x9d, 0xf4,
|
||||||
0xe8, 0xb7, 0x03, 0xc1, 0x4b, 0x53, 0x19, 0x34, 0x03, 0x5f, 0xf0, 0x1d, 0x17, 0x91, 0x73, 0xe5,
|
0x2a, 0xf1, 0xb5, 0xd7, 0x46, 0xe7, 0x01, 0xf4, 0xa6, 0x65, 0x6e, 0x78, 0x7a, 0x71, 0xe1, 0xfe,
|
||||||
0x4d, 0xc2, 0x64, 0x72, 0x60, 0x2b, 0x4b, 0xe3, 0x77, 0x0d, 0xfa, 0x5a, 0x96, 0x79, 0x4d, 0x6c,
|
0xbe, 0xdc, 0x21, 0xef, 0x2f, 0xeb, 0x76, 0xc9, 0x73, 0xf5, 0xd6, 0xbe, 0xd5, 0x05, 0xf7, 0x60,
|
||||||
0x6c, 0xf8, 0x05, 0xa0, 0x1f, 0xa2, 0x5b, 0xe0, 0x6d, 0x78, 0xdd, 0xf6, 0xaa, 0x39, 0xa2, 0x69,
|
0x23, 0x91, 0xa7, 0xaa, 0x90, 0xf1, 0xd5, 0x8e, 0x7d, 0xaf, 0xfa, 0x9a, 0xfb, 0xb0, 0x55, 0x63,
|
||||||
0xd7, 0xb5, 0xe3, 0x6f, 0x6f, 0x9b, 0xd0, 0x56, 0xf1, 0x89, 0xfb, 0xc8, 0x99, 0x3f, 0x83, 0x3b,
|
0xff, 0x35, 0xdd, 0xf4, 0xfa, 0x45, 0xd9, 0x3f, 0x01, 0x84, 0xaf, 0xec, 0xfb, 0x46, 0x47, 0xd0,
|
||||||
0x4c, 0x6d, 0xf7, 0xe3, 0x0b, 0xe7, 0x6b, 0x60, 0x4f, 0x7f, 0xdc, 0xcb, 0xcf, 0x09, 0xa1, 0xcd,
|
0x11, 0x7c, 0xc1, 0xc5, 0x20, 0xd8, 0x69, 0x8f, 0xbb, 0xd1, 0x78, 0x49, 0x4d, 0x47, 0xe3, 0xf7,
|
||||||
0x82, 0x39, 0xc7, 0x2f, 0xb4, 0x6e, 0x4d, 0xdf, 0x02, 0xf3, 0x2f, 0x4c, 0xff, 0x05, 0x00, 0x00,
|
0x15, 0xfa, 0x46, 0x9a, 0xac, 0x24, 0xce, 0x86, 0x0e, 0x21, 0xcc, 0xed, 0x08, 0xb7, 0xbc, 0xcb,
|
||||||
0xff, 0xff, 0x98, 0xa8, 0x2f, 0xbe, 0x35, 0x03, 0x00, 0x00,
|
0xcb, 0x73, 0x12, 0x6f, 0x19, 0x7e, 0x05, 0x68, 0x12, 0xd1, 0x16, 0xb4, 0xe7, 0xbc, 0xf4, 0x1b,
|
||||||
|
0x54, 0x7d, 0xa2, 0x83, 0x7a, 0xab, 0x6e, 0x7e, 0x65, 0x3e, 0xd5, 0xb1, 0xcf, 0x5a, 0x4f, 0x82,
|
||||||
|
0xe3, 0xe7, 0x70, 0x9f, 0xa9, 0xf4, 0x7a, 0xfc, 0x24, 0xf8, 0x1e, 0xba, 0xaf, 0xf3, 0xd6, 0xf6,
|
||||||
|
0x97, 0x88, 0xd0, 0x6a, 0xba, 0x8c, 0xe3, 0x97, 0x5a, 0xfb, 0xa4, 0xd3, 0xd0, 0x6e, 0xfd, 0xc1,
|
||||||
|
0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0x9f, 0x00, 0x31, 0x1f, 0x04, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,16 @@ message Policy {
|
||||||
Stats stats = 2;
|
Stats stats = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message SystemPolicy {
|
||||||
|
message Stats {
|
||||||
|
bool inbound_uplink = 1;
|
||||||
|
bool inbound_downlink = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stats stats = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
map<uint32, Policy> level = 1;
|
map<uint32, Policy> level = 1;
|
||||||
|
SystemPolicy system = 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,14 @@ import (
|
||||||
// Instance is an instance of Policy manager.
|
// Instance is an instance of Policy manager.
|
||||||
type Instance struct {
|
type Instance struct {
|
||||||
levels map[uint32]*Policy
|
levels map[uint32]*Policy
|
||||||
|
system *SystemPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates new Policy manager instance.
|
// New creates new Policy manager instance.
|
||||||
func New(ctx context.Context, config *Config) (*Instance, error) {
|
func New(ctx context.Context, config *Config) (*Instance, error) {
|
||||||
m := &Instance{
|
m := &Instance{
|
||||||
levels: make(map[uint32]*Policy),
|
levels: make(map[uint32]*Policy),
|
||||||
|
system: config.System,
|
||||||
}
|
}
|
||||||
if len(config.Level) > 0 {
|
if len(config.Level) > 0 {
|
||||||
for lv, p := range config.Level {
|
for lv, p := range config.Level {
|
||||||
|
@ -43,6 +45,13 @@ func (m *Instance) ForLevel(level uint32) core.Policy {
|
||||||
return core.DefaultPolicy()
|
return core.DefaultPolicy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Instance) ForSystem() core.SystemPolicy {
|
||||||
|
if m.system == nil {
|
||||||
|
return core.SystemPolicy{}
|
||||||
|
}
|
||||||
|
return m.system.ToCorePolicy()
|
||||||
|
}
|
||||||
|
|
||||||
// Start implements common.Runnable.Start().
|
// Start implements common.Runnable.Start().
|
||||||
func (m *Instance) Start() error {
|
func (m *Instance) Start() error {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -3,6 +3,7 @@ package inbound
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"v2ray.com/core"
|
||||||
"v2ray.com/core/app/proxyman"
|
"v2ray.com/core/app/proxyman"
|
||||||
"v2ray.com/core/app/proxyman/mux"
|
"v2ray.com/core/app/proxyman/mux"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
|
@ -11,6 +12,30 @@ import (
|
||||||
"v2ray.com/core/proxy"
|
"v2ray.com/core/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func getStatCounter(v *core.Instance, tag string) (core.StatCounter, core.StatCounter) {
|
||||||
|
var uplinkCounter core.StatCounter
|
||||||
|
var downlinkCounter core.StatCounter
|
||||||
|
|
||||||
|
policy := v.PolicyManager()
|
||||||
|
stats := v.Stats()
|
||||||
|
if len(tag) > 0 && policy.ForSystem().Stats.InboundUplink {
|
||||||
|
name := "inbound>>>" + tag + ">>>traffic>>>uplink"
|
||||||
|
c, _ := core.GetOrRegisterStatCounter(stats, name)
|
||||||
|
if c != nil {
|
||||||
|
uplinkCounter = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(tag) > 0 && policy.ForSystem().Stats.InboundDownlink {
|
||||||
|
name := "inbound>>>" + tag + ">>>traffic>>>downlink"
|
||||||
|
c, _ := core.GetOrRegisterStatCounter(stats, name)
|
||||||
|
if c != nil {
|
||||||
|
downlinkCounter = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uplinkCounter, downlinkCounter
|
||||||
|
}
|
||||||
|
|
||||||
type AlwaysOnInboundHandler struct {
|
type AlwaysOnInboundHandler struct {
|
||||||
proxy proxy.Inbound
|
proxy proxy.Inbound
|
||||||
workers []worker
|
workers []worker
|
||||||
|
@ -34,6 +59,8 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
||||||
tag: tag,
|
tag: tag,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uplinkCounter, downlinkCounter := getStatCounter(core.MustFromContext(ctx), tag)
|
||||||
|
|
||||||
nl := p.Network()
|
nl := p.Network()
|
||||||
pr := receiverConfig.PortRange
|
pr := receiverConfig.PortRange
|
||||||
address := receiverConfig.Listen.AsAddress()
|
address := receiverConfig.Listen.AsAddress()
|
||||||
|
@ -44,26 +71,30 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
||||||
if nl.HasNetwork(net.Network_TCP) {
|
if nl.HasNetwork(net.Network_TCP) {
|
||||||
newError("creating stream worker on ", address, ":", port).AtDebug().WriteToLog()
|
newError("creating stream worker on ", address, ":", port).AtDebug().WriteToLog()
|
||||||
worker := &tcpWorker{
|
worker := &tcpWorker{
|
||||||
address: address,
|
address: address,
|
||||||
port: net.Port(port),
|
port: net.Port(port),
|
||||||
proxy: p,
|
proxy: p,
|
||||||
stream: receiverConfig.StreamSettings,
|
stream: receiverConfig.StreamSettings,
|
||||||
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffers: receiverConfig.DomainOverride,
|
sniffers: receiverConfig.DomainOverride,
|
||||||
|
uplinkCounter: uplinkCounter,
|
||||||
|
downlinkCounter: downlinkCounter,
|
||||||
}
|
}
|
||||||
h.workers = append(h.workers, worker)
|
h.workers = append(h.workers, worker)
|
||||||
}
|
}
|
||||||
|
|
||||||
if nl.HasNetwork(net.Network_UDP) {
|
if nl.HasNetwork(net.Network_UDP) {
|
||||||
worker := &udpWorker{
|
worker := &udpWorker{
|
||||||
tag: tag,
|
tag: tag,
|
||||||
proxy: p,
|
proxy: p,
|
||||||
address: address,
|
address: address,
|
||||||
port: net.Port(port),
|
port: net.Port(port),
|
||||||
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
|
uplinkCounter: uplinkCounter,
|
||||||
|
downlinkCounter: downlinkCounter,
|
||||||
}
|
}
|
||||||
h.workers = append(h.workers, worker)
|
h.workers = append(h.workers, worker)
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,9 @@ func (h *DynamicInboundHandler) refresh() error {
|
||||||
if address == nil {
|
if address == nil {
|
||||||
address = net.AnyIP
|
address = net.AnyIP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uplinkCounter, downlinkCounter := getStatCounter(h.v, h.tag)
|
||||||
|
|
||||||
for i := uint32(0); i < concurrency; i++ {
|
for i := uint32(0); i < concurrency; i++ {
|
||||||
port := h.allocatePort()
|
port := h.allocatePort()
|
||||||
rawProxy, err := h.v.CreateObject(h.proxyConfig)
|
rawProxy, err := h.v.CreateObject(h.proxyConfig)
|
||||||
|
@ -101,14 +104,16 @@ func (h *DynamicInboundHandler) refresh() error {
|
||||||
nl := p.Network()
|
nl := p.Network()
|
||||||
if nl.HasNetwork(net.Network_TCP) {
|
if nl.HasNetwork(net.Network_TCP) {
|
||||||
worker := &tcpWorker{
|
worker := &tcpWorker{
|
||||||
tag: h.tag,
|
tag: h.tag,
|
||||||
address: address,
|
address: address,
|
||||||
port: port,
|
port: port,
|
||||||
proxy: p,
|
proxy: p,
|
||||||
stream: h.receiverConfig.StreamSettings,
|
stream: h.receiverConfig.StreamSettings,
|
||||||
recvOrigDest: h.receiverConfig.ReceiveOriginalDestination,
|
recvOrigDest: h.receiverConfig.ReceiveOriginalDestination,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffers: h.receiverConfig.DomainOverride,
|
sniffers: h.receiverConfig.DomainOverride,
|
||||||
|
uplinkCounter: uplinkCounter,
|
||||||
|
downlinkCounter: downlinkCounter,
|
||||||
}
|
}
|
||||||
if err := worker.Start(); err != nil {
|
if err := worker.Start(); err != nil {
|
||||||
newError("failed to create TCP worker").Base(err).AtWarning().WriteToLog()
|
newError("failed to create TCP worker").Base(err).AtWarning().WriteToLog()
|
||||||
|
@ -119,12 +124,14 @@ func (h *DynamicInboundHandler) refresh() error {
|
||||||
|
|
||||||
if nl.HasNetwork(net.Network_UDP) {
|
if nl.HasNetwork(net.Network_UDP) {
|
||||||
worker := &udpWorker{
|
worker := &udpWorker{
|
||||||
tag: h.tag,
|
tag: h.tag,
|
||||||
proxy: p,
|
proxy: p,
|
||||||
address: address,
|
address: address,
|
||||||
port: port,
|
port: port,
|
||||||
recvOrigDest: h.receiverConfig.ReceiveOriginalDestination,
|
recvOrigDest: h.receiverConfig.ReceiveOriginalDestination,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
|
uplinkCounter: uplinkCounter,
|
||||||
|
downlinkCounter: downlinkCounter,
|
||||||
}
|
}
|
||||||
if err := worker.Start(); err != nil {
|
if err := worker.Start(); err != nil {
|
||||||
newError("failed to create UDP worker").Base(err).AtWarning().WriteToLog()
|
newError("failed to create UDP worker").Base(err).AtWarning().WriteToLog()
|
||||||
|
|
|
@ -7,13 +7,12 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"v2ray.com/core/common/session"
|
|
||||||
|
|
||||||
"v2ray.com/core"
|
"v2ray.com/core"
|
||||||
"v2ray.com/core/app/proxyman"
|
"v2ray.com/core/app/proxyman"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
|
"v2ray.com/core/common/session"
|
||||||
"v2ray.com/core/common/signal"
|
"v2ray.com/core/common/signal"
|
||||||
"v2ray.com/core/proxy"
|
"v2ray.com/core/proxy"
|
||||||
"v2ray.com/core/transport/internet"
|
"v2ray.com/core/transport/internet"
|
||||||
|
@ -29,14 +28,16 @@ type worker interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type tcpWorker struct {
|
type tcpWorker struct {
|
||||||
address net.Address
|
address net.Address
|
||||||
port net.Port
|
port net.Port
|
||||||
proxy proxy.Inbound
|
proxy proxy.Inbound
|
||||||
stream *internet.StreamConfig
|
stream *internet.StreamConfig
|
||||||
recvOrigDest bool
|
recvOrigDest bool
|
||||||
tag string
|
tag string
|
||||||
dispatcher core.Dispatcher
|
dispatcher core.Dispatcher
|
||||||
sniffers []proxyman.KnownProtocols
|
sniffers []proxyman.KnownProtocols
|
||||||
|
uplinkCounter core.StatCounter
|
||||||
|
downlinkCounter core.StatCounter
|
||||||
|
|
||||||
hub internet.Listener
|
hub internet.Listener
|
||||||
}
|
}
|
||||||
|
@ -63,6 +64,13 @@ func (w *tcpWorker) callback(conn internet.Connection) {
|
||||||
if len(w.sniffers) > 0 {
|
if len(w.sniffers) > 0 {
|
||||||
ctx = proxyman.ContextWithProtocolSniffers(ctx, w.sniffers)
|
ctx = proxyman.ContextWithProtocolSniffers(ctx, w.sniffers)
|
||||||
}
|
}
|
||||||
|
if w.uplinkCounter != nil || w.downlinkCounter != nil {
|
||||||
|
conn = &internet.StatCouterConnection{
|
||||||
|
Connection: conn,
|
||||||
|
Uplink: w.uplinkCounter,
|
||||||
|
Downlink: w.downlinkCounter,
|
||||||
|
}
|
||||||
|
}
|
||||||
if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher); err != nil {
|
if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher); err != nil {
|
||||||
newError("connection ends").Base(err).WithContext(ctx).WriteToLog()
|
newError("connection ends").Base(err).WithContext(ctx).WriteToLog()
|
||||||
}
|
}
|
||||||
|
@ -108,6 +116,8 @@ type udpConn struct {
|
||||||
remote net.Addr
|
remote net.Addr
|
||||||
local net.Addr
|
local net.Addr
|
||||||
done *signal.Done
|
done *signal.Done
|
||||||
|
uplink core.StatCounter
|
||||||
|
downlink core.StatCounter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpConn) updateActivity() {
|
func (c *udpConn) updateActivity() {
|
||||||
|
@ -119,7 +129,11 @@ func (c *udpConn) Read(buf []byte) (int, error) {
|
||||||
case in := <-c.input:
|
case in := <-c.input:
|
||||||
defer in.Release()
|
defer in.Release()
|
||||||
c.updateActivity()
|
c.updateActivity()
|
||||||
return copy(buf, in.Bytes()), nil
|
nBytes := copy(buf, in.Bytes())
|
||||||
|
if c.uplink != nil {
|
||||||
|
c.uplink.Add(int64(nBytes))
|
||||||
|
}
|
||||||
|
return nBytes, nil
|
||||||
case <-c.done.C():
|
case <-c.done.C():
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
|
@ -128,6 +142,9 @@ func (c *udpConn) Read(buf []byte) (int, error) {
|
||||||
// Write implements io.Writer.
|
// Write implements io.Writer.
|
||||||
func (c *udpConn) Write(buf []byte) (int, error) {
|
func (c *udpConn) Write(buf []byte) (int, error) {
|
||||||
n, err := c.output(buf)
|
n, err := c.output(buf)
|
||||||
|
if c.downlink != nil {
|
||||||
|
c.downlink.Add(int64(n))
|
||||||
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.updateActivity()
|
c.updateActivity()
|
||||||
}
|
}
|
||||||
|
@ -167,13 +184,15 @@ type connID struct {
|
||||||
type udpWorker struct {
|
type udpWorker struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
|
|
||||||
proxy proxy.Inbound
|
proxy proxy.Inbound
|
||||||
hub *udp.Hub
|
hub *udp.Hub
|
||||||
address net.Address
|
address net.Address
|
||||||
port net.Port
|
port net.Port
|
||||||
recvOrigDest bool
|
recvOrigDest bool
|
||||||
tag string
|
tag string
|
||||||
dispatcher core.Dispatcher
|
dispatcher core.Dispatcher
|
||||||
|
uplinkCounter core.StatCounter
|
||||||
|
downlinkCounter core.StatCounter
|
||||||
|
|
||||||
done *signal.Done
|
done *signal.Done
|
||||||
activeConn map[connID]*udpConn
|
activeConn map[connID]*udpConn
|
||||||
|
@ -200,7 +219,9 @@ func (w *udpWorker) getConnection(id connID) (*udpConn, bool) {
|
||||||
IP: w.address.IP(),
|
IP: w.address.IP(),
|
||||||
Port: int(w.port),
|
Port: int(w.port),
|
||||||
},
|
},
|
||||||
done: signal.NewDone(),
|
done: signal.NewDone(),
|
||||||
|
uplink: w.uplinkCounter,
|
||||||
|
downlink: w.downlinkCounter,
|
||||||
}
|
}
|
||||||
w.activeConn[id] = conn
|
w.activeConn[id] = conn
|
||||||
|
|
||||||
|
|
18
policy.go
18
policy.go
|
@ -27,6 +27,17 @@ type StatsPolicy struct {
|
||||||
UserDownlink bool
|
UserDownlink bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SystemStatsPolicy struct {
|
||||||
|
// Whether or not to enable stat counter for uplink traffic in inbound handlers.
|
||||||
|
InboundUplink bool
|
||||||
|
// Whether or not to enable stat counter for downlink traffic in inbound handlers.
|
||||||
|
InboundDownlink bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type SystemPolicy struct {
|
||||||
|
Stats SystemStatsPolicy
|
||||||
|
}
|
||||||
|
|
||||||
// Policy is session based settings for controlling V2Ray requests. It contains various settings (or limits) that may differ for different users in the context.
|
// Policy is session based settings for controlling V2Ray requests. It contains various settings (or limits) that may differ for different users in the context.
|
||||||
type Policy struct {
|
type Policy struct {
|
||||||
Timeouts TimeoutPolicy // Timeout settings
|
Timeouts TimeoutPolicy // Timeout settings
|
||||||
|
@ -39,6 +50,9 @@ type PolicyManager interface {
|
||||||
|
|
||||||
// ForLevel returns the Policy for the given user level.
|
// ForLevel returns the Policy for the given user level.
|
||||||
ForLevel(level uint32) Policy
|
ForLevel(level uint32) Policy
|
||||||
|
|
||||||
|
// ForSystem returns the Policy for V2Ray system.
|
||||||
|
ForSystem() SystemPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultPolicy returns the Policy when user is not specified.
|
// DefaultPolicy returns the Policy when user is not specified.
|
||||||
|
@ -47,8 +61,8 @@ func DefaultPolicy() Policy {
|
||||||
Timeouts: TimeoutPolicy{
|
Timeouts: TimeoutPolicy{
|
||||||
Handshake: time.Second * 4,
|
Handshake: time.Second * 4,
|
||||||
ConnectionIdle: time.Second * 300,
|
ConnectionIdle: time.Second * 300,
|
||||||
UplinkOnly: time.Second * 5,
|
UplinkOnly: time.Second * 2,
|
||||||
DownlinkOnly: time.Second * 30,
|
DownlinkOnly: time.Second * 5,
|
||||||
},
|
},
|
||||||
Stats: StatsPolicy{
|
Stats: StatsPolicy{
|
||||||
UserUplink: false,
|
UserUplink: false,
|
||||||
|
|
10
stats.go
10
stats.go
|
@ -17,6 +17,16 @@ type StatManager interface {
|
||||||
GetCounter(string) StatCounter
|
GetCounter(string) StatCounter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetOrRegisterStatCounter tries to get the StatCounter first. If not exist, it then tries to create a new counter.
|
||||||
|
func GetOrRegisterStatCounter(m StatManager, name string) (StatCounter, error) {
|
||||||
|
counter := m.GetCounter(name)
|
||||||
|
if counter != nil {
|
||||||
|
return counter, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.RegisterCounter(name)
|
||||||
|
}
|
||||||
|
|
||||||
type syncStatManager struct {
|
type syncStatManager struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
StatManager
|
StatManager
|
||||||
|
|
|
@ -395,10 +395,16 @@ func TestCommanderStats(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
System: &policy.SystemPolicy{
|
||||||
|
Stats: &policy.SystemPolicy_Stats{
|
||||||
|
InboundUplink: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
Inbound: []*core.InboundHandlerConfig{
|
Inbound: []*core.InboundHandlerConfig{
|
||||||
{
|
{
|
||||||
|
Tag: "vmess",
|
||||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||||
PortRange: net.SinglePortRange(serverPort),
|
PortRange: net.SinglePortRange(serverPort),
|
||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
|
@ -521,5 +527,12 @@ func TestCommanderStats(t *testing.T) {
|
||||||
assert(sresp.Stat.Name, Equals, name)
|
assert(sresp.Stat.Name, Equals, name)
|
||||||
assert(sresp.Stat.Value, Equals, int64(0))
|
assert(sresp.Stat.Value, Equals, int64(0))
|
||||||
|
|
||||||
|
sresp, err = sClient.GetStats(context.Background(), &statscmd.GetStatsRequest{
|
||||||
|
Name: "inbound>>>vmess>>>traffic>>>uplink",
|
||||||
|
Reset_: true,
|
||||||
|
})
|
||||||
|
assert(err, IsNil)
|
||||||
|
assert(sresp.Stat.Value, Equals, int64(10240*1024))
|
||||||
|
|
||||||
CloseAllServers(servers)
|
CloseAllServers(servers)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,3 +7,30 @@ import (
|
||||||
type Connection interface {
|
type Connection interface {
|
||||||
net.Conn
|
net.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type addInt64 interface {
|
||||||
|
Add(int64) int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type StatCouterConnection struct {
|
||||||
|
Connection
|
||||||
|
Uplink addInt64
|
||||||
|
Downlink addInt64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StatCouterConnection) Read(b []byte) (int, error) {
|
||||||
|
nBytes, err := c.Connection.Read(b)
|
||||||
|
if c.Uplink != nil {
|
||||||
|
c.Uplink.Add(int64(nBytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nBytes, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StatCouterConnection) Write(b []byte) (int, error) {
|
||||||
|
nBytes, err := c.Connection.Write(b)
|
||||||
|
if c.Downlink != nil {
|
||||||
|
c.Downlink.Add(int64(nBytes))
|
||||||
|
}
|
||||||
|
return nBytes, err
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue