forked from fossabot/clash
-
Notifications
You must be signed in to change notification settings - Fork 1
/
adapters.go
275 lines (234 loc) · 5.44 KB
/
adapters.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
package constant
import (
"context"
"encoding/json"
"fmt"
"net"
"time"
"github.com/Dreamacro/clash/component/dialer"
)
// Adapter Type
const (
Direct AdapterType = iota
Reject
Shadowsocks
ShadowsocksR
Snell
Socks5
Http
Vmess
Trojan
Ssh
Relay
Selector
Fallback
URLTest
LoadBalance
AutoSelector
)
const (
DefaultTCPTimeout = 5 * time.Second
DefaultUDPTimeout = DefaultTCPTimeout
DefaultTLSTimeout = DefaultTCPTimeout
)
type Connection interface {
Chains() Chain
AppendToChains(adapter ProxyAdapter)
}
type Chain []string
func (c Chain) String() string {
switch len(c) {
case 0:
return ""
case 1:
return c[0]
default:
return fmt.Sprintf("%s[%s]", c[len(c)-1], c[0])
}
}
func (c Chain) Last() string {
switch len(c) {
case 0:
return ""
default:
return c[0]
}
}
type Conn interface {
net.Conn
Connection
}
type PacketConn interface {
net.PacketConn
Connection
// Deprecate WriteWithMetadata because of remote resolve DNS cause TURN failed
// WriteWithMetadata(p []byte, metadata *Metadata) (n int, err error)
}
type ProxyAdapter interface {
Name() string
Type() AdapterType
Addr() string
SupportUDP() bool
MarshalJSON() ([]byte, error)
// StreamConn wraps a protocol around net.Conn with Metadata.
//
// Examples:
// conn, _ := net.DialContext(context.Background(), "tcp", "host:port")
// conn, _ = adapter.StreamConn(conn, metadata)
//
// It returns a C.Conn with protocol which start with
// a new session (if any)
StreamConn(c net.Conn, metadata *Metadata) (net.Conn, error)
// DialContext return a C.Conn with protocol which
// contains multiplexing-related reuse logic (if any)
DialContext(ctx context.Context, metadata *Metadata, opts ...dialer.Option) (Conn, error)
ListenPacketContext(ctx context.Context, metadata *Metadata, opts ...dialer.Option) (PacketConn, error)
// Unwrap extracts the proxy from a proxy-group. It returns nil when nothing to extract.
Unwrap(metadata *Metadata) Proxy
}
type DelayHistory struct {
Time time.Time `json:"time"`
Delay uint16 `json:"delay"`
}
type Proxy interface {
ProxyAdapter
Alive() bool
DelayHistory() []DelayHistory
LastDelay() uint16
URLTest(ctx context.Context, url string) (uint16, error)
// Deprecated: use DialContext instead.
Dial(metadata *Metadata) (Conn, error)
// Deprecated: use DialPacketConn instead.
DialUDP(metadata *Metadata) (PacketConn, error)
}
type InboundType uint8
const (
InboundTypeHTTP InboundType = iota
InboundTypeSOCKS
InboundTypeDirect
)
func (t InboundType) String() string {
return [...]string{"http", "socks", "direct"}[t]
}
func (t *InboundType) FromString(kind string) InboundType {
return map[string]InboundType{
"http": InboundTypeHTTP,
"socks": InboundTypeSOCKS,
"direct": InboundTypeDirect,
}[kind]
}
func (t InboundType) MarshalJSON() ([]byte, error) {
return json.Marshal(t.String())
}
func (t *InboundType) UnmarshalJSON(b []byte) error {
var s string
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
*t = t.FromString(s)
return nil
}
type ProxyType uint8
const (
ProxyTypeDirect ProxyType = iota
ProxyTypeHttp
ProxyTypeReject
ProxyTypeShadowSocks
ProxyTypeShadowSocksR
ProxyTypeSnell
ProxyTypeSocks5
ProxyTypeTrojan
ProxyTypeVmess
ProxyTypeSsh
)
func (t ProxyType) String() string {
return [...]string{"direct", "http", "reject", "ss", "ssr", "snell", "socks5", "trojan", "vmess", "ssh"}[t]
}
func (t *ProxyType) FromString(kind string) ProxyType {
return map[string]ProxyType{
"direct": ProxyTypeDirect,
"http": ProxyTypeHttp,
"reject": ProxyTypeReject,
"ss": ProxyTypeShadowSocks,
"ssr": ProxyTypeShadowSocksR,
"snell": ProxyTypeSnell,
"socks5": ProxyTypeSocks5,
"trojan": ProxyTypeTrojan,
"vmess": ProxyTypeVmess,
"ssh": ProxyTypeSsh,
}[kind]
}
func (t ProxyType) MarshalJSON() ([]byte, error) {
return json.Marshal(t.String())
}
func (t *ProxyType) UnmarshalJSON(b []byte) error {
var s string
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
*t = t.FromString(s)
return nil
}
type Inbound interface {
Name() string
Type() InboundType
RawAddress() string
GetRawConfigString() string
Close()
}
// AdapterType is enum of adapter type
type AdapterType int
func (at AdapterType) String() string {
switch at {
case Direct:
return "Direct"
case Reject:
return "Reject"
case Shadowsocks:
return "Shadowsocks"
case ShadowsocksR:
return "ShadowsocksR"
case Snell:
return "Snell"
case Socks5:
return "Socks5"
case Ssh:
return "Ssh"
case Http:
return "Http"
case Vmess:
return "Vmess"
case Trojan:
return "Trojan"
case Relay:
return "Relay"
case Selector:
return "Selector"
case Fallback:
return "Fallback"
case URLTest:
return "URLTest"
case LoadBalance:
return "LoadBalance"
case AutoSelector:
return "AutoSelector"
default:
return "Unknown"
}
}
// UDPPacket contains the data of UDP packet, and offers control/info of UDP packet's source
type UDPPacket interface {
// Data get the payload of UDP Packet
Data() []byte
// WriteBack writes the payload with source IP/Port equals addr
// - variable source IP/Port is important to STUN
// - if addr is not provided, WriteBack will write out UDP packet with SourceIP/Port equals to original Target,
// this is important when using Fake-IP.
WriteBack(b []byte, addr net.Addr) (n int, err error)
// Drop call after packet is used, could recycle buffer in this function.
Drop()
// LocalAddr returns the source IP/Port of packet
LocalAddr() net.Addr
}