h2o_socketpool_target_t *h2o_socketpool_create_target(h2o_url_t *origin, h2o_socketpool_target_conf_t *lb_target_conf) { struct sockaddr_storage sa; socklen_t salen; h2o_socketpool_target_t *target = h2o_mem_alloc(sizeof(*target)); h2o_url_copy(NULL, &target->url, origin); assert(target->url.host.base[target->url.host.len] == '\0'); /* needs to be null-terminated in order to be used in SNI */ target->type = detect_target_type(origin, &sa, &salen); if (!(target->type == H2O_SOCKETPOOL_TYPE_SOCKADDR && sa.ss_family == AF_UNIX)) { h2o_strtolower(target->url.authority.base, target->url.authority.len); h2o_strtolower(target->url.host.base, target->url.host.len); } switch (target->type) { case H2O_SOCKETPOOL_TYPE_NAMED: target->peer.named_serv.base = h2o_mem_alloc(sizeof(H2O_UINT16_LONGEST_STR)); target->peer.named_serv.len = sprintf(target->peer.named_serv.base, "%u", (unsigned)h2o_url_get_port(&target->url)); break; case H2O_SOCKETPOOL_TYPE_SOCKADDR: assert(salen <= sizeof(target->peer.sockaddr.bytes)); memcpy(&target->peer.sockaddr.bytes, &sa, salen); target->peer.sockaddr.len = salen; break; } target->_shared.leased_count = 0; if (lb_target_conf != NULL) target->conf.weight_m1 = lb_target_conf->weight_m1; else { target->conf.weight_m1 = 0; } h2o_linklist_init_anchor(&target->_shared.sockets); return target; }
h2o_iovec_t h2o_http2_casper_get_cookie(h2o_http2_casper_t *casper) { if (casper->cookie_cache.base != NULL) return casper->cookie_cache; if (casper->keys.size == 0) return (h2o_iovec_t){}; /* encode as binary */ char tiny_bin_buf[128], *bin_buf = tiny_bin_buf; size_t bin_capacity = sizeof(tiny_bin_buf), bin_size; while (bin_size = bin_capacity, golombset_encode(casper->remainder_bits, casper->keys.entries, casper->keys.size, bin_buf, &bin_size) != 0) { if (bin_buf != tiny_bin_buf) free(bin_buf); bin_capacity *= 2; bin_buf = h2o_mem_alloc(bin_capacity); } char *header_bytes = h2o_mem_alloc(sizeof(COOKIE_NAME "=" COOKIE_ATTRIBUTES) - 1 + (bin_size + 3) * 4 / 3); size_t header_len = 0; header_len += append_str(header_bytes + header_len, H2O_STRLIT(COOKIE_NAME "=")); header_len += h2o_base64_encode(header_bytes + header_len, bin_buf, bin_size, 1); header_len += append_str(header_bytes + header_len, H2O_STRLIT(COOKIE_ATTRIBUTES)); if (bin_buf != tiny_bin_buf) free(bin_buf); casper->cookie_cache = h2o_iovec_init(header_bytes, header_len); return casper->cookie_cache; }
static void on_context_init(h2o_handler_t *_self, h2o_context_t *ctx) { struct rp_handler_t *self = (void *)_self; /* use the loop of first context for handling socketpool timeouts */ if (self->sockpool != NULL && self->sockpool->timeout == UINT64_MAX) h2o_socketpool_set_timeout(self->sockpool, ctx->loop, self->config.keepalive_timeout); /* setup a specific client context only if we need to */ if (ctx->globalconf->proxy.io_timeout == self->config.io_timeout && !self->config.websocket.enabled && self->config.ssl_ctx == ctx->globalconf->proxy.ssl_ctx) return; h2o_http1client_ctx_t *client_ctx = h2o_mem_alloc(sizeof(*ctx)); client_ctx->loop = ctx->loop; client_ctx->getaddr_receiver = &ctx->receivers.hostinfo_getaddr; if (ctx->globalconf->proxy.io_timeout == self->config.io_timeout) { client_ctx->io_timeout = &ctx->proxy.io_timeout; } else { client_ctx->io_timeout = h2o_mem_alloc(sizeof(*client_ctx->io_timeout)); h2o_timeout_init(client_ctx->loop, client_ctx->io_timeout, self->config.io_timeout); } if (self->config.websocket.enabled) { /* FIXME avoid creating h2o_timeout_t for every path-level context in case the timeout values are the same */ client_ctx->websocket_timeout = h2o_mem_alloc(sizeof(*client_ctx->websocket_timeout)); h2o_timeout_init(client_ctx->loop, client_ctx->websocket_timeout, self->config.websocket.timeout); } else { client_ctx->websocket_timeout = NULL; } client_ctx->ssl_ctx = self->config.ssl_ctx; h2o_context_set_handler_context(ctx, &self->super, client_ctx); }
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); } }
void h2o_memcached_set(h2o_memcached_context_t *ctx, h2o_iovec_t key, h2o_iovec_t value, uint32_t expiration, int flags) { h2o_memcached_req_t *req = create_req(ctx, REQ_TYPE_SET, key, (flags & H2O_MEMCACHED_ENCODE_KEY) != 0); if ((flags & H2O_MEMCACHED_ENCODE_VALUE) != 0) { req->data.set.value.base = h2o_mem_alloc((value.len + 2) / 3 * 4 + 1); req->data.set.value.len = h2o_base64_encode(req->data.set.value.base, value.base, value.len, 1); } else { req->data.set.value = h2o_iovec_init(h2o_mem_alloc(value.len), value.len); memcpy(req->data.set.value.base, value.base, value.len); } req->data.set.expiration = expiration; dispatch(ctx, req); }
static void register_authority(h2o_globalconf_t *globalconf, h2o_iovec_t host, uint16_t port) { static h2o_iovec_t x_authority = {H2O_STRLIT("x-authority")}; h2o_hostconf_t *hostconf = h2o_config_register_host(globalconf, host, port); h2o_pathconf_t *pathconf = h2o_config_register_path(hostconf, "/"); h2o_file_register(pathconf, "t/00unit/assets", NULL, NULL, 0); char *authority = h2o_mem_alloc(host.len + sizeof(":65535")); sprintf(authority, "%.*s:%" PRIu16, (int)host.len, host.base, port); h2o_headers_command_t *cmds = h2o_mem_alloc(sizeof(*cmds) * 2); cmds[0] = (h2o_headers_command_t){H2O_HEADERS_CMD_ADD, &x_authority, {authority, strlen(authority)}}; cmds[1] = (h2o_headers_command_t){H2O_HEADERS_CMD_NULL}; h2o_headers_register(pathconf, cmds); }
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; }
h2o_websocket_conn_t *h2o_upgrade_to_websocket(h2o_req_t *req, const char *client_key, void *data, h2o_websocket_msg_callback cb) { h2o_websocket_conn_t *conn = h2o_mem_alloc(sizeof(*conn)); char accept_key[29]; /* only for http1 connection */ assert(req->version < 0x200); /* setup the context */ memset(conn, 0, sizeof(*conn)); // conn->sock = sock; set by on_complete conn->ws_callbacks.recv_callback = recv_callback; conn->ws_callbacks.send_callback = send_callback; conn->ws_callbacks.on_msg_recv_callback = on_msg_callback; conn->data = data; conn->cb = cb; wslay_event_context_server_init(&conn->ws_ctx, &conn->ws_callbacks, conn); /* build response */ create_accept_key(accept_key, client_key); req->res.status = 101; req->res.reason = "Switching Protocols"; h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_UPGRADE, NULL, H2O_STRLIT("websocket")); h2o_add_header_by_str(&req->pool, &req->res.headers, H2O_STRLIT("sec-websocket-accept"), 0, NULL, accept_key, strlen(accept_key)); /* send */ h2o_http1_upgrade(req, NULL, 0, on_complete, conn); return conn; }
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; }
int h2o_socketpool_return(h2o_socketpool_t *pool, h2o_socket_t *sock) { struct pool_entry_t *entry; /* reset the on_close callback */ assert(sock->on_close.data == pool); sock->on_close.cb = NULL; sock->on_close.data = NULL; entry = h2o_mem_alloc(sizeof(*entry)); if (h2o_socket_export(sock, &entry->sockinfo) != 0) { free(entry); __sync_sub_and_fetch(&pool->_shared.count, 1); return -1; } memset(&entry->link, 0, sizeof(entry->link)); entry->added_at = h2o_now(h2o_socket_get_loop(sock)); pthread_mutex_lock(&pool->_shared.mutex); destroy_expired(pool); h2o_linklist_insert(&pool->_shared.sockets, &entry->link); pthread_mutex_unlock(&pool->_shared.mutex); return 0; }
h2o_hostinfo_getaddr_req_t *h2o_hostinfo_getaddr(h2o_multithread_receiver_t *receiver, h2o_iovec_t name, h2o_iovec_t serv, int family, int socktype, int protocol, int flags, h2o_hostinfo_getaddr_cb cb, void *cbdata) { h2o_hostinfo_getaddr_req_t *req = h2o_mem_alloc(sizeof(*req) + name.len + 1 + serv.len + 1); req->_receiver = receiver; req->_cb = cb; req->cbdata = cbdata; req->_pending = (h2o_linklist_t){0}; req->_in.name = (char *)req + sizeof(*req); memcpy(req->_in.name, name.base, name.len); req->_in.name[name.len] = '\0'; req->_in.serv = req->_in.name + name.len + 1; memcpy(req->_in.serv, serv.base, serv.len); req->_in.serv[serv.len] = '\0'; memset(&req->_in.hints, 0, sizeof(req->_in.hints)); req->_in.hints.ai_family = family; req->_in.hints.ai_socktype = socktype; req->_in.hints.ai_protocol = protocol; req->_in.hints.ai_flags = flags; h2o__hostinfo_getaddr_dispatch(req); return req; }
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 { 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_http2_stream_t *h2o_http2_stream_open(h2o_http2_conn_t *conn, uint32_t stream_id, const h2o_http2_priority_t *priority, h2o_req_t *src_req) { h2o_http2_stream_t *stream = h2o_mem_alloc(sizeof(*stream)); /* init properties (other than req) */ memset(stream, 0, offsetof(h2o_http2_stream_t, req)); stream->stream_id = stream_id; if (src_req != NULL) stream->is_half_closed = 1; stream->_ostr_final.do_send = finalostream_send; stream->_ostr_final.start_pull = finalostream_start_pull; stream->state = H2O_HTTP2_STREAM_STATE_RECV_PSUEDO_HEADERS; h2o_http2_window_init(&stream->output_window, &conn->peer_settings); h2o_http2_window_init(&stream->input_window, &H2O_HTTP2_SETTINGS_HOST); memcpy(&stream->priority, priority, sizeof(stream->priority)); h2o_buffer_init(&stream->_req_body, &h2o_socket_buffer_prototype); /* init request */ h2o_init_request(&stream->req, &conn->super, src_req); stream->req.version = 0x200; if (src_req != NULL) memset(&stream->req.upgrade, 0, sizeof(stream->req.upgrade)); stream->req._ostr_top = &stream->_ostr_final; h2o_http2_conn_register_stream(conn, stream); return stream; }
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.connect_timeout = H2O_DEFAULT_PROXY_IO_TIMEOUT; config->proxy.first_byte_timeout = H2O_DEFAULT_PROXY_IO_TIMEOUT; config->proxy.emit_x_forwarded_headers = 1; config->proxy.emit_via_header = 1; config->proxy.emit_missing_date_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.active_stream_window_size = H2O_DEFAULT_HTTP2_ACTIVE_STREAM_WINDOW_SIZE; 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->send_informational_mode = H2O_SEND_INFORMATIONAL_MODE_EXCEPT_H1; config->mimemap = h2o_mimemap_create(); h2o_socketpool_init_global(&config->proxy.global_socketpool, SIZE_MAX); h2o_configurator__init_core(config); }
void h2o_socket_ssl_server_handshake(h2o_socket_t *sock, SSL_CTX *ssl_ctx, h2o_socket_cb handshake_cb) { static BIO_METHOD bio_methods = {BIO_TYPE_FD, "h2o_socket", write_bio, read_bio, puts_bio, NULL, ctrl_bio, new_bio, free_bio, NULL}; BIO *bio; 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); bio = BIO_new(&bio_methods); bio->ptr = sock; bio->init = 1; sock->ssl->ssl = SSL_new(ssl_ctx); SSL_set_bio(sock->ssl->ssl, bio, bio); sock->ssl->handshake.cb = handshake_cb; proceed_handshake(sock, 0); }
void h2o_socket_ssl_server_handshake(h2o_socket_t *sock, SSL_CTX *ssl_ctx, h2o_socket_cb handshake_cb) { static BIO_METHOD bio_methods = { BIO_TYPE_FD, "h2o_socket", write_bio, read_bio, puts_bio, NULL, ctrl_bio, new_bio, free_bio, NULL }; BIO *bio; sock->ssl = h2o_mem_alloc(sizeof(*sock->ssl)); memset(sock->ssl, 0, offsetof(struct st_h2o_socket_ssl_t, output.pool)); h2o_buffer_init(&sock->ssl->input.encrypted, &h2o_socket_buffer_prototype); h2o_mem_init_pool(&sock->ssl->output.pool); bio = BIO_new(&bio_methods); bio->ptr = sock; bio->init = 1; sock->ssl->ssl = SSL_new(ssl_ctx); SSL_set_bio(sock->ssl->ssl, bio, bio); sock->ssl->handshake.cb = handshake_cb; proceed_handshake(sock, 0); }
void h2o_duration_stats_register(h2o_globalconf_t *conf) { int i, k; h2o_logger_t *logger; h2o_hostconf_t *hconf; durations_logger = logger = h2o_mem_alloc(sizeof(*logger)); memset(logger, 0, sizeof(*logger)); logger->_config_slot = conf->_num_config_slots++; logger->log_access = stat_access; logger->on_context_init = on_context_init; logger->on_context_dispose = on_context_dispose; for (k = 0; conf->hosts[k]; k++) { hconf = conf->hosts[k]; for (i = 0; i < hconf->paths.size; i++) { int j; for (j = 0; j < hconf->paths.entries[i].handlers.size; j++) { h2o_pathconf_t *pathconf = &hconf->paths.entries[i]; h2o_vector_reserve(NULL, &pathconf->loggers, pathconf->loggers.size + 1); pathconf->loggers.entries[pathconf->loggers.size++] = (void *)logger; } } } }
h2o_http2_stream_t *h2o_http2_stream_open(h2o_http2_conn_t *conn, uint32_t stream_id, h2o_req_t *src_req, const h2o_http2_priority_t *received_priority) { h2o_http2_stream_t *stream = h2o_mem_alloc(sizeof(*stream)); /* init properties (other than req) */ memset(stream, 0, offsetof(h2o_http2_stream_t, req)); stream->stream_id = stream_id; stream->_ostr_final.do_send = finalostream_send; stream->_ostr_final.start_pull = finalostream_start_pull; stream->state = H2O_HTTP2_STREAM_STATE_IDLE; h2o_http2_window_init(&stream->output_window, &conn->peer_settings); h2o_http2_window_init(&stream->input_window, &H2O_HTTP2_SETTINGS_HOST); stream->received_priority = *received_priority; stream->_expected_content_length = SIZE_MAX; /* init request */ h2o_init_request(&stream->req, &conn->super, src_req); stream->req.version = 0x200; if (src_req != NULL) memset(&stream->req.upgrade, 0, sizeof(stream->req.upgrade)); stream->req._ostr_top = &stream->_ostr_final; h2o_http2_conn_register_stream(conn, stream); ++conn->num_streams.priority.open; stream->_num_streams_slot = &conn->num_streams.priority; return stream; }
void h2o_proxy_register_reverse_proxy(h2o_pathconf_t *pathconf, h2o_url_t *upstream, 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; if (config->keepalive_timeout != 0) { self->sockpool = h2o_mem_alloc(sizeof(*self->sockpool)); struct sockaddr_un sa; const char *to_sa_err; int is_ssl = upstream->scheme == &H2O_URL_SCHEME_HTTPS; if ((to_sa_err = h2o_url_host_to_sun(upstream->host, &sa)) == h2o_url_host_to_sun_err_is_not_unix_socket) { h2o_socketpool_init_by_hostport(self->sockpool, upstream->host, h2o_url_get_port(upstream), is_ssl, SIZE_MAX /* FIXME */); } else { assert(to_sa_err == NULL); h2o_socketpool_init_by_address(self->sockpool, (void *)&sa, sizeof(sa), is_ssl, SIZE_MAX /* FIXME */); } } h2o_url_copy(NULL, &self->upstream, upstream); h2o_strtolower(self->upstream.host.base, self->upstream.host.len); self->config = *config; if (self->config.ssl_ctx != NULL) CRYPTO_add(&self->config.ssl_ctx->references, 1, CRYPTO_LOCK_SSL_CTX); }
static h2o_http2_scheduler_queue_t *get_queue(h2o_http2_scheduler_node_t *node) { if (node->_queue == NULL) { node->_queue = h2o_mem_alloc(sizeof(*node->_queue)); queue_init(node->_queue); } return node->_queue; }
static h2o_hostconf_t *create_hostconf(h2o_globalconf_t *globalconf) { h2o_hostconf_t *hostconf = h2o_mem_alloc(sizeof(*hostconf)); *hostconf = (h2o_hostconf_t){globalconf}; h2o_config_init_pathconf(&hostconf->fallback_path, globalconf, NULL, globalconf->mimemap); hostconf->mimemap = globalconf->mimemap; h2o_mem_addref_shared(hostconf->mimemap); return hostconf; }
h2o_iovec_t h2o_decode_base64url(h2o_mem_pool_t *pool, const char *src, size_t len) { h2o_iovec_t decoded; uint32_t t; uint8_t *dst; char remaining_input[4]; decoded.len = len * 3 / 4; decoded.base = pool != NULL ? h2o_mem_alloc_pool(pool, decoded.len + 1) : h2o_mem_alloc(decoded.len + 1); dst = (uint8_t *)decoded.base; while (len >= 4) { if ((t = decode_base64url_quad(src)) == UINT32_MAX) goto Error; *dst++ = t >> 16; *dst++ = t >> 8; *dst++ = t; src += 4; len -= 4; } switch (len) { case 0: break; case 1: goto Error; case 2: remaining_input[0] = *src++; remaining_input[1] = *src++; remaining_input[2] = 'A'; remaining_input[3] = 'A'; if ((t = decode_base64url_quad(remaining_input)) == UINT32_MAX) goto Error; *dst++ = t >> 16; break; case 3: remaining_input[0] = *src++; remaining_input[1] = *src++; remaining_input[2] = *src++; remaining_input[3] = 'A'; if ((t = decode_base64url_quad(remaining_input)) == UINT32_MAX) goto Error; *dst++ = t >> 16; *dst++ = t >> 8; break; } assert((char *)dst - decoded.base == decoded.len); decoded.base[decoded.len] = '\0'; return decoded; Error: if (pool == NULL) free(decoded.base); return h2o_iovec_init(NULL, 0); }
static inline void on_websocket_upgrade(struct rp_generator_t *self, h2o_timeout_t *timeout) { h2o_req_t *req = self->src_req; h2o_socket_t *sock = h2o_http1client_steal_socket(self->client); 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); }
h2o_filecache_t *h2o_filecache_create(size_t capacity) { h2o_filecache_t *cache = h2o_mem_alloc(sizeof(*cache)); cache->hash = kh_init(opencache_set); h2o_linklist_init_anchor(&cache->lru); cache->capacity = capacity; return cache; }
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; }
h2o_filecache_ref_t *h2o_filecache_open_file(h2o_filecache_t *cache, const char *path, int oflag) { khiter_t iter = kh_get(opencache_set, cache->hash, path); h2o_filecache_ref_t *ref; int dummy; /* lookup cache, and return the one if found */ if (iter != kh_end(cache->hash)) { ref = H2O_STRUCT_FROM_MEMBER(h2o_filecache_ref_t, _path, kh_key(cache->hash, iter)); ++ref->_refcnt; goto Exit; } /* create a new cache entry */ ref = h2o_mem_alloc(offsetof(h2o_filecache_ref_t, _path) + strlen(path) + 1); ref->_refcnt = 1; ref->_lru = (h2o_linklist_t){NULL}; strcpy(ref->_path, path); /* if cache is used, then... */ if (cache->capacity != 0) { /* purge one entry from LRU if cache is full */ if (kh_size(cache->hash) == cache->capacity) { h2o_filecache_ref_t *purge_ref = H2O_STRUCT_FROM_MEMBER(h2o_filecache_ref_t, _lru, cache->lru.prev); khiter_t purge_iter = kh_get(opencache_set, cache->hash, purge_ref->_path); assert(purge_iter != kh_end(cache->hash)); release_from_cache(cache, purge_iter); } /* assign the new entry */ ++ref->_refcnt; kh_put(opencache_set, cache->hash, ref->_path, &dummy); h2o_linklist_insert(cache->lru.next, &ref->_lru); } /* open the file, or memoize the error */ if ((ref->fd = open(path, oflag)) != -1 && fstat(ref->fd, &ref->st) == 0) { ref->_last_modified.str[0] = '\0'; ref->_etag.len = 0; } else { ref->open_err = errno; if (ref->fd != -1) { close(ref->fd); ref->fd = -1; } } Exit: /* if the cache entry retains an error, return it instead of the reference */ if (ref->fd == -1) { errno = ref->open_err; h2o_filecache_close_file(ref); ref = NULL; } return ref; }
h2o_http2_casper_t *h2o_http2_casper_create(unsigned capacity_bits, unsigned remainder_bits) { h2o_http2_casper_t *casper = h2o_mem_alloc(sizeof(*casper)); memset(&casper->keys, 0, sizeof(casper->keys)); casper->capacity_bits = capacity_bits; casper->remainder_bits = remainder_bits; casper->cookie_cache = (h2o_iovec_t){}; return casper; }
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 void *durations_status_init(void) { struct st_duration_agg_stats_t *agg_stats; agg_stats = h2o_mem_alloc(sizeof(*agg_stats)); duration_stats_init(&agg_stats->stats); pthread_mutex_init(&agg_stats->mutex, NULL); return agg_stats; }