| /** @file |
| |
| A brief file description |
| |
| @section license License |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| /**************************************************************************** |
| |
| StatPages.cc |
| |
| |
| ****************************************************************************/ |
| |
| #include "tscore/ink_config.h" |
| #include "ProxyConfig.h" |
| #include "StatPages.h" |
| #include "HdrUtils.h" |
| #include "tscore/MatcherUtils.h" |
| |
| #define MAX_STAT_PAGES 32 |
| |
| // Globals |
| StatPagesManager statPagesManager; |
| |
| static struct { |
| char *module; |
| StatPagesFunc func; |
| } stat_pages[MAX_STAT_PAGES]; |
| |
| static int n_stat_pages; |
| |
| void |
| StatPagesManager::init() |
| { |
| ink_mutex_init(&stat_pages_mutex); |
| REC_EstablishStaticConfigInt32(m_enabled, "proxy.config.http_ui_enabled"); |
| } |
| |
| void |
| StatPagesManager::register_http(const char *module, StatPagesFunc func) |
| { |
| ink_mutex_acquire(&stat_pages_mutex); |
| ink_release_assert(n_stat_pages < MAX_STAT_PAGES); |
| |
| stat_pages[n_stat_pages].module = static_cast<char *>(ats_malloc(strlen(module) + 3)); |
| snprintf(stat_pages[n_stat_pages].module, strlen(module) + 3, "{%s}", module); |
| stat_pages[n_stat_pages++].func = func; |
| ink_mutex_release(&stat_pages_mutex); |
| } |
| |
| Action * |
| StatPagesManager::handle_http(Continuation *cont, HTTPHdr *header) |
| { |
| URL *url = header->url_get(); |
| |
| if (((m_enabled == 1 || m_enabled == 3) && is_cache_inspector_page(url)) || |
| ((m_enabled == 2 || m_enabled == 3) && is_stat_page(url) && !is_cache_inspector_page(url))) { |
| int host_len; |
| char host[MAXDNAME + 1]; |
| const char *h; |
| int i; |
| |
| h = url->host_get(&host_len); |
| if (host_len > MAXDNAME) { |
| host_len = MAXDNAME; |
| } |
| memcpy(host, h, host_len); |
| host[host_len] = '\0'; |
| host_len = unescapifyStr(host); |
| |
| for (i = 0; i < n_stat_pages; i++) { |
| if (strlen(host) == strlen(stat_pages[i].module) && strncmp(host, stat_pages[i].module, host_len) == 0) { |
| return stat_pages[i].func(cont, header); |
| } |
| } |
| } |
| |
| cont->handleEvent(STAT_PAGE_FAILURE, nullptr); |
| return ACTION_RESULT_DONE; |
| } |
| |
| bool |
| StatPagesManager::is_stat_page(URL *url) |
| { |
| // This gets called from the state machine, so we should optimize here and not in caller. |
| if (m_enabled <= 0) { |
| return false; |
| } |
| |
| int length; |
| const char *h = url->host_get(&length); |
| char host[MAXDNAME + 1]; |
| |
| if (h == nullptr || length < 2 || length > MAXDNAME) { |
| return false; |
| } |
| |
| memcpy(host, h, length); |
| host[length] = '\0'; |
| length = unescapifyStr(host); |
| |
| if ((host[0] == '{') && (host[length - 1] == '}')) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| bool |
| StatPagesManager::is_cache_inspector_page(URL *url) |
| { |
| int length; |
| const char *h = url->host_get(&length); |
| char host[MAXDNAME + 1]; |
| |
| if (h == nullptr || length < 2 || length > MAXDNAME) { |
| return false; |
| } |
| |
| memcpy(host, h, length); |
| host[length] = '\0'; |
| length = unescapifyStr(host); |
| |
| if (strncmp(host, "{cache}", length) == 0) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| void |
| BaseStatPagesHandler::resp_clear() |
| { |
| ats_free(response); |
| response = nullptr; |
| response_size = 0; |
| response_length = 0; |
| } |
| |
| void |
| BaseStatPagesHandler::resp_add(const char *fmt, ...) |
| { |
| va_list args; |
| char buf[16384]; |
| int length; |
| int size; |
| |
| va_start(args, fmt); |
| length = vsnprintf(buf, 16384, fmt, args); |
| va_end(args); |
| |
| size = response_size; |
| if (size == 0) { |
| size = 1024; |
| } |
| while ((response_length + length + 1) > size) { |
| size *= 2; |
| } |
| |
| if (size != response_size) { |
| if (!response) { |
| response = static_cast<char *>(ats_malloc(size)); |
| } else { |
| response = static_cast<char *>(ats_realloc(response, size)); |
| } |
| response_size = size; |
| } |
| |
| memcpy(&response[response_length], buf, length + 1); |
| response_length += length; |
| } |
| |
| void |
| BaseStatPagesHandler::resp_add_sep() |
| { |
| resp_add("<hr width=\"100%%\">\n"); |
| } |
| |
| void |
| BaseStatPagesHandler::resp_begin(const char *title) |
| { |
| resp_clear(); |
| resp_add("<html>\n" |
| "<head><title>%s</title></head>\n" |
| "<body text=\"#000000\" bgcolor=\"#ffffff\" link=\"#0000ee\" vlink=\"#551a8b\" alink=\"#ff0000\">\n", |
| title); |
| } |
| |
| void |
| BaseStatPagesHandler::resp_end() |
| { |
| resp_add("</body>\n" |
| "</html>\n"); |
| } |
| |
| void |
| BaseStatPagesHandler::resp_begin_numbered() |
| { |
| resp_add("<ol>\n"); |
| } |
| |
| void |
| BaseStatPagesHandler::resp_end_numbered() |
| { |
| resp_add("</ol>\n"); |
| } |
| |
| void |
| BaseStatPagesHandler::resp_begin_unnumbered() |
| { |
| resp_add("<ul>\n"); |
| } |
| |
| void |
| BaseStatPagesHandler::resp_end_unnumbered() |
| { |
| resp_add("</ul>\n"); |
| } |
| |
| void |
| BaseStatPagesHandler::resp_begin_item() |
| { |
| resp_add("<li>\n"); |
| } |
| |
| void |
| BaseStatPagesHandler::resp_end_item() |
| { |
| resp_add("</li>\n"); |
| } |
| |
| void |
| BaseStatPagesHandler::resp_begin_table(int border, int columns, int percent) |
| { |
| resp_add("<table border=%d cols=%d width=\"%d%%\">\n", border, columns, percent); |
| } |
| |
| void |
| BaseStatPagesHandler::resp_end_table() |
| { |
| resp_add("</table>\n"); |
| } |
| |
| void |
| BaseStatPagesHandler::resp_begin_row() |
| { |
| resp_add("<tr>\n"); |
| } |
| |
| void |
| BaseStatPagesHandler::resp_end_row() |
| { |
| resp_add("</tr>\n"); |
| } |
| |
| void |
| BaseStatPagesHandler::resp_begin_column(int percent, const char *align) |
| { |
| if (percent == -1) { |
| resp_add("<td %s%s>\n", align ? "align=" : "", align ? align : ""); |
| } else { |
| resp_add("<td width=\"%d%%\" %s%s>\n", percent, align ? "align=" : "", align ? align : ""); |
| } |
| } |
| |
| void |
| BaseStatPagesHandler::resp_end_column() |
| { |
| resp_add("</td>\n"); |
| } |