Skip to content
This repository has been archived by the owner on May 6, 2020. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
agent: read full data from ctl and tty channels
this patch is to read all the data sent by the proxy and to avoid
error reading more than 4096 bytes

fixes #201

Signed-off-by: Julio Montes <julio.montes@intel.com>
  • Loading branch information
Julio Montes committed Jan 25, 2018
1 parent 865a106 commit 562ee34
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 6 deletions.
27 changes: 21 additions & 6 deletions agent.go
Expand Up @@ -649,6 +649,23 @@ func findVirtualSerialPath(serialName string) (string, error) {
return "", fmt.Errorf("Could not find virtio port %s", serialName)
}

// read l bytes from r
func readAll(r io.Reader, l int) ([]byte, int, error) {
data := make([]byte, l)
var t int
for {
n, err := r.Read(data[t:])
if err != nil {
return nil, -1, err
}

t += n
if t == l {
return data, t, nil
}
}
}

func (p *pod) readCtl() (hyper.HyperCmd, []byte, error) {
buf := make([]byte, ctlHeaderSize)

Expand All @@ -669,9 +686,8 @@ func (p *pod) readCtl() (hyper.HyperCmd, []byte, error) {
return cmd, nil, nil
}

data := make([]byte, length)

n, err = p.ctl.Read(data)
var data []byte
data, n, err = readAll(p.ctl, length)
if err != nil {
return hyper.ErrorCmd, []byte{}, err
}
Expand Down Expand Up @@ -704,9 +720,8 @@ func (p *pod) readTty() (uint64, []byte, error) {
return seq, []byte{}, nil
}

data := make([]byte, length)

n, err = p.tty.Read(data)
var data []byte
data, n, err = readAll(p.tty, length)
if err != nil {
return uint64(0), []byte{}, err
}
Expand Down
159 changes: 159 additions & 0 deletions agent_test.go
Expand Up @@ -17,6 +17,7 @@
package main

import (
"encoding/binary"
"io/ioutil"
"os"
"testing"
Expand Down Expand Up @@ -153,3 +154,161 @@ func TestAgentConfigGetConfig(t *testing.T) {
})
}
}

func TestReadCtl(t *testing.T) {
f, err := ioutil.TempFile("", "ctl")
if err != nil {
t.Error(err)
}
defer f.Close()
defer os.Remove(f.Name())

hCmd := uint32(5)
p := &pod{ctl: f}

// file is empty, read should fail
_, _, err = p.readCtl()
if err == nil {
t.Error(err)
}

// no enough bytes, read should fail
buff := make([]byte, ctlHeaderSize-1)
f.Write(buff)
f.Seek(0, 0)
_, _, err = p.readCtl()
if err == nil {
t.Error(err)
}

// there is no data, read should fail
buff = make([]byte, ctlHeaderSize)
f.Seek(0, 0)
binary.BigEndian.PutUint32(buff[4:ctlHeaderSize], ctlHeaderSize+1)
f.Write(buff)
f.Seek(0, 0)
_, _, err = p.readCtl()
if err == nil {
t.Error(err)
}

bufferSizes := []uint32{0, 2, 55, 278, 698, 1056, 3598, 6527, 10830, 56386, 894305, 9652381}
for _, s := range bufferSizes {
f.Seek(0, 0)

// write command and length
buff = make([]byte, ctlHeaderSize)
binary.BigEndian.PutUint32(buff[:4], hCmd)
binary.BigEndian.PutUint32(buff[4:ctlHeaderSize], s+ctlHeaderSize)
n, err := f.Write(buff)
if err != nil {
t.Error(err)
}
if uint32(n) != uint32(ctlHeaderSize) {
t.Errorf("expected: %d, actual: %d", n, ctlHeaderSize)
}

// write data
data := make([]byte, s)
n, err = f.Write(data)
if err != nil {
t.Error(err)
}
if uint32(n) != uint32(s) {
t.Errorf("expected: %d, actual: %d", n, s)
}

f.Seek(0, 0)

c, d, err := p.readCtl()
if err != nil {
t.Error(err)
}
if uint32(hCmd) != uint32(c) {
t.Errorf("expected: %d, actual: %d", hCmd, c)
}
if s == 0 && len(d) != 0 {
t.Errorf("expected: 0, actual: %d", len(d))
} else if len(data) != len(d) {
t.Errorf("expected: %d, actual: %d", len(data), len(d))
}
}
}

func TestReadTty(t *testing.T) {
f, err := ioutil.TempFile("", "tty")
if err != nil {
t.Error(err)
}
defer f.Close()
defer os.Remove(f.Name())

seq := uint64(5)
p := &pod{tty: f}

// file is empty, read should fail
_, _, err = p.readTty()
if err == nil {
t.Error(err)
}

// no enough bytes, read should fail
buff := make([]byte, ttyHeaderSize-1)
f.Write(buff)
f.Seek(0, 0)
_, _, err = p.readTty()
if err == nil {
t.Error(err)
}

// there is no data, read should fail
buff = make([]byte, ttyHeaderSize)
f.Seek(0, 0)
binary.BigEndian.PutUint32(buff[8:ttyHeaderSize], ttyHeaderSize+1)
f.Write(buff)
f.Seek(0, 0)
_, _, err = p.readTty()
if err == nil {
t.Error(err)
}

bufferSizes := []uint32{0, 2, 55, 278, 698, 1056, 3598, 6527, 10830, 56386, 894305, 9652381}
for _, s := range bufferSizes {
f.Seek(0, 0)

// write command and length
buff = make([]byte, ttyHeaderSize)
binary.BigEndian.PutUint64(buff[:8], seq)
binary.BigEndian.PutUint32(buff[8:ttyHeaderSize], s+ttyHeaderSize)
n, err := f.Write(buff)
if err != nil {
t.Error(err)
}
if uint32(n) != uint32(ttyHeaderSize) {
t.Errorf("expected: %d, actual: %d", n, ttyHeaderSize)
}

// write data
data := make([]byte, s)
n, err = f.Write(data)
if err != nil {
t.Error(err)
}
if uint32(n) != uint32(s) {
t.Errorf("expected: %d, actual: %d", n, s)
}

f.Seek(0, 0)

c, d, err := p.readTty()
if err != nil {
t.Error(err)
}
if seq != uint64(c) {
t.Errorf("expected: %d, actual: %d", seq, c)
}
if len(data) != len(d) {
t.Errorf("expected: %d, actual: %d", len(data), len(d))
}
}
}

0 comments on commit 562ee34

Please sign in to comment.