mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 17:01:09 +03:00
Fixed message serialization following changes in core. Sending of block and transaction.
This commit is contained in:
parent
1008539048
commit
edc6c62577
6 changed files with 132 additions and 56 deletions
|
@ -303,6 +303,12 @@ impl<'a> AsFixedBytes for &'a [u8] {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> AsFixedBytes for String {
|
||||
fn as_fixed_bytes(&self) -> &[u8] {
|
||||
self.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFixedBytes for ::core::hash::Hash {
|
||||
fn as_fixed_bytes(&self) -> &[u8] {
|
||||
self.to_slice()
|
||||
|
|
|
@ -37,8 +37,8 @@ pub enum ErrCodes {
|
|||
|
||||
/// Types of messages
|
||||
enum_from_primitive! {
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Type {
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Type {
|
||||
Error,
|
||||
Hand,
|
||||
Shake,
|
||||
|
@ -46,7 +46,9 @@ pub enum Type {
|
|||
Pong,
|
||||
GetPeerAddrs,
|
||||
PeerAddrs,
|
||||
}
|
||||
Block,
|
||||
Transaction,
|
||||
}
|
||||
}
|
||||
|
||||
/// Header of any protocol message, used to identify incoming messages.
|
||||
|
@ -68,7 +70,9 @@ impl MsgHeader {
|
|||
}
|
||||
|
||||
/// Serialized length of the header in bytes
|
||||
pub fn serialized_len(&self) -> u64 { 3 }
|
||||
pub fn serialized_len(&self) -> u64 {
|
||||
3
|
||||
}
|
||||
}
|
||||
|
||||
impl Writeable for MsgHeader {
|
||||
|
@ -87,8 +91,13 @@ impl Readable<MsgHeader> for MsgHeader {
|
|||
try!(reader.expect_u8(MAGIC[1]));
|
||||
let t = try!(reader.read_u8());
|
||||
match Type::from_u8(t) {
|
||||
Some(ty) => Ok(MsgHeader {magic: MAGIC, msg_type: ty}),
|
||||
None => Err(ser::Error::CorruptedData)
|
||||
Some(ty) => {
|
||||
Ok(MsgHeader {
|
||||
magic: MAGIC,
|
||||
msg_type: ty,
|
||||
})
|
||||
}
|
||||
None => Err(ser::Error::CorruptedData),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +127,7 @@ impl Writeable for Hand {
|
|||
[write_u64, self.nonce]);
|
||||
self.sender_addr.write(writer);
|
||||
self.receiver_addr.write(writer);
|
||||
writer.write_bytes(self.user_agent.as_bytes())
|
||||
writer.write_bytes(&self.user_agent)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,7 +166,7 @@ impl Writeable for Shake {
|
|||
ser_multiwrite!(writer,
|
||||
[write_u32, self.version],
|
||||
[write_u32, self.capabilities.bits()],
|
||||
[write_bytes, self.user_agent.as_bytes()]);
|
||||
[write_bytes, &self.user_agent]);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -182,7 +191,7 @@ pub struct GetPeerAddrs {
|
|||
}
|
||||
|
||||
impl Writeable for GetPeerAddrs {
|
||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
||||
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||
writer.write_u32(self.capabilities.bits())
|
||||
}
|
||||
}
|
||||
|
@ -202,12 +211,12 @@ pub struct PeerAddrs {
|
|||
}
|
||||
|
||||
impl Writeable for PeerAddrs {
|
||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
||||
try_o!(writer.write_u32(self.peers.len() as u32));
|
||||
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||
try!(writer.write_u32(self.peers.len() as u32));
|
||||
for p in &self.peers {
|
||||
p.write(writer);
|
||||
}
|
||||
None
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,9 +243,7 @@ pub struct PeerError {
|
|||
|
||||
impl Writeable for PeerError {
|
||||
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||
ser_multiwrite!(writer,
|
||||
[write_u32, self.code],
|
||||
[write_bytes, self.message.as_bytes()]);
|
||||
ser_multiwrite!(writer, [write_u32, self.code], [write_bytes, &self.message]);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
use mioco::tcp::TcpStream;
|
||||
|
||||
use core::core;
|
||||
use core::ser::Error;
|
||||
use handshake::Handshake;
|
||||
use types::*;
|
||||
|
@ -43,14 +44,24 @@ impl Peer {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn run(&self, na: &NetAdapter) -> Option<Error> {
|
||||
pub fn run(&self, na: &NetAdapter) -> Result<(), Error> {
|
||||
self.proto.handle(na)
|
||||
}
|
||||
|
||||
pub fn send_ping(&self) -> Option<Error> {
|
||||
pub fn send_ping(&self) -> Result<(), Error> {
|
||||
self.proto.send_ping()
|
||||
}
|
||||
|
||||
pub fn send_block(&self, b: &core::Block) -> Result<(), Error> {
|
||||
// TODO don't send if we already got the block from peer
|
||||
self.proto.send_block(b)
|
||||
}
|
||||
|
||||
pub fn send_transaction(&self, tx: &core::Transaction) -> Result<(), Error> {
|
||||
// TODO don't relay if we already got the tx from peer
|
||||
self.proto.send_transaction(tx)
|
||||
}
|
||||
|
||||
pub fn transmitted_bytes(&self) -> (u64, u64) {
|
||||
self.proto.transmitted_bytes()
|
||||
}
|
||||
|
|
|
@ -13,17 +13,16 @@
|
|||
// limitations under the License.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::io::{Read, Write};
|
||||
use std::io::Write;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use mioco;
|
||||
use mioco::sync::mpsc::{sync_channel, SyncSender};
|
||||
use mioco::tcp::{TcpStream, Shutdown};
|
||||
|
||||
use core::core;
|
||||
use core::ser;
|
||||
use handshake::Handshake;
|
||||
use msg::*;
|
||||
use types::*;
|
||||
|
||||
|
@ -62,7 +61,7 @@ impl Protocol for ProtocolV1 {
|
|||
/// to send. Must be called before any interaction with a protocol instance
|
||||
/// and should only be called once. Will block so also needs to be called
|
||||
/// within a coroutine.
|
||||
fn handle(&self, server: &NetAdapter) -> Option<ser::Error> {
|
||||
fn handle(&self, server: &NetAdapter) -> Result<(), ser::Error> {
|
||||
// setup channels so we can switch between reads, writes and close
|
||||
let (msg_send, msg_recv) = sync_channel(10);
|
||||
let (stop_send, stop_recv) = sync_channel(1);
|
||||
|
@ -79,7 +78,7 @@ impl Protocol for ProtocolV1 {
|
|||
select!(
|
||||
r:conn => {
|
||||
// deser the header ot get the message type
|
||||
let header = try_to_o!(ser::deserialize::<MsgHeader>(conn.deref_mut()));
|
||||
let header = try!(ser::deserialize::<MsgHeader>(conn.deref_mut()));
|
||||
if !header.acceptable() {
|
||||
continue;
|
||||
}
|
||||
|
@ -88,10 +87,10 @@ impl Protocol for ProtocolV1 {
|
|||
match header.msg_type {
|
||||
Type::Ping => {
|
||||
// respond with pong
|
||||
let data = try_to_o!(ser::ser_vec(&MsgHeader::new(Type::Pong)));
|
||||
let data = try!(ser::ser_vec(&MsgHeader::new(Type::Pong)));
|
||||
let mut sent_bytes = self.sent_bytes.lock().unwrap();
|
||||
*sent_bytes += data.len() as u64;
|
||||
try_to_o!(conn.deref_mut().write_all(&data[..]).map_err(&ser::Error::IOErr));
|
||||
try!(conn.deref_mut().write_all(&data[..]).map_err(&ser::Error::IOErr));
|
||||
},
|
||||
Type::Pong => {},
|
||||
_ => error!("uncaught unknown"),
|
||||
|
@ -104,13 +103,13 @@ impl Protocol for ProtocolV1 {
|
|||
let data = &msg_recv.recv().unwrap()[..];
|
||||
let mut sent_bytes = self.sent_bytes.lock().unwrap();
|
||||
*sent_bytes += data.len() as u64;
|
||||
try_to_o!(conn.deref_mut().write_all(data).map_err(&ser::Error::IOErr));
|
||||
try!(conn.deref_mut().write_all(data).map_err(&ser::Error::IOErr));
|
||||
},
|
||||
r:stop_recv => {
|
||||
// shuts the connection don and end the loop
|
||||
stop_recv.recv();
|
||||
conn.shutdown(Shutdown::Both);
|
||||
return None;
|
||||
return Ok(());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -118,11 +117,19 @@ impl Protocol for ProtocolV1 {
|
|||
|
||||
/// Sends a ping message to the remote peer. Will panic if handle has never
|
||||
/// been called on this protocol.
|
||||
fn send_ping(&self) -> Option<ser::Error> {
|
||||
let data = try_to_o!(ser::ser_vec(&MsgHeader::new(Type::Ping)));
|
||||
fn send_ping(&self) -> Result<(), ser::Error> {
|
||||
let data = try!(ser::ser_vec(&MsgHeader::new(Type::Ping)));
|
||||
let msg_send = self.msg_send.borrow();
|
||||
msg_send.as_ref().unwrap().send(data);
|
||||
None
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn send_block(&self, b: &core::Block) -> Result<(), ser::Error> {
|
||||
self.send_msg(Type::Block, b)
|
||||
}
|
||||
|
||||
fn send_transaction(&self, tx: &core::Transaction) -> Result<(), ser::Error> {
|
||||
self.send_msg(Type::Transaction, tx)
|
||||
}
|
||||
|
||||
fn transmitted_bytes(&self) -> (u64, u64) {
|
||||
|
@ -136,3 +143,16 @@ impl Protocol for ProtocolV1 {
|
|||
stop_send.as_ref().unwrap().send(0);
|
||||
}
|
||||
}
|
||||
|
||||
impl ProtocolV1 {
|
||||
/// Helper function to avoid boilerplate, builds a header followed by the
|
||||
/// Writeable body and send the whole thing.
|
||||
fn send_msg(&self, t: Type, body: &ser::Writeable) -> Result<(), ser::Error> {
|
||||
let mut data = Vec::new();
|
||||
try!(ser::serialize(&mut data, &MsgHeader::new(t)));
|
||||
try!(ser::serialize(&mut data, body));
|
||||
let msg_send = self.msg_send.borrow();
|
||||
msg_send.as_ref().unwrap().send(data);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,11 +26,14 @@ use mioco;
|
|||
use mioco::sync::mpsc::{sync_channel, SyncSender};
|
||||
use mioco::tcp::{TcpListener, TcpStream};
|
||||
|
||||
use core::core;
|
||||
use core::ser::Error;
|
||||
use handshake::Handshake;
|
||||
use peer::Peer;
|
||||
use types::*;
|
||||
|
||||
/// Default address for peer-to-peer connections, placeholder until better
|
||||
/// configuration is in place.
|
||||
pub const DEFAULT_LISTEN_ADDR: &'static str = "127.0.0.1:3414";
|
||||
|
||||
// replace with some config lookup or something
|
||||
|
@ -89,7 +92,7 @@ impl Server {
|
|||
}
|
||||
|
||||
mioco::spawn(move || -> io::Result<()> {
|
||||
if let Some(err) = wpeer.run(&DummyAdapter{}) {
|
||||
if let Err(err) = wpeer.run(&DummyAdapter{}) {
|
||||
error!("{:?}", err);
|
||||
}
|
||||
Ok(())
|
||||
|
@ -103,6 +106,28 @@ impl Server {
|
|||
}
|
||||
}
|
||||
|
||||
/// Asks all the peers to relay the provided block. A peer may choose to
|
||||
/// ignore the relay request if it has knowledge that the remote peer
|
||||
/// already knows the block.
|
||||
pub fn relay_block(&self, b: &core::Block) -> Result<(), Error> {
|
||||
let peers = self.peers.write().unwrap();
|
||||
for p in peers.deref() {
|
||||
try!(p.send_block(b));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Asks all the peers to relay the provided transaction. A peer may choose
|
||||
/// to ignore the relay request if it has knowledge that the remote peer
|
||||
/// already knows the transaction.
|
||||
pub fn relay_transaction(&self, tx: &core::Transaction) -> Result<(), Error> {
|
||||
let peers = self.peers.write().unwrap();
|
||||
for p in peers.deref() {
|
||||
try!(p.send_transaction(tx));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Stops the server. Disconnect from all peers at the same time.
|
||||
pub fn stop(&self) {
|
||||
let peers = self.peers.write().unwrap();
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
use std::net::SocketAddr;
|
||||
use core::core;
|
||||
use core::ser::Error;
|
||||
|
||||
bitflags! {
|
||||
|
@ -42,10 +43,16 @@ pub trait Protocol {
|
|||
/// be known already, usually passed during construction. Will typically
|
||||
/// block so needs to be called withing a coroutine. Should also be called
|
||||
/// only once.
|
||||
fn handle(&self, na: &NetAdapter) -> Option<Error>;
|
||||
fn handle(&self, na: &NetAdapter) -> Result<(), Error>;
|
||||
|
||||
/// Sends a ping message to the remote peer.
|
||||
fn send_ping(&self) -> Option<Error>;
|
||||
fn send_ping(&self) -> Result<(), Error>;
|
||||
|
||||
/// Relays a block to the remote peer.
|
||||
fn send_block(&self, b: &core::Block) -> Result<(), Error>;
|
||||
|
||||
/// Relays a transaction to the remote peer.
|
||||
fn send_transaction(&self, tx: &core::Transaction) -> Result<(), Error>;
|
||||
|
||||
/// How many bytes have been sent/received to/from the remote peer.
|
||||
fn transmitted_bytes(&self) -> (u64, u64);
|
||||
|
|
Loading…
Reference in a new issue