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

1.1.1.3 ! misho       1: #include "first.h"
        !             2: 
1.1       misho       3: #include "server.h"
                      4: #include "connections.h"
                      5: #include "response.h"
                      6: #include "connections.h"
                      7: #include "log.h"
                      8: 
                      9: #include "plugin.h"
                     10: 
                     11: #include "inet_ntop_cache.h"
                     12: 
                     13: #include <sys/types.h>
                     14: 
                     15: #include <fcntl.h>
                     16: #include <stdlib.h>
                     17: #include <string.h>
                     18: #include <unistd.h>
                     19: #include <errno.h>
                     20: #include <time.h>
                     21: #include <stdio.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: 
1.1.1.2   misho     118:        p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
1.1       misho     119: 
                    120:        for (i = 0; i < srv->config_context->used; i++) {
1.1.1.3 ! misho     121:                data_config const* config = (data_config const*)srv->config_context->data[i];
1.1       misho     122:                plugin_config *s;
                    123: 
                    124:                s = calloc(1, sizeof(plugin_config));
                    125:                s->config_url    = buffer_init();
                    126:                s->status_url    = buffer_init();
                    127:                s->sort          = 1;
                    128:                s->statistics_url    = buffer_init();
                    129: 
                    130:                cv[0].destination = s->status_url;
                    131:                cv[1].destination = s->config_url;
                    132:                cv[2].destination = &(s->sort);
                    133:                cv[3].destination = s->statistics_url;
                    134: 
                    135:                p->config_storage[i] = s;
                    136: 
1.1.1.3 ! misho     137:                if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
1.1       misho     138:                        return HANDLER_ERROR;
                    139:                }
                    140:        }
                    141: 
                    142:        return HANDLER_GO_ON;
                    143: }
                    144: 
                    145: 
                    146: 
                    147: static int mod_status_row_append(buffer *b, const char *key, const char *value) {
                    148:        buffer_append_string_len(b, CONST_STR_LEN("   <tr>\n"));
                    149:        buffer_append_string_len(b, CONST_STR_LEN("    <td><b>"));
                    150:        buffer_append_string(b, key);
                    151:        buffer_append_string_len(b, CONST_STR_LEN("</b></td>\n"));
                    152:        buffer_append_string_len(b, CONST_STR_LEN("    <td>"));
                    153:        buffer_append_string(b, value);
                    154:        buffer_append_string_len(b, CONST_STR_LEN("</td>\n"));
                    155:        buffer_append_string_len(b, CONST_STR_LEN("   </tr>\n"));
                    156: 
                    157:        return 0;
                    158: }
                    159: 
                    160: static int mod_status_header_append(buffer *b, const char *key) {
                    161:        buffer_append_string_len(b, CONST_STR_LEN("   <tr>\n"));
                    162:        buffer_append_string_len(b, CONST_STR_LEN("    <th colspan=\"2\">"));
                    163:        buffer_append_string(b, key);
                    164:        buffer_append_string_len(b, CONST_STR_LEN("</th>\n"));
                    165:        buffer_append_string_len(b, CONST_STR_LEN("   </tr>\n"));
                    166: 
                    167:        return 0;
                    168: }
                    169: 
                    170: static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) {
                    171:        plugin_data *p = p_d;
                    172: 
                    173:        if (p->conf.sort) {
                    174:                buffer_append_string_len(b, CONST_STR_LEN("<th class=\"status\"><a href=\"#\" class=\"sortheader\" onclick=\"resort(this);return false;\">"));
                    175:                buffer_append_string(b, key);
                    176:                buffer_append_string_len(b, CONST_STR_LEN("<span class=\"sortarrow\">:</span></a></th>\n"));
                    177:        } else {
                    178:                buffer_append_string_len(b, CONST_STR_LEN("<th class=\"status\">"));
                    179:                buffer_append_string(b, key);
                    180:                buffer_append_string_len(b, CONST_STR_LEN("</th>\n"));
                    181:        }
                    182: 
                    183:        return 0;
                    184: }
                    185: 
                    186: static int mod_status_get_multiplier(double *avg, char *multiplier, int size) {
                    187:        *multiplier = ' ';
                    188: 
                    189:        if (*avg > size) { *avg /= size; *multiplier = 'k'; }
                    190:        if (*avg > size) { *avg /= size; *multiplier = 'M'; }
                    191:        if (*avg > size) { *avg /= size; *multiplier = 'G'; }
                    192:        if (*avg > size) { *avg /= size; *multiplier = 'T'; }
                    193:        if (*avg > size) { *avg /= size; *multiplier = 'P'; }
                    194:        if (*avg > size) { *avg /= size; *multiplier = 'E'; }
                    195:        if (*avg > size) { *avg /= size; *multiplier = 'Z'; }
                    196:        if (*avg > size) { *avg /= size; *multiplier = 'Y'; }
                    197: 
                    198:        return 0;
                    199: }
                    200: 
                    201: static handler_t mod_status_handle_server_status_html(server *srv, connection *con, void *p_d) {
                    202:        plugin_data *p = p_d;
1.1.1.3 ! misho     203:        buffer *b = buffer_init();
1.1       misho     204:        size_t j;
                    205:        double avg;
                    206:        char multiplier = '\0';
                    207:        char buf[32];
                    208:        time_t ts;
                    209: 
                    210:        int days, hours, mins, seconds;
                    211: 
1.1.1.3 ! misho     212:        /*(CON_STATE_CLOSE must be last state in enum connection_state_t)*/
        !           213:        int cstates[CON_STATE_CLOSE+3];
        !           214:        memset(cstates, 0, sizeof(cstates));
1.1       misho     215: 
                    216:        buffer_copy_string_len(b, CONST_STR_LEN(
                    217:                                 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
                    218:                                 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
                    219:                                 "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
                    220:                                 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
                    221:                                 " <head>\n"
                    222:                                 "  <title>Status</title>\n"
                    223: 
                    224:                                   "  <style type=\"text/css\">\n"
                    225:                                   "    table.status { border: black solid thin; }\n"
                    226:                                   "    td { white-space: nowrap; }\n"
                    227:                                   "    td.int { background-color: #f0f0f0; text-align: right }\n"
                    228:                                   "    td.string { background-color: #f0f0f0; text-align: left }\n"
                    229:                                   "    th.status { background-color: black; color: white; font-weight: bold; }\n"
                    230:                                   "    a.sortheader { background-color: black; color: white; font-weight: bold; text-decoration: none; display: block; }\n"
                    231:                                   "    span.sortarrow { color: white; text-decoration: none; }\n"
                    232:                                   "  </style>\n"));
                    233: 
1.1.1.3 ! misho     234:        if (!buffer_string_is_empty(con->uri.query) && 0 == memcmp(con->uri.query->ptr, CONST_STR_LEN("refresh="))) {
        !           235:                /* Note: Refresh is an historical, but non-standard HTTP header
        !           236:                 * References (meta http-equiv="refresh" use is deprecated):
        !           237:                 *   https://www.w3.org/TR/WCAG10-HTML-TECHS/#meta-element
        !           238:                 *   https://www.w3.org/TR/WCAG10-CORE-TECHS/#auto-page-refresh
        !           239:                 *   https://www.w3.org/QA/Tips/reback
        !           240:                 */
        !           241:                const long refresh = strtol(con->uri.query->ptr+sizeof("refresh=")-1, NULL, 10);
        !           242:                if (refresh > 0) {
        !           243:                        buffer_append_string_len(b, CONST_STR_LEN("<meta http-equiv=\"refresh\" content=\""));
        !           244:                        buffer_append_int(b, refresh < 604800 ? refresh : 604800);
        !           245:                        buffer_append_string_len(b, CONST_STR_LEN("\">\n"));
        !           246:                }
        !           247:        }
        !           248: 
1.1       misho     249:        if (p->conf.sort) {
                    250:                buffer_append_string_len(b, CONST_STR_LEN(
                    251:                                           "<script type=\"text/javascript\">\n"
                    252:                                           "// <!--\n"
                    253:                                           "var sort_column;\n"
                    254:                                           "var prev_span = null;\n"
                    255: 
                    256:                                           "function get_inner_text(el) {\n"
                    257:                                           " if((typeof el == 'string')||(typeof el == 'undefined'))\n"
                    258:                                           "  return el;\n"
                    259:                                           " if(el.innerText)\n"
                    260:                                           "  return el.innerText;\n"
                    261:                                           " else {\n"
                    262:                                           "  var str = \"\";\n"
                    263:                                           "  var cs = el.childNodes;\n"
                    264:                                           "  var l = cs.length;\n"
                    265:                                           "  for (i=0;i<l;i++) {\n"
                    266:                                           "   if (cs[i].nodeType==1) str += get_inner_text(cs[i]);\n"
                    267:                                           "   else if (cs[i].nodeType==3) str += cs[i].nodeValue;\n"
                    268:                                           "  }\n"
                    269:                                           " }\n"
                    270:                                           " return str;\n"
                    271:                                           "}\n"
                    272: 
                    273:                                           "function sortfn(a,b) {\n"
                    274:                                           " var at = get_inner_text(a.cells[sort_column]);\n"
                    275:                                           " var bt = get_inner_text(b.cells[sort_column]);\n"
                    276:                                           " if (a.cells[sort_column].className == 'int') {\n"
                    277:                                           "  return parseInt(at)-parseInt(bt);\n"
                    278:                                           " } else {\n"
                    279:                                           "  aa = at.toLowerCase();\n"
                    280:                                           "  bb = bt.toLowerCase();\n"
                    281:                                           "  if (aa==bb) return 0;\n"
                    282:                                           "  else if (aa<bb) return -1;\n"
                    283:                                           "  else return 1;\n"
                    284:                                           " }\n"
                    285:                                           "}\n"
                    286: 
                    287:                                           "function resort(lnk) {\n"
                    288:                                           " var span = lnk.childNodes[1];\n"
                    289:                                           " var table = lnk.parentNode.parentNode.parentNode.parentNode;\n"
                    290:                                           " var rows = new Array();\n"
                    291:                                           " for (j=1;j<table.rows.length;j++)\n"
                    292:                                           "  rows[j-1] = table.rows[j];\n"
                    293:                                           " sort_column = lnk.parentNode.cellIndex;\n"
                    294:                                           " rows.sort(sortfn);\n"
                    295: 
                    296:                                           " if (prev_span != null) prev_span.innerHTML = '';\n"
                    297:                                           " if (span.getAttribute('sortdir')=='down') {\n"
                    298:                                           "  span.innerHTML = '&uarr;';\n"
                    299:                                           "  span.setAttribute('sortdir','up');\n"
                    300:                                           "  rows.reverse();\n"
                    301:                                           " } else {\n"
                    302:                                           "  span.innerHTML = '&darr;';\n"
                    303:                                           "  span.setAttribute('sortdir','down');\n"
                    304:                                           " }\n"
                    305:                                           " for (i=0;i<rows.length;i++)\n"
                    306:                                           "  table.tBodies[0].appendChild(rows[i]);\n"
                    307:                                           " prev_span = span;\n"
                    308:                                           "}\n"
                    309:                                           "// -->\n"
                    310:                                           "</script>\n"));
                    311:        }
                    312: 
                    313:        buffer_append_string_len(b, CONST_STR_LEN(
                    314:                                 " </head>\n"
                    315:                                 " <body>\n"));
                    316: 
                    317: 
                    318: 
                    319:        /* connection listing */
1.1.1.3 ! misho     320:        buffer_append_string_len(b, CONST_STR_LEN("<h1>Server-Status ("));
        !           321:        buffer_append_string_buffer(b, con->conf.server_tag);
        !           322:        buffer_append_string_len(b, CONST_STR_LEN(")</h1>"));
1.1       misho     323: 
                    324:        buffer_append_string_len(b, CONST_STR_LEN("<table summary=\"status\" class=\"status\">"));
                    325:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Hostname</td><td class=\"string\">"));
                    326:        buffer_append_string_buffer(b, con->uri.authority);
                    327:        buffer_append_string_len(b, CONST_STR_LEN(" ("));
                    328:        buffer_append_string_buffer(b, con->server_name);
                    329:        buffer_append_string_len(b, CONST_STR_LEN(")</td></tr>\n"));
                    330:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Uptime</td><td class=\"string\">"));
                    331: 
                    332:        ts = srv->cur_ts - srv->startup_ts;
                    333: 
                    334:        days = ts / (60 * 60 * 24);
                    335:        ts %= (60 * 60 * 24);
                    336: 
                    337:        hours = ts / (60 * 60);
                    338:        ts %= (60 * 60);
                    339: 
                    340:        mins = ts / (60);
                    341:        ts %= (60);
                    342: 
                    343:        seconds = ts;
                    344: 
                    345:        if (days) {
1.1.1.3 ! misho     346:                buffer_append_int(b, days);
1.1       misho     347:                buffer_append_string_len(b, CONST_STR_LEN(" days "));
                    348:        }
                    349: 
                    350:        if (hours) {
1.1.1.3 ! misho     351:                buffer_append_int(b, hours);
1.1       misho     352:                buffer_append_string_len(b, CONST_STR_LEN(" hours "));
                    353:        }
                    354: 
                    355:        if (mins) {
1.1.1.3 ! misho     356:                buffer_append_int(b, mins);
1.1       misho     357:                buffer_append_string_len(b, CONST_STR_LEN(" min "));
                    358:        }
                    359: 
