]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
rewrite statschannel to use netmgr
authorEvan Hunt <each@isc.org>
Fri, 10 Jul 2020 02:36:10 +0000 (19:36 -0700)
committerEvan Hunt <each@isc.org>
Thu, 16 Jul 2020 05:35:07 +0000 (22:35 -0700)
modify isc_httpd to use the network manager instead of the
isc_socket API.

also cleaned up bin/named/statschannel.c to use CHECK.

bin/named/statschannel.c
lib/isc/httpd.c
lib/isc/include/isc/httpd.h
lib/isc/win32/libisc.def.in

index 59fabdea8992266e5dca8e07e32a22b7ddd715b5..ee9a0f38a8de2f0507320ca363f633dc560dd97d 100644 (file)
@@ -22,7 +22,6 @@
 #include <isc/socket.h>
 #include <isc/stats.h>
 #include <isc/string.h>
-#include <isc/task.h>
 #include <isc/util.h>
 
 #include <dns/cache.h>
 
 #include "xsl_p.h"
 
+#define CHECK(m)                               \
+       do {                                   \
+               result = (m);                  \
+               if (result != ISC_R_SUCCESS) { \
+                       goto cleanup;          \
+               }                              \
+       } while (0)
+
 struct named_statschannel {
        /* Unlocked */
        isc_httpdmgr_t *httpdmgr;
@@ -170,11 +177,11 @@ static const char *gluecachestats_xmldesc[dns_gluecachestatscounter_max];
 #define gluecachestats_xmldesc NULL
 #endif /* EXTENDED_STATS */
 
-#define TRY0(a)                     \
-       do {                        \
-               xmlrc = (a);        \
-               if (xmlrc < 0)      \
-                       goto error; \
+#define TRY0(a)                       \
+       do {                          \
+               xmlrc = (a);          \
+               if (xmlrc < 0)        \
+                       goto cleanup; \
        } while (0)
 
 /*%
@@ -1424,7 +1431,7 @@ dump_counters(isc_stats_t *stats, isc_statsformat_t type, void *arg,
        }
        return (ISC_R_SUCCESS);
 #ifdef HAVE_LIBXML2
-error:
+cleanup:
        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
                      "failed at dump_counters()");
@@ -1486,7 +1493,7 @@ rdtypestat_dump(dns_rdatastatstype_t type, uint64_t val, void *arg) {
        }
        return;
 #ifdef HAVE_LIBXML2
-error:
+cleanup:
        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
                      "failed at rdtypestat_dump()");
@@ -1574,7 +1581,7 @@ rdatasetstats_dump(dns_rdatastatstype_t type, uint64_t val, void *arg) {
        }
        return;
 #ifdef HAVE_LIBXML2
-error:
+cleanup:
        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
                      "failed at rdatasetstats_dump()");
@@ -1629,7 +1636,7 @@ opcodestat_dump(dns_opcode_t code, uint64_t val, void *arg) {
        return;
 
 #ifdef HAVE_LIBXML2
-error:
+cleanup:
        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
                      "failed at opcodestat_dump()");
@@ -1685,7 +1692,7 @@ rcodestat_dump(dns_rcode_t code, uint64_t val, void *arg) {
        return;
 
 #ifdef HAVE_LIBXML2
-error:
+cleanup:
        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
                      "failed at rcodestat_dump()");
@@ -1738,7 +1745,7 @@ dnssecsignstat_dump(dns_keytag_t tag, uint64_t val, void *arg) {
        }
        return;
 #ifdef HAVE_LIBXML2
-error:
+cleanup:
        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
                      "failed at dnssecsignstat_dump()");
@@ -1772,6 +1779,7 @@ zone_xmlrender(dns_zone_t *zone, void *arg) {
        int xmlrc;
        stats_dumparg_t dumparg;
        const char *ztype;
+       isc_time_t timestamp;
 
        statlevel = dns_zone_getstatlevel(zone);
        if (statlevel == dns_zonestat_none) {
@@ -1814,12 +1822,8 @@ zone_xmlrender(dns_zone_t *zone, void *arg) {
         * master zones, only include the loaded time.  For slave zones, also
         * include the expires and refresh times.
         */
-       isc_time_t timestamp;
 
-       result = dns_zone_getloadtime(zone, &timestamp);
-       if (result != ISC_R_SUCCESS) {
-               goto error;
-       }
+       CHECK(dns_zone_getloadtime(zone, &timestamp));
 
        isc_time_formatISO8601(&timestamp, buf, 64);
        TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "loaded"));
@@ -1827,19 +1831,13 @@ zone_xmlrender(dns_zone_t *zone, void *arg) {
        TRY0(xmlTextWriterEndElement(writer));
 
        if (dns_zone_gettype(zone) == dns_zone_slave) {
-               result = dns_zone_getexpiretime(zone, &timestamp);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+               CHECK(dns_zone_getexpiretime(zone, &timestamp));
                isc_time_formatISO8601(&timestamp, buf, 64);
                TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "expires"));
                TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf));
                TRY0(xmlTextWriterEndElement(writer));
 
-               result = dns_zone_getrefreshtime(zone, &timestamp);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+               CHECK(dns_zone_getrefreshtime(zone, &timestamp));
                isc_time_formatISO8601(&timestamp, buf, 64);
                TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "refresh"));
                TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf));
@@ -1862,14 +1860,11 @@ zone_xmlrender(dns_zone_t *zone, void *arg) {
                                                         ISC_XMLCHAR "type",
                                                         ISC_XMLCHAR "rcode"));
 
-                       result = dump_counters(zonestats, isc_statsformat_xml,
-                                              writer, NULL, nsstats_xmldesc,
-                                              ns_statscounter_max,
-                                              nsstats_index, nsstat_values,
-                                              ISC_STATSDUMP_VERBOSE);
-                       if (result != ISC_R_SUCCESS) {
-                               goto error;
-                       }
+                       CHECK(dump_counters(zonestats, isc_statsformat_xml,
+                                           writer, NULL, nsstats_xmldesc,
+                                           ns_statscounter_max, nsstats_index,
+                                           nsstat_values,
+                                           ISC_STATSDUMP_VERBOSE));
                        /* counters type="rcode"*/
                        TRY0(xmlTextWriterEndElement(writer));
                }
@@ -1882,15 +1877,12 @@ zone_xmlrender(dns_zone_t *zone, void *arg) {
                                writer, ISC_XMLCHAR "type",
                                ISC_XMLCHAR "gluecache"));
 
-                       result = dump_counters(
+                       CHECK(dump_counters(
                                gluecachestats, isc_statsformat_xml, writer,
                                NULL, gluecachestats_xmldesc,
                                dns_gluecachestatscounter_max,
                                gluecachestats_index, gluecachestats_values,
-                               ISC_STATSDUMP_VERBOSE);
-                       if (result != ISC_R_SUCCESS) {
-                               goto error;
-                       }
+                               ISC_STATSDUMP_VERBOSE));
                        /* counters type="rcode"*/
                        TRY0(xmlTextWriterEndElement(writer));
                }
@@ -1906,9 +1898,7 @@ zone_xmlrender(dns_zone_t *zone, void *arg) {
                        dumparg.result = ISC_R_SUCCESS;
                        dns_rdatatypestats_dump(rcvquerystats, rdtypestat_dump,
                                                &dumparg, 0);
-                       if (dumparg.result != ISC_R_SUCCESS) {
-                               goto error;
-                       }
+                       CHECK(dumparg.result);
 
                        /* counters type="qtype"*/
                        TRY0(xmlTextWriterEndElement(writer));
@@ -1927,9 +1917,7 @@ zone_xmlrender(dns_zone_t *zone, void *arg) {
                        dns_dnssecsignstats_dump(
                                dnssecsignstats, dns_dnssecsignstats_sign,
                                dnssecsignstat_dump, &dumparg, 0);
-                       if (dumparg.result != ISC_R_SUCCESS) {
-                               goto error;
-                       }
+                       CHECK(dumparg.result);
 
                        /* counters type="dnssec-sign"*/
                        TRY0(xmlTextWriterEndElement(writer));
@@ -1945,9 +1933,7 @@ zone_xmlrender(dns_zone_t *zone, void *arg) {
                        dns_dnssecsignstats_dump(
                                dnssecsignstats, dns_dnssecsignstats_refresh,
                                dnssecsignstat_dump, &dumparg, 0);
-                       if (dumparg.result != ISC_R_SUCCESS) {
-                               goto error;
-                       }
+                       CHECK(dumparg.result);
 
                        /* counters type="dnssec-refresh"*/
                        TRY0(xmlTextWriterEndElement(writer));
@@ -1957,7 +1943,7 @@ zone_xmlrender(dns_zone_t *zone, void *arg) {
        TRY0(xmlTextWriterEndElement(writer)); /* zone */
 
        return (ISC_R_SUCCESS);
-error:
+cleanup:
        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
                      "Failed at zone_xmlrender()");
@@ -1999,7 +1985,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
 
        writer = xmlNewTextWriterDoc(&doc, 0);
        if (writer == NULL) {
-               goto error;
+               goto cleanup;
        }
        TRY0(xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL));
        TRY0(xmlTextWriterWritePI(writer, ISC_XMLCHAR "xml-stylesheet",
@@ -2037,9 +2023,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
 
                dns_opcodestats_dump(server->sctx->opcodestats, opcodestat_dump,
                                     &dumparg, ISC_STATSDUMP_VERBOSE);
-               if (dumparg.result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+               CHECK(dumparg.result);
 
                TRY0(xmlTextWriterEndElement(writer));
 
@@ -2049,9 +2033,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
 
                dns_rcodestats_dump(server->sctx->rcodestats, rcodestat_dump,
                                    &dumparg, ISC_STATSDUMP_VERBOSE);
-               if (dumparg.result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+               CHECK(dumparg.result);
 
                TRY0(xmlTextWriterEndElement(writer));
 
@@ -2062,23 +2044,19 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                dumparg.result = ISC_R_SUCCESS;
                dns_rdatatypestats_dump(server->sctx->rcvquerystats,
                                        rdtypestat_dump, &dumparg, 0);
-               if (dumparg.result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+               CHECK(dumparg.result);
+
                TRY0(xmlTextWriterEndElement(writer)); /* counters */
 
                TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "nsstat"));
 
-               result = dump_counters(ns_stats_get(server->sctx->nsstats),
-                                      isc_statsformat_xml, writer, NULL,
-                                      nsstats_xmldesc, ns_statscounter_max,
-                                      nsstats_index, nsstat_values,
-                                      ISC_STATSDUMP_VERBOSE);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+               CHECK(dump_counters(ns_stats_get(server->sctx->nsstats),
+                                   isc_statsformat_xml, writer, NULL,
+                                   nsstats_xmldesc, ns_statscounter_max,
+                                   nsstats_index, nsstat_values,
+                                   ISC_STATSDUMP_VERBOSE));
 
                TRY0(xmlTextWriterEndElement(writer)); /* /nsstat */
 
@@ -2086,14 +2064,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "zonestat"));
 
-               result = dump_counters(server->zonestats, isc_statsformat_xml,
-                                      writer, NULL, zonestats_xmldesc,
-                                      dns_zonestatscounter_max,
-                                      zonestats_index, zonestat_values,
-                                      ISC_STATSDUMP_VERBOSE);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+               CHECK(dump_counters(server->zonestats, isc_statsformat_xml,
+                                   writer, NULL, zonestats_xmldesc,
+                                   dns_zonestatscounter_max, zonestats_index,
+                                   zonestat_values, ISC_STATSDUMP_VERBOSE));
 
                TRY0(xmlTextWriterEndElement(writer)); /* /zonestat */
 
@@ -2104,13 +2078,11 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "resstat"));
-               result = dump_counters(
-                       server->resolverstats, isc_statsformat_xml, writer,
-                       NULL, resstats_xmldesc, dns_resstatscounter_max,
-                       resstats_index, resstat_values, 0);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+               CHECK(dump_counters(server->resolverstats, isc_statsformat_xml,
+                                   writer, NULL, resstats_xmldesc,
+                                   dns_resstatscounter_max, resstats_index,
+                                   resstat_values, 0));
+
                TRY0(xmlTextWriterEndElement(writer)); /* resstat */
 
 #ifdef HAVE_DNSTAP
@@ -2127,9 +2099,8 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                                dnstapstats_xmldesc, dns_dnstapcounter_max,
                                dnstapstats_index, dnstapstat_values, 0);
                        isc_stats_detach(&dnstapstats);
