2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 14:35:26 +00:00

[master] stats improvements

3700.	[func]		Allow access to subgroups of XML statistics via
			special URLs http://<server>:<port>/xml/v3/server,
			/zones, /net, /tasks, /mem, and /status.  [RT #35115]

3699.	[bug]		Improvements to statistics channel XSL stylesheet:
			the stylesheet can now be cached by the browser;
			section headers are omitted from the stats display
			when there is no data in those sections to be
			displayed; counters are now right-justified for
			easier readability. [RT #35117]
This commit is contained in:
Evan Hunt
2014-01-09 15:14:57 -08:00
parent d4eb30fa2d
commit 789252d55f
12 changed files with 1447 additions and 894 deletions

View File

@@ -26,6 +26,7 @@
#include <isc/socket.h>
#include <isc/string.h>
#include <isc/task.h>
#include <isc/time.h>
#include <isc/util.h>
#include <string.h>
@@ -58,20 +59,6 @@
#define HTTP_SENDGROW 1024
#define HTTP_SEND_MAXLEN 10240
/*%
* HTTP urls. These are the URLs we manage, and the function to call to
* provide the data for it. We pass in the base url (so the same function
* can handle multiple requests), and a structure to fill in to return a
* result to the client. We also pass in a pointer to be filled in for
* the data cleanup function.
*/
struct isc_httpdurl {
char *url;
isc_httpdaction_t *action;
void *action_arg;
ISC_LINK(isc_httpdurl_t) link;
};
#define HTTPD_CLOSE 0x0001 /* Got a Connection: close header */
#define HTTPD_FOUNDHOST 0x0002 /* Got a Host: header */
@@ -87,6 +74,7 @@ struct isc_httpd {
*/
char recvbuf[HTTP_RECVLEN]; /*%< receive buffer */
isc_uint32_t recvlen; /*%< length recv'd */
char *headers; /*%< set in process_request() */
unsigned int method;
char *url;
char *querystring;
@@ -217,20 +205,12 @@ static isc_result_t process_request(isc_httpd_t *, int);
static void httpdmgr_destroy(isc_httpdmgr_t *);
static isc_result_t grow_headerspace(isc_httpd_t *);
static void reset_client(isc_httpd_t *httpd);
static isc_result_t render_404(const char *, const char *,
void *,
unsigned int *, const char **,
const char **, isc_buffer_t *,
isc_httpdfree_t **, void **);
static isc_result_t render_500(const char *, const char *,
void *,
unsigned int *, const char **,
const char **, isc_buffer_t *,
isc_httpdfree_t **, void **);
static isc_httpdaction_t render_404;
static isc_httpdaction_t render_500;
static void
destroy_client(isc_httpd_t **httpdp)
{
destroy_client(isc_httpd_t **httpdp) {
isc_httpd_t *httpd = *httpdp;
isc_httpdmgr_t *httpdmgr = httpd->mgr;
@@ -321,8 +301,7 @@ isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
}
static void
httpdmgr_destroy(isc_httpdmgr_t *httpdmgr)
{
httpdmgr_destroy(isc_httpdmgr_t *httpdmgr) {
isc_mem_t *mctx;
isc_httpdurl_t *url;
@@ -379,8 +358,7 @@ httpdmgr_destroy(isc_httpdmgr_t *httpdmgr)
#define BUFLENOK(s) (httpd->recvbuf - (s) < HTTP_RECVLEN)
static isc_result_t
process_request(isc_httpd_t *httpd, int length)
{
process_request(isc_httpd_t *httpd, int length) {
char *s;
char *p;
int delim;
@@ -390,6 +368,7 @@ process_request(isc_httpd_t *httpd, int length)
httpd->recvlen += length;
httpd->recvbuf[httpd->recvlen] = 0;
httpd->headers = NULL;
/*
* If we don't find a blank line in our buffer, return that we need
@@ -494,6 +473,8 @@ process_request(isc_httpd_t *httpd, int length)
p = s + 1;
s = p;
httpd->headers = s;
if (strstr(s, "Connection: close") != NULL)
httpd->flags |= HTTPD_CLOSE;
@@ -513,8 +494,7 @@ process_request(isc_httpd_t *httpd, int length)
}
static void
isc_httpd_accept(isc_task_t *task, isc_event_t *ev)
{
isc_httpd_accept(isc_task_t *task, isc_event_t *ev) {
isc_result_t result;
isc_httpdmgr_t *httpdmgr = ev->ev_arg;
isc_httpd_t *httpd;
@@ -609,8 +589,8 @@ isc_httpd_accept(isc_task_t *task, isc_event_t *ev)
}
static isc_result_t
render_404(const char *url, const char *querystring,
void *arg,
render_404(const char *url, isc_httpdurl_t *urlinfo,
const char *querystring, const char *headers, void *arg,
unsigned int *retcode, const char **retmsg,
const char **mimetype, isc_buffer_t *b,
isc_httpdfree_t **freecb, void **freecb_args)
@@ -618,7 +598,9 @@ render_404(const char *url, const char *querystring,
static char msg[] = "No such URL.";
UNUSED(url);
UNUSED(urlinfo);
UNUSED(querystring);
UNUSED(headers);
UNUSED(arg);
*retcode = 404;
@@ -633,8 +615,8 @@ render_404(const char *url, const char *querystring,
}
static isc_result_t
render_500(const char *url, const char *querystring,
void *arg,
render_500(const char *url, isc_httpdurl_t *urlinfo,
const char *querystring, const char *headers, void *arg,
unsigned int *retcode, const char **retmsg,
const char **mimetype, isc_buffer_t *b,
isc_httpdfree_t **freecb, void **freecb_args)
@@ -642,7 +624,9 @@ render_500(const char *url, const char *querystring,
static char msg[] = "Internal server failure.";
UNUSED(url);
UNUSED(urlinfo);
UNUSED(querystring);
UNUSED(headers);
UNUSED(arg);
*retcode = 500;
@@ -657,8 +641,7 @@ render_500(const char *url, const char *querystring,
}
static void
isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
{
isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
isc_region_t r;
isc_result_t result;
isc_httpd_t *httpd = ev->ev_arg;
@@ -710,8 +693,9 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
url = ISC_LIST_NEXT(url, link);
}
if (url == NULL)
result = httpd->mgr->render_404(httpd->url, httpd->querystring,
NULL,
result = httpd->mgr->render_404(httpd->url, NULL,
httpd->querystring,
NULL, NULL,
&httpd->retcode,
&httpd->retmsg,
&httpd->mimetype,
@@ -719,14 +703,18 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
&httpd->freecb,
&httpd->freecb_arg);
else
result = url->action(httpd->url, httpd->querystring,
result = url->action(httpd->url, url,
httpd->querystring,
httpd->headers,
url->action_arg,
&httpd->retcode, &httpd->retmsg,
&httpd->mimetype, &httpd->bodybuffer,
&httpd->freecb, &httpd->freecb_arg);
if (result != ISC_R_SUCCESS) {
result = httpd->mgr->render_500(httpd->url, httpd->querystring,
NULL, &httpd->retcode,
result = httpd->mgr->render_500(httpd->url, url,
httpd->querystring,
NULL, NULL,
&httpd->retcode,
&httpd->retmsg,
&httpd->mimetype,
&httpd->bodybuffer,
@@ -739,9 +727,19 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
isc_httpd_addheader(httpd, "Content-Type", httpd->mimetype);
isc_httpd_addheader(httpd, "Date", datebuf);
isc_httpd_addheader(httpd, "Expires", datebuf);
isc_httpd_addheader(httpd, "Last-Modified", datebuf);
isc_httpd_addheader(httpd, "Pragma: no-cache", NULL);
isc_httpd_addheader(httpd, "Cache-Control: no-cache", NULL);
if (url != NULL && url->isstatic) {
char loadbuf[32];
isc_time_formathttptimestamp(&url->loadtime,
loadbuf, sizeof(loadbuf));
isc_httpd_addheader(httpd, "Last-Modified", loadbuf);
isc_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);
}
isc_httpd_addheader(httpd, "Server: libisc", NULL);
isc_httpd_addheaderuint(httpd, "Content-Length",
isc_buffer_usedlength(&httpd->bodybuffer));
@@ -766,8 +764,7 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
}
void
isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp)
{
isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp) {
isc_httpdmgr_t *httpdmgr;
isc_httpd_t *httpd;
httpdmgr = *httpdmgrp;
@@ -794,8 +791,7 @@ isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp)
}
static isc_result_t
grow_headerspace(isc_httpd_t *httpd)
{
grow_headerspace(isc_httpd_t *httpd) {
char *newspace;
unsigned int newlen;
isc_region_t r;
@@ -816,8 +812,7 @@ grow_headerspace(isc_httpd_t *httpd)
}
isc_result_t
isc_httpd_response(isc_httpd_t *httpd)
{
isc_httpd_response(isc_httpd_t *httpd) {
isc_result_t result;
unsigned int needlen;
@@ -869,8 +864,7 @@ isc_httpd_addheader(isc_httpd_t *httpd, const char *name,
}
isc_result_t
isc_httpd_endheaders(isc_httpd_t *httpd)
{
isc_httpd_endheaders(isc_httpd_t *httpd) {
isc_result_t result;
while (isc_buffer_availablelength(&httpd->headerbuffer) < 2) {
@@ -912,8 +906,7 @@ 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_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;
@@ -977,8 +970,7 @@ out:
}
static void
reset_client(isc_httpd_t *httpd)
{
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.
@@ -989,6 +981,7 @@ reset_client(isc_httpd_t *httpd)
httpd->recvbuf[0] = 0;
httpd->recvlen = 0;
httpd->headers = NULL;
httpd->method = ISC_HTTPD_METHODUNKNOWN;
httpd->url = NULL;
httpd->querystring = NULL;
@@ -1002,6 +995,14 @@ reset_client(isc_httpd_t *httpd)
isc_result_t
isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
isc_httpdaction_t *func, void *arg)
{
return (isc_httpdmgr_addurl2(httpdmgr, url, ISC_FALSE, func, arg));
}
isc_result_t
isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url,
isc_boolean_t isstatic,
isc_httpdaction_t *func, void *arg)
{
isc_httpdurl_t *item;
@@ -1022,6 +1023,9 @@ isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
item->action = func;
item->action_arg = arg;
item->isstatic = isstatic;
isc_time_now(&item->loadtime);
ISC_LINK_INIT(item, link);
ISC_LIST_APPEND(httpdmgr->urls, item, link);

View File

@@ -26,6 +26,23 @@
#include <isc/types.h>
#include <isc/mutex.h>
#include <isc/task.h>
#include <isc/time.h>
/*%
* HTTP urls. These are the URLs we manage, and the function to call to
* provide the data for it. We pass in the base url (so the same function
* can handle multiple requests), and a structure to fill in to return a
* result to the client. We also pass in a pointer to be filled in for
* the data cleanup function.
*/
struct isc_httpdurl {
char *url;
isc_httpdaction_t *action;
void *action_arg;
isc_boolean_t isstatic;
isc_time_t loadtime;
ISC_LINK(isc_httpdurl_t) link;
};
#define HTTPD_EVENTCLASS ISC_EVENTCLASS(4300)
#define HTTPD_SHUTDOWN (HTTPD_EVENTCLASS + 0x0001)
@@ -49,6 +66,11 @@ isc_result_t
isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
isc_httpdaction_t *func, void *arg);
isc_result_t
isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url,
isc_boolean_t isstatic,
isc_httpdaction_t *func, void *arg);
isc_result_t
isc_httpd_response(isc_httpd_t *httpd);

View File

@@ -103,7 +103,9 @@ typedef int (*isc_sockfdwatch_t)(isc_task_t *, isc_socket_t *, void *, int);
/* The following cannot be listed alphabetically due to forward reference */
typedef isc_result_t (isc_httpdaction_t)(const char *url,
isc_httpdurl_t *urlinfo,
const char *querystring,
const char *headers,
void *arg,
unsigned int *retcode,
const char **retmsg,

View File

@@ -315,6 +315,16 @@ isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len);
*
*/
isc_result_t
isc_time_parsehttptimestamp(char *input, isc_time_t *t);
/*%<
* Parse the time in 'input' into the isc_time_t pointed to by 't',
* expecting a format like "Mon, 30 Aug 2000 04:06:47 GMT"
*
* Requires:
*\li 'buf' and 't' are not NULL.
*/
void
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len);
/*%<

View File

@@ -407,6 +407,24 @@ isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
INSIST(flen < len);
}
isc_result_t
isc_time_parsehttptimestamp(char *buf, isc_time_t *t) {
struct tm t_tm;
time_t when;
char *p;
REQUIRE(buf != NULL);
REQUIRE(t != NULL);
p = strptime(buf, "%a, %d %b %Y %H:%M:%S %Z", &t_tm);
if (p == NULL)
return (ISC_R_UNEXPECTED);
when = timegm(&t_tm);
if (when == -1)
return (ISC_R_UNEXPECTED);
isc_time_set(t, when, 0);
return (ISC_R_SUCCESS);
}
void
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
time_t now;