Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(chatffi): message metadata #5766

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 45 additions & 7 deletions base_layer/chat_ffi/chat.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ struct ChatClientFFI;

struct ChatMessages;

struct Message;

struct TariAddress;

struct TransportConfig;
Expand Down Expand Up @@ -116,20 +118,56 @@ void destroy_chat_config(struct ApplicationConfig *config);
*
* ## Arguments
* `client` - The Client pointer
* `message` - Pointer to a Message struct
* `error_out` - Pointer to an int which will be modified
*
* ## Returns
* `()` - Does not return a value, equivalent to void in C
*
* # Safety
* The ```message``` should be destroyed after use
*/
void send_chat_message(struct ChatClientFFI *client, struct Message *message, int *error_out);

/**
* Creates a message and returns a ptr to it
*
* ## Arguments
* `receiver` - A string containing a tari address
* `message` - The peer seeds config for the node
* `error_out` - Pointer to an int which will be modified
*
* ## Returns
* `()` - Does not return a value, equivalent to void in C
* `*mut Message` - A pointer to a message object
*
* # Safety
* The ```receiver``` should be destroyed after use
*/
void send_chat_message(struct ChatClientFFI *client,
struct TariAddress *receiver,
const char *message_c_char,
int *error_out);
struct Message *create_chat_message(struct TariAddress *receiver,
const char *message,
int *error_out);

/**
* Creates message metadata and appends it to a Message
*
* ## Arguments
* `message` - A pointer to a message
* `metadata_type` - An int8 that maps to MessageMetadataType enum
* '0' -> Reply
* '1' -> TokenRequest
* `data` - contents for the metadata in string format
* `error_out` - Pointer to an int which will be modified
*
* ## Returns
* `()` - Does not return a value, equivalent to void in C
*
* ## Safety
* `message` should be destroyed eventually
*/
void add_chat_message_metadata(struct Message *message,
const int *metadata_type,
const char *data,
int *error_out);

/**
* Add a contact
Expand All @@ -143,9 +181,9 @@ void send_chat_message(struct ChatClientFFI *client,
* `()` - Does not return a value, equivalent to void in C
*
* # Safety
* The ```address``` should be destroyed after use
* The ```receiver``` should be destroyed after use
*/
void add_chat_contact(struct ChatClientFFI *client, struct TariAddress *receiver, int *error_out);
void add_chat_contact(struct ChatClientFFI *client, struct TariAddress *address, int *error_out);

