Add context idle timeout

This commit is contained in:
Sara Dickinson 2015-06-18 17:11:11 +01:00
parent 8dd8d90e74
commit 68dfb15706
10 changed files with 106 additions and 7 deletions

View File

@ -2233,6 +2233,16 @@ getdns_context_set_timeout(
<p class=cont>Specifies number of milliseconds the API will wait for request to return.
The default is <span class=default>not specified</span>.</p>
<div class=forh>
getdns_return_t
getdns_context_set_idle_timeout(
getdns_context *context,
uint64_t timeout
);</div>
<p class=cont>Specifies number of milliseconds the API will leave an idle TCP, TLS or STARTTLS
connection open for (idle means no outstanding responses and no pending queries).
The default is <span class=default>0</span>.</p>
<h2>8.4 Context for Recursive Resolvers</h2>
<div class=forh>
@ -2444,7 +2454,8 @@ The response dicts inherit the custom memory management functions and the value
<p class=descrip>Change related to <code>getdns_context_set_memory_functions</code></p>
<p class=define>GETDNS_CONTEXT_CODE_TIMEOUT</p>
<p class=descrip>Change related to <code>getdns_context_set_timeout</code></p>
<p class=define>GETDNS_CONTEXT_CODE_IDLE_TIMEOUT</p>
<p class=descrip>Change related to <code>getdns_context_set_idle_timeout</code></p>
<h2>8.11 Getting API information and current Contexts</h2>
<p>An application might want to see information about the API itself and inspect the current context.

View File

@ -63,6 +63,7 @@ static struct const_info consts_info[] = {
{ 614, "GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW", GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW_TEXT },
{ 615, "GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS", GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS_TEXT },
{ 616, "GETDNS_CONTEXT_CODE_TIMEOUT", GETDNS_CONTEXT_CODE_TIMEOUT_TEXT },
{ 617, "GETDNS_CONTEXT_CODE_IDLE_TIMEOUT", GETDNS_CONTEXT_CODE_TIMEOUT_IDLE_TEXT },
{ 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT },
{ 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT },
{ 702, "GETDNS_CALLBACK_TIMEOUT", GETDNS_CALLBACK_TIMEOUT_TEXT },

View File

@ -847,6 +847,7 @@ getdns_context_create_with_extended_memory_functions(
goto error;
result->timeout = 5000;
result->idle_timeout = 0;
result->follow_redirects = GETDNS_REDIRECTS_FOLLOW;
result->dns_root_servers = create_default_root_servers();
result->append_name = GETDNS_APPEND_NAME_ALWAYS;
@ -1387,6 +1388,27 @@ getdns_context_set_timeout(struct getdns_context *context, uint64_t timeout)
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_timeout */
/*
* getdns_context_set_idle_timeout
*
*/
getdns_return_t
getdns_context_set_idle_timeout(struct getdns_context *context, uint64_t timeout)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
if (timeout == 0) {
return GETDNS_RETURN_INVALID_PARAMETER;
}
context->idle_timeout = timeout;
dispatch_updated(context, GETDNS_CONTEXT_CODE_IDLE_TIMEOUT);
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_timeout */
/*
* getdns_context_set_follow_redirects
*
@ -2575,6 +2597,14 @@ getdns_context_get_timeout(getdns_context *context, uint64_t* value) {
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_get_idle_timeout(getdns_context *context, uint64_t* value) {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
*value = context->idle_timeout;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_get_follow_redirects(getdns_context *context,
getdns_redirects_t* value) {

View File

@ -131,6 +131,7 @@ struct getdns_context {
getdns_namespace_t *namespaces;
int namespace_count;
uint64_t timeout;
uint64_t idle_timeout;
getdns_redirects_t follow_redirects;
struct getdns_list *dns_root_servers;
getdns_append_name_t append_name;

View File

@ -242,7 +242,8 @@ typedef enum getdns_context_code_t {
GETDNS_CONTEXT_CODE_EDNS_DO_BIT = 613,
GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW = 614,
GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS = 615,
GETDNS_CONTEXT_CODE_TIMEOUT = 616
GETDNS_CONTEXT_CODE_TIMEOUT = 616,
GETDNS_CONTEXT_CODE_IDLE_TIMEOUT = 617
} getdns_context_code_t;
/**
@ -266,6 +267,7 @@ typedef enum getdns_context_code_t {
#define GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW_TEXT "Change related to getdns_context_set_dnssec_allowed_skew"
#define GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS_TEXT "Change related to getdns_context_set_memory_functions"
#define GETDNS_CONTEXT_CODE_TIMEOUT_TEXT "Change related to getdns_context_set_timeout"
#define GETDNS_CONTEXT_CODE_TIMEOUT_IDLE_TEXT "Change related to getdns_context_set_idle_timeout"
/** @}
*/
@ -973,6 +975,9 @@ getdns_context_set_limit_outstanding_queries(getdns_context *context,
getdns_return_t
getdns_context_set_timeout(getdns_context *context, uint64_t timeout);
getdns_return_t
getdns_context_set_idle_timeout(getdns_context *context, uint64_t timeout);
getdns_return_t
getdns_context_set_follow_redirects(getdns_context *context,
getdns_redirects_t value);

View File

@ -150,6 +150,9 @@ getdns_context_get_limit_outstanding_queries(getdns_context *context,
getdns_return_t
getdns_context_get_timeout(getdns_context *context, uint64_t* timeout);
getdns_return_t
getdns_context_get_idle_timeout(getdns_context *context, uint64_t* timeout);
getdns_return_t
getdns_context_get_follow_redirects(getdns_context *context,
getdns_redirects_t* value);

View File

@ -24,6 +24,7 @@ getdns_context_get_num_pending_requests
getdns_context_get_resolution_type
getdns_context_get_suffix
getdns_context_get_timeout
getdns_context_get_idle_timeout
getdns_context_get_update_callback
getdns_context_get_upstream_recursive_servers
getdns_context_process_async
@ -49,6 +50,7 @@ getdns_context_set_resolution_type
getdns_context_set_return_dnssec_status
getdns_context_set_suffix
getdns_context_set_timeout
getdns_context_set_idle_timeout
getdns_context_set_update_callback
getdns_context_set_upstream_recursive_servers
getdns_context_set_use_threads

View File

@ -539,6 +539,26 @@ stub_timeout_cb(void *userarg)
(void) getdns_context_request_timed_out(netreq->owner);
}
static void
upstream_idle_timeout_cb(void *userarg)
{
DEBUG_STUB("%s\n", __FUNCTION__);
getdns_upstream *upstream = (getdns_upstream *)userarg;
/*There is a race condition with a new request being scheduled while this happens
so take ownership of the fd asap*/
int fd = upstream->fd;
upstream->fd = -1;
upstream->event.timeout_cb = NULL;
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
upstream->tls_hs_state = GETDNS_HS_NONE;
if (upstream->tls_obj != NULL) {
SSL_shutdown(upstream->tls_obj);
SSL_free(upstream->tls_obj);
}
close(fd);
}
static void
upstream_tls_timeout_cb(void *userarg)
{
@ -1205,6 +1225,7 @@ upstream_read_cb(void *userarg)
getdns_upstream *upstream = (getdns_upstream *)userarg;
getdns_network_req *netreq;
getdns_dns_req *dnsreq;
uint64_t idle_timeout;
int q;
uint16_t query_id;
intptr_t query_id_intptr;
@ -1244,6 +1265,8 @@ upstream_read_cb(void *userarg)
upstream->tcp.read_pos - upstream->tcp.read_buf;
upstream->tcp.read_buf = NULL;
upstream->upstreams->current = 0;
/* netreq may die before setting timeout*/
idle_timeout = netreq->owner->context->idle_timeout;
/* TODO: DNSSEC */
netreq->secure = 0;
@ -1297,6 +1320,12 @@ upstream_read_cb(void *userarg)
GETDNS_SCHEDULE_EVENT(upstream->loop,
upstream->fd, TIMEOUT_FOREVER,
&upstream->event);
else {
upstream->event.timeout_cb = upstream_idle_timeout_cb;
GETDNS_SCHEDULE_EVENT(upstream->loop,
upstream->fd, idle_timeout,
&upstream->event);
}
}
}
}
@ -1657,6 +1686,7 @@ upstream_schedule_netreq(getdns_upstream *upstream, getdns_network_req *netreq)
/* Append netreq to write_queue */
if (!upstream->write_queue) {
upstream->write_queue = upstream->write_queue_last = netreq;
upstream->event.timeout_cb = NULL;
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
if (upstream->tls_hs_state == GETDNS_HS_WRITE ||
(upstream->starttls_req &&

View File

@ -152,6 +152,7 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\t-s\tSet stub resolution type (default = recursing)\n");
fprintf(out, "\t-S\tservice lookup (<type> is ignored)\n");
fprintf(out, "\t-t <timeout>\tSet timeout in miliseconds\n");
fprintf(out, "\t-e <idle_timeout>\tSet idle timeout in miliseconds\n");
fprintf(out, "\t-T\tSet transport to TCP only\n");
fprintf(out, "\t-O\tSet transport to TCP only keep connections open\n");
fprintf(out, "\t-L\tSet transport to TLS only keep connections open\n");
@ -377,20 +378,36 @@ getdns_return_t parse_args(int argc, char **argv)
break;
case 't':
if (c[1] != 0 || ++i >= argc || !*argv[i]) {
fprintf(stderr, "ttl expected "
fprintf(stderr, "timeout expected "
"after -t\n");
return GETDNS_RETURN_GENERIC_ERROR;
}
timeout = strtol(argv[i], &endptr, 10);
if (*endptr || timeout < 0) {
fprintf(stderr, "positive "
"numeric ttl expected "
"numeric timeout expected "
"after -t\n");
return GETDNS_RETURN_GENERIC_ERROR;
}
getdns_context_set_timeout(
context, timeout);
goto next;
case 'e':
if (c[1] != 0 || ++i >= argc || !*argv[i]) {
fprintf(stderr, "idle timeout expected "
"after -t\n");
return GETDNS_RETURN_GENERIC_ERROR;
}
timeout = strtol(argv[i], &endptr, 10);
if (*endptr || timeout < 0) {
fprintf(stderr, "positive "
"numeric idle timeout expected "
"after -t\n");
return GETDNS_RETURN_GENERIC_ERROR;
}
getdns_context_set_idle_timeout(
context, timeout);
goto next;
case 'T':
getdns_context_set_dns_transport(context,
GETDNS_TRANSPORT_TCP_ONLY);

View File

@ -139,7 +139,7 @@ main(int argc, char** argv)
getdns_context_run(this_context);
}
getdns_transport_t get_transport = GETDNS_TRANSPORT_UDP_ONLY;
getdns_transport_t get_transport;
return_value = getdns_context_get_dns_transport(this_context, &get_transport);
if (return_value != GETDNS_RETURN_GOOD) {
fprintf(stderr, "Trying to get transport type failed: %d\n",
@ -150,8 +150,6 @@ main(int argc, char** argv)
size_t transport_count = 0;
getdns_transport_list_t *get_transport_list;
getdns_transport_list_t tmp[1] = {GETDNS_TRANSPORT_UDP};
get_transport_list = tmp;
return_value = getdns_context_get_dns_transport_list(this_context, &transport_count, &get_transport_list);
if (return_value != GETDNS_RETURN_GOOD) {
fprintf(stderr, "Trying to get transport type failed: %d\n",
@ -161,6 +159,7 @@ main(int argc, char** argv)
for (size_t i = 0; i < transport_count; i++) {
fprintf(stderr, "Transport %d is %d\n", (int)i, get_transport_list[i]);
}
free(get_transport_list);
/* Clean up */
getdns_context_destroy(this_context);