Make DialTimeout configurable.

This commit is contained in:
NI
2019-08-12 23:50:24 +08:00
parent db633f59bd
commit f3336d61a0
17 changed files with 173 additions and 119 deletions

View File

@@ -36,6 +36,7 @@ RUN set -ex && \
FROM alpine:latest FROM alpine:latest
ENV SSHWIFTY_HOSTNAME= \ ENV SSHWIFTY_HOSTNAME= \
SSHWIFTY_SHAREDKEY= \ SSHWIFTY_SHAREDKEY= \
SSHWIFTY_DIALTIMEOUT=10 \
SSHWIFTY_SOCKS5= \ SSHWIFTY_SOCKS5= \
SSHWIFTY_SOCKS5_USER= \ SSHWIFTY_SOCKS5_USER= \
SSHWIFTY_SOCKS5_PASSWORD= \ SSHWIFTY_SOCKS5_PASSWORD= \

View File

@@ -114,6 +114,12 @@ Here is the options that can be used in a configuration file and what it for:
// Web interface access password. Set to empty to allow public access // Web interface access password. Set to empty to allow public access
"SharedKey": "WEB_ACCESS_PASSWORD", "SharedKey": "WEB_ACCESS_PASSWORD",
// Remote dial timeout. This limits how long of time the backend can spend
// to connect to a remote host. The max timeout will be determined by
// server configuration (ReadTimeout).
// (In Second)
"DialTimeout": 10,
// Socks5 proxy. When set, we will try to connect remote through the given // Socks5 proxy. When set, we will try to connect remote through the given
// proxy // proxy
"Socks5": "localhost:1080", "Socks5": "localhost:1080",
@@ -136,23 +142,29 @@ Here is the options that can be used in a configuration file and what it for:
// Timeout of initial request. HTTP handshake must be finished within // Timeout of initial request. HTTP handshake must be finished within
// this time // this time
// (In Second)
"InitialTimeout": 3, "InitialTimeout": 3,
// How long the connection can be idle before the server disconnects the // How long the connection can be idle before the server disconnects the
// client // client
// (In Second)
"ReadTimeout": 60, "ReadTimeout": 60,
// How long the server will wait until the client connect is ready to // How long the server will wait until the client connect is ready to
// recieve new data // recieve new data
// (In Second)
"WriteTimeout": 60, "WriteTimeout": 60,
// The interval between internal echo requests // The interval between internal echo requests
// (In Second)
"HeartbeatTimeout": 20, "HeartbeatTimeout": 20,
// Forced delay between each request // Forced delay between each request
// (In Milisecond)
"ReadDelay": 10, "ReadDelay": 10,
// Forced delay between each write // Forced delay between each write
// (In Milisecond)
"WriteDelay": 10, "WriteDelay": 10,
// Path to TLS certificate file. Set empty to use HTTP // Path to TLS certificate file. Set empty to use HTTP

View File

