1 /*
2  * Copyright (c) 2014 DeNA Co., Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */
22 #ifndef h2o__configurator_h
23 #define h2o__configurator_h
24 
25 #include "yoml.h"
26 
27 enum {
28     H2O_CONFIGURATOR_FLAG_GLOBAL = 0x1,
29     H2O_CONFIGURATOR_FLAG_HOST = 0x2,
30     H2O_CONFIGURATOR_FLAG_PATH = 0x4,
31     H2O_CONFIGURATOR_FLAG_EXTENSION = 0x8,
32     H2O_CONFIGURATOR_FLAG_ALL_LEVELS =
33         H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_HOST | H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_EXTENSION,
34     H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR = 0x100,
35     H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE = 0x200,
36     H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING = 0x400,
37     H2O_CONFIGURATOR_FLAG_DEFERRED = 0x1000,
38     H2O_CONFIGURATOR_FLAG_SEMI_DEFERRED = 0x2000 /* used by file.custom-handler (invoked before hosts,paths,file-dir, etc.) */
39 };
40 
41 #define H2O_CONFIGURATOR_NUM_LEVELS 4
42 
43 typedef struct st_h2o_configurator_context_t {
44     /**
45      * pointer to globalconf
46      */
47     h2o_globalconf_t *globalconf;
48     /**
49      * pointer to hostconf, or NULL if the context is above host level
50      */
51     h2o_hostconf_t *hostconf;
52     /**
53      * pointer to pathconf (either at path level or custom handler level), or NULL
54      */
55     h2o_pathconf_t *pathconf;
56     /**
57      * pointer to mimemap
58      */
59     h2o_mimemap_t **mimemap;
60     /**
61      * pointer to env
62      */
63     h2o_envconf_t *env;
64     /**
65      * if is a dry run
66      */
67     int dry_run;
68     /**
69      * parent context (or NULL if the context is at global level)
70      */
71     struct st_h2o_configurator_context_t *parent;
72 } h2o_configurator_context_t;
73 
74 typedef int (*h2o_configurator_dispose_cb)(h2o_configurator_t *configurator);
75 typedef int (*h2o_configurator_enter_cb)(h2o_configurator_t *configurator, h2o_configurator_context_t *ctx, yoml_t *node);
76 typedef int (*h2o_configurator_exit_cb)(h2o_configurator_t *configurator, h2o_configurator_context_t *ctx, yoml_t *node);
77 typedef int (*h2o_configurator_command_cb)(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node);
78 typedef h2o_headers_command_t **(*h2o_configurator_get_headers_commands_cb)(h2o_configurator_t *conf);
79 
80 struct st_h2o_configurator_command_t {
81     /**
82      * configurator to which the command belongs
83      */
84     h2o_configurator_t *configurator;
85     /**
86      * name of the command handled by the configurator
87      */
88     const char *name;
89     /**
90      * flags
91      */
92     int flags;
93     /**
94      * mandatory callback called to handle the command
95      */
96     h2o_configurator_command_cb cb;
97 };
98 
99 /**
100  * basic structure of a configurator (handles a configuration command)
101  */
102 struct st_h2o_configurator_t {
103     h2o_linklist_t _link;
104     /**
105      * optional callback called when the global config is being disposed
106      */
107     h2o_configurator_dispose_cb dispose;
108     /**
109      * optional callback called before the configuration commands are handled
110      */
111     h2o_configurator_enter_cb enter;
112     /**
113      * optional callback called after all the configuration commands are handled
114      */
115     h2o_configurator_exit_cb exit;
116     /**
117      * list of commands
118      */
119     H2O_VECTOR(h2o_configurator_command_t) commands;
120 };
121 
122 /**
123  * registers a configurator
124  */
125 h2o_configurator_t *h2o_configurator_create(h2o_globalconf_t *conf, size_t sz);
126 /**
127  *
128  */
129 void h2o_configurator_define_command(h2o_configurator_t *configurator, const char *name, int flags, h2o_configurator_command_cb cb);
130 /**
131  * returns a configurator of given command name
132  * @return configurator for given name or NULL if not found
133  */
134 h2o_configurator_command_t *h2o_configurator_get_command(h2o_globalconf_t *conf, const char *name);
135 /**
136  * applies the configuration to the context
137  * @return 0 if successful, -1 if not
138  */
139 int h2o_configurator_apply(h2o_globalconf_t *config, yoml_t *node, int dry_run);
140 /**
141  *
142  */
143 int h2o_configurator_apply_commands(h2o_configurator_context_t *ctx, yoml_t *node, int flags_mask, const char **ignore_commands);
144 /**
145  * emits configuration error
146  */
147 void h2o_configurator_errprintf(h2o_configurator_command_t *cmd, yoml_t *node, const char *reason, ...)
148     __attribute__((format(printf, 3, 4)));
149 /**
150  * interprets the configuration value using sscanf, or prints an error upon failure
151  * @param configurator configurator
152  * @param node configuration value
153  * @param fmt scanf-style format string
154  * @return 0 if successful, -1 if not
155  */
156 int h2o_configurator_scanf(h2o_configurator_command_t *cmd, yoml_t *node, const char *fmt, ...)
157     __attribute__((format(scanf, 3, 4)));
158 /**
159  * interprets the configuration value and returns the index of the matched string within the candidate strings, or prints an error
160  * upon failure
161  * @param configurator configurator
162  * @param node configuration value
163  * @param candidates a comma-separated list of strings (should not contain whitespaces)
164  * @return index of the matched string within the given list, or -1 if none of them matched
165  */
166 ssize_t h2o_configurator_get_one_of(h2o_configurator_command_t *cmd, yoml_t *node, const char *candidates);
167 /**
168  * extracts values (required and optional) from a mapping by their keys, or prints an error upon failure
169  * @param configurator configurator
170  * @param node the mapping to parse
171  * @param keys_required comma-separated list of required keys (or NULL)
172  * @param keys_optional comma-separated list of optional keys (or NULL)
173  * @param ... pointers to `yoml_t **` for receiving the results; they should appear in the order they appear in the key names
174  * @return 0 if successful, -1 if not
175  */
176 #define h2o_configurator_parse_mapping(cmd, node, keys_required, keys_optional, ...)                                               \
177     h2o_configurator__do_parse_mapping((cmd), (node), (keys_required), (keys_optional), (yoml_t * **[]){__VA_ARGS__},              \
178                                        sizeof((yoml_t ***[]){__VA_ARGS__}) / sizeof(yoml_t ***))
179 int h2o_configurator__do_parse_mapping(h2o_configurator_command_t *cmd, yoml_t *node, const char *keys_required,
180                                        const char *keys_optional, yoml_t ****values, size_t num_values);
181 /**
182  * returns the absolute paths of supplementary commands
183  */
184 char *h2o_configurator_get_cmd_path(const char *cmd);
185 
186 /**
187  * lib/handler/configurator/headers_util.c
188  */
189 void h2o_configurator_define_headers_commands(h2o_globalconf_t *global_conf, h2o_configurator_t *conf, const char *prefix,
190                                               h2o_configurator_get_headers_commands_cb get_commands);
191 
192 void h2o_configurator__init_core(h2o_globalconf_t *conf);
193 void h2o_configurator__dispose_configurators(h2o_globalconf_t *conf);
194 
195 #endif
196