1.1.1.3 ! misho     360:        buffer_append_int(b, seconds);
1.1       misho     361:        buffer_append_string_len(b, CONST_STR_LEN(" s"));
                    362: 
                    363:        buffer_append_string_len(b, CONST_STR_LEN("</td></tr>\n"));
                    364:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Started at</td><td class=\"string\">"));
                    365: 
                    366:        ts = srv->startup_ts;
                    367: 
                    368:        strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts));
                    369:        buffer_append_string(b, buf);
                    370:        buffer_append_string_len(b, CONST_STR_LEN("</td></tr>\n"));
                    371: 
                    372: 
                    373:        buffer_append_string_len(b, CONST_STR_LEN("<tr><th colspan=\"2\">absolute (since start)</th></tr>\n"));
                    374: 
                    375:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Requests</td><td class=\"string\">"));
                    376:        avg = p->abs_requests;
                    377: 
                    378:        mod_status_get_multiplier(&avg, &multiplier, 1000);
                    379: 
1.1.1.3 ! misho     380:        buffer_append_int(b, avg);
1.1       misho     381:        buffer_append_string_len(b, CONST_STR_LEN(" "));
                    382:        if (multiplier) buffer_append_string_len(b, &multiplier, 1);
                    383:        buffer_append_string_len(b, CONST_STR_LEN("req</td></tr>\n"));
                    384: 
                    385:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Traffic</td><td class=\"string\">"));
                    386:        avg = p->abs_traffic_out;
                    387: 
                    388:        mod_status_get_multiplier(&avg, &multiplier, 1024);
                    389: 
