]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add undocumented '-T delay=value' to allow for simulation of remote servers
authorMark Andrews <marka@isc.org>
Sat, 29 Sep 2012 03:07:09 +0000 (13:07 +1000)
committerMark Andrews <marka@isc.org>
Sat, 29 Sep 2012 03:07:09 +0000 (13:07 +1000)
bin/named/client.c
bin/named/include/named/client.h
bin/named/include/named/globals.h
bin/named/main.c

index 5144ff9760796174976854ecea1fea50009597b4..9434ab080b820b9746c11659e0ebb975060cc9b0 100644 (file)
@@ -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);
index d8969f31bb48af7e7ea43ada49a8330a28bec01a..483464d2f0d86c0be963b89bf565c5b97c4d2d9d 100644 (file)
@@ -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;
index aefedc4b8b1d0412a3d61af546d4f1fd4da539fd..c008653d2c40fdd0003de1102b6b82d41a037614 100644 (file)
@@ -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
index 398005620661c973faf1aeeff66aab6dadff280a..eb3b3f4e7f11051c12be85e9ace2f7451ac4c30f 100644 (file)
@@ -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);