fatedier 6 rokov pred
rodič
commit
c1f57da00d
39 zmenil súbory, kde vykonal 244 pridanie a 5000 odobranie
  1. 3 5
      glide.lock
  2. 1 2
      glide.yaml
  3. 1 1
      utils/net/conn.go
  4. 0 1
      vendor/github.com/gorilla/websocket/.travis.yml
  5. 103 37
      vendor/github.com/gorilla/websocket/client.go
  6. 17 107
      vendor/github.com/gorilla/websocket/client_server_test.go
  7. 40 0
      vendor/github.com/gorilla/websocket/client_test.go
  8. 19 25
      vendor/github.com/gorilla/websocket/conn.go
  9. 2 1
      vendor/github.com/gorilla/websocket/conn_test.go
  10. 19 26
      vendor/github.com/gorilla/websocket/doc.go
  11. 1 1
      vendor/github.com/gorilla/websocket/examples/chat/README.md
  12. 2 2
      vendor/github.com/gorilla/websocket/examples/chat/client.go
  13. 0 1
      vendor/github.com/gorilla/websocket/examples/echo/server.go
  14. 3 8
      vendor/github.com/gorilla/websocket/json.go
  15. 1 0
      vendor/github.com/gorilla/websocket/mask.go
  16. 0 77
      vendor/github.com/gorilla/websocket/proxy.go
  17. 13 16
      vendor/github.com/gorilla/websocket/server.go
  18. 0 18
      vendor/github.com/gorilla/websocket/server_test.go
  19. 5 28
      vendor/github.com/gorilla/websocket/util.go
  20. 14 35
      vendor/github.com/gorilla/websocket/util_test.go
  21. 0 473
      vendor/github.com/gorilla/websocket/x_net_proxy.go
  22. 0 24
      vendor/github.com/xtaci/kcp-go/.gitignore
  23. 0 15
      vendor/github.com/xtaci/kcp-go/.travis.yml
  24. 0 22
      vendor/github.com/xtaci/kcp-go/LICENSE
  25. 0 171
      vendor/github.com/xtaci/kcp-go/README.md
  26. 0 263
      vendor/github.com/xtaci/kcp-go/crypt.go
  27. 0 222
      vendor/github.com/xtaci/kcp-go/crypt_test.go
  28. BIN
      vendor/github.com/xtaci/kcp-go/donate.png
  29. 0 303
      vendor/github.com/xtaci/kcp-go/fec.go
  30. BIN
      vendor/github.com/xtaci/kcp-go/frame.png
  31. BIN
      vendor/github.com/xtaci/kcp-go/kcp-go.png
  32. 0 998
      vendor/github.com/xtaci/kcp-go/kcp.go
  33. 0 303
      vendor/github.com/xtaci/kcp-go/kcp_test.go
  34. 0 932
      vendor/github.com/xtaci/kcp-go/sess.go
  35. 0 476
      vendor/github.com/xtaci/kcp-go/sess_test.go
  36. 0 164
      vendor/github.com/xtaci/kcp-go/snmp.go
  37. 0 105
      vendor/github.com/xtaci/kcp-go/updater.go
  38. 0 110
      vendor/github.com/xtaci/kcp-go/xor.go
  39. 0 28
      vendor/github.com/xtaci/kcp-go/xor_test.go

+ 3 - 5
glide.lock

@@ -1,5 +1,5 @@
-hash: 4826a83c4ef4490fd09c560e6a8c8737a7586a97f1beb72294123db65be5ac38
-updated: 2018-04-23T02:10:12.581595+08:00
+hash: 367ad1f2515b51db9d04d5620fd88843fb6faabf303fe3103b896ef7a3f5a126
+updated: 2018-04-23T02:30:29.768749+08:00
 imports:
 - name: github.com/armon/go-socks5
   version: e75332964ef517daa070d7c38a9466a0d687e0a5
@@ -16,7 +16,7 @@ imports:
 - name: github.com/golang/snappy
   version: 5979233c5d6225d4a8e438cdd0b411888449ddab
 - name: github.com/gorilla/websocket
-  version: 292fd08b2560ad524ee37396253d71570339a821
+  version: ea4d1f681babbce9545c9c5f3d5194a789c89f5b
 - name: github.com/julienschmidt/httprouter
   version: 8a45e95fc75cb77048068a62daed98cc22fdac7c
 - name: github.com/klauspost/cpuid
@@ -51,8 +51,6 @@ imports:
   - sm4
 - name: github.com/vaughan0/go-ini
   version: a98ad7ee00ec53921f08832bc06ecf7fd600e6a1
-- name: github.com/xtaci/kcp-go
-  version: df437e2b8ec365a336200f9d9da53441cf72ed47
 - name: github.com/xtaci/smux
   version: 2de5471dfcbc029f5fe1392b83fe784127c4943e
 - name: golang.org/x/crypto

+ 1 - 2
glide.yaml

@@ -46,8 +46,6 @@ import:
   - sm4
 - package: github.com/vaughan0/go-ini
   version: a98ad7ee00ec53921f08832bc06ecf7fd600e6a1
-- package: github.com/xtaci/kcp-go
-  version: v3.17
 - package: github.com/xtaci/smux
   version: 2de5471dfcbc029f5fe1392b83fe784127c4943e
 - package: golang.org/x/crypto
@@ -72,3 +70,4 @@ import:
 - package: github.com/rodaine/table
   version: v1.0.0
 - package: github.com/gorilla/websocket
+  version: v1.2.0

+ 1 - 1
utils/net/conn.go

@@ -26,7 +26,7 @@ import (
 
 	"github.com/fatedier/frp/utils/log"
 
-	kcp "github.com/xtaci/kcp-go"
+	kcp "github.com/fatedier/kcp-go"
 )
 
 // Conn is the interface of connections used in frp.

+ 0 - 1
vendor/github.com/gorilla/websocket/.travis.yml

@@ -8,7 +8,6 @@ matrix:
     - go: 1.6
     - go: 1.7
     - go: 1.8
-    - go: 1.9
     - go: tip
   allow_failures:
     - go: tip

+ 103 - 37
vendor/github.com/gorilla/websocket/client.go

@@ -5,8 +5,10 @@
 package websocket
 
 import (
+	"bufio"
 	"bytes"
 	"crypto/tls"
+	"encoding/base64"
 	"errors"
 	"io"
 	"io/ioutil"
@@ -86,6 +88,50 @@ type Dialer struct {
 
 var errMalformedURL = errors.New("malformed ws or wss URL")
 
+// parseURL parses the URL.
+//
+// This function is a replacement for the standard library url.Parse function.
+// In Go 1.4 and earlier, url.Parse loses information from the path.
+func parseURL(s string) (*url.URL, error) {
+	// From the RFC:
+	//
+	// ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
+	// wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]
+	var u url.URL
+	switch {
+	case strings.HasPrefix(s, "ws://"):
+		u.Scheme = "ws"
+		s = s[len("ws://"):]
+	case strings.HasPrefix(s, "wss://"):
+		u.Scheme = "wss"
+		s = s[len("wss://"):]
+	default:
+		return nil, errMalformedURL
+	}
+
+	if i := strings.Index(s, "?"); i >= 0 {
+		u.RawQuery = s[i+1:]
+		s = s[:i]
+	}
+
+	if i := strings.Index(s, "/"); i >= 0 {
+		u.Opaque = s[i:]
+		s = s[:i]
+	} else {
+		u.Opaque = "/"
+	}
+
+	u.Host = s
+
+	if strings.Contains(u.Host, "@") {
+		// Don't bother parsing user information because user information is
+		// not allowed in websocket URIs.
+		return nil, errMalformedURL
+	}
+
+	return &u, nil
+}
+
 func hostPortNoPort(u *url.URL) (hostPort, hostNoPort string) {
 	hostPort = u.Host
 	hostNoPort = u.Host
@@ -104,7 +150,7 @@ func hostPortNoPort(u *url.URL) (hostPort, hostNoPort string) {
 	return hostPort, hostNoPort
 }
 
-// DefaultDialer is a dialer with all fields set to the default values.
+// DefaultDialer is a dialer with all fields set to the default zero values.
 var DefaultDialer = &Dialer{
 	Proxy: http.ProxyFromEnvironment,
 }
@@ -131,7 +177,7 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re
 		return nil, nil, err
 	}
 
-	u, err := url.Parse(urlStr)
+	u, err := parseURL(urlStr)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -200,52 +246,36 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re
 		req.Header.Set("Sec-Websocket-Extensions", "permessage-deflate; server_no_context_takeover; client_no_context_takeover")
 	}
 
+	hostPort, hostNoPort := hostPortNoPort(u)
+
+	var proxyURL *url.URL
+	// Check wether the proxy method has been configured
+	if d.Proxy != nil {
+		proxyURL, err = d.Proxy(req)
+	}
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var targetHostPort string
+	if proxyURL != nil {
+		targetHostPort, _ = hostPortNoPort(proxyURL)
+	} else {
+		targetHostPort = hostPort
+	}
+
 	var deadline time.Time
 	if d.HandshakeTimeout != 0 {
 		deadline = time.Now().Add(d.HandshakeTimeout)
 	}
 
-	// Get network dial function.
 	netDial := d.NetDial
 	if netDial == nil {
 		netDialer := &net.Dialer{Deadline: deadline}
 		netDial = netDialer.Dial
 	}
 
-	// If needed, wrap the dial function to set the connection deadline.
-	if !deadline.Equal(time.Time{}) {
-		forwardDial := netDial
-		netDial = func(network, addr string) (net.Conn, error) {
-			c, err := forwardDial(network, addr)
-			if err != nil {
-				return nil, err
-			}
-			err = c.SetDeadline(deadline)
-			if err != nil {
-				c.Close()
-				return nil, err
-			}
-			return c, nil
-		}
-	}
-
-	// If needed, wrap the dial function to connect through a proxy.
-	if d.Proxy != nil {
-		proxyURL, err := d.Proxy(req)
-		if err != nil {
-			return nil, nil, err
-		}
-		if proxyURL != nil {
-			dialer, err := proxy_FromURL(proxyURL, netDialerFunc(netDial))
-			if err != nil {
-				return nil, nil, err
-			}
-			netDial = dialer.Dial
-		}
-	}
-
-	hostPort, hostNoPort := hostPortNoPort(u)
-	netConn, err := netDial("tcp", hostPort)
+	netConn, err := netDial("tcp", targetHostPort)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -256,6 +286,42 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re
 		}
 	}()
 
