in conn.go [990:1035]
func (c *Conn) readProtoHeader() (protoHeader, error) {
const protoHeaderSize = 8
// only read from the network once our buffer has been exhausted.
// TODO: this preserves existing behavior as some tests rely on this
// implementation detail (it lets you replay a stream of bytes). we
// might want to consider removing this and fixing the tests as the
// protocol doesn't actually work this way.
if c.rxBuf.Len() == 0 {
for {
err := c.rxBuf.ReadFromOnce(c.net)
if err != nil {
return protoHeader{}, err
}
// read more if buf doesn't contain enough to parse the header
if c.rxBuf.Len() >= protoHeaderSize {
break
}
}
}
buf, ok := c.rxBuf.Next(protoHeaderSize)
if !ok {
return protoHeader{}, errors.New("invalid protoHeader")
}
// bounds check hint to compiler; see golang.org/issue/14808
_ = buf[protoHeaderSize-1]
if !bytes.Equal(buf[:4], []byte{'A', 'M', 'Q', 'P'}) {
return protoHeader{}, fmt.Errorf("unexpected protocol %q", buf[:4])
}
p := protoHeader{
ProtoID: protoID(buf[4]),
Major: buf[5],
Minor: buf[6],
Revision: buf[7],
}
if p.Major != 1 || p.Minor != 0 || p.Revision != 0 {
return protoHeader{}, fmt.Errorf("unexpected protocol version %d.%d.%d", p.Major, p.Minor, p.Revision)
}
return p, nil
}