diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 7d833ee1..a6cb8d55 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,7 +1,7 @@ { "ImportPath": "github.com/xenserver/packer-builder-xenserver", "GoVersion": "go1.6", - "GodepVersion": "v74", + "GodepVersion": "v75", "Packages": [ "./..." ], @@ -64,6 +64,10 @@ "ImportPath": "github.com/mitchellh/go-fs/fat", "Rev": "a34c1b9334e86165685a9449b782f20465eb8c69" }, + { + "ImportPath": "github.com/mitchellh/go-vnc", + "Rev": "723ed9867aed0f3209a81151e52ddc61681f0b01" + }, { "ImportPath": "github.com/mitchellh/iochan", "Rev": "87b45ffd0e9581375c491fef3d32130bb15c5bd7" @@ -161,6 +165,11 @@ "ImportPath": "github.com/packer-community/winrmcp/winrmcp", "Rev": "f1bcf36a69fa2945e65dd099eee11b560fbd3346" }, + { + "ImportPath": "github.com/pkg/errors", + "Comment": "v0.8.0-2-g248dadf", + "Rev": "248dadf4e9068a0b3e79f02ed0a610d935de5302" + }, { "ImportPath": "github.com/pkg/sftp", "Rev": "e84cc8c755ca39b7b64f510fe1fffc1b51f210a5" diff --git a/build.sh b/build.sh index efc343e7..83a77bd5 100755 --- a/build.sh +++ b/build.sh @@ -15,6 +15,9 @@ rm -rf pkg/* rm -rf $GOPATH/pkg/* mkdir -p bin/ +# Fix for ./build.sh: gox: command not found +go get github.com/mitchellh/gox + gox \ -os="${XC_OS}" \ -arch="${XC_ARCH}" \ diff --git a/vendor/github.com/mitchellh/go-vnc/LICENSE b/vendor/github.com/mitchellh/go-vnc/LICENSE new file mode 100644 index 00000000..f9c841a5 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/go-vnc/README.md b/vendor/github.com/mitchellh/go-vnc/README.md new file mode 100644 index 00000000..cb0575b9 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/README.md @@ -0,0 +1,16 @@ +# VNC Library for Go + +go-vnc is a VNC library for Go, initially supporting VNC clients but +with the goal of eventually implementing a VNC server. + +This library implements [RFC 6143](http://tools.ietf.org/html/rfc6143). + +## Usage & Installation + +The library is installable via standard `go get`. The package name is `vnc`. + +``` +$ go get github.com/mitchellh/go-vnc +``` + +Documentation is available on GoDoc: http://godoc.org/github.com/mitchellh/go-vnc diff --git a/vendor/github.com/mitchellh/go-vnc/client.go b/vendor/github.com/mitchellh/go-vnc/client.go new file mode 100644 index 00000000..91402c94 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/client.go @@ -0,0 +1,482 @@ +// Package vnc implements a VNC client. +// +// References: +// [PROTOCOL]: http://tools.ietf.org/html/rfc6143 +package vnc + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "net" + "unicode" +) + +type ClientConn struct { + c net.Conn + config *ClientConfig + + // If the pixel format uses a color map, then this is the color + // map that is used. This should not be modified directly, since + // the data comes from the server. + ColorMap [256]Color + + // Encodings supported by the client. This should not be modified + // directly. Instead, SetEncodings should be used. + Encs []Encoding + + // Width of the frame buffer in pixels, sent from the server. + FrameBufferWidth uint16 + + // Height of the frame buffer in pixels, sent from the server. + FrameBufferHeight uint16 + + // Name associated with the desktop, sent from the server. + DesktopName string + + // The pixel format associated with the connection. This shouldn't + // be modified. If you wish to set a new pixel format, use the + // SetPixelFormat method. + PixelFormat PixelFormat +} + +// A ClientConfig structure is used to configure a ClientConn. After +// one has been passed to initialize a connection, it must not be modified. +type ClientConfig struct { + // A slice of ClientAuth methods. Only the first instance that is + // suitable by the server will be used to authenticate. + Auth []ClientAuth + + // Exclusive determines whether the connection is shared with other + // clients. If true, then all other clients connected will be + // disconnected when a connection is established to the VNC server. + Exclusive bool + + // The channel that all messages received from the server will be + // sent on. If the channel blocks, then the goroutine reading data + // from the VNC server may block indefinitely. It is up to the user + // of the library to ensure that this channel is properly read. + // If this is not set, then all messages will be discarded. + ServerMessageCh chan<- ServerMessage + + // A slice of supported messages that can be read from the server. + // This only needs to contain NEW server messages, and doesn't + // need to explicitly contain the RFC-required messages. + ServerMessages []ServerMessage +} + +func Client(c net.Conn, cfg *ClientConfig) (*ClientConn, error) { + conn := &ClientConn{ + c: c, + config: cfg, + } + + if err := conn.handshake(); err != nil { + conn.Close() + return nil, err + } + + go conn.mainLoop() + + return conn, nil +} + +func (c *ClientConn) Close() error { + return c.c.Close() +} + +// CutText tells the server that the client has new text in its cut buffer. +// The text string MUST only contain Latin-1 characters. This encoding +// is compatible with Go's native string format, but can only use up to +// unicode.MaxLatin values. +// +// See RFC 6143 Section 7.5.6 +func (c *ClientConn) CutText(text string) error { + var buf bytes.Buffer + + // This is the fixed size data we'll send + fixedData := []interface{}{ + uint8(6), + uint8(0), + uint8(0), + uint8(0), + uint32(len(text)), + } + + for _, val := range fixedData { + if err := binary.Write(&buf, binary.BigEndian, val); err != nil { + return err + } + } + + for _, char := range text { + if char > unicode.MaxLatin1 { + return fmt.Errorf("Character '%s' is not valid Latin-1", char) + } + + if err := binary.Write(&buf, binary.BigEndian, uint8(char)); err != nil { + return err + } + } + + dataLength := 8 + len(text) + if _, err := c.c.Write(buf.Bytes()[0:dataLength]); err != nil { + return err + } + + return nil +} + +// Requests a framebuffer update from the server. There may be an indefinite +// time between the request and the actual framebuffer update being +// received. +// +// See RFC 6143 Section 7.5.3 +func (c *ClientConn) FramebufferUpdateRequest(incremental bool, x, y, width, height uint16) error { + var buf bytes.Buffer + var incrementalByte uint8 = 0 + + if incremental { + incrementalByte = 1 + } + + data := []interface{}{ + uint8(3), + incrementalByte, + x, y, width, height, + } + + for _, val := range data { + if err := binary.Write(&buf, binary.BigEndian, val); err != nil { + return err + } + } + + if _, err := c.c.Write(buf.Bytes()[0:10]); err != nil { + return err + } + + return nil +} + +// KeyEvent indiciates a key press or release and sends it to the server. +// The key is indicated using the X Window System "keysym" value. Use +// Google to find a reference of these values. To simulate a key press, +// you must send a key with both a down event, and a non-down event. +// +// See 7.5.4. +func (c *ClientConn) KeyEvent(keysym uint32, down bool) error { + var downFlag uint8 = 0 + if down { + downFlag = 1 + } + + data := []interface{}{ + uint8(4), + downFlag, + uint8(0), + uint8(0), + keysym, + } + + for _, val := range data { + if err := binary.Write(c.c, binary.BigEndian, val); err != nil { + return err + } + } + + return nil +} + +// PointerEvent indicates that pointer movement or a pointer button +// press or release. +// +// The mask is a bitwise mask of various ButtonMask values. When a button +// is set, it is pressed, when it is unset, it is released. +// +// See RFC 6143 Section 7.5.5 +func (c *ClientConn) PointerEvent(mask ButtonMask, x, y uint16) error { + var buf bytes.Buffer + + data := []interface{}{ + uint8(5), + uint8(mask), + x, + y, + } + + for _, val := range data { + if err := binary.Write(&buf, binary.BigEndian, val); err != nil { + return err + } + } + + if _, err := c.c.Write(buf.Bytes()[0:6]); err != nil { + return err + } + + return nil +} + +// SetEncodings sets the encoding types in which the pixel data can +// be sent from the server. After calling this method, the encs slice +// given should not be modified. +// +// See RFC 6143 Section 7.5.2 +func (c *ClientConn) SetEncodings(encs []Encoding) error { + data := make([]interface{}, 3+len(encs)) + data[0] = uint8(2) + data[1] = uint8(0) + data[2] = uint16(len(encs)) + + for i, enc := range encs { + data[3+i] = int32(enc.Type()) + } + + var buf bytes.Buffer + for _, val := range data { + if err := binary.Write(&buf, binary.BigEndian, val); err != nil { + return err + } + } + + dataLength := 4 + (4 * len(encs)) + if _, err := c.c.Write(buf.Bytes()[0:dataLength]); err != nil { + return err + } + + c.Encs = encs + + return nil +} + +// SetPixelFormat sets the format in which pixel values should be sent +// in FramebufferUpdate messages from the server. +// +// See RFC 6143 Section 7.5.1 +func (c *ClientConn) SetPixelFormat(format *PixelFormat) error { + var keyEvent [20]byte + keyEvent[0] = 0 + + pfBytes, err := writePixelFormat(format) + if err != nil { + return err + } + + // Copy the pixel format bytes into the proper slice location + copy(keyEvent[4:], pfBytes) + + // Send the data down the connection + if _, err := c.c.Write(keyEvent[:]); err != nil { + return err + } + + // Reset the color map as according to RFC. + var newColorMap [256]Color + c.ColorMap = newColorMap + + return nil +} + +const pvLen = 12 // ProtocolVersion message length. + +func parseProtocolVersion(pv []byte) (uint, uint, error) { + var major, minor uint + + if len(pv) < pvLen { + return 0, 0, fmt.Errorf("ProtocolVersion message too short (%v < %v)", len(pv), pvLen) + } + + l, err := fmt.Sscanf(string(pv), "RFB %d.%d\n", &major, &minor) + if l != 2 { + return 0, 0, fmt.Errorf("error parsing ProtocolVersion.") + } + if err != nil { + return 0, 0, err + } + + return major, minor, nil +} + +func (c *ClientConn) handshake() error { + var protocolVersion [pvLen]byte + + // 7.1.1, read the ProtocolVersion message sent by the server. + if _, err := io.ReadFull(c.c, protocolVersion[:]); err != nil { + return err + } + + maxMajor, maxMinor, err := parseProtocolVersion(protocolVersion[:]) + if err != nil { + return err + } + if maxMajor < 3 { + return fmt.Errorf("unsupported major version, less than 3: %d", maxMajor) + } + if maxMinor < 8 { + return fmt.Errorf("unsupported minor version, less than 8: %d", maxMinor) + } + + // Respond with the version we will support + if _, err = c.c.Write([]byte("RFB 003.008\n")); err != nil { + return err + } + + // 7.1.2 Security Handshake from server + var numSecurityTypes uint8 + if err = binary.Read(c.c, binary.BigEndian, &numSecurityTypes); err != nil { + return err + } + + if numSecurityTypes == 0 { + return fmt.Errorf("no security types: %s", c.readErrorReason()) + } + + securityTypes := make([]uint8, numSecurityTypes) + if err = binary.Read(c.c, binary.BigEndian, &securityTypes); err != nil { + return err + } + + clientSecurityTypes := c.config.Auth + if clientSecurityTypes == nil { + clientSecurityTypes = []ClientAuth{new(ClientAuthNone)} + } + + var auth ClientAuth +FindAuth: + for _, curAuth := range clientSecurityTypes { + for _, securityType := range securityTypes { + if curAuth.SecurityType() == securityType { + // We use the first matching supported authentication + auth = curAuth + break FindAuth + } + } + } + + if auth == nil { + return fmt.Errorf("no suitable auth schemes found. server supported: %#v", securityTypes) + } + + // Respond back with the security type we'll use + if err = binary.Write(c.c, binary.BigEndian, auth.SecurityType()); err != nil { + return err + } + + if err = auth.Handshake(c.c); err != nil { + return err + } + + // 7.1.3 SecurityResult Handshake + var securityResult uint32 + if err = binary.Read(c.c, binary.BigEndian, &securityResult); err != nil { + return err + } + + if securityResult == 1 { + return fmt.Errorf("security handshake failed: %s", c.readErrorReason()) + } + + // 7.3.1 ClientInit + var sharedFlag uint8 = 1 + if c.config.Exclusive { + sharedFlag = 0 + } + + if err = binary.Write(c.c, binary.BigEndian, sharedFlag); err != nil { + return err + } + + // 7.3.2 ServerInit + if err = binary.Read(c.c, binary.BigEndian, &c.FrameBufferWidth); err != nil { + return err + } + + if err = binary.Read(c.c, binary.BigEndian, &c.FrameBufferHeight); err != nil { + return err + } + + // Read the pixel format + if err = readPixelFormat(c.c, &c.PixelFormat); err != nil { + return err + } + + var nameLength uint32 + if err = binary.Read(c.c, binary.BigEndian, &nameLength); err != nil { + return err + } + + nameBytes := make([]uint8, nameLength) + if err = binary.Read(c.c, binary.BigEndian, &nameBytes); err != nil { + return err + } + + c.DesktopName = string(nameBytes) + + return nil +} + +// mainLoop reads messages sent from the server and routes them to the +// proper channels for users of the client to read. +func (c *ClientConn) mainLoop() { + defer c.Close() + + // Build the map of available server messages + typeMap := make(map[uint8]ServerMessage) + + defaultMessages := []ServerMessage{ + new(FramebufferUpdateMessage), + new(SetColorMapEntriesMessage), + new(BellMessage), + new(ServerCutTextMessage), + } + + for _, msg := range defaultMessages { + typeMap[msg.Type()] = msg + } + + if c.config.ServerMessages != nil { + for _, msg := range c.config.ServerMessages { + typeMap[msg.Type()] = msg + } + } + + for { + var messageType uint8 + if err := binary.Read(c.c, binary.BigEndian, &messageType); err != nil { + break + } + + msg, ok := typeMap[messageType] + if !ok { + // Unsupported message type! Bad! + break + } + + parsedMsg, err := msg.Read(c, c.c) + if err != nil { + break + } + + if c.config.ServerMessageCh == nil { + continue + } + + c.config.ServerMessageCh <- parsedMsg + } +} + +func (c *ClientConn) readErrorReason() string { + var reasonLen uint32 + if err := binary.Read(c.c, binary.BigEndian, &reasonLen); err != nil { + return "" + } + + reason := make([]uint8, reasonLen) + if err := binary.Read(c.c, binary.BigEndian, &reason); err != nil { + return "" + } + + return string(reason) +} diff --git a/vendor/github.com/mitchellh/go-vnc/client_auth.go b/vendor/github.com/mitchellh/go-vnc/client_auth.go new file mode 100644 index 00000000..601e470e --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/client_auth.go @@ -0,0 +1,124 @@ +package vnc + +import ( + "net" + + "crypto/des" + "encoding/binary" +) + +// A ClientAuth implements a method of authenticating with a remote server. +type ClientAuth interface { + // SecurityType returns the byte identifier sent by the server to + // identify this authentication scheme. + SecurityType() uint8 + + // Handshake is called when the authentication handshake should be + // performed, as part of the general RFB handshake. (see 7.2.1) + Handshake(net.Conn) error +} + +// ClientAuthNone is the "none" authentication. See 7.2.1 +type ClientAuthNone byte + +func (*ClientAuthNone) SecurityType() uint8 { + return 1 +} + +func (*ClientAuthNone) Handshake(net.Conn) error { + return nil +} + +// PasswordAuth is VNC authentication, 7.2.2 +type PasswordAuth struct { + Password string +} + +func (p *PasswordAuth) SecurityType() uint8 { + return 2 +} + +func (p *PasswordAuth) Handshake(c net.Conn) error { + randomValue := make([]uint8, 16) + if err := binary.Read(c, binary.BigEndian, &randomValue); err != nil { + return err + } + + crypted, err := p.encrypt(p.Password, randomValue) + + if err != nil { + return err + } + + if err := binary.Write(c, binary.BigEndian, &crypted); err != nil { + return err + } + + return nil +} + +func (p *PasswordAuth) reverseBits(b byte) byte { + var reverse = [256]int{ + 0, 128, 64, 192, 32, 160, 96, 224, + 16, 144, 80, 208, 48, 176, 112, 240, + 8, 136, 72, 200, 40, 168, 104, 232, + 24, 152, 88, 216, 56, 184, 120, 248, + 4, 132, 68, 196, 36, 164, 100, 228, + 20, 148, 84, 212, 52, 180, 116, 244, + 12, 140, 76, 204, 44, 172, 108, 236, + 28, 156, 92, 220, 60, 188, 124, 252, + 2, 130, 66, 194, 34, 162, 98, 226, + 18, 146, 82, 210, 50, 178, 114, 242, + 10, 138, 74, 202, 42, 170, 106, 234, + 26, 154, 90, 218, 58, 186, 122, 250, + 6, 134, 70, 198, 38, 166, 102, 230, + 22, 150, 86, 214, 54, 182, 118, 246, + 14, 142, 78, 206, 46, 174, 110, 238, + 30, 158, 94, 222, 62, 190, 126, 254, + 1, 129, 65, 193, 33, 161, 97, 225, + 17, 145, 81, 209, 49, 177, 113, 241, + 9, 137, 73, 201, 41, 169, 105, 233, + 25, 153, 89, 217, 57, 185, 121, 249, + 5, 133, 69, 197, 37, 165, 101, 229, + 21, 149, 85, 213, 53, 181, 117, 245, + 13, 141, 77, 205, 45, 173, 109, 237, + 29, 157, 93, 221, 61, 189, 125, 253, + 3, 131, 67, 195, 35, 163, 99, 227, + 19, 147, 83, 211, 51, 179, 115, 243, + 11, 139, 75, 203, 43, 171, 107, 235, + 27, 155, 91, 219, 59, 187, 123, 251, + 7, 135, 71, 199, 39, 167, 103, 231, + 23, 151, 87, 215, 55, 183, 119, 247, + 15, 143, 79, 207, 47, 175, 111, 239, + 31, 159, 95, 223, 63, 191, 127, 255, + } + + return byte(reverse[int(b)]) +} + +func (p *PasswordAuth) encrypt(key string, bytes []byte) ([]byte, error) { + keyBytes := []byte{0, 0, 0, 0, 0, 0, 0, 0} + + if len(key) > 8 { + key = key[:8] + } + + for i := 0; i < len(key); i++ { + keyBytes[i] = p.reverseBits(key[i]) + } + + block, err := des.NewCipher(keyBytes) + + if err != nil { + return nil, err + } + + result1 := make([]byte, 8) + block.Encrypt(result1, bytes) + result2 := make([]byte, 8) + block.Encrypt(result2, bytes[8:]) + + crypted := append(result1, result2...) + + return crypted, nil +} diff --git a/vendor/github.com/mitchellh/go-vnc/color.go b/vendor/github.com/mitchellh/go-vnc/color.go new file mode 100644 index 00000000..30df4673 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/color.go @@ -0,0 +1,6 @@ +package vnc + +// Color represents a single color in a color map. +type Color struct { + R, G, B uint16 +} diff --git a/vendor/github.com/mitchellh/go-vnc/encoding.go b/vendor/github.com/mitchellh/go-vnc/encoding.go new file mode 100644 index 00000000..71985957 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/encoding.go @@ -0,0 +1,69 @@ +package vnc + +import ( + "encoding/binary" + "io" +) + +// An Encoding implements a method for encoding pixel data that is +// sent by the server to the client. +type Encoding interface { + // The number that uniquely identifies this encoding type. + Type() int32 + + // Read reads the contents of the encoded pixel data from the reader. + // This should return a new Encoding implementation that contains + // the proper data. + Read(*ClientConn, *Rectangle, io.Reader) (Encoding, error) +} + +// RawEncoding is raw pixel data sent by the server. +// +// See RFC 6143 Section 7.7.1 +type RawEncoding struct { + Colors []Color +} + +func (*RawEncoding) Type() int32 { + return 0 +} + +func (*RawEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) { + bytesPerPixel := c.PixelFormat.BPP / 8 + pixelBytes := make([]uint8, bytesPerPixel) + + var byteOrder binary.ByteOrder = binary.LittleEndian + if c.PixelFormat.BigEndian { + byteOrder = binary.BigEndian + } + + colors := make([]Color, int(rect.Height)*int(rect.Width)) + + for y := uint16(0); y < rect.Height; y++ { + for x := uint16(0); x < rect.Width; x++ { + if _, err := io.ReadFull(r, pixelBytes); err != nil { + return nil, err + } + + var rawPixel uint32 + if c.PixelFormat.BPP == 8 { + rawPixel = uint32(pixelBytes[0]) + } else if c.PixelFormat.BPP == 16 { + rawPixel = uint32(byteOrder.Uint16(pixelBytes)) + } else if c.PixelFormat.BPP == 32 { + rawPixel = byteOrder.Uint32(pixelBytes) + } + + color := &colors[int(y)*int(rect.Width)+int(x)] + if c.PixelFormat.TrueColor { + color.R = uint16((rawPixel >> c.PixelFormat.RedShift) & uint32(c.PixelFormat.RedMax)) + color.G = uint16((rawPixel >> c.PixelFormat.GreenShift) & uint32(c.PixelFormat.GreenMax)) + color.B = uint16((rawPixel >> c.PixelFormat.BlueShift) & uint32(c.PixelFormat.BlueMax)) + } else { + *color = c.ColorMap[rawPixel] + } + } + } + + return &RawEncoding{colors}, nil +} diff --git a/vendor/github.com/mitchellh/go-vnc/pixel_format.go b/vendor/github.com/mitchellh/go-vnc/pixel_format.go new file mode 100644 index 00000000..ff8edbff --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/pixel_format.go @@ -0,0 +1,151 @@ +package vnc + +import ( + "bytes" + "encoding/binary" + "io" +) + +// PixelFormat describes the way a pixel is formatted for a VNC connection. +// +// See RFC 6143 Section 7.4 for information on each of the fields. +type PixelFormat struct { + BPP uint8 + Depth uint8 + BigEndian bool + TrueColor bool + RedMax uint16 + GreenMax uint16 + BlueMax uint16 + RedShift uint8 + GreenShift uint8 + BlueShift uint8 +} + +func readPixelFormat(r io.Reader, result *PixelFormat) error { + var rawPixelFormat [16]byte + if _, err := io.ReadFull(r, rawPixelFormat[:]); err != nil { + return err + } + + var pfBoolByte uint8 + brPF := bytes.NewReader(rawPixelFormat[:]) + if err := binary.Read(brPF, binary.BigEndian, &result.BPP); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &result.Depth); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil { + return err + } + + if pfBoolByte != 0 { + // Big endian is true + result.BigEndian = true + } + + if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil { + return err + } + + if pfBoolByte != 0 { + // True Color is true. So we also have to read all the color max & shifts. + result.TrueColor = true + + if err := binary.Read(brPF, binary.BigEndian, &result.RedMax); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &result.GreenMax); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &result.BlueMax); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &result.RedShift); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &result.GreenShift); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &result.BlueShift); err != nil { + return err + } + } + + return nil +} + +func writePixelFormat(format *PixelFormat) ([]byte, error) { + var buf bytes.Buffer + + // Byte 1 + if err := binary.Write(&buf, binary.BigEndian, format.BPP); err != nil { + return nil, err + } + + // Byte 2 + if err := binary.Write(&buf, binary.BigEndian, format.Depth); err != nil { + return nil, err + } + + var boolByte byte + if format.BigEndian { + boolByte = 1 + } else { + boolByte = 0 + } + + // Byte 3 (BigEndian) + if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil { + return nil, err + } + + if format.TrueColor { + boolByte = 1 + } else { + boolByte = 0 + } + + // Byte 4 (TrueColor) + if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil { + return nil, err + } + + // If we have true color enabled then we have to fill in the rest of the + // structure with the color values. + if format.TrueColor { + if err := binary.Write(&buf, binary.BigEndian, format.RedMax); err != nil { + return nil, err + } + + if err := binary.Write(&buf, binary.BigEndian, format.GreenMax); err != nil { + return nil, err + } + + if err := binary.Write(&buf, binary.BigEndian, format.BlueMax); err != nil { + return nil, err + } + + if err := binary.Write(&buf, binary.BigEndian, format.RedShift); err != nil { + return nil, err + } + + if err := binary.Write(&buf, binary.BigEndian, format.GreenShift); err != nil { + return nil, err + } + + if err := binary.Write(&buf, binary.BigEndian, format.BlueShift); err != nil { + return nil, err + } + } + + return buf.Bytes()[0:16], nil +} diff --git a/vendor/github.com/mitchellh/go-vnc/pointer.go b/vendor/github.com/mitchellh/go-vnc/pointer.go new file mode 100644 index 00000000..86d84e39 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/pointer.go @@ -0,0 +1,16 @@ +package vnc + +// ButtonMask represents a mask of pointer presses/releases. +type ButtonMask uint8 + +// All available button mask components. +const ( + ButtonLeft ButtonMask = 1 << iota + ButtonMiddle + ButtonRight + Button4 + Button5 + Button6 + Button7 + Button8 +) diff --git a/vendor/github.com/mitchellh/go-vnc/server_messages.go b/vendor/github.com/mitchellh/go-vnc/server_messages.go new file mode 100644 index 00000000..c0aae566 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/server_messages.go @@ -0,0 +1,192 @@ +package vnc + +import ( + "encoding/binary" + "fmt" + "io" +) + +// A ServerMessage implements a message sent from the server to the client. +type ServerMessage interface { + // The type of the message that is sent down on the wire. + Type() uint8 + + // Read reads the contents of the message from the reader. At the point + // this is called, the message type has already been read from the reader. + // This should return a new ServerMessage that is the appropriate type. + Read(*ClientConn, io.Reader) (ServerMessage, error) +} + +// FramebufferUpdateMessage consists of a sequence of rectangles of +// pixel data that the client should put into its framebuffer. +type FramebufferUpdateMessage struct { + Rectangles []Rectangle +} + +// Rectangle represents a rectangle of pixel data. +type Rectangle struct { + X uint16 + Y uint16 + Width uint16 + Height uint16 + Enc Encoding +} + +func (*FramebufferUpdateMessage) Type() uint8 { + return 0 +} + +func (*FramebufferUpdateMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) { + // Read off the padding + var padding [1]byte + if _, err := io.ReadFull(r, padding[:]); err != nil { + return nil, err + } + + var numRects uint16 + if err := binary.Read(r, binary.BigEndian, &numRects); err != nil { + return nil, err + } + + // Build the map of encodings supported + encMap := make(map[int32]Encoding) + for _, enc := range c.Encs { + encMap[enc.Type()] = enc + } + + // We must always support the raw encoding + rawEnc := new(RawEncoding) + encMap[rawEnc.Type()] = rawEnc + + rects := make([]Rectangle, numRects) + for i := uint16(0); i < numRects; i++ { + var encodingType int32 + + rect := &rects[i] + data := []interface{}{ + &rect.X, + &rect.Y, + &rect.Width, + &rect.Height, + &encodingType, + } + + for _, val := range data { + if err := binary.Read(r, binary.BigEndian, val); err != nil { + return nil, err + } + } + + enc, ok := encMap[encodingType] + if !ok { + return nil, fmt.Errorf("unsupported encoding type: %d", encodingType) + } + + var err error + rect.Enc, err = enc.Read(c, rect, r) + if err != nil { + return nil, err + } + } + + return &FramebufferUpdateMessage{rects}, nil +} + +// SetColorMapEntriesMessage is sent by the server to set values into +// the color map. This message will automatically update the color map +// for the associated connection, but contains the color change data +// if the consumer wants to read it. +// +// See RFC 6143 Section 7.6.2 +type SetColorMapEntriesMessage struct { + FirstColor uint16 + Colors []Color +} + +func (*SetColorMapEntriesMessage) Type() uint8 { + return 1 +} + +func (*SetColorMapEntriesMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) { + // Read off the padding + var padding [1]byte + if _, err := io.ReadFull(r, padding[:]); err != nil { + return nil, err + } + + var result SetColorMapEntriesMessage + if err := binary.Read(r, binary.BigEndian, &result.FirstColor); err != nil { + return nil, err + } + + var numColors uint16 + if err := binary.Read(r, binary.BigEndian, &numColors); err != nil { + return nil, err + } + + result.Colors = make([]Color, numColors) + for i := uint16(0); i < numColors; i++ { + + color := &result.Colors[i] + data := []interface{}{ + &color.R, + &color.G, + &color.B, + } + + for _, val := range data { + if err := binary.Read(r, binary.BigEndian, val); err != nil { + return nil, err + } + } + + // Update the connection's color map + c.ColorMap[result.FirstColor+i] = *color + } + + return &result, nil +} + +// Bell signals that an audible bell should be made on the client. +// +// See RFC 6143 Section 7.6.3 +type BellMessage byte + +func (*BellMessage) Type() uint8 { + return 2 +} + +func (*BellMessage) Read(*ClientConn, io.Reader) (ServerMessage, error) { + return new(BellMessage), nil +} + +// ServerCutTextMessage indicates the server has new text in the cut buffer. +// +// See RFC 6143 Section 7.6.4 +type ServerCutTextMessage struct { + Text string +} + +func (*ServerCutTextMessage) Type() uint8 { + return 3 +} + +func (*ServerCutTextMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) { + // Read off the padding + var padding [1]byte + if _, err := io.ReadFull(r, padding[:]); err != nil { + return nil, err + } + + var textLength uint32 + if err := binary.Read(r, binary.BigEndian, &textLength); err != nil { + return nil, err + } + + textBytes := make([]uint8, textLength) + if err := binary.Read(r, binary.BigEndian, &textBytes); err != nil { + return nil, err + } + + return &ServerCutTextMessage{string(textBytes)}, nil +} diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml index 024e2846..567ccdbf 100644 --- a/vendor/github.com/pkg/errors/.travis.yml +++ b/vendor/github.com/pkg/errors/.travis.yml @@ -3,7 +3,8 @@ go_import_path: github.com/pkg/errors go: - 1.4.3 - 1.5.4 - - 1.6.2 + - 1.6.3 + - 1.7.3 - tip script: diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md index 6ea6422e..273db3c9 100644 --- a/vendor/github.com/pkg/errors/README.md +++ b/vendor/github.com/pkg/errors/README.md @@ -2,6 +2,8 @@ Package errors provides simple error handling primitives. +`go get github.com/pkg/errors` + The traditional error handling idiom in Go is roughly akin to ```go if err != nil { diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go index 6c45c8dc..842ee804 100644 --- a/vendor/github.com/pkg/errors/errors.go +++ b/vendor/github.com/pkg/errors/errors.go @@ -14,13 +14,18 @@ // Adding context to an error // // The errors.Wrap function returns a new error that adds context to the -// original error. For example +// original error by recording a stack trace at the point Wrap is called, +// and the supplied message. For example // // _, err := ioutil.ReadAll(r) // if err != nil { // return errors.Wrap(err, "read failed") // } // +// If additional control is required the errors.WithStack and errors.WithMessage +// functions destructure errors.Wrap into its component operations of annotating +// an error with a stack trace and an a message, respectively. +// // Retrieving the cause of an error // // Using errors.Wrap constructs a stack of errors, adding context to the @@ -28,7 +33,7 @@ // to reverse the operation of errors.Wrap to retrieve the original error // for inspection. Any error value which implements this interface // -// type Causer interface { +// type causer interface { // Cause() error // } // @@ -43,6 +48,9 @@ // // unknown error // } // +// causer interface is not exported by this package, but is considered a part +// of stable public API. +// // Formatted printing of errors // // All error values returned from this package implement fmt.Formatter and can @@ -77,6 +85,9 @@ // } // } // +// stackTracer interface is not exported by this package, but is considered a part +// of stable public API. +// // See the documentation for Frame.Format for more details. package errors @@ -85,68 +96,74 @@ import ( "io" ) -// _error is an error implementation returned by New and Errorf -// that implements its own fmt.Formatter. -type _error struct { +// New returns an error with the supplied message. +// New also records the stack trace at the point it was called. +func New(message string) error { + return &fundamental{ + msg: message, + stack: callers(), + } +} + +// Errorf formats according to a format specifier and returns the string +// as a value that satisfies error. +// Errorf also records the stack trace at the point it was called. +func Errorf(format string, args ...interface{}) error { + return &fundamental{ + msg: fmt.Sprintf(format, args...), + stack: callers(), + } +} + +// fundamental is an error that has a message and a stack, but no caller. +type fundamental struct { msg string *stack } -func (e _error) Error() string { return e.msg } +func (f *fundamental) Error() string { return f.msg } -func (e _error) Format(s fmt.State, verb rune) { +func (f *fundamental) Format(s fmt.State, verb rune) { switch verb { case 'v': if s.Flag('+') { - io.WriteString(s, e.msg) - fmt.Fprintf(s, "%+v", e.StackTrace()) + io.WriteString(s, f.msg) + f.stack.Format(s, verb) return } fallthrough case 's': - io.WriteString(s, e.msg) + io.WriteString(s, f.msg) + case 'q': + fmt.Fprintf(s, "%q", f.msg) } } -// New returns an error with the supplied message. -func New(message string) error { - return _error{ - message, - callers(), +// WithStack annotates err with a stack trace at the point WithStack was called. +// If err is nil, WithStack returns nil. +func WithStack(err error) error { + if err == nil { + return nil } -} - -// Errorf formats according to a format specifier and returns the string -// as a value that satisfies error. -func Errorf(format string, args ...interface{}) error { - return _error{ - fmt.Sprintf(format, args...), + return &withStack{ + err, callers(), } } -type cause struct { - cause error - msg string -} - -func (c cause) Error() string { return fmt.Sprintf("%s: %v", c.msg, c.Cause()) } -func (c cause) Cause() error { return c.cause } - -// wrapper is an error implementation returned by Wrap and Wrapf -// that implements its own fmt.Formatter. -type wrapper struct { - cause +type withStack struct { + error *stack } -func (w wrapper) Format(s fmt.State, verb rune) { +func (w *withStack) Cause() error { return w.error } + +func (w *withStack) Format(s fmt.State, verb rune) { switch verb { case 'v': if s.Flag('+') { - fmt.Fprintf(s, "%+v\n", w.Cause()) - io.WriteString(s, w.msg) - fmt.Fprintf(s, "%+v", w.StackTrace()) + fmt.Fprintf(s, "%+v", w.Cause()) + w.stack.Format(s, verb) return } fallthrough @@ -157,33 +174,71 @@ func (w wrapper) Format(s fmt.State, verb rune) { } } -// Wrap returns an error annotating err with message. +// Wrap returns an error annotating err with a stack trace +// at the point Wrap is called, and the supplied message. // If err is nil, Wrap returns nil. func Wrap(err error, message string) error { if err == nil { return nil } - return wrapper{ - cause: cause{ - cause: err, - msg: message, - }, - stack: callers(), + err = &withMessage{ + cause: err, + msg: message, + } + return &withStack{ + err, + callers(), } } -// Wrapf returns an error annotating err with the format specifier. +// Wrapf returns an error annotating err with a stack trace +// at the point Wrapf is call, and the format specifier. // If err is nil, Wrapf returns nil. func Wrapf(err error, format string, args ...interface{}) error { if err == nil { return nil } - return wrapper{ - cause: cause{ - cause: err, - msg: fmt.Sprintf(format, args...), - }, - stack: callers(), + err = &withMessage{ + cause: err, + msg: fmt.Sprintf(format, args...), + } + return &withStack{ + err, + callers(), + } +} + +// WithMessage annotates err with a new message. +// If err is nil, WithMessage returns nil. +func WithMessage(err error, message string) error { + if err == nil { + return nil + } + return &withMessage{ + cause: err, + msg: message, + } +} + +type withMessage struct { + cause error + msg string +} + +func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } +func (w *withMessage) Cause() error { return w.cause } + +func (w *withMessage) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v\n", w.Cause()) + io.WriteString(s, w.msg) + return + } + fallthrough + case 's', 'q': + io.WriteString(s, w.Error()) } } @@ -191,7 +246,7 @@ func Wrapf(err error, format string, args ...interface{}) error { // An error value has a cause if it implements the following // interface: // -// type Causer interface { +// type causer interface { // Cause() error // } // diff --git a/vendor/github.com/pkg/errors/errors_test.go b/vendor/github.com/pkg/errors/errors_test.go deleted file mode 100644 index 11d45554..00000000 --- a/vendor/github.com/pkg/errors/errors_test.go +++ /dev/null @@ -1,159 +0,0 @@ -package errors - -import ( - "errors" - "fmt" - "io" - "reflect" - "testing" -) - -func TestNew(t *testing.T) { - tests := []struct { - err string - want error - }{ - {"", fmt.Errorf("")}, - {"foo", fmt.Errorf("foo")}, - {"foo", New("foo")}, - {"string with format specifiers: %v", errors.New("string with format specifiers: %v")}, - } - - for _, tt := range tests { - got := New(tt.err) - if got.Error() != tt.want.Error() { - t.Errorf("New.Error(): got: %q, want %q", got, tt.want) - } - } -} - -func TestWrapNil(t *testing.T) { - got := Wrap(nil, "no error") - if got != nil { - t.Errorf("Wrap(nil, \"no error\"): got %#v, expected nil", got) - } -} - -func TestWrap(t *testing.T) { - tests := []struct { - err error - message string - want string - }{ - {io.EOF, "read error", "read error: EOF"}, - {Wrap(io.EOF, "read error"), "client error", "client error: read error: EOF"}, - } - - for _, tt := range tests { - got := Wrap(tt.err, tt.message).Error() - if got != tt.want { - t.Errorf("Wrap(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want) - } - } -} - -type nilError struct{} - -func (nilError) Error() string { return "nil error" } - -func TestCause(t *testing.T) { - x := New("error") - tests := []struct { - err error - want error - }{{ - // nil error is nil - err: nil, - want: nil, - }, { - // explicit nil error is nil - err: (error)(nil), - want: nil, - }, { - // typed nil is nil - err: (*nilError)(nil), - want: (*nilError)(nil), - }, { - // uncaused error is unaffected - err: io.EOF, - want: io.EOF, - }, { - // caused error returns cause - err: Wrap(io.EOF, "ignored"), - want: io.EOF, - }, { - err: x, // return from errors.New - want: x, - }} - - for i, tt := range tests { - got := Cause(tt.err) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("test %d: got %#v, want %#v", i+1, got, tt.want) - } - } -} - -func TestWrapfNil(t *testing.T) { - got := Wrapf(nil, "no error") - if got != nil { - t.Errorf("Wrapf(nil, \"no error\"): got %#v, expected nil", got) - } -} - -func TestWrapf(t *testing.T) { - tests := []struct { - err error - message string - want string - }{ - {io.EOF, "read error", "read error: EOF"}, - {Wrapf(io.EOF, "read error without format specifiers"), "client error", "client error: read error without format specifiers: EOF"}, - {Wrapf(io.EOF, "read error with %d format specifier", 1), "client error", "client error: read error with 1 format specifier: EOF"}, - } - - for _, tt := range tests { - got := Wrapf(tt.err, tt.message).Error() - if got != tt.want { - t.Errorf("Wrapf(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want) - } - } -} - -func TestErrorf(t *testing.T) { - tests := []struct { - err error - want string - }{ - {Errorf("read error without format specifiers"), "read error without format specifiers"}, - {Errorf("read error with %d format specifier", 1), "read error with 1 format specifier"}, - } - - for _, tt := range tests { - got := tt.err.Error() - if got != tt.want { - t.Errorf("Errorf(%v): got: %q, want %q", tt.err, got, tt.want) - } - } -} - -// errors.New, etc values are not expected to be compared by value -// but the change in errors#27 made them incomparable. Assert that -// various kinds of errors have a functional equality operator, even -// if the result of that equality is always false. -func TestErrorEquality(t *testing.T) { - tests := []struct { - err1, err2 error - }{ - {io.EOF, io.EOF}, - {io.EOF, nil}, - {io.EOF, errors.New("EOF")}, - {io.EOF, New("EOF")}, - {New("EOF"), New("EOF")}, - {New("EOF"), Errorf("EOF")}, - {New("EOF"), Wrap(io.EOF, "EOF")}, - } - for _, tt := range tests { - _ = tt.err1 == tt.err2 // mustn't panic - } -} diff --git a/vendor/github.com/pkg/errors/example_test.go b/vendor/github.com/pkg/errors/example_test.go deleted file mode 100644 index 5bec3ad4..00000000 --- a/vendor/github.com/pkg/errors/example_test.go +++ /dev/null @@ -1,152 +0,0 @@ -package errors_test - -import ( - "fmt" - - "github.com/pkg/errors" -) - -func ExampleNew() { - err := errors.New("whoops") - fmt.Println(err) - - // Output: whoops -} - -func ExampleNew_printf() { - err := errors.New("whoops") - fmt.Printf("%+v", err) - - // Example output: - // whoops - // github.com/pkg/errors_test.ExampleNew_printf - // /home/dfc/src/github.com/pkg/errors/example_test.go:17 - // testing.runExample - // /home/dfc/go/src/testing/example.go:114 - // testing.RunExamples - // /home/dfc/go/src/testing/example.go:38 - // testing.(*M).Run - // /home/dfc/go/src/testing/testing.go:744 - // main.main - // /github.com/pkg/errors/_test/_testmain.go:106 - // runtime.main - // /home/dfc/go/src/runtime/proc.go:183 - // runtime.goexit - // /home/dfc/go/src/runtime/asm_amd64.s:2059 -} - -func ExampleWrap() { - cause := errors.New("whoops") - err := errors.Wrap(cause, "oh noes") - fmt.Println(err) - - // Output: oh noes: whoops -} - -func fn() error { - e1 := errors.New("error") - e2 := errors.Wrap(e1, "inner") - e3 := errors.Wrap(e2, "middle") - return errors.Wrap(e3, "outer") -} - -func ExampleCause() { - err := fn() - fmt.Println(err) - fmt.Println(errors.Cause(err)) - - // Output: outer: middle: inner: error - // error -} - -func ExampleWrap_extended() { - err := fn() - fmt.Printf("%+v\n", err) - - // Example output: - // error - // github.com/pkg/errors_test.fn - // /home/dfc/src/github.com/pkg/errors/example_test.go:47 - // github.com/pkg/errors_test.ExampleCause_printf - // /home/dfc/src/github.com/pkg/errors/example_test.go:63 - // testing.runExample - // /home/dfc/go/src/testing/example.go:114 - // testing.RunExamples - // /home/dfc/go/src/testing/example.go:38 - // testing.(*M).Run - // /home/dfc/go/src/testing/testing.go:744 - // main.main - // /github.com/pkg/errors/_test/_testmain.go:104 - // runtime.main - // /home/dfc/go/src/runtime/proc.go:183 - // runtime.goexit - // /home/dfc/go/src/runtime/asm_amd64.s:2059 - // github.com/pkg/errors_test.fn - // /home/dfc/src/github.com/pkg/errors/example_test.go:48: inner - // github.com/pkg/errors_test.fn - // /home/dfc/src/github.com/pkg/errors/example_test.go:49: middle - // github.com/pkg/errors_test.fn - // /home/dfc/src/github.com/pkg/errors/example_test.go:50: outer -} - -func ExampleWrapf() { - cause := errors.New("whoops") - err := errors.Wrapf(cause, "oh noes #%d", 2) - fmt.Println(err) - - // Output: oh noes #2: whoops -} - -func ExampleErrorf_extended() { - err := errors.Errorf("whoops: %s", "foo") - fmt.Printf("%+v", err) - - // Example output: - // whoops: foo - // github.com/pkg/errors_test.ExampleErrorf - // /home/dfc/src/github.com/pkg/errors/example_test.go:101 - // testing.runExample - // /home/dfc/go/src/testing/example.go:114 - // testing.RunExamples - // /home/dfc/go/src/testing/example.go:38 - // testing.(*M).Run - // /home/dfc/go/src/testing/testing.go:744 - // main.main - // /github.com/pkg/errors/_test/_testmain.go:102 - // runtime.main - // /home/dfc/go/src/runtime/proc.go:183 - // runtime.goexit - // /home/dfc/go/src/runtime/asm_amd64.s:2059 -} - -func Example_stackTrace() { - type stackTracer interface { - StackTrace() errors.StackTrace - } - - err, ok := errors.Cause(fn()).(stackTracer) - if !ok { - panic("oops, err does not implement stackTracer") - } - - st := err.StackTrace() - fmt.Printf("%+v", st[0:2]) // top two frames - - // Example output: - // github.com/pkg/errors_test.fn - // /home/dfc/src/github.com/pkg/errors/example_test.go:47 - // github.com/pkg/errors_test.Example_stackTrace - // /home/dfc/src/github.com/pkg/errors/example_test.go:127 -} - -func ExampleCause_printf() { - err := errors.Wrap(func() error { - return func() error { - return errors.Errorf("hello %s", fmt.Sprintf("world")) - }() - }(), "failed") - - fmt.Printf("%v", err) - - // Output: failed: hello world -} diff --git a/vendor/github.com/pkg/errors/format_test.go b/vendor/github.com/pkg/errors/format_test.go deleted file mode 100644 index d1b2f1b3..00000000 --- a/vendor/github.com/pkg/errors/format_test.go +++ /dev/null @@ -1,153 +0,0 @@ -package errors - -import ( - "fmt" - "io" - "regexp" - "strings" - "testing" -) - -func TestFormatNew(t *testing.T) { - tests := []struct { - error - format string - want string - }{{ - New("error"), - "%s", - "error", - }, { - New("error"), - "%v", - "error", - }, { - New("error"), - "%+v", - "error\n" + - "github.com/pkg/errors.TestFormatNew\n" + - "\t.+/github.com/pkg/errors/format_test.go:25", - }} - - for _, tt := range tests { - testFormatRegexp(t, tt.error, tt.format, tt.want) - } -} - -func TestFormatErrorf(t *testing.T) { - tests := []struct { - error - format string - want string - }{{ - Errorf("%s", "error"), - "%s", - "error", - }, { - Errorf("%s", "error"), - "%v", - "error", - }, { - Errorf("%s", "error"), - "%+v", - "error\n" + - "github.com/pkg/errors.TestFormatErrorf\n" + - "\t.+/github.com/pkg/errors/format_test.go:51", - }} - - for _, tt := range tests { - testFormatRegexp(t, tt.error, tt.format, tt.want) - } -} - -func TestFormatWrap(t *testing.T) { - tests := []struct { - error - format string - want string - }{{ - Wrap(New("error"), "error2"), - "%s", - "error2: error", - }, { - Wrap(New("error"), "error2"), - "%v", - "error2: error", - }, { - Wrap(New("error"), "error2"), - "%+v", - "error\n" + - "github.com/pkg/errors.TestFormatWrap\n" + - "\t.+/github.com/pkg/errors/format_test.go:77", - }, { - Wrap(io.EOF, "error"), - "%s", - "error: EOF", - }, { - Wrap(New("error with space"), "context"), - "%q", - `"context: error with space"`, - }} - - for _, tt := range tests { - testFormatRegexp(t, tt.error, tt.format, tt.want) - } -} - -func TestFormatWrapf(t *testing.T) { - tests := []struct { - error - format string - want string - }{{ - Wrapf(New("error"), "error%d", 2), - "%s", - "error2: error", - }, { - Wrap(io.EOF, "error"), - "%v", - "error: EOF", - }, { - Wrap(io.EOF, "error"), - "%+v", - "EOF\n" + - "error\n" + - "github.com/pkg/errors.TestFormatWrapf\n" + - "\t.+/github.com/pkg/errors/format_test.go:111", - }, { - Wrapf(New("error"), "error%d", 2), - "%v", - "error2: error", - }, { - Wrapf(New("error"), "error%d", 2), - "%+v", - "error\n" + - "github.com/pkg/errors.TestFormatWrapf\n" + - "\t.+/github.com/pkg/errors/format_test.go:122", - }, { - Wrap(Wrap(io.EOF, "error1"), "error2"), - "%+v", - "EOF\n" + - "error1\n" + - "github.com/pkg/errors.TestFormatWrapf\n" + - "\t.+/github.com/pkg/errors/format_test.go:128\n", - }} - - for _, tt := range tests { - testFormatRegexp(t, tt.error, tt.format, tt.want) - } -} - -func testFormatRegexp(t *testing.T, arg interface{}, format, want string) { - got := fmt.Sprintf(format, arg) - lines := strings.SplitN(got, "\n", -1) - for i, w := range strings.SplitN(want, "\n", -1) { - match, err := regexp.MatchString(w, lines[i]) - if err != nil { - t.Fatal(err) - } - if !match { - t.Errorf("fmt.Sprintf(%q, err): got: %q, want: %q", format, got, want) - } - } -} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go index 243a64a2..6b1f2891 100644 --- a/vendor/github.com/pkg/errors/stack.go +++ b/vendor/github.com/pkg/errors/stack.go @@ -100,6 +100,19 @@ func (st StackTrace) Format(s fmt.State, verb rune) { // stack represents a stack of program counters. type stack []uintptr +func (s *stack) Format(st fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case st.Flag('+'): + for _, pc := range *s { + f := Frame(pc) + fmt.Fprintf(st, "\n%+v", f) + } + } + } +} + func (s *stack) StackTrace() StackTrace { f := make([]Frame, len(*s)) for i := 0; i < len(f); i++ { diff --git a/vendor/github.com/pkg/errors/stack_test.go b/vendor/github.com/pkg/errors/stack_test.go deleted file mode 100644 index cd7827bf..00000000 --- a/vendor/github.com/pkg/errors/stack_test.go +++ /dev/null @@ -1,295 +0,0 @@ -package errors - -import ( - "fmt" - "runtime" - "testing" -) - -var initpc, _, _, _ = runtime.Caller(0) - -func TestFrameLine(t *testing.T) { - var tests = []struct { - Frame - want int - }{{ - Frame(initpc), - 9, - }, { - func() Frame { - var pc, _, _, _ = runtime.Caller(0) - return Frame(pc) - }(), - 20, - }, { - func() Frame { - var pc, _, _, _ = runtime.Caller(1) - return Frame(pc) - }(), - 28, - }, { - Frame(0), // invalid PC - 0, - }} - - for _, tt := range tests { - got := tt.Frame.line() - want := tt.want - if want != got { - t.Errorf("Frame(%v): want: %v, got: %v", uintptr(tt.Frame), want, got) - } - } -} - -type X struct{} - -func (x X) val() Frame { - var pc, _, _, _ = runtime.Caller(0) - return Frame(pc) -} - -func (x *X) ptr() Frame { - var pc, _, _, _ = runtime.Caller(0) - return Frame(pc) -} - -func TestFrameFormat(t *testing.T) { - var tests = []struct { - Frame - format string - want string - }{{ - Frame(initpc), - "%s", - "stack_test.go", - }, { - Frame(initpc), - "%+s", - "github.com/pkg/errors.init\n" + - "\t.+/github.com/pkg/errors/stack_test.go", - }, { - Frame(0), - "%s", - "unknown", - }, { - Frame(0), - "%+s", - "unknown", - }, { - Frame(initpc), - "%d", - "9", - }, { - Frame(0), - "%d", - "0", - }, { - Frame(initpc), - "%n", - "init", - }, { - func() Frame { - var x X - return x.ptr() - }(), - "%n", - `\(\*X\).ptr`, - }, { - func() Frame { - var x X - return x.val() - }(), - "%n", - "X.val", - }, { - Frame(0), - "%n", - "", - }, { - Frame(initpc), - "%v", - "stack_test.go:9", - }, { - Frame(initpc), - "%+v", - "github.com/pkg/errors.init\n" + - "\t.+/github.com/pkg/errors/stack_test.go:9", - }, { - Frame(0), - "%v", - "unknown:0", - }} - - for _, tt := range tests { - testFormatRegexp(t, tt.Frame, tt.format, tt.want) - } -} - -func TestFuncname(t *testing.T) { - tests := []struct { - name, want string - }{ - {"", ""}, - {"runtime.main", "main"}, - {"github.com/pkg/errors.funcname", "funcname"}, - {"funcname", "funcname"}, - {"io.copyBuffer", "copyBuffer"}, - {"main.(*R).Write", "(*R).Write"}, - } - - for _, tt := range tests { - got := funcname(tt.name) - want := tt.want - if got != want { - t.Errorf("funcname(%q): want: %q, got %q", tt.name, want, got) - } - } -} - -func TestTrimGOPATH(t *testing.T) { - var tests = []struct { - Frame - want string - }{{ - Frame(initpc), - "github.com/pkg/errors/stack_test.go", - }} - - for _, tt := range tests { - pc := tt.Frame.pc() - fn := runtime.FuncForPC(pc) - file, _ := fn.FileLine(pc) - got := trimGOPATH(fn.Name(), file) - want := tt.want - if want != got { - t.Errorf("%v: want %q, got %q", tt.Frame, want, got) - } - } -} - -func TestStackTrace(t *testing.T) { - tests := []struct { - err error - want []string - }{{ - New("ooh"), []string{ - "github.com/pkg/errors.TestStackTrace\n" + - "\t.+/github.com/pkg/errors/stack_test.go:175", - }, - }, { - Wrap(New("ooh"), "ahh"), []string{ - "github.com/pkg/errors.TestStackTrace\n" + - "\t.+/github.com/pkg/errors/stack_test.go:180", // this is the stack of Wrap, not New - }, - }, { - Cause(Wrap(New("ooh"), "ahh")), []string{ - "github.com/pkg/errors.TestStackTrace\n" + - "\t.+/github.com/pkg/errors/stack_test.go:185", // this is the stack of New - }, - }, { - func() error { return New("ooh") }(), []string{ - `github.com/pkg/errors.(func·005|TestStackTrace.func1)` + - "\n\t.+/github.com/pkg/errors/stack_test.go:190", // this is the stack of New - "github.com/pkg/errors.TestStackTrace\n" + - "\t.+/github.com/pkg/errors/stack_test.go:190", // this is the stack of New's caller - }, - }, { - Cause(func() error { - return func() error { - return Errorf("hello %s", fmt.Sprintf("world")) - }() - }()), []string{ - `github.com/pkg/errors.(func·006|TestStackTrace.func2.1)` + - "\n\t.+/github.com/pkg/errors/stack_test.go:199", // this is the stack of Errorf - `github.com/pkg/errors.(func·007|TestStackTrace.func2)` + - "\n\t.+/github.com/pkg/errors/stack_test.go:200", // this is the stack of Errorf's caller - "github.com/pkg/errors.TestStackTrace\n" + - "\t.+/github.com/pkg/errors/stack_test.go:201", // this is the stack of Errorf's caller's caller - }, - }} - for _, tt := range tests { - x, ok := tt.err.(interface { - StackTrace() StackTrace - }) - if !ok { - t.Errorf("expected %#v to implement StackTrace() StackTrace", tt.err) - continue - } - st := x.StackTrace() - for j, want := range tt.want { - testFormatRegexp(t, st[j], "%+v", want) - } - } -} - -func stackTrace() StackTrace { - const depth = 8 - var pcs [depth]uintptr - n := runtime.Callers(1, pcs[:]) - var st stack = pcs[0:n] - return st.StackTrace() -} - -func TestStackTraceFormat(t *testing.T) { - tests := []struct { - StackTrace - format string - want string - }{{ - nil, - "%s", - `\[\]`, - }, { - nil, - "%v", - `\[\]`, - }, { - nil, - "%+v", - "", - }, { - nil, - "%#v", - `\[\]errors.Frame\(nil\)`, - }, { - make(StackTrace, 0), - "%s", - `\[\]`, - }, { - make(StackTrace, 0), - "%v", - `\[\]`, - }, { - make(StackTrace, 0), - "%+v", - "", - }, { - make(StackTrace, 0), - "%#v", - `\[\]errors.Frame{}`, - }, { - stackTrace()[:2], - "%s", - `\[stack_test.go stack_test.go\]`, - }, { - stackTrace()[:2], - "%v", - `\[stack_test.go:228 stack_test.go:275\]`, - }, { - stackTrace()[:2], - "%+v", - "\n" + - "github.com/pkg/errors.stackTrace\n" + - "\t.+/github.com/pkg/errors/stack_test.go:228\n" + - "github.com/pkg/errors.TestStackTraceFormat\n" + - "\t.+/github.com/pkg/errors/stack_test.go:279", - }, { - stackTrace()[:2], - "%#v", - `\[\]errors.Frame{stack_test.go:228, stack_test.go:287}`, - }} - - for _, tt := range tests { - testFormatRegexp(t, tt.StackTrace, tt.format, tt.want) - } -}