Skip to content

Commit

Permalink
#9 guacamole streams are UTF-8
Browse files Browse the repository at this point in the history
  • Loading branch information
jakecoffman committed Feb 1, 2022
1 parent 702c9f2 commit 16c7931
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 10 deletions.
24 changes: 14 additions & 10 deletions stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ type Stream struct {

// if more than a single instruction is read, the rest are buffered here
parseStart int
buffer []byte
reset []byte
buffer []rune
reset []rune
}

// NewStream creates a new stream
func NewStream(conn net.Conn, timeout time.Duration) (ret *Stream) {
buffer := make([]byte, 0, MaxGuacMessage*3)
buffer := make([]rune, 0, MaxGuacMessage*3)
return &Stream{
conn: conn,
timeout: timeout,
Expand Down Expand Up @@ -111,14 +111,14 @@ func (s *Stream) ReadSome() (instruction []byte, err error) {
// instruction.
switch terminator {
case ';':
instruction = s.buffer[0:i]
instruction = []byte(string(s.buffer[0:i]))
s.parseStart = 0
s.buffer = s.buffer[i:]
return
case ',':
// keep going
default:
err = ErrServer.NewError("Element terminator of instruction was not ';' nor ','")
err = ErrServer.NewError("Element terminator of instruction was not ';' nor ',', twas " + string(terminator))
return
}
default:
Expand All @@ -128,11 +128,8 @@ func (s *Stream) ReadSome() (instruction []byte, err error) {
}
}

if cap(s.buffer) < MaxGuacMessage {
s.Flush()
}

n, err = s.conn.Read(s.buffer[len(s.buffer):cap(s.buffer)])
buffer := make([]byte, 1024)
n, err = s.conn.Read(buffer)
if err != nil && n == 0 {
switch err.(type) {
case net.Error:
Expand All @@ -150,6 +147,13 @@ func (s *Stream) ReadSome() (instruction []byte, err error) {
if n == 0 {
err = ErrServer.NewError("read 0 bytes")
}
runes := []rune(string(buffer[:n]))

if cap(s.buffer)-len(s.buffer) < len(runes) {
s.Flush()
}

n = copy(s.buffer[len(s.buffer):cap(s.buffer)], runes)
// must reslice so len is changed
s.buffer = s.buffer[:len(s.buffer)+n]
}
Expand Down
35 changes: 35 additions & 0 deletions stream_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,41 @@ func TestInstructionReader_ReadSome(t *testing.T) {
}
}

func TestInstructionReader_ReadSome_Unicode(t *testing.T) {
conn := &fakeConn{
ToRead: []byte("4.copy,1.πŸš€;4.copy"),
}
stream := NewStream(conn, 1*time.Minute)

ins, err := stream.ReadSome()

if err != nil {
t.Error("Unexpected error", err)
}
if !bytes.Equal(ins, []byte("4.copy,1.πŸš€;")) {
t.Error("Unexpected bytes returned")
}
if !stream.Available() {
t.Error("Stream has more available but returned false")
}

// Read the rest of the fragmented instruction
n := copy(conn.ToRead, ",1.πŸš€;")
conn.ToRead = conn.ToRead[:n]
conn.HasRead = false
ins, err = stream.ReadSome()

if err != nil {
t.Error("Unexpected error", err)
}
if !bytes.Equal(ins, []byte("4.copy,1.πŸš€;")) {
t.Error("Unexpected bytes returned")
}
if stream.Available() {
t.Error("Stream thinks it has more available but doesn't")
}
}

func TestInstructionReader_Flush(t *testing.T) {
s := NewStream(&fakeConn{}, time.Second)
s.buffer = s.buffer[:4]
Expand Down

0 comments on commit 16c7931

Please sign in to comment.