1.1.1.3 ! misho     390:        snprintf(buf, sizeof(buf), "%.2f", avg);
1.1       misho     391:        buffer_append_string(b, buf);
                    392:        buffer_append_string_len(b, CONST_STR_LEN(" "));
                    393:        if (multiplier) buffer_append_string_len(b, &multiplier, 1);
                    394:        buffer_append_string_len(b, CONST_STR_LEN("byte</td></tr>\n"));
                    395: 
                    396: 
                    397: 
                    398:        buffer_append_string_len(b, CONST_STR_LEN("<tr><th colspan=\"2\">average (since start)</th></tr>\n"));
                    399: 
                    400:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Requests</td><td class=\"string\">"));
                    401:        avg = p->abs_requests / (srv->cur_ts - srv->startup_ts);
                    402: 
                    403:        mod_status_get_multiplier(&avg, &multiplier, 1000);
                    404: 
1.1.1.3 ! misho     405:        buffer_append_int(b, avg);
1.1       misho     406:        buffer_append_string_len(b, CONST_STR_LEN(" "));
                    407:        if (multiplier) buffer_append_string_len(b, &multiplier, 1);
                    408:        buffer_append_string_len(b, CONST_STR_LEN("req/s</td></tr>\n"));
                    409: 
                    410:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Traffic</td><td class=\"string\">"));
                    411:        avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
                    412: 
                    413:        mod_status_get_multiplier(&avg, &multiplier, 1024);
                    414: 
1.1.1.3 ! misho     415:        snprintf(buf, sizeof(buf), "%.2f", avg);
1.1       misho     416:        buffer_append_string(b, buf);
                    417:        buffer_append_string_len(b, CONST_STR_LEN(" "));
                    418:        if (multiplier) buffer_append_string_len(b, &multiplier, 1);
                    419:        buffer_append_string_len(b, CONST_STR_LEN("byte/s</td></tr>\n"));
                    420: 
                    421: 
                    422: 
                    423:        buffer_append_string_len(b, CONST_STR_LEN("<tr><th colspan=\"2\">average (5s sliding average)</th></tr>\n"));
                    424:        for (j = 0, avg = 0; j < 5; j++) {
                    425:                avg += p->mod_5s_requests[j];
                    426:        }
                    427: 
                    428:        avg /= 5;
                    429: 
                    430:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Requests</td><td class=\"string\">"));
                    431: 
                    432:        mod_status_get_multiplier(&avg, &multiplier, 1000);
                    433: 
