Commit 917778c5 authored by Marek Vavruša's avatar Marek Vavruša

Merge branch 'connect-timeout-cleanup'

parents 3f4d8cbe d7631ada
......@@ -30,11 +30,7 @@ struct qr_task
knot_pkt_t *next_query;
uv_handle_t *next_handle;
uv_timer_t timeout;
union {
uv_write_t tcp_send;
uv_udp_send_t udp_send;
uv_connect_t connect;
} ioreq;
uv_connect_t connect;
struct {
union {
struct sockaddr_in ip4;
......@@ -117,8 +113,6 @@ static void qr_task_timeout(uv_timer_t *req)
{
struct qr_task *task = req->data;
if (task->next_handle) {
uv_cancel((uv_req_t *)&task->ioreq);
io_stop_read(task->next_handle);
qr_task_step(task, NULL);
}
}
......@@ -160,7 +154,8 @@ static void qr_task_on_connect(uv_connect_t *connect, int status)
{
uv_stream_t *handle = connect->handle;
struct qr_task *task = connect->data;
if (status == 0) { /* Failed to connect */
/* Use only if succeeded, and the connection didn't change. */
if (status == 0 && ((uv_handle_t *)handle == task->next_handle)) {
qr_task_send(task, (uv_handle_t *)handle, NULL, task->next_query);
}
}
......@@ -177,10 +172,12 @@ static int qr_task_step(struct qr_task *task, knot_pkt_t *packet)
/* Cancel timeout if active, close handle. */
if (task->next_handle) {
if (!uv_is_closing(task->next_handle)) {
io_stop_read(task->next_handle);
uv_close(task->next_handle, (uv_close_cb) free);
}
uv_timer_stop(&task->timeout);
task->next_handle = NULL;
task->connect.handle = NULL;
}
/* Consume input and produce next query */
......@@ -209,7 +206,7 @@ static int qr_task_step(struct qr_task *task, knot_pkt_t *packet)
/* Connect or issue query datagram */
task->next_handle->data = task;
if (sock_type == SOCK_STREAM) {
uv_connect_t *connect = &task->ioreq.connect;
uv_connect_t *connect = &task->connect;
connect->data = task;
if (uv_tcp_connect(connect, (uv_tcp_t *)task->next_handle, addr, qr_task_on_connect) != 0) {
return qr_task_step(task, NULL);
......
......@@ -54,10 +54,9 @@ static void adjust_ttl(knot_rrset_t *rr, uint32_t drift)
}
}
static int loot_cache(namedb_txn_t *txn, knot_pkt_t *pkt, uint8_t tag, uint32_t timestamp)
static int loot_cache_pkt(namedb_txn_t *txn, knot_pkt_t *pkt, const knot_dname_t *qname,
uint16_t rrtype, uint8_t tag, uint32_t timestamp)
{
const knot_dname_t *qname = knot_pkt_qname(pkt);
uint16_t rrtype = knot_pkt_qtype(pkt);
struct kr_cache_entry *entry;
entry = kr_cache_peek(txn, tag, qname, rrtype, &timestamp);
if (!entry) { /* Not in the cache */
......@@ -91,6 +90,25 @@ static int loot_cache(namedb_txn_t *txn, knot_pkt_t *pkt, uint8_t tag, uint32_t
return ret;
}
/** @internal Try to find a shortcut directly to searched packet, otherwise try to find minimised QNAME. */
static int loot_cache(namedb_txn_t *txn, knot_pkt_t *pkt, uint8_t tag, struct kr_query *qry)
{
uint32_t timestamp = qry->timestamp.tv_sec;
const knot_dname_t *qname = qry->sname;
uint16_t rrtype = qry->stype;
int ret = loot_cache_pkt(txn, pkt, qname, rrtype, tag, timestamp);
if (ret == 0) { /* Signalize minimisation disabled */
qry->flags |= QUERY_NO_MINIMIZE;
} else { /* Retry with minimised name */
qname = knot_pkt_qname(pkt);
rrtype = knot_pkt_qtype(pkt);
if (!knot_dname_is_equal(qname, qry->sname)) {
ret = loot_cache_pkt(txn, pkt, qname, rrtype, tag, timestamp);
}
}
return ret;
}
static int peek(knot_layer_t *ctx, knot_pkt_t *pkt)
{
struct kr_request *req = ctx->data;
......@@ -103,24 +121,25 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt)
return ctx->state; /* Only IN class */
}
/* Fetch packet from cache */
/* Prepare read transaction */
namedb_txn_t txn;
struct kr_cache *cache = req->ctx->cache;
if (kr_cache_txn_begin(cache, &txn, NAMEDB_RDONLY) != 0) {
return ctx->state;
}
uint32_t timestamp = qry->timestamp.tv_sec;
if (loot_cache(&txn, pkt, get_tag(req->answer), timestamp) != 0) {
kr_cache_txn_abort(&txn);
return ctx->state;
}
/* Mark as solved from cache */
DEBUG_MSG("=> satisfied from cache\n");
qry->flags |= QUERY_CACHED;
knot_wire_set_qr(pkt->wire);
/* Fetch either answer to original or minimized query */
uint8_t tag = get_tag(req->answer);
int ret = loot_cache(&txn, pkt, tag, qry);
kr_cache_txn_abort(&txn);
return KNOT_STATE_DONE;
if (ret == 0) {
DEBUG_MSG("=> satisfied from cache\n");
qry->flags |= QUERY_CACHED;
pkt->parsed = pkt->size;
knot_wire_set_qr(pkt->wire);
return KNOT_STATE_DONE;
}
return ctx->state;
}
static uint32_t packet_ttl(knot_pkt_t *pkt)
......
......@@ -33,18 +33,28 @@ static int begin(knot_layer_t *ctx, void *module_param)
}
static int loot_rr(namedb_txn_t *txn, knot_pkt_t *pkt, const knot_dname_t *name,
uint16_t rrtype, uint16_t rrclass, uint32_t timestamp)
uint16_t rrclass, uint16_t rrtype, struct kr_query *qry)
{
/* Check if record exists in cache */
uint32_t timestamp = qry->timestamp.tv_sec;
knot_rrset_t cache_rr;
knot_rrset_init(&cache_rr, (knot_dname_t *)name, rrtype, rrclass);
int ret = kr_cache_peek_rr(txn, &cache_rr, &timestamp);
if (ret != 0) {
return ret;
}
knot_rrset_t rr_copy = kr_cache_materialize(&cache_rr, timestamp, &pkt->mm);
if (rr_copy.rrs.rr_count == 0) {
return kr_error(ENOENT);
/* Update packet question */
if (!knot_dname_is_equal(knot_pkt_qname(pkt), name)) {
uint8_t header[KNOT_WIRE_HEADER_SIZE];
memcpy(header, pkt->wire, sizeof(header));
knot_pkt_clear(pkt);
memcpy(pkt->wire, header, sizeof(header));
knot_pkt_put_question(pkt, qry->sname, qry->sclass, qry->stype);
}
/* Update packet answer */
knot_rrset_t rr_copy = kr_cache_materialize(&cache_rr, timestamp, &pkt->mm);
ret = knot_pkt_put(pkt, KNOT_COMPR_HINT_NONE, &rr_copy, KNOT_PF_FREE);
if (ret != 0) {
knot_rrset_clear(&rr_copy, &pkt->mm);
......@@ -53,14 +63,31 @@ static int loot_rr(namedb_txn_t *txn, knot_pkt_t *pkt, const knot_dname_t *name,
return kr_ok();
}
static int loot_cache(namedb_txn_t *txn, knot_pkt_t *pkt, uint32_t timestamp)
static int loot_cache_set(namedb_txn_t *txn, knot_pkt_t *pkt, const knot_dname_t *qname,
uint16_t rrclass, uint16_t rrtype, struct kr_query *qry)
{
const knot_dname_t *qname = knot_pkt_qname(pkt);
uint16_t rrclass = knot_pkt_qclass(pkt);
uint16_t rrtype = knot_pkt_qtype(pkt);
int ret = loot_rr(txn, pkt, qname, rrtype, rrclass, timestamp);
int ret = loot_rr(txn, pkt, qname, rrclass, rrtype, qry);
if (ret == kr_error(ENOENT) && rrtype != KNOT_RRTYPE_CNAME) { /* Chase CNAME if no direct hit */
ret = loot_rr(txn, pkt, qname, KNOT_RRTYPE_CNAME, rrclass, timestamp);
ret = loot_rr(txn, pkt, qname, rrclass, KNOT_RRTYPE_CNAME, qry);
}
return ret;
}
/** @internal Try to find a shortcut directly to searched record, otherwise try to find minimised QNAME. */
static int loot_cache(namedb_txn_t *txn, knot_pkt_t *pkt, struct kr_query *qry)
{
const knot_dname_t *qname = qry->sname;
uint16_t rrclass = qry->sclass;
uint16_t rrtype = qry->stype;
int ret = loot_cache_set(txn, pkt, qname, rrclass, rrtype, qry);
if (ret == 0) { /* Signalize minimisation disabled */
qry->flags |= QUERY_NO_MINIMIZE;
} else { /* Retry with minimised name */
qname = knot_pkt_qname(pkt);
rrtype = knot_pkt_qtype(pkt);
if (!knot_dname_is_equal(qname, qry->sname)) {
ret = loot_cache_set(txn, pkt, qname, rrclass, rrtype, qry);
}
}
return ret;
}
......@@ -77,21 +104,21 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt)
namedb_txn_t txn;
struct kr_cache *cache = req->ctx->cache;
if (kr_cache_txn_begin(cache, &txn, NAMEDB_RDONLY) != 0) {
return KNOT_STATE_CONSUME;
return ctx->state;
}
/* Reconstruct the answer from the cache,
* it may either be a CNAME chain or direct answer.
* Only one step of the chain is resolved at a time.
*/
uint32_t timestamp = qry->timestamp.tv_sec;
int ret = loot_cache(&txn, pkt, timestamp);
int ret = loot_cache(&txn, pkt, qry);
kr_cache_txn_abort(&txn);
if (ret == 0) {
DEBUG_MSG("=> satisfied from cache\n");
qry->flags |= QUERY_CACHED;
pkt->parsed = pkt->size;
knot_wire_set_qr(pkt->wire);
knot_wire_set_aa(pkt->wire);
return KNOT_STATE_DONE;
}
return ctx->state;
......
......@@ -9,6 +9,7 @@ ENV PREFIX /usr/local
ENV BUILD_DIR /tmp/build
ENV BUILD_IGNORE gmp nettle jansson gnutls lua
ENV CFLAGS -DNDEBUG -O2 -g -fstack-protector
ENV LDFLAGS -Wl,--as-needed
# Expose port
EXPOSE 53
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment