diff --git a/base_layer/chat_ffi/chat.h b/base_layer/chat_ffi/chat.h index 654edf1c04..89893c9b37 100644 --- a/base_layer/chat_ffi/chat.h +++ b/base_layer/chat_ffi/chat.h @@ -276,14 +276,14 @@ struct ChatByteVector *read_confirmation_message_id(struct Confirmation *confirm int *error_out); /** - * Get a c_longlong timestamp for the Confirmation + * Get a c_ulonglong timestamp for the Confirmation * * ## Arguments * `confirmation` - A pointer to the Confirmation * `error_out` - Pointer to an int which will be modified * * ## Returns - * `c_longlong` - A uint representation of time since epoch + * `c_ulonglong` - A uint representation of time since epoch. May return 0 on error * * # Safety * The ```confirmation``` When done with the Confirmation it should be destroyed @@ -329,7 +329,7 @@ void add_chat_contact(struct ChatClient *client, struct TariAddress *address, in * `error_out` - Pointer to an int which will be modified * * ## Returns - * `status` - Returns an int representing of the online status + * `status` - Returns an c_uchar representing of the online status * Online = 1, * Offline = 2, * NeverSeen = 3, @@ -338,7 +338,9 @@ void add_chat_contact(struct ChatClient *client, struct TariAddress *address, in * # Safety * The ```address``` should be destroyed after use */ -int check_online_status(struct ChatClient *client, struct TariAddress *receiver, int *error_out); +unsigned char check_online_status(struct ChatClient *client, + struct TariAddress *receiver, + int *error_out); /** * Returns a pointer to a TariAddress @@ -385,14 +387,14 @@ unsigned char read_liveness_data_online_status(struct ContactsLivenessData *live * `error_out` - Pointer to an int which will be modified * * ## Returns - * `c_longlong` - A c_longlong rep of an enum for a contacts online status. May return -1 if an error - * occurs, or 0 if the contact has never been seen + * `c_ulonglong` - A c_longlong rep of timestamp for a contacts last seen status. + * 0 if the contact has never been seen or an error occurs. * * ## Safety * `liveness` should be destroyed eventually */ -long long read_liveness_data_last_seen(struct ContactsLivenessData *liveness, - int *error_out); +unsigned long long read_liveness_data_last_seen(struct ContactsLivenessData *liveness, + int *error_out); /** * Frees memory for a ContactsLivenessData @@ -431,13 +433,13 @@ struct ConversationalistsVector *get_conversationalists(struct ChatClient *clien * `error_out` - Pointer to an int which will be modified * * ## Returns - * `c_int` - The length of the vector. May return -1 if something goes wrong + * `c_uint` - The length of the vector. May return 0 if something goes wrong * * ## Safety * `conversationalists` should be destroyed eventually */ -int conversationalists_vector_len(struct ConversationalistsVector *conversationalists, - int *error_out); +unsigned int conversationalists_vector_len(struct ConversationalistsVector *conversationalists, + int *error_out); /** * Reads the ConversationalistsVector and returns a pointer to a TariAddress at a given position @@ -548,13 +550,12 @@ struct MessageMetadata *chat_metadata_get_at(struct Message *message, * `error_out` - Pointer to an int which will be modified * * ## Returns - * `c_longlong` - The length of the metadata vector for a Message. May return -1 if something goes wrong + * `c_uint` - The length of the metadata vector for a Message. May return 0 if something goes wrong * * ## Safety * `message` should be destroyed eventually */ -long long chat_message_metadata_len(struct Message *message, - int *error_out); +unsigned int chat_message_metadata_len(struct Message *message, int *error_out); /** * Returns a pointer to a ChatByteVector representing the data of the Message @@ -589,21 +590,21 @@ struct ChatByteVector *read_chat_message_body(struct Message *message, int *erro struct TariAddress *read_chat_message_address(struct Message *message, int *error_out); /** - * Returns a c_int representation of the Direction enum + * Returns a c_uchar representation of the Direction enum * * ## Arguments * `message` - A pointer to a Message * `error_out` - Pointer to an int which will be modified * * ## Returns - * `c_int` - A c_int rep of the direction enum. May return -1 if anything goes wrong + * `c_uchar` - A c_uchar rep of the direction enum. May return 0 if anything goes wrong * 0 => Inbound * 1 => Outbound * * ## Safety * `message` should be destroyed eventually */ -int read_chat_message_direction(struct Message *message, int *error_out); +unsigned char read_chat_message_direction(struct Message *message, int *error_out); /** * Returns a c_ulonglong representation of the stored at timestamp as seconds since epoch @@ -674,9 +675,7 @@ struct ChatByteVector *read_chat_message_id(struct Message *message, int *error_ * * ## Arguments * `message` - A pointer to a message - * `metadata_type` - An c_uchar that maps to MessageMetadataType enum - * '0' -> Reply - * '1' -> TokenRequest + * `key` - A pointer to a byte vector containing bytes for the key field * `data` - A pointer to a byte vector containing bytes for the data field * `error_out` - Pointer to an int which will be modified * @@ -687,7 +686,7 @@ struct ChatByteVector *read_chat_message_id(struct Message *message, int *error_ * `message` should be destroyed eventually */ void add_chat_message_metadata(struct Message *message, - unsigned char metadata_type, + struct ChatByteVector *key, struct ChatByteVector *data, int *error_out); @@ -699,14 +698,13 @@ void add_chat_message_metadata(struct Message *message, * `error_out` - Pointer to an int which will be modified * * ## Returns - * `c_int` - An int8 that maps to MessageMetadataType enum. May return -1 if something goes wrong - * '0' -> Reply - * '1' -> TokenRequest + * `*mut ChatByteVector` - A ptr to a ChatByteVector * * ## Safety * `msg_metadata` should be destroyed eventually + * the returned `ChatByteVector` should be destroyed eventually */ -int read_chat_metadata_type(struct MessageMetadata *msg_metadata, int *error_out); +struct ChatByteVector *read_chat_metadata_key(struct MessageMetadata *msg_metadata, int *error_out); /** * Returns a ptr to a ByteVector @@ -759,8 +757,8 @@ void destroy_chat_message_metadata(struct MessageMetadata *ptr); */ struct MessageVector *get_chat_messages(struct ChatClient *client, struct TariAddress *address, - int limit, - int page, + unsigned int limit, + unsigned int page, int *error_out); /** @@ -771,12 +769,12 @@ struct MessageVector *get_chat_messages(struct ChatClient *client, * `error_out` - Pointer to an int which will be modified * * ## Returns - * `c_int` - The length of the metadata vector for a Message. May return -1 if something goes wrong + * `c_uint` - The length of the metadata vector for a Message. May return 0 if something goes wrong * * ## Safety * `messages` should be destroyed eventually */ -int message_vector_len(struct MessageVector *messages, int *error_out); +unsigned int message_vector_len(struct MessageVector *messages, int *error_out); /** * Reads the MessageVector and returns a Message at a given position diff --git a/base_layer/chat_ffi/src/byte_vector.rs b/base_layer/chat_ffi/src/byte_vector.rs index 9a73239e1e..233840c66d 100644 --- a/base_layer/chat_ffi/src/byte_vector.rs +++ b/base_layer/chat_ffi/src/byte_vector.rs @@ -152,3 +152,17 @@ pub unsafe extern "C" fn chat_byte_vector_get_length(vec: *const ChatByteVector, (*vec).0.len() as c_uint } + +pub(crate) unsafe fn process_vector(vector: *mut ChatByteVector, error_out: *mut c_int) -> Vec { + let data_byte_vector_length = chat_byte_vector_get_length(vector, error_out); + let mut bytes: Vec = Vec::new(); + + if data_byte_vector_length > 0 { + for c in 0..data_byte_vector_length { + let byte = chat_byte_vector_get_at(vector, c as c_uint, error_out); + bytes.push(byte); + } + } + + bytes +} diff --git a/base_layer/chat_ffi/src/confirmation.rs b/base_layer/chat_ffi/src/confirmation.rs index d3ef37f127..7f89fd5a29 100644 --- a/base_layer/chat_ffi/src/confirmation.rs +++ b/base_layer/chat_ffi/src/confirmation.rs @@ -101,18 +101,27 @@ pub unsafe extern "C" fn read_confirmation_message_id( let c = &(*confirmation); let data_bytes = c.message_id.clone(); - let len = u32::try_from(data_bytes.len()).expect("Can't cast from usize"); + + let len = match u32::try_from(data_bytes.len()) { + Ok(l) => l, + Err(e) => { + error = LibChatError::from(InterfaceError::ConversionError(e.to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + 0 + }, + }; + chat_byte_vector_create(data_bytes.as_ptr(), len as c_uint, error_out) } -/// Get a c_longlong timestamp for the Confirmation +/// Get a c_ulonglong timestamp for the Confirmation /// /// ## Arguments /// `confirmation` - A pointer to the Confirmation /// `error_out` - Pointer to an int which will be modified /// /// ## Returns -/// `c_longlong` - A uint representation of time since epoch +/// `c_ulonglong` - A uint representation of time since epoch. May return 0 on error /// /// # Safety /// The ```confirmation``` When done with the Confirmation it should be destroyed diff --git a/base_layer/chat_ffi/src/contacts.rs b/base_layer/chat_ffi/src/contacts.rs index 333799a35c..90b7972f8f 100644 --- a/base_layer/chat_ffi/src/contacts.rs +++ b/base_layer/chat_ffi/src/contacts.rs @@ -22,7 +22,7 @@ use std::ptr; -use libc::c_int; +use libc::{c_int, c_uchar}; use tari_chat_client::ChatClient as ChatClientTrait; use tari_common_types::tari_address::TariAddress; @@ -74,7 +74,7 @@ pub unsafe extern "C" fn add_chat_contact(client: *mut ChatClient, address: *mut /// `error_out` - Pointer to an int which will be modified /// /// ## Returns -/// `status` - Returns an int representing of the online status +/// `status` - Returns an c_uchar representing of the online status /// Online = 1, /// Offline = 2, /// NeverSeen = 3, @@ -87,7 +87,7 @@ pub unsafe extern "C" fn check_online_status( client: *mut ChatClient, receiver: *mut TariAddress, error_out: *mut c_int, -) -> c_int { +) -> c_uchar { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); @@ -105,7 +105,7 @@ pub unsafe extern "C" fn check_online_status( let result = (*client).runtime.block_on((*client).client.check_online_status(&rec)); match result { - Ok(status) => status.as_u8().into(), + Ok(status) => status.as_u8(), Err(e) => { error = LibChatError::from(InterfaceError::ContactServiceError(e.to_string())).code; ptr::swap(error_out, &mut error as *mut c_int); diff --git a/base_layer/chat_ffi/src/contacts_liveness_data.rs b/base_layer/chat_ffi/src/contacts_liveness_data.rs index ab27f03e35..c1bb9b305a 100644 --- a/base_layer/chat_ffi/src/contacts_liveness_data.rs +++ b/base_layer/chat_ffi/src/contacts_liveness_data.rs @@ -20,9 +20,9 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::ptr; +use std::{convert::TryFrom, ptr}; -use libc::{c_int, c_longlong, c_uchar}; +use libc::{c_int, c_uchar, c_ulonglong}; use tari_common_types::tari_address::TariAddress; use tari_contacts::contacts_service::handle::ContactsLivenessData; @@ -97,8 +97,8 @@ pub unsafe extern "C" fn read_liveness_data_online_status( /// `error_out` - Pointer to an int which will be modified /// /// ## Returns -/// `c_longlong` - A c_longlong rep of an enum for a contacts online status. May return -1 if an error -/// occurs, or 0 if the contact has never been seen +/// `c_ulonglong` - A c_longlong rep of timestamp for a contacts last seen status. +/// 0 if the contact has never been seen or an error occurs. /// /// ## Safety /// `liveness` should be destroyed eventually @@ -106,7 +106,7 @@ pub unsafe extern "C" fn read_liveness_data_online_status( pub unsafe extern "C" fn read_liveness_data_last_seen( liveness: *mut ContactsLivenessData, error_out: *mut c_int, -) -> c_longlong { +) -> c_ulonglong { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); @@ -117,7 +117,13 @@ pub unsafe extern "C" fn read_liveness_data_last_seen( } match (*liveness).last_ping_pong_received() { - Some(last_seen) => last_seen.timestamp(), + Some(last_seen) => match u64::try_from(last_seen.timestamp()) { + Ok(ls) => ls as c_ulonglong, + Err(_e) => { + ptr::swap(error_out, &mut error as *mut c_int); + 0 + }, + }, None => 0, } } diff --git a/base_layer/chat_ffi/src/conversationalists.rs b/base_layer/chat_ffi/src/conversationalists.rs index 239d5a0b75..c012956abb 100644 --- a/base_layer/chat_ffi/src/conversationalists.rs +++ b/base_layer/chat_ffi/src/conversationalists.rs @@ -77,7 +77,7 @@ pub unsafe extern "C" fn get_conversationalists( /// `error_out` - Pointer to an int which will be modified /// /// ## Returns -/// `c_int` - The length of the vector. May return -1 if something goes wrong +/// `c_uint` - The length of the vector. May return 0 if something goes wrong /// /// ## Safety /// `conversationalists` should be destroyed eventually @@ -85,18 +85,25 @@ pub unsafe extern "C" fn get_conversationalists( pub unsafe extern "C" fn conversationalists_vector_len( conversationalists: *mut ConversationalistsVector, error_out: *mut c_int, -) -> c_int { +) -> c_uint { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); if conversationalists.is_null() { error = LibChatError::from(InterfaceError::NullError("conversationalists".to_string())).code; ptr::swap(error_out, &mut error as *mut c_int); - return -1; + return 0; } let conversationalists = &(*conversationalists); - c_int::try_from(conversationalists.0.len()).unwrap_or(-1) + match c_uint::try_from(conversationalists.0.len()) { + Ok(l) => l, + Err(e) => { + error = LibChatError::from(InterfaceError::ConversionError(e.to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + 0 + }, + } } /// Reads the ConversationalistsVector and returns a pointer to a TariAddress at a given position diff --git a/base_layer/chat_ffi/src/error.rs b/base_layer/chat_ffi/src/error.rs index 48008c4885..69d46ce71b 100644 --- a/base_layer/chat_ffi/src/error.rs +++ b/base_layer/chat_ffi/src/error.rs @@ -36,6 +36,8 @@ pub enum InterfaceError { AllocationError, #[error("An error because the supplied position was out of range")] PositionInvalidError, + #[error("Conversion error: `{0}`")] + ConversionError(String), #[error("The client had an error communication with contact services")] ContactServiceError(String), } @@ -76,6 +78,10 @@ impl From for LibChatError { code: 8, message: format!("{:?}", v), }, + InterfaceError::ConversionError(_) => Self { + code: 9, + message: format!("{:?}", v), + }, } } } diff --git a/base_layer/chat_ffi/src/message.rs b/base_layer/chat_ffi/src/message.rs index c4b6f654bf..9be70ab11b 100644 --- a/base_layer/chat_ffi/src/message.rs +++ b/base_layer/chat_ffi/src/message.rs @@ -22,7 +22,7 @@ use std::{convert::TryFrom, ffi::CStr, ptr}; -use libc::{c_char, c_int, c_longlong, c_uint, c_ulonglong}; +use libc::{c_char, c_int, c_uchar, c_uint, c_ulonglong}; use tari_chat_client::ChatClient as ChatClientTrait; use tari_common_types::tari_address::TariAddress; use tari_contacts::contacts_service::types::{Message, MessageBuilder, MessageMetadata}; @@ -183,25 +183,30 @@ pub unsafe extern "C" fn chat_metadata_get_at( /// `error_out` - Pointer to an int which will be modified /// /// ## Returns -/// `c_longlong` - The length of the metadata vector for a Message. May return -1 if something goes wrong +/// `c_uint` - The length of the metadata vector for a Message. May return 0 if something goes wrong /// /// ## Safety /// `message` should be destroyed eventually #[no_mangle] -pub unsafe extern "C" fn chat_message_metadata_len(message: *mut Message, error_out: *mut c_int) -> c_longlong { +pub unsafe extern "C" fn chat_message_metadata_len(message: *mut Message, error_out: *mut c_int) -> c_uint { 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 -1; + return 0; } let message = &(*message); - #[allow(clippy::cast_possible_wrap)] - let res = message.metadata.len() as i64; - res + match c_uint::try_from(message.metadata.len()) { + Ok(l) => l, + Err(e) => { + error = LibChatError::from(InterfaceError::ConversionError(e.to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + 0 + }, + } } /// Returns a pointer to a ChatByteVector representing the data of the Message @@ -268,31 +273,38 @@ pub unsafe extern "C" fn read_chat_message_address(message: *mut Message, error_ Box::into_raw(Box::new(address)) } -/// Returns a c_int representation of the Direction enum +/// Returns a c_uchar representation of the Direction enum /// /// ## Arguments /// `message` - A pointer to a Message /// `error_out` - Pointer to an int which will be modified /// /// ## Returns -/// `c_int` - A c_int rep of the direction enum. May return -1 if anything goes wrong +/// `c_uchar` - A c_uchar rep of the direction enum. May return 0 if anything goes wrong /// 0 => Inbound /// 1 => Outbound /// /// ## Safety /// `message` should be destroyed eventually #[no_mangle] -pub unsafe extern "C" fn read_chat_message_direction(message: *mut Message, error_out: *mut c_int) -> c_int { +pub unsafe extern "C" fn read_chat_message_direction(message: *mut Message, error_out: *mut c_int) -> c_uchar { 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 -1; + return 0; } - c_int::from((*message).direction.as_byte()) + match c_uchar::try_from((*message).direction.as_byte()) { + Ok(d) => d, + Err(e) => { + error = LibChatError::from(InterfaceError::ConversionError(e.to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + 0 + }, + } } /// Returns a c_ulonglong representation of the stored at timestamp as seconds since epoch diff --git a/base_layer/chat_ffi/src/message_metadata.rs b/base_layer/chat_ffi/src/message_metadata.rs index a3e06492c6..c93d4a6398 100644 --- a/base_layer/chat_ffi/src/message_metadata.rs +++ b/base_layer/chat_ffi/src/message_metadata.rs @@ -22,12 +22,12 @@ use std::{convert::TryFrom, ptr}; -use libc::{c_int, c_uchar, c_uint}; -use tari_contacts::contacts_service::types::{Message, MessageMetadata, MessageMetadataType}; +use libc::{c_int, c_uint}; +use tari_contacts::contacts_service::types::{Message, MessageMetadata}; use tari_utilities::ByteArray; use crate::{ - byte_vector::{chat_byte_vector_create, chat_byte_vector_get_at, chat_byte_vector_get_length, ChatByteVector}, + byte_vector::{chat_byte_vector_create, process_vector, ChatByteVector}, error::{InterfaceError, LibChatError}, }; @@ -35,9 +35,7 @@ use crate::{ /// /// ## Arguments /// `message` - A pointer to a message -/// `metadata_type` - An c_uchar that maps to MessageMetadataType enum -/// '0' -> Reply -/// '1' -> TokenRequest +/// `key` - A pointer to a byte vector containing bytes for the key field /// `data` - A pointer to a byte vector containing bytes for the data field /// `error_out` - Pointer to an int which will be modified /// @@ -49,49 +47,26 @@ use crate::{ #[no_mangle] pub unsafe extern "C" fn add_chat_message_metadata( message: *mut Message, - metadata_type: c_uchar, + key: *mut ChatByteVector, data: *mut ChatByteVector, 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) { - Some(t) => t, - None => { - error = LibChatError::from(InterfaceError::InvalidArgument( - "Couldn't convert byte to Metadata type".to_string(), - )) - .code; + for (name, d) in [("key", key), ("data", data)] { + if d.is_null() { + error = LibChatError::from(InterfaceError::NullError(name.to_string())).code; ptr::swap(error_out, &mut error as *mut c_int); return; - }, - }; - - 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 chat_byte_vector_length = chat_byte_vector_get_length(data, error_out); - let mut bytes: Vec = Vec::new(); - for c in 0..chat_byte_vector_length { - let byte = chat_byte_vector_get_at(data, c as c_uint, error_out); - assert_eq!(error, 0); - bytes.push(byte); + } } let metadata = MessageMetadata { - metadata_type, - data: bytes, + key: process_vector(key, error_out), + data: process_vector(data, error_out), }; + (*message).push(metadata); } @@ -102,25 +77,37 @@ pub unsafe extern "C" fn add_chat_message_metadata( /// `error_out` - Pointer to an int which will be modified /// /// ## Returns -/// `c_int` - An int8 that maps to MessageMetadataType enum. May return -1 if something goes wrong -/// '0' -> Reply -/// '1' -> TokenRequest +/// `*mut ChatByteVector` - A ptr to a ChatByteVector /// /// ## Safety /// `msg_metadata` should be destroyed eventually +/// the returned `ChatByteVector` should be destroyed eventually #[no_mangle] -pub unsafe extern "C" fn read_chat_metadata_type(msg_metadata: *mut MessageMetadata, error_out: *mut c_int) -> c_int { +pub unsafe extern "C" fn read_chat_metadata_key( + msg_metadata: *mut MessageMetadata, + error_out: *mut c_int, +) -> *mut ChatByteVector { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); if msg_metadata.is_null() { error = LibChatError::from(InterfaceError::NullError("message".to_string())).code; ptr::swap(error_out, &mut error as *mut c_int); - return -1; + return ptr::null_mut(); } - let md = &(*msg_metadata); - c_int::from(md.metadata_type.as_byte()) + let data = (*msg_metadata).key.clone(); + let data_bytes = data.as_bytes(); + let len = match c_uint::try_from(data_bytes.len()) { + Ok(num) => num, + Err(_e) => { + error = LibChatError::from(InterfaceError::PositionInvalidError).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + }, + }; + + chat_byte_vector_create(data_bytes.as_ptr(), len, error_out) } /// Returns a ptr to a ByteVector @@ -190,7 +177,12 @@ mod test { use super::*; use crate::{ - byte_vector::{chat_byte_vector_create, chat_byte_vector_destroy}, + byte_vector::{ + chat_byte_vector_create, + chat_byte_vector_destroy, + chat_byte_vector_get_at, + chat_byte_vector_get_length, + }, message::{chat_metadata_get_at, destroy_chat_message}, }; @@ -201,10 +193,15 @@ mod test { let data = "hello".to_string(); let data_bytes = data.as_bytes(); - let len = u32::try_from(data.len()).expect("Can't cast from usize"); - let data = unsafe { chat_byte_vector_create(data_bytes.as_ptr(), len as c_uint, error_out) }; + let data_len = u32::try_from(data.len()).expect("Can't cast from usize"); + let data = unsafe { chat_byte_vector_create(data_bytes.as_ptr(), data_len as c_uint, error_out) }; - unsafe { add_chat_message_metadata(message_ptr, 0, data, error_out) } + let key = "gif".to_string(); + let key_bytes = key.as_bytes(); + let key_len = u32::try_from(key.len()).expect("Can't cast from usize"); + let key = unsafe { chat_byte_vector_create(key_bytes.as_ptr(), key_len as c_uint, error_out) }; + + unsafe { add_chat_message_metadata(message_ptr, key, data, error_out) } let message = unsafe { Box::from_raw(message_ptr) }; assert_eq!(message.metadata.len(), 1); @@ -232,27 +229,41 @@ mod test { let data_bytes = data.as_bytes(); let len = u32::try_from(data.len()).expect("Can't cast from usize"); let data = chat_byte_vector_create(data_bytes.as_ptr(), len as c_uint, error_out); - let md_type = 0; - add_chat_message_metadata(message_ptr, md_type, data, error_out); + let key = "gif".to_string(); + let key_bytes = key.as_bytes(); + let len = u32::try_from(key.len()).expect("Can't cast from usize"); + let key = chat_byte_vector_create(key_bytes.as_ptr(), len as c_uint, error_out); + + add_chat_message_metadata(message_ptr, key, data, error_out); let metadata_ptr = chat_metadata_get_at(message_ptr, 0, error_out); - let metadata_type = read_chat_metadata_type(metadata_ptr, error_out); - let metadata_byte_vector = read_chat_metadata_data(metadata_ptr, error_out); + let metadata_key_vector = read_chat_metadata_key(metadata_ptr, error_out); + let metadata_key_vector_len = chat_byte_vector_get_length(metadata_key_vector, error_out); + + let mut metadata_key = vec![]; + + for i in 0..metadata_key_vector_len { + metadata_key.push(chat_byte_vector_get_at(metadata_key_vector, i, error_out)); + } + + let metadata_data_vector = read_chat_metadata_data(metadata_ptr, error_out); + let metadata_data_vector_len = chat_byte_vector_get_length(metadata_data_vector, error_out); let mut metadata_data = vec![]; - for i in 0..len { - metadata_data.push(chat_byte_vector_get_at(metadata_byte_vector, i, error_out)); + for i in 0..metadata_data_vector_len { + metadata_data.push(chat_byte_vector_get_at(metadata_data_vector, i, error_out)); } - assert_eq!(metadata_type, i32::from(md_type)); + assert_eq!(metadata_key, key_bytes); assert_eq!(metadata_data, data_bytes); destroy_chat_message_metadata(metadata_ptr); destroy_chat_message(message_ptr); - chat_byte_vector_destroy(metadata_byte_vector); + chat_byte_vector_destroy(metadata_key_vector); + chat_byte_vector_destroy(metadata_data_vector); drop(Box::from_raw(error_out)); } } diff --git a/base_layer/chat_ffi/src/messages.rs b/base_layer/chat_ffi/src/messages.rs index 88fe872179..1e8a87b6d4 100644 --- a/base_layer/chat_ffi/src/messages.rs +++ b/base_layer/chat_ffi/src/messages.rs @@ -25,10 +25,7 @@ use std::{convert::TryFrom, ptr}; use libc::{c_int, c_uint}; use tari_chat_client::ChatClient as ChatClientTrait; use tari_common_types::tari_address::TariAddress; -use tari_contacts::contacts_service::{ - handle::{DEFAULT_MESSAGE_LIMIT, DEFAULT_MESSAGE_PAGE}, - types::Message, -}; +use tari_contacts::contacts_service::types::Message; use crate::{ error::{InterfaceError, LibChatError}, @@ -58,8 +55,8 @@ pub struct MessageVector(pub Vec); pub unsafe extern "C" fn get_chat_messages( client: *mut ChatClient, address: *mut TariAddress, - limit: c_int, - page: c_int, + limit: c_uint, + page: c_uint, error_out: *mut c_int, ) -> *mut MessageVector { let mut error = 0; @@ -75,8 +72,8 @@ pub unsafe extern "C" fn get_chat_messages( ptr::swap(error_out, &mut error as *mut c_int); } - let mlimit = u64::try_from(limit).unwrap_or(DEFAULT_MESSAGE_LIMIT); - let mpage = u64::try_from(page).unwrap_or(DEFAULT_MESSAGE_PAGE); + let mlimit = u64::from(limit); + let mpage = u64::from(page); let result = (*client) .runtime @@ -99,23 +96,30 @@ pub unsafe extern "C" fn get_chat_messages( /// `error_out` - Pointer to an int which will be modified /// /// ## Returns -/// `c_int` - The length of the metadata vector for a Message. May return -1 if something goes wrong +/// `c_uint` - The length of the metadata vector for a Message. May return 0 if something goes wrong /// /// ## Safety /// `messages` should be destroyed eventually #[no_mangle] -pub unsafe extern "C" fn message_vector_len(messages: *mut MessageVector, error_out: *mut c_int) -> c_int { +pub unsafe extern "C" fn message_vector_len(messages: *mut MessageVector, error_out: *mut c_int) -> c_uint { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); if messages.is_null() { error = LibChatError::from(InterfaceError::NullError("message".to_string())).code; ptr::swap(error_out, &mut error as *mut c_int); - return -1; + return 0; } let messages = &(*messages); - c_int::try_from(messages.0.len()).unwrap_or(-1) + match c_uint::try_from(messages.0.len()) { + Ok(l) => l, + Err(e) => { + error = LibChatError::from(InterfaceError::ConversionError(e.to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + 0 + }, + } } /// Reads the MessageVector and returns a Message at a given position diff --git a/base_layer/contacts/proto/message.proto b/base_layer/contacts/proto/message.proto index 6770cb65b7..92c3b7d7fc 100644 --- a/base_layer/contacts/proto/message.proto +++ b/base_layer/contacts/proto/message.proto @@ -18,14 +18,10 @@ enum DirectionEnum { } message MessageMetadata { - MessageTypeEnum metadata_type = 1; + bytes key = 1; bytes data = 2; } -enum MessageTypeEnum { - TokenRequest = 0; -} - message Confirmation { bytes message_id = 1; uint64 timestamp = 2; diff --git a/base_layer/contacts/src/chat_client/src/client.rs b/base_layer/contacts/src/chat_client/src/client.rs index 0e33079075..801f318fc7 100644 --- a/base_layer/contacts/src/chat_client/src/client.rs +++ b/base_layer/contacts/src/chat_client/src/client.rs @@ -34,7 +34,7 @@ use tari_comms::{peer_manager::PeerFeatures, CommsNode, NodeIdentity}; use tari_contacts::contacts_service::{ handle::ContactsServiceHandle, service::ContactOnlineStatus, - types::{Message, MessageBuilder, MessageMetadata, MessageMetadataType}, + types::{Message, MessageBuilder, MessageMetadata}, }; use tari_shutdown::Shutdown; @@ -45,7 +45,7 @@ const LOG_TARGET: &str = "contacts::chat_client"; #[async_trait] pub trait ChatClient { async fn add_contact(&self, address: &TariAddress) -> Result<(), Error>; - fn add_metadata(&self, message: Message, metadata_type: MessageMetadataType, data: String) -> Message; + fn add_metadata(&self, message: Message, metadata_type: String, data: String) -> Message; async fn check_online_status(&self, address: &TariAddress) -> Result; fn create_message(&self, receiver: &TariAddress, message: String) -> Message; async fn get_messages(&self, sender: &TariAddress, limit: u64, page: u64) -> Result, Error>; @@ -198,9 +198,9 @@ impl ChatClient for Client { MessageBuilder::new().address(receiver.clone()).message(message).build() } - fn add_metadata(&self, mut message: Message, metadata_type: MessageMetadataType, data: String) -> Message { + fn add_metadata(&self, mut message: Message, key: String, data: String) -> Message { let metadata = MessageMetadata { - metadata_type, + key: key.into_bytes(), data: data.into_bytes(), }; diff --git a/base_layer/contacts/src/contacts_service/types/message.rs b/base_layer/contacts/src/contacts_service/types/message.rs index 9dac4657ad..d259f8da78 100644 --- a/base_layer/contacts/src/contacts_service/types/message.rs +++ b/base_layer/contacts/src/contacts_service/types/message.rs @@ -70,38 +70,17 @@ impl Direction { #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct MessageMetadata { - pub metadata_type: MessageMetadataType, + pub key: Vec, pub data: Vec, } -#[repr(u8)] -#[derive(FromPrimitive, Debug, Copy, Clone, Default, Deserialize, Serialize, PartialEq)] -pub enum MessageMetadataType { - Reply = 0, - #[default] - TokenRequest = 1, -} - -impl MessageMetadataType { - pub fn as_byte(self) -> u8 { - self as u8 - } - - pub fn from_byte(value: u8) -> Option { - FromPrimitive::from_u8(value) - } -} - impl TryFrom for Message { type Error = String; fn try_from(message: proto::Message) -> Result { let mut metadata = vec![]; for m in message.metadata { - match MessageMetadata::try_from(m) { - Ok(md) => metadata.push(md), - Err(e) => return Err(e), - } + metadata.push(m.into()); } Ok(Self { @@ -138,19 +117,11 @@ impl From for OutboundDomainMessage { } } -impl TryFrom for MessageMetadata { - type Error = String; - - fn try_from(md: proto::MessageMetadata) -> Result { - if let Some(md_type) = - MessageMetadataType::from_byte(u8::try_from(md.metadata_type).map_err(|e| e.to_string())?) - { - Ok(Self { - data: md.data, - metadata_type: md_type, - }) - } else { - Err("Not a valid metadata type".into()) +impl From for MessageMetadata { + fn from(md: proto::MessageMetadata) -> Self { + Self { + data: md.data, + key: md.key, } } } @@ -159,7 +130,7 @@ impl From for proto::MessageMetadata { fn from(md: MessageMetadata) -> Self { Self { data: md.data, - metadata_type: i32::from(md.metadata_type.as_byte()), + key: md.key, } } } diff --git a/base_layer/contacts/src/contacts_service/types/mod.rs b/base_layer/contacts/src/contacts_service/types/mod.rs index 16fdb38a46..3faa818886 100644 --- a/base_layer/contacts/src/contacts_service/types/mod.rs +++ b/base_layer/contacts/src/contacts_service/types/mod.rs @@ -24,7 +24,7 @@ mod contact; pub use contact::Contact; mod message; -pub use message::{Direction, Message, MessageMetadata, MessageMetadataType}; +pub use message::{Direction, Message, MessageMetadata}; mod message_builder; pub use message_builder::MessageBuilder; diff --git a/integration_tests/src/chat_ffi.rs b/integration_tests/src/chat_ffi.rs index 6ecd2d0be7..3b02918d38 100644 --- a/integration_tests/src/chat_ffi.rs +++ b/integration_tests/src/chat_ffi.rs @@ -41,10 +41,7 @@ use tari_comms::{ multiaddr::Multiaddr, peer_manager::{Peer, PeerFeatures}, }; -use tari_contacts::contacts_service::{ - service::ContactOnlineStatus, - types::{Message, MessageMetadataType}, -}; +use tari_contacts::contacts_service::{service::ContactOnlineStatus, types::Message}; use crate::{chat_client::test_config, get_port}; @@ -92,7 +89,7 @@ extern "C" { pub fn send_chat_message(client: *mut ClientFFI, message: *mut c_void, error_out: *const c_int); pub fn add_chat_message_metadata( message: *mut c_void, - metadata_type: c_int, + metadata_type: *const c_char, data: *const c_char, error_out: *const c_int, ) -> *mut c_void; @@ -199,20 +196,22 @@ impl ChatClient for ChatFFI { } } - fn add_metadata(&self, message: Message, metadata_type: MessageMetadataType, data: String) -> Message { + fn add_metadata(&self, message: Message, key: String, data: String) -> Message { let message_ptr = Box::into_raw(Box::new(message)) as *mut c_void; - let message_type = metadata_type.as_byte(); - let error_out = Box::into_raw(Box::new(0)); - let bytes = data.into_bytes(); - let len = i32::try_from(bytes.len()).expect("Truncation occurred") as c_uint; - let byte_data = unsafe { chat_byte_vector_create(bytes.as_ptr(), len, error_out) }; + let key_bytes = key.into_bytes(); + let len = i32::try_from(key_bytes.len()).expect("Truncation occurred") as c_uint; + let byte_key = unsafe { chat_byte_vector_create(key_bytes.as_ptr(), len, error_out) }; + + let data_bytes = data.into_bytes(); + let len = i32::try_from(data_bytes.len()).expect("Truncation occurred") as c_uint; + let byte_data = unsafe { chat_byte_vector_create(data_bytes.as_ptr(), len, error_out) }; unsafe { add_chat_message_metadata( message_ptr, - i32::from(message_type), + byte_key as *const c_char, byte_data as *const c_char, error_out, ); diff --git a/integration_tests/tests/steps/chat_steps.rs b/integration_tests/tests/steps/chat_steps.rs index 7b7d6aa525..7fc202faf2 100644 --- a/integration_tests/tests/steps/chat_steps.rs +++ b/integration_tests/tests/steps/chat_steps.rs @@ -26,7 +26,7 @@ use cucumber::{then, when}; use tari_contacts::contacts_service::{ handle::{DEFAULT_MESSAGE_LIMIT, DEFAULT_MESSAGE_PAGE}, service::ContactOnlineStatus, - types::{Direction, Message, MessageMetadata, MessageMetadataType}, + types::{Direction, Message, MessageMetadata}, }; use tari_integration_tests::{chat_client::spawn_chat_client, TariWorld}; @@ -108,7 +108,7 @@ async fn i_reply_to_message( let message = sender.add_metadata( message, - MessageMetadataType::Reply, + "reply".to_string(), String::from_utf8(inbound_chat_message.message_id).expect("bytes to uuid"), ); @@ -221,11 +221,7 @@ async fn have_replied_message( let metadata: &MessageMetadata = &inbound_chat_message.metadata[0]; // Metadata data is a reply type - assert_eq!( - metadata.metadata_type, - MessageMetadataType::Reply, - "Metadata type is wrong" - ); + assert_eq!(metadata.key, "reply".as_bytes(), "Metadata type is wrong"); // Metadata data contains id to original message assert_eq!(