1.1.1.3 ! misho     434:        buffer_append_int(b, avg);
1.1       misho     435:        buffer_append_string_len(b, CONST_STR_LEN(" "));
                    436:        if (multiplier) buffer_append_string_len(b, &multiplier, 1);
                    437: 
                    438:        buffer_append_string_len(b, CONST_STR_LEN("req/s</td></tr>\n"));
                    439: 
                    440:        for (j = 0, avg = 0; j < 5; j++) {
                    441:                avg += p->mod_5s_traffic_out[j];
                    442:        }
                    443: 
                    444:        avg /= 5;
                    445: 
                    446:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Traffic</td><td class=\"string\">"));
                    447: 
                    448:        mod_status_get_multiplier(&avg, &multiplier, 1024);
                    449: 
1.1.1.3 ! misho     450:        snprintf(buf, sizeof(buf), "%.2f", avg);
1.1       misho     451:        buffer_append_string(b, buf);
                    452:        buffer_append_string_len(b, CONST_STR_LEN(" "));
                    453:        if (multiplier) buffer_append_string_len(b, &multiplier, 1);
                    454:        buffer_append_string_len(b, CONST_STR_LEN("byte/s</td></tr>\n"));
                    455: 
                    456:        buffer_append_string_len(b, CONST_STR_LEN("</table>\n"));
                    457: 
1.1.1.3 ! misho     458:        buffer_append_string_len(b, CONST_STR_LEN("<hr />\n<pre>\n"));
1.1       misho     459: 
                    460:        buffer_append_string_len(b, CONST_STR_LEN("<b>"));
1.1.1.3 ! misho     461:        buffer_append_int(b, srv->conns->used);
1.1       misho     462:        buffer_append_string_len(b, CONST_STR_LEN(" connections</b>\n"));
                    463: 
                    464:        for (j = 0; j < srv->conns->used; j++) {
                    465:                connection *c = srv->conns->ptr[j];
                    466:                const char *state;
                    467: 
1.1.1.3 ! misho     468:                if (CON_STATE_READ == c->state && !buffer_string_is_empty(c->request.orig_uri)) {
1.1       misho     469:                        state = "k";
1.1.1.3 ! misho     470:                        ++cstates[CON_STATE_CLOSE+2];
1.1       misho     471:                } else {
                    472:                        state = connection_get_short_state(c->state);
1.1.1.3 ! misho     473:                        ++cstates[(c->state <= CON_STATE_CLOSE ? c->state : CON_STATE_CLOSE+1)];
1.1       misho     474:                }
                    475: 
                    476:                buffer_append_string_len(b, state, 1);
                    477: 
                    478:                if (((j + 1) % 50) == 0) {
                    479:                        buffer_append_string_len(b, CONST_STR_LEN("\n"));
                    480:                }
                    481:        }
1.1.1.3 ! misho     482:        buffer_append_string_len(b, CONST_STR_LEN("\n\n<table>\n"));
        !           483:        buffer_append_string_len(b, CONST_STR_LEN("<tr><td style=\"text-align:right\">"));
        !           484:        buffer_append_int(b, cstates[CON_STATE_CLOSE+2]);
        !           485:        buffer_append_string_len(b, CONST_STR_LEN("<td>&nbsp;&nbsp;k = keep-alive</td></tr>\n"));
        !           486:        for (j = 0; j < CON_STATE_CLOSE+2; ++j) {
        !           487:                /*(skip "unknown" state if there are none; there should not be any unknown)*/
        !           488:                if (0 == cstates[j] && j == CON_STATE_CLOSE+1) continue;
        !           489:                buffer_append_string_len(b, CONST_STR_LEN("<tr><td style=\"text-align:right\">"));
        !           490:                buffer_append_int(b, cstates[j]);
        !           491:                buffer_append_string_len(b, CONST_STR_LEN("</td><td>&nbsp;&nbsp;"));
        !           492:                buffer_append_string_len(b, connection_get_short_state(j), 1);
        !           493:                buffer_append_string_len(b, CONST_STR_LEN(" = "));
        !           494:                buffer_append_string(b, connection_get_state(j));
        !           495:                buffer_append_string_len(b, CONST_STR_LEN("</td></tr>\n"));
        !           496:        }
        !           497:        buffer_append_string_len(b, CONST_STR_LEN("</table>"));
1.1       misho     498: 
                    499:        buffer_append_string_len(b, CONST_STR_LEN("\n</pre><hr />\n<h2>Connections</h2>\n"));
                    500: 
                    501:        buffer_append_string_len(b, CONST_STR_LEN("<table summary=\"status\" class=\"status\">\n"));
                    502:        buffer_append_string_len(b, CONST_STR_LEN("<tr>"));
                    503:        mod_status_header_append_sort(b, p_d, "Client IP");
                    504:        mod_status_header_append_sort(b, p_d, "Read");
                    505:        mod_status_header_append_sort(b, p_d, "Written");
                    506:        mod_status_header_append_sort(b, p_d, "State");
                    507:        mod_status_header_append_sort(b, p_d, "Time");
                    508:        mod_status_header_append_sort(b, p_d, "Host");
                    509:        mod_status_header_append_sort(b, p_d, "URI");
                    510:        mod_status_header_append_sort(b, p_d, "File");
                    511:        buffer_append_string_len(b, CONST_STR_LEN("</tr>\n"));
                    512: 
                    513:        for (j = 0; j < srv->conns->used; j++) {
                    514:                connection *c = srv->conns->ptr[j];
                    515: 
                    516:                buffer_append_string_len(b, CONST_STR_LEN("<tr><td class=\"string\">"));
                    517: 
                    518:                buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
                    519: 
                    520:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"int\">"));
                    521: 
                    522:                if (c->request.content_length) {
1.1.1.3 ! misho     523:                        buffer_append_int(b, c->request_content_queue->bytes_in);
1.1       misho     524:                        buffer_append_string_len(b, CONST_STR_LEN("/"));
1.1.1.3 ! misho     525:                        buffer_append_int(b, c->request.content_length);
1.1       misho     526:                } else {
                    527:                        buffer_append_string_len(b, CONST_STR_LEN("0/0"));
                    528:                }
                    529: 
                    530:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"int\">"));
                    531: 
