diff --git a/cmd/apps/therealproxy-client/therealproxy-client.go b/cmd/apps/therealproxy-client/therealproxy-client.go index 53cf3ff45..96c9079cb 100644 --- a/cmd/apps/therealproxy-client/therealproxy-client.go +++ b/cmd/apps/therealproxy-client/therealproxy-client.go @@ -6,6 +6,7 @@ package main import ( "flag" "net" + "time" "github.com/SkycoinProject/dmsg/cipher" @@ -18,9 +19,11 @@ import ( func main() { log := app.NewLogger(skyenv.SkyproxyClientName) therealproxy.Log = log.PackageLogger(skyenv.SkyproxyClientName) + defaultTimeout := skyenv.SkyproxyClientTimeout var addr = flag.String("addr", skyenv.SkyproxyClientAddr, "Client address to listen on") var serverPK = flag.String("srv", "", "PubKey of the server to connect to") + var timeout = flag.String("timeout", defaultTimeout.String(), "Connection timeout duration") flag.Parse() config := &app.Config{AppName: skyenv.SkyproxyClientName, AppVersion: skyenv.SkyproxyClientVersion, ProtocolVersion: skyenv.AppProtocolVersion} @@ -51,7 +54,13 @@ func main() { remote := routing.Addr{PubKey: pk, Port: routing.Port(skyenv.SkyproxyPort)} - client, err := therealproxy.NewClient(l, socksApp, remote) + clientTimeout, err := time.ParseDuration(*timeout) + if err != nil { + log.Warnf("Bad duration format, using default (%v)", defaultTimeout) + clientTimeout = defaultTimeout + } + + client, err := therealproxy.NewClient(l, socksApp, remote, clientTimeout) if err != nil { log.Fatal("Failed to create a new client: ", err) } diff --git a/internal/skyenv/const.go b/internal/skyenv/const.go index 25014054e..710feffbb 100644 --- a/internal/skyenv/const.go +++ b/internal/skyenv/const.go @@ -1,5 +1,9 @@ package skyenv +import ( + "time" +) + // Constants for default services. const ( DefaultTpDiscAddr = "http://transport.discovery.skywire.skycoin.com" @@ -45,9 +49,12 @@ const ( SkyproxyVersion = "1.0" SkyproxyPort = uint16(3) - SkyproxyClientName = "socksproxy-client" - SkyproxyClientVersion = "1.0" - SkyproxyClientPort = uint16(13) - SkyproxyClientAddr = ":1080" - // TODO(evanlinjin): skyproxy-client requires + SkyproxyClientName = "socksproxy-client" + SkyproxyClientVersion = "1.0" + SkyproxyClientPort = uint16(13) + SkyproxyClientAddr = ":1080" + SkyproxyClientTimeout = 5 * time.Second + SkyproxyReconnectInterval = 1 * time.Second + SkyproxyRetryTimes = 0 + SkyproxyRetryFactor = 1 ) diff --git a/internal/therealproxy/client.go b/internal/therealproxy/client.go index b0135dc1f..655051f2f 100644 --- a/internal/therealproxy/client.go +++ b/internal/therealproxy/client.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/yamux" "github.com/SkycoinProject/skywire-mainnet/internal/netutil" + "github.com/SkycoinProject/skywire-mainnet/internal/skyenv" "github.com/SkycoinProject/skywire-mainnet/pkg/app" "github.com/SkycoinProject/skywire-mainnet/pkg/routing" ) @@ -19,18 +20,20 @@ var Log = logging.MustGetLogger("therealproxy") // Client implement multiplexing proxy client using yamux. type Client struct { - session *yamux.Session listener net.Listener app *app.App addr routing.Addr + timeout time.Duration + session *yamux.Session } // NewClient constructs a new Client. -func NewClient(lis net.Listener, app *app.App, addr routing.Addr) (*Client, error) { +func NewClient(lis net.Listener, app *app.App, addr routing.Addr, timeout time.Duration) (*Client, error) { c := &Client{ listener: lis, app: app, addr: addr, + timeout: timeout, } if err := c.connect(); err != nil { return nil, err @@ -40,7 +43,7 @@ func NewClient(lis net.Listener, app *app.App, addr routing.Addr) (*Client, erro } func (c *Client) connect() error { - r := netutil.NewRetrier(time.Second, 0, 1) + r := netutil.NewRetrier(skyenv.SkyproxyReconnectInterval, skyenv.SkyproxyRetryTimes, skyenv.SkyproxyRetryFactor) var conn net.Conn err := r.Do(func() error { @@ -52,7 +55,12 @@ func (c *Client) connect() error { return fmt.Errorf("failed to dial to a server: %v", err) } - session, err := yamux.Client(conn, nil) + // If connection fails, yamux client doesn't wait, fails early and reconnects. + yamuxCfg := yamux.DefaultConfig() + yamuxCfg.KeepAliveInterval = c.timeout + yamuxCfg.ConnectionWriteTimeout = c.timeout + + session, err := yamux.Client(conn, yamuxCfg) if err != nil { return fmt.Errorf("failed to create client: %s", err) } @@ -84,7 +92,7 @@ func (c *Client) createStream() net.Conn { Log.Warnf("Failed to open yamux session: %v", err) - delay := 1 * time.Second + delay := skyenv.SkyproxyReconnectInterval Log.Warnf("Restarting in %v", delay) time.Sleep(delay)