Annotation of embedaddon/lighttpd/src/mod_status.c, revision 1.1

1.1     ! misho       1: #include "server.h"
        !             2: #include "connections.h"
        !             3: #include "response.h"
        !             4: #include "connections.h"
        !             5: #include "log.h"
        !             6: 
        !             7: #include "plugin.h"
        !             8: 
        !             9: #include "inet_ntop_cache.h"
        !            10: 
        !            11: #include <sys/types.h>
        !            12: 
        !            13: #include <fcntl.h>
        !            14: #include <stdlib.h>
        !            15: #include <string.h>
        !            16: #include <unistd.h>
        !            17: #include <errno.h>
        !            18: #include <time.h>
        !            19: #include <stdio.h>
        !            20: 
        !            21: #include "version.h"
        !            22: 
        !            23: typedef struct {
        !            24:        buffer *config_url;
        !            25:        buffer *status_url;
        !            26:        buffer *statistics_url;
        !            27: 
        !            28:        int     sort;
        !            29: } plugin_config;
        !            30: 
        !            31: typedef struct {
        !            32:        PLUGIN_DATA;
        !            33: 
        !            34:        double traffic_out;
        !            35:        double requests;
        !            36: 
        !            37:        double mod_5s_traffic_out[5];
        !            38:        double mod_5s_requests[5];
        !            39:        size_t mod_5s_ndx;
        !            40: 
        !            41:        double rel_traffic_out;
        !            42:        double rel_requests;
        !            43: 
        !            44:        double abs_traffic_out;
        !            45:        double abs_requests;
        !            46: 
        !            47:        double bytes_written;
        !            48: 
        !            49:        buffer *module_list;
        !            50: 
        !            51:        plugin_config **config_storage;
        !            52: 
        !            53:        plugin_config conf;
        !            54: } plugin_data;
        !            55: 
        !            56: INIT_FUNC(mod_status_init) {
        !            57:        plugin_data *p;
        !            58:        size_t i;
        !            59: 
        !            60:        p = calloc(1, sizeof(*p));
        !            61: 
        !            62:        p->traffic_out = p->requests = 0;
        !            63:        p->rel_traffic_out = p->rel_requests = 0;
        !            64:        p->abs_traffic_out = p->abs_requests = 0;
        !            65:        p->bytes_written = 0;
        !            66:        p->module_list = buffer_init();
        !            67: 
        !            68:        for (i = 0; i < 5; i++) {
        !            69:                p->mod_5s_traffic_out[i] = p->mod_5s_requests[i] = 0;
        !            70:        }
        !            71: 
        !            72:        return p;
        !            73: }
        !            74: 
        !            75: FREE_FUNC(mod_status_free) {
        !            76:        plugin_data *p = p_d;
        !            77: 
        !            78:        UNUSED(srv);
        !            79: 
        !            80:        if (!p) return HANDLER_GO_ON;
        !            81: 
        !            82:        buffer_free(p->module_list);
        !            83: 
        !            84:        if (p->config_storage) {
        !            85:                size_t i;
        !            86:                for (i = 0; i < srv->config_context->used; i++) {
        !            87:                        plugin_config *s = p->config_storage[i];
        !            88: 
        !            89:                        buffer_free(s->status_url);
        !            90:                        buffer_free(s->statistics_url);
        !            91:                        buffer_free(s->config_url);
        !            92: 
        !            93:                        free(s);
        !            94:                }
        !            95:                free(p->config_storage);
        !            96:        }
        !            97: 
        !            98: 
        !            99:        free(p);
        !           100: 
        !           101:        return HANDLER_GO_ON;
        !           102: }
        !           103: 
        !           104: SETDEFAULTS_FUNC(mod_status_set_defaults) {
        !           105:        plugin_data *p = p_d;
        !           106:        size_t i;
        !           107: 
        !           108:        config_values_t cv[] = {
        !           109:                { "status.status-url",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
        !           110:                { "status.config-url",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
        !           111:                { "status.enable-sort",          NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
        !           112:                { "status.statistics-url",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
        !           113:                { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
        !           114:        };
        !           115: 
        !           116:        if (!p) return HANDLER_ERROR;
        !           117: 
        !           118:        p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
        !           119: 
        !           120:        for (i = 0; i < srv->config_context->used; i++) {
        !           121:                plugin_config *s;
        !           122: 
        !           123:                s = calloc(1, sizeof(plugin_config));
        !           124:                s->config_url    = buffer_init();
        !           125:                s->status_url    = buffer_init();
        !           126:                s->sort          = 1;
        !           127:                s->statistics_url    = buffer_init();
        !           128: 
        !           129:                cv[0].destination = s->status_url;
        !           130:                cv[1].destination = s->config_url;
        !           131:                cv[2].destination = &(s->sort);
        !           132:                cv[3].destination = s->statistics_url;
        !           133: 
        !           134:                p->config_storage[i] = s;
        !           135: 
        !           136:                if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
        !           137:                        return HANDLER_ERROR;
        !           138:                }
        !           139:        }
        !           140: 
        !           141:        return HANDLER_GO_ON;
        !           142: }
        !           143: 
        !           144: 
        !           145: 
        !           146: static int mod_status_row_append(buffer *b, const char *key, const char *value) {
        !           147:        buffer_append_string_len(b, CONST_STR_LEN("   <tr>\n"));
        !           148:        buffer_append_string_len(b, CONST_STR_LEN("    <td><b>"));
        !           149:        buffer_append_string(b, key);
        !           150:        buffer_append_string_len(b, CONST_STR_LEN("</b></td>\n"));
        !           151:        buffer_append_string_len(b, CONST_STR_LEN("    <td>"));
        !           152:        buffer_append_string(b, value);
        !           153:        buffer_append_string_len(b, CONST_STR_LEN("</td>\n"));
        !           154:        buffer_append_string_len(b, CONST_STR_LEN("   </tr>\n"));
        !           155: 
        !           156:        return 0;
        !           157: }
        !           158: 
        !           159: static int mod_status_header_append(buffer *b, const char *key) {
        !           160:        buffer_append_string_len(b, CONST_STR_LEN("   <tr>\n"));
        !           161:        buffer_append_string_len(b, CONST_STR_LEN("    <th colspan=\"2\">"));
        !           162:        buffer_append_string(b, key);
        !           163:        buffer_append_string_len(b, CONST_STR_LEN("</th>\n"));
        !           164:        buffer_append_string_len(b, CONST_STR_LEN("   </tr>\n"));
        !           165: 
        !           166:        return 0;
        !           167: }
        !           168: 
        !           169: static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) {
        !           170:        plugin_data *p = p_d;
        !           171: 
        !           172:        if (p->conf.sort) {
        !           173:                buffer_append_string_len(b, CONST_STR_LEN("<th class=\"status\"><a href=\"#\" class=\"sortheader\" onclick=\"resort(this);return false;\">"));
        !           174:                buffer_append_string(b, key);
        !           175:                buffer_append_string_len(b, CONST_STR_LEN("<span class=\"sortarrow\">:</span></a></th>\n"));
        !           176:        } else {
        !           177:                buffer_append_string_len(b, CONST_STR_LEN("<th class=\"status\">"));
        !           178:                buffer_append_string(b, key);
        !           179:                buffer_append_string_len(b, CONST_STR_LEN("</th>\n"));
        !           180:        }
        !           181: 
        !           182:        return 0;
        !           183: }
        !           184: 
        !           185: static int mod_status_get_multiplier(double *avg, char *multiplier, int size) {
        !           186:        *multiplier = ' ';
        !           187: 
        !           188:        if (*avg > size) { *avg /= size; *multiplier = 'k'; }
        !           189:        if (*avg > size) { *avg /= size; *multiplier = 'M'; }
        !           190:        if (*avg > size) { *avg /= size; *multiplier = 'G'; }
        !           191:        if (*avg > size) { *avg /= size; *multiplier = 'T'; }
        !           192:        if (*avg > size) { *avg /= size; *multiplier = 'P'; }
        !           193:        if (*avg > size) { *avg /= size; *multiplier = 'E'; }
        !           194:        if (*avg > size) { *avg /= size; *multiplier = 'Z'; }
        !           195:        if (*avg > size) { *avg /= size; *multiplier = 'Y'; }
        !           196: 
        !           197:        return 0;
        !           198: }
        !           199: 
        !           200: static handler_t mod_status_handle_server_status_html(server *srv, connection *con, void *p_d) {
        !           201:        plugin_data *p = p_d;
        !           202:        buffer *b;
        !           203:        size_t j;
        !           204:        double avg;
        !           205:        char multiplier = '\0';
        !           206:        char buf[32];
        !           207:        time_t ts;
        !           208: 
        !           209:        int days, hours, mins, seconds;
        !           210: 
        !           211:        b = chunkqueue_get_append_buffer(con->write_queue);
        !           212: 
        !           213:        buffer_copy_string_len(b, CONST_STR_LEN(
        !           214:                                 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
        !           215:                                 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
        !           216:                                 "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
        !           217:                                 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
        !           218:                                 " <head>\n"
        !           219:                                 "  <title>Status</title>\n"
        !           220: 
        !           221:                                   "  <style type=\"text/css\">\n"
        !           222:                                   "    table.status { border: black solid thin; }\n"
        !           223:                                   "    td { white-space: nowrap; }\n"
        !           224:                                   "    td.int { background-color: #f0f0f0; text-align: right }\n"
        !           225:                                   "    td.string { background-color: #f0f0f0; text-align: left }\n"
        !           226:                                   "    th.status { background-color: black; color: white; font-weight: bold; }\n"
        !           227:                                   "    a.sortheader { background-color: black; color: white; font-weight: bold; text-decoration: none; display: block; }\n"
        !           228:                                   "    span.sortarrow { color: white; text-decoration: none; }\n"
        !           229:                                   "  </style>\n"));
        !           230: 
        !           231:        if (p->conf.sort) {
        !           232:                buffer_append_string_len(b, CONST_STR_LEN(
        !           233:                                           "<script type=\"text/javascript\">\n"
        !           234:                                           "// <!--\n"
        !           235:                                           "var sort_column;\n"
        !           236:                                           "var prev_span = null;\n"
        !           237: 
        !           238:                                           "function get_inner_text(el) {\n"
        !           239:                                           " if((typeof el == 'string')||(typeof el == 'undefined'))\n"
        !           240:                                           "  return el;\n"
        !           241:                                           " if(el.innerText)\n"
        !           242:                                           "  return el.innerText;\n"
        !           243:                                           " else {\n"
        !           244:                                           "  var str = \"\";\n"
        !           245:                                           "  var cs = el.childNodes;\n"
        !           246:                                           "  var l = cs.length;\n"
        !           247:                                           "  for (i=0;i<l;i++) {\n"
        !           248:                                           "   if (cs[i].nodeType==1) str += get_inner_text(cs[i]);\n"
        !           249:                                           "   else if (cs[i].nodeType==3) str += cs[i].nodeValue;\n"
        !           250:                                           "  }\n"
        !           251:                                           " }\n"
        !           252:                                           " return str;\n"
        !           253:                                           "}\n"
        !           254: 
        !           255:                                           "function sortfn(a,b) {\n"
        !           256:                                           " var at = get_inner_text(a.cells[sort_column]);\n"
        !           257:                                           " var bt = get_inner_text(b.cells[sort_column]);\n"
        !           258:                                           " if (a.cells[sort_column].className == 'int') {\n"
        !           259:                                           "  return parseInt(at)-parseInt(bt);\n"
        !           260:                                           " } else {\n"
        !           261:                                           "  aa = at.toLowerCase();\n"
        !           262:                                           "  bb = bt.toLowerCase();\n"
        !           263:                                           "  if (aa==bb) return 0;\n"
        !           264:                                           "  else if (aa<bb) return -1;\n"
        !           265:                                           "  else return 1;\n"
        !           266:                                           " }\n"
        !           267:                                           "}\n"
        !           268: 
        !           269:                                           "function resort(lnk) {\n"
        !           270:                                           " var span = lnk.childNodes[1];\n"
        !           271:                                           " var table = lnk.parentNode.parentNode.parentNode.parentNode;\n"
        !           272:                                           " var rows = new Array();\n"
        !           273:                                           " for (j=1;j<table.rows.length;j++)\n"
        !           274:                                           "  rows[j-1] = table.rows[j];\n"
        !           275:                                           " sort_column = lnk.parentNode.cellIndex;\n"
        !           276:                                           " rows.sort(sortfn);\n"
        !           277: 
        !           278:                                           " if (prev_span != null) prev_span.innerHTML = '';\n"
        !           279:                                           " if (span.getAttribute('sortdir')=='down') {\n"
        !           280:                                           "  span.innerHTML = '&uarr;';\n"
        !           281:                                           "  span.setAttribute('sortdir','up');\n"
        !           282:                                           "  rows.reverse();\n"
        !           283:                                           " } else {\n"
        !           284:                                           "  span.innerHTML = '&darr;';\n"
        !           285:                                           "  span.setAttribute('sortdir','down');\n"
        !           286:                                           " }\n"
        !           287:                                           " for (i=0;i<rows.length;i++)\n"
        !           288:                                           "  table.tBodies[0].appendChild(rows[i]);\n"
        !           289:                                           " prev_span = span;\n"
        !           290:                                           "}\n"
        !           291:                                           "// -->\n"
        !           292:                                           "</script>\n"));
        !           293:        }
        !           294: 
        !           295:        buffer_append_string_len(b, CONST_STR_LEN(
        !           296:                                 " </head>\n"
        !           297:                                 " <body>\n"));
        !           298: 
        !           299: 
        !           300: 
        !           301:        /* connection listing */
        !           302:        buffer_append_string_len(b, CONST_STR_LEN("<h1>Server-Status (" PACKAGE_NAME " " PACKAGE_VERSION ")</h1>"));
        !           303: 
        !           304:        buffer_append_string_len(b, CONST_STR_LEN("<table summary=\"status\" class=\"status\">"));
        !           305:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Hostname</td><td class=\"string\">"));
        !           306:        buffer_append_string_buffer(b, con->uri.authority);
        !           307:        buffer_append_string_len(b, CONST_STR_LEN(" ("));
        !           308:        buffer_append_string_buffer(b, con->server_name);
        !           309:        buffer_append_string_len(b, CONST_STR_LEN(")</td></tr>\n"));
        !           310:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Uptime</td><td class=\"string\">"));
        !           311: 
        !           312:        ts = srv->cur_ts - srv->startup_ts;
        !           313: 
        !           314:        days = ts / (60 * 60 * 24);
        !           315:        ts %= (60 * 60 * 24);
        !           316: 
        !           317:        hours = ts / (60 * 60);
        !           318:        ts %= (60 * 60);
        !           319: 
        !           320:        mins = ts / (60);
        !           321:        ts %= (60);
        !           322: 
        !           323:        seconds = ts;
        !           324: 
        !           325:        if (days) {
        !           326:                buffer_append_long(b, days);
        !           327:                buffer_append_string_len(b, CONST_STR_LEN(" days "));
        !           328:        }
        !           329: 
        !           330:        if (hours) {
        !           331:                buffer_append_long(b, hours);
        !           332:                buffer_append_string_len(b, CONST_STR_LEN(" hours "));
        !           333:        }
        !           334: 
        !           335:        if (mins) {
        !           336:                buffer_append_long(b, mins);
        !           337:                buffer_append_string_len(b, CONST_STR_LEN(" min "));
        !           338:        }
        !           339: 
        !           340:        buffer_append_long(b, seconds);
        !           341:        buffer_append_string_len(b, CONST_STR_LEN(" s"));
        !           342: 
        !           343:        buffer_append_string_len(b, CONST_STR_LEN("</td></tr>\n"));
        !           344:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Started at</td><td class=\"string\">"));
        !           345: 
        !           346:        ts = srv->startup_ts;
        !           347: 
        !           348:        strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts));
        !           349:        buffer_append_string(b, buf);
        !           350:        buffer_append_string_len(b, CONST_STR_LEN("</td></tr>\n"));
        !           351: 
        !           352: 
        !           353:        buffer_append_string_len(b, CONST_STR_LEN("<tr><th colspan=\"2\">absolute (since start)</th></tr>\n"));
        !           354: 
        !           355:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Requests</td><td class=\"string\">"));
        !           356:        avg = p->abs_requests;
        !           357: 
        !           358:        mod_status_get_multiplier(&avg, &multiplier, 1000);
        !           359: 
        !           360:        buffer_append_long(b, avg);
        !           361:        buffer_append_string_len(b, CONST_STR_LEN(" "));
        !           362:        if (multiplier) buffer_append_string_len(b, &multiplier, 1);
        !           363:        buffer_append_string_len(b, CONST_STR_LEN("req</td></tr>\n"));
        !           364: 
        !           365:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Traffic</td><td class=\"string\">"));
        !           366:        avg = p->abs_traffic_out;
        !           367: 
        !           368:        mod_status_get_multiplier(&avg, &multiplier, 1024);
        !           369: 
        !           370:        sprintf(buf, "%.2f", avg);
        !           371:        buffer_append_string(b, buf);
        !           372:        buffer_append_string_len(b, CONST_STR_LEN(" "));
        !           373:        if (multiplier) buffer_append_string_len(b, &multiplier, 1);
        !           374:        buffer_append_string_len(b, CONST_STR_LEN("byte</td></tr>\n"));
        !           375: 
        !           376: 
        !           377: 
        !           378:        buffer_append_string_len(b, CONST_STR_LEN("<tr><th colspan=\"2\">average (since start)</th></tr>\n"));
        !           379: 
        !           380:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Requests</td><td class=\"string\">"));
        !           381:        avg = p->abs_requests / (srv->cur_ts - srv->startup_ts);
        !           382: 
        !           383:        mod_status_get_multiplier(&avg, &multiplier, 1000);
        !           384: 
        !           385:        buffer_append_long(b, avg);
        !           386:        buffer_append_string_len(b, CONST_STR_LEN(" "));
        !           387:        if (multiplier) buffer_append_string_len(b, &multiplier, 1);
        !           388:        buffer_append_string_len(b, CONST_STR_LEN("req/s</td></tr>\n"));
        !           389: 
        !           390:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Traffic</td><td class=\"string\">"));
        !           391:        avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
        !           392: 
        !           393:        mod_status_get_multiplier(&avg, &multiplier, 1024);
        !           394: 
        !           395:        sprintf(buf, "%.2f", avg);
        !           396:        buffer_append_string(b, buf);
        !           397:        buffer_append_string_len(b, CONST_STR_LEN(" "));
        !           398:        if (multiplier) buffer_append_string_len(b, &multiplier, 1);
        !           399:        buffer_append_string_len(b, CONST_STR_LEN("byte/s</td></tr>\n"));
        !           400: 
        !           401: 
        !           402: 
        !           403:        buffer_append_string_len(b, CONST_STR_LEN("<tr><th colspan=\"2\">average (5s sliding average)</th></tr>\n"));
        !           404:        for (j = 0, avg = 0; j < 5; j++) {
        !           405:                avg += p->mod_5s_requests[j];
        !           406:        }
        !           407: 
        !           408:        avg /= 5;
        !           409: 
        !           410:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Requests</td><td class=\"string\">"));
        !           411: 
        !           412:        mod_status_get_multiplier(&avg, &multiplier, 1000);
        !           413: 
        !           414:        buffer_append_long(b, avg);
        !           415:        buffer_append_string_len(b, CONST_STR_LEN(" "));
        !           416:        if (multiplier) buffer_append_string_len(b, &multiplier, 1);
        !           417: 
        !           418:        buffer_append_string_len(b, CONST_STR_LEN("req/s</td></tr>\n"));
        !           419: 
        !           420:        for (j = 0, avg = 0; j < 5; j++) {
        !           421:                avg += p->mod_5s_traffic_out[j];
        !           422:        }
        !           423: 
        !           424:        avg /= 5;
        !           425: 
        !           426:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Traffic</td><td class=\"string\">"));
        !           427: 
        !           428:        mod_status_get_multiplier(&avg, &multiplier, 1024);
        !           429: 
        !           430:        sprintf(buf, "%.2f", avg);
        !           431:        buffer_append_string(b, buf);
        !           432:        buffer_append_string_len(b, CONST_STR_LEN(" "));
        !           433:        if (multiplier) buffer_append_string_len(b, &multiplier, 1);
        !           434:        buffer_append_string_len(b, CONST_STR_LEN("byte/s</td></tr>\n"));
        !           435: 
        !           436:        buffer_append_string_len(b, CONST_STR_LEN("</table>\n"));
        !           437: 
        !           438: 
        !           439:        buffer_append_string_len(b, CONST_STR_LEN(
        !           440:                "<hr />\n<pre><b>legend</b>\n"
        !           441:                ". = connect, C = close, E = hard error, k = keep-alive\n"
        !           442:                "r = read, R = read-POST, W = write, h = handle-request\n"
        !           443:                "q = request-start,  Q = request-end\n"
        !           444:                "s = response-start, S = response-end\n"));
        !           445: 
        !           446:        buffer_append_string_len(b, CONST_STR_LEN("<b>"));
        !           447:        buffer_append_long(b, srv->conns->used);
        !           448:        buffer_append_string_len(b, CONST_STR_LEN(" connections</b>\n"));
        !           449: 
        !           450:        for (j = 0; j < srv->conns->used; j++) {
        !           451:                connection *c = srv->conns->ptr[j];
        !           452:                const char *state;
        !           453: 
        !           454:                if (CON_STATE_READ == c->state && c->request.orig_uri->used > 0) {
        !           455:                        state = "k";
        !           456:                } else {
        !           457:                        state = connection_get_short_state(c->state);
        !           458:                }
        !           459: 
        !           460:                buffer_append_string_len(b, state, 1);
        !           461: 
        !           462:                if (((j + 1) % 50) == 0) {
        !           463:                        buffer_append_string_len(b, CONST_STR_LEN("\n"));
        !           464:                }
        !           465:        }
        !           466: 
        !           467:        buffer_append_string_len(b, CONST_STR_LEN("\n</pre><hr />\n<h2>Connections</h2>\n"));
        !           468: 
        !           469:        buffer_append_string_len(b, CONST_STR_LEN("<table summary=\"status\" class=\"status\">\n"));
        !           470:        buffer_append_string_len(b, CONST_STR_LEN("<tr>"));
        !           471:        mod_status_header_append_sort(b, p_d, "Client IP");
        !           472:        mod_status_header_append_sort(b, p_d, "Read");
        !           473:        mod_status_header_append_sort(b, p_d, "Written");
        !           474:        mod_status_header_append_sort(b, p_d, "State");
        !           475:        mod_status_header_append_sort(b, p_d, "Time");
        !           476:        mod_status_header_append_sort(b, p_d, "Host");
        !           477:        mod_status_header_append_sort(b, p_d, "URI");
        !           478:        mod_status_header_append_sort(b, p_d, "File");
        !           479:        buffer_append_string_len(b, CONST_STR_LEN("</tr>\n"));
        !           480: 
        !           481:        for (j = 0; j < srv->conns->used; j++) {
        !           482:                connection *c = srv->conns->ptr[j];
        !           483: 
        !           484:                buffer_append_string_len(b, CONST_STR_LEN("<tr><td class=\"string\">"));
        !           485: 
        !           486:                buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
        !           487: 
        !           488:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"int\">"));
        !           489: 
        !           490:                if (c->request.content_length) {
        !           491:                        buffer_append_long(b, c->request_content_queue->bytes_in);
        !           492:                        buffer_append_string_len(b, CONST_STR_LEN("/"));
        !           493:                        buffer_append_long(b, c->request.content_length);
        !           494:                } else {
        !           495:                        buffer_append_string_len(b, CONST_STR_LEN("0/0"));
        !           496:                }
        !           497: 
        !           498:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"int\">"));
        !           499: 
        !           500:                buffer_append_off_t(b, chunkqueue_written(c->write_queue));
        !           501:                buffer_append_string_len(b, CONST_STR_LEN("/"));
        !           502:                buffer_append_off_t(b, chunkqueue_length(c->write_queue));
        !           503: 
        !           504:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"string\">"));
        !           505: 
        !           506:                if (CON_STATE_READ == c->state && c->request.orig_uri->used > 0) {
        !           507:                        buffer_append_string_len(b, CONST_STR_LEN("keep-alive"));
        !           508:                } else {
        !           509:                        buffer_append_string(b, connection_get_state(c->state));
        !           510:                }
        !           511: 
        !           512:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"int\">"));
        !           513: 
        !           514:                buffer_append_long(b, srv->cur_ts - c->request_start);
        !           515: 
        !           516:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"string\">"));
        !           517: 
        !           518:                if (buffer_is_empty(c->server_name)) {
        !           519:                        buffer_append_string_buffer(b, c->uri.authority);
        !           520:                }
        !           521:                else {
        !           522:                        buffer_append_string_buffer(b, c->server_name);
        !           523:                }
        !           524: 
        !           525:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"string\">"));
        !           526: 
        !           527:                if (!buffer_is_empty(c->uri.path)) {
        !           528:                        buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
        !           529:                }
        !           530: 
        !           531:                if (!buffer_is_empty(c->uri.query)) {
        !           532:                        buffer_append_string_len(b, CONST_STR_LEN("?"));
        !           533:                        buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.query), ENCODING_HTML);
        !           534:                }
        !           535: 
        !           536:                if (!buffer_is_empty(c->request.orig_uri)) {
        !           537:                        buffer_append_string_len(b, CONST_STR_LEN(" ("));
        !           538:                        buffer_append_string_encoded(b, CONST_BUF_LEN(c->request.orig_uri), ENCODING_HTML);
        !           539:                        buffer_append_string_len(b, CONST_STR_LEN(")"));
        !           540:                }
        !           541:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"string\">"));
        !           542: 
        !           543:                buffer_append_string_buffer(b, c->physical.path);
        !           544: 
        !           545:                buffer_append_string_len(b, CONST_STR_LEN("</td></tr>\n"));
        !           546:        }
        !           547: 
        !           548: 
        !           549:        buffer_append_string_len(b, CONST_STR_LEN(
        !           550:                      "</table>\n"));
        !           551: 
        !           552: 
        !           553:        buffer_append_string_len(b, CONST_STR_LEN(
        !           554:                      " </body>\n"
        !           555:                      "</html>\n"
        !           556:                      ));
        !           557: 
        !           558:        response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
        !           559: 
        !           560:        return 0;
        !           561: }
        !           562: 
        !           563: 
        !           564: static handler_t mod_status_handle_server_status_text(server *srv, connection *con, void *p_d) {
        !           565:        plugin_data *p = p_d;
        !           566:        buffer *b;
        !           567:        double avg;
        !           568:        time_t ts;
        !           569:        char buf[32];
        !           570:        unsigned int k;
        !           571:        unsigned int l;
        !           572: 
        !           573:        b = chunkqueue_get_append_buffer(con->write_queue);
        !           574: 
        !           575:        /* output total number of requests */
        !           576:        buffer_append_string_len(b, CONST_STR_LEN("Total Accesses: "));
        !           577:        avg = p->abs_requests;
        !           578:        snprintf(buf, sizeof(buf) - 1, "%.0f", avg);
        !           579:        buffer_append_string(b, buf);
        !           580:        buffer_append_string_len(b, CONST_STR_LEN("\n"));
        !           581: 
        !           582:        /* output total traffic out in kbytes */
        !           583:        buffer_append_string_len(b, CONST_STR_LEN("Total kBytes: "));
        !           584:        avg = p->abs_traffic_out / 1024;
        !           585:        snprintf(buf, sizeof(buf) - 1, "%.0f", avg);
        !           586:        buffer_append_string(b, buf);
        !           587:        buffer_append_string_len(b, CONST_STR_LEN("\n"));
        !           588: 
        !           589:        /* output uptime */
        !           590:        buffer_append_string_len(b, CONST_STR_LEN("Uptime: "));
        !           591:        ts = srv->cur_ts - srv->startup_ts;
        !           592:        buffer_append_long(b, ts);
        !           593:        buffer_append_string_len(b, CONST_STR_LEN("\n"));
        !           594: 
        !           595:        /* output busy servers */
        !           596:        buffer_append_string_len(b, CONST_STR_LEN("BusyServers: "));
        !           597:        buffer_append_long(b, srv->conns->used);
        !           598:        buffer_append_string_len(b, CONST_STR_LEN("\n"));
        !           599: 
        !           600:        buffer_append_string_len(b, CONST_STR_LEN("IdleServers: "));
        !           601:        buffer_append_long(b, srv->conns->size - srv->conns->used);
        !           602:        buffer_append_string_len(b, CONST_STR_LEN("\n"));
        !           603: 
        !           604:        /* output scoreboard */
        !           605:        buffer_append_string_len(b, CONST_STR_LEN("Scoreboard: "));
        !           606:        for (k = 0; k < srv->conns->used; k++) {
        !           607:                connection *c = srv->conns->ptr[k];
        !           608:                const char *state = connection_get_short_state(c->state);
        !           609:                buffer_append_string_len(b, state, 1);
        !           610:        }
        !           611:        for (l = 0; l < srv->conns->size - srv->conns->used; l++) {
        !           612:                buffer_append_string_len(b, CONST_STR_LEN("_"));
        !           613:        }
        !           614:        buffer_append_string_len(b, CONST_STR_LEN("\n"));
        !           615: 
        !           616:        /* set text/plain output */
        !           617: 
        !           618:        response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
        !           619: 
        !           620:        return 0;
        !           621: }
        !           622: 
        !           623: static handler_t mod_status_handle_server_statistics(server *srv, connection *con, void *p_d) {
        !           624:        buffer *b;
        !           625:        size_t i;
        !           626:        array *st = srv->status;
        !           627:        UNUSED(p_d);
        !           628: 
        !           629:        if (0 == st->used) {
        !           630:                /* we have nothing to send */
        !           631:                con->http_status = 204;
        !           632:                con->file_finished = 1;
        !           633: 
        !           634:                return HANDLER_FINISHED;
        !           635:        }
        !           636: 
        !           637:        b = chunkqueue_get_append_buffer(con->write_queue);
        !           638: 
        !           639:        for (i = 0; i < st->used; i++) {
        !           640:                size_t ndx = st->sorted[i];
        !           641: 
        !           642:                buffer_append_string_buffer(b, st->data[ndx]->key);
        !           643:                buffer_append_string_len(b, CONST_STR_LEN(": "));
        !           644:                buffer_append_long(b, ((data_integer *)(st->data[ndx]))->value);
        !           645:                buffer_append_string_len(b, CONST_STR_LEN("\n"));
        !           646:        }
        !           647: 
        !           648:        response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
        !           649: 
        !           650:        con->http_status = 200;
        !           651:        con->file_finished = 1;
        !           652: 
        !           653:        return HANDLER_FINISHED;
        !           654: }
        !           655: 
        !           656: 
        !           657: static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) {
        !           658: 
        !           659:        if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) {
        !           660:                mod_status_handle_server_status_text(srv, con, p_d);
        !           661:        } else {
        !           662:                mod_status_handle_server_status_html(srv, con, p_d);
        !           663:        }
        !           664: 
        !           665:        con->http_status = 200;
        !           666:        con->file_finished = 1;
        !           667: 
        !           668:        return HANDLER_FINISHED;
        !           669: }
        !           670: 
        !           671: 
        !           672: static handler_t mod_status_handle_server_config(server *srv, connection *con, void *p_d) {
        !           673:        plugin_data *p = p_d;
        !           674:        buffer *b, *m = p->module_list;
        !           675:        size_t i;
        !           676: 
        !           677:        struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
        !           678:        {
        !           679:                /* - epoll is most reliable
        !           680:                 * - select works everywhere
        !           681:                 */
        !           682: #ifdef USE_LINUX_EPOLL
        !           683:                { FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" },
        !           684: #endif
        !           685: #ifdef USE_POLL
        !           686:                { FDEVENT_HANDLER_POLL,           "poll" },
        !           687: #endif
        !           688: #ifdef USE_SELECT
        !           689:                { FDEVENT_HANDLER_SELECT,         "select" },
        !           690: #endif
        !           691: #ifdef USE_LIBEV
        !           692:                { FDEVENT_HANDLER_LIBEV,          "libev" },
        !           693: #endif
        !           694: #ifdef USE_SOLARIS_DEVPOLL
        !           695:                { FDEVENT_HANDLER_SOLARIS_DEVPOLL,"solaris-devpoll" },
        !           696: #endif
        !           697: #ifdef USE_SOLARIS_PORT
        !           698:                { FDEVENT_HANDLER_SOLARIS_PORT,   "solaris-eventports" },
        !           699: #endif
        !           700: #ifdef USE_FREEBSD_KQUEUE
        !           701:                { FDEVENT_HANDLER_FREEBSD_KQUEUE, "freebsd-kqueue" },
        !           702: #endif
        !           703:                { FDEVENT_HANDLER_UNSET,          NULL }
        !           704:        };
        !           705: 
        !           706:        b = chunkqueue_get_append_buffer(con->write_queue);
        !           707: 
        !           708:        buffer_copy_string_len(b, CONST_STR_LEN(
        !           709:                           "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
        !           710:                           "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
        !           711:                           "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
        !           712:                           "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
        !           713:                           " <head>\n"
        !           714:                           "  <title>Status</title>\n"
        !           715:                           " </head>\n"
        !           716:                           " <body>\n"
        !           717:                           "  <h1>" PACKAGE_DESC "</h1>\n"
        !           718:                           "  <table summary=\"status\" border=\"1\">\n"));
        !           719: 
        !           720:        mod_status_header_append(b, "Server-Features");
        !           721: #ifdef HAVE_PCRE_H
        !           722:        mod_status_row_append(b, "RegEx Conditionals", "enabled");
        !           723: #else
        !           724:        mod_status_row_append(b, "RegEx Conditionals", "disabled - pcre missing");
        !           725: #endif
        !           726:        mod_status_header_append(b, "Network Engine");
        !           727: 
        !           728:        for (i = 0; event_handlers[i].name; i++) {
        !           729:                if (event_handlers[i].et == srv->event_handler) {
        !           730:                        mod_status_row_append(b, "fd-Event-Handler", event_handlers[i].name);
        !           731:                        break;
        !           732:                }
        !           733:        }
        !           734: 
        !           735:        mod_status_header_append(b, "Config-File-Settings");
        !           736: 
        !           737:        for (i = 0; i < srv->plugins.used; i++) {
        !           738:                plugin **ps = srv->plugins.ptr;
        !           739: 
        !           740:                plugin *pl = ps[i];
        !           741: 
        !           742:                if (i == 0) {
        !           743:                        buffer_copy_string_buffer(m, pl->name);
        !           744:                } else {
        !           745:                        buffer_append_string_len(m, CONST_STR_LEN("<br />"));
        !           746:                        buffer_append_string_buffer(m, pl->name);
        !           747:                }
        !           748:        }
        !           749: 
        !           750:        mod_status_row_append(b, "Loaded Modules", m->ptr);
        !           751: 
        !           752:        buffer_append_string_len(b, CONST_STR_LEN("  </table>\n"));
        !           753: 
        !           754:        buffer_append_string_len(b, CONST_STR_LEN(
        !           755:                      " </body>\n"
        !           756:                      "</html>\n"
        !           757:                      ));
        !           758: 
        !           759:        response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
        !           760: 
        !           761:        con->http_status = 200;
        !           762:        con->file_finished = 1;
        !           763: 
        !           764:        return HANDLER_FINISHED;
        !           765: }
        !           766: 
        !           767: #define PATCH(x) \
        !           768:        p->conf.x = s->x;
        !           769: static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
        !           770:        size_t i, j;
        !           771:        plugin_config *s = p->config_storage[0];
        !           772: 
        !           773:        PATCH(status_url);
        !           774:        PATCH(config_url);
        !           775:        PATCH(sort);
        !           776:        PATCH(statistics_url);
        !           777: 
        !           778:        /* skip the first, the global context */
        !           779:        for (i = 1; i < srv->config_context->used; i++) {
        !           780:                data_config *dc = (data_config *)srv->config_context->data[i];
        !           781:                s = p->config_storage[i];
        !           782: 
        !           783:                /* condition didn't match */
        !           784:                if (!config_check_cond(srv, con, dc)) continue;
        !           785: 
        !           786:                /* merge config */
        !           787:                for (j = 0; j < dc->value->used; j++) {
        !           788:                        data_unset *du = dc->value->data[j];
        !           789: 
        !           790:                        if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.status-url"))) {
        !           791:                                PATCH(status_url);
        !           792:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) {
        !           793:                                PATCH(config_url);
        !           794:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.enable-sort"))) {
        !           795:                                PATCH(sort);
        !           796:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
        !           797:                                PATCH(statistics_url);
        !           798:                        }
        !           799:                }
        !           800:        }
        !           801: 
        !           802:        return 0;
        !           803: }
        !           804: 
        !           805: static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
        !           806:        plugin_data *p = p_d;
        !           807: 
        !           808:        if (con->mode != DIRECT) return HANDLER_GO_ON;
        !           809: 
        !           810:        mod_status_patch_connection(srv, con, p);
        !           811: 
        !           812:        if (!buffer_is_empty(p->conf.status_url) &&
        !           813:            buffer_is_equal(p->conf.status_url, con->uri.path)) {
        !           814:                return mod_status_handle_server_status(srv, con, p_d);
        !           815:        } else if (!buffer_is_empty(p->conf.config_url) &&
        !           816:            buffer_is_equal(p->conf.config_url, con->uri.path)) {
        !           817:                return mod_status_handle_server_config(srv, con, p_d);
        !           818:        } else if (!buffer_is_empty(p->conf.statistics_url) &&
        !           819:            buffer_is_equal(p->conf.statistics_url, con->uri.path)) {
        !           820:                return mod_status_handle_server_statistics(srv, con, p_d);
        !           821:        }
        !           822: 
        !           823:        return HANDLER_GO_ON;
        !           824: }
        !           825: 
        !           826: TRIGGER_FUNC(mod_status_trigger) {
        !           827:        plugin_data *p = p_d;
        !           828:        size_t i;
        !           829: 
        !           830:        /* check all connections */
        !           831:        for (i = 0; i < srv->conns->used; i++) {
        !           832:                connection *c = srv->conns->ptr[i];
        !           833: 
        !           834:                p->bytes_written += c->bytes_written_cur_second;
        !           835:        }
        !           836: 
        !           837:        /* a sliding average */
        !           838:        p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written;
        !           839:        p->mod_5s_requests   [p->mod_5s_ndx] = p->requests;
        !           840: 
        !           841:        p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5;
        !           842: 
        !           843:        p->abs_traffic_out += p->bytes_written;
        !           844:        p->rel_traffic_out += p->bytes_written;
        !           845: 
        !           846:        p->bytes_written = 0;
        !           847: 
        !           848:        /* reset storage - second */
        !           849:        p->traffic_out = 0;
        !           850:        p->requests    = 0;
        !           851: 
        !           852:        return HANDLER_GO_ON;
        !           853: }
        !           854: 
        !           855: REQUESTDONE_FUNC(mod_status_account) {
        !           856:        plugin_data *p = p_d;
        !           857: 
        !           858:        UNUSED(srv);
        !           859: 
        !           860:        p->requests++;
        !           861:        p->rel_requests++;
        !           862:        p->abs_requests++;
        !           863: 
        !           864:        p->bytes_written += con->bytes_written_cur_second;
        !           865: 
        !           866:        return HANDLER_GO_ON;
        !           867: }
        !           868: 
        !           869: int mod_status_plugin_init(plugin *p);
        !           870: int mod_status_plugin_init(plugin *p) {
        !           871:        p->version     = LIGHTTPD_VERSION_ID;
        !           872:        p->name        = buffer_init_string("status");
        !           873: 
        !           874:        p->init        = mod_status_init;
        !           875:        p->cleanup     = mod_status_free;
        !           876:        p->set_defaults= mod_status_set_defaults;
        !           877: 
        !           878:        p->handle_uri_clean    = mod_status_handler;
        !           879:        p->handle_trigger      = mod_status_trigger;
        !           880:        p->handle_request_done = mod_status_account;
        !           881: 
        !           882:        p->data        = NULL;
        !           883: 
        !           884:        return 0;
        !           885: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>