1.1.1.3 ! misho     532:                buffer_append_int(b, c->write_queue->bytes_out);
1.1       misho     533:                buffer_append_string_len(b, CONST_STR_LEN("/"));
1.1.1.3 ! misho     534:                buffer_append_int(b, c->write_queue->bytes_out + chunkqueue_length(c->write_queue));
1.1       misho     535: 
                    536:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"string\">"));
                    537: 
1.1.1.3 ! misho     538:                if (CON_STATE_READ == c->state && !buffer_string_is_empty(c->request.orig_uri)) {
1.1       misho     539:                        buffer_append_string_len(b, CONST_STR_LEN("keep-alive"));
                    540:                } else {
                    541:                        buffer_append_string(b, connection_get_state(c->state));
                    542:                }
                    543: 
                    544:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"int\">"));
                    545: 
1.1.1.3 ! misho     546:                buffer_append_int(b, srv->cur_ts - c->request_start);
1.1       misho     547: 
                    548:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"string\">"));
                    549: 
1.1.1.3 ! misho     550:                if (buffer_string_is_empty(c->server_name)) {
1.1       misho     551:                        buffer_append_string_buffer(b, c->uri.authority);
                    552:                }
                    553:                else {
                    554:                        buffer_append_string_buffer(b, c->server_name);
                    555:                }
                    556: 
                    557:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"string\">"));
                    558: 
1.1.1.3 ! misho     559:                if (!buffer_string_is_empty(c->uri.path)) {
1.1       misho     560:                        buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
                    561:                }
                    562: 
1.1.1.3 ! misho     563:                if (!buffer_string_is_empty(c->uri.query)) {
1.1       misho     564:                        buffer_append_string_len(b, CONST_STR_LEN("?"));
                    565:                        buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.query), ENCODING_HTML);
                    566:                }
                    567: 
1.1.1.3 ! misho     568:                if (!buffer_string_is_empty(c->request.orig_uri)) {
1.1       misho     569:                        buffer_append_string_len(b, CONST_STR_LEN(" ("));
                    570:                        buffer_append_string_encoded(b, CONST_BUF_LEN(c->request.orig_uri), ENCODING_HTML);
                    571:                        buffer_append_string_len(b, CONST_STR_LEN(")"));
                    572:                }
                    573:                buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"string\">"));
                    574: 
                    575:                buffer_append_string_buffer(b, c->physical.path);
                    576: 
                    577:                buffer_append_string_len(b, CONST_STR_LEN("</td></tr>\n"));
                    578:        }
                    579: 
                    580: 
                    581:        buffer_append_string_len(b, CONST_STR_LEN(
                    582:                      "</table>\n"));
                    583: 
                    584: 
                    585:        buffer_append_string_len(b, CONST_STR_LEN(
                    586:                      " </body>\n"
                    587:                      "</html>\n"
                    588:                      ));
                    589: 
1.1.1.3 ! misho     590:        chunkqueue_append_buffer(con->write_queue, b);
        !           591:        buffer_free(b);
        !           592: 
1.1       misho     593:        response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
                    594: 
                    595:        return 0;
                    596: }
                    597: 
                    598: 
                    599: static handler_t mod_status_handle_server_status_text(server *srv, connection *con, void *p_d) {
                    600:        plugin_data *p = p_d;
1.1.1.3 ! misho     601:        buffer *b = buffer_init();
1.1       misho     602:        double avg;
                    603:        time_t ts;
                    604:        char buf[32];
                    605:        unsigned int k;
                    606:        unsigned int l;
                    607: 
                    608:        /* output total number of requests */
                    609:        buffer_append_string_len(b, CONST_STR_LEN("Total Accesses: "));
                    610:        avg = p->abs_requests;
                    611:        snprintf(buf, sizeof(buf) - 1, "%.0f", avg);
                    612:        buffer_append_string(b, buf);
                    613:        buffer_append_string_len(b, CONST_STR_LEN("\n"));
                    614: 
                    615:        /* output total traffic out in kbytes */
                    616:        buffer_append_string_len(b, CONST_STR_LEN("Total kBytes: "));
                    617:        avg = p->abs_traffic_out / 1024;
                    618:        snprintf(buf, sizeof(buf) - 1, "%.0f", avg);
                    619:        buffer_append_string(b, buf);
                    620:        buffer_append_string_len(b, CONST_STR_LEN("\n"));
                    621: 
                    622:        /* output uptime */
                    623:        buffer_append_string_len(b, CONST_STR_LEN("Uptime: "));
                    624:        ts = srv->cur_ts - srv->startup_ts;
1.1.1.3 ! misho     625:        buffer_append_int(b, ts);
1.1       misho     626:        buffer_append_string_len(b, CONST_STR_LEN("\n"));
                    627: 
                    628:        /* output busy servers */
                    629:        buffer_append_string_len(b, CONST_STR_LEN("BusyServers: "));
1.1.1.3 ! misho     630:        buffer_append_int(b, srv->conns->used);
1.1       misho     631:        buffer_append_string_len(b, CONST_STR_LEN("\n"));
                    632: 
                    633:        buffer_append_string_len(b, CONST_STR_LEN("IdleServers: "));
1.1.1.3 ! misho     634:        buffer_append_int(b, srv->conns->size - srv->conns->used);
        !           635:        buffer_append_string_len(b, CONST_STR_LEN("\n"));
1.1       misho     636: 
1.1.1.3 ! misho     637:        /* output scoreboard */
        !           638:        buffer_append_string_len(b, CONST_STR_LEN("Scoreboard: "));
        !           639:        for (k = 0; k < srv->conns->used; k++) {
        !           640:                connection *c = srv->conns->ptr[k];
        !           641:                const char *state =
        !           642:                  (CON_STATE_READ == c->state && !buffer_string_is_empty(c->request.orig_uri))
        !           643:                    ? "k"
        !           644:                    : connection_get_short_state(c->state);
1.1       misho     645:                buffer_append_string_len(b, state, 1);
                    646:        }
                    647:        for (l = 0; l < srv->conns->size - srv->conns->used; l++) {
                    648:                buffer_append_string_len(b, CONST_STR_LEN("_"));
                    649:        }
                    650:        buffer_append_string_len(b, CONST_STR_LEN("\n"));
                    651: 
1.1.1.3 ! misho     652:        chunkqueue_append_buffer(con->write_queue, b);
        !           653:        buffer_free(b);
1.1       misho     654: 
1.1.1.3 ! misho     655:        /* set text/plain output */
1.1       misho     656:        response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
                    657: 
                    658:        return 0;
                    659: }
                    660: 
