Chore: improve outbound architecture
This commit is contained in:
parent
373a6cad22
commit
c8366739ee
13 changed files with 105 additions and 239 deletions
26
adapters/outbound/base.go
Normal file
26
adapters/outbound/base.go
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package adapters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Base struct {
|
||||||
|
name string
|
||||||
|
tp C.AdapterType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Base) Name() string {
|
||||||
|
return b.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Base) Type() C.AdapterType {
|
||||||
|
return b.tp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Base) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(map[string]string{
|
||||||
|
"type": b.Type().String(),
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,38 +1,16 @@
|
||||||
package adapters
|
package adapters
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DirectAdapter is a directly connected adapter
|
type Direct struct {
|
||||||
type DirectAdapter struct {
|
*Base
|
||||||
conn net.Conn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close is used to close connection
|
func (d *Direct) Generator(metadata *C.Metadata) (net.Conn, error) {
|
||||||
func (d *DirectAdapter) Close() {
|
|
||||||
d.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conn is used to http request
|
|
||||||
func (d *DirectAdapter) Conn() net.Conn {
|
|
||||||
return d.conn
|
|
||||||
}
|
|
||||||
|
|
||||||
type Direct struct{}
|
|
||||||
|
|
||||||
func (d *Direct) Name() string {
|
|
||||||
return "DIRECT"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Direct) Type() C.AdapterType {
|
|
||||||
return C.Direct
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Direct) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err error) {
|
|
||||||
address := net.JoinHostPort(metadata.Host, metadata.Port)
|
address := net.JoinHostPort(metadata.Host, metadata.Port)
|
||||||
if metadata.IP != nil {
|
if metadata.IP != nil {
|
||||||
address = net.JoinHostPort(metadata.IP.String(), metadata.Port)
|
address = net.JoinHostPort(metadata.IP.String(), metadata.Port)
|
||||||
|
@ -40,18 +18,17 @@ func (d *Direct) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err er
|
||||||
|
|
||||||
c, err := net.DialTimeout("tcp", address, tcpTimeout)
|
c, err := net.DialTimeout("tcp", address, tcpTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
tcpKeepAlive(c)
|
tcpKeepAlive(c)
|
||||||
return &DirectAdapter{conn: c}, nil
|
return c, nil
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Direct) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(map[string]string{
|
|
||||||
"type": d.Type().String(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDirect() *Direct {
|
func NewDirect() *Direct {
|
||||||
return &Direct{}
|
return &Direct{
|
||||||
|
Base: &Base{
|
||||||
|
name: "DIRECT",
|
||||||
|
tp: C.Direct,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package adapters
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ type proxy struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Fallback struct {
|
type Fallback struct {
|
||||||
name string
|
*Base
|
||||||
proxies []*proxy
|
proxies []*proxy
|
||||||
rawURL string
|
rawURL string
|
||||||
interval time.Duration
|
interval time.Duration
|
||||||
|
@ -29,14 +30,6 @@ type FallbackOption struct {
|
||||||
Interval int `proxy:"interval"`
|
Interval int `proxy:"interval"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Fallback) Name() string {
|
|
||||||
return f.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Fallback) Type() C.AdapterType {
|
|
||||||
return C.Fallback
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Fallback) Now() string {
|
func (f *Fallback) Now() string {
|
||||||
_, proxy := f.findNextValidProxy(0)
|
_, proxy := f.findNextValidProxy(0)
|
||||||
if proxy != nil {
|
if proxy != nil {
|
||||||
|
@ -45,7 +38,7 @@ func (f *Fallback) Now() string {
|
||||||
return f.proxies[0].RawProxy.Name()
|
return f.proxies[0].RawProxy.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Fallback) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err error) {
|
func (f *Fallback) Generator(metadata *C.Metadata) (net.Conn, error) {
|
||||||
idx := 0
|
idx := 0
|
||||||
var proxy *proxy
|
var proxy *proxy
|
||||||
for {
|
for {
|
||||||
|
@ -53,13 +46,13 @@ func (f *Fallback) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err
|
||||||
if proxy == nil {
|
if proxy == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
adapter, err = proxy.RawProxy.Generator(metadata)
|
adapter, err := proxy.RawProxy.Generator(metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
proxy.Valid = false
|
proxy.Valid = false
|
||||||
idx++
|
idx++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return
|
return adapter, err
|
||||||
}
|
}
|
||||||
return f.proxies[0].RawProxy.Generator(metadata)
|
return f.proxies[0].RawProxy.Generator(metadata)
|
||||||
}
|
}
|
||||||
|
@ -138,7 +131,10 @@ func NewFallback(option FallbackOption, proxies []C.Proxy) (*Fallback, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Fallback := &Fallback{
|
Fallback := &Fallback{
|
||||||
name: option.Name,
|
Base: &Base{
|
||||||
|
name: option.Name,
|
||||||
|
tp: C.Fallback,
|
||||||
|
},
|
||||||
proxies: warpperProxies,
|
proxies: warpperProxies,
|
||||||
rawURL: option.URL,
|
rawURL: option.URL,
|
||||||
interval: interval,
|
interval: interval,
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -16,23 +15,9 @@ import (
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HTTPAdapter is a proxy adapter
|
|
||||||
type HTTPAdapter struct {
|
|
||||||
conn net.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close is used to close connection
|
|
||||||
func (ha *HTTPAdapter) Close() {
|
|
||||||
ha.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ha *HTTPAdapter) Conn() net.Conn {
|
|
||||||
return ha.conn
|
|
||||||
}
|
|
||||||
|
|
||||||
type Http struct {
|
type Http struct {
|
||||||
|
*Base
|
||||||
addr string
|
addr string
|
||||||
name string
|
|
||||||
user string
|
user string
|
||||||
pass string
|
pass string
|
||||||
tls bool
|
tls bool
|
||||||
|
@ -50,15 +35,7 @@ type HttpOption struct {
|
||||||
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Http) Name() string {
|
func (h *Http) Generator(metadata *C.Metadata) (net.Conn, error) {
|
||||||
return h.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Http) Type() C.AdapterType {
|
|
||||||
return C.Http
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Http) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err error) {
|
|
||||||
c, err := net.DialTimeout("tcp", h.addr, tcpTimeout)
|
c, err := net.DialTimeout("tcp", h.addr, tcpTimeout)
|
||||||
if err == nil && h.tls {
|
if err == nil && h.tls {
|
||||||
cc := tls.Client(c, h.tlsConfig)
|
cc := tls.Client(c, h.tlsConfig)
|
||||||
|
@ -74,7 +51,7 @@ func (h *Http) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err erro
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &HTTPAdapter{conn: c}, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Http) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error {
|
func (h *Http) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error {
|
||||||
|
@ -118,12 +95,6 @@ func (h *Http) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error {
|
||||||
return fmt.Errorf("can not connect remote err code: %d", resp.StatusCode)
|
return fmt.Errorf("can not connect remote err code: %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Http) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(map[string]string{
|
|
||||||
"type": h.Type().String(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewHttp(option HttpOption) *Http {
|
func NewHttp(option HttpOption) *Http {
|
||||||
var tlsConfig *tls.Config
|
var tlsConfig *tls.Config
|
||||||
if option.TLS {
|
if option.TLS {
|
||||||
|
@ -137,8 +108,11 @@ func NewHttp(option HttpOption) *Http {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Http{
|
return &Http{
|
||||||
|
Base: &Base{
|
||||||
|
name: option.Name,
|
||||||
|
tp: C.Http,
|
||||||
|
},
|
||||||
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
||||||
name: option.Name,
|
|
||||||
user: option.UserName,
|
user: option.UserName,
|
||||||
pass: option.Password,
|
pass: option.Password,
|
||||||
tls: option.TLS,
|
tls: option.TLS,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package adapters
|
package adapters
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
@ -9,42 +8,21 @@ import (
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RejectAdapter is a reject connected adapter
|
|
||||||
type RejectAdapter struct {
|
|
||||||
conn net.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close is used to close connection
|
|
||||||
func (r *RejectAdapter) Close() {}
|
|
||||||
|
|
||||||
// Conn is used to http request
|
|
||||||
func (r *RejectAdapter) Conn() net.Conn {
|
|
||||||
return r.conn
|
|
||||||
}
|
|
||||||
|
|
||||||
type Reject struct {
|
type Reject struct {
|
||||||
|
*Base
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reject) Name() string {
|
func (r *Reject) Generator(metadata *C.Metadata) (net.Conn, error) {
|
||||||
return "REJECT"
|
return &NopConn{}, nil
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Reject) Type() C.AdapterType {
|
|
||||||
return C.Reject
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Reject) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err error) {
|
|
||||||
return &RejectAdapter{conn: &NopConn{}}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Reject) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(map[string]string{
|
|
||||||
"type": r.Type().String(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewReject() *Reject {
|
func NewReject() *Reject {
|
||||||
return &Reject{}
|
return &Reject{
|
||||||
|
Base: &Base{
|
||||||
|
name: "REJECT",
|
||||||
|
tp: C.Reject,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type NopConn struct{}
|
type NopConn struct{}
|
||||||
|
|
|
@ -3,13 +3,14 @@ package adapters
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Selector struct {
|
type Selector struct {
|
||||||
name string
|
*Base
|
||||||
selected C.Proxy
|
selected C.Proxy
|
||||||
proxies map[string]C.Proxy
|
proxies map[string]C.Proxy
|
||||||
}
|
}
|
||||||
|
@ -19,15 +20,7 @@ type SelectorOption struct {
|
||||||
Proxies []string `proxy:"proxies"`
|
Proxies []string `proxy:"proxies"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Selector) Name() string {
|
func (s *Selector) Generator(metadata *C.Metadata) (net.Conn, error) {
|
||||||
return s.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Selector) Type() C.AdapterType {
|
|
||||||
return C.Selector
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Selector) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err error) {
|
|
||||||
return s.selected.Generator(metadata)
|
return s.selected.Generator(metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +61,10 @@ func NewSelector(name string, proxies []C.Proxy) (*Selector, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &Selector{
|
s := &Selector{
|
||||||
name: name,
|
Base: &Base{
|
||||||
|
name: name,
|
||||||
|
tp: C.Selector,
|
||||||
|
},
|
||||||
proxies: mapping,
|
proxies: mapping,
|
||||||
selected: proxies[0],
|
selected: proxies[0],
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,30 +7,16 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/component/simple-obfs"
|
obfs "github.com/Dreamacro/clash/component/simple-obfs"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
|
||||||
"github.com/Dreamacro/go-shadowsocks2/core"
|
"github.com/Dreamacro/go-shadowsocks2/core"
|
||||||
"github.com/Dreamacro/go-shadowsocks2/socks"
|
"github.com/Dreamacro/go-shadowsocks2/socks"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ShadowsocksAdapter is a shadowsocks adapter
|
|
||||||
type ShadowsocksAdapter struct {
|
|
||||||
conn net.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close is used to close connection
|
|
||||||
func (ss *ShadowsocksAdapter) Close() {
|
|
||||||
ss.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *ShadowsocksAdapter) Conn() net.Conn {
|
|
||||||
return ss.conn
|
|
||||||
}
|
|
||||||
|
|
||||||
type ShadowSocks struct {
|
type ShadowSocks struct {
|
||||||
|
*Base
|
||||||
server string
|
server string
|
||||||
name string
|
|
||||||
obfs string
|
obfs string
|
||||||
obfsHost string
|
obfsHost string
|
||||||
cipher core.Cipher
|
cipher core.Cipher
|
||||||
|
@ -46,15 +32,7 @@ type ShadowSocksOption struct {
|
||||||
ObfsHost string `proxy:"obfs-host,omitempty"`
|
ObfsHost string `proxy:"obfs-host,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *ShadowSocks) Name() string {
|
func (ss *ShadowSocks) Generator(metadata *C.Metadata) (net.Conn, error) {
|
||||||
return ss.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *ShadowSocks) Type() C.AdapterType {
|
|
||||||
return C.Shadowsocks
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *ShadowSocks) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err error) {
|
|
||||||
c, err := net.DialTimeout("tcp", ss.server, tcpTimeout)
|
c, err := net.DialTimeout("tcp", ss.server, tcpTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error", ss.server)
|
return nil, fmt.Errorf("%s connect error", ss.server)
|
||||||
|
@ -69,7 +47,7 @@ func (ss *ShadowSocks) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter,
|
||||||
}
|
}
|
||||||
c = ss.cipher.StreamConn(c)
|
c = ss.cipher.StreamConn(c)
|
||||||
_, err = c.Write(serializesSocksAddr(metadata))
|
_, err = c.Write(serializesSocksAddr(metadata))
|
||||||
return &ShadowsocksAdapter{conn: c}, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *ShadowSocks) MarshalJSON() ([]byte, error) {
|
func (ss *ShadowSocks) MarshalJSON() ([]byte, error) {
|
||||||
|
@ -94,8 +72,11 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ShadowSocks{
|
return &ShadowSocks{
|
||||||
|
Base: &Base{
|
||||||
|
name: option.Name,
|
||||||
|
tp: C.Shadowsocks,
|
||||||
|
},
|
||||||
server: server,
|
server: server,
|
||||||
name: option.Name,
|
|
||||||
cipher: ciph,
|
cipher: ciph,
|
||||||
obfs: obfs,
|
obfs: obfs,
|
||||||
obfsHost: obfsHost,
|
obfsHost: obfsHost,
|
||||||
|
|
|
@ -3,7 +3,6 @@ package adapters
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -15,23 +14,9 @@ import (
|
||||||
"github.com/Dreamacro/go-shadowsocks2/socks"
|
"github.com/Dreamacro/go-shadowsocks2/socks"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Socks5Adapter is a shadowsocks adapter
|
|
||||||
type Socks5Adapter struct {
|
|
||||||
conn net.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close is used to close connection
|
|
||||||
func (ss *Socks5Adapter) Close() {
|
|
||||||
ss.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *Socks5Adapter) Conn() net.Conn {
|
|
||||||
return ss.conn
|
|
||||||
}
|
|
||||||
|
|
||||||
type Socks5 struct {
|
type Socks5 struct {
|
||||||
|
*Base
|
||||||
addr string
|
addr string
|
||||||
name string
|
|
||||||
user string
|
user string
|
||||||
pass string
|
pass string
|
||||||
tls bool
|
tls bool
|
||||||
|
@ -49,15 +34,7 @@ type Socks5Option struct {
|
||||||
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *Socks5) Name() string {
|
func (ss *Socks5) Generator(metadata *C.Metadata) (net.Conn, error) {
|
||||||
return ss.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *Socks5) Type() C.AdapterType {
|
|
||||||
return C.Socks5
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *Socks5) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err error) {
|
|
||||||
c, err := net.DialTimeout("tcp", ss.addr, tcpTimeout)
|
c, err := net.DialTimeout("tcp", ss.addr, tcpTimeout)
|
||||||
|
|
||||||
if err == nil && ss.tls {
|
if err == nil && ss.tls {
|
||||||
|
@ -73,13 +50,7 @@ func (ss *Socks5) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err e
|
||||||
if err := ss.shakeHand(metadata, c); err != nil {
|
if err := ss.shakeHand(metadata, c); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &Socks5Adapter{conn: c}, nil
|
return c, nil
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *Socks5) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(map[string]string{
|
|
||||||
"type": ss.Type().String(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *Socks5) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error {
|
func (ss *Socks5) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error {
|
||||||
|
@ -154,8 +125,11 @@ func NewSocks5(option Socks5Option) *Socks5 {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Socks5{
|
return &Socks5{
|
||||||
|
Base: &Base{
|
||||||
|
name: option.Name,
|
||||||
|
tp: C.Socks5,
|
||||||
|
},
|
||||||
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
||||||
name: option.Name,
|
|
||||||
user: option.UserName,
|
user: option.UserName,
|
||||||
pass: option.Password,
|
pass: option.Password,
|
||||||
tls: option.TLS,
|
tls: option.TLS,
|
||||||
|
|
|
@ -3,6 +3,7 @@ package adapters
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
@ -12,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type URLTest struct {
|
type URLTest struct {
|
||||||
name string
|
*Base
|
||||||
proxies []C.Proxy
|
proxies []C.Proxy
|
||||||
rawURL string
|
rawURL string
|
||||||
fast C.Proxy
|
fast C.Proxy
|
||||||
|
@ -28,19 +29,11 @@ type URLTestOption struct {
|
||||||
Interval int `proxy:"interval"`
|
Interval int `proxy:"interval"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *URLTest) Name() string {
|
|
||||||
return u.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *URLTest) Type() C.AdapterType {
|
|
||||||
return C.URLTest
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *URLTest) Now() string {
|
func (u *URLTest) Now() string {
|
||||||
return u.fast.Name()
|
return u.fast.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *URLTest) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err error) {
|
func (u *URLTest) Generator(metadata *C.Metadata) (net.Conn, error) {
|
||||||
a, err := u.fast.Generator(metadata)
|
a, err := u.fast.Generator(metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
go u.speedTest()
|
go u.speedTest()
|
||||||
|
@ -128,7 +121,10 @@ func NewURLTest(option URLTestOption, proxies []C.Proxy) (*URLTest, error) {
|
||||||
|
|
||||||
interval := time.Duration(option.Interval) * time.Second
|
interval := time.Duration(option.Interval) * time.Second
|
||||||
urlTest := &URLTest{
|
urlTest := &URLTest{
|
||||||
name: option.Name,
|
Base: &Base{
|
||||||
|
name: option.Name,
|
||||||
|
tp: C.URLTest,
|
||||||
|
},
|
||||||
proxies: proxies[:],
|
proxies: proxies[:],
|
||||||
rawURL: option.URL,
|
rawURL: option.URL,
|
||||||
fast: proxies[0],
|
fast: proxies[0],
|
||||||
|
|
|
@ -36,7 +36,7 @@ func DelayTest(proxy C.Proxy, url string) (t int16, err error) {
|
||||||
defer instance.Close()
|
defer instance.Close()
|
||||||
transport := &http.Transport{
|
transport := &http.Transport{
|
||||||
Dial: func(string, string) (net.Conn, error) {
|
Dial: func(string, string) (net.Conn, error) {
|
||||||
return instance.Conn(), nil
|
return instance, nil
|
||||||
},
|
},
|
||||||
// from http.DefaultTransport
|
// from http.DefaultTransport
|
||||||
MaxIdleConns: 100,
|
MaxIdleConns: 100,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package adapters
|
package adapters
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -11,22 +10,8 @@ import (
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VmessAdapter is a vmess adapter
|
|
||||||
type VmessAdapter struct {
|
|
||||||
conn net.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close is used to close connection
|
|
||||||
func (v *VmessAdapter) Close() {
|
|
||||||
v.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *VmessAdapter) Conn() net.Conn {
|
|
||||||
return v.conn
|
|
||||||
}
|
|
||||||
|
|
||||||
type Vmess struct {
|
type Vmess struct {
|
||||||
name string
|
*Base
|
||||||
server string
|
server string
|
||||||
client *vmess.Client
|
client *vmess.Client
|
||||||
}
|
}
|
||||||
|
@ -45,28 +30,14 @@ type VmessOption struct {
|
||||||
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Vmess) Name() string {
|
func (v *Vmess) Generator(metadata *C.Metadata) (net.Conn, error) {
|
||||||
return v.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *Vmess) Type() C.AdapterType {
|
|
||||||
return C.Vmess
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *Vmess) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err error) {
|
|
||||||
c, err := net.DialTimeout("tcp", v.server, tcpTimeout)
|
c, err := net.DialTimeout("tcp", v.server, tcpTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error", v.server)
|
return nil, fmt.Errorf("%s connect error", v.server)
|
||||||
}
|
}
|
||||||
tcpKeepAlive(c)
|
tcpKeepAlive(c)
|
||||||
c, err = v.client.New(c, parseVmessAddr(metadata))
|
c, err = v.client.New(c, parseVmessAddr(metadata))
|
||||||
return &VmessAdapter{conn: c}, err
|
return c, err
|
||||||
}
|
|
||||||
|
|
||||||
func (v *Vmess) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(map[string]interface{}{
|
|
||||||
"type": v.Type().String(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVmess(option VmessOption) (*Vmess, error) {
|
func NewVmess(option VmessOption) (*Vmess, error) {
|
||||||
|
@ -89,7 +60,10 @@ func NewVmess(option VmessOption) (*Vmess, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Vmess{
|
return &Vmess{
|
||||||
name: option.Name,
|
Base: &Base{
|
||||||
|
name: option.Name,
|
||||||
|
tp: C.Vmess,
|
||||||
|
},
|
||||||
server: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
server: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
||||||
client: client,
|
client: client,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
|
@ -17,11 +17,6 @@ const (
|
||||||
Vmess
|
Vmess
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProxyAdapter interface {
|
|
||||||
Conn() net.Conn
|
|
||||||
Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
type ServerAdapter interface {
|
type ServerAdapter interface {
|
||||||
Metadata() *Metadata
|
Metadata() *Metadata
|
||||||
Close()
|
Close()
|
||||||
|
@ -30,7 +25,7 @@ type ServerAdapter interface {
|
||||||
type Proxy interface {
|
type Proxy interface {
|
||||||
Name() string
|
Name() string
|
||||||
Type() AdapterType
|
Type() AdapterType
|
||||||
Generator(metadata *Metadata) (ProxyAdapter, error)
|
Generator(metadata *Metadata) (net.Conn, error)
|
||||||
MarshalJSON() ([]byte, error)
|
MarshalJSON() ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/adapters/inbound"
|
adapters "github.com/Dreamacro/clash/adapters/inbound"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -22,8 +21,8 @@ const (
|
||||||
|
|
||||||
var bufPool = sync.Pool{New: func() interface{} { return make([]byte, bufferSize) }}
|
var bufPool = sync.Pool{New: func() interface{} { return make([]byte, bufferSize) }}
|
||||||
|
|
||||||
func (t *Tunnel) handleHTTP(request *adapters.HTTPAdapter, proxy C.ProxyAdapter) {
|
func (t *Tunnel) handleHTTP(request *adapters.HTTPAdapter, outbound net.Conn) {
|
||||||
conn := newTrafficTrack(proxy.Conn(), t.traffic)
|
conn := newTrafficTrack(outbound, t.traffic)
|
||||||
req := request.R
|
req := request.R
|
||||||
host := req.Host
|
host := req.Host
|
||||||
keepalive := true
|
keepalive := true
|
||||||
|
@ -76,8 +75,8 @@ func (t *Tunnel) handleHTTP(request *adapters.HTTPAdapter, proxy C.ProxyAdapter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tunnel) handleSOCKS(request *adapters.SocketAdapter, proxy C.ProxyAdapter) {
|
func (t *Tunnel) handleSOCKS(request *adapters.SocketAdapter, outbound net.Conn) {
|
||||||
conn := newTrafficTrack(proxy.Conn(), t.traffic)
|
conn := newTrafficTrack(outbound, t.traffic)
|
||||||
relay(request.Conn(), conn)
|
relay(request.Conn(), conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue