Example #1
0
File: rproxy.c Project: Gwill/h2o
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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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);
    }
}
Example #5
0
File: rproxy.c Project: Gwill/h2o
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);
}
Example #6
0
File: config.c Project: ifzz/h2o
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;
}
Example #7
0
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;
}
Example #8
0
File: file.c Project: lhjay1/h2o
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;
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
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);
    }
}
Example #12
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;
}
Example #13
0
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;
}
Example #14
0
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);
}
Example #15
0
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);
}
Example #16
0
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;
}
Example #17
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;
}
Example #18
0
File: http1.c Project: ifzz/h2o
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;
}
Example #19
0
File: config.c Project: Gwill/h2o
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;
}
Example #20
0
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();
}
Example #21
0
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;
}
Example #22
0
File: util.c Project: nwcs/h2o
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){};
}
Example #23
0
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);
}
Example #24
0
File: file.c Project: ancuop/h2o
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;
}
Example #25
0
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;
}
Example #26
0
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);
}
Example #27
0
File: file.c Project: ancuop/h2o
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);
}
Example #28
0
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);
}
Example #29
0
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;
}
Example #30
0
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);
}