mirror of https://github.com/getdnsapi/getdns.git
Improve TCP close handling and sync connection closing
This commit is contained in:
parent
8c61ecd024
commit
e20d679bc8
|
@ -537,6 +537,31 @@ priv_getdns_upstreams_dereference(getdns_upstreams *upstreams)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
priv_getdns_upstream_shutdown(getdns_upstream *upstream) {
|
||||||
|
/*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;
|
||||||
|
/* If the connection had a problem, but had worked this time,
|
||||||
|
* then allow re-use in the future*/
|
||||||
|
if (upstream->tcp.write_error == 1 &&
|
||||||
|
upstream->responses_received > 0)
|
||||||
|
upstream->tcp.write_error = 0;
|
||||||
|
upstream->writes_done = 0;
|
||||||
|
upstream->responses_received = 0;
|
||||||
|
if (upstream->tls_hs_state != GETDNS_HS_FAILED)
|
||||||
|
upstream->tls_hs_state = GETDNS_HS_NONE;
|
||||||
|
/* Now TLS stuff*/
|
||||||
|
if (upstream->tls_obj != NULL) {
|
||||||
|
SSL_shutdown(upstream->tls_obj);
|
||||||
|
SSL_free(upstream->tls_obj);
|
||||||
|
upstream->tls_obj = NULL;
|
||||||
|
}
|
||||||
|
if (fd != -1)
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t*
|
static uint8_t*
|
||||||
upstream_addr(getdns_upstream *upstream)
|
upstream_addr(getdns_upstream *upstream)
|
||||||
{
|
{
|
||||||
|
@ -597,7 +622,7 @@ upstream_init(getdns_upstream *upstream,
|
||||||
|
|
||||||
/* How is this upstream doing? */
|
/* How is this upstream doing? */
|
||||||
upstream->writes_done = 0;
|
upstream->writes_done = 0;
|
||||||
upstream->responses_recieved = 0;
|
upstream->responses_received = 0;
|
||||||
upstream->to_retry = 2;
|
upstream->to_retry = 2;
|
||||||
upstream->back_off = 1;
|
upstream->back_off = 1;
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ typedef struct getdns_upstream {
|
||||||
|
|
||||||
/* How is this upstream doing? */
|
/* How is this upstream doing? */
|
||||||
size_t writes_done;
|
size_t writes_done;
|
||||||
size_t responses_recieved;
|
size_t responses_received;
|
||||||
int to_retry;
|
int to_retry;
|
||||||
int back_off;
|
int back_off;
|
||||||
|
|
||||||
|
@ -241,4 +241,6 @@ void priv_getdns_context_ub_read_cb(void *userarg);
|
||||||
|
|
||||||
void priv_getdns_upstreams_dereference(getdns_upstreams *upstreams);
|
void priv_getdns_upstreams_dereference(getdns_upstreams *upstreams);
|
||||||
|
|
||||||
|
void priv_getdns_upstream_shutdown(getdns_upstream *upstreams);
|
||||||
|
|
||||||
#endif /* _GETDNS_CONTEXT_H_ */
|
#endif /* _GETDNS_CONTEXT_H_ */
|
||||||
|
|
36
src/stub.c
36
src/stub.c
|
@ -505,13 +505,7 @@ upstream_erred(getdns_upstream *upstream)
|
||||||
netreq->state = NET_REQ_FINISHED;
|
netreq->state = NET_REQ_FINISHED;
|
||||||
priv_getdns_check_dns_req_complete(netreq->owner);
|
priv_getdns_check_dns_req_complete(netreq->owner);
|
||||||
}
|
}
|
||||||
if (upstream->tls_obj) {
|
priv_getdns_upstream_shutdown(upstream);
|
||||||
SSL_shutdown(upstream->tls_obj);
|
|
||||||
SSL_free(upstream->tls_obj);
|
|
||||||
upstream->tls_obj = NULL;
|
|
||||||
}
|
|
||||||
close(upstream->fd);
|
|
||||||
upstream->fd = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -555,30 +549,20 @@ stub_timeout_cb(void *userarg)
|
||||||
(void) getdns_context_request_timed_out(netreq->owner);
|
(void) getdns_context_request_timed_out(netreq->owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
upstream_idle_timeout_cb(void *userarg)
|
upstream_idle_timeout_cb(void *userarg)
|
||||||
{
|
{
|
||||||
getdns_upstream *upstream = (getdns_upstream *)userarg;
|
getdns_upstream *upstream = (getdns_upstream *)userarg;
|
||||||
DEBUG_STUB("*** %s: **Closing connection %d**\n",
|
DEBUG_STUB("*** %s: **Closing connection %d**\n",
|
||||||
__FUNCTION__, upstream->fd);
|
__FUNCTION__, upstream->fd);
|
||||||
/*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;
|
upstream->event.timeout_cb = NULL;
|
||||||
upstream->event.read_cb = NULL;
|
upstream->event.read_cb = NULL;
|
||||||
upstream->event.write_cb = NULL;
|
upstream->event.write_cb = NULL;
|
||||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||||
if (upstream->tls_hs_state != GETDNS_HS_FAILED)
|
priv_getdns_upstream_shutdown(upstream);
|
||||||
upstream->tls_hs_state = GETDNS_HS_NONE;
|
|
||||||
if (upstream->tls_obj != NULL) {
|
|
||||||
SSL_shutdown(upstream->tls_obj);
|
|
||||||
SSL_free(upstream->tls_obj);
|
|
||||||
upstream->tls_obj = NULL;
|
|
||||||
}
|
}
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
upstream_tls_timeout_cb(void *userarg)
|
upstream_tls_timeout_cb(void *userarg)
|
||||||
|
@ -1329,7 +1313,7 @@ upstream_read_cb(void *userarg)
|
||||||
netreq->response_len =
|
netreq->response_len =
|
||||||
upstream->tcp.read_pos - upstream->tcp.read_buf;
|
upstream->tcp.read_pos - upstream->tcp.read_buf;
|
||||||
upstream->tcp.read_buf = NULL;
|
upstream->tcp.read_buf = NULL;
|
||||||
upstream->responses_recieved++;
|
upstream->responses_received++;
|
||||||
/* TODO[TLS]: I don't think we should do this for TCP. We should stay
|
/* TODO[TLS]: I don't think we should do this for TCP. We should stay
|
||||||
* on a working connection until we hit a problem.*/
|
* on a working connection until we hit a problem.*/
|
||||||
upstream->upstreams->current = 0;
|
upstream->upstreams->current = 0;
|
||||||
|
@ -1674,7 +1658,7 @@ fallback_on_write(getdns_network_req *netreq)
|
||||||
|
|
||||||
/* For sync messages we must re-schedule the events on the old upstream
|
/* For sync messages we must re-schedule the events on the old upstream
|
||||||
* here too. Must schedule this last to make sure it is called back first! */
|
* here too. Must schedule this last to make sure it is called back first! */
|
||||||
if (netreq->owner->loop != upstream->loop && upstream->write_queue)
|
if (netreq->owner->loop != upstream->loop)
|
||||||
upstream_reschedule_netreq_events(upstream, upstream->write_queue);
|
upstream_reschedule_netreq_events(upstream, upstream->write_queue);
|
||||||
|
|
||||||
if (result != GETDNS_RETURN_GOOD)
|
if (result != GETDNS_RETURN_GOOD)
|
||||||
|
@ -1751,13 +1735,7 @@ upstream_reschedule_netreq_events(getdns_upstream *upstream,
|
||||||
* 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);
|
||||||
if (upstream->tls_obj) {
|
priv_getdns_upstream_shutdown(upstream);
|
||||||
SSL_shutdown(upstream->tls_obj);
|
|
||||||
SSL_free(upstream->tls_obj);
|
|
||||||
upstream->tls_obj = NULL;
|
|
||||||
}
|
|
||||||
close(upstream->fd);
|
|
||||||
upstream->fd = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue