Remove context refrence from Contact struct

This will allow the Rust Context API to be refactored without breaking
the C API.  Full details in #476 aka
a0b5e32f98
This commit is contained in:
Floris Bruynooghe
2019-09-11 22:36:27 +02:00
committed by Floris Bruynooghe
parent 5ce27b16f1
commit aefddf7f5e
6 changed files with 58 additions and 65 deletions

View File

@@ -1217,19 +1217,18 @@ pub unsafe extern "C" fn dc_delete_contact(
}
#[no_mangle]
pub unsafe extern "C" fn dc_get_contact<'a>(
pub unsafe extern "C" fn dc_get_contact(
context: *mut dc_context_t,
contact_id: u32,
) -> *mut dc_contact_t<'a> {
) -> *mut dc_contact_t {
if context.is_null() {
eprintln!("ignoring careless call to dc_get_contact()");
return ptr::null_mut();
}
let context = &*context;
Contact::get_by_id(context, contact_id)
.map(|contact| Box::into_raw(Box::new(contact)))
.map(|contact| Box::into_raw(Box::new(ContactWrapper { context, contact })))
.unwrap_or_else(|_| std::ptr::null_mut())
}
@@ -2299,8 +2298,20 @@ pub unsafe extern "C" fn dc_msg_latefiling_mediasize(
// dc_contact_t
/// FFI struct for [dc_contact_t]
///
/// This is the structure behind [dc_contact_t] which is the opaque
/// structure representing a contact in the FFI API. It exists
/// because the FFI API has a refernce from the message to the
/// context, but the Rust API does not, so the FFI layer needs to glue
/// these together.
pub struct ContactWrapper {
context: *const dc_context_t,
contact: contact::Contact,
}
#[no_mangle]
pub type dc_contact_t<'a> = contact::Contact<'a>;
pub type dc_contact_t = ContactWrapper;
#[no_mangle]
pub unsafe extern "C" fn dc_contact_unref(contact: *mut dc_contact_t) {
@@ -2308,7 +2319,6 @@ pub unsafe extern "C" fn dc_contact_unref(contact: *mut dc_contact_t) {
eprintln!("ignoring careless call to dc_contact_unref()");
return;
}
Box::from_raw(contact);
}
@@ -2318,10 +2328,8 @@ pub unsafe extern "C" fn dc_contact_get_id(contact: *mut dc_contact_t) -> u32 {
eprintln!("ignoring careless call to dc_contact_get_id()");
return 0;
}
let contact = &*contact;
contact.get_id()
let ffi_contact = &*contact;
ffi_contact.contact.get_id()
}
#[no_mangle]
@@ -2330,10 +2338,8 @@ pub unsafe extern "C" fn dc_contact_get_addr(contact: *mut dc_contact_t) -> *mut
eprintln!("ignoring careless call to dc_contact_get_addr()");
return dc_strdup(ptr::null());
}
let contact = &*contact;
contact.get_addr().strdup()
let ffi_contact = &*contact;
ffi_contact.contact.get_addr().strdup()
}
#[no_mangle]
@@ -2342,10 +2348,8 @@ pub unsafe extern "C" fn dc_contact_get_name(contact: *mut dc_contact_t) -> *mut
eprintln!("ignoring careless call to dc_contact_get_name()");
return dc_strdup(ptr::null());
}
let contact = &*contact;
contact.get_name().strdup()
let ffi_contact = &*contact;
ffi_contact.contact.get_name().strdup()
}
#[no_mangle]
@@ -2356,10 +2360,8 @@ pub unsafe extern "C" fn dc_contact_get_display_name(
eprintln!("ignoring careless call to dc_contact_get_display_name()");
return dc_strdup(ptr::null());
}
let contact = &*contact;
contact.get_display_name().strdup()
let ffi_contact = &*contact;
ffi_contact.contact.get_display_name().strdup()
}
#[no_mangle]
@@ -2370,10 +2372,8 @@ pub unsafe extern "C" fn dc_contact_get_name_n_addr(
eprintln!("ignoring careless call to dc_contact_get_name_n_addr()");
return dc_strdup(ptr::null());
}
let contact = &*contact;
contact.get_name_n_addr().strdup()
let ffi_contact = &*contact;
ffi_contact.contact.get_name_n_addr().strdup()
}
#[no_mangle]
@@ -2384,10 +2384,8 @@ pub unsafe extern "C" fn dc_contact_get_first_name(
eprintln!("ignoring careless call to dc_contact_get_first_name()");
return dc_strdup(ptr::null());
}
let contact = &*contact;
contact.get_first_name().strdup()
let ffi_contact = &*contact;
ffi_contact.contact.get_first_name().strdup()
}
#[no_mangle]
@@ -2398,11 +2396,10 @@ pub unsafe extern "C" fn dc_contact_get_profile_image(
eprintln!("ignoring careless call to dc_contact_get_profile_image()");
return ptr::null_mut(); // NULL explicitly defined as "no profile image"
}
let contact = &*contact;
contact
.get_profile_image()
let ffi_contact = &*contact;
ffi_contact
.contact
.get_profile_image(&*ffi_contact.context)
.map(|p| p.to_str().unwrap().to_string().strdup())
.unwrap_or_else(|| std::ptr::null_mut())
}
@@ -2413,10 +2410,8 @@ pub unsafe extern "C" fn dc_contact_get_color(contact: *mut dc_contact_t) -> u32
eprintln!("ignoring careless call to dc_contact_get_color()");
return 0;
}
let contact = &*contact;
contact.get_color()
let ffi_contact = &*contact;
ffi_contact.contact.get_color()
}
#[no_mangle]
@@ -2425,10 +2420,8 @@ pub unsafe extern "C" fn dc_contact_is_blocked(contact: *mut dc_contact_t) -> li
eprintln!("ignoring careless call to dc_contact_is_blocked()");
return 0;
}
let contact = &*contact;
contact.is_blocked() as libc::c_int
let ffi_contact = &*contact;
ffi_contact.contact.is_blocked() as libc::c_int
}
#[no_mangle]
@@ -2437,10 +2430,8 @@ pub unsafe extern "C" fn dc_contact_is_verified(contact: *mut dc_contact_t) -> l
eprintln!("ignoring careless call to dc_contact_is_verified()");
return 0;
}
let contact = &*contact;
contact.is_verified() as libc::c_int
let ffi_contact = &*contact;
ffi_contact.contact.is_verified(&*ffi_contact.context) as libc::c_int
}
// dc_lot_t

