Get sync messages working with new async code.

This commit is contained in:
Sara Dickinson 2015-04-27 15:32:57 +01:00
parent 3de15ad782
commit 4e6e66fc77
2 changed files with 122 additions and 60 deletions

View File

@ -68,11 +68,11 @@ getdns_port_array[GETDNS_PORT_LAST] = {
GETDNS_PORT_NUM_TLS
};
// char*
// getdns_port_str_array[] = {
// "53",
// "1021"
// };
char*
getdns_port_str_array[] = {
GETDNS_PORT_STR_TCP,
GETDNS_PORT_STR_TLS
};
/* Private functions */
getdns_return_t create_default_namespaces(struct getdns_context *context);
@ -672,9 +672,7 @@ set_os_defaults(struct getdns_context *context)
getdns_port_type_t port_type = GETDNS_PORT_FIRST;
for (; port_type < GETDNS_PORT_LAST; port_type++) {
// TODO[TLS]: Seeing strange crash in ub_create_ctx when using the loop here....
fprintf(stderr,"creating upstream %s\n", parse);
if ((s = getaddrinfo(parse, "53", /*getdns_port_str_array[port_type],*/ &hints, &result)))
if ((s = getaddrinfo(parse, getdns_port_str_array[port_type], &hints, &result)))
continue;
/* No lookups, so maximal 1 result */

View File

@ -45,6 +45,9 @@
#define STUB_TCP_AGAIN -2
#define STUB_TCP_ERROR -1
/*TODO[TLS]: REMOVE!!!!!*/
#define TLS_DEBUG 1
static time_t secret_rollover_time = 0;
static uint32_t secret = 0;
static uint32_t prev_secret = 0;
@ -57,6 +60,8 @@ static int connect_to_upstream(getdns_upstream *upstream,
getdns_context *context);
static void upstream_schedule_netreq(getdns_upstream *upstream,
getdns_network_req *netreq);
static void netreq_upstream_read_cb(void *userarg);
static void netreq_upstream_write_cb(void *userarg);
static void
rollover_secret()
@ -318,7 +323,9 @@ static void
upstream_erred(getdns_upstream *upstream)
{
getdns_network_req *netreq;
fprintf(stderr,"[TLS]: upstream_erred\n");
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: ERROR(upstream_erred)\n");
#endif
while ((netreq = upstream->write_queue)) {
stub_cleanup(netreq);
netreq->state = NET_REQ_FINISHED;
@ -351,7 +358,9 @@ priv_getdns_cancel_stub_request(getdns_network_req *netreq)
static void
stub_erred(getdns_network_req *netreq)
{
fprintf(stderr,"[TLS]: stub_erred\n");
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: ERROR(stub_erred)\n");
#endif
stub_next_upstream(netreq);
stub_cleanup(netreq);
/* TODO[TLS]: When we get an error (which is probably a timeout) and are
@ -364,7 +373,9 @@ stub_erred(getdns_network_req *netreq)
static void
stub_timeout_cb(void *userarg)
{
fprintf(stderr,"[TLS]: stub_timeout_cb\n");
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: TIMEOUT(stub_timeout_cb)\n");
#endif
getdns_network_req *netreq = (getdns_network_req *)userarg;
stub_next_upstream(netreq);
@ -652,8 +663,9 @@ create_tls_object(getdns_context *context, int fd)
static int
do_tls_handshake(getdns_upstream *upstream)
{
fprintf(stderr,"[TLS]: do_tls_handshake\n");
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: TLS(do_tls_handshake)\n");
#endif
int r;
int want;
@ -684,7 +696,6 @@ do_tls_handshake(getdns_upstream *upstream)
SSL_free(upstream->tls_obj);
upstream->tls_obj = NULL;
upstream->tls_hs_state = GETDNS_HS_FAILED;
upstream->fd = -1;
return STUB_TLS_SETUP_ERROR;
}
}
@ -699,44 +710,83 @@ do_tls_handshake(getdns_upstream *upstream)
/* TODO[TLS]: Make generic function for switching transport */
/* TODO[TLS]: Should think about fallback on read error aswell.*/
static int
fallback_on_tls_write_error(getdns_network_req *netreq) {
fprintf(stderr,"[TLS]: method: fallback_on_tls_write_error\n");
static getdns_upstream*
pick_and_connect_to_fallback_upstream(getdns_network_req *netreq)
{
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: FALLBACK(pick_and_connect_to_fallback_upstream)\n");
#endif
getdns_base_transport_t *next_transport = netreq->dns_base_transport;
if (*(++next_transport) != GETDNS_BASE_TRANSPORT_TCP)
/* TODO[TLS]: Fallback through upstreams....?*/
return STUB_TCP_ERROR;
return NULL;
getdns_upstream *new_upstream = pick_upstream(netreq, *next_transport);
/* TODO[TLS]: Fallback through upstreams....?*/
if (!new_upstream)
return NULL;
int fd = connect_to_upstream(new_upstream, *next_transport, netreq->owner->context);
if (fd == -1)
return NULL;
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: FALLBACK(pick_and_connect_to_fallback_upstream): now using fd %d \n", new_upstream->fd);
#endif
return new_upstream;
}
getdns_upstream *upstream = netreq->upstream;
/* Remove from queue, clearing event if we are the last*/
static int
move_netreq(getdns_network_req *netreq, getdns_upstream *upstream, getdns_upstream *new_upstream)
{
/* Remove from queue, clearing event and fd if we are the last*/
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: FALLBACK(move_netreq)\n");
#endif
if (!(upstream->write_queue = netreq->write_queue_tail)) {
upstream->write_queue_last = NULL;
upstream->event.write_cb = NULL;
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
close(upstream->fd);
upstream->fd = -1;
}
netreq->write_queue_tail = NULL;
getdns_upstream *new_upstream = pick_upstream(netreq, *next_transport);
/* TODO[TLS]: Fallback through upstreams....?*/
if (!new_upstream)
return STUB_TCP_ERROR;
int fd = connect_to_upstream(new_upstream, *next_transport, netreq->owner->context);
if (fd == -1)
return STUB_TCP_ERROR;
fprintf(stderr,"[TLS]: tcp_fallback to %d \n", new_upstream->fd);
/* Schedule with the new upstream */
netreq->upstream = new_upstream;
upstream_schedule_netreq(new_upstream, netreq);
/* TODO[TLS]: Timout need to be adjusted and rescheduled on the new fd ....*/
/* Note, setup timeout should be shorter than message timeout for
* messages with fallback or don't have time to re-try. */
// GETDNS_SCHEDULE_EVENT(
// dnsreq->loop, upstream->fd, dnsreq->context->timeout,
// getdns_eventloop_event_init(&netreq->event, netreq, NULL,
// ( dnsreq->loop != upstream->loop /* Synchronous lookup? */
// ? netreq_upstream_write_cb : NULL), stub_timeout_cb));
/* For sync messages we must re-schedule the events here.*/
if (netreq->owner->loop != upstream->loop) {
/* Create an event for the new upstream*/
GETDNS_CLEAR_EVENT(netreq->owner->loop, &netreq->event);
GETDNS_SCHEDULE_EVENT(
netreq->owner->loop, new_upstream->fd, netreq->owner->context->timeout,
getdns_eventloop_event_init(&netreq->event, netreq,
( new_upstream->netreq_by_query_id.count ?
netreq_upstream_read_cb : NULL ),
( new_upstream->write_queue ?
netreq_upstream_write_cb : NULL),
stub_timeout_cb));
/* Now one for the old upstream. Must schedule this last to make sure
* it is called back first....?*/
if (upstream->write_queue) {
GETDNS_CLEAR_EVENT(netreq->owner->loop, &upstream->write_queue->event);
GETDNS_SCHEDULE_EVENT(
upstream->write_queue->owner->loop, upstream->fd,
upstream->write_queue->owner->context->timeout,
getdns_eventloop_event_init(&upstream->write_queue->event,
upstream->write_queue,
( upstream->netreq_by_query_id.count ?
netreq_upstream_read_cb : NULL ),
( upstream->write_queue ?
netreq_upstream_write_cb : NULL),
stub_timeout_cb));
}
}
return STUB_TCP_AGAIN;
}
@ -757,22 +807,17 @@ check_tls(getdns_upstream* upstream)
socklen_t len = (socklen_t)sizeof(error);
/* TODO: This doesn't handle the case where the far end doesn't do a reset
* as is the case with e.g. 8.8.8.8. For that case the timeout kicks in
* and the user callback fails the message without the chance to fallback...
* Note that acutally the TCP code doesn't check the connection state before
* doing a first write either....
* Perhaps we should have a write_timeout_cb on the write and then schedule
* the stub_timeout_cb for matching the response??? */
* and the user callback fails the message without the chance to fallback.*/
getsockopt(upstream->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
if (error == EINPROGRESS || error == EWOULDBLOCK) {
fprintf(stderr,"[TLS]: blocking.......\n");
if (error == EINPROGRESS || error == EWOULDBLOCK)
return STUB_TCP_AGAIN; /* try again */
}
else if (error != 0) {
fprintf(stderr,"[TLS]: died gettting connection\n");
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: TLS(check_tls): died gettting connection\n");
#endif
SSL_free(upstream->tls_obj);
upstream->tls_obj = NULL;
upstream->tls_hs_state = GETDNS_HS_FAILED;
upstream->fd = -1;
return STUB_TLS_SETUP_ERROR;
}
@ -860,8 +905,6 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp, struct mem_funcs
return GLDNS_ID_WIRE(tcp->read_buf);
}
static void netreq_upstream_read_cb(void *userarg);
static void netreq_upstream_write_cb(void *userarg);
static void
upstream_read_cb(void *userarg)
{
@ -872,8 +915,10 @@ upstream_read_cb(void *userarg)
uint16_t query_id;
intptr_t query_id_intptr;
fprintf(stderr,"[TLS]: upstream_read_cb on %d\n", upstream->fd);
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: **********CALLBACK***********\n");
fprintf(stderr,"[TLS]: READ(upstream_read_cb): on %d\n", upstream->fd);
#endif
if (upstream->dns_base_transport == GETDNS_BASE_TRANSPORT_TLS)
q = stub_tls_read(upstream, &upstream->tcp,
@ -1154,12 +1199,15 @@ static void
upstream_write_cb(void *userarg)
{
getdns_upstream *upstream = (getdns_upstream *)userarg;
getdns_upstream *new_upstream;
getdns_network_req *netreq = upstream->write_queue;
getdns_dns_req *dnsreq = netreq->owner;
int q;
fprintf(stderr,"[TLS]: method: upstream_write_cb %d\n", upstream->fd);
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: **********CALLBACK***********\n");
fprintf(stderr,"[TLS]: WRITE(upstream_write_cb): upstream fd %d, SEND netreq %p \n", upstream->fd, netreq);
#endif
if (upstream->dns_base_transport == GETDNS_BASE_TRANSPORT_TLS)
q = stub_tls_write(upstream, &upstream->tcp, netreq);
@ -1177,14 +1225,18 @@ upstream_write_cb(void *userarg)
case STUB_TLS_SETUP_ERROR:
/* Could not complete the TLS set up. Need to fallback on this upstream
* if possible.*/
if (fallback_on_tls_write_error(netreq) == STUB_TCP_ERROR)
new_upstream = pick_and_connect_to_fallback_upstream(netreq);
if (!new_upstream)
//TODO[TLS]: Need a different error case here for msg_erred?
stub_erred(netreq);
if (move_netreq(netreq, upstream, new_upstream) == STUB_TCP_ERROR)
//TODO[TLS]: Need a different error case here for msg_erred?
stub_erred(netreq);
return;
default:
netreq->query_id = (uint16_t) q;
fprintf(stderr,"[TLS]: method: upstream_write_cb, successfull write %d\n", upstream->fd);
fprintf(stderr, "[TLS]: WRITE(upstream_write_cb): successfull write on fd %d\n", upstream->fd);
/* Unqueue the netreq from the write_queue */
if (!(upstream->write_queue = netreq->write_queue_tail)) {
@ -1224,7 +1276,6 @@ upstream_write_cb(void *userarg)
static void
netreq_upstream_write_cb(void *userarg)
{
fprintf(stderr,"[TLS]: method: SYNC netreq_upstream_write_cb \n");
upstream_write_cb(((getdns_network_req *)userarg)->upstream);
}
@ -1235,7 +1286,9 @@ upstream_schedule_netreq(getdns_upstream *upstream, getdns_network_req *netreq)
assert(upstream->fd >= 0);
assert(upstream->loop);
fprintf(stderr,"[TLS]: method: upstream_schedule_netreq %d\n", upstream->fd);
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: SCHEDULE(upstream_schedule_netreq): fd %d\n", upstream->fd);
#endif
/* Append netreq to write_queue */
if (!upstream->write_queue) {
@ -1280,10 +1333,19 @@ connect_to_upstream(getdns_upstream *upstream, getdns_base_transport_t transport
getdns_context *context)
{
if ((transport == GETDNS_BASE_TRANSPORT_TCP ||
transport == GETDNS_BASE_TRANSPORT_TLS)
&& upstream->fd != -1) {
fprintf(stderr,"[TLS]: method: tcp_connect using existing fd %d\n", upstream->fd);
if (transport == GETDNS_BASE_TRANSPORT_TCP && upstream->fd != -1) {
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: CONNECT(connect_to_upstream): tcp_connect using existing TCP fd %d\n", upstream->fd);
#endif
return upstream->fd;
}
if (transport == GETDNS_BASE_TRANSPORT_TLS &&
!(upstream->tls_hs_state == GETDNS_HS_FAILED
|| upstream->tls_hs_state == GETDNS_HS_NONE)) {
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: CONNECT(connect_to_upstream): tcp_connect using existing TLS fd %d\n", upstream->fd);
#endif
return upstream->fd;
}
@ -1320,7 +1382,9 @@ connect_to_upstream(getdns_upstream *upstream, getdns_base_transport_t transport
upstream->loop = context->extension;
upstream->fd = fd;
}
fprintf(stderr,"[TLS]: method: tcp_connect created new connection %d\n", fd);
#ifdef TLS_DEBUG
fprintf(stderr,"[TLS]: CONNECT(connect_to_upstream): created new connection %d\n", fd);
#endif
return fd;
}