// The actual message receiving logic. Reads a message from the stream, verifies // its mac, decodes the headers and send it upwards. Direct receive is public for // handshake simplifications, after which the link should switch to channel mode. func (l *Link) RecvDirect() (*proto.Message, error) { var msg proto.Message var err error // Retrieve a new package if err = l.socket.Recv(&l.inHeadBuf); err != nil { return nil, err } if err = l.socket.Recv(&msg.Data); err != nil { return nil, err } if err = l.socket.Recv(&l.inMacBuf); err != nil { return nil, err } // Verify the message contents (payload + header) l.inMacer.Write(l.inHeadBuf) l.inMacer.Write(msg.Data) if !bytes.Equal(l.inMacBuf, l.inMacer.Sum(nil)) { err = errors.New(fmt.Sprintf("mac mismatch: have %v, want %v.", l.inMacer.Sum(nil), l.inMacBuf)) return nil, err } // Extract the package contents l.inCipher.XORKeyStream(l.inHeadBuf, l.inHeadBuf) l.inBuffer.Write(l.inHeadBuf) if err = l.inCoder.Decode(&msg.Head); err != nil { return nil, err } // Set the message security knowingly to true msg.KnownSecure() return &msg, nil }