コード例 #1
0
ファイル: socketpool.c プロジェクト: IvwsIgeMq/h2o
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;
}
コード例 #2
0
ファイル: timeout.c プロジェクト: topcpporg/h2
void h2o_timeout_link(h2o_loop_t *loop, h2o_timeout_t *timeout, h2o_timeout_entry_t *entry)
{
    /* insert at tail, so that the entries are sorted in ascending order */
    h2o_linklist_insert(&timeout->_entries, &entry->_link);
    /* set data */
    entry->registered_at = h2o_now(loop);

    h2o_timeout__do_link(loop, timeout, entry);
}
コード例 #3
0
ファイル: socket.c プロジェクト: deweerdt/h2o
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);
    }
}
コード例 #4
0
ファイル: socketpool.c プロジェクト: LearningSystems/h2o
static void destroy_expired(h2o_socketpool_t *pool)
{
    /* caller should lock the mutex */
    uint64_t expire_before = h2o_now(pool->_interval_cb.loop) - pool->timeout;
    while (!h2o_linklist_is_empty(&pool->_shared.sockets)) {
        struct pool_entry_t *entry = H2O_STRUCT_FROM_MEMBER(struct pool_entry_t, link, pool->_shared.sockets.next);
        if (entry->added_at > expire_before)
            break;
        destroy_attached(entry);
        __sync_sub_and_fetch(&pool->_shared.count, 1);
    }
}
コード例 #5
0
ファイル: context.c プロジェクト: topcpporg/h2
void h2o_context_update_timestamp_cache(h2o_context_t *ctx)
{
    time_t prev_sec = ctx->_timestamp_cache.tv_at.tv_sec;
    ctx->_timestamp_cache.uv_now_at = h2o_now(ctx->loop);
    gettimeofday(&ctx->_timestamp_cache.tv_at, NULL);
    if (ctx->_timestamp_cache.tv_at.tv_sec != prev_sec) {
        struct tm gmt;
        /* update the string cache */
        if (ctx->_timestamp_cache.value != NULL)
            h2o_mem_release_shared(ctx->_timestamp_cache.value);
        ctx->_timestamp_cache.value = h2o_mem_alloc_shared(NULL, sizeof(h2o_timestamp_string_t), NULL);
        gmtime_r(&ctx->_timestamp_cache.tv_at.tv_sec, &gmt);
        h2o_time2str_rfc1123(ctx->_timestamp_cache.value->rfc1123, &gmt);
        h2o_time2str_log(ctx->_timestamp_cache.value->log, ctx->_timestamp_cache.tv_at.tv_sec);
    }
}
コード例 #6
0
ファイル: socket.c プロジェクト: deweerdt/h2o
static void on_handshake_complete(h2o_socket_t *sock, const char *err)
{
    if (err == NULL) {
        const SSL_CIPHER *cipher = SSL_get_current_cipher(sock->ssl->ssl);
        switch (SSL_CIPHER_get_id(cipher)) {
        case TLS1_CK_RSA_WITH_AES_128_GCM_SHA256:
        case TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256:
        case TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
        case TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
        case TLS1_CK_RSA_WITH_AES_256_GCM_SHA384:
        case TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384:
        case TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
        case TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
            sock->ssl->record_overhead = 5 /* header */ + 8 /* record_iv_length (RFC 5288 3) */ + 16 /* tag (RFC 5116 5.1) */;
            break;
#if defined(TLS1_CK_DHE_RSA_CHACHA20_POLY1305)
        case TLS1_CK_DHE_RSA_CHACHA20_POLY1305:
        case TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305:
        case TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305:
            sock->ssl->record_overhead = 5 /* header */ + 16 /* tag */;
            break;
#endif
        default:
            sock->ssl->record_overhead = 32; /* sufficiently large number that can hold most payloads */
            break;
        }
    }

    /* set ssl session into the cache */
    if (sock->ssl->handshake.client.session_cache != NULL) {
        if (err == NULL || err == h2o_socket_error_ssl_cert_name_mismatch) {
            SSL_SESSION *session = SSL_get1_session(sock->ssl->ssl);
            h2o_cache_set(sock->ssl->handshake.client.session_cache, h2o_now(h2o_socket_get_loop(sock)),
                          sock->ssl->handshake.client.session_cache_key, sock->ssl->handshake.client.session_cache_key_hash,
                          h2o_iovec_init(session, 1));
        }
    }

    h2o_socket_cb handshake_cb = sock->ssl->handshake.cb;
    sock->_cb.write = NULL;
    sock->ssl->handshake.cb = NULL;
    decode_ssl_input(sock);
    handshake_cb(sock, err);
}
コード例 #7
0
ファイル: context.c プロジェクト: bowlofstew/h2o
void h2o_get_timestamp(h2o_context_t *ctx, h2o_mem_pool_t *pool, h2o_timestamp_t *ts)
{
    uint64_t now = h2o_now(ctx->loop);

    if (ctx->_timestamp_cache.uv_now_at != now) {
        time_t prev_sec = ctx->_timestamp_cache.tv_at.tv_sec;
        ctx->_timestamp_cache.uv_now_at = now;
        gettimeofday(&ctx->_timestamp_cache.tv_at, NULL);
        if (ctx->_timestamp_cache.tv_at.tv_sec != prev_sec) {
            /* update the string cache */
            if (ctx->_timestamp_cache.value != NULL)
                h2o_mem_release_shared(ctx->_timestamp_cache.value);
            ctx->_timestamp_cache.value = h2o_mem_alloc_shared(NULL, sizeof(h2o_timestamp_string_t), NULL);
            h2o_time2str_rfc1123(ctx->_timestamp_cache.value->rfc1123, ctx->_timestamp_cache.tv_at.tv_sec);
            h2o_time2str_log(ctx->_timestamp_cache.value->log, ctx->_timestamp_cache.tv_at.tv_sec);
        }
    }

    ts->at = ctx->_timestamp_cache.tv_at;
    h2o_mem_link_shared(pool, ctx->_timestamp_cache.value);
    ts->str = ctx->_timestamp_cache.value;
}
コード例 #8
0
ファイル: world.c プロジェクト: djones6/FrameworkBenchmarks
static int do_multiple_queries(bool do_update, bool use_cache, h2o_req_t *req)
{
	thread_context_t * const ctx = H2O_STRUCT_FROM_MEMBER(thread_context_t,
	                                                      event_loop.h2o_ctx,
	                                                      req->conn->ctx);

	const size_t num_query = get_query_number(req);

	// MAX_QUERIES is a relatively small number, so assume no overflow in the following
	// arithmetic operations.
	assert(num_query <= MAX_QUERIES);

	size_t base_size = offsetof(multiple_query_ctx_t, res) + num_query * sizeof(query_result_t);

	base_size = ((base_size + _Alignof(query_param_t) - 1) / _Alignof(query_param_t));
	base_size = base_size * _Alignof(query_param_t);

	const size_t num_query_in_progress = MIN(num_query, ctx->config->max_db_conn_num);
	size_t sz = base_size + num_query_in_progress * sizeof(query_param_t);

	if (do_update) {
		const size_t reuse_size = (num_query_in_progress - 1) * sizeof(query_param_t);
		const size_t update_query_len = MAX_UPDATE_QUERY_LEN(num_query);

		if (update_query_len > reuse_size)
			sz += update_query_len - reuse_size;
	}

	multiple_query_ctx_t * const query_ctx = calloc(1, sz);

	if (query_ctx) {
		multiple_query_ctx_t ** const p = h2o_mem_alloc_shared(&req->pool,
		                                                       sizeof(*p),
		                                                       cleanup_multiple_query_request);

		*p = query_ctx;
		query_ctx->ctx = ctx;
		query_ctx->num_query = num_query;
		query_ctx->req = req;
		query_ctx->do_update = do_update;
		query_ctx->use_cache = use_cache;
		query_ctx->query_param = (query_param_t *) ((char *) query_ctx + base_size);
		initialize_ids(num_query, query_ctx->res, &ctx->random_seed);

		if (use_cache) {
			fetch_from_cache(h2o_now(ctx->event_loop.h2o_ctx.loop),
			                 &ctx->global_data->world_cache,
			                 query_ctx);

			if (query_ctx->num_result == query_ctx->num_query) {
				complete_multiple_query(query_ctx);
				return 0;
			}
		}

		query_ctx->num_query_in_progress = MIN(num_query_in_progress,
		                                       query_ctx->num_query - query_ctx->num_result);

		for (size_t i = 0; i < query_ctx->num_query_in_progress; i++) {
			query_ctx->query_param[i].ctx = query_ctx;
			// We need a copy of id because the original may be overwritten
			// by a completed query.
			query_ctx->query_param[i].id = htonl(query_ctx->res[query_ctx->num_result + i].id);
			query_ctx->query_param[i].id_format = 1;
			query_ctx->query_param[i].id_len = sizeof(query_ctx->query_param[i].id);
			query_ctx->query_param[i].id_pointer = (const char *) &query_ctx->query_param[i].id;
			query_ctx->query_param[i].param.command = WORLD_TABLE_NAME;
			query_ctx->query_param[i].param.nParams = 1;
			query_ctx->query_param[i].param.on_error = on_multiple_query_error;
			query_ctx->query_param[i].param.on_result = on_multiple_query_result;
			query_ctx->query_param[i].param.on_timeout = on_multiple_query_timeout;
			query_ctx->query_param[i].param.paramFormats = &query_ctx->query_param[i].id_format;
			query_ctx->query_param[i].param.paramLengths = &query_ctx->query_param[i].id_len;
			query_ctx->query_param[i].param.paramValues = &query_ctx->query_param[i].id_pointer;
			query_ctx->query_param[i].param.flags = IS_PREPARED;
			query_ctx->query_param[i].param.resultFormat = 1;

			if (execute_query(ctx, &query_ctx->query_param[i].param)) {
				query_ctx->num_query_in_progress = i;
				query_ctx->cleanup = true;
				send_service_unavailable_error(DB_REQ_ERROR, req);
				return 0;
			}
		}
	}
	else
		send_error(INTERNAL_SERVER_ERROR, REQ_ERROR, req);

	return 0;
}