From 8334f9e36afa2ad073ae281353b53f143f91015e Mon Sep 17 00:00:00 2001 From: zephinzer <1324745-zephinzer@users.noreply.gitlab.com> Date: Fri, 25 Jun 2021 12:31:12 +0800 Subject: [PATCH] made connection error limit into a configuration --- README.md | 1 + cmd/cloudshell/config.go | 5 +++++ cmd/cloudshell/main.go | 9 ++++++--- pkg/xtermjs/handler_websocket.go | 13 +++++++++---- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index fc07abc..e257af8 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ Configurations can be set via flags or environment variables. To view available | Allowed hostnames | `--allowed-hostnames` | `ALLOWED_HOSTNAMES` | `"localhost"` | Comma delimited list of hostnames that are allowed to connect to the websocket | | Arguments | `--arguments` | `ARGUMENTS` | `"-l"` | Comma delimited list of arguments that should be passed to the target binary | | Command | `--command` | `COMMAND` | `"/bin/bash"` | Absolute path to the binary to run | +| Connection error limit | `--connection-error-limit` | `CONNECTION_ERROR_LIMIT` | `10` | Number of times a connection should be re-attempted by the server to the XTerm.js frontend before the connection is considered dead and shut down | | Maximum buffer size in bytes | `--max-buffer-size-bytes` | `MAX_BUFFER_SIZE_BYTES` | `512` | Maximum length of input from the browser terminal | | Log format | `--log-format` | `LOG_FORMAT` | `"text"` | Format with which to output logs, one of `"json"` or `"text"` | | Log level | `--log-level` | `LOG_LEVEL` | `"debug"` | Minimum level of logs to output, one of `"trace"`, `"debug"`, `"info"`, `"warn"`, `"error"` | diff --git a/cmd/cloudshell/config.go b/cmd/cloudshell/config.go index c2dd44d..3d6eb99 100644 --- a/cmd/cloudshell/config.go +++ b/cmd/cloudshell/config.go @@ -24,6 +24,11 @@ var conf = config.Map{ Usage: "absolute path to command to run", Shorthand: "t", }, + "connection-error-limit": &config.Int{ + Default: 10, + Usage: "number of times a connection should be re-attempted before it's considered dead", + Shorthand: "l", + }, "max-buffer-size-bytes": &config.Int{ Default: 512, Usage: "maximum length of input from terminal", diff --git a/cmd/cloudshell/main.go b/cmd/cloudshell/main.go index 5a3c666..62fd285 100644 --- a/cmd/cloudshell/main.go +++ b/cmd/cloudshell/main.go @@ -38,6 +38,7 @@ func runE(_ *cobra.Command, _ []string) error { // debug stuff command := conf.GetString("command") + connectionErrorLimit := conf.GetInt("connection-error-limit") arguments := conf.GetStringSlice("arguments") allowedHostnames := conf.GetStringSlice("allowed-hostnames") maxBufferSizeBytes := conf.GetInt("max-buffer-size-bytes") @@ -62,6 +63,7 @@ func runE(_ *cobra.Command, _ []string) error { log.Infof("arguments : ['%s']", strings.Join(arguments, "', '")) log.Infof("allowed hosts : ['%s']", strings.Join(allowedHostnames, "', '")) + log.Infof("connection error limit: %v", connectionErrorLimit) log.Infof("max buffer size : %v bytes", maxBufferSizeBytes) log.Infof("server address : '%s' ", serverAddress) log.Infof("server port : %v", serverPort) @@ -76,9 +78,10 @@ func runE(_ *cobra.Command, _ []string) error { // this is the endpoint for xterm.js to connect to xtermjsHandlerOptions := xtermjs.HandlerOpts{ - AllowedHostnames: allowedHostnames, - Arguments: arguments, - Command: command, + AllowedHostnames: allowedHostnames, + Arguments: arguments, + Command: command, + ConnectionErrorLimit: connectionErrorLimit, CreateLogger: func(connectionUUID string, r *http.Request) xtermjs.Logger { createRequestLog(r, map[string]interface{}{"connection_uuid": connectionUUID}).Infof("created logger for connection '%s'", connectionUUID) return createRequestLog(nil, map[string]interface{}{"connection_uuid": connectionUUID}) diff --git a/pkg/xtermjs/handler_websocket.go b/pkg/xtermjs/handler_websocket.go index 3c31e47..012c27b 100644 --- a/pkg/xtermjs/handler_websocket.go +++ b/pkg/xtermjs/handler_websocket.go @@ -16,9 +16,7 @@ import ( "github.com/gorilla/websocket" ) -// ConnectionErrorLimit defines the number of consecutive errors that can happen -// before a connection is considered unusable -const ConnectionErrorLimit = 10 +const DefaultConnectionErrorLimit = 10 type HandlerOpts struct { // AllowedHostnames is a list of strings which will be matched to the client @@ -28,6 +26,9 @@ type HandlerOpts struct { Arguments []string // Command is the path to the binary we should create a TTY for Command string + // ConnectionErrorLimit defines the number of consecutive errors that can happen + // before a connection is considered unusable + ConnectionErrorLimit int // CreateLogger when specified should return a logger that the handler will use. // The string argument being passed in will be a unique identifier for the // current connection. When not specified, logs will be sent to stdout @@ -37,6 +38,10 @@ type HandlerOpts struct { func GetHandler(opts HandlerOpts) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { + connectionErrorLimit := opts.ConnectionErrorLimit + if connectionErrorLimit < 0 { + connectionErrorLimit = DefaultConnectionErrorLimit + } maxBufferSizeBytes := opts.MaxBufferSizeBytes connectionUUID, err := uuid.NewUUID() @@ -98,7 +103,7 @@ func GetHandler(opts HandlerOpts) func(http.ResponseWriter, *http.Request) { errorCounter := 0 for { // consider the connection closed/errored out - if errorCounter > ConnectionErrorLimit { + if errorCounter > connectionErrorLimit { waiter.Done() break }