mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
Netevent work
git-svn-id: file:///svn/unbound/trunk@27 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
df792cc3af
commit
8982c72e5c
8 changed files with 392 additions and 26 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
2
doc/plan
2
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
|
||||
|
|
|
|||
21
util/log.c
21
util/log.c
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
11
util/log.h
11
util/log.h
|
|
@ -27,16 +27,25 @@
|
|||
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 */
|
||||
|
|
|
|||
240
util/netevent.c
Normal file
240
util/netevent.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
||||
135
util/netevent.h
135
util/netevent.h
|
|
@ -30,10 +30,31 @@
|
|||
#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.
|
||||
/** 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;
|
||||
|
||||
/** callback when done.
|
||||
tcp_accept does not get called back, is NULL then.
|
||||
|
||||
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.
|
||||
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 */
|
||||
|
|
|
|||
Loading…
Reference in a new issue