diff --git a/whisper/whisperv6/doc.go b/whisper/whisperv6/doc.go index 5ad660616..9659e6c46 100644 --- a/whisper/whisperv6/doc.go +++ b/whisper/whisperv6/doc.go @@ -95,3 +95,40 @@ type MailServer interface { Archive(env *Envelope) DeliverMail(whisperPeer *Peer, request *Envelope) } + +type envelopeSource int + +const ( + _ = iota + // peerSource indicates a source as a regular peer. + peerSource envelopeSource = iota + // p2pSource indicates that envelop was received from a trusted peer. + p2pSource +) + +// EnvelopeMeta keeps metadata of received envelopes. +type EnvelopeMeta struct { + Hash string + Topic TopicType + Size uint32 + Source envelopeSource + IsNew bool + Peer string +} + +// SourceString converts source to string. +func (m *EnvelopeMeta) SourceString() string { + switch m.Source { + case peerSource: + return "peer" + case p2pSource: + return "p2p" + default: + return "unknown" + } +} + +// EnvelopeTracer tracks received envelopes. +type EnvelopeTracer interface { + Trace(*EnvelopeMeta) +} diff --git a/whisper/whisperv6/whisper.go b/whisper/whisperv6/whisper.go index 54d7d0f24..ce9405dff 100644 --- a/whisper/whisperv6/whisper.go +++ b/whisper/whisperv6/whisper.go @@ -85,7 +85,8 @@ type Whisper struct { statsMu sync.Mutex // guard stats stats Statistics // Statistics of whisper node - mailServer MailServer // MailServer interface + mailServer MailServer // MailServer interface + envelopeTracer EnvelopeTracer // Service collecting envelopes metadata } // New creates a Whisper client ready to communicate through the Ethereum P2P network. @@ -209,6 +210,12 @@ func (whisper *Whisper) RegisterServer(server MailServer) { whisper.mailServer = server } +// RegisterEnvelopeTracer registers an EnveloperTracer to collect information +// about received envelopes. +func (whisper *Whisper) RegisterEnvelopeTracer(tracer EnvelopeTracer) { + whisper.envelopeTracer = tracer +} + // Protocols returns the whisper sub-protocols ran by this particular client. func (whisper *Whisper) Protocols() []p2p.Protocol { return []p2p.Protocol{whisper.protocol} @@ -737,6 +744,7 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { trouble := false for _, env := range envelopes { + whisper.traceEnvelope(env, !whisper.isEnvelopeCached(env.Hash()), peerSource, p) cached, err := whisper.add(env) if err != nil { trouble = true @@ -787,6 +795,7 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { return errors.New("invalid direct message") } whisper.postEvent(&envelope, true) + whisper.traceEnvelope(&envelope, false, p2pSource, p) } case p2pRequestCode: // Must be processed if mail server is implemented. Otherwise ignore. @@ -883,6 +892,22 @@ func (whisper *Whisper) add(envelope *Envelope) (bool, error) { return true, nil } +// traceEnvelope collects basic metadata about an envelope and sender peer. +func (whisper *Whisper) traceEnvelope(envelope *Envelope, isNew bool, source envelopeSource, peer *Peer) { + if whisper.envelopeTracer == nil { + return + } + + whisper.envelopeTracer.Trace(&EnvelopeMeta{ + Hash: envelope.Hash().String(), + Topic: BytesToTopic(envelope.Topic[:]), + Size: uint32(envelope.size()), + Source: source, + IsNew: isNew, + Peer: peer.peer.Info().ID, + }) +} + // postEvent queues the message for further processing. func (whisper *Whisper) postEvent(envelope *Envelope, isP2P bool) { if isP2P {