change Transporter interface
This commit is contained in:
parent
346c2c27e5
commit
89d2b7b466
@ -89,15 +89,15 @@ func main() {
|
|||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// http2
|
// http2+tls, http2+tcp
|
||||||
gost.Node{
|
gost.Node{
|
||||||
Addr: "127.0.0.1:1443",
|
Addr: "127.0.0.1:1443",
|
||||||
Client: gost.NewClient(
|
Client: gost.NewClient(
|
||||||
gost.HTTP2Connector(url.UserPassword("admin", "123456")),
|
gost.HTTP2Connector(url.UserPassword("admin", "123456")),
|
||||||
gost.HTTP2Transporter(
|
gost.HTTP2Transporter(
|
||||||
nil,
|
nil,
|
||||||
&tls.Config{InsecureSkipVerify: true},
|
&tls.Config{InsecureSkipVerify: true}, // or nil, will use h2c mode (http2+tcp).
|
||||||
time.Second*60,
|
time.Second*1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -138,6 +138,6 @@ func main() {
|
|||||||
rb, _ = httputil.DumpResponse(resp, true)
|
rb, _ = httputil.DumpResponse(resp, true)
|
||||||
log.Println(string(rb))
|
log.Println(string(rb))
|
||||||
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(1000 * time.Millisecond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package gost
|
package gost
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,13 +23,13 @@ func NewClient(c Connector, tr Transporter) *Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dial connects to the target address.
|
// Dial connects to the target address.
|
||||||
func (c *Client) Dial(addr string) (net.Conn, error) {
|
func (c *Client) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
||||||
return c.Transporter.Dial(addr)
|
return c.Transporter.Dial(addr, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handshake performs a handshake with the proxy over connection conn.
|
// Handshake performs a handshake with the proxy over connection conn.
|
||||||
func (c *Client) Handshake(conn net.Conn) (net.Conn, error) {
|
func (c *Client) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
return c.Transporter.Handshake(conn)
|
return c.Transporter.Handshake(conn, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect connects to the address addr via the proxy over connection conn.
|
// Connect connects to the address addr via the proxy over connection conn.
|
||||||
@ -40,13 +41,13 @@ func (c *Client) Connect(conn net.Conn, addr string) (net.Conn, error) {
|
|||||||
var DefaultClient = NewClient(HTTPConnector(nil), TCPTransporter())
|
var DefaultClient = NewClient(HTTPConnector(nil), TCPTransporter())
|
||||||
|
|
||||||
// Dial connects to the address addr via the DefaultClient.
|
// Dial connects to the address addr via the DefaultClient.
|
||||||
func Dial(addr string) (net.Conn, error) {
|
func Dial(addr string, options ...DialOption) (net.Conn, error) {
|
||||||
return DefaultClient.Dial(addr)
|
return DefaultClient.Dial(addr, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handshake performs a handshake via the DefaultClient.
|
// Handshake performs a handshake via the DefaultClient.
|
||||||
func Handshake(conn net.Conn) (net.Conn, error) {
|
func Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
return DefaultClient.Handshake(conn)
|
return DefaultClient.Handshake(conn, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect connects to the address addr via the DefaultClient.
|
// Connect connects to the address addr via the DefaultClient.
|
||||||
@ -61,8 +62,8 @@ type Connector interface {
|
|||||||
|
|
||||||
// Transporter is responsible for handshaking with the proxy server.
|
// Transporter is responsible for handshaking with the proxy server.
|
||||||
type Transporter interface {
|
type Transporter interface {
|
||||||
Dial(addr string) (net.Conn, error)
|
Dial(addr string, options ...DialOption) (net.Conn, error)
|
||||||
Handshake(conn net.Conn) (net.Conn, error)
|
Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error)
|
||||||
// Indicate that the Transporter supports multiplex
|
// Indicate that the Transporter supports multiplex
|
||||||
Multiplex() bool
|
Multiplex() bool
|
||||||
}
|
}
|
||||||
@ -75,14 +76,56 @@ func TCPTransporter() Transporter {
|
|||||||
return &tcpTransporter{}
|
return &tcpTransporter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *tcpTransporter) Dial(addr string) (net.Conn, error) {
|
func (tr *tcpTransporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
||||||
return net.Dial("tcp", addr)
|
return net.Dial("tcp", addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *tcpTransporter) Handshake(conn net.Conn) (net.Conn, error) {
|
func (tr *tcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *tcpTransporter) Multiplex() bool {
|
func (tr *tcpTransporter) Multiplex() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DialOptions describes the options for dialing.
|
||||||
|
type DialOptions struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialOption allows a common way to set dial options.
|
||||||
|
type DialOption func(opts *DialOptions)
|
||||||
|
|
||||||
|
// HandshakeOptions describes the options for handshake.
|
||||||
|
type HandshakeOptions struct {
|
||||||
|
Addr string
|
||||||
|
TLSConfig *tls.Config
|
||||||
|
WSOptions *WSOptions
|
||||||
|
KCPConfig *KCPConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandshakeOption allows a common way to set handshake options.
|
||||||
|
type HandshakeOption func(opts *HandshakeOptions)
|
||||||
|
|
||||||
|
func AddrHandshakeOption(addr string) HandshakeOption {
|
||||||
|
return func(opts *HandshakeOptions) {
|
||||||
|
opts.Addr = addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TLSConfigHandshakeOption(config *tls.Config) HandshakeOption {
|
||||||
|
return func(opts *HandshakeOptions) {
|
||||||
|
opts.TLSConfig = config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WSOptionsHandshakeOption(options *WSOptions) HandshakeOption {
|
||||||
|
return func(opts *HandshakeOptions) {
|
||||||
|
opts.WSOptions = options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func KCPConfigHandshakeOption(config *KCPConfig) HandshakeOption {
|
||||||
|
return func(opts *HandshakeOptions) {
|
||||||
|
opts.KCPConfig = config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
186
gost/http2.go
186
gost/http2.go
@ -79,8 +79,8 @@ type http2Transporter struct {
|
|||||||
tlsConfig *tls.Config
|
tlsConfig *tls.Config
|
||||||
tr *http2.Transport
|
tr *http2.Transport
|
||||||
chain *Chain
|
chain *Chain
|
||||||
conns map[string]*http2.ClientConn
|
sessions map[string]*http2Session
|
||||||
connMutex sync.Mutex
|
sessionMutex sync.Mutex
|
||||||
pingInterval time.Duration
|
pingInterval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,93 +97,49 @@ func HTTP2Transporter(chain *Chain, config *tls.Config, ping time.Duration) Tran
|
|||||||
tr: new(http2.Transport),
|
tr: new(http2.Transport),
|
||||||
chain: chain,
|
chain: chain,
|
||||||
pingInterval: ping,
|
pingInterval: ping,
|
||||||
conns: make(map[string]*http2.ClientConn),
|
sessions: make(map[string]*http2Session),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *http2Transporter) Dial(addr string) (net.Conn, error) {
|
func (tr *http2Transporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
||||||
tr.connMutex.Lock()
|
tr.sessionMutex.Lock()
|
||||||
conn, ok := tr.conns[addr]
|
defer tr.sessionMutex.Unlock()
|
||||||
|
|
||||||
|
session, ok := tr.sessions[addr]
|
||||||
if !ok {
|
if !ok {
|
||||||
cc, err := tr.chain.Dial(addr)
|
conn, err := tr.chain.Dial(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tr.connMutex.Unlock()
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if tr.tlsConfig != nil {
|
if tr.tlsConfig != nil {
|
||||||
tc := tls.Client(cc, tr.tlsConfig)
|
tc := tls.Client(conn, tr.tlsConfig)
|
||||||
if err := tc.Handshake(); err != nil {
|
if err := tc.Handshake(); err != nil {
|
||||||
tr.connMutex.Unlock()
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cc = tc
|
conn = tc
|
||||||
}
|
}
|
||||||
conn, err = tr.tr.NewClientConn(cc)
|
cc, err := tr.tr.NewClientConn(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tr.connMutex.Unlock()
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tr.conns[addr] = conn
|
session = newHTTP2Session(conn, cc, tr.pingInterval)
|
||||||
go tr.ping(tr.pingInterval, addr, conn)
|
tr.sessions[addr] = session
|
||||||
}
|
}
|
||||||
tr.connMutex.Unlock()
|
|
||||||
|
|
||||||
if !conn.CanTakeNewRequest() {
|
if !session.Healthy() {
|
||||||
tr.connMutex.Lock()
|
session.Close()
|
||||||
delete(tr.conns, addr) // TODO: we could re-connect to the addr automatically.
|
delete(tr.sessions, addr) // TODO: we could re-connect to the addr automatically.
|
||||||
tr.connMutex.Unlock()
|
|
||||||
return nil, errors.New("connection is dead")
|
return nil, errors.New("connection is dead")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &http2DummyConn{
|
return &http2DummyConn{
|
||||||
raddr: addr,
|
raddr: addr,
|
||||||
conn: conn,
|
conn: session.clientConn,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *http2Transporter) ping(interval time.Duration, addr string, conn *http2.ClientConn) {
|
func (tr *http2Transporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
if interval <= 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Log("[http2] ping is enabled, interval:", interval)
|
|
||||||
|
|
||||||
baseCtx := context.Background()
|
|
||||||
t := time.NewTicker(interval)
|
|
||||||
retries := PingRetries
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-t.C:
|
|
||||||
if !conn.CanTakeNewRequest() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx, cancel := context.WithTimeout(baseCtx, PingTimeout)
|
|
||||||
if err := conn.Ping(ctx); err != nil {
|
|
||||||
log.Logf("[http2] ping: %s", err)
|
|
||||||
if retries > 0 {
|
|
||||||
retries--
|
|
||||||
log.Log("[http2] retry ping")
|
|
||||||
cancel()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// connection is dead, remove it.
|
|
||||||
tr.connMutex.Lock()
|
|
||||||
delete(tr.conns, addr)
|
|
||||||
tr.connMutex.Unlock()
|
|
||||||
|
|
||||||
cancel()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cancel()
|
|
||||||
retries = PingRetries
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *http2Transporter) Handshake(conn net.Conn) (net.Conn, error) {
|
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,6 +289,112 @@ func (h *http2Handler) handleFunc(w http.ResponseWriter, r *http.Request) {
|
|||||||
log.Logf("[http2] %s >-< %s", r.RemoteAddr, target)
|
log.Logf("[http2] %s >-< %s", r.RemoteAddr, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type http2Listener struct {
|
||||||
|
ln net.Listener
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTP2Listener creates a Listener for server using HTTP2 as transport.
|
||||||
|
func HTTP2Listener(addr string, config *tls.Config) (Listener, error) {
|
||||||
|
var ln net.Listener
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if config != nil {
|
||||||
|
ln, err = tls.Listen("tcp", addr, config)
|
||||||
|
} else {
|
||||||
|
ln, err = net.Listen("tcp", addr)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ln, err
|
||||||
|
//return &http2Listener{ln: ln}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type http2Session struct {
|
||||||
|
conn net.Conn
|
||||||
|
clientConn *http2.ClientConn
|
||||||
|
closeChan chan struct{}
|
||||||
|
pingChan chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newHTTP2Session(conn net.Conn, clientConn *http2.ClientConn, interval time.Duration) *http2Session {
|
||||||
|
session := &http2Session{
|
||||||
|
conn: conn,
|
||||||
|
clientConn: clientConn,
|
||||||
|
closeChan: make(chan struct{}),
|
||||||
|
}
|
||||||
|
if interval > 0 {
|
||||||
|
session.pingChan = make(chan struct{})
|
||||||
|
go session.Ping(interval)
|
||||||
|
}
|
||||||
|
return session
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *http2Session) Ping(interval time.Duration) {
|
||||||
|
if interval <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer close(s.pingChan)
|
||||||
|
log.Log("[http2] ping is enabled, interval:", interval)
|
||||||
|
|
||||||
|
baseCtx := context.Background()
|
||||||
|
t := time.NewTicker(interval)
|
||||||
|
retries := PingRetries
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-t.C:
|
||||||
|
if Debug {
|
||||||
|
log.Log("[http2] sending ping")
|
||||||
|
}
|
||||||
|
if !s.clientConn.CanTakeNewRequest() {
|
||||||
|
log.Logf("[http2] connection is dead")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithTimeout(baseCtx, PingTimeout)
|
||||||
|
if err := s.clientConn.Ping(ctx); err != nil {
|
||||||
|
log.Logf("[http2] ping: %s", err)
|
||||||
|
if retries > 0 {
|
||||||
|
retries--
|
||||||
|
log.Log("[http2] retry ping")
|
||||||
|
cancel()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if Debug {
|
||||||
|
log.Log("[http2] ping OK")
|
||||||
|
}
|
||||||
|
cancel()
|
||||||
|
retries = PingRetries
|
||||||
|
|
||||||
|
case <-s.closeChan:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *http2Session) Healthy() bool {
|
||||||
|
select {
|
||||||
|
case <-s.pingChan:
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return s.clientConn.CanTakeNewRequest()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *http2Session) Close() error {
|
||||||
|
select {
|
||||||
|
case <-s.closeChan:
|
||||||
|
default:
|
||||||
|
close(s.closeChan)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// HTTP2 connection, wrapped up just like a net.Conn
|
// HTTP2 connection, wrapped up just like a net.Conn
|
||||||
type http2Conn struct {
|
type http2Conn struct {
|
||||||
r io.Reader
|
r io.Reader
|
||||||
|
10
gost/kcp.go
10
gost/kcp.go
@ -179,25 +179,23 @@ func KCPTransporter(config *KCPConfig) Transporter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *kcpTransporter) Dial(addr string) (conn net.Conn, err error) {
|
func (tr *kcpTransporter) Dial(addr string, options ...DialOption) (conn net.Conn, err error) {
|
||||||
tr.sessionMutex.Lock()
|
tr.sessionMutex.Lock()
|
||||||
|
defer tr.sessionMutex.Unlock()
|
||||||
|
|
||||||
session, ok := tr.sessions[addr]
|
session, ok := tr.sessions[addr]
|
||||||
if !ok {
|
if !ok {
|
||||||
session, err = tr.dial(addr, tr.config)
|
session, err = tr.dial(addr, tr.config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tr.sessionMutex.Unlock()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tr.sessions[addr] = session
|
tr.sessions[addr] = session
|
||||||
}
|
}
|
||||||
tr.sessionMutex.Unlock()
|
|
||||||
|
|
||||||
conn, err = session.GetConn()
|
conn, err = session.GetConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tr.sessionMutex.Lock()
|
|
||||||
session.Close()
|
session.Close()
|
||||||
delete(tr.sessions, addr) // TODO: we could obtain a new session automatically.
|
delete(tr.sessions, addr) // TODO: we could obtain a new session automatically.
|
||||||
tr.sessionMutex.Unlock()
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -241,7 +239,7 @@ func (tr *kcpTransporter) dial(addr string, config *KCPConfig) (*kcpSession, err
|
|||||||
return &kcpSession{conn: conn, session: session}, nil
|
return &kcpSession{conn: conn, session: session}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *kcpTransporter) Handshake(conn net.Conn) (net.Conn, error) {
|
func (tr *kcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,8 +189,8 @@ func http2Server() {
|
|||||||
s.Handle(gost.HTTP2Handler(
|
s.Handle(gost.HTTP2Handler(
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
))
|
))
|
||||||
ln, err := gost.TLSListener(":1443", tlsConfig())
|
ln, err := gost.TLSListener(":1443", tlsConfig()) // HTTP2 h2 mode
|
||||||
// ln, err := gost.TCPListener(":1443")
|
// ln, err := gost.TCPListener(":1443") // HTTP2 h2c mode
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
18
gost/tls.go
18
gost/tls.go
@ -6,21 +6,27 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type tlsTransporter struct {
|
type tlsTransporter struct {
|
||||||
tlsConfig *tls.Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TLSTransporter creates a Transporter that is used by TLS proxy client.
|
// TLSTransporter creates a Transporter that is used by TLS proxy client.
|
||||||
// It accepts a TLS config for TLS handshake.
|
// It accepts a TLS config for TLS handshake.
|
||||||
func TLSTransporter(cfg *tls.Config) Transporter {
|
func TLSTransporter() Transporter {
|
||||||
return &tlsTransporter{tlsConfig: cfg}
|
return &tlsTransporter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *tlsTransporter) Dial(addr string) (net.Conn, error) {
|
func (tr *tlsTransporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
||||||
return net.Dial("tcp", addr)
|
return net.Dial("tcp", addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *tlsTransporter) Handshake(conn net.Conn) (net.Conn, error) {
|
func (tr *tlsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
return tls.Client(conn, tr.tlsConfig), nil
|
opts := &HandshakeOptions{}
|
||||||
|
for _, option := range options {
|
||||||
|
option(opts)
|
||||||
|
}
|
||||||
|
if opts.TLSConfig == nil {
|
||||||
|
opts.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||||
|
}
|
||||||
|
return tls.Client(conn, opts.TLSConfig), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *tlsTransporter) Multiplex() bool {
|
func (tr *tlsTransporter) Multiplex() bool {
|
||||||
|
48
gost/ws.go
48
gost/ws.go
@ -27,14 +27,14 @@ type websocketConn struct {
|
|||||||
rb []byte
|
rb []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func websocketClientConn(url string, conn net.Conn, options *WSOptions) (net.Conn, error) {
|
func websocketClientConn(url string, conn net.Conn, tlsConfig *tls.Config, options *WSOptions) (net.Conn, error) {
|
||||||
if options == nil {
|
if options == nil {
|
||||||
options = &WSOptions{}
|
options = &WSOptions{}
|
||||||
}
|
}
|
||||||
dialer := websocket.Dialer{
|
dialer := websocket.Dialer{
|
||||||
ReadBufferSize: options.ReadBufferSize,
|
ReadBufferSize: options.ReadBufferSize,
|
||||||
WriteBufferSize: options.WriteBufferSize,
|
WriteBufferSize: options.WriteBufferSize,
|
||||||
TLSClientConfig: options.TLSConfig,
|
TLSClientConfig: tlsConfig,
|
||||||
HandshakeTimeout: options.HandshakeTimeout,
|
HandshakeTimeout: options.HandshakeTimeout,
|
||||||
EnableCompression: options.EnableCompression,
|
EnableCompression: options.EnableCompression,
|
||||||
NetDial: func(net, addr string) (net.Conn, error) {
|
NetDial: func(net, addr string) (net.Conn, error) {
|
||||||
@ -98,26 +98,31 @@ func (c *websocketConn) SetWriteDeadline(t time.Time) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type wsTransporter struct {
|
type wsTransporter struct {
|
||||||
addr string
|
|
||||||
options *WSOptions
|
options *WSOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// WSTransporter creates a Transporter that is used by websocket proxy client.
|
// WSTransporter creates a Transporter that is used by websocket proxy client.
|
||||||
func WSTransporter(addr string, opts *WSOptions) Transporter {
|
func WSTransporter(opts *WSOptions) Transporter {
|
||||||
return &wsTransporter{
|
return &wsTransporter{
|
||||||
addr: addr,
|
|
||||||
options: opts,
|
options: opts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *wsTransporter) Dial(addr string) (net.Conn, error) {
|
func (tr *wsTransporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
||||||
tr.addr = addr // NOTE: the addr must match the initial tr.addr
|
|
||||||
return net.Dial("tcp", addr)
|
return net.Dial("tcp", addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *wsTransporter) Handshake(conn net.Conn) (net.Conn, error) {
|
func (tr *wsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
url := url.URL{Scheme: "ws", Host: tr.addr, Path: "/ws"}
|
opts := &HandshakeOptions{}
|
||||||
return websocketClientConn(url.String(), conn, tr.options)
|
for _, option := range options {
|
||||||
|
option(opts)
|
||||||
|
}
|
||||||
|
wsOptions := tr.options
|
||||||
|
if opts.WSOptions != nil {
|
||||||
|
wsOptions = opts.WSOptions
|
||||||
|
}
|
||||||
|
url := url.URL{Scheme: "ws", Host: opts.Addr, Path: "/ws"}
|
||||||
|
return websocketClientConn(url.String(), conn, nil, wsOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *wsTransporter) Multiplex() bool {
|
func (tr *wsTransporter) Multiplex() bool {
|
||||||
@ -125,25 +130,34 @@ func (tr *wsTransporter) Multiplex() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type wssTransporter struct {
|
type wssTransporter struct {
|
||||||
addr string
|
|
||||||
options *WSOptions
|
options *WSOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// WSSTransporter creates a Transporter that is used by websocket secure proxy client.
|
// WSSTransporter creates a Transporter that is used by websocket secure proxy client.
|
||||||
func WSSTransporter(addr string, opts *WSOptions) Transporter {
|
func WSSTransporter(opts *WSOptions) Transporter {
|
||||||
return &wssTransporter{
|
return &wssTransporter{
|
||||||
addr: addr,
|
|
||||||
options: opts,
|
options: opts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *wssTransporter) Dial(addr string) (net.Conn, error) {
|
func (tr *wssTransporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
||||||
return net.Dial("tcp", addr)
|
return net.Dial("tcp", addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *wssTransporter) Handshake(conn net.Conn) (net.Conn, error) {
|
func (tr *wssTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
url := url.URL{Scheme: "wss", Host: tr.addr, Path: "/ws"}
|
opts := &HandshakeOptions{}
|
||||||
return websocketClientConn(url.String(), conn, tr.options)
|
for _, option := range options {
|
||||||
|
option(opts)
|
||||||
|
}
|
||||||
|
wsOptions := tr.options
|
||||||
|
if opts.WSOptions != nil {
|
||||||
|
wsOptions = opts.WSOptions
|
||||||
|
}
|
||||||
|
if opts.TLSConfig == nil {
|
||||||
|
opts.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||||
|
}
|
||||||
|
url := url.URL{Scheme: "wss", Host: opts.Addr, Path: "/ws"}
|
||||||
|
return websocketClientConn(url.String(), conn, opts.TLSConfig, wsOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *wssTransporter) Multiplex() bool {
|
func (tr *wssTransporter) Multiplex() bool {
|
||||||
|
Loading…
Reference in New Issue
Block a user