More bug fixes and tidy up

This commit is contained in:
Sara Dickinson 2015-06-26 14:27:21 +01:00
parent ddd90e29c5
commit 8925fb22fc
1 changed files with 39 additions and 42 deletions

View File

@ -385,6 +385,22 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport)
return fd; return fd;
} }
static int
tcp_connected(getdns_upstream *upstream) {
/* Already tried and failed, so let the fallback code take care of things */
if (upstream->fd == -1 || upstream->tcp.write_error != 0)
return STUB_TCP_ERROR;
int error = 0;
socklen_t len = (socklen_t)sizeof(error);
getsockopt(upstream->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
if (error == EINPROGRESS || error == EWOULDBLOCK)
return STUB_TCP_AGAIN; /* try again */
else if (error != 0)
return STUB_TCP_ERROR;
return 0;
}
/**************************/ /**************************/
/* Error/cleanup functions*/ /* Error/cleanup functions*/
/**************************/ /**************************/
@ -440,6 +456,7 @@ stub_cleanup(getdns_network_req *netreq)
if (r == upstream->write_queue_last) if (r == upstream->write_queue_last)
upstream->write_queue_last = upstream->write_queue_last =
prev_r ? prev_r : NULL; prev_r ? prev_r : NULL;
netreq->write_queue_tail = NULL;
break; break;
} }
upstream_reschedule_events(upstream, netreq->owner->context->idle_timeout); upstream_reschedule_events(upstream, netreq->owner->context->idle_timeout);
@ -694,19 +711,9 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
uint16_t query_id; uint16_t query_id;
intptr_t query_id_intptr; intptr_t query_id_intptr;
/* Move to generic function*/ int q = tcp_connected(netreq->upstream);
if (q != 0)
/* Already tried and failed, so let the fallback code take care of things */ return q;
if (netreq->upstream->tcp.write_error != 0)
return STUB_TCP_ERROR;
int error = 0;
socklen_t len = (socklen_t)sizeof(error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
if (error == EINPROGRESS || error == EWOULDBLOCK)
return STUB_TCP_AGAIN; /* try again */
else if (error != 0)
return STUB_TCP_ERROR;
/* Do we have remaining data that we could not write before? */ /* Do we have remaining data that we could not write before? */
if (! tcp->write_buf) { if (! tcp->write_buf) {
@ -926,24 +933,17 @@ tls_do_handshake(getdns_upstream *upstream)
timeout in sync mode.... Need a timer on requests really.... Worst case timeout in sync mode.... Need a timer on requests really.... Worst case
is we add TIMEOUT_TLS to the total timeout, since TLS is likely to be is we add TIMEOUT_TLS to the total timeout, since TLS is likely to be
the first choice if it is used at all.*/ the first choice if it is used at all.*/
if (netreq && (netreq->event.read_cb || netreq->event.write_cb)) { if (netreq && (netreq->event.read_cb || netreq->event.write_cb))
GETDNS_CLEAR_EVENT(netreq->owner->loop, &netreq->event); upstream_reschedule_netreq_events(upstream, netreq);
GETDNS_SCHEDULE_EVENT(
netreq->owner->loop, upstream->fd, netreq->owner->context->timeout,
getdns_eventloop_event_init(
&netreq->event, netreq,
NULL, netreq_upstream_write_cb,
stub_timeout_cb));
}
return 0; return 0;
} }
static int static int
tls_connected(getdns_upstream* upstream) tls_connected(getdns_upstream* upstream)
{ {
/* Already have a connection*/ /* Already have a TLS connection*/
if (upstream->tls_hs_state == GETDNS_HS_DONE && if (upstream->tls_hs_state == GETDNS_HS_DONE &&
(upstream->tls_obj != NULL) && (upstream->fd != -1)) (upstream->tls_obj != NULL))
return 0; return 0;
/* Already tried and failed, so let the fallback code take care of things */ /* Already tried and failed, so let the fallback code take care of things */
@ -951,13 +951,12 @@ tls_connected(getdns_upstream* upstream)
return STUB_TLS_SETUP_ERROR; return STUB_TLS_SETUP_ERROR;
/* Lets make sure the connection is up before we try a handshake*/ /* Lets make sure the connection is up before we try a handshake*/
int error = 0; int q = tcp_connected(upstream);
socklen_t len = (socklen_t)sizeof(error); if (q != 0) {
getsockopt(upstream->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len); if (q == STUB_TCP_ERROR)
if (error == EINPROGRESS || error == EWOULDBLOCK) tls_cleanup(upstream);
return STUB_TCP_AGAIN; /* try again */ return q;
else if (error != 0) }
return tls_cleanup(upstream);
return tls_do_handshake(upstream); return tls_do_handshake(upstream);
} }
@ -1400,6 +1399,8 @@ upstream_write_cb(void *userarg)
/* Problem with the TCP connection itself. Need to fallback.*/ /* Problem with the TCP connection itself. Need to fallback.*/
DEBUG_STUB("--- WRITE: Setting write error\n"); DEBUG_STUB("--- WRITE: Setting write error\n");
upstream->tcp.write_error = 1; upstream->tcp.write_error = 1;
/* Use policy of trying next upstream in this case. Need more work on
* TCP connection re-use.*/
stub_next_upstream(netreq); stub_next_upstream(netreq);
/* Fall through */ /* Fall through */
case STUB_TLS_SETUP_ERROR: case STUB_TLS_SETUP_ERROR:
@ -1558,7 +1559,6 @@ int
upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport, upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport,
getdns_dns_req *dnsreq) getdns_dns_req *dnsreq)
{ {
//DEBUG_STUB(" %s\n", __FUNCTION__);
int fd = -1; int fd = -1;
switch(transport) { switch(transport) {
case GETDNS_TRANSPORT_UDP: case GETDNS_TRANSPORT_UDP:
@ -1667,14 +1667,6 @@ fallback_on_write(getdns_network_req *netreq)
DEBUG_STUB("#-----> %s: %p TYPE: %d\n", __FUNCTION__, netreq, netreq->request_type); DEBUG_STUB("#-----> %s: %p TYPE: %d\n", __FUNCTION__, netreq, netreq->request_type);
getdns_upstream *upstream = netreq->upstream; getdns_upstream *upstream = netreq->upstream;
/* Remove from queue and deal with the old upstream events*/
if (!(upstream->write_queue = netreq->write_queue_tail)) {
upstream->write_queue_last = NULL;
upstream->event.write_cb = NULL;
}
netreq->write_queue_tail = NULL;
upstream_reschedule_events(upstream, netreq->owner->context->idle_timeout);
/* Try to find a fallback transport*/ /* Try to find a fallback transport*/
getdns_return_t result = priv_getdns_submit_stub_request(netreq); getdns_return_t result = priv_getdns_submit_stub_request(netreq);
@ -1732,7 +1724,8 @@ upstream_reschedule_events(getdns_upstream *upstream, size_t idle_timeout) {
static void static void
upstream_reschedule_netreq_events(getdns_upstream *upstream, upstream_reschedule_netreq_events(getdns_upstream *upstream,
getdns_network_req *netreq) { getdns_network_req *netreq) {
DEBUG_STUB("# %s: %p: TYPE: %d\n", __FUNCTION__, netreq, netreq->request_type); DEBUG_STUB("# %s: %p: TYPE: %d\n", __FUNCTION__,
netreq, netreq->request_type);
getdns_dns_req *dnsreq = netreq->owner; getdns_dns_req *dnsreq = netreq->owner;
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
if (upstream->netreq_by_query_id.count || upstream->write_queue) if (upstream->netreq_by_query_id.count || upstream->write_queue)
@ -1746,7 +1739,11 @@ upstream_reschedule_netreq_events(getdns_upstream *upstream,
stub_timeout_cb)); stub_timeout_cb));
else { else {
/* This is a sync call, and the connection is idle. But we can't set a /* This is a sync call, and the connection is idle. But we can't set a
* timeout since we won't have an event loop if there are no netreqs * timeout since we won't have an event loop if there are no netreqs.
* Could set a timer and check it when the next req comes in but...
* chances are it will be on the same transport and if we have a new
* req the conneciton is no longer idle so probably better to re-use
* than shut and immediately open a new one!
* So we will have to be aggressive and shut the connection....*/ * So we will have to be aggressive and shut the connection....*/
DEBUG_STUB("# %s: **Closing connection %d**\n", DEBUG_STUB("# %s: **Closing connection %d**\n",
__FUNCTION__, upstream->fd); __FUNCTION__, upstream->fd);