Compare commits

..
6 Commits
4 changed files with 59 additions and 23 deletions
+1
View File
@@ -28,6 +28,7 @@ type Config struct {
NoCongestion int `json:"nc"`
SockBuf int `json:"sockbuf"`
KeepAlive int `json:"keepalive"`
Log string `json:"log"`
}
func parseJSONConfig(config *Config, path string) error {
+41 -15
View File
@@ -12,6 +12,7 @@ import (
"golang.org/x/crypto/pbkdf2"
"github.com/golang/snappy"
"github.com/pkg/errors"
"github.com/urfave/cli"
kcp "github.com/xtaci/kcp-go"
"github.com/xtaci/smux"
@@ -60,16 +61,10 @@ func handleClient(p1, p2 io.ReadWriteCloser) {
// start tunnel
p1die := make(chan struct{})
go func() {
io.Copy(p1, p2)
close(p1die)
}()
go func() { io.Copy(p1, p2); close(p1die) }()
p2die := make(chan struct{})
go func() {
io.Copy(p2, p1)
close(p2die)
}()
go func() { io.Copy(p2, p1); close(p2die) }()
// wait for tunnel termination
select {
@@ -201,6 +196,11 @@ func main() {
Value: 10, // nat keepalive interval in seconds
Hidden: true,
},
cli.StringFlag{
Name: "log",
Value: "",
Usage: "specify a log file to output, default goes to stderr",
},
cli.StringFlag{
Name: "c",
Value: "", // when the value is not empty, the config path must exists
@@ -230,12 +230,21 @@ func main() {
config.NoCongestion = c.Int("nc")
config.SockBuf = c.Int("sockbuf")
config.KeepAlive = c.Int("keepalive")
config.Log = c.String("log")
if c.String("c") != "" {
err := parseJSONConfig(&config, c.String("c"))
checkError(err)
}
// log redirect
if config.Log != "" {
f, err := os.OpenFile(config.Log, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
checkError(err)
defer f.Close()
log.SetOutput(f)
}
switch config.Mode {
case "normal":
config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 30, 2, 1
@@ -301,9 +310,11 @@ func main() {
smuxConfig := smux.DefaultConfig()
smuxConfig.MaxReceiveBuffer = config.SockBuf
createConn := func() *smux.Session {
createConn := func() (*smux.Session, error) {
kcpconn, err := kcp.DialWithOptions(config.RemoteAddr, block, config.DataShard, config.ParityShard)
checkError(err)
if err != nil {
return nil, errors.Wrap(err, "createConn()")
}
kcpconn.SetStreamMode(true)
kcpconn.SetNoDelay(config.NoDelay, config.Interval, config.Resend, config.NoCongestion)
kcpconn.SetWindowSize(config.SndWnd, config.RcvWnd)
@@ -328,8 +339,21 @@ func main() {
} else {
session, err = smux.Client(newCompStream(kcpconn), smuxConfig)
}
checkError(err)
return session
if err != nil {
return nil, errors.Wrap(err, "createConn()")
}
return session, nil
}
// wait until a connection is ready
waitConn := func() *smux.Session {
for {
if session, err := createConn(); err == nil {
return session
} else {
time.Sleep(time.Second)
}
}
}
numconn := uint16(config.Conn)
@@ -339,7 +363,9 @@ func main() {
}, numconn)
for k := range muxes {
muxes[k].session = createConn()
sess, err := createConn()
checkError(err)
muxes[k].session = sess
muxes[k].ttl = time.Now().Add(time.Duration(config.AutoExpire) * time.Second)
}
@@ -361,7 +387,7 @@ func main() {
// do auto expiration
if config.AutoExpire > 0 && time.Now().After(muxes[idx].ttl) {
chScavenger <- muxes[idx].session
muxes[idx].session = createConn()
muxes[idx].session = waitConn()
muxes[idx].ttl = time.Now().Add(time.Duration(config.AutoExpire) * time.Second)
}
@@ -369,7 +395,7 @@ func main() {
p2, err := muxes[idx].session.OpenStream()
if err != nil { // mux failure
chScavenger <- muxes[idx].session
muxes[idx].session = createConn()
muxes[idx].session = waitConn()
muxes[idx].ttl = time.Now().Add(time.Duration(config.AutoExpire) * time.Second)
goto OPEN_P2
}
+1
View File
@@ -26,6 +26,7 @@ type Config struct {
NoCongestion int `json:"nc"`
SockBuf int `json:"sockbuf"`
KeepAlive int `json:"keepalive"`
Log string `json:"log"`
}
func parseJSONConfig(config *Config, path string) error {
+16 -8
View File
@@ -93,16 +93,10 @@ func handleClient(p1, p2 io.ReadWriteCloser) {
// start tunnel
p1die := make(chan struct{})
go func() {
io.Copy(p1, p2)
close(p1die)
}()
go func() { io.Copy(p1, p2); close(p1die) }()
p2die := make(chan struct{})
go func() {
io.Copy(p2, p1)
close(p2die)
}()
go func() { io.Copy(p2, p1); close(p2die) }()
// wait for tunnel termination
select {
@@ -224,6 +218,11 @@ func main() {
Value: 10, // nat keepalive interval in seconds
Hidden: true,
},
cli.StringFlag{
Name: "log",
Value: "",
Usage: "specify a log file to output, default goes to stderr",
},
cli.StringFlag{
Name: "c",
Value: "", // when the value is not empty, the config path must exists
@@ -251,6 +250,7 @@ func main() {
config.NoCongestion = c.Int("nc")
config.SockBuf = c.Int("sockbuf")
config.KeepAlive = c.Int("keepalive")
config.Log = c.String("log")
if c.String("c") != "" {
//Now only support json config file
@@ -258,6 +258,14 @@ func main() {
checkError(err)
}
// log redirect
if config.Log != "" {
f, err := os.OpenFile(config.Log, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
checkError(err)
defer f.Close()
log.SetOutput(f)
}
switch config.Mode {
case "normal":
config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 30, 2, 1