From 8666d122f0eb5f4435f7bd768a7ccb3a8b2a8c5c Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sat, 11 Jun 2016 17:20:48 +0800 Subject: [PATCH 01/33] InboundHandlerMeta,OutboundHandlerMeta added KcpSupported bool to declare KCP support --- proxy/proxy.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proxy/proxy.go b/proxy/proxy.go index bf7469ba..f0c10048 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -18,11 +18,15 @@ type InboundHandlerMeta struct { Tag string Address v2net.Address Port v2net.Port + //Whether this proxy support KCP connections + KcpSupported bool } type OutboundHandlerMeta struct { Tag string Address v2net.Address + //Whether this proxy support KCP connections + KcpSupported bool } // An InboundHandler handles inbound network connections to V2Ray. From 63c1f2106db2a4405bce08880f54ec596d303037 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sat, 11 Jun 2016 17:30:38 +0800 Subject: [PATCH 02/33] Added kcp related configs --- transport/hub/kcp/config.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 transport/hub/kcp/config.go diff --git a/transport/hub/kcp/config.go b/transport/hub/kcp/config.go new file mode 100644 index 00000000..e0bfd2b7 --- /dev/null +++ b/transport/hub/kcp/config.go @@ -0,0 +1,22 @@ +package kcp + +type AdvancedConfig struct { + Mtu int `json:"MaximumTransmissionUnit"` + Sndwnd int `json:"SendingWindowSize"` + Rcvwnd int `json:"ReceivingWindowSize"` + Fec int `json:"ForwardErrorCorrectionGroupSize"` + Acknodelay bool `json:"AcknowledgeNoDelay"` + Dscp int `json:"Dscp"` + ReadTimeout int `json:"ReadTimeout"` + WriteTimeout int `json:"WriteTimeout"` +} + +type Config struct { + Mode string `json:"Mode"` + Key string `json:"EncryptionKey"` + AdvancedConfigs *AdvancedConfig `json:"AdvancedConfig,omitempty"` +} + +var DefaultAdvancedConfigs = &AdvancedConfig{ + Mtu: 1350, Sndwnd: 1024, Rcvwnd: 1024, Fec: 4, Dscp: 0, ReadTimeout: 60, WriteTimeout: 40, Acknodelay: false, +} From 12c40b719536a2d78277b5fe859cb4a557e27a74 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sat, 11 Jun 2016 19:37:19 +0800 Subject: [PATCH 03/33] Renamed to kcpv avoid name conflict --- transport/hub/{kcp => kcpv}/config.go | 2 +- transport/hub/kcpv/config_json.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) rename transport/hub/{kcp => kcpv}/config.go (98%) create mode 100644 transport/hub/kcpv/config_json.go diff --git a/transport/hub/kcp/config.go b/transport/hub/kcpv/config.go similarity index 98% rename from transport/hub/kcp/config.go rename to transport/hub/kcpv/config.go index e0bfd2b7..c304e566 100644 --- a/transport/hub/kcp/config.go +++ b/transport/hub/kcpv/config.go @@ -1,4 +1,4 @@ -package kcp +package kcpv type AdvancedConfig struct { Mtu int `json:"MaximumTransmissionUnit"` diff --git a/transport/hub/kcpv/config_json.go b/transport/hub/kcpv/config_json.go new file mode 100644 index 00000000..c838104c --- /dev/null +++ b/transport/hub/kcpv/config_json.go @@ -0,0 +1 @@ +package kcpv From 77eee3ed37bb43887f425accef0d7c15d146b23e Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sat, 11 Jun 2016 19:38:19 +0800 Subject: [PATCH 04/33] Added kcp json parser(By doing nothing) --- transport/hub/kcpv/config_json.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/transport/hub/kcpv/config_json.go b/transport/hub/kcpv/config_json.go index c838104c..66974c20 100644 --- a/transport/hub/kcpv/config_json.go +++ b/transport/hub/kcpv/config_json.go @@ -1 +1,3 @@ package kcpv + +//We can use the default version of json parser From a8792b2b601d6f605ab54fcac1af63c8f7e1aa1b Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sat, 11 Jun 2016 19:51:02 +0800 Subject: [PATCH 05/33] Added Config for KCP connetions --- transport/config.go | 8 ++++++++ transport/config_json.go | 13 +++++++++++-- transport/transport.go | 8 ++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/transport/config.go b/transport/config.go index 967b0b1b..4a408198 100644 --- a/transport/config.go +++ b/transport/config.go @@ -1,12 +1,20 @@ package transport +import "github.com/v2ray/v2ray-core/transport/hub/kcpv" + type Config struct { ConnectionReuse bool + enableKcp bool + kcpConfig *kcpv.Config } func (this *Config) Apply() error { if this.ConnectionReuse { connectionReuse = true } + enableKcp = this.enableKcp + if enableKcp { + KcpConfig = this.kcpConfig + } return nil } diff --git a/transport/config_json.go b/transport/config_json.go index 95fd56e0..571ecf99 100644 --- a/transport/config_json.go +++ b/transport/config_json.go @@ -2,18 +2,27 @@ package transport -import "encoding/json" +import ( + "encoding/json" + + "github.com/v2ray/v2ray-core/transport/hub/kcpv" +) func (this *Config) UnmarshalJSON(data []byte) error { type JsonConfig struct { - ConnectionReuse bool `json:"connectionReuse"` + ConnectionReuse bool `json:"connectionReuse"` + EnableKcp bool `json:"EnableKCP,omitempty"` + KcpConfig *kcpv.Config `json:"KcpConfig,omitempty"` } jsonConfig := &JsonConfig{ ConnectionReuse: true, + EnableKcp: false, } if err := json.Unmarshal(data, jsonConfig); err != nil { return err } this.ConnectionReuse = jsonConfig.ConnectionReuse + this.enableKcp = jsonConfig.EnableKcp + this.kcpConfig = kcpConfig return nil } diff --git a/transport/transport.go b/transport/transport.go index ce88dd16..34ef7ebc 100644 --- a/transport/transport.go +++ b/transport/transport.go @@ -1,9 +1,17 @@ package transport +import "github.com/v2ray/v2ray-core/transport/hub/kcpv" + var ( connectionReuse = true + enableKcp = false + KcpConfig *kcpv.Config ) func IsConnectionReusable() bool { return connectionReuse } + +func IsKcpEnabled() bool { + return enableKcp +} From 6f0b4aaf31cb8c52501df837ed1a20e78d04f230 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sat, 11 Jun 2016 22:22:43 +0800 Subject: [PATCH 06/33] KCP: sorrgated Listener and conn --- transport/hub/kcp.go | 104 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 transport/hub/kcp.go diff --git a/transport/hub/kcp.go b/transport/hub/kcp.go new file mode 100644 index 00000000..29ee1b5a --- /dev/null +++ b/transport/hub/kcp.go @@ -0,0 +1,104 @@ +package hub + +import ( + "errors" + "net" + "time" + + "github.com/v2ray/v2ray-core/common/log" + "github.com/v2ray/v2ray-core/transport/hub/kcpv" + "github.com/xtaci/kcp-go" +) + +type KCPVlistener struct { + lst *kcp.Listener + conf *kcpv.Config +} + +func (kvl *KCPVlistener) Accept() (*KCPVconn, error) { + conn, err := kvl.lst.Accept() + if err != nil { + return nil, err + } + nodelay, interval, resend, nc := 0, 40, 0, 0 + if kvl.conf.Mode != "manual" { + switch kvl.conf.Mode { + case "normal": + nodelay, interval, resend, nc = 0, 30, 2, 1 + case "fast": + nodelay, interval, resend, nc = 0, 20, 2, 1 + case "fast2": + nodelay, interval, resend, nc = 1, 20, 2, 1 + case "fast3": + nodelay, interval, resend, nc = 1, 10, 2, 1 + } + } else { + log.Error("kcp: Accepted Unsuccessfully: Manual mode is not supported.(yet!)") + return nil, errors.New("kcp: Manual Not Implemented") + } + + conn.SetNoDelay(nodelay, interval, resend, nc) + conn.SetWindowSize(kvl.conf.AdvancedConfigs.Sndwnd, kvl.conf.AdvancedConfigs.Rcvwnd) + conn.SetMtu(kvl.conf.AdvancedConfigs.Mtu) + conn.SetACKNoDelay(kvl.conf.AdvancedConfigs.Acknodelay) + conn.SetDSCP(kvl.conf.AdvancedConfigs.Dscp) + + kcv := &KCPVconn{hc: conn} + kcv.conf = kvl.conf + return kcv, nil +} +func (kvl *KCPVlistener) Close() error { + return kvl.lst.Close() +} +func (kvl *KCPVlistener) Addr() net.Addr { + return kvl.lst.Addr() +} + +type KCPVconn struct { + hc *kcp.UDPSession + conf *kcpv.Config + conntokeep time.Time +} + +func (kcpvc *KCPVconn) Read(b []byte) (int, error) { + ifb := time.Now().Add(time.Duration(kcpvc.conf.AdvancedConfigs.ReadTimeout) * time.Second) + if ifb.After(kcpvc.conntokeep) { + kcpvc.conntokeep = ifb + } + kcpvc.hc.SetDeadline(kcpvc.conntokeep) + return kcpvc.hc.Read(b) +} + +func (kcpvc *KCPVconn) Write(b []byte) (int, error) { + ifb := time.Now().Add(time.Duration(kcpvc.conf.AdvancedConfigs.WriteTimeout) * time.Second) + if ifb.After(kcpvc.conntokeep) { + kcpvc.conntokeep = ifb + } + kcpvc.hc.SetDeadline(kcpvc.conntokeep) + return kcpvc.hc.Write(b) +} + +func (kcpvc *KCPVconn) Close() error { + + return kcpvc.hc.Close() +} + +func (kcpvc *KCPVconn) LocalAddr() net.Addr { + return kcpvc.hc.LocalAddr() +} + +func (kcpvc *KCPVconn) RemoteAddr() net.Addr { + return kcpvc.hc.RemoteAddr() +} + +func (kcpvc *KCPVconn) SetDeadline(t time.Time) error { + return kcpvc.hc.SetDeadline(t) +} + +func (kcpvc *KCPVconn) SetReadDeadline(t time.Time) error { + return kcpvc.hc.SetReadDeadline(t) +} + +func (kcpvc *KCPVconn) SetWriteDeadline(t time.Time) error { + return kcpvc.hc.SetWriteDeadline(t) +} From 0f28c577cebe23185556fe20cce685976d0976f9 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 12:02:16 +0800 Subject: [PATCH 07/33] KCP: Chiper generater --- transport/hub/kcpv/crypto.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 transport/hub/kcpv/crypto.go diff --git a/transport/hub/kcpv/crypto.go b/transport/hub/kcpv/crypto.go new file mode 100644 index 00000000..049c9f2d --- /dev/null +++ b/transport/hub/kcpv/crypto.go @@ -0,0 +1,21 @@ +package kcpv + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/sha256" +) + +func generateKeyFromConfigString(key string) []byte { + key += "consensus salt: Let's fight arcifical deceleration with our code. We shall prove our believes with action." + keyw := sha256.Sum256([]byte(key)) + return keyw[:] +} + +func generateBlockWithKey(key []byte) (cipher.Block, error) { + return aes.NewCipher(key) +} + +func GetChipher(key string) (cipher.Block, error) { + return generateBlockWithKey(generateKeyFromConfigString(key)) +} From e84d52263de0c80bbbff453500975751f71aec4f Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 12:24:09 +0800 Subject: [PATCH 08/33] KCP: Moved apply to KCPv --- transport/hub/kcp.go | 51 +++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/transport/hub/kcp.go b/transport/hub/kcp.go index 29ee1b5a..aa5ed603 100644 --- a/transport/hub/kcp.go +++ b/transport/hub/kcp.go @@ -20,31 +20,13 @@ func (kvl *KCPVlistener) Accept() (*KCPVconn, error) { if err != nil { return nil, err } - nodelay, interval, resend, nc := 0, 40, 0, 0 - if kvl.conf.Mode != "manual" { - switch kvl.conf.Mode { - case "normal": - nodelay, interval, resend, nc = 0, 30, 2, 1 - case "fast": - nodelay, interval, resend, nc = 0, 20, 2, 1 - case "fast2": - nodelay, interval, resend, nc = 1, 20, 2, 1 - case "fast3": - nodelay, interval, resend, nc = 1, 10, 2, 1 - } - } else { - log.Error("kcp: Accepted Unsuccessfully: Manual mode is not supported.(yet!)") - return nil, errors.New("kcp: Manual Not Implemented") - } - - conn.SetNoDelay(nodelay, interval, resend, nc) - conn.SetWindowSize(kvl.conf.AdvancedConfigs.Sndwnd, kvl.conf.AdvancedConfigs.Rcvwnd) - conn.SetMtu(kvl.conf.AdvancedConfigs.Mtu) - conn.SetACKNoDelay(kvl.conf.AdvancedConfigs.Acknodelay) - conn.SetDSCP(kvl.conf.AdvancedConfigs.Dscp) kcv := &KCPVconn{hc: conn} kcv.conf = kvl.conf + err = kcv.ApplyConf() + if err != nil { + return nil, err + } return kcv, nil } func (kvl *KCPVlistener) Close() error { @@ -77,6 +59,31 @@ func (kcpvc *KCPVconn) Write(b []byte) (int, error) { kcpvc.hc.SetDeadline(kcpvc.conntokeep) return kcpvc.hc.Write(b) } +func (kcpvc *KCPVconn) ApplyConf() error { + nodelay, interval, resend, nc := 0, 40, 0, 0 + if kcpvc.conf.Mode != "manual" { + switch kcpvc.conf.Mode { + case "normal": + nodelay, interval, resend, nc = 0, 30, 2, 1 + case "fast": + nodelay, interval, resend, nc = 0, 20, 2, 1 + case "fast2": + nodelay, interval, resend, nc = 1, 20, 2, 1 + case "fast3": + nodelay, interval, resend, nc = 1, 10, 2, 1 + } + } else { + log.Error("kcp: Failed to Apply configure: Manual mode is not supported.(yet!)") + return errors.New("kcp: Manual Not Implemented") + } + + kcpvc.hc.SetNoDelay(nodelay, interval, resend, nc) + kcpvc.hc.SetWindowSize(kcpvc.conf.AdvancedConfigs.Sndwnd, kcpvc.conf.AdvancedConfigs.Rcvwnd) + kcpvc.hc.SetMtu(kcpvc.conf.AdvancedConfigs.Mtu) + kcpvc.hc.SetACKNoDelay(kcpvc.conf.AdvancedConfigs.Acknodelay) + kcpvc.hc.SetDSCP(kcpvc.conf.AdvancedConfigs.Dscp) + return nil +} func (kcpvc *KCPVconn) Close() error { From 2fd963801c43d2a4dd43acd8e8b8cb4081c39947 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 12:25:51 +0800 Subject: [PATCH 09/33] KCP: Added Dial func --- transport/hub/kcp.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/transport/hub/kcp.go b/transport/hub/kcp.go index aa5ed603..8d0fc00a 100644 --- a/transport/hub/kcp.go +++ b/transport/hub/kcp.go @@ -6,6 +6,7 @@ import ( "time" "github.com/v2ray/v2ray-core/common/log" + "github.com/v2ray/v2ray-core/transport" "github.com/v2ray/v2ray-core/transport/hub/kcpv" "github.com/xtaci/kcp-go" ) @@ -109,3 +110,19 @@ func (kcpvc *KCPVconn) SetReadDeadline(t time.Time) error { func (kcpvc *KCPVconn) SetWriteDeadline(t time.Time) error { return kcpvc.hc.SetWriteDeadline(t) } + +func DialKCP(dest v2net.Destination) (*KCPVconn, error) { + kcpconf := transport.KcpConfig + cpip, _ := kcpv.GetChipher(kcpconf.Key) + kcv, err := kcp.DialWithOptions(kcpconf.AdvancedConfigs.Fec, dest.NetAddr(), cpip) + if err != nil { + return nil, err + } + kcvn := &KCPVconn{hc: kcv} + kcvn.conf = kcpconf + err = kcvn.ApplyConf() + if err != nil { + return nil, err + } + return kcvn, nil +} From e51710d14454b1cb88f452831335666fb4b3d4ac Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 12:37:56 +0800 Subject: [PATCH 10/33] Func: ListenTCP6 --- transport/hub/tcp.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/transport/hub/tcp.go b/transport/hub/tcp.go index 49b59d00..c3e89120 100644 --- a/transport/hub/tcp.go +++ b/transport/hub/tcp.go @@ -8,6 +8,8 @@ import ( "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/proxy" + "github.com/v2ray/v2ray-core/transport" ) var ( @@ -47,6 +49,14 @@ func ListenTCP(address v2net.Address, port v2net.Port, callback ConnectionHandle go hub.start() return hub, nil } +func ListenTCP6(address v2net.Address, port v2net.Port, callback ConnectionHandler, proxyMeta proxy.InboundHandlerMeta, tlsConfig *tls.Config) (*TCPHub, error) { + if proxyMeta.KcpSupported && transport.IsKcpEnabled() { + return nil, errors.New("ListenTCP6: Not Implemented") + } else { + return ListenTCP(address, port, callback, tlsConfig) + } + return nil, errors.New("ListenTCP6: Not Implemented") +} func (this *TCPHub) Close() { this.accepting = false From 70201d8879925bb144ee802fbb9fbe360817697e Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 13:14:07 +0800 Subject: [PATCH 11/33] KCP:func ListenKCP finished --- transport/hub/kcp.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/transport/hub/kcp.go b/transport/hub/kcp.go index 8d0fc00a..fa0aaf47 100644 --- a/transport/hub/kcp.go +++ b/transport/hub/kcp.go @@ -6,6 +6,7 @@ import ( "time" "github.com/v2ray/v2ray-core/common/log" + v2net "github.com/v2ray/v2ray-core/common/net" "github.com/v2ray/v2ray-core/transport" "github.com/v2ray/v2ray-core/transport/hub/kcpv" "github.com/xtaci/kcp-go" @@ -126,3 +127,12 @@ func DialKCP(dest v2net.Destination) (*KCPVconn, error) { } return kcvn, nil } + +func ListenKCP(address v2net.Address, port v2net.Port) (*KCPVlistener, error) { + kcpconf := transport.KcpConfig + cpip, _ := kcpv.GetChipher(kcpconf.Key) + laddr := address.String() + ":" + port.String() + kcl, err := kcp.ListenWithOptions(kcpconf.AdvancedConfigs.Fec, laddr, cpip) + kcvl := &KCPVlistener{lst: kcl, conf: kcpconf} + return kcvl, err +} From 35b30e5bb0c5161b1db15f496080618f94895b5b Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 13:22:09 +0800 Subject: [PATCH 12/33] Finished ListenKCPhub --- transport/hub/kcp.go | 2 +- transport/hub/tcp.go | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/transport/hub/kcp.go b/transport/hub/kcp.go index fa0aaf47..eb62da3e 100644 --- a/transport/hub/kcp.go +++ b/transport/hub/kcp.go @@ -17,7 +17,7 @@ type KCPVlistener struct { conf *kcpv.Config } -func (kvl *KCPVlistener) Accept() (*KCPVconn, error) { +func (kvl *KCPVlistener) Accept() (net.Conn, error) { conn, err := kvl.lst.Accept() if err != nil { return nil, err diff --git a/transport/hub/tcp.go b/transport/hub/tcp.go index c3e89120..b230d655 100644 --- a/transport/hub/tcp.go +++ b/transport/hub/tcp.go @@ -49,9 +49,31 @@ func ListenTCP(address v2net.Address, port v2net.Port, callback ConnectionHandle go hub.start() return hub, nil } +func ListenKCPhub(address v2net.Address, port v2net.Port, callback ConnectionHandler, tlsConfig *tls.Config) (*TCPHub, error) { + listener, err := ListenKCP(address, port) + if err != nil { + return nil, err + } + var hub *TCPHub + if tlsConfig != nil { + tlsListener := tls.NewListener(listener, tlsConfig) + hub = &TCPHub{ + listener: tlsListener, + connCallback: callback, + } + } else { + hub = &TCPHub{ + listener: listener, + connCallback: callback, + } + } + + go hub.start() + return hub, nil +} func ListenTCP6(address v2net.Address, port v2net.Port, callback ConnectionHandler, proxyMeta proxy.InboundHandlerMeta, tlsConfig *tls.Config) (*TCPHub, error) { if proxyMeta.KcpSupported && transport.IsKcpEnabled() { - return nil, errors.New("ListenTCP6: Not Implemented") + return ListenKCPhub(address, port, callback, tlsConfig) } else { return ListenTCP(address, port, callback, tlsConfig) } From c07d478ab5b42fee40836f116227678309856381 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 13:38:14 +0800 Subject: [PATCH 13/33] KCP: Dialers for KCP --- transport/hub/dialer.go | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/transport/hub/dialer.go b/transport/hub/dialer.go index 86ffa032..1687ef64 100644 --- a/transport/hub/dialer.go +++ b/transport/hub/dialer.go @@ -6,6 +6,7 @@ import ( "time" v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/proxy" "github.com/v2ray/v2ray-core/transport" ) @@ -62,3 +63,46 @@ func DialWithoutCache(src v2net.Address, dest v2net.Destination) (net.Conn, erro return dialer.Dial(dest.Network().String(), dest.NetAddr()) } + +func Dial3(src v2net.Address, dest v2net.Destination, proxyMeta proxy.InboundHandlerMeta) (*Connection, error) { + if proxyMeta.KcpSupported && transport.IsKcpEnabled() { + DialKCP3(src, dest, proxyMeta) + } + return Dial(src, dest) +} +func DialWithoutCache3(src v2net.Address, dest v2net.Destination, proxyMeta proxy.InboundHandlerMeta) (net.Conn, error) { + if proxyMeta.KcpSupported && transport.IsKcpEnabled() { + } + return DialWithoutCache(src, dest) +} + +func DialKCP3(src v2net.Address, dest v2net.Destination, proxyMeta proxy.InboundHandlerMeta) (*Connection, error) { + if src == nil { + src = v2net.AnyIP + } + id := src.String() + "-" + dest.NetAddr() + var conn net.Conn + if dest.IsTCP() && transport.IsConnectionReusable() { + conn = globalCache.Get(id) + } + if conn == nil { + var err error + conn, err = DialWithoutCache3(src, dest, proxyMeta) + if err != nil { + return nil, err + } + } + return &Connection{ + dest: id, + conn: conn, + listener: globalCache, + }, nil +} + +/*DialKCPWithoutCache Dial KCP connection +This Dialer will ignore src this is a restriction +due to github.com/xtaci/kcp-go.DialWithOptions +*/ +func DialKCPWithoutCache(src v2net.Address, dest v2net.Destination) (net.Conn, error) { + return DialKCP(dest) +} From 4f9a9d1f0c6579ae599d0efbd9c6067805fff2d9 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 13:43:05 +0800 Subject: [PATCH 14/33] KCP: fix: meta type --- transport/hub/dialer.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/transport/hub/dialer.go b/transport/hub/dialer.go index 1687ef64..b9d99a45 100644 --- a/transport/hub/dialer.go +++ b/transport/hub/dialer.go @@ -64,19 +64,19 @@ func DialWithoutCache(src v2net.Address, dest v2net.Destination) (net.Conn, erro return dialer.Dial(dest.Network().String(), dest.NetAddr()) } -func Dial3(src v2net.Address, dest v2net.Destination, proxyMeta proxy.InboundHandlerMeta) (*Connection, error) { +func Dial3(src v2net.Address, dest v2net.Destination, proxyMeta proxy.OutboundHandlerMeta) (*Connection, error) { if proxyMeta.KcpSupported && transport.IsKcpEnabled() { DialKCP3(src, dest, proxyMeta) } return Dial(src, dest) } -func DialWithoutCache3(src v2net.Address, dest v2net.Destination, proxyMeta proxy.InboundHandlerMeta) (net.Conn, error) { +func DialWithoutCache3(src v2net.Address, dest v2net.Destination, proxyMeta proxy.OutboundHandlerMeta) (net.Conn, error) { if proxyMeta.KcpSupported && transport.IsKcpEnabled() { } return DialWithoutCache(src, dest) } -func DialKCP3(src v2net.Address, dest v2net.Destination, proxyMeta proxy.InboundHandlerMeta) (*Connection, error) { +func DialKCP3(src v2net.Address, dest v2net.Destination, proxyMeta proxy.OutboundHandlerMeta) (*Connection, error) { if src == nil { src = v2net.AnyIP } From 09125741663564ff5f44fcfa137338bc616e4bfd Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 13:45:21 +0800 Subject: [PATCH 15/33] KCP: amend proxyMeta -> *proxymeta --- transport/hub/dialer.go | 6 +++--- transport/hub/tcp.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/transport/hub/dialer.go b/transport/hub/dialer.go index b9d99a45..ca56051f 100644 --- a/transport/hub/dialer.go +++ b/transport/hub/dialer.go @@ -64,19 +64,19 @@ func DialWithoutCache(src v2net.Address, dest v2net.Destination) (net.Conn, erro return dialer.Dial(dest.Network().String(), dest.NetAddr()) } -func Dial3(src v2net.Address, dest v2net.Destination, proxyMeta proxy.OutboundHandlerMeta) (*Connection, error) { +func Dial3(src v2net.Address, dest v2net.Destination, proxyMeta *proxy.OutboundHandlerMeta) (*Connection, error) { if proxyMeta.KcpSupported && transport.IsKcpEnabled() { DialKCP3(src, dest, proxyMeta) } return Dial(src, dest) } -func DialWithoutCache3(src v2net.Address, dest v2net.Destination, proxyMeta proxy.OutboundHandlerMeta) (net.Conn, error) { +func DialWithoutCache3(src v2net.Address, dest v2net.Destination, proxyMeta *proxy.OutboundHandlerMeta) (net.Conn, error) { if proxyMeta.KcpSupported && transport.IsKcpEnabled() { } return DialWithoutCache(src, dest) } -func DialKCP3(src v2net.Address, dest v2net.Destination, proxyMeta proxy.OutboundHandlerMeta) (*Connection, error) { +func DialKCP3(src v2net.Address, dest v2net.Destination, proxyMeta *proxy.OutboundHandlerMeta) (*Connection, error) { if src == nil { src = v2net.AnyIP } diff --git a/transport/hub/tcp.go b/transport/hub/tcp.go index b230d655..8f63d3ab 100644 --- a/transport/hub/tcp.go +++ b/transport/hub/tcp.go @@ -71,7 +71,7 @@ func ListenKCPhub(address v2net.Address, port v2net.Port, callback ConnectionHan go hub.start() return hub, nil } -func ListenTCP6(address v2net.Address, port v2net.Port, callback ConnectionHandler, proxyMeta proxy.InboundHandlerMeta, tlsConfig *tls.Config) (*TCPHub, error) { +func ListenTCP6(address v2net.Address, port v2net.Port, callback ConnectionHandler, proxyMeta *proxy.InboundHandlerMeta, tlsConfig *tls.Config) (*TCPHub, error) { if proxyMeta.KcpSupported && transport.IsKcpEnabled() { return ListenKCPhub(address, port, callback, tlsConfig) } else { From 6d6158b0890d9373539c1ecbe811bd995dc16f49 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 13:48:40 +0800 Subject: [PATCH 16/33] KCP: Vmess will pass its meta to Dial3 and ListenTCP6 --- proxy/vmess/inbound/inbound.go | 2 +- proxy/vmess/outbound/outbound.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 715c3373..12809a14 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -106,7 +106,7 @@ func (this *VMessInboundHandler) Start() error { return nil } - tcpListener, err := hub.ListenTCP(this.meta.Address, this.meta.Port, this.HandleConnection, nil) + tcpListener, err := hub.ListenTCP6(this.meta.Address, this.meta.Port, this.HandleConnection, this.meta, nil) if err != nil { log.Error("Unable to listen tcp ", this.meta.Address, ":", this.meta.Port, ": ", err) return err diff --git a/proxy/vmess/outbound/outbound.go b/proxy/vmess/outbound/outbound.go index 7699996b..3c7f46c8 100644 --- a/proxy/vmess/outbound/outbound.go +++ b/proxy/vmess/outbound/outbound.go @@ -34,7 +34,7 @@ func (this *VMessOutboundHandler) Dispatch(target v2net.Destination, payload *al err := retry.Timed(5, 100).On(func() error { rec = this.receiverManager.PickReceiver() - rawConn, err := hub.Dial(this.meta.Address, rec.Destination) + rawConn, err := hub.Dial3(this.meta.Address, rec.Destination, this.meta) if err != nil { return err } From 29cb680a4ba75b1e4515218c09853c16a1b34dab Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 13:52:29 +0800 Subject: [PATCH 17/33] KCP: VMess will advertise its KCP capacity --- proxy/vmess/inbound/inbound.go | 4 +++- proxy/vmess/outbound/outbound.go | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 12809a14..2e5579f2 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -220,7 +220,9 @@ func (this *VMessInboundHandler) HandleConnection(connection *hub.Connection) { readFinish.Lock() } - +func (this *VMessInboundHandler) setProxyCap() { + this.meta.KcpSupported = true +} func init() { internal.MustRegisterInboundHandlerCreator("vmess", func(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) { diff --git a/proxy/vmess/outbound/outbound.go b/proxy/vmess/outbound/outbound.go index 3c7f46c8..a06d9512 100644 --- a/proxy/vmess/outbound/outbound.go +++ b/proxy/vmess/outbound/outbound.go @@ -154,7 +154,9 @@ func (this *VMessOutboundHandler) handleResponse(session *raw.ClientSession, con return } - +func (this *VMessOutboundHandler) setProxyCap() { + this.meta.KcpSupported = true +} func init() { internal.MustRegisterOutboundHandlerCreator("vmess", func(space app.Space, rawConfig interface{}, meta *proxy.OutboundHandlerMeta) (proxy.OutboundHandler, error) { From e72a7cb96fcc3c5e59bb76b01acc4eb36634ddee Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 13:57:08 +0800 Subject: [PATCH 18/33] KCP: VMess will call setProxyCap to advertise KCP capacity on init --- proxy/vmess/inbound/inbound.go | 2 ++ proxy/vmess/outbound/outbound.go | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 2e5579f2..e084da2e 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -248,6 +248,8 @@ func init() { handler.inboundHandlerManager = space.GetApp(proxyman.APP_ID_INBOUND_MANAGER).(proxyman.InboundHandlerManager) } + handler.setProxyCap() + return handler, nil }) } diff --git a/proxy/vmess/outbound/outbound.go b/proxy/vmess/outbound/outbound.go index a06d9512..517f4f63 100644 --- a/proxy/vmess/outbound/outbound.go +++ b/proxy/vmess/outbound/outbound.go @@ -161,9 +161,14 @@ func init() { internal.MustRegisterOutboundHandlerCreator("vmess", func(space app.Space, rawConfig interface{}, meta *proxy.OutboundHandlerMeta) (proxy.OutboundHandler, error) { vOutConfig := rawConfig.(*Config) - return &VMessOutboundHandler{ + + handler := &VMessOutboundHandler{ receiverManager: NewReceiverManager(vOutConfig.Receivers), meta: meta, - }, nil + } + + handler.setProxyCap() + + return handler, nil }) } From cbb183ec58303afb580fde6ac2677468fdd0d5b2 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 14:10:19 +0800 Subject: [PATCH 19/33] KCP: Fixed transport/config_json.go jsonConfig.KcpConfig, jsonConfig.KcpConfig.AdvancedConfig == nil --- transport/config_json.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/transport/config_json.go b/transport/config_json.go index 571ecf99..b2d98a1e 100644 --- a/transport/config_json.go +++ b/transport/config_json.go @@ -23,6 +23,10 @@ func (this *Config) UnmarshalJSON(data []byte) error { } this.ConnectionReuse = jsonConfig.ConnectionReuse this.enableKcp = jsonConfig.EnableKcp - this.kcpConfig = kcpConfig + this.kcpConfig = jsonConfig.KcpConfig + if jsonConfig.KcpConfig.AdvancedConfig == nil { + jsonConfig.KcpConfig.AdvancedConfig = kcpv.DefaultAdvancedConfigs + } + return nil } From 7fdf0de06d703139c11781c96bf11d3b165f8561 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 14:12:48 +0800 Subject: [PATCH 20/33] KCP: Fixed: typo in --- transport/config_json.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/transport/config_json.go b/transport/config_json.go index b2d98a1e..8f900701 100644 --- a/transport/config_json.go +++ b/transport/config_json.go @@ -24,8 +24,8 @@ func (this *Config) UnmarshalJSON(data []byte) error { this.ConnectionReuse = jsonConfig.ConnectionReuse this.enableKcp = jsonConfig.EnableKcp this.kcpConfig = jsonConfig.KcpConfig - if jsonConfig.KcpConfig.AdvancedConfig == nil { - jsonConfig.KcpConfig.AdvancedConfig = kcpv.DefaultAdvancedConfigs + if jsonConfig.KcpConfig.AdvancedConfigs == nil { + jsonConfig.KcpConfig.AdvancedConfigs = kcpv.DefaultAdvancedConfigs } return nil From 579786166caa04b743ddeca5a6463146faac2b15 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 15:15:47 +0800 Subject: [PATCH 21/33] Fix: DialWithoutCache3 misbehave --- transport/hub/dialer.go | 1 + 1 file changed, 1 insertion(+) diff --git a/transport/hub/dialer.go b/transport/hub/dialer.go index ca56051f..8dc3a611 100644 --- a/transport/hub/dialer.go +++ b/transport/hub/dialer.go @@ -72,6 +72,7 @@ func Dial3(src v2net.Address, dest v2net.Destination, proxyMeta *proxy.OutboundH } func DialWithoutCache3(src v2net.Address, dest v2net.Destination, proxyMeta *proxy.OutboundHandlerMeta) (net.Conn, error) { if proxyMeta.KcpSupported && transport.IsKcpEnabled() { + return DialKCPWithoutCache(src, dest) } return DialWithoutCache(src, dest) } From 9315bb29fbf45edbb857fffd351a4579458501d5 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 15:21:59 +0800 Subject: [PATCH 22/33] Fix: Dial3 misbehave --- transport/hub/dialer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/hub/dialer.go b/transport/hub/dialer.go index 8dc3a611..add425b9 100644 --- a/transport/hub/dialer.go +++ b/transport/hub/dialer.go @@ -66,7 +66,7 @@ func DialWithoutCache(src v2net.Address, dest v2net.Destination) (net.Conn, erro func Dial3(src v2net.Address, dest v2net.Destination, proxyMeta *proxy.OutboundHandlerMeta) (*Connection, error) { if proxyMeta.KcpSupported && transport.IsKcpEnabled() { - DialKCP3(src, dest, proxyMeta) + return DialKCP3(src, dest, proxyMeta) } return Dial(src, dest) } From d0d63ee5b3f4572333cb0c8b58651687e3406f92 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 22:37:50 +0800 Subject: [PATCH 23/33] Removed manadory mandatory requirement for Read/Write Timeout --- transport/config.go | 1 + transport/hub/dialer.go | 13 +++---------- transport/hub/kcp.go | 28 ++++++++++++++++++++++++++-- transport/hub/kcpv/config.go | 2 +- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/transport/config.go b/transport/config.go index 1e05004c..18205c1c 100644 --- a/transport/config.go +++ b/transport/config.go @@ -17,6 +17,7 @@ func (this *Config) Apply() error { enableKcp = this.enableKcp if enableKcp { KcpConfig = this.kcpConfig + connectionReuse = false } return nil } diff --git a/transport/hub/dialer.go b/transport/hub/dialer.go index add425b9..e4c73c06 100644 --- a/transport/hub/dialer.go +++ b/transport/hub/dialer.go @@ -82,16 +82,9 @@ func DialKCP3(src v2net.Address, dest v2net.Destination, proxyMeta *proxy.Outbou src = v2net.AnyIP } id := src.String() + "-" + dest.NetAddr() - var conn net.Conn - if dest.IsTCP() && transport.IsConnectionReusable() { - conn = globalCache.Get(id) - } - if conn == nil { - var err error - conn, err = DialWithoutCache3(src, dest, proxyMeta) - if err != nil { - return nil, err - } + conn, err := DialWithoutCache3(src, dest, proxyMeta) + if err != nil { + return nil, err } return &Connection{ dest: id, diff --git a/transport/hub/kcp.go b/transport/hub/kcp.go index eb62da3e..e5a7ef96 100644 --- a/transport/hub/kcp.go +++ b/transport/hub/kcp.go @@ -13,8 +13,10 @@ import ( ) type KCPVlistener struct { - lst *kcp.Listener - conf *kcpv.Config + lst *kcp.Listener + conf *kcpv.Config + previousSocketid map[int]uint32 + previousSocketid_mapid int } func (kvl *KCPVlistener) Accept() (net.Conn, error) { @@ -23,6 +25,28 @@ func (kvl *KCPVlistener) Accept() (net.Conn, error) { return nil, err } + if kvl.previousSocketid == nil { + kvl.previousSocketid = make(map[int]uint32) + } + + var badbit bool = false + + for _, key := range kvl.previousSocketid { + log.Info("kcp: listener testing,", key, ":", conn.GetConv()) + if key == conn.GetConv() { + badbit = true + } + } + if badbit { + return nil, errors.New("KCP:ConnDup, Don't worry~") + } else { + kvl.previousSocketid_mapid++ + kvl.previousSocketid[kvl.previousSocketid_mapid] = conn.GetConv() + if kvl.previousSocketid_mapid >= 512 { + delete(kvl.previousSocketid, kvl.previousSocketid_mapid-512) + } + } + kcv := &KCPVconn{hc: conn} kcv.conf = kvl.conf err = kcv.ApplyConf() diff --git a/transport/hub/kcpv/config.go b/transport/hub/kcpv/config.go index c304e566..348b31de 100644 --- a/transport/hub/kcpv/config.go +++ b/transport/hub/kcpv/config.go @@ -18,5 +18,5 @@ type Config struct { } var DefaultAdvancedConfigs = &AdvancedConfig{ - Mtu: 1350, Sndwnd: 1024, Rcvwnd: 1024, Fec: 4, Dscp: 0, ReadTimeout: 60, WriteTimeout: 40, Acknodelay: false, + Mtu: 1350, Sndwnd: 1024, Rcvwnd: 1024, Fec: 4, Dscp: 0, ReadTimeout: 18600, WriteTimeout: 18500, Acknodelay: false, } From f4ff2e9366c4b346a51e16ec2dc337061087b390 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 12 Jun 2016 22:39:38 +0800 Subject: [PATCH 24/33] Removed manadory mandatory requirement for Read/Write Timeout+ --- transport/hub/kcp.go | 1 - 1 file changed, 1 deletion(-) diff --git a/transport/hub/kcp.go b/transport/hub/kcp.go index e5a7ef96..1ceebc0c 100644 --- a/transport/hub/kcp.go +++ b/transport/hub/kcp.go @@ -32,7 +32,6 @@ func (kvl *KCPVlistener) Accept() (net.Conn, error) { var badbit bool = false for _, key := range kvl.previousSocketid { - log.Info("kcp: listener testing,", key, ":", conn.GetConv()) if key == conn.GetConv() { badbit = true } From f6019623917bb45e5f17b7b868fecc89b30681b1 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Mon, 13 Jun 2016 06:16:44 +0800 Subject: [PATCH 25/33] KCP: discard useless conn in Accept --- transport/hub/kcp.go | 7 +++++++ transport/hub/tcp.go | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/transport/hub/kcp.go b/transport/hub/kcp.go index 1ceebc0c..6bf88b10 100644 --- a/transport/hub/kcp.go +++ b/transport/hub/kcp.go @@ -19,6 +19,12 @@ type KCPVlistener struct { previousSocketid_mapid int } +/*Accept Accept a KCP connection +Since KCP is stateless, if package deliver after it was closed, +It could be reconized as a new connection and call accept. +If we can detect that the connection is of such a kind, +we will discard that conn. +*/ func (kvl *KCPVlistener) Accept() (net.Conn, error) { conn, err := kvl.lst.Accept() if err != nil { @@ -37,6 +43,7 @@ func (kvl *KCPVlistener) Accept() (net.Conn, error) { } } if badbit { + conn.Close() return nil, errors.New("KCP:ConnDup, Don't worry~") } else { kvl.previousSocketid_mapid++ diff --git a/transport/hub/tcp.go b/transport/hub/tcp.go index 8f63d3ab..266f13d8 100644 --- a/transport/hub/tcp.go +++ b/transport/hub/tcp.go @@ -92,7 +92,7 @@ func (this *TCPHub) start() { if err != nil { if this.accepting { - log.Warning("Listener: Failed to accept new TCP connection: ", err) + log.info("Listener: Failed to accept new TCP connection: ", err) } continue } From 4df5d42011e79967992c0ae26efa313c333975f9 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Mon, 13 Jun 2016 06:17:28 +0800 Subject: [PATCH 26/33] KCP: discard useless conn in Accept+ --- transport/hub/tcp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/hub/tcp.go b/transport/hub/tcp.go index 266f13d8..5f02c1b3 100644 --- a/transport/hub/tcp.go +++ b/transport/hub/tcp.go @@ -92,7 +92,7 @@ func (this *TCPHub) start() { if err != nil { if this.accepting { - log.info("Listener: Failed to accept new TCP connection: ", err) + log.Info("Listener: Failed to accept new TCP connection: ", err) } continue } From 9144b66217169e28897815d84a6f3947f333bd1b Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Mon, 13 Jun 2016 07:08:40 +0800 Subject: [PATCH 27/33] KCP: delay conn close to prevent conn leak --- transport/hub/kcp.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/transport/hub/kcp.go b/transport/hub/kcp.go index 6bf88b10..db712086 100644 --- a/transport/hub/kcp.go +++ b/transport/hub/kcp.go @@ -74,6 +74,8 @@ type KCPVconn struct { conntokeep time.Time } +var counter int + func (kcpvc *KCPVconn) Read(b []byte) (int, error) { ifb := time.Now().Add(time.Duration(kcpvc.conf.AdvancedConfigs.ReadTimeout) * time.Second) if ifb.After(kcpvc.conntokeep) { @@ -114,12 +116,19 @@ func (kcpvc *KCPVconn) ApplyConf() error { kcpvc.hc.SetMtu(kcpvc.conf.AdvancedConfigs.Mtu) kcpvc.hc.SetACKNoDelay(kcpvc.conf.AdvancedConfigs.Acknodelay) kcpvc.hc.SetDSCP(kcpvc.conf.AdvancedConfigs.Dscp) + //counter++ + //log.Info(counter) return nil } func (kcpvc *KCPVconn) Close() error { - - return kcpvc.hc.Close() + go func() { + time.Sleep(2000 * time.Millisecond) + //counter-- + //log.Info(counter) + kcpvc.hc.Close() + }() + return nil } func (kcpvc *KCPVconn) LocalAddr() net.Addr { From 29e9473026877490fa90a4b9d5e01ec37ca134f0 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Mon, 13 Jun 2016 12:56:37 +0800 Subject: [PATCH 28/33] KCP: delay conn close to prevent conn leak+ --- transport/hub/kcp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/hub/kcp.go b/transport/hub/kcp.go index db712086..63c67001 100644 --- a/transport/hub/kcp.go +++ b/transport/hub/kcp.go @@ -74,7 +74,7 @@ type KCPVconn struct { conntokeep time.Time } -var counter int +//var counter int func (kcpvc *KCPVconn) Read(b []byte) (int, error) { ifb := time.Now().Add(time.Duration(kcpvc.conf.AdvancedConfigs.ReadTimeout) * time.Second) From 0f368f8139019d44ea69a3df5dc829afa35d42d4 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Mon, 13 Jun 2016 15:03:58 +0800 Subject: [PATCH 29/33] KCP: comments --- transport/config.go | 7 ++++++ transport/hub/kcp.go | 14 +++++++++++ transport/hub/kcpv/config.go | 45 +++++++++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/transport/config.go b/transport/config.go index 18205c1c..7ea9becc 100644 --- a/transport/config.go +++ b/transport/config.go @@ -17,6 +17,13 @@ func (this *Config) Apply() error { enableKcp = this.enableKcp if enableKcp { KcpConfig = this.kcpConfig + /* + KCP do not support connectionReuse, + it is mandatory to set connectionReuse to false + Since KCP have no handshake and + does not SlowStart, there isn't benefit to + use that anyway. + */ connectionReuse = false } return nil diff --git a/transport/hub/kcp.go b/transport/hub/kcp.go index 63c67001..d50c00c4 100644 --- a/transport/hub/kcp.go +++ b/transport/hub/kcp.go @@ -48,6 +48,11 @@ func (kvl *KCPVlistener) Accept() (net.Conn, error) { } else { kvl.previousSocketid_mapid++ kvl.previousSocketid[kvl.previousSocketid_mapid] = conn.GetConv() + /* + Here we assume that count(connection) < 512 + This won't always true. + More work might be necessary to deal with this in a better way. + */ if kvl.previousSocketid_mapid >= 512 { delete(kvl.previousSocketid, kvl.previousSocketid_mapid-512) } @@ -93,6 +98,11 @@ func (kcpvc *KCPVconn) Write(b []byte) (int, error) { kcpvc.hc.SetDeadline(kcpvc.conntokeep) return kcpvc.hc.Write(b) } + +/*ApplyConf will apply kcpvc.conf to current Socket + +It is recommmanded to call this func once and only once +*/ func (kcpvc *KCPVconn) ApplyConf() error { nodelay, interval, resend, nc := 0, 40, 0, 0 if kcpvc.conf.Mode != "manual" { @@ -121,6 +131,10 @@ func (kcpvc *KCPVconn) ApplyConf() error { return nil } +/*Close Close the current conn +We have to delay the close of Socket for a few second +or the VMess EOF can be too late to send. +*/ func (kcpvc *KCPVconn) Close() error { go func() { time.Sleep(2000 * time.Millisecond) diff --git a/transport/hub/kcpv/config.go b/transport/hub/kcpv/config.go index 348b31de..9b162d30 100644 --- a/transport/hub/kcpv/config.go +++ b/transport/hub/kcpv/config.go @@ -1,5 +1,34 @@ package kcpv +/*AdvancedConfig define behavior of KCP in detail + +MaximumTransmissionUnit: +Largest protocol data unit that the layer can pass onwards +can be discovered by running tracepath + +SendingWindowSize , ReceivingWindowSize: +the size of Tx/Rx window, by packet + +ForwardErrorCorrectionGroupSize: +The the size of packet to generate a Forward Error Correction +packet, this is used to counteract packet loss. + +AcknowledgeNoDelay: +Do not wait a certain of time before sending the ACK packet, +increase bandwich cost and might increase performance + +Dscp: +Differentiated services code point, +be used to reconized to discriminate packet. +It is recommanded to keep it 0 to avoid being detected. + +ReadTimeout,WriteTimeout: +Close the Socket if it have been silent for too long, +Small value can recycle zombie socket faster but +can cause v2ray to kill the proxy connection it is relaying, +Higher value can prevent server from closing zombie socket and +waste resources. +*/ type AdvancedConfig struct { Mtu int `json:"MaximumTransmissionUnit"` Sndwnd int `json:"SendingWindowSize"` @@ -11,6 +40,20 @@ type AdvancedConfig struct { WriteTimeout int `json:"WriteTimeout"` } +/*Config define basic behavior of KCP +Mode: +can be one of these values: +fast3,fast2,fast,normal +<<<<<<- less delay +->>>>>> less bandwich wasted + +EncryptionKey: +a string that will be the EncryptionKey of +All KCP connection we Listen-Accpet or +Dial, We are not very sure about how this +encryption hehave and DO use a unique randomly +generated key. +*/ type Config struct { Mode string `json:"Mode"` Key string `json:"EncryptionKey"` @@ -18,5 +61,5 @@ type Config struct { } var DefaultAdvancedConfigs = &AdvancedConfig{ - Mtu: 1350, Sndwnd: 1024, Rcvwnd: 1024, Fec: 4, Dscp: 0, ReadTimeout: 18600, WriteTimeout: 18500, Acknodelay: false, + Mtu: 1350, Sndwnd: 1024, Rcvwnd: 1024, Fec: 4, Dscp: 0, ReadTimeout: 600, WriteTimeout: 500, Acknodelay: false, } From 18841209ee31a6b1fb9acb731bbfaf8963b95894 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Mon, 13 Jun 2016 15:57:49 +0800 Subject: [PATCH 30/33] KCP:Some Tests --- transport/hub/kcp_test.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 transport/hub/kcp_test.go diff --git a/transport/hub/kcp_test.go b/transport/hub/kcp_test.go new file mode 100644 index 00000000..30feb80b --- /dev/null +++ b/transport/hub/kcp_test.go @@ -0,0 +1,31 @@ +package hub_test + +import "testing" + +import ( + v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/testing/assert" + "github.com/v2ray/v2ray-core/transport" + "github.com/v2ray/v2ray-core/transport/hub" + "github.com/v2ray/v2ray-core/transport/hub/kcpv" +) + +func Test_Pair(t *testing.T) { + assert := assert.On(t) + transport.KcpConfig = &kcpv.Config{} + transport.KcpConfig.Mode = "fast2" + transport.KcpConfig.Key = "key" + transport.KcpConfig.AdvancedConfigs = kcpv.DefaultAdvancedConfigs + lst, _ := hub.ListenKCP(v2net.ParseAddress("127.0.0.1"), 17777) + go func() { + connx, err2 := lst.Accept() + assert.Error(err2).IsNil() + connx.Close() + }() + conn, _ := hub.DialKCP(v2net.TCPDestination(v2net.ParseAddress("127.0.0.1"), 17777)) + conn.LocalAddr() + conn.RemoteAddr() + conn.ApplyConf() + conn.Write([]byte("x")) + conn.Close() +} From 14623e6fa4d40a35f6212feb97a9dbdf9aa59d7c Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Mon, 13 Jun 2016 16:01:27 +0800 Subject: [PATCH 31/33] KCP: This code cause unwanted effect --- transport/hub/tcp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/hub/tcp.go b/transport/hub/tcp.go index 5f02c1b3..8f63d3ab 100644 --- a/transport/hub/tcp.go +++ b/transport/hub/tcp.go @@ -92,7 +92,7 @@ func (this *TCPHub) start() { if err != nil { if this.accepting { - log.Info("Listener: Failed to accept new TCP connection: ", err) + log.Warning("Listener: Failed to accept new TCP connection: ", err) } continue } From bcf87d159247c242eddf185ee1ca8ce7b0ec2c7a Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Mon, 13 Jun 2016 16:34:35 +0800 Subject: [PATCH 32/33] KCP: style --- transport/hub/kcp.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/transport/hub/kcp.go b/transport/hub/kcp.go index d50c00c4..818dc742 100644 --- a/transport/hub/kcp.go +++ b/transport/hub/kcp.go @@ -66,9 +66,11 @@ func (kvl *KCPVlistener) Accept() (net.Conn, error) { } return kcv, nil } + func (kvl *KCPVlistener) Close() error { return kvl.lst.Close() } + func (kvl *KCPVlistener) Addr() net.Addr { return kvl.lst.Addr() } From de4b4516ee06926587dde92f06db03f809d9394e Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Mon, 13 Jun 2016 17:49:21 +0800 Subject: [PATCH 33/33] Fix: check jsonConfig.KcpConfig --- transport/config_json.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/transport/config_json.go b/transport/config_json.go index 8f900701..4328aaa0 100644 --- a/transport/config_json.go +++ b/transport/config_json.go @@ -5,6 +5,7 @@ package transport import ( "encoding/json" + "github.com/v2ray/v2ray-core/common/log" "github.com/v2ray/v2ray-core/transport/hub/kcpv" ) @@ -23,9 +24,15 @@ func (this *Config) UnmarshalJSON(data []byte) error { } this.ConnectionReuse = jsonConfig.ConnectionReuse this.enableKcp = jsonConfig.EnableKcp - this.kcpConfig = jsonConfig.KcpConfig - if jsonConfig.KcpConfig.AdvancedConfigs == nil { - jsonConfig.KcpConfig.AdvancedConfigs = kcpv.DefaultAdvancedConfigs + if jsonConfig.KcpConfig != nil { + this.kcpConfig = jsonConfig.KcpConfig + if jsonConfig.KcpConfig.AdvancedConfigs == nil { + jsonConfig.KcpConfig.AdvancedConfigs = kcpv.DefaultAdvancedConfigs + } + } else { + if jsonConfig.EnableKcp { + log.Error("transport: You have enabled KCP but no configure is given") + } } return nil