// Modified from http://golang.org/src/pkg/encoding/binary/varint.go#106 func readVarint32(dst io.Writer, src io.Reader) (int32, int, error) { var x int32 var s uint var i int var buf [4]byte for i = 0; i < 4; i++ { _, err := src.Read(buf[i : i+1]) if err != nil { return 0, i + 1, err } if buf[i] < 0x80 { x |= int32(buf[i]) << s break } x |= int32(buf[i]&0x7f) << s s += 7 } if i > 3 || (i == 3 && buf[3]&0x80 > 0) { return x, i + 1, glog.NewError("Malformed remaining length. 4th byte has continuation bit set.") } if dst != nil { if n, err := dst.Write(buf[:i+1]); err != nil { return x, n, glog.NewError("Error writing data: %v", err) } } return x, i + 1, nil }
func readUint16(buf *bytes.Buffer) (uint16, error) { if buf.Len() < 2 { return 0, glog.NewError("Insufficient buffer size. Expecting %d, got %d.", 2, buf.Len()) } return binary.BigEndian.Uint16(buf.Next(2)), nil }
func (this *fixedHeader) copy(src io.Reader) (int64, error) { total, err := io.CopyN(this.buf, src, 1) if err != nil { return 0, err } b, err := this.buf.ReadByte() if err != nil { return 0, err } mtype := MessageType(b >> 4) if !mtype.Valid() { return total, glog.NewError("Invalid message type %d.", mtype) } if mtype != this.mtype { return total, glog.NewError("Invalid message type %d. Expecting %d.", mtype, this.mtype) } this.flags = b & 0x0f if this.mtype != PUBLISH && this.flags != this.mtype.DefaultFlags() { return total, glog.NewError("Invalid message (%d) flags. Expecting %d, got %d", this.mtype, this.mtype.DefaultFlags, this.flags) } if this.mtype == PUBLISH && !ValidQos((this.flags>>1)&0x3) { return total, glog.NewError("Invalid QoS (%d) for PUBLISH message.", (this.flags>>1)&0x3) } var m int this.remlen, m, err = readVarint32(this.buf, src) if err != nil { return total + int64(m), err } total += int64(m) this.buf.Next(m) n, err := io.CopyN(this.buf, src, int64(this.remlen)) if err != nil { return total + n, err } return total, nil }
func writeVarint32(dst io.Writer, x int32) (int, error) { if x > maxRemainingLength { return 0, glog.NewError("Exceeded maximum of %d", maxRemainingLength) } var buf [4]byte i := 0 for x >= 0x80 { buf[i] = byte(x) | 0x80 x >>= 7 i++ } buf[i] = byte(x) n, err := dst.Write(buf[:i+1]) if err != nil { return n, glog.NewError("Error writing data: %v", err) } return n, nil }
func readLPBytes(buf *bytes.Buffer) ([]byte, int, error) { total := 0 n, err := readUint16(buf) total += 2 if err != nil { return nil, total, err } if buf.Len() < int(n) { return nil, total, glog.NewError("Insufficient buffer size. Expecting %d, got %d.", n, buf.Len()) } total += int(n) return buf.Next(int(n)), total, nil }
func writeLPBytes(buf *bytes.Buffer, b []byte) (int, error) { if len(b) > int(maxLPString) { return 0, glog.NewError("Length greater than %d bytes.", maxLPString) } total := 0 err := writeUint16(buf, uint16(len(b))) if err != nil { return 0, err } total += 2 n, err := buf.Write(b) if err != nil { return total, err } total += n return total, nil }