1.1.1.3 ! misho     661: 
        !           662: static handler_t mod_status_handle_server_status_json(server *srv, connection *con, void *p_d) {
        !           663:        plugin_data *p = p_d;
        !           664:        buffer *b = buffer_init();
        !           665:        double avg;
        !           666:        time_t ts;
        !           667:        char buf[32];
        !           668:        size_t j;
        !           669:        unsigned int jsonp = 0;
        !           670: 
        !           671:        if (buffer_string_length(con->uri.query) >= sizeof("jsonp=")-1
        !           672:           && 0 == memcmp(con->uri.query->ptr, CONST_STR_LEN("jsonp="))) {
        !           673:                /* not a full parse of query string for multiple parameters,
        !           674:                * not URL-decoding param and not XML-encoding (XSS protection),
        !           675:                * so simply ensure that json function name isalnum() or '_' */
        !           676:                const char *f = con->uri.query->ptr + sizeof("jsonp=")-1;
        !           677:                int len = 0;
        !           678:                while (light_isalnum(f[len]) || f[len] == '_') ++len;
        !           679:                if (0 != len && light_isalpha(f[0]) && f[len] == '\0') {
        !           680:                        buffer_append_string_len(b, f, len);
        !           681:                        buffer_append_string_len(b, CONST_STR_LEN("("));
        !           682:                        jsonp = 1;
        !           683:                }
        !           684:        }
        !           685: 
        !           686:        /* output total number of requests */
        !           687:        buffer_append_string_len(b, CONST_STR_LEN("{\n\t\"RequestsTotal\": "));
        !           688:        avg = p->abs_requests;
        !           689:        snprintf(buf, sizeof(buf) - 1, "%.0f", avg);
        !           690:        buffer_append_string(b, buf);
        !           691:        buffer_append_string_len(b, CONST_STR_LEN(",\n"));
        !           692: 
        !           693:        /* output total traffic out in kbytes */
        !           694:        buffer_append_string_len(b, CONST_STR_LEN("\t\"TrafficTotal\": "));
        !           695:        avg = p->abs_traffic_out / 1024;
        !           696:        snprintf(buf, sizeof(buf) - 1, "%.0f", avg);
        !           697:        buffer_append_string(b, buf);
        !           698:        buffer_append_string_len(b, CONST_STR_LEN(",\n"));
        !           699: 
        !           700:        /* output uptime */
        !           701:        buffer_append_string_len(b, CONST_STR_LEN("\t\"Uptime\": "));
        !           702:        ts = srv->cur_ts - srv->startup_ts;
        !           703:        buffer_append_int(b, ts);
        !           704:        buffer_append_string_len(b, CONST_STR_LEN(",\n"));
        !           705: 
        !           706:        /* output busy servers */
        !           707:        buffer_append_string_len(b, CONST_STR_LEN("\t\"BusyServers\": "));
        !           708:        buffer_append_int(b, srv->conns->used);
        !           709:        buffer_append_string_len(b, CONST_STR_LEN(",\n"));
        !           710: 
        !           711:        buffer_append_string_len(b, CONST_STR_LEN("\t\"IdleServers\": "));
        !           712:        buffer_append_int(b, srv->conns->size - srv->conns->used);
        !           713:        buffer_append_string_len(b, CONST_STR_LEN(",\n"));
        !           714: 
        !           715:        for (j = 0, avg = 0; j < 5; j++) {
        !           716:                avg += p->mod_5s_requests[j];
        !           717:        }
        !           718: 
        !           719:        avg /= 5;
        !           720: 
        !           721:        buffer_append_string_len(b, CONST_STR_LEN("\t\"RequestAverage5s\":"));
        !           722:        buffer_append_int(b, avg);
        !           723:        buffer_append_string_len(b, CONST_STR_LEN(",\n"));
        !           724: 
        !           725:        for (j = 0, avg = 0; j < 5; j++) {
        !           726:                avg += p->mod_5s_traffic_out[j];
        !           727:        }
        !           728: 
        !           729:        avg /= 5;
        !           730: 
        !           731:        buffer_append_string_len(b, CONST_STR_LEN("\t\"TrafficAverage5s\":"));
        !           732:        buffer_append_int(b, avg / 1024); /* kbps */
        !           733:        buffer_append_string_len(b, CONST_STR_LEN("\n}"));
        !           734: 
        !           735:        if (jsonp) buffer_append_string_len(b, CONST_STR_LEN(");"));
        !           736: 
        !           737:        chunkqueue_append_buffer(con->write_queue, b);
        !           738:        buffer_free(b);
        !           739: 
        !           740:        /* set text/plain output */
        !           741:        response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("application/javascript"));
        !           742: 
        !           743:        return 0;
        !           744: }
        !           745: 
        !           746: 
