diff options
author | Christian Pointner <equinox@helsinki.at> | 2015-12-21 19:10:24 (GMT) |
---|---|---|
committer | Christian Pointner <equinox@helsinki.at> | 2015-12-21 19:10:24 (GMT) |
commit | c06f4c3db13c69ec5ff8f3685aa5055c2645b144 (patch) | |
tree | 077665352f75a0ded9351b38c133a402c560c755 | |
parent | a82af17b7242d0ee3794f8252fe0b4375a4b1e72 (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.go | 82 |
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) } } |