Compare commits

...

3 commits

Author SHA1 Message Date
9db0f9f923
Refactor cmd execution function chain to be more readable
The execution was originaly build to be used as a lib, but this is no
longer the case and so I removed all the `io.Writer` and `io.Reader`
interactions. The app reads now from Stdin and writes to Stdout as it
did before.
It also redoes the error handling so that all errors that are not
treated are being handled in the `main` function.
2022-02-03 00:27:16 +01:00
df5d02cbe4
Extract shared cmd execution into own function 2022-02-02 23:20:08 +01:00
6ee166e754
Move cli/entry.go into main.go
This is to remove the directory that is used in cobra setups.
While we could kept the file inside the root directory but it only
contains two small functions that can be moved into the `main.go` file.
2022-02-02 22:44:49 +01:00
2 changed files with 73 additions and 92 deletions

View file

@ -1,84 +0,0 @@
package cli
import (
"bufio"
"fmt"
"io"
"log"
"os"
"strings"
"github.com/hamburghammer/rcon"
)
// Start a interactive connection. Uses the given reader and writer to inteact with the created connection.
func Start(hostPort string, password string, in io.Reader, out io.Writer) {
remoteConsole, err := rcon.Dial(hostPort, password)
if err != nil {
log.Fatal("Failed to connect to RCON server", err)
}
defer remoteConsole.Close()
scanner := bufio.NewScanner(in)
out.Write([]byte("To quit the session type 'exit'.\n"))
out.Write([]byte("> "))
for scanner.Scan() {
cmd := scanner.Text()
if cmd == "exit" {
return
}
reqID, err := remoteConsole.Write(cmd)
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to send command:", err.Error())
continue
}
resp, respID, err := remoteConsole.Read()
if err != nil {
if err == io.EOF {
return
}
fmt.Fprintln(os.Stderr, "Failed to read command:", err.Error())
continue
}
if reqID != respID {
fmt.Fprintln(out, "Weird. This response is for another request.")
}
fmt.Fprintln(out, resp)
out.Write([]byte("> "))
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading standard input:", err)
}
}
// Execute runs the given command against the remote console and writes the response into the writer.
func Execute(hostPort string, password string, out io.Writer, command ...string) {
remoteConsole, err := rcon.Dial(hostPort, password)
if err != nil {
log.Fatal("Failed to connect to RCON server", err)
}
defer remoteConsole.Close()
preparedCmd := strings.Join(command, " ")
reqID, err := remoteConsole.Write(preparedCmd)
resp, respID, err := remoteConsole.Read()
if err != nil {
if err == io.EOF {
return
}
fmt.Fprintln(os.Stderr, "Failed to read command:", err.Error())
return
}
if reqID != respID {
fmt.Fprintln(out, "Weird. This response is for another request.")
}
fmt.Fprintln(out, resp)
}

81
main.go
View file

@ -1,11 +1,15 @@
package main package main
import ( import (
"bufio"
"errors"
"fmt" "fmt"
"io"
"net" "net"
"os" "os"
"strings"
"github.com/itzg/rcon-cli/cli" "github.com/hamburghammer/rcon"
flags "github.com/spf13/pflag" flags "github.com/spf13/pflag"
) )
@ -34,7 +38,11 @@ func main() {
return return
} }
run(commands...) err := run(strings.Join(commands, " "))
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
} }
func parseArgs(args []string) ([]string, error) { func parseArgs(args []string) ([]string, error) {
@ -70,14 +78,25 @@ func loadEnvIfNotSet() {
} }
} }
func run(args ...string) { func run(cmd string) error {
hostPort := net.JoinHostPort(host, port) hostPort := net.JoinHostPort(host, port)
remoteConsole, err := rcon.Dial(hostPort, password)
if len(args) == 0 { if err != nil {
cli.Start(hostPort, password, os.Stdin, os.Stdout) return fmt.Errorf("failed to connect to RCON server: %w", err)
} else {
cli.Execute(hostPort, password, os.Stdout, args...)
} }
defer remoteConsole.Close()
if len(cmd) == 0 {
err = executeInteractive(remoteConsole)
} else {
resp, err := execute(cmd, remoteConsole)
if err != nil {
return err
}
fmt.Println(resp)
}
return err
} }
func printHelp() { func printHelp() {
@ -100,3 +119,49 @@ EXAMPLES:
%sPORT=25575 rcon-cli stop %sPORT=25575 rcon-cli stop
`, envVarPrefix, envVarPrefix) `, envVarPrefix, envVarPrefix)
} }
func executeInteractive(remoteConsole *rcon.RemoteConsole) error {
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("To quit the session type 'exit'.")
for scanner.Scan() {
fmt.Print("> ")
cmd := scanner.Text()
if cmd == "exit" {
return nil
}
resp, err := execute(cmd, remoteConsole)
if err != nil {
return err
}
fmt.Println(resp)
}
if err := scanner.Err(); err != nil {
return fmt.Errorf("reading standard input: %w", err)
}
return nil
}
func execute(cmd string, remoteConsole *rcon.RemoteConsole) (string, error) {
resp := ""
reqID, err := remoteConsole.Write(cmd)
if err != nil {
return resp, fmt.Errorf("failed to send command: %w", err)
}
resp, respID, err := remoteConsole.Read()
if err != nil {
if err == io.EOF {
return resp, nil
}
return resp, fmt.Errorf("failed to read command: %w", err)
}
if reqID != respID {
return resp, errors.New("the response id didn't match the request id")
}
return resp, nil
}