1 /* 2 * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Ryosuke Matsumoto 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 H20_MRUBY_H 23 #define H20_MRUBY_H 24 25 #include "h2o.h" 26 #include <mruby.h> 27 #include <mruby/data.h> 28 #include <mruby/proc.h> 29 #include <mruby/compile.h> 30 31 #define H2O_MRUBY_MODULE_NAME "h2o_mruby" 32 33 enum { 34 /* [0 .. H2O_MAX_TOKENS-1] are header names */ 35 /* [H2O_MAX_TOKENS .. H2O_MAX_TOKENS*2-1] are header names in environment variable style (i.e, "HTTP_FOO_BAR") */ 36 H2O_MRUBY_LIT_REQUEST_METHOD = H2O_MAX_TOKENS * 2, 37 H2O_MRUBY_LIT_SCRIPT_NAME, 38 H2O_MRUBY_LIT_PATH_INFO, 39 H2O_MRUBY_LIT_QUERY_STRING, 40 H2O_MRUBY_LIT_SERVER_NAME, 41 H2O_MRUBY_LIT_SERVER_ADDR, 42 H2O_MRUBY_LIT_SERVER_PORT, 43 H2O_MRUBY_LIT_SERVER_PROTOCOL, 44 H2O_MRUBY_LIT_CONTENT_LENGTH, 45 H2O_MRUBY_LIT_REMOTE_ADDR, 46 H2O_MRUBY_LIT_REMOTE_PORT, 47 H2O_MRUBY_LIT_REMOTE_USER, 48 H2O_MRUBY_LIT_RACK_URL_SCHEME, 49 H2O_MRUBY_LIT_RACK_MULTITHREAD, 50 H2O_MRUBY_LIT_RACK_MULTIPROCESS, 51 H2O_MRUBY_LIT_RACK_RUN_ONCE, 52 H2O_MRUBY_LIT_RACK_HIJACK_, 53 H2O_MRUBY_LIT_RACK_INPUT, 54 H2O_MRUBY_LIT_RACK_ERRORS, 55 H2O_MRUBY_LIT_RACK_EARLY_HINTS, 56 H2O_MRUBY_LIT_SERVER_SOFTWARE, 57 H2O_MRUBY_LIT_SERVER_SOFTWARE_VALUE, 58 H2O_MRUBY_LIT_H2O_REMAINING_DELEGATIONS, 59 H2O_MRUBY_LIT_H2O_REMAINING_REPROCESSES, 60 H2O_MRUBY_LIT_H2O_GET_RTT, 61 H2O_MRUBY_PROC_EACH_TO_ARRAY, 62 H2O_MRUBY_PROC_APP_TO_FIBER, 63 64 H2O_MRUBY_H2O_MODULE, 65 H2O_MRUBY_GENERATOR_CLASS, 66 H2O_MRUBY_ERROR_STREAM_CLASS, 67 H2O_MRUBY_APP_REQUEST_CLASS, 68 H2O_MRUBY_APP_INPUT_STREAM_CLASS, 69 70 /* used by sender.c */ 71 H2O_MRUBY_SENDER_PROC_EACH_TO_FIBER, 72 73 /* used by http_request.c */ 74 H2O_MRUBY_HTTP_REQUEST_CLASS, 75 H2O_MRUBY_HTTP_INPUT_STREAM_CLASS, 76 H2O_MRUBY_HTTP_EMPTY_INPUT_STREAM_CLASS, 77 78 /* used by channel.c */ 79 H2O_MRUBY_CHANNEL_CLASS, 80 81 H2O_MRUBY_NUM_CONSTANTS 82 }; 83 84 typedef struct st_h2o_mruby_config_vars_t { 85 h2o_iovec_t source; 86 char *path; 87 int lineno; 88 } h2o_mruby_config_vars_t; 89 90 typedef struct st_h2o_mruby_handler_t { 91 h2o_handler_t super; 92 h2o_mruby_config_vars_t config; 93 h2o_pathconf_t *pathconf; 94 } h2o_mruby_handler_t; 95 96 typedef struct st_h2o_mruby_context_t h2o_mruby_context_t; 97 typedef mrb_value (*h2o_mruby_callback_t)(h2o_mruby_context_t *ctx, mrb_value input, mrb_value *receiver, mrb_value args, 98 int *run_again); 99 typedef H2O_VECTOR(h2o_mruby_callback_t) h2o_mruby_callbacks_t; 100 101 typedef struct st_h2o_mruby_shared_context_t { 102 h2o_context_t *ctx; 103 mrb_state *mrb; 104 mrb_value constants; 105 struct st_h2o_mruby_context_t *current_context; 106 struct { 107 mrb_sym sym_call; 108 mrb_sym sym_close; 109 mrb_sym sym_method; 110 mrb_sym sym_headers; 111 mrb_sym sym_body; 112 mrb_sym sym_async; 113 } symbols; 114 h2o_mruby_callbacks_t callbacks; 115 } h2o_mruby_shared_context_t; 116 117 struct st_h2o_mruby_context_t { 118 h2o_mruby_handler_t *handler; 119 mrb_value proc; 120 h2o_mruby_shared_context_t *shared; 121 mrb_value blocking_reqs; 122 mrb_value resumers; 123 }; 124 125 typedef struct st_h2o_mruby_sender_t h2o_mruby_sender_t; 126 typedef struct st_h2o_mruby_http_request_context_t h2o_mruby_http_request_context_t; 127 typedef struct st_h2o_mruby_channel_context_t h2o_mruby_channel_context_t; 128 typedef struct st_h2o_mruby_generator_t h2o_mruby_generator_t; 129 130 typedef int (*h2o_mruby_send_response_callback_t)(h2o_mruby_generator_t *generator, mrb_int status, mrb_value resp, 131 int *is_delegate); 132 133 struct st_h2o_mruby_sender_t { 134 /** 135 * The body object being sent to the native side. Becomes nil on eos. 136 */ 137 mrb_value body_obj; 138 /** 139 * Size of the body being sent. SIZE_MAX indicates that the number is undetermined (i.e. no Content-Length). 140 */ 141 size_t bytes_left; 142 /** 143 * Initializes the subclass. called immediately after h2o_start_response is called 144 */ 145 void (*start)(h2o_mruby_generator_t *generator); 146 /** 147 * called directly by protocol handler 148 */ 149 void (*proceed)(h2o_generator_t *generator, h2o_req_t *req); 150 /** 151 * called when the generator is disposed 152 */ 153 void (*dispose)(h2o_mruby_generator_t *generator); 154 /** 155 * if `h2o_send` has been closed (by passing any other flag than in-progress 156 */ 157 unsigned char final_sent : 1; 158 }; 159 160 typedef struct st_h2o_mruby_error_stream_t { 161 h2o_mruby_context_t *ctx; 162 h2o_mruby_generator_t *generator; 163 } h2o_mruby_error_stream_t; 164 165 struct st_h2o_mruby_generator_t { 166 h2o_generator_t super; 167 h2o_req_t *req; /* becomes NULL once the underlying connection gets terminated */ 168 h2o_mruby_context_t *ctx; 169 mrb_value rack_input; 170 h2o_mruby_sender_t *sender; 171 h2o_mruby_error_stream_t *error_stream; 172 struct { 173 mrb_value generator; 174 mrb_value error_stream; 175 } refs; 176 }; 177 178 #define h2o_mruby_assert(mrb) \ 179 do { \ 180 if (mrb->exc != NULL) \ 181 h2o_mruby__abort_exc(mrb, "unexpected ruby error", __FILE__, __LINE__); \ 182 } while (0) 183 184 #define h2o_mruby_new_str(mrb, s, l) h2o_mruby__new_str((mrb), (s), (l), 0, __FILE__, __LINE__) 185 #define h2o_mruby_new_str_static(mrb, s, l) h2o_mruby__new_str((mrb), (s), (l), 1, __FILE__, __LINE__) 186 187 /* source files using this macro should include mruby/throw.h */ 188 #define H2O_MRUBY_EXEC_GUARD(block) \ 189 do { \ 190 struct mrb_jmpbuf *prev_jmp = mrb->jmp; \ 191 struct mrb_jmpbuf c_jmp; \ 192 MRB_TRY(&c_jmp) \ 193 { \ 194 mrb->jmp = &c_jmp; \ 195 do { \ 196 block \ 197 } while (0); \ 198 mrb->jmp = prev_jmp; \ 199 } \ 200 MRB_CATCH(&c_jmp) \ 201 { \ 202 mrb->jmp = prev_jmp; \ 203 } \ 204 MRB_END_EXC(&c_jmp); \ 205 } while (0) 206 207 /* handler/mruby.c */ 208 void h2o_mruby__abort_exc(mrb_state *mrb, const char *mess, const char *file, int line); 209 mrb_value h2o_mruby__new_str(mrb_state *mrb, const char *s, size_t len, int is_static, const char *file, int line); 210 mrb_value h2o_mruby_to_str(mrb_state *mrb, mrb_value v); 211 mrb_value h2o_mruby_to_int(mrb_state *mrb, mrb_value v); 212 mrb_value h2o_mruby_eval_expr(mrb_state *mrb, const char *expr); 213 mrb_value h2o_mruby_eval_expr_location(mrb_state *mrb, const char *expr, const char *path, const int lineno); 214 void h2o_mruby_define_callback(mrb_state *mrb, const char *name, h2o_mruby_callback_t callback); 215 mrb_value h2o_mruby_create_data_instance(mrb_state *mrb, mrb_value class_obj, void *ptr, const mrb_data_type *type); 216 void h2o_mruby_setup_globals(mrb_state *mrb); 217 struct RProc *h2o_mruby_compile_code(mrb_state *mrb, h2o_mruby_config_vars_t *config, char *errbuf); 218 h2o_mruby_handler_t *h2o_mruby_register(h2o_pathconf_t *pathconf, h2o_mruby_config_vars_t *config); 219 220 void h2o_mruby_run_fiber(h2o_mruby_context_t *ctx, mrb_value receiver, mrb_value input, int *is_delegate); 221 mrb_value h2o_mruby_each_to_array(h2o_mruby_shared_context_t *shared_ctx, mrb_value src); 222 int h2o_mruby_iterate_rack_headers(h2o_mruby_shared_context_t *shared_ctx, mrb_value headers, 223 int (*cb)(h2o_mruby_shared_context_t *, h2o_iovec_t *, h2o_iovec_t, void *), void *cb_data); 224 int h2o_mruby_iterate_header_values(h2o_mruby_shared_context_t *shared_ctx, mrb_value name, mrb_value value, 225 int (*cb)(h2o_mruby_shared_context_t *, h2o_iovec_t *, h2o_iovec_t, void *), void *cb_data); 226 int h2o_mruby_iterate_native_headers(h2o_mruby_shared_context_t *shared_ctx, h2o_mem_pool_t *pool, h2o_headers_t *headers, 227 int (*cb)(h2o_mruby_shared_context_t *, h2o_mem_pool_t *, h2o_header_t *, void *), 228 void *cb_data); 229 int h2o_mruby_set_response_header(h2o_mruby_shared_context_t *shared_ctx, h2o_iovec_t *name, h2o_iovec_t value, void *req); 230 231 mrb_value h2o_mruby_token_string(h2o_mruby_shared_context_t *shared, const h2o_token_t *token); 232 mrb_value h2o_mruby_token_env_key(h2o_mruby_shared_context_t *shared, const h2o_token_t *token); 233 234 /* handler/mruby/sender.c */ 235 void h2o_mruby_sender_init_context(h2o_mruby_shared_context_t *ctx); 236 /** 237 * create and set new sender object corresponding the body argument. called only from send_response in mruby.c 238 */ 239 int h2o_mruby_init_sender(h2o_mruby_generator_t *generator, mrb_value body); 240 /** 241 * create base sender object, called by subclasses (http_request, middleware, etc) 242 */ 243 h2o_mruby_sender_t *h2o_mruby_sender_create(h2o_mruby_generator_t *generator, mrb_value body, size_t alignment, size_t sz); 244 /** 245 * a wrapper of h2o_send with counting and checking content-length 246 */ 247 void h2o_mruby_sender_do_send(h2o_mruby_generator_t *generator, h2o_sendvec_t *bufs, size_t bufcnt, h2o_send_state_t state); 248 /** 249 * utility function used by sender implementations that needs buffering 250 */ 251 void h2o_mruby_sender_do_send_buffer(h2o_mruby_generator_t *generator, h2o_doublebuffer_t *db, h2o_buffer_t **input, int is_final); 252 /** 253 * close body object, called when responding is stopped or finally disposed 254 */ 255 void h2o_mruby_sender_close_body(h2o_mruby_generator_t *generator); 256 257 /* handler/mruby/http_request.c */ 258 void h2o_mruby_http_request_init_context(h2o_mruby_shared_context_t *ctx); 259 h2o_mruby_sender_t *h2o_mruby_http_sender_create(h2o_mruby_generator_t *generator, mrb_value body); 260 261 /* handler/mruby/redis.c */ 262 void h2o_mruby_redis_init_context(h2o_mruby_shared_context_t *ctx); 263 264 /* handler/mruby/sleep.c */ 265 void h2o_mruby_sleep_init_context(h2o_mruby_shared_context_t *ctx); 266 267 /* handler/mruby/middleware.c */ 268 void h2o_mruby_middleware_init_context(h2o_mruby_shared_context_t *ctx); 269 h2o_mruby_sender_t *h2o_mruby_middleware_sender_create(h2o_mruby_generator_t *generator, mrb_value body); 270 h2o_mruby_send_response_callback_t h2o_mruby_middleware_get_send_response_callback(h2o_mruby_context_t *ctx, mrb_value resp); 271 272 /* handler/mruby/channel.c */ 273 void h2o_mruby_channel_init_context(h2o_mruby_shared_context_t *ctx); 274 275 /* handler/configurator/mruby.c */ 276 void h2o_mruby_register_configurator(h2o_globalconf_t *conf); 277 278 h2o_mruby_generator_t *h2o_mruby_get_generator(mrb_state *mrb, mrb_value obj); 279 h2o_mruby_error_stream_t *h2o_mruby_get_error_stream(mrb_state *mrb, mrb_value obj); 280 281 #endif 282