init of network primitives
This commit is contained in:
parent
7a13143824
commit
e4e101bb6b
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
mod address;
|
||||
mod service;
|
||||
|
||||
pub use self::service::ServiceFlags;
|
|
@ -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())
|
||||
}
|
||||
}
|
|
@ -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>()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue