summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/lib/core
diff options
context:
space:
mode:
Diffstat (limited to 'web/server/h2o/libh2o/lib/core')
-rw-r--r--web/server/h2o/libh2o/lib/core/config.c325
-rw-r--r--web/server/h2o/libh2o/lib/core/configurator.c1102
-rw-r--r--web/server/h2o/libh2o/lib/core/context.c201
-rw-r--r--web/server/h2o/libh2o/lib/core/headers.c155
-rw-r--r--web/server/h2o/libh2o/lib/core/logconf.c793
-rw-r--r--web/server/h2o/libh2o/lib/core/proxy.c610
-rw-r--r--web/server/h2o/libh2o/lib/core/request.c696
-rw-r--r--web/server/h2o/libh2o/lib/core/token.c28
-rw-r--r--web/server/h2o/libh2o/lib/core/token_table.h408
-rw-r--r--web/server/h2o/libh2o/lib/core/util.c562
10 files changed, 0 insertions, 4880 deletions
diff --git a/web/server/h2o/libh2o/lib/core/config.c b/web/server/h2o/libh2o/lib/core/config.c
deleted file mode 100644
index ce1d32018..000000000
--- a/web/server/h2o/libh2o/lib/core/config.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <inttypes.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "h2o.h"
-#include "h2o/configurator.h"
-#include "h2o/http1.h"
-#include "h2o/http2.h"
-
-static h2o_hostconf_t *create_hostconf(h2o_globalconf_t *globalconf)
-{
- h2o_hostconf_t *hostconf = h2o_mem_alloc(sizeof(*hostconf));
- *hostconf = (h2o_hostconf_t){globalconf};
- hostconf->http2.push_preload = 1; /* enabled by default */
- h2o_config_init_pathconf(&hostconf->fallback_path, globalconf, NULL, globalconf->mimemap);
- hostconf->mimemap = globalconf->mimemap;
- h2o_mem_addref_shared(hostconf->mimemap);
- return hostconf;
-}
-
-static void destroy_hostconf(h2o_hostconf_t *hostconf)
-{
- size_t i;
-
- if (hostconf->authority.hostport.base != hostconf->authority.host.base)
- free(hostconf->authority.hostport.base);
- free(hostconf->authority.host.base);
- for (i = 0; i != hostconf->paths.size; ++i) {
- h2o_pathconf_t *pathconf = hostconf->paths.entries + i;
- h2o_config_dispose_pathconf(pathconf);
- }
- free(hostconf->paths.entries);
- h2o_config_dispose_pathconf(&hostconf->fallback_path);
- h2o_mem_release_shared(hostconf->mimemap);
-
- free(hostconf);
-}
-
-static void on_dispose_envconf(void *_envconf)
-{
- h2o_envconf_t *envconf = _envconf;
- size_t i;
-
- if (envconf->parent != NULL)
- h2o_mem_release_shared(envconf->parent);
-
- for (i = 0; i != envconf->unsets.size; ++i)
- h2o_mem_release_shared(envconf->unsets.entries[i].base);
- free(envconf->unsets.entries);
- for (i = 0; i != envconf->sets.size; ++i)
- h2o_mem_release_shared(envconf->sets.entries[i].base);
- free(envconf->sets.entries);
-}
-
-h2o_envconf_t *h2o_config_create_envconf(h2o_envconf_t *parent)
-{
- h2o_envconf_t *envconf = h2o_mem_alloc_shared(NULL, sizeof(*envconf), on_dispose_envconf);
- *envconf = (h2o_envconf_t){NULL};
-
- if (parent != NULL) {
- envconf->parent = parent;
- h2o_mem_addref_shared(parent);
- }
- return envconf;
-}
-
-void h2o_config_setenv(h2o_envconf_t *envconf, const char *name, const char *value)
-{
- size_t name_len = strlen(name), i;
- h2o_iovec_t *value_slot;
-
- /* remove from the list of unsets */
- for (i = 0; i != envconf->unsets.size; ++i) {
- if (h2o_memis(envconf->unsets.entries[i].base, envconf->unsets.entries[i].len, name, name_len)) {
- h2o_mem_release_shared(envconf->unsets.entries[i].base);
- h2o_vector_erase(&envconf->unsets, i);
- break;
- }
- }
- /* find the slot */
- for (i = 0; i != envconf->sets.size; i += 2) {
- if (h2o_memis(envconf->sets.entries[i].base, envconf->sets.entries[i].len, name, name_len)) {
- value_slot = envconf->sets.entries + i + 1;
- h2o_mem_release_shared(value_slot->base);
- goto SetValue;
- }
- }
- /* name not found in existing sets */
- h2o_vector_reserve(NULL, &envconf->sets, envconf->sets.size + 2);
- envconf->sets.entries[envconf->sets.size++] = h2o_strdup_shared(NULL, name, name_len);
- value_slot = envconf->sets.entries + envconf->sets.size++;
-SetValue:
- *value_slot = h2o_strdup_shared(NULL, value, SIZE_MAX);
-}
-
-void h2o_config_unsetenv(h2o_envconf_t *envconf, const char *name)
-{
- size_t i, name_len = strlen(name);
-
- /* do nothing if already set */
- for (i = 0; i != envconf->unsets.size; ++i)
- if (h2o_memis(envconf->unsets.entries[i].base, envconf->unsets.entries[i].len, name, name_len))
- return;
- /* register */
- h2o_vector_reserve(NULL, &envconf->unsets, envconf->unsets.size + 1);
- envconf->unsets.entries[envconf->unsets.size++] = h2o_strdup_shared(NULL, name, name_len);
-}
-
-void h2o_config_init_pathconf(h2o_pathconf_t *pathconf, h2o_globalconf_t *globalconf, const char *path, h2o_mimemap_t *mimemap)
-{
- memset(pathconf, 0, sizeof(*pathconf));
- pathconf->global = globalconf;
- h2o_chunked_register(pathconf);
- if (path != NULL)
- pathconf->path = h2o_strdup(NULL, path, SIZE_MAX);
- h2o_mem_addref_shared(mimemap);
- pathconf->mimemap = mimemap;
- pathconf->error_log.emit_request_errors = 1;
-}
-
-void h2o_config_dispose_pathconf(h2o_pathconf_t *pathconf)
-{
-#define DESTROY_LIST(type, list) \
- do { \
- size_t i; \
- for (i = 0; i != list.size; ++i) { \
- type *e = list.entries[i]; \
- if (e->dispose != NULL) \
- e->dispose(e); \
- free(e); \
- } \
- free(list.entries); \
- } while (0)
- DESTROY_LIST(h2o_handler_t, pathconf->handlers);
- DESTROY_LIST(h2o_filter_t, pathconf->filters);
- DESTROY_LIST(h2o_logger_t, pathconf->loggers);
-#undef DESTROY_LIST
-
- free(pathconf->path.base);
- if (pathconf->mimemap != NULL)
- h2o_mem_release_shared(pathconf->mimemap);
- if (pathconf->env != NULL)
- h2o_mem_release_shared(pathconf->env);
-}
-
-void h2o_config_init(h2o_globalconf_t *config)
-{
- memset(config, 0, sizeof(*config));
- config->hosts = h2o_mem_alloc(sizeof(config->hosts[0]));
- config->hosts[0] = NULL;
- h2o_linklist_init_anchor(&config->configurators);
- config->server_name = h2o_iovec_init(H2O_STRLIT("h2o/" H2O_VERSION));
- config->max_request_entity_size = H2O_DEFAULT_MAX_REQUEST_ENTITY_SIZE;
- config->max_delegations = H2O_DEFAULT_MAX_DELEGATIONS;
- config->handshake_timeout = H2O_DEFAULT_HANDSHAKE_TIMEOUT;
- config->http1.req_timeout = H2O_DEFAULT_HTTP1_REQ_TIMEOUT;
- config->http1.upgrade_to_http2 = H2O_DEFAULT_HTTP1_UPGRADE_TO_HTTP2;
- config->http1.callbacks = H2O_HTTP1_CALLBACKS;
- config->http2.idle_timeout = H2O_DEFAULT_HTTP2_IDLE_TIMEOUT;
- config->http2.graceful_shutdown_timeout = H2O_DEFAULT_HTTP2_GRACEFUL_SHUTDOWN_TIMEOUT;
- config->proxy.io_timeout = H2O_DEFAULT_PROXY_IO_TIMEOUT;
- config->proxy.emit_x_forwarded_headers = 1;
- config->proxy.emit_via_header = 1;
- config->http2.max_concurrent_requests_per_connection = H2O_HTTP2_SETTINGS_HOST.max_concurrent_streams;
- config->http2.max_streams_for_priority = 16;
- config->http2.latency_optimization.min_rtt = 50; // milliseconds
- config->http2.latency_optimization.max_additional_delay = 10;
- config->http2.latency_optimization.max_cwnd = 65535;
- config->http2.callbacks = H2O_HTTP2_CALLBACKS;
- config->mimemap = h2o_mimemap_create();
-
- h2o_configurator__init_core(config);
-}
-
-h2o_pathconf_t *h2o_config_register_path(h2o_hostconf_t *hostconf, const char *path, int flags)
-{
- h2o_pathconf_t *pathconf;
-
- h2o_vector_reserve(NULL, &hostconf->paths, hostconf->paths.size + 1);
- pathconf = hostconf->paths.entries + hostconf->paths.size++;
-
- h2o_config_init_pathconf(pathconf, hostconf->global, path, hostconf->mimemap);
-
- return pathconf;
-}
-
-void h2o_config_register_status_handler(h2o_globalconf_t *config, h2o_status_handler_t status_handler)
-{
- h2o_vector_reserve(NULL, &config->statuses, config->statuses.size + 1);
- config->statuses.entries[config->statuses.size++] = status_handler;
-}
-
-void h2o_config_register_simple_status_handler(h2o_globalconf_t *config, h2o_iovec_t name, final_status_handler_cb status_handler)
-{
- h2o_status_handler_t *sh;
-
- h2o_vector_reserve(NULL, &config->statuses, config->statuses.size + 1);
- sh = &config->statuses.entries[config->statuses.size++];
- memset(sh, 0, sizeof(*sh));
- sh->name = h2o_strdup(NULL, name.base, name.len);
- sh->final = status_handler;
-}
-
-h2o_hostconf_t *h2o_config_register_host(h2o_globalconf_t *config, h2o_iovec_t host, uint16_t port)
-{
- h2o_hostconf_t *hostconf = NULL;
- h2o_iovec_t host_lc;
-
- assert(host.len != 0);
-
- /* convert hostname to lowercase */
- host_lc = h2o_strdup(NULL, host.base, host.len);
- h2o_strtolower(host_lc.base, host_lc.len);
-
- { /* return NULL if given authority is already registered */
- h2o_hostconf_t **p;
- for (p = config->hosts; *p != NULL; ++p)
- if (h2o_memis((*p)->authority.host.base, (*p)->authority.host.len, host_lc.base, host_lc.len) &&
- (*p)->authority.port == port)
- goto Exit;
- }
-
- /* create hostconf */
- hostconf = create_hostconf(config);
- hostconf->authority.host = host_lc;
- host_lc = (h2o_iovec_t){NULL};
- hostconf->authority.port = port;
- if (hostconf->authority.port == 65535) {
- hostconf->authority.hostport = hostconf->authority.host;
- } else {
- hostconf->authority.hostport.base = h2o_mem_alloc(hostconf->authority.host.len + sizeof("[]:" H2O_UINT16_LONGEST_STR));
- if (strchr(hostconf->authority.host.base, ':') != NULL) {
- hostconf->authority.hostport.len =
- sprintf(hostconf->authority.hostport.base, "[%s]:%" PRIu16, hostconf->authority.host.base, port);
- } else {
- hostconf->authority.hostport.len =
- sprintf(hostconf->authority.hostport.base, "%s:%" PRIu16, hostconf->authority.host.base, port);
- }
- }
-
- /* append to the list */
- h2o_append_to_null_terminated_list((void *)&config->hosts, hostconf);
-
-Exit:
- free(host_lc.base);
- return hostconf;
-}
-
-void h2o_config_dispose(h2o_globalconf_t *config)
-{
- size_t i;
-
- for (i = 0; config->hosts[i] != NULL; ++i) {
- h2o_hostconf_t *hostconf = config->hosts[i];
- destroy_hostconf(hostconf);
- }
- free(config->hosts);
-
- h2o_mem_release_shared(config->mimemap);
- h2o_configurator__dispose_configurators(config);
-}
-
-h2o_handler_t *h2o_create_handler(h2o_pathconf_t *conf, size_t sz)
-{
- h2o_handler_t *handler = h2o_mem_alloc(sz);
-
- memset(handler, 0, sz);
- handler->_config_slot = conf->global->_num_config_slots++;
-
- h2o_vector_reserve(NULL, &conf->handlers, conf->handlers.size + 1);
- conf->handlers.entries[conf->handlers.size++] = handler;
-
- return handler;
-}
-
-h2o_filter_t *h2o_create_filter(h2o_pathconf_t *conf, size_t sz)
-{
- h2o_filter_t *filter = h2o_mem_alloc(sz);
-
- memset(filter, 0, sz);
- filter->_config_slot = conf->global->_num_config_slots++;
-
- h2o_vector_reserve(NULL, &conf->filters, conf->filters.size + 1);
- memmove(conf->filters.entries + 1, conf->filters.entries, conf->filters.size * sizeof(conf->filters.entries[0]));
- conf->filters.entries[0] = filter;
- ++conf->filters.size;
-
- return filter;
-}
-
-h2o_logger_t *h2o_create_logger(h2o_pathconf_t *conf, size_t sz)
-{
- h2o_logger_t *logger = h2o_mem_alloc(sz);
-
- memset(logger, 0, sz);
- logger->_config_slot = conf->global->_num_config_slots++;
-
- h2o_vector_reserve(NULL, &conf->loggers, conf->loggers.size + 1);
- conf->loggers.entries[conf->loggers.size++] = logger;
-
- return logger;
-}
diff --git a/web/server/h2o/libh2o/lib/core/configurator.c b/web/server/h2o/libh2o/lib/core/configurator.c
deleted file mode 100644
index 891770cc2..000000000
--- a/web/server/h2o/libh2o/lib/core/configurator.c
+++ /dev/null
@@ -1,1102 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Fastly, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include "h2o.h"
-#include "h2o/configurator.h"
-
-struct st_core_config_vars_t {
- struct {
- unsigned reprioritize_blocking_assets : 1;
- unsigned push_preload : 1;
- h2o_casper_conf_t casper;
- } http2;
- struct {
- unsigned emit_request_errors : 1;
- } error_log;
-};
-
-struct st_core_configurator_t {
- h2o_configurator_t super;
- struct st_core_config_vars_t *vars, _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
-};
-
-static h2o_configurator_context_t *create_context(h2o_configurator_context_t *parent, int is_custom_handler)
-{
- h2o_configurator_context_t *ctx = h2o_mem_alloc(sizeof(*ctx));
- if (parent == NULL) {
- *ctx = (h2o_configurator_context_t){NULL};
- return ctx;
- }
- *ctx = *parent;
- if (ctx->env != NULL)
- h2o_mem_addref_shared(ctx->env);
- ctx->parent = parent;
- return ctx;
-}
-
-static void destroy_context(h2o_configurator_context_t *ctx)
-{
- if (ctx->env != NULL) {
- if (ctx->pathconf != NULL)
- ctx->pathconf->env = ctx->env;
- else
- h2o_mem_release_shared(ctx->env);
- }
- free(ctx);
-}
-
-static int on_core_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_core_configurator_t *self = (void *)_self;
-
- ++self->vars;
- self->vars[0] = self->vars[-1];
- return 0;
-}
-
-static int on_core_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_core_configurator_t *self = (void *)_self;
-
- if (ctx->hostconf != NULL && ctx->pathconf == NULL) {
- /* exitting from host-level configuration */
- ctx->hostconf->http2.reprioritize_blocking_assets = self->vars->http2.reprioritize_blocking_assets;
- ctx->hostconf->http2.push_preload = self->vars->http2.push_preload;
- ctx->hostconf->http2.casper = self->vars->http2.casper;
- } else if (ctx->pathconf != NULL) {
- /* exitting from path or extension-level configuration */
- ctx->pathconf->error_log.emit_request_errors = self->vars->error_log.emit_request_errors;
- }
-
- --self->vars;
- return 0;
-}
-
-static void destroy_configurator(h2o_configurator_t *configurator)
-{
- if (configurator->dispose != NULL)
- configurator->dispose(configurator);
- free(configurator->commands.entries);
- free(configurator);
-}
-
-static int setup_configurators(h2o_configurator_context_t *ctx, int is_enter, yoml_t *node)
-{
- h2o_linklist_t *n;
-
- for (n = ctx->globalconf->configurators.next; n != &ctx->globalconf->configurators; n = n->next) {
- h2o_configurator_t *c = H2O_STRUCT_FROM_MEMBER(h2o_configurator_t, _link, n);
- if (is_enter) {
- if (c->enter != NULL && c->enter(c, ctx, node) != 0)
- return -1;
- } else {
- if (c->exit != NULL && c->exit(c, ctx, node) != 0)
- return -1;
- }
- }
-
- return 0;
-}
-
-static int config_timeout(h2o_configurator_command_t *cmd, yoml_t *node, uint64_t *slot)
-{
- uint64_t timeout_in_secs;
-
- if (h2o_configurator_scanf(cmd, node, "%" SCNu64, &timeout_in_secs) != 0)
- return -1;
-
- *slot = timeout_in_secs * 1000;
- return 0;
-}
-
-int h2o_configurator_apply_commands(h2o_configurator_context_t *ctx, yoml_t *node, int flags_mask, const char **ignore_commands)
-{
- struct st_cmd_value_t {
- h2o_configurator_command_t *cmd;
- yoml_t *value;
- };
- H2O_VECTOR(struct st_cmd_value_t) deferred = {NULL}, semi_deferred = {NULL};
- int ret = -1;
-
- if (node != NULL && node->type != YOML_TYPE_MAPPING) {
- h2o_configurator_errprintf(NULL, node, "node must be a MAPPING");
- goto Exit;
- }
-
- /* call on_enter of every configurator */
- if (setup_configurators(ctx, 1, node) != 0)
- goto Exit;
-
- /* handle the configuration commands */
- if (node != NULL) {
- size_t i;
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key, *value = node->data.mapping.elements[i].value;
- h2o_configurator_command_t *cmd;
- /* obtain the target command */
- if (key->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(NULL, key, "command must be a string");
- goto Exit;
- }
- if (ignore_commands != NULL) {
- size_t i;
- for (i = 0; ignore_commands[i] != NULL; ++i)
- if (strcmp(ignore_commands[i], key->data.scalar) == 0)
- goto SkipCommand;
- }
- if ((cmd = h2o_configurator_get_command(ctx->globalconf, key->data.scalar)) == NULL) {
- h2o_configurator_errprintf(NULL, key, "unknown command: %s", key->data.scalar);
- goto Exit;
- }
- if ((cmd->flags & flags_mask) == 0) {
- h2o_configurator_errprintf(cmd, key, "the command cannot be used at this level");
- goto Exit;
- }
- /* check value type */
- if ((cmd->flags & (H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR | H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE |
- H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING)) != 0) {
- switch (value->type) {
- case YOML_TYPE_SCALAR:
- if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR) == 0) {
- h2o_configurator_errprintf(cmd, value, "argument cannot be a scalar");
- goto Exit;
- }
- break;
- case YOML_TYPE_SEQUENCE:
- if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE) == 0) {
- h2o_configurator_errprintf(cmd, value, "argument cannot be a sequence");
- goto Exit;
- }
- break;
- case YOML_TYPE_MAPPING:
- if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING) == 0) {
- h2o_configurator_errprintf(cmd, value, "argument cannot be a mapping");
- goto Exit;
- }
- break;
- default:
- assert(!"unreachable");
- break;
- }
- }
- /* handle the command (or keep it for later execution) */
- if ((cmd->flags & H2O_CONFIGURATOR_FLAG_SEMI_DEFERRED) != 0) {
- h2o_vector_reserve(NULL, &semi_deferred, semi_deferred.size + 1);
- semi_deferred.entries[semi_deferred.size++] = (struct st_cmd_value_t){cmd, value};
- } else if ((cmd->flags & H2O_CONFIGURATOR_FLAG_DEFERRED) != 0) {
- h2o_vector_reserve(NULL, &deferred, deferred.size + 1);
- deferred.entries[deferred.size++] = (struct st_cmd_value_t){cmd, value};
- } else {
- if (cmd->cb(cmd, ctx, value) != 0)
- goto Exit;
- }
- SkipCommand:;
- }
- for (i = 0; i != semi_deferred.size; ++i) {
- struct st_cmd_value_t *pair = semi_deferred.entries + i;
- if (pair->cmd->cb(pair->cmd, ctx, pair->value) != 0)
- goto Exit;
- }
- for (i = 0; i != deferred.size; ++i) {
- struct st_cmd_value_t *pair = deferred.entries + i;
- if (pair->cmd->cb(pair->cmd, ctx, pair->value) != 0)
- goto Exit;
- }
- }
-
- /* call on_exit of every configurator */
- if (setup_configurators(ctx, 0, node) != 0)
- goto Exit;
-
- ret = 0;
-Exit:
- free(deferred.entries);
- free(semi_deferred.entries);
- return ret;
-}
-
-static int sort_from_longer_paths(const yoml_mapping_element_t *x, const yoml_mapping_element_t *y)
-{
- size_t xlen = strlen(x->key->data.scalar), ylen = strlen(y->key->data.scalar);
- if (xlen < ylen)
- return 1;
- else if (xlen > ylen)
- return -1;
- /* apply strcmp for stable sort */
- return strcmp(x->key->data.scalar, y->key->data.scalar);
-}
-
-static yoml_t *convert_path_config_node(h2o_configurator_command_t *cmd, yoml_t *node)
-{
- size_t i, j;
-
- switch (node->type) {
- case YOML_TYPE_MAPPING:
- break;
- case YOML_TYPE_SEQUENCE: {
- /* convert to mapping */
- yoml_t *map = h2o_mem_alloc(sizeof(yoml_t));
- *map = (yoml_t){YOML_TYPE_MAPPING};
- if (node->filename != NULL)
- map->filename = h2o_strdup(NULL, node->filename, SIZE_MAX).base;
- map->line = node->line;
- map->column = node->column;
- if (node->anchor != NULL)
- map->anchor = h2o_strdup(NULL, node->anchor, SIZE_MAX).base;
- map->_refcnt = 1;
-
- for (i = 0; i != node->data.sequence.size; ++i) {
- yoml_t *elem = node->data.sequence.elements[i];
- if (elem->type != YOML_TYPE_MAPPING) {
- yoml_free(map, NULL);
- goto Error;
- }
- for (j = 0; j != elem->data.mapping.size; ++j) {
- yoml_t *elemkey = elem->data.mapping.elements[j].key;
- yoml_t *elemvalue = elem->data.mapping.elements[j].value;
- map = h2o_mem_realloc(map, offsetof(yoml_t, data.mapping.elements) +
- sizeof(yoml_mapping_element_t) * (map->data.mapping.size + 1));
- map->data.mapping.elements[map->data.mapping.size].key = elemkey;
- map->data.mapping.elements[map->data.mapping.size].value = elemvalue;
- ++map->data.mapping.size;
- ++elemkey->_refcnt;
- ++elemvalue->_refcnt;
- }
- }
- return map;
- } break;
- default:
- Error:
- h2o_configurator_errprintf(cmd, node, "value must be a mapping or sequence of mapping");
- return NULL;
- }
-
- ++node->_refcnt;
- return node;
-}
-
-static int config_path(h2o_configurator_context_t *parent_ctx, h2o_pathconf_t *pathconf, yoml_t *node)
-{
- h2o_configurator_context_t *path_ctx = create_context(parent_ctx, 0);
- path_ctx->pathconf = pathconf;
- path_ctx->mimemap = &pathconf->mimemap;
-
- int ret = h2o_configurator_apply_commands(path_ctx, node, H2O_CONFIGURATOR_FLAG_PATH, NULL);
-
- destroy_context(path_ctx);
- return ret;
-}
-
-static int on_config_paths(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- size_t i;
-
- /* sort by the length of the path (descending) */
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key;
- if (key->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, key, "key (representing the virtual path) must be a string");
- return -1;
- }
- }
- qsort(node->data.mapping.elements, node->data.mapping.size, sizeof(node->data.mapping.elements[0]),
- (int (*)(const void *, const void *))sort_from_longer_paths);
-
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key, *value;
- if ((value = convert_path_config_node(cmd, node->data.mapping.elements[i].value)) == NULL)
- return -1;
- h2o_pathconf_t *pathconf = h2o_config_register_path(ctx->hostconf, key->data.scalar, 0);
- int cmd_ret = config_path(ctx, pathconf, value);
- yoml_free(value, NULL);
- if (cmd_ret != 0)
- return cmd_ret;
- }
-
- /* configure fallback path along with ordinary paths */
- return config_path(ctx, &ctx->hostconf->fallback_path, NULL);
-}
-
-static int on_config_hosts(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- size_t i;
-
- if (node->data.mapping.size == 0) {
- h2o_configurator_errprintf(cmd, node, "the mapping cannot be empty");
- return -1;
- }
-
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key;
- yoml_t *value = node->data.mapping.elements[i].value;
- h2o_iovec_t hostname;
- uint16_t port;
- if (key->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, key, "key (representing the hostname) must be a string");
- return -1;
- }
- if (h2o_url_parse_hostport(key->data.scalar, strlen(key->data.scalar), &hostname, &port) == NULL) {
- h2o_configurator_errprintf(cmd, key, "invalid key (must be either `host` or `host:port`)");
- return -1;
- }
- assert(hostname.len != 0);
- if ((hostname.base[0] == '*' && !(hostname.len == 1 || hostname.base[1] == '.')) ||
- memchr(hostname.base + 1, '*', hostname.len - 1) != NULL) {
- h2o_configurator_errprintf(cmd, key, "wildcard (*) can only be used at the start of the hostname");
- return -1;
- }
- h2o_configurator_context_t *host_ctx = create_context(ctx, 0);
- if ((host_ctx->hostconf = h2o_config_register_host(host_ctx->globalconf, hostname, port)) == NULL) {
- h2o_configurator_errprintf(cmd, key, "duplicate host entry");
- destroy_context(host_ctx);
- return -1;
- }
- host_ctx->mimemap = &host_ctx->hostconf->mimemap;
- int cmd_ret = h2o_configurator_apply_commands(host_ctx, value, H2O_CONFIGURATOR_FLAG_HOST, NULL);
- destroy_context(host_ctx);
- if (cmd_ret != 0)
- return -1;
- if (yoml_get(value, "paths") == NULL) {
- h2o_configurator_errprintf(NULL, value, "mandatory configuration directive `paths` is missing");
- return -1;
- }
- }
-
- return 0;
-}
-
-static int on_config_limit_request_body(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- return h2o_configurator_scanf(cmd, node, "%zu", &ctx->globalconf->max_request_entity_size);
-}
-
-static int on_config_max_delegations(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- return h2o_configurator_scanf(cmd, node, "%u", &ctx->globalconf->max_delegations);
-}
-
-static int on_config_handshake_timeout(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- return config_timeout(cmd, node, &ctx->globalconf->handshake_timeout);
-}
-
-static int on_config_http1_request_timeout(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- return config_timeout(cmd, node, &ctx->globalconf->http1.req_timeout);
-}
-
-static int on_config_http1_upgrade_to_http2(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
- if (ret == -1)
- return -1;
- ctx->globalconf->http1.upgrade_to_http2 = (int)ret;
- return 0;
-}
-
-static int on_config_http2_idle_timeout(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- return config_timeout(cmd, node, &ctx->globalconf->http2.idle_timeout);
-}
-
-static int on_config_http2_graceful_shutdown_timeout(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- return config_timeout(cmd, node, &ctx->globalconf->http2.graceful_shutdown_timeout);
-}
-
-static int on_config_http2_max_concurrent_requests_per_connection(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx,
- yoml_t *node)
-{
- return h2o_configurator_scanf(cmd, node, "%zu", &ctx->globalconf->http2.max_concurrent_requests_per_connection);
-}
-
-static int on_config_http2_latency_optimization_min_rtt(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx,
- yoml_t *node)
-{
- return h2o_configurator_scanf(cmd, node, "%u", &ctx->globalconf->http2.latency_optimization.min_rtt);
-}
-
-static int on_config_http2_latency_optimization_max_additional_delay(h2o_configurator_command_t *cmd,
- h2o_configurator_context_t *ctx, yoml_t *node)
-{
- double ratio;
- if (h2o_configurator_scanf(cmd, node, "%lf", &ratio) != 0)
- return -1;
- if (!(0.0 < ratio)) {
- h2o_configurator_errprintf(cmd, node, "ratio must be a positive number");
- return -1;
- }
- ctx->globalconf->http2.latency_optimization.max_additional_delay = 100 * ratio;
- return 0;
-}
-
-static int on_config_http2_latency_optimization_max_cwnd(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx,
- yoml_t *node)
-{
- return h2o_configurator_scanf(cmd, node, "%u", &ctx->globalconf->http2.latency_optimization.max_cwnd);
-}
-
-static int on_config_http2_reprioritize_blocking_assets(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx,
- yoml_t *node)
-{
- struct st_core_configurator_t *self = (void *)cmd->configurator;
- ssize_t on;
-
- if ((on = h2o_configurator_get_one_of(cmd, node, "OFF,ON")) == -1)
- return -1;
- self->vars->http2.reprioritize_blocking_assets = (int)on;
-
- return 0;
-}
-
-static int on_config_http2_push_preload(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_core_configurator_t *self = (void *)cmd->configurator;
- ssize_t on;
-
- if ((on = h2o_configurator_get_one_of(cmd, node, "OFF,ON")) == -1)
- return -1;
- self->vars->http2.push_preload = (int)on;
-
- return 0;
-}
-
-static int on_config_http2_casper(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- static const h2o_casper_conf_t defaults = {
- 13, /* casper_bits: default (2^13 ~= 100 assets * 1/0.01 collision probability) */
- 0 /* track blocking assets only */
- };
-
- struct st_core_configurator_t *self = (void *)cmd->configurator;
-
- switch (node->type) {
- case YOML_TYPE_SCALAR:
- if (strcasecmp(node->data.scalar, "OFF") == 0) {
- self->vars->http2.casper = (h2o_casper_conf_t){0};
- } else if (strcasecmp(node->data.scalar, "ON") == 0) {
- self->vars->http2.casper = defaults;
- }
- break;
- case YOML_TYPE_MAPPING: {
- /* set to default */
- self->vars->http2.casper = defaults;
- /* override the attributes defined */
- yoml_t *t;
- if ((t = yoml_get(node, "capacity-bits")) != NULL) {
- if (!(t->type == YOML_TYPE_SCALAR && sscanf(t->data.scalar, "%u", &self->vars->http2.casper.capacity_bits) == 1 &&
- self->vars->http2.casper.capacity_bits < 16)) {
- h2o_configurator_errprintf(cmd, t, "value of `capacity-bits` must be an integer between 0 to 15");
- return -1;
- }
- }
- if ((t = yoml_get(node, "tracking-types")) != NULL) {
- if (t->type == YOML_TYPE_SCALAR && strcasecmp(t->data.scalar, "blocking-assets") == 0) {
- self->vars->http2.casper.track_all_types = 0;
- } else if (t->type == YOML_TYPE_SCALAR && strcasecmp(t->data.scalar, "all") == 0) {
- self->vars->http2.casper.track_all_types = 1;
- } else {
- h2o_configurator_errprintf(cmd, t, "value of `tracking-types` must be either of: `blocking-assets` or `all`");
- return -1;
- }
- }
- } break;
- default:
- h2o_configurator_errprintf(cmd, node, "value must be `OFF`,`ON` or a mapping containing the necessary attributes");
- return -1;
- }
-
- return 0;
-}
-
-static int assert_is_mimetype(h2o_configurator_command_t *cmd, yoml_t *node)
-{
- if (node->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, node, "expected a scalar (mime-type)");
- return -1;
- }
- if (strchr(node->data.scalar, '/') == NULL) {
- h2o_configurator_errprintf(cmd, node, "the string \"%s\" does not look like a mime-type", node->data.scalar);
- return -1;
- }
- return 0;
-}
-
-static int assert_is_extension(h2o_configurator_command_t *cmd, yoml_t *node)
-{
- if (node->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, node, "expected a scalar (extension)");
- return -1;
- }
- if (node->data.scalar[0] != '.') {
- h2o_configurator_errprintf(cmd, node, "given extension \"%s\" does not start with a \".\"", node->data.scalar);
- return -1;
- }
- return 0;
-}
-
-static int set_mimetypes(h2o_configurator_command_t *cmd, h2o_mimemap_t *mimemap, yoml_t *node)
-{
- size_t i, j;
-
- assert(node->type == YOML_TYPE_MAPPING);
-
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key;
- yoml_t *value = node->data.mapping.elements[i].value;
- if (assert_is_mimetype(cmd, key) != 0)
- return -1;
- switch (value->type) {
- case YOML_TYPE_SCALAR:
- if (assert_is_extension(cmd, value) != 0)
- return -1;
- h2o_mimemap_define_mimetype(mimemap, value->data.scalar + 1, key->data.scalar, NULL);
- break;
- case YOML_TYPE_SEQUENCE:
- for (j = 0; j != value->data.sequence.size; ++j) {
- yoml_t *ext_node = value->data.sequence.elements[j];
- if (assert_is_extension(cmd, ext_node) != 0)
- return -1;
- h2o_mimemap_define_mimetype(mimemap, ext_node->data.scalar + 1, key->data.scalar, NULL);
- }
- break;
- case YOML_TYPE_MAPPING: {
- yoml_t *t;
- h2o_mime_attributes_t attr;
- h2o_mimemap_get_default_attributes(key->data.scalar, &attr);
- if ((t = yoml_get(value, "is_compressible")) != NULL) {
- if (t->type == YOML_TYPE_SCALAR && strcasecmp(t->data.scalar, "YES") == 0) {
- attr.is_compressible = 1;
- } else if (t->type == YOML_TYPE_SCALAR && strcasecmp(t->data.scalar, "NO") == 0) {
- attr.is_compressible = 0;
- } else {
- h2o_configurator_errprintf(cmd, t, "`is_compressible` attribute must be either of: `YES` or `NO`");
- return -1;
- }
- }
- if ((t = yoml_get(value, "priority")) != NULL) {
- if (t->type == YOML_TYPE_SCALAR && strcasecmp(t->data.scalar, "normal") == 0) {
- attr.priority = H2O_MIME_ATTRIBUTE_PRIORITY_NORMAL;
- } else if (t->type == YOML_TYPE_SCALAR && strcasecmp(t->data.scalar, "highest") == 0) {
- attr.priority = H2O_MIME_ATTRIBUTE_PRIORITY_HIGHEST;
- } else {
- h2o_configurator_errprintf(cmd, t, "`priority` attribute must be either of: `normal` or `highest`");
- return -1;
- }
- }
- if ((t = yoml_get(value, "extensions")) == NULL) {
- h2o_configurator_errprintf(cmd, value, "cannot find mandatory attribute `extensions`");
- return -1;
- }
- if (t->type != YOML_TYPE_SEQUENCE) {
- h2o_configurator_errprintf(cmd, t, "`extensions` attribute must be a sequence of scalars");
- return -1;
- }
- for (j = 0; j != t->data.sequence.size; ++j) {
- yoml_t *ext_node = t->data.sequence.elements[j];
- if (assert_is_extension(cmd, ext_node) != 0)
- return -1;
- h2o_mimemap_define_mimetype(mimemap, ext_node->data.scalar + 1, key->data.scalar, &attr);
- }
- } break;
- default:
- fprintf(stderr, "logic flaw at %s:%d\n", __FILE__, __LINE__);
- abort();
- }
- }
-
- return 0;
-}
-
-static int on_config_mime_settypes(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- h2o_mimemap_t *newmap = h2o_mimemap_create();
- h2o_mimemap_clear_types(newmap);
- h2o_mimemap_set_default_type(newmap, h2o_mimemap_get_default_type(*ctx->mimemap)->data.mimetype.base, NULL);
- if (set_mimetypes(cmd, newmap, node) != 0) {
- h2o_mem_release_shared(newmap);
- return -1;
- }
-
- h2o_mem_release_shared(*ctx->mimemap);
- *ctx->mimemap = newmap;
- return 0;
-}
-
-static void clone_mimemap_if_clean(h2o_configurator_context_t *ctx)
-{
- if (ctx->parent == NULL)
- return;
- if (*ctx->mimemap != *ctx->parent->mimemap)
- return;
- h2o_mem_release_shared(*ctx->mimemap);
- /* even after release, ctx->mimemap is still retained by the parent and therefore we can use it as the argument to clone */
- *ctx->mimemap = h2o_mimemap_clone(*ctx->mimemap);
-}
-
-static int on_config_mime_addtypes(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- clone_mimemap_if_clean(ctx);
- return set_mimetypes(cmd, *ctx->mimemap, node);
-}
-
-static int on_config_mime_removetypes(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- size_t i;
-
- clone_mimemap_if_clean(ctx);
- for (i = 0; i != node->data.sequence.size; ++i) {
- yoml_t *ext_node = node->data.sequence.elements[i];
- if (assert_is_extension(cmd, ext_node) != 0)
- return -1;
- h2o_mimemap_remove_type(*ctx->mimemap, ext_node->data.scalar + 1);
- }
-
- return 0;
-}
-
-static int on_config_mime_setdefaulttype(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- if (assert_is_mimetype(cmd, node) != 0)
- return -1;
-
- clone_mimemap_if_clean(ctx);
- h2o_mimemap_set_default_type(*ctx->mimemap, node->data.scalar, NULL);
-
- return 0;
-}
-
-static int on_config_custom_handler(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- static const char *ignore_commands[] = {"extension", NULL};
- yoml_t *ext_node;
- const char **exts;
- h2o_mimemap_type_t *type = NULL;
-
- if (node->type != YOML_TYPE_MAPPING) {
- h2o_configurator_errprintf(cmd, node, "argument must be a MAPPING");
- return -1;
- }
- if ((ext_node = yoml_get(node, "extension")) == NULL) {
- h2o_configurator_errprintf(cmd, node, "mandatory key `extension` is missing");
- return -1;
- }
-
- /* create dynamic type */
- switch (ext_node->type) {
- case YOML_TYPE_SCALAR:
- if (assert_is_extension(cmd, ext_node) != 0)
- return -1;
- exts = alloca(2 * sizeof(*exts));
- exts[0] = ext_node->data.scalar + 1;
- exts[1] = NULL;
- break;
- case YOML_TYPE_SEQUENCE: {
- exts = alloca((ext_node->data.sequence.size + 1) * sizeof(*exts));
- size_t i;
- for (i = 0; i != ext_node->data.sequence.size; ++i) {
- yoml_t *n = ext_node->data.sequence.elements[i];
- if (assert_is_extension(cmd, n) != 0)
- return -1;
- exts[i] = n->data.scalar + 1;
- }
- exts[i] = NULL;
- } break;
- default:
- h2o_configurator_errprintf(cmd, ext_node, "`extensions` must be a scalar or sequence of scalar");
- return -1;
- }
- clone_mimemap_if_clean(ctx);
- type = h2o_mimemap_define_dynamic(*ctx->mimemap, exts, ctx->globalconf);
-
- /* apply the configuration commands */
- h2o_configurator_context_t *ext_ctx = create_context(ctx, 1);
- ext_ctx->pathconf = &type->data.dynamic.pathconf;
- ext_ctx->mimemap = NULL;
- int cmd_ret = h2o_configurator_apply_commands(ext_ctx, node, H2O_CONFIGURATOR_FLAG_EXTENSION, ignore_commands);
- destroy_context(ext_ctx);
- if (cmd_ret != 0)
- return cmd_ret;
- switch (type->data.dynamic.pathconf.handlers.size) {
- case 1:
- break;
- case 0:
- h2o_configurator_errprintf(cmd, node, "no handler declared for given extension");
- return -1;
- default:
- h2o_configurator_errprintf(cmd, node, "cannot assign more than one handler for given extension");
- return -1;
- }
-
- return 0;
-}
-
-static void inherit_env_if_necessary(h2o_configurator_context_t *ctx)
-{
- if (ctx->env == (ctx->parent != NULL ? ctx->parent->env : NULL))
- ctx->env = h2o_config_create_envconf(ctx->env);
-}
-
-static int on_config_setenv(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- size_t i;
-
- inherit_env_if_necessary(ctx);
-
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key, *value = node->data.mapping.elements[i].value;
- if (key->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, key, "key must be a scalar");
- return -1;
- }
- if (value->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, value, "value must be a scalar");
- return -1;
- }
- h2o_config_setenv(ctx->env, key->data.scalar, value->data.scalar);
- }
-
- return 0;
-}
-
-static int on_config_unsetenv(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- inherit_env_if_necessary(ctx);
-
- switch (node->type) {
- case YOML_TYPE_SCALAR:
- h2o_config_unsetenv(ctx->env, node->data.scalar);
- break;
- case YOML_TYPE_SEQUENCE: {
- size_t i;
- for (i = 0; i != node->data.sequence.size; ++i) {
- yoml_t *element = node->data.sequence.elements[i];
- if (element->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, element, "element of a sequence passed to unsetenv must be a scalar");
- return -1;
- }
- h2o_config_unsetenv(ctx->env, element->data.scalar);
- }
- } break;
- default:
- h2o_configurator_errprintf(cmd, node, "argument to unsetenv must be either a scalar or a sequence");
- return -1;
- }
-
- return 0;
-}
-
-static int on_config_server_name(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- ctx->globalconf->server_name = h2o_strdup(NULL, node->data.scalar, SIZE_MAX);
- return 0;
-}
-
-static int on_config_send_server_name(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- switch(h2o_configurator_get_one_of(cmd, node, "OFF,ON,preserve")) {
- case 0: /* off */
- ctx->globalconf->server_name = h2o_iovec_init(H2O_STRLIT(""));
- break;
- case 1: /* on */
- break;
- case 2: /* preserve */
- ctx->globalconf->server_name = h2o_iovec_init(H2O_STRLIT(""));
- ctx->globalconf->proxy.preserve_server_header = 1;
- break;
- default:
- return -1;
- }
- return 0;
-}
-
-static int on_config_error_log_emit_request_errors(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_core_configurator_t *self = (void *)cmd->configurator;
- ssize_t on;
-
- if ((on = h2o_configurator_get_one_of(cmd, node, "OFF,ON")) == -1)
- return -1;
-
- self->vars->error_log.emit_request_errors = (int)on;
- return 0;
-}
-
-void h2o_configurator__init_core(h2o_globalconf_t *conf)
-{
- /* check if already initialized */
- if (h2o_configurator_get_command(conf, "files") != NULL)
- return;
-
- { /* `hosts` and `paths` */
- h2o_configurator_t *c = h2o_configurator_create(conf, sizeof(*c));
- h2o_configurator_define_command(c, "hosts", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING |
- H2O_CONFIGURATOR_FLAG_DEFERRED,
- on_config_hosts);
- h2o_configurator_define_command(c, "paths", H2O_CONFIGURATOR_FLAG_HOST | H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING |
- H2O_CONFIGURATOR_FLAG_DEFERRED,
- on_config_paths);
- };
-
- { /* setup global configurators */
- struct st_core_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
- c->super.enter = on_core_enter;
- c->super.exit = on_core_exit;
- c->vars = c->_vars_stack;
- c->vars->http2.reprioritize_blocking_assets = 1; /* defaults to ON */
- c->vars->http2.push_preload = 1; /* defaults to ON */
- c->vars->error_log.emit_request_errors = 1; /* defaults to ON */
- h2o_configurator_define_command(&c->super, "limit-request-body",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_limit_request_body);
- h2o_configurator_define_command(&c->super, "max-delegations",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_max_delegations);
- h2o_configurator_define_command(&c->super, "handshake-timeout",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_handshake_timeout);
- h2o_configurator_define_command(&c->super, "http1-request-timeout",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http1_request_timeout);
- h2o_configurator_define_command(&c->super, "http1-upgrade-to-http2",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http1_upgrade_to_http2);
- h2o_configurator_define_command(&c->super, "http2-idle-timeout",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_idle_timeout);
- h2o_configurator_define_command(&c->super, "http2-graceful-shutdown-timeout",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_graceful_shutdown_timeout);
- h2o_configurator_define_command(&c->super, "http2-max-concurrent-requests-per-connection",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_max_concurrent_requests_per_connection);
- h2o_configurator_define_command(&c->super, "http2-latency-optimization-min-rtt",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_latency_optimization_min_rtt);
- h2o_configurator_define_command(&c->super, "http2-latency-optimization-max-additional-delay",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_latency_optimization_max_additional_delay);
- h2o_configurator_define_command(&c->super, "http2-latency-optimization-max-cwnd",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_latency_optimization_max_cwnd);
- h2o_configurator_define_command(&c->super, "http2-reprioritize-blocking-assets",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_HOST |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_reprioritize_blocking_assets);
- h2o_configurator_define_command(&c->super, "http2-push-preload", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_HOST |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_push_preload);
- h2o_configurator_define_command(&c->super, "http2-casper", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_HOST,
- on_config_http2_casper);
- h2o_configurator_define_command(&c->super, "file.mime.settypes",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING,
- on_config_mime_settypes);
- h2o_configurator_define_command(&c->super, "file.mime.addtypes",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING,
- on_config_mime_addtypes);
- h2o_configurator_define_command(&c->super, "file.mime.removetypes",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE,
- on_config_mime_removetypes);
- h2o_configurator_define_command(&c->super, "file.mime.setdefaulttype",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_mime_setdefaulttype);
- h2o_configurator_define_command(&c->super, "file.custom-handler",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_SEMI_DEFERRED,
- on_config_custom_handler);
- h2o_configurator_define_command(&c->super, "setenv",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING, on_config_setenv);
- h2o_configurator_define_command(&c->super, "unsetenv", H2O_CONFIGURATOR_FLAG_ALL_LEVELS, on_config_unsetenv);
- h2o_configurator_define_command(&c->super, "server-name",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_server_name);
- h2o_configurator_define_command(&c->super, "send-server-name",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR |
- H2O_CONFIGURATOR_FLAG_DEFERRED,
- on_config_send_server_name);
- h2o_configurator_define_command(&c->super, "error-log.emit-request-errors",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_error_log_emit_request_errors);
- }
-}
-
-void h2o_configurator__dispose_configurators(h2o_globalconf_t *conf)
-{
- while (!h2o_linklist_is_empty(&conf->configurators)) {
- h2o_configurator_t *c = H2O_STRUCT_FROM_MEMBER(h2o_configurator_t, _link, conf->configurators.next);
- h2o_linklist_unlink(&c->_link);
- if (c->dispose != NULL)
- c->dispose(c);
- destroy_configurator(c);
- }
-}
-
-h2o_configurator_t *h2o_configurator_create(h2o_globalconf_t *conf, size_t sz)
-{
- h2o_configurator_t *c;
-
- assert(sz >= sizeof(*c));
-
- c = h2o_mem_alloc(sz);
- memset(c, 0, sz);
- h2o_linklist_insert(&conf->configurators, &c->_link);
-
- return c;
-}
-
-void h2o_configurator_define_command(h2o_configurator_t *configurator, const char *name, int flags, h2o_configurator_command_cb cb)
-{
- h2o_configurator_command_t *cmd;
-
- h2o_vector_reserve(NULL, &configurator->commands, configurator->commands.size + 1);
- cmd = configurator->commands.entries + configurator->commands.size++;
- cmd->configurator = configurator;
- cmd->flags = flags;
- cmd->name = name;
- cmd->cb = cb;
-}
-
-h2o_configurator_command_t *h2o_configurator_get_command(h2o_globalconf_t *conf, const char *name)
-{
- h2o_linklist_t *node;
- size_t i;
-
- for (node = conf->configurators.next; node != &conf->configurators; node = node->next) {
- h2o_configurator_t *configurator = H2O_STRUCT_FROM_MEMBER(h2o_configurator_t, _link, node);
- for (i = 0; i != configurator->commands.size; ++i) {
- h2o_configurator_command_t *cmd = configurator->commands.entries + i;
- if (strcmp(cmd->name, name) == 0) {
- return cmd;
- }
- }
- }
-
- return NULL;
-}
-
-int h2o_configurator_apply(h2o_globalconf_t *config, yoml_t *node, int dry_run)
-{
- h2o_configurator_context_t *ctx = create_context(NULL, 0);
- ctx->globalconf = config;
- ctx->mimemap = &ctx->globalconf->mimemap;
- ctx->dry_run = dry_run;
- int cmd_ret = h2o_configurator_apply_commands(ctx, node, H2O_CONFIGURATOR_FLAG_GLOBAL, NULL);
- destroy_context(ctx);
-
- if (cmd_ret != 0)
- return cmd_ret;
- if (config->hosts[0] == NULL) {
- h2o_configurator_errprintf(NULL, node, "mandatory configuration directive `hosts` is missing");
- return -1;
- }
- return 0;
-}
-
-void h2o_configurator_errprintf(h2o_configurator_command_t *cmd, yoml_t *node, const char *reason, ...)
-{
- va_list args;
-
- fprintf(stderr, "[%s:%zu] ", node->filename ? node->filename : "-", node->line + 1);
- if (cmd != NULL)
- fprintf(stderr, "in command %s, ", cmd->name);
- va_start(args, reason);
- vfprintf(stderr, reason, args);
- va_end(args);
- fputc('\n', stderr);
-}
-
-int h2o_configurator_scanf(h2o_configurator_command_t *cmd, yoml_t *node, const char *fmt, ...)
-{
- va_list args;
- int sscan_ret;
-
- if (node->type != YOML_TYPE_SCALAR)
- goto Error;
- va_start(args, fmt);
- sscan_ret = vsscanf(node->data.scalar, fmt, args);
- va_end(args);
- if (sscan_ret != 1)
- goto Error;
-
- return 0;
-Error:
- h2o_configurator_errprintf(cmd, node, "argument must match the format: %s", fmt);
- return -1;
-}
-
-ssize_t h2o_configurator_get_one_of(h2o_configurator_command_t *cmd, yoml_t *node, const char *candidates)
-{
- const char *config_str, *cand_str;
- ssize_t config_str_len, cand_index;
-
- if (node->type != YOML_TYPE_SCALAR)
- goto Error;
-
- config_str = node->data.scalar;
- config_str_len = strlen(config_str);
-
- cand_str = candidates;
- for (cand_index = 0;; ++cand_index) {
- if (strncasecmp(cand_str, config_str, config_str_len) == 0 &&
- (cand_str[config_str_len] == '\0' || cand_str[config_str_len] == ',')) {
- /* found */
- return cand_index;
- }
- cand_str = strchr(cand_str, ',');
- if (cand_str == NULL)
- goto Error;
- cand_str += 1; /* skip ',' */
- }
-/* not reached */
-
-Error:
- h2o_configurator_errprintf(cmd, node, "argument must be one of: %s", candidates);
- return -1;
-}
-
-char *h2o_configurator_get_cmd_path(const char *cmd)
-{
- char *root, *cmd_fullpath;
-
- /* just return the cmd (being strdup'ed) in case we do not need to prefix the value */
- if (cmd[0] == '/' || strchr(cmd, '/') == NULL)
- goto ReturnOrig;
-
- /* obtain root */
- if ((root = getenv("H2O_ROOT")) == NULL) {
- root = H2O_TO_STR(H2O_ROOT);
- }
-
- /* build full-path and return */
- cmd_fullpath = h2o_mem_alloc(strlen(root) + strlen(cmd) + 2);
- sprintf(cmd_fullpath, "%s/%s", root, cmd);
- return cmd_fullpath;
-
-ReturnOrig:
- return h2o_strdup(NULL, cmd, SIZE_MAX).base;
-}
diff --git a/web/server/h2o/libh2o/lib/core/context.c b/web/server/h2o/libh2o/lib/core/context.c
deleted file mode 100644
index 8d1101381..000000000
--- a/web/server/h2o/libh2o/lib/core/context.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 2014 DeNA Co., Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <stddef.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include "h2o.h"
-#include "h2o/memcached.h"
-
-void h2o_context_init_pathconf_context(h2o_context_t *ctx, h2o_pathconf_t *pathconf)
-{
- /* add pathconf to the inited list (or return if already inited) */
- size_t i;
- for (i = 0; i != ctx->_pathconfs_inited.size; ++i)
- if (ctx->_pathconfs_inited.entries[i] == pathconf)
- return;
- h2o_vector_reserve(NULL, &ctx->_pathconfs_inited, ctx->_pathconfs_inited.size + 1);
- ctx->_pathconfs_inited.entries[ctx->_pathconfs_inited.size++] = pathconf;
-
-#define DOIT(type, list) \
- do { \
- size_t i; \
- for (i = 0; i != pathconf->list.size; ++i) { \
- type *o = pathconf->list.entries[i]; \
- if (o->on_context_init != NULL) \
- o->on_context_init(o, ctx); \
- } \
- } while (0)
-
- DOIT(h2o_handler_t, handlers);
- DOIT(h2o_filter_t, filters);
- DOIT(h2o_logger_t, loggers);
-
-#undef DOIT
-}
-
-void h2o_context_dispose_pathconf_context(h2o_context_t *ctx, h2o_pathconf_t *pathconf)
-{
- /* nullify pathconf in the inited list (or return if already disposed) */
- size_t i;
- for (i = 0; i != ctx->_pathconfs_inited.size; ++i)
- if (ctx->_pathconfs_inited.entries[i] == pathconf)
- break;
- if (i == ctx->_pathconfs_inited.size)
- return;
- ctx->_pathconfs_inited.entries[i] = NULL;
-
-#define DOIT(type, list) \
- do { \
- size_t i; \
- for (i = 0; i != pathconf->list.size; ++i) { \
- type *o = pathconf->list.entries[i]; \
- if (o->on_context_dispose != NULL) \
- o->on_context_dispose(o, ctx); \
- } \
- } while (0)
-
- DOIT(h2o_handler_t, handlers);
- DOIT(h2o_filter_t, filters);
- DOIT(h2o_logger_t, loggers);
-
-#undef DOIT
-}
-
-void h2o_context_init(h2o_context_t *ctx, h2o_loop_t *loop, h2o_globalconf_t *config)
-{
- size_t i, j;
-
- assert(config->hosts[0] != NULL);
-
- memset(ctx, 0, sizeof(*ctx));
- ctx->loop = loop;
- ctx->globalconf = config;
- h2o_timeout_init(ctx->loop, &ctx->zero_timeout, 0);
- h2o_timeout_init(ctx->loop, &ctx->one_sec_timeout, 1000);
- h2o_timeout_init(ctx->loop, &ctx->hundred_ms_timeout, 100);
- ctx->queue = h2o_multithread_create_queue(loop);
- h2o_multithread_register_receiver(ctx->queue, &ctx->receivers.hostinfo_getaddr, h2o_hostinfo_getaddr_receiver);
- ctx->filecache = h2o_filecache_create(config->filecache.capacity);
-
- h2o_timeout_init(ctx->loop, &ctx->handshake_timeout, config->handshake_timeout);
- h2o_timeout_init(ctx->loop, &ctx->http1.req_timeout, config->http1.req_timeout);
- h2o_linklist_init_anchor(&ctx->http1._conns);
- h2o_timeout_init(ctx->loop, &ctx->http2.idle_timeout, config->http2.idle_timeout);
- h2o_timeout_init(ctx->loop, &ctx->http2.graceful_shutdown_timeout, config->http2.graceful_shutdown_timeout);
- h2o_linklist_init_anchor(&ctx->http2._conns);
- ctx->proxy.client_ctx.loop = loop;
- h2o_timeout_init(ctx->loop, &ctx->proxy.io_timeout, config->proxy.io_timeout);
- ctx->proxy.client_ctx.getaddr_receiver = &ctx->receivers.hostinfo_getaddr;
- ctx->proxy.client_ctx.io_timeout = &ctx->proxy.io_timeout;
- ctx->proxy.client_ctx.ssl_ctx = config->proxy.ssl_ctx;
-
- ctx->_module_configs = h2o_mem_alloc(sizeof(*ctx->_module_configs) * config->_num_config_slots);
- memset(ctx->_module_configs, 0, sizeof(*ctx->_module_configs) * config->_num_config_slots);
-
- static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- pthread_mutex_lock(&mutex);
- for (i = 0; config->hosts[i] != NULL; ++i) {
- h2o_hostconf_t *hostconf = config->hosts[i];
- for (j = 0; j != hostconf->paths.size; ++j) {
- h2o_pathconf_t *pathconf = hostconf->paths.entries + j;
- h2o_context_init_pathconf_context(ctx, pathconf);
- }
- h2o_context_init_pathconf_context(ctx, &hostconf->fallback_path);
- }
- pthread_mutex_unlock(&mutex);
-}
-
-void h2o_context_dispose(h2o_context_t *ctx)
-{
- h2o_globalconf_t *config = ctx->globalconf;
- size_t i, j;
-
- for (i = 0; config->hosts[i] != NULL; ++i) {
- h2o_hostconf_t *hostconf = config->hosts[i];
- for (j = 0; j != hostconf->paths.size; ++j) {
- h2o_pathconf_t *pathconf = hostconf->paths.entries + j;
- h2o_context_dispose_pathconf_context(ctx, pathconf);
- }
- h2o_context_dispose_pathconf_context(ctx, &hostconf->fallback_path);
- }
- free(ctx->_pathconfs_inited.entries);
- free(ctx->_module_configs);
- h2o_timeout_dispose(ctx->loop, &ctx->zero_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->one_sec_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->hundred_ms_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->handshake_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->http1.req_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->http2.idle_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->http2.graceful_shutdown_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->proxy.io_timeout);
- /* what should we do here? assert(!h2o_linklist_is_empty(&ctx->http2._conns); */
-
- h2o_filecache_destroy(ctx->filecache);
- ctx->filecache = NULL;
-
- /* clear storage */
- for (i = 0; i != ctx->storage.size; ++i) {
- h2o_context_storage_item_t *item = ctx->storage.entries + i;
- if (item->dispose != NULL) {
- item->dispose(item->data);
- }
- }
- free(ctx->storage.entries);
-
- /* TODO assert that the all the getaddrinfo threads are idle */
- h2o_multithread_unregister_receiver(ctx->queue, &ctx->receivers.hostinfo_getaddr);
- h2o_multithread_destroy_queue(ctx->queue);
-
- if (ctx->_timestamp_cache.value != NULL)
- h2o_mem_release_shared(ctx->_timestamp_cache.value);
-
-#if H2O_USE_LIBUV
- /* make sure the handles released by h2o_timeout_dispose get freed */
- uv_run(ctx->loop, UV_RUN_NOWAIT);
-#endif
-}
-
-void h2o_context_request_shutdown(h2o_context_t *ctx)
-{
- ctx->shutdown_requested = 1;
- if (ctx->globalconf->http1.callbacks.request_shutdown != NULL)
- ctx->globalconf->http1.callbacks.request_shutdown(ctx);
- if (ctx->globalconf->http2.callbacks.request_shutdown != NULL)
- ctx->globalconf->http2.callbacks.request_shutdown(ctx);
-}
-
-void h2o_context_update_timestamp_cache(h2o_context_t *ctx)
-{
- time_t prev_sec = ctx->_timestamp_cache.tv_at.tv_sec;
- ctx->_timestamp_cache.uv_now_at = h2o_now(ctx->loop);
- gettimeofday(&ctx->_timestamp_cache.tv_at, NULL);
- if (ctx->_timestamp_cache.tv_at.tv_sec != prev_sec) {
- struct tm gmt;
- /* update the string cache */
- if (ctx->_timestamp_cache.value != NULL)
- h2o_mem_release_shared(ctx->_timestamp_cache.value);
- ctx->_timestamp_cache.value = h2o_mem_alloc_shared(NULL, sizeof(h2o_timestamp_string_t), NULL);
- gmtime_r(&ctx->_timestamp_cache.tv_at.tv_sec, &gmt);
- h2o_time2str_rfc1123(ctx->_timestamp_cache.value->rfc1123, &gmt);
- h2o_time2str_log(ctx->_timestamp_cache.value->log, ctx->_timestamp_cache.tv_at.tv_sec);
- }
-}
diff --git a/web/server/h2o/libh2o/lib/core/headers.c b/web/server/h2o/libh2o/lib/core/headers.c
deleted file mode 100644
index d31183623..000000000
--- a/web/server/h2o/libh2o/lib/core/headers.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2014 DeNA Co., Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <stddef.h>
-#include <stdio.h>
-#include "h2o.h"
-
-static void add_header(h2o_mem_pool_t *pool, h2o_headers_t *headers, h2o_iovec_t *name, const char *orig_name, const char *value,
- size_t value_len)
-{
- h2o_header_t *slot;
-
- h2o_vector_reserve(pool, headers, headers->size + 1);
- slot = headers->entries + headers->size++;
-
- slot->name = name;
- slot->value.base = (char *)value;
- slot->value.len = value_len;
- slot->orig_name = orig_name ? h2o_strdup(pool, orig_name, name->len).base : NULL;
-}
-
-ssize_t h2o_find_header(const h2o_headers_t *headers, const h2o_token_t *token, ssize_t cursor)
-{
- for (++cursor; cursor < headers->size; ++cursor) {
- if (headers->entries[cursor].name == &token->buf) {
- return cursor;
- }
- }
- return -1;
-}
-
-ssize_t h2o_find_header_by_str(const h2o_headers_t *headers, const char *name, size_t name_len, ssize_t cursor)
-{
- for (++cursor; cursor < headers->size; ++cursor) {
- h2o_header_t *t = headers->entries + cursor;
- if (h2o_memis(t->name->base, t->name->len, name, name_len)) {
- return cursor;
- }
- }
- return -1;
-}
-
-void h2o_add_header(h2o_mem_pool_t *pool, h2o_headers_t *headers, const h2o_token_t *token, const char *orig_name,
- const char *value, size_t value_len)
-{
- add_header(pool, headers, (h2o_iovec_t *)&token->buf, orig_name, value, value_len);
-}
-
-void h2o_add_header_by_str(h2o_mem_pool_t *pool, h2o_headers_t *headers, const char *name, size_t name_len, int maybe_token,
- const char *orig_name, const char *value, size_t value_len)
-{
- h2o_iovec_t *name_buf;
-
- if (maybe_token) {
- const h2o_token_t *token = h2o_lookup_token(name, name_len);
- if (token != NULL) {
- add_header(pool, headers, (h2o_iovec_t *)token, orig_name, value, value_len);
- return;
- }
- }
- name_buf = h2o_mem_alloc_pool(pool, sizeof(h2o_iovec_t));
- name_buf->base = (char *)name;
- name_buf->len = name_len;
- add_header(pool, headers, name_buf, orig_name, value, value_len);
-}
-
-void h2o_set_header(h2o_mem_pool_t *pool, h2o_headers_t *headers, const h2o_token_t *token, const char *value, size_t value_len,
- int overwrite_if_exists)
-{
- ssize_t cursor = h2o_find_header(headers, token, -1);
- if (cursor != -1) {
- if (overwrite_if_exists) {
- h2o_iovec_t *slot = &headers->entries[cursor].value;
- slot->base = (char *)value;
- slot->len = value_len;
- }
- } else {
- h2o_add_header(pool, headers, token, NULL, value, value_len);
- }
-}
-
-void h2o_set_header_by_str(h2o_mem_pool_t *pool, h2o_headers_t *headers, const char *name, size_t name_len, int maybe_token,
- const char *value, size_t value_len, int overwrite_if_exists)
-{
- ssize_t cursor;
-
- if (maybe_token) {
- const h2o_token_t *token = h2o_lookup_token(name, name_len);
- if (token != NULL) {
- h2o_set_header(pool, headers, token, value, value_len, overwrite_if_exists);
- return;
- }
- }
-
- cursor = h2o_find_header_by_str(headers, name, name_len, -1);
- if (cursor != -1) {
- if (overwrite_if_exists) {
- h2o_iovec_t *slot = &headers->entries[cursor].value;
- slot->base = (char *)value;
- slot->len = value_len;
- }
- } else {
- h2o_iovec_t *name_buf = h2o_mem_alloc_pool(pool, sizeof(h2o_iovec_t));
- name_buf->base = (char *)name;
- name_buf->len = name_len;
- add_header(pool, headers, name_buf, NULL, value, value_len);
- }
-}
-
-void h2o_set_header_token(h2o_mem_pool_t *pool, h2o_headers_t *headers, const h2o_token_t *token, const char *value,
- size_t value_len)
-{
- h2o_header_t *dest = NULL;
- size_t i;
- for (i = 0; i != headers->size; ++i) {
- if (headers->entries[i].name == &token->buf) {
- if (h2o_contains_token(headers->entries[i].value.base, headers->entries[i].value.len, value, value_len, ','))
- return;
- dest = headers->entries + i;
- }
- }
- if (dest != NULL) {
- dest->value = h2o_concat(pool, dest->value, h2o_iovec_init(H2O_STRLIT(", ")), h2o_iovec_init(value, value_len));
- } else {
- h2o_add_header(pool, headers, token, NULL, value, value_len);
- }
-}
-
-ssize_t h2o_delete_header(h2o_headers_t *headers, ssize_t cursor)
-{
- assert(cursor != -1);
-
- --headers->size;
- memmove(headers->entries + cursor, headers->entries + cursor + 1, sizeof(h2o_header_t) * (headers->size - cursor));
-
- return cursor;
-}
diff --git a/web/server/h2o/libh2o/lib/core/logconf.c b/web/server/h2o/libh2o/lib/core/logconf.c
deleted file mode 100644
index 4d79736cc..000000000
--- a/web/server/h2o/libh2o/lib/core/logconf.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "h2o.h"
-
-enum {
- ELEMENT_TYPE_EMPTY, /* empty element (with suffix only) */
- ELEMENT_TYPE_LOCAL_ADDR, /* %A */
- ELEMENT_TYPE_BYTES_SENT, /* %b */
- ELEMENT_TYPE_PROTOCOL, /* %H */
- ELEMENT_TYPE_REMOTE_ADDR, /* %h */
- ELEMENT_TYPE_LOGNAME, /* %l */
- ELEMENT_TYPE_METHOD, /* %m */
- ELEMENT_TYPE_LOCAL_PORT, /* %p, %{local}p */
- ELEMENT_TYPE_REMOTE_PORT, /* %{remote}p */
- ELEMENT_TYPE_ENV_VAR, /* %{..}e */
- ELEMENT_TYPE_QUERY, /* %q */
- ELEMENT_TYPE_REQUEST_LINE, /* %r */
- ELEMENT_TYPE_STATUS, /* %s */
- ELEMENT_TYPE_TIMESTAMP, /* %t */
- ELEMENT_TYPE_TIMESTAMP_STRFTIME, /* %{...}t */
- ELEMENT_TYPE_TIMESTAMP_SEC_SINCE_EPOCH, /* %{sec}t */
- ELEMENT_TYPE_TIMESTAMP_MSEC_SINCE_EPOCH, /* %{msec}t */
- ELEMENT_TYPE_TIMESTAMP_USEC_SINCE_EPOCH, /* %{usec}t */
- ELEMENT_TYPE_TIMESTAMP_MSEC_FRAC, /* %{msec_frac}t */
- ELEMENT_TYPE_TIMESTAMP_USEC_FRAC, /* %{usec_frac}t */
- ELEMENT_TYPE_URL_PATH, /* %U */
- ELEMENT_TYPE_REMOTE_USER, /* %u */
- ELEMENT_TYPE_AUTHORITY, /* %V */
- ELEMENT_TYPE_HOSTCONF, /* %v */
- ELEMENT_TYPE_IN_HEADER_TOKEN, /* %{data.header_token}i */
- ELEMENT_TYPE_IN_HEADER_STRING, /* %{data.name}i */
- ELEMENT_TYPE_OUT_HEADER_TOKEN, /* %{data.header_token}o */
- ELEMENT_TYPE_OUT_HEADER_STRING, /* %{data.name}o */
- ELEMENT_TYPE_OUT_HEADER_TOKEN_CONCATENATED, /* %{data.header_token}o */
- ELEMENT_TYPE_EXTENDED_VAR, /* %{data.name}x */
- ELEMENT_TYPE_CONNECTION_ID, /* %{connection-id}x */
- ELEMENT_TYPE_CONNECT_TIME, /* %{connect-time}x */
- ELEMENT_TYPE_REQUEST_HEADER_TIME, /* %{request-header-time}x */
- ELEMENT_TYPE_REQUEST_BODY_TIME, /* %{request-body-time}x */
- ELEMENT_TYPE_REQUEST_TOTAL_TIME, /* %{request-total-time}x */
- ELEMENT_TYPE_PROCESS_TIME, /* %{process-time}x */
- ELEMENT_TYPE_RESPONSE_TIME, /* %{response-total-time}x */
- ELEMENT_TYPE_DURATION, /* %{duration}x */
- ELEMENT_TYPE_ERROR, /* %{error}x */
- ELEMENT_TYPE_PROTOCOL_SPECIFIC, /* %{protocol-specific...}x */
- NUM_ELEMENT_TYPES
-};
-
-struct log_element_t {
- unsigned type;
- h2o_iovec_t suffix;
- union {
- const h2o_token_t *header_token;
- h2o_iovec_t name;
- size_t protocol_specific_callback_index;
- } data;
- unsigned magically_quoted_json : 1; /* whether to omit surrounding doublequotes when the output is null */
- unsigned original_response : 1;
-};
-
-struct st_h2o_logconf_t {
- H2O_VECTOR(struct log_element_t) elements;
- int escape;
-};
-
-static h2o_iovec_t strdup_lowercased(const char *s, size_t len)
-{
- h2o_iovec_t v = h2o_strdup(NULL, s, len);
- h2o_strtolower(v.base, v.len);
- return v;
-}
-
-static int determine_magicquote_nodes(h2o_logconf_t *logconf, char *errbuf)
-{
- size_t element_index;
- int quote_char = '\0'; /* the quote char being used if the state machine is within a string literal */
- int just_in = 0; /* if we just went into the string literal */
-
- for (element_index = 0; element_index < logconf->elements.size; ++element_index) {
- h2o_iovec_t suffix = logconf->elements.entries[element_index].suffix;
- logconf->elements.entries[element_index].magically_quoted_json = just_in && suffix.len != 0 && suffix.base[0] == quote_char;
-
- just_in = 0;
-
- size_t i;
- for (i = 0; i < suffix.len; ++i) {
- just_in = 0;
- if (quote_char != '\0') {
- if (quote_char == suffix.base[i]) {
- /* out of quote? */
- size_t j, num_bs = 0;
- for (j = i; j != 0; ++num_bs)
- if (suffix.base[--j] != '\\')
- break;
- if (num_bs % 2 == 0)
- quote_char = '\0';
- }
- } else {
- if (suffix.base[i] == '"' || suffix.base[i] == '\'') {
- quote_char = suffix.base[i];
- just_in = 1;
- }
- }
- }
- }
-
- return 1;
-}
-
-h2o_logconf_t *h2o_logconf_compile(const char *fmt, int escape, char *errbuf)
-{
- h2o_logconf_t *logconf = h2o_mem_alloc(sizeof(*logconf));
- const char *pt = fmt;
- size_t fmt_len = strlen(fmt);
-
- *logconf = (h2o_logconf_t){{NULL}, escape};
-
-#define LAST_ELEMENT() (logconf->elements.entries + logconf->elements.size - 1)
-/* suffix buffer is always guaranteed to be larger than the fmt + (sizeof('\n') - 1) (so that they would be no buffer overruns) */
-#define NEW_ELEMENT(ty) \
- do { \
- h2o_vector_reserve(NULL, &logconf->elements, logconf->elements.size + 1); \
- logconf->elements.size++; \
- *LAST_ELEMENT() = (struct log_element_t){0}; \
- LAST_ELEMENT()->type = ty; \
- LAST_ELEMENT()->suffix.base = h2o_mem_alloc(fmt_len + 1); \
- } while (0)
-
- while (*pt != '\0') {
- if (memcmp(pt, "%%", 2) == 0) {
- ++pt; /* emit % */
- } else if (*pt == '%') {
- ++pt;
- /* handle < and > */
- int log_original = 0;
- for (;; ++pt) {
- if (*pt == '<') {
- log_original = 1;
- } else if (*pt == '>') {
- log_original = 0;
- } else {
- break;
- }
- }
- /* handle {...}n */
- if (*pt == '{') {
- const h2o_token_t *token;
- const char *quote_end = strchr(++pt, '}');
- if (quote_end == NULL) {
- sprintf(errbuf, "failed to compile log format: unterminated header name starting at: \"%16s\"", pt);
- goto Error;
- }
- const char modifier = quote_end[1];
- switch (modifier) {
- case 'i':
- case 'o': {
- h2o_iovec_t name = strdup_lowercased(pt, quote_end - pt);
- token = h2o_lookup_token(name.base, name.len);
- if (token != NULL) {
- free(name.base);
- if (modifier == 'o' && token == H2O_TOKEN_SET_COOKIE) {
- NEW_ELEMENT(ELEMENT_TYPE_OUT_HEADER_TOKEN_CONCATENATED);
- LAST_ELEMENT()->data.header_token = token;
- } else {
- NEW_ELEMENT(modifier == 'i' ? ELEMENT_TYPE_IN_HEADER_TOKEN : ELEMENT_TYPE_OUT_HEADER_TOKEN);
- LAST_ELEMENT()->data.header_token = token;
- }
- } else {
- NEW_ELEMENT(modifier == 'i' ? ELEMENT_TYPE_IN_HEADER_STRING : ELEMENT_TYPE_OUT_HEADER_STRING);
- LAST_ELEMENT()->data.name = name;
- }
- LAST_ELEMENT()->original_response = log_original;
- } break;
- case 'p':
- if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("local"))) {
- NEW_ELEMENT(ELEMENT_TYPE_LOCAL_PORT);
- } else if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("remote"))) {
- NEW_ELEMENT(ELEMENT_TYPE_REMOTE_PORT);
- } else {
- sprintf(errbuf, "failed to compile log format: unknown specifier for %%{...}p");
- goto Error;
- }
- break;
- case 'e':
- {
- h2o_iovec_t name = h2o_strdup(NULL, pt, quote_end - pt);
- NEW_ELEMENT(ELEMENT_TYPE_ENV_VAR);
- LAST_ELEMENT()->data.name = name;
- }
- break;
- case 't':
- if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("sec"))) {
- NEW_ELEMENT(ELEMENT_TYPE_TIMESTAMP_SEC_SINCE_EPOCH);
- } else if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("msec"))) {
- NEW_ELEMENT(ELEMENT_TYPE_TIMESTAMP_MSEC_SINCE_EPOCH);
- } else if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("usec"))) {
- NEW_ELEMENT(ELEMENT_TYPE_TIMESTAMP_USEC_SINCE_EPOCH);
- } else if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("msec_frac"))) {
- NEW_ELEMENT(ELEMENT_TYPE_TIMESTAMP_MSEC_FRAC);
- } else if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("usec_frac"))) {
- NEW_ELEMENT(ELEMENT_TYPE_TIMESTAMP_USEC_FRAC);
- } else {
- h2o_iovec_t name = h2o_strdup(NULL, pt, quote_end - pt);
- NEW_ELEMENT(ELEMENT_TYPE_TIMESTAMP_STRFTIME);
- LAST_ELEMENT()->data.name = name;
- }
- break;
- case 'x':
-#define MAP_EXT_TO_TYPE(name, id) \
- if (h2o_lcstris(pt, quote_end - pt, H2O_STRLIT(name))) { \
- NEW_ELEMENT(id); \
- goto MAP_EXT_Found; \
- }
-#define MAP_EXT_TO_PROTO(name, cb) \
- if (h2o_lcstris(pt, quote_end - pt, H2O_STRLIT(name))) { \
- h2o_conn_callbacks_t dummy_; \
- NEW_ELEMENT(ELEMENT_TYPE_PROTOCOL_SPECIFIC); \
- LAST_ELEMENT()->data.protocol_specific_callback_index = \
- &dummy_.log_.cb - dummy_.log_.callbacks; \
- goto MAP_EXT_Found; \
- }
- MAP_EXT_TO_TYPE("connection-id", ELEMENT_TYPE_CONNECTION_ID);
- MAP_EXT_TO_TYPE("connect-time", ELEMENT_TYPE_CONNECT_TIME);
- MAP_EXT_TO_TYPE("request-total-time", ELEMENT_TYPE_REQUEST_TOTAL_TIME);
- MAP_EXT_TO_TYPE("request-header-time", ELEMENT_TYPE_REQUEST_HEADER_TIME);
- MAP_EXT_TO_TYPE("request-body-time", ELEMENT_TYPE_REQUEST_BODY_TIME);
- MAP_EXT_TO_TYPE("process-time", ELEMENT_TYPE_PROCESS_TIME);
- MAP_EXT_TO_TYPE("response-time", ELEMENT_TYPE_RESPONSE_TIME);
- MAP_EXT_TO_TYPE("duration", ELEMENT_TYPE_DURATION);
- MAP_EXT_TO_TYPE("error", ELEMENT_TYPE_ERROR);
- MAP_EXT_TO_PROTO("http1.request-index", http1.request_index);
- MAP_EXT_TO_PROTO("http2.stream-id", http2.stream_id);
- MAP_EXT_TO_PROTO("http2.priority.received", http2.priority_received);
- MAP_EXT_TO_PROTO("http2.priority.received.exclusive", http2.priority_received_exclusive);
- MAP_EXT_TO_PROTO("http2.priority.received.parent", http2.priority_received_parent);
- MAP_EXT_TO_PROTO("http2.priority.received.weight", http2.priority_received_weight);
- MAP_EXT_TO_PROTO("http2.priority.actual", http2.priority_actual);
- MAP_EXT_TO_PROTO("http2.priority.actual.parent", http2.priority_actual_parent);
- MAP_EXT_TO_PROTO("http2.priority.actual.weight", http2.priority_actual_weight);
- MAP_EXT_TO_PROTO("ssl.protocol-version", ssl.protocol_version);
- MAP_EXT_TO_PROTO("ssl.session-reused", ssl.session_reused);
- MAP_EXT_TO_PROTO("ssl.cipher", ssl.cipher);
- MAP_EXT_TO_PROTO("ssl.cipher-bits", ssl.cipher_bits);
- MAP_EXT_TO_PROTO("ssl.session-id", ssl.session_id);
- { /* not found */
- h2o_iovec_t name = strdup_lowercased(pt, quote_end - pt);
- NEW_ELEMENT(ELEMENT_TYPE_EXTENDED_VAR);
- LAST_ELEMENT()->data.name = name;
- }
- MAP_EXT_Found:
-#undef MAP_EXT_TO_TYPE
-#undef MAP_EXT_TO_PROTO
- break;
- default:
- sprintf(errbuf, "failed to compile log format: header name is not followed by either `i`, `o`, `x`, `e`");
- goto Error;
- }
- pt = quote_end + 2;
- continue;
- } else {
- unsigned type = NUM_ELEMENT_TYPES;
- switch (*pt++) {
-#define TYPE_MAP(ch, ty) \
- case ch: \
- type = ty; \
- break
- TYPE_MAP('A', ELEMENT_TYPE_LOCAL_ADDR);
- TYPE_MAP('b', ELEMENT_TYPE_BYTES_SENT);
- TYPE_MAP('H', ELEMENT_TYPE_PROTOCOL);
- TYPE_MAP('h', ELEMENT_TYPE_REMOTE_ADDR);
- TYPE_MAP('l', ELEMENT_TYPE_LOGNAME);
- TYPE_MAP('m', ELEMENT_TYPE_METHOD);
- TYPE_MAP('p', ELEMENT_TYPE_LOCAL_PORT);
- TYPE_MAP('e', ELEMENT_TYPE_ENV_VAR);
- TYPE_MAP('q', ELEMENT_TYPE_QUERY);
- TYPE_MAP('r', ELEMENT_TYPE_REQUEST_LINE);
- TYPE_MAP('s', ELEMENT_TYPE_STATUS);
- TYPE_MAP('t', ELEMENT_TYPE_TIMESTAMP);
- TYPE_MAP('U', ELEMENT_TYPE_URL_PATH);
- TYPE_MAP('u', ELEMENT_TYPE_REMOTE_USER);
- TYPE_MAP('V', ELEMENT_TYPE_AUTHORITY);
- TYPE_MAP('v', ELEMENT_TYPE_HOSTCONF);
-#undef TYPE_MAP
- default:
- sprintf(errbuf, "failed to compile log format: unknown escape sequence: %%%c", pt[-1]);
- goto Error;
- }
- NEW_ELEMENT(type);
- LAST_ELEMENT()->original_response = log_original;
- continue;
- }
- }
- /* emit current char */
- if (logconf->elements.size == 0)
- NEW_ELEMENT(ELEMENT_TYPE_EMPTY);
- LAST_ELEMENT()->suffix.base[LAST_ELEMENT()->suffix.len++] = *pt++;
- }
-
- /* emit end-of-line */
- if (logconf->elements.size == 0)
- NEW_ELEMENT(ELEMENT_TYPE_EMPTY);
- LAST_ELEMENT()->suffix.base[LAST_ELEMENT()->suffix.len++] = '\n';
-
-#undef NEW_ELEMENT
-#undef LAST_ELEMENT
-
- if (escape == H2O_LOGCONF_ESCAPE_JSON) {
- if (!determine_magicquote_nodes(logconf, errbuf))
- goto Error;
- }
-
- return logconf;
-
-Error:
- h2o_logconf_dispose(logconf);
- return NULL;
-}
-
-void h2o_logconf_dispose(h2o_logconf_t *logconf)
-{
- size_t i;
-
- for (i = 0; i != logconf->elements.size; ++i) {
- free(logconf->elements.entries[i].suffix.base);
- switch (logconf->elements.entries[i].type) {
- case ELEMENT_TYPE_EXTENDED_VAR:
- case ELEMENT_TYPE_IN_HEADER_STRING:
- case ELEMENT_TYPE_OUT_HEADER_STRING:
- case ELEMENT_TYPE_TIMESTAMP_STRFTIME:
- free(logconf->elements.entries[i].data.name.base);
- break;
- default:
- break;
- }
- }
- free(logconf->elements.entries);
- free(logconf);
-}
-
-static inline char *append_safe_string(char *pos, const char *src, size_t len)
-{
- memcpy(pos, src, len);
- return pos + len;
-}
-
-static char *append_unsafe_string_apache(char *pos, const char *src, size_t len)
-{
- const char *src_end = src + len;
-
- for (; src != src_end; ++src) {
- if (' ' <= *src && *src < 0x7d && *src != '"') {
- *pos++ = *src;
- } else {
- *pos++ = '\\';
- *pos++ = 'x';
- *pos++ = ("0123456789abcdef")[(*src >> 4) & 0xf];
- *pos++ = ("0123456789abcdef")[*src & 0xf];
- }
- }
-
- return pos;
-}
-
-static char *append_unsafe_string_json(char *pos, const char *src, size_t len)
-{
- const char *src_end = src + len;
-
- for (; src != src_end; ++src) {
- if (' ' <= *src && *src < 0x7e) {
- if (*src == '"' || *src == '\\')
- *pos++ = '\\';
- *pos++ = *src;
- } else {
- *pos++ = '\\';
- *pos++ = 'u';
- *pos++ = '0';
- *pos++ = '0';
- *pos++ = ("0123456789abcdef")[(*src >> 4) & 0xf];
- *pos++ = ("0123456789abcdef")[*src & 0xf];
- }
- }
-
- return pos;
-}
-
-static char *append_addr(char *pos, socklen_t (*cb)(h2o_conn_t *conn, struct sockaddr *sa), h2o_conn_t *conn, h2o_iovec_t nullexpr)
-{
- struct sockaddr_storage ss;
- socklen_t sslen;
-
- if ((sslen = cb(conn, (void *)&ss)) == 0)
- goto Fail;
- size_t l = h2o_socket_getnumerichost((void *)&ss, sslen, pos);
- if (l == SIZE_MAX)
- goto Fail;
- pos += l;
- return pos;
-
-Fail:
- memcpy(pos, nullexpr.base, nullexpr.len);
- pos += nullexpr.len;
- return pos;
-}
-
-static char *append_port(char *pos, socklen_t (*cb)(h2o_conn_t *conn, struct sockaddr *sa), h2o_conn_t *conn, h2o_iovec_t nullexpr)
-{
- struct sockaddr_storage ss;
- socklen_t sslen;
-
- if ((sslen = cb(conn, (void *)&ss)) == 0)
- goto Fail;
- int32_t port = h2o_socket_getport((void *)&ss);
- if (port == -1)
- goto Fail;
- pos += sprintf(pos, "%" PRIu16, (uint16_t)port);
- return pos;
-
-Fail:
- memcpy(pos, nullexpr.base, nullexpr.len);
- pos += nullexpr.len;
- return pos;
-}
-
-#define APPEND_DURATION(pos, name) \
- do { \
- int64_t delta_usec; \
- if (!h2o_time_compute_##name(req, &delta_usec)) \
- goto EmitNull; \
- int32_t delta_sec = (int32_t)(delta_usec / (1000 * 1000)); \
- delta_usec -= ((int64_t)delta_sec * (1000 * 1000)); \
- RESERVE(sizeof(H2O_INT32_LONGEST_STR ".999999") - 1); \
- pos += sprintf(pos, "%" PRId32, delta_sec); \
- if (delta_usec != 0) { \
- int i; \
- *pos++ = '.'; \
- for (i = 5; i >= 0; --i) { \
- pos[i] = '0' + delta_usec % 10; \
- delta_usec /= 10; \
- } \
- pos += 6; \
- } \
- } while (0);
-
-static char *expand_line_buf(char *line, size_t *cur_size, size_t required, int should_realloc)
-{
- size_t new_size = *cur_size;
-
- /* determine the new size */
- do {
- new_size *= 2;
- } while (new_size < required);
-
- /* reallocate */
- if (!should_realloc) {
- char *newpt = h2o_mem_alloc(new_size);
- memcpy(newpt, line, *cur_size);
- line = newpt;
- } else {
- line = h2o_mem_realloc(line, new_size);
- }
- *cur_size = new_size;
-
- return line;
-}
-
-char *h2o_log_request(h2o_logconf_t *logconf, h2o_req_t *req, size_t *len, char *buf)
-{
- char *line = buf, *pos = line, *line_end = line + *len;
- h2o_iovec_t nullexpr;
- char *(*append_unsafe_string)(char *pos, const char *src, size_t len);
- size_t element_index, unsafe_factor;
- struct tm localt = {0};
- int should_realloc_on_expand = 0;
-
- switch (logconf->escape) {
- case H2O_LOGCONF_ESCAPE_APACHE:
- nullexpr = h2o_iovec_init(H2O_STRLIT("-"));
- append_unsafe_string = append_unsafe_string_apache;
- unsafe_factor = 4;
- break;
- case H2O_LOGCONF_ESCAPE_JSON:
- nullexpr = h2o_iovec_init(H2O_STRLIT("null"));
- append_unsafe_string = append_unsafe_string_json;
- unsafe_factor = 6;
- break;
- default:
- h2o_fatal("unexpected escape mode");
- break;
- }
-
- for (element_index = 0; element_index != logconf->elements.size; ++element_index) {
- struct log_element_t *element = logconf->elements.entries + element_index;
-
-/* reserve capacity + suffix.len */
-#define RESERVE(capacity) \
- do { \
- if ((capacity) + element->suffix.len > line_end - pos) { \
- size_t off = pos - line; \
- size_t size = line_end - line; \
- line = expand_line_buf(line, &size, off + (capacity) + element->suffix.len, should_realloc_on_expand); \
- pos = line + off; \
- line_end = line + size; \
- should_realloc_on_expand = 1; \
- } \
- } while (0)
-
- switch (element->type) {
- case ELEMENT_TYPE_EMPTY:
- RESERVE(0);
- break;
- case ELEMENT_TYPE_LOCAL_ADDR: /* %A */
- RESERVE(NI_MAXHOST);
- pos = append_addr(pos, req->conn->callbacks->get_sockname, req->conn, nullexpr);
- break;
- case ELEMENT_TYPE_BYTES_SENT: /* %b */
- RESERVE(sizeof(H2O_UINT64_LONGEST_STR) - 1);
- pos += sprintf(pos, "%" PRIu64, (uint64_t)req->bytes_sent);
- break;
- case ELEMENT_TYPE_PROTOCOL: /* %H */
- RESERVE(sizeof("HTTP/1.1"));
- pos += h2o_stringify_protocol_version(pos, req->version);
- break;
- case ELEMENT_TYPE_REMOTE_ADDR: /* %h */
- RESERVE(NI_MAXHOST);
- pos = append_addr(pos, req->conn->callbacks->get_peername, req->conn, nullexpr);
- break;
- case ELEMENT_TYPE_METHOD: /* %m */
- RESERVE(req->input.method.len * unsafe_factor);
- pos = append_unsafe_string(pos, req->input.method.base, req->input.method.len);
- break;
- case ELEMENT_TYPE_LOCAL_PORT: /* %p */
- RESERVE(sizeof(H2O_UINT16_LONGEST_STR) - 1);
- pos = append_port(pos, req->conn->callbacks->get_sockname, req->conn, nullexpr);
- break;
- case ELEMENT_TYPE_REMOTE_PORT: /* %{remote}p */
- RESERVE(sizeof(H2O_UINT16_LONGEST_STR) - 1);
- pos = append_port(pos, req->conn->callbacks->get_peername, req->conn, nullexpr);
- break;
- case ELEMENT_TYPE_ENV_VAR: /* %{..}e */ {
- h2o_iovec_t *env_var = h2o_req_getenv(req, element->data.name.base, element->data.name.len, 0);
- if (env_var == NULL)
- goto EmitNull;
- RESERVE(env_var->len * unsafe_factor);
- pos = append_safe_string(pos, env_var->base, env_var->len);
- } break;
- case ELEMENT_TYPE_QUERY: /* %q */
- if (req->input.query_at != SIZE_MAX) {
- size_t len = req->input.path.len - req->input.query_at;
- RESERVE(len * unsafe_factor);
- pos = append_unsafe_string(pos, req->input.path.base + req->input.query_at, len);
- }
- break;
- case ELEMENT_TYPE_REQUEST_LINE: /* %r */
- RESERVE((req->input.method.len + req->input.path.len) * unsafe_factor + sizeof(" HTTP/1.1"));
- pos = append_unsafe_string(pos, req->input.method.base, req->input.method.len);
- *pos++ = ' ';
- pos = append_unsafe_string(pos, req->input.path.base, req->input.path.len);
- *pos++ = ' ';
- pos += h2o_stringify_protocol_version(pos, req->version);
- break;
- case ELEMENT_TYPE_STATUS: /* %s */
- RESERVE(sizeof(H2O_INT32_LONGEST_STR) - 1);
- pos += sprintf(pos, "%" PRId32, (int32_t)(element->original_response ? req->res.original.status : req->res.status));
- break;
- case ELEMENT_TYPE_TIMESTAMP: /* %t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- RESERVE(H2O_TIMESTR_LOG_LEN + 2);
- *pos++ = '[';
- pos = append_safe_string(pos, req->processed_at.str->log, H2O_TIMESTR_LOG_LEN);
- *pos++ = ']';
- break;
- case ELEMENT_TYPE_TIMESTAMP_STRFTIME: /* %{...}t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- {
- size_t bufsz, len;
- if (localt.tm_year == 0)
- localtime_r(&req->processed_at.at.tv_sec, &localt);
- for (bufsz = 128;; bufsz *= 2) {
- RESERVE(bufsz);
- if ((len = strftime(pos, bufsz, element->data.name.base, &localt)) != 0)
- break;
- }
- pos += len;
- }
- break;
- case ELEMENT_TYPE_TIMESTAMP_SEC_SINCE_EPOCH: /* %{sec}t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- RESERVE(sizeof(H2O_UINT32_LONGEST_STR) - 1);
- pos += sprintf(pos, "%" PRIu32, (uint32_t)req->processed_at.at.tv_sec);
- break;
- case ELEMENT_TYPE_TIMESTAMP_MSEC_SINCE_EPOCH: /* %{msec}t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- RESERVE(sizeof(H2O_UINT64_LONGEST_STR) - 1);
- pos += sprintf(pos, "%" PRIu64,
- (uint64_t)req->processed_at.at.tv_sec * 1000 + (uint64_t)req->processed_at.at.tv_usec / 1000);
- break;
- case ELEMENT_TYPE_TIMESTAMP_USEC_SINCE_EPOCH: /* %{usec}t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- RESERVE(sizeof(H2O_UINT64_LONGEST_STR) - 1);
- pos +=
- sprintf(pos, "%" PRIu64, (uint64_t)req->processed_at.at.tv_sec * 1000000 + (uint64_t)req->processed_at.at.tv_usec);
- break;
- case ELEMENT_TYPE_TIMESTAMP_MSEC_FRAC: /* %{msec_frac}t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- RESERVE(3);
- pos += sprintf(pos, "%03u", (unsigned)(req->processed_at.at.tv_usec / 1000));
- break;
- case ELEMENT_TYPE_TIMESTAMP_USEC_FRAC: /* %{usec_frac}t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- RESERVE(6);
- pos += sprintf(pos, "%06u", (unsigned)req->processed_at.at.tv_usec);
- break;
- case ELEMENT_TYPE_URL_PATH: /* %U */ {
- size_t path_len = req->input.query_at == SIZE_MAX ? req->input.path.len : req->input.query_at;
- RESERVE(path_len * unsafe_factor);
- pos = append_unsafe_string(pos, req->input.path.base, path_len);
- } break;
- case ELEMENT_TYPE_REMOTE_USER: /* %u */ {
- h2o_iovec_t *remote_user = h2o_req_getenv(req, H2O_STRLIT("REMOTE_USER"), 0);
- if (remote_user == NULL)
- goto EmitNull;
- RESERVE(remote_user->len * unsafe_factor);
- pos = append_unsafe_string(pos, remote_user->base, remote_user->len);
- } break;
- case ELEMENT_TYPE_AUTHORITY: /* %V */
- RESERVE(req->input.authority.len * unsafe_factor);
- pos = append_unsafe_string(pos, req->input.authority.base, req->input.authority.len);
- break;
- case ELEMENT_TYPE_HOSTCONF: /* %v */
- RESERVE(req->hostconf->authority.hostport.len * unsafe_factor);
- pos = append_unsafe_string(pos, req->hostconf->authority.hostport.base, req->hostconf->authority.hostport.len);
- break;
-
-#define EMIT_HEADER(__headers, concat, findfunc, ...) \
- do { \
- h2o_headers_t *headers = (__headers); \
- ssize_t index = -1; \
- int found = 0; \
- while ((index = (findfunc)(headers, __VA_ARGS__, index)) != -1) { \
- if (found) { \
- RESERVE(2); \
- *pos++ = ','; \
- *pos++ = ' '; \
- } else { \
- found = 1; \
- } \
- const h2o_header_t *header = headers->entries + index; \
- RESERVE(header->value.len *unsafe_factor); \
- pos = append_unsafe_string(pos, header->value.base, header->value.len); \
- if (!concat) \
- break; \
- } \
- if (!found) \
- goto EmitNull; \
- } while (0)
-
- case ELEMENT_TYPE_IN_HEADER_TOKEN:
- EMIT_HEADER(&req->headers, 0, h2o_find_header, element->data.header_token);
- break;
- case ELEMENT_TYPE_IN_HEADER_STRING:
- EMIT_HEADER(&req->headers, 0, h2o_find_header_by_str, element->data.name.base, element->data.name.len);
- break;
- case ELEMENT_TYPE_OUT_HEADER_TOKEN:
- EMIT_HEADER(element->original_response ? &req->res.original.headers : &req->res.headers, 0, h2o_find_header,
- element->data.header_token);
- break;
- case ELEMENT_TYPE_OUT_HEADER_STRING:
- EMIT_HEADER(element->original_response ? &req->res.original.headers : &req->res.headers, 0, h2o_find_header_by_str,
- element->data.name.base, element->data.name.len);
- break;
- case ELEMENT_TYPE_OUT_HEADER_TOKEN_CONCATENATED:
- EMIT_HEADER(element->original_response ? &req->res.original.headers : &req->res.headers, 1, h2o_find_header,
- element->data.header_token);
- break;
-
-#undef EMIT_HEADER
-
- case ELEMENT_TYPE_CONNECTION_ID:
- RESERVE(sizeof(H2O_UINT64_LONGEST_STR) - 1);
- pos += sprintf(pos, "%" PRIu64, req->conn->id);
- break;
-
- case ELEMENT_TYPE_CONNECT_TIME:
- APPEND_DURATION(pos, connect_time);
- break;
-
- case ELEMENT_TYPE_REQUEST_HEADER_TIME:
- APPEND_DURATION(pos, header_time);
- break;
-
- case ELEMENT_TYPE_REQUEST_BODY_TIME:
- APPEND_DURATION(pos, body_time);
- break;
-
- case ELEMENT_TYPE_REQUEST_TOTAL_TIME:
- APPEND_DURATION(pos, request_total_time);
- break;
-
- case ELEMENT_TYPE_PROCESS_TIME:
- APPEND_DURATION(pos, process_time);
- break;
-
- case ELEMENT_TYPE_RESPONSE_TIME:
- APPEND_DURATION(pos, response_time);
- break;
-
- case ELEMENT_TYPE_DURATION:
- APPEND_DURATION(pos, duration);
- break;
-
- case ELEMENT_TYPE_ERROR: {
- size_t i;
- for (i = 0; i != req->error_logs.size; ++i) {
- h2o_req_error_log_t *log = req->error_logs.entries + i;
- size_t module_len = strlen(log->module);
- RESERVE(sizeof("[] ") - 1 + module_len + log->msg.len * unsafe_factor);
- *pos++ = '[';
- pos = append_safe_string(pos, log->module, module_len);
- *pos++ = ']';
- *pos++ = ' ';
- pos = append_unsafe_string(pos, log->msg.base, log->msg.len);
- }
- } break;
-
- case ELEMENT_TYPE_PROTOCOL_SPECIFIC: {
- h2o_iovec_t (*cb)(h2o_req_t *) = req->conn->callbacks->log_.callbacks[element->data.protocol_specific_callback_index];
- if (cb != NULL) {
- h2o_iovec_t s = cb(req);
- if (s.base == NULL)
- goto EmitNull;
- RESERVE(s.len);
- pos = append_safe_string(pos, s.base, s.len);
- } else {
- goto EmitNull;
- }
- } break;
-
- case ELEMENT_TYPE_LOGNAME: /* %l */
- case ELEMENT_TYPE_EXTENDED_VAR: /* %{...}x */
- EmitNull:
- RESERVE(nullexpr.len);
- /* special case that trims surrounding quotes */
- if (element->magically_quoted_json) {
- --pos;
- pos = append_safe_string(pos, nullexpr.base, nullexpr.len);
- pos = append_safe_string(pos, element->suffix.base + 1, element->suffix.len - 1);
- continue;
- }
- pos = append_safe_string(pos, nullexpr.base, nullexpr.len);
- break;
-
- default:
- assert(!"unknown type");
- break;
- }
-
-#undef RESERVE
-
- pos = append_safe_string(pos, element->suffix.base, element->suffix.len);
- }
-
- *len = pos - line;
- return line;
-}
diff --git a/web/server/h2o/libh2o/lib/core/proxy.c b/web/server/h2o/libh2o/lib/core/proxy.c
deleted file mode 100644
index edb4baf9d..000000000
--- a/web/server/h2o/libh2o/lib/core/proxy.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * Copyright (c) 2014,2015 DeNA Co., Ltd., Kazuho Oku, Masahiro Nagano
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include "picohttpparser.h"
-#include "h2o.h"
-#include "h2o/http1.h"
-#include "h2o/http1client.h"
-#include "h2o/tunnel.h"
-
-struct rp_generator_t {
- h2o_generator_t super;
- h2o_req_t *src_req;
- h2o_http1client_t *client;
- struct {
- h2o_iovec_t bufs[2]; /* first buf is the request line and headers, the second is the POST content */
- int is_head;
- } up_req;
- h2o_buffer_t *last_content_before_send;
- h2o_doublebuffer_t sending;
- int is_websocket_handshake;
- int had_body_error; /* set if an error happened while fetching the body so that we can propagate the error */
-};
-
-struct rp_ws_upgrade_info_t {
- h2o_context_t *ctx;
- h2o_timeout_t *timeout;
- h2o_socket_t *upstream_sock;
-};
-
-static h2o_http1client_ctx_t *get_client_ctx(h2o_req_t *req)
-{
- h2o_req_overrides_t *overrides = req->overrides;
- if (overrides != NULL && overrides->client_ctx != NULL)
- return overrides->client_ctx;
- return &req->conn->ctx->proxy.client_ctx;
-}
-
-static h2o_iovec_t rewrite_location(h2o_mem_pool_t *pool, const char *location, size_t location_len, h2o_url_t *match,
- const h2o_url_scheme_t *req_scheme, h2o_iovec_t req_authority, h2o_iovec_t req_basepath)
-{
- h2o_url_t loc_parsed;
-
- if (h2o_url_parse(location, location_len, &loc_parsed) != 0)
- goto NoRewrite;
- if (loc_parsed.scheme != &H2O_URL_SCHEME_HTTP)
- goto NoRewrite;
- if (!h2o_url_hosts_are_equal(&loc_parsed, match))
- goto NoRewrite;
- if (h2o_url_get_port(&loc_parsed) != h2o_url_get_port(match))
- goto NoRewrite;
- if (loc_parsed.path.len < match->path.len)
- goto NoRewrite;
- if (memcmp(loc_parsed.path.base, match->path.base, match->path.len) != 0)
- goto NoRewrite;
-
- return h2o_concat(pool, req_scheme->name, h2o_iovec_init(H2O_STRLIT("://")), req_authority, req_basepath,
- h2o_iovec_init(loc_parsed.path.base + match->path.len, loc_parsed.path.len - match->path.len));
-
-NoRewrite:
- return (h2o_iovec_t){NULL};
-}
-
-static h2o_iovec_t build_request_merge_headers(h2o_mem_pool_t *pool, h2o_iovec_t merged, h2o_iovec_t added, int seperator)
-{
- if (added.len == 0)
- return merged;
- if (merged.len == 0)
- return added;
-
- size_t newlen = merged.len + 2 + added.len;
- char *buf = h2o_mem_alloc_pool(pool, newlen);
- memcpy(buf, merged.base, merged.len);
- buf[merged.len] = seperator;
- buf[merged.len + 1] = ' ';
- memcpy(buf + merged.len + 2, added.base, added.len);
- merged.base = buf;
- merged.len = newlen;
- return merged;
-}
-
-/*
- * A request without neither Content-Length or Transfer-Encoding header implies a zero-length request body (see 6th rule of RFC 7230
- * 3.3.3).
- * OTOH, section 3.3.3 states:
- *
- * A user agent SHOULD send a Content-Length in a request message when
- * no Transfer-Encoding is sent and the request method defines a meaning
- * for an enclosed payload body. For example, a Content-Length header
- * field is normally sent in a POST request even when the value is 0
- * (indicating an empty payload body). A user agent SHOULD NOT send a
- * Content-Length header field when the request message does not contain
- * a payload body and the method semantics do not anticipate such a
- * body.
- *
- * PUT and POST define a meaning for the payload body, let's emit a
- * Content-Length header if it doesn't exist already, since the server
- * might send a '411 Length Required' response.
- *
- * see also: ML thread starting at https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0580.html
- */
-static int req_requires_content_length(h2o_req_t *req)
-{
- int is_put_or_post =
- (req->method.len >= 1 && req->method.base[0] == 'P' && (h2o_memis(req->method.base, req->method.len, H2O_STRLIT("POST")) ||
- h2o_memis(req->method.base, req->method.len, H2O_STRLIT("PUT"))));
-
- return is_put_or_post && h2o_find_header(&req->res.headers, H2O_TOKEN_TRANSFER_ENCODING, -1) == -1;
-}
-
-static h2o_iovec_t build_request(h2o_req_t *req, int keepalive, int is_websocket_handshake, int use_proxy_protocol)
-{
- h2o_iovec_t buf;
- size_t offset = 0, remote_addr_len = SIZE_MAX;
- char remote_addr[NI_MAXHOST];
- struct sockaddr_storage ss;
- socklen_t sslen;
- h2o_iovec_t cookie_buf = {NULL}, xff_buf = {NULL}, via_buf = {NULL};
- int preserve_x_forwarded_proto = req->conn->ctx->globalconf->proxy.preserve_x_forwarded_proto;
- int emit_x_forwarded_headers = req->conn->ctx->globalconf->proxy.emit_x_forwarded_headers;
- int emit_via_header = req->conn->ctx->globalconf->proxy.emit_via_header;
-
- /* for x-f-f */
- if ((sslen = req->conn->callbacks->get_peername(req->conn, (void *)&ss)) != 0)
- remote_addr_len = h2o_socket_getnumerichost((void *)&ss, sslen, remote_addr);
-
- /* build response */
- buf.len = req->method.len + req->path.len + req->authority.len + 512;
- if (use_proxy_protocol)
- buf.len += H2O_PROXY_HEADER_MAX_LENGTH;
- buf.base = h2o_mem_alloc_pool(&req->pool, buf.len);
-
-#define RESERVE(sz) \
- do { \
- size_t required = offset + sz + 4 /* for "\r\n\r\n" */; \
- if (required > buf.len) { \
- do { \
- buf.len *= 2; \
- } while (required > buf.len); \
- char *newp = h2o_mem_alloc_pool(&req->pool, buf.len); \
- memcpy(newp, buf.base, offset); \
- buf.base = newp; \
- } \
- } while (0)
-#define APPEND(s, l) \
- do { \
- memcpy(buf.base + offset, (s), (l)); \
- offset += (l); \
- } while (0)
-#define APPEND_STRLIT(lit) APPEND((lit), sizeof(lit) - 1)
-#define FLATTEN_PREFIXED_VALUE(prefix, value, add_size) \
- do { \
- RESERVE(sizeof(prefix) - 1 + value.len + 2 + add_size); \
- APPEND_STRLIT(prefix); \
- if (value.len != 0) { \
- APPEND(value.base, value.len); \
- if (add_size != 0) { \
- buf.base[offset++] = ','; \
- buf.base[offset++] = ' '; \
- } \
- } \
- } while (0)
-
- if (use_proxy_protocol)
- offset += h2o_stringify_proxy_header(req->conn, buf.base + offset);
-
- APPEND(req->method.base, req->method.len);
- buf.base[offset++] = ' ';
- APPEND(req->path.base, req->path.len);
- APPEND_STRLIT(" HTTP/1.1\r\nconnection: ");
- if (is_websocket_handshake) {
- APPEND_STRLIT("upgrade\r\nupgrade: websocket\r\nhost: ");
- } else if (keepalive) {
- APPEND_STRLIT("keep-alive\r\nhost: ");
- } else {
- APPEND_STRLIT("close\r\nhost: ");
- }
- APPEND(req->authority.base, req->authority.len);
- buf.base[offset++] = '\r';
- buf.base[offset++] = '\n';
- assert(offset <= buf.len);
- if (req->entity.base != NULL || req_requires_content_length(req)) {
- RESERVE(sizeof("content-length: " H2O_UINT64_LONGEST_STR) - 1);
- offset += sprintf(buf.base + offset, "content-length: %zu\r\n", req->entity.len);
- }
-
- /* rewrite headers if necessary */
- h2o_headers_t req_headers = req->headers;
- if (req->overrides != NULL && req->overrides->headers_cmds != NULL) {
- req_headers.entries = NULL;
- req_headers.size = 0;
- req_headers.capacity = 0;
- h2o_headers_command_t *cmd;
- h2o_vector_reserve(&req->pool, &req_headers, req->headers.capacity);
- memcpy(req_headers.entries, req->headers.entries, sizeof(req->headers.entries[0]) * req->headers.size);
- req_headers.size = req->headers.size;
- for (cmd = req->overrides->headers_cmds; cmd->cmd != H2O_HEADERS_CMD_NULL; ++cmd)
- h2o_rewrite_headers(&req->pool, &req_headers, cmd);
- }
-
- {
- const h2o_header_t *h, *h_end;
- for (h = req_headers.entries, h_end = h + req_headers.size; h != h_end; ++h) {
- if (h2o_iovec_is_token(h->name)) {
- const h2o_token_t *token = (void *)h->name;
- if (token->proxy_should_drop_for_req) {
- continue;
- } else if (token == H2O_TOKEN_COOKIE) {
- /* merge the cookie headers; see HTTP/2 8.1.2.5 and HTTP/1 (RFC6265 5.4) */
- /* FIXME current algorithm is O(n^2) against the number of cookie headers */
- cookie_buf = build_request_merge_headers(&req->pool, cookie_buf, h->value, ';');
- continue;
- } else if (token == H2O_TOKEN_VIA) {
- if (!emit_via_header) {
- goto AddHeader;
- }
- via_buf = build_request_merge_headers(&req->pool, via_buf, h->value, ',');
- continue;
- } else if (token == H2O_TOKEN_X_FORWARDED_FOR) {
- if (!emit_x_forwarded_headers) {
- goto AddHeader;
- }
- xff_buf = build_request_merge_headers(&req->pool, xff_buf, h->value, ',');
- continue;
- }
- }
- if (!preserve_x_forwarded_proto && h2o_lcstris(h->name->base, h->name->len, H2O_STRLIT("x-forwarded-proto")))
- continue;
- AddHeader:
- RESERVE(h->name->len + h->value.len + 2);
- APPEND(h->orig_name ? h->orig_name : h->name->base, h->name->len);
- buf.base[offset++] = ':';
- buf.base[offset++] = ' ';
- APPEND(h->value.base, h->value.len);
- buf.base[offset++] = '\r';
- buf.base[offset++] = '\n';
- }
- }
- if (cookie_buf.len != 0) {
- FLATTEN_PREFIXED_VALUE("cookie: ", cookie_buf, 0);
- buf.base[offset++] = '\r';
- buf.base[offset++] = '\n';
- }
- if (emit_x_forwarded_headers) {
- if (!preserve_x_forwarded_proto) {
- FLATTEN_PREFIXED_VALUE("x-forwarded-proto: ", req->input.scheme->name, 0);
- buf.base[offset++] = '\r';
- buf.base[offset++] = '\n';
- }
- if (remote_addr_len != SIZE_MAX) {
- FLATTEN_PREFIXED_VALUE("x-forwarded-for: ", xff_buf, remote_addr_len);
- APPEND(remote_addr, remote_addr_len);
- } else {
- FLATTEN_PREFIXED_VALUE("x-forwarded-for: ", xff_buf, 0);
- }
- buf.base[offset++] = '\r';
- buf.base[offset++] = '\n';
- }
- if (emit_via_header) {
- FLATTEN_PREFIXED_VALUE("via: ", via_buf, sizeof("1.1 ") - 1 + req->input.authority.len);
- if (req->version < 0x200) {
- buf.base[offset++] = '1';
- buf.base[offset++] = '.';
- buf.base[offset++] = '0' + (0x100 <= req->version && req->version <= 0x109 ? req->version - 0x100 : 0);
- } else {
- buf.base[offset++] = '2';
- }
- buf.base[offset++] = ' ';
- APPEND(req->input.authority.base, req->input.authority.len);
- buf.base[offset++] = '\r';
- buf.base[offset++] = '\n';
- }
- APPEND_STRLIT("\r\n");
-
-#undef RESERVE
-#undef APPEND
-#undef APPEND_STRLIT
-#undef FLATTEN_PREFIXED_VALUE
-
- /* set the length */
- assert(offset <= buf.len);
- buf.len = offset;
-
- return buf;
-}
-
-static void do_close(h2o_generator_t *generator, h2o_req_t *req)
-{
- struct rp_generator_t *self = (void *)generator;
-
- if (self->client != NULL) {
- h2o_http1client_cancel(self->client);
- self->client = NULL;
- }
-}
-
-static void do_send(struct rp_generator_t *self)
-{
- h2o_iovec_t vecs[1];
- size_t veccnt;
- h2o_send_state_t ststate;
-
- assert(self->sending.bytes_inflight == 0);
-
- vecs[0] = h2o_doublebuffer_prepare(&self->sending,
- self->client != NULL ? &self->client->sock->input : &self->last_content_before_send,
- self->src_req->preferred_chunk_size);
-
- if (self->client == NULL && vecs[0].len == self->sending.buf->size && self->last_content_before_send->size == 0) {
- veccnt = vecs[0].len != 0 ? 1 : 0;
- ststate = H2O_SEND_STATE_FINAL;
- } else {
- if (vecs[0].len == 0)
- return;
- veccnt = 1;
- ststate = H2O_SEND_STATE_IN_PROGRESS;
- }
-
- if (self->had_body_error)
- ststate = H2O_SEND_STATE_ERROR;
-
- h2o_send(self->src_req, vecs, veccnt, ststate);
-}
-
-static void do_proceed(h2o_generator_t *generator, h2o_req_t *req)
-{
- struct rp_generator_t *self = (void *)generator;
-
- h2o_doublebuffer_consume(&self->sending);
- do_send(self);
-}
-
-static void on_websocket_upgrade_complete(void *_info, h2o_socket_t *sock, size_t reqsize)
-{
- struct rp_ws_upgrade_info_t *info = _info;
-
- if (sock != NULL) {
- h2o_buffer_consume(&sock->input, reqsize);//It is detached from conn. Let's trash unused data.
- h2o_tunnel_establish(info->ctx, sock, info->upstream_sock, info->timeout);
- } else {
- h2o_socket_close(info->upstream_sock);
- }
- free(info);
-}
-
-static inline void on_websocket_upgrade(struct rp_generator_t *self, h2o_timeout_t *timeout, int rlen)
-{
- h2o_req_t *req = self->src_req;
- h2o_socket_t *sock = h2o_http1client_steal_socket(self->client);
- h2o_buffer_consume(&sock->input, rlen);//trash data after stealing sock.
- struct rp_ws_upgrade_info_t *info = h2o_mem_alloc(sizeof(*info));
- info->upstream_sock = sock;
- info->timeout = timeout;
- info->ctx = req->conn->ctx;
- h2o_http1_upgrade(req, NULL, 0, on_websocket_upgrade_complete, info);
-}
-
-static int on_body(h2o_http1client_t *client, const char *errstr)
-{
- struct rp_generator_t *self = client->data;
-
- if (errstr != NULL) {
- /* detach the content */
- self->last_content_before_send = self->client->sock->input;
- h2o_buffer_init(&self->client->sock->input, &h2o_socket_buffer_prototype);
- self->client = NULL;
- if (errstr != h2o_http1client_error_is_eos) {
- h2o_req_log_error(self->src_req, "lib/core/proxy.c", "%s", errstr);
- self->had_body_error = 1;
- }
- }
- if (self->sending.bytes_inflight == 0)
- do_send(self);
-
- return 0;
-}
-
-static char compress_hint_to_enum(const char *val, size_t len)
-{
- if (h2o_lcstris(val, len, H2O_STRLIT("on"))) {
- return H2O_COMPRESS_HINT_ENABLE;
- }
- if (h2o_lcstris(val, len, H2O_STRLIT("off"))) {
- return H2O_COMPRESS_HINT_DISABLE;
- }
- return H2O_COMPRESS_HINT_AUTO;
-}
-
-static h2o_http1client_body_cb on_head(h2o_http1client_t *client, const char *errstr, int minor_version, int status,
- h2o_iovec_t msg, h2o_header_t *headers, size_t num_headers, int rlen)
-{
- struct rp_generator_t *self = client->data;
- h2o_req_t *req = self->src_req;
- size_t i;
-
- if (errstr != NULL && errstr != h2o_http1client_error_is_eos) {
- self->client = NULL;
- h2o_req_log_error(req, "lib/core/proxy.c", "%s", errstr);
- h2o_send_error_502(req, "Gateway Error", errstr, 0);
- return NULL;
- }
-
- /* copy the response (note: all the headers must be copied; http1client discards the input once we return from this callback) */
- req->res.status = status;
- req->res.reason = h2o_strdup(&req->pool, msg.base, msg.len).base;
- for (i = 0; i != num_headers; ++i) {
- if (h2o_iovec_is_token(headers[i].name)) {
- const h2o_token_t *token = H2O_STRUCT_FROM_MEMBER(h2o_token_t, buf, headers[i].name);
- h2o_iovec_t value;
- if (token->proxy_should_drop_for_res) {
- goto Skip;
- }
- if (token == H2O_TOKEN_CONTENT_LENGTH) {
- if (req->res.content_length != SIZE_MAX ||
- (req->res.content_length = h2o_strtosize(headers[i].value.base, headers[i].value.len)) == SIZE_MAX) {
- self->client = NULL;
- h2o_req_log_error(req, "lib/core/proxy.c", "%s", "invalid response from upstream (malformed content-length)");
- h2o_send_error_502(req, "Gateway Error", "invalid response from upstream", 0);
- return NULL;
- }
- goto Skip;
- } else if (token == H2O_TOKEN_LOCATION) {
- if (req->res_is_delegated && (300 <= status && status <= 399) && status != 304) {
- self->client = NULL;
- h2o_iovec_t method = h2o_get_redirect_method(req->method, status);
- h2o_send_redirect_internal(req, method, headers[i].value.base, headers[i].value.len, 1);
- return NULL;
- }
- if (req->overrides != NULL && req->overrides->location_rewrite.match != NULL) {
- value = rewrite_location(&req->pool, headers[i].value.base, headers[i].value.len,
- req->overrides->location_rewrite.match, req->input.scheme, req->input.authority,
- req->overrides->location_rewrite.path_prefix);
- if (value.base != NULL)
- goto AddHeader;
- }
- goto AddHeaderDuped;
- } else if (token == H2O_TOKEN_LINK) {
- h2o_iovec_t new_value;
- new_value = h2o_push_path_in_link_header(req, headers[i].value.base, headers[i].value.len);
- if (!new_value.len)
- goto Skip;
- headers[i].value.base = new_value.base;
- headers[i].value.len = new_value.len;
- } else if (token == H2O_TOKEN_SERVER) {
- if (!req->conn->ctx->globalconf->proxy.preserve_server_header)
- goto Skip;
- } else if (token == H2O_TOKEN_X_COMPRESS_HINT) {
- req->compress_hint = compress_hint_to_enum(headers[i].value.base, headers[i].value.len);
- goto Skip;
- }
- /* default behaviour, transfer the header downstream */
- AddHeaderDuped:
- value = h2o_strdup(&req->pool, headers[i].value.base, headers[i].value.len);
- AddHeader:
- h2o_add_header(&req->pool, &req->res.headers, token, headers[i].orig_name, value.base, value.len);
- Skip:;
- } else {
- h2o_iovec_t name = h2o_strdup(&req->pool, headers[i].name->base, headers[i].name->len);
- h2o_iovec_t value = h2o_strdup(&req->pool, headers[i].value.base, headers[i].value.len);
- h2o_add_header_by_str(&req->pool, &req->res.headers, name.base, name.len, 0, headers[i].orig_name, value.base,
- value.len);
- }
- }
-
- if (self->is_websocket_handshake && req->res.status == 101) {
- h2o_http1client_ctx_t *client_ctx = get_client_ctx(req);
- assert(client_ctx->websocket_timeout != NULL);
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_UPGRADE, NULL, H2O_STRLIT("websocket"));
- on_websocket_upgrade(self, client_ctx->websocket_timeout, rlen);
- self->client = NULL;
- return NULL;
- }
- /* declare the start of the response */
- h2o_start_response(req, &self->super);
-
- if (errstr == h2o_http1client_error_is_eos) {
- self->client = NULL;
- h2o_send(req, NULL, 0, H2O_SEND_STATE_FINAL);
- return NULL;
- }
-
- return on_body;
-}
-
-static int on_1xx(h2o_http1client_t *client, int minor_version, int status, h2o_iovec_t msg, h2o_header_t *headers,
- size_t num_headers)
-{
- struct rp_generator_t *self = client->data;
- size_t i;
-
- for (i = 0; i != num_headers; ++i) {
- if (headers[i].name == &H2O_TOKEN_LINK->buf)
- h2o_push_path_in_link_header(self->src_req, headers[i].value.base, headers[i].value.len);
- }
-
- return 0;
-}
-
-static h2o_http1client_head_cb on_connect(h2o_http1client_t *client, const char *errstr, h2o_iovec_t **reqbufs, size_t *reqbufcnt,
- int *method_is_head)
-{
- struct rp_generator_t *self = client->data;
-
- if (errstr != NULL) {
- self->client = NULL;
- h2o_req_log_error(self->src_req, "lib/core/proxy.c", "%s", errstr);
- h2o_send_error_502(self->src_req, "Gateway Error", errstr, 0);
- return NULL;
- }
-
- *reqbufs = self->up_req.bufs;
- *reqbufcnt = self->up_req.bufs[1].base != NULL ? 2 : 1;
- *method_is_head = self->up_req.is_head;
- self->client->informational_cb = on_1xx;
- return on_head;
-}
-
-static void on_generator_dispose(void *_self)
-{
- struct rp_generator_t *self = _self;
-
- if (self->client != NULL) {
- h2o_http1client_cancel(self->client);
- self->client = NULL;
- }
- h2o_buffer_dispose(&self->last_content_before_send);
- h2o_doublebuffer_dispose(&self->sending);
-}
-
-static struct rp_generator_t *proxy_send_prepare(h2o_req_t *req, int keepalive, int use_proxy_protocol)
-{
- struct rp_generator_t *self = h2o_mem_alloc_shared(&req->pool, sizeof(*self), on_generator_dispose);
- h2o_http1client_ctx_t *client_ctx = get_client_ctx(req);
-
- self->super.proceed = do_proceed;
- self->super.stop = do_close;
- self->src_req = req;
- if (client_ctx->websocket_timeout != NULL && h2o_lcstris(req->upgrade.base, req->upgrade.len, H2O_STRLIT("websocket"))) {
- self->is_websocket_handshake = 1;
- } else {
- self->is_websocket_handshake = 0;
- }
- self->had_body_error = 0;
- self->up_req.bufs[0] = build_request(req, keepalive, self->is_websocket_handshake, use_proxy_protocol);
- self->up_req.bufs[1] = req->entity;
- self->up_req.is_head = h2o_memis(req->method.base, req->method.len, H2O_STRLIT("HEAD"));
- h2o_buffer_init(&self->last_content_before_send, &h2o_socket_buffer_prototype);
- h2o_doublebuffer_init(&self->sending, &h2o_socket_buffer_prototype);
-
- return self;
-}
-
-void h2o__proxy_process_request(h2o_req_t *req)
-{
- h2o_req_overrides_t *overrides = req->overrides;
- h2o_http1client_ctx_t *client_ctx = get_client_ctx(req);
- struct rp_generator_t *self;
-
- if (overrides != NULL) {
- if (overrides->socketpool != NULL) {
- if (overrides->use_proxy_protocol)
- assert(!"proxy protocol cannot be used for a persistent upstream connection");
- self = proxy_send_prepare(req, 1, 0);
- h2o_http1client_connect_with_pool(&self->client, self, client_ctx, overrides->socketpool, on_connect);
- return;
- } else if (overrides->hostport.host.base != NULL) {
- self = proxy_send_prepare(req, 0, overrides->use_proxy_protocol);
- h2o_http1client_connect(&self->client, self, client_ctx, req->overrides->hostport.host, req->overrides->hostport.port,
- 0, on_connect);
- return;
- }
- }
- { /* default logic */
- h2o_iovec_t host;
- uint16_t port;
- if (h2o_url_parse_hostport(req->authority.base, req->authority.len, &host, &port) == NULL) {
- h2o_req_log_error(req, "lib/core/proxy.c", "invalid URL supplied for internal redirection:%s://%.*s%.*s",
- req->scheme->name.base, (int)req->authority.len, req->authority.base, (int)req->path.len,
- req->path.base);
- h2o_send_error_502(req, "Gateway Error", "internal error", 0);
- return;
- }
- if (port == 65535)
- port = req->scheme->default_port;
- self = proxy_send_prepare(req, 0, overrides != NULL && overrides->use_proxy_protocol);
- h2o_http1client_connect(&self->client, self, client_ctx, host, port, req->scheme == &H2O_URL_SCHEME_HTTPS, on_connect);
- return;
- }
-}
diff --git a/web/server/h2o/libh2o/lib/core/request.c b/web/server/h2o/libh2o/lib/core/request.c
deleted file mode 100644
index 96aabb22d..000000000
--- a/web/server/h2o/libh2o/lib/core/request.c
+++ /dev/null
@@ -1,696 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Tatsuhiro Tsujikawa
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/uio.h>
-#include "h2o.h"
-
-#ifndef IOV_MAX
-#define IOV_MAX UIO_MAXIOV
-#endif
-
-#define INITIAL_INBUFSZ 8192
-
-struct st_deferred_request_action_t {
- h2o_timeout_entry_t timeout;
- h2o_req_t *req;
-};
-
-struct st_delegate_request_deferred_t {
- struct st_deferred_request_action_t super;
- h2o_handler_t *current_handler;
-};
-
-struct st_reprocess_request_deferred_t {
- struct st_deferred_request_action_t super;
- h2o_iovec_t method;
- const h2o_url_scheme_t *scheme;
- h2o_iovec_t authority;
- h2o_iovec_t path;
- h2o_req_overrides_t *overrides;
- int is_delegated;
-};
-
-struct st_send_error_deferred_t {
- h2o_req_t *req;
- int status;
- const char *reason;
- const char *body;
- int flags;
- h2o_timeout_entry_t _timeout;
-};
-
-static void on_deferred_action_dispose(void *_action)
-{
- struct st_deferred_request_action_t *action = _action;
- if (h2o_timeout_is_linked(&action->timeout))
- h2o_timeout_unlink(&action->timeout);
-}
-
-static struct st_deferred_request_action_t *create_deferred_action(h2o_req_t *req, size_t sz, h2o_timeout_cb cb)
-{
- struct st_deferred_request_action_t *action = h2o_mem_alloc_shared(&req->pool, sz, on_deferred_action_dispose);
- *action = (struct st_deferred_request_action_t){{0, cb}, req};
- h2o_timeout_link(req->conn->ctx->loop, &req->conn->ctx->zero_timeout, &action->timeout);
- return action;
-}
-
-static h2o_hostconf_t *find_hostconf(h2o_hostconf_t **hostconfs, h2o_iovec_t authority, uint16_t default_port)
-{
- h2o_iovec_t hostname;
- uint16_t port;
- char *hostname_lc;
-
- /* safe-guard for alloca */
- if (authority.len >= 65536)
- return NULL;
-
- /* extract the specified hostname and port */
- if (h2o_url_parse_hostport(authority.base, authority.len, &hostname, &port) == NULL)
- return NULL;
- if (port == 65535)
- port = default_port;
-
- /* convert supplied hostname to lower-case */
- hostname_lc = alloca(hostname.len);
- memcpy(hostname_lc, hostname.base, hostname.len);
- h2o_strtolower(hostname_lc, hostname.len);
-
- do {
- h2o_hostconf_t *hostconf = *hostconfs;
- if (hostconf->authority.port == port || (hostconf->authority.port == 65535 && port == default_port)) {
- if (hostconf->authority.host.base[0] == '*') {
- /* matching against "*.foo.bar" */
- size_t cmplen = hostconf->authority.host.len - 1;
- if (cmplen < hostname.len &&
- memcmp(hostconf->authority.host.base + 1, hostname_lc + hostname.len - cmplen, cmplen) == 0)
- return hostconf;
- } else {
- /* exact match */
- if (h2o_memis(hostconf->authority.host.base, hostconf->authority.host.len, hostname_lc, hostname.len))
- return hostconf;
- }
- }
- } while (*++hostconfs != NULL);
-
- return NULL;
-}
-
-static h2o_hostconf_t *setup_before_processing(h2o_req_t *req)
-{
- h2o_context_t *ctx = req->conn->ctx;
- h2o_hostconf_t *hostconf;
-
- h2o_get_timestamp(ctx, &req->pool, &req->processed_at);
-
- /* find the host context */
- if (req->input.authority.base != NULL) {
- if (req->conn->hosts[1] == NULL ||
- (hostconf = find_hostconf(req->conn->hosts, req->input.authority, req->input.scheme->default_port)) == NULL)
- hostconf = *req->conn->hosts;
- } else {
- /* set the authority name to the default one */
- hostconf = *req->conn->hosts;
- req->input.authority = hostconf->authority.hostport;
- }
-
- req->scheme = req->input.scheme;
- req->method = req->input.method;
- req->authority = req->input.authority;
- req->path = req->input.path;
- req->path_normalized =
- h2o_url_normalize_path(&req->pool, req->input.path.base, req->input.path.len, &req->query_at, &req->norm_indexes);
- req->input.query_at = req->query_at; /* we can do this since input.path == path */
-
- return hostconf;
-}
-
-static void call_handlers(h2o_req_t *req, h2o_handler_t **handler)
-{
- h2o_handler_t **end = req->pathconf->handlers.entries + req->pathconf->handlers.size;
-
- for (; handler != end; ++handler)
- if ((*handler)->on_req(*handler, req) == 0)
- return;
-
- h2o_send_error_404(req, "File Not Found", "not found", 0);
-}
-
-static void process_hosted_request(h2o_req_t *req, h2o_hostconf_t *hostconf)
-{
- h2o_pathconf_t *selected_pathconf = &hostconf->fallback_path;
- size_t i;
-
- /* setup pathconf, or redirect to "path/" */
- for (i = 0; i != hostconf->paths.size; ++i) {
- h2o_pathconf_t *candidate = hostconf->paths.entries + i;
- if (req->path_normalized.len >= candidate->path.len &&
- memcmp(req->path_normalized.base, candidate->path.base, candidate->path.len) == 0 &&
- (candidate->path.base[candidate->path.len - 1] == '/' || req->path_normalized.len == candidate->path.len ||
- req->path_normalized.base[candidate->path.len] == '/')) {
- selected_pathconf = candidate;
- break;
- }
- }
- h2o_req_bind_conf(req, hostconf, selected_pathconf);
-
- call_handlers(req, req->pathconf->handlers.entries);
-}
-
-static void deferred_proceed_cb(h2o_timeout_entry_t *entry)
-{
- h2o_req_t *req = H2O_STRUCT_FROM_MEMBER(h2o_req_t, _timeout_entry, entry);
- h2o_proceed_response(req);
-}
-
-static void close_generator_and_filters(h2o_req_t *req)
-{
- /* close the generator if it is still open */
- if (req->_generator != NULL) {
- /* close generator */
- if (req->_generator->stop != NULL)
- req->_generator->stop(req->_generator, req);
- req->_generator = NULL;
- }
- /* close the ostreams still open */
- while (req->_ostr_top->next != NULL) {
- if (req->_ostr_top->stop != NULL)
- req->_ostr_top->stop(req->_ostr_top, req);
- req->_ostr_top = req->_ostr_top->next;
- }
-}
-
-static void reset_response(h2o_req_t *req)
-{
- req->res = (h2o_res_t){0, NULL, SIZE_MAX};
- req->res.reason = "OK";
- req->_next_filter_index = 0;
- req->bytes_sent = 0;
-}
-
-static void retain_original_response(h2o_req_t *req)
-{
- if (req->res.original.status != 0)
- return;
-
- req->res.original.status = req->res.status;
- h2o_vector_reserve(&req->pool, &req->res.original.headers, req->res.headers.size);
- h2o_memcpy(req->res.original.headers.entries, req->res.headers.entries,
- sizeof(req->res.headers.entries[0]) * req->res.headers.size);
- req->res.original.headers.size = req->res.headers.size;
-}
-
-void h2o_init_request(h2o_req_t *req, h2o_conn_t *conn, h2o_req_t *src)
-{
- /* clear all memory (expect memory pool, since it is large) */
- memset(req, 0, offsetof(h2o_req_t, pool));
-
- /* init memory pool (before others, since it may be used) */
- h2o_mem_init_pool(&req->pool);
-
- /* init properties that should be initialized to non-zero */
- req->conn = conn;
- req->_timeout_entry.cb = deferred_proceed_cb;
- req->res.reason = "OK"; /* default to "OK" regardless of the status value, it's not important after all (never sent in HTTP2) */
- req->res.content_length = SIZE_MAX;
- req->preferred_chunk_size = SIZE_MAX;
-
- if (src != NULL) {
- size_t i;
-#define COPY(buf) \
- do { \
- req->buf.base = h2o_mem_alloc_pool(&req->pool, src->buf.len); \
- memcpy(req->buf.base, src->buf.base, src->buf.len); \
- req->buf.len = src->buf.len; \
- } while (0)
- COPY(input.authority);
- COPY(input.method);
- COPY(input.path);
- req->input.scheme = src->input.scheme;
- req->version = src->version;
- req->entity = src->entity;
- req->http1_is_persistent = src->http1_is_persistent;
- req->timestamps = src->timestamps;
- if (src->upgrade.base != NULL) {
- COPY(upgrade);
- } else {
- req->upgrade.base = NULL;
- req->upgrade.len = 0;
- }
-#undef COPY
- h2o_vector_reserve(&req->pool, &req->headers, src->headers.size);
- req->headers.size = src->headers.size;
- for (i = 0; i != src->headers.size; ++i) {
- h2o_header_t *dst_header = req->headers.entries + i, *src_header = src->headers.entries + i;
- if (h2o_iovec_is_token(src_header->name)) {
- dst_header->name = src_header->name;
- } else {
- dst_header->name = h2o_mem_alloc_pool(&req->pool, sizeof(*dst_header->name));
- *dst_header->name = h2o_strdup(&req->pool, src_header->name->base, src_header->name->len);
- }
- dst_header->value = h2o_strdup(&req->pool, src_header->value.base, src_header->value.len);
- if (!src_header->orig_name)
- dst_header->orig_name = NULL;
- else
- dst_header->orig_name = h2o_strdup(&req->pool, src_header->orig_name, src_header->name->len).base;
- }
- if (src->env.size != 0) {
- h2o_vector_reserve(&req->pool, &req->env, src->env.size);
- req->env.size = src->env.size;
- for (i = 0; i != req->env.size; ++i)
- req->env.entries[i] = h2o_strdup(&req->pool, src->env.entries[i].base, src->env.entries[i].len);
- }
- }
-}
-
-void h2o_dispose_request(h2o_req_t *req)
-{
- close_generator_and_filters(req);
-
- h2o_timeout_unlink(&req->_timeout_entry);
-
- if (req->version != 0 && req->pathconf != NULL) {
- h2o_logger_t **logger = req->pathconf->loggers.entries, **end = logger + req->pathconf->loggers.size;
- for (; logger != end; ++logger) {
- (*logger)->log_access((*logger), req);
- }
- }
-
- h2o_mem_clear_pool(&req->pool);
-}
-
-void h2o_process_request(h2o_req_t *req)
-{
- h2o_hostconf_t *hostconf = setup_before_processing(req);
- process_hosted_request(req, hostconf);
-}
-
-void h2o_delegate_request(h2o_req_t *req, h2o_handler_t *current_handler)
-{
- h2o_handler_t **handler = req->pathconf->handlers.entries, **end = handler + req->pathconf->handlers.size;
-
- for (; handler != end; ++handler) {
- if (*handler == current_handler) {
- ++handler;
- break;
- }
- }
- call_handlers(req, handler);
-}
-
-static void on_delegate_request_cb(h2o_timeout_entry_t *entry)
-{
- struct st_delegate_request_deferred_t *args =
- H2O_STRUCT_FROM_MEMBER(struct st_delegate_request_deferred_t, super.timeout, entry);
- h2o_delegate_request(args->super.req, args->current_handler);
-}
-
-void h2o_delegate_request_deferred(h2o_req_t *req, h2o_handler_t *current_handler)
-{
- struct st_delegate_request_deferred_t *args =
- (struct st_delegate_request_deferred_t *)create_deferred_action(req, sizeof(*args), on_delegate_request_cb);
- args->current_handler = current_handler;
-}
-
-void h2o_reprocess_request(h2o_req_t *req, h2o_iovec_t method, const h2o_url_scheme_t *scheme, h2o_iovec_t authority,
- h2o_iovec_t path, h2o_req_overrides_t *overrides, int is_delegated)
-{
- h2o_hostconf_t *hostconf;
-
- retain_original_response(req);
-
- /* close generators and filters that are already running */
- close_generator_and_filters(req);
-
- /* setup the request/response parameters */
- req->method = method;
- req->scheme = scheme;
- req->authority = authority;
- req->path = path;
- req->path_normalized = h2o_url_normalize_path(&req->pool, req->path.base, req->path.len, &req->query_at, &req->norm_indexes);
- req->overrides = overrides;
- req->res_is_delegated |= is_delegated;
- reset_response(req);
-
- /* check the delegation (or reprocess) counter */
- if (req->res_is_delegated) {
- if (req->num_delegated == req->conn->ctx->globalconf->max_delegations) {
- /* TODO log */
- h2o_send_error_502(req, "Gateway Error", "too many internal delegations", 0);
- return;
- }
- ++req->num_delegated;
- } else {
- if (req->num_reprocessed >= 5) {
- /* TODO log */
- h2o_send_error_502(req, "Gateway Error", "too many internal reprocesses", 0);
- return;
- }
- ++req->num_reprocessed;
- }
-
- /* handle the response using the handlers, if hostconf exists */
- h2o_hostconf_t **hosts = is_delegated ? req->conn->ctx->globalconf->hosts : req->conn->hosts;
- if (req->overrides == NULL && (hostconf = find_hostconf(hosts, req->authority, req->scheme->default_port)) != NULL) {
- req->pathconf = NULL;
- process_hosted_request(req, hostconf);
- return;
- }
-
- /* uses the current pathconf, in other words, proxy uses the previous pathconf for building filters */
- h2o__proxy_process_request(req);
-}
-
-static void on_reprocess_request_cb(h2o_timeout_entry_t *entry)
-{
- struct st_reprocess_request_deferred_t *args =
- H2O_STRUCT_FROM_MEMBER(struct st_reprocess_request_deferred_t, super.timeout, entry);
- h2o_reprocess_request(args->super.req, args->method, args->scheme, args->authority, args->path, args->overrides,
- args->is_delegated);
-}
-
-void h2o_reprocess_request_deferred(h2o_req_t *req, h2o_iovec_t method, const h2o_url_scheme_t *scheme, h2o_iovec_t authority,
- h2o_iovec_t path, h2o_req_overrides_t *overrides, int is_delegated)
-{
- struct st_reprocess_request_deferred_t *args =
- (struct st_reprocess_request_deferred_t *)create_deferred_action(req, sizeof(*args), on_reprocess_request_cb);
- args->method = method;
- args->scheme = scheme;
- args->authority = authority;
- args->path = path;
- args->overrides = overrides;
- args->is_delegated = is_delegated;
-}
-
-void h2o_start_response(h2o_req_t *req, h2o_generator_t *generator)
-{
- retain_original_response(req);
-
- /* set generator */
- assert(req->_generator == NULL);
- req->_generator = generator;
-
- /* setup response filters */
- if (req->prefilters != NULL) {
- req->prefilters->on_setup_ostream(req->prefilters, req, &req->_ostr_top);
- } else {
- h2o_setup_next_ostream(req, &req->_ostr_top);
- }
-}
-
-void h2o_send(h2o_req_t *req, h2o_iovec_t *bufs, size_t bufcnt, h2o_send_state_t state)
-{
- assert(req->_generator != NULL);
-
- if (!h2o_send_state_is_in_progress(state))
- req->_generator = NULL;
-
- req->_ostr_top->do_send(req->_ostr_top, req, bufs, bufcnt, state);
-}
-
-h2o_req_prefilter_t *h2o_add_prefilter(h2o_req_t *req, size_t sz)
-{
- h2o_req_prefilter_t *prefilter = h2o_mem_alloc_pool(&req->pool, sz);
- prefilter->next = req->prefilters;
- req->prefilters = prefilter;
- return prefilter;
-}
-
-h2o_ostream_t *h2o_add_ostream(h2o_req_t *req, size_t sz, h2o_ostream_t **slot)
-{
- h2o_ostream_t *ostr = h2o_mem_alloc_pool(&req->pool, sz);
- ostr->next = *slot;
- ostr->do_send = NULL;
- ostr->stop = NULL;
- ostr->start_pull = NULL;
-
- *slot = ostr;
-
- return ostr;
-}
-
-static void apply_env(h2o_req_t *req, h2o_envconf_t *env)
-{
- size_t i;
-
- if (env->parent != NULL)
- apply_env(req, env->parent);
- for (i = 0; i != env->unsets.size; ++i)
- h2o_req_unsetenv(req, env->unsets.entries[i].base, env->unsets.entries[i].len);
- for (i = 0; i != env->sets.size; i += 2)
- *h2o_req_getenv(req, env->sets.entries[i].base, env->sets.entries[i].len, 1) = env->sets.entries[i + 1];
-}
-
-void h2o_req_bind_conf(h2o_req_t *req, h2o_hostconf_t *hostconf, h2o_pathconf_t *pathconf)
-{
- req->hostconf = hostconf;
- req->pathconf = pathconf;
- if (pathconf->env != NULL)
- apply_env(req, pathconf->env);
-}
-
-void h2o_ostream_send_next(h2o_ostream_t *ostream, h2o_req_t *req, h2o_iovec_t *bufs, size_t bufcnt, h2o_send_state_t state)
-{
- if (!h2o_send_state_is_in_progress(state)) {
- assert(req->_ostr_top == ostream);
- req->_ostr_top = ostream->next;
- } else if (bufcnt == 0) {
- h2o_timeout_link(req->conn->ctx->loop, &req->conn->ctx->zero_timeout, &req->_timeout_entry);
- return;
- }
- ostream->next->do_send(ostream->next, req, bufs, bufcnt, state);
-}
-
-void h2o_req_fill_mime_attributes(h2o_req_t *req)
-{
- ssize_t content_type_index;
- h2o_mimemap_type_t *mime;
-
- if (req->res.mime_attr != NULL)
- return;
-
- if ((content_type_index = h2o_find_header(&req->res.headers, H2O_TOKEN_CONTENT_TYPE, -1)) != -1 &&
- (mime = h2o_mimemap_get_type_by_mimetype(req->pathconf->mimemap, req->res.headers.entries[content_type_index].value, 0)) !=
- NULL)
- req->res.mime_attr = &mime->data.attr;
- else
- req->res.mime_attr = &h2o_mime_attributes_as_is;
-}
-
-void h2o_send_inline(h2o_req_t *req, const char *body, size_t len)
-{
- static h2o_generator_t generator = {NULL, NULL};
-
- h2o_iovec_t buf = h2o_strdup(&req->pool, body, len);
- /* the function intentionally does not set the content length, since it may be used for generating 304 response, etc. */
- /* req->res.content_length = buf.len; */
-
- h2o_start_response(req, &generator);
-
- if (h2o_memis(req->input.method.base, req->input.method.len, H2O_STRLIT("HEAD")))
- h2o_send(req, NULL, 0, H2O_SEND_STATE_FINAL);
- else
- h2o_send(req, &buf, 1, H2O_SEND_STATE_FINAL);
-}
-
-void h2o_send_error_generic(h2o_req_t *req, int status, const char *reason, const char *body, int flags)
-{
- if (req->pathconf == NULL) {
- h2o_hostconf_t *hostconf = setup_before_processing(req);
- h2o_req_bind_conf(req, hostconf, &hostconf->fallback_path);
- }
-
- if ((flags & H2O_SEND_ERROR_HTTP1_CLOSE_CONNECTION) != 0)
- req->http1_is_persistent = 0;
-
- req->res.status = status;
- req->res.reason = reason;
- req->res.content_length = strlen(body);
-
- if ((flags & H2O_SEND_ERROR_KEEP_HEADERS) == 0)
- memset(&req->res.headers, 0, sizeof(req->res.headers));
-
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, NULL, H2O_STRLIT("text/plain; charset=utf-8"));
-
- h2o_send_inline(req, body, SIZE_MAX);
-}
-
-#define DECL_SEND_ERROR_DEFERRED(status_) \
- static void send_error_deferred_cb_##status_(h2o_timeout_entry_t *entry) \
- { \
- struct st_send_error_deferred_t *args = H2O_STRUCT_FROM_MEMBER(struct st_send_error_deferred_t, _timeout, entry); \
- reset_response(args->req); \
- args->req->conn->ctx->emitted_error_status[H2O_STATUS_ERROR_##status_]++; \
- h2o_send_error_generic(args->req, args->status, args->reason, args->body, args->flags); \
- } \
- \
- static void h2o_send_error_deferred_##status_(h2o_req_t *req, const char *reason, const char *body, int flags) \
- { \
- struct st_send_error_deferred_t *args = h2o_mem_alloc_pool(&req->pool, sizeof(*args)); \
- *args = (struct st_send_error_deferred_t){req, status_, reason, body, flags}; \
- args->_timeout.cb = send_error_deferred_cb_##status_; \
- h2o_timeout_link(req->conn->ctx->loop, &req->conn->ctx->zero_timeout, &args->_timeout); \
- }
-
-DECL_SEND_ERROR_DEFERRED(502)
-
-#undef DECL_SEND_ERROR_DEFERRED
-
-void h2o_req_log_error(h2o_req_t *req, const char *module, const char *fmt, ...)
-{
-#define INITIAL_BUF_SIZE 256
-
- char *errbuf = h2o_mem_alloc_pool(&req->pool, INITIAL_BUF_SIZE);
- int errlen;
- va_list args;
-
- va_start(args, fmt);
- errlen = vsnprintf(errbuf, INITIAL_BUF_SIZE, fmt, args);
- va_end(args);
-
- if (errlen >= INITIAL_BUF_SIZE) {
- errbuf = h2o_mem_alloc_pool(&req->pool, errlen + 1);
- va_start(args, fmt);
- errlen = vsnprintf(errbuf, errlen + 1, fmt, args);
- va_end(args);
- }
-
-#undef INITIAL_BUF_SIZE
-
- /* save the log */
- h2o_vector_reserve(&req->pool, &req->error_logs, req->error_logs.size + 1);
- req->error_logs.entries[req->error_logs.size++] = (h2o_req_error_log_t){module, h2o_iovec_init(errbuf, errlen)};
-
- if (req->pathconf->error_log.emit_request_errors) {
- /* build prefix */
- char *prefix = alloca(sizeof("[] in request::") + 32 + strlen(module)), *p = prefix;
- p += sprintf(p, "[%s] in request:", module);
- if (req->path.len < 32) {
- memcpy(p, req->path.base, req->path.len);
- p += req->path.len;
- } else {
- memcpy(p, req->path.base, 29);
- p += 29;
- memcpy(p, "...", 3);
- p += 3;
- }
- *p++ = ':';
- /* use writev(2) to emit error atomically */
- struct iovec vecs[] = {{prefix, p - prefix}, {errbuf, errlen}, {"\n", 1}};
- H2O_BUILD_ASSERT(sizeof(vecs) / sizeof(vecs[0]) < IOV_MAX);
- writev(2, vecs, sizeof(vecs) / sizeof(vecs[0]));
- }
-}
-
-void h2o_send_redirect(h2o_req_t *req, int status, const char *reason, const char *url, size_t url_len)
-{
- if (req->res_is_delegated) {
- h2o_iovec_t method = h2o_get_redirect_method(req->method, status);
- h2o_send_redirect_internal(req, method, url, url_len, 0);
- return;
- }
-
- static h2o_generator_t generator = {NULL, NULL};
- static const h2o_iovec_t body_prefix = {H2O_STRLIT("<!DOCTYPE html><TITLE>Moved</TITLE><P>The document has moved <A HREF=\"")};
- static const h2o_iovec_t body_suffix = {H2O_STRLIT("\">here</A>")};
-
- /* build and send response */
- h2o_iovec_t bufs[3];
- size_t bufcnt;
- if (h2o_memis(req->input.method.base, req->input.method.len, H2O_STRLIT("HEAD"))) {
- req->res.content_length = SIZE_MAX;
- bufcnt = 0;
- } else {
- bufs[0] = body_prefix;
- bufs[1] = h2o_htmlescape(&req->pool, url, url_len);
- bufs[2] = body_suffix;
- bufcnt = 3;
- req->res.content_length = body_prefix.len + bufs[1].len + body_suffix.len;
- }
- req->res.status = status;
- req->res.reason = reason;
- req->res.headers = (h2o_headers_t){NULL};
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_LOCATION, NULL, url, url_len);
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, NULL, H2O_STRLIT("text/html; charset=utf-8"));
- h2o_start_response(req, &generator);
- h2o_send(req, bufs, bufcnt, H2O_SEND_STATE_FINAL);
-}
-
-void h2o_send_redirect_internal(h2o_req_t *req, h2o_iovec_t method, const char *url_str, size_t url_len, int preserve_overrides)
-{
- h2o_url_t url;
-
- /* parse the location URL */
- if (h2o_url_parse_relative(url_str, url_len, &url) != 0) {
- /* TODO log fprintf(stderr, "[proxy] cannot handle location header: %.*s\n", (int)url_len, url); */
- h2o_send_error_deferred_502(req, "Gateway Error", "internal error", 0);
- return;
- }
- /* convert the location to absolute (while creating copies of the values passed to the deferred call) */
- if (url.scheme == NULL)
- url.scheme = req->scheme;
- if (url.authority.base == NULL) {
- if (req->hostconf != NULL)
- url.authority = req->hostconf->authority.hostport;
- else
- url.authority = req->authority;
- } else {
- if (h2o_lcstris(url.authority.base, url.authority.len, req->authority.base, req->authority.len)) {
- url.authority = req->authority;
- } else {
- url.authority = h2o_strdup(&req->pool, url.authority.base, url.authority.len);
- preserve_overrides = 0;
- }
- }
- h2o_iovec_t base_path = req->path;
- h2o_url_resolve_path(&base_path, &url.path);
- url.path = h2o_concat(&req->pool, base_path, url.path);
-
- h2o_reprocess_request_deferred(req, method, url.scheme, url.authority, url.path, preserve_overrides ? req->overrides : NULL, 1);
-}
-
-h2o_iovec_t h2o_get_redirect_method(h2o_iovec_t method, int status)
-{
- if (h2o_memis(method.base, method.len, H2O_STRLIT("POST")) && !(status == 307 || status == 308))
- method = h2o_iovec_init(H2O_STRLIT("GET"));
- return method;
-}
-
-h2o_iovec_t h2o_push_path_in_link_header(h2o_req_t *req, const char *value, size_t value_len)
-{
- int i;
- h2o_iovec_t ret = h2o_iovec_init(value, value_len);
- if (req->conn->callbacks->push_path == NULL)
- return ret;
-
- h2o_iovec_vector_t paths = h2o_extract_push_path_from_link_header(
- &req->pool, value, value_len, req->path_normalized, req->input.scheme, req->input.authority,
- req->res_is_delegated ? req->scheme : NULL, req->res_is_delegated ? &req->authority : NULL, &ret);
- if (paths.size == 0)
- return ret;
-
- for (i = 0; i < paths.size; i++) {
- req->conn->callbacks->push_path(req, paths.entries[i].base, paths.entries[i].len);
- }
- return ret;
-}
diff --git a/web/server/h2o/libh2o/lib/core/token.c b/web/server/h2o/libh2o/lib/core/token.c
deleted file mode 100644
index e21ce2383..000000000
--- a/web/server/h2o/libh2o/lib/core/token.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2014 DeNA Co., Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include "h2o.h"
-#include "token_table.h"
-
-int h2o_iovec_is_token(const h2o_iovec_t *buf)
-{
- return &h2o__tokens[0].buf <= buf && buf <= &h2o__tokens[H2O_MAX_TOKENS - 1].buf;
-}
diff --git a/web/server/h2o/libh2o/lib/core/token_table.h b/web/server/h2o/libh2o/lib/core/token_table.h
deleted file mode 100644
index ae26aa6c4..000000000
--- a/web/server/h2o/libh2o/lib/core/token_table.h
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright (c) 2014 DeNA Co., Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the &quot;Software&quot;), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-/* DO NOT EDIT! generated by tokens.pl */
-h2o_token_t h2o__tokens[] = {{{H2O_STRLIT(":authority")}, 1, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT(":method")}, 2, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT(":path")}, 4, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT(":scheme")}, 6, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT(":status")}, 8, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("accept")}, 19, 0, 0, 0, 0, 1, 0},
- {{H2O_STRLIT("accept-charset")}, 15, 0, 0, 0, 0, 1, 0},
- {{H2O_STRLIT("accept-encoding")}, 16, 0, 0, 0, 0, 1, 0},
- {{H2O_STRLIT("accept-language")}, 17, 0, 0, 0, 0, 1, 0},
- {{H2O_STRLIT("accept-ranges")}, 18, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("access-control-allow-origin")}, 20, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("age")}, 21, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("allow")}, 22, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("authorization")}, 23, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("cache-control")}, 24, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("cache-digest")}, 0, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("connection")}, 0, 1, 1, 0, 1, 0, 0},
- {{H2O_STRLIT("content-disposition")}, 25, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("content-encoding")}, 26, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("content-language")}, 27, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("content-length")}, 28, 0, 0, 1, 0, 0, 0},
- {{H2O_STRLIT("content-location")}, 29, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("content-range")}, 30, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("content-type")}, 31, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("cookie")}, 32, 0, 0, 0, 0, 0, 1},
- {{H2O_STRLIT("date")}, 33, 0, 1, 0, 0, 0, 0},
- {{H2O_STRLIT("etag")}, 34, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("expect")}, 35, 0, 0, 1, 0, 0, 0},
- {{H2O_STRLIT("expires")}, 36, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("from")}, 37, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("host")}, 38, 0, 0, 1, 1, 0, 0},
- {{H2O_STRLIT("http2-settings")}, 0, 1, 0, 0, 1, 0, 0},
- {{H2O_STRLIT("if-match")}, 39, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("if-modified-since")}, 40, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("if-none-match")}, 41, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("if-range")}, 42, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("if-unmodified-since")}, 43, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("keep-alive")}, 0, 1, 1, 0, 0, 0, 0},
- {{H2O_STRLIT("last-modified")}, 44, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("link")}, 45, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("location")}, 46, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("max-forwards")}, 47, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("proxy-authenticate")}, 48, 1, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("proxy-authorization")}, 49, 1, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("range")}, 50, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("referer")}, 51, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("refresh")}, 52, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("retry-after")}, 53, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("server")}, 54, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("set-cookie")}, 55, 0, 0, 0, 0, 0, 1},
- {{H2O_STRLIT("strict-transport-security")}, 56, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("te")}, 0, 1, 0, 0, 1, 0, 0},
- {{H2O_STRLIT("transfer-encoding")}, 57, 1, 1, 1, 1, 0, 0},
- {{H2O_STRLIT("upgrade")}, 0, 1, 1, 1, 1, 0, 0},
- {{H2O_STRLIT("user-agent")}, 58, 0, 0, 0, 0, 1, 0},
- {{H2O_STRLIT("vary")}, 59, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("via")}, 60, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("www-authenticate")}, 61, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("x-compress-hint")}, 0, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("x-forwarded-for")}, 0, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("x-reproxy-url")}, 0, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("x-traffic")}, 0, 0, 0, 0, 0, 0, 0}};
-size_t h2o__num_tokens = 62;
-
-const h2o_token_t *h2o_lookup_token(const char *name, size_t len)
-{
- switch (len) {
- case 2:
- switch (name[1]) {
- case 'e':
- if (memcmp(name, "t", 1) == 0)
- return H2O_TOKEN_TE;
- break;
- }
- break;
- case 3:
- switch (name[2]) {
- case 'a':
- if (memcmp(name, "vi", 2) == 0)
- return H2O_TOKEN_VIA;
- break;
- case 'e':
- if (memcmp(name, "ag", 2) == 0)
- return H2O_TOKEN_AGE;
- break;
- }
- break;
- case 4:
- switch (name[3]) {
- case 'e':
- if (memcmp(name, "dat", 3) == 0)
- return H2O_TOKEN_DATE;
- break;
- case 'g':
- if (memcmp(name, "eta", 3) == 0)
- return H2O_TOKEN_ETAG;
- break;
- case 'k':
- if (memcmp(name, "lin", 3) == 0)
- return H2O_TOKEN_LINK;
- break;
- case 'm':
- if (memcmp(name, "fro", 3) == 0)
- return H2O_TOKEN_FROM;
- break;
- case 't':
- if (memcmp(name, "hos", 3) == 0)
- return H2O_TOKEN_HOST;
- break;
- case 'y':
- if (memcmp(name, "var", 3) == 0)
- return H2O_TOKEN_VARY;
- break;
- }
- break;
- case 5:
- switch (name[4]) {
- case 'e':
- if (memcmp(name, "rang", 4) == 0)
- return H2O_TOKEN_RANGE;
- break;
- case 'h':
- if (memcmp(name, ":pat", 4) == 0)
- return H2O_TOKEN_PATH;
- break;
- case 'w':
- if (memcmp(name, "allo", 4) == 0)
- return H2O_TOKEN_ALLOW;
- break;
- }
- break;
- case 6:
- switch (name[5]) {
- case 'e':
- if (memcmp(name, "cooki", 5) == 0)
- return H2O_TOKEN_COOKIE;
- break;
- case 'r':
- if (memcmp(name, "serve", 5) == 0)
- return H2O_TOKEN_SERVER;
- break;
- case 't':
- if (memcmp(name, "accep", 5) == 0)
- return H2O_TOKEN_ACCEPT;
- if (memcmp(name, "expec", 5) == 0)
- return H2O_TOKEN_EXPECT;
- break;
- }
- break;
- case 7:
- switch (name[6]) {
- case 'd':
- if (memcmp(name, ":metho", 6) == 0)
- return H2O_TOKEN_METHOD;
- break;
- case 'e':
- if (memcmp(name, ":schem", 6) == 0)
- return H2O_TOKEN_SCHEME;
- if (memcmp(name, "upgrad", 6) == 0)
- return H2O_TOKEN_UPGRADE;
- break;
- case 'h':
- if (memcmp(name, "refres", 6) == 0)
- return H2O_TOKEN_REFRESH;
- break;
- case 'r':
- if (memcmp(name, "refere", 6) == 0)
- return H2O_TOKEN_REFERER;
- break;
- case 's':
- if (memcmp(name, ":statu", 6) == 0)
- return H2O_TOKEN_STATUS;
- if (memcmp(name, "expire", 6) == 0)
- return H2O_TOKEN_EXPIRES;
- break;
- }
- break;
- case 8:
- switch (name[7]) {
- case 'e':
- if (memcmp(name, "if-rang", 7) == 0)
- return H2O_TOKEN_IF_RANGE;
- break;
- case 'h':
- if (memcmp(name, "if-matc", 7) == 0)
- return H2O_TOKEN_IF_MATCH;
- break;
- case 'n':
- if (memcmp(name, "locatio", 7) == 0)
- return H2O_TOKEN_LOCATION;
- break;
- }
- break;
- case 9:
- switch (name[8]) {
- case 'c':
- if (memcmp(name, "x-traffi", 8) == 0)
- return H2O_TOKEN_X_TRAFFIC;
- break;
- }
- break;
- case 10:
- switch (name[9]) {
- case 'e':
- if (memcmp(name, "keep-aliv", 9) == 0)
- return H2O_TOKEN_KEEP_ALIVE;
- if (memcmp(name, "set-cooki", 9) == 0)
- return H2O_TOKEN_SET_COOKIE;
- break;
- case 'n':
- if (memcmp(name, "connectio", 9) == 0)
- return H2O_TOKEN_CONNECTION;
- break;
- case 't':
- if (memcmp(name, "user-agen", 9) == 0)
- return H2O_TOKEN_USER_AGENT;
- break;
- case 'y':
- if (memcmp(name, ":authorit", 9) == 0)
- return H2O_TOKEN_AUTHORITY;
- break;
- }
- break;
- case 11:
- switch (name[10]) {
- case 'r':
- if (memcmp(name, "retry-afte", 10) == 0)
- return H2O_TOKEN_RETRY_AFTER;
- break;
- }
- break;
- case 12:
- switch (name[11]) {
- case 'e':
- if (memcmp(name, "content-typ", 11) == 0)
- return H2O_TOKEN_CONTENT_TYPE;
- break;
- case 's':
- if (memcmp(name, "max-forward", 11) == 0)
- return H2O_TOKEN_MAX_FORWARDS;
- break;
- case 't':
- if (memcmp(name, "cache-diges", 11) == 0)
- return H2O_TOKEN_CACHE_DIGEST;
- break;
- }
- break;
- case 13:
- switch (name[12]) {
- case 'd':
- if (memcmp(name, "last-modifie", 12) == 0)
- return H2O_TOKEN_LAST_MODIFIED;
- break;
- case 'e':
- if (memcmp(name, "content-rang", 12) == 0)
- return H2O_TOKEN_CONTENT_RANGE;
- break;
- case 'h':
- if (memcmp(name, "if-none-matc", 12) == 0)
- return H2O_TOKEN_IF_NONE_MATCH;
- break;
- case 'l':
- if (memcmp(name, "cache-contro", 12) == 0)
- return H2O_TOKEN_CACHE_CONTROL;
- if (memcmp(name, "x-reproxy-ur", 12) == 0)
- return H2O_TOKEN_X_REPROXY_URL;
- break;
- case 'n':
- if (memcmp(name, "authorizatio", 12) == 0)
- return H2O_TOKEN_AUTHORIZATION;
- break;
- case 's':
- if (memcmp(name, "accept-range", 12) == 0)
- return H2O_TOKEN_ACCEPT_RANGES;
- break;
- }
- break;
- case 14:
- switch (name[13]) {
- case 'h':
- if (memcmp(name, "content-lengt", 13) == 0)
- return H2O_TOKEN_CONTENT_LENGTH;
- break;
- case 's':
- if (memcmp(name, "http2-setting", 13) == 0)
- return H2O_TOKEN_HTTP2_SETTINGS;
- break;
- case 't':
- if (memcmp(name, "accept-charse", 13) == 0)
- return H2O_TOKEN_ACCEPT_CHARSET;
- break;
- }
- break;
- case 15:
- switch (name[14]) {
- case 'e':
- if (memcmp(name, "accept-languag", 14) == 0)
- return H2O_TOKEN_ACCEPT_LANGUAGE;
- break;
- case 'g':
- if (memcmp(name, "accept-encodin", 14) == 0)
- return H2O_TOKEN_ACCEPT_ENCODING;
- break;
- case 'r':
- if (memcmp(name, "x-forwarded-fo", 14) == 0)
- return H2O_TOKEN_X_FORWARDED_FOR;
- break;
- case 't':
- if (memcmp(name, "x-compress-hin", 14) == 0)
- return H2O_TOKEN_X_COMPRESS_HINT;
- break;
- }
- break;
- case 16:
- switch (name[15]) {
- case 'e':
- if (memcmp(name, "content-languag", 15) == 0)
- return H2O_TOKEN_CONTENT_LANGUAGE;
- if (memcmp(name, "www-authenticat", 15) == 0)
- return H2O_TOKEN_WWW_AUTHENTICATE;
- break;
- case 'g':
- if (memcmp(name, "content-encodin", 15) == 0)
- return H2O_TOKEN_CONTENT_ENCODING;
- break;
- case 'n':
- if (memcmp(name, "content-locatio", 15) == 0)
- return H2O_TOKEN_CONTENT_LOCATION;
- break;
- }
- break;
- case 17:
- switch (name[16]) {
- case 'e':
- if (memcmp(name, "if-modified-sinc", 16) == 0)
- return H2O_TOKEN_IF_MODIFIED_SINCE;
- break;
- case 'g':
- if (memcmp(name, "transfer-encodin", 16) == 0)
- return H2O_TOKEN_TRANSFER_ENCODING;
- break;
- }
- break;
- case 18:
- switch (name[17]) {
- case 'e':
- if (memcmp(name, "proxy-authenticat", 17) == 0)
- return H2O_TOKEN_PROXY_AUTHENTICATE;
- break;
- }
- break;
- case 19:
- switch (name[18]) {
- case 'e':
- if (memcmp(name, "if-unmodified-sinc", 18) == 0)
- return H2O_TOKEN_IF_UNMODIFIED_SINCE;
- break;
- case 'n':
- if (memcmp(name, "content-dispositio", 18) == 0)
- return H2O_TOKEN_CONTENT_DISPOSITION;
- if (memcmp(name, "proxy-authorizatio", 18) == 0)
- return H2O_TOKEN_PROXY_AUTHORIZATION;
- break;
- }
- break;
- case 25:
- switch (name[24]) {
- case 'y':
- if (memcmp(name, "strict-transport-securit", 24) == 0)
- return H2O_TOKEN_STRICT_TRANSPORT_SECURITY;
- break;
- }
- break;
- case 27:
- switch (name[26]) {
- case 'n':
- if (memcmp(name, "access-control-allow-origi", 26) == 0)
- return H2O_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
- break;
- }
- break;
- }
-
- return NULL;
-}
diff --git a/web/server/h2o/libh2o/lib/core/util.c b/web/server/h2o/libh2o/lib/core/util.c
deleted file mode 100644
index 50d2b2493..000000000
--- a/web/server/h2o/libh2o/lib/core/util.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Satoh Hiroh
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <assert.h>
-#include <inttypes.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include "h2o.h"
-#include "h2o/http1.h"
-#include "h2o/http2.h"
-
-struct st_h2o_accept_data_t {
- h2o_accept_ctx_t *ctx;
- h2o_socket_t *sock;
- h2o_timeout_entry_t timeout;
- h2o_memcached_req_t *async_resumption_get_req;
- struct timeval connected_at;
-};
-
-static void on_accept_timeout(h2o_timeout_entry_t *entry);
-
-static struct st_h2o_accept_data_t *create_accept_data(h2o_accept_ctx_t *ctx, h2o_socket_t *sock, struct timeval connected_at)
-{
- struct st_h2o_accept_data_t *data = h2o_mem_alloc(sizeof(*data));
-
- data->ctx = ctx;
- data->sock = sock;
- data->timeout = (h2o_timeout_entry_t){0};
- data->timeout.cb = on_accept_timeout;
- h2o_timeout_link(ctx->ctx->loop, &ctx->ctx->handshake_timeout, &data->timeout);
- data->async_resumption_get_req = NULL;
- data->connected_at = connected_at;
-
- sock->data = data;
- return data;
-}
-
-static void free_accept_data(struct st_h2o_accept_data_t *data)
-{
- assert(data->async_resumption_get_req == NULL);
- h2o_timeout_unlink(&data->timeout);
- free(data);
-}
-
-static struct {
- h2o_memcached_context_t *memc;
- unsigned expiration;
-} async_resumption_context;
-
-static void async_resumption_on_get(h2o_iovec_t session_data, void *_accept_data)
-{
- struct st_h2o_accept_data_t *accept_data = _accept_data;
- accept_data->async_resumption_get_req = NULL;
- h2o_socket_ssl_resume_server_handshake(accept_data->sock, session_data);
-}
-
-static void async_resumption_get(h2o_socket_t *sock, h2o_iovec_t session_id)
-{
- struct st_h2o_accept_data_t *data = sock->data;
-
- data->async_resumption_get_req =
- h2o_memcached_get(async_resumption_context.memc, data->ctx->libmemcached_receiver, session_id, async_resumption_on_get,
- data, H2O_MEMCACHED_ENCODE_KEY | H2O_MEMCACHED_ENCODE_VALUE);
-}
-
-static void async_resumption_new(h2o_iovec_t session_id, h2o_iovec_t session_data)
-{
- h2o_memcached_set(async_resumption_context.memc, session_id, session_data,
- (uint32_t)time(NULL) + async_resumption_context.expiration,
- H2O_MEMCACHED_ENCODE_KEY | H2O_MEMCACHED_ENCODE_VALUE);
-}
-
-void h2o_accept_setup_async_ssl_resumption(h2o_memcached_context_t *memc, unsigned expiration)
-{
- async_resumption_context.memc = memc;
- async_resumption_context.expiration = expiration;
- h2o_socket_ssl_async_resumption_init(async_resumption_get, async_resumption_new);
-}
-
-void on_accept_timeout(h2o_timeout_entry_t *entry)
-{
- /* TODO log */
- struct st_h2o_accept_data_t *data = H2O_STRUCT_FROM_MEMBER(struct st_h2o_accept_data_t, timeout, entry);
- if (data->async_resumption_get_req != NULL) {
- h2o_memcached_cancel_get(async_resumption_context.memc, data->async_resumption_get_req);
- data->async_resumption_get_req = NULL;
- }
- h2o_socket_t *sock = data->sock;
- free_accept_data(data);
- h2o_socket_close(sock);
-}
-
-static void on_ssl_handshake_complete(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_accept_data_t *data = sock->data;
- sock->data = NULL;
-
- if (err != NULL) {
- h2o_socket_close(sock);
- goto Exit;
- }
-
- h2o_iovec_t proto = h2o_socket_ssl_get_selected_protocol(sock);
- const h2o_iovec_t *ident;
- for (ident = h2o_http2_alpn_protocols; ident->len != 0; ++ident) {
- if (proto.len == ident->len && memcmp(proto.base, ident->base, proto.len) == 0) {
- /* connect as http2 */
- h2o_http2_accept(data->ctx, sock, data->connected_at);
- goto Exit;
- }
- }
- /* connect as http1 */
- h2o_http1_accept(data->ctx, sock, data->connected_at);
-
-Exit:
- free_accept_data(data);
-}
-
-static ssize_t parse_proxy_line(char *src, size_t len, struct sockaddr *sa, socklen_t *salen)
-{
-#define CHECK_EOF() \
- if (p == end) \
- return -2
-#define EXPECT_CHAR(ch) \
- do { \
- CHECK_EOF(); \
- if (*p++ != ch) \
- return -1; \
- } while (0)
-#define SKIP_TO_WS() \
- do { \
- do { \
- CHECK_EOF(); \
- } while (*p++ != ' '); \
- --p; \
- } while (0)
-
- char *p = src, *end = p + len;
- void *addr;
- in_port_t *port;
-
- /* "PROXY "*/
- EXPECT_CHAR('P');
- EXPECT_CHAR('R');
- EXPECT_CHAR('O');
- EXPECT_CHAR('X');
- EXPECT_CHAR('Y');
- EXPECT_CHAR(' ');
-
- /* "TCP[46] " */
- CHECK_EOF();
- if (*p++ != 'T') {
- *salen = 0; /* indicate that no data has been obtained */
- goto SkipToEOL;
- }
- EXPECT_CHAR('C');
- EXPECT_CHAR('P');
- CHECK_EOF();
- switch (*p++) {
- case '4':
- *salen = sizeof(struct sockaddr_in);
- memset(sa, 0, sizeof(struct sockaddr_in));
- sa->sa_family = AF_INET;
- addr = &((struct sockaddr_in *)sa)->sin_addr;
- port = &((struct sockaddr_in *)sa)->sin_port;
- break;
- case '6':
- *salen = sizeof(struct sockaddr_in6);
- memset(sa, 0, sizeof(struct sockaddr_in6));
- sa->sa_family = AF_INET6;
- addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
- port = &((struct sockaddr_in6 *)sa)->sin6_port;
- break;
- default:
- return -1;
- }
- EXPECT_CHAR(' ');
-
- /* parse peer address */
- char *addr_start = p;
- SKIP_TO_WS();
- *p = '\0';
- if (inet_pton(sa->sa_family, addr_start, addr) != 1)
- return -1;
- *p++ = ' ';
-
- /* skip local address */
- SKIP_TO_WS();
- ++p;
-
- /* parse peer port */
- char *port_start = p;
- SKIP_TO_WS();
- *p = '\0';
- unsigned short usval;
- if (sscanf(port_start, "%hu", &usval) != 1)
- return -1;
- *port = htons(usval);
- *p++ = ' ';
-
-SkipToEOL:
- do {
- CHECK_EOF();
- } while (*p++ != '\r');
- CHECK_EOF();
- if (*p++ != '\n')
- return -2;
- return p - src;
-
-#undef CHECK_EOF
-#undef EXPECT_CHAR
-#undef SKIP_TO_WS
-}
-
-static void on_read_proxy_line(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_accept_data_t *data = sock->data;
-
- if (err != NULL) {
- free_accept_data(data);
- h2o_socket_close(sock);
- return;
- }
-
- struct sockaddr_storage addr;
- socklen_t addrlen;
- ssize_t r = parse_proxy_line(sock->input->bytes, sock->input->size, (void *)&addr, &addrlen);
- switch (r) {
- case -1: /* error, just pass the input to the next handler */
- break;
- case -2: /* incomplete */
- return;
- default:
- h2o_buffer_consume(&sock->input, r);
- if (addrlen != 0)
- h2o_socket_setpeername(sock, (void *)&addr, addrlen);
- break;
- }
-
- if (data->ctx->ssl_ctx != NULL) {
- h2o_socket_ssl_handshake(sock, data->ctx->ssl_ctx, NULL, on_ssl_handshake_complete);
- } else {
- struct st_h2o_accept_data_t *data = sock->data;
- sock->data = NULL;
- h2o_http1_accept(data->ctx, sock, data->connected_at);
- free_accept_data(data);
- }
-}
-
-void h2o_accept(h2o_accept_ctx_t *ctx, h2o_socket_t *sock)
-{
- struct timeval connected_at = *h2o_get_timestamp(ctx->ctx, NULL, NULL);
-
- if (ctx->expect_proxy_line || ctx->ssl_ctx != NULL) {
- create_accept_data(ctx, sock, connected_at);
- if (ctx->expect_proxy_line) {
- h2o_socket_read_start(sock, on_read_proxy_line);
- } else {
- h2o_socket_ssl_handshake(sock, ctx->ssl_ctx, NULL, on_ssl_handshake_complete);
- }
- } else {
- h2o_http1_accept(ctx, sock, connected_at);
- }
-}
-
-size_t h2o_stringify_protocol_version(char *dst, int version)
-{
- char *p = dst;
-
- if (version < 0x200) {
- assert(version <= 0x109);
-#define PREFIX "HTTP/1."
- memcpy(p, PREFIX, sizeof(PREFIX) - 1);
- p += sizeof(PREFIX) - 1;
-#undef PREFIX
- *p++ = '0' + (version & 0xff);
- } else {
-#define PROTO "HTTP/2"
- memcpy(p, PROTO, sizeof(PROTO) - 1);
- p += sizeof(PROTO) - 1;
-#undef PROTO
- }
-
- *p = '\0';
- return p - dst;
-}
-
-size_t h2o_stringify_proxy_header(h2o_conn_t *conn, char *buf)
-{
- struct sockaddr_storage ss;
- socklen_t sslen;
- size_t strlen;
- uint16_t peerport;
- char *dst = buf;
-
- if ((sslen = conn->callbacks->get_peername(conn, (void *)&ss)) == 0)
- goto Unknown;
- switch (ss.ss_family) {
- case AF_INET:
- memcpy(dst, "PROXY TCP4 ", 11);
- dst += 11;
- break;
- case AF_INET6:
- memcpy(dst, "PROXY TCP6 ", 11);
- dst += 11;
- break;
- default:
- goto Unknown;
- }
- if ((strlen = h2o_socket_getnumerichost((void *)&ss, sslen, dst)) == SIZE_MAX)
- goto Unknown;
- dst += strlen;
- *dst++ = ' ';
-
- peerport = h2o_socket_getport((void *)&ss);
-
- if ((sslen = conn->callbacks->get_sockname(conn, (void *)&ss)) == 0)
- goto Unknown;
- if ((strlen = h2o_socket_getnumerichost((void *)&ss, sslen, dst)) == SIZE_MAX)
- goto Unknown;
- dst += strlen;
- *dst++ = ' ';
-
- dst += sprintf(dst, "%" PRIu16 " %" PRIu16 "\r\n", peerport, (uint16_t)h2o_socket_getport((void *)&ss));
-
- return dst - buf;
-
-Unknown:
- memcpy(buf, "PROXY UNKNOWN\r\n", 15);
- return 15;
-}
-
-static void push_one_path(h2o_mem_pool_t *pool, h2o_iovec_vector_t *paths_to_push, h2o_iovec_t url, h2o_iovec_t base_path,
- const h2o_url_scheme_t *input_scheme, h2o_iovec_t input_authority, const h2o_url_scheme_t *base_scheme,
- h2o_iovec_t *base_authority)
-{
- h2o_url_t parsed, resolved;
-
- /* check the authority, and extract absolute path */
- if (h2o_url_parse_relative(url.base, url.len, &parsed) != 0)
- return;
-
- /* fast-path for abspath form */
- if (base_scheme == NULL && parsed.scheme == NULL && parsed.authority.base == NULL && url.len != 0 && url.base[0] == '/') {
- h2o_vector_reserve(pool, paths_to_push, paths_to_push->size + 1);
- paths_to_push->entries[paths_to_push->size++] = h2o_strdup(pool, url.base, url.len);
- return;
- }
-
- /* check scheme and authority if given URL contains either of the two, or if base is specified */
- h2o_url_t base = {input_scheme, input_authority, {NULL}, base_path, 65535};
- if (base_scheme != NULL) {
- base.scheme = base_scheme;
- base.authority = *base_authority;
- }
- h2o_url_resolve(pool, &base, &parsed, &resolved);
- if (input_scheme != resolved.scheme)
- return;
- if (!h2o_lcstris(input_authority.base, input_authority.len, resolved.authority.base, resolved.authority.len))
- return;
-
- h2o_vector_reserve(pool, paths_to_push, paths_to_push->size + 1);
- paths_to_push->entries[paths_to_push->size++] = resolved.path;
-}
-
-h2o_iovec_vector_t h2o_extract_push_path_from_link_header(h2o_mem_pool_t *pool, const char *value, size_t value_len,
- h2o_iovec_t base_path, const h2o_url_scheme_t *input_scheme,
- h2o_iovec_t input_authority, const h2o_url_scheme_t *base_scheme,
- h2o_iovec_t *base_authority, h2o_iovec_t *filtered_value)
-{
- h2o_iovec_vector_t paths_to_push = {NULL};
- h2o_iovec_t iter = h2o_iovec_init(value, value_len), token_value;
- const char *token;
- size_t token_len;
- *filtered_value = h2o_iovec_init(NULL, 0);
-
-#define PUSH_FILTERED_VALUE(s, e) \
- do { \
- if (filtered_value->len != 0) { \
- memcpy(filtered_value->base + filtered_value->len, ", ", 2); \
- filtered_value->len += 2; \
- } \
- memcpy(filtered_value->base + filtered_value->len, (s), (e) - (s)); \
- filtered_value->len += (e) - (s); \
- } while (0)
-
- /* extract URL values from Link: </pushed.css>; rel=preload */
- do {
- if ((token = h2o_next_token(&iter, ';', &token_len, NULL)) == NULL)
- break;
- /* first element should be <URL> */
- if (!(token_len >= 2 && token[0] == '<' && token[token_len - 1] == '>'))
- break;
- h2o_iovec_t url_with_brackets = h2o_iovec_init(token, token_len);
- /* find rel=preload */
- int preload = 0, nopush = 0, push_only = 0;
- while ((token = h2o_next_token(&iter, ';', &token_len, &token_value)) != NULL &&
- !h2o_memis(token, token_len, H2O_STRLIT(","))) {
- if (h2o_lcstris(token, token_len, H2O_STRLIT("rel")) &&
- h2o_lcstris(token_value.base, token_value.len, H2O_STRLIT("preload"))) {
- preload++;
- } else if (h2o_lcstris(token, token_len, H2O_STRLIT("nopush"))) {
- nopush++;
- } else if (h2o_lcstris(token, token_len, H2O_STRLIT("x-http2-push-only"))) {
- push_only++;
- }
- }
- /* push the path */
- if (!nopush && preload)
- push_one_path(pool, &paths_to_push, h2o_iovec_init(url_with_brackets.base + 1, url_with_brackets.len - 2), base_path,
- input_scheme, input_authority, base_scheme, base_authority);
- /* store the elements that needs to be preserved to filtered_value */
- if (push_only) {
- if (filtered_value->base == NULL) {
- /* the max. size of filtered_value would be x2 in the worst case, when "," is converted to ", " */
- filtered_value->base = h2o_mem_alloc_pool(pool, value_len * 2);
- const char *prev_comma = h2o_memrchr(value, ',', url_with_brackets.base - value);
- if (prev_comma != NULL)
- PUSH_FILTERED_VALUE(value, prev_comma);
- }
- } else if (filtered_value->base != NULL) {
- PUSH_FILTERED_VALUE(url_with_brackets.base, token != NULL ? token : value + value_len);
- }
- } while (token != NULL);
-
- if (filtered_value->base != NULL) {
- if (token != NULL)
- PUSH_FILTERED_VALUE(token, value + value_len);
- } else {
- *filtered_value = h2o_iovec_init(value, value_len);
- }
-
- return paths_to_push;
-
-#undef PUSH_FILTERED_VALUE
-}
-
-int h2o_get_compressible_types(const h2o_headers_t *headers)
-{
- size_t header_index;
- int compressible_types = 0;
-
- for (header_index = 0; header_index != headers->size; ++header_index) {
- const h2o_header_t *header = headers->entries + header_index;
- if (H2O_UNLIKELY(header->name == &H2O_TOKEN_ACCEPT_ENCODING->buf)) {
- h2o_iovec_t iter = h2o_iovec_init(header->value.base, header->value.len);
- const char *token = NULL;
- size_t token_len = 0;
- while ((token = h2o_next_token(&iter, ',', &token_len, NULL)) != NULL) {
- if (h2o_lcstris(token, token_len, H2O_STRLIT("gzip")))
- compressible_types |= H2O_COMPRESSIBLE_GZIP;
- else if (h2o_lcstris(token, token_len, H2O_STRLIT("br")))
- compressible_types |= H2O_COMPRESSIBLE_BROTLI;
- }
- }
- }
-
- return compressible_types;
-}
-
-h2o_iovec_t h2o_build_destination(h2o_req_t *req, const char *prefix, size_t prefix_len, int use_path_normalized)
-{
- h2o_iovec_t parts[4];
- size_t num_parts = 0;
- int conf_ends_with_slash = req->pathconf->path.base[req->pathconf->path.len - 1] == '/';
- int prefix_ends_with_slash = prefix[prefix_len - 1] == '/';
-
- /* destination starts with given prefix */
- parts[num_parts++] = h2o_iovec_init(prefix, prefix_len);
-
- /* make adjustments depending on the trailing slashes */
- if (conf_ends_with_slash != prefix_ends_with_slash) {
- if (conf_ends_with_slash) {
- parts[num_parts++] = h2o_iovec_init(H2O_STRLIT("/"));
- } else {
- if (req->path_normalized.len != req->pathconf->path.len)
- parts[num_parts - 1].len -= 1;
- }
- }
-
- /* append suffix path and query */
-
- if (use_path_normalized) {
- parts[num_parts++] = h2o_uri_escape(&req->pool, req->path_normalized.base + req->pathconf->path.len,
- req->path_normalized.len - req->pathconf->path.len, "/@:");
- if (req->query_at != SIZE_MAX) {
- parts[num_parts++] = h2o_iovec_init(req->path.base + req->query_at, req->path.len - req->query_at);
- }
- } else {
- if (req->path.len > 1) {
- /*
- * When proxying, we want to modify the input URL as little
- * as possible. We use norm_indexes to find the start of
- * the path we want to forward.
- */
- size_t next_unnormalized;
- if (req->norm_indexes && req->pathconf->path.len > 1) {
- next_unnormalized = req->norm_indexes[req->pathconf->path.len - 1];
- } else {
- next_unnormalized = req->pathconf->path.len;
- }
-
- /*
- * Special case: the input path didn't have any '/' including the first,
- * so the first character is actually found at '0'
- */
- if (req->path.base[0] != '/' && next_unnormalized == 1) {
- next_unnormalized = 0;
- }
- parts[num_parts++] = (h2o_iovec_t){req->path.base + next_unnormalized, req->path.len - next_unnormalized};
- }
- }
-
- return h2o_concat_list(&req->pool, parts, num_parts);
-}
-
-/* h2-14 and h2-16 are kept for backwards compatibility, as they are often used */
-#define ALPN_ENTRY(s) \
- { \
- H2O_STRLIT(s) \
- }
-#define ALPN_PROTOCOLS_CORE ALPN_ENTRY("h2"), ALPN_ENTRY("h2-16"), ALPN_ENTRY("h2-14")
-#define NPN_PROTOCOLS_CORE \
- "\x02" \
- "h2" \
- "\x05" \
- "h2-16" \
- "\x05" \
- "h2-14"
-
-static const h2o_iovec_t http2_alpn_protocols[] = {ALPN_PROTOCOLS_CORE, {NULL}};
-const h2o_iovec_t *h2o_http2_alpn_protocols = http2_alpn_protocols;
-
-static const h2o_iovec_t alpn_protocols[] = {ALPN_PROTOCOLS_CORE, {H2O_STRLIT("http/1.1")}, {NULL}};
-const h2o_iovec_t *h2o_alpn_protocols = alpn_protocols;
-
-const char *h2o_http2_npn_protocols = NPN_PROTOCOLS_CORE;
-const char *h2o_npn_protocols = NPN_PROTOCOLS_CORE "\x08"
- "http/1.1";
-
-uint64_t h2o_connection_id = 0;