init of network primitives

This commit is contained in:
debris 2016-09-18 02:01:01 +02:00
parent 7a13143824
commit e4e101bb6b
6 changed files with 275 additions and 14 deletions

View File

@ -10,7 +10,9 @@ extern crate secp256k1;
extern crate base58;
pub mod keys;
pub mod net;
pub mod script;
pub mod block;
pub mod block_header;
pub mod compact_integer;

137
src/net/address.rs Normal file
View File

@ -0,0 +1,137 @@
use std::{net, str};
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};
use stream::{Stream, Serializable};
use reader::{Reader, Deserializable, Error as ReaderError};
use net::ServiceFlags;
pub struct Port(u16);
impl From<u16> for Port {
fn from(port: u16) -> Self {
Port(port)
}
}
impl Serializable for Port {
fn serialize(&self, stream: &mut Stream) {
stream.write_u16::<BigEndian>(self.0).unwrap();
}
}
impl Deserializable for Port {
fn deserialize(reader: &mut Reader) -> Result<Self, ReaderError> where Self: Sized {
Ok(try!(reader.read_u16::<BigEndian>().map(Port)))
}
}
pub struct IpAddress(net::IpAddr);
impl From<net::IpAddr> for IpAddress {
fn from(ip: net::IpAddr) -> Self {
IpAddress(ip)
}
}
impl From<&'static str> for IpAddress {
fn from(s: &'static str) -> Self {
s.parse().unwrap()
}
}
impl str::FromStr for IpAddress {
type Err = <net::IpAddr as str::FromStr>::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.parse().map(IpAddress)
}
}
impl Serializable for IpAddress {
fn serialize(&self, stream: &mut Stream) {
match self.0 {
net::IpAddr::V4(address) => {
stream
.append_bytes(&[0u8; 12])
.append_bytes(&address.octets());
},
net::IpAddr::V6(address) => {
for segment in &address.segments() {
stream.write_u16::<BigEndian>(*segment).unwrap();
}
},
}
}
}
impl Deserializable for IpAddress {
fn deserialize(reader: &mut Reader) -> Result<Self, ReaderError> where Self: Sized {
let bytes = try!(reader.read_bytes(12));
if bytes == &[0u8; 12] {
let address = try!(reader.read_bytes(4));
let address = net::Ipv4Addr::new(address[0], address[1], address[2], address[3]);
Ok(IpAddress(net::IpAddr::V4(address)))
} else {
let address = net::Ipv6Addr::new(
try!(reader.read_u16::<BigEndian>()),
try!(reader.read_u16::<BigEndian>()),
try!(reader.read_u16::<BigEndian>()),
try!(reader.read_u16::<BigEndian>()),
try!(reader.read_u16::<BigEndian>()),
try!(reader.read_u16::<BigEndian>()),
try!(reader.read_u16::<BigEndian>()),
try!(reader.read_u16::<BigEndian>())
);
Ok(IpAddress(net::IpAddr::V6(address)))
}
}
}
pub struct NetAddress {
pub services: ServiceFlags,
pub address: IpAddress,
pub port: Port,
}
impl Serializable for NetAddress {
fn serialize(&self, stream: &mut Stream) {
stream
.append(&self.services)
.append(&self.address)
.append(&self.port);
}
}
impl Deserializable for NetAddress {
fn deserialize(reader: &mut Reader) -> Result<Self, ReaderError> where Self: Sized {
let net = NetAddress {
services: try!(reader.read()),
address: try!(reader.read()),
port: try!(reader.read()),
};
Ok(net)
}
}
#[cfg(test)]
mod tests {
use stream::serialize;
use net::ServiceFlags;
use super::NetAddress;
#[test]
fn test_net_address_serialize() {
let expeted = vec![
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x00, 0x00, 0x01,
0x20, 0x8d
];
let address = NetAddress {
services: ServiceFlags::default().network(true),
address: "::ffff:a00:1".into(),
port: 8333.into(),
};
assert_eq!(expeted, serialize(&address));
}
}

4
src/net/mod.rs Normal file
View File

@ -0,0 +1,4 @@
mod address;
mod service;
pub use self::service::ServiceFlags;

91
src/net/service.rs Normal file
View File

@ -0,0 +1,91 @@
use stream::{Serializable, Stream};
use reader::{Deserializable, Reader, Error as ReaderError};
#[derive(Debug, Default, PartialEq, Clone)]
pub struct ServiceFlags {
pub network: bool,
pub getutxo: bool,
pub bloom: bool,
pub witness: bool,
pub xthin: bool,
}
impl<'a> From<&'a ServiceFlags> for u64 {
fn from(s: &'a ServiceFlags) -> Self {
let mut result = 0u64;
if s.network {
result |= 1 << 0;
}
if s.getutxo {
result |= 1 << 1;
}
if s.bloom {
result |= 1 << 2;
}
if s.witness {
result |= 1 << 3;
}
if s.xthin {
result |= 1 << 4;
}
result
}
}
// TODO: do we need to throw err on unknown service flags?
impl From<u64> for ServiceFlags {
fn from(v: u64) -> Self {
ServiceFlags {
network: v & 0x1 != 0,
getutxo: v & 0x10 != 0,
bloom: v & 0x100 != 0,
witness: v & 0x1000 != 0,
xthin: v & 0x10000 != 0,
}
}
}
impl ServiceFlags {
pub fn network(mut self, v: bool) -> Self {
self.network = v;
self
}
pub fn getutxo(mut self, v: bool) -> Self {
self.getutxo = v;
self
}
pub fn bloom(mut self, v: bool) -> Self {
self.bloom = v;
self
}
pub fn witness(mut self, v: bool) -> Self {
self.witness = v;
self
}
pub fn xthin(mut self, v: bool) -> Self {
self.xthin = v;
self
}
}
impl Serializable for ServiceFlags {
fn serialize(&self, stream: &mut Stream) {
stream.append(&u64::from(self));
}
}
impl Deserializable for ServiceFlags {
fn deserialize(reader: &mut Reader) -> Result<Self, ReaderError> where Self: Sized {
reader.read().map(|v: u64| v.into())
}
}