View File

@@ -301,7 +301,7 @@ unsafe fn log_contactlist(context: &Context, contacts: &Vec<u32>) {
if let Ok(contact) = Contact::get_by_id(context, contact_id) {
let name = contact.get_name();
let addr = contact.get_addr();
let verified_state = contact.is_verified();
let verified_state = contact.is_verified(context);
let verified_str = if VerifiedStatus::Unverified != verified_state {
if verified_state == VerifiedStatus::BidirectVerified {
" √√"

View File

@@ -189,7 +189,7 @@ impl Chat {
let contacts = get_chat_contacts(context, self.id);
if !contacts.is_empty() {
if let Ok(contact) = Contact::get_by_id(context, contacts[0]) {
return contact.get_profile_image();
return contact.get_profile_image(context);
}
}
}
@@ -1365,7 +1365,7 @@ pub fn add_contact_to_chat_ex(
} else {
// else continue and send status mail
if chat.typ == Chattype::VerifiedGroup {
if contact.is_verified() != VerifiedStatus::BidirectVerified {
if contact.is_verified(context) != VerifiedStatus::BidirectVerified {
error!(
context,
"Only bidirectional verified contacts can be added to verified groups."

View File

@@ -31,8 +31,7 @@ const DC_ORIGIN_MIN_CONTACT_LIST: i32 = 0x100;
/// For this purpose, internally, two names are tracked -
/// authorized-name and given-name.
/// By default, these names are equal, but functions working with contact names
pub struct Contact<'a> {
context: &'a Context,
pub struct Contact {
/// The contact ID.
///
/// Special message IDs:
@@ -139,11 +138,10 @@ pub enum VerifiedStatus {
BidirectVerified = 2,
}
impl<'a> Contact<'a> {
pub fn load_from_db(context: &'a Context, contact_id: u32) -> Result<Self> {
impl Contact {
pub fn load_from_db(context: &Context, contact_id: u32) -> Result<Self> {
if contact_id == DC_CONTACT_ID_SELF {
let contact = Contact {
context,
id: contact_id,
name: context.stock_str(StockMessage::SelfMsg).into(),
authname: "".into(),
@@ -162,7 +160,6 @@ impl<'a> Contact<'a> {
params![contact_id as i32],
|row| {
let contact = Self {
context,
id: contact_id,
name: row.get::<_, String>(0)?,
authname: row.get::<_, String>(4)?,
@@ -181,7 +178,7 @@ impl<'a> Contact<'a> {
}
/// Check if a contact is blocked.
pub fn is_blocked_load(context: &'a Context, id: u32) -> bool {
pub fn is_blocked_load(context: &Context, id: u32) -> bool {
Self::load_from_db(context, id)
.map(|contact| contact.blocked)
.unwrap_or_default()
@@ -766,9 +763,9 @@ impl<'a> Contact<'a> {
/// Get the contact's profile image.
/// This is the image set by each remote user on their own
/// using dc_set_config(context, "selfavatar", image).
pub fn get_profile_image(&self) -> Option<PathBuf> {
pub fn get_profile_image(&self, context: &Context) -> Option<PathBuf> {
if self.id == DC_CONTACT_ID_SELF {
if let Some(p) = self.context.get_config(Config::Selfavatar) {
if let Some(p) = context.get_config(Config::Selfavatar) {
return Some(PathBuf::from(p));
}
}
@@ -789,14 +786,18 @@ impl<'a> Contact<'a> {
///
/// The UI may draw a checkbox or something like that beside verified contacts.
///
pub fn is_verified(&self) -> VerifiedStatus {
self.is_verified_ex(None)
pub fn is_verified(&self, context: &Context) -> VerifiedStatus {
self.is_verified_ex(context, None)
}
/// Same as `Contact::is_verified` but allows speeding up things
/// by adding the peerstate belonging to the contact.
/// If you do not have the peerstate available, it is loaded automatically.
pub fn is_verified_ex(&self, peerstate: Option<&Peerstate<'a>>) -> VerifiedStatus {
pub fn is_verified_ex(
&self,
context: &Context,
peerstate: Option<&Peerstate>,
) -> VerifiedStatus {
// We're always sort of secured-verified as we could verify the key on this device any time with the key
// on this device
if self.id == DC_CONTACT_ID_SELF {
@@ -809,7 +810,7 @@ impl<'a> Contact<'a> {
}
}
let peerstate = Peerstate::from_addr(self.context, &self.context.sql, &self.addr);
let peerstate = Peerstate::from_addr(context, &context.sql, &self.addr);
if let Some(ps) = peerstate {
if ps.verified_key().is_some() {
return VerifiedStatus::BidirectVerified;

View File

@@ -1760,7 +1760,8 @@ unsafe fn check_verified_properties(
let peerstate = Peerstate::from_addr(context, &context.sql, contact.get_addr());
if peerstate.is_none()
|| contact.is_verified_ex(peerstate.as_ref()) != VerifiedStatus::BidirectVerified
|| contact.is_verified_ex(context, peerstate.as_ref())
!= VerifiedStatus::BidirectVerified
{
verify_fail("The sender of this message is not verified.".into());
return 0;

View File

@@ -617,7 +617,7 @@ pub fn handle_securejoin_handshake(
==== Step 8 in "Out-of-band verified groups" protocol ====
============================================================ */
if let Ok(contact) = Contact::get_by_id(context, contact_id) {
if contact.is_verified() == VerifiedStatus::Unverified {
if contact.is_verified(context) == VerifiedStatus::Unverified {
warn!(context, "vg-member-added-received invalid.",);
return ret;
}