github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/whisper/filter.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Contains the message filter for fine grained subscriptions. 18 19 package whisper 20 21 import ( 22 "crypto/ecdsa" 23 24 "github.com/ethereumproject/go-ethereum/event/filter" 25 ) 26 27 // Filter is used to subscribe to specific types of whisper messages. 28 type Filter struct { 29 To *ecdsa.PublicKey // Recipient of the message 30 From *ecdsa.PublicKey // Sender of the message 31 Topics [][]Topic // Topics to filter messages with 32 Fn func(msg *Message) // Handler in case of a match 33 } 34 35 // NewFilterTopics creates a 2D topic array used by whisper.Filter from binary 36 // data elements. 37 func NewFilterTopics(data ...[][]byte) [][]Topic { 38 filter := make([][]Topic, len(data)) 39 for i, condition := range data { 40 // Handle the special case of condition == [[]byte{}] 41 if len(condition) == 1 && len(condition[0]) == 0 { 42 filter[i] = []Topic{} 43 continue 44 } 45 // Otherwise flatten normally 46 filter[i] = NewTopics(condition...) 47 } 48 return filter 49 } 50 51 // filterer is the internal, fully initialized filter ready to match inbound 52 // messages to a variety of criteria. 53 type filterer struct { 54 to string // Recipient of the message 55 from string // Sender of the message 56 matcher *topicMatcher // Topics to filter messages with 57 fn func(data interface{}) // Handler in case of a match 58 } 59 60 // Compare checks if the specified filter matches the current one. 61 func (self filterer) Compare(f filter.Filter) bool { 62 filter := f.(filterer) 63 64 // Check the message sender and recipient 65 if len(self.to) > 0 && self.to != filter.to { 66 return false 67 } 68 if len(self.from) > 0 && self.from != filter.from { 69 return false 70 } 71 // Check the topic filtering 72 topics := make([]Topic, len(filter.matcher.conditions)) 73 for i, group := range filter.matcher.conditions { 74 // Message should contain a single topic entry, extract 75 for topics[i] = range group { 76 break 77 } 78 } 79 if !self.matcher.Matches(topics) { 80 return false 81 } 82 return true 83 } 84 85 // Trigger is called when a filter successfully matches an inbound message. 86 func (self filterer) Trigger(data interface{}) { 87 self.fn(data) 88 }