/**
* Check the online status of a contact
Expand Down
141 changes: 123 additions & 18 deletions base_layer/chat_ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ use tari_common_types::tari_address::TariAddress;
use tari_comms::multiaddr::Multiaddr;
use tari_contacts::contacts_service::{
handle::{DEFAULT_MESSAGE_LIMIT, DEFAULT_MESSAGE_PAGE},
types::Message,
types::{Message, MessageBuilder, MessageMetadata, MessageMetadataType},
};
use tari_p2p::{SocksAuthentication, TorControlAuthentication, TorTransportConfig, TransportConfig, TransportType};
use tari_utilities::hex;
Expand Down Expand Up @@ -485,22 +485,16 @@ unsafe fn init_logging(log_path: PathBuf, error_out: *mut c_int) {
///
/// ## Arguments
/// `client` - The Client pointer
/// `receiver` - A string containing a tari address
/// `message` - The peer seeds config for the node
/// `message` - Pointer to a Message struct
/// `error_out` - Pointer to an int which will be modified
///
/// ## Returns
/// `()` - Does not return a value, equivalent to void in C
///
/// # Safety
/// The ```receiver``` should be destroyed after use
/// The ```message``` should be destroyed after use
#[no_mangle]
pub unsafe extern "C" fn send_chat_message(
client: *mut ChatClientFFI,
receiver: *mut TariAddress,
message_c_char: *const c_char,
error_out: *mut c_int,
) {
pub unsafe extern "C" fn send_chat_message(client: *mut ChatClientFFI, message: *mut Message, error_out: *mut c_int) {
let mut error = 0;
ptr::swap(error_out, &mut error as *mut c_int);

Expand All @@ -509,23 +503,119 @@ pub unsafe extern "C" fn send_chat_message(
ptr::swap(error_out, &mut error as *mut c_int);
}

if message.is_null() {
error = LibChatError::from(InterfaceError::NullError("message".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
}

(*client)
.runtime
.block_on((*client).client.send_message((*message).clone()));
}

/// Creates a message and returns a ptr to it
///
/// ## Arguments
/// `receiver` - A string containing a tari address
/// `message` - The peer seeds config for the node
/// `error_out` - Pointer to an int which will be modified
///
/// ## Returns
/// `*mut Message` - A pointer to a message object
///
/// # Safety
/// The ```receiver``` should be destroyed after use
#[no_mangle]
pub unsafe extern "C" fn create_chat_message(
receiver: *mut TariAddress,
message: *const c_char,
error_out: *mut c_int,
) -> *mut Message {
let mut error = 0;
ptr::swap(error_out, &mut error as *mut c_int);

if receiver.is_null() {
error = LibChatError::from(InterfaceError::NullError("receiver".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
}

let message = match CStr::from_ptr(message_c_char).to_str() {
let message_str = match CStr::from_ptr(message).to_str() {
Ok(str) => str.to_string(),
Err(e) => {
error = LibChatError::from(InterfaceError::InvalidArgument(e.to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
return ptr::null_mut();
},
};

let message_out = MessageBuilder::new()
.address((*receiver).clone())
.message(message_str)
.build();

Box::into_raw(Box::new(message_out))
}

/// Creates message metadata and appends it to a Message
///
/// ## Arguments
/// `message` - A pointer to a message
/// `metadata_type` - An int8 that maps to MessageMetadataType enum
/// '0' -> Reply
/// '1' -> TokenRequest
/// `data` - contents for the metadata in string format
/// `error_out` - Pointer to an int which will be modified
///
/// ## Returns
/// `()` - Does not return a value, equivalent to void in C
///
/// ## Safety
/// `message` should be destroyed eventually
#[no_mangle]
pub unsafe extern "C" fn add_chat_message_metadata(
message: *mut Message,
metadata_type: *const c_int,
data: *const c_char,
error_out: *mut c_int,
) {
let mut error = 0;
ptr::swap(error_out, &mut error as *mut c_int);

if message.is_null() {
error = LibChatError::from(InterfaceError::NullError("message".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
return;
}

let metadata_type = match MessageMetadataType::from_byte(metadata_type as u8) {
Some(t) => t,
None => {
error = LibChatError::from(InterfaceError::InvalidArgument(
"Couldn't convert byte to Metadata type".to_string(),
))
.code;
ptr::swap(error_out, &mut error as *mut c_int);
return;
},
};

(*client)
.runtime
.block_on((*client).client.send_message((*receiver).clone(), message));
if data.is_null() {
error = LibChatError::from(InterfaceError::NullError("data".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
return;
}

let data: Vec<u8> = match CStr::from_ptr(data).to_str() {
Ok(str) => str.as_bytes().into(),
Err(e) => {
error = LibChatError::from(InterfaceError::InvalidArgument(e.to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
return;
},
};

let metadata = MessageMetadata { metadata_type, data };
(*message).push(metadata);
}

/// Add a contact
Expand All @@ -539,11 +629,11 @@ pub unsafe extern "C" fn send_chat_message(
/// `()` - Does not return a value, equivalent to void in C
///
/// # Safety
/// The ```address``` should be destroyed after use
/// The ```receiver``` should be destroyed after use
#[no_mangle]
pub unsafe extern "C" fn add_chat_contact(
client: *mut ChatClientFFI,
receiver: *mut TariAddress,
address: *mut TariAddress,
error_out: *mut c_int,
) {
let mut error = 0;
Expand All @@ -554,12 +644,12 @@ pub unsafe extern "C" fn add_chat_contact(
ptr::swap(error_out, &mut error as *mut c_int);
}

if receiver.is_null() {
if address.is_null() {
error = LibChatError::from(InterfaceError::NullError("receiver".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
}

(*client).runtime.block_on((*client).client.add_contact(&(*receiver)));
(*client).runtime.block_on((*client).client.add_contact(&(*address)));
}

/// Check the online status of a contact
Expand Down Expand Up @@ -969,4 +1059,19 @@ mod test {
destroy_chat_tor_transport_config(transport_config);
}
}

#[test]
fn test_metadata_adding() {
let message_ptr = Box::into_raw(Box::default());

let data_c_str = CString::new("hello".to_string()).unwrap();
let data_char: *const c_char = CString::into_raw(data_c_str) as *const c_char;

let error_out = Box::into_raw(Box::new(0));

unsafe { add_chat_message_metadata(message_ptr, 1 as *const c_int, data_char, error_out) }

let message = unsafe { Box::from_raw(message_ptr) };
assert_eq!(message.metadata.len(), 1)
}
}
2 changes: 2 additions & 0 deletions base_layer/contacts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ num-derive = "0.3.3"
num-traits = "0.2.15"
prost = "0.9"
rand = "0.8"
serde = "1.0.136"
serde_json = "1.0.79"
thiserror = "1.0.26"
tokio = { version = "1.23", features = ["sync", "macros"] }
tower = "0.4"
Expand Down
24 changes: 20 additions & 4 deletions base_layer/contacts/examples/chat_client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use tari_comms::{CommsNode, NodeIdentity};
use tari_contacts::contacts_service::{
handle::ContactsServiceHandle,
service::ContactOnlineStatus,
types::{Message, MessageBuilder},
types::{Message, MessageBuilder, MessageMetadata, MessageMetadataType},
};
use tari_shutdown::Shutdown;

Expand All @@ -44,9 +44,11 @@ const LOG_TARGET: &str = "contacts::chat_client";
#[async_trait]
pub trait ChatClient {
async fn add_contact(&self, address: &TariAddress);
fn add_metadata(&self, message: Message, metadata_type: MessageMetadataType, data: String) -> Message;
async fn check_online_status(&self, address: &TariAddress) -> ContactOnlineStatus;
async fn send_message(&self, receiver: TariAddress, message: String);
fn create_message(&self, receiver: &TariAddress, message: String) -> Message;
async fn get_messages(&self, sender: &TariAddress, limit: u64, page: u64) -> Vec<Message>;
async fn send_message(&self, message: Message);
fn identity(&self) -> &NodeIdentity;
fn shutdown(&mut self);
}
Expand Down Expand Up @@ -148,10 +150,10 @@ impl ChatClient for Client {
ContactOnlineStatus::Offline
}

async fn send_message(&self, receiver: TariAddress, message: String) {
async fn send_message(&self, message: Message) {
if let Some(mut contacts_service) = self.contacts.clone() {
contacts_service
.send_message(MessageBuilder::new().message(message).address(receiver).build())
.send_message(message)
.await
.expect("Message wasn't sent");
}
Expand All @@ -168,6 +170,20 @@ impl ChatClient for Client {

messages
}

fn create_message(&self, receiver: &TariAddress, message: String) -> Message {
MessageBuilder::new().address(receiver.clone()).message(message).build()
}

fn add_metadata(&self, mut message: Message, metadata_type: MessageMetadataType, data: String) -> Message {
let metadata = MessageMetadata {
metadata_type,
data: data.into_bytes(),
};

message.push(metadata);
message
}
}

pub async fn wait_for_connectivity(comms: CommsNode) -> anyhow::Result<()> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE contacts drop metadata;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE messages ADD metadata BLOB;
18 changes: 14 additions & 4 deletions base_layer/contacts/proto/message.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,23 @@ package tari.contacts.chat;

message Message {
bytes body = 1;
bytes address = 2;
DirectionEnum direction = 3;
uint64 stored_at = 4;
bytes message_id = 5;
repeated MessageMetadata metadata = 2;
bytes address = 3;
DirectionEnum direction = 4;
uint64 stored_at = 5;
bytes message_id = 6;
}

enum DirectionEnum {
Inbound = 0;
Outbound = 1;
}

message MessageMetadata {
MessageTypeEnum metadata_type = 1;
bytes data = 2;
}

enum MessageTypeEnum {
TokenRequest = 0;
}
Loading