# HG changeset patch # User sqwishy # Date 1392870715 28800 # Wed Feb 19 20:31:55 2014 -0800 # Node ID 744c0fbe848c12859b63485ea2a5f7885a853225 # Parent 705458d02ecb92e292ddbab33e1d00498ce705ef implements terminal packets diff --git a/gorcon/client.go b/gorcon/client.go --- a/gorcon/client.go +++ b/gorcon/client.go @@ -21,6 +21,7 @@ type Client struct { net.Conn queue commQueue + sendmutex sync.Mutex } func NewClient(addr string) (c *Client, err error) { @@ -39,32 +40,43 @@ } func (c *Client) Auth(data string) (<-chan error) { - _, errch := c.writeCommand(AUTH_ID, SERVERDATA_AUTH, []byte(data)) + _, errch := c.sendCmd(AUTH_ID, SERVERDATA_AUTH, []byte(data)) return errch } func (c *Client) Exec(data string) (<-chan *Message, <-chan error) { - return c.writeCommand(EXEC_ID, SERVERDATA_EXECCOMMAND, []byte(data)) + return c.sendCmd(EXEC_ID, SERVERDATA_EXECCOMMAND, []byte(data)) } -func (c *Client) writeCommand(id int32, cmdtype CmdType, body []byte) (<-chan *Message, <-chan error) { +func (c *Client) sendCmd(id int32, cmdtype CmdType, body []byte) (<-chan *Message, <-chan error) { msgch := make(chan *Message, 1) // Keep these async errch := make(chan error, 1) + c.sendmutex.Lock() + defer c.sendmutex.Unlock() if err := writeCommand(c, id, cmdtype, body); err != nil { errch <- err //close(msgch) - } else { - c.queue.Push(&comm{msgch, errch}) + return msgch, errch + } + c.queue.Push(&comm{msgch, errch}) + if id == EXEC_ID { + // Also send a terminal packet (this seems like a not great place to put this?) + if err := writeCommand(c, TERM_ID, cmdtype, []byte{}); err != nil { + // We have to panic here + // We can't simply remove msg from the queue since readLoop() may + // or may not have started writing to it already + panic(err) + } } return msgch, errch } func (c *Client) readLoop() { + var current *Message r := bufio.NewReader(c) for { - resp, err := readResp(r) - log.Printf("<<< %+v / %v\n", resp, err) - // TODO, implement terminal packets + pack, err := readResp(r) + log.Printf("<<< %+v / %v\n", pack, err) comm := c.queue.Peek() if comm == nil { log.Panicln("u maek le bug uheuheuheh") @@ -76,26 +88,38 @@ } comm.errch <- err } - if (resp.Id == AUTH_ID || resp.Id == -1) && resp.Type == SERVERDATA_AUTH_RESPONSE { + // TODO a switch may be more readable + if (pack.Id == AUTH_ID || pack.Id == -1) && pack.Type == SERVERDATA_AUTH_RESPONSE { // Packet two of two of response to auth request log.Println("Received two of two of responses to auth request") c.queue.Pop() - if resp.Id == AUTH_ID { + if pack.Id == AUTH_ID { comm.errch <- nil } else { comm.errch <- fmt.Errorf("Authentication Failed") } //close(comm.msgch) - } else if resp.Id == AUTH_ID && resp.Type == SERVERDATA_RESPONSE_VALUE { + } else if pack.Id == AUTH_ID && pack.Type == SERVERDATA_RESPONSE_VALUE { // Packet one of two of response to auth request log.Println("Received one of two of responses to auth request") continue - } else if (resp.Id & EXEC_ID|TERM_ID != 0) && (resp.Type == SERVERDATA_RESPONSE_VALUE) { + } else if (pack.Id == EXEC_ID) && (pack.Type == SERVERDATA_RESPONSE_VALUE) { + // Response to an exec packet log.Println("Received response to exec request") + if current == nil { + current = &Message{pack.Body} + } else { + current.Contents = append(current.Contents, pack.Body...) + } + } else if (pack.Id == TERM_ID) && (pack.Type == SERVERDATA_RESPONSE_VALUE) { + // Terminal response to an exec packet + log.Println("Received terminal response") + comm.msgch <- current c.queue.Pop() - comm.msgch <- &Message{[]*packet{resp}} + current = nil //close(comm.errch) } else { + // Some other case that we don't handle properly log.Println("Received ... fuck if I know ... I'm likely going to crash and burn!") c.queue.Pop() } @@ -106,14 +130,7 @@ // This needs help ... type Message struct { - packets []*packet -} - -func (m *Message) AllText() (s string) { - for _, p := range m.packets { - s += string(p.Body) - } - return + Contents []byte } //////////////////////////////////////////////////////////////////////////////// diff --git a/main.go b/main.go --- a/main.go +++ b/main.go @@ -60,8 +60,7 @@ msgch, errch := client.Exec(inp) select { case msg := <-msgch: - log.Println(msg) - log.Print(string(msg.AllText())) + log.Print(string(msg.Contents)) case err := <-errch: log.Panicln(err) }