// The actual message sending logic. Calculates the payload MAC, encrypts the // headers and sends it down to the stream. Direct send is public for handshake // simplifications. After that is done, the link should switch to channel mode. func (l *Link) SendDirect(msg *proto.Message) error { var err error // Sanity check for message data security if !msg.Secure() && len(msg.Data) > 0 { log.Printf("link: unsecured data, send denied.") return errors.New("unsecured data, send denied") } // Flatten and encrypt the headers if err = l.outCoder.Encode(msg.Head); err != nil { return err } l.outCipher.XORKeyStream(l.outBuffer.Bytes(), l.outBuffer.Bytes()) defer l.outBuffer.Reset() // Generate the MAC of the encrypted payload and headers l.outMacer.Write(l.outBuffer.Bytes()) l.outMacer.Write(msg.Data) // Send the multi-part message (headers + payload + MAC) if err = l.socket.Send(l.outBuffer.Bytes()); err != nil { return err } if err = l.socket.Send(msg.Data); err != nil { return err } if err = l.socket.Send(l.outMacer.Sum(nil)); err != nil { return err } return l.socket.Flush() }