Rewrite POP nethook as a connection layer.
authorThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Fri, 3 Jul 2009 21:11:46 +0000 (18:11 -0300)
committerThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Fri, 3 Jul 2009 21:15:40 +0000 (18:15 -0300)
It seemed the most simple thing to do so we could drop the nethook
interface entirely.

pop.c
pop.h

diff --git a/pop.c b/pop.c
index 357a394..63ce258 100644 (file)
--- a/pop.c
+++ b/pop.c
 
 #include <glib.h>
 #include <string.h>
-#include "nethook.h"
+#include "hcconn_internal.h"
 #include "pop.h"
 #include "usermap.h"
 
 typedef struct
 {
-  net_read orig_read;
-  gpointer orig_data;
   GString *buffer;
   GString *line;
+  GString *push;
   gchar *user;
+  HCConn *lowconn;
 } pop_t;
 
+void
+pop_destroy (pop_t *pop)
+{
+  g_string_free (pop->buffer, TRUE);
+  g_string_free (pop->line, TRUE);
+  g_string_free (pop->push, TRUE);
+  if (pop->user)
+    g_free (pop->user);
+  g_slice_free (pop_t, (gpointer) pop);
+}
+
 static int
 pop_check_user (pop_t *pop)
 {
@@ -78,54 +89,95 @@ pop_getline (pop_t *pop)
 }
 
 static void
-pop_read (net_hook_t *hook, gchar *buffer, size_t len)
+pop_watch (HCConn *conn, HCEvent event, gpointer data)
 {
-  pop_t *pop = hook->data;
-  g_string_append_len (pop->buffer, buffer, len);
-  while (pop_getline (pop) == 0)
+  char buffer[4096];
+  int r;
+  HCConn *pop_conn = data;
+  pop_t *pop = pop_conn->layer;
+  switch (event)
     {
-      if (pop_check_user (pop) == 0)
+    case HC_EVENT_READ:
+      while ((r = hc_conn_read (conn, buffer, sizeof (buffer))) > 0)
         {
-          g_message ("User is trying to authenticate as %s.", pop->user);
-          if (usermap_perm (pop->user) == ACCESS_DENY)
+          g_string_append_len (pop->buffer, buffer, r);
+          while (pop_getline (pop) == 0)
             {
-              g_message ("Denying access to user %s.", pop->user);
-              pop_destroy (hook);
-              hc_conn_close (hook->peer->conn);
-              hc_conn_close (hook->conn);
-              return;
+              if (pop_check_user (pop) == 0)
+                {
+                  g_message ("User is trying to authenticate as %s.",
+                             pop->user);
+                  if (usermap_perm (pop->user) == ACCESS_DENY)
+                    {
+                      g_message ("Denying access to user %s.", pop->user);
+                      if (pop_conn->func)
+                        pop_conn->func (pop_conn, HC_EVENT_CLOSE,
+                                        pop_conn->data);
+                      return;
+                    }
+                }
+              g_string_append_len (pop->push, pop->line->str, pop->line->len);
+              if (pop_conn->func)
+                pop_conn->func (pop_conn, HC_EVENT_READ, pop_conn->data);
             }
         }
-      hook->data = pop->orig_data;
-      pop->orig_read (hook, pop->line->str, pop->line->len);
-      hook->data = pop;
+      break;
+    case HC_EVENT_CLOSE:
+      if (pop_conn->func)
+        pop_conn->func (pop_conn, event, pop_conn->data);
+      break;
     }
 }
 
-net_hook_t *
-pop_hook_new (net_hook_t *layer)
+static ssize_t
+pop_read (gpointer data, gchar *buffer, size_t len)
+{
+  pop_t *pop = data;
+  int r;
+  if (len > pop->push->len)
+    {
+      r = pop->push->len;
+      memcpy (buffer, pop->push->str, r);
+      g_string_truncate (pop->push, 0);
+    }
+  else
+    {
+      r = len;
+      memcpy (buffer, pop->push->str, r);
+      g_string_erase (pop->push, 0, r);
+    }
+  return r;
+}
+
+static ssize_t
+pop_write (gpointer data, gchar *buffer, size_t len)
+{
+  pop_t *pop = data;
+  hc_conn_write (pop->lowconn, buffer, len);
+  return len;
+}
+
+static void
+pop_close (gpointer data)
+{
+  pop_t *pop = data;
+  hc_conn_close (pop->lowconn);
+  pop_destroy (pop);
+}
+
+void
+hc_conn_set_driver_pop (HCConn *conn, HCConn *lowconn)
 {
   pop_t *pop;
   pop = g_slice_new (pop_t);
-  pop->orig_read = layer->read;
-  pop->orig_data = layer->data;
   pop->buffer = g_string_sized_new (4096);
   pop->line = g_string_sized_new (4096);
+  pop->push = g_string_sized_new (4096);
   pop->user = NULL;
-  layer->read = pop_read;
-  layer->data = pop;
-  return layer;
-}
-
-void
-pop_destroy (net_hook_t *hook)
-{
-  pop_t *pop = hook->data;
-  g_string_free (pop->buffer, TRUE);
-  g_string_free (pop->line, TRUE);
-  if (pop->user)
-    g_free (pop->user);
-  hook->read = pop->orig_read;
-  hook->data = pop->orig_data;
-  g_slice_free (net_hook_t, (gpointer) pop);
+  pop->lowconn = lowconn;
+  conn->read = pop_read;
+  conn->write = pop_write;
+  conn->close = pop_close;
+  conn->layer = pop;
+  hc_conn_set_callback (lowconn, pop_watch, conn);
 }
diff --git a/pop.h b/pop.h
index 647fae0..2c64621 100644 (file)
--- a/pop.h
+++ b/pop.h
@@ -21,9 +21,8 @@
 #ifndef POPPROXY_POP_H
 #define POPPROXY_POP_H
 
-#include "nethook.h"
+#include "hcconn.h"
 
-net_hook_t* pop_hook_new (net_hook_t *);
-void pop_destroy (net_hook_t*);
+void hc_conn_set_driver_pop (HCConn *, HCConn *);
 
 #endif