1use std::iter;
23use std::io::Cursor;
24use std::sync::mpsc::Sender;
25
26use blockdata::block;
27use blockdata::transaction;
28use network::address::Address;
29use network::message_network;
30use network::message_blockdata;
31use consensus::encode::{Decodable, Encodable};
32use consensus::encode::CheckedData;
33use consensus::encode::{self, serialize, Encoder, Decoder};
34use util;
35
36#[derive(PartialEq, Eq, Clone, Debug)]
38pub struct CommandString(pub String);
39
40impl<S: Encoder> Encodable<S> for CommandString {
41 #[inline]
42 fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> {
43 let &CommandString(ref inner_str) = self;
44 let mut rawbytes = [0u8; 12];
45 let strbytes = inner_str.as_bytes();
46 if strbytes.len() > 12 {
47 panic!("Command string longer than 12 bytes");
48 }
49 for x in 0..strbytes.len() {
50 rawbytes[x] = strbytes[x];
51 }
52 rawbytes.consensus_encode(s)
53 }
54}
55
56impl<D: Decoder> Decodable<D> for CommandString {
57 #[inline]
58 fn consensus_decode(d: &mut D) -> Result<CommandString, encode::Error> {
59 let rawbytes: [u8; 12] = Decodable::consensus_decode(d)?;
60 let rv = iter::FromIterator::from_iter(rawbytes.iter().filter_map(|&u| if u > 0 { Some(u as char) } else { None }));
61 Ok(CommandString(rv))
62 }
63}
64
65pub struct RawNetworkMessage {
67 pub magic: u32,
69 pub payload: NetworkMessage
71}
72
73pub enum SocketResponse {
75 MessageReceived(NetworkMessage),
77 ConnectionFailed(util::Error, Sender<()>)
79}
80
81#[derive(Clone, PartialEq, Eq, Debug)]
82pub enum NetworkMessage {
85 Version(message_network::VersionMessage),
87 Verack,
89 Addr(Vec<(u32, Address)>),
91 Inv(Vec<message_blockdata::Inventory>),
93 GetData(Vec<message_blockdata::Inventory>),
95 NotFound(Vec<message_blockdata::Inventory>),
97 GetBlocks(message_blockdata::GetBlocksMessage),
99 GetHeaders(message_blockdata::GetHeadersMessage),
101 MemPool,
103 Tx(transaction::Transaction),
105 Block(block::Block),
107 Headers(Vec<block::LoneBlockHeader>),
109 GetAddr,
111 Ping(u64),
116 Pong(u64),
118 Alert(Vec<u8>)
123}
124
125impl RawNetworkMessage {
126 pub fn command(&self) -> String {
128 match self.payload {
129 NetworkMessage::Version(_) => "version",
130 NetworkMessage::Verack => "verack",
131 NetworkMessage::Addr(_) => "addr",
132 NetworkMessage::Inv(_) => "inv",
133 NetworkMessage::GetData(_) => "getdata",
134 NetworkMessage::NotFound(_) => "notfound",
135 NetworkMessage::GetBlocks(_) => "getblocks",
136 NetworkMessage::GetHeaders(_) => "getheaders",
137 NetworkMessage::MemPool => "mempool",
138 NetworkMessage::Tx(_) => "tx",
139 NetworkMessage::Block(_) => "block",
140 NetworkMessage::Headers(_) => "headers",
141 NetworkMessage::GetAddr => "getaddr",
142 NetworkMessage::Ping(_) => "ping",
143 NetworkMessage::Pong(_) => "pong",
144 NetworkMessage::Alert(_) => "alert",
145 }.to_owned()
146 }
147}
148
149impl<S: Encoder> Encodable<S> for RawNetworkMessage {
150 fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> {
151 self.magic.consensus_encode(s)?;
152 CommandString(self.command()).consensus_encode(s)?;
153 CheckedData(match self.payload {
154 NetworkMessage::Version(ref dat) => serialize(dat),
155 NetworkMessage::Addr(ref dat) => serialize(dat),
156 NetworkMessage::Inv(ref dat) => serialize(dat),
157 NetworkMessage::GetData(ref dat) => serialize(dat),
158 NetworkMessage::NotFound(ref dat) => serialize(dat),
159 NetworkMessage::GetBlocks(ref dat) => serialize(dat),
160 NetworkMessage::GetHeaders(ref dat) => serialize(dat),
161 NetworkMessage::Tx(ref dat) => serialize(dat),
162 NetworkMessage::Block(ref dat) => serialize(dat),
163 NetworkMessage::Headers(ref dat) => serialize(dat),
164 NetworkMessage::Ping(ref dat) => serialize(dat),
165 NetworkMessage::Pong(ref dat) => serialize(dat),
166 NetworkMessage::Alert(ref dat) => serialize(dat),
167 NetworkMessage::Verack
168 | NetworkMessage::MemPool
169 | NetworkMessage::GetAddr => vec![],
170 }).consensus_encode(s)
171 }
172}
173
174impl<D: Decoder> Decodable<D> for RawNetworkMessage {
175 fn consensus_decode(d: &mut D) -> Result<RawNetworkMessage, encode::Error> {
176 let magic = Decodable::consensus_decode(d)?;
177 let CommandString(cmd): CommandString= Decodable::consensus_decode(d)?;
178 let CheckedData(raw_payload): CheckedData = Decodable::consensus_decode(d)?;
179
180 let mut mem_d = Cursor::new(raw_payload);
181 let payload = match &cmd[..] {
182 "version" => NetworkMessage::Version(Decodable::consensus_decode(&mut mem_d)?),
183 "verack" => NetworkMessage::Verack,
184 "addr" => NetworkMessage::Addr(Decodable::consensus_decode(&mut mem_d)?),
185 "inv" => NetworkMessage::Inv(Decodable::consensus_decode(&mut mem_d)?),
186 "getdata" => NetworkMessage::GetData(Decodable::consensus_decode(&mut mem_d)?),
187 "notfound" => NetworkMessage::NotFound(Decodable::consensus_decode(&mut mem_d)?),
188 "getblocks" => NetworkMessage::GetBlocks(Decodable::consensus_decode(&mut mem_d)?),
189 "getheaders" => NetworkMessage::GetHeaders(Decodable::consensus_decode(&mut mem_d)?),
190 "mempool" => NetworkMessage::MemPool,
191 "block" => NetworkMessage::Block(Decodable::consensus_decode(&mut mem_d)?),
192 "headers" => NetworkMessage::Headers(Decodable::consensus_decode(&mut mem_d)?),
193 "getaddr" => NetworkMessage::GetAddr,
194 "ping" => NetworkMessage::Ping(Decodable::consensus_decode(&mut mem_d)?),
195 "pong" => NetworkMessage::Pong(Decodable::consensus_decode(&mut mem_d)?),
196 "tx" => NetworkMessage::Tx(Decodable::consensus_decode(&mut mem_d)?),
197 "alert" => NetworkMessage::Alert(Decodable::consensus_decode(&mut mem_d)?),
198 _ => return Err(encode::Error::UnrecognizedNetworkCommand(cmd)),
199 };
200 Ok(RawNetworkMessage {
201 magic: magic,
202 payload: payload
203 })
204 }
205}
206
207#[cfg(test)]
208mod test {
209 use super::{RawNetworkMessage, NetworkMessage, CommandString};
210
211 use consensus::encode::{deserialize, serialize};
212
213 #[test]
214 fn serialize_commandstring_test() {
215 let cs = CommandString("Andrew".to_owned());
216 assert_eq!(serialize(&cs), vec![0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
217 }
218
219 #[test]
220 fn deserialize_commandstring_test() {
221 let cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
222 assert!(cs.is_ok());
223 assert_eq!(cs.unwrap(), CommandString("Andrew".to_owned()));
224
225 let short_cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]);
226 assert!(short_cs.is_err());
227 }
228
229 #[test]
230 fn serialize_verack_test() {
231 assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::Verack }),
232 vec![0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x61,
233 0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]);
235 }
236
237 #[test]
238 fn serialize_ping_test() {
239 assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::Ping(100) }),
240 vec![0xf9, 0xbe, 0xb4, 0xd9, 0x70, 0x69, 0x6e, 0x67,
241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242 0x08, 0x00, 0x00, 0x00, 0x24, 0x67, 0xf1, 0x1d,
243 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
244 }
245
246
247 #[test]
248 fn serialize_mempool_test() {
249 assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::MemPool }),
250 vec![0xf9, 0xbe, 0xb4, 0xd9, 0x6d, 0x65, 0x6d, 0x70,
251 0x6f, 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
252 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]);
253 }
254
255 #[test]
256 fn serialize_getaddr_test() {
257 assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::GetAddr }),
258 vec![0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61,
259 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
260 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]);
261 }
262
263}