@@ -27,6 +27,12 @@ import (
"github.com/niruix/sshwifty/application/rw" "github.com/niruix/sshwifty/application/rw"
) )
// CommandConfiguration contains configuration data needed to run command
type CommandConfiguration struct {
Dial network.Dial
DialTimeout time.Duration
}
// Commander command control // Commander command control
type Commander struct { type Commander struct {
commands Commands commands Commands
@@ -41,7 +47,7 @@ func New(cs Commands) Commander {
// New Adds a new client // New Adds a new client
func (c Commander) New( func (c Commander) New(
dialer network.Dial, cfg CommandConfiguration,
receiver rw.FetchReader, receiver rw.FetchReader,
sender io.Writer, sender io.Writer,
senderLock *sync.Mutex, senderLock *sync.Mutex,
@@ -50,7 +56,7 @@ func (c Commander) New(
l log.Logger, l log.Logger,
) (Handler, error) { ) (Handler, error) {
return newHandler( return newHandler(
dialer, cfg,
&c.commands, &c.commands,
receiver, receiver,
sender, sender,

View File

@@ -22,7 +22,6 @@ import (
"fmt" "fmt"
"github.com/niruix/sshwifty/application/log" "github.com/niruix/sshwifty/application/log"
"github.com/niruix/sshwifty/application/network"
) )
// Consts // Consts
@@ -37,7 +36,11 @@ var (
) )
// Command represents a command handler machine builder // Command represents a command handler machine builder
type Command func(l log.Logger, w StreamResponder, d network.Dial) FSMMachine type Command func(
l log.Logger,
w StreamResponder,
cfg CommandConfiguration,
) FSMMachine
// Commands contains data of all commands // Commands contains data of all commands
type Commands [MaxCommandID + 1]Command type Commands [MaxCommandID + 1]Command
@@ -57,7 +60,10 @@ func (c *Commands) Register(id byte, cb Command) {
// Run creates command executer // Run creates command executer
func (c Commands) Run( func (c Commands) Run(
id byte, l log.Logger, w StreamResponder, dial network.Dial) (FSM, error) { id byte,
l log.Logger,
w StreamResponder,
cfg CommandConfiguration) (FSM, error) {
if id > MaxCommandID { if id > MaxCommandID {
return FSM{}, ErrCommandRunUndefinedCommand return FSM{}, ErrCommandRunUndefinedCommand
} }
@@ -68,5 +74,5 @@ func (c Commands) Run(
return FSM{}, ErrCommandRunUndefinedCommand return FSM{}, ErrCommandRunUndefinedCommand
} }
return newFSM(cc(l, w, dial)), nil return newFSM(cc(l, w, cfg)), nil
} }

View File

@@ -25,7 +25,6 @@ import (
"time" "time"
"github.com/niruix/sshwifty/application/log" "github.com/niruix/sshwifty/application/log"
"github.com/niruix/sshwifty/application/network"
"github.com/niruix/sshwifty/application/rw" "github.com/niruix/sshwifty/application/rw"
) )
@@ -105,7 +104,7 @@ func (h streamHandlerSender) Write(b []byte) (int, error) {
// Handler client stream control // Handler client stream control
type Handler struct { type Handler struct {
dialer network.Dial cfg CommandConfiguration
commands *Commands commands *Commands
receiver rw.FetchReader receiver rw.FetchReader
sender handlerSender sender handlerSender
@@ -118,7 +117,7 @@ type Handler struct {
} }
func newHandler( func newHandler(
dialer network.Dial, cfg CommandConfiguration,
commands *Commands, commands *Commands,
receiver rw.FetchReader, receiver rw.FetchReader,
sender io.Writer, sender io.Writer,
@@ -128,7 +127,7 @@ func newHandler(
l log.Logger, l log.Logger,
) Handler { ) Handler {
return Handler{ return Handler{
dialer: dialer, cfg: cfg,
commands: commands, commands: commands,
receiver: receiver, receiver: receiver,
sender: handlerSender{writer: sender, lock: senderLock}, sender: handlerSender{writer: sender, lock: senderLock},
@@ -235,7 +234,7 @@ func (e *Handler) handleStream(h Header, d byte, l log.Logger) error {
return st.reinit(h, &e.receiver, streamHandlerSender{ return st.reinit(h, &e.receiver, streamHandlerSender{
handlerSender: &e.sender, handlerSender: &e.sender,
sendDelay: e.sendDelay, sendDelay: e.sendDelay,
}, l, e.commands, e.dialer, e.rBuf[:]) }, l, e.commands, e.cfg, e.rBuf[:])
} }
func (e *Handler) handleClose(h Header, d byte, l log.Logger) error { func (e *Handler) handleClose(h Header, d byte, l log.Logger) error {

View File

@@ -78,7 +78,7 @@ func TestHandlerHandleEcho(t *testing.T) {
} }
lock := sync.Mutex{} lock := sync.Mutex{}
handler := newHandler( handler := newHandler(
nil, CommandConfiguration{},
nil, nil,
rw.NewFetchReader(testDummyFetchGen(s)), rw.NewFetchReader(testDummyFetchGen(s)),
&w, &w,

View File

@@ -25,7 +25,6 @@ import (
"testing" "testing"
"github.com/niruix/sshwifty/application/log" "github.com/niruix/sshwifty/application/log"
"github.com/niruix/sshwifty/application/network"
"github.com/niruix/sshwifty/application/rw" "github.com/niruix/sshwifty/application/rw"
) )
@@ -58,7 +57,7 @@ func testDummyFetchChainGen(dd <-chan []byte) rw.FetchReaderFetcher {
} }
type dummyStreamCommand struct { type dummyStreamCommand struct {
lock sync.Mutex lock sync.Mutex
l log.Logger l log.Logger
w StreamResponder w StreamResponder
downWait sync.WaitGroup downWait sync.WaitGroup
@@ -67,9 +66,12 @@ type dummyStreamCommand struct {
} }
func newDummyStreamCommand( func newDummyStreamCommand(
l log.Logger, w StreamResponder, d network.Dial) FSMMachine { l log.Logger,
w StreamResponder,
cfg CommandConfiguration,
) FSMMachine {
return &dummyStreamCommand{ return &dummyStreamCommand{
lock:sync.Mutex{}, lock: sync.Mutex{},
l: l, l: l,
w: w, w: w,
downWait: sync.WaitGroup{}, downWait: sync.WaitGroup{},
@@ -84,7 +86,7 @@ func (d *dummyStreamCommand) Bootup(
) (FSMState, FSMError) { ) (FSMState, FSMError) {
d.downWait.Add(1) d.downWait.Add(1)
echoTrans:=d.echoTrans echoTrans := d.echoTrans
go func() { go func() {
defer func() { defer func() {
@@ -178,7 +180,7 @@ func TestHandlerHandleStream(t *testing.T) {
lock := sync.Mutex{} lock := sync.Mutex{}
hhd := newHandler( hhd := newHandler(
nil, CommandConfiguration{},
&cmds, &cmds,
rw.NewFetchReader(readerSource), rw.NewFetchReader(readerSource),
wBuffer, wBuffer,

View File

@@ -22,7 +22,6 @@ import (
"io" "io"
"github.com/niruix/sshwifty/application/log" "github.com/niruix/sshwifty/application/log"
"github.com/niruix/sshwifty/application/network"
"github.com/niruix/sshwifty/application/rw" "github.com/niruix/sshwifty/application/rw"
) )
@@ -342,7 +341,7 @@ func (c *stream) reinit(
w streamHandlerSender, w streamHandlerSender,
l log.Logger, l log.Logger,
cc *Commands, cc *Commands,
dialer network.Dial, cfg CommandConfiguration,
b []byte, b []byte,
) error { ) error {
hd := streamInitialHeader{} hd := streamInitialHeader{}
@@ -355,7 +354,8 @@ func (c *stream) reinit(
l = l.Context("Command (%d)", hd.command()) l = l.Context("Command (%d)", hd.command())
ccc, cccErr := cc.Run(hd.command(), l, newStreamResponder(w, h), dialer) ccc, cccErr := cc.Run(
hd.command(), l, newStreamResponder(w, h), cfg)
if cccErr != nil { if cccErr != nil {
hd.set(0, uint16(StreamErrorCommandUndefined), false) hd.set(0, uint16(StreamErrorCommandUndefined), false)

View File

@@ -22,13 +22,11 @@ import (
"io" "io"
"net" "net"
"sync" "sync"
"time"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
"github.com/niruix/sshwifty/application/command" "github.com/niruix/sshwifty/application/command"
"github.com/niruix/sshwifty/application/log" "github.com/niruix/sshwifty/application/log"
"github.com/niruix/sshwifty/application/network"
"github.com/niruix/sshwifty/application/rw" "github.com/niruix/sshwifty/application/rw"
) )
@@ -116,8 +114,7 @@ func (s sshRemoteConn) isValid() bool {
type sshClient struct { type sshClient struct {
w command.StreamResponder w command.StreamResponder
l log.Logger l log.Logger
dial network.Dial cfg command.CommandConfiguration
dialTimeout time.Duration
remoteCloseWait sync.WaitGroup remoteCloseWait sync.WaitGroup
credentialReceive chan []byte credentialReceive chan []byte
credentialProcessed bool credentialProcessed bool
@@ -132,13 +129,12 @@ type sshClient struct {
func newSSH( func newSSH(
l log.Logger, l log.Logger,
w command.StreamResponder, w command.StreamResponder,
dial network.Dial, cfg command.CommandConfiguration,
) command.FSMMachine { ) command.FSMMachine {
return &sshClient{ return &sshClient{
w: w, w: w,
l: l, l: l,
dial: dial, cfg: cfg,
dialTimeout: 10 * time.Second,
remoteCloseWait: sync.WaitGroup{}, remoteCloseWait: sync.WaitGroup{},
credentialReceive: make(chan []byte, 1), credentialReceive: make(chan []byte, 1),
credentialProcessed: false, credentialProcessed: false,
@@ -300,7 +296,7 @@ func (d *sshClient) comfirmRemoteFingerprint(
func (d *sshClient) dialRemote( func (d *sshClient) dialRemote(
network, addr string, config *ssh.ClientConfig) (*ssh.Client, error) { network, addr string, config *ssh.ClientConfig) (*ssh.Client, error) {
conn, err := d.dial(network, addr, config.Timeout) conn, err := d.cfg.Dial(network, addr, config.Timeout)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -332,7 +328,7 @@ func (d *sshClient) remote(
HostKeyCallback: func(h string, r net.Addr, k ssh.PublicKey) error { HostKeyCallback: func(h string, r net.Addr, k ssh.PublicKey) error {
return d.comfirmRemoteFingerprint(h, r, k, buf[:]) return d.comfirmRemoteFingerprint(h, r, k, buf[:])
}, },
Timeout: d.dialTimeout, Timeout: d.cfg.DialTimeout,
}) })
if dErr != nil { if dErr != nil {

View File

@@ -21,11 +21,9 @@ import (
"errors" "errors"
"io" "io"
"sync" "sync"
"time"
"github.com/niruix/sshwifty/application/command" "github.com/niruix/sshwifty/application/command"
"github.com/niruix/sshwifty/application/log" "github.com/niruix/sshwifty/application/log"
"github.com/niruix/sshwifty/application/network"
"github.com/niruix/sshwifty/application/rw" "github.com/niruix/sshwifty/application/rw"
) )
@@ -48,28 +46,26 @@ const (
) )
type telnetClient struct { type telnetClient struct {
l log.Logger l log.Logger
w command.StreamResponder w command.StreamResponder
dial network.Dial cfg command.CommandConfiguration
remoteChan chan io.WriteCloser remoteChan chan io.WriteCloser
remoteConn io.WriteCloser remoteConn io.WriteCloser
closeWait sync.WaitGroup closeWait sync.WaitGroup
dialTimeout time.Duration
} }
func newTelnet( func newTelnet(
l log.Logger, l log.Logger,
w command.StreamResponder, w command.StreamResponder,
dial network.Dial, cfg command.CommandConfiguration,
) command.FSMMachine { ) command.FSMMachine {
return &telnetClient{ return &telnetClient{
l: l, l: l,
w: w, w: w,
dial: dial, cfg: cfg,
remoteChan: make(chan io.WriteCloser, 1), remoteChan: make(chan io.WriteCloser, 1),
remoteConn: nil, remoteConn: nil,
closeWait: sync.WaitGroup{}, closeWait: sync.WaitGroup{},
dialTimeout: 10 * time.Second,
} }
} }
@@ -101,7 +97,7 @@ func (d *telnetClient) remote(addr string) {
buf := [4096]byte{} buf := [4096]byte{}
clientConn, clientConnErr := d.dial("tcp", addr, d.dialTimeout) clientConn, clientConnErr := d.cfg.Dial("tcp", addr, d.cfg.DialTimeout)
if clientConnErr != nil { if clientConnErr != nil {
errLen := copy( errLen := copy(

View File

@@ -121,17 +121,19 @@ func (s Server) Verify() error {
// Configuration contains configuration of the application // Configuration contains configuration of the application
type Configuration struct { type Configuration struct {
HostName string HostName string
SharedKey string SharedKey string
Dialer network.Dial Dialer network.Dial
Servers []Server DialTimeout time.Duration
Servers []Server
} }
// Common settings shared by mulitple servers // Common settings shared by mulitple servers
type Common struct { type Common struct {
HostName string HostName string
SharedKey string SharedKey string
Dialer network.Dial Dialer network.Dial
DialTimeout time.Duration
} }
// Verify verifies current setting // Verify verifies current setting
@@ -155,24 +157,31 @@ func (c Configuration) Verify() error {
// Common returns common settings // Common returns common settings
func (c Configuration) Common() Common { func (c Configuration) Common() Common {
return Common{
HostName: c.HostName,
SharedKey: c.SharedKey,
Dialer: c.Dialer,
}
}
// WithDefault build the configuration and fill the blank with default values
func (c Common) WithDefault() Common {
dialer := c.Dialer dialer := c.Dialer
if dialer == nil { if dialer == nil {
dialer = network.TCPDial() dialer = network.TCPDial()
} }
dialTimeout := c.DialTimeout
if dialTimeout <= 1*time.Second {
dialTimeout = 1 * time.Second
}
return Common{ return Common{
HostName: c.HostName, HostName: c.HostName,
SharedKey: c.SharedKey, SharedKey: c.SharedKey,
Dialer: dialer, Dialer: c.Dialer,
DialTimeout: c.DialTimeout,
} }
} }
// DecideDialTimeout will return a reasonable timeout for dialing
func (c Common) DecideDialTimeout(max time.Duration) time.Duration {
if c.DialTimeout > max {
return max
}
return c.DialTimeout
}

View File

@@ -22,9 +22,9 @@ import (
"os" "os"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/niruix/sshwifty/application/log" "github.com/niruix/sshwifty/application/log"
"github.com/niruix/sshwifty/application/network"
) )
const ( const (
@@ -46,12 +46,21 @@ func Enviro() Loader {
return func(log log.Logger) (string, Configuration, error) { return func(log log.Logger) (string, Configuration, error) {
log.Info("Loading configuration from environment variables ...") log.Info("Loading configuration from environment variables ...")
cfg := fileCfgCommon{ dialTimeout, _ := strconv.ParseUint(
parseEviro("SSHWIFTY_DIALTIMEOUT"), 10, 32)
cfg, dialer, cfgErr := fileCfgCommon{
HostName: parseEviro("SSHWIFTY_HOSTNAME"), HostName: parseEviro("SSHWIFTY_HOSTNAME"),
SharedKey: parseEviro("SSHWIFTY_SHAREDKEY"), SharedKey: parseEviro("SSHWIFTY_SHAREDKEY"),
DialTimeout: int(dialTimeout),
Socks5: parseEviro("SSHWIFTY_SOCKS5"), Socks5: parseEviro("SSHWIFTY_SOCKS5"),
Socks5User: parseEviro("SSHWIFTY_SOCKS5_USER"), Socks5User: parseEviro("SSHWIFTY_SOCKS5_USER"),
Socks5Password: parseEviro("SSHWIFTY_SOCKS5_PASSWORD"), Socks5Password: parseEviro("SSHWIFTY_SOCKS5_PASSWORD"),
}.build()
if cfgErr != nil {
return enviroTypeName, Configuration{}, fmt.Errorf(
"Failed to build the configuration: %s", cfgErr)
} }
listenPort, listenPortErr := strconv.ParseUint( listenPort, listenPortErr := strconv.ParseUint(
@@ -93,26 +102,12 @@ func Enviro() Loader {
TLSCertificateKeyFile: parseEviro("SSHWIFTY_TLSCERTIFICATEKEYFILE"), TLSCertificateKeyFile: parseEviro("SSHWIFTY_TLSCERTIFICATEKEYFILE"),
} }
var dialer network.Dial
if len(cfg.Socks5) <= 0 {
dialer = network.TCPDial()
} else {
sDial, sDialErr := network.BuildSocks5Dial(
cfg.Socks5, cfg.Socks5User, cfg.Socks5Password)
if sDialErr != nil {
return enviroTypeName, Configuration{}, sDialErr
}
dialer = sDial
}
return enviroTypeName, Configuration{ return enviroTypeName, Configuration{
HostName: cfg.HostName, HostName: cfg.HostName,
SharedKey: cfg.SharedKey, SharedKey: cfg.SharedKey,
Dialer: dialer, Dialer: dialer,
Servers: []Server{cfgSer.build()}, DialTimeout: time.Duration(cfg.DialTimeout) * time.Second,
Servers: []Server{cfgSer.build()},
}, nil }, nil
} }
} }

View File

@@ -49,7 +49,7 @@ type fileCfgServer struct {
TLSCertificateKeyFile string // Location of TLS certificate key TLSCertificateKeyFile string // Location of TLS certificate key
} }
func (f fileCfgServer) minDur(current, min int) int { func (f fileCfgServer) durationAtLeast(current, min int) int {
if current > min { if current > min {
return current return current
} }
@@ -62,17 +62,17 @@ func (f *fileCfgServer) build() Server {
ListenInterface: f.ListenInterface, ListenInterface: f.ListenInterface,
ListenPort: f.ListenPort, ListenPort: f.ListenPort,
InitialTimeout: time.Duration( InitialTimeout: time.Duration(
f.minDur(f.InitialTimeout, 5)) * time.Second, f.durationAtLeast(f.InitialTimeout, 5)) * time.Second,
ReadTimeout: time.Duration( ReadTimeout: time.Duration(
f.minDur(f.ReadTimeout, 30)) * time.Second, f.durationAtLeast(f.ReadTimeout, 30)) * time.Second,
WriteTimeout: time.Duration( WriteTimeout: time.Duration(
f.minDur(f.WriteTimeout, 30)) * time.Second, f.durationAtLeast(f.WriteTimeout, 30)) * time.Second,
HeartbeatTimeout: time.Duration( HeartbeatTimeout: time.Duration(
f.minDur(f.HeartbeatTimeout, 10)) * time.Second, f.durationAtLeast(f.HeartbeatTimeout, 10)) * time.Second,
ReadDelay: time.Duration( ReadDelay: time.Duration(
f.minDur(f.ReadDelay, 0)) * time.Millisecond, f.durationAtLeast(f.ReadDelay, 0)) * time.Millisecond,
WriteDelay: time.Duration( WriteDelay: time.Duration(
f.minDur(f.WriteDelay, 0)) * time.Millisecond, f.durationAtLeast(f.WriteDelay, 0)) * time.Millisecond,
TLSCertificateFile: f.TLSCertificateFile, TLSCertificateFile: f.TLSCertificateFile,
TLSCertificateKeyFile: f.TLSCertificateKeyFile, TLSCertificateKeyFile: f.TLSCertificateKeyFile,
} }
@@ -81,12 +81,46 @@ func (f *fileCfgServer) build() Server {
type fileCfgCommon struct { type fileCfgCommon struct {
HostName string // Host name HostName string // Host name
SharedKey string // Shared key, empty to enable public access SharedKey string // Shared key, empty to enable public access
DialTimeout int // DialTimeout, min 5s
Socks5 string // Socks5 server address, optional Socks5 string // Socks5 server address, optional
Socks5User string // Login user for socks5 server, optional Socks5User string // Login user for socks5 server, optional
Socks5Password string // Login pass for socks5 server, optional Socks5Password string // Login pass for socks5 server, optional
Servers []*fileCfgServer // Servers Servers []*fileCfgServer // Servers
} }
func (f fileCfgCommon) build() (fileCfgCommon, network.Dial, error) {
dialTimeout := f.DialTimeout
if dialTimeout < 3 {
dialTimeout = 3
}
var dialer network.Dial
if len(f.Socks5) <= 0 {
dialer = network.TCPDial()
} else {
sDial, sDialErr := network.BuildSocks5Dial(
f.Socks5, f.Socks5User, f.Socks5Password)
if sDialErr != nil {
return fileCfgCommon{}, nil, sDialErr
}
dialer = sDial
}
return fileCfgCommon{
HostName: f.HostName,
SharedKey: f.SharedKey,
DialTimeout: dialTimeout,
Socks5: f.Socks5,
Socks5User: f.Socks5User,
Socks5Password: f.Socks5Password,
Servers: f.Servers,
}, dialer, nil
}
func loadFile(filePath string) (string, Configuration, error) { func loadFile(filePath string) (string, Configuration, error) {
f, fErr := os.Open(filePath) f, fErr := os.Open(filePath)
@@ -105,32 +139,24 @@ func loadFile(filePath string) (string, Configuration, error) {
return fileTypeName, Configuration{}, jDecodeErr return fileTypeName, Configuration{}, jDecodeErr
} }
servers := make([]Server, len(cfg.Servers)) finalCfg, dialer, cfgErr := cfg.build()
for i := range servers { if cfgErr != nil {
servers[i] = cfg.Servers[i].build() return fileTypeName, Configuration{}, cfgErr
} }
var dialer network.Dial servers := make([]Server, len(finalCfg.Servers))
if len(cfg.Socks5) <= 0 { for i := range servers {
dialer = network.TCPDial() servers[i] = finalCfg.Servers[i].build()
} else {
sDial, sDialErr := network.BuildSocks5Dial(
cfg.Socks5, cfg.Socks5User, cfg.Socks5Password)
if sDialErr != nil {
return fileTypeName, Configuration{}, sDialErr
}
dialer = sDial
} }
return fileTypeName, Configuration{ return fileTypeName, Configuration{
HostName: cfg.HostName, HostName: finalCfg.HostName,
SharedKey: cfg.SharedKey, SharedKey: finalCfg.SharedKey,
Dialer: dialer, Dialer: dialer,
Servers: servers, DialTimeout: time.Duration(finalCfg.DialTimeout) * time.Second,
Servers: servers,
}, nil }, nil
} }

View File

@@ -358,7 +358,11 @@ func (s socket) Get(
senderLock := sync.Mutex{} senderLock := sync.Mutex{}
cmdExec, cmdExecErr := s.commander.New( cmdExec, cmdExecErr := s.commander.New(
s.commonCfg.Dialer, rw.NewFetchReader(func() ([]byte, error) { command.CommandConfiguration{
Dial: s.commonCfg.Dialer,
DialTimeout: s.commonCfg.DecideDialTimeout(s.serverCfg.ReadTimeout),
},
rw.NewFetchReader(func() ([]byte, error) {
defer s.increaseNonce(readNonce[:]) defer s.increaseNonce(readNonce[:])
// Size is unencrypted // Size is unencrypted
@@ -402,7 +406,8 @@ func (s socket) Get(
readNonce[:], readNonce[:],
cipherReadBuf[:packageSize], cipherReadBuf[:packageSize],
nil) nil)
}), socketPackageWriter{ }),
socketPackageWriter{
w: wsWriter, w: wsWriter,
packager: func(w websocketWriter, b []byte) error { packager: func(w websocketWriter, b []byte) error {
start := 0 start := 0

View File

@@ -42,7 +42,8 @@ func BuildSocks5Dial(
timeout time.Duration, timeout time.Duration,
) (net.Conn, error) { ) (net.Conn, error) {
dial, dialErr := proxy.SOCKS5("tcp", socks5Address, auth, &net.Dialer{ dial, dialErr := proxy.SOCKS5("tcp", socks5Address, auth, &net.Dialer{
Timeout: timeout, Timeout: timeout,
Deadline: time.Now().Add(timeout),
}) })
if dialErr != nil { if dialErr != nil {

View File

@@ -80,7 +80,6 @@ func (s Server) Serve(
closeCallback CloseCallback, closeCallback CloseCallback,
handlerBuilder HandlerBuilder, handlerBuilder HandlerBuilder,
) *Serving { ) *Serving {
ccCfg := commonCfg.WithDefault()
ssCfg := serverCfg.WithDefault() ssCfg := serverCfg.WithDefault()
l := s.logger.Context( l := s.logger.Context(
@@ -88,7 +87,7 @@ func (s Server) Serve(
ss := &Serving{ ss := &Serving{
server: http.Server{ server: http.Server{
Handler: handlerBuilder(ccCfg, ssCfg, l), Handler: handlerBuilder(commonCfg, ssCfg, l),
ReadTimeout: ssCfg.ReadTimeout, ReadTimeout: ssCfg.ReadTimeout,
ReadHeaderTimeout: ssCfg.InitialTimeout, ReadHeaderTimeout: ssCfg.InitialTimeout,
WriteTimeout: ssCfg.WriteTimeout, WriteTimeout: ssCfg.WriteTimeout,

View File

@@ -1,6 +1,7 @@
{ {
"HostName": "", "HostName": "",
"SharedKey": "WEB_ACCESS_PASSWORD", "SharedKey": "WEB_ACCESS_PASSWORD",
"DialTimeout": 5,
"Socks5": "", "Socks5": "",
"Socks5User": "", "Socks5User": "",
"Socks5Password": "", "Socks5Password": "",