Compare commits

...
74 Commits
Author SHA1 Message Date
xtaci 3127b2d19f lint 2016-09-06 16:29:36 +08:00
xtaci 3db63cdff6 add a max ttl for session in scavenger 2016-09-03 14:32:35 +08:00
xtaci 5154cf81de api change of smux 2016-09-02 23:18:29 +08:00
xtaci cc80029b1e adjust params 2016-09-02 17:29:55 +08:00
xtaci 23d6624745 upd 2016-09-02 17:05:44 +08:00
xtaci f38f7a8ac5 scavenge only 2016-09-02 10:55:22 +08:00
xtaci e913f96f7e Merge branch 'smux' 2016-09-02 10:54:00 +08:00
xtaci 5d0d8bd74d upd 2016-09-02 10:42:23 +08:00
xtaci 4010c83e8f upd 2016-09-01 15:02:21 +08:00
xtaci 76351dff2b upd 2016-09-01 12:59:08 +08:00
xtaci 7a5807cbf5 Revert "explict close session"
This reverts commit cb0f299263.
2016-08-31 23:24:30 +08:00
xtaci 6b26c75ea5 upd 2016-08-31 21:48:43 +08:00
xtaci 0873f349c3 upd 2016-08-31 21:46:14 +08:00
xtaci 281f8675a3 upd 2016-08-31 21:33:52 +08:00
xtaci 65512e9296 upd 2016-08-31 21:31:05 +08:00
xtaci 3ea858ed90 upd 2016-08-31 21:29:27 +08:00
xtaci 5f23781fc0 scavenger 2016-08-31 21:27:19 +08:00
xtaci 2b3573f4ea Merge branch 'master' into smux 2016-08-31 18:10:48 +08:00
xtaci cb0f299263 explict close session 2016-08-31 18:07:24 +08:00
xtaci f64bc908ee upd 2016-08-31 16:30:51 +08:00
xtaci 43c6a674ef upd 2016-08-31 15:28:43 +08:00
xtaci 1a48680a55 upd 2016-08-31 15:23:31 +08:00
xtaci dbdb5293b4 branch smux 2016-08-31 11:39:56 +08:00
xtaci 94070bfcbe should continue 2016-08-30 15:34:19 +08:00
xtaciandGitHub 398a0bf9fc Merge pull request #166 from jannson/master
add support for json configuration
2016-08-30 14:56:33 +08:00
janson ff54a2dc92 better for parseJsonConfig 2016-08-30 14:44:55 +08:00
janson 747eba0ee1 add usage and check error for json config 2016-08-30 14:24:08 +08:00
janson f057cbc7f4 add support for json configuration (server side) 2016-08-30 13:50:37 +08:00
janson a83ae4bf15 add support for json configuration 2016-08-30 13:39:08 +08:00
xtaci 4d062090a7 bugfix 2016-08-30 11:17:15 +08:00
xtaci 27f76582e1 structured configuration 2016-08-29 16:06:38 +08:00
xtaci b023b542e8 handle errors gracefully 2016-08-28 10:37:09 +08:00
xtaci 9a3be067bf upd 2016-08-27 21:52:42 +08:00
xtaci 8705bd7670 upd 2016-08-27 09:17:16 +08:00
xtaci b4e5181a2f optimize retry strategy 2016-08-27 09:00:35 +08:00
xtaci 94f61b5945 upd param 2016-08-26 13:04:38 +08:00
xtaci efc0b99d21 Revert "replace yamux with muxado"
This reverts commit 3803993529.
2016-08-26 11:35:13 +08:00
xtaci 3803993529 replace yamux with muxado 2016-08-26 10:58:43 +08:00
xtaci d23ff7c351 upd 2016-08-25 20:34:33 +08:00
xtaci f383ee31a5 add autoexpire option 2016-08-25 20:33:04 +08:00
xtaci d399f220f0 remove a line 2016-08-25 20:04:34 +08:00
xtaci 59a1bbc7b8 SetFinalizer to session 2016-08-25 18:22:20 +08:00
xtaci 3b656e101f better api 2016-08-25 11:46:17 +08:00
xtaci aec364eb72 set tcp socket buffer 2016-08-24 12:27:33 +08:00
xtaci e26ab6729f spelling 2016-08-22 14:46:57 +08:00
xtaci 583fe3ba24 simple layer 2016-08-21 19:09:08 +08:00
xtaci 7fd6442284 refer to my fork 2016-08-20 21:15:05 +08:00
xtaci 81f4643830 Revert "refer to fork"
This reverts commit 744a6407e7.
2016-08-20 20:49:44 +08:00
xtaci 744a6407e7 refer to fork 2016-08-20 20:23:04 +08:00
xtaci 2cf5292ac1 revert yamux config 2016-08-20 18:37:52 +08:00
xtaci b3a8b631b4 upd README 2016-08-20 16:48:10 +08:00
xtaci 1167419210 add salsa20, xtea crypto 2016-08-20 15:02:25 +08:00
xtaci 56f9f0d01a Merge branch 'master' of https://github.com/xtaci/kcptun 2016-08-20 13:39:01 +08:00
xtaci 96888f1cac pisces 2016-08-20 13:35:27 +08:00
xtaciandGitHub e752d70c79 Update README.en.md 2016-08-20 10:47:59 +08:00
xtaciandGitHub a882b94e5b Update README.md 2016-08-20 10:46:34 +08:00
xtaciandGitHub 790a6d5352 Update README.en.md 2016-08-19 21:21:03 +08:00
xtaciandGitHub 603c2db5ab Update README.md 2016-08-19 21:20:15 +08:00
xtaci 581df3a34d update README.md 2016-08-19 15:00:25 +08:00
xtaci 6113d2b497 update README.md 2016-08-19 14:27:13 +08:00
xtaci d3b8a4d71d keep compatiability 2016-08-19 13:17:02 +08:00
xtaci 1f0a4a2c2f change default settings 2016-08-19 12:31:51 +08:00
xtaci 75923fb08f adjust -help 2016-08-19 12:22:36 +08:00
xtaci 0243422885 add supports for blowfish, cast5, 3des 2016-08-19 11:15:13 +08:00
xtaci 6374cb0d36 Merge branch 'master' of https://github.com/xtaci/kcptun 2016-08-18 23:44:25 +08:00
xtaci 0aedc21c50 Revert "change default resend from 2 -> 3"
This reverts commit 003617186b.
2016-08-18 23:40:51 +08:00
xtaciandGitHub 727887517f Update README.en.md 2016-08-18 10:56:46 +08:00
xtaciandGitHub 7b81b24e8d Update README.md 2016-08-18 10:55:55 +08:00
xtaci ba22434379 experimental Bounds Checking Elimination 2016-08-18 09:51:17 +08:00
xtaci 003617186b change default resend from 2 -> 3 2016-08-17 21:07:27 +08:00
xtaciandGitHub b9ce27cb3e Update README.en.md 2016-08-17 11:33:53 +08:00
xtaciandGitHub c93a199823 Update README.md 2016-08-17 11:32:58 +08:00
xtaci bb34894947 upd issue 2016-08-17 11:26:35 +08:00
xtaci f743a075c5 upd 2016-08-17 11:22:09 +08:00
9 changed files with 443 additions and 216 deletions
+9 -8
View File
@@ -2,11 +2,12 @@ Before firing issue, make sure you figured out the following common questions.
PLEASE DO SEARCH FIRST.
1. Are you using the **latest release**?
2. Which **OS** do you use?
3. Which end for this issue related to, **client or server**?
4. Are you using the **same version** for both client & server
5. Did you correctly set the ***-target value, -t value target server address (default: "127.0.0.1:12948")*** on the server side?
6. Can ```telnet target port``` successful?
7. ```-nocomp, -datashard, -parityshard, -key, -crypt``` ***must be the same*** on both side.
8. Does your ***firewall allows UDP*** communications? (including your ISP Cable-Modem)
1. Check your ```-key xxx``` for at least 3 times, ***MAKE SURE*** both sides share the same secret.
2. ```-nocomp, -datashard, -parityshard, -key, -crypt``` ***must be the same*** on both side.
3. Did you correctly set the ***-target*** on the server side?
4. ***MAKE SURE*** ```telnet target port``` on your server successful(don't ask me why couldn't).
5. Does your ***firewall allows UDP*** communications? (including your ISP Cable-Modem)
6. Are you using the **same version** for both client & server
7. Are you using the **latest release**?
8. Which **OS** do you use?
9. Which end for this issue related to, **client or server**?
+1 -2
View File
@@ -3,7 +3,6 @@ MAINTAINER xtaci <daniel820313@gmail.com>
RUN apk update && \
apk upgrade && \
apk add git
RUN go get github.com/xtaci/kcptun/client
RUN go get github.com/xtaci/kcptun/server
RUN go get github.com/xtaci/kcptun/client && go get github.com/xtaci/kcptun/server
EXPOSE 29900/udp
EXPOSE 12948
+25 -18
View File
@@ -1,7 +1,7 @@
# <img src="logo.png" alt="kcptun" height="60px" />
[![GoDoc][1]][2] [![Release][13]][14] [![Powered][17]][18] [![MIT licensed][11]][12] [![Build Status][3]][4] [![Go Report Card][5]][6] [![Downloads][15]][16] [![Gitter][19]][20]
[1]: https://godoc.org/github.com/xtaci/kcptun?status.svg
[2]: https://godoc.org/github.com/xtaci/kcptun
[![Release][13]][14] [![Powered][17]][18] [![MIT licensed][11]][12] [![Build Status][3]][4] [![Go Report Card][5]][6] [![Downloads][15]][16] [![Gitter][19]][20] [![Docker][1]][2]
[1]: https://images.microbadger.com/badges/image/xtaci/kcptun.svg
[2]: https://microbadger.com/images/xtaci/kcptun
[3]: https://travis-ci.org/xtaci/kcptun.svg?branch=master
[4]: https://travis-ci.org/xtaci/kcptun
[5]: https://goreportcard.com/badge/github.com/xtaci/kcptun
@@ -40,6 +40,7 @@ Client Side: ./client_darwin_amd64 -r "SERVERIP:4000" -l ":1080" -mode fast2 //
* WIFI: 5GHz TL-WDR3320
### *Usage* :lollipop:
Help output under MacOS X:
```
$ ./client_darwin_amd64 -h
NAME:
@@ -49,7 +50,7 @@ USAGE:
client_darwin_amd64 [global options] command [command options] [arguments...]
VERSION:
20160811
20160820
COMMANDS:
help, h Shows a list of commands or help for one command
@@ -57,22 +58,21 @@ COMMANDS:
GLOBAL OPTIONS:
--localaddr value, -l value local listen address (default: ":12948")
--remoteaddr value, -r value kcp server address (default: "vps:29900")
--key value key for communcation, must be the same as kcptun server (default: "it's a secrect") [$KCPTUN_KEY]
--crypt value methods for encryption: aes, tea, xor, none (default: "aes")
--mode value mode for communication: fast3, fast2, fast, normal (default: "fast")
--conn value establish N physical connections as specified by 'conn' to server (default: 1)
--mtu value set MTU of UDP packets, suggest 'tracepath' to discover path mtu (default: 1350)
--key value pre-shared secret for client and server (default: "it's a secrect") [$KCPTUN_KEY]
--crypt value aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, none (default: "aes")
--mode value profiles: fast3, fast2, fast, normal (default: "fast")
--conn value set num of UDP connections to server (default: 1)
--mtu value set maximum transmission unit of UDP packets (default: 1350)
--sndwnd value set send window size(num of packets) (default: 128)
--rcvwnd value set receive window size(num of packets) (default: 1024)
--nocomp disable compression
--datashard value set reed-solomon erasure coding - datashard (default: 10)
--parityshard value set reed-solomon erasure coding - parityshard (default: 3)
--dscp value set DSCP(6bit) (default: 0)
--nocomp disable compression
--help, -h show help
--version, -v print the version
```
```
$ ./server_darwin_amd64 -h
NAME:
kcptun - kcptun server
@@ -81,7 +81,7 @@ USAGE:
server_darwin_amd64 [global options] command [command options] [arguments...]
VERSION:
20160811
20160820
COMMANDS:
help, h Shows a list of commands or help for one command
@@ -89,16 +89,16 @@ COMMANDS:
GLOBAL OPTIONS:
--listen value, -l value kcp server listen address (default: ":29900")
--target value, -t value target server address (default: "127.0.0.1:12948")
--key value key for communcation, must be the same as kcptun client (default: "it's a secrect") [$KCPTUN_KEY]
--crypt value methods for encryption: aes, tea, xor, none (default: "aes")
--mode value mode for communication: fast3, fast2, fast, normal (default: "fast")
--mtu value set MTU of UDP packets, suggest 'tracepath' to discover path mtu (default: 1350)
--key value pre-shared secret for client and server (default: "it's a secrect") [$KCPTUN_KEY]
--crypt value aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, none (default: "aes")
--mode value profiles: fast3, fast2, fast, normal (default: "fast")
--mtu value set maximum transmission unit of UDP packets (default: 1350)
--sndwnd value set send window size(num of packets) (default: 1024)
--rcvwnd value set receive window size(num of packets) (default: 1024)
--nocomp disable compression
--datashard value set reed-solomon erasure coding - datashard (default: 10)
--parityshard value set reed-solomon erasure coding - parityshard (default: 3)
--dscp value set DSCP(6bit) (default: 0)
--nocomp disable compression
--help, -h show help
--version, -v print the version
```
@@ -124,6 +124,12 @@ other parameters can be set independently.
***NOTICE: if too much retranmission happens, it's quite possible the windows are too large***
### *Security* :lollipop:
No matter what encryption you are using for application layer, if you specify ```-crypt none``` to kcptun,
the header will be ***PLAINTEXT*** to everyone; I suggest ```-crypt aes-128``` for encryption at least .
NOTICE: ```-crypt xor``` is also insecure, do not use this unless you know what you are doing.
### *Memory Control* :lollipop:
Routers, mobile devices are sensitive to memory consumption; by setting GOGC environment(eg: GOGC=20) will lower memory consumption.
Reference: https://blog.golang.org/go15gc
@@ -159,6 +165,7 @@ Manual control is supported with hidden parameters, you must understand KCP prot
```
-mode manual -nodelay 1 -resend 2 -nc 1 -interval 20
```
I suggest fast2 for high-loss network, normal for low-loss network.
### *Forward Error Correction* :lollipop:
In coding theory, the ReedSolomon code belongs to the class of non-binary cyclic error-correcting codes. The ReedSolomon code is based on univariate polynomials over finite fields.
+24 -19
View File
@@ -1,7 +1,7 @@
# <img src="logo.png" alt="kcptun" height="60px" />
[![GoDoc][1]][2] [![Release][13]][14] [![Powered][17]][18] [![MIT licensed][11]][12] [![Build Status][3]][4] [![Go Report Card][5]][6] [![Downloads][15]][16] [![Gitter][19]][20]
[1]: https://godoc.org/github.com/xtaci/kcptun?status.svg
[2]: https://godoc.org/github.com/xtaci/kcptun
[![Release][13]][14] [![Powered][17]][18] [![MIT licensed][11]][12] [![Build Status][3]][4] [![Go Report Card][5]][6] [![Downloads][15]][16] [![Gitter][19]][20] [![Docker][1]][2]
[1]: https://images.microbadger.com/badges/image/xtaci/kcptun.svg
[2]: https://microbadger.com/images/xtaci/kcptun
[3]: https://travis-ci.org/xtaci/kcptun.svg?branch=master
[4]: https://travis-ci.org/xtaci/kcptun
[5]: https://goreportcard.com/badge/github.com/xtaci/kcptun
@@ -47,7 +47,7 @@ USAGE:
client_darwin_amd64 [global options] command [command options] [arguments...]
VERSION:
20160811
20160820
COMMANDS:
help, h Shows a list of commands or help for one command
@@ -55,22 +55,21 @@ COMMANDS:
GLOBAL OPTIONS:
--localaddr value, -l value local listen address (default: ":12948")
--remoteaddr value, -r value kcp server address (default: "vps:29900")
--key value key for communcation, must be the same as kcptun server (default: "it's a secrect") [$KCPTUN_KEY]
--crypt value methods for encryption: aes, tea, xor, none (default: "aes")
--mode value mode for communication: fast3, fast2, fast, normal (default: "fast")
--conn value establish N physical connections as specified by 'conn' to server (default: 1)
--mtu value set MTU of UDP packets, suggest 'tracepath' to discover path mtu (default: 1350)
--key value pre-shared secret for client and server (default: "it's a secrect") [$KCPTUN_KEY]
--crypt value aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, none (default: "aes")
--mode value profiles: fast3, fast2, fast, normal (default: "fast")
--conn value set num of UDP connections to server (default: 1)
--mtu value set maximum transmission unit of UDP packets (default: 1350)
--sndwnd value set send window size(num of packets) (default: 128)
--rcvwnd value set receive window size(num of packets) (default: 1024)
--nocomp disable compression
--datashard value set reed-solomon erasure coding - datashard (default: 10)
--parityshard value set reed-solomon erasure coding - parityshard (default: 3)
--dscp value set DSCP(6bit) (default: 0)
--nocomp disable compression
--help, -h show help
--version, -v print the version
```
```
$ ./server_darwin_amd64 -h
NAME:
kcptun - kcptun server
@@ -79,7 +78,7 @@ USAGE:
server_darwin_amd64 [global options] command [command options] [arguments...]
VERSION:
20160811
20160820
COMMANDS:
help, h Shows a list of commands or help for one command
@@ -87,16 +86,16 @@ COMMANDS:
GLOBAL OPTIONS:
--listen value, -l value kcp server listen address (default: ":29900")
--target value, -t value target server address (default: "127.0.0.1:12948")
--key value key for communcation, must be the same as kcptun client (default: "it's a secrect") [$KCPTUN_KEY]
--crypt value methods for encryption: aes, tea, xor, none (default: "aes")
--mode value mode for communication: fast3, fast2, fast, normal (default: "fast")
--mtu value set MTU of UDP packets, suggest 'tracepath' to discover path mtu (default: 1350)
--key value pre-shared secret for client and server (default: "it's a secrect") [$KCPTUN_KEY]
--crypt value aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, none (default: "aes")
--mode value profiles: fast3, fast2, fast, normal (default: "fast")
--mtu value set maximum transmission unit of UDP packets (default: 1350)
--sndwnd value set send window size(num of packets) (default: 1024)
--rcvwnd value set receive window size(num of packets) (default: 1024)
--nocomp disable compression
--datashard value set reed-solomon erasure coding - datashard (default: 10)
--parityshard value set reed-solomon erasure coding - parityshard (default: 3)
--dscp value set DSCP(6bit) (default: 0)
--nocomp disable compression
--help, -h show help
--version, -v print the version
```
@@ -142,6 +141,11 @@ GLOBAL OPTIONS:
max_bandwidth_fec = max_bandwidth * (10 + 3) /10 = 1.3*max_bandwidth 1.3 * 25Mbps = 32.5Mbps
```
### *安全* :lollipop:
无论你上层如何加密,如果```-crypt none```,那么协议头部都是***明文***的,建议至少采用```-crypt aes-128```加密。
注意: ```-crypt xor``` 也是不安全的,除非你知道你在做什么。
### *内存控制* :lollipop:
路由器,手机等嵌入式设备通常对内存用量敏感,通过调节环境变量GOGC(例如GOGC=20)后启动client,可以降低内存使用。
参考:https://blog.golang.org/go15gc
@@ -201,6 +205,7 @@ DSCP差分服务代码点(Differentiated Services Code Point),IETF于1998
```
-mode manual -nodelay 1 -resend 2 -nc 1 -interval 20
```
高丢包率的网络建议采用fast2, 低丢包率的网络,建议采用normal。
### *SNMP* :lollipop:
```go
@@ -251,7 +256,7 @@ type Snmp struct {
对该项目的捐款将用于[gonet/2](http://gonet2.github.io/)游戏服务器框架的研发。
```特别感谢: 郑H立, 南D风, Li, 七q, 凌J,昶,Les*ables, Ky*n, 噼**啦, 等,名字已做特殊处理。```
```特别感谢: 郑H立, 南D风, Li, 七q, 凌J,昶,Les*ables, Ky*n, 噼**啦, *斌, 小苍** 等,名字已做特殊处理。```
### *参考资料* :paperclip:
1. https://github.com/skywind3000/kcp -- KCP - A Fast and Reliable ARQ Protocol.
+5 -4
View File
@@ -12,6 +12,7 @@ fi
VERSION=`date -u +%Y%m%d`
LDFLAGS="-X main.VERSION=$VERSION -s -w"
GCFLAGS="-B"
OSES=(linux darwin windows freebsd)
ARCHS=(amd64 386)
@@ -22,8 +23,8 @@ for os in ${OSES[@]}; do
then
suffix=".exe"
fi
env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -o client_${os}_${arch}${suffix} github.com/xtaci/kcptun/client
env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -o server_${os}_${arch}${suffix} github.com/xtaci/kcptun/server
env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o client_${os}_${arch}${suffix} github.com/xtaci/kcptun/client
env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o server_${os}_${arch}${suffix} github.com/xtaci/kcptun/server
if $UPX; then upx -9 client_${os}_${arch}${suffix} server_${os}_${arch}${suffix};fi
tar -zcf kcptun-${os}-${arch}-$VERSION.tar.gz client_${os}_${arch}${suffix} server_${os}_${arch}${suffix}
$MD5 kcptun-${os}-${arch}-$VERSION.tar.gz
@@ -33,8 +34,8 @@ done
# ARM
ARMS=(5 6 7)
for v in ${ARMS[@]}; do
env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=$v go build -ldflags "$LDFLAGS" -o client_linux_arm$v github.com/xtaci/kcptun/client
env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=$v go build -ldflags "$LDFLAGS" -o server_linux_arm$v github.com/xtaci/kcptun/server
env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=$v go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o client_linux_arm$v github.com/xtaci/kcptun/client
env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=$v go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o server_linux_arm$v github.com/xtaci/kcptun/server
done
if $UPX; then upx -9 client_linux_arm* server_linux_arm*;fi
tar -zcf kcptun-linux-arm-$VERSION.tar.gz client_linux_arm* server_linux_arm*
+41
View File
@@ -0,0 +1,41 @@
package main
import (
"encoding/json"
"os"
)
// Config for client
type Config struct {
LocalAddr string `json:"localaddr"`
RemoteAddr string `json:"remoteaddr"`
Key string `json:"key"`
Crypt string `json:"crypt"`
Mode string `json:"mode"`
Conn int `json:"conn"`
AutoExpire int `json:"autoexpire"`
MTU int `json:"mtu"`
SndWnd int `json:"sndwnd"`
RcvWnd int `json:"rcvwnd"`
DataShard int `json:"datashard"`
ParityShard int `json:"parityshard"`
DSCP int `json:"dscp"`
NoComp bool `json:"nocomp"`
AckNodelay bool `json:"acknodelay"`
NoDelay int `json:"nodelay"`
Interval int `json:"interval"`
Resend int `json:"resend"`
NoCongestion int `json:"nc"`
SockBuf int `json:"sockbuf"`
KeepAlive int `json:"keepalive"`
}
func parseJSONConfig(config *Config, path string) error {
file, err := os.Open(path) // For read access.
if err != nil {
return err
}
defer file.Close()
return json.NewDecoder(file).Decode(config)
}
+179 -87
View File
@@ -12,9 +12,9 @@ import (
"golang.org/x/crypto/pbkdf2"
"github.com/golang/snappy"
"github.com/hashicorp/yamux"
"github.com/urfave/cli"
kcp "github.com/xtaci/kcp-go"
"github.com/xtaci/smux"
)
var (
@@ -80,7 +80,7 @@ func handleClient(p1, p2 io.ReadWriteCloser) {
func checkError(err error) {
if err != nil {
log.Println(err)
log.Printf("%+v\n", err)
os.Exit(-1)
}
}
@@ -93,7 +93,7 @@ func main() {
}
myApp := cli.NewApp()
myApp.Name = "kcptun"
myApp.Usage = "kcptun client"
myApp.Usage = "client(with SMUX)"
myApp.Version = VERSION
myApp.Flags = []cli.Flag{
cli.StringFlag{
@@ -109,28 +109,33 @@ func main() {
cli.StringFlag{
Name: "key",
Value: "it's a secrect",
Usage: "key for communcation, must be the same as kcptun server",
Usage: "pre-shared secret between client and server",
EnvVar: "KCPTUN_KEY",
},
cli.StringFlag{
Name: "crypt",
Value: "aes",
Usage: "methods for encryption: aes, aes-128, aes-192, tea, xor, none",
Usage: "aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, none",
},
cli.StringFlag{
Name: "mode",
Value: "fast",
Usage: "mode for communication: fast3, fast2, fast, normal",
Usage: "profiles: fast3, fast2, fast, normal",
},
cli.IntFlag{
Name: "conn",
Value: 1,
Usage: "establish N physical connections as specified by 'conn' to server",
Usage: "set num of UDP connections to server",
},
cli.IntFlag{
Name: "autoexpire",
Value: 0,
Usage: "set auto expiration time(in seconds) for a single UDP connection, 0 to disable",
},
cli.IntFlag{
Name: "mtu",
Value: 1350,
Usage: "set MTU of UDP packets, suggest 'tracepath' to discover path mtu",
Usage: "set maximum transmission unit for UDP packets",
},
cli.IntFlag{
Name: "sndwnd",
@@ -142,10 +147,6 @@ func main() {
Value: 1024,
Usage: "set receive window size(num of packets)",
},
cli.BoolFlag{
Name: "nocomp",
Usage: "disable compression",
},
cli.IntFlag{
Name: "datashard",
Value: 10,
@@ -156,16 +157,20 @@ func main() {
Value: 3,
Usage: "set reed-solomon erasure coding - parityshard",
},
cli.BoolFlag{
Name: "acknodelay",
Usage: "flush ack immediately when a packet is received",
Hidden: true,
},
cli.IntFlag{
Name: "dscp",
Value: 0,
Usage: "set DSCP(6bit)",
},
cli.BoolFlag{
Name: "nocomp",
Usage: "disable compression",
},
cli.BoolFlag{
Name: "acknodelay",
Usage: "flush ack immediately when a packet is received",
Hidden: true,
},
cli.IntFlag{
Name: "nodelay",
Value: 0,
@@ -196,32 +201,61 @@ func main() {
Value: 10, // nat keepalive interval in seconds
Hidden: true,
},
cli.StringFlag{
Name: "c",
Value: "", // when the value is not empty, the config path must exists
Usage: "config from json file, which will override the command from shell",
},
}
myApp.Action = func(c *cli.Context) error {
config := Config{}
config.LocalAddr = c.String("localaddr")
config.RemoteAddr = c.String("remoteaddr")
config.Key = c.String("key")
config.Crypt = c.String("crypt")
config.Mode = c.String("mode")
config.Conn = c.Int("conn")
config.AutoExpire = c.Int("autoexpire")
config.MTU = c.Int("mtu")
config.SndWnd = c.Int("sndwnd")
config.RcvWnd = c.Int("rcvwnd")
config.DataShard = c.Int("datashard")
config.ParityShard = c.Int("parityshard")
config.DSCP = c.Int("dscp")
config.NoComp = c.Bool("nocomp")
config.AckNodelay = c.Bool("acknodelay")
config.NoDelay = c.Int("nodelay")
config.Interval = c.Int("interval")
config.Resend = c.Int("resend")
config.NoCongestion = c.Int("nc")
config.SockBuf = c.Int("sockbuf")
config.KeepAlive = c.Int("keepalive")
if c.String("c") != "" {
err := parseJSONConfig(&config, c.String("c"))
checkError(err)
}
switch config.Mode {
case "normal":
config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 30, 2, 1
case "fast":
config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 20, 2, 1
case "fast2":
config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 1, 20, 2, 1
case "fast3":
config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 1, 10, 2, 1
}
log.Println("version:", VERSION)
addr, err := net.ResolveTCPAddr("tcp", c.String("localaddr"))
addr, err := net.ResolveTCPAddr("tcp", config.LocalAddr)
checkError(err)
listener, err := net.ListenTCP("tcp", addr)
checkError(err)
// kcp server
nodelay, interval, resend, nc := c.Int("nodelay"), c.Int("interval"), c.Int("resend"), c.Int("nc")
switch c.String("mode") {
case "normal":
nodelay, interval, resend, nc = 0, 30, 2, 1
case "fast":
nodelay, interval, resend, nc = 0, 20, 2, 1
case "fast2":
nodelay, interval, resend, nc = 1, 20, 2, 1
case "fast3":
nodelay, interval, resend, nc = 1, 10, 2, 1
}
crypt := c.String("crypt")
pass := pbkdf2.Key([]byte(c.String("key")), []byte(SALT), 4096, 32, sha1.New)
pass := pbkdf2.Key([]byte(config.Key), []byte(SALT), 4096, 32, sha1.New)
var block kcp.BlockCrypt
switch c.String("crypt") {
switch config.Crypt {
case "tea":
block, _ = kcp.NewTEABlockCrypt(pass[:16])
case "xor":
@@ -232,87 +266,112 @@ func main() {
block, _ = kcp.NewAESBlockCrypt(pass[:16])
case "aes-192":
block, _ = kcp.NewAESBlockCrypt(pass[:24])
case "blowfish":
block, _ = kcp.NewBlowfishBlockCrypt(pass)
case "twofish":
block, _ = kcp.NewTwofishBlockCrypt(pass)
case "cast5":
block, _ = kcp.NewCast5BlockCrypt(pass[:16])
case "3des":
block, _ = kcp.NewTripleDESBlockCrypt(pass[:24])
case "xtea":
block, _ = kcp.NewXTEABlockCrypt(pass[:16])
case "salsa20":
block, _ = kcp.NewSalsa20BlockCrypt(pass)
default:
config.Crypt = "aes"
block, _ = kcp.NewAESBlockCrypt(pass)
}
remoteaddr := c.String("remoteaddr")
datashard, parityshard := c.Int("datashard"), c.Int("parityshard")
mtu, sndwnd, rcvwnd := c.Int("mtu"), c.Int("sndwnd"), c.Int("rcvwnd")
nocomp, acknodelay := c.Bool("nocomp"), c.Bool("acknodelay")
dscp, sockbuf, keepalive, conn := c.Int("dscp"), c.Int("sockbuf"), c.Int("keepalive"), c.Int("conn")
log.Println("listening on:", listener.Addr())
log.Println("encryption:", crypt)
log.Println("nodelay parameters:", nodelay, interval, resend, nc)
log.Println("remote address:", remoteaddr)
log.Println("sndwnd:", sndwnd, "rcvwnd:", rcvwnd)
log.Println("compression:", !nocomp)
log.Println("mtu:", mtu)
log.Println("datashard:", datashard, "parityshard:", parityshard)
log.Println("acknodelay:", acknodelay)
log.Println("dscp:", dscp)
log.Println("sockbuf:", sockbuf)
log.Println("keepalive:", keepalive)
log.Println("conn:", conn)
log.Println("encryption:", config.Crypt)
log.Println("nodelay parameters:", config.NoDelay, config.Interval, config.Resend, config.NoCongestion)
log.Println("remote address:", config.RemoteAddr)
log.Println("sndwnd:", config.SndWnd, "rcvwnd:", config.RcvWnd)
log.Println("compression:", !config.NoComp)
log.Println("mtu:", config.MTU)
log.Println("datashard:", config.DataShard, "parityshard:", config.ParityShard)
log.Println("acknodelay:", config.AckNodelay)
log.Println("dscp:", config.DSCP)
log.Println("sockbuf:", config.SockBuf)
log.Println("keepalive:", config.KeepAlive)
log.Println("conn:", config.Conn)
log.Println("autoexpire:", config.AutoExpire)
config := &yamux.Config{
AcceptBacklog: 256,
EnableKeepAlive: true,
KeepAliveInterval: 30 * time.Second,
ConnectionWriteTimeout: 30 * time.Second,
MaxStreamWindowSize: uint32(sockbuf),
LogOutput: os.Stderr,
}
createConn := func() *yamux.Session {
kcpconn, err := kcp.DialWithOptions(remoteaddr, block, datashard, parityshard)
smuxConfig := smux.DefaultConfig()
smuxConfig.MaxReceiveBuffer = config.SockBuf
createConn := func() *smux.Session {
kcpconn, err := kcp.DialWithOptions(config.RemoteAddr, block, config.DataShard, config.ParityShard)
checkError(err)
kcpconn.SetStreamMode(true)
kcpconn.SetNoDelay(nodelay, interval, resend, nc)
kcpconn.SetWindowSize(sndwnd, rcvwnd)
kcpconn.SetMtu(mtu)
kcpconn.SetACKNoDelay(acknodelay)
kcpconn.SetKeepAlive(keepalive)
kcpconn.SetNoDelay(config.NoDelay, config.Interval, config.Resend, config.NoCongestion)
kcpconn.SetWindowSize(config.SndWnd, config.RcvWnd)
kcpconn.SetMtu(config.MTU)
kcpconn.SetACKNoDelay(config.AckNodelay)
kcpconn.SetKeepAlive(config.KeepAlive)
if err := kcpconn.SetDSCP(dscp); err != nil {
if err := kcpconn.SetDSCP(config.DSCP); err != nil {
log.Println("SetDSCP:", err)
}
if err := kcpconn.SetReadBuffer(sockbuf); err != nil {
if err := kcpconn.SetReadBuffer(config.SockBuf); err != nil {
log.Println("SetReadBuffer:", err)
}
if err := kcpconn.SetWriteBuffer(sockbuf); err != nil {
if err := kcpconn.SetWriteBuffer(config.SockBuf); err != nil {
log.Println("SetWriteBuffer:", err)
}
// stream multiplex
var session *yamux.Session
if nocomp {
session, err = yamux.Client(kcpconn, config)
var session *smux.Session
if config.NoComp {
session, err = smux.Client(kcpconn, smuxConfig)
} else {
session, err = yamux.Client(newCompStream(kcpconn), config)
session, err = smux.Client(newCompStream(kcpconn), smuxConfig)
}
checkError(err)
return session
}
numconn := uint16(conn)
var muxes []*yamux.Session
for i := uint16(0); i < numconn; i++ {
muxes = append(muxes, createConn())
numconn := uint16(config.Conn)
muxes := make([]struct {
session *smux.Session
ttl time.Time
}, numconn)
for k := range muxes {
muxes[k].session = createConn()
muxes[k].ttl = time.Now().Add(time.Duration(config.AutoExpire) * time.Second)
}
chScavenger := make(chan *smux.Session, 128)
go scavenger(chScavenger)
rr := uint16(0)
for {
p1, err := listener.AcceptTCP()
if err := p1.SetReadBuffer(config.SockBuf); err != nil {
log.Println("TCP SetReadBuffer:", err)
}
if err := p1.SetWriteBuffer(config.SockBuf); err != nil {
log.Println("TCP SetWriteBuffer:", err)
}
checkError(err)
mux := muxes[rr%numconn]
p2, err := mux.Open()
if err != nil { // yamux failure
log.Println(err)
p1.Close()
muxes[rr%numconn] = createConn()
mux.Close()
continue
idx := rr % numconn
OPEN_P2:
// do auto expiration
if config.AutoExpire > 0 && time.Now().After(muxes[idx].ttl) {
chScavenger <- muxes[idx].session
muxes[idx].session = createConn()
muxes[idx].ttl = time.Now().Add(time.Duration(config.AutoExpire) * time.Second)
}
// do session open
p2, err := muxes[idx].session.OpenStream()
if err != nil { // mux failure
chScavenger <- muxes[idx].session
muxes[idx].session = createConn()
muxes[idx].ttl = time.Now().Add(time.Duration(config.AutoExpire) * time.Second)
goto OPEN_P2
}
go handleClient(p1, p2)
rr++
@@ -320,3 +379,36 @@ func main() {
}
myApp.Run(os.Args)
}
type scavengeSession struct {
session *smux.Session
ttl time.Time
}
const (
maxScavengeTTL = 10 * time.Minute
)
func scavenger(ch chan *smux.Session) {
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
var sessionList []scavengeSession
for {
select {
case sess := <-ch:
sessionList = append(sessionList, scavengeSession{sess, time.Now()})
case <-ticker.C:
var newList []scavengeSession
for k := range sessionList {
s := sessionList[k]
if s.session.NumStreams() == 0 || s.session.IsClosed() || time.Since(s.ttl) > maxScavengeTTL {
log.Println("session scavenged")
s.session.Close()
} else {
newList = append(newList, sessionList[k])
}
}
sessionList = newList
}
}
}
+39
View File
@@ -0,0 +1,39 @@
package main
import (
"encoding/json"
"os"
)
// Config for server
type Config struct {
Listen string `json:"listen"`
Target string `json:"target"`
Key string `json:"key"`
Crypt string `json:"crypt"`
Mode string `json:"mode"`
MTU int `json:"mtu"`
SndWnd int `json:"sndwnd"`
RcvWnd int `json:"rcvwnd"`
DataShard int `json:"datashard"`
ParityShard int `json:"parityshard"`
DSCP int `json:"dscp"`
NoComp bool `json:"nocomp"`
AckNodelay bool `json:"acknodelay"`
NoDelay int `json:"nodelay"`
Interval int `json:"interval"`
Resend int `json:"resend"`
NoCongestion int `json:"nc"`
SockBuf int `json:"sockbuf"`
KeepAlive int `json:"keepalive"`
}
func parseJSONConfig(config *Config, path string) error {
file, err := os.Open(path) // For read access.
if err != nil {
return err
}
defer file.Close()
return json.NewDecoder(file).Decode(config)
}
+120 -78
View File
@@ -12,9 +12,9 @@ import (
"golang.org/x/crypto/pbkdf2"
"github.com/golang/snappy"
"github.com/hashicorp/yamux"
"github.com/urfave/cli"
kcp "github.com/xtaci/kcp-go"
"github.com/xtaci/smux"
)
var (
@@ -53,25 +53,33 @@ func newCompStream(conn net.Conn) *compStream {
}
// handle multiplex-ed connection
func handleMux(conn io.ReadWriteCloser, target string, config *yamux.Config) {
func handleMux(conn io.ReadWriteCloser, config *Config) {
// stream multiplex
mux, err := yamux.Server(conn, config)
smuxConfig := smux.DefaultConfig()
smuxConfig.MaxReceiveBuffer = config.SockBuf
mux, err := smux.Server(conn, smuxConfig)
if err != nil {
log.Println(err)
return
}
defer mux.Close()
for {
p1, err := mux.Accept()
p1, err := mux.AcceptStream()
if err != nil {
log.Println(err)
return
}
p2, err := net.DialTimeout("tcp", target, 5*time.Second)
p2, err := net.DialTimeout("tcp", config.Target, 5*time.Second)
if err != nil {
p1.Close()
log.Println(err)
return
continue
}
if err := p2.(*net.TCPConn).SetReadBuffer(config.SockBuf); err != nil {
log.Println("TCP SetReadBuffer:", err)
}
if err := p2.(*net.TCPConn).SetWriteBuffer(config.SockBuf); err != nil {
log.Println("TCP SetWriteBuffer:", err)
}
go handleClient(p1, p2)
}
@@ -103,6 +111,13 @@ func handleClient(p1, p2 io.ReadWriteCloser) {
}
}
func checkError(err error) {
if err != nil {
log.Printf("%+v\n", err)
os.Exit(-1)
}
}
func main() {
rand.Seed(int64(time.Now().Nanosecond()))
if VERSION == "SELFBUILD" {
@@ -111,7 +126,7 @@ func main() {
}
myApp := cli.NewApp()
myApp.Name = "kcptun"
myApp.Usage = "kcptun server"
myApp.Usage = "server(with SMUX)"
myApp.Version = VERSION
myApp.Flags = []cli.Flag{
cli.StringFlag{
@@ -127,23 +142,23 @@ func main() {
cli.StringFlag{
Name: "key",
Value: "it's a secrect",
Usage: "key for communcation, must be the same as kcptun client",
Usage: "pre-shared secret between client and server",
EnvVar: "KCPTUN_KEY",
},
cli.StringFlag{
Name: "crypt",
Value: "aes",
Usage: "methods for encryption: aes, aes-128, aes-192, tea, xor, none",
Usage: "aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, none",
},
cli.StringFlag{
Name: "mode",
Value: "fast",
Usage: "mode for communication: fast3, fast2, fast, normal",
Usage: "profiles: fast3, fast2, fast, normal",
},
cli.IntFlag{
Name: "mtu",
Value: 1350,
Usage: "set MTU of UDP packets, suggest 'tracepath' to discover path mtu",
Usage: "set maximum transmission unit for UDP packets",
},
cli.IntFlag{
Name: "sndwnd",
@@ -155,10 +170,6 @@ func main() {
Value: 1024,
Usage: "set receive window size(num of packets)",
},
cli.BoolFlag{
Name: "nocomp",
Usage: "disable compression",
},
cli.IntFlag{
Name: "datashard",
Value: 10,
@@ -169,16 +180,20 @@ func main() {
Value: 3,
Usage: "set reed-solomon erasure coding - parityshard",
},
cli.BoolFlag{
Name: "acknodelay",
Usage: "flush ack immediately when a packet is received",
Hidden: true,
},
cli.IntFlag{
Name: "dscp",
Value: 0,
Usage: "set DSCP(6bit)",
},
cli.BoolFlag{
Name: "nocomp",
Usage: "disable compression",
},
cli.BoolFlag{
Name: "acknodelay",
Usage: "flush ack immediately when a packet is received",
Hidden: true,
},
cli.IntFlag{
Name: "nodelay",
Value: 0,
@@ -209,25 +224,55 @@ func main() {
Value: 10, // nat keepalive interval in seconds
Hidden: true,
},
cli.StringFlag{
Name: "c",
Value: "", // when the value is not empty, the config path must exists
Usage: "config from json file, which will override the command from shell",
},
}
myApp.Action = func(c *cli.Context) error {
log.Println("version:", VERSION)
nodelay, interval, resend, nc := c.Int("nodelay"), c.Int("interval"), c.Int("resend"), c.Int("nc")
switch c.String("mode") {
case "normal":
nodelay, interval, resend, nc = 0, 30, 2, 1
case "fast":
nodelay, interval, resend, nc = 0, 20, 2, 1
case "fast2":
nodelay, interval, resend, nc = 1, 20, 2, 1
case "fast3":
nodelay, interval, resend, nc = 1, 10, 2, 1
config := Config{}
config.Listen = c.String("listen")
config.Target = c.String("target")
config.Key = c.String("key")
config.Crypt = c.String("crypt")
config.Mode = c.String("mode")
config.MTU = c.Int("mtu")
config.SndWnd = c.Int("sndwnd")
config.RcvWnd = c.Int("rcvwnd")
config.DataShard = c.Int("datashard")
config.ParityShard = c.Int("parityshard")
config.DSCP = c.Int("dscp")
config.NoComp = c.Bool("nocomp")
config.AckNodelay = c.Bool("acknodelay")
config.NoDelay = c.Int("nodelay")
config.Interval = c.Int("interval")
config.Resend = c.Int("resend")
config.NoCongestion = c.Int("nc")
config.SockBuf = c.Int("sockbuf")
config.KeepAlive = c.Int("keepalive")
if c.String("c") != "" {
//Now only support json config file
err := parseJSONConfig(&config, c.String("c"))
checkError(err)
}
crypt := c.String("crypt")
pass := pbkdf2.Key([]byte(c.String("key")), []byte(SALT), 4096, 32, sha1.New)
switch config.Mode {
case "normal":
config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 30, 2, 1
case "fast":
config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 20, 2, 1
case "fast2":
config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 1, 20, 2, 1
case "fast3":
config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 1, 10, 2, 1
}
log.Println("version:", VERSION)
pass := pbkdf2.Key([]byte(config.Key), []byte(SALT), 4096, 32, sha1.New)
var block kcp.BlockCrypt
switch crypt {
switch config.Crypt {
case "tea":
block, _ = kcp.NewTEABlockCrypt(pass[:16])
case "xor":
@@ -238,67 +283,64 @@ func main() {
block, _ = kcp.NewAESBlockCrypt(pass[:16])
case "aes-192":
block, _ = kcp.NewAESBlockCrypt(pass[:24])
case "blowfish":
block, _ = kcp.NewBlowfishBlockCrypt(pass)
case "twofish":
block, _ = kcp.NewTwofishBlockCrypt(pass)
case "cast5":
block, _ = kcp.NewCast5BlockCrypt(pass[:16])
case "3des":
block, _ = kcp.NewTripleDESBlockCrypt(pass[:24])
case "xtea":
block, _ = kcp.NewXTEABlockCrypt(pass[:16])
case "salsa20":
block, _ = kcp.NewSalsa20BlockCrypt(pass)
default:
config.Crypt = "aes"
block, _ = kcp.NewAESBlockCrypt(pass)
}
datashard, parityshard := c.Int("datashard"), c.Int("parityshard")
lis, err := kcp.ListenWithOptions(c.String("listen"), block, datashard, parityshard)
if err != nil {
log.Fatal(err)
}
lis, err := kcp.ListenWithOptions(config.Listen, block, config.DataShard, config.ParityShard)
checkError(err)
log.Println("listening on:", lis.Addr())
log.Println("target:", config.Target)
log.Println("encryption:", config.Crypt)
log.Println("nodelay parameters:", config.NoDelay, config.Interval, config.Resend, config.NoCongestion)
log.Println("sndwnd:", config.SndWnd, "rcvwnd:", config.RcvWnd)
log.Println("compression:", !config.NoComp)
log.Println("mtu:", config.MTU)
log.Println("datashard:", config.DataShard, "parityshard:", config.ParityShard)
log.Println("acknodelay:", config.AckNodelay)
log.Println("dscp:", config.DSCP)
log.Println("sockbuf:", config.SockBuf)
log.Println("keepalive:", config.KeepAlive)
mtu, sndwnd, rcvwnd := c.Int("mtu"), c.Int("sndwnd"), c.Int("rcvwnd")
nocomp, acknodelay := c.Bool("nocomp"), c.Bool("acknodelay")
dscp, sockbuf, keepalive := c.Int("dscp"), c.Int("sockbuf"), c.Int("keepalive")
target := c.String("target")
log.Println("listening on ", lis.Addr())
log.Println("encryption:", crypt)
log.Println("nodelay parameters:", nodelay, interval, resend, nc)
log.Println("sndwnd:", sndwnd, "rcvwnd:", rcvwnd)
log.Println("compression:", !nocomp)
log.Println("mtu:", mtu)
log.Println("datashard:", datashard, "parityshard:", parityshard)
log.Println("acknodelay:", acknodelay)
log.Println("dscp:", dscp)
log.Println("sockbuf:", sockbuf)
log.Println("keepalive:", keepalive)
if err := lis.SetDSCP(dscp); err != nil {
if err := lis.SetDSCP(config.DSCP); err != nil {
log.Println("SetDSCP:", err)
}
if err := lis.SetReadBuffer(sockbuf); err != nil {
if err := lis.SetReadBuffer(config.SockBuf); err != nil {
log.Println("SetReadBuffer:", err)
}
if err := lis.SetWriteBuffer(sockbuf); err != nil {
if err := lis.SetWriteBuffer(config.SockBuf); err != nil {
log.Println("SetWriteBuffer:", err)
}
config := &yamux.Config{
AcceptBacklog: 256,
EnableKeepAlive: true,
KeepAliveInterval: 30 * time.Second,
ConnectionWriteTimeout: 30 * time.Second,
MaxStreamWindowSize: uint32(sockbuf),
LogOutput: os.Stderr,
}
for {
if conn, err := lis.Accept(); err == nil {
if conn, err := lis.AcceptKCP(); err == nil {
log.Println("remote address:", conn.RemoteAddr())
conn.SetStreamMode(true)
conn.SetNoDelay(nodelay, interval, resend, nc)
conn.SetMtu(mtu)
conn.SetWindowSize(sndwnd, rcvwnd)
conn.SetACKNoDelay(acknodelay)
conn.SetKeepAlive(keepalive)
conn.SetNoDelay(config.NoDelay, config.Interval, config.Resend, config.NoCongestion)
conn.SetMtu(config.MTU)
conn.SetWindowSize(config.SndWnd, config.RcvWnd)
conn.SetACKNoDelay(config.AckNodelay)
conn.SetKeepAlive(config.KeepAlive)
if nocomp {
go handleMux(conn, target, config)
if config.NoComp {
go handleMux(conn, &config)
} else {
go handleMux(newCompStream(conn), target, config)
go handleMux(newCompStream(conn), &config)
}
} else {
log.Println(err)
log.Printf("%+v", err)
}
}
}