// Sends a direct message to a known node. func (o *Overlay) Direct(dest *big.Int, msg *proto.Message) error { if err := msg.Encrypt(); err != nil { return err } o.sendDirect(dest, msg) return nil }
// Balances a message to one of the subscribed nodes. func (o *Overlay) Balance(topic string, msg *proto.Message) error { if err := msg.Encrypt(); err != nil { return err } o.sendBalance(pastry.Resolve(topic), msg) return nil }
// 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 }
// 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() }
// Handles the load balancing event of a topio. func (o *Overlay) handleBalance(msg *proto.Message, topicId *big.Int, prevHop *big.Int) (bool, error) { sid := topicId.String() // Fetch the topic or report not found o.lock.RLock() top, ok := o.topics[sid] topName := o.names[sid] o.lock.RUnlock() if !ok { // No error, but not handled either return false, nil } // Fetch the recipient and either forward or deliver node, err := top.Balance(prevHop) if err != nil { return true, err } // If it's a remote node, forward if node.Cmp(o.pastry.Self()) != 0 { o.fwdBalance(node, msg) return true, nil } // Remove all carrier headers and decrypt head := msg.Head.Meta.(*header) msg.Head.Meta = head.Meta if err := msg.Decrypt(); err != nil { return true, err } // Deliver to the application on the specific topic o.app.HandleBalance(head.Sender, topName, msg) return true, nil }
// Handles the receiving of a direct message and delivers the contents upstream. func (o *Overlay) handleDirect(msg *proto.Message) error { // Remove all scribe headers and decrypt contents head := msg.Head.Meta.(*header) msg.Head.Meta = head.Meta if err := msg.Decrypt(); err != nil { return err } // Deliver the message upstream o.app.HandleDirect(head.Sender, msg) return nil }