mirror of https://github.com/getdnsapi/getdns.git
Get the async getaddress going
This commit is contained in:
parent
0c5d8b2c32
commit
ff83b43081
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include <string.h>
|
||||
#include "context.h"
|
||||
#include "util-internal.h"
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
/* stuff to make it compile pedantically */
|
||||
|
@ -60,13 +61,9 @@ static struct getdns_dict* create_ipaddr_dict_from_rdf(ldns_rdf* rdf) {
|
|||
getdns_dict *result = getdns_dict_create();
|
||||
/* set type */
|
||||
if (rt == LDNS_RDF_TYPE_A) {
|
||||
getdns_bindata type_bin = { (size_t) strlen(GETDNS_STR_IPV4),
|
||||
(uint8_t*) GETDNS_STR_IPV4 };
|
||||
getdns_dict_set_bindata(result, GETDNS_STR_ADDRESS_TYPE, &type_bin);
|
||||
getdns_dict_util_set_string(result, GETDNS_STR_ADDRESS_TYPE, GETDNS_STR_IPV4);
|
||||
} else {
|
||||
getdns_bindata type_bin = { (size_t) strlen(GETDNS_STR_IPV6),
|
||||
(uint8_t*) GETDNS_STR_IPV6 };
|
||||
getdns_dict_set_bindata(result, GETDNS_STR_ADDRESS_TYPE, &type_bin);
|
||||
getdns_dict_util_set_string(result, GETDNS_STR_ADDRESS_TYPE, GETDNS_STR_IPV6);
|
||||
}
|
||||
/* set data */
|
||||
getdns_bindata data_bin = { sz, ldns_rdf_data(rdf) };
|
||||
|
|
|
@ -508,7 +508,7 @@ getdns_dict_set_bindata(struct getdns_dict *dict, char *name, struct getdns_bind
|
|||
item->data.bindata = (struct getdns_bindata *) malloc(sizeof(struct getdns_bindata));
|
||||
if(item->data.bindata != NULL)
|
||||
{
|
||||
item->data.bindata->data = (void *) malloc(item->data.bindata->size);
|
||||
item->data.bindata->data = (void *) malloc(child_bindata->size);
|
||||
if(item->data.bindata->data != NULL)
|
||||
{
|
||||
item->data.bindata->size = child_bindata->size;
|
||||
|
|
|
@ -64,25 +64,83 @@
|
|||
/* stuff to make it compile pedantically */
|
||||
#define UNUSED_PARAM(x) ((void)(x))
|
||||
|
||||
/* libevent callback for a network request */
|
||||
static void dns_req_callback(int fd, short events, void *arg) {
|
||||
getdns_dns_req *request = (getdns_dns_req*) arg;
|
||||
uint8_t data[1500];
|
||||
if (events & EV_READ) {
|
||||
while (1) {
|
||||
ssize_t r = recv(fd, data, sizeof(data), MSG_DONTWAIT);
|
||||
if (r < 0) {
|
||||
if (errno == EAGAIN) return;
|
||||
/* otherwise failed */
|
||||
request->user_callback(request->context,
|
||||
GETDNS_CALLBACK_ERROR,
|
||||
NULL, request->user_pointer,
|
||||
request->trans_id);
|
||||
}
|
||||
/* parse a packet */
|
||||
ldns_pkt* pkt = NULL;
|
||||
ldns_wire2pkt(&pkt, data, r);
|
||||
if (pkt == NULL) {
|
||||
/* otherwise failed */
|
||||
request->user_callback(request->context,
|
||||
GETDNS_CALLBACK_ERROR,
|
||||
NULL, request->user_pointer,
|
||||
request->trans_id);
|
||||
} else {
|
||||
/* success */
|
||||
getdns_dict* response = create_getdns_response(pkt);
|
||||
ldns_pkt_free(pkt);
|
||||
request->user_callback(request->context, GETDNS_CALLBACK_COMPLETE,
|
||||
response, request->user_pointer,
|
||||
request->trans_id);
|
||||
}
|
||||
}
|
||||
} else if (events & EV_TIMEOUT) {
|
||||
request->user_callback(request->context, GETDNS_CALLBACK_TIMEOUT,
|
||||
NULL, request->user_pointer, request->trans_id);
|
||||
}
|
||||
/* clean up ns since right now it's 1:1 with the request */
|
||||
nameserver_free(request->current_req->ns);
|
||||
/* cleanup the request */
|
||||
dns_req_free(request);
|
||||
}
|
||||
|
||||
/* submit a new request to the event loop */
|
||||
static getdns_return_t submit_new_dns_req(getdns_dns_req *request) {
|
||||
getdns_dict *nameserver = NULL;
|
||||
getdns_dict *ip_dict = NULL;
|
||||
getdns_context_t context = request->context;
|
||||
struct sockaddr_storage sockdata;
|
||||
uint8_t* data = NULL;
|
||||
size_t data_len = 0;
|
||||
struct timeval timeout = { 5, 0 };
|
||||
|
||||
/* get first upstream server */
|
||||
getdns_list_get_dict(context->upstream_list, 0, &nameserver);
|
||||
if (!nameserver) {
|
||||
getdns_list_get_dict(context->upstream_list, 0, &ip_dict);
|
||||
if (!ip_dict) {
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
/* setup socket */
|
||||
if (dict_to_sockaddr(nameserver, &sockdata) != GETDNS_RETURN_GOOD) {
|
||||
/* get the nameserver */
|
||||
getdns_nameserver *ns = nameserver_new_from_ip_dict(context, ip_dict);
|
||||
if (!ns) {
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
evutil_socket_t sock = socket(sockdata.ss_family, SOCK_DGRAM, 0);
|
||||
evutil_make_socket_closeonexec(sock);
|
||||
evutil_make_socket_nonblocking(sock);
|
||||
|
||||
request->current_req->ns = ns;
|
||||
|
||||
/* schedule on the loop */
|
||||
ns->event = event_new(context->event_base, request->current_req->ns->socket,
|
||||
EV_READ | EV_TIMEOUT,
|
||||
dns_req_callback, request);
|
||||
|
||||
event_add(ns->event, &timeout);
|
||||
|
||||
/* send data */
|
||||
ldns_pkt *pkt = request->current_req->pkt;
|
||||
ldns_pkt2wire(&data, pkt, &data_len);
|
||||
send(ns->socket, data, data_len, MSG_DONTWAIT);
|
||||
free(data);
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
|
|
@ -28,4 +28,70 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "types-internal.h"
|
||||
#include "util-internal.h"
|
||||
|
||||
/* useful macros */
|
||||
#define gd_malloc(sz) context->memory_allocator(sz)
|
||||
#define gd_free(ptr) context->memory_deallocator(ptr)
|
||||
|
||||
getdns_nameserver* nameserver_new_from_ip_dict(getdns_context_t context,
|
||||
getdns_dict* ip_dict) {
|
||||
if (!context || !ip_dict) {
|
||||
return NULL;
|
||||
}
|
||||
struct sockaddr_storage sockdata;
|
||||
/* setup socket */
|
||||
if (dict_to_sockaddr(ip_dict, &sockdata) != GETDNS_RETURN_GOOD) {
|
||||
return NULL;
|
||||
}
|
||||
getdns_nameserver *result = gd_malloc(sizeof(getdns_nameserver));
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
memset(result, 0, sizeof(getdns_nameserver));
|
||||
result->context = context;
|
||||
|
||||
/* create socket */
|
||||
evutil_socket_t sock = socket(sockdata.ss_family, SOCK_DGRAM, 0);
|
||||
evutil_make_socket_closeonexec(sock);
|
||||
evutil_make_socket_nonblocking(sock);
|
||||
|
||||
result->address = sockdata;
|
||||
result->socket = sock;
|
||||
|
||||
int connected = -1;
|
||||
if (sockdata.ss_family == AF_INET) {
|
||||
connected = connect(sock, (struct sockaddr *) &sockdata, sizeof(struct sockaddr_in));
|
||||
} else if (sockdata.ss_family == AF_INET6) {
|
||||
connected = connect(sock, (struct sockaddr *) &sockdata, sizeof(struct sockaddr_in6));
|
||||
}
|
||||
if (connected != 0) {
|
||||
// sad
|
||||
nameserver_free(result);
|
||||
result= NULL;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void nameserver_free(getdns_nameserver* nameserver) {
|
||||
if (!nameserver) {
|
||||
return;
|
||||
}
|
||||
if (nameserver->event) {
|
||||
event_del(nameserver->event);
|
||||
event_free(nameserver->event);
|
||||
}
|
||||
getdns_context_t context = nameserver->context;
|
||||
evutil_closesocket(nameserver->socket);
|
||||
gd_free(nameserver);
|
||||
|
||||
}
|
||||
|
||||
/* TODO */
|
||||
getdns_dict* nameserver_to_dict(getdns_nameserver* nameserver) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,8 +49,7 @@ void network_req_free(getdns_network_req* net_req) {
|
|||
getdns_network_req* network_req_new(getdns_context_t context,
|
||||
const char* name,
|
||||
uint16_t request_type,
|
||||
struct getdns_dict* extensions,
|
||||
getdns_transaction_t *transaction_id) {
|
||||
struct getdns_dict* extensions) {
|
||||
getdns_network_req *net_req = NULL;
|
||||
ldns_pkt *pkt = NULL;
|
||||
net_req = gd_malloc(sizeof(getdns_network_req));
|
||||
|
@ -70,10 +69,6 @@ getdns_network_req* network_req_new(getdns_context_t context,
|
|||
return NULL;
|
||||
}
|
||||
net_req->pkt = pkt;
|
||||
net_req->trans_id = ldns_pkt_id(pkt);
|
||||
if (transaction_id) {
|
||||
*transaction_id = net_req->trans_id;
|
||||
}
|
||||
|
||||
return net_req;
|
||||
}
|
||||
|
@ -106,12 +101,17 @@ getdns_dns_req* dns_req_new(getdns_context_t context,
|
|||
|
||||
/* create the initial network request */
|
||||
net_req = network_req_new(context, name, request_type,
|
||||
extensions, transaction_id);
|
||||
extensions);
|
||||
if (!net_req) {
|
||||
dns_req_free(result);
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
result->trans_id = ldns_pkt_id(net_req->pkt);
|
||||
if (transaction_id) {
|
||||
*transaction_id = result->trans_id;
|
||||
}
|
||||
|
||||
result->current_req = net_req;
|
||||
net_req->owner = result;
|
||||
|
||||
|
|
|
@ -46,9 +46,9 @@ typedef struct getdns_nameserver {
|
|||
|
||||
int failed_times; /* number of times which we have given this server a chance */
|
||||
int timedout; /* number of times in a row a request has timed out */
|
||||
struct event event;
|
||||
|
||||
struct event timeout_event; /* used to keep the timeout for */
|
||||
struct event* event;
|
||||
|
||||
/* when we next probe this server. */
|
||||
/* Valid if state == 0 */
|
||||
/* Outstanding probe request for this nameserver, if any */
|
||||
|
@ -76,12 +76,7 @@ typedef struct getdns_network_req {
|
|||
int tx_count; /* the number of times that this packet has been sent */
|
||||
|
||||
/* not owned */
|
||||
struct nameserver *ns; /* the server which we last sent it (unused) */
|
||||
getdns_dict *upstream_server;
|
||||
|
||||
struct event timeout_event;
|
||||
|
||||
getdns_transaction_t trans_id; /* the transaction id */
|
||||
getdns_nameserver *ns; /* the server which we sent to */
|
||||
|
||||
unsigned transmit_me :1; /* needs to be transmitted */
|
||||
|
||||
|
@ -103,6 +98,8 @@ typedef struct getdns_dns_req {
|
|||
getdns_callback_t user_callback;
|
||||
void *user_pointer;
|
||||
|
||||
getdns_transaction_t trans_id; /* the transaction id */
|
||||
|
||||
|
||||
int pending_cb; /* Waiting for its callback to be invoked; not
|
||||
* owned by event base any more. */
|
||||
|
@ -119,8 +116,7 @@ void network_req_free(getdns_network_req* net_req);
|
|||
getdns_network_req* network_req_new(getdns_context_t context,
|
||||
const char* name,
|
||||
uint16_t request_type,
|
||||
struct getdns_dict* extensions,
|
||||
getdns_transaction_t *transaction_id);
|
||||
struct getdns_dict* extensions);
|
||||
|
||||
|
||||
/* dns request utils */
|
||||
|
@ -134,9 +130,12 @@ getdns_dns_req* dns_req_new(getdns_context_t context,
|
|||
void dns_req_free(getdns_dns_req* req);
|
||||
|
||||
/* nameserver utils */
|
||||
getdns_nameserver* nameserver_new_from_ip_dict(getdns_dict* ip_dict);
|
||||
getdns_nameserver* nameserver_new_from_ip_dict(getdns_context_t context,
|
||||
getdns_dict* ip_dict);
|
||||
|
||||
void nameserver_free(getdns_nameserver* nameserver);
|
||||
|
||||
getdns_dict* nameserver_to_dict(getdns_nameserver* nameserver);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,6 +30,15 @@
|
|||
|
||||
#include "util-internal.h"
|
||||
|
||||
getdns_return_t getdns_dict_util_set_string(getdns_dict* dict, char* name,
|
||||
char* value) {
|
||||
char data[strlen(value) + 1];
|
||||
data[strlen(value)] = 0;
|
||||
memcpy(data, value, strlen(value));
|
||||
getdns_bindata type_bin = { strlen(value) + 1, (uint8_t*) data };
|
||||
return getdns_dict_set_bindata(dict, name, &type_bin);
|
||||
}
|
||||
|
||||
getdns_return_t dict_to_sockaddr(getdns_dict* ns, struct sockaddr_storage* output) {
|
||||
struct getdns_bindata *address_type = NULL;
|
||||
struct getdns_bindata *address_data = NULL;
|
||||
|
@ -42,7 +51,7 @@ getdns_return_t dict_to_sockaddr(getdns_dict* ns, struct sockaddr_storage* outpu
|
|||
if (!address_type || !address_data) {
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
if (strcmp((char*) address_type->data, GETDNS_STR_IPV4)) {
|
||||
if (strcmp((char*) address_type->data, GETDNS_STR_IPV4) == 0) {
|
||||
/* data is an in_addr_t */
|
||||
struct sockaddr_in* addr = (struct sockaddr_in*) output;
|
||||
addr->sin_family = AF_INET;
|
||||
|
@ -75,5 +84,14 @@ ldns_pkt *create_new_pkt(getdns_context_t context,
|
|||
return pkt;
|
||||
}
|
||||
|
||||
|
||||
getdns_dict *create_getdns_response(ldns_pkt* pkt) {
|
||||
char* data = ldns_pkt2str(pkt);
|
||||
getdns_dict* result = getdns_dict_create();
|
||||
getdns_bindata bindata = {
|
||||
strlen(data), (uint8_t*) data
|
||||
};
|
||||
getdns_dict_set_bindata(result, "pkt", &bindata);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,3 +38,10 @@ ldns_pkt *create_new_pkt(getdns_context_t context,
|
|||
const char* name,
|
||||
uint16_t request_type,
|
||||
struct getdns_dict* extensions);
|
||||
|
||||
getdns_dict *create_getdns_response(ldns_pkt* pkt);
|
||||
|
||||
/* dict util */
|
||||
getdns_return_t getdns_dict_util_set_string(getdns_dict* dict, char* name,
|
||||
char* value);
|
||||
|
||||
|
|
Loading…
Reference in New Issue