]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Netevent work
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 23 Jan 2007 13:46:18 +0000 (13:46 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 23 Jan 2007 13:46:18 +0000 (13:46 +0000)
git-svn-id: file:///svn/unbound/trunk@27 be551aaa-1e26-0410-a405-d3ace91eadb9

Makefile.in
configure.ac
doc/Changelog
doc/plan
util/log.c
util/log.h
util/netevent.c [new file with mode: 0644]
util/netevent.h

index 0d44e9ffde340ef69017bb79bf4fb85260a43f96..557c7a555584abd224d592e7655c258f2471cc92 100644 (file)
@@ -67,11 +67,11 @@ all:        $(COMMON_OBJ) unbound unittest
 
 unbound:       $(COMMON_OBJ) $(DAEMON_OBJ)
        $(INFO) Link $@
-       $Q$(LINK) -o $@ $^
+       $Q$(LINK) -o $@ $^ $(LIBS)
 
 unittest:      $(COMMON_OBJ) $(UNITTEST_OBJ)
        $(INFO) Link $@
-       $Q$(LINK) -o $@ $^
+       $Q$(LINK) -o $@ $^ $(LIBS)
 
 clean:
        rm -f *.o *.d *.lo *~ tags
index a331450b3bd96ac796eb4c3b9560fab8dd2099c9..7e592f749ff7db0dd6d1f6ebd92d080892de9bf0 100644 (file)
@@ -188,6 +188,7 @@ AC_CHECK_TYPE(in_port_t, [], [AC_DEFINE([in_port_t], [uint16_t], [in_port_t])],
 # check to see if libraries are needed for these functions.
 AC_CHECK_LIB(socket, socket)
 AC_CHECK_LIB(nsl, inet_pton)
+AC_CHECK_LIB(event, event_set)
 
 AC_FUNC_MALLOC
 
index 5049a96663feddd7cf9e1595324032a6fdba6b30..f517f0b801ddf3b3e73b11d4788c8f576fb6c8cb 100644 (file)
@@ -1,3 +1,7 @@
+23  January 2007: Wouter
+       - added libevent to configure to link with.
+       - util/netevent setup work.
+
 22  January 2007: Wouter
        - Designed header file for network communication.
 
index c23cdee90c2a66e592c14761e66ad0c130e1735b..7a90a1705f658722e25d984972bfffd9631ffeae 100644 (file)
--- a/doc/plan
+++ b/doc/plan
@@ -35,7 +35,7 @@ Roughly the boxes are as follows:
 0.8 Library use - resolver validator lib (and test apps)
 0.9 Corner cases - be able to resolve in the wild. Run fuzzers.
     Run as many tests as we can think of.
-1.0 El product. Run shadow for a resolver in production for several
+0.10 Beta release. Run shadow for a resolver in production for several
     weeks.
 
 For boxes 0.5-1.0 the planning is to be revised, at the 0.5 stage external
index 56e4e21512a47d98efa758d2706159f16486dbe5..3c20045bfabfc17ba3b4f264bc9c445a5efaa124 100644 (file)
@@ -23,13 +23,13 @@ log_init()
 }
 
 void
-log_vmsg(const char *format, va_list args)
+log_vmsg(const char* type, const char *format, va_list args)
 {
        char message[MAXSYSLOGMSGLEN];
        const char* ident="unbound";
        vsnprintf(message, sizeof(message), format, args);
-       fprintf(stderr, "[%d] %s[%d]: %s\n",
-               (int)time(NULL), ident, (int)getpid(), message);
+       fprintf(stderr, "[%d] %s[%d] %s: %s\n",
+               (int)time(NULL), ident, (int)getpid(), type, message);
 }
 
 /**
@@ -41,6 +41,19 @@ log_info(const char *format, ...)
 {
         va_list args;
        va_start(args, format);
-       log_vmsg(format, args);
+       log_vmsg("info", format, args);
+       va_end(args);
+}
+
+/**
+ * implementation of log_err
+ * @param format: format string printf-style.
+ */
+void
+log_err(const char *format, ...)
+{
+        va_list args;
+       va_start(args, format);
+       log_vmsg("error", format, args);
        va_end(args);
 }
index 06f0a27b05fbf70f9089fa4727ebd3c324918568..bffe11286f318efc473f662519896e4f0ab94c01 100644 (file)
 void log_init();
 
 /**
+ * Log informational message.
  * Pass printf formatted arguments. No trailing newline is needed.
  * @param format: printf-style format string. Arguments follow.
  */
 void log_info(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
 
+/**
+ * Log error message.
+ * Pass printf formatted arguments. No trailing newline is needed.
+ * @param format: printf-style format string. Arguments follow.
+ */
+void log_err(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
+
 /**
  * va_list argument version of log_info.
+ * @param type: string to designate type of message (info, error).
  * @param format: the printf style format to print. no newline.
  * @param args: arguments for format string.
  */
-void log_vmsg(const char *format, va_list args);
+void log_vmsg(const char* type, const char *format, va_list args);
 
 #endif /* UTIL_LOG_H */
diff --git a/util/netevent.c b/util/netevent.c
new file mode 100644 (file)
index 0000000..c265526
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * util/netevent.c - event notification
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * See LICENSE for the license.
+ *
+ */
+
+/**
+ * \file
+ *
+ * This file contains event notification functions.
+ */
+
+#include "util/netevent.h"
+#include "util/log.h"
+#include <errno.h>
+
+/* we use libevent */
+#include <event.h>
+
+/**
+ * The internal event structure for keeping libevent info for the event.
+ * Possibly other structures (list, tree) this is part of.
+ */
+struct internal_event {
+       /** libevent event type, alloced here */
+       struct event ev;
+};
+
+/**
+ * Internal base structure, so that every thread has its own events.
+ */
+struct internal_base {
+       /** libevent event_base type. */
+       struct event_base* base;
+};
+
+struct comm_base* comm_base_create()
+{
+       struct comm_base* b = (struct comm_base*)calloc(1,
+               sizeof(struct comm_base));
+       if(!b)
+               return NULL;
+       b->eb = (struct internal_base*)calloc(1, sizeof(struct internal_base));
+       if(!b->eb) {
+               free(b);
+               return NULL;
+       }
+       b->eb->base = event_init();
+       if(!b->eb->base) {
+               free(b->eb);
+               free(b);
+               return NULL;
+       }
+       return b;
+}
+
+void comm_base_delete(struct comm_base* b)
+{
+       /* No way to delete event_base! leaks. */
+       b->eb->base = NULL;
+       free(b->eb);
+       free(b);
+}
+
+void comm_base_dispatch(struct comm_base* b)
+{
+       int retval;
+       while(1) {
+               retval = event_base_dispatch(b->eb->base);
+               if(retval != 0) {
+                       log_err("event_dispatch returned error %d, "
+                               "errno is %s", retval, strerror(errno));
+               }
+       }
+}
+
+/**
+ * libevent callback routine for commpoint udp
+ * @param fd: file descriptor.
+ * @param event: event bits from libevent: 
+ *     EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
+ * @param arg: the comm_point structure.
+ */
+static void 
+comm_point_udp_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event), 
+       void* arg)
+{
+       struct comm_point* c = (struct comm_point*)arg;
+       log_info("callback udp for %x", (int)c);
+}
+
+/**
+ * libevent callback routine for commpoint tcp accept listeners.
+ * @param fd: file descriptor.
+ * @param event: event bits from libevent: 
+ *     EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
+ * @param arg: the comm_point structure.
+ */
+static void 
+comm_point_tcp_accept_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event), 
+       void* arg)
+{
+       struct comm_point* c = (struct comm_point*)arg;
+       log_info("callback tcpaccept for %x", (int)c);
+}
+
+struct comm_point* comm_point_create_udp(struct comm_base *base,
+       int fd, struct buffer* buffer,
+       comm_point_callback_t* callback, void* callback_arg)
+{
+       struct comm_point* c = (struct comm_point*)calloc(1,
+               sizeof(struct comm_point));
+       short evbits;
+       if(!c)
+               return NULL;
+       c->ev = (struct internal_event*)calloc(1,
+               sizeof(struct internal_event));
+       if(!c->ev) {
+               free(c);
+               return NULL;
+       }
+       c->fd = fd;
+       c->buffer = buffer;
+       c->timeout = NULL;
+       c->tcp_is_reading = 0;
+       c->tcp_byte_count = 0;
+       c->tcp_parent = NULL;
+       c->cur_tcp_count = 0;
+       c->max_tcp_count = 0;
+       c->tcp_handlers = NULL;
+       c->tcp_free = NULL;
+       c->type = comm_udp;
+       c->tcp_do_close = 0;
+       c->tcp_do_toggle_rw = 0;
+       c->callback = callback;
+       c->cb_arg = callback_arg;
+       evbits = EV_READ | EV_PERSIST;
+       /* libevent stuff */
+       event_set(&c->ev->ev, c->fd, evbits, comm_point_udp_callback, c);
+       if(event_base_set(base->eb->base, &c->ev->ev) != 0 ||
+               event_add(&c->ev->ev, c->timeout) != 0 ) {
+               log_err("could not add udp event");
+               comm_point_delete(c);
+               return NULL;
+       }
+       return c;
+}
+
+struct comm_point* 
+comm_point_create_tcp_handler(struct comm_base *base, 
+       struct comm_point* parent, size_t bufsize,
+        comm_point_callback_t* callback, void* callback_arg)
+{
+       return NULL;
+}
+
+struct comm_point* 
+comm_point_create_tcp(struct comm_base *base, int fd, int num, size_t bufsize,
+        comm_point_callback_t* callback, void* callback_arg)
+{
+       struct comm_point* c = (struct comm_point*)calloc(1,
+               sizeof(struct comm_point));
+       short evbits;
+       int i;
+       /* first allocate the TCP accept listener */
+       if(!c)
+               return NULL;
+       c->ev = (struct internal_event*)calloc(1,
+               sizeof(struct internal_event));
+       if(!c->ev) {
+               free(c);
+               return NULL;
+       }
+       c->fd = fd;
+       c->buffer = NULL;
+       c->timeout = NULL;
+       c->tcp_is_reading = 0;
+       c->tcp_byte_count = 0;
+       c->tcp_parent = NULL;
+       c->cur_tcp_count = 0;
+       c->max_tcp_count = num;
+       c->tcp_handlers = (struct comm_point**)calloc(num,
+               sizeof(struct comm_point*));
+       c->tcp_free = NULL;
+       c->type = comm_tcp_accept;
+       c->tcp_do_close = 0;
+       c->tcp_do_toggle_rw = 0;
+       c->callback = NULL;
+       c->cb_arg = NULL;
+       evbits = EV_READ | EV_PERSIST;
+       /* libevent stuff */
+       event_set(&c->ev->ev, c->fd, evbits, comm_point_tcp_accept_callback, c);
+       if( event_base_set(base->eb->base, &c->ev->ev) != 0 ||
+               event_add(&c->ev->ev, c->timeout) != 0 )
+       {
+               log_err("could not add tcpacc event");
+               if(!event_del(&c->ev->ev)) {
+                       log_err("could not event_del tcpacc event");
+               }
+               free(c->tcp_handlers);
+               free(c->ev);
+               free(c);
+               return NULL;
+       }
+
+       /* now prealloc the tcp handlers */
+       for(i=0; i<num; i++) {
+               c->tcp_handlers[i] = comm_point_create_tcp_handler(base,
+                       c, bufsize, callback, callback_arg);
+       }
+       
+       return c;
+}
+
+void comm_point_close(struct comm_point* c)
+{
+       if(c->fd != -1)
+               close(c->fd);
+       c->fd = -1;
+       if(event_del(&c->ev->ev) != 0) {
+               log_err("could not event_del on close");
+       }
+}
+
+void comm_point_delete(struct comm_point* c)
+{
+       comm_point_close(c);
+       if(c->tcp_handlers) {
+               int i;
+               for(i=0; i<c->max_tcp_count; i++)
+                       comm_point_delete(c->tcp_handlers[i]);
+               free(c->tcp_handlers);
+       }
+       free(c->ev);
+       free(c);
+}
+
index e3632aaeb3a9627bfa0480a2ef4326633ba774b9..e0cddb3d2107a83c1a8566fc4019849739f5213a 100644 (file)
 #include "config.h"
 struct buffer;
 
