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 */ h2o_configurator_t *c = h2o_configurator_create(conf, sizeof(*c)); h2o_configurator_define_command(c, "limit-request-body", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_limit_request_body); h2o_configurator_define_command(c, "max-delegations", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_max_delegations); h2o_configurator_define_command(c, "http1-request-timeout", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_http1_request_timeout); h2o_configurator_define_command(c, "http1-upgrade-to-http2", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_http1_upgrade_to_http2); h2o_configurator_define_command(c, "http2-idle-timeout", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_http2_idle_timeout); h2o_configurator_define_command(c, "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, "http2-reprioritize-blocking-assets", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_http2_reprioritize_blocking_assets); } }
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 = {}, semi_deferred = {}; size_t i; int ret = -1; if (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 */ 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_push_back(NULL, &semi_deferred, ((struct st_cmd_value_t){cmd, value})); } else if ((cmd->flags & H2O_CONFIGURATOR_FLAG_DEFERRED) != 0) {
int h2o_configurator_apply_commands(h2o_configurator_context_t *ctx, yoml_t *node, int flags_mask, const char **ignore_commands) { struct { h2o_configurator_command_t *cmd; yoml_t *value; } *deferred; size_t num_deferred = 0, i; if (node->type != YOML_TYPE_MAPPING) { h2o_configurator_errprintf(NULL, node, "node must be a MAPPING"); return -1; } deferred = alloca(sizeof(*deferred) * node->data.mapping.size); /* call on_enter of every configurator */ if (setup_configurators(ctx, 1, node) != 0) return -1; /* handle the configuration commands */ 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"); return -1; } 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); return -1; } if ((cmd->flags & flags_mask) == 0) { h2o_configurator_errprintf(cmd, key, "the command cannot be used at this level"); return -1; } /* 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"); return -1; } break; case YOML_TYPE_SEQUENCE: if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE) == 0) { h2o_configurator_errprintf(cmd, value, "argument cannot be a sequence"); return -1; } break; case YOML_TYPE_MAPPING: if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING) == 0) { h2o_configurator_errprintf(cmd, value, "argument cannot be a mapping"); return -1; } break; default: assert(!"unreachable"); break; } } /* handle the command (or keep it for later execution) */ if ((cmd->flags & H2O_CONFIGURATOR_FLAG_DEFERRED) != 0) { deferred[num_deferred].cmd = cmd; deferred[num_deferred].value = value; ++num_deferred; } else { if (cmd->cb(cmd, ctx, value) != 0) return -1; } SkipCommand: ; } for (i = 0; i != num_deferred; ++i) { if (deferred[i].cmd->cb(deferred[i].cmd, ctx, deferred[i].value) != 0) return -1; } /* call on_enter of every configurator */ if (setup_configurators(ctx, 0, node) != 0) return -1; return 0; }