1
0
Fork 0
mirror of https://github.com/deltachat/deltachat-core.git synced 2025-10-06 03:50:08 +02:00

Prepare thread for message fetching.

This commit is contained in:
B. Petersen 2016-07-18 00:23:31 +02:00
parent 9c4e1000ef
commit 6d5b5983e7
7 changed files with 178 additions and 76 deletions

View file

@ -87,6 +87,7 @@ int main(int argc, char ** argv)
printf("get <key> show configuration value\n");
printf("connect connect to mailbox server\n");
printf("disconnect disconnect from mailbox server\n");
printf("fetch fetch messages\n");
printf("info show database information\n");
printf("exit exit program\n");
}
@ -117,12 +118,20 @@ int main(int argc, char ** argv)
}
else if( strcmp(cmd, "connect")==0 )
{
mailbox->Connect();
if( !mailbox->Connect() ) {
print_error();
}
}
else if( strcmp(cmd, "disconnect")==0 )
{
mailbox->Disconnect();
}
else if( strcmp(cmd, "fetch")==0 )
{
if( !mailbox->Fetch() ) {
print_error();
}
}
else if( strncmp(cmd, "set", 3)==0 )
{
char* arg1 = (char*)strstr(cmd, " ");

View file

@ -23,6 +23,11 @@
* Authors: Björn Petersen
* Purpose: Reading from IMAP servers, see header for details.
*
*******************************************************************************
*
* TODO: On Android, I think, the thread must be marked using
* AttachCurrentThread(), see MailCore2 code
*
******************************************************************************/
@ -47,6 +52,7 @@ static bool is_error(int r, const char* msg)
return true;
}
static char * get_msg_att_msg_content(struct mailimap_msg_att * msg_att, size_t * p_msg_size)
{
clistiter * cur;
@ -182,6 +188,11 @@ static void fetch_messages(struct mailimap * imap)
clistiter * cur;
int r;
r = mailimap_select(imap, "INBOX");
if( is_error(r, "could not select INBOX") ) {
return;
}
/* as improvement UIDVALIDITY should be read and the message cache should be cleaned
if the UIDVALIDITY is not the same */
@ -211,52 +222,127 @@ static void fetch_messages(struct mailimap * imap)
mailimap_fetch_list_free(fetch_result);
}
/*******************************************************************************
* The working thread
******************************************************************************/
void MrImap::WorkingThread()
{
// connect to server
struct mailimap* imap;
int r;
imap = mailimap_new(0, NULL);
r = mailimap_ssl_connect(imap, m_loginParam->m_mail_server, m_loginParam->m_mail_port);
if( is_error(r, "could not connect to server") ) {
goto WorkingThread_Exit;
}
r = mailimap_login(imap, m_loginParam->m_mail_user, m_loginParam->m_mail_pw);
if( is_error(r, "could not login") ) {
goto WorkingThread_Exit;
}
// endless look
while( 1 )
{
// wait for condition
pthread_mutex_lock(&m_condmutex);
pthread_cond_wait(&m_cond, &m_condmutex); // wait unlocks the mutex and waits for signal, if it returns, the mutex is locked again
int dowhat = m_dowhat;
pthread_mutex_unlock(&m_condmutex);
switch( dowhat )
{
case DO_FETCH:
fetch_messages(imap);
break;
case DO_EXIT:
goto WorkingThread_Exit;
}
}
WorkingThread_Exit:
if( imap ) {
mailimap_logout(imap);
mailimap_free(imap);
imap = NULL;
}
m_threadRunning = false;
}
/*******************************************************************************
* Connect/disconnect by start/stop the working thread
******************************************************************************/
MrImap::MrImap(MrMailbox* mailbox)
{
m_mailbox = mailbox;
m_mailbox = mailbox;
m_threadRunning = false;
m_loginParam = NULL;
pthread_mutex_init(&m_condmutex, NULL);
pthread_cond_init(&m_cond, NULL);
}
MrImap::~MrImap()
{
Disconnect();
pthread_cond_destroy(&m_cond);
pthread_mutex_destroy(&m_condmutex);
}
bool MrImap::Connect(const MrLoginParam* param)
{
struct mailimap * imap;
int r;
if( param->m_mail_server == NULL || param->m_mail_user == NULL || param->m_mail_pw == NULL ) {
return false;
if( param==NULL || param->m_mail_server==NULL || param->m_mail_user==NULL || param->m_mail_pw==NULL ) {
return false; // error, bad parameters
}
imap = mailimap_new(0, NULL);
r = mailimap_ssl_connect(imap, param->m_mail_server, param->m_mail_port);
if( is_error(r, "could not connect to server") ) {
return false;
if( m_threadRunning ) {
return true; // already trying to connect
}
r = mailimap_login(imap, param->m_mail_user, param->m_mail_pw);
if( is_error(r, "could not login") ) {
return false;
}
r = mailimap_select(imap, "INBOX");
if( is_error(r, "could not select INBOX") ) {
return false;
}
fetch_messages(imap);
mailimap_logout(imap);
mailimap_free(imap);
m_loginParam = param;
m_threadRunning = true;
pthread_create(&m_thread, NULL, (void * (*)(void *)) MrImap::StartupHelper, this);
// success, so far, the real connection takes place in the working thread
return true;
}
void MrImap::Disconnect()
{
if( !m_threadRunning ) {
return; // already disconnected
}
pthread_mutex_lock(&m_condmutex);
m_dowhat = DO_EXIT;
pthread_mutex_unlock(&m_condmutex);
pthread_cond_signal(&m_cond);
}
bool MrImap::Fetch()
{
if( !m_threadRunning ) {
return false; // not connected
}
pthread_mutex_lock(&m_condmutex);
m_dowhat = DO_FETCH;
pthread_mutex_unlock(&m_condmutex);
pthread_cond_signal(&m_cond);
// success, so far
return true;
}

View file

@ -37,13 +37,29 @@ class MrMailbox;
class MrImap
{
public:
MrImap (MrMailbox* mailbox);
~MrImap ();
bool Connect (const MrLoginParam*);
void Disconnect ();
MrImap (MrMailbox* mailbox);
~MrImap ();
bool IsConnected () { return m_threadRunning; }
bool Connect (const MrLoginParam*);
void Disconnect ();
bool Fetch ();
private:
MrMailbox* m_mailbox;
MrMailbox* m_mailbox;
const MrLoginParam* m_loginParam;
pthread_t m_thread;
bool m_threadRunning;
pthread_cond_t m_cond;
pthread_mutex_t m_condmutex;
#define DO_FETCH 1
#define DO_EXIT 2
int m_dowhat;
static void StartupHelper (MrImap* imap) { imap->WorkingThread(); }
void WorkingThread ();
};

View file

@ -32,10 +32,8 @@
#include "mrloginparam.h"
MrLoginParam::MrLoginParam(MrMailbox* mailbox)
MrLoginParam::MrLoginParam()
{
m_mailbox = mailbox;
// init pointers (this cannot be done by Clear() as this function checks against NULL pointers)
m_email = NULL;
@ -75,24 +73,6 @@ void MrLoginParam::Clear()
}
void MrLoginParam::ReadFromSql()
{
Clear();
m_email = m_mailbox->GetConfig ("email", NULL);
m_mail_server = m_mailbox->GetConfig ("mail_server", NULL);
m_mail_port = m_mailbox->GetConfigInt("mail_port", 0);
m_mail_user = m_mailbox->GetConfig ("mail_user", NULL);
m_mail_pw = m_mailbox->GetConfig ("mail_pw", NULL);
m_send_server = m_mailbox->GetConfig ("send_server", NULL);
m_send_port = m_mailbox->GetConfigInt("send_port", 0);
m_send_user = m_mailbox->GetConfig ("send_user", NULL);
m_send_pw = m_mailbox->GetConfig ("send_pw", NULL);
}
void MrLoginParam::Complete()
{
if( m_email == NULL ) {

View file

@ -36,15 +36,12 @@ class MrMailbox;
class MrLoginParam
{
public:
MrLoginParam (MrMailbox* mailbox);
MrLoginParam ();
~MrLoginParam ();
// clears all data and frees its memory. All pointers are NULL after this function is called.
void Clear ();
// read all data from database, unset values are still NULL after calling ReadFromSql()
void ReadFromSql ();
// tries to set missing parameters from at least m_email and m_mail_pw
void Complete ();
@ -60,9 +57,6 @@ public:
char* m_send_user;
char* m_send_pw;
uint16_t m_send_port;
private:
MrMailbox* m_mailbox;
};

View file

@ -63,18 +63,6 @@ bool MrMailbox::Open(const char* dbfile)
}
}
// test LibEtPan
#if 0
struct mailimf_mailbox * mb;
char * display_name;
char * address;
display_name = strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?=");
address = strdup("dinh.viet.hoa@free.fr");
mb = mailimf_mailbox_new(display_name, address); // mailimf_mailbox_new() takes ownership of the given strings!
mailimf_mailbox_free(mb);
#endif
// success
return true;
@ -98,15 +86,36 @@ void MrMailbox::Close()
******************************************************************************/
void MrMailbox::Connect()
bool MrMailbox::Connect()
{
MrLoginParam param(this);
if( m_imap.IsConnected() ) {
return true;
}
param.ReadFromSql();
// read parameter, unset parameters are still NULL afterwards
{
MrSqlite3Locker locker(m_sql);
param.Complete();
m_loginParam.Clear();
m_imap.Connect(&param);
m_loginParam.m_email = m_sql.GetConfig ("email", NULL);
m_loginParam.m_mail_server = m_sql.GetConfig ("mail_server", NULL);
m_loginParam.m_mail_port = m_sql.GetConfigInt("mail_port", 0);
m_loginParam.m_mail_user = m_sql.GetConfig ("mail_user", NULL);
m_loginParam.m_mail_pw = m_sql.GetConfig ("mail_pw", NULL);
m_loginParam.m_send_server = m_sql.GetConfig ("send_server", NULL);
m_loginParam.m_send_port = m_sql.GetConfigInt("send_port", 0);
m_loginParam.m_send_user = m_sql.GetConfig ("send_user", NULL);
m_loginParam.m_send_pw = m_sql.GetConfig ("send_pw", NULL);
}
// try to suggest unset parameters
m_loginParam.Complete();
// connect
return m_imap.Connect(&m_loginParam);
}
@ -116,6 +125,12 @@ void MrMailbox::Disconnect()
}
bool MrMailbox::Fetch()
{
return m_imap.Fetch();
}
/*******************************************************************************
* Handle contacts
******************************************************************************/

View file

@ -59,8 +59,9 @@ public:
void Close ();
// connect to the mailbox: error are be received asynchronously.
void Connect ();
bool Connect ();
void Disconnect ();
bool Fetch ();
// iterate contacts
size_t GetContactCnt () { MrSqlite3Locker l(m_sql); return m_sql.GetContactCnt(); }
@ -82,6 +83,7 @@ public:
private:
// private stuff
MrSqlite3 m_sql;
MrLoginParam m_loginParam;
MrImap m_imap;
friend class MrImap;
};