1.1       misho     747: static handler_t mod_status_handle_server_statistics(server *srv, connection *con, void *p_d) {
                    748:        buffer *b;
                    749:        size_t i;
                    750:        array *st = srv->status;
                    751:        UNUSED(p_d);
                    752: 
                    753:        if (0 == st->used) {
                    754:                /* we have nothing to send */
                    755:                con->http_status = 204;
                    756:                con->file_finished = 1;
                    757: 
                    758:                return HANDLER_FINISHED;
                    759:        }
                    760: 
1.1.1.3 ! misho     761:        b = buffer_init();
1.1       misho     762:        for (i = 0; i < st->used; i++) {
                    763:                size_t ndx = st->sorted[i];
                    764: 
                    765:                buffer_append_string_buffer(b, st->data[ndx]->key);
                    766:                buffer_append_string_len(b, CONST_STR_LEN(": "));
1.1.1.3 ! misho     767:                buffer_append_int(b, ((data_integer *)(st->data[ndx]))->value);
1.1       misho     768:                buffer_append_string_len(b, CONST_STR_LEN("\n"));
                    769:        }
                    770: 
1.1.1.3 ! misho     771:        chunkqueue_append_buffer(con->write_queue, b);
        !           772:        buffer_free(b);
        !           773: 
1.1       misho     774:        response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
                    775: 
                    776:        con->http_status = 200;
                    777:        con->file_finished = 1;
                    778: 
                    779:        return HANDLER_FINISHED;
                    780: }
                    781: 
                    782: 
                    783: static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) {
                    784: 
                    785:        if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) {
                    786:                mod_status_handle_server_status_text(srv, con, p_d);
1.1.1.3 ! misho     787:        } else if (buffer_string_length(con->uri.query) >= sizeof("json")-1
        !           788:                   && 0 == memcmp(con->uri.query->ptr, CONST_STR_LEN("json"))) {
        !           789:                mod_status_handle_server_status_json(srv, con, p_d);
1.1       misho     790:        } else {
                    791:                mod_status_handle_server_status_html(srv, con, p_d);
                    792:        }
                    793: 
                    794:        con->http_status = 200;
                    795:        con->file_finished = 1;
                    796: 
                    797:        return HANDLER_FINISHED;
                    798: }
                    799: 
                    800: 
                    801: static handler_t mod_status_handle_server_config(server *srv, connection *con, void *p_d) {
                    802:        plugin_data *p = p_d;
1.1.1.3 ! misho     803:        buffer *b = buffer_init();
        !           804:        buffer *m = p->module_list;
1.1       misho     805:        size_t i;
                    806: 
                    807:        struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
                    808:        {
                    809:                /* - epoll is most reliable
                    810:                 * - select works everywhere
                    811:                 */
                    812: #ifdef USE_LINUX_EPOLL
                    813:                { FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" },
                    814: #endif
                    815: #ifdef USE_POLL
                    816:                { FDEVENT_HANDLER_POLL,           "poll" },
                    817: #endif
                    818: #ifdef USE_SELECT
                    819:                { FDEVENT_HANDLER_SELECT,         "select" },
                    820: #endif
                    821: #ifdef USE_LIBEV
                    822:                { FDEVENT_HANDLER_LIBEV,          "libev" },
                    823: #endif
                    824: #ifdef USE_SOLARIS_DEVPOLL
                    825:                { FDEVENT_HANDLER_SOLARIS_DEVPOLL,"solaris-devpoll" },
                    826: #endif
                    827: #ifdef USE_SOLARIS_PORT
                    828:                { FDEVENT_HANDLER_SOLARIS_PORT,   "solaris-eventports" },
                    829: #endif
                    830: #ifdef USE_FREEBSD_KQUEUE
                    831:                { FDEVENT_HANDLER_FREEBSD_KQUEUE, "freebsd-kqueue" },
                    832: #endif
                    833:                { FDEVENT_HANDLER_UNSET,          NULL }
                    834:        };
                    835: 
                    836:        buffer_copy_string_len(b, CONST_STR_LEN(
                    837:                           "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
                    838:                           "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
                    839:                           "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
                    840:                           "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
                    841:                           " <head>\n"
                    842:                           "  <title>Status</title>\n"
                    843:                           " </head>\n"
                    844:                           " <body>\n"
1.1.1.3 ! misho     845:                           "  <h1>"));
        !           846:        buffer_append_string_buffer(b, con->conf.server_tag);
        !           847:        buffer_append_string_len(b, CONST_STR_LEN(
        !           848:                           "</h1>\n"
1.1       misho     849:                           "  <table summary=\"status\" border=\"1\">\n"));
                    850: 
                    851:        mod_status_header_append(b, "Server-Features");
                    852: #ifdef HAVE_PCRE_H
                    853:        mod_status_row_append(b, "RegEx Conditionals", "enabled");
                    854: #else
                    855:        mod_status_row_append(b, "RegEx Conditionals", "disabled - pcre missing");
                    856: #endif
                    857:        mod_status_header_append(b, "Network Engine");
                    858: 
                    859:        for (i = 0; event_handlers[i].name; i++) {
                    860:                if (event_handlers[i].et == srv->event_handler) {
                    861:                        mod_status_row_append(b, "fd-Event-Handler", event_handlers[i].name);
                    862:                        break;
                    863:                }
                    864:        }
                    865: 
                    866:        mod_status_header_append(b, "Config-File-Settings");
                    867: 
                    868:        for (i = 0; i < srv->plugins.used; i++) {
                    869:                plugin **ps = srv->plugins.ptr;
                    870: 
                    871:                plugin *pl = ps[i];
                    872: 
                    873:                if (i == 0) {
1.1.1.3 ! misho     874:                        buffer_copy_buffer(m, pl->name);
1.1       misho     875:                } else {
                    876:                        buffer_append_string_len(m, CONST_STR_LEN("<br />"));
                    877:                        buffer_append_string_buffer(m, pl->name);
                    878:                }
                    879:        }
                    880: 
                    881:        mod_status_row_append(b, "Loaded Modules", m->ptr);
                    882: 
                    883:        buffer_append_string_len(b, CONST_STR_LEN("  </table>\n"));
                    884: 
                    885:        buffer_append_string_len(b, CONST_STR_LEN(
                    886:                      " </body>\n"
                    887:                      "</html>\n"
                    888:                      ));
                    889: 
1.1.1.3 ! misho     890:        chunkqueue_append_buffer(con->write_queue, b);
        !           891:        buffer_free(b);
        !           892: 
1.1       misho     893:        response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
                    894: 
                    895:        con->http_status = 200;
                    896:        con->file_finished = 1;
                    897: 
                    898:        return HANDLER_FINISHED;
                    899: }
                    900: 
                    901: #define PATCH(x) \
                    902:        p->conf.x = s->x;
                    903: static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
                    904:        size_t i, j;
                    905:        plugin_config *s = p->config_storage[0];
                    906: 
                    907:        PATCH(status_url);
                    908:        PATCH(config_url);
                    909:        PATCH(sort);
                    910:        PATCH(statistics_url);
                    911: 
                    912:        /* skip the first, the global context */
                    913:        for (i = 1; i < srv->config_context->used; i++) {
                    914:                data_config *dc = (data_config *)srv->config_context->data[i];
                    915:                s = p->config_storage[i];
                    916: 
                    917:                /* condition didn't match */
                    918:                if (!config_check_cond(srv, con, dc)) continue;
                    919: 
                    920:                /* merge config */
                    921:                for (j = 0; j < dc->value->used; j++) {
                    922:                        data_unset *du = dc->value->data[j];
                    923: 
                    924:                        if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.status-url"))) {
                    925:                                PATCH(status_url);
                    926:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) {
                    927:                                PATCH(config_url);
                    928:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.enable-sort"))) {
                    929:                                PATCH(sort);
                    930:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
                    931:                                PATCH(statistics_url);
                    932:                        }
                    933:                }
                    934:        }
                    935: 
                    936:        return 0;
                    937: }
                    938: 
                    939: static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
                    940:        plugin_data *p = p_d;
                    941: 
                    942:        if (con->mode != DIRECT) return HANDLER_GO_ON;
                    943: 
                    944:        mod_status_patch_connection(srv, con, p);
                    945: 
