Skip to content

Commit

Permalink
remove Socket and InstructionReader struct (living on as an interface)
Browse files Browse the repository at this point in the history
  • Loading branch information
jakecoffman committed Sep 17, 2019
1 parent 1018235 commit 9c48d0d
Show file tree
Hide file tree
Showing 11 changed files with 289 additions and 308 deletions.
26 changes: 13 additions & 13 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ func NewGuacamoleClientInformation() *ClientInfo {
}
}

func assertOpcode(reader *InstructionReader, opcode string) (instruction *Instruction, err error) {
instruction, err = reader.ReadOne()
func assertOpcode(stream *Stream, opcode string) (instruction *Instruction, err error) {
instruction, err = ReadOne(stream)
if err != nil {
return
}
Expand All @@ -56,21 +56,21 @@ func assertOpcode(reader *InstructionReader, opcode string) (instruction *Instru
return
}

func ConfigureSocket(socket *Socket, config *Config, info *ClientInfo) error {
func ConfigureSocket(stream *Stream, config *Config, info *ClientInfo) error {
// Get protocol / connection ID
selectArg := config.ConnectionID
if len(selectArg) == 0 {
selectArg = config.Protocol
}

// Send requested protocol or connection ID
_, err := writeInstruction(socket, NewInstruction("select", selectArg))
_, err := writeInstruction(stream, NewInstruction("select", selectArg))
if err != nil {
return err
}

// Wait for server Args
args, err := assertOpcode(socket.InstructionReader, "args")
args, err := assertOpcode(stream, "args")
if err != nil {
return err
}
Expand All @@ -93,7 +93,7 @@ func ConfigureSocket(socket *Socket, config *Config, info *ClientInfo) error {
}

// Send size
_, err = writeInstruction(socket, NewInstruction("size",
_, err = writeInstruction(stream, NewInstruction("size",
fmt.Sprintf("%v", info.OptimalScreenWidth),
fmt.Sprintf("%v", info.OptimalScreenHeight),
fmt.Sprintf("%v", info.OptimalResolution)),
Expand All @@ -104,31 +104,31 @@ func ConfigureSocket(socket *Socket, config *Config, info *ClientInfo) error {
}

// Send supported audio formats
_, err = writeInstruction(socket, NewInstruction("audio", info.AudioMimetypes...))
_, err = writeInstruction(stream, NewInstruction("audio", info.AudioMimetypes...))
if err != nil {
return err
}

// Send supported video formats
_, err = writeInstruction(socket, NewInstruction("video", info.VideoMimetypes...))
_, err = writeInstruction(stream, NewInstruction("video", info.VideoMimetypes...))
if err != nil {
return err
}

// Send supported image formats
_, err = writeInstruction(socket, NewInstruction("image", info.ImageMimetypes...))
_, err = writeInstruction(stream, NewInstruction("image", info.ImageMimetypes...))
if err != nil {
return err
}

// Send Args
_, err = writeInstruction(socket, NewInstruction("connect", argValueS...))
_, err = writeInstruction(stream, NewInstruction("connect", argValueS...))
if err != nil {
return err
}

// Wait for ready, store ID
ready, err := assertOpcode(socket.InstructionReader, "ready")
ready, err := assertOpcode(stream, "ready")
if err != nil {
return err
}
Expand All @@ -139,8 +139,8 @@ func ConfigureSocket(socket *Socket, config *Config, info *ClientInfo) error {
return err
}

socket.InstructionReader.Flush()
socket.ID = readyArgs[0]
stream.Flush()
stream.ConnectionID = readyArgs[0]

return nil
}
Expand Down
2 changes: 1 addition & 1 deletion httpTunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
* information is not necessary for tunnels associated with WebSocket
* connections, as each WebSocket connection has its own read thread which
* continuously checks the state of the tunnel and which will automatically
* timeout when the underlying socket times out, but the HTTP tunnel has no
* timeout when the underlying stream times out, but the HTTP tunnel has no
* such thread. Because the HTTP tunnel requires the stream to be split across
* multiple requests, tracking of activity on the tunnel must be performed
* independently of the HTTP requests.
Expand Down
9 changes: 4 additions & 5 deletions httpTunnelServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,11 @@ func (s *HttpTunnelServer) doRead(response http.ResponseWriter, request *http.Re
}

// writeSome drains the guacd buffer holding instructions into the response
func (s *HttpTunnelServer) writeSome(response http.ResponseWriter, reader *InstructionReader, tunnel Tunnel) (err error) {
func (s *HttpTunnelServer) writeSome(response http.ResponseWriter, guacd InstructionReader, tunnel Tunnel) (err error) {
var message []byte

// For all messages, until another stream is ready (we send at least one message)
for {
message, err = reader.ReadSome()
message, err = guacd.ReadSome()
if err != nil {
s.deregisterTunnel(tunnel)
tunnel.Close()
Expand All @@ -203,13 +202,13 @@ func (s *HttpTunnelServer) writeSome(response http.ResponseWriter, reader *Instr
return
}

if !reader.Available() {
if !guacd.Available() {
if v, ok := response.(http.Flusher); ok {
v.Flush()
}
}

// No more messages another stream can take over
// No more messages another guacd can take over
if tunnel.HasQueuedReaderThreads() {
break
}
Expand Down
77 changes: 73 additions & 4 deletions instruction.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@ package guac

import (
"fmt"
"strconv"
)

// Instruction instruction container
// * An abstract representation of a Guacamole instruction, as defined by the
// * Guacamole protocol.
// Instruction represents a Guacamole instruction
type Instruction struct {
Opcode string
Args []string
ProtocolForm string
}

// NewInstruction Construct function
// NewInstruction creates an instruction
func NewInstruction(opcode string, args ...string) *Instruction {
return &Instruction{
Opcode: opcode,
Args: args,
}
}

// String returns the on-wire representation of the instruction
func (opt *Instruction) String() string {
if len(opt.ProtocolForm) > 0 {
return opt.ProtocolForm
Expand All @@ -34,3 +34,72 @@ func (opt *Instruction) String() string {

return opt.ProtocolForm
}

// ReadOne takes an instruction from the stream and parses it into an Instruction
func ReadOne(stream *Stream) (instruction *Instruction, err error) {
var instructionBuffer []byte

// Get instruction
instructionBuffer, err = stream.ReadSome()

// If EOF, return EOF
if err != nil {
return
}

// Start of element
elementStart := 0

// Build list of elements
elements := make([]string, 0, 1)
for elementStart < len(instructionBuffer) {
// Find end of length
lengthEnd := -1
for i := elementStart; i < len(instructionBuffer); i++ {
if instructionBuffer[i] == '.' {
lengthEnd = i
break
}
}
// read() is required to return a complete instruction. If it does
// not, this is a severe internal error.
if lengthEnd == -1 {
err = ErrServer.NewError("ReadSome returned incomplete instruction.")
return
}

// Parse length
length, e := strconv.Atoi(string(instructionBuffer[elementStart:lengthEnd]))
if e != nil {
err = ErrServer.NewError("ReadSome returned wrong pattern instruction.", e.Error())
return
}

// Parse element from just after period
elementStart = lengthEnd + 1
element := string(instructionBuffer[elementStart : elementStart+length])

// Append element to list of elements
elements = append(elements, element)

// ReadSome terminator after element
elementStart += length
terminator := instructionBuffer[elementStart]

// Continue reading instructions after terminator
elementStart++

// If we've reached the end of the instruction
if terminator == ';' {
break
}

}

// Pull Opcode off elements list
// Create instruction
instruction = NewInstruction(elements[0], elements[1:]...)

// Return parsed instruction
return
}
Loading

0 comments on commit 9c48d0d

Please sign in to comment.