Use buffered reading and higher level APIs to detect when http response is fully parsed

This commit is contained in:
Dom Del Nano 2021-11-03 07:45:19 -07:00
parent 6e84e6d371
commit 1e4b5dd51b

View File

@ -1,8 +1,7 @@
package common package common
/* Heavily borrowed from builder/quemu/step_type_boot_command.go */
import ( import (
"bufio"
"context" "context"
"crypto/tls" "crypto/tls"
"fmt" "fmt"
@ -11,10 +10,10 @@ import (
"net" "net"
"strings" "strings"
"github.com/hashicorp/packer-plugin-sdk/bootcommand"
"github.com/hashicorp/packer-plugin-sdk/multistep" "github.com/hashicorp/packer-plugin-sdk/multistep"
"github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-sdk/template/interpolate" "github.com/hashicorp/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer-plugin-sdk/bootcommand"
"github.com/mitchellh/go-vnc" "github.com/mitchellh/go-vnc"
) )
@ -104,35 +103,40 @@ func (self *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateB
} }
// Look for \r\n\r\n sequence. Everything after the HTTP Header is for the vnc client. // Look for \r\n\r\n sequence. Everything after the HTTP Header is for the vnc client.
reader := bufio.NewReader(tlsConn)
builder := strings.Builder{} var httpResp string
buffer := make([]byte, 1)
sequenceProgress := 0
for { for {
if _, err := io.ReadFull(tlsConn, buffer); err != nil { httpResp, err = reader.ReadString('\r')
if err != nil {
err := fmt.Errorf("failed to start vnc session: %v", err) err := fmt.Errorf("failed to start vnc session: %v", err)
state.Put("error", err) state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
builder.WriteByte(buffer[0]) // Peek at the next three bytes to see if it contains the remaining \n\r\n
var b []byte
if buffer[0] == '\n' && sequenceProgress % 2 == 1 { b, err = reader.Peek(3)
sequenceProgress++ if err != nil {
} else if buffer[0] == '\r' && sequenceProgress % 2 == 0 { e := fmt.Errorf("failed to start vnc session: %v", err)
sequenceProgress++ state.Put("error", e)
} else { ui.Error(e.Error())
sequenceProgress = 0 return multistep.ActionHalt
}
if b[0] == '\n' && b[1] == '\r' && b[2] == '\n' {
if _, err = reader.Discard(3); err != nil {
e := fmt.Errorf("failed to start vnc session: %v", err)
state.Put("error", e)
ui.Error(e.Error())
return multistep.ActionHalt
} }
if sequenceProgress == 4 {
break break
} }
} }
ui.Say(fmt.Sprintf("Received response: %s", builder.String())) ui.Say(fmt.Sprintf("Received response: %s", httpResp))
vncClient, err := vnc.Client(tlsConn, &vnc.ClientConfig{Exclusive: false}) vncClient, err := vnc.Client(tlsConn, &vnc.ClientConfig{Exclusive: false})
@ -145,7 +149,6 @@ func (self *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateB
defer vncClient.Close() defer vncClient.Close()
log.Printf("Connected to the VNC console: %s", vncClient.DesktopName) log.Printf("Connected to the VNC console: %s", vncClient.DesktopName)
// find local ip // find local ip
@ -196,7 +199,6 @@ func (self *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateB
return multistep.ActionHalt return multistep.ActionHalt
} }
ui.Say("Finished typing.") ui.Say("Finished typing.")
return multistep.ActionContinue return multistep.ActionContinue