1package conf
2
3import (
4	"encoding/json"
5
6	"github.com/golang/protobuf/proto"
7
8	"github.com/v2fly/v2ray-core/v4/common/protocol"
9	"github.com/v2fly/v2ray-core/v4/common/serial"
10	"github.com/v2fly/v2ray-core/v4/proxy/socks"
11)
12
13type SocksAccount struct {
14	Username string `json:"user"`
15	Password string `json:"pass"`
16}
17
18func (v *SocksAccount) Build() *socks.Account {
19	return &socks.Account{
20		Username: v.Username,
21		Password: v.Password,
22	}
23}
24
25const (
26	AuthMethodNoAuth   = "noauth"
27	AuthMethodUserPass = "password"
28)
29
30type SocksServerConfig struct {
31	AuthMethod string          `json:"auth"`
32	Accounts   []*SocksAccount `json:"accounts"`
33	UDP        bool            `json:"udp"`
34	Host       *Address        `json:"ip"`
35	Timeout    uint32          `json:"timeout"`
36	UserLevel  uint32          `json:"userLevel"`
37}
38
39func (v *SocksServerConfig) Build() (proto.Message, error) {
40	config := new(socks.ServerConfig)
41	switch v.AuthMethod {
42	case AuthMethodNoAuth:
43		config.AuthType = socks.AuthType_NO_AUTH
44	case AuthMethodUserPass:
45		config.AuthType = socks.AuthType_PASSWORD
46	default:
47		// newError("unknown socks auth method: ", v.AuthMethod, ". Default to noauth.").AtWarning().WriteToLog()
48		config.AuthType = socks.AuthType_NO_AUTH
49	}
50
51	if len(v.Accounts) > 0 {
52		config.Accounts = make(map[string]string, len(v.Accounts))
53		for _, account := range v.Accounts {
54			config.Accounts[account.Username] = account.Password
55		}
56	}
57
58	config.UdpEnabled = v.UDP
59	if v.Host != nil {
60		config.Address = v.Host.Build()
61	}
62
63	config.Timeout = v.Timeout
64	config.UserLevel = v.UserLevel
65	return config, nil
66}
67
68type SocksRemoteConfig struct {
69	Address *Address          `json:"address"`
70	Port    uint16            `json:"port"`
71	Users   []json.RawMessage `json:"users"`
72}
73type SocksClientConfig struct {
74	Servers []*SocksRemoteConfig `json:"servers"`
75}
76
77func (v *SocksClientConfig) Build() (proto.Message, error) {
78	config := new(socks.ClientConfig)
79	config.Server = make([]*protocol.ServerEndpoint, len(v.Servers))
80	for idx, serverConfig := range v.Servers {
81		server := &protocol.ServerEndpoint{
82			Address: serverConfig.Address.Build(),
83			Port:    uint32(serverConfig.Port),
84		}
85		for _, rawUser := range serverConfig.Users {
86			user := new(protocol.User)
87			if err := json.Unmarshal(rawUser, user); err != nil {
88				return nil, newError("failed to parse Socks user").Base(err).AtError()
89			}
90			account := new(SocksAccount)
91			if err := json.Unmarshal(rawUser, account); err != nil {
92				return nil, newError("failed to parse socks account").Base(err).AtError()
93			}
94			user.Account = serial.ToTypedMessage(account.Build())
95			server.User = append(server.User, user)
96		}
97		config.Server[idx] = server
98	}
99	return config, nil
100}
101