1.1.1.3 ! misho     946:        if (!buffer_string_is_empty(p->conf.status_url) &&
1.1       misho     947:            buffer_is_equal(p->conf.status_url, con->uri.path)) {
                    948:                return mod_status_handle_server_status(srv, con, p_d);
1.1.1.3 ! misho     949:        } else if (!buffer_string_is_empty(p->conf.config_url) &&
1.1       misho     950:            buffer_is_equal(p->conf.config_url, con->uri.path)) {
                    951:                return mod_status_handle_server_config(srv, con, p_d);
1.1.1.3 ! misho     952:        } else if (!buffer_string_is_empty(p->conf.statistics_url) &&
1.1       misho     953:            buffer_is_equal(p->conf.statistics_url, con->uri.path)) {
                    954:                return mod_status_handle_server_statistics(srv, con, p_d);
                    955:        }
                    956: 
                    957:        return HANDLER_GO_ON;
                    958: }
                    959: 
                    960: TRIGGER_FUNC(mod_status_trigger) {
                    961:        plugin_data *p = p_d;
                    962:        size_t i;
                    963: 
                    964:        /* check all connections */
                    965:        for (i = 0; i < srv->conns->used; i++) {
                    966:                connection *c = srv->conns->ptr[i];
                    967: 
                    968:                p->bytes_written += c->bytes_written_cur_second;
                    969:        }
                    970: 
                    971:        /* a sliding average */
                    972:        p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written;
                    973:        p->mod_5s_requests   [p->mod_5s_ndx] = p->requests;
                    974: 
                    975:        p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5;
                    976: 
                    977:        p->abs_traffic_out += p->bytes_written;
                    978:        p->rel_traffic_out += p->bytes_written;
                    979: 
                    980:        p->bytes_written = 0;
                    981: 
                    982:        /* reset storage - second */
                    983:        p->traffic_out = 0;
                    984:        p->requests    = 0;
                    985: 
                    986:        return HANDLER_GO_ON;
                    987: }
                    988: 
                    989: REQUESTDONE_FUNC(mod_status_account) {
                    990:        plugin_data *p = p_d;
                    991: 
                    992:        UNUSED(srv);
                    993: 
                    994:        p->requests++;
                    995:        p->rel_requests++;
                    996:        p->abs_requests++;
                    997: 
                    998:        p->bytes_written += con->bytes_written_cur_second;
                    999: 
                   1000:        return HANDLER_GO_ON;
                   1001: }
                   1002: 
                   1003: int mod_status_plugin_init(plugin *p);
                   1004: int mod_status_plugin_init(plugin *p) {
                   1005:        p->version     = LIGHTTPD_VERSION_ID;
                   1006:        p->name        = buffer_init_string("status");
                   1007: 
                   1008:        p->init        = mod_status_init;
                   1009:        p->cleanup     = mod_status_free;
                   1010:        p->set_defaults= mod_status_set_defaults;
                   1011: 
                   1012:        p->handle_uri_clean    = mod_status_handler;
                   1013:        p->handle_trigger      = mod_status_trigger;
                   1014:        p->handle_request_done = mod_status_account;
                   1015: 
                   1016:        p->data        = NULL;
                   1017: 
                   1018:        return 0;
                   1019: }

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