1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
use bytes::Bytes;
use ensicoin_serializer::{Deserialize, Deserializer, Serialize};

mod addr;
mod getblocks;
mod getmempool;
mod inv;
mod ping;
mod whoami;

pub use addr::{Addr, Address, GetAddr};
pub use getblocks::GetBlocks;
pub use getmempool::GetMempool;
pub use inv::{GetData, Inv, InvVect, NotFound};
pub use ping::{Ping, Pong};
pub use whoami::{Whoami, WhoamiAck};

#[derive(Debug)]
pub enum ResourceType {
    Transaction,
    Block,
}

impl Serialize for ResourceType {
    fn serialize(&self) -> Bytes {
        match self {
            ResourceType::Block => (1 as u32).serialize(),
            ResourceType::Transaction => (0 as u32).serialize(),
        }
    }
}

impl Deserialize for ResourceType {
    fn deserialize(
        de: &mut ensicoin_serializer::Deserializer,
    ) -> ensicoin_serializer::Result<ResourceType> {
        match u32::deserialize(de) {
            Ok(0) => Ok(ResourceType::Transaction),
            Ok(1) => Ok(ResourceType::Block),
            Ok(n) => Err(ensicoin_serializer::Error::Message(format!(
                "Invalid DataType: {}",
                n
            ))),
            Err(e) => Err(ensicoin_serializer::Error::Message(format!(
                "Error reading DataType: {}",
                e
            ))),
        }
    }
}

#[derive(PartialEq, Eq, Debug, Clone)]
pub enum MessageType {
    Whoami,
    WhoamiAck,
    Inv,
    GetData,
    NotFound,
    GetBlocks,
    GetMempool,
    GetAddr,
    Addr,
    Block,
    Transaction,
    Ping,
    Pong,
    Unknown(Vec<u8>),
}

impl Deserialize for MessageType {
    fn deserialize(de: &mut Deserializer) -> ensicoin_serializer::Result<MessageType> {
        let raw_type = match de.extract_bytes(12) {
            Err(e) => {
                return Err(ensicoin_serializer::Error::Message(format!(
                    "Error in reading message type: {}",
                    e
                )));
            }
            Ok(v) => v.to_vec(),
        };
        Ok(
            if raw_type == [119, 104, 111, 97, 109, 105, 0, 0, 0, 0, 0, 0] {
                MessageType::Whoami
            } else if raw_type == [119, 104, 111, 97, 109, 105, 97, 99, 107, 0, 0, 0] {
                MessageType::WhoamiAck
            } else if raw_type == [50, 112, 108, 117, 115, 50, 105, 115, 52, 0, 0, 0] {
                MessageType::Ping
            } else if raw_type == [109, 105, 110, 117, 115, 49, 116, 104, 97, 116, 115, 51] {
                MessageType::Pong
            } else if raw_type == [105, 110, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0] {
                MessageType::Inv
            } else if raw_type == [103, 101, 116, 100, 97, 116, 97, 0, 0, 0, 0, 0] {
                MessageType::GetData
            } else if raw_type == [110, 111, 116, 102, 111, 117, 110, 100, 0, 0, 0, 0] {
                MessageType::NotFound
            } else if raw_type == [103, 101, 116, 98, 108, 111, 99, 107, 115, 0, 0, 0] {
                MessageType::GetBlocks
            } else if raw_type == [116, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] {
                MessageType::Transaction
            } else if raw_type == [98, 108, 111, 99, 107, 0, 0, 0, 0, 0, 0, 0] {
                MessageType::Block
            } else if raw_type == [103, 101, 116, 97, 100, 100, 114, 0, 0, 0, 0, 0] {
                MessageType::GetAddr
            } else if raw_type == [103, 101, 116, 109, 101, 109, 112, 111, 111, 108, 0, 0] {
                MessageType::GetMempool
            } else if raw_type == [97, 100, 100, 114, 0, 0, 0, 0, 0, 0, 0, 0] {
                MessageType::Addr
            } else {
                MessageType::Unknown(raw_type)
            },
        )
    }
}

impl std::fmt::Display for MessageType {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match self {
                MessageType::Ping => "2plus2is4".to_string(),
                MessageType::Pong => "minus1thats3".to_string(),
                MessageType::Whoami => "Whoami".to_string(),
                MessageType::WhoamiAck => "WhoamiAck".to_string(),
                MessageType::Inv => "Inv".to_string(),
                MessageType::GetData => "GetData".to_string(),
                MessageType::NotFound => "NotFound".to_string(),
                MessageType::GetBlocks => "GetBlocks".to_string(),
                MessageType::GetMempool => "GetMempool".to_string(),
                MessageType::Transaction => "Transaction".to_string(),
                MessageType::GetAddr => "GetAddr".to_string(),
                MessageType::Addr => "Addr".to_string(),
                MessageType::Block => "Block".to_string(),
                MessageType::Unknown(s) => format!(
                    "Unknown: {}",
                    String::from_utf8(s.clone()).unwrap_or("<INVALID UTF8>".to_string())
                )
                .trim_matches('\x00')
                .to_string(),
            }
        )
    }
}

pub trait Message: Serialize {
    fn message_string() -> [u8; 12];
    fn message_type() -> MessageType;
    fn raw_bytes(&self) -> (MessageType, Bytes) {
        let magic: u32 = 422021;
        let message_string = Self::message_string();
        let payload = self.serialize();
        let payload_length: u64 = payload.len() as u64;

        let mut v = Bytes::new();
        v.extend_from_slice(&magic.serialize());
        v.extend_from_slice(&message_string);
        v.extend_from_slice(&payload_length.serialize());
        v.extend_from_slice(&payload);
        (Self::message_type(), v)
    }
}