| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | package whisper | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2014-12-10 14:17:32 +01:00
										 |  |  | 	"crypto/ecdsa" | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	"sync" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-21 00:57:18 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2014-12-10 14:17:32 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2015-02-14 00:25:47 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto/ecies" | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/event/filter" | 
					
						
							| 
									
										
										
										
											2014-12-15 12:01:55 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger" | 
					
						
							| 
									
										
										
										
											2015-04-07 14:57:04 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger/glog" | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/p2p" | 
					
						
							|  |  |  | 	"gopkg.in/fatih/set.v0" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							| 
									
										
										
										
											2015-04-14 14:28:59 +03:00
										 |  |  | 	statusCode   = 0x00 | 
					
						
							|  |  |  | 	messagesCode = 0x01 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	protocolVersion uint64 = 0x02 | 
					
						
							|  |  |  | 	protocolName           = "shh" | 
					
						
							| 
									
										
										
										
											2015-04-13 11:31:51 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	signatureFlag   = byte(1 << 7) | 
					
						
							|  |  |  | 	signatureLength = 65 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-16 11:20:01 +03:00
										 |  |  | 	expirationCycle   = 800 * time.Millisecond | 
					
						
							|  |  |  | 	transmissionCycle = 300 * time.Millisecond | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 16:19:34 +03:00
										 |  |  | const ( | 
					
						
							| 
									
										
										
										
											2015-04-14 15:16:02 +03:00
										 |  |  | 	DefaultTTL = 50 * time.Second | 
					
						
							|  |  |  | 	DefaultPoW = 50 * time.Millisecond | 
					
						
							| 
									
										
										
										
											2015-04-13 16:19:34 +03:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | type MessageEvent struct { | 
					
						
							|  |  |  | 	To      *ecdsa.PrivateKey | 
					
						
							|  |  |  | 	From    *ecdsa.PublicKey | 
					
						
							|  |  |  | 	Message *Message | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 16:19:34 +03:00
										 |  |  | // Whisper represents a dark communication interface through the Ethereum | 
					
						
							|  |  |  | // network, using its very own P2P communication layer. | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | type Whisper struct { | 
					
						
							|  |  |  | 	protocol p2p.Protocol | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 	filters  *filter.Filters | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-16 13:05:35 +03:00
										 |  |  | 	keys map[string]*ecdsa.PrivateKey | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-16 13:05:35 +03:00
										 |  |  | 	messages    map[common.Hash]*Envelope // Pool of messages currently tracked by this node | 
					
						
							|  |  |  | 	expirations map[uint32]*set.SetNonTS  // Message expiration pool (TODO: something lighter) | 
					
						
							|  |  |  | 	poolMu      sync.RWMutex              // Mutex to sync the message and expiration pools | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-16 13:05:35 +03:00
										 |  |  | 	peers  map[*peer]struct{} // Set of currently active peers | 
					
						
							|  |  |  | 	peerMu sync.RWMutex       // Mutex to sync the active peer set | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	quit chan struct{} | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-17 16:45:44 +03:00
										 |  |  | // New creates a Whisper client ready to communicate through the Ethereum P2P | 
					
						
							|  |  |  | // network. | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | func New() *Whisper { | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	whisper := &Whisper{ | 
					
						
							| 
									
										
										
										
											2015-04-16 13:05:35 +03:00
										 |  |  | 		filters:     filter.New(), | 
					
						
							|  |  |  | 		keys:        make(map[string]*ecdsa.PrivateKey), | 
					
						
							|  |  |  | 		messages:    make(map[common.Hash]*Envelope), | 
					
						
							|  |  |  | 		expirations: make(map[uint32]*set.SetNonTS), | 
					
						
							|  |  |  | 		peers:       make(map[*peer]struct{}), | 
					
						
							|  |  |  | 		quit:        make(chan struct{}), | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 	whisper.filters.Start() | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// p2p whisper sub protocol handler | 
					
						
							|  |  |  | 	whisper.protocol = p2p.Protocol{ | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 		Name:    protocolName, | 
					
						
							|  |  |  | 		Version: uint(protocolVersion), | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 		Length:  2, | 
					
						
							| 
									
										
										
										
											2015-04-14 14:28:59 +03:00
										 |  |  | 		Run:     whisper.handlePeer, | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return whisper | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | // Protocol returns the whisper sub-protocol handler for this particular client. | 
					
						
							|  |  |  | func (self *Whisper) Protocol() p2p.Protocol { | 
					
						
							|  |  |  | 	return self.protocol | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | // Version returns the whisper sub-protocols version number. | 
					
						
							|  |  |  | func (self *Whisper) Version() uint { | 
					
						
							|  |  |  | 	return self.protocol.Version | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | // NewIdentity generates a new cryptographic identity for the client, and injects | 
					
						
							|  |  |  | // it into the known identities for message decryption. | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | func (self *Whisper) NewIdentity() *ecdsa.PrivateKey { | 
					
						
							|  |  |  | 	key, err := crypto.GenerateKey() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-14 18:12:18 +01:00
										 |  |  | 	self.keys[string(crypto.FromECDSAPub(&key.PublicKey))] = key | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return key | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | // HasIdentity checks if the the whisper node is configured with the private key | 
					
						
							|  |  |  | // of the specified public pair. | 
					
						
							| 
									
										
										
										
											2015-01-14 18:12:18 +01:00
										 |  |  | func (self *Whisper) HasIdentity(key *ecdsa.PublicKey) bool { | 
					
						
							|  |  |  | 	return self.keys[string(crypto.FromECDSAPub(key))] != nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | // GetIdentity retrieves the private key of the specified public identity. | 
					
						
							| 
									
										
										
										
											2015-01-14 18:12:18 +01:00
										 |  |  | func (self *Whisper) GetIdentity(key *ecdsa.PublicKey) *ecdsa.PrivateKey { | 
					
						
							|  |  |  | 	return self.keys[string(crypto.FromECDSAPub(key))] | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | // Watch installs a new message handler to run in case a matching packet arrives | 
					
						
							|  |  |  | // from the whisper network. | 
					
						
							|  |  |  | func (self *Whisper) Watch(options Filter) int { | 
					
						
							| 
									
										
										
										
											2015-04-21 18:31:08 +03:00
										 |  |  | 	filter := filterer{ | 
					
						
							|  |  |  | 		to:      string(crypto.FromECDSAPub(options.To)), | 
					
						
							|  |  |  | 		from:    string(crypto.FromECDSAPub(options.From)), | 
					
						
							|  |  |  | 		matcher: newTopicMatcher(options.Topics...), | 
					
						
							|  |  |  | 		fn: func(data interface{}) { | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 			options.Fn(data.(*Message)) | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return self.filters.Install(filter) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Unwatch removes an installed message handler. | 
					
						
							|  |  |  | func (self *Whisper) Unwatch(id int) { | 
					
						
							|  |  |  | 	self.filters.Uninstall(id) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Send injects a message into the whisper send queue, to be distributed in the | 
					
						
							|  |  |  | // network in the coming cycles. | 
					
						
							|  |  |  | func (self *Whisper) Send(envelope *Envelope) error { | 
					
						
							|  |  |  | 	return self.add(envelope) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *Whisper) Start() { | 
					
						
							|  |  |  | 	glog.V(logger.Info).Infoln("Whisper started") | 
					
						
							|  |  |  | 	go self.update() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *Whisper) Stop() { | 
					
						
							|  |  |  | 	close(self.quit) | 
					
						
							|  |  |  | 	glog.V(logger.Info).Infoln("Whisper stopped") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-17 16:45:44 +03:00
										 |  |  | // Messages retrieves all the currently pooled messages matching a filter id. | 
					
						
							| 
									
										
										
										
											2015-04-14 15:02:31 +03:00
										 |  |  | func (self *Whisper) Messages(id int) []*Message { | 
					
						
							|  |  |  | 	messages := make([]*Message, 0) | 
					
						
							|  |  |  | 	if filter := self.filters.Get(id); filter != nil { | 
					
						
							|  |  |  | 		for _, envelope := range self.messages { | 
					
						
							|  |  |  | 			if message := self.open(envelope); message != nil { | 
					
						
							|  |  |  | 				if self.filters.Match(filter, createFilter(message, envelope.Topics)) { | 
					
						
							|  |  |  | 					messages = append(messages, message) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return messages | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 14:28:59 +03:00
										 |  |  | // handlePeer is called by the underlying P2P layer when the whisper sub-protocol | 
					
						
							|  |  |  | // connection is negotiated. | 
					
						
							|  |  |  | func (self *Whisper) handlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error { | 
					
						
							| 
									
										
										
										
											2015-04-22 17:40:39 +03:00
										 |  |  | 	// Create the new peer and start tracking it | 
					
						
							|  |  |  | 	whisperPeer := newPeer(self, peer, rw) | 
					
						
							| 
									
										
										
										
											2015-04-14 14:28:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-16 13:05:35 +03:00
										 |  |  | 	self.peerMu.Lock() | 
					
						
							|  |  |  | 	self.peers[whisperPeer] = struct{}{} | 
					
						
							|  |  |  | 	self.peerMu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defer func() { | 
					
						
							|  |  |  | 		self.peerMu.Lock() | 
					
						
							|  |  |  | 		delete(self.peers, whisperPeer) | 
					
						
							|  |  |  | 		self.peerMu.Unlock() | 
					
						
							|  |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2015-04-22 17:40:39 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Run the peer handshake and state updates | 
					
						
							|  |  |  | 	if err := whisperPeer.handshake(); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	whisperPeer.start() | 
					
						
							|  |  |  | 	defer whisperPeer.stop() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 14:28:59 +03:00
										 |  |  | 	// Read and process inbound messages directly to merge into client-global state | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		// Fetch the next packet and decode the contained envelopes | 
					
						
							|  |  |  | 		packet, err := rw.ReadMsg() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		var envelopes []*Envelope | 
					
						
							|  |  |  | 		if err := packet.Decode(&envelopes); err != nil { | 
					
						
							| 
									
										
										
										
											2015-05-06 23:19:14 +02:00
										 |  |  | 			glog.V(logger.Info).Infof("%v: failed to decode envelope: %v", peer, err) | 
					
						
							| 
									
										
										
										
											2015-04-14 14:28:59 +03:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Inject all envelopes into the internal pool | 
					
						
							|  |  |  | 		for _, envelope := range envelopes { | 
					
						
							|  |  |  | 			if err := self.add(envelope); err != nil { | 
					
						
							|  |  |  | 				// TODO Punish peer here. Invalid envelope. | 
					
						
							| 
									
										
										
										
											2015-05-06 23:19:14 +02:00
										 |  |  | 				glog.V(logger.Debug).Infof("%v: failed to pool envelope: %v", peer, err) | 
					
						
							| 
									
										
										
										
											2015-04-14 14:28:59 +03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			whisperPeer.mark(envelope) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | // add inserts a new envelope into the message pool to be distributed within the | 
					
						
							|  |  |  | // whisper network. It also inserts the envelope into the expiration pool at the | 
					
						
							|  |  |  | // appropriate time-stamp. | 
					
						
							|  |  |  | func (self *Whisper) add(envelope *Envelope) error { | 
					
						
							| 
									
										
										
										
											2015-04-16 13:05:35 +03:00
										 |  |  | 	self.poolMu.Lock() | 
					
						
							|  |  |  | 	defer self.poolMu.Unlock() | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Insert the message into the tracked pool | 
					
						
							|  |  |  | 	hash := envelope.Hash() | 
					
						
							|  |  |  | 	if _, ok := self.messages[hash]; ok { | 
					
						
							|  |  |  | 		glog.V(logger.Detail).Infof("whisper envelope already cached: %x\n", envelope) | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	self.messages[hash] = envelope | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Insert the message into the expiration pool for later removal | 
					
						
							| 
									
										
										
										
											2015-04-16 13:05:35 +03:00
										 |  |  | 	if self.expirations[envelope.Expiry] == nil { | 
					
						
							|  |  |  | 		self.expirations[envelope.Expiry] = set.NewNonTS() | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-16 13:05:35 +03:00
										 |  |  | 	if !self.expirations[envelope.Expiry].Has(hash) { | 
					
						
							|  |  |  | 		self.expirations[envelope.Expiry].Add(hash) | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Notify the local node of a message arrival | 
					
						
							|  |  |  | 		go self.postEvent(envelope) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	glog.V(logger.Detail).Infof("cached whisper envelope %x\n", envelope) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2015-01-12 20:36:45 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | // postEvent opens an envelope with the configured identities and delivers the | 
					
						
							|  |  |  | // message upstream from application processing. | 
					
						
							|  |  |  | func (self *Whisper) postEvent(envelope *Envelope) { | 
					
						
							|  |  |  | 	if message := self.open(envelope); message != nil { | 
					
						
							|  |  |  | 		self.filters.Notify(createFilter(message, envelope.Topics), message) | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | // open tries to decrypt a whisper envelope with all the configured identities, | 
					
						
							|  |  |  | // returning the decrypted message and the key used to achieve it. If not keys | 
					
						
							|  |  |  | // are configured, open will return the payload as if non encrypted. | 
					
						
							|  |  |  | func (self *Whisper) open(envelope *Envelope) *Message { | 
					
						
							|  |  |  | 	// Short circuit if no identity is set, and assume clear-text | 
					
						
							|  |  |  | 	if len(self.keys) == 0 { | 
					
						
							|  |  |  | 		if message, err := envelope.Open(nil); err == nil { | 
					
						
							|  |  |  | 			return message | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 	// Iterate over the keys and try to decrypt the message | 
					
						
							|  |  |  | 	for _, key := range self.keys { | 
					
						
							|  |  |  | 		message, err := envelope.Open(key) | 
					
						
							| 
									
										
										
										
											2015-04-21 12:45:10 +03:00
										 |  |  | 		if err == nil { | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 			message.To = &key.PublicKey | 
					
						
							|  |  |  | 			return message | 
					
						
							| 
									
										
										
										
											2015-04-21 12:45:10 +03:00
										 |  |  | 		} else if err == ecies.ErrInvalidPublicKey { | 
					
						
							|  |  |  | 			return message | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 	// Failed to decrypt, don't return anything | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | // createFilter creates a message filter to check against installed handlers. | 
					
						
							|  |  |  | func createFilter(message *Message, topics []Topic) filter.Filter { | 
					
						
							| 
									
										
										
										
											2015-04-21 18:31:08 +03:00
										 |  |  | 	matcher := make([][]Topic, len(topics)) | 
					
						
							|  |  |  | 	for i, topic := range topics { | 
					
						
							|  |  |  | 		matcher[i] = []Topic{topic} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return filterer{ | 
					
						
							|  |  |  | 		to:      string(crypto.FromECDSAPub(message.To)), | 
					
						
							|  |  |  | 		from:    string(crypto.FromECDSAPub(message.Recover())), | 
					
						
							|  |  |  | 		matcher: newTopicMatcher(matcher...), | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // update loops until the lifetime of the whisper node, updating its internal | 
					
						
							|  |  |  | // state by expiring stale messages from the pool. | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | func (self *Whisper) update() { | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 	// Start a ticker to check for expirations | 
					
						
							| 
									
										
										
										
											2015-04-16 11:20:01 +03:00
										 |  |  | 	expire := time.NewTicker(expirationCycle) | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Repeat updates until termination is requested | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case <-expire.C: | 
					
						
							|  |  |  | 			self.expire() | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 		case <-self.quit: | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 			return | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-08 13:16:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | // expire iterates over all the expiration timestamps, removing all stale | 
					
						
							|  |  |  | // messages from the pools. | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | func (self *Whisper) expire() { | 
					
						
							| 
									
										
										
										
											2015-04-16 13:05:35 +03:00
										 |  |  | 	self.poolMu.Lock() | 
					
						
							|  |  |  | 	defer self.poolMu.Unlock() | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 	now := uint32(time.Now().Unix()) | 
					
						
							| 
									
										
										
										
											2015-04-16 13:05:35 +03:00
										 |  |  | 	for then, hashSet := range self.expirations { | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 		// Short circuit if a future time | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 		if then > now { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 		// Dump all expired messages and remove timestamp | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 		hashSet.Each(func(v interface{}) bool { | 
					
						
							| 
									
										
										
										
											2015-03-21 00:57:18 +01:00
										 |  |  | 			delete(self.messages, v.(common.Hash)) | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 			return true | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2015-04-16 13:05:35 +03:00
										 |  |  | 		self.expirations[then].Clear() | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | // envelopes retrieves all the messages currently pooled by the node. | 
					
						
							|  |  |  | func (self *Whisper) envelopes() []*Envelope { | 
					
						
							| 
									
										
										
										
											2015-04-16 13:05:35 +03:00
										 |  |  | 	self.poolMu.RLock() | 
					
						
							|  |  |  | 	defer self.poolMu.RUnlock() | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 	envelopes := make([]*Envelope, 0, len(self.messages)) | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	for _, envelope := range self.messages { | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 		envelopes = append(envelopes, envelope) | 
					
						
							| 
									
										
										
										
											2015-01-12 20:36:45 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-14 13:24:43 +03:00
										 |  |  | 	return envelopes | 
					
						
							| 
									
										
										
										
											2015-01-12 20:36:45 +01:00
										 |  |  | } |