add icmp tunnel
This commit is contained in:
42
pkg/dialer/icmp/conn.go
Normal file
42
pkg/dialer/icmp/conn.go
Normal file
@ -0,0 +1,42 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
)
|
||||
|
||||
type quicSession struct {
|
||||
session quic.Session
|
||||
}
|
||||
|
||||
func (session *quicSession) GetConn() (*quicConn, error) {
|
||||
stream, err := session.session.OpenStreamSync(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &quicConn{
|
||||
Stream: stream,
|
||||
laddr: session.session.LocalAddr(),
|
||||
raddr: session.session.RemoteAddr(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (session *quicSession) Close() error {
|
||||
return session.session.CloseWithError(quic.ApplicationErrorCode(0), "closed")
|
||||
}
|
||||
|
||||
type quicConn struct {
|
||||
quic.Stream
|
||||
laddr net.Addr
|
||||
raddr net.Addr
|
||||
}
|
||||
|
||||
func (c *quicConn) LocalAddr() net.Addr {
|
||||
return c.laddr
|
||||
}
|
||||
|
||||
func (c *quicConn) RemoteAddr() net.Addr {
|
||||
return c.raddr
|
||||
}
|
130
pkg/dialer/icmp/dialer.go
Normal file
130
pkg/dialer/icmp/dialer.go
Normal file
@ -0,0 +1,130 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
icmp_pkg "github.com/go-gost/gost/pkg/common/util/icmp"
|
||||
"github.com/go-gost/gost/pkg/dialer"
|
||||
"github.com/go-gost/gost/pkg/logger"
|
||||
md "github.com/go-gost/gost/pkg/metadata"
|
||||
"github.com/go-gost/gost/pkg/registry"
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"golang.org/x/net/icmp"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.DialerRegistry().Register("icmp", NewDialer)
|
||||
}
|
||||
|
||||
type icmpDialer struct {
|
||||
sessions map[string]*quicSession
|
||||
sessionMutex sync.Mutex
|
||||
logger logger.Logger
|
||||
md metadata
|
||||
options dialer.Options
|
||||
}
|
||||
|
||||
func NewDialer(opts ...dialer.Option) dialer.Dialer {
|
||||
options := dialer.Options{}
|
||||
for _, opt := range opts {
|
||||
opt(&options)
|
||||
}
|
||||
|
||||
return &icmpDialer{
|
||||
sessions: make(map[string]*quicSession),
|
||||
logger: options.Logger,
|
||||
options: options,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *icmpDialer) Init(md md.Metadata) (err error) {
|
||||
if err = d.parseMetadata(md); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *icmpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (conn net.Conn, err error) {
|
||||
if _, _, err := net.SplitHostPort(addr); err != nil {
|
||||
addr = net.JoinHostPort(addr, "0")
|
||||
}
|
||||
|
||||
raddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.sessionMutex.Lock()
|
||||
defer d.sessionMutex.Unlock()
|
||||
|
||||
session, ok := d.sessions[addr]
|
||||
if !ok {
|
||||
options := &dialer.DialOptions{}
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
|
||||
var pc net.PacketConn
|
||||
pc, err = icmp.ListenPacket("ip4:icmp", "")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
id := raddr.Port
|
||||
if id == 0 {
|
||||
id = rand.New(rand.NewSource(time.Now().UnixNano())).Intn(math.MaxUint16) + 1
|
||||
raddr.Port = id
|
||||
}
|
||||
pc = icmp_pkg.ClientConn(pc, id)
|
||||
|
||||
session, err = d.initSession(ctx, raddr, pc)
|
||||
if err != nil {
|
||||
d.logger.Error(err)
|
||||
pc.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.sessions[addr] = session
|
||||
}
|
||||
|
||||
conn, err = session.GetConn()
|
||||
if err != nil {
|
||||
session.Close()
|
||||
delete(d.sessions, addr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (d *icmpDialer) initSession(ctx context.Context, addr net.Addr, conn net.PacketConn) (*quicSession, error) {
|
||||
quicConfig := &quic.Config{
|
||||
KeepAlive: d.md.keepAlive,
|
||||
HandshakeIdleTimeout: d.md.handshakeTimeout,
|
||||
MaxIdleTimeout: d.md.maxIdleTimeout,
|
||||
Versions: []quic.VersionNumber{
|
||||
quic.Version1,
|
||||
quic.VersionDraft29,
|
||||
},
|
||||
}
|
||||
|
||||
tlsCfg := d.options.TLSConfig
|
||||
tlsCfg.NextProtos = []string{"http/3", "quic/v1"}
|
||||
|
||||
session, err := quic.DialContext(ctx, conn, addr, addr.String(), tlsCfg, quicConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &quicSession{session: session}, nil
|
||||
}
|
||||
|
||||
// Multiplex implements dialer.Multiplexer interface.
|
||||
func (d *icmpDialer) Multiplex() bool {
|
||||
return true
|
||||
}
|
29
pkg/dialer/icmp/metadata.go
Normal file
29
pkg/dialer/icmp/metadata.go
Normal file
@ -0,0 +1,29 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||
)
|
||||
|
||||
type metadata struct {
|
||||
keepAlive bool
|
||||
maxIdleTimeout time.Duration
|
||||
handshakeTimeout time.Duration
|
||||
}
|
||||
|
||||
func (d *icmpDialer) parseMetadata(md mdata.Metadata) (err error) {
|
||||
const (
|
||||
keepAlive = "keepAlive"
|
||||
handshakeTimeout = "handshakeTimeout"
|
||||
maxIdleTimeout = "maxIdleTimeout"
|
||||
)
|
||||
|
||||
d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout)
|
||||
|
||||
d.md.keepAlive = mdata.GetBool(md, keepAlive)
|
||||
d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout)
|
||||
d.md.maxIdleTimeout = mdata.GetDuration(md, maxIdleTimeout)
|
||||
|
||||
return
|
||||
}
|
@ -7,7 +7,6 @@ import (
|
||||
)
|
||||
|
||||
type muxSession struct {
|
||||
conn net.Conn
|
||||
session *smux.Session
|
||||
}
|
||||
|
||||
|
@ -26,17 +26,19 @@ type kcpDialer struct {
|
||||
sessionMutex sync.Mutex
|
||||
logger logger.Logger
|
||||
md metadata
|
||||
options dialer.Options
|
||||
}
|
||||
|
||||
func NewDialer(opts ...dialer.Option) dialer.Dialer {
|
||||
options := &dialer.Options{}
|
||||
options := dialer.Options{}
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
opt(&options)
|
||||
}
|
||||
|
||||
return &kcpDialer{
|
||||
sessions: make(map[string]*muxSession),
|
||||
logger: options.Logger,
|
||||
options: options,
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,12 +52,12 @@ func (d *kcpDialer) Init(md md.Metadata) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Multiplex implements dialer.Multiplexer interface.
|
||||
func (d *kcpDialer) Multiplex() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *kcpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (conn net.Conn, err error) {
|
||||
raddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.sessionMutex.Lock()
|
||||
defer d.sessionMutex.Unlock()
|
||||
|
||||
@ -70,86 +72,55 @@ func (d *kcpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
|
||||
opt(&options)
|
||||
}
|
||||
|
||||
var pc net.PacketConn
|
||||
if d.md.config.TCP {
|
||||
raddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
pc, err = tcpraw.Dial("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pc, err := tcpraw.Dial("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn = &fakeTCPConn{
|
||||
pc = &fakeTCPConn{
|
||||
raddr: raddr,
|
||||
PacketConn: pc,
|
||||
}
|
||||
} else {
|
||||
conn, err = options.NetDialer.Dial(ctx, "udp", addr)
|
||||
c, err := options.NetDialer.Dial(ctx, "udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
pc, ok = c.(net.PacketConn)
|
||||
if !ok {
|
||||
c.Close()
|
||||
return nil, errors.New("quic: wrong connection type")
|
||||
}
|
||||
}
|
||||
|
||||
session, err = d.initSession(ctx, raddr, pc)
|
||||
if err != nil {
|
||||
d.logger.Error(err)
|
||||
pc.Close()
|
||||
return nil, err
|
||||
}
|
||||
session = &muxSession{conn: conn}
|
||||
d.sessions[addr] = session
|
||||
}
|
||||
|
||||
return session.conn, err
|
||||
}
|
||||
|
||||
// Handshake implements dialer.Handshaker
|
||||
func (d *kcpDialer) Handshake(ctx context.Context, conn net.Conn, options ...dialer.HandshakeOption) (net.Conn, error) {
|
||||
opts := &dialer.HandshakeOptions{}
|
||||
for _, option := range options {
|
||||
option(opts)
|
||||
}
|
||||
|
||||
d.sessionMutex.Lock()
|
||||
defer d.sessionMutex.Unlock()
|
||||
|
||||
if d.md.handshakeTimeout > 0 {
|
||||
conn.SetDeadline(time.Now().Add(d.md.handshakeTimeout))
|
||||
defer conn.SetDeadline(time.Time{})
|
||||
}
|
||||
|
||||
session, ok := d.sessions[opts.Addr]
|
||||
if session != nil && session.conn != conn {
|
||||
conn.Close()
|
||||
return nil, errors.New("kcp: unrecognized connection")
|
||||
}
|
||||
|
||||
if !ok || session.session == nil {
|
||||
s, err := d.initSession(ctx, opts.Addr, conn)
|
||||
if err != nil {
|
||||
d.logger.Error(err)
|
||||
conn.Close()
|
||||
delete(d.sessions, opts.Addr)
|
||||
return nil, err
|
||||
}
|
||||
session = s
|
||||
d.sessions[opts.Addr] = session
|
||||
}
|
||||
cc, err := session.GetConn()
|
||||
conn, err = session.GetConn()
|
||||
if err != nil {
|
||||
session.Close()
|
||||
delete(d.sessions, opts.Addr)
|
||||
delete(d.sessions, addr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cc, nil
|
||||
return
|
||||
}
|
||||
|
||||
func (d *kcpDialer) initSession(ctx context.Context, addr string, conn net.Conn) (*muxSession, error) {
|
||||
pc, ok := conn.(net.PacketConn)
|
||||
if !ok {
|
||||
return nil, errors.New("kcp: wrong connection type")
|
||||
}
|
||||
|
||||
func (d *kcpDialer) initSession(ctx context.Context, addr net.Addr, conn net.PacketConn) (*muxSession, error) {
|
||||
config := d.md.config
|
||||
|
||||
kcpconn, err := kcp.NewConn(addr,
|
||||
kcpconn, err := kcp.NewConn(addr.String(),
|
||||
kcp_util.BlockCrypt(config.Key, config.Crypt, kcp_util.DefaultSalt),
|
||||
config.DataShard, config.ParityShard, pc)
|
||||
config.DataShard, config.ParityShard, conn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -162,15 +133,15 @@ func (d *kcpDialer) initSession(ctx context.Context, addr string, conn net.Conn)
|
||||
kcpconn.SetACKNoDelay(config.AckNodelay)
|
||||
|
||||
if config.DSCP > 0 {
|
||||
if err := kcpconn.SetDSCP(config.DSCP); err != nil {
|
||||
d.logger.Warn("SetDSCP: ", err)
|
||||
if er := kcpconn.SetDSCP(config.DSCP); er != nil {
|
||||
d.logger.Warn("SetDSCP: ", er)
|
||||
}
|
||||
}
|
||||
if err := kcpconn.SetReadBuffer(config.SockBuf); err != nil {
|
||||
d.logger.Warn("SetReadBuffer: ", err)
|
||||
if er := kcpconn.SetReadBuffer(config.SockBuf); er != nil {
|
||||
d.logger.Warn("SetReadBuffer: ", er)
|
||||
}
|
||||
if err := kcpconn.SetWriteBuffer(config.SockBuf); err != nil {
|
||||
d.logger.Warn("SetWriteBuffer: ", err)
|
||||
if er := kcpconn.SetWriteBuffer(config.SockBuf); er != nil {
|
||||
d.logger.Warn("SetWriteBuffer: ", er)
|
||||
}
|
||||
|
||||
// stream multiplex
|
||||
@ -185,5 +156,10 @@ func (d *kcpDialer) initSession(ctx context.Context, addr string, conn net.Conn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &muxSession{conn: conn, session: session}, nil
|
||||
return &muxSession{session: session}, nil
|
||||
}
|
||||
|
||||
// Multiplex implements dialer.Multiplexer interface.
|
||||
func (d *kcpDialer) Multiplex() bool {
|
||||
return true
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
)
|
||||
|
||||
type quicSession struct {
|
||||
conn net.Conn
|
||||
session quic.Session
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-gost/gost/pkg/dialer"
|
||||
quic_util "github.com/go-gost/gost/pkg/internal/util/quic"
|
||||
@ -48,12 +47,16 @@ func (d *quicDialer) Init(md md.Metadata) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Multiplex implements dialer.Multiplexer interface.
|
||||
func (d *quicDialer) Multiplex() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *quicDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (conn net.Conn, err error) {
|
||||
if _, _, err := net.SplitHostPort(addr); err != nil {
|
||||
addr = net.JoinHostPort(addr, "0")
|
||||
}
|
||||
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.sessionMutex.Lock()
|
||||
defer d.sessionMutex.Unlock()
|
||||
|
||||
@ -64,80 +67,41 @@ func (d *quicDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO
|
||||
opt(options)
|
||||
}
|
||||
|
||||
host := d.md.host
|
||||
if host == "" {
|
||||
host = options.Host
|
||||
}
|
||||
if h, _, _ := net.SplitHostPort(host); h != "" {
|
||||
host = h
|
||||
}
|
||||
conn, err = options.NetDialer.Dial(ctx, "udp", "")
|
||||
c, err := options.NetDialer.Dial(ctx, "udp", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pc, ok := c.(net.PacketConn)
|
||||
if !ok {
|
||||
c.Close()
|
||||
return nil, errors.New("quic: wrong connection type")
|
||||
}
|
||||
|
||||
if d.md.cipherKey != nil {
|
||||
conn = quic_util.CipherConn(conn.(*net.UDPConn), d.md.cipherKey)
|
||||
pc = quic_util.CipherPacketConn(pc, d.md.cipherKey)
|
||||
}
|
||||
|
||||
session, err = d.initSession(ctx, udpAddr, pc)
|
||||
if err != nil {
|
||||
d.logger.Error(err)
|
||||
pc.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
session = &quicSession{conn: conn}
|
||||
d.sessions[addr] = session
|
||||
}
|
||||
|
||||
return session.conn, err
|
||||
}
|
||||
|
||||
// Handshake implements dialer.Handshaker
|
||||
func (d *quicDialer) Handshake(ctx context.Context, conn net.Conn, options ...dialer.HandshakeOption) (net.Conn, error) {
|
||||
opts := &dialer.HandshakeOptions{}
|
||||
for _, option := range options {
|
||||
option(opts)
|
||||
}
|
||||
|
||||
d.sessionMutex.Lock()
|
||||
defer d.sessionMutex.Unlock()
|
||||
|
||||
if d.md.handshakeTimeout > 0 {
|
||||
conn.SetDeadline(time.Now().Add(d.md.handshakeTimeout))
|
||||
defer conn.SetDeadline(time.Time{})
|
||||
}
|
||||
|
||||
session, ok := d.sessions[opts.Addr]
|
||||
if session != nil && session.conn != conn {
|
||||
conn.Close()
|
||||
return nil, errors.New("quic: unrecognized connection")
|
||||
}
|
||||
if !ok || session.session == nil {
|
||||
s, err := d.initSession(ctx, opts.Addr, conn)
|
||||
if err != nil {
|
||||
d.logger.Error(err)
|
||||
conn.Close()
|
||||
delete(d.sessions, opts.Addr)
|
||||
return nil, err
|
||||
}
|
||||
session = s
|
||||
d.sessions[opts.Addr] = session
|
||||
}
|
||||
cc, err := session.GetConn()
|
||||
conn, err = session.GetConn()
|
||||
if err != nil {
|
||||
session.Close()
|
||||
delete(d.sessions, opts.Addr)
|
||||
delete(d.sessions, addr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cc, nil
|
||||
return
|
||||
}
|
||||
|
||||
func (d *quicDialer) initSession(ctx context.Context, addr string, conn net.Conn) (*quicSession, error) {
|
||||
pc, ok := conn.(net.PacketConn)
|
||||
if !ok {
|
||||
return nil, errors.New("quic: wrong connection type")
|
||||
}
|
||||
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func (d *quicDialer) initSession(ctx context.Context, addr net.Addr, conn net.PacketConn) (*quicSession, error) {
|
||||
quicConfig := &quic.Config{
|
||||
KeepAlive: d.md.keepAlive,
|
||||
HandshakeIdleTimeout: d.md.handshakeTimeout,
|
||||
@ -151,10 +115,14 @@ func (d *quicDialer) initSession(ctx context.Context, addr string, conn net.Conn
|
||||
tlsCfg := d.options.TLSConfig
|
||||
tlsCfg.NextProtos = []string{"http/3", "quic/v1"}
|
||||
|
||||
session, err := quic.DialContext(ctx, pc, udpAddr, addr, tlsCfg, quicConfig)
|
||||
session, err := quic.DialContext(ctx, conn, addr, addr.String(), tlsCfg, quicConfig)
|
||||
if err != nil {
|
||||
d.logger.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
return &quicSession{conn: conn, session: session}, nil
|
||||
return &quicSession{session: session}, nil
|
||||
}
|
||||
|
||||
// Multiplex implements dialer.Multiplexer interface.
|
||||
func (d *quicDialer) Multiplex() bool {
|
||||
return true
|
||||
}
|
||||
|
@ -72,8 +72,8 @@ func (d *wsDialer) Handshake(ctx context.Context, conn net.Conn, options ...dial
|
||||
}
|
||||
|
||||
if d.md.handshakeTimeout > 0 {
|
||||
conn.SetDeadline(time.Now().Add(d.md.handshakeTimeout))
|
||||
defer conn.SetDeadline(time.Time{})
|
||||
conn.SetReadDeadline(time.Now().Add(d.md.handshakeTimeout))
|
||||
defer conn.SetReadDeadline(time.Time{})
|
||||
}
|
||||
|
||||
host := d.md.host
|
||||
@ -103,6 +103,8 @@ func (d *wsDialer) Handshake(ctx context.Context, conn net.Conn, options ...dial
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
cc := ws_util.Conn(c)
|
||||
|
||||
if d.md.keepAlive > 0 {
|
||||
c.SetReadDeadline(time.Now().Add(d.md.keepAlive * 2))
|
||||
c.SetPongHandler(func(string) error {
|
||||
@ -110,13 +112,13 @@ func (d *wsDialer) Handshake(ctx context.Context, conn net.Conn, options ...dial
|
||||
d.options.Logger.Infof("pong: set read deadline: %v", d.md.keepAlive*2)
|
||||
return nil
|
||||
})
|
||||
go d.keepAlive(c)
|
||||
go d.keepAlive(cc)
|
||||
}
|
||||
|
||||
return ws_util.Conn(c), nil
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
func (d *wsDialer) keepAlive(conn *websocket.Conn) {
|
||||
func (d *wsDialer) keepAlive(conn ws_util.WebsocketConn) {
|
||||
ticker := time.NewTicker(d.md.keepAlive)
|
||||
defer ticker.Stop()
|
||||
|
||||
|
@ -103,11 +103,6 @@ func (d *mwsDialer) Handshake(ctx context.Context, conn net.Conn, options ...dia
|
||||
d.sessionMutex.Lock()
|
||||
defer d.sessionMutex.Unlock()
|
||||
|
||||
if d.md.handshakeTimeout > 0 {
|
||||
conn.SetDeadline(time.Now().Add(d.md.handshakeTimeout))
|
||||
defer conn.SetDeadline(time.Time{})
|
||||
}
|
||||
|
||||
session, ok := d.sessions[opts.Addr]
|
||||
if session != nil && session.conn != conn {
|
||||
conn.Close()
|
||||
@ -156,23 +151,31 @@ func (d *mwsDialer) initSession(ctx context.Context, host string, conn net.Conn)
|
||||
dialer.TLSClientConfig = d.options.TLSConfig
|
||||
}
|
||||
|
||||
if d.md.handshakeTimeout > 0 {
|
||||
conn.SetReadDeadline(time.Now().Add(d.md.handshakeTimeout))
|
||||
}
|
||||
|
||||
c, resp, err := dialer.DialContext(ctx, url.String(), d.md.header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
if d.md.handshakeTimeout > 0 {
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
}
|
||||
|
||||
cc := ws_util.Conn(c)
|
||||
|
||||
if d.md.keepAlive > 0 {
|
||||
c.SetReadDeadline(time.Now().Add(d.md.keepAlive * 2))
|
||||
c.SetPongHandler(func(string) error {
|
||||
c.SetReadDeadline(time.Now().Add(d.md.keepAlive * 2))
|
||||
return nil
|
||||
})
|
||||
go d.keepAlive(c)
|
||||
go d.keepAlive(cc)
|
||||
}
|
||||
|
||||
conn = ws_util.Conn(c)
|
||||
|
||||
// stream multiplex
|
||||
smuxConfig := smux.DefaultConfig()
|
||||
smuxConfig.KeepAliveDisabled = d.md.muxKeepAliveDisabled
|
||||
@ -192,14 +195,14 @@ func (d *mwsDialer) initSession(ctx context.Context, host string, conn net.Conn)
|
||||
smuxConfig.MaxStreamBuffer = d.md.muxMaxStreamBuffer
|
||||
}
|
||||
|
||||
session, err := smux.Client(conn, smuxConfig)
|
||||
session, err := smux.Client(cc, smuxConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &muxSession{conn: conn, session: session}, nil
|
||||
return &muxSession{conn: cc, session: session}, nil
|
||||
}
|
||||
|
||||
func (d *mwsDialer) keepAlive(conn *websocket.Conn) {
|
||||
func (d *mwsDialer) keepAlive(conn ws_util.WebsocketConn) {
|
||||
ticker := time.NewTicker(d.md.keepAlive)
|
||||
defer ticker.Stop()
|
||||
|
||||
|
Reference in New Issue
Block a user