-/** internal event notification data storage structure. */
+/* internal event notification data storage structure. */
 struct internal_event;
+struct internal_base;
+struct comm_point;
 
-/** Communication point to the network */
+/** callback from communication point function type */
+typedef int comm_point_callback_t(struct comm_point*, void*, int);
+
+/**
+ * A communication point dispatcher. Thread specific.
+ */
+struct comm_base {
+       /** behind the scenes structure. with say libevent info. alloced */
+       struct internal_base* eb;
+};
+
+/** 
+ * Communication point to the network 
+ * These behaviours can be accomplished by setting the flags
+ * and passing return values from the callback.
+ *    udp frontside: called after readdone. sendafter.
+ *    tcp frontside: called readdone, sendafter. close.
+ *    udp behind: called after readdone. No send after.
+ *    tcp behind: write done, read done, then called. No send after.
+ */
 struct comm_point {
        /** behind the scenes structure, with say libevent info. alloced. */
        struct internal_event* ev;
@@ -53,7 +74,7 @@ struct comm_point {
        /** The current read/write count for TCP */
        size_t tcp_byte_count;
        /** parent communication point (for TCP sockets) */
-       struct comm_point tcp_parent;
+       struct comm_point *tcp_parent;
 
        /* -------- TCP Accept -------- */
        /** current number of TCP connections on this socket */
@@ -62,7 +83,7 @@ struct comm_point {
        int max_tcp_count;
        /** malloced array of tcp handlers for a tcp-accept, 
            of size max_tcp_count. */
-       struct comm_point *tcp_handlers;
+       struct comm_point **tcp_handlers;
        /** linked list of free tcp_handlers to use for new queries.
            For tcp_accept the first entry, for tcp_handlers the next one. */
        struct comm_point *tcp_free;
@@ -77,28 +98,106 @@ struct comm_point {
                comm_tcp  
        } type;
 
-       /** what to do when read/write is done.
+       /* ---------- Behaviour ----------- */
+       /** if set, the connection is closed on error, on timeout, 
+           and after read/write completes. No callback is done. */
+       int tcp_do_close;
 
-           For a query this means it is read in and ready to be processed.
-           After that the buffer will be sent back to client.
-           tcp_accept does not get called back, is NULL then.
+       /** if set, read/write completes:
+               read/write state of tcp is toggled.
+               buffer reset/bytecount reset.
+               this flag cleared.
+           So that when that is done the callback is called. */
+       int tcp_do_toggle_rw;
 
-           udp frontside: called after readdone. sendafter.
-           tcp frontside: called readdone, sendafter. close.
-           udp behind: called after readdone. No send after.
-           tcp behind: write done, read done, then called. No send after.
+       /** callback when done.
+           tcp_accept does not get called back, is NULL then.
+           If a timeout happens, callback with timeout=1 is called.
+           If an error happens, callback is called with error set 
+           nonzero. If nonzero, it is an errno value.
+           If the connection is closed (by remote end) then the
+           callback is called with error set to -1.
 
            declare as: 
-           int my_callback(struct comm_point*, void* cb_arg, int timeout);
+           int my_callback(struct comm_point* c, void* my_arg, 
+               int timeout, int error);
 
-           if the routine returns 0, no answer is sent back.
-           For TCP handlers after the answer is sent back the fd is closed.
-           If a timeout happens, TCP handler is closed, and callback with
-           timeout=1 is called.
+           if the routine returns 0, nothing is done.
+           Notzero, the buffer will be sent back to client.
+                       For UDP this is done without changing the commpoint.
+                       In TCP it sets write state.
        */
-       int (*)(struct comm_point*, void*) callback;
+       comm_point_callback_t* callback;
        /** argument to pass to callback. */
        void *cb_arg;
 };
 
+/**
+ * Create a new comm base.
+ * @return: the new comm base. NULL on error.
+ */
+struct comm_base* comm_base_create();
+
+/**
+ * Destroy a comm base.
+ * All comm points must have been deleted.
+ * @param b: the base to delete.
+ */
+void comm_base_delete(struct comm_base* b);
+
+/**
+ * Dispatch the comm base events.
+ * @param b: the communication to perform.
+ */
+void comm_base_dispatch(struct comm_base* b);
+
+/**
+ * Create an UDP comm point. Calls malloc.
+ * setups the structure with the parameters you provide.
+ * @param base: in which base to alloc the commpoint.
+ * @param fd : file descriptor of open UDP socket.
+ * @param buffer: shared buffer by UDP sockets from this thread.
+ * @param callback: callback function pointer.
+ * @param callback_arg: will be passed to your callback function.
+ * @return: returns the allocated communication point. NULL on error.
+ * Sets timeout to NULL. Turns off TCP options.
+ */
+struct comm_point* comm_point_create_udp(struct comm_base *base,
+       int fd, struct buffer* buffer, 
+       comm_point_callback_t* callback, void* callback_arg);
+
+/**
+ * Create a TCP listener comm point. Calls malloc.
+ * Setups the structure with the parameters you provide.
+ * Also Creates TCP Handlers, pre allocated for you.
+ * Uses the parameters you provide.
+ * @param base: in which base to alloc the commpoint.
+ * @param fd: file descriptor of open TCP socket set to listen nonblocking.
+ * @param num: becomes max_tcp_count, the routine allocates that
+ *     many tcp handler commpoints.
+ * @param bufsize: size of buffer to create for handlers.
+ * @param callback: callback function pointer for TCP handlers.
+ * @param callback_arg: will be passed to your callback function.
+ * @return: returns the TCP listener commpoint. You can find the
+ *     TCP handlers in the array inside the listener commpoint.
+ *     returns NULL on error.
+ * Inits timeout to NULL. All handlers are on the free list.
+ */
+struct comm_point* comm_point_create_tcp(struct comm_base *base,
+       int fd, int num, size_t bufsize, 
+       comm_point_callback_t* callback, void* callback_arg);
+
+/**
+ * Close a comm point fd.
+ * @param c: comm point to close.
+ */
+void comm_point_close(struct comm_point* c);
+
+/**
+ * Close and deallocate (free) the comm point. If the comm point is
+ * a tcp-accept point, also its tcp-handler points are deleted.
+ * @param c: comm point to delete.
+ */
+void comm_point_delete(struct comm_point* c);
+
 #endif /* NET_EVENT_H */