kcp: add fake TCP support
This commit is contained in:
parent
62a17f07f7
commit
c5fc56d151
@ -139,6 +139,13 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if config == nil {
|
||||||
|
conf := gost.DefaultKCPConfig
|
||||||
|
if node.GetBool("tcp") {
|
||||||
|
conf.TCP = true
|
||||||
|
}
|
||||||
|
config = &conf
|
||||||
|
}
|
||||||
tr = gost.KCPTransporter(config)
|
tr = gost.KCPTransporter(config)
|
||||||
case "ssh":
|
case "ssh":
|
||||||
if node.Protocol == "direct" || node.Protocol == "remote" {
|
if node.Protocol == "direct" || node.Protocol == "remote" {
|
||||||
@ -322,6 +329,13 @@ func (r *route) GenRouters() ([]router, error) {
|
|||||||
if er != nil {
|
if er != nil {
|
||||||
return nil, er
|
return nil, er
|
||||||
}
|
}
|
||||||
|
if config == nil {
|
||||||
|
conf := gost.DefaultKCPConfig
|
||||||
|
if node.GetBool("tcp") {
|
||||||
|
conf.TCP = true
|
||||||
|
}
|
||||||
|
config = &conf
|
||||||
|
}
|
||||||
ln, err = gost.KCPListener(node.Addr, config)
|
ln, err = gost.KCPListener(node.Addr, config)
|
||||||
case "ssh":
|
case "ssh":
|
||||||
config := &gost.SSHConfig{
|
config := &gost.SSHConfig{
|
||||||
|
34
ftcp.go
34
ftcp.go
@ -99,11 +99,7 @@ func (l *fakeTCPListener) listenLoop() {
|
|||||||
|
|
||||||
conn, ok := l.connMap.Get(raddr.String())
|
conn, ok := l.connMap.Get(raddr.String())
|
||||||
if !ok {
|
if !ok {
|
||||||
cc := &fakeTCPConn{
|
conn = newUDPServerConn(l.ln, raddr, l.config.TTL, l.config.QueueSize)
|
||||||
raddr: raddr,
|
|
||||||
PacketConn: l.ln,
|
|
||||||
}
|
|
||||||
conn = newUDPServerConn(cc, raddr, l.config.TTL, l.config.QueueSize)
|
|
||||||
conn.onClose = func() {
|
conn.onClose = func() {
|
||||||
l.connMap.Delete(raddr.String())
|
l.connMap.Delete(raddr.String())
|
||||||
log.Logf("[ftcp] %s closed (%d)", raddr, l.connMap.Size())
|
log.Logf("[ftcp] %s closed (%d)", raddr, l.connMap.Size())
|
||||||
@ -157,7 +153,6 @@ func (l *fakeTCPListener) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type fakeTCPConn struct {
|
type fakeTCPConn struct {
|
||||||
mss int
|
|
||||||
raddr net.Addr
|
raddr net.Addr
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
}
|
}
|
||||||
@ -171,33 +166,6 @@ func (c *fakeTCPConn) Write(b []byte) (n int, err error) {
|
|||||||
return c.WriteTo(b, c.raddr)
|
return c.WriteTo(b, c.raddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fakeTCPConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
|
||||||
mss := c.mss
|
|
||||||
if mss <= 0 {
|
|
||||||
mss = 1460
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
if len(b) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
var nn int
|
|
||||||
if len(b) <= mss {
|
|
||||||
nn, err = c.PacketConn.WriteTo(b, addr)
|
|
||||||
n += nn
|
|
||||||
break
|
|
||||||
}
|
|
||||||
nn, err = c.PacketConn.WriteTo(b[:mss], addr)
|
|
||||||
n += nn
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
b = b[mss:]
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *fakeTCPConn) RemoteAddr() net.Addr {
|
func (c *fakeTCPConn) RemoteAddr() net.Addr {
|
||||||
return c.raddr
|
return c.raddr
|
||||||
}
|
}
|
||||||
|
73
kcp.go
73
kcp.go
@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
"github.com/go-log/log"
|
"github.com/go-log/log"
|
||||||
"github.com/klauspost/compress/snappy"
|
"github.com/klauspost/compress/snappy"
|
||||||
|
"github.com/xtaci/tcpraw"
|
||||||
"gopkg.in/xtaci/kcp-go.v4"
|
"gopkg.in/xtaci/kcp-go.v4"
|
||||||
"gopkg.in/xtaci/smux.v1"
|
"gopkg.in/xtaci/smux.v1"
|
||||||
)
|
)
|
||||||
@ -46,6 +47,7 @@ type KCPConfig struct {
|
|||||||
SnmpLog string `json:"snmplog"`
|
SnmpLog string `json:"snmplog"`
|
||||||
SnmpPeriod int `json:"snmpperiod"`
|
SnmpPeriod int `json:"snmpperiod"`
|
||||||
Signal bool `json:"signal"` // Signal enables the signal SIGUSR1 feature.
|
Signal bool `json:"signal"` // Signal enables the signal SIGUSR1 feature.
|
||||||
|
TCP bool `json:"tcp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initializes the KCP config.
|
// Init initializes the KCP config.
|
||||||
@ -85,6 +87,7 @@ var (
|
|||||||
SnmpLog: "",
|
SnmpLog: "",
|
||||||
SnmpPeriod: 60,
|
SnmpPeriod: 60,
|
||||||
Signal: false,
|
Signal: false,
|
||||||
|
TCP: false,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -129,13 +132,24 @@ func (tr *kcpTransporter) Dial(addr string, options ...DialOption) (conn net.Con
|
|||||||
ok = false
|
ok = false
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
timeout := opts.Timeout
|
raddr, err := net.ResolveUDPAddr("udp", addr)
|
||||||
if timeout <= 0 {
|
|
||||||
timeout = DialTimeout
|
|
||||||
}
|
|
||||||
conn, err = net.DialTimeout("udp", addr, timeout)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
|
}
|
||||||
|
if tr.config.TCP {
|
||||||
|
pc, err := tcpraw.Dial("tcp", addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn = &fakeTCPConn{
|
||||||
|
raddr: raddr,
|
||||||
|
PacketConn: pc,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
conn, err = net.ListenUDP("udp", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
session = &muxSession{conn: conn}
|
session = &muxSession{conn: conn}
|
||||||
tr.sessions[addr] = session
|
tr.sessions[addr] = session
|
||||||
@ -184,14 +198,14 @@ func (tr *kcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tr *kcpTransporter) initSession(addr string, conn net.Conn, config *KCPConfig) (*muxSession, error) {
|
func (tr *kcpTransporter) initSession(addr string, conn net.Conn, config *KCPConfig) (*muxSession, error) {
|
||||||
udpConn, ok := conn.(*net.UDPConn)
|
pc, ok := conn.(net.PacketConn)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("kcp: wrong connection type")
|
return nil, errors.New("kcp: wrong connection type")
|
||||||
}
|
}
|
||||||
|
|
||||||
kcpconn, err := kcp.NewConn(addr,
|
kcpconn, err := kcp.NewConn(addr,
|
||||||
blockCrypt(config.Key, config.Crypt, KCPSalt),
|
blockCrypt(config.Key, config.Crypt, KCPSalt),
|
||||||
config.DataShard, config.ParityShard, &connectedUDPConn{udpConn})
|
config.DataShard, config.ParityShard, pc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -203,9 +217,11 @@ func (tr *kcpTransporter) initSession(addr string, conn net.Conn, config *KCPCon
|
|||||||
kcpconn.SetMtu(config.MTU)
|
kcpconn.SetMtu(config.MTU)
|
||||||
kcpconn.SetACKNoDelay(config.AckNodelay)
|
kcpconn.SetACKNoDelay(config.AckNodelay)
|
||||||
|
|
||||||
// if err := kcpconn.SetDSCP(config.DSCP); err != nil {
|
if config.DSCP > 0 {
|
||||||
// log.Log("[kcp]", err)
|
if err := kcpconn.SetDSCP(config.DSCP); err != nil {
|
||||||
// }
|
log.Log("[kcp]", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
if err := kcpconn.SetReadBuffer(config.SockBuf); err != nil {
|
if err := kcpconn.SetReadBuffer(config.SockBuf); err != nil {
|
||||||
log.Log("[kcp]", err)
|
log.Log("[kcp]", err)
|
||||||
}
|
}
|
||||||
@ -247,14 +263,31 @@ func KCPListener(addr string, config *KCPConfig) (Listener, error) {
|
|||||||
}
|
}
|
||||||
config.Init()
|
config.Init()
|
||||||
|
|
||||||
ln, err := kcp.ListenWithOptions(addr,
|
var err error
|
||||||
blockCrypt(config.Key, config.Crypt, KCPSalt), config.DataShard, config.ParityShard)
|
var ln *kcp.Listener
|
||||||
|
if config.TCP {
|
||||||
|
var conn net.PacketConn
|
||||||
|
conn, err = tcpraw.Listen("tcp", addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ln, err = kcp.ServeConn(
|
||||||
|
blockCrypt(config.Key, config.Crypt, KCPSalt), config.DataShard, config.ParityShard, conn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ln, err = kcp.ListenWithOptions(addr,
|
||||||
|
blockCrypt(config.Key, config.Crypt, KCPSalt), config.DataShard, config.ParityShard)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// if err = ln.SetDSCP(config.DSCP); err != nil {
|
if config.DSCP > 0 {
|
||||||
// log.Log("[kcp]", err)
|
if err = ln.SetDSCP(config.DSCP); err != nil {
|
||||||
// }
|
log.Log("[kcp]", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
if err = ln.SetReadBuffer(config.SockBuf); err != nil {
|
if err = ln.SetReadBuffer(config.SockBuf); err != nil {
|
||||||
log.Log("[kcp]", err)
|
log.Log("[kcp]", err)
|
||||||
}
|
}
|
||||||
@ -468,11 +501,3 @@ func (c *compStreamConn) SetReadDeadline(t time.Time) error {
|
|||||||
func (c *compStreamConn) SetWriteDeadline(t time.Time) error {
|
func (c *compStreamConn) SetWriteDeadline(t time.Time) error {
|
||||||
return c.conn.SetWriteDeadline(t)
|
return c.conn.SetWriteDeadline(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// connectedUDPConn is a wrapper for net.UDPConn which converts WriteTo syscalls
|
|
||||||
// to Write syscalls that are 4 times faster on some OS'es. This should only be
|
|
||||||
// used for connections that were produced by a net.Dial* call.
|
|
||||||
type connectedUDPConn struct{ *net.UDPConn }
|
|
||||||
|
|
||||||
// WriteTo redirects all writes to the Write syscall, which is 4 times faster.
|
|
||||||
func (c *connectedUDPConn) WriteTo(b []byte, addr net.Addr) (int, error) { return c.Write(b) }
|
|
||||||
|
Loading…
Reference in New Issue
Block a user