static int parse_url(h2o_mempool_t *pool, const char *url, char const **host, uint16_t *port, char const **path) { const char *hp_start, *hp_end, *colon_at; /* check and skip scheme */ if (strncmp(url, "http://", 7) != 0) { return 0; } hp_start = url + 7; /* locate the end of hostport */ if ((hp_end = strchr(hp_start, '/')) != NULL) { *path = hp_end; } else { hp_end = hp_start + strlen(hp_start); *path = "/"; } /* parse hostport */ for (colon_at = hp_start; colon_at != hp_end; ++colon_at) if (*colon_at == ':') break; if (colon_at != hp_end) { *host = h2o_strdup(pool, hp_start, colon_at - hp_start).base; if ((*port = strtol(colon_at + 1, NULL, 10)) == 0) return 0; } else { *host = h2o_strdup(pool, hp_start, hp_end - hp_start).base; *port = 80; } /* success */ return 1; }
h2o_memcached_context_t *h2o_memcached_create_context(const char *host, uint16_t port, size_t num_threads, const char *prefix) { h2o_memcached_context_t *ctx = h2o_mem_alloc(sizeof(*ctx)); pthread_mutex_init(&ctx->mutex, NULL); pthread_cond_init(&ctx->cond, NULL); h2o_linklist_init_anchor(&ctx->pending); ctx->num_threads_connected = 0; ctx->host = h2o_strdup(NULL, host, SIZE_MAX).base; ctx->port = port; ctx->prefix = h2o_strdup(NULL, prefix, SIZE_MAX); { /* start the threads */ pthread_t tid; pthread_attr_t attr; size_t i; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, 1); for (i = 0; i != num_threads; ++i) h2o_multithread_create_thread(&tid, &attr, thread_main, ctx); pthread_attr_destroy(&attr); } return ctx; }
static h2o_http1client_body_cb on_head(h2o_http1client_t *client, const char *errstr, int minor_version, int status, h2o_iovec_t msg, struct phr_header *headers, size_t num_headers) { struct rp_generator_t *self = client->data; size_t i; if (errstr != NULL && errstr != h2o_http1client_error_is_eos) { self->client = NULL; h2o_send_error(self->src_req, 502, "Gateway Error", errstr, 0); return NULL; } /* copy the response */ self->src_req->res.status = status; self->src_req->res.reason = h2o_strdup(&self->src_req->pool, msg.base, msg.len).base; for (i = 0; i != num_headers; ++i) { const h2o_token_t *token = h2o_lookup_token(headers[i].name, headers[i].name_len); h2o_iovec_t value; if (token != NULL) { if (token->is_connection_specific) { goto Skip; } if (token == H2O_TOKEN_CONTENT_LENGTH) { if (self->src_req->res.content_length != SIZE_MAX || (self->src_req->res.content_length = h2o_strtosize(headers[i].value, headers[i].value_len)) == SIZE_MAX) { self->client = NULL; h2o_send_error(self->src_req, 502, "Gateway Error", "invalid response from upstream", 0); return NULL; } goto Skip; } else if (token == H2O_TOKEN_LOCATION) { value = rewrite_location(&self->src_req->pool, headers[i].value, headers[i].value_len, self->upstream, self->src_req->scheme, self->src_req->authority, self->src_req->pathconf->path); goto AddHeader; } /* default behaviour, transfer the header downstream */ value = h2o_strdup(&self->src_req->pool, headers[i].value, headers[i].value_len); AddHeader: h2o_add_header(&self->src_req->pool, &self->src_req->res.headers, token, value.base, value.len); Skip: ; } else { h2o_iovec_t name = h2o_strdup(&self->src_req->pool, headers[i].name, headers[i].name_len); h2o_iovec_t value = h2o_strdup(&self->src_req->pool, headers[i].value, headers[i].value_len); h2o_add_header_by_str(&self->src_req->pool, &self->src_req->res.headers, name.base, name.len, 0, value.base, value.len); } } /* declare the start of the response */ h2o_start_response(self->src_req, &self->super); if (errstr == h2o_http1client_error_is_eos) { self->client = NULL; h2o_send(self->src_req, NULL, 0, 1); return NULL; } return on_body; }
void h2o_socket_ssl_handshake(h2o_socket_t *sock, SSL_CTX *ssl_ctx, const char *server_name, h2o_socket_cb handshake_cb) { sock->ssl = h2o_mem_alloc(sizeof(*sock->ssl)); memset(sock->ssl, 0, offsetof(struct st_h2o_socket_ssl_t, output.pool)); /* setup the buffers; sock->input should be empty, sock->ssl->input.encrypted should contain the initial input, if any */ h2o_buffer_init(&sock->ssl->input.encrypted, &h2o_socket_buffer_prototype); if (sock->input->size != 0) { h2o_buffer_t *tmp = sock->input; sock->input = sock->ssl->input.encrypted; sock->ssl->input.encrypted = tmp; } h2o_mem_init_pool(&sock->ssl->output.pool); create_ssl(sock, ssl_ctx); sock->ssl->handshake.cb = handshake_cb; if (server_name == NULL) { /* is server */ if (SSL_CTX_sess_get_get_cb(ssl_ctx) != NULL) sock->ssl->handshake.server.async_resumption.state = ASYNC_RESUMPTION_STATE_RECORD; if (sock->ssl->input.encrypted->size != 0) proceed_handshake(sock, 0); else h2o_socket_read_start(sock, proceed_handshake); } else { sock->ssl->handshake.client.server_name = h2o_strdup(NULL, server_name, SIZE_MAX).base; SSL_set_tlsext_host_name(sock->ssl->ssl, sock->ssl->handshake.client.server_name); proceed_handshake(sock, 0); } }
static void on_setup_ostream(h2o_filter_t *self, h2o_req_t *req, h2o_ostream_t **slot) { struct rproxy_t *rproxy; ssize_t reproxy_header_index; h2o_buf_t reproxy_url; /* do nothing unless 200 */ if (req->res.status != 200) goto SkipMe; if ((reproxy_header_index = h2o_find_header(&req->res.headers, H2O_TOKEN_X_REPROXY_URL, -1)) == -1) goto SkipMe; reproxy_url = req->res.headers.entries[reproxy_header_index].value; h2o_delete_header(&req->res.headers, reproxy_header_index); /* setup */ rproxy = (void*)h2o_add_ostream(req, sizeof(struct rproxy_t), slot); rproxy->filter = self; rproxy->super.do_send = send_chunk; rproxy->reproxy_url = h2o_strdup(&req->pool, reproxy_url.base, reproxy_url.len).base; /* next ostream is setup when send_chunk receives EOS */ return; SkipMe: h2o_setup_next_ostream(self, req, slot); }
h2o_hostconf_t *h2o_config_register_host(h2o_globalconf_t *config, h2o_iovec_t host, uint16_t port) { h2o_hostconf_t *hostconf; assert(host.len != 0); /* create hostconf */ hostconf = create_hostconf(config); hostconf->authority.host = h2o_strdup(NULL, host.base, host.len); h2o_strtolower(hostconf->authority.host.base, hostconf->authority.host.len); 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("[]:65535")); 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); return hostconf; }
void h2o_proxy_register_reverse_proxy(h2o_pathconf_t *pathconf, const char *host, uint16_t port, const char *real_path, h2o_proxy_config_vars_t *config) { struct rp_handler_t *self = (void*)h2o_create_handler(pathconf, sizeof(*self)); self->super.on_context_init = on_context_init; self->super.on_context_dispose = on_context_dispose; self->super.dispose = on_handler_dispose; self->super.on_req = on_req; self->upstream.host = h2o_strdup(NULL, host, SIZE_MAX); self->upstream.port = port; self->upstream.path = h2o_strdup(NULL, real_path, SIZE_MAX); if (config->use_keepalive) { self->sockpool = h2o_mem_alloc(sizeof(*self->sockpool)); h2o_socketpool_init(self->sockpool, host, port, SIZE_MAX /* FIXME */); } self->config = *config; }
h2o_file_handler_t *h2o_file_register(h2o_hostconf_t *host_config, const char *virtual_path, const char *real_path, const char **index_files, h2o_mimemap_t *mimemap) { h2o_file_handler_t *self; size_t i; if (index_files == NULL) index_files = default_index_files; /* allocate memory */ for (i = 0; index_files[i] != NULL; ++i) ; self = (void*)h2o_create_handler(host_config, offsetof(h2o_file_handler_t, index_files[0]) + sizeof(self->index_files[0]) * (i + 1)); /* setup callbacks */ self->super.dispose = on_dispose; self->super.on_req = on_req; /* setup attributes */ self->virtual_path = append_slash_and_dup(virtual_path); self->real_path = append_slash_and_dup(real_path); if (mimemap != NULL) { h2o_mempool_addref_shared(mimemap); self->mimemap = mimemap; } else { self->mimemap = h2o_mimemap_create(); } for (i = 0; index_files[i] != NULL; ++i) { self->index_files[i] = h2o_strdup(NULL, index_files[i], SIZE_MAX); if (self->max_index_file_len < self->index_files[i].len) self->max_index_file_len = self->index_files[i].len; } return self; }
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, {}, 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; }
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) { #ifdef H2O_ROOT root = H2O_ROOT; #endif if (root == NULL) goto ReturnOrig; } /* 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; }
void h2o_socket_ssl_handshake(h2o_socket_t *sock, SSL_CTX *ssl_ctx, const char *server_name, h2o_socket_cb handshake_cb) { sock->ssl = h2o_mem_alloc(sizeof(*sock->ssl)); memset(sock->ssl, 0, offsetof(struct st_h2o_socket_ssl_t, output.pool)); /* setup the buffers; sock->input should be empty, sock->ssl->input.encrypted should contain the initial input, if any */ h2o_buffer_init(&sock->ssl->input.encrypted, &h2o_socket_buffer_prototype); if (sock->input->size != 0) { h2o_buffer_t *tmp = sock->input; sock->input = sock->ssl->input.encrypted; sock->ssl->input.encrypted = tmp; } h2o_mem_init_pool(&sock->ssl->output.pool); create_ssl(sock, ssl_ctx); sock->ssl->handshake.cb = handshake_cb; if (server_name == NULL) { /* is server */ if (SSL_CTX_sess_get_get_cb(ssl_ctx) != NULL) sock->ssl->handshake.server.async_resumption.state = ASYNC_RESUMPTION_STATE_RECORD; if (sock->ssl->input.encrypted->size != 0) proceed_handshake(sock, 0); else h2o_socket_read_start(sock, proceed_handshake); } else { h2o_cache_t *session_cache = h2o_socket_ssl_get_session_cache(ssl_ctx); if (session_cache != NULL) { struct sockaddr_storage sa; int32_t port; if (h2o_socket_getpeername(sock, (struct sockaddr *)&sa) != 0 && (port = h2o_socket_getport((struct sockaddr *)&sa)) != -1) { /* session cache is available */ h2o_iovec_t session_cache_key; session_cache_key.base = h2o_mem_alloc(strlen(server_name) + sizeof(":" H2O_UINT16_LONGEST_STR)); session_cache_key.len = sprintf(session_cache_key.base, "%s:%" PRIu16, server_name, (uint16_t)port); sock->ssl->handshake.client.session_cache = session_cache; sock->ssl->handshake.client.session_cache_key = session_cache_key; sock->ssl->handshake.client.session_cache_key_hash = h2o_cache_calchash(session_cache_key.base, session_cache_key.len); /* fetch from session cache */ h2o_cache_ref_t *cacheref = h2o_cache_fetch(session_cache, h2o_now(h2o_socket_get_loop(sock)), sock->ssl->handshake.client.session_cache_key, sock->ssl->handshake.client.session_cache_key_hash); if (cacheref != NULL) { SSL_set_session(sock->ssl->ssl, (SSL_SESSION *)cacheref->value.base); h2o_cache_release(session_cache, cacheref); } } } sock->ssl->handshake.client.server_name = h2o_strdup(NULL, server_name, SIZE_MAX).base; SSL_set_tlsext_host_name(sock->ssl->ssl, sock->ssl->handshake.client.server_name); proceed_handshake(sock, 0); } }
h2o_redirect_handler_t *h2o_redirect_register(h2o_pathconf_t *pathconf, int internal, int status, const char *prefix) { h2o_redirect_handler_t *self = (void *)h2o_create_handler(pathconf, sizeof(*self)); self->super.dispose = on_dispose; self->super.on_req = on_req; self->internal = internal; self->status = status; self->prefix = h2o_strdup(NULL, prefix, SIZE_MAX); return self; }
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; 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_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); h2o_send(req, &buf, 1, 1); }
static void common_init(h2o_socketpool_t *pool, h2o_socketpool_type_t type, h2o_iovec_t host, int is_ssl, size_t capacity) { memset(pool, 0, sizeof(*pool)); pool->type = type; pool->peer.host = h2o_strdup(NULL, host.base, host.len); pool->is_ssl = is_ssl; pool->capacity = capacity; pool->timeout = UINT64_MAX; pthread_mutex_init(&pool->_shared.mutex, NULL); h2o_linklist_init_anchor(&pool->_shared.sockets); }
int h2o_proxy_send(h2o_req_t *req, h2o_http1client_ctx_t *client_ctx, h2o_proxy_location_t *upstream) { struct rp_generator_t *self = proxy_send_prepare(req, upstream, 0); self->client = h2o_http1client_connect( client_ctx, &req->pool, h2o_strdup(&req->pool, upstream->host.base, upstream->host.len).base, upstream->port, on_connect); self->client->data = self; return 0; }
static int extract_name_value(const char *src, h2o_iovec_t **name, h2o_iovec_t *value) { const char *colon = strchr(src, ':'); if (colon == NULL) return -1; if (extract_name(src, colon - src, name) != 0) return -1; *value = h2o_str_stripws(colon + 1, strlen(colon + 1)); *value = h2o_strdup(NULL, value->base, value->len); return 0; }
static ssize_t fixup_request(struct st_h2o_http1_conn_t *conn, struct phr_header *headers, size_t num_headers, int minor_version, h2o_iovec_t *expect) { ssize_t entity_header_index; h2o_iovec_t connection = {NULL, 0}, host = {NULL, 0}, upgrade = {NULL, 0}; expect->base = NULL; expect->len = 0; conn->req.input.scheme = conn->sock->ssl != NULL ? &H2O_URL_SCHEME_HTTPS : &H2O_URL_SCHEME_HTTP; conn->req.version = 0x100 | (minor_version != 0); /* init headers */ entity_header_index = init_headers(&conn->req.pool, &conn->req.headers, headers, num_headers, &connection, &host, &upgrade, expect); /* copy the values to pool, since the buffer pointed by the headers may get realloced */ if (entity_header_index != -1) { size_t i; conn->req.input.method = h2o_strdup(&conn->req.pool, conn->req.input.method.base, conn->req.input.method.len); conn->req.input.path = h2o_strdup(&conn->req.pool, conn->req.input.path.base, conn->req.input.path.len); for (i = 0; i != conn->req.headers.size; ++i) { h2o_header_t *header = conn->req.headers.entries + i; if (!h2o_iovec_is_token(header->name)) { *header->name = h2o_strdup(&conn->req.pool, header->name->base, header->name->len); } header->value = h2o_strdup(&conn->req.pool, header->value.base, header->value.len); } if (host.base != NULL) host = h2o_strdup(&conn->req.pool, host.base, host.len); if (upgrade.base != NULL) upgrade = h2o_strdup(&conn->req.pool, upgrade.base, upgrade.len); } /* move host header to req->authority */ if (host.base != NULL) conn->req.input.authority = host; /* setup persistent flag (and upgrade info) */ if (connection.base != NULL) { /* TODO contains_token function can be faster */ if (h2o_contains_token(connection.base, connection.len, H2O_STRLIT("keep-alive"), ',')) { conn->req.http1_is_persistent = 1; } if (upgrade.base != NULL && h2o_contains_token(connection.base, connection.len, H2O_STRLIT("upgrade"), ',')) { conn->req.upgrade = upgrade; } } else if (conn->req.version >= 0x101) { /* defaults to keep-alive if >= HTTP/1.1 */ conn->req.http1_is_persistent = 1; } /* disable keep-alive if shutdown is requested */ if (conn->req.http1_is_persistent && conn->super.ctx->shutdown_requested) conn->req.http1_is_persistent = 0; return entity_header_index; }
h2o_host_configuration_t *h2o_config_register_virtual_host(h2o_global_configuration_t *config, const char *hostname) { h2o_host_configuration_t *host_config = h2o_malloc(sizeof(*host_config)); size_t i; memset(host_config, 0, sizeof(*host_config)); init_host_config(host_config); host_config->hostname = h2o_strdup(NULL, hostname, SIZE_MAX); for (i = 0; i != host_config->hostname.len; ++i) host_config->hostname.base[i] = h2o_tolower(host_config->hostname.base[i]); h2o_linklist_insert(&config->virtual_hosts, &host_config->_link); return host_config; }
static mrb_value h2o_mrb_req_send(mrb_state *mrb, mrb_value self) { h2o_mruby_internal_context_t *mruby_ctx = (h2o_mruby_internal_context_t *)mrb->ud; char *s; mrb_int len; if (mruby_ctx->state != H2O_MRUBY_STATE_UNDETERMINED) mrb_raise(mrb, E_RUNTIME_ERROR, "response already sent"); mrb_get_args(mrb, "s", &s, &len); h2o_mruby_fixup_and_send(mruby_ctx->req, h2o_strdup(&mruby_ctx->req->pool, s, len).base, len); mruby_ctx->state = H2O_MRUBY_STATE_RESPONSE_SENT; return mrb_nil_value(); }
static ssize_t 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_flags_t flags) { 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; slot->flags = flags; return headers->size - 1; }
h2o_iovec_t h2o_extract_push_path_from_link_header(h2o_mem_pool_t *pool, const char *value, size_t value_len, const h2o_url_scheme_t *base_scheme, h2o_iovec_t *base_authority, h2o_iovec_t *base_path) { h2o_iovec_t url; h2o_url_t parsed, resolved; { /* extract URL value from: Link: </pushed.css>; rel=preload */ h2o_iovec_t iter = h2o_iovec_init(value, value_len), token_value; const char *token; size_t token_len; /* first element should be <URL> */ if ((token = h2o_next_token(&iter, ';', &token_len, NULL)) == NULL) goto None; if (!(token_len >= 2 && token[0] == '<' && token[token_len - 1] == '>')) goto None; url = h2o_iovec_init(token + 1, token_len - 2); /* find rel=preload */ while ((token = h2o_next_token(&iter, ';', &token_len, &token_value)) != NULL) { if (h2o_lcstris(token, token_len, H2O_STRLIT("rel")) && h2o_lcstris(token_value.base, token_value.len, H2O_STRLIT("preload"))) break; } if (token == NULL) goto None; } /* check the authority, and extract absolute path */ if (h2o_url_parse_relative(url.base, url.len, &parsed) != 0) goto None; /* return the URL found in Link header, if it is an absolute path-only URL */ if (parsed.scheme == NULL && parsed.authority.base == NULL && url.len != 0 && url.base[0] == '/') return h2o_strdup(pool, url.base, url.len); /* check scheme and authority if given URL contains either of the two */ h2o_url_t base = {base_scheme, *base_authority, {}, *base_path, 65535}; h2o_url_resolve(pool, &base, &parsed, &resolved); if (base.scheme != resolved.scheme) goto None; if (parsed.authority.base != NULL && !h2o_lcstris(base.authority.base, base.authority.len, resolved.authority.base, resolved.authority.len)) goto None; return resolved.path; None: return (h2o_iovec_t){}; }
void h2o_socketpool_init_by_hostport(h2o_socketpool_t *pool, h2o_iovec_t host, uint16_t port, size_t capacity) { struct sockaddr_in sin = {}; if (h2o_hostinfo_aton(host, &sin.sin_addr) == 0) { sin.sin_family = AF_INET; sin.sin_port = htons(port); h2o_socketpool_init_by_address(pool, (void *)&sin, sizeof(sin), capacity); return; } common_init(pool, H2O_SOCKETPOOL_TYPE_NAMED, capacity); pool->peer.named.host = h2o_strdup(NULL, host.base, host.len); pool->peer.named.port.base = h2o_mem_alloc(sizeof("65535")); pool->peer.named.port.len = sprintf(pool->peer.named.port.base, "%u", (unsigned)port); }
h2o_handler_t *h2o_file_register_file(h2o_pathconf_t *pathconf, const char *real_path, h2o_mimemap_type_t *mime_type, int flags) { struct st_h2o_specific_file_handler_t *self = (void *)h2o_create_handler(pathconf, sizeof(*self)); self->super.on_context_init = specific_handler_on_context_init; self->super.on_context_dispose = specific_handler_on_context_dispose; self->super.dispose = specific_handler_on_dispose; self->super.on_req = specific_handler_on_req; self->real_path = h2o_strdup(NULL, real_path, SIZE_MAX); h2o_mem_addref_shared(mime_type); self->mime_type = mime_type; self->flags = flags; return &self->super; }
static int chunked_test(h2o_handler_t *self, h2o_req_t *req) { if (h2o_memis(req->method.base, req->method.len, H2O_STRLIT("GET")) && h2o_memis(req->path.base, req->path.len, H2O_STRLIT("/chunked-test"))) { static h2o_generator_t generator = { NULL, NULL }; h2o_buf_t body = h2o_strdup(&req->pool, "hello world\n", SIZE_MAX); req->res.status = 200; req->res.reason = "OK"; h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, H2O_STRLIT("text/plain")); h2o_start_response(req, &generator); h2o_send(req, &body, 1, 1); return 0; } return -1; }
static mrb_value h2o_mrb_req_set_reason(mrb_state *mrb, mrb_value self) { h2o_mruby_internal_context_t *mruby_ctx = (h2o_mruby_internal_context_t *)mrb->ud; const char *s; mrb_int len; if (mruby_ctx->state != H2O_MRUBY_STATE_UNDETERMINED) mrb_raise(mrb, E_RUNTIME_ERROR, "response already sent"); mrb_get_args(mrb, "s", &s, &len); if (s == NULL || len == 0) mrb_raise(mrb, E_RUNTIME_ERROR, "cannot set an empty string to `reason`"); mruby_ctx->req->res.reason = h2o_strdup(&mruby_ctx->req->pool, s, len).base; return mrb_str_new(mrb, s, len); }
static int delegate_dynamic_request(h2o_req_t *req, size_t url_path_len, const char *local_path, size_t local_path_len, h2o_mimemap_type_t *mime_type) { h2o_filereq_t *filereq; h2o_handler_t *handler; assert(mime_type->data.dynamic.pathconf.handlers.size == 1); filereq = h2o_mem_alloc_pool(&req->pool, sizeof(*filereq)); filereq->url_path_len = url_path_len; filereq->local_path = h2o_strdup(&req->pool, local_path, local_path_len); h2o_req_bind_conf(req, req->hostconf, &mime_type->data.dynamic.pathconf); req->filereq = filereq; handler = mime_type->data.dynamic.pathconf.handlers.entries[0]; return handler->on_req(handler, req); }
void h2o_socketpool_init(h2o_socketpool_t *pool, const char *host, uint16_t port, size_t capacity) { memset(pool, 0, sizeof(*pool)); if (inet_pton(AF_INET, host, &pool->peer.sin.sin_addr) == 1) { pool->peer.sin.sin_family = AF_INET; pool->peer.sin.sin_port = htons(port); } else { pool->peer.named.host = h2o_strdup(NULL, host, SIZE_MAX); sprintf(pool->peer.named.port, "%u", (unsigned)port); pool->peer.is_named = 1; } pool->capacity = capacity; pool->timeout = UINT64_MAX; pthread_mutex_init(&pool->_shared.mutex, NULL); h2o_linklist_init_anchor(&pool->_shared.sockets); }
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){}; 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("[]:65535")); 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_socketpool_init(h2o_socketpool_t *pool, h2o_iovec_t host, uint16_t port, size_t capacity) { memset(pool, 0, sizeof(*pool)); if (h2o_hostinfo_aton(host, &pool->peer.sin.sin_addr) == 0) { pool->peer.sin.sin_family = AF_INET; pool->peer.sin.sin_port = htons(port); } else { pool->peer.named.host = h2o_strdup(NULL, host.base, host.len); pool->peer.named.port.base = h2o_mem_alloc(sizeof("65535")); pool->peer.named.port.len = sprintf(pool->peer.named.port.base, "%u", (unsigned)port); pool->peer.is_named = 1; } pool->capacity = capacity; pool->timeout = UINT64_MAX; pthread_mutex_init(&pool->_shared.mutex, NULL); h2o_linklist_init_anchor(&pool->_shared.sockets); }