-                       if (result != ISC_R_SUCCESS) {
-                               goto error;
-                       }
+                       CHECK(result);
+
                        TRY0(xmlTextWriterEndElement(writer)); /* dnstap */
                }
 #endif /* ifdef HAVE_DNSTAP */
@@ -2140,14 +2111,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "sockstat"));
 
-               result = dump_counters(server->sockstats, isc_statsformat_xml,
-                                      writer, NULL, sockstats_xmldesc,
-                                      isc_sockstatscounter_max,
-                                      sockstats_index, sockstat_values,
-                                      ISC_STATSDUMP_VERBOSE);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+               CHECK(dump_counters(server->sockstats, isc_statsformat_xml,
+                                   writer, NULL, sockstats_xmldesc,
+                                   isc_sockstatscounter_max, sockstats_index,
+                                   sockstat_values, ISC_STATSDUMP_VERBOSE));
 
                TRY0(xmlTextWriterEndElement(writer)); /* /sockstat */
        }
@@ -2161,13 +2128,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "request-size"));
 
-               result = dump_counters(
+               CHECK(dump_counters(
                        server->sctx->udpinstats4, isc_statsformat_xml, writer,
                        NULL, udpinsizestats_xmldesc, dns_sizecounter_in_max,
-                       udpinsizestats_index, udpinsizestat_values, 0);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+                       udpinsizestats_index, udpinsizestat_values, 0));
 
                TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
 
@@ -2175,13 +2139,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "response-size"));
 
-               result = dump_counters(
+               CHECK(dump_counters(
                        server->sctx->udpoutstats4, isc_statsformat_xml, writer,
                        NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max,
-                       udpoutsizestats_index, udpoutsizestat_values, 0);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+                       udpoutsizestats_index, udpoutsizestat_values, 0));
 
                TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
                TRY0(xmlTextWriterEndElement(writer)); /* </udp> */
@@ -2191,27 +2152,20 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "request-size"));
 
-               result = dump_counters(
+               CHECK(dump_counters(
                        server->sctx->tcpinstats4, isc_statsformat_xml, writer,
                        NULL, tcpinsizestats_xmldesc, dns_sizecounter_in_max,
-                       tcpinsizestats_index, tcpinsizestat_values, 0);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+                       tcpinsizestats_index, tcpinsizestat_values, 0));
 
                TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
-
                TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "response-size"));
 
-               result = dump_counters(
+               CHECK(dump_counters(
                        server->sctx->tcpoutstats4, isc_statsformat_xml, writer,
                        NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max,
-                       tcpoutsizestats_index, tcpoutsizestat_values, 0);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+                       tcpoutsizestats_index, tcpoutsizestat_values, 0));
 
                TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
                TRY0(xmlTextWriterEndElement(writer)); /* </tcp> */
@@ -2223,13 +2177,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "request-size"));
 
-               result = dump_counters(
+               CHECK(dump_counters(
                        server->sctx->udpinstats6, isc_statsformat_xml, writer,
                        NULL, udpinsizestats_xmldesc, dns_sizecounter_in_max,
-                       udpinsizestats_index, udpinsizestat_values, 0);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+                       udpinsizestats_index, udpinsizestat_values, 0));
 
                TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
 
@@ -2237,13 +2188,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "response-size"));
 
-               result = dump_counters(
+               CHECK(dump_counters(
                        server->sctx->udpoutstats6, isc_statsformat_xml, writer,
                        NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max,
-                       udpoutsizestats_index, udpoutsizestat_values, 0);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+                       udpoutsizestats_index, udpoutsizestat_values, 0));
 
                TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
                TRY0(xmlTextWriterEndElement(writer)); /* </udp> */
@@ -2253,13 +2201,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "request-size"));
 
-               result = dump_counters(
+               CHECK(dump_counters(
                        server->sctx->tcpinstats6, isc_statsformat_xml, writer,
                        NULL, tcpinsizestats_xmldesc, dns_sizecounter_in_max,
-                       tcpinsizestats_index, tcpinsizestat_values, 0);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+                       tcpinsizestats_index, tcpinsizestat_values, 0));
 
                TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
 
@@ -2267,13 +2212,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "response-size"));
 
-               result = dump_counters(
+               CHECK(dump_counters(
                        server->sctx->tcpoutstats6, isc_statsformat_xml, writer,
                        NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max,
-                       tcpoutsizestats_index, tcpoutsizestat_values, 0);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+                       tcpoutsizestats_index, tcpoutsizestat_values, 0));
 
                TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
                TRY0(xmlTextWriterEndElement(writer)); /* </tcp> */
@@ -2296,11 +2238,8 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                if ((flags & STATS_XML_ZONES) != 0) {
                        TRY0(xmlTextWriterStartElement(writer,
                                                       ISC_XMLCHAR "zones"));
-                       result = dns_zt_apply(view->zonetable, true, NULL,
-                                             zone_xmlrender, writer);
-                       if (result != ISC_R_SUCCESS) {
-                               goto error;
-                       }
+                       CHECK(dns_zt_apply(view->zonetable, true, NULL,
+                                          zone_xmlrender, writer));
                        TRY0(xmlTextWriterEndElement(writer)); /* /zones */
                }
 
@@ -2318,9 +2257,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                        dumparg.result = ISC_R_SUCCESS;
                        dns_rdatatypestats_dump(view->resquerystats,
                                                rdtypestat_dump, &dumparg, 0);
-                       if (dumparg.result != ISC_R_SUCCESS) {
-                               goto error;
-                       }
+                       CHECK(dumparg.result);
                }
                TRY0(xmlTextWriterEndElement(writer));
 
@@ -2329,14 +2266,11 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "resstats"));
                if (view->resstats != NULL) {
-                       result = dump_counters(
-                               view->resstats, isc_statsformat_xml, writer,
-                               NULL, resstats_xmldesc, dns_resstatscounter_max,
-                               resstats_index, resstat_values,
-                               ISC_STATSDUMP_VERBOSE);
-                       if (result != ISC_R_SUCCESS) {
-                               goto error;
-                       }
+                       CHECK(dump_counters(view->resstats, isc_statsformat_xml,
+                                           writer, NULL, resstats_xmldesc,
+                                           dns_resstatscounter_max,
+                                           resstats_index, resstat_values,
+                                           ISC_STATSDUMP_VERBOSE));
                }
                TRY0(xmlTextWriterEndElement(writer)); /* </resstats> */
 
@@ -2350,9 +2284,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                        dumparg.result = ISC_R_SUCCESS;
                        dns_rdatasetstats_dump(cacherrstats, rdatasetstats_dump,
                                               &dumparg, 0);
-                       if (dumparg.result != ISC_R_SUCCESS) {
-                               goto error;
-                       }
+                       CHECK(dumparg.result);
                        TRY0(xmlTextWriterEndElement(writer)); /* cache */
                }
 
@@ -2361,14 +2293,11 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
                TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
                                                 ISC_XMLCHAR "adbstat"));
                if (view->adbstats != NULL) {
-                       result = dump_counters(
-                               view->adbstats, isc_statsformat_xml, writer,
-                               NULL, adbstats_xmldesc, dns_adbstats_max,
-                               adbstats_index, adbstat_values,
-                               ISC_STATSDUMP_VERBOSE);
-                       if (result != ISC_R_SUCCESS) {
-                               goto error;
-                       }
+                       CHECK(dump_counters(view->adbstats, isc_statsformat_xml,
+                                           writer, NULL, adbstats_xmldesc,
+                                           dns_adbstats_max, adbstats_index,
+                                           adbstat_values,
+                                           ISC_STATSDUMP_VERBOSE));
                }
                TRY0(xmlTextWriterEndElement(writer)); /* </adbstats> */
 
