nps/component/client/conn.go
2022-01-23 17:30:38 +08:00

70 lines
1.7 KiB
Go

package client
import (
"crypto/tls"
"ehang.io/nps/lib/pb"
"ehang.io/nps/transport"
"github.com/lucas-clemente/quic-go"
"github.com/pkg/errors"
"io"
"net"
"time"
)
type TunnelCreator interface {
NewMux(bridgeAddr string, message *pb.ConnRequest, config *tls.Config) (net.Listener, error)
}
type BaseTunnelCreator struct{}
func (bc BaseTunnelCreator) handshake(npcInfo *pb.ConnRequest, rw io.ReadWriteCloser) error {
_, err := pb.WriteMessage(rw, npcInfo)
if err != nil {
return errors.Wrap(err, "write handshake message")
}
var resp pb.NpcResponse
_, err = pb.ReadMessage(rw, &resp)
if err != nil || !resp.Success {
return errors.Wrap(err, resp.Message)
}
return nil
}
type TcpTunnelCreator struct{ BaseTunnelCreator }
func (tc TcpTunnelCreator) NewMux(bridgeAddr string, message *pb.ConnRequest, config *tls.Config) (net.Listener, error) {
conn, err := tls.Dial("tcp", bridgeAddr, config)
if err != nil {
return nil, err
}
if err := tc.handshake(message, conn); err != nil {
return nil, err
}
server := transport.NewYaMux(conn, nil)
return server, server.Server()
}
type QUICTunnelCreator struct{ BaseTunnelCreator }
func (tc QUICTunnelCreator) NewMux(bridgeAddr string, message *pb.ConnRequest, config *tls.Config) (net.Listener, error) {
session, err := quic.DialAddr(bridgeAddr, config, &quic.Config{
MaxIncomingStreams: 1000000,
MaxIncomingUniStreams: 1000000,
MaxIdleTimeout: time.Minute,
KeepAlive: true,
})
if err != nil {
return nil, err
}
stream, err := session.OpenStream()
if err != nil {
return nil, err
}
err = tc.handshake(message, stream)
if err != nil {
return nil, err
}
server := transport.NewQUIC(session)
return server, server.Server()
}