rust-bitcoin-unsafe-fast/src/network/address.rs

101 lines
3.2 KiB
Rust
Raw Normal View History

2014-07-18 13:56:17 +00:00
// Rust Bitcoin Library
// Written in 2014 by
// Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//
//! # Bitcoin network addresses
//!
//! This module defines the structures and functions needed to encode
//! network addresses in Bitcoin messages.
//!
use std::fmt;
use std::io::{IoResult, standard_error, InvalidInput};
use network::serialize::Serializable;
/// A message which can be sent on the Bitcoin network
pub struct Address {
/// Services provided by the peer whose address this is
pub services: u64,
/// Network byte-order ipv6 address, or ipv4-mapped ipv6 address
pub address: [u8, ..16],
/// Network port
pub port: u16
}
impl Serializable for Address {
fn serialize(&self) -> Vec<u8> {
let mut rv = vec!();
rv.extend(self.services.serialize().move_iter());
rv.extend(self.address.iter().map(|n| *n));
// Explicitly code the port since it needs to be big-endian
rv.extend([(self.port / 256) as u8, (self.port % 256) as u8].iter().map(|n| *n));
rv
}
fn deserialize<I: Iterator<u8>>(mut iter: I) -> IoResult<Address> {
let ret = Address {
services: try!(Serializable::deserialize(iter.by_ref())),
address: try!(Serializable::deserialize(iter.by_ref())),
// Explicitly code the port since it needs to be big-endian
port: {
let b1 = iter.next();
let b2 = iter.next();
if b1.is_none() || b2.is_none() {
return Err(standard_error(InvalidInput));
}
(b1.unwrap() as u16) * 0x100 + (b2.unwrap() as u16)
}
};
Ok(ret)
}
}
impl fmt::Show for Address {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// TODO: render services and hex-ize address
write!(f, "Address {{services: {}, address: {}, port: {}}}",
self.services, self.address.as_slice(), self.port)
}
}
#[test]
fn serialize_address_test() {
assert!(Address {
services: 1,
address: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1],
port: 8333
}.serialize() == Vec::from_slice([1u8, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1,
0x20, 0x8d]));
}
#[test]
fn deserialize_address_test() {
let mut addr: IoResult<Address> = Serializable::deserialize([1u8, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1,
0x20, 0x8d].iter().map(|n| *n));
assert!(addr.is_ok())
let full = addr.unwrap();
assert!(full.services == 1);
assert!(full.address == [0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1]);
assert!(full.port == 8333);
addr = Serializable::deserialize([1u8, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1].iter().map(|n| *n));
assert!(addr.is_err());
}