CLI support (#59)
parent
852faf64ff
commit
499524d9bc
36
chat.go
36
chat.go
|
@ -2,6 +2,7 @@ package proxy
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -59,8 +60,41 @@ func onChatMsg(cc *ClientConn, cmd *mt.ToSrvChatMsg) (string, bool) {
|
|||
return fmt.Sprintf("Missing permission %s.", cmd.Perm), true
|
||||
}
|
||||
|
||||
return cmd.Handler(cc, args...), true
|
||||
return cmd.Handler(cc, nil, args...), true
|
||||
}
|
||||
|
||||
return "", false
|
||||
}
|
||||
|
||||
func onTelnetMsg(tlog func(dir string, v ...interface{}), w io.Writer, msg string) string {
|
||||
initChatCmds()
|
||||
|
||||
substrs := strings.Split(msg, " ")
|
||||
cmdName := substrs[0]
|
||||
|
||||
var args []string
|
||||
if len(substrs) > 1 {
|
||||
args = substrs[1:]
|
||||
}
|
||||
|
||||
v := make([]interface{}, 2+len(args))
|
||||
v[0] = "command"
|
||||
v[1] = cmdName
|
||||
|
||||
for i, arg := range args {
|
||||
v[i+2] = arg
|
||||
}
|
||||
|
||||
tlog("-->", v...)
|
||||
|
||||
if !ChatCmdExists(cmdName) {
|
||||
tlog("<--", "unknown command", cmdName)
|
||||
return "Command not found.\n"
|
||||
}
|
||||
|
||||
chatCmdsMu.RLock()
|
||||
defer chatCmdsMu.RUnlock()
|
||||
|
||||
cmd := chatCmds[cmdName]
|
||||
return cmd.Handler(nil, w, args...) + "\n"
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ const defaultCmdPrefix = ">"
|
|||
const defaultSendInterval = 0.09
|
||||
const defaultUserLimit = 10
|
||||
const defaultAuthBackend = "sqlite3"
|
||||
const defaultTelnetAddr = ":40010"
|
||||
const defaultTelnetAddr = "[::1]:40010"
|
||||
const defaultBindAddr = ":40000"
|
||||
const defaultListInterval = 300
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package proxy
|
||||
|
||||
import "sync"
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// A ChatCmd holds information on how to handle a chat command.
|
||||
type ChatCmd struct {
|
||||
|
@ -8,7 +11,7 @@ type ChatCmd struct {
|
|||
Perm string
|
||||
Help string
|
||||
Usage string
|
||||
Handler func(*ClientConn, ...string) string
|
||||
Handler func(*ClientConn, io.Writer, ...string) string
|
||||
}
|
||||
|
||||
var chatCmds map[string]ChatCmd
|
||||
|
|
61
telnet.go
61
telnet.go
|
@ -5,9 +5,24 @@ import (
|
|||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"math"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// A TelnetWriter can be used to print something at the other end
|
||||
// of a telnet connection. It implements the io.Writer interface.
|
||||
type TelnetWriter struct {
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
// Write writes its parameter to the telnet connection.
|
||||
// A trailing newline is always appended.
|
||||
// It returns the number of bytes written and an error.
|
||||
func (tw *TelnetWriter) Write(p []byte) (n int, err error) {
|
||||
return tw.conn.Write(append(p, '\n'))
|
||||
}
|
||||
|
||||
var telnetCh = make(chan struct{})
|
||||
|
||||
func telnetServer() error {
|
||||
|
@ -17,6 +32,8 @@ func telnetServer() error {
|
|||
}
|
||||
defer ln.Close()
|
||||
|
||||
log.Print("{←|⇶} listen telnet ", ln.Addr())
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-telnetCh:
|
||||
|
@ -34,16 +51,39 @@ func telnetServer() error {
|
|||
}
|
||||
|
||||
func handleTelnet(conn net.Conn) {
|
||||
tlog := func(dir string, v ...interface{}) {
|
||||
format := "{%s} %s {←|⇶}"
|
||||
format += strings.Repeat(" %v", len(v))
|
||||
|
||||
log.Printf(format, append([]interface{}{
|
||||
conn.RemoteAddr(),
|
||||
dir,
|
||||
}, v...)...)
|
||||
}
|
||||
|
||||
tlog("<->", "telnet connect")
|
||||
|
||||
defer tlog("<->", "telnet disconnect")
|
||||
defer conn.Close()
|
||||
|
||||
r, w := bufio.NewReader(conn), bufio.NewWriter(conn)
|
||||
b := bufio.NewReadWriter(r, w)
|
||||
readString := func(delim byte) (string, error) {
|
||||
s, err := bufio.NewReader(conn).ReadString(delim)
|
||||
i := int(math.Max(float64(len(s)-2), 1))
|
||||
s = s[:i]
|
||||
return s, err
|
||||
}
|
||||
|
||||
writeString := func(s string) (n int, err error) {
|
||||
return io.WriteString(conn, s)
|
||||
}
|
||||
|
||||
writeString("mt-multiserver-proxy console\n")
|
||||
writeString("Type \\quit or \\q to disconnect.\n")
|
||||
|
||||
b.WriteString("mt-multiserver-proxy console\n")
|
||||
for {
|
||||
b.WriteString(">")
|
||||
writeString(Conf().CmdPrefix)
|
||||
|
||||
_, err := b.ReadString('\n')
|
||||
s, err := readString('\n')
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return
|
||||
|
@ -52,5 +92,16 @@ func handleTelnet(conn net.Conn) {
|
|||
log.Print("{←|⇶} ", err)
|
||||
continue
|
||||
}
|
||||
|
||||
tlog("-->", "telnet command", s)
|
||||
|
||||
if s == "\\quit" || s == "\\q" {
|
||||
return
|
||||
}
|
||||
|
||||
result := onTelnetMsg(tlog, &TelnetWriter{conn: conn}, s)
|
||||
if result != "" {
|
||||
writeString(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue