diff --git a/Knot.files b/Knot.files index 856043c8f0d01cac454bcad8517d0c9ee44172de..2dc8800f2d07dfbc1cf3b97b9075b6e6086b212a 100644 --- a/Knot.files +++ b/Knot.files @@ -125,6 +125,8 @@ src/knot/nameserver/process_query.c src/knot/nameserver/process_query.h src/knot/nameserver/query_module.c src/knot/nameserver/query_module.h +src/knot/nameserver/requestor.c +src/knot/nameserver/requestor.h src/knot/nameserver/update.c src/knot/nameserver/update.h src/knot/other/debug.h @@ -308,6 +310,7 @@ tests/pkt.c tests/process_answer.c tests/process_query.c tests/query_module.c +tests/requestor.c tests/rrl.c tests/rrset.c tests/sample_conf.h diff --git a/src/knot/nameserver/requestor.c b/src/knot/nameserver/requestor.c index 422130bf27027746a3ae6d66cb7152c4772842e4..02ff932484b8428a6875ed1f8034e022111875e1 100644 --- a/src/knot/nameserver/requestor.c +++ b/src/knot/nameserver/requestor.c @@ -23,6 +23,7 @@ struct request { node_t node; int fd; int state; + const struct sockaddr_storage *remote, *origin; knot_pkt_t *query; knot_process_t process; uint8_t *pkt_buf; @@ -118,12 +119,13 @@ static int request_recv(struct request *request, struct timeval *timeout) return NS_PROC_FAIL; } - return KNOT_EOK; + return ret; } -void requestor_init(struct requestor *requestor, mm_ctx_t *mm) +void requestor_init(struct requestor *requestor, const knot_process_module_t *module, mm_ctx_t *mm) { memset(requestor, 0, sizeof(struct requestor)); + requestor->module = module; requestor->mm = mm; init_list(&requestor->pending); } @@ -139,33 +141,47 @@ bool requestor_finished(struct requestor *requestor) return requestor == NULL || EMPTY_LIST(requestor->pending); } -int requestor_enqueue(struct requestor *requestor, knot_pkt_t *query, - const knot_process_module_t *module, void *param) +struct request *requestor_make(struct requestor *requestor, + const struct sockaddr_storage *from, + const struct sockaddr_storage *to, + knot_pkt_t *query) +{ + if (requestor == NULL || query == NULL || to == NULL) { + return NULL; + } + + /* Form a pending request. */ + struct request *request = request_make(requestor->mm); + if (request == NULL) { + return NULL; + } + + request->origin = from; + request->remote = to; + request->fd = -1; + request->query = query; + return request; +} + +int requestor_enqueue(struct requestor *requestor, struct request * request, void *param) { - if (requestor == NULL || query == NULL) { + if (requestor == NULL || request == NULL) { return KNOT_EINVAL; } /* Fetch a bound socket. */ - int fd = net_connected_socket(SOCK_STREAM, requestor->remote, - requestor->origin, O_NONBLOCK); + int fd = net_connected_socket(SOCK_STREAM, request->remote, + request->origin, O_NONBLOCK); if (fd < 0) { return KNOT_ECONN; } /* Form a pending request. */ - struct request *request = request_make(requestor->mm); - if (request == NULL) { - close(fd); - return KNOT_ENOMEM; - } - request->fd = fd; - request->query = query; request->state = NS_PROC_FULL; /* We have a query to be sent. */ memcpy(&request->process.mm, requestor->mm, sizeof(mm_ctx_t)); - knot_process_begin(&request->process, param, module); + knot_process_begin(&request->process, param, requestor->module); add_tail(&requestor->pending, &request->node); @@ -198,15 +214,18 @@ static int exec_request(struct request *last, struct timeval *timeout) /* Receive and process expected answers. */ while(last->state == NS_PROC_MORE) { - ret = request_recv(last, timeout); - if (ret != KNOT_EOK) { - return ret; + int rcvd = request_recv(last, timeout); + if (rcvd <= 0) { + return rcvd; } - last->state = knot_process_in(last->pkt_buf, ret, &last->process); + last->state = knot_process_in(last->pkt_buf, rcvd, &last->process); + if (last->state == NS_PROC_FAIL) { + return KNOT_ERROR; + } } - return ret; + return KNOT_EOK; } int requestor_exec(struct requestor *requestor, struct timeval *timeout) diff --git a/src/knot/nameserver/requestor.h b/src/knot/nameserver/requestor.h index e5616e4b071848b3f6c48447fc1bef12cd7712bb..f0b45378a7cb0a60d4008b0395c0279936416bae 100644 --- a/src/knot/nameserver/requestor.h +++ b/src/knot/nameserver/requestor.h @@ -20,13 +20,15 @@ #include "knot/nameserver/process_answer.h" #include "common/lists.h" +struct request; + /*! \brief Requestor structure. * * Requestor holds a FIFO of pending queries with given remote. */ struct requestor { /* Requestor target and source address. */ - const struct sockaddr_storage *remote, *origin; + const knot_process_module_t *module; //knot_sign_context_t tsig; /* @note not implemented */ @@ -37,7 +39,7 @@ struct requestor { /*! * \brief Initialize requestor structure. */ -void requestor_init(struct requestor *requestor, mm_ctx_t *mm); +void requestor_init(struct requestor *requestor, const knot_process_module_t *module, mm_ctx_t *mm); /*! * \brief Clear the requestor structure and close pending queries. @@ -47,6 +49,13 @@ void requestor_clear(struct requestor *requestor); /*! \brief Return true if there are no pending queries. */ bool requestor_finished(struct requestor *requestor); + +/*! \brief Make request out of endpoints and query. */ +struct request *requestor_make(struct requestor *requestor, + const struct sockaddr_storage *from, + const struct sockaddr_storage *to, + knot_pkt_t *query); + /*! * \brief Enqueue a query for processing. * @@ -60,8 +69,7 @@ bool requestor_finished(struct requestor *requestor); * * \return KNOT_EOK or error */ -int requestor_enqueue(struct requestor *requestor, knot_pkt_t *query, - const knot_process_module_t *module, void *param); +int requestor_enqueue(struct requestor *requestor, struct request *request, void *param); /*! * \brief Close first pending request. diff --git a/tests/requestor.c b/tests/requestor.c index 0393a383a6d13bb6df9998e2492388aa3d279c17..a8b32236f47f41db66f2163694bc2a0ad7bcabbe 100644 --- a/tests/requestor.c +++ b/tests/requestor.c @@ -64,18 +64,19 @@ static void* responder_thread(void *arg) #define CONNECTED_TESTS 4 #define TESTS_COUNT DISCONNECTED_TESTS + CONNECTED_TESTS -static knot_pkt_t *make_query(mm_ctx_t *mm) +static struct request *make_query(struct requestor *requestor, struct sockaddr_storage *remote) { - knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, mm); + knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, requestor->mm); assert(pkt); knot_pkt_put_question(pkt, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_SOA); - return pkt; + + return requestor_make(requestor, NULL, remote, pkt); } -static void test_disconnected(struct requestor *requestor) +static void test_disconnected(struct requestor *requestor, struct sockaddr_storage *remote) { /* Enqueue packet. */ - int ret = requestor_enqueue(requestor, make_query(requestor->mm), &dummy_module, NULL); + int ret = requestor_enqueue(requestor, make_query(requestor, remote), NULL); is_int(KNOT_EOK, ret, "requestor: disconnected/enqueue"); /* Wait for completion. */ @@ -84,10 +85,10 @@ static void test_disconnected(struct requestor *requestor) is_int(KNOT_ECONNREFUSED, ret, "requestor: disconnected/wait"); } -static void test_connected(struct requestor *requestor) +static void test_connected(struct requestor *requestor, struct sockaddr_storage *remote) { /* Enqueue packet. */ - int ret = requestor_enqueue(requestor, make_query(requestor->mm), &dummy_module, NULL); + int ret = requestor_enqueue(requestor, make_query(requestor, remote), NULL);; is_int(KNOT_EOK, ret, "requestor: connected/enqueue"); /* Wait for completion. */ @@ -98,7 +99,7 @@ static void test_connected(struct requestor *requestor) /* Enqueue multiple queries. */ ret = KNOT_EOK; for (unsigned i = 0; i < 10; ++i) { - ret |= requestor_enqueue(requestor, make_query(requestor->mm), &dummy_module, NULL); + ret |= requestor_enqueue(requestor, make_query(requestor, remote), NULL);; } is_int(KNOT_EOK, ret, "requestor: multiple enqueue"); @@ -127,12 +128,10 @@ int main(int argc, char *argv[]) /* Initialize requestor. */ struct requestor requestor; - requestor_init(&requestor, &mm); - requestor.remote = &remote; - requestor.origin = NULL; + requestor_init(&requestor, &dummy_module, &mm); /* Test requestor in disconnected environment. */ - test_disconnected(&requestor); + test_disconnected(&requestor, &remote); /* Bind to random port. */ int origin_fd = net_bound_socket(SOCK_STREAM, &remote); @@ -147,7 +146,7 @@ int main(int argc, char *argv[]) pthread_create(&thread, 0, responder_thread, &origin_fd); /* Test requestor in connected environment. */ - test_connected(&requestor); + test_connected(&requestor, &remote); /* TSIG secured. */ #warning TODO: when ported sign_packet/verify_packet