RLPXPacket.h 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  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 RLPXPacket.h
  15. * @author Alex Leverington <nessence@gmail.com>
  16. * @date 2015
  17. */
  18. #pragma once
  19. #include <algorithm>
  20. #include "Common.h"
  21. namespace dev
  22. {
  23. namespace p2p
  24. {
  25. struct RLPXInvalidPacket: virtual dev::Exception {};
  26. static bytesConstRef nextRLP(bytesConstRef _b) { try { RLP r(_b, RLP::AllowNonCanon); return _b.cropped(0, std::min((size_t)r.actualSize(), _b.size())); } catch(...) {} return bytesConstRef(); }
  27. /**
  28. * RLPX Packet
  29. */
  30. class RLPXPacket
  31. {
  32. public:
  33. /// Construct packet. RLPStream data is invalidated.
  34. RLPXPacket(uint8_t _capId, RLPStream& _type, RLPStream& _data): m_cap(_capId), m_type(_type.out()), m_data(_data.out()) {}
  35. /// Construct packet from single bytestream. RLPStream data is invalidated.
  36. RLPXPacket(unsigned _capId, bytesConstRef _in): m_cap(_capId), m_type(nextRLP(_in).toBytes()) { if (_in.size() > m_type.size()) { m_data.resize(_in.size() - m_type.size()); _in.cropped(m_type.size()).copyTo(&m_data); } }
  37. RLPXPacket(RLPXPacket const& _p) = delete;
  38. RLPXPacket(RLPXPacket&& _p): m_cap(_p.m_cap), m_type(_p.m_type), m_data(_p.m_data) {}
  39. bytes const& type() const { return m_type; }
  40. bytes const& data() const { return m_data; }
  41. uint8_t cap() const { return m_cap; }
  42. size_t size() const { try { return RLP(m_type).actualSize() + RLP(m_data, RLP::LaissezFaire).actualSize(); } catch(...) { return 0; } }
  43. /// Appends byte data and returns if packet is valid.
  44. bool append(bytesConstRef _in) { auto offset = m_data.size(); m_data.resize(offset + _in.size()); _in.copyTo(bytesRef(&m_data).cropped(offset)); return isValid(); }
  45. virtual bool isValid() const noexcept { try { return !(m_type.empty() && m_data.empty()) && RLP(m_type).actualSize() == m_type.size() && RLP(m_data).actualSize() == m_data.size(); } catch (...) {} return false; }
  46. protected:
  47. uint8_t m_cap;
  48. bytes m_type;
  49. bytes m_data;
  50. };
  51. }
  52. }