github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/whisper/mailserver/mailserver.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU 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 // go-ethereum 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 General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package mailserver 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 23 "github.com/atheioschain/go-atheios/cmd/utils" 24 "github.com/atheioschain/go-atheios/common" 25 "github.com/atheioschain/go-atheios/crypto" 26 "github.com/atheioschain/go-atheios/logger" 27 "github.com/atheioschain/go-atheios/logger/glog" 28 "github.com/atheioschain/go-atheios/rlp" 29 whisper "github.com/atheioschain/go-atheios/whisper/whisperv5" 30 "github.com/syndtr/goleveldb/leveldb" 31 "github.com/syndtr/goleveldb/leveldb/util" 32 ) 33 34 const MailServerKeyName = "958e04ab302fb36ad2616a352cbac79d" 35 36 type WMailServer struct { 37 db *leveldb.DB 38 w *whisper.Whisper 39 pow float64 40 key []byte 41 } 42 43 type DBKey struct { 44 timestamp uint32 45 hash common.Hash 46 raw []byte 47 } 48 49 func NewDbKey(t uint32, h common.Hash) *DBKey { 50 const sz = common.HashLength + 4 51 var k DBKey 52 k.timestamp = t 53 k.hash = h 54 k.raw = make([]byte, sz) 55 binary.BigEndian.PutUint32(k.raw, k.timestamp) 56 copy(k.raw[4:], k.hash[:]) 57 return &k 58 } 59 60 func (s *WMailServer) Init(shh *whisper.Whisper, path string, password string, pow float64) { 61 var err error 62 if len(path) == 0 { 63 utils.Fatalf("DB file is not specified") 64 } 65 66 if len(password) == 0 { 67 utils.Fatalf("Password is not specified for MailServer") 68 } 69 70 s.db, err = leveldb.OpenFile(path, nil) 71 if err != nil { 72 utils.Fatalf("Failed to open DB file: %s", err) 73 } 74 75 s.w = shh 76 s.pow = pow 77 78 err = s.w.AddSymKey(MailServerKeyName, []byte(password)) 79 if err != nil { 80 utils.Fatalf("Failed to create symmetric key for MailServer: %s", err) 81 } 82 s.key = s.w.GetSymKey(MailServerKeyName) 83 } 84 85 func (s *WMailServer) Close() { 86 if s.db != nil { 87 s.db.Close() 88 } 89 } 90 91 func (s *WMailServer) Archive(env *whisper.Envelope) { 92 key := NewDbKey(env.Expiry-env.TTL, env.Hash()) 93 rawEnvelope, err := rlp.EncodeToBytes(env) 94 if err != nil { 95 glog.V(logger.Error).Infof("rlp.EncodeToBytes failed: %s", err) 96 } else { 97 err = s.db.Put(key.raw, rawEnvelope, nil) 98 if err != nil { 99 glog.V(logger.Error).Infof("Writing to DB failed: %s", err) 100 } 101 } 102 } 103 104 func (s *WMailServer) DeliverMail(peer *whisper.Peer, request *whisper.Envelope) { 105 if peer == nil { 106 glog.V(logger.Error).Info("Whisper peer is nil") 107 return 108 } 109 110 ok, lower, upper, topic := s.validateRequest(peer.ID(), request) 111 if ok { 112 s.processRequest(peer, lower, upper, topic) 113 } 114 } 115 116 func (s *WMailServer) processRequest(peer *whisper.Peer, lower, upper uint32, topic whisper.TopicType) []*whisper.Envelope { 117 ret := make([]*whisper.Envelope, 0) 118 var err error 119 var zero common.Hash 120 var empty whisper.TopicType 121 kl := NewDbKey(lower, zero) 122 ku := NewDbKey(upper, zero) 123 i := s.db.NewIterator(&util.Range{Start: kl.raw, Limit: ku.raw}, nil) 124 defer i.Release() 125 126 for i.Next() { 127 var envelope whisper.Envelope 128 err = rlp.DecodeBytes(i.Value(), &envelope) 129 if err != nil { 130 glog.V(logger.Error).Infof("RLP decoding failed: %s", err) 131 } 132 133 if topic == empty || envelope.Topic == topic { 134 if peer == nil { 135 // used for test purposes 136 ret = append(ret, &envelope) 137 } else { 138 err = s.w.SendP2PDirect(peer, &envelope) 139 if err != nil { 140 glog.V(logger.Error).Infof("Failed to send direct message to peer: %s", err) 141 return nil 142 } 143 } 144 } 145 } 146 147 err = i.Error() 148 if err != nil { 149 glog.V(logger.Error).Infof("Level DB iterator error: %s", err) 150 } 151 152 return ret 153 } 154 155 func (s *WMailServer) validateRequest(peerID []byte, request *whisper.Envelope) (bool, uint32, uint32, whisper.TopicType) { 156 var topic whisper.TopicType 157 if s.pow > 0.0 && request.PoW() < s.pow { 158 return false, 0, 0, topic 159 } 160 161 f := whisper.Filter{KeySym: s.key} 162 decrypted := request.Open(&f) 163 if decrypted == nil { 164 glog.V(logger.Warn).Infof("Failed to decrypt p2p request") 165 return false, 0, 0, topic 166 } 167 168 if len(decrypted.Payload) < 8 { 169 glog.V(logger.Warn).Infof("Undersized p2p request") 170 return false, 0, 0, topic 171 } 172 173 src := crypto.FromECDSAPub(decrypted.Src) 174 if len(src)-len(peerID) == 1 { 175 src = src[1:] 176 } 177 if !bytes.Equal(peerID, src) { 178 glog.V(logger.Warn).Infof("Wrong signature of p2p request") 179 return false, 0, 0, topic 180 } 181 182 lower := binary.BigEndian.Uint32(decrypted.Payload[:4]) 183 upper := binary.BigEndian.Uint32(decrypted.Payload[4:8]) 184 185 if len(decrypted.Payload) >= 8+whisper.TopicLength { 186 topic = whisper.BytesToTopic(decrypted.Payload[8:]) 187 } 188 189 return true, lower, upper, topic 190 }