aboutsummaryrefslogtreecommitdiffstats
path: root/whisper/whisperv5/filter.go
diff options
context:
space:
mode:
authorgluk256 <gluk256@users.noreply.github.com>2017-04-10 05:49:22 +0800
committerFelix Lange <fjl@users.noreply.github.com>2017-04-10 05:49:22 +0800
commit9cd713551627a9b48e04a77f64a15ea6f829dcf4 (patch)
treef1849e61cd8269dfe9c70861f49216cf78acec3b /whisper/whisperv5/filter.go
parent8570ef19eb8dfe4e2a450525c589dec291f3a517 (diff)
downloaddexon-9cd713551627a9b48e04a77f64a15ea6f829dcf4.tar
dexon-9cd713551627a9b48e04a77f64a15ea6f829dcf4.tar.gz
dexon-9cd713551627a9b48e04a77f64a15ea6f829dcf4.tar.bz2
dexon-9cd713551627a9b48e04a77f64a15ea6f829dcf4.tar.lz
dexon-9cd713551627a9b48e04a77f64a15ea6f829dcf4.tar.xz
dexon-9cd713551627a9b48e04a77f64a15ea6f829dcf4.tar.zst
dexon-9cd713551627a9b48e04a77f64a15ea6f829dcf4.zip
whisper: big refactoring (#13852)
* whisper: GetMessages fixed; size restriction updated * whisper: made PoW and MaxMsgSize customizable * whisper: test added * whisper: sym key management changed * whisper: identity management refactored * whisper: API refactoring (Post and Filter) * whisper: big refactoring complete * whisper: spelling fix * whisper: variable topic size allowed for a filter * whisper: final update * whisper: formatting * whisper: file exchange introduced in wnode * whisper: bugfix * whisper: API updated + new tests * whisper: statistics updated * whisper: wnode server updated * whisper: allowed filtering for variable topic size * whisper: tests added * whisper: resolving merge conflicts * whisper: refactoring (documenting mostly) * whsiper: tests fixed * whisper: down cased error messages * whisper: documenting the API functions * whisper: logging fixed * whisper: fixed wnode parameters * whisper: logs fixed (typos)
Diffstat (limited to 'whisper/whisperv5/filter.go')
-rw-r--r--whisper/whisperv5/filter.go99
1 files changed, 57 insertions, 42 deletions
diff --git a/whisper/whisperv5/filter.go b/whisper/whisperv5/filter.go
index ffa5ae946..03101d4a4 100644
--- a/whisper/whisperv5/filter.go
+++ b/whisper/whisperv5/filter.go
@@ -18,7 +18,6 @@ package whisperv5
import (
"crypto/ecdsa"
- crand "crypto/rand"
"fmt"
"sync"
@@ -30,9 +29,9 @@ type Filter struct {
Src *ecdsa.PublicKey // Sender of the message
KeyAsym *ecdsa.PrivateKey // Private Key of recipient
KeySym []byte // Key associated with the Topic
- Topics []TopicType // Topics to filter messages with
+ Topics [][]byte // Topics to filter messages with
PoW float64 // Proof of work as described in the Whisper spec
- AcceptP2P bool // Indicates whether this filter is interested in direct peer-to-peer messages
+ AllowP2P bool // Indicates whether this filter is interested in direct peer-to-peer messages
SymKeyHash common.Hash // The Keccak256Hash of the symmetric key, needed for optimization
Messages map[common.Hash]*ReceivedMessage
@@ -52,47 +51,35 @@ func NewFilters(w *Whisper) *Filters {
}
}
-func (fs *Filters) generateRandomID() (id string, err error) {
- buf := make([]byte, 20)
- for i := 0; i < 3; i++ {
- _, err = crand.Read(buf)
- if err != nil {
- continue
- }
- if !validateSymmetricKey(buf) {
- err = fmt.Errorf("error in generateRandomID: crypto/rand failed to generate random data")
- continue
- }
- id = common.Bytes2Hex(buf)
- if fs.watchers[id] != nil {
- err = fmt.Errorf("error in generateRandomID: generated same ID twice")
- continue
- }
- return id, err
- }
-
- return "", err
-}
-
func (fs *Filters) Install(watcher *Filter) (string, error) {
if watcher.Messages == nil {
watcher.Messages = make(map[common.Hash]*ReceivedMessage)
}
+ id, err := GenerateRandomID()
+ if err != nil {
+ return "", err
+ }
+
fs.mutex.Lock()
defer fs.mutex.Unlock()
- id, err := fs.generateRandomID()
- if err == nil {
- fs.watchers[id] = watcher
+ if fs.watchers[id] != nil {
+ return "", fmt.Errorf("failed to generate unique ID")
}
+
+ fs.watchers[id] = watcher
return id, err
}
-func (fs *Filters) Uninstall(id string) {
+func (fs *Filters) Uninstall(id string) bool {
fs.mutex.Lock()
defer fs.mutex.Unlock()
- delete(fs.watchers, id)
+ if fs.watchers[id] != nil {
+ delete(fs.watchers, id)
+ return true
+ }
+ return false
}
func (fs *Filters) Get(id string) *Filter {
@@ -102,11 +89,16 @@ func (fs *Filters) Get(id string) *Filter {
}
func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
- fs.mutex.RLock()
var msg *ReceivedMessage
- for j, watcher := range fs.watchers {
- if p2pMessage && !watcher.AcceptP2P {
- log.Trace(fmt.Sprintf("msg [%x], filter [%s]: p2p messages are not allowed", env.Hash(), j))
+
+ fs.mutex.RLock()
+ defer fs.mutex.RUnlock()
+
+ i := -1 // only used for logging info
+ for _, watcher := range fs.watchers {
+ i++
+ if p2pMessage && !watcher.AllowP2P {
+ log.Trace(fmt.Sprintf("msg [%x], filter [%d]: p2p messages are not allowed", env.Hash(), i))
continue
}
@@ -118,22 +110,32 @@ func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
if match {
msg = env.Open(watcher)
if msg == nil {
- log.Trace(fmt.Sprintf("msg [%x], filter [%s]: failed to open", env.Hash(), j))
+ log.Trace("processing message: failed to open", "message", env.Hash().Hex(), "filter", i)
}
} else {
- log.Trace(fmt.Sprintf("msg [%x], filter [%s]: does not match", env.Hash(), j))
+ log.Trace("processing message: does not match", "message", env.Hash().Hex(), "filter", i)
}
}
if match && msg != nil {
+ log.Trace("processing message: decrypted", "hash", env.Hash().Hex())
watcher.Trigger(msg)
}
}
- fs.mutex.RUnlock() // we need to unlock before calling addDecryptedMessage
+}
- if msg != nil {
- fs.whisper.addDecryptedMessage(msg)
+func (f *Filter) processEnvelope(env *Envelope) *ReceivedMessage {
+ if f.MatchEnvelope(env) {
+ msg := env.Open(f)
+ if msg != nil {
+ return msg
+ } else {
+ log.Trace("processing envelope: failed to open", "hash", env.Hash().Hex())
+ }
+ } else {
+ log.Trace("processing envelope: does not match", "hash", env.Hash().Hex())
}
+ return nil
}
func (f *Filter) expectsAsymmetricEncryption() bool {
@@ -200,20 +202,33 @@ func (f *Filter) MatchTopic(topic TopicType) bool {
return true
}
- for _, t := range f.Topics {
- if t == topic {
+ for _, bt := range f.Topics {
+ if matchSingleTopic(topic, bt) {
return true
}
}
return false
}
+func matchSingleTopic(topic TopicType, bt []byte) bool {
+ if len(bt) > 4 {
+ bt = bt[:4]
+ }
+
+ for j, b := range bt {
+ if topic[j] != b {
+ return false
+ }
+ }
+ return true
+}
+
func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool {
if !ValidatePublicKey(a) {
return false
} else if !ValidatePublicKey(b) {
return false
}
- // the Curve is always the same, just compare the points
+ // the curve is always the same, just compare the points
return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0
}