/* adns.c, liboop, copyright 1999 Dan Egnor
This is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License, version 2.1 or later.
See the file COPYING for details. */
#ifdef HAVE_ADNS
#include "oop.h"
#include "adns.h"
#include "oop-adns.h"
#include <assert.h>
#ifdef HAVE_STRING_H
#include <string.h> /* Needed on NetBSD1.1/SPARC due to bzero/FD_ZERO. */
#endif
#ifdef HAVE_STRINGS_H
#include <strings.h> /* Needed on AIX 4.2 due to bzero/FD_ZERO. */
#endif
struct oop_adapter_adns {
oop_source *source;
oop_adapter_select *select;
adns_state state;
int count;
};
struct oop_adns_query {
oop_adapter_adns *a;
adns_query query;
oop_adns_call *call;
void *data;
};
static oop_call_select on_select;
static oop_call_time on_process;
static void set_select(oop_adapter_adns *);
oop_adapter_adns *oop_adns_new(
oop_source *source,
adns_initflags flags,FILE *diag)
{
oop_adapter_adns *a = oop_malloc(sizeof(*a));
if (NULL == a) return NULL;
a->select = NULL;
a->state = NULL;
if (adns_init(&a->state,flags | adns_if_noautosys,diag)
|| (NULL == (a->select = oop_select_new(source,on_select,a)))) {
if (NULL != a->state) adns_finish(a->state);
if (NULL != a->select) oop_select_delete(a->select);
oop_free(a);
return NULL;
}
a->source = source;
a->count = 0;
return a;
}
void oop_adns_delete(oop_adapter_adns *a) {
assert(0 == a->count &&
"deleting oop_adapter_adns with outstanding queries");
a->source->cancel_time(a->source,OOP_TIME_NOW,on_process,a);
oop_select_delete(a->select);
adns_finish(a->state);
oop_free(a);
}
oop_adns_query *oop_adns_submit(
oop_adapter_adns *a,int *errcode,
const char *owner,adns_rrtype type,adns_queryflags flags,
oop_adns_call *call,void *data)
{
oop_adns_query *q = oop_malloc(sizeof(*q));
int err;
if (NULL == q) return NULL;
err = adns_submit(a->state,owner,type,flags,q,&q->query);
if (errcode) *errcode = err;
if (err) {
oop_free(q);
return NULL;
}
q->a = a;
q->call = call;
q->data = data;
++q->a->count;
set_select(a);
return q;
}
oop_adns_query *oop_adns_submit_reverse(
oop_adapter_adns *a,int *errcode,
const struct sockaddr *addr,adns_rrtype type,adns_queryflags flags,
oop_adns_call *call,void *data)
{
oop_adns_query *q = oop_malloc(sizeof(*q));
int err;
if (NULL == q) return NULL;
err = adns_submit_reverse(a->state,addr,type,flags,q,&q->query);
if (errcode) *errcode = err;
if (err) {
oop_free(q);
return NULL;
}
q->a = a;
q->call = call;
q->data = data;
++q->a->count;
set_select(a);
return q;
}
void oop_adns_cancel(oop_adns_query *q) {
adns_cancel(q->query);
--q->a->count;
set_select(q->a);
oop_free(q);
}
static void set_select(oop_adapter_adns *a) {
fd_set rfd,wfd,xfd;
struct timeval buf,*out = NULL,now;
int maxfd = 0;
FD_ZERO(&rfd);
FD_ZERO(&wfd);
FD_ZERO(&xfd);
gettimeofday(&now,NULL);
adns_beforeselect(a->state,&maxfd,&rfd,&wfd,&xfd,&out,&buf,&now);
oop_select_set(a->select,maxfd,&rfd,&wfd,&xfd,out);
}
static void *on_process(oop_source *source,struct timeval when,void *data) {
oop_adapter_adns *a = (oop_adapter_adns *) data;
adns_answer *r;
adns_query query;
oop_adns_query *q = NULL;
void *adns_data;
query = NULL;
if (0 == adns_check(a->state,&query,&r,&adns_data)) {
q = (oop_adns_query *) adns_data;
assert(query == q->query);
}
set_select(a);
if (NULL != q) {
oop_adns_call *call = q->call;
void *data = q->data;
assert(a == q->a);
--q->a->count;
oop_free(q);
source->on_time(source,when,on_process,a);
return call(a,r,data);
}
return OOP_CONTINUE;
}
static void *on_select(
oop_adapter_select *select,
int num,fd_set *rfd,fd_set *wfd,fd_set *xfd,
struct timeval now,void *data)
{
oop_adapter_adns *a = (oop_adapter_adns *) data;
adns_afterselect(a->state,num,rfd,wfd,xfd,&now);
return on_process(a->source,OOP_TIME_NOW,a);
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1