first buffer, readline implementation
authorChristian Thaeter <ct@pipapo.org>
Wed, 3 Oct 2007 09:37:31 +0000 (11:37 +0200)
committerChristian Thaeter <ct@pipapo.org>
Wed, 3 Oct 2007 09:37:31 +0000 (11:37 +0200)
rxpd.c
rxpd.h

diff --git a/rxpd.c b/rxpd.c
index 578099e..e7a71d6 100644 (file)
--- a/rxpd.c
+++ b/rxpd.c
@@ -99,9 +99,9 @@ rxpd_rule_new (const char* buf)
               regfree (&self->rx);
               char ebuf[256];
               size_t len = regerror (err, NULL, ebuf, 256);
-              self->string = malloc(len + strlen(buf) + 9);
+              self->string = malloc(len + strlen(buf) + 14);
               if (!self->string) abort();
-              strcpy (self->string, "# ");
+              strcpy (self->string, "#ERROR ");
               strcat (self->string, ebuf);
               strcat (self->string, " in '");
               strcat (self->string, buf);
@@ -136,12 +136,12 @@ rxpd_rule_delete (struct rxpd_rule* rule)
 int
 rxpd_file_load (struct rxpd_base* base, const char* filename)
 {
-  char buf[2048];
+  char buf[4096];
 
   // TODO better filenname validation / error handling
   if (!filename ||
       strchr (filename, '/') ||
-      strlen (filename) + strlen (base->rulesdir) > 2047)
+      strlen (filename) + strlen (base->rulesdir) > 4097)
     abort();
 
   strcpy (buf, base->rulesdir);
@@ -159,7 +159,7 @@ rxpd_file_load (struct rxpd_base* base, const char* filename)
   if (!f) abort();
 
   // TODO test excess line length = error
-  while (fgets (buf, 2048, f))
+  while (fgets (buf, 4096, f))
     {
       size_t last = strlen(buf);
       if (buf[last-1] == '\n')
@@ -234,7 +234,7 @@ rxpd_socket_new_tcp4 (struct rxpd_base* base, const char* addr, unsigned short p
   if (bind (self->fd, (struct sockaddr*)&listen_addr, sizeof (listen_addr)) == -1)
     abort();
 
-  static int yes=1;
+  static int yes = 1;
   if (setsockopt (self->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
     abort ();
 
@@ -294,6 +294,73 @@ rxpd_socket_accept (int fd, short event, void* ptr)
   rxpd_connection_activate (conn);
 }
 
+///
+
+struct rxpd_buffer*
+rxpd_buffer_init (struct rxpd_buffer* self, struct rxpd_connection* conn)
+{
+  self->conn = conn;
+  self->state = RXPD_OK;
+  self->eol = self->eob = self->buffer;
+  self->buffer [4095] = '\0';
+  return self;
+}
+
+
+char*
+rxpd_buffer_readline (struct rxpd_buffer* self, int again)
+{
+  int fd = self->conn->fd;
+
+  if (self->eol != self->buffer)
+    {
+      //there was a line pending, discard it now
+      memmove (self->buffer, self->eol+1, self->eob - self->eol - 1);
+      self->eob = (char*)(self->eob - (self->eol - self->buffer + 1));
+      self->eol = self->buffer;
+      // TODO handle \r's
+    }
+
+  if (!again && self->state == RXPD_OK)   // we only read when again is 0, first iteration
+    {
+      ssize_t r = 0;
+      do
+        {
+          r = read(fd, self->eob, 4096 - (self->eob - self->buffer));
+        }
+      while (r == -1 && errno == EINTR);
+
+      if (r == -1)
+        self->state = RXPD_ERROR;
+
+      if (r == 0)
+        {
+          shutdown (fd, SHUT_RD);
+          self->state = RXPD_EOF;
+        }
+
+      self->eob += r;
+    }
+
+  // find next newline, terminate string there
+  for (char* i = self->buffer; i < self->eob; ++i)
+    {
+      if (*i == '\n')
+        {
+          *i = '\0';
+          self->eol = i;
+          break;
+        }
+    }
+
+  // TODO handle buffer overfulls
+  return self->eol == self->buffer ? NULL : self->buffer;
+}
+
+
+
+
 ///
 
 struct rxpd_connection*
@@ -310,10 +377,16 @@ rxpd_connection_new (struct rxpd_base* base, int fd)
   if (self->fd == -1)
     abort ();
 
+  static int yes = 1;
+  if (setsockopt (self->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
+    abort ();
+
+
   self->base = base;
   self->file = NULL;
 
-  self->eol = self->eob = self->buffer;
+  rxpd_buffer_init (&self->in, self);
+  rxpd_buffer_init (&self->out, self);
   
   event_set (&self->ev, self->fd, EV_READ, rxpd_connection_parse_cmd, self);
 
@@ -357,18 +430,21 @@ rxpd_connection_suspend (struct rxpd_connection* self)
 }
 
 
-
-
-int
-rxpd_connection_readline (struct rxpd_connection* self)
-{
-}
-
 void
 rxpd_connection_parse_cmd (int sock, short event, void* ptr)
 {
   printf ("parse cmd\n");
+  struct rxpd_connection* self = (struct rxpd_connection*) ptr;
+
+  char* line;
+  line = rxpd_buffer_readline (&self->in, 0);
+  printf ("got line '%s'\n", line);
+
+
   // TODO policy check
+
+  //if (rxpd_buffer_state (&self->in) != RXPD_EOF)
+  //  event_add (&self->ev, NULL);
 }
 
 void
diff --git a/rxpd.h b/rxpd.h
index 565fd2f..be3b80d 100644 (file)
--- a/rxpd.h
+++ b/rxpd.h
@@ -24,6 +24,7 @@
 #include "llist.h"
 #include "psplay.h"
 
+#include <errno.h>
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -56,6 +57,7 @@ struct rxpd_base;
 struct rxpd_file;
 struct rxpd_rule;
 struct rxpd_socket;
+struct rxpd_buffer;
 struct rxpd_connection;
 
 struct rxpd_base
@@ -144,6 +146,36 @@ rxpd_socket_suspend (struct rxpd_socket* self);
 
 //
 
+enum rxpd_buffer_state_e
+  {
+    RXPD_OK,            // operational
+    RXPD_EOF,           // connection closed
+    RXPD_ERROR          // some other error
+  };
+
+struct rxpd_buffer
+{
+  struct rxpd_connection* conn;
+  enum rxpd_buffer_state_e state;
+  char* eol;
+  char* eob;
+  char buffer[4096];
+};
+
+struct rxpd_buffer*
+rxpd_buffer_init (struct rxpd_buffer* self, struct rxpd_connection* conn);
+
+char*
+rxpd_buffer_readline (struct rxpd_buffer* self, int again);
+
+inline static enum rxpd_buffer_state_e
+rxpd_buffer_state (struct rxpd_buffer* self)
+{
+  return self->state;
+}
+
+
+//
 struct rxpd_connection
 {
   llist node;
@@ -154,9 +186,8 @@ struct rxpd_connection
 
   struct sockaddr peer_addr;
 
-  char* eol;
-  char* eob;
-  char buffer[4096];
+  struct rxpd_buffer in;
+  struct rxpd_buffer out;
 };