@@ -2411,12 +2340,12 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
 
        xmlDocDumpFormatMemoryEnc(doc, buf, buflen, "UTF-8", 0);
        if (*buf == NULL) {
-               goto error;
+               goto cleanup;
        }
        xmlFreeDoc(doc);
        return (ISC_R_SUCCESS);
 
-error:
+cleanup:
        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
                      "failed generating XML response");
@@ -2573,18 +2502,11 @@ render_xml_traffic(const char *url, isc_httpdurl_t *urlinfo,
 #define STATS_JSON_TRAFFIC 0x20
 #define STATS_JSON_ALL    0xff
 
-#define CHECK(m)                             \
-       do {                                 \
-               result = (m);                \
-               if (result != ISC_R_SUCCESS) \
-                       goto error;          \
-       } while (0)
-
 #define CHECKMEM(m)                              \
        do {                                     \
                if (m == NULL) {                 \
                        result = ISC_R_NOMEMORY; \
-                       goto error;              \
+                       goto cleanup;            \
                }                                \
        } while (0)
 
@@ -2664,27 +2586,18 @@ zone_jsonrender(dns_zone_t *zone, void *arg) {
 
        isc_time_t timestamp;
 
-       result = dns_zone_getloadtime(zone, &timestamp);
-       if (result != ISC_R_SUCCESS) {
-               goto error;
-       }
+       CHECK(dns_zone_getloadtime(zone, &timestamp));
 
        isc_time_formatISO8601(&timestamp, buf, 64);
        json_object_object_add(zoneobj, "loaded", json_object_new_string(buf));
 
        if (dns_zone_gettype(zone) == dns_zone_slave) {
-               result = dns_zone_getexpiretime(zone, &timestamp);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+               CHECK(dns_zone_getexpiretime(zone, &timestamp));
                isc_time_formatISO8601(&timestamp, buf, 64);
                json_object_object_add(zoneobj, "expires",
                                       json_object_new_string(buf));
 
-               result = dns_zone_getrefreshtime(zone, &timestamp);
-               if (result != ISC_R_SUCCESS) {
-                       goto error;
-               }
+               CHECK(dns_zone_getrefreshtime(zone, &timestamp));
                isc_time_formatISO8601(&timestamp, buf, 64);
                json_object_object_add(zoneobj, "refresh",
                                       json_object_new_string(buf));
@@ -2703,7 +2616,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) {
                        json_object *counters = json_object_new_object();
                        if (counters == NULL) {
                                result = ISC_R_NOMEMORY;
-                               goto error;
+                               goto cleanup;
                        }
 
                        result = dump_counters(zonestats, isc_statsformat_json,
@@ -2712,7 +2625,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) {
                                               nsstats_index, nsstat_values, 0);
                        if (result != ISC_R_SUCCESS) {
                                json_object_put(counters);
-                               goto error;
+                               goto cleanup;
                        }
 
                        if (json_object_get_object(counters)->count != 0) {
@@ -2728,7 +2641,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) {
                        json_object *counters = json_object_new_object();
                        if (counters == NULL) {
                                result = ISC_R_NOMEMORY;
-                               goto error;
+                               goto cleanup;
                        }
 
                        result = dump_counters(
@@ -2738,7 +2651,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) {
                                gluecachestats_index, gluecachestats_values, 0);
                        if (result != ISC_R_SUCCESS) {
                                json_object_put(counters);
-                               goto error;
+                               goto cleanup;
                        }
 
                        if (json_object_get_object(counters)->count != 0) {
@@ -2762,7 +2675,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) {
                                                &dumparg, 0);
                        if (dumparg.result != ISC_R_SUCCESS) {
                                json_object_put(counters);
-                               goto error;
+                               goto cleanup;
                        }
 
                        if (json_object_get_object(counters)->count != 0) {
@@ -2787,7 +2700,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) {
                                dnssecsignstat_dump, &dumparg, 0);
                        if (dumparg.result != ISC_R_SUCCESS) {
                                json_object_put(sign_counters);
-                               goto error;
+                               goto cleanup;
                        }
 
                        if (json_object_get_object(sign_counters)->count != 0) {
@@ -2809,7 +2722,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) {
                                dnssecsignstat_dump, &dumparg, 0);
                        if (dumparg.result != ISC_R_SUCCESS) {
                                json_object_put(refresh_counters);
-                               goto error;
+                               goto cleanup;
                        }
 
                        if (json_object_get_object(refresh_counters)->count !=
@@ -2827,7 +2740,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) {
        zoneobj = NULL;
        result = ISC_R_SUCCESS;
 
-error:
+cleanup:
        if (zoneobj != NULL) {
                json_object_put(zoneobj);
        }
@@ -2912,7 +2825,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                                     &dumparg, ISC_STATSDUMP_VERBOSE);
                if (dumparg.result != ISC_R_SUCCESS) {
                        json_object_put(counters);
-                       goto error;
+                       goto cleanup;
                }
 
                if (json_object_get_object(counters)->count != 0) {
@@ -2931,7 +2844,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                                    &dumparg, ISC_STATSDUMP_VERBOSE);
                if (dumparg.result != ISC_R_SUCCESS) {
                        json_object_put(counters);
-                       goto error;
+                       goto cleanup;
                }
 
                if (json_object_get_object(counters)->count != 0) {
@@ -2950,7 +2863,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                                        rdtypestat_dump, &dumparg, 0);
                if (dumparg.result != ISC_R_SUCCESS) {
                        json_object_put(counters);
-                       goto error;
+                       goto cleanup;
                }
 
                if (json_object_get_object(counters)->count != 0) {
@@ -2971,7 +2884,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                                       nsstats_index, nsstat_values, 0);
                if (result != ISC_R_SUCCESS) {
                        json_object_put(counters);
-                       goto error;
+                       goto cleanup;
                }
 
                if (json_object_get_object(counters)->count != 0) {
@@ -2992,7 +2905,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                                       zonestats_index, zonestat_values, 0);
                if (result != ISC_R_SUCCESS) {
                        json_object_put(counters);
-                       goto error;
+                       goto cleanup;
                }
 
                if (json_object_get_object(counters)->count != 0) {
@@ -3014,7 +2927,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                        resstats_index, resstat_values, 0);
                if (result != ISC_R_SUCCESS) {
                        json_object_put(counters);
-                       goto error;
+                       goto cleanup;
                }
 
                if (json_object_get_object(counters)->count != 0) {
@@ -3039,7 +2952,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                        isc_stats_detach(&dnstapstats);
                        if (result != ISC_R_SUCCESS) {
                                json_object_put(counters);
-                               goto error;
+                               goto cleanup;
                        }
 
                        if (json_object_get_object(counters)->count != 0) {
@@ -3069,12 +2982,8 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                        CHECKMEM(za);
 
                        if ((flags & STATS_JSON_ZONES) != 0) {
-                               result = dns_zt_apply(view->zonetable, true,
-                                                     NULL, zone_jsonrender,
-                                                     za);
-                               if (result != ISC_R_SUCCESS) {
-                                       goto error;
-                               }
+                               CHECK(dns_zt_apply(view->zonetable, true, NULL,
+                                                  zone_jsonrender, za));
                        }
 
                        if (json_object_array_length(za) != 0) {
@@ -3107,7 +3016,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                                        if (result != ISC_R_SUCCESS) {
                                                json_object_put(counters);
                                                result = dumparg.result;
-                                               goto error;
+                                               goto cleanup;
                                        }
 
                                        json_object_object_add(res, "stats",
@@ -3127,7 +3036,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                                        if (dumparg.result != ISC_R_SUCCESS) {
                                                json_object_put(counters);
                                                result = dumparg.result;
-                                               goto error;
+                                               goto cleanup;
                                        }
 
                                        json_object_object_add(res, "qtypes",
@@ -3147,7 +3056,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                                        if (dumparg.result != ISC_R_SUCCESS) {
                                                json_object_put(counters);
                                                result = dumparg.result;
-                                               goto error;
+                                               goto cleanup;
                                        }
 
                                        json_object_object_add(res, "cache",
@@ -3161,7 +3070,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                                                              counters);
                                if (result != ISC_R_SUCCESS) {
                                        json_object_put(counters);
-                                       goto error;
+                                       goto cleanup;
                                }
 
                                json_object_object_add(res, "cachestats",
@@ -3182,7 +3091,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                                        if (result != ISC_R_SUCCESS) {
                                                json_object_put(counters);
                                                result = dumparg.result;
-                                               goto error;
+                                               goto cleanup;
                                        }
 
                                        json_object_object_add(res, "adb",
@@ -3208,7 +3117,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                                       sockstats_index, sockstat_values, 0);
                if (result != ISC_R_SUCCESS) {
                        json_object_put(counters);
-                       goto error;
+                       goto cleanup;
                }
 
                if (json_object_get_object(counters)->count != 0) {
@@ -3224,7 +3133,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                result = isc_socketmgr_renderjson(named_g_socketmgr, sockets);
                if (result != ISC_R_SUCCESS) {
                        json_object_put(sockets);
-                       goto error;
+                       goto cleanup;
                }
 
                json_object_object_add(bindstats, "socketmgr", sockets);
@@ -3237,7 +3146,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                result = isc_taskmgr_renderjson(named_g_taskmgr, tasks);
                if (result != ISC_R_SUCCESS) {
                        json_object_put(tasks);
-                       goto error;
+                       goto cleanup;
                }
 
                json_object_object_add(bindstats, "taskmgr", tasks);
@@ -3250,7 +3159,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
                result = isc_mem_renderjson(memory);
                if (result != ISC_R_SUCCESS) {
                        json_object_put(memory);
-                       goto error;
+                       goto cleanup;
                }
 
                json_object_object_add(bindstats, "memory", memory);
@@ -3375,7 +3284,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
 
        result = ISC_R_SUCCESS;
 
-error:
+cleanup:
        if (udpreq4 != NULL) {
                json_object_put(udpreq4);
        }
@@ -3654,7 +3563,7 @@ client_ok(const isc_sockaddr_t *fromaddr, void *arg) {
 
 static void
 destroy_listener(void *arg) {
-       named_statschannel_t *listener = arg;
+       named_statschannel_t *listener = (named_statschannel_t *)arg;
 
        REQUIRE(listener != NULL);
        REQUIRE(!ISC_LINK_LINKED(listener, link));
@@ -3672,22 +3581,15 @@ add_listener(named_server_t *server, named_statschannel_t **listenerp,
             isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
             const char *socktext) {
        isc_result_t result;
-       named_statschannel_t *listener;
-       isc_task_t *task = NULL;
-       isc_socket_t *sock = NULL;
-       const cfg_obj_t *allow;
+       named_statschannel_t *listener = NULL;
+       const cfg_obj_t *allow = NULL;
        dns_acl_t *new_acl = NULL;
+       int pf;
 
        listener = isc_mem_get(server->mctx, sizeof(*listener));
-
-       listener->httpdmgr = NULL;
-       listener->address = *addr;
-       listener->acl = NULL;
-       listener->mctx = NULL;
+       *listener = (named_statschannel_t){ .address = *addr };
        ISC_LINK_INIT(listener, link);
-
        isc_mutex_init(&listener->lock);
-
        isc_mem_attach(server->mctx, &listener->mctx);
 
        allow = cfg_tuple_get(listen_params, "allow");
@@ -3698,104 +3600,80 @@ add_listener(named_server_t *server, named_statschannel_t **listenerp,
        } else {
                result = dns_acl_any(listener->mctx, &new_acl);
        }
-       if (result != ISC_R_SUCCESS) {
-               goto cleanup;
-       }
+       CHECK(result);
+
        dns_acl_attach(new_acl, &listener->acl);
        dns_acl_detach(&new_acl);
 
-       result = isc_task_create(named_g_taskmgr, 0, &task);
-       if (result != ISC_R_SUCCESS) {
-               goto cleanup;
-       }
-       isc_task_setname(task, "statchannel", NULL);
-
-       result = isc_socket_create(named_g_socketmgr, isc_sockaddr_pf(addr),
-                                  isc_sockettype_tcp, &sock);
-       if (result != ISC_R_SUCCESS) {
-               goto cleanup;
-       }
-       isc_socket_setname(sock, "statchannel", NULL);
-
-#ifndef ISC_ALLOW_MAPPED
-       isc_socket_ipv6only(sock, true);
-#endif /* ifndef ISC_ALLOW_MAPPED */
-
-       result = isc_socket_bind(sock, addr, ISC_SOCKET_REUSEADDRESS);
-       if (result != ISC_R_SUCCESS) {
-               goto cleanup;
+       pf = isc_sockaddr_pf(&listener->address);
+       if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
+           (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
+       {
+               CHECK(ISC_R_FAMILYNOSUPPORT);
        }
 
-       result = isc_httpdmgr_create(server->mctx, sock, task, client_ok,
-                                    destroy_listener, listener,
-                                    named_g_timermgr, &listener->httpdmgr);
-       if (result != ISC_R_SUCCESS) {
-               goto cleanup;
-       }
+       CHECK(isc_httpdmgr_create(named_g_nm, server->mctx, addr, client_ok,
+                                 destroy_listener, listener,
+                                 &listener->httpdmgr));
 
 #ifdef HAVE_LIBXML2
-       isc_httpdmgr_addurl(listener->httpdmgr, "/", render_xml_all, server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/xml", render_xml_all, server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3", render_xml_all,
+       isc_httpdmgr_addurl(listener->httpdmgr, "/", false, render_xml_all,
                            server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/status",
+       isc_httpdmgr_addurl(listener->httpdmgr, "/xml", false, render_xml_all,
+                           server);
+       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3", false,
+                           render_xml_all, server);
+       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/status", false,
                            render_xml_status, server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/server",
+       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/server", false,
                            render_xml_server, server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/zones",
+       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/zones", false,
                            render_xml_zones, server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/net", render_xml_net,
-                           server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/tasks",
+       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/net", false,
+                           render_xml_net, server);
+       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/tasks", false,
                            render_xml_tasks, server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/mem", render_xml_mem,
-                           server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/traffic",
+       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/mem", false,
+                           render_xml_mem, server);
+       isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/traffic", false,
                            render_xml_traffic, server);
 #endif /* ifdef HAVE_LIBXML2 */
 #ifdef HAVE_JSON_C
-       isc_httpdmgr_addurl(listener->httpdmgr, "/json", render_json_all,
-                           server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1", render_json_all,
+       isc_httpdmgr_addurl(listener->httpdmgr, "/json", false, render_json_all,
                            server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/status",
+       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1", false,
+                           render_json_all, server);
+       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/status", false,
                            render_json_status, server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/server",
+       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/server", false,
                            render_json_server, server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/zones",
+       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/zones", false,
                            render_json_zones, server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/tasks",
+       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/tasks", false,
                            render_json_tasks, server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/net", render_json_net,
-                           server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/mem", render_json_mem,
-                           server);
-       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/traffic",
+       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/net", false,
+                           render_json_net, server);
+       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/mem", false,
+                           render_json_mem, server);
+       isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/traffic", false,
                            render_json_traffic, server);
 #endif /* ifdef HAVE_JSON_C */
-       isc_httpdmgr_addurl2(listener->httpdmgr, "/bind9.xsl", true, render_xsl,
-                            server);
+       isc_httpdmgr_addurl(listener->httpdmgr, "/bind9.xsl", true, render_xsl,
+                           server);
 
        *listenerp = listener;
        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                      NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE,
                      "statistics channel listening on %s", socktext);
 
+       return (ISC_R_SUCCESS);
+
 cleanup:
-       if (result != ISC_R_SUCCESS) {
-               if (listener->acl != NULL) {
-                       dns_acl_detach(&listener->acl);
-               }
-               isc_mutex_destroy(&listener->lock);
-               isc_mem_putanddetach(&listener->mctx, listener,
-                                    sizeof(*listener));
-       }
-       if (task != NULL) {
-               isc_task_detach(&task);
-       }
-       if (sock != NULL) {
-               isc_socket_detach(&sock);
+       if (listener->acl != NULL) {
+               dns_acl_detach(&listener->acl);
        }
+       isc_mutex_destroy(&listener->lock);
+       isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener));
 
        return (result);
 }
index d3117d4d6a80277955c7389cedc38a389b125930..2bd82da721df9feb98de1e8e78ea992e2447fb4b 100644 (file)
 #include <isc/buffer.h>
 #include <isc/httpd.h>
 #include <isc/mem.h>
+#include <isc/netmgr.h>
 #include <isc/print.h>
 #include <isc/refcount.h>
 #include <isc/socket.h>
 #include <isc/string.h>
-#include <isc/task.h>
 #include <isc/time.h>
 #include <isc/util.h>
 
 #include <zlib.h>
 #endif /* ifdef HAVE_ZLIB */
 
-/*%
- * TODO:
- *
- *  o  Make the URL processing external functions which will fill-in a buffer
- *     structure we provide, or return an error and we will render a generic
- *     page and close the client.
- */
-
-#define MSHUTTINGDOWN(cm)    ((cm->flags & ISC_HTTPDMGR_FLAGSHUTTINGDOWN) != 0)
-#define MSETSHUTTINGDOWN(cm) (cm->flags |= ISC_HTTPDMGR_FLAGSHUTTINGDOWN)
+#define CHECK(m)                               \
+       do {                                   \
+               result = (m);                  \
+               if (result != ISC_R_SUCCESS) { \
+                       goto cleanup;          \
+               }                              \
+       } while (0)
 
 #define HTTP_RECVLEN    1024
 #define HTTP_SENDGROW   1024
 #define HTTPDMGR_MAGIC   ISC_MAGIC('H', 'p', 'd', 'm')
 #define VALID_HTTPDMGR(m) ISC_MAGIC_VALID(m, HTTPDMGR_MAGIC)
 
+/*%
+ * Client states.
+ *
+ * _RECV       The client is waiting for data after starting a read.
+ * _SEND       All data for a response has completed, and a reply was
+ *             sent via a send call.
+ */
+
+typedef enum { RECV, SEND } state_t;
+
+/*%
+ * HTTP methods.
+ */
+typedef enum { METHOD_UNKNOWN = 0, METHOD_GET = 1, METHOD_POST = 2 } method_t;
+
 /*% http client */
 struct isc_httpd {
        unsigned int magic; /* HTTPD_MAGIC */
-       isc_refcount_t references;
+
        isc_httpdmgr_t *mgr; /*%< our parent */
        ISC_LINK(isc_httpd_t) link;
-       unsigned int state;
-       isc_socket_t *sock;
+
+       isc_nmhandle_t *handle;
+       state_t state;
+       int flags;
 
        /*%
         * Received data state.
@@ -71,16 +85,11 @@ struct isc_httpd {
        char recvbuf[HTTP_RECVLEN]; /*%< receive buffer */
        uint32_t recvlen;           /*%< length recv'd */
        char *headers;              /*%< set in process_request() */
-       unsigned int method;
+       method_t method;
        char *url;
        char *querystring;
        char *protocol;
 
-       /*
-        * Flags on the httpd client.
-        */
-       int flags;
-
        /*%
         * Transmit data state.
         *
@@ -119,14 +128,11 @@ struct isc_httpd {
        void *freecb_arg;
 };
 
-/*% lightweight socket manager for httpd output */
 struct isc_httpdmgr {
        unsigned int magic; /* HTTPDMGR_MAGIC */
        isc_refcount_t references;
        isc_mem_t *mctx;
-       isc_socket_t *sock; /*%< listening socket */
-       isc_task_t *task;   /*%< owning task */
-       isc_timermgr_t *timermgr;
+       isc_nmsocket_t *sock;
 
        isc_httpdclientok_t *client_ok;  /*%< client validator */
        isc_httpdondestroy_t *ondestroy; /*%< cleanup callback */
@@ -142,73 +148,30 @@ struct isc_httpdmgr {
        isc_httpdaction_t *render_500;
 };
 
-/*%
- * HTTP methods.
- */
-#define ISC_HTTPD_METHODUNKNOWN 0
-#define ISC_HTTPD_METHODGET    1
-#define ISC_HTTPD_METHODPOST   2
-
-/*%
- * Client states.
- *
- * _IDLE       The client is not doing anything at all.  This state should
- *             only occur just after creation, and just before being
- *             destroyed.
- *
- * _RECV       The client is waiting for data after issuing a socket recv().
- *
- * _RECVDONE   Data has been received, and is being processed.
- *
- * _SEND       All data for a response has completed, and a reply was
- *             sent via a socket send() call.
- *
- * _SENDDONE   Send is completed.
- *
- * Badly formatted state table:
- *
- *     IDLE -> RECV when client has a recv() queued.
- *
- *     RECV -> RECVDONE when recvdone event received.
- *
- *     RECVDONE -> SEND if the data for a reply is at hand.
- *
- *     SEND -> RECV when a senddone event was received.
- *
- *     At any time -> RECV on error.  If RECV fails, the client will
- *     self-destroy, closing the socket and freeing memory.
- */
-#define ISC_HTTPD_STATEIDLE    0
-#define ISC_HTTPD_STATERECV    1
-#define ISC_HTTPD_STATERECVDONE 2
-#define ISC_HTTPD_STATESEND    3
-#define ISC_HTTPD_STATESENDDONE 4
-
-#define ISC_HTTPD_ISRECV(c)    ((c)->state == ISC_HTTPD_STATERECV)
-#define ISC_HTTPD_ISRECVDONE(c) ((c)->state == ISC_HTTPD_STATERECVDONE)
-#define ISC_HTTPD_ISSEND(c)    ((c)->state == ISC_HTTPD_STATESEND)
-#define ISC_HTTPD_ISSENDDONE(c) ((c)->state == ISC_HTTPD_STATESENDDONE)
-
-/*%
- * Overall magic test that means we're not idle.
- */
-#define ISC_HTTPD_SETRECV(c)    ((c)->state = ISC_HTTPD_STATERECV)
-#define ISC_HTTPD_SETRECVDONE(c) ((c)->state = ISC_HTTPD_STATERECVDONE)
-#define ISC_HTTPD_SETSEND(c)    ((c)->state = ISC_HTTPD_STATESEND)
-#define ISC_HTTPD_SETSENDDONE(c) ((c)->state = ISC_HTTPD_STATESENDDONE)
-
+static isc_result_t
+httpd_newconn(isc_nmhandle_t *, isc_result_t, void *);
 static void
-isc_httpd_accept(isc_task_t *, isc_event_t *);
+httpd_request(isc_nmhandle_t *, isc_result_t, isc_region_t *, void *);
 static void
-isc_httpd_recvdone(isc_task_t *, isc_event_t *);
+httpd_senddone(isc_nmhandle_t *, isc_result_t, void *);
 static void
-isc_httpd_senddone(isc_task_t *, isc_event_t *);
+httpd_reset(void *);
+static void
+httpd_put(void *);
+
+static isc_result_t
+httpd_addheader(isc_httpd_t *, const char *, const char *);
+static isc_result_t
+httpd_addheaderuint(isc_httpd_t *, const char *, int);
 static isc_result_t
-process_request(isc_httpd_t *, int);
+httpd_endheaders(isc_httpd_t *);
+static isc_result_t
+httpd_response(isc_httpd_t *);
+
+static isc_result_t
+process_request(isc_httpd_t *, isc_region_t *);
 static isc_result_t
 grow_headerspace(isc_httpd_t *);
-static void
-reset_client(isc_httpd_t *httpd);
 
 static isc_httpdaction_t render_404;
 static isc_httpdaction_t render_500;
@@ -217,26 +180,13 @@ static isc_httpdaction_t render_500;
 static void (*finishhook)(void) = NULL;
 #endif /* ENABLE_AFL */
 
-static void
-maybe_destroy_httpd(isc_httpd_t *);
-static void
-destroy_httpd(isc_httpd_t *);
-static void
-maybe_destroy_httpdmgr(isc_httpdmgr_t *);
 static void
 destroy_httpdmgr(isc_httpdmgr_t *);
 
 static void
-isc_httpdmgr_attach(isc_httpdmgr_t *, isc_httpdmgr_t **);
+httpdmgr_attach(isc_httpdmgr_t *, isc_httpdmgr_t **);
 static void
-isc_httpdmgr_detach(isc_httpdmgr_t **);
-
-static void
-maybe_destroy_httpd(isc_httpd_t *httpd) {
-       if (isc_refcount_decrement(&httpd->references) == 1) {
-               destroy_httpd(httpd);
-       }
-}
+httpdmgr_detach(isc_httpdmgr_t **);
 
 static inline void
 free_buffer(isc_mem_t *mctx, isc_buffer_t *buffer) {
@@ -248,101 +198,20 @@ free_buffer(isc_mem_t *mctx, isc_buffer_t *buffer) {
        }
 }
 
-static void
-destroy_httpd(isc_httpd_t *httpd) {
-       isc_httpdmgr_t *httpdmgr;
-
-       REQUIRE(VALID_HTTPD(httpd));
-
-       httpdmgr = httpd->mgr;
-       REQUIRE(VALID_HTTPDMGR(httpdmgr));
-
-       /*
-        * Unlink before calling isc_socket_detach so
-        * isc_httpdmgr_shutdown does not dereference a NULL pointer
-        * when calling isc_socket_cancel().
-        */
-       LOCK(&httpdmgr->lock);
-       ISC_LIST_UNLINK(httpdmgr->running, httpd, link);
-       UNLOCK(&httpdmgr->lock);
-
-       httpd->magic = 0;
-       isc_refcount_destroy(&httpd->references);
-       isc_socket_detach(&httpd->sock);
-
-       free_buffer(httpdmgr->mctx, &httpd->headerbuffer);
-       free_buffer(httpdmgr->mctx, &httpd->compbuffer);
-
-       isc_mem_put(httpdmgr->mctx, httpd, sizeof(isc_httpd_t));
-
-#if ENABLE_AFL
-       if (finishhook != NULL) {
-               finishhook();
-       }
-#endif /* ENABLE_AFL */
-
-       isc_httpdmgr_detach(&httpdmgr);
-}
-
-static inline isc_result_t
-httpdmgr_socket_accept(isc_task_t *task, isc_httpdmgr_t *httpdmgr) {
-       isc_result_t result = ISC_R_SUCCESS;
-
-       /* decremented in isc_httpd_accept */
-       isc_refcount_increment(&httpdmgr->references);
-       result = isc_socket_accept(httpdmgr->sock, task, isc_httpd_accept,
-                                  httpdmgr);
-       if (result != ISC_R_SUCCESS) {
-               INSIST(isc_refcount_decrement(&httpdmgr->references) > 1);
-       }
-       return (result);
-}
-
-static inline void
-httpd_socket_recv(isc_httpd_t *httpd, isc_region_t *region, isc_task_t *task) {
-       isc_result_t result = ISC_R_SUCCESS;
-
-       /* decremented in isc_httpd_recvdone */
-       (void)isc_refcount_increment(&httpd->references);
-       result = isc_socket_recv(httpd->sock, region, 1, task,
-                                isc_httpd_recvdone, httpd);
-       if (result != ISC_R_SUCCESS) {
-               INSIST(isc_refcount_decrement(&httpd->references) > 1);
-       }
-}
-
-static inline void
-httpd_socket_send(isc_httpd_t *httpd, isc_region_t *region, isc_task_t *task) {
-       isc_result_t result = ISC_R_SUCCESS;
-
-       /* decremented in isc_httpd_senddone */
-       (void)isc_refcount_increment(&httpd->references);
-       result = isc_socket_send(httpd->sock, region, task, isc_httpd_senddone,
-                                httpd);
-       if (result != ISC_R_SUCCESS) {
-               INSIST(isc_refcount_decrement(&httpd->references) > 1);
-       }
-}
-
 isc_result_t
-isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
+isc_httpdmgr_create(isc_nm_t *nm, isc_mem_t *mctx, isc_sockaddr_t *addr,
                    isc_httpdclientok_t *client_ok,
                    isc_httpdondestroy_t *ondestroy, void *cb_arg,
-                   isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdmgrp) {
+                   isc_httpdmgr_t **httpdmgrp) {
        isc_result_t result;
-       isc_httpdmgr_t *httpdmgr;
+       isc_httpdmgr_t *httpdmgr = NULL;
 
+       REQUIRE(nm != NULL);
        REQUIRE(mctx != NULL);
-       REQUIRE(sock != NULL);
-       REQUIRE(task != NULL);
-       REQUIRE(tmgr != NULL);
        REQUIRE(httpdmgrp != NULL && *httpdmgrp == NULL);
 
        httpdmgr = isc_mem_get(mctx, sizeof(isc_httpdmgr_t));
-
-       *httpdmgr = (isc_httpdmgr_t){ .timermgr = tmgr, /* XXXMLG no attach
-                                                        * function? */
-                                     .client_ok = client_ok,
+       *httpdmgr = (isc_httpdmgr_t){ .client_ok = client_ok,
                                      .ondestroy = ondestroy,
                                      .cb_arg = cb_arg,
                                      .render_404 = render_404,
@@ -350,49 +219,34 @@ isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
 
        isc_mutex_init(&httpdmgr->lock);
        isc_mem_attach(mctx, &httpdmgr->mctx);
-       isc_socket_attach(sock, &httpdmgr->sock);
-       isc_task_attach(task, &httpdmgr->task);
 
        ISC_LIST_INIT(httpdmgr->running);
        ISC_LIST_INIT(httpdmgr->urls);
 
        isc_refcount_init(&httpdmgr->references, 1);
 
-       /* XXXMLG ignore errors on isc_socket_listen() */
-       result = isc_socket_listen(sock, SOMAXCONN);
-       if (result != ISC_R_SUCCESS) {
-               UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                "isc_socket_listen() failed: %s",
-                                isc_result_totext(result));
-               goto cleanup;
-       }
-
-       (void)isc_socket_filter(sock, "httpready");
+       CHECK(isc_nm_listentcp(nm, (isc_nmiface_t *)addr, httpd_newconn,
+                              httpdmgr, sizeof(isc_httpd_t), 5, NULL,
+                              &httpdmgr->sock));
 
        httpdmgr->magic = HTTPDMGR_MAGIC;
-
-       result = httpdmgr_socket_accept(task, httpdmgr);
-       if (result != ISC_R_SUCCESS) {
-               goto cleanup;
-       }
-
        *httpdmgrp = httpdmgr;
+
        return (ISC_R_SUCCESS);
 
 cleanup:
        httpdmgr->magic = 0;
        isc_refcount_decrement(&httpdmgr->references);
        isc_refcount_destroy(&httpdmgr->references);
-       isc_task_detach(&httpdmgr->task);
-       isc_socket_detach(&httpdmgr->sock);
        isc_mem_detach(&httpdmgr->mctx);
        isc_mutex_destroy(&httpdmgr->lock);
        isc_mem_put(mctx, httpdmgr, sizeof(isc_httpdmgr_t));
+
        return (result);
 }
 
 static void
-isc_httpdmgr_attach(isc_httpdmgr_t *source, isc_httpdmgr_t **targetp) {
+httpdmgr_attach(isc_httpdmgr_t *source, isc_httpdmgr_t **targetp) {
        REQUIRE(VALID_HTTPDMGR(source));
        REQUIRE(targetp != NULL && *targetp == NULL);
 
@@ -402,16 +256,15 @@ isc_httpdmgr_attach(isc_httpdmgr_t *source, isc_httpdmgr_t **targetp) {
 }
 
 static void
-isc_httpdmgr_detach(isc_httpdmgr_t **httpdmgrp) {
-       REQUIRE(httpdmgrp != NULL && VALID_HTTPDMGR(*httpdmgrp));
-       isc_httpdmgr_t *httpdmgr = *httpdmgrp;
-       *httpdmgrp = NULL;
+httpdmgr_detach(isc_httpdmgr_t **httpdmgrp) {
+       isc_httpdmgr_t *httpdmgr = NULL;
 
-       maybe_destroy_httpdmgr(httpdmgr);
-}
+       REQUIRE(httpdmgrp != NULL);
+       REQUIRE(VALID_HTTPDMGR(*httpdmgrp));
+
+       httpdmgr = *httpdmgrp;
+       *httpdmgrp = NULL;
 
-static void
-maybe_destroy_httpdmgr(isc_httpdmgr_t *httpdmgr) {
        if (isc_refcount_decrement(&httpdmgr->references) == 1) {
                destroy_httpdmgr(httpdmgr);
        }
@@ -425,14 +278,14 @@ destroy_httpdmgr(isc_httpdmgr_t *httpdmgr) {
 
        LOCK(&httpdmgr->lock);
 
-       httpdmgr->magic = 0;
+       REQUIRE((httpdmgr->flags & ISC_HTTPDMGR_SHUTTINGDOWN) != 0);
+       REQUIRE(ISC_LIST_EMPTY(httpdmgr->running));
 
-       INSIST(MSHUTTINGDOWN(httpdmgr));
-       INSIST(ISC_LIST_EMPTY(httpdmgr->running));
+       httpdmgr->magic = 0;
 
-       isc_socket_detach(&httpdmgr->sock);
-       isc_task_detach(&httpdmgr->task);
-       httpdmgr->timermgr = NULL;
+       if (httpdmgr->sock != NULL) {
+               isc_nmsocket_close(&httpdmgr->sock);
+       }
 
        /*
         * Clear out the list of all actions we know about.  Just free the
@@ -532,18 +385,18 @@ have_header(isc_httpd_t *httpd, const char *header, const char *value,
                                h++;
                        }
                }
+
                return (false);
        }
 }
 
 static isc_result_t
-process_request(isc_httpd_t *httpd, int length) {
-       char *s;
-       char *p;
+process_request(isc_httpd_t *httpd, isc_region_t *region) {
+       char *s = NULL, *p = NULL;
        int delim;
 
-       httpd->recvlen += length;
-
+       memmove(httpd->recvbuf + httpd->recvlen, region->base, region->length);
+       httpd->recvlen += region->length;
        httpd->recvbuf[httpd->recvlen] = 0;
        httpd->headers = NULL;
 
@@ -571,10 +424,10 @@ process_request(isc_httpd_t *httpd, int length) {
         * cause an error to be returned.
         */
        if (strncmp(httpd->recvbuf, "GET ", 4) == 0) {
-               httpd->method = ISC_HTTPD_METHODGET;
+               httpd->method = METHOD_GET;
                p = httpd->recvbuf + 4;
        } else if (strncmp(httpd->recvbuf, "POST ", 5) == 0) {
-               httpd->method = ISC_HTTPD_METHODPOST;
+               httpd->method = METHOD_POST;
                p = httpd->recvbuf + 5;
        } else {
                return (ISC_R_RANGE);
@@ -715,93 +568,134 @@ process_request(isc_httpd_t *httpd, int length) {
 }
 
 static void
-isc_httpd_create(isc_httpdmgr_t *httpdmgr, isc_socket_t *sock,
-                isc_httpd_t **httpdp) {
-       isc_httpd_t *httpd;
-       char *headerdata;
+httpd_reset(void *arg) {
+       isc_httpd_t *httpd = (isc_httpd_t *)arg;
+       isc_httpdmgr_t *httpdmgr = NULL;
+
+       REQUIRE(VALID_HTTPD(httpd));
+
+       httpdmgr = httpd->mgr;
+
+       REQUIRE(VALID_HTTPDMGR(httpdmgr));
+
+       LOCK(&httpdmgr->lock);
+       ISC_LIST_UNLINK(httpdmgr->running, httpd, link);
+       UNLOCK(&httpdmgr->lock);
+
+       httpd->recvbuf[0] = 0;
+       httpd->recvlen = 0;
+       httpd->headers = NULL;
+       httpd->method = METHOD_UNKNOWN;
+       httpd->url = NULL;
+       httpd->querystring = NULL;
+       httpd->protocol = NULL;
+       httpd->flags = 0;
 
+       isc_buffer_clear(&httpd->headerbuffer);
+       isc_buffer_clear(&httpd->compbuffer);
+       isc_buffer_invalidate(&httpd->bodybuffer);
+
+       httpdmgr_detach(&httpdmgr);
+}
+
+static void
+httpd_put(void *arg) {
+       isc_httpd_t *httpd = (isc_httpd_t *)arg;
+       isc_httpdmgr_t *httpdmgr = NULL;
+
+       REQUIRE(VALID_HTTPD(httpd));
+
+       httpdmgr = httpd->mgr;
        REQUIRE(VALID_HTTPDMGR(httpdmgr));
-       REQUIRE(httpdp != NULL && *httpdp == NULL);
 
-       httpd = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpd_t));
+       httpd->magic = 0;
 
-       *httpd = (isc_httpd_t){ .sock = sock };
+       free_buffer(httpdmgr->mctx, &httpd->headerbuffer);
+       free_buffer(httpdmgr->mctx, &httpd->compbuffer);
 
-       isc_httpdmgr_attach(httpdmgr, &httpd->mgr);
+#if ENABLE_AFL
+       if (finishhook != NULL) {
+               finishhook();
+       }
+#endif /* ENABLE_AFL */
+}
 
-       isc_refcount_init(&httpd->references, 1);
-       ISC_HTTPD_SETRECV(httpd);
-       isc_socket_setname(httpd->sock, "httpd", NULL);
+static isc_result_t
+new_httpd(isc_httpdmgr_t *httpdmgr, isc_nmhandle_t *handle) {
+       isc_result_t result;
+       isc_httpd_t *httpd = NULL;
+       char *headerdata = NULL;
+
+       REQUIRE(VALID_HTTPDMGR(httpdmgr));
+
+       httpd = isc_nmhandle_getdata(handle);
+       if (httpd == NULL) {
+               httpd = isc_nmhandle_getextra(handle);
+               *httpd = (isc_httpd_t){ .handle = NULL };
+       }
+
+       if (httpd->handle == NULL) {
+               isc_nmhandle_setdata(handle, httpd, httpd_reset, httpd_put);
+       } else {
+               INSIST(httpd->handle == handle);
+       }
+
+       httpdmgr_attach(httpdmgr, &httpd->mgr);
 
        /*
         * Initialize the buffer for our headers.
         */
        headerdata = isc_mem_get(httpdmgr->mctx, HTTP_SENDGROW);
        isc_buffer_init(&httpd->headerbuffer, headerdata, HTTP_SENDGROW);
+       isc_buffer_clear(&httpd->headerbuffer);
 
        isc_buffer_initnull(&httpd->compbuffer);
-       isc_buffer_initnull(&httpd->bodybuffer);
-       reset_client(httpd);
+       isc_buffer_clear(&httpd->compbuffer);
+
+       isc_buffer_invalidate(&httpd->bodybuffer);
 
        ISC_LINK_INIT(httpd, link);
-       ISC_LIST_APPEND(httpdmgr->running, httpd, link);
 
        httpd->magic = HTTPD_MAGIC;
+       httpd->state = RECV;
+
+       LOCK(&httpdmgr->lock);
+       ISC_LIST_APPEND(httpdmgr->running, httpd, link);
+       UNLOCK(&httpdmgr->lock);
+
+       isc_nmhandle_ref(handle);
+       result = isc_nm_read(handle, httpd_request, httpdmgr);
+       if (result != ISC_R_SUCCESS) {
+               isc_nmhandle_unref(handle);
+       }
 
-       *httpdp = httpd;
+       return (result);
 }
 
-static void
-isc_httpd_accept(isc_task_t *task, isc_event_t *ev) {
-       isc_httpdmgr_t *httpdmgr = ev->ev_arg;
-       isc_httpd_t *httpd = NULL;
-       isc_region_t r;
-       isc_socket_newconnev_t *nev = (isc_socket_newconnev_t *)ev;
+static isc_result_t
+httpd_newconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
+       isc_httpdmgr_t *httpdmgr = (isc_httpdmgr_t *)arg;
        isc_sockaddr_t peeraddr;
 
        REQUIRE(VALID_HTTPDMGR(httpdmgr));
 
-       LOCK(&httpdmgr->lock);
-       if (MSHUTTINGDOWN(httpdmgr)) {
-               goto out;
-       }
-
-       if (nev->result == ISC_R_CANCELED) {
-               goto out;
-       }
-
-       if (nev->result != ISC_R_SUCCESS) {
-               /* XXXMLG log failure */
-               goto requeue;
+       if ((httpdmgr->flags & ISC_HTTPDMGR_SHUTTINGDOWN) != 0) {
+               return (ISC_R_CANCELED);
+       } else if (result == ISC_R_CANCELED) {
+               isc_httpdmgr_shutdown(&httpdmgr);
+               return (result);
+       } else if (result != ISC_R_SUCCESS) {
+               return (result);
        }
 
-       (void)isc_socket_getpeername(nev->newsocket, &peeraddr);
+       peeraddr = isc_nmhandle_peeraddr(handle);
        if (httpdmgr->client_ok != NULL &&
            !(httpdmgr->client_ok)(&peeraddr, httpdmgr->cb_arg))
        {
-               isc_socket_detach(&nev->newsocket);
-               goto requeue;
-       }
-
-       isc_httpd_create(httpdmgr, nev->newsocket, &httpd);
-
-       r.base = (unsigned char *)httpd->recvbuf;
-       r.length = HTTP_RECVLEN - 1;
-
-       httpd_socket_recv(httpd, &r, task);
-
-requeue:
-       (void)httpdmgr_socket_accept(task, httpdmgr);
-
-out:
-       UNLOCK(&httpdmgr->lock);
-
-       if (httpd != NULL) {
-               maybe_destroy_httpd(httpd);
+               return (ISC_R_FAILURE);
        }
-       maybe_destroy_httpdmgr(httpdmgr);
 
-       isc_event_free(&ev);
+       return (new_httpd(httpdmgr, handle));
 }
 
 static isc_result_t
@@ -898,7 +792,7 @@ alloc_compspace(isc_httpd_t *httpd, unsigned int size) {
  *                          data would be larger than input data
  */
 static isc_result_t
-isc_httpd_compress(isc_httpd_t *httpd) {
+httpd_compress(isc_httpd_t *httpd) {
        z_stream zstr;
        isc_region_t r;
        isc_result_t result;
@@ -938,60 +832,53 @@ isc_httpd_compress(isc_httpd_t *httpd) {
 #endif /* ifdef HAVE_ZLIB */
 
 static void
-isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
+httpd_request(isc_nmhandle_t *handle, isc_result_t eresult,
+             isc_region_t *region, void *arg) {
        isc_result_t result;
-       isc_httpd_t *httpd = ev->ev_arg;
-       isc_socketevent_t *sev = (isc_socketevent_t *)ev;
-       isc_buffer_t *databuffer;
-       isc_httpdurl_t *url;
+       isc_httpd_t *httpd = NULL;
+       isc_httpdmgr_t *mgr = (isc_httpdmgr_t *)arg;
+       isc_buffer_t *databuffer = NULL;
+       isc_httpdurl_t *url = NULL;
        isc_time_t now;
        isc_region_t r;
        bool is_compressed = false;
        char datebuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
 
-       REQUIRE(VALID_HTTPD(httpd));
+       httpd = isc_nmhandle_getdata(handle);
 
-       INSIST(ISC_HTTPD_ISRECV(httpd));
+       REQUIRE(httpd->state == RECV);
 
-       if (sev->result != ISC_R_SUCCESS) {
-               goto out;
+       if (eresult != ISC_R_SUCCESS) {
+               goto done;
        }
 
-       result = process_request(httpd, sev->n);
+       result = process_request(httpd, region);
        if (result == ISC_R_NOTFOUND) {
-               if (httpd->recvlen >= HTTP_RECVLEN - 1) {
-                       goto out;
+               if (httpd->recvlen < HTTP_RECVLEN - 1) {
+                       /* don't unref, continue reading */
+                       return;
                }
-               r.base = (unsigned char *)httpd->recvbuf + httpd->recvlen;
-               r.length = HTTP_RECVLEN - httpd->recvlen - 1;
-
-               httpd_socket_recv(httpd, &r, task);
-               goto out;
+               goto done;
        } else if (result != ISC_R_SUCCESS) {
-               goto out;
+               goto done;
        }
 
-       ISC_HTTPD_SETSEND(httpd);
-
-       /*
-        * XXXMLG Call function here.  Provide an add-header function
-        * which will append the common headers to a response we generate.
-        */
        isc_buffer_initnull(&httpd->bodybuffer);
        isc_time_now(&now);
        isc_time_formathttptimestamp(&now, datebuf, sizeof(datebuf));
-       LOCK(&httpd->mgr->lock);
-       url = ISC_LIST_HEAD(httpd->mgr->urls);
+
+       LOCK(&mgr->lock);
+       url = ISC_LIST_HEAD(mgr->urls);
        while (url != NULL) {
                if (strcmp(httpd->url, url->url) == 0) {
                        break;
                }
                url = ISC_LIST_NEXT(url, link);
        }
-       UNLOCK(&httpd->mgr->lock);
+       UNLOCK(&mgr->lock);
 
        if (url == NULL) {
-               result = httpd->mgr->render_404(
+               result = mgr->render_404(
                        httpd->url, NULL, httpd->querystring, NULL, NULL,
                        &httpd->retcode, &httpd->retmsg, &httpd->mimetype,
                        &httpd->bodybuffer, &httpd->freecb, &httpd->freecb_arg);
@@ -1003,7 +890,7 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
                                     &httpd->freecb, &httpd->freecb_arg);
        }
        if (result != ISC_R_SUCCESS) {
-               result = httpd->mgr->render_500(
+               result = mgr->render_500(
                        httpd->url, url, httpd->querystring, NULL, NULL,
                        &httpd->retcode, &httpd->retmsg, &httpd->mimetype,
                        &httpd->bodybuffer, &httpd->freecb, &httpd->freecb_arg);
@@ -1012,69 +899,77 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
 
 #ifdef HAVE_ZLIB
        if ((httpd->flags & HTTPD_ACCEPT_DEFLATE) != 0) {
-               result = isc_httpd_compress(httpd);
+               result = httpd_compress(httpd);
                if (result == ISC_R_SUCCESS) {
                        is_compressed = true;
                }
        }
 #endif /* ifdef HAVE_ZLIB */
 
-       isc_httpd_response(httpd);
+       httpd_response(httpd);
        if ((httpd->flags & HTTPD_KEEPALIVE) != 0) {
-               isc_httpd_addheader(httpd, "Connection", "Keep-Alive");
+               httpd_addheader(httpd, "Connection", "Keep-Alive");
        }
-       isc_httpd_addheader(httpd, "Content-Type", httpd->mimetype);
-       isc_httpd_addheader(httpd, "Date", datebuf);
-       isc_httpd_addheader(httpd, "Expires", datebuf);
+       httpd_addheader(httpd, "Content-Type", httpd->mimetype);
+       httpd_addheader(httpd, "Date", datebuf);
+       httpd_addheader(httpd, "Expires", datebuf);
 
        if (url != NULL && url->isstatic) {
                char loadbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
                isc_time_formathttptimestamp(&url->loadtime, loadbuf,
                                             sizeof(loadbuf));
-               isc_httpd_addheader(httpd, "Last-Modified", loadbuf);
-               isc_httpd_addheader(httpd, "Cache-Control: public", NULL);
+               httpd_addheader(httpd, "Last-Modified", loadbuf);
+               httpd_addheader(httpd, "Cache-Control: public", NULL);
        } else {
-               isc_httpd_addheader(httpd, "Last-Modified", datebuf);
-               isc_httpd_addheader(httpd, "Pragma: no-cache", NULL);
-               isc_httpd_addheader(httpd, "Cache-Control: no-cache", NULL);
+               httpd_addheader(httpd, "Last-Modified", datebuf);
+               httpd_addheader(httpd, "Pragma: no-cache", NULL);
+               httpd_addheader(httpd, "Cache-Control: no-cache", NULL);
        }
 
-       isc_httpd_addheader(httpd, "Server: libisc", NULL);
+       httpd_addheader(httpd, "Server: libisc", NULL);
 
        if (is_compressed) {
-               isc_httpd_addheader(httpd, "Content-Encoding", "deflate");
-               isc_httpd_addheaderuint(
-                       httpd, "Content-Length",
-                       isc_buffer_usedlength(&httpd->compbuffer));
+               httpd_addheader(httpd, "Content-Encoding", "deflate");
+               httpd_addheaderuint(httpd, "Content-Length",
+                                   isc_buffer_usedlength(&httpd->compbuffer));
        } else {
-               isc_httpd_addheaderuint(
-                       httpd, "Content-Length",
-                       isc_buffer_usedlength(&httpd->bodybuffer));
+               httpd_addheaderuint(httpd, "Content-Length",
+                                   isc_buffer_usedlength(&httpd->bodybuffer));
        }
 
-       isc_httpd_endheaders(httpd); /* done */
+       httpd_endheaders(httpd); /* done */
 
        /*
         * Append either the compressed or the non-compressed response body to
         * the response headers and store the result in httpd->sendbuffer.
         */
-       isc_buffer_dup(httpd->mgr->mctx, &httpd->sendbuffer,
-                      &httpd->headerbuffer);
+       isc_buffer_dup(mgr->mctx, &httpd->sendbuffer, &httpd->headerbuffer);
        isc_buffer_setautorealloc(httpd->sendbuffer, true);
        databuffer = (is_compressed ? &httpd->compbuffer : &httpd->bodybuffer);
        isc_buffer_usedregion(databuffer, &r);
        result = isc_buffer_copyregion(httpd->sendbuffer, &r);
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
        /*
         * Determine total response size.
         */
        isc_buffer_usedregion(httpd->sendbuffer, &r);
 
-       httpd_socket_send(httpd, &r, task);
+       isc_nm_pauseread(handle);
+       httpd->state = SEND;
+
+       isc_nmhandle_ref(handle);
+       result = isc_nm_send(handle, &r, httpd_senddone, httpd);
+       if (result != ISC_R_SUCCESS) {
+               isc_nm_resumeread(handle);
+               isc_nmhandle_unref(handle);
+
+               httpd->state = RECV;
+       }
 
-out:
-       maybe_destroy_httpd(httpd);
-       isc_event_free(&ev);
+       return;
+done:
+       isc_nmhandle_unref(handle);
 }
 
 void
@@ -1083,31 +978,29 @@ isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp) {
        isc_httpd_t *httpd;
 
        REQUIRE(httpdmgrp != NULL);
+       REQUIRE(VALID_HTTPDMGR(*httpdmgrp));
+
        httpdmgr = *httpdmgrp;
        *httpdmgrp = NULL;
-       REQUIRE(VALID_HTTPDMGR(httpdmgr));
-
-       LOCK(&httpdmgr->lock);
 
-       MSETSHUTTINGDOWN(httpdmgr);
+       isc_nm_stoplistening(httpdmgr->sock);
 
-       isc_socket_cancel(httpdmgr->sock, httpdmgr->task, ISC_SOCKCANCEL_ALL);
+       LOCK(&httpdmgr->lock);
+       httpdmgr->flags |= ISC_HTTPDMGR_SHUTTINGDOWN;
 
        httpd = ISC_LIST_HEAD(httpdmgr->running);
        while (httpd != NULL) {
-               isc_socket_cancel(httpd->sock, httpdmgr->task,
-                                 ISC_SOCKCANCEL_ALL);
+               isc_nmhandle_unref(httpd->handle);
                httpd = ISC_LIST_NEXT(httpd, link);
        }
-
        UNLOCK(&httpdmgr->lock);
 
-       maybe_destroy_httpdmgr(httpdmgr);
+       httpdmgr_detach(&httpdmgr);
 }
 
 static isc_result_t
 grow_headerspace(isc_httpd_t *httpd) {
-       char *newspace;
+       char *newspace = NULL;
        unsigned int newlen;
        isc_region_t r;
 
@@ -1126,8 +1019,8 @@ grow_headerspace(isc_httpd_t *httpd) {
        return (ISC_R_SUCCESS);
 }
 
-isc_result_t
-isc_httpd_response(isc_httpd_t *httpd) {
+static isc_result_t
+httpd_response(isc_httpd_t *httpd) {
        isc_result_t result;
        unsigned int needlen;
 
@@ -1149,8 +1042,8 @@ isc_httpd_response(isc_httpd_t *httpd) {
                                  httpd->retmsg));
 }
 
-isc_result_t
-isc_httpd_addheader(isc_httpd_t *httpd, const char *name, const char *val) {
+static isc_result_t
+httpd_addheader(isc_httpd_t *httpd, const char *name, const char *val) {
        isc_result_t result;
        unsigned int needlen;
 
@@ -1178,8 +1071,8 @@ isc_httpd_addheader(isc_httpd_t *httpd, const char *name, const char *val) {
        }
 }
 
-isc_result_t
-isc_httpd_endheaders(isc_httpd_t *httpd) {
+static isc_result_t
+httpd_endheaders(isc_httpd_t *httpd) {
        isc_result_t result;
 
        REQUIRE(VALID_HTTPD(httpd));
@@ -1194,8 +1087,8 @@ isc_httpd_endheaders(isc_httpd_t *httpd) {
        return (isc_buffer_printf(&httpd->headerbuffer, "\r\n"));
 }
 
-isc_result_t
-isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val) {
+static isc_result_t
+httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val) {
        isc_result_t result;
        unsigned int needlen;
        char buf[sizeof "18446744073709551616"];
@@ -1220,23 +1113,17 @@ isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val) {
 }
 
 static void
-isc_httpd_senddone(isc_task_t *task, isc_event_t *ev) {
-       isc_httpd_t *httpd = ev->ev_arg;
-       isc_region_t r;
-       isc_socketevent_t *sev = (isc_socketevent_t *)ev;
+httpd_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
+       isc_httpd_t *httpd = (isc_httpd_t *)arg;
 
        REQUIRE(VALID_HTTPD(httpd));
-
-       INSIST(ISC_HTTPD_ISSEND(httpd));
+       REQUIRE(httpd->state == SEND);
 
        isc_buffer_free(&httpd->sendbuffer);
 
        /*
         * We will always want to clean up our receive buffer, even if we
         * got an error on send or we are shutting down.
-        *
-        * We will pass in the buffer only if there is data in it.  If
-        * there is no data, we will pass in a NULL.
         */
        if (httpd->freecb != NULL) {
                isc_buffer_t *b = NULL;
@@ -1246,63 +1133,18 @@ isc_httpd_senddone(isc_task_t *task, isc_event_t *ev) {
                }
        }
 
-       if (sev->result != ISC_R_SUCCESS) {
-               goto out;
-       }
-
-       if ((httpd->flags & HTTPD_CLOSE) != 0) {
-               goto out;
+       if (result != ISC_R_SUCCESS) {
+               return;
        }
 
-       ISC_HTTPD_SETRECV(httpd);
-
-       reset_client(httpd);
-
-       r.base = (unsigned char *)httpd->recvbuf;
-       r.length = HTTP_RECVLEN - 1;
-
-       httpd_socket_recv(httpd, &r, task);
-
-out:
-       maybe_destroy_httpd(httpd);
-       isc_event_free(&ev);
-}
-
-static void
-reset_client(isc_httpd_t *httpd) {
-       /*
-        * Catch errors here.  We MUST be in RECV mode, and we MUST NOT have
-        * any outstanding buffers.  If we have buffers, we have a leak.
-        */
-       INSIST(ISC_HTTPD_ISRECV(httpd));
-       INSIST(!ISC_LINK_LINKED(&httpd->headerbuffer, link));
-       INSIST(!ISC_LINK_LINKED(&httpd->bodybuffer, link));
-
-       httpd->recvbuf[0] = 0;
-       httpd->recvlen = 0;
-       httpd->headers = NULL;
-       httpd->method = ISC_HTTPD_METHODUNKNOWN;
-       httpd->url = NULL;
-       httpd->querystring = NULL;
-       httpd->protocol = NULL;
-       httpd->flags = 0;
-
-       isc_buffer_clear(&httpd->headerbuffer);
-       isc_buffer_clear(&httpd->compbuffer);
-       isc_buffer_invalidate(&httpd->bodybuffer);
+       httpd->state = RECV;
+       isc_nm_resumeread(handle);
+       isc_nmhandle_unref(handle);
 }
 
 isc_result_t
-isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
+isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url, bool isstatic,
                    isc_httpdaction_t *func, void *arg) {
-       /* REQUIRE(VALID_HTTPDMGR(httpdmgr)); Dummy function */
-
-       return (isc_httpdmgr_addurl2(httpdmgr, url, false, func, arg));
-}
-
-isc_result_t
-isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url, bool isstatic,
-                    isc_httpdaction_t *func, void *arg) {
        isc_httpdurl_t *item;
 
        REQUIRE(VALID_HTTPDMGR(httpdmgr));
index cfc3508054e6bd39ef0781d3b3a2ead5cac0c63d..bc52f4b14e9844cc9284959fc0bc60400a32f8de 100644 (file)
@@ -42,41 +42,21 @@ struct isc_httpdurl {
 #define HTTPD_EVENTCLASS ISC_EVENTCLASS(4300)
 #define HTTPD_SHUTDOWN  (HTTPD_EVENTCLASS + 0x0001)
 
-#define ISC_HTTPDMGR_FLAGSHUTTINGDOWN 0x00000001
+#define ISC_HTTPDMGR_SHUTTINGDOWN 0x00000001
 
-/*
- * Create a new http daemon which will send, once every time period,
- * a http-like header followed by HTTP data.
- */
 isc_result_t
-isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
+isc_httpdmgr_create(isc_nm_t *nm, isc_mem_t *mctx, isc_sockaddr_t *addr,
                    isc_httpdclientok_t * client_ok,
-                   isc_httpdondestroy_t *ondestory, void *cb_arg,
-                   isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdp);
+                   isc_httpdondestroy_t *ondestroy, void *cb_arg,
+                   isc_httpdmgr_t **httpdmgrp);
 
 void
 isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdp);
 
 isc_result_t
-isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
+isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url, bool isstatic,
                    isc_httpdaction_t *func, void *arg);
 
-isc_result_t
-isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url, bool isstatic,
-                    isc_httpdaction_t *func, void *arg);
-
-isc_result_t
-isc_httpd_response(isc_httpd_t *httpd);
-
-isc_result_t
-isc_httpd_addheader(isc_httpd_t *httpd, const char *name, const char *val);
-
-isc_result_t
-isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val);
-
-isc_result_t
-isc_httpd_endheaders(isc_httpd_t *httpd);
-
 void
 isc_httpd_setfinishhook(void (*fn)(void));
 
index 102a2263ed654161430c25d29b13b3be30c6adeb..496464328e8d0a99e0cef389fce7397f6e793c85 100644 (file)
@@ -291,13 +291,8 @@ isc_ht_iter_delcurrent_next
 isc_ht_iter_destroy
 isc_ht_iter_first
 isc_ht_iter_next
-isc_httpd_addheader
-isc_httpd_addheaderuint
-isc_httpd_endheaders
-isc_httpd_response
 isc_httpd_setfinishhook
 isc_httpdmgr_addurl
-isc_httpdmgr_addurl2
 isc_httpdmgr_create
 isc_httpdmgr_shutdown
 isc_interfaceiter_create