diff --git a/spec/index.html b/spec/index.html index 7c9d1a45..b6ead3e1 100644 --- a/spec/index.html +++ b/spec/index.html @@ -2233,6 +2233,16 @@ getdns_context_set_timeout(
Specifies number of milliseconds the API will wait for request to return. The default is not specified.
+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 0.
+Change related to getdns_context_set_memory_functions
GETDNS_CONTEXT_CODE_TIMEOUT
Change related to getdns_context_set_timeout
GETDNS_CONTEXT_CODE_IDLE_TIMEOUT
+Change related to getdns_context_set_idle_timeout
An application might want to see information about the API itself and inspect the current context.
diff --git a/src/const-info.c b/src/const-info.c
index 8ed8b1fe..ecad9e5b 100644
--- a/src/const-info.c
+++ b/src/const-info.c
@@ -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 },
diff --git a/src/context.c b/src/context.c
index 873a7a7a..ec92e852 100644
--- a/src/context.c
+++ b/src/context.c
@@ -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) {
diff --git a/src/context.h b/src/context.h
index 75ba33da..040f18d3 100644
--- a/src/context.h
+++ b/src/context.h
@@ -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;
diff --git a/src/getdns/getdns.h.in b/src/getdns/getdns.h.in
index fcd0d7f1..3f133a4f 100644
--- a/src/getdns/getdns.h.in
+++ b/src/getdns/getdns.h.in
@@ -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);
diff --git a/src/getdns/getdns_extra.h b/src/getdns/getdns_extra.h
index 66fbb942..36e0497d 100644
--- a/src/getdns/getdns_extra.h
+++ b/src/getdns/getdns_extra.h
@@ -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);
diff --git a/src/libgetdns.symbols b/src/libgetdns.symbols
index f42334c1..656c29be 100644
--- a/src/libgetdns.symbols
+++ b/src/libgetdns.symbols
@@ -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
diff --git a/src/stub.c b/src/stub.c
index d9097f85..df06c9c4 100644
--- a/src/stub.c
+++ b/src/stub.c
@@ -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 &&
diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c
index 0ae3216a..83064557 100644
--- a/src/test/getdns_query.c
+++ b/src/test/getdns_query.c
@@ -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 (