refactor(lot): rust memory management

This commit is contained in:
dignifiedquire
2019-08-17 15:47:35 +02:00
parent 8c10aa287c
commit 9ec7833a50
10 changed files with 290 additions and 309 deletions

View File

@@ -986,12 +986,13 @@ pub unsafe extern "C" fn dc_stop_ongoing_process(context: *mut dc_context_t) {
pub unsafe extern "C" fn dc_check_qr(
context: *mut dc_context_t,
qr: *mut libc::c_char,
) -> *mut dc_lot::dc_lot_t {
) -> *mut dc_lot_t {
assert!(!context.is_null());
assert!(!qr.is_null());
let context = &*context;
dc_qr::dc_check_qr(context, qr)
let lot = dc_qr::dc_check_qr(context, qr);
Box::into_raw(Box::new(lot))
}
#[no_mangle]
@@ -1264,13 +1265,14 @@ pub unsafe extern "C" fn dc_chatlist_get_summary<'a>(
chatlist: *mut dc_chatlist_t<'a>,
index: libc::size_t,
chat: *mut dc_chat_t<'a>,
) -> *mut dc_lot::dc_lot_t {
) -> *mut dc_lot_t {
assert!(!chatlist.is_null());
let chat = if chat.is_null() { None } else { Some(&*chat) };
let list = &*chatlist;
list.get_summary(index as usize, chat)
let lot = list.get_summary(index as usize, chat);
Box::into_raw(Box::new(lot))
}
#[no_mangle]
@@ -1542,11 +1544,12 @@ pub unsafe extern "C" fn dc_msg_get_showpadlock(msg: *mut dc_msg::dc_msg_t) -> l
pub unsafe extern "C" fn dc_msg_get_summary<'a>(
msg: *mut dc_msg::dc_msg_t<'a>,
chat: *mut dc_chat_t<'a>,
) -> *mut dc_lot::dc_lot_t {
) -> *mut dc_lot_t {
assert!(!msg.is_null());
let chat = if chat.is_null() { None } else { Some(&*chat) };
dc_msg::dc_msg_get_summary(msg, chat)
let lot = dc_msg::dc_msg_get_summary(msg, chat);
Box::into_raw(Box::new(lot))
}
#[no_mangle]
@@ -1789,67 +1792,74 @@ pub unsafe extern "C" fn dc_contact_is_verified(contact: *mut dc_contact_t) -> l
// dc_lot_t
#[no_mangle]
pub type dc_lot_t = dc_lot::dc_lot_t;
pub type dc_lot_t = dc_lot::Lot;
#[no_mangle]
pub unsafe extern "C" fn dc_lot_new() -> *mut dc_lot::dc_lot_t {
dc_lot::dc_lot_new()
pub unsafe extern "C" fn dc_lot_new() -> *mut dc_lot_t {
Box::into_raw(Box::new(dc_lot::Lot::new()))
}
#[no_mangle]
pub unsafe extern "C" fn dc_lot_empty(lot: *mut dc_lot::dc_lot_t) {
pub unsafe extern "C" fn dc_lot_empty(lot: *mut dc_lot_t) {
assert!(!lot.is_null());
dc_lot::dc_lot_empty(lot)
let _lot = Box::from_raw(lot);
*lot = dc_lot::Lot::new();
}
#[no_mangle]
pub unsafe extern "C" fn dc_lot_unref(lot: *mut dc_lot::dc_lot_t) {
pub unsafe extern "C" fn dc_lot_unref(lot: *mut dc_lot_t) {
assert!(!lot.is_null());
dc_lot::dc_lot_unref(lot)
Box::from_raw(lot);
}
#[no_mangle]
pub unsafe extern "C" fn dc_lot_get_text1(lot: *mut dc_lot::dc_lot_t) -> *mut libc::c_char {
pub unsafe extern "C" fn dc_lot_get_text1(lot: *mut dc_lot_t) -> *mut libc::c_char {
assert!(!lot.is_null());
dc_lot::dc_lot_get_text1(lot)
let lot = &*lot;
lot.get_text1()
}
#[no_mangle]
pub unsafe extern "C" fn dc_lot_get_text2(lot: *mut dc_lot::dc_lot_t) -> *mut libc::c_char {
pub unsafe extern "C" fn dc_lot_get_text2(lot: *mut dc_lot_t) -> *mut libc::c_char {
assert!(!lot.is_null());
dc_lot::dc_lot_get_text2(lot)
let lot = &*lot;
lot.get_text2()
}
#[no_mangle]
pub unsafe extern "C" fn dc_lot_get_text1_meaning(lot: *mut dc_lot::dc_lot_t) -> libc::c_int {
pub unsafe extern "C" fn dc_lot_get_text1_meaning(lot: *mut dc_lot_t) -> libc::c_int {
assert!(!lot.is_null());
dc_lot::dc_lot_get_text1_meaning(lot)
let lot = &*lot;
lot.get_text1_meaning()
}
#[no_mangle]
pub unsafe extern "C" fn dc_lot_get_state(lot: *mut dc_lot::dc_lot_t) -> libc::c_int {
pub unsafe extern "C" fn dc_lot_get_state(lot: *mut dc_lot_t) -> libc::c_int {
assert!(!lot.is_null());
dc_lot::dc_lot_get_state(lot)
let lot = &*lot;
lot.get_state()
}
#[no_mangle]
pub unsafe extern "C" fn dc_lot_get_id(lot: *mut dc_lot::dc_lot_t) -> u32 {
pub unsafe extern "C" fn dc_lot_get_id(lot: *mut dc_lot_t) -> u32 {
assert!(!lot.is_null());
dc_lot::dc_lot_get_id(lot)
let lot = &*lot;
lot.get_id()
}
#[no_mangle]
pub unsafe extern "C" fn dc_lot_get_timestamp(lot: *mut dc_lot::dc_lot_t) -> i64 {
pub unsafe extern "C" fn dc_lot_get_timestamp(lot: *mut dc_lot_t) -> i64 {
assert!(!lot.is_null());
dc_lot::dc_lot_get_timestamp(lot)
let lot = &*lot;
lot.get_timestamp()
}
#[no_mangle]

View File

@@ -12,7 +12,6 @@ use deltachat::dc_configure::*;
use deltachat::dc_imex::*;
use deltachat::dc_job::*;
use deltachat::dc_location::*;
use deltachat::dc_lot::*;
use deltachat::dc_msg::*;
use deltachat::dc_qr::*;
use deltachat::dc_receive_imf::*;
@@ -621,7 +620,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
let statestr = if chat.is_archived() {
" [Archived]"
} else {
match dc_lot_get_state(lot) {
match lot.get_state() {
20 => " o",
26 => "",
28 => " √√",
@@ -629,9 +628,9 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
_ => "",
}
};
let timestr = dc_timestamp_to_str(dc_lot_get_timestamp(lot));
let text1 = dc_lot_get_text1(lot);
let text2 = dc_lot_get_text2(lot);
let timestr = dc_timestamp_to_str(lot.get_timestamp());
let text1 = lot.get_text1();
let text2 = lot.get_text2();
info!(
context,
0,
@@ -649,7 +648,6 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
);
free(text1 as *mut libc::c_void);
free(text2 as *mut libc::c_void);
dc_lot_unref(lot);
info!(
context, 0,
"================================================================================"
@@ -1054,12 +1052,11 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
let res = dc_check_qr(context, arg1_c);
println!(
"state={}, id={}, text1={}, text2={}",
(*res).state as libc::c_int,
(*res).id,
to_string((*res).text1),
to_string((*res).text2)
res.get_state(),
res.get_id(),
to_string(res.get_text1()),
to_string(res.get_text2())
);
dc_lot_unref(res);
}
"event" => {
ensure!(!arg1.is_empty(), "Argument <id> missing.");

View File

@@ -16,7 +16,6 @@ use deltachat::dc_job::{
dc_perform_imap_fetch, dc_perform_imap_idle, dc_perform_imap_jobs, dc_perform_smtp_idle,
dc_perform_smtp_jobs,
};
use deltachat::dc_lot::*;
extern "C" fn cb(_ctx: &Context, event: Event, data1: usize, data2: usize) -> usize {
println!("[{:?}]", event);
@@ -104,8 +103,8 @@ fn main() {
for i in 0..chats.len() {
let summary = chats.get_summary(0, None);
let text1 = dc_lot_get_text1(summary);
let text2 = dc_lot_get_text2(summary);
let text1 = summary.get_text1();
let text2 = summary.get_text2();
let text1_s = if !text1.is_null() {
Some(CStr::from_ptr(text1))
@@ -118,7 +117,6 @@ fn main() {
None
};
println!("chat: {} - {:?} - {:?}", i, text1_s, text2_s,);
dc_lot_unref(summary);
}
thread::sleep(duration);

View File

@@ -2,7 +2,7 @@ use crate::chat::*;
use crate::constants::*;
use crate::contact::*;
use crate::context::*;
use crate::dc_lot::*;
use crate::dc_lot::Lot;
use crate::dc_msg::*;
use crate::dc_tools::*;
use crate::error::Result;
@@ -249,15 +249,15 @@ impl<'a> Chatlist<'a> {
/// - dc_lot_t::timestamp: the timestamp of the message. 0 if not applicable.
/// - dc_lot_t::state: The state of the message as one of the DC_STATE_* constants (see #dc_msg_get_state()).
// 0 if not applicable.
pub unsafe fn get_summary(&self, index: usize, chat: Option<&Chat<'a>>) -> *mut dc_lot_t {
pub unsafe fn get_summary(&self, index: usize, chat: Option<&Chat<'a>>) -> Lot {
// The summary is created by the chat, not by the last message.
// This is because we may want to display drafts here or stuff as
// "is typing".
// Also, sth. as "No messages" would not work if the summary comes from a message.
let mut ret = dc_lot_new();
let mut ret = Lot::new();
if index >= self.ids.len() {
(*ret).text2 = "ErrBadChatlistIndex".strdup();
ret.text2 = "ErrBadChatlistIndex".strdup();
return ret;
}
@@ -291,11 +291,11 @@ impl<'a> Chatlist<'a> {
};
if chat.id == DC_CHAT_ID_ARCHIVED_LINK as u32 {
(*ret).text2 = dc_strdup(ptr::null())
ret.text2 = dc_strdup(ptr::null())
} else if lastmsg.is_null() || (*lastmsg).from_id == DC_CONTACT_ID_UNDEFINED as u32 {
(*ret).text2 = self.context.stock_str(StockMessage::NoMessages).strdup();
ret.text2 = self.context.stock_str(StockMessage::NoMessages).strdup();
} else {
dc_lot_fill(ret, lastmsg, chat, lastcontact.as_ref(), self.context);
ret.fill(lastmsg, chat, lastcontact.as_ref(), self.context);
}
dc_msg_unref(lastmsg);

View File

@@ -6,7 +6,7 @@ use crate::contact::*;
use crate::dc_job::*;
use crate::dc_jobthread::*;
use crate::dc_loginparam::*;
use crate::dc_lot::dc_lot_t;
use crate::dc_lot::Lot;
use crate::dc_move::*;
use crate::dc_msg::*;
use crate::dc_receive_imf::*;
@@ -99,21 +99,11 @@ impl Default for RunningState {
}
}
#[derive(Debug, PartialEq, Eq)]
#[derive(Default)]
pub struct BobStatus {
pub expects: i32,
pub status: i32,
pub qr_scan: *mut dc_lot_t,
}
impl Default for BobStatus {
fn default() -> Self {
BobStatus {
expects: 0,
status: 0,
qr_scan: std::ptr::null_mut(),
}
}
pub qr_scan: Option<Lot>,
}
#[derive(Default, Debug)]

View File

@@ -5,174 +5,132 @@ use crate::context::Context;
use crate::dc_msg::*;
use crate::dc_tools::*;
use crate::stock::StockMessage;
use crate::types::*;
use crate::x::*;
/* * Structure behind dc_lot_t */
#[derive(Copy, Clone)]
#[repr(C)]
pub struct dc_lot_t {
pub text1_meaning: libc::c_int,
pub text1: *mut libc::c_char,
pub text2: *mut libc::c_char,
pub timestamp: i64,
pub state: libc::c_int,
pub id: uint32_t,
pub fingerprint: *mut libc::c_char,
pub invitenumber: *mut libc::c_char,
pub auth: *mut libc::c_char,
/// An object containing a set of values.
/// The meaning of the values is defined by the function returning the object.
/// Lot objects are created
/// eg. by chatlist.get_summary() or dc_msg_get_summary().
///
/// _Lot_ is used in the meaning _heap_ here.
#[derive(Clone)]
pub struct Lot {
pub(crate) text1_meaning: i32,
pub(crate) text1: *mut libc::c_char,
pub(crate) text2: *mut libc::c_char,
pub(crate) timestamp: i64,
pub(crate) state: i32,
pub(crate) id: u32,
pub(crate) fingerprint: *mut libc::c_char,
pub(crate) invitenumber: *mut libc::c_char,
pub(crate) auth: *mut libc::c_char,
}
/* *
* @class dc_lot_t
*
* An object containing a set of values.
* The meaning of the values is defined by the function returning the object.
* Lot objects are created
* eg. by chatlist.get_summary() or dc_msg_get_summary().
*
* NB: _Lot_ is used in the meaning _heap_ here.
*/
pub unsafe fn dc_lot_new() -> *mut dc_lot_t {
let mut lot: *mut dc_lot_t;
lot = calloc(1, ::std::mem::size_of::<dc_lot_t>()) as *mut dc_lot_t;
assert!(!lot.is_null());
(*lot).text1_meaning = 0i32;
lot
}
pub unsafe fn dc_lot_empty(mut lot: *mut dc_lot_t) {
if lot.is_null() {
return;
}
free((*lot).text1 as *mut libc::c_void);
(*lot).text1 = 0 as *mut libc::c_char;
(*lot).text1_meaning = 0i32;
free((*lot).text2 as *mut libc::c_void);
(*lot).text2 = 0 as *mut libc::c_char;
free((*lot).fingerprint as *mut libc::c_void);
(*lot).fingerprint = 0 as *mut libc::c_char;
free((*lot).invitenumber as *mut libc::c_void);
(*lot).invitenumber = 0 as *mut libc::c_char;
free((*lot).auth as *mut libc::c_void);
(*lot).auth = 0 as *mut libc::c_char;
(*lot).timestamp = 0;
(*lot).state = 0i32;
(*lot).id = 0i32 as uint32_t;
}
pub unsafe fn dc_lot_unref(set: *mut dc_lot_t) {
if set.is_null() {
return;
}
dc_lot_empty(set);
free(set as *mut libc::c_void);
}
pub unsafe fn dc_lot_get_text1(lot: *const dc_lot_t) -> *mut libc::c_char {
if lot.is_null() {
return 0 as *mut libc::c_char;
}
dc_strdup_keep_null((*lot).text1)
}
pub unsafe fn dc_lot_get_text2(lot: *const dc_lot_t) -> *mut libc::c_char {
if lot.is_null() {
return 0 as *mut libc::c_char;
}
dc_strdup_keep_null((*lot).text2)
}
pub unsafe fn dc_lot_get_text1_meaning(lot: *const dc_lot_t) -> libc::c_int {
if lot.is_null() {
return 0i32;
}
(*lot).text1_meaning
}
pub unsafe fn dc_lot_get_state(lot: *const dc_lot_t) -> libc::c_int {
if lot.is_null() {
return 0i32;
}
(*lot).state
}
pub unsafe fn dc_lot_get_id(lot: *const dc_lot_t) -> uint32_t {
if lot.is_null() {
return 0i32 as uint32_t;
}
(*lot).id
}
pub unsafe fn dc_lot_get_timestamp(lot: *const dc_lot_t) -> i64 {
if lot.is_null() {
return 0;
}
(*lot).timestamp
}
/* library-internal */
/* in practice, the user additionally cuts the string himself pixel-accurate */
pub unsafe fn dc_lot_fill(
mut lot: *mut dc_lot_t,
msg: *mut dc_msg_t,
chat: &Chat,
contact: Option<&Contact>,
context: &Context,
) {
if lot.is_null() || msg.is_null() {
return;
}
if (*msg).state == 19i32 {
(*lot).text1 = context.stock_str(StockMessage::Draft).strdup();
(*lot).text1_meaning = 1i32
} else if (*msg).from_id == 1i32 as libc::c_uint {
if 0 != dc_msg_is_info(msg) || chat.is_self_talk() {
(*lot).text1 = 0 as *mut libc::c_char;
(*lot).text1_meaning = 0i32
} else {
(*lot).text1 = context.stock_str(StockMessage::SelfMsg).strdup();
(*lot).text1_meaning = 3i32
impl Lot {
pub fn new() -> Self {
Lot {
text1_meaning: 0,
text1: std::ptr::null_mut(),
text2: std::ptr::null_mut(),
timestamp: 0,
state: 0,
id: 0,
fingerprint: std::ptr::null_mut(),
invitenumber: std::ptr::null_mut(),
auth: std::ptr::null_mut(),
}
} else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup {
if 0 != dc_msg_is_info(msg) || contact.is_none() {
(*lot).text1 = 0 as *mut libc::c_char;
(*lot).text1_meaning = 0i32
} else {
if chat.id == 1 {
if let Some(contact) = contact {
(*lot).text1 = contact.get_display_name().strdup();
} else {
(*lot).text1 = std::ptr::null_mut();
}
}
pub unsafe fn get_text1(&self) -> *mut libc::c_char {
dc_strdup_keep_null(self.text1)
}
pub unsafe fn get_text2(&self) -> *mut libc::c_char {
dc_strdup_keep_null(self.text2)
}
pub fn get_text1_meaning(&self) -> i32 {
self.text1_meaning
}
pub fn get_state(&self) -> i32 {
self.state
}
pub fn get_id(&self) -> u32 {
self.id
}
pub fn get_timestamp(&self) -> i64 {
self.timestamp
}
/* library-internal */
/* in practice, the user additionally cuts the string himself pixel-accurate */
pub unsafe fn fill(
&mut self,
msg: *mut dc_msg_t,
chat: &Chat,
contact: Option<&Contact>,
context: &Context,
) {
if msg.is_null() {
return;
}
if (*msg).state == 19i32 {
self.text1 = context.stock_str(StockMessage::Draft).strdup();
self.text1_meaning = 1i32
} else if (*msg).from_id == 1i32 as libc::c_uint {
if 0 != dc_msg_is_info(msg) || chat.is_self_talk() {
self.text1 = 0 as *mut libc::c_char;
self.text1_meaning = 0i32
} else {
if let Some(contact) = contact {
(*lot).text1 = contact.get_first_name().strdup();
} else {
(*lot).text1 = std::ptr::null_mut();
}
self.text1 = context.stock_str(StockMessage::SelfMsg).strdup();
self.text1_meaning = 3i32
}
(*lot).text1_meaning = 2i32;
} else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup {
if 0 != dc_msg_is_info(msg) || contact.is_none() {
self.text1 = 0 as *mut libc::c_char;
self.text1_meaning = 0i32
} else {
if chat.id == 1 {
if let Some(contact) = contact {
self.text1 = contact.get_display_name().strdup();
} else {
self.text1 = std::ptr::null_mut();
}
} else {
if let Some(contact) = contact {
self.text1 = contact.get_first_name().strdup();
} else {
self.text1 = std::ptr::null_mut();
}
}
self.text1_meaning = 2i32;
}
}
self.text2 = dc_msg_get_summarytext_by_raw(
(*msg).type_0,
(*msg).text.as_ref(),
&mut (*msg).param,
160,
context,
)
.strdup();
self.timestamp = dc_msg_get_timestamp(msg);
self.state = (*msg).state;
}
}
impl Drop for Lot {
fn drop(&mut self) {
unsafe {
free(self.text1.cast());
free(self.text2.cast());
free(self.fingerprint.cast());
free(self.invitenumber.cast());
free(self.auth.cast());
}
}
(*lot).text2 = dc_msg_get_summarytext_by_raw(
(*msg).type_0,
(*msg).text.as_ref(),
&mut (*msg).param,
160,
context,
)
.strdup();
(*lot).timestamp = dc_msg_get_timestamp(msg);
(*lot).state = (*msg).state;
}

View File

@@ -1,13 +1,15 @@
use std::ffi::CString;
use std::path::Path;
use std::ptr;
use phf::phf_map;
use crate::chat::{self, Chat};
use crate::constants::*;
use crate::contact::*;
use crate::context::*;
use crate::dc_job::*;
use crate::dc_lot::dc_lot_t;
use crate::dc_lot::*;
use crate::dc_lot::Lot;
use crate::dc_tools::*;
use crate::param::*;
use crate::pgp::*;
@@ -15,8 +17,6 @@ use crate::sql;
use crate::stock::StockMessage;
use crate::types::*;
use crate::x::*;
use phf::phf_map;
use std::ptr;
/* * the structure behind dc_msg_t */
#[derive(Clone)]
@@ -741,11 +741,8 @@ pub unsafe fn dc_msg_get_showpadlock(msg: *const dc_msg_t) -> libc::c_int {
0
}
pub unsafe fn dc_msg_get_summary<'a>(
msg: *mut dc_msg_t<'a>,
chat: Option<&Chat<'a>>,
) -> *mut dc_lot_t {
let ret = dc_lot_new();
pub unsafe fn dc_msg_get_summary<'a>(msg: *mut dc_msg_t<'a>, chat: Option<&Chat<'a>>) -> Lot {
let mut ret = Lot::new();
if msg.is_null() {
return ret;
@@ -771,7 +768,7 @@ pub unsafe fn dc_msg_get_summary<'a>(
None
};
dc_lot_fill(ret, msg, chat, contact.as_ref(), (*msg).context);
ret.fill(msg, chat, contact.as_ref(), (*msg).context);
ret
}

View File

@@ -4,7 +4,7 @@ use crate::chat;
use crate::constants::Blocked;
use crate::contact::*;
use crate::context::Context;
use crate::dc_lot::*;
use crate::dc_lot::Lot;
use crate::dc_strencode::*;
use crate::dc_tools::*;
use crate::key::*;
@@ -23,7 +23,7 @@ use crate::x::*;
// text1=text
// text1=URL
// text1=error string
pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc_lot_t {
pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> Lot {
let mut ok_to_continue = true;
let mut payload: *mut libc::c_char = 0 as *mut libc::c_char;
// must be normalized, if set
@@ -33,12 +33,12 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
let mut name: *mut libc::c_char = 0 as *mut libc::c_char;
let mut invitenumber: *mut libc::c_char = 0 as *mut libc::c_char;
let mut auth: *mut libc::c_char = 0 as *mut libc::c_char;
let mut qr_parsed: *mut dc_lot_t = dc_lot_new();
let mut qr_parsed = Lot::new();
let mut chat_id: uint32_t = 0i32 as uint32_t;
let mut device_msg = "".to_string();
let mut grpid: *mut libc::c_char = 0 as *mut libc::c_char;
let mut grpname: *mut libc::c_char = 0 as *mut libc::c_char;
(*qr_parsed).state = 0i32;
qr_parsed.state = 0i32;
if !qr.is_null() {
info!(context, 0, "Scanned QR code: {}", as_str(qr),);
/* split parameters from the qr code
@@ -136,8 +136,8 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
*semicolon = 0i32 as libc::c_char
}
} else {
(*qr_parsed).state = 400i32;
(*qr_parsed).text1 =
qr_parsed.state = 400i32;
qr_parsed.text1 =
dc_strdup(b"Bad e-mail address.\x00" as *const u8 as *const libc::c_char);
ok_to_continue = false;
}
@@ -201,16 +201,16 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
free(addr as *mut libc::c_void);
addr = temp;
if !may_be_valid_addr(as_str(addr)) {
(*qr_parsed).state = 400i32;
(*qr_parsed).text1 =
qr_parsed.state = 400i32;
qr_parsed.text1 =
dc_strdup(b"Bad e-mail address.\x00" as *const u8 as *const libc::c_char);
ok_to_continue = false;
}
}
}
if ok_to_continue && !fingerprint.is_null() && strlen(fingerprint) != 40 {
(*qr_parsed).state = 400i32;
(*qr_parsed).text1 = dc_strdup(
qr_parsed.state = 400i32;
qr_parsed.text1 = dc_strdup(
b"Bad fingerprint length in QR code.\x00" as *const u8 as *const libc::c_char,
);
ok_to_continue = false;
@@ -221,37 +221,37 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
Peerstate::from_fingerprint(context, &context.sql, as_str(fingerprint));
if addr.is_null() || invitenumber.is_null() || auth.is_null() {
if let Some(peerstate) = peerstate {
(*qr_parsed).state = 210i32;
qr_parsed.state = 210i32;
let addr = peerstate
.addr
.as_ref()
.map(|s| s.as_str())
.unwrap_or_else(|| "");
(*qr_parsed).id =
qr_parsed.id =
Contact::add_or_lookup(context, "", addr, Origin::UnhandledQrScan)
.map(|(id, _)| id)
.unwrap_or_default();
let (id, _) = chat::create_or_lookup_by_contact_id(
context,
(*qr_parsed).id,
qr_parsed.id,
Blocked::Deaddrop,
)
.unwrap_or_default();
chat_id = id;
device_msg = format!("{} verified.", peerstate.addr.unwrap_or_default());
} else {
(*qr_parsed).text1 = dc_format_fingerprint_c(fingerprint);
(*qr_parsed).state = 230i32;
qr_parsed.text1 = dc_format_fingerprint_c(fingerprint);
qr_parsed.state = 230i32;
}
} else {
if !grpid.is_null() && !grpname.is_null() {
(*qr_parsed).state = 202i32;
(*qr_parsed).text1 = dc_strdup(grpname);
(*qr_parsed).text2 = dc_strdup(grpid)
qr_parsed.state = 202i32;
qr_parsed.text1 = dc_strdup(grpname);
qr_parsed.text2 = dc_strdup(grpid)
} else {
(*qr_parsed).state = 200i32
qr_parsed.state = 200i32
}
(*qr_parsed).id = Contact::add_or_lookup(
qr_parsed.id = Contact::add_or_lookup(
context,
as_str(name),
as_str(addr),
@@ -259,13 +259,13 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
)
.map(|(id, _)| id)
.unwrap_or_default();
(*qr_parsed).fingerprint = dc_strdup(fingerprint);
(*qr_parsed).invitenumber = dc_strdup(invitenumber);
(*qr_parsed).auth = dc_strdup(auth)
qr_parsed.fingerprint = dc_strdup(fingerprint);
qr_parsed.invitenumber = dc_strdup(invitenumber);
qr_parsed.auth = dc_strdup(auth)
}
} else if !addr.is_null() {
(*qr_parsed).state = 320i32;
(*qr_parsed).id = Contact::add_or_lookup(
qr_parsed.state = 320i32;
qr_parsed.id = Contact::add_or_lookup(
context,
as_str(name),
as_str(addr),
@@ -278,11 +278,11 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
|| strstr(qr, b"https://\x00" as *const u8 as *const libc::c_char)
== qr as *mut libc::c_char
{
(*qr_parsed).state = 332i32;
(*qr_parsed).text1 = dc_strdup(qr)
qr_parsed.state = 332i32;
qr_parsed.text1 = dc_strdup(qr)
} else {
(*qr_parsed).state = 330i32;
(*qr_parsed).text1 = dc_strdup(qr)
qr_parsed.state = 330i32;
qr_parsed.text1 = dc_strdup(qr)
}
if !device_msg.is_empty() {
chat::add_device_msg(context, chat_id, device_msg);

View File

@@ -8,7 +8,6 @@ use crate::contact::*;
use crate::context::Context;
use crate::dc_configure::*;
use crate::dc_e2ee::*;
use crate::dc_lot::*;
use crate::dc_mimeparser::*;
use crate::dc_msg::*;
use crate::dc_qr::*;
@@ -137,17 +136,17 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
let ongoing_allocated: libc::c_int;
let mut contact_chat_id: uint32_t = 0i32 as uint32_t;
let mut join_vg: libc::c_int = 0i32;
let mut qr_scan: *mut dc_lot_t = 0 as *mut dc_lot_t;
info!(context, 0, "Requesting secure-join ...",);
dc_ensure_secret_key_exists(context).ok();
ongoing_allocated = dc_alloc_ongoing(context);
if !(ongoing_allocated == 0i32) {
qr_scan = dc_check_qr(context, qr);
if qr_scan.is_null() || (*qr_scan).state != 200i32 && (*qr_scan).state != 202i32 {
let qr_scan = dc_check_qr(context, qr);
if qr_scan.state != 200i32 && qr_scan.state != 202i32 {
error!(context, 0, "Unknown QR code.",);
} else {
contact_chat_id =
chat::create_by_contact_id(context, (*qr_scan).id).unwrap_or_default();
contact_chat_id = chat::create_by_contact_id(context, qr_scan.id).unwrap_or_default();
if contact_chat_id == 0i32 as libc::c_uint {
error!(context, 0, "Unknown contact.",);
} else if !(context
@@ -157,17 +156,26 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
.unwrap()
.shall_stop_ongoing)
{
join_vg = ((*qr_scan).state == 202i32) as libc::c_int;
join_vg = (qr_scan.state == 202i32) as libc::c_int;
{
let bob_a = context.bob.clone();
let mut bob = bob_a.write().unwrap();
let mut bob = context.bob.write().unwrap();
bob.status = 0;
bob.qr_scan = qr_scan;
bob.qr_scan = Some(qr_scan);
}
if 0 != fingerprint_equals_sender(context, (*qr_scan).fingerprint, contact_chat_id)
{
if 0 != fingerprint_equals_sender(
context,
context
.bob
.read()
.unwrap()
.qr_scan
.as_ref()
.unwrap()
.fingerprint,
contact_chat_id,
) {
info!(context, 0, "Taking protocol shortcut.");
context.bob.clone().write().unwrap().expects = 6;
context.bob.write().unwrap().expects = 6;
context.call_cb(
Event::SECUREJOIN_JOINER_PROGRESS,
chat_id_2_contact_id(context, contact_chat_id) as uintptr_t,
@@ -182,17 +190,17 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
} else {
b"vc-request-with-auth\x00" as *const u8 as *const libc::c_char
},
(*qr_scan).auth,
context.bob.read().unwrap().qr_scan.as_ref().unwrap().auth,
own_fingerprint,
if 0 != join_vg {
as_str((*qr_scan).text2)
as_str(context.bob.read().unwrap().qr_scan.as_ref().unwrap().text2)
} else {
""
},
);
free(own_fingerprint as *mut libc::c_void);
} else {
context.bob.clone().write().unwrap().expects = 2;
context.bob.write().unwrap().expects = 2;
send_handshake_msg(
context,
contact_chat_id,
@@ -201,7 +209,14 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
} else {
b"vc-request\x00" as *const u8 as *const libc::c_char
},
(*qr_scan).invitenumber,
context
.bob
.read()
.unwrap()
.qr_scan
.as_ref()
.unwrap()
.invitenumber,
0 as *const libc::c_char,
"",
);
@@ -220,15 +235,13 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
}
}
}
let bob_a = context.bob.clone();
let mut bob = bob_a.write().unwrap();
let mut bob = context.bob.write().unwrap();
bob.expects = 0;
if bob.status == 1 {
if 0 != join_vg {
ret_chat_id = chat::get_chat_id_by_grpid(
context,
to_string((*qr_scan).text2),
to_string(bob.qr_scan.as_ref().unwrap().text2),
None,
0 as *mut libc::c_int,
) as libc::c_int
@@ -236,9 +249,9 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
ret_chat_id = contact_chat_id as libc::c_int
}
}
bob.qr_scan = std::ptr::null_mut();
dc_lot_unref(qr_scan);
bob.qr_scan = None;
if 0 != ongoing_allocated {
dc_free_ongoing(context);
}
@@ -414,10 +427,9 @@ pub unsafe fn dc_handle_securejoin_handshake(
) == 0i32
{
let cond = {
let bob_a = context.bob.clone();
let bob = bob_a.read().unwrap();
let scan = bob.qr_scan;
scan.is_null() || bob.expects != 2 || 0 != join_vg && (*scan).state != 202
let bob = context.bob.read().unwrap();
let scan = bob.qr_scan.as_ref();
scan.is_none() || bob.expects != 2 || 0 != join_vg && scan.unwrap().state != 202
};
if cond {
@@ -426,11 +438,22 @@ pub unsafe fn dc_handle_securejoin_handshake(
current_block = 4378276786830486580;
} else {
{
let scan = context.bob.clone().read().unwrap().qr_scan;
scanned_fingerprint_of_alice = dc_strdup((*scan).fingerprint);
auth = dc_strdup((*scan).auth);
scanned_fingerprint_of_alice = dc_strdup(
context
.bob
.read()
.unwrap()
.qr_scan
.as_ref()
.unwrap()
.fingerprint,
);
auth =
dc_strdup(context.bob.read().unwrap().qr_scan.as_ref().unwrap().auth);
if 0 != join_vg {
grpid = to_string((*scan).text2);
grpid = to_string(
context.bob.read().unwrap().qr_scan.as_ref().unwrap().text2,
);
}
}
if !encrypted_and_signed(mimeparser, scanned_fingerprint_of_alice) {
@@ -468,7 +491,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
contact_id as uintptr_t,
400i32 as uintptr_t,
);
context.bob.clone().write().unwrap().expects = 6;
context.bob.write().unwrap().expects = 6;
send_handshake_msg(
context,
@@ -619,13 +642,14 @@ pub unsafe fn dc_handle_securejoin_handshake(
if 0 != join_vg {
ret = 0x1i32
}
if context.bob.clone().read().unwrap().expects != 6 {
if context.bob.read().unwrap().expects != 6 {
info!(context, 0, "Message belongs to a different handshake.",);
current_block = 4378276786830486580;
} else {
let cond = {
let scan = context.bob.clone().read().unwrap().qr_scan;
scan.is_null() || 0 != join_vg && (*scan).state != 202
let bob = context.bob.read().unwrap();
let scan = bob.qr_scan.as_ref();
scan.is_none() || 0 != join_vg && scan.unwrap().state != 202
};
if cond {
warn!(
@@ -635,10 +659,20 @@ pub unsafe fn dc_handle_securejoin_handshake(
current_block = 4378276786830486580;
} else {
{
let scan = context.bob.clone().read().unwrap().qr_scan;
scanned_fingerprint_of_alice = dc_strdup((*scan).fingerprint);
scanned_fingerprint_of_alice = dc_strdup(
context
.bob
.read()
.unwrap()
.qr_scan
.as_ref()
.unwrap()
.fingerprint,
);
if 0 != join_vg {
grpid = to_string((*scan).text2);
grpid = to_string(
context.bob.read().unwrap().qr_scan.as_ref().unwrap().text2,
);
}
}
let mut vg_expect_encrypted: libc::c_int = 1i32;
@@ -717,7 +751,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
4378276786830486580 => {}
_ => {
secure_connection_established(context, contact_chat_id);
context.bob.clone().write().unwrap().expects = 0;
context.bob.write().unwrap().expects = 0;
if 0 != join_vg {
send_handshake_msg(
context,
@@ -790,7 +824,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
}
unsafe fn end_bobs_joining(context: &Context, status: libc::c_int) {
context.bob.clone().write().unwrap().status = status;
context.bob.write().unwrap().status = status;
dc_stop_ongoing_process(context);
}

View File

@@ -13,7 +13,6 @@ use deltachat::contact::*;
use deltachat::context::*;
use deltachat::dc_configure::*;
use deltachat::dc_imex::*;
use deltachat::dc_lot::*;
use deltachat::dc_mimeparser::*;
use deltachat::dc_qr::*;
use deltachat::dc_securejoin::*;
@@ -455,20 +454,18 @@ unsafe fn stress_functions(context: &Context) {
3,
) == 0i32)
);
let mut res: *mut dc_lot_t = dc_check_qr(context, qr);
assert!(res.is_null());
assert!(!((*res).state == 200i32 || (*res).state == 220i32 || (*res).state == 230i32));
let mut res = dc_check_qr(context, qr);
assert!(
!(res.get_state() == 200i32 || res.get_state() == 220i32 || res.get_state() == 230i32)
);
dc_lot_unref(res);
free(qr as *mut libc::c_void);
res =
dc_check_qr(context,
b"BEGIN:VCARD\nVERSION:3.0\nN:Last;First\nEMAIL;TYPE=INTERNET:stress@test.local\nEND:VCARD\x00"
as *const u8 as *const libc::c_char);
assert!(res.is_null());
assert!(!((*res).state == 320i32));
assert!(!((*res).id != 0i32 as libc::c_uint));
dc_lot_unref(res);
assert!(!(res.get_state() == 320i32));
assert!(!(res.get_id() != 0i32 as libc::c_uint));
};
}