Furrent
message.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cstdint>
4 #include <memory>
5 #include <optional>
6 #include <vector>
7 
8 #include "download/bitfield.hpp"
9 #include "torrent.hpp"
10 #include "util/result.hpp"
11 
12 using namespace fur::util;
13 using namespace fur::download::bitfield;
14 
15 namespace fur::download::message {
16 enum class MessageKind {
17  KeepAlive,
18  Choke,
19  Unchoke,
20  Interested,
22  Have,
23  Bitfield,
24  Request,
25  Piece,
26 };
27 
28 enum class DecodeError {
39 };
40 
41 std::string display_decode_error(const DecodeError& err);
42 
46 class Message {
47  public:
48  virtual ~Message() = default;
52  [[nodiscard]] virtual std::vector<uint8_t> encode() const;
53 
59  [[nodiscard]] static Result<std::unique_ptr<Message>, DecodeError> decode(
60  const TorrentFile& torrent, const std::vector<uint8_t>& buf);
61 
64  [[nodiscard]] virtual MessageKind kind() const = 0;
65 
66  private:
68  [[nodiscard]] virtual uint8_t message_id() const = 0;
71  [[nodiscard]] virtual std::vector<uint8_t> encode_payload() const = 0;
72 };
73 
78 class KeepAliveMessage final : public Message {
79  public:
82  [[nodiscard]] std::vector<uint8_t> encode() const override {
83  return {0, 0, 0, 0};
84  }
85 
86  [[nodiscard]] MessageKind kind() const override {
87  return MessageKind::KeepAlive;
88  }
89 
90  private:
93  [[nodiscard]] uint8_t message_id() const override { return 0; }
96  [[nodiscard]] std::vector<uint8_t> encode_payload() const override {
97  return {};
98  }
99 };
100 
104 class ChokeMessage final : public Message {
105  public:
106  [[nodiscard]] MessageKind kind() const override { return MessageKind::Choke; }
107 
108  private:
109  [[nodiscard]] uint8_t message_id() const override { return 0; }
110  [[nodiscard]] std::vector<uint8_t> encode_payload() const override {
111  return {};
112  }
113 };
114 
117 class UnchokeMessage final : public Message {
118  public:
119  [[nodiscard]] MessageKind kind() const override {
120  return MessageKind::Unchoke;
121  }
122 
123  private:
124  [[nodiscard]] uint8_t message_id() const override { return 1; }
125  [[nodiscard]] std::vector<uint8_t> encode_payload() const override {
126  return {};
127  }
128 };
129 
132 class InterestedMessage final : public Message {
133  public:
134  [[nodiscard]] MessageKind kind() const override {
135  return MessageKind::Interested;
136  }
137 
138  private:
139  [[nodiscard]] uint8_t message_id() const override { return 2; }
140  [[nodiscard]] std::vector<uint8_t> encode_payload() const override {
141  return {};
142  }
143 };
144 
148 class NotInterestedMessage final : public Message {
149  public:
150  [[nodiscard]] MessageKind kind() const override {
151  return MessageKind::NotInterested;
152  }
153 
154  private:
155  [[nodiscard]] uint8_t message_id() const override { return 3; }
156  [[nodiscard]] std::vector<uint8_t> encode_payload() const override {
157  return {};
158  }
159 };
160 
163 class HaveMessage final : public Message {
164  public:
166  const int64_t index;
167 
168  explicit HaveMessage(int64_t index) : index{index} {}
169 
170  [[nodiscard]] static Result<std::unique_ptr<HaveMessage>, DecodeError> decode(
171  const std::vector<uint8_t>& buf);
172 
173  [[nodiscard]] MessageKind kind() const override { return MessageKind::Have; }
174 
175  private:
176  [[nodiscard]] uint8_t message_id() const override { return 4; }
177  [[nodiscard]] std::vector<uint8_t> encode_payload() const override;
178 };
179 
183 class BitfieldMessage final : public Message {
184  public:
187 
188  explicit BitfieldMessage(Bitfield bitfield) : bitfield{std::move(bitfield)} {}
189 
190  [[nodiscard]] static std::unique_ptr<BitfieldMessage> decode(
191  const TorrentFile& torrent, const std::vector<uint8_t>& buf);
192 
193  [[nodiscard]] MessageKind kind() const override {
194  return MessageKind::Bitfield;
195  }
196 
197  private:
198  [[nodiscard]] uint8_t message_id() const override { return 5; }
199  [[nodiscard]] std::vector<uint8_t> encode_payload() const override;
200 };
201 
204 class RequestMessage final : public Message {
205  public:
207  const int64_t index;
209  const int64_t begin;
211  const int64_t length;
212 
213  RequestMessage(int64_t index, int64_t begin, int64_t length)
214  : index{index}, begin{begin}, length{length} {}
215 
217  decode(const std::vector<uint8_t>& buf);
218 
219  [[nodiscard]] MessageKind kind() const override {
220  return MessageKind::Request;
221  }
222 
223  private:
224  [[nodiscard]] uint8_t message_id() const override { return 6; }
225  [[nodiscard]] std::vector<uint8_t> encode_payload() const override;
226 };
227 
231 class PieceMessage final : public Message {
232  public:
234  const int64_t index;
236  const int64_t begin;
238  const std::vector<uint8_t> block;
239 
240  PieceMessage(int64_t index, int64_t begin, std::vector<uint8_t> block)
241  : index{index}, begin{begin}, block{std::move(block)} {}
242 
244  decode(const std::vector<uint8_t>& buf);
245 
246  [[nodiscard]] MessageKind kind() const override { return MessageKind::Piece; }
247 
248  private:
249  [[nodiscard]] uint8_t message_id() const override { return 7; }
250  [[nodiscard]] std::vector<uint8_t> encode_payload() const override;
251 };
252 
253 // WARN: BitTorrent specifies a CancelMessage with ID 8, but we don't expect to
254 // ever send or receive it
255 
256 // WARN: BitTorrent specifies a PortMessage with ID 9, but we don't expect to
257 // ever send or receive it
258 } // namespace fur::download::message
fur::download::message::MessageKind
MessageKind
Definition: message.hpp:16
fur::download::message::HaveMessage::index
const int64_t index
Index of the newly acquired piece.
Definition: message.hpp:166
fur::download::message::UnchokeMessage::kind
MessageKind kind() const override
Definition: message.hpp:119
torrent.hpp
fur::download::message::InterestedMessage
Definition: message.hpp:132
fur::download::message::InterestedMessage::kind
MessageKind kind() const override
Definition: message.hpp:134
fur::download::bitfield::Bitfield
Definition: bitfield.hpp:24
fur::download::message::RequestMessage::index
const int64_t index
Index of the piece.
Definition: message.hpp:207
fur::download::message::RequestMessage::RequestMessage
RequestMessage(int64_t index, int64_t begin, int64_t length)
Definition: message.hpp:213
fur::download::message::UnchokeMessage
Definition: message.hpp:117
fur::util::Result
Used to handle errors without using exceptions.
Definition: result.hpp:18
fur::download::message::PieceMessage::block
const std::vector< uint8_t > block
The actual bytes from the piece.
Definition: message.hpp:238
fur::download::message::MessageKind::Interested
@ Interested
fur::download::message::RequestMessage::kind
MessageKind kind() const override
Definition: message.hpp:219
fur::download::message::KeepAliveMessage
Definition: message.hpp:78
fur::download::message::KeepAliveMessage::encode
std::vector< uint8_t > encode() const override
Definition: message.hpp:82
fur::download::message::display_decode_error
std::string display_decode_error(const DecodeError &err)
Definition: message.cpp:10
fur::download::message::MessageKind::Choke
@ Choke
fur::download::message::MessageKind::NotInterested
@ NotInterested
fur::download::message::DecodeError
DecodeError
Definition: message.hpp:28
fur::download::message::BitfieldMessage::bitfield
const Bitfield bitfield
Bitfield representing the pieces available.
Definition: message.hpp:186
fur::download::message::KeepAliveMessage::kind
MessageKind kind() const override
Definition: message.hpp:86
fur::download::message::BitfieldMessage::BitfieldMessage
BitfieldMessage(Bitfield bitfield)
Definition: message.hpp:188
fur::download::message::DecodeError::UnknownMessageID
@ UnknownMessageID
Not a known message type.
fur::download::message::HaveMessage
Definition: message.hpp:163
fur::download::message::RequestMessage::begin
const int64_t begin
Offset from the beginning of the piece.
Definition: message.hpp:209
bitfield.hpp
fur::download::message::PieceMessage
Definition: message.hpp:231
fur::download::message::HaveMessage::HaveMessage
HaveMessage(int64_t index)
Definition: message.hpp:168
fur::TorrentFile
Represents a parsed .torrent file.
Definition: torrent.hpp:32
fur::download::message::MessageKind::Unchoke
@ Unchoke
fur::download::message::RequestMessage::length
const int64_t length
How many bytes we're asking. Typically 16KB.
Definition: message.hpp:211
fur::download::message::BitfieldMessage
Definition: message.hpp:183
fur::download::message::BitfieldMessage::kind
MessageKind kind() const override
Definition: message.hpp:193
fur::download::message::NotInterestedMessage::kind
MessageKind kind() const override
Definition: message.hpp:150
fur::download::message::DecodeError::InvalidPayloadLength
@ InvalidPayloadLength
fur::download::message::Message
Definition: message.hpp:46
fur::download::message::MessageKind::Have
@ Have
fur::download::message::ChokeMessage::kind
MessageKind kind() const override
Definition: message.hpp:106
fur::download::message::DecodeError::UnexpectedPayload
@ UnexpectedPayload
Message has payload but didn't expect any.
fur::download::message
Definition: message.cpp:9
fur::download::message::PieceMessage::index
const int64_t index
Index of the piece.
Definition: message.hpp:234
fur::download::message::MessageKind::KeepAlive
@ KeepAlive
fur::download::message::NotInterestedMessage
Definition: message.hpp:148
fur::download::message::PieceMessage::kind
MessageKind kind() const override
Definition: message.hpp:246
fur::Piece
Definition: torrent.hpp:75
fur::download::message::DecodeError::InvalidHeader
@ InvalidHeader
fur::util
Definition: result.hpp:12
fur::download::bitfield
Definition: bitfield.cpp:24
fur::download::message::HaveMessage::kind
MessageKind kind() const override
Definition: message.hpp:173
result.hpp
fur::download::message::RequestMessage
Definition: message.hpp:204
fur::download::message::PieceMessage::PieceMessage
PieceMessage(int64_t index, int64_t begin, std::vector< uint8_t > block)
Definition: message.hpp:240
fur::download::message::PieceMessage::begin
const int64_t begin
Offset from the beginning of the piece.
Definition: message.hpp:236
fur::download::message::MessageKind::Request
@ Request
fur::download::message::ChokeMessage
Definition: message.hpp:104