udp work.

git-svn-id: file:///svn/unbound/trunk@45 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-01-31 09:32:30 +00:00
parent 9becddebbc
commit 775158882e
7 changed files with 180 additions and 45 deletions

View file

@ -45,17 +45,87 @@
#include "util/netevent.h" #include "util/netevent.h"
#include "services/listen_dnsport.h" #include "services/listen_dnsport.h"
/** handles callbacks from listening event interface */ /** process incoming request */
static int worker_handle_request(ldns_buffer* packet, void* arg) static void worker_process_query(struct worker* worker)
{ {
/* query the forwarding address */
}
/** check request sanity. Returns error code, 0 OK, or -1 discard. */
static int worker_check_request(ldns_buffer* pkt)
{
if(ldns_buffer_limit(pkt) < LDNS_HEADER_SIZE) {
verbose(VERB_DETAIL, "request too short, discarded");
return -1;
}
if(LDNS_QR_WIRE(ldns_buffer_begin(pkt))) {
verbose(VERB_DETAIL, "request has QR bit on, discarded");
return -1;
}
if(LDNS_OPCODE_WIRE(ldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY) {
verbose(VERB_DETAIL, "request unknown opcode %d",
LDNS_OPCODE_WIRE(ldns_buffer_begin(pkt)));
return LDNS_RCODE_NOTIMPL;
}
if(LDNS_QDCOUNT(ldns_buffer_begin(pkt)) != 1) {
verbose(VERB_DETAIL, "request wrong nr qd=%d",
LDNS_QDCOUNT(ldns_buffer_begin(pkt)));
return LDNS_RCODE_FORMERR;
}
if(LDNS_ANCOUNT(ldns_buffer_begin(pkt)) != 0) {
verbose(VERB_DETAIL, "request wrong nr an=%d",
LDNS_ANCOUNT(ldns_buffer_begin(pkt)));
return LDNS_RCODE_FORMERR;
}
if(LDNS_NSCOUNT(ldns_buffer_begin(pkt)) != 0) {
verbose(VERB_DETAIL, "request wrong nr ns=%d",
LDNS_NSCOUNT(ldns_buffer_begin(pkt)));
return LDNS_RCODE_FORMERR;
}
if(LDNS_ARCOUNT(ldns_buffer_begin(pkt)) != 0) {
verbose(VERB_DETAIL, "request wrong nr ar=%d",
LDNS_ARCOUNT(ldns_buffer_begin(pkt)));
return LDNS_RCODE_FORMERR;
}
return 0;
}
/** handles callbacks from listening event interface */
static int worker_handle_request(struct comm_point* c, void* arg, int error,
struct comm_reply* repinfo)
{
struct worker* worker = (struct worker*)arg;
int ret;
log_info("worker handle request"); log_info("worker handle request");
if(error != 0) {
log_err("called with err=%d", error);
return 0;
}
if((ret=worker_check_request(c->buffer)) != 0) {
if(ret != -1) {
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), ret);
return 1;
}
return 0;
}
if(worker->num_requests > 0) {
verbose(VERB_DETAIL, "worker: too many requests active. "
"dropping incoming query.");
return 0;
}
/* answer it */
worker->num_requests ++;
memcpy(&worker->query_reply, repinfo, sizeof(struct comm_reply));
worker_process_query(worker);
return 0; return 0;
} }
struct worker* worker_init(const char* port, int do_ip4, int do_ip6, struct worker* worker_init(const char* port, int do_ip4, int do_ip6,
int do_udp, int do_tcp, size_t buffer_size) int do_udp, int do_tcp, size_t buffer_size)
{ {
struct worker* worker = (struct worker*)malloc(sizeof(struct worker)); struct worker* worker = (struct worker*)calloc(1,
sizeof(struct worker));
if(!worker) if(!worker)
return NULL; return NULL;
worker->base = comm_base_create(); worker->base = comm_base_create();

View file

@ -44,7 +44,7 @@
#define DAEMON_WORKER_H #define DAEMON_WORKER_H
#include "config.h" #include "config.h"
struct comm_base; #include "util/netevent.h"
struct listen_dnsport; struct listen_dnsport;
/** /**
@ -57,6 +57,12 @@ struct worker {
/** the frontside listening interface where request events come in */ /** the frontside listening interface where request events come in */
struct listen_dnsport* front; struct listen_dnsport* front;
/** our one and only query, packet buffer and where to send. */
struct comm_reply query_reply;
/** number of requests currently active */
int num_requests;
}; };
/** /**

View file

@ -1,5 +1,9 @@
31 January 2007: Wouter 31 January 2007: Wouter
- Added makedist.sh script to make release tarball. - Added makedist.sh script to make release tarball.
- Removed listen callback layer, did not add anything.
- Added UDP recv to netevent, worker callback for udp.
- netevent communication reply storage structure.
- minimal query header sanity checking for worker.
30 January 2007: Wouter 30 January 2007: Wouter
- links in example/ldns-testpkts.c and .h for premade packet support. - links in example/ldns-testpkts.c and .h for premade packet support.

View file

@ -55,18 +55,6 @@
/** number of simultaneous open TCP connections */ /** number of simultaneous open TCP connections */
#define TCP_COUNT 10 #define TCP_COUNT 10
/** callback of comm_point_callback_t for events. */
static int listen_udp_callback(struct comm_point* cp, void* arg, int error)
{
return 0;
}
/** callback of comm_point_callback_t for events. */
static int listen_tcp_callback(struct comm_point* cp, void* arg, int error)
{
return 0;
}
/** /**
* Debug print of the getaddrinfo returned address. * Debug print of the getaddrinfo returned address.
* @param addr: the address returned. * @param addr: the address returned.
@ -199,12 +187,15 @@ make_sock(int stype, const char* ifname, const char* port,
* @param do_tcp: if udp should be used. * @param do_tcp: if udp should be used.
* @param hints: for getaddrinfo. family and flags have to be set by caller. * @param hints: for getaddrinfo. family and flags have to be set by caller.
* @param bufsize: TCP buffer size. * @param bufsize: TCP buffer size.
* @param cb: callback function
* @param cb_arg: user parameter for callback function.
* @return: returns false on error. * @return: returns false on error.
*/ */
static int static int
listen_create_if(const char* ifname, struct listen_dnsport* front, listen_create_if(const char* ifname, struct listen_dnsport* front,
struct comm_base* base, const char* port, int do_udp, int do_tcp, struct comm_base* base, const char* port, int do_udp, int do_tcp,
struct addrinfo *hints, size_t bufsize) struct addrinfo *hints, size_t bufsize, comm_point_callback_t* cb,
void *cb_arg)
{ {
struct comm_point *cp_udp = NULL, *cp_tcp = NULL; struct comm_point *cp_udp = NULL, *cp_tcp = NULL;
struct listen_list *el_udp, *el_tcp; struct listen_list *el_udp, *el_tcp;
@ -215,7 +206,7 @@ listen_create_if(const char* ifname, struct listen_dnsport* front,
if((s = make_sock(SOCK_DGRAM, ifname, port, hints)) == -1) if((s = make_sock(SOCK_DGRAM, ifname, port, hints)) == -1)
return 0; return 0;
cp_udp = comm_point_create_udp(base, s, front->udp_buff, cp_udp = comm_point_create_udp(base, s, front->udp_buff,
listen_udp_callback, front); cb, cb_arg);
if(!cp_udp) { if(!cp_udp) {
log_err("can't create commpoint"); log_err("can't create commpoint");
close(s); close(s);
@ -228,7 +219,7 @@ listen_create_if(const char* ifname, struct listen_dnsport* front,
return 0; return 0;
} }
cp_tcp = comm_point_create_tcp(base, s, TCP_COUNT, bufsize, cp_tcp = comm_point_create_tcp(base, s, TCP_COUNT, bufsize,
listen_tcp_callback, front); cb, cb_arg);
if(!cp_tcp) { if(!cp_tcp) {
log_err("can't create commpoint"); log_err("can't create commpoint");
comm_point_delete(cp_udp); comm_point_delete(cp_udp);
@ -254,18 +245,16 @@ listen_create_if(const char* ifname, struct listen_dnsport* front,
el_udp->com = cp_udp; el_udp->com = cp_udp;
el_udp->next = front->cps; el_udp->next = front->cps;
front->cps = el_udp; front->cps = el_udp;
comm_point_set_cb_arg(el_udp->com, el_udp);
el_tcp->com = cp_tcp; el_tcp->com = cp_tcp;
el_tcp->next = front->cps; el_tcp->next = front->cps;
front->cps = el_tcp; front->cps = el_tcp;
comm_point_set_cb_arg(el_tcp->com, el_tcp);
return 1; return 1;
} }
struct listen_dnsport* struct listen_dnsport*
listen_create(struct comm_base* base, int num_ifs, const char* ifs[], listen_create(struct comm_base* base, int num_ifs, const char* ifs[],
const char* port, int do_ip4, int do_ip6, int do_udp, int do_tcp, const char* port, int do_ip4, int do_ip6, int do_udp, int do_tcp,
size_t bufsize, listen_dnsport_cb_t* cb, void *cb_arg) size_t bufsize, comm_point_callback_t* cb, void *cb_arg)
{ {
struct addrinfo hints; struct addrinfo hints;
int i; int i;
@ -274,8 +263,6 @@ listen_create(struct comm_base* base, int num_ifs, const char* ifs[],
if(!front) if(!front)
return NULL; return NULL;
front->cps = NULL; front->cps = NULL;
front->cb = cb;
front->cb_arg = cb_arg;
front->udp_buff = ldns_buffer_new(bufsize); front->udp_buff = ldns_buffer_new(bufsize);
if(!front->udp_buff) { if(!front->udp_buff) {
free(front); free(front);
@ -304,13 +291,13 @@ listen_create(struct comm_base* base, int num_ifs, const char* ifs[],
if(num_ifs == 0) { if(num_ifs == 0) {
if(!listen_create_if(NULL, front, base, port, if(!listen_create_if(NULL, front, base, port,
do_udp, do_tcp, &hints, bufsize)) { do_udp, do_tcp, &hints, bufsize, cb, cb_arg)) {
listen_delete(front); listen_delete(front);
return NULL; return NULL;
} }
} else for(i = 0; i<num_ifs; i++) { } else for(i = 0; i<num_ifs; i++) {
if(!listen_create_if(ifs[i], front, base, port, if(!listen_create_if(ifs[i], front, base, port,
do_udp, do_tcp, &hints, bufsize)) { do_udp, do_tcp, &hints, bufsize, cb, cb_arg)) {
listen_delete(front); listen_delete(front);
return NULL; return NULL;
} }

View file

@ -43,12 +43,9 @@
#define LISTEN_DNSPORT_H #define LISTEN_DNSPORT_H
#include "config.h" #include "config.h"
struct comm_base; #include "util/netevent.h"
struct listen_list; struct listen_list;
/** The callback type for a incoming request packet */
typedef int listen_dnsport_cb_t(ldns_buffer* packet, void* arg);
/** /**
* Listening for queries structure. * Listening for queries structure.
* Contains list of query-listen sockets. * Contains list of query-listen sockets.
@ -63,12 +60,6 @@ struct listen_dnsport {
/** list of comm points used to get incoming events */ /** list of comm points used to get incoming events */
struct listen_list *cps; struct listen_list *cps;
/** callback function that accepts incoming message. */
listen_dnsport_cb_t* cb;
/** callback argument */
void *cb_arg;
}; };
/** /**
@ -95,14 +86,15 @@ struct listen_list {
* @param do_udp: listen to udp queries. * @param do_udp: listen to udp queries.
* @param do_tcp: listen to tcp queries. * @param do_tcp: listen to tcp queries.
* @param bufsize: size of datagram buffer. * @param bufsize: size of datagram buffer.
* @param cb: callback function when a request arrives. * @param cb: callback function when a request arrives. It is passed
* the packet and user argument. Return true to send a reply.
* @param cb_arg: user data argument for callback function. * @param cb_arg: user data argument for callback function.
* @return: the malloced listening structure, ready for use. NULL on error. * @return: the malloced listening structure, ready for use. NULL on error.
*/ */
struct listen_dnsport* listen_create(struct comm_base* base, struct listen_dnsport* listen_create(struct comm_base* base,
int num_ifs, const char* ifs[], const char* port, int num_ifs, const char* ifs[], const char* port,
int do_ip4, int do_ip6, int do_udp, int do_tcp, int do_ip4, int do_ip6, int do_udp, int do_tcp,
size_t bufsize, listen_dnsport_cb_t* cb, void *cb_arg); size_t bufsize, comm_point_callback_t* cb, void *cb_arg);
/** /**
* delete the listening structure * delete the listening structure

View file

@ -146,12 +146,51 @@ comm_base_dispatch(struct comm_base* b)
} }
} }
/** send a UDP reply */
static void static void
comm_point_udp_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event), comm_point_send_udp_msg(struct comm_point *c, struct sockaddr* addr,
void* arg) socklen_t addrlen) {
ssize_t sent;
sent = sendto(c->fd, ldns_buffer_begin(c->buffer),
ldns_buffer_remaining(c->buffer), 0,
addr, addrlen);
if(sent == -1) {
log_err("sendto failed: %s", strerror(errno));
} else if((size_t)sent != ldns_buffer_remaining(c->buffer)) {
log_err("sent %d in place of %d bytes",
sent, (int)ldns_buffer_remaining(c->buffer));
}
}
static void
comm_point_udp_callback(int fd, short event, void* arg)
{ {
struct comm_point* c = (struct comm_point*)arg; struct comm_reply rep;
log_info("callback udp for %x", (int)c); ssize_t recv;
rep.c = (struct comm_point*)arg;
verbose(VERB_ALGO, "callback udp");
if(!(event&EV_READ))
return;
log_assert(rep.c && rep.c->buffer && rep.c->fd == fd);
ldns_buffer_clear(rep.c->buffer);
recv = recvfrom(fd, ldns_buffer_begin(rep.c->buffer),
ldns_buffer_remaining(rep.c->buffer), 0,
(struct sockaddr*)&rep.addr, &rep.addrlen);
if(recv == -1) {
if(errno != EAGAIN && errno != EINTR) {
log_err("recvfrom failed: %s", strerror(errno));
}
return;
}
ldns_buffer_skip(rep.c->buffer, recv);
ldns_buffer_flip(rep.c->buffer);
if((*rep.c->callback)(rep.c, rep.c->cb_arg, 0, &rep)) {
/* send back immediate reply */
comm_point_send_udp_msg(rep.c, (struct sockaddr*)&rep.addr,
rep.addrlen);
}
} }
static void static void
@ -358,3 +397,15 @@ comm_point_set_cb_arg(struct comm_point* c, void *arg)
log_assert(c); log_assert(c);
c->cb_arg = arg; c->cb_arg = arg;
} }
void comm_point_send_reply(struct comm_reply *repinfo)
{
log_assert(repinfo && repinfo->c);
if(repinfo->c->type == comm_udp) {
comm_point_send_udp_msg(repinfo->c,
(struct sockaddr*)&repinfo->addr, repinfo->addrlen);
} else {
log_info("tcp reply");
}
}

View file

@ -55,13 +55,15 @@
#include "config.h" #include "config.h"
struct comm_point; struct comm_point;
struct comm_reply;
/* internal event notification data storage structure. */ /* internal event notification data storage structure. */
struct internal_event; struct internal_event;
struct internal_base; struct internal_base;
/** callback from communication point function type */ /** callback from communication point function type */
typedef int comm_point_callback_t(struct comm_point*, void*, int); typedef int comm_point_callback_t(struct comm_point*, void*, int,
struct comm_reply*);
/** /**
* A communication point dispatcher. Thread specific. * A communication point dispatcher. Thread specific.
@ -142,10 +144,15 @@ struct comm_point {
nonzero. If nonzero, it is an errno value. nonzero. If nonzero, it is an errno value.
If the connection is closed (by remote end) then the If the connection is closed (by remote end) then the
callback is called with error set to -1. callback is called with error set to -1.
If a timeout happens on the connection, the error is set to -2.
The reply_info can be copied if the reply needs to happen at a
later time. It consists of a struct with commpoint and address.
It can be passed to a msg send routine some time later.
Note the reply information is temporary and must be copied.
declare as: declare as:
int my_callback(struct comm_point* c, void* my_arg, int my_callback(struct comm_point* c, void* my_arg, int error,
int timeout, int error); struct comm_reply *reply_info);
if the routine returns 0, nothing is done. if the routine returns 0, nothing is done.
Notzero, the buffer will be sent back to client. Notzero, the buffer will be sent back to client.
@ -157,6 +164,18 @@ struct comm_point {
void *cb_arg; void *cb_arg;
}; };
/**
* Reply information for a communication point.
*/
struct comm_reply {
/** the comm_point with fd to send reply on to. */
struct comm_point *c;
/** the address (for UDP based communication) */
struct sockaddr_storage addr;
/** length of address */
socklen_t addrlen;
};
/** /**
* Create a new comm base. * Create a new comm base.
* @return: the new comm base. NULL on error. * @return: the new comm base. NULL on error.
@ -232,4 +251,10 @@ void comm_point_delete(struct comm_point* c);
*/ */
void comm_point_set_cb_arg(struct comm_point* c, void *arg); void comm_point_set_cb_arg(struct comm_point* c, void *arg);
/**
* Send reply. Put message into commpoint buffer.
* @param repinfo: The reply info copied from a commpoint callback call.
*/
void comm_point_send_reply(struct comm_reply *repinfo);
#endif /* NET_EVENT_H */ #endif /* NET_EVENT_H */