diff --git a/src/blockchain/blockchain.rs b/src/blockchain/blockchain.rs index 956af13..9fcc138 100644 --- a/src/blockchain/blockchain.rs +++ b/src/blockchain/blockchain.rs @@ -177,7 +177,7 @@ impl Blockchain { true } - pub fn get_domain_info(&self, domain: &str) -> Option { + pub fn get_domain_transaction(&self, domain: &str) -> Option { if domain.is_empty() { return None; } @@ -193,14 +193,21 @@ impl Blockchain { let pub_key = Bytes::from_bytes(statement.read::>(5).unwrap().as_slice()); let signature = Bytes::from_bytes(statement.read::>(6).unwrap().as_slice()); let transaction = Transaction { identity, confirmation, method, data, pub_key, signature }; - debug!("Got transaction: {:?}", &transaction); + debug!("Found transaction for domain {}: {:?}", domain, &transaction); if transaction.check_for(domain) { - return Some(transaction.data); + return Some(transaction); } } None } + pub fn get_domain_info(&self, domain: &str) -> Option { + match self.get_domain_transaction(domain) { + None => { None } + Some(transaction) => { Some(transaction.data) } + } + } + pub fn last_block(&self) -> Option { self.last_block.clone() } diff --git a/src/main.rs b/src/main.rs index f11e075..00c2b60 100644 --- a/src/main.rs +++ b/src/main.rs @@ -248,10 +248,23 @@ fn run_interface(context: Arc>, miner: Arc>) { let guard = context.lock().unwrap(); guard.get_keystore() }; - create_domain(miner.clone(), name, records, &keystore); + let transaction = { context.lock().unwrap().blockchain.get_domain_transaction(&name) }; + match transaction { + None => { + create_domain(miner.clone(), name, records, &keystore); + } + Some(transaction) => { + if transaction.pub_key == keystore.get_public() { + create_domain(miner.clone(), name, records, &keystore); + } else { + warn!("Tried to mine not owned domain!"); + let _ = web_view.eval(&format!("showWarning('{}');", "You cannot change domain that you don't own!")); + } + } + } } else { warn!("Error in DNS records for domain!"); - web_view.eval(&format!("showWarning('{}');", "Something wrong with your records! Please, correct the error and try again.")); + let _ = web_view.eval(&format!("showWarning('{}');", "Something wrong with your records! Please, correct the error and try again.")); } } ChangeDomain { .. } => {} diff --git a/src/p2p/network.rs b/src/p2p/network.rs index 7cb3287..981487c 100644 --- a/src/p2p/network.rs +++ b/src/p2p/network.rs @@ -88,28 +88,8 @@ impl Network { poll.registry().reregister(&mut server, SERVER, Interest::READABLE).expect("Error reregistering server"); } token => { - match peers.get_mut_peer(&token) { - Some(_peer) => { - match handle_connection_event(context.clone(), &mut peers, &poll.registry(), &event) { - Ok(result) => { - if !result { - match peers.remove_peer(&token) { - None => {} - Some(mut peer) => { - let stream = peer.get_stream(); - let _ = poll.registry().deregister(stream); - let _ = stream.shutdown(Shutdown::Both); - info!("Peer connection {:?} has shut down", &peer.get_addr()); - } - } - } - } - Err(_err) => { - peers.remove_peer(&token); - } - } - } - None => { warn!("Odd event from poll"); } + if !handle_connection_event(context.clone(), &mut peers, &poll.registry(), &event) { + let _ = peers.close_peer(poll.registry(), &token); } } } @@ -126,9 +106,9 @@ impl Network { } } -fn handle_connection_event(context: Arc>, peers: &mut Peers, registry: &Registry, event: &Event) -> io::Result { +fn handle_connection_event(context: Arc>, peers: &mut Peers, registry: &Registry, event: &Event) -> bool { if event.is_error() || (event.is_read_closed() && event.is_write_closed()) { - return Ok(false); + return false; } if event.is_readable() { @@ -168,14 +148,10 @@ fn handle_connection_event(context: Arc>, peers: &mut Peers, regi } } } - Err(_) => { return Ok(false); } + Err(_) => { return false; } } } else { - // Try to reregister connection - let peer = peers.get_mut_peer(&event.token()).expect("Error getting peer for connection"); - let mut stream = peer.get_stream(); - registry.reregister(stream, event.token(), Interest::READABLE); - return Ok(true); + return false; } } @@ -220,7 +196,7 @@ fn handle_connection_event(context: Arc>, peers: &mut Peers, regi } } - Ok(true) + true } fn read_message(stream: &mut TcpStream) -> Result, ()> { @@ -233,7 +209,7 @@ fn read_message(stream: &mut TcpStream) -> Result, ()> { } }; trace!("Payload size is {}", data_size); - if data_size > MAX_PACKET_SIZE { + if data_size > MAX_PACKET_SIZE || data_size == 0 { return Err(()); } diff --git a/src/p2p/peer.rs b/src/p2p/peer.rs index 6f6c4c9..af73fc1 100644 --- a/src/p2p/peer.rs +++ b/src/p2p/peer.rs @@ -24,6 +24,10 @@ impl Peer { &mut self.stream } + pub fn set_stream(&mut self, stream: TcpStream) { + self.stream = stream; + } + pub fn get_state(&self) -> &State { &self.state } @@ -48,6 +52,10 @@ impl Peer { self.state.disabled() } + pub fn is_inbound(&self) -> bool { + self.inbound + } + /// If loopback address then we care about ip and port. /// If regular address then we only care about the ip and ignore the port. pub fn equals(&self, addr: &SocketAddr) -> bool { diff --git a/src/p2p/peers.rs b/src/p2p/peers.rs index 1321ced..58e9777 100644 --- a/src/p2p/peers.rs +++ b/src/p2p/peers.rs @@ -1,5 +1,5 @@ use std::collections::HashMap; -use std::net::SocketAddr; +use std::net::{SocketAddr, Shutdown}; use mio::{Token, Interest, Registry}; use mio::net::TcpStream; use crate::p2p::{Peer, State, Message}; @@ -32,8 +32,23 @@ impl Peers { self.peers.get_mut(token) } - pub fn remove_peer(&mut self, token: &Token) -> Option { - self.peers.remove(token) + pub fn close_peer(&mut self, registry: &Registry, token: &Token) { + let mut peer = self.peers.get_mut(token); + match peer { + Some(mut peer) => { + let mut stream = peer.get_stream(); + let _ = stream.shutdown(Shutdown::Both); + registry.deregister(stream); + info!("Peer connection {:?} has shut down", &peer.get_addr()); + + if !peer.disabled() && !peer.is_inbound() { + peer.set_state(State::offline()); + } else { + self.peers.remove(token); + } + } + None => {} + } } pub fn add_peers_from_exchange(&mut self, peers: Vec) { @@ -41,7 +56,8 @@ impl Peers { // TODO make it return error if these peers are wrong and seem like an attack for peer in peers.iter() { let addr: SocketAddr = peer.parse().expect(&format!("Error parsing peer {}", peer)); - if addr.ip().is_loopback() { + if skip_addr(&addr) { + info!("Skipping address from exchange: {}", &addr); continue; // Return error in future } let mut found = false; @@ -101,6 +117,23 @@ impl Peers { _ => {} } } + + for (token, peer) in self.peers.iter_mut() { + if peer.get_state().need_reconnect() { + let addr = peer.get_addr(); + match TcpStream::connect(addr.clone()) { + Ok(mut stream) => { + registry.register(&mut stream, token.clone(), Interest::WRITABLE).unwrap(); + peer.set_state(State::Connecting); + peer.set_stream(stream); + info!("Created connection to peer {}", &addr); + } + Err(e) => { + error!("Error connecting to peer {}: {}", &addr, e); + } + } + } + } } pub fn connect_new_peers(&mut self, registry: &Registry, unique_token: &mut Token) { @@ -124,4 +157,25 @@ impl Peers { } self.new_peers.clear(); } +} + +fn skip_addr(addr: &SocketAddr) -> bool { + if addr.ip().is_loopback() { + return true; + } + match addr { + SocketAddr::V4(addr) => { + if addr.ip().is_private() { + return true; + } + } + SocketAddr::V6(addr) => { + // TODO uncomment when stabilized + // if addr.ip().is_unique_local() { + // return true; + // } + } + } + + false } \ No newline at end of file diff --git a/src/p2p/state.rs b/src/p2p/state.rs index ef169f7..d91eea2 100644 --- a/src/p2p/state.rs +++ b/src/p2p/state.rs @@ -36,6 +36,13 @@ impl State { } } + pub fn is_idle(&self) -> bool { + match self { + State::Idle { .. } => { true } + _ => { false } + } + } + pub fn disabled(&self) -> bool { match self { State::Error => { true } @@ -46,4 +53,11 @@ impl State { _ => { false } } } + + pub fn need_reconnect(&self) -> bool { + match self { + State::Offline { from } => { from.elapsed().as_secs() > 60 } + _ => { false } + } + } } diff --git a/src/webview/index.html b/src/webview/index.html index f7b00d9..31f22d1 100644 --- a/src/webview/index.html +++ b/src/webview/index.html @@ -99,10 +99,10 @@ @@ -145,17 +145,23 @@