Skip to content

Commit

Permalink
feat: show the banned reason if a peer was banned in the contacts (#4525
Browse files Browse the repository at this point in the history
)

Description
---
Currently, if a peer has been banned, the constants will only show the peer is offline. 
This PR queries the peer manager for the peer to ask if the peer was banned or not. When asking the contact service in the wallet for the online status of the contact, the service will now report if the peer was banned, as well the reason for the banning.
  • Loading branch information
SWvheerden committed Aug 24, 2022
1 parent c2dfa23 commit f970f81
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 15 deletions.
2 changes: 1 addition & 1 deletion applications/tari_console_wallet/src/ui/state/app_state.rs
Expand Up @@ -757,7 +757,7 @@ impl AppStateInner {
let online_status = self
.wallet
.contacts_service
.get_contact_online_status(contact.last_seen)
.get_contact_online_status(contact.clone())
.await?;
ui_contacts.push(UiContact::from(contact.clone()).with_online_status(format!("{}", online_status)));
}
Expand Down
3 changes: 3 additions & 0 deletions base_layer/wallet/src/contacts_service/error.rs
Expand Up @@ -21,6 +21,7 @@
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use diesel::result::Error as DieselError;
use tari_comms::connectivity::ConnectivityError;
use tari_p2p::services::liveness::error::LivenessError;
use tari_service_framework::reply_channel::TransportChannelError;
use thiserror::Error;
Expand All @@ -40,6 +41,8 @@ pub enum ContactsServiceError {
TransportChannelError(#[from] TransportChannelError),
#[error("Livenessl error: `{0}`")]
LivenessError(#[from] LivenessError),
#[error("ConnectivityError error: `{0}`")]
ConnectivityError(#[from] ConnectivityError),
}

#[derive(Debug, Error)]
Expand Down
6 changes: 3 additions & 3 deletions base_layer/wallet/src/contacts_service/handle.rs
Expand Up @@ -128,7 +128,7 @@ pub enum ContactsServiceRequest {
UpsertContact(Contact),
RemoveContact(CommsPublicKey),
GetContacts,
GetContactOnlineStatus(Option<NaiveDateTime>),
GetContactOnlineStatus(Contact),
}

#[derive(Debug)]
Expand Down Expand Up @@ -212,11 +212,11 @@ impl ContactsServiceHandle {
/// Determines the contact's online status based on their last seen time
pub async fn get_contact_online_status(
&mut self,
last_seen: Option<NaiveDateTime>,
contact: Contact,
) -> Result<ContactOnlineStatus, ContactsServiceError> {
match self
.request_response_service
.call(ContactsServiceRequest::GetContactOnlineStatus(last_seen))
.call(ContactsServiceRequest::GetContactOnlineStatus(contact))
.await??
{
ContactsServiceResponse::OnlineStatus(status) => Ok(status),
Expand Down
20 changes: 15 additions & 5 deletions base_layer/wallet/src/contacts_service/service.rs
Expand Up @@ -67,6 +67,7 @@ pub enum ContactOnlineStatus {
Online,
Offline,
NeverSeen,
Banned(String),
}

impl Display for ContactOnlineStatus {
Expand All @@ -75,6 +76,7 @@ impl Display for ContactOnlineStatus {
ContactOnlineStatus::Online => write!(f, "Online"),
ContactOnlineStatus::Offline => write!(f, "Offline"),
ContactOnlineStatus::NeverSeen => write!(f, "NeverSeen"),
ContactOnlineStatus::Banned(reason) => write!(f, "Banned: {}", reason),
}
}
}
Expand Down Expand Up @@ -226,8 +228,8 @@ where T: ContactsBackend + 'static
}
Ok(result.map(ContactsServiceResponse::Contacts)?)
},
ContactsServiceRequest::GetContactOnlineStatus(last_seen) => {
let result = self.get_online_status(last_seen);
ContactsServiceRequest::GetContactOnlineStatus(contact) => {
let result = self.get_online_status(&contact).await;
Ok(result.map(ContactsServiceResponse::OnlineStatus)?)
},
}
Expand Down Expand Up @@ -277,7 +279,7 @@ where T: ContactsBackend + 'static
// Update offline status
if let Ok(contacts) = self.db.get_contacts().await {
for contact in contacts {
let online_status = self.get_online_status(contact.last_seen)?;
let online_status = self.get_online_status(&contact).await?;
if online_status == ContactOnlineStatus::Online {
continue;
}
Expand All @@ -302,9 +304,17 @@ where T: ContactsBackend + 'static
Ok(())
}

fn get_online_status(&self, last_seen: Option<NaiveDateTime>) -> Result<ContactOnlineStatus, ContactsServiceError> {
async fn get_online_status(&self, contact: &Contact) -> Result<ContactOnlineStatus, ContactsServiceError> {
let mut online_status = ContactOnlineStatus::NeverSeen;
if let Some(time) = last_seen {
match self.connectivity.get_peer_info(contact.node_id.clone()).await? {
Some(peer_data) => {
if peer_data.banned_until().is_some() {
return Ok(ContactOnlineStatus::Banned(peer_data.banned_reason));
}
},
None => return Ok(online_status),
};
if let Some(time) = contact.last_seen {
if self.is_online(time) {
online_status = ContactOnlineStatus::Online;
} else {
Expand Down
14 changes: 11 additions & 3 deletions base_layer/wallet_ffi/src/lib.rs
Expand Up @@ -2251,16 +2251,24 @@ pub unsafe extern "C" fn liveness_data_get_message_type(
pub unsafe extern "C" fn liveness_data_get_online_status(
liveness_data: *mut TariContactsLivenessData,
error_out: *mut c_int,
) -> c_int {
) -> *const c_char {
let mut error = 0;
let mut result = CString::new("").expect("Blank CString will not fail.");
ptr::swap(error_out, &mut error as *mut c_int);
if liveness_data.is_null() {
error = LibWalletError::from(InterfaceError::NullError("liveness_data".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
return -1;
return result.into_raw();
}
let status = (*liveness_data).online_status();
status as c_int
match CString::new(status.to_string()) {
Ok(v) => result = v,
_ => {
error = LibWalletError::from(InterfaceError::PointerError("message".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
},
}
result.into_raw()
}

/// Frees memory for a TariContactsLivenessData
Expand Down
4 changes: 2 additions & 2 deletions base_layer/wallet_ffi/wallet.h
Expand Up @@ -1235,8 +1235,8 @@ int liveness_data_get_message_type(TariContactsLivenessData *liveness_data,
* The ```liveness_data_destroy``` method must be called when finished with a TariContactsLivenessData to prevent a
* memory leak
*/
int liveness_data_get_online_status(TariContactsLivenessData *liveness_data,
int *error_out);
const char *liveness_data_get_online_status(TariContactsLivenessData *liveness_data,
int *error_out);

/**
* Frees memory for a TariContactsLivenessData
Expand Down
10 changes: 10 additions & 0 deletions comms/core/src/connectivity/manager.rs
Expand Up @@ -248,6 +248,16 @@ impl ConnectivityManagerActor {
.cloned(),
);
},
GetPeerStats(node_id, reply) => {
let peer = match self.peer_manager.find_by_node_id(&node_id).await {
Ok(v) => v,
Err(e) => {
error!(target: LOG_TARGET, "Error when retrieving peer: {:?}", e);
None
},
};
let _result = reply.send(peer);
},
GetAllConnectionStates(reply) => {
let states = self.pool.all().into_iter().cloned().collect();
let _result = reply.send(states);
Expand Down
17 changes: 16 additions & 1 deletion comms/core/src/connectivity/requester.rs
Expand Up @@ -39,7 +39,11 @@ use super::{
manager::ConnectivityStatus,
ConnectivitySelection,
};
use crate::{connection_manager::ConnectionManagerError, peer_manager::NodeId, PeerConnection};
use crate::{
connection_manager::ConnectionManagerError,
peer_manager::{NodeId, Peer},
PeerConnection,
};

const LOG_TARGET: &str = "comms::connectivity::requester";

Expand Down Expand Up @@ -100,6 +104,7 @@ pub enum ConnectivityRequest {
BanPeer(NodeId, Duration, String),
AddPeerToAllowList(NodeId),
RemovePeerFromAllowList(NodeId),
GetPeerStats(NodeId, oneshot::Sender<Option<Peer>>),
}

/// Handle to make requests and read events from the ConnectivityManager actor.
Expand Down Expand Up @@ -204,6 +209,16 @@ impl ConnectivityRequester {
reply_rx.await.map_err(|_| ConnectivityError::ActorResponseCancelled)
}

/// Get the peer information from the peer, will return none if the peer is not found
pub async fn get_peer_info(&self, node_id: NodeId) -> Result<Option<Peer>, ConnectivityError> {
let (reply_tx, reply_rx) = oneshot::channel();
self.sender
.send(ConnectivityRequest::GetPeerStats(node_id, reply_tx))
.await
.map_err(|_| ConnectivityError::ActorDisconnected)?;
reply_rx.await.map_err(|_| ConnectivityError::ActorResponseCancelled)
}

/// Get the current [ConnectivityStatus](self::ConnectivityStatus).
pub async fn get_connectivity_status(&mut self) -> Result<ConnectivityStatus, ConnectivityError> {
let (reply_tx, reply_rx) = oneshot::channel();
Expand Down
3 changes: 3 additions & 0 deletions comms/core/src/test_utils/mocks/connectivity_manager.rs
Expand Up @@ -259,6 +259,9 @@ impl ConnectivityManagerMock {
})
.await
},
GetPeerStats(_, _) => {
unimplemented!()
},
GetAllConnectionStates(_) => unimplemented!(),
BanPeer(_, _, _) => {},
AddPeerToAllowList(_) => {},
Expand Down

0 comments on commit f970f81

Please sign in to comment.