diff --git a/cmd/tesla-control/main.go b/cmd/tesla-control/main.go index cc812671..cb670ac9 100644 --- a/cmd/tesla-control/main.go +++ b/cmd/tesla-control/main.go @@ -56,8 +56,8 @@ func Usage() { } } -func runCommand(acct *account.Account, car *vehicle.Vehicle, args []string) int { - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) +func runCommand(acct *account.Account, car *vehicle.Vehicle, args []string, timeout time.Duration) int { + ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() if err := execute(ctx, acct, car, args); err != nil { @@ -73,7 +73,7 @@ func runCommand(acct *account.Account, car *vehicle.Vehicle, args []string) int return 0 } -func runInteractiveShell(acct *account.Account, car *vehicle.Vehicle) int { +func runInteractiveShell(acct *account.Account, car *vehicle.Vehicle, timeout time.Duration) int { scanner := bufio.NewScanner(os.Stdin) for fmt.Printf("> "); scanner.Scan(); fmt.Printf("> ") { args, err := shlex.Split(scanner.Text()) @@ -87,7 +87,7 @@ func runInteractiveShell(acct *account.Account, car *vehicle.Vehicle) int { writeErr("Invalid command: %s", err) continue } - runCommand(acct, car, args) + runCommand(acct, car, args, timeout) } if err := scanner.Err(); err != nil { writeErr("Error reading command: %s", err) @@ -103,8 +103,10 @@ func main() { }() var ( - debug bool - forceBLE bool + debug bool + forceBLE bool + commandTimeout time.Duration + connTimeout time.Duration ) config, err := cli.NewConfig(cli.FlagAll) if err != nil { @@ -114,6 +116,8 @@ func main() { flag.Usage = Usage flag.BoolVar(&debug, "debug", false, "Enable verbose debugging messages") flag.BoolVar(&forceBLE, "ble", false, "Force BLE connection even if OAuth environment variables are defined") + flag.DurationVar(&commandTimeout, "command-timeout", 5*time.Second, "Set timeout for commands sent to the vehicle.") + flag.DurationVar(&connTimeout, "connect-timeout", 20*time.Second, "Set timeout for establishing initial connection.") config.RegisterCommandLineFlags() flag.Parse() @@ -150,7 +154,7 @@ func main() { return } - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), connTimeout) defer cancel() acct, car, err := config.Connect(ctx) @@ -171,8 +175,8 @@ func main() { } if flag.NArg() > 0 { - status = runCommand(acct, car, flag.Args()) + status = runCommand(acct, car, flag.Args(), commandTimeout) } else { - status = runInteractiveShell(acct, car) + status = runInteractiveShell(acct, car, commandTimeout) } } diff --git a/cmd/tesla-http-proxy/main.go b/cmd/tesla-http-proxy/main.go index 80e12390..9fbac93f 100644 --- a/cmd/tesla-http-proxy/main.go +++ b/cmd/tesla-http-proxy/main.go @@ -7,6 +7,7 @@ import ( "fmt" "net/http" "os" + "time" "github.com/teslamotors/vehicle-command/internal/log" "github.com/teslamotors/vehicle-command/pkg/cli" @@ -43,6 +44,7 @@ func main() { verbose bool host string port int + timeout time.Duration ) config, err := cli.NewConfig(cli.FlagPrivateKey) @@ -64,6 +66,7 @@ func main() { flag.BoolVar(&verbose, "verbose", false, "Enable verbose logging") flag.StringVar(&host, "host", "localhost", "Proxy server `hostname`") flag.IntVar(&port, "port", defaultPort, "`Port` to listen on") + flag.DurationVar(&timeout, "timeout", proxy.DefaultTimeout, "Timeout interval when sending commands") flag.Usage = Usage config.RegisterCommandLineFlags() flag.Parse() @@ -97,6 +100,7 @@ func main() { if err != nil { return } + p.Timeout = timeout addr := fmt.Sprintf("%s:%d", host, port) log.Info("Listening on %s", addr) diff --git a/pkg/proxy/proxy.go b/pkg/proxy/proxy.go index 20a32257..a71c764c 100644 --- a/pkg/proxy/proxy.go +++ b/pkg/proxy/proxy.go @@ -22,7 +22,7 @@ import ( ) const ( - defaultTimeout = 10 * time.Second + DefaultTimeout = 10 * time.Second maxRequestBodyBytes = 512 vinLength = 17 proxyProtocolVersion = "tesla-http-proxy/1.0.0" @@ -90,7 +90,7 @@ func (p *Proxy) unlockVIN(vin string) { // command-authentication key, not a TLS key.) func New(ctx context.Context, skey protocol.ECDHPrivateKey, cacheSize int) (*Proxy, error) { return &Proxy{ - Timeout: defaultTimeout, + Timeout: DefaultTimeout, commandKey: skey, sessions: cache.New(cacheSize), }, nil