mirror of
https://github.com/EchoVault/SugarDB.git
synced 2025-10-14 20:16:05 +08:00
166 lines
3.3 KiB
Go
166 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"os"
|
|
"path"
|
|
|
|
"github.com/kelvinmwinuka/memstore/serialization"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type Config struct {
|
|
TLS bool `json:"tls" yaml:"tls"`
|
|
Key string `json:"key" yaml:"key"`
|
|
Cert string `json:"cert" yaml:"cert"`
|
|
Port uint16 `json:"port" yaml:"port"`
|
|
}
|
|
|
|
func main() {
|
|
TLS := flag.Bool("tls", false, "Start the server in TLS mode. Default is false")
|
|
Key := flag.String("key", "", "The private key file path.")
|
|
Cert := flag.String("cert", "", "The signed certificate file path.")
|
|
Port := flag.Int("port", 7480, "Port to use. Default is 7480")
|
|
|
|
config := flag.String(
|
|
"config",
|
|
"",
|
|
`File path to a JSON or YAML config file.The values in this config file will override the flag values.`,
|
|
)
|
|
|
|
flag.Parse()
|
|
|
|
var conf Config
|
|
|
|
if len(*config) > 0 {
|
|
// Load config from config file
|
|
if f, err := os.Open(*config); err != nil {
|
|
panic(err)
|
|
} else {
|
|
defer f.Close()
|
|
|
|
ext := path.Ext(f.Name())
|
|
|
|
if ext == ".json" {
|
|
json.NewDecoder(f).Decode(&conf)
|
|
}
|
|
|
|
if ext == ".yaml" || ext == ".yml" {
|
|
yaml.NewDecoder(f).Decode(&conf)
|
|
}
|
|
}
|
|
|
|
} else {
|
|
conf = Config{
|
|
TLS: *TLS,
|
|
Key: *Key,
|
|
Cert: *Cert,
|
|
Port: uint16(*Port),
|
|
}
|
|
}
|
|
|
|
var conn net.Conn
|
|
var err error
|
|
|
|
if !conf.TLS {
|
|
fmt.Println("Starting client in TCP mode...")
|
|
|
|
conn, err = net.Dial("tcp", fmt.Sprintf("%s:%d", "localhost", conf.Port))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
} else {
|
|
// Dial TLS
|
|
fmt.Println("Starting client in TLS mode...")
|
|
|
|
f, err := os.Open(conf.Cert)
|
|
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
cert, err := io.ReadAll(bufio.NewReader(f))
|
|
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
rootCAs := x509.NewCertPool()
|
|
|
|
ok := rootCAs.AppendCertsFromPEM(cert)
|
|
if !ok {
|
|
panic("Failed to parse certificate")
|
|
}
|
|
|
|
conn, err = tls.Dial("tcp", fmt.Sprintf("%s:%d", "localhost", conf.Port), &tls.Config{
|
|
RootCAs: rootCAs,
|
|
})
|
|
|
|
if err != nil {
|
|
panic(fmt.Sprintf("Handshake Error: %s", err.Error()))
|
|
}
|
|
}
|
|
|
|
defer conn.Close()
|
|
|
|
done := make(chan struct{})
|
|
|
|
connRW := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
|
stdioRW := bufio.NewReadWriter(bufio.NewReader(os.Stdin), bufio.NewWriter(os.Stdout))
|
|
|
|
go func() {
|
|
for {
|
|
stdioRW.Write([]byte("\n> "))
|
|
stdioRW.Flush()
|
|
|
|
if in, err := stdioRW.ReadBytes(byte('\n')); err != nil {
|
|
stdioRW.Write([]byte(fmt.Sprintf("ERROR: %s\n", err)))
|
|
stdioRW.Flush()
|
|
} else {
|
|
in := bytes.TrimSpace(in)
|
|
|
|
// Check for quit command
|
|
if bytes.Equal(bytes.ToLower(in), []byte("quit")) {
|
|
break
|
|
}
|
|
|
|
if err := serialization.Encode(connRW, string(in)); err != nil {
|
|
stdioRW.Write([]byte(fmt.Sprintf("%s\n", err.Error())))
|
|
stdioRW.Flush()
|
|
} else {
|
|
// Write encoded command to the connection
|
|
connRW.Write([]byte("\n"))
|
|
connRW.Flush()
|
|
|
|
// Read response from server
|
|
if l, _, err := connRW.ReadLine(); err != nil {
|
|
if err == io.EOF {
|
|
// Break loop when we detect an EOF (Connection closed)
|
|
stdioRW.Write([]byte("Connection closed"))
|
|
stdioRW.Flush()
|
|
break
|
|
} else {
|
|
stdioRW.Write([]byte(err.Error()))
|
|
stdioRW.Flush()
|
|
}
|
|
} else {
|
|
stdioRW.Write(l)
|
|
stdioRW.Flush()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
done <- struct{}{}
|
|
}()
|
|
|
|
<-done
|
|
}
|