summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@helsinki.at>2015-12-21 19:10:24 (GMT)
committerChristian Pointner <equinox@helsinki.at>2015-12-21 19:10:24 (GMT)
commitc06f4c3db13c69ec5ff8f3685aa5055c2645b144 (patch)
tree077665352f75a0ded9351b38c133a402c560c755
parenta82af17b7242d0ee3794f8252fe0b4375a4b1e72 (diff)
reading telnet command is now seperate goroutinge in order to read Ctrl-C while command is running
-rw-r--r--src/helsinki.at/rhimportd/ctrlTelnet.go82
1 files changed, 51 insertions, 31 deletions
diff --git a/src/helsinki.at/rhimportd/ctrlTelnet.go b/src/helsinki.at/rhimportd/ctrlTelnet.go
index 0c0b2be..ff94d49 100644
--- a/src/helsinki.at/rhimportd/ctrlTelnet.go
+++ b/src/helsinki.at/rhimportd/ctrlTelnet.go
@@ -82,7 +82,7 @@ func (c *TelnetClient) handle_cmd_help(args []string) {
switch args[0] {
case "quit":
c.say("usage: quit")
- c.say(" terminates the client connection.")
+ c.say(" terminates the client connection. You may also use Ctrl-D to do this.")
return
case "help":
c.say("usage: help [ <cmd> ]")
@@ -150,7 +150,7 @@ func (c *TelnetClient) handle_cmd_help(args []string) {
default:
c.say("usage: <cmd> [ [ <arg1> ] ... ]")
c.say(" available commands:")
- c.say(" quit close connection")
+ c.say(" quit close connection (or use Ctrl-D)")
c.say(" help [ <cmd> ] print this, or help for specific command")
c.say(" set <param> <value> sets parameter <param> on current import context")
c.say(" show shows current import context")
@@ -316,16 +316,18 @@ func (c *TelnetClient) handle_cmd_run(args []string) {
}
}
-func (c *TelnetClient) handle_cmd(cmdstr string) bool {
+func (c *TelnetClient) handle_cmd(cmdstr string, done chan<- bool) {
cmdslice := strings.Fields(cmdstr)
if len(cmdslice) == 0 || cmdslice[0] == "" {
- return false
+ done <- false
+ return
}
cmd := cmdslice[0]
args := cmdslice[1:]
if cmd == "quit" {
- return true
+ done <- true
+ return
} else if cmd == "help" {
c.handle_cmd_help(args)
} else if cmd == "set" {
@@ -337,9 +339,9 @@ func (c *TelnetClient) handle_cmd(cmdstr string) bool {
} else if cmd == "run" {
c.handle_cmd_run(args)
} else {
- c.say("unknown command")
+ c.say("unknown command '%s'", cmd)
}
- return false
+ done <- false
}
func (c *TelnetClient) handle_iac(iac []byte) bool {
@@ -400,17 +402,17 @@ func ScanLinesTelnet(data []byte, atEOF bool) (advance int, token []byte, err er
}
if iiac >= 0 {
l := 2
- if (len(data) - iiac) < 1 {
+ if (len(data) - iiac) < 2 {
return 0, nil, nil // data does not yet contain the telnet command code -> need more data
}
switch data[iiac+1] {
case DONT, DO, WONT, WILL:
- if (len(data) - iiac) < 2 {
+ if (len(data) - iiac) < 3 {
return 0, nil, nil // this is a 3-byte command and data does not yet contain the option code -> need more data
}
l = 3
}
-
+ // TODO: this doesn't handle escaped IAC bytes correctly: this means utf-8 might be broken...
return iiac + l, data[iiac : iiac+l], nil // found a Telnet Command
}
if atEOF {
@@ -419,34 +421,52 @@ func ScanLinesTelnet(data []byte, atEOF bool) (advance int, token []byte, err er
return 0, nil, nil // we have found none of the escape codes -> need more data
}
-func (c *TelnetClient) handle() {
- defer func() {
- if err := c.scanner.Err(); err != nil {
- rhdl.Printf("telnet-ctrl(%s): read command error: %s", c.conn.RemoteAddr(), err)
- } else {
- rhdl.Printf("telnet-ctrl(%s): connection closed", c.conn.RemoteAddr())
- }
- c.conn.Close()
- }()
+func (c *TelnetClient) recv(in chan<- string) {
+ defer close(in)
- c.write_string(prompt)
for c.scanner.Scan() {
b := c.scanner.Bytes()
- if len(b) > 0 {
- switch b[0] {
- case EOT:
+ if len(b) > 0 && b[0] == EOT {
+ rhdl.Printf("telnet-ctrl(%s): Ctrl-D received, closing", c.conn.RemoteAddr())
+ return
+ }
+ in <- string(b)
+ }
+ if err := c.scanner.Err(); err != nil {
+ rhdl.Printf("telnet-ctrl(%s): recv() error: %s", c.conn.RemoteAddr(), err)
+ } else {
+ rhdl.Printf("telnet-ctrl(%s): Connection closed by foreign host", c.conn.RemoteAddr())
+ }
+}
+
+func (c *TelnetClient) handle() {
+ defer c.conn.Close()
+
+ in := make(chan string)
+ go c.recv(in)
+
+ done := make(chan bool)
+ c.write_string(prompt)
+ for {
+ select {
+ case cmd, ok := <-in:
+ if !ok {
return
- case IAC:
- if exit := c.handle_iac(c.scanner.Bytes()); exit {
- return
- }
- default:
- if exit := c.handle_cmd(string(b)); exit {
- return
+ }
+ if len(cmd) > 0 {
+ switch cmd[0] {
+ case IAC:
+ c.handle_iac([]byte(cmd))
+ default:
+ go c.handle_cmd(cmd, done)
}
+ } else {
c.write_string(prompt)
}
- } else {
+ case exit := <-done:
+ if exit {
+ return
+ }
c.write_string(prompt)
}
}