WhisperPeer.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file WhisperPeer.cpp
  15. * @author Gav Wood <i@gavwood.com>
  16. * @date 2014
  17. */
  18. #include <libdevcore/Log.h>
  19. #include <libp2p/All.h>
  20. #include "WhisperHost.h"
  21. using namespace std;
  22. using namespace dev;
  23. using namespace dev::p2p;
  24. using namespace dev::shh;
  25. WhisperPeer::WhisperPeer(std::shared_ptr<Session> _s, HostCapabilityFace* _h, unsigned _i, CapDesc const&, uint16_t _capID):
  26. Capability(_s, _h, _i, _capID)
  27. {
  28. RLPStream s;
  29. sealAndSend(prep(s, StatusPacket, 1) << version());
  30. noteAdvertiseTopicsOfInterest();
  31. }
  32. WhisperPeer::~WhisperPeer()
  33. {
  34. }
  35. WhisperHost* WhisperPeer::host() const
  36. {
  37. return static_cast<WhisperHost*>(Capability::hostCapability());
  38. }
  39. bool WhisperPeer::interpret(unsigned _id, RLP const& _r)
  40. {
  41. switch (_id)
  42. {
  43. case StatusPacket:
  44. {
  45. auto protocolVersion = _r[0].toInt<unsigned>();
  46. clog(NetMessageSummary) << "Status: " << protocolVersion;
  47. if (protocolVersion != version())
  48. disable("Invalid protocol version.");
  49. for (auto const& m: host()->all())
  50. {
  51. Guard l(x_unseen);
  52. m_unseen.insert(make_pair(0, m.first));
  53. }
  54. if (session()->id() < host()->host()->id())
  55. sendMessages();
  56. noteAdvertiseTopicsOfInterest();
  57. break;
  58. }
  59. case MessagesPacket:
  60. {
  61. for (auto i: _r)
  62. host()->inject(Envelope(i), this);
  63. break;
  64. }
  65. case TopicFilterPacket:
  66. {
  67. setBloom((TopicBloomFilterHash)_r[0]);
  68. break;
  69. }
  70. default:
  71. return false;
  72. }
  73. return true;
  74. }
  75. void WhisperPeer::sendMessages()
  76. {
  77. if (m_advertiseTopicsOfInterest)
  78. sendTopicsOfInterest(host()->bloom());
  79. multimap<unsigned, h256> available;
  80. DEV_GUARDED(x_unseen)
  81. m_unseen.swap(available);
  82. RLPStream amalg;
  83. // send the highest rated messages first
  84. for (auto i = available.rbegin(); i != available.rend(); ++i)
  85. host()->streamMessage(i->second, amalg);
  86. unsigned msgCount = available.size();
  87. if (msgCount)
  88. {
  89. RLPStream s;
  90. prep(s, MessagesPacket, msgCount).appendRaw(amalg.out(), msgCount);
  91. sealAndSend(s);
  92. }
  93. }
  94. void WhisperPeer::noteNewMessage(h256 _h, Envelope const& _m)
  95. {
  96. unsigned rate = ratingForPeer(_m);
  97. Guard l(x_unseen);
  98. m_unseen.insert(make_pair(rate, _h));
  99. }
  100. unsigned WhisperPeer::ratingForPeer(Envelope const& e) const
  101. {
  102. // we try to estimate, how valuable this nessage will be for the remote peer,
  103. // according to the following criteria:
  104. // 1. bloom filter
  105. // 2. time to live
  106. // 3. proof of work
  107. unsigned rating = 0;
  108. if (e.matchesBloomFilter(bloom()))
  109. ++rating;
  110. rating *= 256;
  111. unsigned ttlReward = (256 > e.ttl() ? 256 - e.ttl() : 0);
  112. rating += ttlReward;
  113. rating *= 256;
  114. rating += e.workProved();
  115. return rating;
  116. }
  117. void WhisperPeer::sendTopicsOfInterest(TopicBloomFilterHash const& _bloom)
  118. {
  119. DEV_GUARDED(x_advertiseTopicsOfInterest)
  120. m_advertiseTopicsOfInterest = false;
  121. RLPStream s;
  122. prep(s, TopicFilterPacket, 1);
  123. s << _bloom;
  124. sealAndSend(s);
  125. }