use bitcoincash::network::constants::Network;
use bitcoincash::network::message::NetworkMessage;
use bitcoincash::network::message_blockdata::InvType;
use bitcoincash::network::socket::Socket;
use bitcoincash::hash_types::Txid;
use bitcoincash::util::Error;
use std::sync::mpsc::Sender;
use std::thread;
use std::time::Duration;
use crate::util;
fn connect() -> Result<Socket, Error> {
let mut sock = Socket::new(Network::Bitcoin);
sock.connect("127.0.0.1", 8333)?;
Ok(sock)
}
fn handle(mut sock: Socket, tx: Sender<Txid>) {
let version_msg = match sock.version_message(0) {
Ok(msg) => msg,
Err(e) => {
warn!("failed to create version message: {}", e);
return;
}
};
let mut outgoing = vec![version_msg];
loop {
for msg in outgoing.split_off(0) {
trace!("send {:?}", msg);
if let Err(e) = sock.send_message(msg.clone()) {
warn!("failed to connect to node: {}", e);
break;
}
}
let msg = match sock.receive_message() {
Ok(msg) => msg,
Err(e) => {
warn!("failed to receive p2p message: {}", e);
break;
}
};
trace!("recv {:?}", msg);
match msg {
NetworkMessage::Alert(_) => continue, NetworkMessage::Version(_) => outgoing.push(NetworkMessage::Verack),
NetworkMessage::Ping(nonce) => outgoing.push(NetworkMessage::Pong(nonce)),
NetworkMessage::Inv(ref inventory) => {
for inv in inventory.iter().filter(|inv| inv.inv_type == InvType::Block) {
if let Err(e) = tx.send(inv.hash) {
warn!("failed to send block hash to channel: {}", e);
}
}
}
_ => (),
};
}
}
pub fn run() -> util::Channel<Txid> {
let chan = util::Channel::new();
let tx = chan.sender();
util::spawn_thread("p2p", move || loop {
match connect() {
Ok(sock) => handle(sock, tx.clone()),
Err(e) => warn!("p2p error: {}", e),
}
thread::sleep(Duration::from_secs(3));
});
chan
}