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 "services/listen_dnsport.h"
/** handles callbacks from listening event interface */
static int worker_handle_request(ldns_buffer* packet, void* arg)
/** process incoming request */
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");
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;
}
struct worker* worker_init(const char* port, int do_ip4, int do_ip6,
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)
return NULL;
worker->base = comm_base_create();

View file

@ -44,7 +44,7 @@
#define DAEMON_WORKER_H
#include "config.h"
struct comm_base;
#include "util/netevent.h"
struct listen_dnsport;
/**
@ -57,6 +57,12 @@ struct worker {
/** the frontside listening interface where request events come in */
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
- 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
- links in example/ldns-testpkts.c and .h for premade packet support.

View file

@ -55,18 +55,6 @@
/** number of simultaneous open TCP connections */
#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.
* @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 hints: for getaddrinfo. family and flags have to be set by caller.
* @param bufsize: TCP buffer size.
* @param cb: callback function
* @param cb_arg: user parameter for callback function.
* @return: returns false on error.
*/
static int
listen_create_if(const char* ifname, struct listen_dnsport* front,
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 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)
return 0;
cp_udp = comm_point_create_udp(base, s, front->udp_buff,
listen_udp_callback, front);
cb, cb_arg);
if(!cp_udp) {
log_err("can't create commpoint");
close(s);
@ -228,7 +219,7 @@ listen_create_if(const char* ifname, struct listen_dnsport* front,
return 0;
}
cp_tcp = comm_point_create_tcp(base, s, TCP_COUNT, bufsize,
listen_tcp_callback, front);
cb, cb_arg);
if(!cp_tcp) {
log_err("can't create commpoint");
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->next = front->cps;
front->cps = el_udp;
comm_point_set_cb_arg(el_udp->com, el_udp);
el_tcp->com = cp_tcp;
el_tcp->next = front->cps;
front->cps = el_tcp;
comm_point_set_cb_arg(el_tcp->com, el_tcp);
return 1;
}
struct listen_dnsport*
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,
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;
int i;
@ -274,8 +263,6 @@ listen_create(struct comm_base* base, int num_ifs, const char* ifs[],
if(!front)
return NULL;
front->cps = NULL;
front->cb = cb;
front->cb_arg = cb_arg;
front->udp_buff = ldns_buffer_new(bufsize);
if(!front->udp_buff) {
free(front);
@ -304,13 +291,13 @@ listen_create(struct comm_base* base, int num_ifs, const char* ifs[],
if(num_ifs == 0) {
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);
return NULL;
}
} else for(i = 0; i<num_ifs; i++) {
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);
return NULL;
}

View file

@ -43,12 +43,9 @@
#define LISTEN_DNSPORT_H
#include "config.h"
struct comm_base;
#include "util/netevent.h"
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.
* Contains list of query-listen sockets.
@ -63,12 +60,6 @@ struct listen_dnsport {
/** list of comm points used to get incoming events */
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_tcp: listen to tcp queries.
* @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.
* @return: the malloced listening structure, ready for use. NULL on error.
*/
struct listen_dnsport* 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,
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

View file

@ -146,12 +146,51 @@ comm_base_dispatch(struct comm_base* b)
}
}
/** send a UDP reply */
static void
comm_point_udp_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
void* arg)
comm_point_send_udp_msg(struct comm_point *c, struct sockaddr* addr,
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;
log_info("callback udp for %x", (int)c);
struct comm_reply rep;
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
@ -358,3 +397,15 @@ comm_point_set_cb_arg(struct comm_point* c, void *arg)
log_assert(c);
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"
struct comm_point;
struct comm_reply;
/* internal event notification data storage structure. */
struct internal_event;
struct internal_base;
/** 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.
@ -142,10 +144,15 @@ struct comm_point {
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.
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:
int my_callback(struct comm_point* c, void* my_arg,
int timeout, int error);
int my_callback(struct comm_point* c, void* my_arg, int error,
struct comm_reply *reply_info);
if the routine returns 0, nothing is done.
Notzero, the buffer will be sent back to client.
@ -157,6 +164,18 @@ struct comm_point {
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.
* @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);
/**
* 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 */