forked from TuanKiri/socks5
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.go
151 lines (117 loc) Β· 2.67 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package socks5
import (
"context"
"net"
"time"
)
type config struct {
host string
address string
readTimeout time.Duration
writeTimeout time.Duration
getPasswordTimeout time.Duration
authMethods map[byte]struct{}
publicIP net.IP
}
type Server struct {
config *config
logger Logger
store Store
driver Driver
metrics Metrics
rules Rules
active chan struct{}
done chan struct{}
closeListener func() error
}
func New(opts ...Option) *Server {
options := &options{}
for _, opt := range opts {
opt(options)
}
options = optsWithDefaults(options)
return &Server{
config: &config{
host: options.host,
address: options.listenAddress(),
readTimeout: options.readTimeout,
writeTimeout: options.writeTimeout,
getPasswordTimeout: options.getPasswordTimeout,
authMethods: options.authMethods(),
publicIP: options.publicIP,
},
logger: options.logger,
store: options.store,
driver: options.driver,
metrics: options.metrics,
rules: options.rules,
active: make(chan struct{}),
done: make(chan struct{}),
}
}
func (s *Server) ListenAndServe() error {
l, err := s.driver.Listen("tcp", s.config.address)
if err != nil {
return err
}
s.closeListener = closeListenerFn(l)
ctx := context.Background()
s.logger.Info(ctx, "server starting...")
for s.isActive() {
conn, err := l.Accept()
if err != nil {
if !isClosedListenerError(err) {
s.logger.Error(ctx, "failed to accept connection: "+err.Error())
}
continue
}
go s.serve(conn)
}
s.logger.Info(ctx, "server stopping...")
close(s.done)
return nil
}
func (s *Server) Shutdown() error {
if !s.isActive() {
return nil
}
close(s.active)
err := s.closeListener()
<-s.done
return err
}
func (s *Server) serve(conn net.Conn) {
defer conn.Close()
remoteAddr := conn.RemoteAddr()
if !s.rules.IsAllowConnection(remoteAddr) {
return
}
s.setConnDeadline(conn)
ctx := contextWithRemoteAddress(context.Background(), remoteAddr)
s.handshake(ctx, newConnection(conn))
}
func (s *Server) setConnDeadline(conn net.Conn) {
currentTime := time.Now().Local()
if s.config.readTimeout != 0 {
conn.SetReadDeadline(currentTime.Add(s.config.readTimeout))
}
if s.config.writeTimeout != 0 {
conn.SetWriteDeadline(currentTime.Add(s.config.writeTimeout))
}
}
func (s *Server) isActive() bool {
select {
case <-s.active:
return false
default:
return true
}
}
func closeListenerFn(l net.Listener) func() error {
return func() error {
if l == nil {
return nil
}
return l.Close()
}
}