Further pop_mx_ng work
[apps/madmutt.git] / lib-mx / pop-new.c
index 3936cbb..4978f8f 100644 (file)
 
 #include <lib-sys/evtloop.h>
 #include "pop.h"
 
 #include <lib-sys/evtloop.h>
 #include "pop.h"
+#include "account.h"
+
+#define POP3_PORT         110
+#define POP3S_PORT        995
+
+enum pop_state {
+    POP_NEW,
+    POP_READY,
+};
 
 typedef struct pop_data_t {
     int refcnt;
 
 typedef struct pop_data_t {
     int refcnt;
-    job_t *w;
+    enum pop_state state;
+
+    volatile job_t *w;
+
+    ACCOUNT act;
 } pop_data_t;
 } pop_data_t;
-DO_INIT(pop_data_t, pop_data);
-DO_WIPE(pop_data_t, pop_data);
-DO_REFCNT(pop_data_t, pop_data);
+static void pop_data_delete(pop_data_t **tp);
 DO_ARRAY_TYPE(pop_data_t, pop_data);
 DO_ARRAY_FUNCS(pop_data_t, pop_data, pop_data_delete);
 
 DO_ARRAY_TYPE(pop_data_t, pop_data);
 DO_ARRAY_FUNCS(pop_data_t, pop_data, pop_data_delete);
 
@@ -38,6 +49,41 @@ DO_ARRAY_FUNCS(pop_data_t, pop_data, pop_data_delete);
 
 static pop_data_array conns;
 
 
 static pop_data_array conns;
 
+static inline pop_data_t *pop_data_new(void)
+{
+    pop_data_t *res = p_new(pop_data_t, 1);
+    res->refcnt = 1;
+    pop_data_array_append(&conns, res);
+    return res;
+}
+static inline pop_data_t *pop_data_dup(pop_data_t *t)
+{
+    t->refcnt++;
+    return t;
+}
+static void pop_data_wipe(pop_data_t *pd)
+{
+    if (pd->w)
+        IGNORE(el_job_release((job_t *)pd->w, EL_KILLED));
+}
+static void pop_data_delete(pop_data_t **tp)
+{
+    if (!*tp)
+        return;
+    if (--(*tp)->refcnt > 0) {
+        *tp = NULL;
+    } else {
+        for (int i = 0; i < conns.len; i++) {
+            if (conns.arr[i] == *tp) {
+                pop_data_array_take(&conns, i);
+                break;
+            }
+        }
+        pop_data_wipe(*tp);
+        p_delete(tp);
+    }
+}
+
 static __init void pop_initialize(void)
 {
     pop_data_array_init(&conns);
 static __init void pop_initialize(void)
 {
     pop_data_array_init(&conns);
@@ -53,11 +99,14 @@ static __fini void pop_shutdown(void)
 
 static int pop_setup(job_t *w, void *cfg)
 {
 
 static int pop_setup(job_t *w, void *cfg)
 {
+    w->ptr = pop_data_dup(cfg);
+    /* FIXME */ return el_job_release(w, EL_ERROR);
     return 0;
 }
 
 static void pop_finalize(job_t *w, el_status reason)
 {
     return 0;
 }
 
 static void pop_finalize(job_t *w, el_status reason)
 {
+    pop_data_delete((pop_data_t **)(void *)&w->ptr);
 }
 
 static machine_t const pop_machine = {
 }
 
 static machine_t const pop_machine = {
@@ -70,18 +119,85 @@ static machine_t const pop_machine = {
 /* pop3 mx driver                                                           */
 /****************************************************************************/
 
 /* pop3 mx driver                                                           */
 /****************************************************************************/
 
+static int pop_parse_path(const char *path, ACCOUNT *act)
+{
+    ciss_url_t url;
+    char s[BUFSIZ];
+
+    /* Defaults */
+    act->flags = 0;
+    act->port  = POP3_PORT;
+    act->type  = M_ACCT_TYPE_POP;
+    m_strcpy(s, sizeof(s), path);
+    url_parse_ciss(&url, s);
+
+    if (url.scheme == U_POP || url.scheme == U_POPS) {
+        if (url.scheme == U_POPS) {
+            act->has_ssl = 1;
+            act->port    = POP3S_PORT;
+        }
+
+        if (m_strisempty(url.path) && !mutt_account_fromurl(act, &url))
+            return 0;
+    }
+
+    return -1;
+}
+
+static pop_data_t *pop_find_conn(ACCOUNT *act)
+{
+    pop_data_t *pd = NULL;
+
+    el_lock();
+    for (int i = 0; i < conns.len; i++) {
+        if (mutt_account_match(act, &conns.arr[i]->act)) {
+            pd = pop_data_dup(conns.arr[i]);
+            break;
+        }
+    }
+    if (!pd) {
+        pd = pop_data_new();
+        pd->act = *act;
+    }
+    if (!pd->w) {
+        pd->w = el_job_start(&pop_machine, pd);
+    }
+    while (pd->w && pd->state != POP_READY) {
+        el_wait(pd->w);
+    }
+    if (!pd->w)
+        pop_data_delete(&pd);
+
+    el_unlock();
+    return pd;
+}
+
+static int pop_open_mailbox(CONTEXT *ctx)
+{
+    char buf[BUFSIZ];
+    ACCOUNT act;
+    ciss_url_t url;
+    pop_data_t *pd = NULL;
+
+    if (pop_parse_path(ctx->path, &act)) {
+        mutt_error(_("%s is an invalid POP path"), ctx->path);
+        mutt_sleep(2);
+        return -1;
+    }
+
+    p_clear(&url, 1);
+    mutt_account_tourl(&act, &url);
+
+    pd = pop_find_conn(&act);
+    if (pd) {
+        ctx->data = pd;
+        url_ciss_tostring(&url, buf, sizeof (buf), 0);
+        m_strreplace(&ctx->path, buf);
+    }
+    return 0;
+}
+
 mx_t const pop_mx_ng = {
 mx_t const pop_mx_ng = {
-    M_POP,
-    0,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+    .type            = M_POP,
+    .mx_open_mailbox = pop_open_mailbox,
 };
 };