Let clients subscribe to the ledger over TCP
TODO: Add more tests Fixes #27
This commit is contained in:
@ -3,24 +3,26 @@
|
||||
//! transfer funds to other users.
|
||||
|
||||
use accountant_skel::{Request, Response};
|
||||
use bincode::{deserialize, serialize};
|
||||
use bincode::{deserialize, serialize, serialized_size};
|
||||
use entry::Entry;
|
||||
use hash::Hash;
|
||||
use signature::{KeyPair, PublicKey, Signature};
|
||||
use std::io;
|
||||
use std::net::UdpSocket;
|
||||
use std::io::{self, Read};
|
||||
use std::net::{TcpStream, UdpSocket};
|
||||
use transaction::Transaction;
|
||||
|
||||
pub struct AccountantStub {
|
||||
pub addr: String,
|
||||
pub socket: UdpSocket,
|
||||
pub stream: TcpStream,
|
||||
}
|
||||
|
||||
impl AccountantStub {
|
||||
pub fn new(addr: &str, socket: UdpSocket) -> Self {
|
||||
pub fn new(addr: &str, socket: UdpSocket, stream: TcpStream) -> Self {
|
||||
AccountantStub {
|
||||
addr: addr.to_string(),
|
||||
socket,
|
||||
stream,
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,25 +81,29 @@ impl AccountantStub {
|
||||
last_id: &Hash,
|
||||
) -> io::Result<(bool, Hash)> {
|
||||
let mut last_id = *last_id;
|
||||
let req = Request::GetEntries { last_id };
|
||||
let data = serialize(&req).unwrap();
|
||||
self.socket.send_to(&data, &self.addr).map(|_| ())?;
|
||||
|
||||
let mut buf = vec![0u8; 65_535];
|
||||
self.socket.recv_from(&mut buf)?;
|
||||
let resp = deserialize(&buf).expect("deserialize signature");
|
||||
let mut buf_offset = 0;
|
||||
let mut found = false;
|
||||
if let Response::Entries { entries } = resp {
|
||||
for Entry { id, events, .. } in entries {
|
||||
last_id = id;
|
||||
if !found {
|
||||
for event in events {
|
||||
if let Some(sig) = event.get_signature() {
|
||||
if sig == *wait_sig {
|
||||
found = true;
|
||||
if let Ok(bytes) = self.stream.read(&mut buf) {
|
||||
loop {
|
||||
match deserialize::<Entry>(&buf[buf_offset..]) {
|
||||
Ok(entry) => {
|
||||
buf_offset += serialized_size(&entry).unwrap() as usize;
|
||||
last_id = entry.id;
|
||||
if !found {
|
||||
for event in entry.events {
|
||||
if let Some(sig) = event.get_signature() {
|
||||
if sig == *wait_sig {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
println!("read {} of {} in buf", buf_offset, bytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -112,6 +118,9 @@ impl AccountantStub {
|
||||
let ret = self.check_on_signature(wait_sig, &last_id)?;
|
||||
found = ret.0;
|
||||
last_id = ret.1;
|
||||
|
||||
// Clunky way to force a sync in the skel.
|
||||
self.get_last_id()?;
|
||||
}
|
||||
Ok(last_id)
|
||||
}
|
||||
@ -139,19 +148,19 @@ mod tests {
|
||||
let bob_pubkey = KeyPair::new().pubkey();
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let acc = Arc::new(Mutex::new(AccountantSkel::new(acc, sink())));
|
||||
let threads = AccountantSkel::serve(acc, addr, exit.clone()).unwrap();
|
||||
let _threads = AccountantSkel::serve(acc, addr, exit.clone()).unwrap();
|
||||
sleep(Duration::from_millis(300));
|
||||
|
||||
let socket = UdpSocket::bind(send_addr).unwrap();
|
||||
let mut acc = AccountantStub::new(addr, socket);
|
||||
let stream = TcpStream::connect(addr).expect("tcp connect");
|
||||
stream.set_nonblocking(true).expect("nonblocking");
|
||||
|
||||
let mut acc = AccountantStub::new(addr, socket, stream);
|
||||
let last_id = acc.get_last_id().unwrap();
|
||||
let sig = acc.transfer(500, &alice.keypair(), bob_pubkey, &last_id)
|
||||
.unwrap();
|
||||
acc.wait_on_signature(&sig, &last_id).unwrap();
|
||||
assert_eq!(acc.get_balance(&bob_pubkey).unwrap().unwrap(), 500);
|
||||
exit.store(true, Ordering::Relaxed);
|
||||
for t in threads {
|
||||
t.join().expect("join");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user