implements terminal packets
2 files changed, 39 insertions(+), 23 deletions(-)

M gorcon/client.go
M main.go
M gorcon/client.go +38 -21
@@ 21,6 21,7 @@ const (
 type Client struct {
     net.Conn
     queue commQueue
+    sendmutex sync.Mutex
 }
 
 func NewClient(addr string) (c *Client, err error) {

          
@@ 39,32 40,43 @@ func NewClient(addr string) (c *Client, 
 }
 
 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 @@ func (c *Client) readLoop() {
             }
             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 @@ func (c *Client) readLoop() {
 
 // 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
 }
 
 ////////////////////////////////////////////////////////////////////////////////

          
M main.go +1 -2
@@ 60,8 60,7 @@ func main() {
         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)
         }