123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- /*
- This file is part of cpp-ethereum.
- cpp-ethereum is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- cpp-ethereum is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
- */
- /** @file WhisperPeer.cpp
- * @author Gav Wood <i@gavwood.com>
- * @date 2014
- */
- #include <libdevcore/Log.h>
- #include <libp2p/All.h>
- #include "WhisperHost.h"
- using namespace std;
- using namespace dev;
- using namespace dev::p2p;
- using namespace dev::shh;
- WhisperPeer::WhisperPeer(std::shared_ptr<Session> _s, HostCapabilityFace* _h, unsigned _i, CapDesc const&, uint16_t _capID):
- Capability(_s, _h, _i, _capID)
- {
- RLPStream s;
- sealAndSend(prep(s, StatusPacket, 1) << version());
- noteAdvertiseTopicsOfInterest();
- }
- WhisperPeer::~WhisperPeer()
- {
- }
- WhisperHost* WhisperPeer::host() const
- {
- return static_cast<WhisperHost*>(Capability::hostCapability());
- }
- bool WhisperPeer::interpret(unsigned _id, RLP const& _r)
- {
- switch (_id)
- {
- case StatusPacket:
- {
- auto protocolVersion = _r[0].toInt<unsigned>();
- clog(NetMessageSummary) << "Status: " << protocolVersion;
- if (protocolVersion != version())
- disable("Invalid protocol version.");
- for (auto const& m: host()->all())
- {
- Guard l(x_unseen);
- m_unseen.insert(make_pair(0, m.first));
- }
- if (session()->id() < host()->host()->id())
- sendMessages();
- noteAdvertiseTopicsOfInterest();
- break;
- }
- case MessagesPacket:
- {
- for (auto i: _r)
- host()->inject(Envelope(i), this);
- break;
- }
- case TopicFilterPacket:
- {
- setBloom((TopicBloomFilterHash)_r[0]);
- break;
- }
- default:
- return false;
- }
- return true;
- }
- void WhisperPeer::sendMessages()
- {
- if (m_advertiseTopicsOfInterest)
- sendTopicsOfInterest(host()->bloom());
- multimap<unsigned, h256> available;
- DEV_GUARDED(x_unseen)
- m_unseen.swap(available);
- RLPStream amalg;
- // send the highest rated messages first
- for (auto i = available.rbegin(); i != available.rend(); ++i)
- host()->streamMessage(i->second, amalg);
- unsigned msgCount = available.size();
- if (msgCount)
- {
- RLPStream s;
- prep(s, MessagesPacket, msgCount).appendRaw(amalg.out(), msgCount);
- sealAndSend(s);
- }
- }
- void WhisperPeer::noteNewMessage(h256 _h, Envelope const& _m)
- {
- unsigned rate = ratingForPeer(_m);
- Guard l(x_unseen);
- m_unseen.insert(make_pair(rate, _h));
- }
- unsigned WhisperPeer::ratingForPeer(Envelope const& e) const
- {
- // we try to estimate, how valuable this nessage will be for the remote peer,
- // according to the following criteria:
- // 1. bloom filter
- // 2. time to live
- // 3. proof of work
- unsigned rating = 0;
- if (e.matchesBloomFilter(bloom()))
- ++rating;
- rating *= 256;
- unsigned ttlReward = (256 > e.ttl() ? 256 - e.ttl() : 0);
- rating += ttlReward;
- rating *= 256;
- rating += e.workProved();
- return rating;
- }
- void WhisperPeer::sendTopicsOfInterest(TopicBloomFilterHash const& _bloom)
- {
- DEV_GUARDED(x_advertiseTopicsOfInterest)
- m_advertiseTopicsOfInterest = false;
- RLPStream s;
- prep(s, TopicFilterPacket, 1);
- s << _bloom;
- sealAndSend(s);
- }
|