koibumi_core/
object.rs

1//! Object types defined in the Bitmessage protocol.
2
3mod msg;
4pub use crate::object::msg::{Msg, TryIntoMsgError};
5
6mod broadcast;
7pub use crate::object::broadcast::{
8    Broadcast, BroadcastV4, BroadcastV5, Tag, TryIntoBroadcastError,
9};
10
11mod onionpeer;
12pub use crate::object::onionpeer::{Onionpeer, TryFromOnionpeerError};
13
14use std::{
15    convert::TryFrom,
16    fmt,
17    io::{self, Read, Write},
18};
19
20use crate::{
21    address::{Address, Error as AddressError},
22    crypto::{self, PrivateKeyError},
23    io::{LenBm, ReadFrom, WriteTo},
24    time::Time,
25    var_type::VarInt,
26};
27
28pub use crate::stream::StreamNumber;
29
30/// Represents type of object such as public key or one-to-one message.
31#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
32pub struct ObjectType(u32);
33
34impl ObjectType {
35    /// Constructs an object type from a value.
36    pub const fn new(value: u32) -> Self {
37        Self(value)
38    }
39
40    /// Returns the value as `u32`.
41    pub fn as_u32(self) -> u32 {
42        self.0
43    }
44}
45
46impl fmt::Display for ObjectType {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        self.0.fmt(f)
49    }
50}
51
52impl From<u32> for ObjectType {
53    fn from(value: u32) -> Self {
54        Self(value)
55    }
56}
57
58impl WriteTo for ObjectType {
59    fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
60        self.0.write_to(w)
61    }
62}
63
64impl ReadFrom for ObjectType {
65    fn read_from(r: &mut dyn Read) -> io::Result<Self>
66    where
67        Self: Sized,
68    {
69        Ok(Self(u32::read_from(r)?))
70    }
71}
72
73impl LenBm for ObjectType {
74    fn len_bm(&self) -> usize {
75        self.0.len_bm()
76    }
77}
78
79/// A version number used in Bitmessage objects.
80#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
81pub struct ObjectVersion(u64);
82
83impl fmt::Display for ObjectVersion {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        self.0.fmt(f)
86    }
87}
88
89impl ObjectVersion {
90    /// Constructs an object version from a value.
91    pub const fn new(value: u64) -> Self {
92        Self(value)
93    }
94
95    /// Returns the value as `u64`.
96    pub fn as_u64(self) -> u64 {
97        self.0
98    }
99}
100
101impl From<u64> for ObjectVersion {
102    fn from(value: u64) -> Self {
103        Self(value)
104    }
105}
106
107impl WriteTo for ObjectVersion {
108    fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
109        VarInt::new(self.0).write_to(w)
110    }
111}
112
113impl ReadFrom for ObjectVersion {
114    fn read_from(r: &mut dyn Read) -> io::Result<Self>
115    where
116        Self: Sized,
117    {
118        Ok(Self(VarInt::read_from(r)?.as_u64()))
119    }
120}
121
122impl LenBm for ObjectVersion {
123    fn len_bm(&self) -> usize {
124        VarInt::new(self.0).len_bm()
125    }
126}
127
128/// The header structure of Bitmessage objects.
129#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
130pub struct Header {
131    expires_time: Time,
132    object_type: ObjectType,
133    version: ObjectVersion,
134    stream_number: StreamNumber,
135}
136
137impl Header {
138    /// Constructs an object header from the specified parameters.
139    pub fn new(
140        expires_time: Time,
141        object_type: ObjectType,
142        version: ObjectVersion,
143        stream_number: StreamNumber,
144    ) -> Self {
145        Self {
146            expires_time,
147            object_type,
148            version,
149            stream_number,
150        }
151    }
152
153    /// Returns the expires time.
154    pub fn expires_time(&self) -> Time {
155        self.expires_time
156    }
157
158    /// Returns the object type.
159    pub fn object_type(&self) -> ObjectType {
160        self.object_type
161    }
162
163    /// Returns the object version.
164    pub fn version(&self) -> ObjectVersion {
165        self.version
166    }
167
168    /// Returns the stream number.
169    pub fn stream_number(&self) -> StreamNumber {
170        self.stream_number
171    }
172}
173
174impl WriteTo for Header {
175    fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
176        self.expires_time.write_to(w)?;
177        self.object_type.write_to(w)?;
178        self.version.write_to(w)?;
179        self.stream_number.write_to(w)?;
180        Ok(())
181    }
182}
183
184impl ReadFrom for Header {
185    fn read_from(r: &mut dyn Read) -> io::Result<Self>
186    where
187        Self: Sized,
188    {
189        Ok(Self {
190            expires_time: Time::read_from(r)?,
191            object_type: ObjectType::read_from(r)?,
192            version: ObjectVersion::read_from(r)?,
193            stream_number: StreamNumber::read_from(r)?,
194        })
195    }
196}
197
198impl LenBm for Header {
199    fn len_bm(&self) -> usize {
200        self.expires_time.len_bm()
201            + self.object_type.len_bm()
202            + self.version.len_bm()
203            + self.stream_number.len_bm()
204    }
205}
206
207#[test]
208fn test_header_write_to() {
209    let test = Header::new(
210        0x0123_4567_89ab_cdef.into(),
211        2.into(),
212        3u64.into(),
213        1u32.into(),
214    );
215    let mut bytes = Vec::new();
216    test.write_to(&mut bytes).unwrap();
217    let expected = [
218        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x02, 3, 1,
219    ];
220    assert_eq!(bytes, expected);
221}
222
223#[test]
224fn test_header_read_from() {
225    use std::io::Cursor;
226
227    let mut bytes = Cursor::new([
228        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x02, 3, 1,
229    ]);
230    let test = Header::read_from(&mut bytes).unwrap();
231    let expected = Header::new(
232        0x0123_4567_89ab_cdef.into(),
233        2.into(),
234        3u64.into(),
235        1u32.into(),
236    );
237    assert_eq!(test, expected);
238}
239
240/// Known types of Bitmessage objects.
241#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
242pub enum ObjectKind {
243    /// getpubkey object type.
244    Getpubkey,
245    /// pubkey object type.
246    Pubkey,
247    /// msg object type.
248    Msg,
249    /// broadcast object type.
250    Broadcast,
251    /// onionpeer object type.
252    Onionpeer,
253    //I2p,
254    //Addr,
255}
256
257const OBJECT_GETPUBKEY: u32 = 0;
258const OBJECT_PUBKEY: u32 = 1;
259const OBJECT_MSG: u32 = 2;
260const OBJECT_BROADCAST: u32 = 3;
261const OBJECT_ONIONPEER: u32 = 0x74_6f72;
262//const OBJECT_I2P: u32 = 0x493250;
263//const OBJECT_ADDR: u32 = 0x61646472;
264
265/// The error type returned when a conversion from a Bitmessage object type
266/// to a known object type fails.
267///
268/// This error is used as the error type for the `TryFrom` implementation
269/// for `ObjectKind`.
270///
271/// The source object type is returned as a payload of this error type.
272#[derive(Clone, PartialEq, Eq, Debug)]
273pub struct TryFromObjectTypeError(ObjectType);
274
275impl fmt::Display for TryFromObjectTypeError {
276    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277        write!(f, "unknown object type {}", self.0)
278    }
279}
280
281impl std::error::Error for TryFromObjectTypeError {}
282
283impl TryFrom<ObjectType> for ObjectKind {
284    type Error = TryFromObjectTypeError;
285
286    fn try_from(t: ObjectType) -> Result<Self, <Self as TryFrom<ObjectType>>::Error> {
287        match t.as_u32() {
288            OBJECT_GETPUBKEY => Ok(Self::Getpubkey),
289            OBJECT_PUBKEY => Ok(Self::Pubkey),
290            OBJECT_MSG => Ok(Self::Msg),
291            OBJECT_BROADCAST => Ok(Self::Broadcast),
292            OBJECT_ONIONPEER => Ok(Self::Onionpeer),
293            _ => Err(TryFromObjectTypeError(t)),
294        }
295    }
296}
297
298impl From<ObjectKind> for ObjectType {
299    fn from(kind: ObjectKind) -> Self {
300        match kind {
301            ObjectKind::Getpubkey => OBJECT_GETPUBKEY.into(),
302            ObjectKind::Pubkey => OBJECT_PUBKEY.into(),
303            ObjectKind::Msg => OBJECT_MSG.into(),
304            ObjectKind::Broadcast => OBJECT_BROADCAST.into(),
305            ObjectKind::Onionpeer => OBJECT_ONIONPEER.into(),
306        }
307    }
308}
309
310/// This error indicates
311/// that the decryption failed.
312#[derive(Debug)]
313pub enum DecryptError {
314    /// A standard I/O error was caught during decrypting a message.
315    /// The actual error caught is returned as a payload of this variant.
316    IoError(io::Error),
317    /// Indicates that the operation on a private key failed.
318    PrivateKeyError(PrivateKeyError),
319    /// A decryption error was caught during decrypting a message.
320    /// The actual error caught is returned as a payload of this variant.
321    DecryptError(crypto::DecryptError),
322    /// Indicates that the stream numbers from the header and the content does not match.
323    StreamsNotMatch {
324        /// The stream number from the header.
325        headers: StreamNumber,
326        /// The stream number from the content.
327        contents: StreamNumber,
328    },
329    /// An error was caught during conversion from public keys to an address.
330    /// The actual error caught is returned as a payload of this variant.
331    AddressError(AddressError),
332    /// Indicates that the address reconstructed from the message content does not match the sender address.
333    /// The expected and the actual addressess are returned as payloads of this variant.
334    InvalidAddress {
335        /// The expected address.
336        expected: Address,
337        /// The actual address.
338        actual: Address,
339    },
340    /// An error was caught during verification of the signature.
341    /// The actual error caught is returned as a payload of this variant.
342    VerifyError(crypto::VerifyError),
343}
344
345impl fmt::Display for DecryptError {
346    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
347        match self {
348            Self::IoError(err) => err.fmt(f),
349            Self::PrivateKeyError(err) => err.fmt(f),
350            Self::DecryptError(err) => err.fmt(f),
351            Self::StreamsNotMatch { headers, contents } => write!(
352                f,
353                "streams not match: header's is {}, but content's is {}",
354                headers, contents
355            ),
356            Self::AddressError(err) => err.fmt(f),
357            Self::InvalidAddress { expected, actual } => write!(
358                f,
359                "address is expected to be {}, but actual is {}",
360                expected, actual
361            ),
362            Self::VerifyError(err) => err.fmt(f),
363        }
364    }
365}
366
367impl std::error::Error for DecryptError {}
368
369impl From<io::Error> for DecryptError {
370    fn from(err: io::Error) -> Self {
371        Self::IoError(err)
372    }
373}
374
375impl From<PrivateKeyError> for DecryptError {
376    fn from(err: PrivateKeyError) -> Self {
377        Self::PrivateKeyError(err)
378    }
379}
380
381impl From<crypto::DecryptError> for DecryptError {
382    fn from(err: crypto::DecryptError) -> Self {
383        Self::DecryptError(err)
384    }
385}
386
387impl From<AddressError> for DecryptError {
388    fn from(err: AddressError) -> Self {
389        Self::AddressError(err)
390    }
391}
392
393impl From<crypto::VerifyError> for DecryptError {
394    fn from(err: crypto::VerifyError) -> Self {
395        Self::VerifyError(err)
396    }
397}