+	if err := netConn.SetDeadline(deadline); err != nil {
+		return nil, nil, err
+	}
+
+	if proxyURL != nil {
+		connectHeader := make(http.Header)
+		if user := proxyURL.User; user != nil {
+			proxyUser := user.Username()
+			if proxyPassword, passwordSet := user.Password(); passwordSet {
+				credential := base64.StdEncoding.EncodeToString([]byte(proxyUser + ":" + proxyPassword))
+				connectHeader.Set("Proxy-Authorization", "Basic "+credential)
+			}
+		}
+		connectReq := &http.Request{
+			Method: "CONNECT",
+			URL:    &url.URL{Opaque: hostPort},
+			Host:   hostPort,
+			Header: connectHeader,
+		}
+
+		connectReq.Write(netConn)
+
+		// Read response.
+		// Okay to use and discard buffered reader here, because
+		// TLS server will not speak until spoken to.
+		br := bufio.NewReader(netConn)
+		resp, err := http.ReadResponse(br, connectReq)
+		if err != nil {
+			return nil, nil, err
+		}
+		if resp.StatusCode != 200 {
+			f := strings.SplitN(resp.Status, " ", 2)
+			return nil, nil, errors.New(f[1])
+		}
+	}
+
 	if u.Scheme == "https" {
 		cfg := cloneTLSConfig(d.TLSClientConfig)
 		if cfg.ServerName == "" {

+ 17 - 107
vendor/github.com/gorilla/websocket/client_server_test.go

@@ -5,14 +5,11 @@
 package websocket
 
 import (
-	"bytes"
 	"crypto/tls"
 	"crypto/x509"
 	"encoding/base64"
-	"encoding/binary"
 	"io"
 	"io/ioutil"
-	"net"
 	"net/http"
 	"net/http/cookiejar"
 	"net/http/httptest"
@@ -34,10 +31,9 @@ var cstUpgrader = Upgrader{
 }
 
 var cstDialer = Dialer{
-	Subprotocols:     []string{"p1", "p2"},
-	ReadBufferSize:   1024,
-	WriteBufferSize:  1024,
-	HandshakeTimeout: 30 * time.Second,
+	Subprotocols:    []string{"p1", "p2"},
+	ReadBufferSize:  1024,
+	WriteBufferSize: 1024,
 }
 
 type cstHandler struct{ *testing.T }
@@ -147,9 +143,8 @@ func TestProxyDial(t *testing.T) {
 	s := newServer(t)
 	defer s.Close()
 
-	surl, _ := url.Parse(s.Server.URL)
+	surl, _ := url.Parse(s.URL)
 
-	cstDialer := cstDialer // make local copy for modification on next line.
 	cstDialer.Proxy = http.ProxyURL(surl)
 
 	connect := false
@@ -165,8 +160,8 @@ func TestProxyDial(t *testing.T) {
 			}
 
 			if !connect {
-				t.Log("connect not received")
-				http.Error(w, "connect not received", 405)
+				t.Log("connect not recieved")
+				http.Error(w, "connect not recieved", 405)
 				return
 			}
 			origHandler.ServeHTTP(w, r)
@@ -178,16 +173,16 @@ func TestProxyDial(t *testing.T) {
 	}
 	defer ws.Close()
 	sendRecv(t, ws)
+
+	cstDialer.Proxy = http.ProxyFromEnvironment
 }
 
 func TestProxyAuthorizationDial(t *testing.T) {
 	s := newServer(t)
 	defer s.Close()
 
-	surl, _ := url.Parse(s.Server.URL)
+	surl, _ := url.Parse(s.URL)
 	surl.User = url.UserPassword("username", "password")
-
-	cstDialer := cstDialer // make local copy for modification on next line.
 	cstDialer.Proxy = http.ProxyURL(surl)
 
 	connect := false
@@ -205,8 +200,8 @@ func TestProxyAuthorizationDial(t *testing.T) {
 			}
 
 			if !connect {
-				t.Log("connect with proxy authorization not received")
-				http.Error(w, "connect with proxy authorization not received", 405)
+				t.Log("connect with proxy authorization not recieved")
+				http.Error(w, "connect with proxy authorization not recieved", 405)
 				return
 			}
 			origHandler.ServeHTTP(w, r)
@@ -218,6 +213,8 @@ func TestProxyAuthorizationDial(t *testing.T) {
 	}
 	defer ws.Close()
 	sendRecv(t, ws)
+
+	cstDialer.Proxy = http.ProxyFromEnvironment
 }
 
 func TestDial(t *testing.T) {
@@ -240,7 +237,7 @@ func TestDialCookieJar(t *testing.T) {
 	d := cstDialer
 	d.Jar = jar
 
-	u, _ := url.Parse(s.URL)
+	u, _ := parseURL(s.URL)
 
 	switch u.Scheme {
 	case "ws":
@@ -249,7 +246,7 @@ func TestDialCookieJar(t *testing.T) {
 		u.Scheme = "https"
 	}
 
-	cookies := []*http.Cookie{{Name: "gorilla", Value: "ws", Path: "/"}}
+	cookies := []*http.Cookie{&http.Cookie{Name: "gorilla", Value: "ws", Path: "/"}}
 	d.Jar.SetCookies(u, cookies)
 
 	ws, _, err := d.Dial(s.URL, nil)
@@ -401,17 +398,9 @@ func TestBadMethod(t *testing.T) {
 	}))
 	defer s.Close()
 
-	req, err := http.NewRequest("POST", s.URL, strings.NewReader(""))
-	if err != nil {
-		t.Fatalf("NewRequest returned error %v", err)
-	}
-	req.Header.Set("Connection", "upgrade")
-	req.Header.Set("Upgrade", "websocket")
-	req.Header.Set("Sec-Websocket-Version", "13")
-
-	resp, err := http.DefaultClient.Do(req)
+	resp, err := http.PostForm(s.URL, url.Values{})
 	if err != nil {
-		t.Fatalf("Do returned error %v", err)
+		t.Fatalf("PostForm returned error %v", err)
 	}
 	resp.Body.Close()
 	if resp.StatusCode != http.StatusMethodNotAllowed {
@@ -521,82 +510,3 @@ func TestDialCompression(t *testing.T) {
 	defer ws.Close()
 	sendRecv(t, ws)
 }
-
-func TestSocksProxyDial(t *testing.T) {
-	s := newServer(t)
-	defer s.Close()
-
-	proxyListener, err := net.Listen("tcp", "127.0.0.1:0")
-	if err != nil {
-		t.Fatalf("listen failed: %v", err)
-	}
-	defer proxyListener.Close()
-	go func() {
-		c1, err := proxyListener.Accept()
-		if err != nil {
-			t.Errorf("proxy accept failed: %v", err)
-			return
-		}
-		defer c1.Close()
-
-		c1.SetDeadline(time.Now().Add(30 * time.Second))
-
-		buf := make([]byte, 32)
-		if _, err := io.ReadFull(c1, buf[:3]); err != nil {
-			t.Errorf("read failed: %v", err)
-			return
-		}
-		if want := []byte{5, 1, 0}; !bytes.Equal(want, buf[:len(want)]) {
-			t.Errorf("read %x, want %x", buf[:len(want)], want)
-		}
-		if _, err := c1.Write([]byte{5, 0}); err != nil {
-			t.Errorf("write failed: %v", err)
-			return
-		}
-		if _, err := io.ReadFull(c1, buf[:10]); err != nil {
-			t.Errorf("read failed: %v", err)
-			return
-		}
-		if want := []byte{5, 1, 0, 1}; !bytes.Equal(want, buf[:len(want)]) {
-			t.Errorf("read %x, want %x", buf[:len(want)], want)
-			return
-		}
-		buf[1] = 0
-		if _, err := c1.Write(buf[:10]); err != nil {
-			t.Errorf("write failed: %v", err)
-			return
-		}
-
-		ip := net.IP(buf[4:8])
-		port := binary.BigEndian.Uint16(buf[8:10])
-
-		c2, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: ip, Port: int(port)})
-		if err != nil {
-			t.Errorf("dial failed; %v", err)
-			return
-		}
-		defer c2.Close()
-		done := make(chan struct{})
-		go func() {
-			io.Copy(c1, c2)
-			close(done)
-		}()
-		io.Copy(c2, c1)
-		<-done
-	}()
-
-	purl, err := url.Parse("socks5://" + proxyListener.Addr().String())
-	if err != nil {
-		t.Fatalf("parse failed: %v", err)
-	}
-
-	cstDialer := cstDialer // make local copy for modification on next line.
-	cstDialer.Proxy = http.ProxyURL(purl)
-
-	ws, _, err := cstDialer.Dial(s.URL, nil)
-	if err != nil {
-		t.Fatalf("Dial: %v", err)
-	}
-	defer ws.Close()
-	sendRecv(t, ws)
-}

+ 40 - 0
vendor/github.com/gorilla/websocket/client_test.go

@@ -6,9 +6,49 @@ package websocket
 
 import (
 	"net/url"
+	"reflect"
 	"testing"
 )
 
+var parseURLTests = []struct {
+	s   string
+	u   *url.URL
+	rui string
+}{
+	{"ws://example.com/", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}, "/"},
+	{"ws://example.com", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}, "/"},
+	{"ws://example.com:7777/", &url.URL{Scheme: "ws", Host: "example.com:7777", Opaque: "/"}, "/"},
+	{"wss://example.com/", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/"}, "/"},
+	{"wss://example.com/a/b", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b"}, "/a/b"},
+	{"ss://example.com/a/b", nil, ""},
+	{"ws://webmaster@example.com/", nil, ""},
+	{"wss://example.com/a/b?x=y", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b", RawQuery: "x=y"}, "/a/b?x=y"},
+	{"wss://example.com?x=y", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/", RawQuery: "x=y"}, "/?x=y"},
+}
+
+func TestParseURL(t *testing.T) {
+	for _, tt := range parseURLTests {
+		u, err := parseURL(tt.s)
+		if tt.u != nil && err != nil {
+			t.Errorf("parseURL(%q) returned error %v", tt.s, err)
+			continue
+		}
+		if tt.u == nil {
+			if err == nil {
+				t.Errorf("parseURL(%q) did not return error", tt.s)
+			}
+			continue
+		}
+		if !reflect.DeepEqual(u, tt.u) {
+			t.Errorf("parseURL(%q) = %v, want %v", tt.s, u, tt.u)
+			continue
+		}
+		if u.RequestURI() != tt.rui {
+			t.Errorf("parseURL(%q).RequestURI() = %v, want %v", tt.s, u.RequestURI(), tt.rui)
+		}
+	}
+}
+
 var hostPortNoPortTests = []struct {
 	u                    *url.URL
 	hostPort, hostNoPort string

+ 19 - 25
vendor/github.com/gorilla/websocket/conn.go

@@ -76,7 +76,7 @@ const (
 	// is UTF-8 encoded text.
 	PingMessage = 9
 
-	// PongMessage denotes a pong control message. The optional message payload
+	// PongMessage denotes a ping control message. The optional message payload
 	// is UTF-8 encoded text.
 	PongMessage = 10
 )
@@ -100,8 +100,9 @@ func (e *netError) Error() string   { return e.msg }
 func (e *netError) Temporary() bool { return e.temporary }
 func (e *netError) Timeout() bool   { return e.timeout }
 
-// CloseError represents a close message.
+// CloseError represents close frame.
 type CloseError struct {
+
 	// Code is defined in RFC 6455, section 11.7.
 	Code int
 
@@ -342,8 +343,7 @@ func (c *Conn) Subprotocol() string {
 	return c.subprotocol
 }
 
-// Close closes the underlying network connection without sending or waiting
-// for a close message.
+// Close closes the underlying network connection without sending or waiting for a close frame.
 func (c *Conn) Close() error {
 	return c.conn.Close()
 }
@@ -484,9 +484,6 @@ func (c *Conn) prepWrite(messageType int) error {
 //
 // There can be at most one open writer on a connection. NextWriter closes the
 // previous writer if the application has not already done so.
-//
-// All message types (TextMessage, BinaryMessage, CloseMessage, PingMessage and
-// PongMessage) are supported.
 func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) {
 	if err := c.prepWrite(messageType); err != nil {
 		return nil, err
@@ -767,6 +764,7 @@ func (c *Conn) SetWriteDeadline(t time.Time) error {
 // Read methods
 
 func (c *Conn) advanceFrame() (int, error) {
+
 	// 1. Skip remainder of previous frame.
 
 	if c.readRemaining > 0 {
@@ -1035,7 +1033,7 @@ func (c *Conn) SetReadDeadline(t time.Time) error {
 }
 
 // SetReadLimit sets the maximum size for a message read from the peer. If a
-// message exceeds the limit, the connection sends a close message to the peer
+// message exceeds the limit, the connection sends a close frame to the peer
 // and returns ErrReadLimit to the application.
 func (c *Conn) SetReadLimit(limit int64) {
 	c.readLimit = limit
@@ -1048,21 +1046,24 @@ func (c *Conn) CloseHandler() func(code int, text string) error {
 
 // SetCloseHandler sets the handler for close messages received from the peer.
 // The code argument to h is the received close code or CloseNoStatusReceived
-// if the close message is empty. The default close handler sends a close
-// message back to the peer.
+// if the close message is empty. The default close handler sends a close frame
+// back to the peer.
 //
 // The application must read the connection to process close messages as
-// described in the section on Control Messages above.
+// described in the section on Control Frames above.
 //
-// The connection read methods return a CloseError when a close message is
+// The connection read methods return a CloseError when a close frame is
 // received. Most applications should handle close messages as part of their
 // normal error handling. Applications should only set a close handler when the
-// application must perform some action before sending a close message back to
+// application must perform some action before sending a close frame back to
 // the peer.
 func (c *Conn) SetCloseHandler(h func(code int, text string) error) {
 	if h == nil {
 		h = func(code int, text string) error {
-			message := FormatCloseMessage(code, "")
+			message := []byte{}
+			if code != CloseNoStatusReceived {
+				message = FormatCloseMessage(code, "")
+			}
 			c.WriteControl(CloseMessage, message, time.Now().Add(writeWait))
 			return nil
 		}
@@ -1076,11 +1077,11 @@ func (c *Conn) PingHandler() func(appData string) error {
 }
 
 // SetPingHandler sets the handler for ping messages received from the peer.
-// The appData argument to h is the PING message application data. The default
+// The appData argument to h is the PING frame application data. The default
 // ping handler sends a pong to the peer.
 //
 // The application must read the connection to process ping messages as
-// described in the section on Control Messages above.
+// described in the section on Control Frames above.
 func (c *Conn) SetPingHandler(h func(appData string) error) {
 	if h == nil {
 		h = func(message string) error {
@@ -1102,11 +1103,11 @@ func (c *Conn) PongHandler() func(appData string) error {
 }
 
 // SetPongHandler sets the handler for pong messages received from the peer.
-// The appData argument to h is the PONG message application data. The default
+// The appData argument to h is the PONG frame application data. The default
 // pong handler does nothing.
 //
 // The application must read the connection to process ping messages as
-// described in the section on Control Messages above.
+// described in the section on Control Frames above.
 func (c *Conn) SetPongHandler(h func(appData string) error) {
 	if h == nil {
 		h = func(string) error { return nil }
@@ -1140,14 +1141,7 @@ func (c *Conn) SetCompressionLevel(level int) error {
 }
 
 // FormatCloseMessage formats closeCode and text as a WebSocket close message.
-// An empty message is returned for code CloseNoStatusReceived.
 func FormatCloseMessage(closeCode int, text string) []byte {
-	if closeCode == CloseNoStatusReceived {
-		// Return empty message because it's illegal to send
-		// CloseNoStatusReceived. Return non-nil value in case application
-		// checks for nil.
-		return []byte{}
-	}
 	buf := make([]byte, 2+len(text))
 	binary.BigEndian.PutUint16(buf, uint16(closeCode))
 	copy(buf[2:], text)

+ 2 - 1
vendor/github.com/gorilla/websocket/conn_test.go

@@ -341,6 +341,7 @@ func TestUnderlyingConn(t *testing.T) {
 }
 
 func TestBufioReadBytes(t *testing.T) {
+
 	// Test calling bufio.ReadBytes for value longer than read buffer size.
 
 	m := make([]byte, 512)
@@ -365,7 +366,7 @@ func TestBufioReadBytes(t *testing.T) {
 		t.Fatalf("ReadBytes() returned %v", err)
 	}
 	if len(p) != len(m) {
-		t.Fatalf("read returned %d bytes, want %d bytes", len(p), len(m))
+		t.Fatalf("read returnd %d bytes, want %d bytes", len(p), len(m))
 	}
 }
 

+ 19 - 26
vendor/github.com/gorilla/websocket/doc.go

@@ -6,8 +6,9 @@
 //
 // Overview
 //
-// The Conn type represents a WebSocket connection. A server application calls
-// the Upgrader.Upgrade method from an HTTP request handler to get a *Conn:
+// The Conn type represents a WebSocket connection. A server application uses
+// the Upgrade function from an Upgrader object with a HTTP request handler
+// to get a pointer to a Conn:
 //
 //  var upgrader = websocket.Upgrader{
 //      ReadBufferSize:  1024,
@@ -30,12 +31,10 @@
 //  for {
 //      messageType, p, err := conn.ReadMessage()
 //      if err != nil {
-//          log.Println(err)
 //          return
 //      }
-//      if err := conn.WriteMessage(messageType, p); err != nil {
-//          log.Println(err)
-//          return
+//      if err = conn.WriteMessage(messageType, p); err != nil {
+//          return err
 //      }
 //  }
 //
@@ -86,26 +85,20 @@
 // and pong. Call the connection WriteControl, WriteMessage or NextWriter
 // methods to send a control message to the peer.
 //
-// Connections handle received close messages by calling the handler function
-// set with the SetCloseHandler method and by returning a *CloseError from the
-// NextReader, ReadMessage or the message Read method. The default close
-// handler sends a close message to the peer.
-//
-// Connections handle received ping messages by calling the handler function
-// set with the SetPingHandler method. The default ping handler sends a pong
-// message to the peer.
+// Connections handle received close messages by sending a close message to the
+// peer and returning a *CloseError from the the NextReader, ReadMessage or the
+// message Read method.
 //
-// Connections handle received pong messages by calling the handler function
-// set with the SetPongHandler method. The default pong handler does nothing.
-// If an application sends ping messages, then the application should set a
-// pong handler to receive the corresponding pong.
+// Connections handle received ping and pong messages by invoking callback
+// functions set with SetPingHandler and SetPongHandler methods. The callback
+// functions are called from the NextReader, ReadMessage and the message Read
+// methods.
 //
-// The control message handler functions are called from the NextReader,
-// ReadMessage and message reader Read methods. The default close and ping
-// handlers can block these methods for a short time when the handler writes to
-// the connection.
+// The default ping handler sends a pong to the peer. The application's reading
+// goroutine can block for a short time while the handler writes the pong data
+// to the connection.
 //
-// The application must read the connection to process close, ping and pong
+// The application must read the connection to process ping, pong and close
 // messages sent from the peer. If the application is not otherwise interested
 // in messages from the peer, then the application should start a goroutine to
 // read and discard messages from the peer. A simple example is:
@@ -154,9 +147,9 @@
 //      CheckOrigin: func(r *http.Request) bool { return true },
 //  }
 //
-// The deprecated package-level Upgrade function does not perform origin
-// checking. The application is responsible for checking the Origin header
-// before calling the Upgrade function.
+// The deprecated Upgrade function does not enforce an origin policy. It's the
+// application's responsibility to check the Origin header before calling
+// Upgrade.
 //
 // Compression EXPERIMENTAL
 //

+ 1 - 1
vendor/github.com/gorilla/websocket/examples/chat/README.md

@@ -1,6 +1,6 @@
 # Chat Example
 
-This application shows how to use the
+This application shows how to use use the
 [websocket](https://github.com/gorilla/websocket) package to implement a simple
 web chat application.
 

+ 2 - 2
vendor/github.com/gorilla/websocket/examples/chat/client.go

@@ -64,7 +64,7 @@ func (c *Client) readPump() {
 	for {
 		_, message, err := c.conn.ReadMessage()
 		if err != nil {
-			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
+			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
 				log.Printf("error: %v", err)
 			}
 			break
@@ -113,7 +113,7 @@ func (c *Client) writePump() {
 			}
 		case <-ticker.C:
 			c.conn.SetWriteDeadline(time.Now().Add(writeWait))
-			if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil {
+			if err := c.conn.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
 				return
 			}
 		}

+ 0 - 1
vendor/github.com/gorilla/websocket/examples/echo/server.go

@@ -55,7 +55,6 @@ func main() {
 
 var homeTemplate = template.Must(template.New("").Parse(`
 <!DOCTYPE html>
-<html>
 <head>
 <meta charset="utf-8">
 <script>  

+ 3 - 8
vendor/github.com/gorilla/websocket/json.go

@@ -9,14 +9,12 @@ import (
 	"io"
 )
 
-// WriteJSON writes the JSON encoding of v as a message.
-//
-// Deprecated: Use c.WriteJSON instead.
+// WriteJSON is deprecated, use c.WriteJSON instead.
 func WriteJSON(c *Conn, v interface{}) error {
 	return c.WriteJSON(v)
 }
 
-// WriteJSON writes the JSON encoding of v as a message.
+// WriteJSON writes the JSON encoding of v to the connection.
 //
 // See the documentation for encoding/json Marshal for details about the
 // conversion of Go values to JSON.
@@ -33,10 +31,7 @@ func (c *Conn) WriteJSON(v interface{}) error {
 	return err2
 }
 
-// ReadJSON reads the next JSON-encoded message from the connection and stores
-// it in the value pointed to by v.
-//
-// Deprecated: Use c.ReadJSON instead.
+// ReadJSON is deprecated, use c.ReadJSON instead.
 func ReadJSON(c *Conn, v interface{}) error {
 	return c.ReadJSON(v)
 }

+ 1 - 0
vendor/github.com/gorilla/websocket/mask.go

@@ -11,6 +11,7 @@ import "unsafe"
 const wordSize = int(unsafe.Sizeof(uintptr(0)))
 
 func maskBytes(key [4]byte, pos int, b []byte) int {
+
 	// Mask one byte at a time for small buffers.
 	if len(b) < 2*wordSize {
 		for i := range b {

+ 0 - 77
vendor/github.com/gorilla/websocket/proxy.go

@@ -1,77 +0,0 @@
-// Copyright 2017 The Gorilla WebSocket Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
-	"bufio"
-	"encoding/base64"
-	"errors"
-	"net"
-	"net/http"
-	"net/url"
-	"strings"
-)
-
-type netDialerFunc func(netowrk, addr string) (net.Conn, error)
-
-func (fn netDialerFunc) Dial(network, addr string) (net.Conn, error) {
-	return fn(network, addr)
-}
-
-func init() {
-	proxy_RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy_Dialer) (proxy_Dialer, error) {
-		return &httpProxyDialer{proxyURL: proxyURL, fowardDial: forwardDialer.Dial}, nil
-	})
-}
-
-type httpProxyDialer struct {
-	proxyURL   *url.URL
-	fowardDial func(network, addr string) (net.Conn, error)
-}
-
-func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) {
-	hostPort, _ := hostPortNoPort(hpd.proxyURL)
-	conn, err := hpd.fowardDial(network, hostPort)
-	if err != nil {
-		return nil, err
-	}
-
-	connectHeader := make(http.Header)
-	if user := hpd.proxyURL.User; user != nil {
-		proxyUser := user.Username()
-		if proxyPassword, passwordSet := user.Password(); passwordSet {
-			credential := base64.StdEncoding.EncodeToString([]byte(proxyUser + ":" + proxyPassword))
-			connectHeader.Set("Proxy-Authorization", "Basic "+credential)
-		}
-	}
-
-	connectReq := &http.Request{
-		Method: "CONNECT",
-		URL:    &url.URL{Opaque: addr},
-		Host:   addr,
-		Header: connectHeader,
-	}
-
-	if err := connectReq.Write(conn); err != nil {
-		conn.Close()
-		return nil, err
-	}
-
-	// Read response. It's OK to use and discard buffered reader here becaue
-	// the remote server does not speak until spoken to.
-	br := bufio.NewReader(conn)
-	resp, err := http.ReadResponse(br, connectReq)
-	if err != nil {
-		conn.Close()
-		return nil, err
-	}
-
-	if resp.StatusCode != 200 {
-		conn.Close()
-		f := strings.SplitN(resp.Status, " ", 2)
-		return nil, errors.New(f[1])
-	}
-	return conn, nil
-}

+ 13 - 16
vendor/github.com/gorilla/websocket/server.go

@@ -76,7 +76,7 @@ func checkSameOrigin(r *http.Request) bool {
 	if err != nil {
 		return false
 	}
-	return equalASCIIFold(u.Host, r.Host)
+	return u.Host == r.Host
 }
 
 func (u *Upgrader) selectSubprotocol(r *http.Request, responseHeader http.Header) string {
@@ -104,28 +104,26 @@ func (u *Upgrader) selectSubprotocol(r *http.Request, responseHeader http.Header
 // If the upgrade fails, then Upgrade replies to the client with an HTTP error
 // response.
 func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeader http.Header) (*Conn, error) {
-	const badHandshake = "websocket: the client is not using the websocket protocol: "
+	if r.Method != "GET" {
+		return u.returnError(w, r, http.StatusMethodNotAllowed, "websocket: not a websocket handshake: request method is not GET")
+	}
 
-	if !tokenListContainsValue(r.Header, "Connection", "upgrade") {
-		return u.returnError(w, r, http.StatusBadRequest, badHandshake+"'upgrade' token not found in 'Connection' header")
+	if _, ok := responseHeader["Sec-Websocket-Extensions"]; ok {
+		return u.returnError(w, r, http.StatusInternalServerError, "websocket: application specific 'Sec-Websocket-Extensions' headers are unsupported")
 	}
 
-	if !tokenListContainsValue(r.Header, "Upgrade", "websocket") {
-		return u.returnError(w, r, http.StatusBadRequest, badHandshake+"'websocket' token not found in 'Upgrade' header")
+	if !tokenListContainsValue(r.Header, "Connection", "upgrade") {
+		return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'upgrade' token not found in 'Connection' header")
 	}
 
-	if r.Method != "GET" {
-		return u.returnError(w, r, http.StatusMethodNotAllowed, badHandshake+"request method is not GET")
+	if !tokenListContainsValue(r.Header, "Upgrade", "websocket") {
+		return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'websocket' token not found in 'Upgrade' header")
 	}
 
 	if !tokenListContainsValue(r.Header, "Sec-Websocket-Version", "13") {
 		return u.returnError(w, r, http.StatusBadRequest, "websocket: unsupported version: 13 not found in 'Sec-Websocket-Version' header")
 	}
 
-	if _, ok := responseHeader["Sec-Websocket-Extensions"]; ok {
-		return u.returnError(w, r, http.StatusInternalServerError, "websocket: application specific 'Sec-Websocket-Extensions' headers are unsupported")
-	}
-
 	checkOrigin := u.CheckOrigin
 	if checkOrigin == nil {
 		checkOrigin = checkSameOrigin
@@ -232,11 +230,10 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
 
 // Upgrade upgrades the HTTP server connection to the WebSocket protocol.
 //
-// Deprecated: Use websocket.Upgrader instead.
+// This function is deprecated, use websocket.Upgrader instead.
 //
-// Upgrade does not perform origin checking. The application is responsible for
-// checking the Origin header before calling Upgrade. An example implementation
-// of the same origin policy check is:
+// The application is responsible for checking the request origin before
+// calling Upgrade. An example implementation of the same origin policy is:
 //
 //	if req.Header.Get("Origin") != "http://"+req.Host {
 //		http.Error(w, "Origin not allowed", 403)

+ 0 - 18
vendor/github.com/gorilla/websocket/server_test.go

@@ -49,21 +49,3 @@ func TestIsWebSocketUpgrade(t *testing.T) {
 		}
 	}
 }
-
-var checkSameOriginTests = []struct {
-	ok bool
-	r  *http.Request
-}{
-	{false, &http.Request{Host: "example.org", Header: map[string][]string{"Origin": []string{"https://other.org"}}}},
-	{true, &http.Request{Host: "example.org", Header: map[string][]string{"Origin": []string{"https://example.org"}}}},
-	{true, &http.Request{Host: "Example.org", Header: map[string][]string{"Origin": []string{"https://example.org"}}}},
-}
-
-func TestCheckSameOrigin(t *testing.T) {
-	for _, tt := range checkSameOriginTests {
-		ok := checkSameOrigin(tt.r)
-		if tt.ok != ok {
-			t.Errorf("checkSameOrigin(%+v) returned %v, want %v", tt.r, ok, tt.ok)
-		}
-	}
-}

+ 5 - 28
vendor/github.com/gorilla/websocket/util.go

@@ -11,7 +11,6 @@ import (
 	"io"
 	"net/http"
 	"strings"
-	"unicode/utf8"
 )
 
 var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
@@ -112,14 +111,14 @@ func nextTokenOrQuoted(s string) (value string, rest string) {
 				case escape:
 					escape = false
 					p[j] = b
-					j++
+					j += 1
 				case b == '\\':
 					escape = true
 				case b == '"':
 					return string(p[:j]), s[i+1:]
 				default:
 					p[j] = b
-					j++
+					j += 1
 				}
 			}
 			return "", ""
@@ -128,31 +127,8 @@ func nextTokenOrQuoted(s string) (value string, rest string) {
 	return "", ""
 }
 
-// equalASCIIFold returns true if s is equal to t with ASCII case folding.
-func equalASCIIFold(s, t string) bool {
-	for s != "" && t != "" {
-		sr, size := utf8.DecodeRuneInString(s)
-		s = s[size:]
-		tr, size := utf8.DecodeRuneInString(t)
-		t = t[size:]
-		if sr == tr {
-			continue
-		}
-		if 'A' <= sr && sr <= 'Z' {
-			sr = sr + 'a' - 'A'
-		}
-		if 'A' <= tr && tr <= 'Z' {
-			tr = tr + 'a' - 'A'
-		}
-		if sr != tr {
-			return false
-		}
-	}
-	return s == t
-}
-
 // tokenListContainsValue returns true if the 1#token header with the given
-// name contains a token equal to value with ASCII case folding.
+// name contains token.
 func tokenListContainsValue(header http.Header, name string, value string) bool {
 headers:
 	for _, s := range header[name] {
@@ -166,7 +142,7 @@ headers:
 			if s != "" && s[0] != ',' {
 				continue headers
 			}
-			if equalASCIIFold(t, value) {
+			if strings.EqualFold(t, value) {
 				return true
 			}
 			if s == "" {
@@ -180,6 +156,7 @@ headers:
 
 // parseExtensiosn parses WebSocket extensions from a header.
 func parseExtensions(header http.Header) []map[string]string {
+
 	// From RFC 6455:
 	//
 	//  Sec-WebSocket-Extensions = extension-list

+ 14 - 35
vendor/github.com/gorilla/websocket/util_test.go

@@ -10,24 +10,6 @@ import (
 	"testing"
 )
 
-var equalASCIIFoldTests = []struct {
-	t, s string
-	eq   bool
-}{
-	{"WebSocket", "websocket", true},
-	{"websocket", "WebSocket", true},
-	{"Öyster", "öyster", false},
-}
-
-func TestEqualASCIIFold(t *testing.T) {
-	for _, tt := range equalASCIIFoldTests {
-		eq := equalASCIIFold(tt.s, tt.t)
-		if eq != tt.eq {
-			t.Errorf("equalASCIIFold(%q, %q) = %v, want %v", tt.s, tt.t, eq, tt.eq)
-		}
-	}
-}
-
 var tokenListContainsValueTests = []struct {
 	value string
 	ok    bool
@@ -56,32 +38,29 @@ var parseExtensionTests = []struct {
 	value      string
 	extensions []map[string]string
 }{
-	{`foo`, []map[string]string{{"": "foo"}}},
+	{`foo`, []map[string]string{map[string]string{"": "foo"}}},
 	{`foo, bar; baz=2`, []map[string]string{
-		{"": "foo"},
-		{"": "bar", "baz": "2"}}},
+		map[string]string{"": "foo"},
+		map[string]string{"": "bar", "baz": "2"}}},
 	{`foo; bar="b,a;z"`, []map[string]string{
-		{"": "foo", "bar": "b,a;z"}}},
+		map[string]string{"": "foo", "bar": "b,a;z"}}},
 	{`foo , bar; baz = 2`, []map[string]string{
-		{"": "foo"},
-		{"": "bar", "baz": "2"}}},
+		map[string]string{"": "foo"},
+		map[string]string{"": "bar", "baz": "2"}}},
 	{`foo, bar; baz=2 junk`, []map[string]string{
-		{"": "foo"}}},
+		map[string]string{"": "foo"}}},
 	{`foo junk, bar; baz=2 junk`, nil},
 	{`mux; max-channels=4; flow-control, deflate-stream`, []map[string]string{
-		{"": "mux", "max-channels": "4", "flow-control": ""},
-		{"": "deflate-stream"}}},
+		map[string]string{"": "mux", "max-channels": "4", "flow-control": ""},
+		map[string]string{"": "deflate-stream"}}},
 	{`permessage-foo; x="10"`, []map[string]string{
-		{"": "permessage-foo", "x": "10"}}},
+		map[string]string{"": "permessage-foo", "x": "10"}}},
 	{`permessage-foo; use_y, permessage-foo`, []map[string]string{
-		{"": "permessage-foo", "use_y": ""},
-		{"": "permessage-foo"}}},
+		map[string]string{"": "permessage-foo", "use_y": ""},
+		map[string]string{"": "permessage-foo"}}},
 	{`permessage-deflate; client_max_window_bits; server_max_window_bits=10 , permessage-deflate; client_max_window_bits`, []map[string]string{
-		{"": "permessage-deflate", "client_max_window_bits": "", "server_max_window_bits": "10"},
-		{"": "permessage-deflate", "client_max_window_bits": ""}}},
-	{"permessage-deflate; server_no_context_takeover; client_max_window_bits=15", []map[string]string{
-		{"": "permessage-deflate", "server_no_context_takeover": "", "client_max_window_bits": "15"},
-	}},
+		map[string]string{"": "permessage-deflate", "client_max_window_bits": "", "server_max_window_bits": "10"},
+		map[string]string{"": "permessage-deflate", "client_max_window_bits": ""}}},
 }
 
 func TestParseExtensions(t *testing.T) {

+ 0 - 473
vendor/github.com/gorilla/websocket/x_net_proxy.go

@@ -1,473 +0,0 @@
-// Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.
-//go:generate bundle -o x_net_proxy.go golang.org/x/net/proxy
-
-// Package proxy provides support for a variety of protocols to proxy network
-// data.
-//
-
-package websocket
-
-import (
-	"errors"
-	"io"
-	"net"
-	"net/url"
-	"os"
-	"strconv"
-	"strings"
-	"sync"
-)
-
-type proxy_direct struct{}
-
-// Direct is a direct proxy: one that makes network connections directly.
-var proxy_Direct = proxy_direct{}
-
-func (proxy_direct) Dial(network, addr string) (net.Conn, error) {
-	return net.Dial(network, addr)
-}
-
-// A PerHost directs connections to a default Dialer unless the host name
-// requested matches one of a number of exceptions.
-type proxy_PerHost struct {
-	def, bypass proxy_Dialer
-
-	bypassNetworks []*net.IPNet
-	bypassIPs      []net.IP
-	bypassZones    []string
-	bypassHosts    []string
-}
-
-// NewPerHost returns a PerHost Dialer that directs connections to either
-// defaultDialer or bypass, depending on whether the connection matches one of
-// the configured rules.
-func proxy_NewPerHost(defaultDialer, bypass proxy_Dialer) *proxy_PerHost {
-	return &proxy_PerHost{
-		def:    defaultDialer,
-		bypass: bypass,
-	}
-}
-
-// Dial connects to the address addr on the given network through either
-// defaultDialer or bypass.
-func (p *proxy_PerHost) Dial(network, addr string) (c net.Conn, err error) {
-	host, _, err := net.SplitHostPort(addr)
-	if err != nil {
-		return nil, err
-	}
-
-	return p.dialerForRequest(host).Dial(network, addr)
-}
-
-func (p *proxy_PerHost) dialerForRequest(host string) proxy_Dialer {
-	if ip := net.ParseIP(host); ip != nil {
-		for _, net := range p.bypassNetworks {
-			if net.Contains(ip) {
-				return p.bypass
-			}
-		}
-		for _, bypassIP := range p.bypassIPs {
-			if bypassIP.Equal(ip) {
-				return p.bypass
-			}
-		}
-		return p.def
-	}
-
-	for _, zone := range p.bypassZones {
-		if strings.HasSuffix(host, zone) {
-			return p.bypass
-		}
-		if host == zone[1:] {
-			// For a zone ".example.com", we match "example.com"
-			// too.
-			return p.bypass
-		}
-	}
-	for _, bypassHost := range p.bypassHosts {
-		if bypassHost == host {
-			return p.bypass
-		}
-	}
-	return p.def
-}
-
-// AddFromString parses a string that contains comma-separated values
-// specifying hosts that should use the bypass proxy. Each value is either an
-// IP address, a CIDR range, a zone (*.example.com) or a host name
-// (localhost). A best effort is made to parse the string and errors are
-// ignored.
-func (p *proxy_PerHost) AddFromString(s string) {
-	hosts := strings.Split(s, ",")
-	for _, host := range hosts {
-		host = strings.TrimSpace(host)
-		if len(host) == 0 {
-			continue
-		}
-		if strings.Contains(host, "/") {
-			// We assume that it's a CIDR address like 127.0.0.0/8
-			if _, net, err := net.ParseCIDR(host); err == nil {
-				p.AddNetwork(net)
-			}
-			continue
-		}
-		if ip := net.ParseIP(host); ip != nil {
-			p.AddIP(ip)
-			continue
-		}
-		if strings.HasPrefix(host, "*.") {
-			p.AddZone(host[1:])
-			continue
-		}
-		p.AddHost(host)
-	}
-}
-
-// AddIP specifies an IP address that will use the bypass proxy. Note that
-// this will only take effect if a literal IP address is dialed. A connection
-// to a named host will never match an IP.
-func (p *proxy_PerHost) AddIP(ip net.IP) {
-	p.bypassIPs = append(p.bypassIPs, ip)
-}
-
-// AddNetwork specifies an IP range that will use the bypass proxy. Note that
-// this will only take effect if a literal IP address is dialed. A connection
-// to a named host will never match.
-func (p *proxy_PerHost) AddNetwork(net *net.IPNet) {
-	p.bypassNetworks = append(p.bypassNetworks, net)
-}
-
-// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of
-// "example.com" matches "example.com" and all of its subdomains.
-func (p *proxy_PerHost) AddZone(zone string) {
-	if strings.HasSuffix(zone, ".") {
-		zone = zone[:len(zone)-1]
-	}
-	if !strings.HasPrefix(zone, ".") {
-		zone = "." + zone
-	}
-	p.bypassZones = append(p.bypassZones, zone)
-}
-
-// AddHost specifies a host name that will use the bypass proxy.
-func (p *proxy_PerHost) AddHost(host string) {
-	if strings.HasSuffix(host, ".") {
-		host = host[:len(host)-1]
-	}
-	p.bypassHosts = append(p.bypassHosts, host)
-}
-
-// A Dialer is a means to establish a connection.
-type proxy_Dialer interface {
-	// Dial connects to the given address via the proxy.
-	Dial(network, addr string) (c net.Conn, err error)
-}
-
-// Auth contains authentication parameters that specific Dialers may require.
-type proxy_Auth struct {
-	User, Password string
-}
-
-// FromEnvironment returns the dialer specified by the proxy related variables in
-// the environment.
-func proxy_FromEnvironment() proxy_Dialer {
-	allProxy := proxy_allProxyEnv.Get()
-	if len(allProxy) == 0 {
-		return proxy_Direct
-	}
-
-	proxyURL, err := url.Parse(allProxy)
-	if err != nil {
-		return proxy_Direct
-	}
-	proxy, err := proxy_FromURL(proxyURL, proxy_Direct)
-	if err != nil {
-		return proxy_Direct
-	}
-
-	noProxy := proxy_noProxyEnv.Get()
-	if len(noProxy) == 0 {
-		return proxy
-	}
-
-	perHost := proxy_NewPerHost(proxy, proxy_Direct)
-	perHost.AddFromString(noProxy)
-	return perHost
-}
-
-// proxySchemes is a map from URL schemes to a function that creates a Dialer
-// from a URL with such a scheme.
-var proxy_proxySchemes map[string]func(*url.URL, proxy_Dialer) (proxy_Dialer, error)
-
-// RegisterDialerType takes a URL scheme and a function to generate Dialers from
-// a URL with that scheme and a forwarding Dialer. Registered schemes are used
-// by FromURL.
-func proxy_RegisterDialerType(scheme string, f func(*url.URL, proxy_Dialer) (proxy_Dialer, error)) {
-	if proxy_proxySchemes == nil {
-		proxy_proxySchemes = make(map[string]func(*url.URL, proxy_Dialer) (proxy_Dialer, error))
-	}
-	proxy_proxySchemes[scheme] = f
-}
-
-// FromURL returns a Dialer given a URL specification and an underlying
-// Dialer for it to make network requests.
-func proxy_FromURL(u *url.URL, forward proxy_Dialer) (proxy_Dialer, error) {
-	var auth *proxy_Auth
-	if u.User != nil {
-		auth = new(proxy_Auth)
-		auth.User = u.User.Username()
-		if p, ok := u.User.Password(); ok {
-			auth.Password = p
-		}
-	}
-
-	switch u.Scheme {
-	case "socks5":
-		return proxy_SOCKS5("tcp", u.Host, auth, forward)
-	}
-
-	// If the scheme doesn't match any of the built-in schemes, see if it
-	// was registered by another package.
-	if proxy_proxySchemes != nil {
-		if f, ok := proxy_proxySchemes[u.Scheme]; ok {
-			return f(u, forward)
-		}
-	}
-
-	return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
-}
-
-var (
-	proxy_allProxyEnv = &proxy_envOnce{
-		names: []string{"ALL_PROXY", "all_proxy"},
-	}
-	proxy_noProxyEnv = &proxy_envOnce{
-		names: []string{"NO_PROXY", "no_proxy"},
-	}
-)
-
-// envOnce looks up an environment variable (optionally by multiple
-// names) once. It mitigates expensive lookups on some platforms
-// (e.g. Windows).
-// (Borrowed from net/http/transport.go)
-type proxy_envOnce struct {
-	names []string
-	once  sync.Once
-	val   string
-}
-
-func (e *proxy_envOnce) Get() string {
-	e.once.Do(e.init)
-	return e.val
-}
-
-func (e *proxy_envOnce) init() {
-	for _, n := range e.names {
-		e.val = os.Getenv(n)
-		if e.val != "" {
-			return
-		}
-	}
-}
-
-// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address
-// with an optional username and password. See RFC 1928 and RFC 1929.
-func proxy_SOCKS5(network, addr string, auth *proxy_Auth, forward proxy_Dialer) (proxy_Dialer, error) {
-	s := &proxy_socks5{
-		network: network,
-		addr:    addr,
-		forward: forward,
-	}
-	if auth != nil {
-		s.user = auth.User
-		s.password = auth.Password
-	}
-
-	return s, nil
-}
-
-type proxy_socks5 struct {
-	user, password string
-	network, addr  string
-	forward        proxy_Dialer
-}
-
-const proxy_socks5Version = 5
-
-const (
-	proxy_socks5AuthNone     = 0
-	proxy_socks5AuthPassword = 2
-)
-
-const proxy_socks5Connect = 1
-
-const (
-	proxy_socks5IP4    = 1
-	proxy_socks5Domain = 3
-	proxy_socks5IP6    = 4
-)
-
-var proxy_socks5Errors = []string{
-	"",
-	"general failure",
-	"connection forbidden",
-	"network unreachable",
-	"host unreachable",
-	"connection refused",
-	"TTL expired",
-	"command not supported",
-	"address type not supported",
-}
-
-// Dial connects to the address addr on the given network via the SOCKS5 proxy.
-func (s *proxy_socks5) Dial(network, addr string) (net.Conn, error) {
-	switch network {
-	case "tcp", "tcp6", "tcp4":
-	default:
-		return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network)
-	}
-
-	conn, err := s.forward.Dial(s.network, s.addr)
-	if err != nil {
-		return nil, err
-	}
-	if err := s.connect(conn, addr); err != nil {
-		conn.Close()
-		return nil, err
-	}
-	return conn, nil
-}
-
-// connect takes an existing connection to a socks5 proxy server,
-// and commands the server to extend that connection to target,
-// which must be a canonical address with a host and port.
-func (s *proxy_socks5) connect(conn net.Conn, target string) error {
-	host, portStr, err := net.SplitHostPort(target)
-	if err != nil {
-		return err
-	}
-
-	port, err := strconv.Atoi(portStr)
-	if err != nil {
-		return errors.New("proxy: failed to parse port number: " + portStr)
-	}
-	if port < 1 || port > 0xffff {
-		return errors.New("proxy: port number out of range: " + portStr)
-	}
-
-	// the size here is just an estimate
-	buf := make([]byte, 0, 6+len(host))
-
-	buf = append(buf, proxy_socks5Version)
-	if len(s.user) > 0 && len(s.user) < 256 && len(s.password) < 256 {
-		buf = append(buf, 2 /* num auth methods */, proxy_socks5AuthNone, proxy_socks5AuthPassword)
-	} else {
-		buf = append(buf, 1 /* num auth methods */, proxy_socks5AuthNone)
-	}
-
-	if _, err := conn.Write(buf); err != nil {
-		return errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error())
-	}
-
-	if _, err := io.ReadFull(conn, buf[:2]); err != nil {
-		return errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error())
-	}
-	if buf[0] != 5 {
-		return errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0])))
-	}
-	if buf[1] == 0xff {
-		return errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication")
-	}
-
-	// See RFC 1929
-	if buf[1] == proxy_socks5AuthPassword {
-		buf = buf[:0]
-		buf = append(buf, 1 /* password protocol version */)
-		buf = append(buf, uint8(len(s.user)))
-		buf = append(buf, s.user...)
-		buf = append(buf, uint8(len(s.password)))
-		buf = append(buf, s.password...)
-
-		if _, err := conn.Write(buf); err != nil {
-			return errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
-		}
-
-		if _, err := io.ReadFull(conn, buf[:2]); err != nil {
-			return errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
-		}
-
-		if buf[1] != 0 {
-			return errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password")
-		}
-	}
-
-	buf = buf[:0]
-	buf = append(buf, proxy_socks5Version, proxy_socks5Connect, 0 /* reserved */)
-
-	if ip := net.ParseIP(host); ip != nil {
-		if ip4 := ip.To4(); ip4 != nil {
-			buf = append(buf, proxy_socks5IP4)
-			ip = ip4
-		} else {
-			buf = append(buf, proxy_socks5IP6)
-		}
-		buf = append(buf, ip...)
-	} else {
-		if len(host) > 255 {
-			return errors.New("proxy: destination host name too long: " + host)
-		}
-		buf = append(buf, proxy_socks5Domain)
-		buf = append(buf, byte(len(host)))
-		buf = append(buf, host...)
-	}
-	buf = append(buf, byte(port>>8), byte(port))
-
-	if _, err := conn.Write(buf); err != nil {
-		return errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
-	}
-
-	if _, err := io.ReadFull(conn, buf[:4]); err != nil {
-		return errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
-	}
-
-	failure := "unknown error"
-	if int(buf[1]) < len(proxy_socks5Errors) {
-		failure = proxy_socks5Errors[buf[1]]
-	}
-
-	if len(failure) > 0 {
-		return errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure)
-	}
-
-	bytesToDiscard := 0
-	switch buf[3] {
-	case proxy_socks5IP4:
-		bytesToDiscard = net.IPv4len
-	case proxy_socks5IP6:
-		bytesToDiscard = net.IPv6len
-	case proxy_socks5Domain:
-		_, err := io.ReadFull(conn, buf[:1])
-		if err != nil {
-			return errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error())
-		}
-		bytesToDiscard = int(buf[0])
-	default:
-		return errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr)
-	}
-
-	if cap(buf) < bytesToDiscard {
-		buf = make([]byte, bytesToDiscard)
-	} else {
-		buf = buf[:bytesToDiscard]
-	}
-	if _, err := io.ReadFull(conn, buf); err != nil {
-		return errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error())
-	}
-
-	// Also need to discard the port number
-	if _, err := io.ReadFull(conn, buf[:2]); err != nil {
-		return errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error())
-	}
-
-	return nil
-}

+ 0 - 24
vendor/github.com/xtaci/kcp-go/.gitignore

@@ -1,24 +0,0 @@
-# Compiled Object files, Static and Dynamic libs (Shared Objects)
-*.o
-*.a
-*.so
-
-# Folders
-_obj
-_test
-
-# Architecture specific extensions/prefixes
-*.[568vq]
-[568vq].out
-
-*.cgo1.go
-*.cgo2.c
-_cgo_defun.c
-_cgo_gotypes.go
-_cgo_export.*
-
-_testmain.go
-
-*.exe
-*.test
-*.prof

+ 0 - 15
vendor/github.com/xtaci/kcp-go/.travis.yml

@@ -1,15 +0,0 @@
-language: go
-go:
-    - 1.8
-
-before_install:
-    - go get -t -v ./...
-
-install:
-    - go get github.com/xtaci/kcp-go
-
-script:
-    - go test -coverprofile=coverage.txt -covermode=atomic -bench .
-
-after_success:
-    - bash <(curl -s https://codecov.io/bash)

+ 0 - 22
vendor/github.com/xtaci/kcp-go/LICENSE

@@ -1,22 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 Daniel Fu
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-

+ 0 - 171
vendor/github.com/xtaci/kcp-go/README.md

@@ -1,171 +0,0 @@
-<img src="kcp-go.png" alt="kcp-go" height="50px" />
-
-
-[![GoDoc][1]][2] [![Powered][9]][10] [![MIT licensed][11]][12] [![Build Status][3]][4] [![Go Report Card][5]][6] [![Coverage Statusd][7]][8]
-
-[1]: https://godoc.org/github.com/xtaci/kcp-go?status.svg
-[2]: https://godoc.org/github.com/xtaci/kcp-go
-[3]: https://travis-ci.org/xtaci/kcp-go.svg?branch=master
-[4]: https://travis-ci.org/xtaci/kcp-go
-[5]: https://goreportcard.com/badge/github.com/xtaci/kcp-go
-[6]: https://goreportcard.com/report/github.com/xtaci/kcp-go
-[7]: https://codecov.io/gh/xtaci/kcp-go/branch/master/graph/badge.svg
-[8]: https://codecov.io/gh/xtaci/kcp-go
-[9]: https://img.shields.io/badge/KCP-Powered-blue.svg
-[10]: https://github.com/skywind3000/kcp
-[11]: https://img.shields.io/badge/license-MIT-blue.svg
-[12]: LICENSE
-
-## Introduction
-
-**kcp-go** is a **Production-Grade Reliable-UDP** library for [golang](https://golang.org/). 
-
-It provides **fast, ordered and error-checked** delivery of streams over **UDP** packets, has been well tested with opensource project [kcptun](https://github.com/xtaci/kcptun). Millions of devices(from low-end MIPS routers to high-end servers) are running with **kcp-go** at present, including applications like **online games, live broadcasting, file synchronization and network acceleration**.
-
-[Lastest Release](https://github.com/xtaci/kcp-go/releases)
-
-## Features
-
-1. Optimized for **Realtime Multiplayer Games, Audio/Video Streaming**.
-1. Compatible with [skywind3000's](https://github.com/skywind3000) C version with language specific optimizations.
-1. **Cache friendly** and **Memory optimized** design, offers extremely **High Performance** core.
-1. Compatible with [net.Conn](https://golang.org/pkg/net/#Conn) and [net.Listener](https://golang.org/pkg/net/#Listener), easy to use.
-1. [FEC(Forward Error Correction)](https://en.wikipedia.org/wiki/Forward_error_correction) Support with [Reed-Solomon Codes](https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction)
-1. Packet level encryption support with [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard), [TEA](https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm), [3DES](https://en.wikipedia.org/wiki/Triple_DES), [Blowfish](https://en.wikipedia.org/wiki/Blowfish_(cipher)), [Cast5](https://en.wikipedia.org/wiki/CAST-128), [Salsa20]( https://en.wikipedia.org/wiki/Salsa20), etc. in [CFB](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Feedback_.28CFB.29) mode.
-1. **O(1) goroutines** created for the entire server application, minimized goroutine context switch.
-
-## Conventions
-
-Control messages like **SYN/FIN/RST** in TCP **are not defined** in KCP, you need some **keepalive/heartbeat mechanism** in the application-level. A real world example is to use some **multiplexing** protocol over session, such as [smux](https://github.com/xtaci/smux)(with embedded keepalive mechanism), see [kcptun](https://github.com/xtaci/kcptun) for example.
-
-## Documentation
-
-For complete documentation, see the associated [Godoc](https://godoc.org/github.com/xtaci/kcp-go).
-
-## Specification
-
-<img src="frame.png" alt="Frame Format" height="109px" />
-
-```
-+-----------------+
-| SESSION         |
-+-----------------+
-| KCP(ARQ)        |
-+-----------------+
-| FEC(OPTIONAL)   |
-+-----------------+
-| CRYPTO(OPTIONAL)|
-+-----------------+
-| UDP(PACKET)     |
-+-----------------+
-| IP              |
-+-----------------+
-| LINK            |
-+-----------------+
-| PHY             |
-+-----------------+
-(LAYER MODEL OF KCP-GO)
-```
-
-
-## Usage
-
-Client:   [full demo](https://github.com/xtaci/kcptun/blob/master/client/main.go)
-```go
-kcpconn, err := kcp.DialWithOptions("192.168.0.1:10000", nil, 10, 3)
-```
-Server:   [full demo](https://github.com/xtaci/kcptun/blob/master/server/main.go)
-```go
-lis, err := kcp.ListenWithOptions(":10000", nil, 10, 3)
-```
-
-## Performance
-```
-  Model Name:	MacBook Pro
-  Model Identifier:	MacBookPro12,1
-  Processor Name:	Intel Core i5
-  Processor Speed:	2.7 GHz
-  Number of Processors:	1
-  Total Number of Cores:	2
-  L2 Cache (per Core):	256 KB
-  L3 Cache:	3 MB
-  Memory:	8 GB
-```
-```
-$ go test -v -run=^$ -bench .
-beginning tests, encryption:salsa20, fec:10/3
-BenchmarkAES128-4          	  200000	      8256 ns/op	 363.33 MB/s	       0 B/op	       0 allocs/op
-BenchmarkAES192-4          	  200000	      9153 ns/op	 327.74 MB/s	       0 B/op	       0 allocs/op
-BenchmarkAES256-4          	  200000	     10079 ns/op	 297.64 MB/s	       0 B/op	       0 allocs/op
-BenchmarkTEA-4             	  100000	     18643 ns/op	 160.91 MB/s	       0 B/op	       0 allocs/op
-BenchmarkXOR-4             	 5000000	       316 ns/op	9486.46 MB/s	       0 B/op	       0 allocs/op
-BenchmarkBlowfish-4        	   50000	     35643 ns/op	  84.17 MB/s	       0 B/op	       0 allocs/op
-BenchmarkNone-4            	30000000	        56.2 ns/op	53371.83 MB/s	       0 B/op	       0 allocs/op
-BenchmarkCast5-4           	   30000	     44744 ns/op	  67.05 MB/s	       0 B/op	       0 allocs/op
-Benchmark3DES-4            	    2000	    639839 ns/op	   4.69 MB/s	       2 B/op	       0 allocs/op
-BenchmarkTwofish-4         	   30000	     43368 ns/op	  69.17 MB/s	       0 B/op	       0 allocs/op
-BenchmarkXTEA-4            	   30000	     57673 ns/op	  52.02 MB/s	       0 B/op	       0 allocs/op
-BenchmarkSalsa20-4         	  300000	      3917 ns/op	 765.80 MB/s	       0 B/op	       0 allocs/op
-BenchmarkFlush-4           	10000000	       226 ns/op	       0 B/op	       0 allocs/op
-BenchmarkEchoSpeed4K-4     	    5000	    300030 ns/op	  13.65 MB/s	    5672 B/op	     177 allocs/op
-BenchmarkEchoSpeed64K-4    	     500	   3202335 ns/op	  20.47 MB/s	   73295 B/op	    2198 allocs/op
-BenchmarkEchoSpeed512K-4   	      50	  24926924 ns/op	  21.03 MB/s	  659339 B/op	   17602 allocs/op
-BenchmarkEchoSpeed1M-4     	      20	  64857821 ns/op	  16.17 MB/s	 1772437 B/op	   42869 allocs/op
-BenchmarkSinkSpeed4K-4     	   30000	     50230 ns/op	  81.54 MB/s	    2058 B/op	      48 allocs/op
-BenchmarkSinkSpeed64K-4    	    2000	    648718 ns/op	 101.02 MB/s	   31165 B/op	     687 allocs/op
-BenchmarkSinkSpeed256K-4   	     300	   4635905 ns/op	 113.09 MB/s	  286229 B/op	    5516 allocs/op
-BenchmarkSinkSpeed1M-4     	     200	   9566933 ns/op	 109.60 MB/s	  463771 B/op	   10701 allocs/op
-PASS
-ok  	_/Users/xtaci/.godeps/src/github.com/xtaci/kcp-go	39.689s
-```
-
-## Design Considerations
-
-1. slice vs. container/list
-
-`kcp.flush()` loops through the send queue for retransmission checking for every 20ms(interval).
-
-I've wrote a benchmark for comparing sequential loop through *slice* and *container/list* here:
-
-https://github.com/xtaci/notes/blob/master/golang/benchmark2/cachemiss_test.go
-
-```
-BenchmarkLoopSlice-4   	2000000000	         0.39 ns/op
-BenchmarkLoopList-4    	100000000	        54.6 ns/op
-```
-
-List structure introduces **heavy cache misses** compared to slice which owns better **locality**, 5000 connections with 32 window size and 20ms interval will cost 6us/0.03%(cpu) using slice, and 8.7ms/43.5%(cpu) for list for each `kcp.flush()`.
-
-2. Timing accuracy vs. syscall clock_gettime
-
-Timing is **critical** to **RTT estimator**, inaccurate timing introduces false retransmissions in KCP, but calling `time.Now()` costs 42 cycles(10.5ns on 4GHz CPU, 15.6ns on my MacBook Pro 2.7GHz), the benchmark for time.Now():
-
-https://github.com/xtaci/notes/blob/master/golang/benchmark2/syscall_test.go
-
-```
-BenchmarkNow-4         	100000000	        15.6 ns/op
-```
-
-In kcp-go, after each `kcp.output()` function call, current time will be updated upon return, and each `kcp.flush()` will get current time once. For most of the time, 5000 connections costs 5000 * 15.6ns = 78us(no packet needs to be sent by `kcp.output()`), as for 10MB/s data transfering with 1400 MTU, `kcp.output()` will be called around 7500 times and costs 117us for `time.Now()` in **every second**.
-
-
-## Tuning
-
-Q: I'm running > 3000 connections on my server. the CPU utilization is high.
-
-A: A standalone `agent` or `gate` server for kcp-go is suggested, not only for CPU utilization, but also important to the **precision** of RTT measurements which indirectly affects retransmission. By increasing update `interval` with `SetNoDelay` like `conn.SetNoDelay(1, 40, 1, 1)` will dramatically reduce system load.
-
-## Who is using this?
-
-1. https://github.com/xtaci/kcptun -- A Secure Tunnel Based On KCP over UDP.
-2. https://github.com/getlantern/lantern -- Lantern delivers fast access to the open Internet. 
-3. https://github.com/smallnest/rpcx -- A RPC service framework based on net/rpc like alibaba Dubbo and weibo Motan.
-4. https://github.com/gonet2/agent -- A gateway for games with stream multiplexing.
-5. https://github.com/syncthing/syncthing -- Open Source Continuous File Synchronization.
-6. https://play.google.com/store/apps/details?id=com.k17game.k3 -- Battle Zone - Earth 2048, a world-wide strategy game.
-
-## Links
-
-1. https://github.com/xtaci/libkcp -- FEC enhanced KCP session library for iOS/Android in C++
-2. https://github.com/skywind3000/kcp -- A Fast and Reliable ARQ Protocol
-3. https://github.com/klauspost/reedsolomon -- Reed-Solomon Erasure Coding in Go

+ 0 - 263
vendor/github.com/xtaci/kcp-go/crypt.go

@@ -1,263 +0,0 @@
-package kcp
-
-import (
-	"crypto/aes"
-	"crypto/cipher"
-	"crypto/des"
-	"crypto/sha1"
-
-	"golang.org/x/crypto/blowfish"
-	"golang.org/x/crypto/cast5"
-	"golang.org/x/crypto/pbkdf2"
-	"golang.org/x/crypto/salsa20"
-	"golang.org/x/crypto/tea"
-	"golang.org/x/crypto/twofish"
-	"golang.org/x/crypto/xtea"
-)
-
-var (
-	initialVector = []byte{167, 115, 79, 156, 18, 172, 27, 1, 164, 21, 242, 193, 252, 120, 230, 107}
-	saltxor       = `sH3CIVoF#rWLtJo6`
-)
-
-// BlockCrypt defines encryption/decryption methods for a given byte slice.
-// Notes on implementing: the data to be encrypted contains a builtin
-// nonce at the first 16 bytes
-type BlockCrypt interface {
-	// Encrypt encrypts the whole block in src into dst.
-	// Dst and src may point at the same memory.
-	Encrypt(dst, src []byte)
-
-	// Decrypt decrypts the whole block in src into dst.
-	// Dst and src may point at the same memory.
-	Decrypt(dst, src []byte)
-}
-
-type salsa20BlockCrypt struct {
-	key [32]byte
-}
-
-// NewSalsa20BlockCrypt https://en.wikipedia.org/wiki/Salsa20
-func NewSalsa20BlockCrypt(key []byte) (BlockCrypt, error) {
-	c := new(salsa20BlockCrypt)
-	copy(c.key[:], key)
-	return c, nil
-}
-
-func (c *salsa20BlockCrypt) Encrypt(dst, src []byte) {
-	salsa20.XORKeyStream(dst[8:], src[8:], src[:8], &c.key)
-	copy(dst[:8], src[:8])
-}
-func (c *salsa20BlockCrypt) Decrypt(dst, src []byte) {
-	salsa20.XORKeyStream(dst[8:], src[8:], src[:8], &c.key)
-	copy(dst[:8], src[:8])
-}
-
-type twofishBlockCrypt struct {
-	encbuf []byte
-	decbuf []byte
-	block  cipher.Block
-}
-
-// NewTwofishBlockCrypt https://en.wikipedia.org/wiki/Twofish
-func NewTwofishBlockCrypt(key []byte) (BlockCrypt, error) {
-	c := new(twofishBlockCrypt)
-	block, err := twofish.NewCipher(key)
-	if err != nil {
-		return nil, err
-	}
-	c.block = block
-	c.encbuf = make([]byte, twofish.BlockSize)
-	c.decbuf = make([]byte, 2*twofish.BlockSize)
-	return c, nil
-}
-
-func (c *twofishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
-func (c *twofishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-type tripleDESBlockCrypt struct {
-	encbuf []byte
-	decbuf []byte
-	block  cipher.Block
-}
-
-// NewTripleDESBlockCrypt https://en.wikipedia.org/wiki/Triple_DES
-func NewTripleDESBlockCrypt(key []byte) (BlockCrypt, error) {
-	c := new(tripleDESBlockCrypt)
-	block, err := des.NewTripleDESCipher(key)
-	if err != nil {
-		return nil, err
-	}
-	c.block = block
-	c.encbuf = make([]byte, des.BlockSize)
-	c.decbuf = make([]byte, 2*des.BlockSize)
-	return c, nil
-}
-
-func (c *tripleDESBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
-func (c *tripleDESBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-type cast5BlockCrypt struct {
-	encbuf []byte
-	decbuf []byte
-	block  cipher.Block
-}
-
-// NewCast5BlockCrypt https://en.wikipedia.org/wiki/CAST-128
-func NewCast5BlockCrypt(key []byte) (BlockCrypt, error) {
-	c := new(cast5BlockCrypt)
-	block, err := cast5.NewCipher(key)
-	if err != nil {
-		return nil, err
-	}
-	c.block = block
-	c.encbuf = make([]byte, cast5.BlockSize)
-	c.decbuf = make([]byte, 2*cast5.BlockSize)
-	return c, nil
-}
-
-func (c *cast5BlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
-func (c *cast5BlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-type blowfishBlockCrypt struct {
-	encbuf []byte
-	decbuf []byte
-	block  cipher.Block
-}
-
-// NewBlowfishBlockCrypt https://en.wikipedia.org/wiki/Blowfish_(cipher)
-func NewBlowfishBlockCrypt(key []byte) (BlockCrypt, error) {
-	c := new(blowfishBlockCrypt)
-	block, err := blowfish.NewCipher(key)
-	if err != nil {
-		return nil, err
-	}
-	c.block = block
-	c.encbuf = make([]byte, blowfish.BlockSize)
-	c.decbuf = make([]byte, 2*blowfish.BlockSize)
-	return c, nil
-}
-
-func (c *blowfishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
-func (c *blowfishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-type aesBlockCrypt struct {
-	encbuf []byte
-	decbuf []byte
-	block  cipher.Block
-}
-
-// NewAESBlockCrypt https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
-func NewAESBlockCrypt(key []byte) (BlockCrypt, error) {
-	c := new(aesBlockCrypt)
-	block, err := aes.NewCipher(key)
-	if err != nil {
-		return nil, err
-	}
-	c.block = block
-	c.encbuf = make([]byte, aes.BlockSize)
-	c.decbuf = make([]byte, 2*aes.BlockSize)
-	return c, nil
-}
-
-func (c *aesBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
-func (c *aesBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-type teaBlockCrypt struct {
-	encbuf []byte
-	decbuf []byte
-	block  cipher.Block
-}
-
-// NewTEABlockCrypt https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
-func NewTEABlockCrypt(key []byte) (BlockCrypt, error) {
-	c := new(teaBlockCrypt)
-	block, err := tea.NewCipherWithRounds(key, 16)
-	if err != nil {
-		return nil, err
-	}
-	c.block = block
-	c.encbuf = make([]byte, tea.BlockSize)
-	c.decbuf = make([]byte, 2*tea.BlockSize)
-	return c, nil
-}
-
-func (c *teaBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
-func (c *teaBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-type xteaBlockCrypt struct {
-	encbuf []byte
-	decbuf []byte
-	block  cipher.Block
-}
-
-// NewXTEABlockCrypt https://en.wikipedia.org/wiki/XTEA
-func NewXTEABlockCrypt(key []byte) (BlockCrypt, error) {
-	c := new(xteaBlockCrypt)
-	block, err := xtea.NewCipher(key)
-	if err != nil {
-		return nil, err
-	}
-	c.block = block
-	c.encbuf = make([]byte, xtea.BlockSize)
-	c.decbuf = make([]byte, 2*xtea.BlockSize)
-	return c, nil
-}
-
-func (c *xteaBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
-func (c *xteaBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-type simpleXORBlockCrypt struct {
-	xortbl []byte
-}
-
-// NewSimpleXORBlockCrypt simple xor with key expanding
-func NewSimpleXORBlockCrypt(key []byte) (BlockCrypt, error) {
-	c := new(simpleXORBlockCrypt)
-	c.xortbl = pbkdf2.Key(key, []byte(saltxor), 32, mtuLimit, sha1.New)
-	return c, nil
-}
-
-func (c *simpleXORBlockCrypt) Encrypt(dst, src []byte) { xorBytes(dst, src, c.xortbl) }
-func (c *simpleXORBlockCrypt) Decrypt(dst, src []byte) { xorBytes(dst, src, c.xortbl) }
-
-type noneBlockCrypt struct{}
-
-// NewNoneBlockCrypt does nothing but copying
-func NewNoneBlockCrypt(key []byte) (BlockCrypt, error) {
-	return new(noneBlockCrypt), nil
-}
-
-func (c *noneBlockCrypt) Encrypt(dst, src []byte) { copy(dst, src) }
-func (c *noneBlockCrypt) Decrypt(dst, src []byte) { copy(dst, src) }
-
-// packet encryption with local CFB mode
-func encrypt(block cipher.Block, dst, src, buf []byte) {
-	blocksize := block.BlockSize()
-	tbl := buf[:blocksize]
-	block.Encrypt(tbl, initialVector)
-	n := len(src) / blocksize
-	base := 0
-	for i := 0; i < n; i++ {
-		xorWords(dst[base:], src[base:], tbl)
-		block.Encrypt(tbl, dst[base:])
-		base += blocksize
-	}
-	xorBytes(dst[base:], src[base:], tbl)
-}
-
-func decrypt(block cipher.Block, dst, src, buf []byte) {
-	blocksize := block.BlockSize()
-	tbl := buf[:blocksize]
-	next := buf[blocksize:]
-	block.Encrypt(tbl, initialVector)
-	n := len(src) / blocksize
-	base := 0
-	for i := 0; i < n; i++ {
-		block.Encrypt(next, src[base:])
-		xorWords(dst[base:], src[base:], tbl)
-		tbl, next = next, tbl
-		base += blocksize
-	}
-	xorBytes(dst[base:], src[base:], tbl)
-}

+ 0 - 222
vendor/github.com/xtaci/kcp-go/crypt_test.go

@@ -1,222 +0,0 @@
-package kcp
-
-import (
-	"bytes"
-	"crypto/rand"
-	"hash/crc32"
-	"io"
-	"testing"
-)
-
-func TestAES(t *testing.T) {
-	bc, err := NewAESBlockCrypt(pass[:32])
-	if err != nil {
-		t.Fatal(err)
-	}
-	cryptTest(t, bc)
-}
-
-func TestTEA(t *testing.T) {
-	bc, err := NewTEABlockCrypt(pass[:16])
-	if err != nil {
-		t.Fatal(err)
-	}
-	cryptTest(t, bc)
-}
-
-func TestXOR(t *testing.T) {
-	bc, err := NewSimpleXORBlockCrypt(pass[:32])
-	if err != nil {
-		t.Fatal(err)
-	}
-	cryptTest(t, bc)
-}
-
-func TestBlowfish(t *testing.T) {
-	bc, err := NewBlowfishBlockCrypt(pass[:32])
-	if err != nil {
-		t.Fatal(err)
-	}
-	cryptTest(t, bc)
-}
-
-func TestNone(t *testing.T) {
-	bc, err := NewNoneBlockCrypt(pass[:32])
-	if err != nil {
-		t.Fatal(err)
-	}
-	cryptTest(t, bc)
-}
-
-func TestCast5(t *testing.T) {
-	bc, err := NewCast5BlockCrypt(pass[:16])
-	if err != nil {
-		t.Fatal(err)
-	}
-	cryptTest(t, bc)
-}
-
-func Test3DES(t *testing.T) {
-	bc, err := NewTripleDESBlockCrypt(pass[:24])
-	if err != nil {
-		t.Fatal(err)
-	}
-	cryptTest(t, bc)
-}
-
-func TestTwofish(t *testing.T) {
-	bc, err := NewTwofishBlockCrypt(pass[:32])
-	if err != nil {
-		t.Fatal(err)
-	}
-	cryptTest(t, bc)
-}
-
-func TestXTEA(t *testing.T) {
-	bc, err := NewXTEABlockCrypt(pass[:16])
-	if err != nil {
-		t.Fatal(err)
-	}
-	cryptTest(t, bc)
-}
-
-func TestSalsa20(t *testing.T) {
-	bc, err := NewSalsa20BlockCrypt(pass[:32])
-	if err != nil {
-		t.Fatal(err)
-	}
-	cryptTest(t, bc)
-}
-
-func cryptTest(t *testing.T, bc BlockCrypt) {
-	data := make([]byte, mtuLimit)
-	io.ReadFull(rand.Reader, data)
-	dec := make([]byte, mtuLimit)
-	enc := make([]byte, mtuLimit)
-	bc.Encrypt(enc, data)
-	bc.Decrypt(dec, enc)
-	if !bytes.Equal(data, dec) {
-		t.Fail()
-	}
-}
-
-func BenchmarkAES128(b *testing.B) {
-	bc, err := NewAESBlockCrypt(pass[:16])
-	if err != nil {
-		b.Fatal(err)
-	}
-
-	benchCrypt(b, bc)
-}
-
-func BenchmarkAES192(b *testing.B) {
-	bc, err := NewAESBlockCrypt(pass[:24])
-	if err != nil {
-		b.Fatal(err)
-	}
-
-	benchCrypt(b, bc)
-}
-
-func BenchmarkAES256(b *testing.B) {
-	bc, err := NewAESBlockCrypt(pass[:32])
-	if err != nil {
-		b.Fatal(err)
-	}
-
-	benchCrypt(b, bc)
-}
-
-func BenchmarkTEA(b *testing.B) {
-	bc, err := NewTEABlockCrypt(pass[:16])
-	if err != nil {
-		b.Fatal(err)
-	}
-	benchCrypt(b, bc)
-}
-
-func BenchmarkXOR(b *testing.B) {
-	bc, err := NewSimpleXORBlockCrypt(pass[:32])
-	if err != nil {
-		b.Fatal(err)
-	}
-	benchCrypt(b, bc)
-}
-
-func BenchmarkBlowfish(b *testing.B) {
-	bc, err := NewBlowfishBlockCrypt(pass[:32])
-	if err != nil {
-		b.Fatal(err)
-	}
-	benchCrypt(b, bc)
-}
-
-func BenchmarkNone(b *testing.B) {
-	bc, err := NewNoneBlockCrypt(pass[:32])
-	if err != nil {
-		b.Fatal(err)
-	}
-	benchCrypt(b, bc)
-}
-
-func BenchmarkCast5(b *testing.B) {
-	bc, err := NewCast5BlockCrypt(pass[:16])
-	if err != nil {
-		b.Fatal(err)
-	}
-	benchCrypt(b, bc)
-}
-
-func Benchmark3DES(b *testing.B) {
-	bc, err := NewTripleDESBlockCrypt(pass[:24])
-	if err != nil {
-		b.Fatal(err)
-	}
-	benchCrypt(b, bc)
-}
-
-func BenchmarkTwofish(b *testing.B) {
-	bc, err := NewTwofishBlockCrypt(pass[:32])
-	if err != nil {
-		b.Fatal(err)
-	}
-	benchCrypt(b, bc)
-}
-
-func BenchmarkXTEA(b *testing.B) {
-	bc, err := NewXTEABlockCrypt(pass[:16])
-	if err != nil {
-		b.Fatal(err)
-	}
-	benchCrypt(b, bc)
-}
-
-func BenchmarkSalsa20(b *testing.B) {
-	bc, err := NewSalsa20BlockCrypt(pass[:32])
-	if err != nil {
-		b.Fatal(err)
-	}
-	benchCrypt(b, bc)
-}
-
-func benchCrypt(b *testing.B, bc BlockCrypt) {
-	b.ReportAllocs()
-	data := make([]byte, mtuLimit)
-	io.ReadFull(rand.Reader, data)
-	dec := make([]byte, mtuLimit)
-	enc := make([]byte, mtuLimit)
-
-	for i := 0; i < b.N; i++ {
-		bc.Encrypt(enc, data)
-		bc.Decrypt(dec, enc)
-	}
-	b.SetBytes(int64(len(enc) * 2))
-}
-
-func BenchmarkCRC32(b *testing.B) {
-	content := make([]byte, 1024)
-	b.SetBytes(int64(len(content)))
-	for i := 0; i < b.N; i++ {
-		crc32.ChecksumIEEE(content)
-	}
-}

BIN
vendor/github.com/xtaci/kcp-go/donate.png


+ 0 - 303
vendor/github.com/xtaci/kcp-go/fec.go

@@ -1,303 +0,0 @@
-package kcp
-
-import (
-	"encoding/binary"
-	"sync/atomic"
-
-	"github.com/klauspost/reedsolomon"
-)
-
-const (
-	fecHeaderSize      = 6
-	fecHeaderSizePlus2 = fecHeaderSize + 2 // plus 2B data size
-	typeData           = 0xf1
-	typeFEC            = 0xf2
-)
-
-type (
-	// fecPacket is a decoded FEC packet
-	fecPacket struct {
-		seqid uint32
-		flag  uint16
-		data  []byte
-	}
-
-	// fecDecoder for decoding incoming packets
-	fecDecoder struct {
-		rxlimit      int // queue size limit
-		dataShards   int
-		parityShards int
-		shardSize    int
-		rx           []fecPacket // ordered receive queue
-
-		// caches
-		decodeCache [][]byte
-		flagCache   []bool
-
-		// RS decoder
-		codec reedsolomon.Encoder
-	}
-)
-
-func newFECDecoder(rxlimit, dataShards, parityShards int) *fecDecoder {
-	if dataShards <= 0 || parityShards <= 0 {
-		return nil
-	}
-	if rxlimit < dataShards+parityShards {
-		return nil
-	}
-
-	fec := new(fecDecoder)
-	fec.rxlimit = rxlimit
-	fec.dataShards = dataShards
-	fec.parityShards = parityShards
-	fec.shardSize = dataShards + parityShards
-	enc, err := reedsolomon.New(dataShards, parityShards, reedsolomon.WithMaxGoroutines(1))
-	if err != nil {
-		return nil
-	}
-	fec.codec = enc
-	fec.decodeCache = make([][]byte, fec.shardSize)
-	fec.flagCache = make([]bool, fec.shardSize)
-	return fec
-}
-
-// decodeBytes a fec packet
-func (dec *fecDecoder) decodeBytes(data []byte) fecPacket {
-	var pkt fecPacket
-	pkt.seqid = binary.LittleEndian.Uint32(data)
-	pkt.flag = binary.LittleEndian.Uint16(data[4:])
-	// allocate memory & copy
-	buf := xmitBuf.Get().([]byte)[:len(data)-6]
-	copy(buf, data[6:])
-	pkt.data = buf
-	return pkt
-}
-
-// decode a fec packet
-func (dec *fecDecoder) decode(pkt fecPacket) (recovered [][]byte) {
-	// insertion
-	n := len(dec.rx) - 1
-	insertIdx := 0
-	for i := n; i >= 0; i-- {
-		if pkt.seqid == dec.rx[i].seqid { // de-duplicate
-			xmitBuf.Put(pkt.data)
-			return nil
-		} else if _itimediff(pkt.seqid, dec.rx[i].seqid) > 0 { // insertion
-			insertIdx = i + 1
-			break
-		}
-	}
-
-	// insert into ordered rx queue
-	if insertIdx == n+1 {
-		dec.rx = append(dec.rx, pkt)
-	} else {
-		dec.rx = append(dec.rx, fecPacket{})
-		copy(dec.rx[insertIdx+1:], dec.rx[insertIdx:]) // shift right
-		dec.rx[insertIdx] = pkt
-	}
-
-	// shard range for current packet
-	shardBegin := pkt.seqid - pkt.seqid%uint32(dec.shardSize)
-	shardEnd := shardBegin + uint32(dec.shardSize) - 1
-
-	// max search range in ordered queue for current shard
-	searchBegin := insertIdx - int(pkt.seqid%uint32(dec.shardSize))
-	if searchBegin < 0 {
-		searchBegin = 0
-	}
-	searchEnd := searchBegin + dec.shardSize - 1
-	if searchEnd >= len(dec.rx) {
-		searchEnd = len(dec.rx) - 1
-	}
-
-	// re-construct datashards
-	if searchEnd-searchBegin+1 >= dec.dataShards {
-		var numshard, numDataShard, first, maxlen int
-
-		// zero cache
-		shards := dec.decodeCache
-		shardsflag := dec.flagCache
-		for k := range dec.decodeCache {
-			shards[k] = nil
-			shardsflag[k] = false
-		}
-
-		// shard assembly
-		for i := searchBegin; i <= searchEnd; i++ {
-			seqid := dec.rx[i].seqid
-			if _itimediff(seqid, shardEnd) > 0 {
-				break
-			} else if _itimediff(seqid, shardBegin) >= 0 {
-				shards[seqid%uint32(dec.shardSize)] = dec.rx[i].data
-				shardsflag[seqid%uint32(dec.shardSize)] = true
-				numshard++
-				if dec.rx[i].flag == typeData {
-					numDataShard++
-				}
-				if numshard == 1 {
-					first = i
-				}
-				if len(dec.rx[i].data) > maxlen {
-					maxlen = len(dec.rx[i].data)
-				}
-			}
-		}
-
-		if numDataShard == dec.dataShards {
-			// case 1:  no lost data shards
-			dec.rx = dec.freeRange(first, numshard, dec.rx)
-		} else if numshard >= dec.dataShards {
-			// case 2: data shard lost, but  recoverable from parity shard
-			for k := range shards {
-				if shards[k] != nil {
-					dlen := len(shards[k])
-					shards[k] = shards[k][:maxlen]
-					xorBytes(shards[k][dlen:], shards[k][dlen:], shards[k][dlen:])
-				}
-			}
-			if err := dec.codec.Reconstruct(shards); err == nil {
-				for k := range shards[:dec.dataShards] {
-					if !shardsflag[k] {
-						recovered = append(recovered, shards[k])
-					}
-				}
-			}
-			dec.rx = dec.freeRange(first, numshard, dec.rx)
-		}
-	}
-
-	// keep rxlimit
-	if len(dec.rx) > dec.rxlimit {
-		if dec.rx[0].flag == typeData { // record unrecoverable data
-			atomic.AddUint64(&DefaultSnmp.FECShortShards, 1)
-		}
-		dec.rx = dec.freeRange(0, 1, dec.rx)
-	}
-	return
-}
-
-// free a range of fecPacket, and zero for GC recycling
-func (dec *fecDecoder) freeRange(first, n int, q []fecPacket) []fecPacket {
-	for i := first; i < first+n; i++ { // free
-		xmitBuf.Put(q[i].data)
-	}
-	copy(q[first:], q[first+n:])
-	for i := 0; i < n; i++ { // dereference data
-		q[len(q)-1-i].data = nil
-	}
-	return q[:len(q)-n]
-}
-
-type (
-	// fecEncoder for encoding outgoing packets
-	fecEncoder struct {
-		dataShards   int
-		parityShards int
-		shardSize    int
-		paws         uint32 // Protect Against Wrapped Sequence numbers
-		next         uint32 // next seqid
-
-		shardCount int // count the number of datashards collected
-		maxSize    int // record maximum data length in datashard
-
-		headerOffset  int // FEC header offset
-		payloadOffset int // FEC payload offset
-
-		// caches
-		shardCache  [][]byte
-		encodeCache [][]byte
-
-		// RS encoder
-		codec reedsolomon.Encoder
-	}
-)
-
-func newFECEncoder(dataShards, parityShards, offset int) *fecEncoder {
-	if dataShards <= 0 || parityShards <= 0 {
-		return nil
-	}
-	fec := new(fecEncoder)
-	fec.dataShards = dataShards
-	fec.parityShards = parityShards
-	fec.shardSize = dataShards + parityShards
-	fec.paws = (0xffffffff/uint32(fec.shardSize) - 1) * uint32(fec.shardSize)
-	fec.headerOffset = offset
-	fec.payloadOffset = fec.headerOffset + fecHeaderSize
-
-	enc, err := reedsolomon.New(dataShards, parityShards, reedsolomon.WithMaxGoroutines(1))
-	if err != nil {
-		return nil
-	}
-	fec.codec = enc
-
-	// caches
-	fec.encodeCache = make([][]byte, fec.shardSize)
-	fec.shardCache = make([][]byte, fec.shardSize)
-	for k := range fec.shardCache {
-		fec.shardCache[k] = make([]byte, mtuLimit)
-	}
-	return fec
-}
-
-// encode the packet, output parity shards if we have enough datashards
-// the content of returned parityshards will change in next encode
-func (enc *fecEncoder) encode(b []byte) (ps [][]byte) {
-	enc.markData(b[enc.headerOffset:])
-	binary.LittleEndian.PutUint16(b[enc.payloadOffset:], uint16(len(b[enc.payloadOffset:])))
-
-	// copy data to fec datashards
-	sz := len(b)
-	enc.shardCache[enc.shardCount] = enc.shardCache[enc.shardCount][:sz]
-	copy(enc.shardCache[enc.shardCount], b)
-	enc.shardCount++
-
-	// record max datashard length
-	if sz > enc.maxSize {
-		enc.maxSize = sz
-	}
-
-	//  calculate Reed-Solomon Erasure Code
-	if enc.shardCount == enc.dataShards {
-		// bzero each datashard's tail
-		for i := 0; i < enc.dataShards; i++ {
-			shard := enc.shardCache[i]
-			slen := len(shard)
-			xorBytes(shard[slen:enc.maxSize], shard[slen:enc.maxSize], shard[slen:enc.maxSize])
-		}
-
-		// construct equal-sized slice with stripped header
-		cache := enc.encodeCache
-		for k := range cache {
-			cache[k] = enc.shardCache[k][enc.payloadOffset:enc.maxSize]
-		}
-
-		// rs encode
-		if err := enc.codec.Encode(cache); err == nil {
-			ps = enc.shardCache[enc.dataShards:]
-			for k := range ps {
-				enc.markFEC(ps[k][enc.headerOffset:])
-				ps[k] = ps[k][:enc.maxSize]
-			}
-		}
-
-		// reset counters to zero
-		enc.shardCount = 0
-		enc.maxSize = 0
-	}
-
-	return
-}
-
-func (enc *fecEncoder) markData(data []byte) {
-	binary.LittleEndian.PutUint32(data, enc.next)
-	binary.LittleEndian.PutUint16(data[4:], typeData)
-	enc.next++
-}
-
-func (enc *fecEncoder) markFEC(data []byte) {
-	binary.LittleEndian.PutUint32(data, enc.next)
-	binary.LittleEndian.PutUint16(data[4:], typeFEC)
-	enc.next = (enc.next + 1) % enc.paws
-}

BIN
vendor/github.com/xtaci/kcp-go/frame.png


BIN
vendor/github.com/xtaci/kcp-go/kcp-go.png


+ 0 - 998
vendor/github.com/xtaci/kcp-go/kcp.go

@@ -1,998 +0,0 @@
-// Package kcp - A Fast and Reliable ARQ Protocol
-package kcp
-
-import (
-	"encoding/binary"
-	"sync/atomic"
-)
-
-const (
-	IKCP_RTO_NDL     = 30  // no delay min rto
-	IKCP_RTO_MIN     = 100 // normal min rto
-	IKCP_RTO_DEF     = 200
-	IKCP_RTO_MAX     = 60000
-	IKCP_CMD_PUSH    = 81 // cmd: push data
-	IKCP_CMD_ACK     = 82 // cmd: ack
-	IKCP_CMD_WASK    = 83 // cmd: window probe (ask)
-	IKCP_CMD_WINS    = 84 // cmd: window size (tell)
-	IKCP_ASK_SEND    = 1  // need to send IKCP_CMD_WASK
-	IKCP_ASK_TELL    = 2  // need to send IKCP_CMD_WINS
-	IKCP_WND_SND     = 32
-	IKCP_WND_RCV     = 32
-	IKCP_MTU_DEF     = 1400
-	IKCP_ACK_FAST    = 3
-	IKCP_INTERVAL    = 100
-	IKCP_OVERHEAD    = 24
-	IKCP_DEADLINK    = 20
-	IKCP_THRESH_INIT = 2
-	IKCP_THRESH_MIN  = 2
-	IKCP_PROBE_INIT  = 7000   // 7 secs to probe window size
-	IKCP_PROBE_LIMIT = 120000 // up to 120 secs to probe window
-)
-
-// output_callback is a prototype which ought capture conn and call conn.Write
-type output_callback func(buf []byte, size int)
-
-/* encode 8 bits unsigned int */
-func ikcp_encode8u(p []byte, c byte) []byte {
-	p[0] = c
-	return p[1:]
-}
-
-/* decode 8 bits unsigned int */
-func ikcp_decode8u(p []byte, c *byte) []byte {
-	*c = p[0]
-	return p[1:]
-}
-
-/* encode 16 bits unsigned int (lsb) */
-func ikcp_encode16u(p []byte, w uint16) []byte {
-	binary.LittleEndian.PutUint16(p, w)
-	return p[2:]
-}
-
-/* decode 16 bits unsigned int (lsb) */
-func ikcp_decode16u(p []byte, w *uint16) []byte {
-	*w = binary.LittleEndian.Uint16(p)
-	return p[2:]
-}
-
-/* encode 32 bits unsigned int (lsb) */
-func ikcp_encode32u(p []byte, l uint32) []byte {
-	binary.LittleEndian.PutUint32(p, l)
-	return p[4:]
-}
-
-/* decode 32 bits unsigned int (lsb) */
-func ikcp_decode32u(p []byte, l *uint32) []byte {
-	*l = binary.LittleEndian.Uint32(p)
-	return p[4:]
-}
-
-func _imin_(a, b uint32) uint32 {
-	if a <= b {
-		return a
-	}
-	return b
-}
-
-func _imax_(a, b uint32) uint32 {
-	if a >= b {
-		return a
-	}
-	return b
-}
-
-func _ibound_(lower, middle, upper uint32) uint32 {
-	return _imin_(_imax_(lower, middle), upper)
-}
-
-func _itimediff(later, earlier uint32) int32 {
-	return (int32)(later - earlier)
-}
-
-// segment defines a KCP segment
-type segment struct {
-	conv     uint32
-	cmd      uint8
-	frg      uint8
-	wnd      uint16
-	ts       uint32
-	sn       uint32
-	una      uint32
-	rto      uint32
-	xmit     uint32
-	resendts uint32
-	fastack  uint32
-	data     []byte
-}
-
-// encode a segment into buffer
-func (seg *segment) encode(ptr []byte) []byte {
-	ptr = ikcp_encode32u(ptr, seg.conv)
-	ptr = ikcp_encode8u(ptr, seg.cmd)
-	ptr = ikcp_encode8u(ptr, seg.frg)
-	ptr = ikcp_encode16u(ptr, seg.wnd)
-	ptr = ikcp_encode32u(ptr, seg.ts)
-	ptr = ikcp_encode32u(ptr, seg.sn)
-	ptr = ikcp_encode32u(ptr, seg.una)
-	ptr = ikcp_encode32u(ptr, uint32(len(seg.data)))
-	atomic.AddUint64(&DefaultSnmp.OutSegs, 1)
-	return ptr
-}
-
-// KCP defines a single KCP connection
-type KCP struct {
-	conv, mtu, mss, state                  uint32
-	snd_una, snd_nxt, rcv_nxt              uint32
-	ssthresh                               uint32
-	rx_rttvar, rx_srtt                     int32
-	rx_rto, rx_minrto                      uint32
-	snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe uint32
-	interval, ts_flush                     uint32
-	nodelay, updated                       uint32
-	ts_probe, probe_wait                   uint32
-	dead_link, incr                        uint32
-
-	fastresend     int32
-	nocwnd, stream int32
-
-	snd_queue []segment
-	rcv_queue []segment
-	snd_buf   []segment
-	rcv_buf   []segment
-
-	acklist []ackItem
-
-	buffer []byte
-	output output_callback
-}
-
-type ackItem struct {
-	sn uint32
-	ts uint32
-}
-
-// NewKCP create a new kcp control object, 'conv' must equal in two endpoint
-// from the same connection.
-func NewKCP(conv uint32, output output_callback) *KCP {
-	kcp := new(KCP)
-	kcp.conv = conv
-	kcp.snd_wnd = IKCP_WND_SND
-	kcp.rcv_wnd = IKCP_WND_RCV
-	kcp.rmt_wnd = IKCP_WND_RCV
-	kcp.mtu = IKCP_MTU_DEF
-	kcp.mss = kcp.mtu - IKCP_OVERHEAD
-	kcp.buffer = make([]byte, (kcp.mtu+IKCP_OVERHEAD)*3)
-	kcp.rx_rto = IKCP_RTO_DEF
-	kcp.rx_minrto = IKCP_RTO_MIN
-	kcp.interval = IKCP_INTERVAL
-	kcp.ts_flush = IKCP_INTERVAL
-	kcp.ssthresh = IKCP_THRESH_INIT
-	kcp.dead_link = IKCP_DEADLINK
-	kcp.output = output
-	return kcp
-}
-
-// newSegment creates a KCP segment
-func (kcp *KCP) newSegment(size int) (seg segment) {
-	seg.data = xmitBuf.Get().([]byte)[:size]
-	return
-}
-
-// delSegment recycles a KCP segment
-func (kcp *KCP) delSegment(seg segment) {
-	xmitBuf.Put(seg.data)
-}
-
-// PeekSize checks the size of next message in the recv queue
-func (kcp *KCP) PeekSize() (length int) {
-	if len(kcp.rcv_queue) == 0 {
-		return -1
-	}
-
-	seg := &kcp.rcv_queue[0]
-	if seg.frg == 0 {
-		return len(seg.data)
-	}
-
-	if len(kcp.rcv_queue) < int(seg.frg+1) {
-		return -1
-	}
-
-	for k := range kcp.rcv_queue {
-		seg := &kcp.rcv_queue[k]
-		length += len(seg.data)
-		if seg.frg == 0 {
-			break
-		}
-	}
-	return
-}
-
-// Recv is user/upper level recv: returns size, returns below zero for EAGAIN
-func (kcp *KCP) Recv(buffer []byte) (n int) {
-	if len(kcp.rcv_queue) == 0 {
-		return -1
-	}
-
-	peeksize := kcp.PeekSize()
-	if peeksize < 0 {
-		return -2
-	}
-
-	if peeksize > len(buffer) {
-		return -3
-	}
-
-	var fast_recover bool
-	if len(kcp.rcv_queue) >= int(kcp.rcv_wnd) {
-		fast_recover = true
-	}
-
-	// merge fragment
-	count := 0
-	for k := range kcp.rcv_queue {
-		seg := &kcp.rcv_queue[k]
-		copy(buffer, seg.data)
-		buffer = buffer[len(seg.data):]
-		n += len(seg.data)
-		count++
-		kcp.delSegment(*seg)
-		if seg.frg == 0 {
-			break
-		}
-	}
-	if count > 0 {
-		kcp.rcv_queue = kcp.remove_front(kcp.rcv_queue, count)
-	}
-
-	// move available data from rcv_buf -> rcv_queue
-	count = 0
-	for k := range kcp.rcv_buf {
-		seg := &kcp.rcv_buf[k]
-		if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) {
-			kcp.rcv_nxt++
-			count++
-		} else {
-			break
-		}
-	}
-
-	if count > 0 {
-		kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcv_buf[:count]...)
-		kcp.rcv_buf = kcp.remove_front(kcp.rcv_buf, count)
-	}
-
-	// fast recover
-	if len(kcp.rcv_queue) < int(kcp.rcv_wnd) && fast_recover {
-		// ready to send back IKCP_CMD_WINS in ikcp_flush
-		// tell remote my window size
-		kcp.probe |= IKCP_ASK_TELL
-	}
-	return
-}
-
-// Send is user/upper level send, returns below zero for error
-func (kcp *KCP) Send(buffer []byte) int {
-	var count int
-	if len(buffer) == 0 {
-		return -1
-	}
-
-	// append to previous segment in streaming mode (if possible)
-	if kcp.stream != 0 {
-		n := len(kcp.snd_queue)
-		if n > 0 {
-			seg := &kcp.snd_queue[n-1]
-			if len(seg.data) < int(kcp.mss) {
-				capacity := int(kcp.mss) - len(seg.data)
-				extend := capacity
-				if len(buffer) < capacity {
-					extend = len(buffer)
-				}
-
-				// grow slice, the underlying cap is guaranteed to
-				// be larger than kcp.mss
-				oldlen := len(seg.data)
-				seg.data = seg.data[:oldlen+extend]
-				copy(seg.data[oldlen:], buffer)
-				buffer = buffer[extend:]
-			}
-		}
-
-		if len(buffer) == 0 {
-			return 0
-		}
-	}
-
-	if len(buffer) <= int(kcp.mss) {
-		count = 1
-	} else {
-		count = (len(buffer) + int(kcp.mss) - 1) / int(kcp.mss)
-	}
-
-	if count > 255 {
-		return -2
-	}
-
-	if count == 0 {
-		count = 1
-	}
-
-	for i := 0; i < count; i++ {
-		var size int
-		if len(buffer) > int(kcp.mss) {
-			size = int(kcp.mss)
-		} else {
-			size = len(buffer)
-		}
-		seg := kcp.newSegment(size)
-		copy(seg.data, buffer[:size])
-		if kcp.stream == 0 { // message mode
-			seg.frg = uint8(count - i - 1)
-		} else { // stream mode
-			seg.frg = 0
-		}
-		kcp.snd_queue = append(kcp.snd_queue, seg)
-		buffer = buffer[size:]
-	}
-	return 0
-}
-
-func (kcp *KCP) update_ack(rtt int32) {
-	// https://tools.ietf.org/html/rfc6298
-	var rto uint32
-	if kcp.rx_srtt == 0 {
-		kcp.rx_srtt = rtt
-		kcp.rx_rttvar = rtt >> 1
-	} else {
-		delta := rtt - kcp.rx_srtt
-		kcp.rx_srtt += delta >> 3
-		if delta < 0 {
-			delta = -delta
-		}
-		if rtt < kcp.rx_srtt-kcp.rx_rttvar {
-			// if the new RTT sample is below the bottom of the range of
-			// what an RTT measurement is expected to be.
-			// give an 8x reduced weight versus its normal weighting
-			kcp.rx_rttvar += (delta - kcp.rx_rttvar) >> 5
-		} else {
-			kcp.rx_rttvar += (delta - kcp.rx_rttvar) >> 2
-		}
-	}
-	rto = uint32(kcp.rx_srtt) + _imax_(kcp.interval, uint32(kcp.rx_rttvar)<<2)
-	kcp.rx_rto = _ibound_(kcp.rx_minrto, rto, IKCP_RTO_MAX)
-}
-
-func (kcp *KCP) shrink_buf() {
-	if len(kcp.snd_buf) > 0 {
-		seg := &kcp.snd_buf[0]
-		kcp.snd_una = seg.sn
-	} else {
-		kcp.snd_una = kcp.snd_nxt
-	}
-}
-
-func (kcp *KCP) parse_ack(sn uint32) {
-	if _itimediff(sn, kcp.snd_una) < 0 || _itimediff(sn, kcp.snd_nxt) >= 0 {
-		return
-	}
-
-	for k := range kcp.snd_buf {
-		seg := &kcp.snd_buf[k]
-		if sn == seg.sn {
-			kcp.delSegment(*seg)
-			copy(kcp.snd_buf[k:], kcp.snd_buf[k+1:])
-			kcp.snd_buf[len(kcp.snd_buf)-1] = segment{}
-			kcp.snd_buf = kcp.snd_buf[:len(kcp.snd_buf)-1]
-			break
-		}
-		if _itimediff(sn, seg.sn) < 0 {
-			break
-		}
-	}
-}
-
-func (kcp *KCP) parse_fastack(sn uint32) {
-	if _itimediff(sn, kcp.snd_una) < 0 || _itimediff(sn, kcp.snd_nxt) >= 0 {
-		return
-	}
-
-	for k := range kcp.snd_buf {
-		seg := &kcp.snd_buf[k]
-		if _itimediff(sn, seg.sn) < 0 {
-			break
-		} else if sn != seg.sn {
-			seg.fastack++
-		}
-	}
-}
-
-func (kcp *KCP) parse_una(una uint32) {
-	count := 0
-	for k := range kcp.snd_buf {
-		seg := &kcp.snd_buf[k]
-		if _itimediff(una, seg.sn) > 0 {
-			kcp.delSegment(*seg)
-			count++
-		} else {
-			break
-		}
-	}
-	if count > 0 {
-		kcp.snd_buf = kcp.remove_front(kcp.snd_buf, count)
-	}
-}
-
-// ack append
-func (kcp *KCP) ack_push(sn, ts uint32) {
-	kcp.acklist = append(kcp.acklist, ackItem{sn, ts})
-}
-
-func (kcp *KCP) parse_data(newseg segment) {
-	sn := newseg.sn
-	if _itimediff(sn, kcp.rcv_nxt+kcp.rcv_wnd) >= 0 ||
-		_itimediff(sn, kcp.rcv_nxt) < 0 {
-		kcp.delSegment(newseg)
-		return
-	}
-
-	n := len(kcp.rcv_buf) - 1
-	insert_idx := 0
-	repeat := false
-	for i := n; i >= 0; i-- {
-		seg := &kcp.rcv_buf[i]
-		if seg.sn == sn {
-			repeat = true
-			atomic.AddUint64(&DefaultSnmp.RepeatSegs, 1)
-			break
-		}
-		if _itimediff(sn, seg.sn) > 0 {
-			insert_idx = i + 1
-			break
-		}
-	}
-
-	if !repeat {
-		if insert_idx == n+1 {
-			kcp.rcv_buf = append(kcp.rcv_buf, newseg)
-		} else {
-			kcp.rcv_buf = append(kcp.rcv_buf, segment{})
-			copy(kcp.rcv_buf[insert_idx+1:], kcp.rcv_buf[insert_idx:])
-			kcp.rcv_buf[insert_idx] = newseg
-		}
-	} else {
-		kcp.delSegment(newseg)
-	}
-
-	// move available data from rcv_buf -> rcv_queue
-	count := 0
-	for k := range kcp.rcv_buf {
-		seg := &kcp.rcv_buf[k]
-		if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) {
-			kcp.rcv_nxt++
-			count++
-		} else {
-			break
-		}
-	}
-	if count > 0 {
-		kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcv_buf[:count]...)
-		kcp.rcv_buf = kcp.remove_front(kcp.rcv_buf, count)
-	}
-}
-
-// Input when you received a low level packet (eg. UDP packet), call it
-// regular indicates a regular packet has received(not from FEC)
-func (kcp *KCP) Input(data []byte, regular, ackNoDelay bool) int {
-	una := kcp.snd_una
-	if len(data) < IKCP_OVERHEAD {
-		return -1
-	}
-
-	var maxack uint32
-	var lastackts uint32
-	var flag int
-	var inSegs uint64
-
-	for {
-		var ts, sn, length, una, conv uint32
-		var wnd uint16
-		var cmd, frg uint8
-
-		if len(data) < int(IKCP_OVERHEAD) {
-			break
-		}
-
-		data = ikcp_decode32u(data, &conv)
-		if conv != kcp.conv {
-			return -1
-		}
-
-		data = ikcp_decode8u(data, &cmd)
-		data = ikcp_decode8u(data, &frg)
-		data = ikcp_decode16u(data, &wnd)
-		data = ikcp_decode32u(data, &ts)
-		data = ikcp_decode32u(data, &sn)
-		data = ikcp_decode32u(data, &una)
-		data = ikcp_decode32u(data, &length)
-		if len(data) < int(length) {
-			return -2
-		}
-
-		if cmd != IKCP_CMD_PUSH && cmd != IKCP_CMD_ACK &&
-			cmd != IKCP_CMD_WASK && cmd != IKCP_CMD_WINS {
-			return -3
-		}
-
-		// only trust window updates from regular packets. i.e: latest update
-		if regular {
-			kcp.rmt_wnd = uint32(wnd)
-		}
-		kcp.parse_una(una)
-		kcp.shrink_buf()
-
-		if cmd == IKCP_CMD_ACK {
-			kcp.parse_ack(sn)
-			kcp.shrink_buf()
-			if flag == 0 {
-				flag = 1
-				maxack = sn
-			} else if _itimediff(sn, maxack) > 0 {
-				maxack = sn
-			}
-			lastackts = ts
-		} else if cmd == IKCP_CMD_PUSH {
-			if _itimediff(sn, kcp.rcv_nxt+kcp.rcv_wnd) < 0 {
-				kcp.ack_push(sn, ts)
-				if _itimediff(sn, kcp.rcv_nxt) >= 0 {
-					seg := kcp.newSegment(int(length))
-					seg.conv = conv
-					seg.cmd = cmd
-					seg.frg = frg
-					seg.wnd = wnd
-					seg.ts = ts
-					seg.sn = sn
-					seg.una = una
-					copy(seg.data, data[:length])
-					kcp.parse_data(seg)
-				} else {
-					atomic.AddUint64(&DefaultSnmp.RepeatSegs, 1)
-				}
-			} else {
-				atomic.AddUint64(&DefaultSnmp.RepeatSegs, 1)
-			}
-		} else if cmd == IKCP_CMD_WASK {
-			// ready to send back IKCP_CMD_WINS in Ikcp_flush
-			// tell remote my window size
-			kcp.probe |= IKCP_ASK_TELL
-		} else if cmd == IKCP_CMD_WINS {
-			// do nothing
-		} else {
-			return -3
-		}
-
-		inSegs++
-		data = data[length:]
-	}
-	atomic.AddUint64(&DefaultSnmp.InSegs, inSegs)
-
-	if flag != 0 && regular {
-		kcp.parse_fastack(maxack)
-		current := currentMs()
-		if _itimediff(current, lastackts) >= 0 {
-			kcp.update_ack(_itimediff(current, lastackts))
-		}
-	}
-
-	if _itimediff(kcp.snd_una, una) > 0 {
-		if kcp.cwnd < kcp.rmt_wnd {
-			mss := kcp.mss
-			if kcp.cwnd < kcp.ssthresh {
-				kcp.cwnd++
-				kcp.incr += mss
-			} else {
-				if kcp.incr < mss {
-					kcp.incr = mss
-				}
-				kcp.incr += (mss*mss)/kcp.incr + (mss / 16)
-				if (kcp.cwnd+1)*mss <= kcp.incr {
-					kcp.cwnd++
-				}
-			}
-			if kcp.cwnd > kcp.rmt_wnd {
-				kcp.cwnd = kcp.rmt_wnd
-				kcp.incr = kcp.rmt_wnd * mss
-			}
-		}
-	}
-
-	if ackNoDelay && len(kcp.acklist) > 0 { // ack immediately
-		kcp.flush(true)
-	} else if kcp.rmt_wnd == 0 && len(kcp.acklist) > 0 { // window zero
-		kcp.flush(true)
-	}
-	return 0
-}
-
-func (kcp *KCP) wnd_unused() uint16 {
-	if len(kcp.rcv_queue) < int(kcp.rcv_wnd) {
-		return uint16(int(kcp.rcv_wnd) - len(kcp.rcv_queue))
-	}
-	return 0
-}
-
-// flush pending data
-func (kcp *KCP) flush(ackOnly bool) {
-	var seg segment
-	seg.conv = kcp.conv
-	seg.cmd = IKCP_CMD_ACK
-	seg.wnd = kcp.wnd_unused()
-	seg.una = kcp.rcv_nxt
-
-	buffer := kcp.buffer
-	// flush acknowledges
-	ptr := buffer
-	for i, ack := range kcp.acklist {
-		size := len(buffer) - len(ptr)
-		if size+IKCP_OVERHEAD > int(kcp.mtu) {
-			kcp.output(buffer, size)
-			ptr = buffer
-		}
-		// filter jitters caused by bufferbloat
-		if ack.sn >= kcp.rcv_nxt || len(kcp.acklist)-1 == i {
-			seg.sn, seg.ts = ack.sn, ack.ts
-			ptr = seg.encode(ptr)
-		}
-	}
-	kcp.acklist = kcp.acklist[0:0]
-
-	if ackOnly { // flash remain ack segments
-		size := len(buffer) - len(ptr)
-		if size > 0 {
-			kcp.output(buffer, size)
-		}
-		return
-	}
-
-	// probe window size (if remote window size equals zero)
-	if kcp.rmt_wnd == 0 {
-		current := currentMs()
-		if kcp.probe_wait == 0 {
-			kcp.probe_wait = IKCP_PROBE_INIT
-			kcp.ts_probe = current + kcp.probe_wait
-		} else {
-			if _itimediff(current, kcp.ts_probe) >= 0 {
-				if kcp.probe_wait < IKCP_PROBE_INIT {
-					kcp.probe_wait = IKCP_PROBE_INIT
-				}
-				kcp.probe_wait += kcp.probe_wait / 2
-				if kcp.probe_wait > IKCP_PROBE_LIMIT {
-					kcp.probe_wait = IKCP_PROBE_LIMIT
-				}
-				kcp.ts_probe = current + kcp.probe_wait
-				kcp.probe |= IKCP_ASK_SEND
-			}
-		}
-	} else {
-		kcp.ts_probe = 0
-		kcp.probe_wait = 0
-	}
-
-	// flush window probing commands
-	if (kcp.probe & IKCP_ASK_SEND) != 0 {
-		seg.cmd = IKCP_CMD_WASK
-		size := len(buffer) - len(ptr)
-		if size+IKCP_OVERHEAD > int(kcp.mtu) {
-			kcp.output(buffer, size)
-			ptr = buffer
-		}
-		ptr = seg.encode(ptr)
-	}
-
-	// flush window probing commands
-	if (kcp.probe & IKCP_ASK_TELL) != 0 {
-		seg.cmd = IKCP_CMD_WINS
-		size := len(buffer) - len(ptr)
-		if size+IKCP_OVERHEAD > int(kcp.mtu) {
-			kcp.output(buffer, size)
-			ptr = buffer
-		}
-		ptr = seg.encode(ptr)
-	}
-
-	kcp.probe = 0
-
-	// calculate window size
-	cwnd := _imin_(kcp.snd_wnd, kcp.rmt_wnd)
-	if kcp.nocwnd == 0 {
-		cwnd = _imin_(kcp.cwnd, cwnd)
-	}
-
-	// sliding window, controlled by snd_nxt && sna_una+cwnd
-	newSegsCount := 0
-	for k := range kcp.snd_queue {
-		if _itimediff(kcp.snd_nxt, kcp.snd_una+cwnd) >= 0 {
-			break
-		}
-		newseg := kcp.snd_queue[k]
-		newseg.conv = kcp.conv
-		newseg.cmd = IKCP_CMD_PUSH
-		newseg.sn = kcp.snd_nxt
-		kcp.snd_buf = append(kcp.snd_buf, newseg)
-		kcp.snd_nxt++
-		newSegsCount++
-		kcp.snd_queue[k].data = nil
-	}
-	if newSegsCount > 0 {
-		kcp.snd_queue = kcp.remove_front(kcp.snd_queue, newSegsCount)
-	}
-
-	// calculate resent
-	resent := uint32(kcp.fastresend)
-	if kcp.fastresend <= 0 {
-		resent = 0xffffffff
-	}
-
-	// check for retransmissions
-	current := currentMs()
-	var change, lost, lostSegs, fastRetransSegs, earlyRetransSegs uint64
-	for k := range kcp.snd_buf {
-		segment := &kcp.snd_buf[k]
-		needsend := false
-		if segment.xmit == 0 { // initial transmit
-			needsend = true
-			segment.rto = kcp.rx_rto
-			segment.resendts = current + segment.rto
-		} else if _itimediff(current, segment.resendts) >= 0 { // RTO
-			needsend = true
-			if kcp.nodelay == 0 {
-				segment.rto += kcp.rx_rto
-			} else {
-				segment.rto += kcp.rx_rto / 2
-			}
-			segment.resendts = current + segment.rto
-			lost++
-			lostSegs++
-		} else if segment.fastack >= resent { // fast retransmit
-			needsend = true
-			segment.fastack = 0
-			segment.rto = kcp.rx_rto
-			segment.resendts = current + segment.rto
-			change++
-			fastRetransSegs++
-		} else if segment.fastack > 0 && newSegsCount == 0 { // early retransmit
-			needsend = true
-			segment.fastack = 0
-			segment.rto = kcp.rx_rto
-			segment.resendts = current + segment.rto
-			change++
-			earlyRetransSegs++
-		}
-
-		if needsend {
-			segment.xmit++
-			segment.ts = current
-			segment.wnd = seg.wnd
-			segment.una = seg.una
-
-			size := len(buffer) - len(ptr)
-			need := IKCP_OVERHEAD + len(segment.data)
-
-			if size+need > int(kcp.mtu) {
-				kcp.output(buffer, size)
-				current = currentMs() // time update for a blocking call
-				ptr = buffer
-			}
-
-			ptr = segment.encode(ptr)
-			copy(ptr, segment.data)
-			ptr = ptr[len(segment.data):]
-
-			if segment.xmit >= kcp.dead_link {
-				kcp.state = 0xFFFFFFFF
-			}
-		}
-	}
-
-	// flash remain segments
-	size := len(buffer) - len(ptr)
-	if size > 0 {
-		kcp.output(buffer, size)
-	}
-
-	// counter updates
-	sum := lostSegs
-	if lostSegs > 0 {
-		atomic.AddUint64(&DefaultSnmp.LostSegs, lostSegs)
-	}
-	if fastRetransSegs > 0 {
-		atomic.AddUint64(&DefaultSnmp.FastRetransSegs, fastRetransSegs)
-		sum += fastRetransSegs
-	}
-	if earlyRetransSegs > 0 {
-		atomic.AddUint64(&DefaultSnmp.EarlyRetransSegs, earlyRetransSegs)
-		sum += earlyRetransSegs
-	}
-	if sum > 0 {
-		atomic.AddUint64(&DefaultSnmp.RetransSegs, sum)
-	}
-
-	// update ssthresh
-	// rate halving, https://tools.ietf.org/html/rfc6937
-	if change > 0 {
-		inflight := kcp.snd_nxt - kcp.snd_una
-		kcp.ssthresh = inflight / 2
-		if kcp.ssthresh < IKCP_THRESH_MIN {
-			kcp.ssthresh = IKCP_THRESH_MIN
-		}
-		kcp.cwnd = kcp.ssthresh + resent
-		kcp.incr = kcp.cwnd * kcp.mss
-	}
-
-	// congestion control, https://tools.ietf.org/html/rfc5681
-	if lost > 0 {
-		kcp.ssthresh = cwnd / 2
-		if kcp.ssthresh < IKCP_THRESH_MIN {
-			kcp.ssthresh = IKCP_THRESH_MIN
-		}
-		kcp.cwnd = 1
-		kcp.incr = kcp.mss
-	}
-
-	if kcp.cwnd < 1 {
-		kcp.cwnd = 1
-		kcp.incr = kcp.mss
-	}
-}
-
-// Update updates state (call it repeatedly, every 10ms-100ms), or you can ask
-// ikcp_check when to call it again (without ikcp_input/_send calling).
-// 'current' - current timestamp in millisec.
-func (kcp *KCP) Update() {
-	var slap int32
-
-	current := currentMs()
-	if kcp.updated == 0 {
-		kcp.updated = 1
-		kcp.ts_flush = current
-	}
-
-	slap = _itimediff(current, kcp.ts_flush)
-
-	if slap >= 10000 || slap < -10000 {
-		kcp.ts_flush = current
-		slap = 0
-	}
-
-	if slap >= 0 {
-		kcp.ts_flush += kcp.interval
-		if _itimediff(current, kcp.ts_flush) >= 0 {
-			kcp.ts_flush = current + kcp.interval
-		}
-		kcp.flush(false)
-	}
-}
-
-// Check determines when should you invoke ikcp_update:
-// returns when you should invoke ikcp_update in millisec, if there
-// is no ikcp_input/_send calling. you can call ikcp_update in that
-// time, instead of call update repeatly.
-// Important to reduce unnacessary ikcp_update invoking. use it to
-// schedule ikcp_update (eg. implementing an epoll-like mechanism,
-// or optimize ikcp_update when handling massive kcp connections)
-func (kcp *KCP) Check() uint32 {
-	current := currentMs()
-	ts_flush := kcp.ts_flush
-	tm_flush := int32(0x7fffffff)
-	tm_packet := int32(0x7fffffff)
-	minimal := uint32(0)
-	if kcp.updated == 0 {
-		return current
-	}
-
-	if _itimediff(current, ts_flush) >= 10000 ||
-		_itimediff(current, ts_flush) < -10000 {
-		ts_flush = current
-	}
-
-	if _itimediff(current, ts_flush) >= 0 {
-		return current
-	}
-
-	tm_flush = _itimediff(ts_flush, current)
-
-	for k := range kcp.snd_buf {
-		seg := &kcp.snd_buf[k]
-		diff := _itimediff(seg.resendts, current)
-		if diff <= 0 {
-			return current
-		}
-		if diff < tm_packet {
-			tm_packet = diff
-		}
-	}
-
-	minimal = uint32(tm_packet)
-	if tm_packet >= tm_flush {
-		minimal = uint32(tm_flush)
-	}
-	if minimal >= kcp.interval {
-		minimal = kcp.interval
-	}
-
-	return current + minimal
-}
-
-// SetMtu changes MTU size, default is 1400
-func (kcp *KCP) SetMtu(mtu int) int {
-	if mtu < 50 || mtu < IKCP_OVERHEAD {
-		return -1
-	}
-	buffer := make([]byte, (mtu+IKCP_OVERHEAD)*3)
-	if buffer == nil {
-		return -2
-	}
-	kcp.mtu = uint32(mtu)
-	kcp.mss = kcp.mtu - IKCP_OVERHEAD
-	kcp.buffer = buffer
-	return 0
-}
-
-// NoDelay options
-// fastest: ikcp_nodelay(kcp, 1, 20, 2, 1)
-// nodelay: 0:disable(default), 1:enable
-// interval: internal update timer interval in millisec, default is 100ms
-// resend: 0:disable fast resend(default), 1:enable fast resend
-// nc: 0:normal congestion control(default), 1:disable congestion control
-func (kcp *KCP) NoDelay(nodelay, interval, resend, nc int) int {
-	if nodelay >= 0 {
-		kcp.nodelay = uint32(nodelay)
-		if nodelay != 0 {
-			kcp.rx_minrto = IKCP_RTO_NDL
-		} else {
-			kcp.rx_minrto = IKCP_RTO_MIN
-		}
-	}
-	if interval >= 0 {
-		if interval > 5000 {
-			interval = 5000
-		} else if interval < 10 {
-			interval = 10
-		}
-		kcp.interval = uint32(interval)
-	}
-	if resend >= 0 {
-		kcp.fastresend = int32(resend)
-	}
-	if nc >= 0 {
-		kcp.nocwnd = int32(nc)
-	}
-	return 0
-}
-
-// WndSize sets maximum window size: sndwnd=32, rcvwnd=32 by default
-func (kcp *KCP) WndSize(sndwnd, rcvwnd int) int {
-	if sndwnd > 0 {
-		kcp.snd_wnd = uint32(sndwnd)
-	}
-	if rcvwnd > 0 {
-		kcp.rcv_wnd = uint32(rcvwnd)
-	}
-	return 0
-}
-
-// WaitSnd gets how many packet is waiting to be sent
-func (kcp *KCP) WaitSnd() int {
-	return len(kcp.snd_buf) + len(kcp.snd_queue)
-}
-
-// remove front n elements from queue
-func (kcp *KCP) remove_front(q []segment, n int) []segment {
-	newn := copy(q, q[n:])
-	for i := newn; i < len(q); i++ {
-		q[i] = segment{} // manual set nil for GC
-	}
-	return q[:newn]
-}

+ 0 - 303
vendor/github.com/xtaci/kcp-go/kcp_test.go

@@ -1,303 +0,0 @@
-package kcp
-
-import (
-	"bytes"
-	"container/list"
-	"encoding/binary"
-	"fmt"
-	"math/rand"
-	"sync"
-	"testing"
-	"time"
-)
-
-func iclock() int32 {
-	return int32((time.Now().UnixNano() / 1000000) & 0xffffffff)
-}
-
-type DelayPacket struct {
-	_ptr  []byte
-	_size int
-	_ts   int32
-}
-
-func (p *DelayPacket) Init(size int, src []byte) {
-	p._ptr = make([]byte, size)
-	p._size = size
-	copy(p._ptr, src[:size])
-}
-
-func (p *DelayPacket) ptr() []byte    { return p._ptr }
-func (p *DelayPacket) size() int      { return p._size }
-func (p *DelayPacket) ts() int32      { return p._ts }
-func (p *DelayPacket) setts(ts int32) { p._ts = ts }
-
-type DelayTunnel struct{ *list.List }
-type Random *rand.Rand
-type LatencySimulator struct {
-	current                        int32
-	lostrate, rttmin, rttmax, nmax int
-	p12                            DelayTunnel
-	p21                            DelayTunnel
-	r12                            *rand.Rand
-	r21                            *rand.Rand
-}
-
-// lostrate: 往返一周丢包率的百分比,默认 10%
-// rttmin:rtt最小值,默认 60
-// rttmax:rtt最大值,默认 125
-//func (p *LatencySimulator)Init(int lostrate = 10, int rttmin = 60, int rttmax = 125, int nmax = 1000):
-func (p *LatencySimulator) Init(lostrate, rttmin, rttmax, nmax int) {
-	p.r12 = rand.New(rand.NewSource(9))
-	p.r21 = rand.New(rand.NewSource(99))
-	p.p12 = DelayTunnel{list.New()}
-	p.p21 = DelayTunnel{list.New()}
-	p.current = iclock()
-	p.lostrate = lostrate / 2 // 上面数据是往返丢包率,单程除以2
-	p.rttmin = rttmin / 2
-	p.rttmax = rttmax / 2
-	p.nmax = nmax
-}
-
-// 发送数据
-// peer - 端点0/1,从0发送,从1接收;从1发送从0接收
-func (p *LatencySimulator) send(peer int, data []byte, size int) int {
-	rnd := 0
-	if peer == 0 {
-		rnd = p.r12.Intn(100)
-	} else {
-		rnd = p.r21.Intn(100)
-	}
-	//println("!!!!!!!!!!!!!!!!!!!!", rnd, p.lostrate, peer)
-	if rnd < p.lostrate {
-		return 0
-	}
-	pkt := &DelayPacket{}
-	pkt.Init(size, data)
-	p.current = iclock()
-	delay := p.rttmin
-	if p.rttmax > p.rttmin {
-		delay += rand.Int() % (p.rttmax - p.rttmin)
-	}
-	pkt.setts(p.current + int32(delay))
-	if peer == 0 {
-		p.p12.PushBack(pkt)
-	} else {
-		p.p21.PushBack(pkt)
-	}
-	return 1
-}
-
-// 接收数据
-func (p *LatencySimulator) recv(peer int, data []byte, maxsize int) int32 {
-	var it *list.Element
-	if peer == 0 {
-		it = p.p21.Front()
-		if p.p21.Len() == 0 {
-			return -1
-		}
-	} else {
-		it = p.p12.Front()
-		if p.p12.Len() == 0 {
-			return -1
-		}
-	}
-	pkt := it.Value.(*DelayPacket)
-	p.current = iclock()
-	if p.current < pkt.ts() {
-		return -2
-	}
-	if maxsize < pkt.size() {
-		return -3
-	}
-	if peer == 0 {
-		p.p21.Remove(it)
-	} else {
-		p.p12.Remove(it)
-	}
-	maxsize = pkt.size()
-	copy(data, pkt.ptr()[:maxsize])
-	return int32(maxsize)
-}
-
-//=====================================================================
-//=====================================================================
-
-// 模拟网络
-var vnet *LatencySimulator
-
-// 测试用例
-func test(mode int) {
-	// 创建模拟网络:丢包率10%,Rtt 60ms~125ms
-	vnet = &LatencySimulator{}
-	vnet.Init(10, 60, 125, 1000)
-
-	// 创建两个端点的 kcp对象,第一个参数 conv是会话编号,同一个会话需要相同
-	// 最后一个是 user参数,用来传递标识
-	output1 := func(buf []byte, size int) {
-		if vnet.send(0, buf, size) != 1 {
-		}
-	}
-	output2 := func(buf []byte, size int) {
-		if vnet.send(1, buf, size) != 1 {
-		}
-	}
-	kcp1 := NewKCP(0x11223344, output1)
-	kcp2 := NewKCP(0x11223344, output2)
-
-	current := uint32(iclock())
-	slap := current + 20
-	index := 0
-	next := 0
-	var sumrtt uint32
-	count := 0
-	maxrtt := 0
-
-	// 配置窗口大小:平均延迟200ms,每20ms发送一个包,
-	// 而考虑到丢包重发,设置最大收发窗口为128
-	kcp1.WndSize(128, 128)
-	kcp2.WndSize(128, 128)
-
-	// 判断测试用例的模式
-	if mode == 0 {
-		// 默认模式
-		kcp1.NoDelay(0, 10, 0, 0)
-		kcp2.NoDelay(0, 10, 0, 0)
-	} else if mode == 1 {
-		// 普通模式,关闭流控等
-		kcp1.NoDelay(0, 10, 0, 1)
-		kcp2.NoDelay(0, 10, 0, 1)
-	} else {
-		// 启动快速模式
-		// 第二个参数 nodelay-启用以后若干常规加速将启动
-		// 第三个参数 interval为内部处理时钟,默认设置为 10ms
-		// 第四个参数 resend为快速重传指标,设置为2
-		// 第五个参数 为是否禁用常规流控,这里禁止
-		kcp1.NoDelay(1, 10, 2, 1)
-		kcp2.NoDelay(1, 10, 2, 1)
-	}
-
-	buffer := make([]byte, 2000)
-	var hr int32
-
-	ts1 := iclock()
-
-	for {
-		time.Sleep(1 * time.Millisecond)
-		current = uint32(iclock())
-		kcp1.Update()
-		kcp2.Update()
-
-		// 每隔 20ms,kcp1发送数据
-		for ; current >= slap; slap += 20 {
-			buf := new(bytes.Buffer)
-			binary.Write(buf, binary.LittleEndian, uint32(index))
-			index++
-			binary.Write(buf, binary.LittleEndian, uint32(current))
-			// 发送上层协议包
-			kcp1.Send(buf.Bytes())
-			//println("now", iclock())
-		}
-
-		// 处理虚拟网络:检测是否有udp包从p1->p2
-		for {
-			hr = vnet.recv(1, buffer, 2000)
-			if hr < 0 {
-				break
-			}
-			// 如果 p2收到udp,则作为下层协议输入到kcp2
-			kcp2.Input(buffer[:hr], true, false)
-		}
-
-		// 处理虚拟网络:检测是否有udp包从p2->p1
-		for {
-			hr = vnet.recv(0, buffer, 2000)
-			if hr < 0 {
-				break
-			}
-			// 如果 p1收到udp,则作为下层协议输入到kcp1
-			kcp1.Input(buffer[:hr], true, false)
-			//println("@@@@", hr, r)
-		}
-
-		// kcp2接收到任何包都返回回去
-		for {
-			hr = int32(kcp2.Recv(buffer[:10]))
-			// 没有收到包就退出
-			if hr < 0 {
-				break
-			}
-			// 如果收到包就回射
-			buf := bytes.NewReader(buffer)
-			var sn uint32
-			binary.Read(buf, binary.LittleEndian, &sn)
-			kcp2.Send(buffer[:hr])
-		}
-
-		// kcp1收到kcp2的回射数据
-		for {
-			hr = int32(kcp1.Recv(buffer[:10]))
-			buf := bytes.NewReader(buffer)
-			// 没有收到包就退出
-			if hr < 0 {
-				break
-			}
-			var sn uint32
-			var ts, rtt uint32
-			binary.Read(buf, binary.LittleEndian, &sn)
-			binary.Read(buf, binary.LittleEndian, &ts)
-			rtt = uint32(current) - ts
-
-			if sn != uint32(next) {
-				// 如果收到的包不连续
-				//for i:=0;i<8 ;i++ {
-				//println("---", i, buffer[i])
-				//}
-				println("ERROR sn ", count, "<->", next, sn)
-				return
-			}
-
-			next++
-			sumrtt += rtt
-			count++
-			if rtt > uint32(maxrtt) {
-				maxrtt = int(rtt)
-			}
-
-			//println("[RECV] mode=", mode, " sn=", sn, " rtt=", rtt)
-		}
-
-		if next > 100 {
-			break
-		}
-	}
-
-	ts1 = iclock() - ts1
-
-	names := []string{"default", "normal", "fast"}
-	fmt.Printf("%s mode result (%dms):\n", names[mode], ts1)
-	fmt.Printf("avgrtt=%d maxrtt=%d\n", int(sumrtt/uint32(count)), maxrtt)
-}
-
-func TestNetwork(t *testing.T) {
-	test(0) // 默认模式,类似 TCP:正常模式,无快速重传,常规流控
-	test(1) // 普通模式,关闭流控等
-	test(2) // 快速模式,所有开关都打开,且关闭流控
-}
-
-func BenchmarkFlush(b *testing.B) {
-	kcp := NewKCP(1, func(buf []byte, size int) {})
-	kcp.snd_buf = make([]segment, 32)
-	for k := range kcp.snd_buf {
-		kcp.snd_buf[k].xmit = 1
-		kcp.snd_buf[k].resendts = currentMs() + 10000
-	}
-	b.ResetTimer()
-	b.ReportAllocs()
-	var mu sync.Mutex
-	for i := 0; i < b.N; i++ {
-		mu.Lock()
-		kcp.flush(false)
-		mu.Unlock()
-	}
-}

+ 0 - 932
vendor/github.com/xtaci/kcp-go/sess.go

@@ -1,932 +0,0 @@
-package kcp
-
-import (
-	"crypto/rand"
-	"encoding/binary"
-	"hash/crc32"
-	"io"
-	"net"
-	"sync"
-	"sync/atomic"
-	"time"
-
-	"github.com/pkg/errors"
-	"golang.org/x/net/ipv4"
-)
-
-type errTimeout struct {
-	error
-}
-
-func (errTimeout) Timeout() bool   { return true }
-func (errTimeout) Temporary() bool { return true }
-func (errTimeout) Error() string   { return "i/o timeout" }
-
-const (
-	// 16-bytes magic number for each packet
-	nonceSize = 16
-
-	// 4-bytes packet checksum
-	crcSize = 4
-
-	// overall crypto header size
-	cryptHeaderSize = nonceSize + crcSize
-
-	// maximum packet size
-	mtuLimit = 1500
-
-	// FEC keeps rxFECMulti* (dataShard+parityShard) ordered packets in memory
-	rxFECMulti = 3
-
-	// accept backlog
-	acceptBacklog = 128
-
-	// prerouting(to session) queue
-	qlen = 128
-)
-
-const (
-	errBrokenPipe       = "broken pipe"
-	errInvalidOperation = "invalid operation"
-)
-
-var (
-	// global packet buffer
-	// shared among sending/receiving/FEC
-	xmitBuf sync.Pool
-)
-
-func init() {
-	xmitBuf.New = func() interface{} {
-		return make([]byte, mtuLimit)
-	}
-}
-
-type (
-	// UDPSession defines a KCP session implemented by UDP
-	UDPSession struct {
-		updaterIdx int            // record slice index in updater
-		conn       net.PacketConn // the underlying packet connection
-		kcp        *KCP           // KCP ARQ protocol
-		l          *Listener      // point to the Listener if it's accepted by Listener
-		block      BlockCrypt     // block encryption
-
-		// kcp receiving is based on packets
-		// recvbuf turns packets into stream
-		recvbuf []byte
-		bufptr  []byte
-		// extended output buffer(with header)
-		ext []byte
-
-		// FEC
-		fecDecoder *fecDecoder
-		fecEncoder *fecEncoder
-
-		// settings
-		remote     net.Addr  // remote peer address
-		rd         time.Time // read deadline
-		wd         time.Time // write deadline
-		headerSize int       // the overall header size added before KCP frame
-		ackNoDelay bool      // send ack immediately for each incoming packet
-		writeDelay bool      // delay kcp.flush() for Write() for bulk transfer
-		dup        int       // duplicate udp packets
-
-		// notifications
-		die          chan struct{} // notify session has Closed
-		chReadEvent  chan struct{} // notify Read() can be called without blocking
-		chWriteEvent chan struct{} // notify Write() can be called without blocking
-		chErrorEvent chan error    // notify Read() have an error
-
-		isClosed bool // flag the session has Closed
-		mu       sync.Mutex
-	}
-
-	setReadBuffer interface {
-		SetReadBuffer(bytes int) error
-	}
-
-	setWriteBuffer interface {
-		SetWriteBuffer(bytes int) error
-	}
-)
-
-// newUDPSession create a new udp session for client or server
-func newUDPSession(conv uint32, dataShards, parityShards int, l *Listener, conn net.PacketConn, remote net.Addr, block BlockCrypt) *UDPSession {
-	sess := new(UDPSession)
-	sess.die = make(chan struct{})
-	sess.chReadEvent = make(chan struct{}, 1)
-	sess.chWriteEvent = make(chan struct{}, 1)
-	sess.chErrorEvent = make(chan error, 1)
-	sess.remote = remote
-	sess.conn = conn
-	sess.l = l
-	sess.block = block
-	sess.recvbuf = make([]byte, mtuLimit)
-
-	// FEC initialization
-	sess.fecDecoder = newFECDecoder(rxFECMulti*(dataShards+parityShards), dataShards, parityShards)
-	if sess.block != nil {
-		sess.fecEncoder = newFECEncoder(dataShards, parityShards, cryptHeaderSize)
-	} else {
-		sess.fecEncoder = newFECEncoder(dataShards, parityShards, 0)
-	}
-
-	// calculate header size
-	if sess.block != nil {
-		sess.headerSize += cryptHeaderSize
-	}
-	if sess.fecEncoder != nil {
-		sess.headerSize += fecHeaderSizePlus2
-	}
-
-	// only allocate extended packet buffer
-	// when the extra header is required
-	if sess.headerSize > 0 {
-		sess.ext = make([]byte, mtuLimit)
-	}
-
-	sess.kcp = NewKCP(conv, func(buf []byte, size int) {
-		if size >= IKCP_OVERHEAD {
-			sess.output(buf[:size])
-		}
-	})
-	sess.kcp.SetMtu(IKCP_MTU_DEF - sess.headerSize)
-
-	// add current session to the global updater,
-	// which periodically calls sess.update()
-	updater.addSession(sess)
-
-	if sess.l == nil { // it's a client connection
-		go sess.readLoop()
-		atomic.AddUint64(&DefaultSnmp.ActiveOpens, 1)
-	} else {
-		atomic.AddUint64(&DefaultSnmp.PassiveOpens, 1)
-	}
-	currestab := atomic.AddUint64(&DefaultSnmp.CurrEstab, 1)
-	maxconn := atomic.LoadUint64(&DefaultSnmp.MaxConn)
-	if currestab > maxconn {
-		atomic.CompareAndSwapUint64(&DefaultSnmp.MaxConn, maxconn, currestab)
-	}
-
-	return sess
-}
-
-// Read implements net.Conn
-func (s *UDPSession) Read(b []byte) (n int, err error) {
-	for {
-		s.mu.Lock()
-		if len(s.bufptr) > 0 { // copy from buffer into b
-			n = copy(b, s.bufptr)
-			s.bufptr = s.bufptr[n:]
-			s.mu.Unlock()
-			return n, nil
-		}
-
-		if s.isClosed {
-			s.mu.Unlock()
-			return 0, errors.New(errBrokenPipe)
-		}
-
-		if size := s.kcp.PeekSize(); size > 0 { // peek data size from kcp
-			atomic.AddUint64(&DefaultSnmp.BytesReceived, uint64(size))
-			if len(b) >= size { // direct write to b
-				s.kcp.Recv(b)
-				s.mu.Unlock()
-				return size, nil
-			}
-
-			// resize kcp receive buffer
-			// to make sure recvbuf has enough capacity
-			if cap(s.recvbuf) < size {
-				s.recvbuf = make([]byte, size)
-			}
-
-			// resize recvbuf slice length
-			s.recvbuf = s.recvbuf[:size]
-			s.kcp.Recv(s.recvbuf)
-			n = copy(b, s.recvbuf)   // copy to b
-			s.bufptr = s.recvbuf[n:] // update pointer
-			s.mu.Unlock()
-			return n, nil
-		}
-
-		// read deadline
-		var timeout *time.Timer
-		var c <-chan time.Time
-		if !s.rd.IsZero() {
-			if time.Now().After(s.rd) {
-				s.mu.Unlock()
-				return 0, errTimeout{}
-			}
-
-			delay := s.rd.Sub(time.Now())
-			timeout = time.NewTimer(delay)
-			c = timeout.C
-		}
-		s.mu.Unlock()
-
-		// wait for read event or timeout
-		select {
-		case <-s.chReadEvent:
-		case <-c:
-		case <-s.die:
-		case err = <-s.chErrorEvent:
-			if timeout != nil {
-				timeout.Stop()
-			}
-			return n, err
-		}
-
-		if timeout != nil {
-			timeout.Stop()
-		}
-	}
-}
-
-// Write implements net.Conn
-func (s *UDPSession) Write(b []byte) (n int, err error) {
-	for {
-		s.mu.Lock()
-		if s.isClosed {
-			s.mu.Unlock()
-			return 0, errors.New(errBrokenPipe)
-		}
-
-		// api flow control
-		if s.kcp.WaitSnd() < int(s.kcp.snd_wnd) {
-			n = len(b)
-			for {
-				if len(b) <= int(s.kcp.mss) {
-					s.kcp.Send(b)
-					break
-				} else {
-					s.kcp.Send(b[:s.kcp.mss])
-					b = b[s.kcp.mss:]
-				}
-			}
-
-			if !s.writeDelay {
-				s.kcp.flush(false)
-			}
-			s.mu.Unlock()
-			atomic.AddUint64(&DefaultSnmp.BytesSent, uint64(n))
-			return n, nil
-		}
-
-		// write deadline
-		var timeout *time.Timer
-		var c <-chan time.Time
-		if !s.wd.IsZero() {
-			if time.Now().After(s.wd) {
-				s.mu.Unlock()
-				return 0, errTimeout{}
-			}
-			delay := s.wd.Sub(time.Now())
-			timeout = time.NewTimer(delay)
-			c = timeout.C
-		}
-		s.mu.Unlock()
-
-		// wait for write event or timeout
-		select {
-		case <-s.chWriteEvent:
-		case <-c:
-		case <-s.die:
-		}
-
-		if timeout != nil {
-			timeout.Stop()
-		}
-	}
-}
-
-// Close closes the connection.
-func (s *UDPSession) Close() error {
-	// remove this session from updater & listener(if necessary)
-	updater.removeSession(s)
-	if s.l != nil { // notify listener
-		s.l.closeSession(s.remote)
-	}
-
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	if s.isClosed {
-		return errors.New(errBrokenPipe)
-	}
-	close(s.die)
-	s.isClosed = true
-	atomic.AddUint64(&DefaultSnmp.CurrEstab, ^uint64(0))
-	if s.l == nil { // client socket close
-		return s.conn.Close()
-	}
-	return nil
-}
-
-// LocalAddr returns the local network address. The Addr returned is shared by all invocations of LocalAddr, so do not modify it.
-func (s *UDPSession) LocalAddr() net.Addr { return s.conn.LocalAddr() }
-
-// RemoteAddr returns the remote network address. The Addr returned is shared by all invocations of RemoteAddr, so do not modify it.
-func (s *UDPSession) RemoteAddr() net.Addr { return s.remote }
-
-// SetDeadline sets the deadline associated with the listener. A zero time value disables the deadline.
-func (s *UDPSession) SetDeadline(t time.Time) error {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	s.rd = t
-	s.wd = t
-	return nil
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (s *UDPSession) SetReadDeadline(t time.Time) error {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	s.rd = t
-	return nil
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (s *UDPSession) SetWriteDeadline(t time.Time) error {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	s.wd = t
-	return nil
-}
-
-// SetWriteDelay delays write for bulk transfer until the next update interval
-func (s *UDPSession) SetWriteDelay(delay bool) {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	s.writeDelay = delay
-}
-
-// SetWindowSize set maximum window size
-func (s *UDPSession) SetWindowSize(sndwnd, rcvwnd int) {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	s.kcp.WndSize(sndwnd, rcvwnd)
-}
-
-// SetMtu sets the maximum transmission unit(not including UDP header)
-func (s *UDPSession) SetMtu(mtu int) bool {
-	if mtu > mtuLimit {
-		return false
-	}
-
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	s.kcp.SetMtu(mtu - s.headerSize)
-	return true
-}
-
-// SetStreamMode toggles the stream mode on/off
-func (s *UDPSession) SetStreamMode(enable bool) {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	if enable {
-		s.kcp.stream = 1
-	} else {
-		s.kcp.stream = 0
-	}
-}
-
-// SetACKNoDelay changes ack flush option, set true to flush ack immediately,
-func (s *UDPSession) SetACKNoDelay(nodelay bool) {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	s.ackNoDelay = nodelay
-}
-
-// SetDUP duplicates udp packets for kcp output, for testing purpose only
-func (s *UDPSession) SetDUP(dup int) {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	s.dup = dup
-}
-
-// SetNoDelay calls nodelay() of kcp
-// https://github.com/skywind3000/kcp/blob/master/README.en.md#protocol-configuration
-func (s *UDPSession) SetNoDelay(nodelay, interval, resend, nc int) {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	s.kcp.NoDelay(nodelay, interval, resend, nc)
-}
-
-// SetDSCP sets the 6bit DSCP field of IP header, no effect if it's accepted from Listener
-func (s *UDPSession) SetDSCP(dscp int) error {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	if s.l == nil {
-		if nc, ok := s.conn.(*connectedUDPConn); ok {
-			return ipv4.NewConn(nc.UDPConn).SetTOS(dscp << 2)
-		} else if nc, ok := s.conn.(net.Conn); ok {
-			return ipv4.NewConn(nc).SetTOS(dscp << 2)
-		}
-	}
-	return errors.New(errInvalidOperation)
-}
-
-// SetReadBuffer sets the socket read buffer, no effect if it's accepted from Listener
-func (s *UDPSession) SetReadBuffer(bytes int) error {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	if s.l == nil {
-		if nc, ok := s.conn.(setReadBuffer); ok {
-			return nc.SetReadBuffer(bytes)
-		}
-	}
-	return errors.New(errInvalidOperation)
-}
-
-// SetWriteBuffer sets the socket write buffer, no effect if it's accepted from Listener
-func (s *UDPSession) SetWriteBuffer(bytes int) error {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	if s.l == nil {
-		if nc, ok := s.conn.(setWriteBuffer); ok {
-			return nc.SetWriteBuffer(bytes)
-		}
-	}
-	return errors.New(errInvalidOperation)
-}
-
-// output pipeline entry
-// steps for output data processing:
-// 0. Header extends
-// 1. FEC
-// 2. CRC32
-// 3. Encryption
-// 4. WriteTo kernel
-func (s *UDPSession) output(buf []byte) {
-	var ecc [][]byte
-
-	// 0. extend buf's header space(if necessary)
-	ext := buf
-	if s.headerSize > 0 {
-		ext = s.ext[:s.headerSize+len(buf)]
-		copy(ext[s.headerSize:], buf)
-	}
-
-	// 1. FEC encoding
-	if s.fecEncoder != nil {
-		ecc = s.fecEncoder.encode(ext)
-	}
-
-	// 2&3. crc32 & encryption
-	if s.block != nil {
-		io.ReadFull(rand.Reader, ext[:nonceSize])
-		checksum := crc32.ChecksumIEEE(ext[cryptHeaderSize:])
-		binary.LittleEndian.PutUint32(ext[nonceSize:], checksum)
-		s.block.Encrypt(ext, ext)
-
-		for k := range ecc {
-			io.ReadFull(rand.Reader, ecc[k][:nonceSize])
-			checksum := crc32.ChecksumIEEE(ecc[k][cryptHeaderSize:])
-			binary.LittleEndian.PutUint32(ecc[k][nonceSize:], checksum)
-			s.block.Encrypt(ecc[k], ecc[k])
-		}
-	}
-
-	// 4. WriteTo kernel
-	nbytes := 0
-	npkts := 0
-	for i := 0; i < s.dup+1; i++ {
-		if n, err := s.conn.WriteTo(ext, s.remote); err == nil {
-			nbytes += n
-			npkts++
-		}
-	}
-
-	for k := range ecc {
-		if n, err := s.conn.WriteTo(ecc[k], s.remote); err == nil {
-			nbytes += n
-			npkts++
-		}
-	}
-	atomic.AddUint64(&DefaultSnmp.OutPkts, uint64(npkts))
-	atomic.AddUint64(&DefaultSnmp.OutBytes, uint64(nbytes))
-}
-
-// kcp update, returns interval for next calling
-func (s *UDPSession) update() (interval time.Duration) {
-	s.mu.Lock()
-	s.kcp.flush(false)
-	if s.kcp.WaitSnd() < int(s.kcp.snd_wnd) {
-		s.notifyWriteEvent()
-	}
-	interval = time.Duration(s.kcp.interval) * time.Millisecond
-	s.mu.Unlock()
-	return
-}
-
-// GetConv gets conversation id of a session
-func (s *UDPSession) GetConv() uint32 { return s.kcp.conv }
-
-func (s *UDPSession) notifyReadEvent() {
-	select {
-	case s.chReadEvent <- struct{}{}:
-	default:
-	}
-}
-
-func (s *UDPSession) notifyWriteEvent() {
-	select {
-	case s.chWriteEvent <- struct{}{}:
-	default:
-	}
-}
-
-func (s *UDPSession) kcpInput(data []byte) {
-	var kcpInErrors, fecErrs, fecRecovered, fecParityShards uint64
-
-	if s.fecDecoder != nil {
-		f := s.fecDecoder.decodeBytes(data)
-		s.mu.Lock()
-		if f.flag == typeData {
-			if ret := s.kcp.Input(data[fecHeaderSizePlus2:], true, s.ackNoDelay); ret != 0 {
-				kcpInErrors++
-			}
-		}
-
-		if f.flag == typeData || f.flag == typeFEC {
-			if f.flag == typeFEC {
-				fecParityShards++
-			}
-
-			recovers := s.fecDecoder.decode(f)
-			for _, r := range recovers {
-				if len(r) >= 2 { // must be larger than 2bytes
-					sz := binary.LittleEndian.Uint16(r)
-					if int(sz) <= len(r) && sz >= 2 {
-						if ret := s.kcp.Input(r[2:sz], false, s.ackNoDelay); ret == 0 {
-							fecRecovered++
-						} else {
-							kcpInErrors++
-						}
-					} else {
-						fecErrs++
-					}
-				} else {
-					fecErrs++
-				}
-			}
-		}
-
-		// notify reader
-		if n := s.kcp.PeekSize(); n > 0 {
-			s.notifyReadEvent()
-		}
-		s.mu.Unlock()
-	} else {
-		s.mu.Lock()
-		if ret := s.kcp.Input(data, true, s.ackNoDelay); ret != 0 {
-			kcpInErrors++
-		}
-		// notify reader
-		if n := s.kcp.PeekSize(); n > 0 {
-			s.notifyReadEvent()
-		}
-		s.mu.Unlock()
-	}
-
-	atomic.AddUint64(&DefaultSnmp.InPkts, 1)
-	atomic.AddUint64(&DefaultSnmp.InBytes, uint64(len(data)))
-	if fecParityShards > 0 {
-		atomic.AddUint64(&DefaultSnmp.FECParityShards, fecParityShards)
-	}
-	if kcpInErrors > 0 {
-		atomic.AddUint64(&DefaultSnmp.KCPInErrors, kcpInErrors)
-	}
-	if fecErrs > 0 {
-		atomic.AddUint64(&DefaultSnmp.FECErrs, fecErrs)
-	}
-	if fecRecovered > 0 {
-		atomic.AddUint64(&DefaultSnmp.FECRecovered, fecRecovered)
-	}
-}
-
-func (s *UDPSession) receiver(ch chan<- []byte) {
-	for {
-		data := xmitBuf.Get().([]byte)[:mtuLimit]
-		if n, _, err := s.conn.ReadFrom(data); err == nil && n >= s.headerSize+IKCP_OVERHEAD {
-			select {
-			case ch <- data[:n]:
-			case <-s.die:
-				return
-			}
-		} else if err != nil {
-			s.chErrorEvent <- err
-			return
-		} else {
-			atomic.AddUint64(&DefaultSnmp.InErrs, 1)
-		}
-	}
-}
-
-// read loop for client session
-func (s *UDPSession) readLoop() {
-	chPacket := make(chan []byte, qlen)
-	go s.receiver(chPacket)
-
-	for {
-		select {
-		case data := <-chPacket:
-			raw := data
-			dataValid := false
-			if s.block != nil {
-				s.block.Decrypt(data, data)
-				data = data[nonceSize:]
-				checksum := crc32.ChecksumIEEE(data[crcSize:])
-				if checksum == binary.LittleEndian.Uint32(data) {
-					data = data[crcSize:]
-					dataValid = true
-				} else {
-					atomic.AddUint64(&DefaultSnmp.InCsumErrors, 1)
-				}
-			} else if s.block == nil {
-				dataValid = true
-			}
-
-			if dataValid {
-				s.kcpInput(data)
-			}
-			xmitBuf.Put(raw)
-		case <-s.die:
-			return
-		}
-	}
-}
-
-type (
-	// Listener defines a server listening for connections
-	Listener struct {
-		block        BlockCrypt     // block encryption
-		dataShards   int            // FEC data shard
-		parityShards int            // FEC parity shard
-		fecDecoder   *fecDecoder    // FEC mock initialization
-		conn         net.PacketConn // the underlying packet connection
-
-		sessions        map[string]*UDPSession // all sessions accepted by this Listener
-		chAccepts       chan *UDPSession       // Listen() backlog
-		chSessionClosed chan net.Addr          // session close queue
-		headerSize      int                    // the overall header size added before KCP frame
-		die             chan struct{}          // notify the listener has closed
-		rd              atomic.Value           // read deadline for Accept()
-		wd              atomic.Value
-	}
-
-	// incoming packet
-	inPacket struct {
-		from net.Addr
-		data []byte
-	}
-)
-
-// monitor incoming data for all connections of server
-func (l *Listener) monitor() {
-	chPacket := make(chan inPacket, qlen)
-	go l.receiver(chPacket)
-	for {
-		select {
-		case p := <-chPacket:
-			raw := p.data
-			data := p.data
-			from := p.from
-			dataValid := false
-			if l.block != nil {
-				l.block.Decrypt(data, data)
-				data = data[nonceSize:]
-				checksum := crc32.ChecksumIEEE(data[crcSize:])
-				if checksum == binary.LittleEndian.Uint32(data) {
-					data = data[crcSize:]
-					dataValid = true
-				} else {
-					atomic.AddUint64(&DefaultSnmp.InCsumErrors, 1)
-				}
-			} else if l.block == nil {
-				dataValid = true
-			}
-
-			if dataValid {
-				addr := from.String()
-				s, ok := l.sessions[addr]
-				if !ok { // new session
-					if len(l.chAccepts) < cap(l.chAccepts) { // do not let new session overwhelm accept queue
-						var conv uint32
-						convValid := false
-						if l.fecDecoder != nil {
-							isfec := binary.LittleEndian.Uint16(data[4:])
-							if isfec == typeData {
-								conv = binary.LittleEndian.Uint32(data[fecHeaderSizePlus2:])
-								convValid = true
-							}
-						} else {
-							conv = binary.LittleEndian.Uint32(data)
-							convValid = true
-						}
-
-						if convValid {
-							s := newUDPSession(conv, l.dataShards, l.parityShards, l, l.conn, from, l.block)
-							s.kcpInput(data)
-							l.sessions[addr] = s
-							l.chAccepts <- s
-						}
-					}
-				} else {
-					s.kcpInput(data)
-				}
-			}
-
-			xmitBuf.Put(raw)
-		case deadlink := <-l.chSessionClosed:
-			delete(l.sessions, deadlink.String())
-		case <-l.die:
-			return
-		}
-	}
-}
-
-func (l *Listener) receiver(ch chan<- inPacket) {
-	for {
-		data := xmitBuf.Get().([]byte)[:mtuLimit]
-		if n, from, err := l.conn.ReadFrom(data); err == nil && n >= l.headerSize+IKCP_OVERHEAD {
-			select {
-			case ch <- inPacket{from, data[:n]}:
-			case <-l.die:
-				return
-			}
-		} else if err != nil {
-			return
-		} else {
-			atomic.AddUint64(&DefaultSnmp.InErrs, 1)
-		}
-	}
-}
-
-// SetReadBuffer sets the socket read buffer for the Listener
-func (l *Listener) SetReadBuffer(bytes int) error {
-	if nc, ok := l.conn.(setReadBuffer); ok {
-		return nc.SetReadBuffer(bytes)
-	}
-	return errors.New(errInvalidOperation)
-}
-
-// SetWriteBuffer sets the socket write buffer for the Listener
-func (l *Listener) SetWriteBuffer(bytes int) error {
-	if nc, ok := l.conn.(setWriteBuffer); ok {
-		return nc.SetWriteBuffer(bytes)
-	}
-	return errors.New(errInvalidOperation)
-}
-
-// SetDSCP sets the 6bit DSCP field of IP header
-func (l *Listener) SetDSCP(dscp int) error {
-	if nc, ok := l.conn.(net.Conn); ok {
-		return ipv4.NewConn(nc).SetTOS(dscp << 2)
-	}
-	return errors.New(errInvalidOperation)
-}
-
-// Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn.
-func (l *Listener) Accept() (net.Conn, error) {
-	return l.AcceptKCP()
-}
-
-// AcceptKCP accepts a KCP connection
-func (l *Listener) AcceptKCP() (*UDPSession, error) {
-	var timeout <-chan time.Time
-	if tdeadline, ok := l.rd.Load().(time.Time); ok && !tdeadline.IsZero() {
-		timeout = time.After(tdeadline.Sub(time.Now()))
-	}
-
-	select {
-	case <-timeout:
-		return nil, &errTimeout{}
-	case c := <-l.chAccepts:
-		return c, nil
-	case <-l.die:
-		return nil, errors.New(errBrokenPipe)
-	}
-}
-
-// SetDeadline sets the deadline associated with the listener. A zero time value disables the deadline.
-func (l *Listener) SetDeadline(t time.Time) error {
-	l.SetReadDeadline(t)
-	l.SetWriteDeadline(t)
-	return nil
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (l *Listener) SetReadDeadline(t time.Time) error {
-	l.rd.Store(t)
-	return nil
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (l *Listener) SetWriteDeadline(t time.Time) error {
-	l.wd.Store(t)
-	return nil
-}
-
-// Close stops listening on the UDP address. Already Accepted connections are not closed.
-func (l *Listener) Close() error {
-	close(l.die)
-	return l.conn.Close()
-}
-
-// closeSession notify the listener that a session has closed
-func (l *Listener) closeSession(remote net.Addr) bool {
-	select {
-	case l.chSessionClosed <- remote:
-		return true
-	case <-l.die:
-		return false
-	}
-}
-
-// Addr returns the listener's network address, The Addr returned is shared by all invocations of Addr, so do not modify it.
-func (l *Listener) Addr() net.Addr { return l.conn.LocalAddr() }
-
-// Listen listens for incoming KCP packets addressed to the local address laddr on the network "udp",
-func Listen(laddr string) (net.Listener, error) { return ListenWithOptions(laddr, nil, 0, 0) }
-
-// ListenWithOptions listens for incoming KCP packets addressed to the local address laddr on the network "udp" with packet encryption,
-// dataShards, parityShards defines Reed-Solomon Erasure Coding parameters
-func ListenWithOptions(laddr string, block BlockCrypt, dataShards, parityShards int) (*Listener, error) {
-	udpaddr, err := net.ResolveUDPAddr("udp", laddr)
-	if err != nil {
-		return nil, errors.Wrap(err, "net.ResolveUDPAddr")
-	}
-	conn, err := net.ListenUDP("udp", udpaddr)
-	if err != nil {
-		return nil, errors.Wrap(err, "net.ListenUDP")
-	}
-
-	return ServeConn(block, dataShards, parityShards, conn)
-}
-
-// ServeConn serves KCP protocol for a single packet connection.
-func ServeConn(block BlockCrypt, dataShards, parityShards int, conn net.PacketConn) (*Listener, error) {
-	l := new(Listener)
-	l.conn = conn
-	l.sessions = make(map[string]*UDPSession)
-	l.chAccepts = make(chan *UDPSession, acceptBacklog)
-	l.chSessionClosed = make(chan net.Addr)
-	l.die = make(chan struct{})
-	l.dataShards = dataShards
-	l.parityShards = parityShards
-	l.block = block
-	l.fecDecoder = newFECDecoder(rxFECMulti*(dataShards+parityShards), dataShards, parityShards)
-
-	// calculate header size
-	if l.block != nil {
-		l.headerSize += cryptHeaderSize
-	}
-	if l.fecDecoder != nil {
-		l.headerSize += fecHeaderSizePlus2
-	}
-
-	go l.monitor()
-	return l, nil
-}
-
-// Dial connects to the remote address "raddr" on the network "udp"
-func Dial(raddr string) (net.Conn, error) { return DialWithOptions(raddr, nil, 0, 0) }
-
-// DialWithOptions connects to the remote address "raddr" on the network "udp" with packet encryption
-func DialWithOptions(raddr string, block BlockCrypt, dataShards, parityShards int) (*UDPSession, error) {
-	udpaddr, err := net.ResolveUDPAddr("udp", raddr)
-	if err != nil {
-		return nil, errors.Wrap(err, "net.ResolveUDPAddr")
-	}
-
-	udpconn, err := net.DialUDP("udp", nil, udpaddr)
-	if err != nil {
-		return nil, errors.Wrap(err, "net.DialUDP")
-	}
-
-	return NewConn(raddr, block, dataShards, parityShards, &connectedUDPConn{udpconn})
-}
-
-// NewConn establishes a session and talks KCP protocol over a packet connection.
-func NewConn(raddr string, block BlockCrypt, dataShards, parityShards int, conn net.PacketConn) (*UDPSession, error) {
-	udpaddr, err := net.ResolveUDPAddr("udp", raddr)
-	if err != nil {
-		return nil, errors.Wrap(err, "net.ResolveUDPAddr")
-	}
-
-	var convid uint32
-	binary.Read(rand.Reader, binary.LittleEndian, &convid)
-	return newUDPSession(convid, dataShards, parityShards, nil, conn, udpaddr, block), nil
-}
-
-// returns current time in milliseconds
-func currentMs() uint32 { return uint32(time.Now().UnixNano() / int64(time.Millisecond)) }
-
-// 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) }

+ 0 - 476
vendor/github.com/xtaci/kcp-go/sess_test.go

@@ -1,476 +0,0 @@
-package kcp
-
-import (
-	"crypto/sha1"
-	"fmt"
-	"io"
-	"log"
-	"net"
-	"net/http"
-	_ "net/http/pprof"
-	"sync"
-	"testing"
-	"time"
-
-	"golang.org/x/crypto/pbkdf2"
-)
-
-const portEcho = "127.0.0.1:9999"
-const portSink = "127.0.0.1:19999"
-const portTinyBufferEcho = "127.0.0.1:29999"
-const portListerner = "127.0.0.1:9998"
-const salt = "kcptest"
-
-var key = []byte("testkey")
-var fec = 4
-var pass = pbkdf2.Key(key, []byte(portSink), 4096, 32, sha1.New)
-
-func init() {
-	go func() {
-		log.Println(http.ListenAndServe("localhost:6060", nil))
-	}()
-
-	go echoServer()
-	go sinkServer()
-	go tinyBufferEchoServer()
-	println("beginning tests, encryption:salsa20, fec:10/3")
-}
-
-func dialEcho() (*UDPSession, error) {
-	//block, _ := NewNoneBlockCrypt(pass)
-	//block, _ := NewSimpleXORBlockCrypt(pass)
-	//block, _ := NewTEABlockCrypt(pass[:16])
-	//block, _ := NewAESBlockCrypt(pass)
-	block, _ := NewSalsa20BlockCrypt(pass)
-	sess, err := DialWithOptions(portEcho, block, 10, 3)
-	if err != nil {
-		panic(err)
-	}
-
-	sess.SetStreamMode(true)
-	sess.SetStreamMode(false)
-	sess.SetStreamMode(true)
-	sess.SetWindowSize(4096, 4096)
-	sess.SetReadBuffer(4 * 1024 * 1024)
-	sess.SetWriteBuffer(4 * 1024 * 1024)
-	sess.SetStreamMode(true)
-	sess.SetNoDelay(1, 10, 2, 1)
-	sess.SetMtu(1400)
-	sess.SetMtu(1600)
-	sess.SetMtu(1400)
-	sess.SetACKNoDelay(true)
-	sess.SetDeadline(time.Now().Add(time.Minute))
-	return sess, err
-}
-
-func dialSink() (*UDPSession, error) {
-	sess, err := DialWithOptions(portSink, nil, 0, 0)
-	if err != nil {
-		panic(err)
-	}
-
-	sess.SetStreamMode(true)
-	sess.SetWindowSize(4096, 4096)
-	sess.SetReadBuffer(4 * 1024 * 1024)
-	sess.SetWriteBuffer(4 * 1024 * 1024)
-	sess.SetStreamMode(true)
-	sess.SetNoDelay(1, 10, 2, 1)
-	sess.SetMtu(1400)
-	sess.SetACKNoDelay(true)
-	sess.SetDeadline(time.Now().Add(time.Minute))
-	return sess, err
-}
-
-func dialTinyBufferEcho() (*UDPSession, error) {
-	//block, _ := NewNoneBlockCrypt(pass)
-	//block, _ := NewSimpleXORBlockCrypt(pass)
-	//block, _ := NewTEABlockCrypt(pass[:16])
-	//block, _ := NewAESBlockCrypt(pass)
-	block, _ := NewSalsa20BlockCrypt(pass)
-	sess, err := DialWithOptions(portTinyBufferEcho, block, 10, 3)
-	if err != nil {
-		panic(err)
-	}
-	return sess, err
-}
-
-//////////////////////////
-func listenEcho() (net.Listener, error) {
-	//block, _ := NewNoneBlockCrypt(pass)
-	//block, _ := NewSimpleXORBlockCrypt(pass)
-	//block, _ := NewTEABlockCrypt(pass[:16])
-	//block, _ := NewAESBlockCrypt(pass)
-	block, _ := NewSalsa20BlockCrypt(pass)
-	return ListenWithOptions(portEcho, block, 10, 3)
-}
-func listenTinyBufferEcho() (net.Listener, error) {
-	//block, _ := NewNoneBlockCrypt(pass)
-	//block, _ := NewSimpleXORBlockCrypt(pass)
-	//block, _ := NewTEABlockCrypt(pass[:16])
-	//block, _ := NewAESBlockCrypt(pass)
-	block, _ := NewSalsa20BlockCrypt(pass)
-	return ListenWithOptions(portTinyBufferEcho, block, 10, 3)
-}
-
-func listenSink() (net.Listener, error) {
-	return ListenWithOptions(portSink, nil, 0, 0)
-}
-
-func echoServer() {
-	l, err := listenEcho()
-	if err != nil {
-		panic(err)
-	}
-
-	go func() {
-		kcplistener := l.(*Listener)
-		kcplistener.SetReadBuffer(4 * 1024 * 1024)
-		kcplistener.SetWriteBuffer(4 * 1024 * 1024)
-		kcplistener.SetDSCP(46)
-		for {
-			s, err := l.Accept()
-			if err != nil {
-				return
-			}
-
-			// coverage test
-			s.(*UDPSession).SetReadBuffer(4 * 1024 * 1024)
-			s.(*UDPSession).SetWriteBuffer(4 * 1024 * 1024)
-			go handleEcho(s.(*UDPSession))
-		}
-	}()
-}
-
-func sinkServer() {
-	l, err := listenSink()
-	if err != nil {
-		panic(err)
-	}
-
-	go func() {
-		kcplistener := l.(*Listener)
-		kcplistener.SetReadBuffer(4 * 1024 * 1024)
-		kcplistener.SetWriteBuffer(4 * 1024 * 1024)
-		kcplistener.SetDSCP(46)
-		for {
-			s, err := l.Accept()
-			if err != nil {
-				return
-			}
-
-			go handleSink(s.(*UDPSession))
-		}
-	}()
-}
-
-func tinyBufferEchoServer() {
-	l, err := listenTinyBufferEcho()
-	if err != nil {
-		panic(err)
-	}
-
-	go func() {
-		for {
-			s, err := l.Accept()
-			if err != nil {
-				return
-			}
-			go handleTinyBufferEcho(s.(*UDPSession))
-		}
-	}()
-}
-
-///////////////////////////
-
-func handleEcho(conn *UDPSession) {
-	conn.SetStreamMode(true)
-	conn.SetWindowSize(4096, 4096)
-	conn.SetNoDelay(1, 10, 2, 1)
-	conn.SetDSCP(46)
-	conn.SetMtu(1400)
-	conn.SetACKNoDelay(false)
-	conn.SetReadDeadline(time.Now().Add(time.Hour))
-	conn.SetWriteDeadline(time.Now().Add(time.Hour))
-	buf := make([]byte, 65536)
-	for {
-		n, err := conn.Read(buf)
-		if err != nil {
-			panic(err)
-		}
-		conn.Write(buf[:n])
-	}
-}
-
-func handleSink(conn *UDPSession) {
-	conn.SetStreamMode(true)
-	conn.SetWindowSize(4096, 4096)
-	conn.SetNoDelay(1, 10, 2, 1)
-	conn.SetDSCP(46)
-	conn.SetMtu(1400)
-	conn.SetACKNoDelay(false)
-	conn.SetReadDeadline(time.Now().Add(time.Hour))
-	conn.SetWriteDeadline(time.Now().Add(time.Hour))
-	buf := make([]byte, 65536)
-	for {
-		_, err := conn.Read(buf)
-		if err != nil {
-			panic(err)
-		}
-	}
-}
-
-func handleTinyBufferEcho(conn *UDPSession) {
-	conn.SetStreamMode(true)
-	buf := make([]byte, 2)
-	for {
-		n, err := conn.Read(buf)
-		if err != nil {
-			panic(err)
-		}
-		conn.Write(buf[:n])
-	}
-}
-
-///////////////////////////
-
-func TestTimeout(t *testing.T) {
-	cli, err := dialEcho()
-	if err != nil {
-		panic(err)
-	}
-	buf := make([]byte, 10)
-
-	//timeout
-	cli.SetDeadline(time.Now().Add(time.Second))
-	<-time.After(2 * time.Second)
-	n, err := cli.Read(buf)
-	if n != 0 || err == nil {
-		t.Fail()
-	}
-	cli.Close()
-}
-
-func TestSendRecv(t *testing.T) {
-	cli, err := dialEcho()
-	if err != nil {
-		panic(err)
-	}
-	cli.SetWriteDelay(true)
-	cli.SetDUP(1)
-	const N = 100
-	buf := make([]byte, 10)
-	for i := 0; i < N; i++ {
-		msg := fmt.Sprintf("hello%v", i)
-		cli.Write([]byte(msg))
-		if n, err := cli.Read(buf); err == nil {
-			if string(buf[:n]) != msg {
-				t.Fail()
-			}
-		} else {
-			panic(err)
-		}
-	}
-	cli.Close()
-}
-
-func TestTinyBufferReceiver(t *testing.T) {
-	cli, err := dialTinyBufferEcho()
-	if err != nil {
-		panic(err)
-	}
-	const N = 100
-	snd := byte(0)
-	fillBuffer := func(buf []byte) {
-		for i := 0; i < len(buf); i++ {
-			buf[i] = snd
-			snd++
-		}
-	}
-
-	rcv := byte(0)
-	check := func(buf []byte) bool {
-		for i := 0; i < len(buf); i++ {
-			if buf[i] != rcv {
-				return false
-			}
-			rcv++
-		}
-		return true
-	}
-	sndbuf := make([]byte, 7)
-	rcvbuf := make([]byte, 7)
-	for i := 0; i < N; i++ {
-		fillBuffer(sndbuf)
-		cli.Write(sndbuf)
-		if n, err := io.ReadFull(cli, rcvbuf); err == nil {
-			if !check(rcvbuf[:n]) {
-				t.Fail()
-			}
-		} else {
-			panic(err)
-		}
-	}
-	cli.Close()
-}
-
-func TestClose(t *testing.T) {
-	cli, err := dialEcho()
-	if err != nil {
-		panic(err)
-	}
-	buf := make([]byte, 10)
-
-	cli.Close()
-	if cli.Close() == nil {
-		t.Fail()
-	}
-	n, err := cli.Write(buf)
-	if n != 0 || err == nil {
-		t.Fail()
-	}
-	n, err = cli.Read(buf)
-	if n != 0 || err == nil {
-		t.Fail()
-	}
-	cli.Close()
-}
-
-func TestParallel1024CLIENT_64BMSG_64CNT(t *testing.T) {
-	var wg sync.WaitGroup
-	wg.Add(1024)
-	for i := 0; i < 1024; i++ {
-		go parallel_client(&wg)
-	}
-	wg.Wait()
-}
-
-func parallel_client(wg *sync.WaitGroup) (err error) {
-	cli, err := dialEcho()
-	if err != nil {
-		panic(err)
-	}
-
-	err = echo_tester(cli, 64, 64)
-	wg.Done()
-	return
-}
-
-func BenchmarkEchoSpeed4K(b *testing.B) {
-	speedclient(b, 4096)
-}
-
-func BenchmarkEchoSpeed64K(b *testing.B) {
-	speedclient(b, 65536)
-}
-
-func BenchmarkEchoSpeed512K(b *testing.B) {
-	speedclient(b, 524288)
-}
-
-func BenchmarkEchoSpeed1M(b *testing.B) {
-	speedclient(b, 1048576)
-}
-
-func speedclient(b *testing.B, nbytes int) {
-	b.ReportAllocs()
-	cli, err := dialEcho()
-	if err != nil {
-		panic(err)
-	}
-
-	if err := echo_tester(cli, nbytes, b.N); err != nil {
-		b.Fail()
-	}
-	b.SetBytes(int64(nbytes))
-}
-
-func BenchmarkSinkSpeed4K(b *testing.B) {
-	sinkclient(b, 4096)
-}
-
-func BenchmarkSinkSpeed64K(b *testing.B) {
-	sinkclient(b, 65536)
-}
-
-func BenchmarkSinkSpeed256K(b *testing.B) {
-	sinkclient(b, 524288)
-}
-
-func BenchmarkSinkSpeed1M(b *testing.B) {
-	sinkclient(b, 1048576)
-}
-
-func sinkclient(b *testing.B, nbytes int) {
-	b.ReportAllocs()
-	cli, err := dialSink()
-	if err != nil {
-		panic(err)
-	}
-
-	sink_tester(cli, nbytes, b.N)
-	b.SetBytes(int64(nbytes))
-}
-
-func echo_tester(cli net.Conn, msglen, msgcount int) error {
-	buf := make([]byte, msglen)
-	for i := 0; i < msgcount; i++ {
-		// send packet
-		if _, err := cli.Write(buf); err != nil {
-			return err
-		}
-
-		// receive packet
-		nrecv := 0
-		for {
-			n, err := cli.Read(buf)
-			if err != nil {
-				return err
-			} else {
-				nrecv += n
-				if nrecv == msglen {
-					break
-				}
-			}
-		}
-	}
-	return nil
-}
-
-func sink_tester(cli *UDPSession, msglen, msgcount int) error {
-	// sender
-	buf := make([]byte, msglen)
-	for i := 0; i < msgcount; i++ {
-		if _, err := cli.Write(buf); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func TestSNMP(t *testing.T) {
-	t.Log(DefaultSnmp.Copy())
-	t.Log(DefaultSnmp.Header())
-	t.Log(DefaultSnmp.ToSlice())
-	DefaultSnmp.Reset()
-	t.Log(DefaultSnmp.ToSlice())
-}
-
-func TestListenerClose(t *testing.T) {
-	l, err := ListenWithOptions(portListerner, nil, 10, 3)
-	if err != nil {
-		t.Fail()
-	}
-	l.SetReadDeadline(time.Now().Add(time.Second))
-	l.SetWriteDeadline(time.Now().Add(time.Second))
-	l.SetDeadline(time.Now().Add(time.Second))
-	time.Sleep(2 * time.Second)
-	if _, err := l.Accept(); err == nil {
-		t.Fail()
-	}
-
-	l.Close()
-	fakeaddr, _ := net.ResolveUDPAddr("udp6", "127.0.0.1:1111")
-	if l.closeSession(fakeaddr) {
-		t.Fail()
-	}
-}

+ 0 - 164
vendor/github.com/xtaci/kcp-go/snmp.go

@@ -1,164 +0,0 @@
-package kcp
-
-import (
-	"fmt"
-	"sync/atomic"
-)
-
-// Snmp defines network statistics indicator
-type Snmp struct {
-	BytesSent        uint64 // bytes sent from upper level
-	BytesReceived    uint64 // bytes received to upper level
-	MaxConn          uint64 // max number of connections ever reached
-	ActiveOpens      uint64 // accumulated active open connections
-	PassiveOpens     uint64 // accumulated passive open connections
-	CurrEstab        uint64 // current number of established connections
-	InErrs           uint64 // UDP read errors reported from net.PacketConn
-	InCsumErrors     uint64 // checksum errors from CRC32
-	KCPInErrors      uint64 // packet iput errors reported from KCP
-	InPkts           uint64 // incoming packets count
-	OutPkts          uint64 // outgoing packets count
-	InSegs           uint64 // incoming KCP segments
-	OutSegs          uint64 // outgoing KCP segments
-	InBytes          uint64 // UDP bytes received
-	OutBytes         uint64 // UDP bytes sent
-	RetransSegs      uint64 // accmulated retransmited segments
-	FastRetransSegs  uint64 // accmulated fast retransmitted segments
-	EarlyRetransSegs uint64 // accmulated early retransmitted segments
-	LostSegs         uint64 // number of segs infered as lost
-	RepeatSegs       uint64 // number of segs duplicated
-	FECRecovered     uint64 // correct packets recovered from FEC
-	FECErrs          uint64 // incorrect packets recovered from FEC
-	FECParityShards  uint64 // FEC segments received
-	FECShortShards   uint64 // number of data shards that's not enough for recovery
-}
-
-func newSnmp() *Snmp {
-	return new(Snmp)
-}
-
-// Header returns all field names
-func (s *Snmp) Header() []string {
-	return []string{
-		"BytesSent",
-		"BytesReceived",
-		"MaxConn",
-		"ActiveOpens",
-		"PassiveOpens",
-		"CurrEstab",
-		"InErrs",
-		"InCsumErrors",
-		"KCPInErrors",
-		"InPkts",
-		"OutPkts",
-		"InSegs",
-		"OutSegs",
-		"InBytes",
-		"OutBytes",
-		"RetransSegs",
-		"FastRetransSegs",
-		"EarlyRetransSegs",
-		"LostSegs",
-		"RepeatSegs",
-		"FECParityShards",
-		"FECErrs",
-		"FECRecovered",
-		"FECShortShards",
-	}
-}
-
-// ToSlice returns current snmp info as slice
-func (s *Snmp) ToSlice() []string {
-	snmp := s.Copy()
-	return []string{
-		fmt.Sprint(snmp.BytesSent),
-		fmt.Sprint(snmp.BytesReceived),
-		fmt.Sprint(snmp.MaxConn),
-		fmt.Sprint(snmp.ActiveOpens),
-		fmt.Sprint(snmp.PassiveOpens),
-		fmt.Sprint(snmp.CurrEstab),
-		fmt.Sprint(snmp.InErrs),
-		fmt.Sprint(snmp.InCsumErrors),
-		fmt.Sprint(snmp.KCPInErrors),
-		fmt.Sprint(snmp.InPkts),
-		fmt.Sprint(snmp.OutPkts),
-		fmt.Sprint(snmp.InSegs),
-		fmt.Sprint(snmp.OutSegs),
-		fmt.Sprint(snmp.InBytes),
-		fmt.Sprint(snmp.OutBytes),
-		fmt.Sprint(snmp.RetransSegs),
-		fmt.Sprint(snmp.FastRetransSegs),
-		fmt.Sprint(snmp.EarlyRetransSegs),
-		fmt.Sprint(snmp.LostSegs),
-		fmt.Sprint(snmp.RepeatSegs),
-		fmt.Sprint(snmp.FECParityShards),
-		fmt.Sprint(snmp.FECErrs),
-		fmt.Sprint(snmp.FECRecovered),
-		fmt.Sprint(snmp.FECShortShards),
-	}
-}
-
-// Copy make a copy of current snmp snapshot
-func (s *Snmp) Copy() *Snmp {
-	d := newSnmp()
-	d.BytesSent = atomic.LoadUint64(&s.BytesSent)
-	d.BytesReceived = atomic.LoadUint64(&s.BytesReceived)
-	d.MaxConn = atomic.LoadUint64(&s.MaxConn)
-	d.ActiveOpens = atomic.LoadUint64(&s.ActiveOpens)
-	d.PassiveOpens = atomic.LoadUint64(&s.PassiveOpens)
-	d.CurrEstab = atomic.LoadUint64(&s.CurrEstab)
-	d.InErrs = atomic.LoadUint64(&s.InErrs)
-	d.InCsumErrors = atomic.LoadUint64(&s.InCsumErrors)
-	d.KCPInErrors = atomic.LoadUint64(&s.KCPInErrors)
-	d.InPkts = atomic.LoadUint64(&s.InPkts)
-	d.OutPkts = atomic.LoadUint64(&s.OutPkts)
-	d.InSegs = atomic.LoadUint64(&s.InSegs)
-	d.OutSegs = atomic.LoadUint64(&s.OutSegs)
-	d.InBytes = atomic.LoadUint64(&s.InBytes)
-	d.OutBytes = atomic.LoadUint64(&s.OutBytes)
-	d.RetransSegs = atomic.LoadUint64(&s.RetransSegs)
-	d.FastRetransSegs = atomic.LoadUint64(&s.FastRetransSegs)
-	d.EarlyRetransSegs = atomic.LoadUint64(&s.EarlyRetransSegs)
-	d.LostSegs = atomic.LoadUint64(&s.LostSegs)
-	d.RepeatSegs = atomic.LoadUint64(&s.RepeatSegs)
-	d.FECParityShards = atomic.LoadUint64(&s.FECParityShards)
-	d.FECErrs = atomic.LoadUint64(&s.FECErrs)
-	d.FECRecovered = atomic.LoadUint64(&s.FECRecovered)
-	d.FECShortShards = atomic.LoadUint64(&s.FECShortShards)
-	return d
-}
-
-// Reset values to zero
-func (s *Snmp) Reset() {
-	atomic.StoreUint64(&s.BytesSent, 0)
-	atomic.StoreUint64(&s.BytesReceived, 0)
-	atomic.StoreUint64(&s.MaxConn, 0)
-	atomic.StoreUint64(&s.ActiveOpens, 0)
-	atomic.StoreUint64(&s.PassiveOpens, 0)
-	atomic.StoreUint64(&s.CurrEstab, 0)
-	atomic.StoreUint64(&s.InErrs, 0)
-	atomic.StoreUint64(&s.InCsumErrors, 0)
-	atomic.StoreUint64(&s.KCPInErrors, 0)
-	atomic.StoreUint64(&s.InPkts, 0)
-	atomic.StoreUint64(&s.OutPkts, 0)
-	atomic.StoreUint64(&s.InSegs, 0)
-	atomic.StoreUint64(&s.OutSegs, 0)
-	atomic.StoreUint64(&s.InBytes, 0)
-	atomic.StoreUint64(&s.OutBytes, 0)
-	atomic.StoreUint64(&s.RetransSegs, 0)
-	atomic.StoreUint64(&s.FastRetransSegs, 0)
-	atomic.StoreUint64(&s.EarlyRetransSegs, 0)
-	atomic.StoreUint64(&s.LostSegs, 0)
-	atomic.StoreUint64(&s.RepeatSegs, 0)
-	atomic.StoreUint64(&s.FECParityShards, 0)
-	atomic.StoreUint64(&s.FECErrs, 0)
-	atomic.StoreUint64(&s.FECRecovered, 0)
-	atomic.StoreUint64(&s.FECShortShards, 0)
-}
-
-// DefaultSnmp is the global KCP connection statistics collector
-var DefaultSnmp *Snmp
-
-func init() {
-	DefaultSnmp = newSnmp()
-}

+ 0 - 105
vendor/github.com/xtaci/kcp-go/updater.go

@@ -1,105 +0,0 @@
-package kcp
-
-import (
-	"container/heap"
-	"sync"
-	"time"
-)
-
-var updater updateHeap
-
-func init() {
-	updater.init()
-	go updater.updateTask()
-}
-
-// entry contains a session update info
-type entry struct {
-	ts time.Time
-	s  *UDPSession
-}
-
-// a global heap managed kcp.flush() caller
-type updateHeap struct {
-	entries  []entry
-	mu       sync.Mutex
-	chWakeUp chan struct{}
-}
-
-func (h *updateHeap) Len() int           { return len(h.entries) }
-func (h *updateHeap) Less(i, j int) bool { return h.entries[i].ts.Before(h.entries[j].ts) }
-func (h *updateHeap) Swap(i, j int) {
-	h.entries[i], h.entries[j] = h.entries[j], h.entries[i]
-	h.entries[i].s.updaterIdx = i
-	h.entries[j].s.updaterIdx = j
-}
-
-func (h *updateHeap) Push(x interface{}) {
-	h.entries = append(h.entries, x.(entry))
-	n := len(h.entries)
-	h.entries[n-1].s.updaterIdx = n - 1
-}
-
-func (h *updateHeap) Pop() interface{} {
-	n := len(h.entries)
-	x := h.entries[n-1]
-	h.entries[n-1].s.updaterIdx = -1
-	h.entries[n-1] = entry{} // manual set nil for GC
-	h.entries = h.entries[0 : n-1]
-	return x
-}
-
-func (h *updateHeap) init() {
-	h.chWakeUp = make(chan struct{}, 1)
-}
-
-func (h *updateHeap) addSession(s *UDPSession) {
-	h.mu.Lock()
-	heap.Push(h, entry{time.Now(), s})
-	h.mu.Unlock()
-	h.wakeup()
-}
-
-func (h *updateHeap) removeSession(s *UDPSession) {
-	h.mu.Lock()
-	if s.updaterIdx != -1 {
-		heap.Remove(h, s.updaterIdx)
-	}
-	h.mu.Unlock()
-}
-
-func (h *updateHeap) wakeup() {
-	select {
-	case h.chWakeUp <- struct{}{}:
-	default:
-	}
-}
-
-func (h *updateHeap) updateTask() {
-	var timer <-chan time.Time
-	for {
-		select {
-		case <-timer:
-		case <-h.chWakeUp:
-		}
-
-		h.mu.Lock()
-		hlen := h.Len()
-		now := time.Now()
-		for i := 0; i < hlen; i++ {
-			entry := heap.Pop(h).(entry)
-			if now.After(entry.ts) {
-				entry.ts = now.Add(entry.s.update())
-				heap.Push(h, entry)
-			} else {
-				heap.Push(h, entry)
-				break
-			}
-		}
-
-		if hlen > 0 {
-			timer = time.After(h.entries[0].ts.Sub(now))
-		}
-		h.mu.Unlock()
-	}
-}

+ 0 - 110
vendor/github.com/xtaci/kcp-go/xor.go

@@ -1,110 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package kcp
-
-import (
-	"runtime"
-	"unsafe"
-)
-
-const wordSize = int(unsafe.Sizeof(uintptr(0)))
-const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x"
-
-// fastXORBytes xors in bulk. It only works on architectures that
-// support unaligned read/writes.
-func fastXORBytes(dst, a, b []byte) int {
-	n := len(a)
-	if len(b) < n {
-		n = len(b)
-	}
-
-	w := n / wordSize
-	if w > 0 {
-		wordBytes := w * wordSize
-		fastXORWords(dst[:wordBytes], a[:wordBytes], b[:wordBytes])
-	}
-
-	for i := (n - n%wordSize); i < n; i++ {
-		dst[i] = a[i] ^ b[i]
-	}
-
-	return n
-}
-
-func safeXORBytes(dst, a, b []byte) int {
-	n := len(a)
-	if len(b) < n {
-		n = len(b)
-	}
-	ex := n % 8
-	for i := 0; i < ex; i++ {
-		dst[i] = a[i] ^ b[i]
-	}
-
-	for i := ex; i < n; i += 8 {
-		_dst := dst[i : i+8]
-		_a := a[i : i+8]
-		_b := b[i : i+8]
-		_dst[0] = _a[0] ^ _b[0]
-		_dst[1] = _a[1] ^ _b[1]
-		_dst[2] = _a[2] ^ _b[2]
-		_dst[3] = _a[3] ^ _b[3]
-
-		_dst[4] = _a[4] ^ _b[4]
-		_dst[5] = _a[5] ^ _b[5]
-		_dst[6] = _a[6] ^ _b[6]
-		_dst[7] = _a[7] ^ _b[7]
-	}
-	return n
-}
-
-// xorBytes xors the bytes in a and b. The destination is assumed to have enough
-// space. Returns the number of bytes xor'd.
-func xorBytes(dst, a, b []byte) int {
-	if supportsUnaligned {
-		return fastXORBytes(dst, a, b)
-	}
-	// TODO(hanwen): if (dst, a, b) have common alignment
-	// we could still try fastXORBytes. It is not clear
-	// how often this happens, and it's only worth it if
-	// the block encryption itself is hardware
-	// accelerated.
-	return safeXORBytes(dst, a, b)
-}
-
-// fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.)
-// The arguments are assumed to be of equal length.
-func fastXORWords(dst, a, b []byte) {
-	dw := *(*[]uintptr)(unsafe.Pointer(&dst))
-	aw := *(*[]uintptr)(unsafe.Pointer(&a))
-	bw := *(*[]uintptr)(unsafe.Pointer(&b))
-	n := len(b) / wordSize
-	ex := n % 8
-	for i := 0; i < ex; i++ {
-		dw[i] = aw[i] ^ bw[i]
-	}
-
-	for i := ex; i < n; i += 8 {
-		_dw := dw[i : i+8]
-		_aw := aw[i : i+8]
-		_bw := bw[i : i+8]
-		_dw[0] = _aw[0] ^ _bw[0]
-		_dw[1] = _aw[1] ^ _bw[1]
-		_dw[2] = _aw[2] ^ _bw[2]
-		_dw[3] = _aw[3] ^ _bw[3]
-		_dw[4] = _aw[4] ^ _bw[4]
-		_dw[5] = _aw[5] ^ _bw[5]
-		_dw[6] = _aw[6] ^ _bw[6]
-		_dw[7] = _aw[7] ^ _bw[7]
-	}
-}
-
-func xorWords(dst, a, b []byte) {
-	if supportsUnaligned {
-		fastXORWords(dst, a, b)
-	} else {
-		safeXORBytes(dst, a, b)
-	}
-}

+ 0 - 28
vendor/github.com/xtaci/kcp-go/xor_test.go

@@ -1,28 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package kcp
-
-import (
-	"bytes"
-	"testing"
-)
-
-func TestXORBytes(t *testing.T) {
-	for alignP := 0; alignP < 2; alignP++ {
-		for alignQ := 0; alignQ < 2; alignQ++ {
-			for alignD := 0; alignD < 2; alignD++ {
-				p := make([]byte, 1024)[alignP:]
-				q := make([]byte, 1024)[alignQ:]
-				d1 := make([]byte, 1024+alignD)[alignD:]
-				d2 := make([]byte, 1024+alignD)[alignD:]
-				xorBytes(d1, p, q)
-				safeXORBytes(d2, p, q)
-				if !bytes.Equal(d1, d2) {
-					t.Error("not equal")
-				}
-			}
-		}
-	}
-}