View File

@ -1,4 +1,4 @@
use std::{io, cmp};
use byteorder::{LittleEndian, ReadBytesExt};
pub fn deserialize<T>(buffer: &[u8]) -> Result<T, Error> where T: Deserializable {
@ -18,6 +18,12 @@ pub enum Error {
UnreadData,
}
impl From<io::Error> for Error {
fn from(_: io::Error) -> Self {
Error::UnexpectedEnd
}
}
pub trait Deserializable {
fn deserialize(reader: &mut Reader) -> Result<Self, Error> where Self: Sized;
}
@ -27,6 +33,15 @@ pub struct Reader<'a> {
read: usize,
}
impl<'a> io::Read for Reader<'a> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
let to_read = cmp::min(self.buffer.len() - self.read, buf.len());
buf[0..to_read].copy_from_slice(&self.buffer[self.read..self.read + to_read]);
self.read += to_read;
Ok(to_read)
}
}
impl<'a> Reader<'a> {
pub fn new(buffer: &'a [u8]) -> Reader {
Reader {
@ -68,35 +83,35 @@ impl<'a> Reader<'a> {
impl Deserializable for i32 {
#[inline]
fn deserialize(reader: &mut Reader) -> Result<Self, Error> where Self: Sized {
Ok(try!(reader.read_bytes(4)).read_i32::<LittleEndian>().unwrap())
Ok(try!(reader.read_i32::<LittleEndian>()))
}
}
impl Deserializable for u8 {
#[inline]
fn deserialize(reader: &mut Reader) -> Result<Self, Error> where Self: Sized {
Ok(try!(reader.read_bytes(1)).read_u8().unwrap())
Ok(try!(reader.read_u8()))
}
}
impl Deserializable for u16 {
#[inline]
fn deserialize(reader: &mut Reader) -> Result<Self, Error> where Self: Sized {
Ok(try!(reader.read_bytes(2)).read_u16::<LittleEndian>().unwrap())
Ok(try!(reader.read_u16::<LittleEndian>()))
}
}
impl Deserializable for u32 {
#[inline]
fn deserialize(reader: &mut Reader) -> Result<Self, Error> where Self: Sized {
Ok(try!(reader.read_bytes(4)).read_u32::<LittleEndian>().unwrap())
Ok(try!(reader.read_u32::<LittleEndian>()))
}
}
impl Deserializable for u64 {
#[inline]
fn deserialize(reader: &mut Reader) -> Result<Self, Error> where Self: Sized {
Ok(try!(reader.read_bytes(8)).read_u64::<LittleEndian>().unwrap())
Ok(try!(reader.read_u64::<LittleEndian>()))
}
}

View File

@ -1,5 +1,5 @@
//! Stream used for serialization.
use std::io::Write;
use std::io::{self, Write};
use byteorder::{LittleEndian, WriteBytesExt};
pub fn serialize(t: &Serializable) -> Vec<u8> {
@ -9,7 +9,7 @@ pub fn serialize(t: &Serializable) -> Vec<u8> {
}
pub trait Serializable {
/// Serialize the struct and appends it to the end of stream.
/// Serialize the struct and appends it to the end of stream.
fn serialize(&self, s: &mut Stream);
}
@ -20,7 +20,7 @@ pub struct Stream {
}
impl Stream {
/// Serializes the struct and appends it to the end of stream.
/// Serializes the struct and appends it to the end of stream.
pub fn append(&mut self, t: &Serializable) -> &mut Self {
t.serialize(self);
self
@ -47,38 +47,50 @@ impl Stream {
}
}
impl Write for Stream {
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
self.buffer.write(buf)
}
#[inline]
fn flush(&mut self) -> Result<(), io::Error> {
self.buffer.flush()
}
}
impl Serializable for i32 {
#[inline]
fn serialize(&self, s: &mut Stream) {
s.buffer.write_i32::<LittleEndian>(*self).unwrap();
s.write_i32::<LittleEndian>(*self).unwrap();
}
}
impl Serializable for u8 {
#[inline]
fn serialize(&self, s: &mut Stream) {
s.buffer.write_u8(*self).unwrap();
s.write_u8(*self).unwrap();
}
}
impl Serializable for u16 {
#[inline]
fn serialize(&self, s: &mut Stream) {
s.buffer.write_u16::<LittleEndian>(*self).unwrap();
s.write_u16::<LittleEndian>(*self).unwrap();
}
}
impl Serializable for u32 {
#[inline]
fn serialize(&self, s: &mut Stream) {
s.buffer.write_u32::<LittleEndian>(*self).unwrap();
s.write_u32::<LittleEndian>(*self).unwrap();
}
}
impl Serializable for u64 {
#[inline]
fn serialize(&self, s: &mut Stream) {
s.buffer.write_u64::<LittleEndian>(*self).unwrap();
s.write_u64::<LittleEndian>(*self).unwrap();
}
}