From f1c0e232f534fd44e180baad97faa4ff2f242f10 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Sun, 6 Jan 2019 01:16:15 +0000 Subject: [PATCH] Run SMTP and IMAP in their own threads --- delta-connection.c | 72 ++++++++++++++++++++++++++++++++++++++++------ delta-connection.h | 10 +++++-- libdelta.c | 4 +-- libdelta.h | 4 --- 4 files changed, 74 insertions(+), 16 deletions(-) diff --git a/delta-connection.c b/delta-connection.c index 57c25ec..8babd8c 100644 --- a/delta-connection.c +++ b/delta-connection.c @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -13,6 +14,38 @@ void delta_recv_im(DeltaConnectionData *conn, uint32_t msg_id); +void *imap_thread_func(void *delta_connection_data) +{ + DeltaConnectionData *conn = (DeltaConnectionData *)delta_connection_data; + g_assert(conn != NULL); + + dc_context_t *mailbox = conn->mailbox; + g_assert(mailbox != NULL); + + while (conn->runthreads) { + dc_perform_imap_jobs(mailbox); + dc_perform_imap_fetch(mailbox); + dc_perform_imap_idle(mailbox); + } + + return NULL; +} +void *smtp_thread_func(void *delta_connection_data) +{ + DeltaConnectionData *conn = (DeltaConnectionData *)delta_connection_data; + g_assert(conn != NULL); + + dc_context_t *mailbox = conn->mailbox; + g_assert(mailbox != NULL); + + while (conn->runthreads) { + dc_perform_smtp_jobs(mailbox); + dc_perform_smtp_idle(mailbox); + } + + return NULL; +} + void _transpose_config(dc_context_t *mailbox, PurpleAccount *acct) { @@ -22,12 +55,12 @@ _transpose_config(dc_context_t *mailbox, PurpleAccount *acct) const char *imap_host = purple_account_get_string(acct, PLUGIN_ACCOUNT_OPT_IMAP_SERVER_HOST, NULL); const char *imap_user = purple_account_get_string(acct, PLUGIN_ACCOUNT_OPT_IMAP_USER, NULL); const char *imap_pass = purple_account_get_password(acct); - const char *imap_port = purple_account_get_string(acct, PLUGIN_ACCOUNT_OPT_IMAP_SERVER_PORT, DEFAULT_IMAP_PORT); + const char *imap_port = purple_account_get_string(acct, PLUGIN_ACCOUNT_OPT_IMAP_SERVER_PORT, NULL); const char *smtp_host = purple_account_get_string(acct, PLUGIN_ACCOUNT_OPT_SMTP_SERVER_HOST, NULL); const char *smtp_user = purple_account_get_string(acct, PLUGIN_ACCOUNT_OPT_SMTP_USER, NULL); const char *smtp_pass = purple_account_get_string(acct, PLUGIN_ACCOUNT_OPT_SMTP_PASS, NULL); - const char *smtp_port = purple_account_get_string(acct, PLUGIN_ACCOUNT_OPT_SMTP_SERVER_PORT, DEFAULT_SMTP_PORT); + const char *smtp_port = purple_account_get_string(acct, PLUGIN_ACCOUNT_OPT_SMTP_SERVER_PORT, NULL); dc_set_config(mailbox, PLUGIN_ACCOUNT_OPT_ADDR, addr); dc_set_config(mailbox, PLUGIN_ACCOUNT_OPT_DISPLAY_NAME, display); @@ -174,6 +207,9 @@ my_delta_handler(dc_context_t* mailbox, int event, uintptr_t data1, uintptr_t da printf("my_delta_handler(mailbox, %d, %lu, %lu)\n", event, data1, data2); switch (event) { + case DC_EVENT_SMTP_MESSAGE_SENT: + case DC_EVENT_IMAP_CONNECTED: + case DC_EVENT_SMTP_CONNECTED: case DC_EVENT_INFO: printf("INFO: %s\n", (char *)data2); break; @@ -181,6 +217,7 @@ my_delta_handler(dc_context_t* mailbox, int event, uintptr_t data1, uintptr_t da printf("WARNING: %s\n", (char *)data2); break; case DC_EVENT_ERROR: + case DC_EVENT_ERROR_NETWORK: printf("ERROR: %d: %s\n", (int)data1, (char *)data2); break; @@ -209,6 +246,9 @@ my_delta_handler(dc_context_t* mailbox, int event, uintptr_t data1, uintptr_t da case DC_EVENT_CONFIGURE_PROGRESS: purple_connection_update_progress(conn->pc, "Connecting...", (int)data1, MAX_DELTA_CONFIGURE); + if ((int)data1 == MAX_DELTA_CONFIGURE) { + purple_connection_set_state(conn->pc, PURPLE_CONNECTED); + } break; case DC_EVENT_HTTP_GET: printf("HTTP GET requested: %s\n", (char *)data1); @@ -250,14 +290,26 @@ delta_connection_free(PurpleConnection *pc) g_assert(conn != NULL); - purple_connection_set_protocol_data(pc, NULL); - + conn->runthreads = 0; + if (conn->mailbox != NULL) { + dc_maybe_network(conn->mailbox); + + // TODO: correctly handle join failing + if (pthread_join(conn->imap_thread, NULL) != 0) { + debug("joining imap thread failed!\n"); + } + if (pthread_join(conn->smtp_thread, NULL) != 0) { + debug("joining smtp thread failed!\n"); + } + dc_stop_ongoing_process(conn->mailbox); dc_close(conn->mailbox); dc_context_unref(conn->mailbox); } + purple_connection_set_protocol_data(pc, NULL); + // TODO: free resources as they are added to DeltaConnectionData conn->pc = NULL; conn->mailbox = NULL; @@ -283,18 +335,22 @@ delta_connection_start_login(PurpleConnection *pc) } conn->mailbox = mailbox; - _transpose_config(mailbox, acct); + conn->runthreads = 1; + pthread_create(&conn->imap_thread, NULL, imap_thread_func, conn); + pthread_create(&conn->smtp_thread, NULL, smtp_thread_func, conn); + purple_connection_set_state(pc, PURPLE_CONNECTING); purple_connection_update_progress(pc, "Connecting...", 1, MAX_DELTA_CONFIGURE); - if (!dc_is_configured(mailbox)) { + if (dc_is_configured(mailbox)) { + purple_connection_set_state(conn->pc, PURPLE_CONNECTED); + } else { dc_configure(mailbox); } -// FIXME: ensure this is set by the connection handler -// purple_connection_set_state(pc, PURPLE_CONNECTED); + dc_maybe_network(mailbox); return; } diff --git a/delta-connection.h b/delta-connection.h index d317004..8feb698 100644 --- a/delta-connection.h +++ b/delta-connection.h @@ -3,16 +3,22 @@ #include #include +#include struct _PurpleConnection; -//struct _dc_context_t; typedef struct _DeltaConnectionData { struct _PurpleConnection *pc; dc_context_t *mailbox; + + // Set to 0 to convince threads to exit + int runthreads; + + pthread_t imap_thread; + pthread_t smtp_thread; } DeltaConnectionData; -#define MAX_DELTA_CONFIGURE 901 +#define MAX_DELTA_CONFIGURE 1000 void delta_connection_new(struct _PurpleConnection *pc); void delta_connection_free(struct _PurpleConnection *pc); diff --git a/libdelta.c b/libdelta.c index ad57bb9..787472f 100644 --- a/libdelta.c +++ b/libdelta.c @@ -83,7 +83,7 @@ delta_init_plugin(PurplePlugin *plugin) opts = g_list_prepend(opts, str_opt("Display Name", PLUGIN_ACCOUNT_OPT_DISPLAY_NAME, NULL)); opts = g_list_prepend(opts, str_opt("IMAP Server Host", PLUGIN_ACCOUNT_OPT_IMAP_SERVER_HOST, NULL)); - opts = g_list_prepend(opts, str_opt("IMAP Server Port", PLUGIN_ACCOUNT_OPT_IMAP_SERVER_PORT, DEFAULT_IMAP_PORT)); + opts = g_list_prepend(opts, str_opt("IMAP Server Port", PLUGIN_ACCOUNT_OPT_IMAP_SERVER_PORT, NULL)); opts = g_list_prepend(opts, str_opt("IMAP Username", PLUGIN_ACCOUNT_OPT_IMAP_USER, NULL)); @@ -93,7 +93,7 @@ delta_init_plugin(PurplePlugin *plugin) // opts = g_list_prepend(opts, pwd_opt("IMAP Password", PLUGIN_ACCOUNT_OPT_IMAP_PASS, "")); opts = g_list_prepend(opts, str_opt("SMTP Server Host", PLUGIN_ACCOUNT_OPT_SMTP_SERVER_HOST, NULL)); - opts = g_list_prepend(opts, str_opt("SMTP Server Port", PLUGIN_ACCOUNT_OPT_SMTP_SERVER_PORT, DEFAULT_SMTP_PORT)); + opts = g_list_prepend(opts, str_opt("SMTP Server Port", PLUGIN_ACCOUNT_OPT_SMTP_SERVER_PORT, NULL)); opts = g_list_prepend(opts, str_opt("SMTP Username", PLUGIN_ACCOUNT_OPT_SMTP_USER, NULL)); opts = g_list_prepend(opts, pwd_opt("SMTP Password", PLUGIN_ACCOUNT_OPT_SMTP_PASS, NULL)); diff --git a/libdelta.h b/libdelta.h index ec7015e..1caba51 100644 --- a/libdelta.h +++ b/libdelta.h @@ -10,10 +10,6 @@ OPT_PROTO_CHAT_TOPIC | \ OPT_PROTO_IM_IMAGE -#define DEFAULT_SMTP_PORT "0" -#define DEFAULT_IMAP_PORT "0" - - // These two will instead be the pidgin "username" and "password" options that // I can't seem to get rid of. #define PLUGIN_ACCOUNT_OPT_ADDR "addr"