From cc0a2f0283ffd7c7aaed368832bf157b09136525 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Sat, 29 Sep 2012 13:07:09 +1000 Subject: [PATCH] Add undocumented '-T delay=value' to allow for simulation of remote servers --- bin/named/client.c | 74 ++++++++++++++++++++++++++++++- bin/named/include/named/client.h | 1 + bin/named/include/named/globals.h | 1 + bin/named/main.c | 5 +++ 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/bin/named/client.c b/bin/named/client.c index 5144ff9760..9434ab080b 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -535,6 +535,8 @@ exit_check(ns_client_t *client) { isc_event_free((isc_event_t **)&client->sendevent); isc_event_free((isc_event_t **)&client->recvevent); isc_timer_detach(&client->timer); + if (client->delaytimer != NULL) + isc_timer_detach(&client->delaytimer); if (client->tcpbuf != NULL) isc_mem_put(client->mctx, client->tcpbuf, @@ -913,8 +915,8 @@ ns_client_sendraw(ns_client_t *client, dns_message_t *message) { ns_client_next(client, result); } -void -ns_client_send(ns_client_t *client) { +static void +client_send(ns_client_t *client) { isc_result_t result; unsigned char *data; isc_buffer_t buffer; @@ -1075,6 +1077,72 @@ ns_client_send(ns_client_t *client) { ns_client_next(client, result); } +/* + * Completes the sending of a delayed client response. + */ +static void +client_delay(isc_task_t *task, isc_event_t *event) { + ns_client_t *client; + + REQUIRE(event != NULL); + REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE || + event->ev_type == ISC_TIMEREVENT_IDLE); + client = event->ev_arg; + REQUIRE(NS_CLIENT_VALID(client)); + REQUIRE(task == client->task); + REQUIRE(client->delaytimer != NULL); + + UNUSED(task); + + CTRACE("client_delay"); + + isc_event_free(&event); + isc_timer_detach(&client->delaytimer); + + client_send(client); + ns_client_detach(&client); +} + +void +ns_client_send(ns_client_t *client) { + + /* + * Delay the response by ns_g_delay ms. + */ + if (ns_g_delay != 0) { + ns_client_t *dummy = NULL; + isc_result_t result; + isc_interval_t interval; + + /* + * Replace ourselves if we have not already been replaced. + */ + if (!client->mortal) { + result = ns_client_replace(client); + if (result != ISC_R_SUCCESS) + goto nodelay; + } + + ns_client_attach(client, &dummy); + if (ns_g_delay >= 1000) + isc_interval_set(&interval, ns_g_delay / 1000, + (ns_g_delay % 1000) * 1000000); + else + isc_interval_set(&interval, 0, ns_g_delay * 1000000); + result = isc_timer_create(client->manager->timermgr, + isc_timertype_once, NULL, &interval, + client->task, client_delay, + client, &client->delaytimer); + if (result == ISC_R_SUCCESS) + return; + + ns_client_detach(&dummy); + } + + nodelay: + client_send(client); +} + #if NS_CLIENT_DROPPORT #define DROPPORT_NO 0 #define DROPPORT_REQUEST 1 @@ -2060,6 +2128,8 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { goto cleanup_task; client->timerset = ISC_FALSE; + client->delaytimer = NULL; + client->message = NULL; result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE, &client->message); diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index d8969f31bb..483464d2f0 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -115,6 +115,7 @@ struct ns_client { dns_tcpmsg_t tcpmsg; isc_boolean_t tcpmsg_valid; isc_timer_t * timer; + isc_timer_t * delaytimer; isc_boolean_t timerset; dns_message_t * message; isc_socketevent_t * sendevent; diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index aefedc4b8b..c008653d2c 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.h @@ -154,6 +154,7 @@ EXTERN isc_boolean_t ns_g_memstatistics INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_clienttest INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_nosoa INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_noaa INIT(ISC_FALSE); +EXTERN unsigned int ns_g_delay INIT(0); #undef EXTERN #undef INIT diff --git a/bin/named/main.c b/bin/named/main.c index 3980056206..eb3b3f4e7f 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -512,6 +512,8 @@ parse_command_line(int argc, char *argv[]) { /* * clienttest: make clients single shot with their * own memory context. + * delay=xxxx: delay client responses by xxxx ms to + * simulate remote servers. */ if (!strcmp(isc_commandline_argument, "clienttest")) ns_g_clienttest = ISC_TRUE; @@ -523,6 +525,9 @@ parse_command_line(int argc, char *argv[]) { maxudp = 512; else if (!strcmp(isc_commandline_argument, "maxudp1460")) maxudp = 1460; + else if (!strncmp(isc_commandline_argument, + "delay=", 6)) + ns_g_delay = atoi(isc_commandline_argument + 6); else fprintf(stderr, "unknown -T flag '%s\n", isc_commandline_argument);