static void initiate_graceful_shutdown(h2o_context_t *ctx) { /* draft-16 6.8 * A server that is attempting to gracefully shut down a connection SHOULD send an initial GOAWAY frame with the last stream * identifier set to 231-1 and a NO_ERROR code. This signals to the client that a shutdown is imminent and that no further * requests can be initiated. After waiting at least one round trip time, the server can send another GOAWAY frame with an * updated last stream identifier. This ensures that a connection can be cleanly shut down without losing requests. */ h2o_linklist_t *node; /* only doit once */ if (ctx->http2._graceful_shutdown_timeout.cb != NULL) return; ctx->http2._graceful_shutdown_timeout.cb = graceful_shutdown_resend_goaway; for (node = ctx->http2._conns.next; node != &ctx->http2._conns; node = node->next) { h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, _conns, node); if (conn->state < H2O_HTTP2_CONN_STATE_HALF_CLOSED) { h2o_http2_encode_goaway_frame(&conn->_write.buf, INT32_MAX, H2O_HTTP2_ERROR_NONE, (h2o_iovec_t){H2O_STRLIT("graceful shutdown")}); h2o_http2_conn_request_write(conn); } } h2o_timeout_link(ctx->loop, &ctx->one_sec_timeout, &ctx->http2._graceful_shutdown_timeout); }
static void update_idle_timeout(h2o_http2_conn_t *conn) { h2o_timeout_unlink(&conn->_timeout_entry); if (conn->num_streams.responding == 0) { assert(h2o_linklist_is_empty(&conn->_pending_reqs)); conn->_timeout_entry.cb = on_idle_timeout; h2o_timeout_link(conn->super.ctx->loop, &conn->super.ctx->http2.idle_timeout, &conn->_timeout_entry); } }
void h2o_socketpool_set_timeout(h2o_socketpool_t *pool, h2o_loop_t *loop, uint64_t msec) { pool->timeout = msec; pool->_interval_cb.loop = loop; h2o_timeout_init(loop, &pool->_interval_cb.timeout, 1000); pool->_interval_cb.entry.cb = on_timeout; h2o_timeout_link(loop, &pool->_interval_cb.timeout, &pool->_interval_cb.entry); }
void h2o_socketpool_register_loop(h2o_socketpool_t *pool, h2o_loop_t *loop) { if (pool->_interval_cb.loop != NULL) return; pool->_interval_cb.loop = loop; h2o_timeout_init(loop, &pool->_interval_cb.timeout, 1000); pool->_interval_cb.entry.cb = on_timeout; h2o_timeout_link(loop, &pool->_interval_cb.timeout, &pool->_interval_cb.entry); }
void h2o_ostream_send_next(h2o_ostream_t *ostream, h2o_req_t *req, h2o_buf_t *bufs, size_t bufcnt, int is_final) { if (is_final) { assert(req->_ostr_top == ostream); req->_ostr_top = ostream->next; } else if (bufcnt == 0) { h2o_timeout_link(req->conn->ctx->loop, &req->conn->ctx->zero_timeout, &req->_timeout_entry); return; } ostream->next->do_send(ostream->next, req, bufs, bufcnt, is_final); }
static void set_timeout(struct st_h2o_http1_conn_t *conn, h2o_timeout_t *timeout, h2o_timeout_cb cb) { if (conn->_timeout != NULL) { h2o_timeout_unlink(&conn->_timeout_entry); conn->_timeout_entry.cb = NULL; } conn->_timeout = timeout; if (timeout != NULL) { h2o_timeout_link(conn->super.ctx->loop, timeout, &conn->_timeout_entry); conn->_timeout_entry.cb = cb; } }
static struct st_h2o_accept_data_t *create_accept_data(h2o_accept_ctx_t *ctx, h2o_socket_t *sock) { struct st_h2o_accept_data_t *data = h2o_mem_alloc(sizeof(*data)); data->ctx = ctx; data->sock = sock; data->timeout = (h2o_timeout_entry_t){}; data->timeout.cb = on_accept_timeout; h2o_timeout_link(ctx->ctx->loop, &ctx->ctx->handshake_timeout, &data->timeout); sock->data = data; return data; }
static void on_timeout(h2o_timeout_entry_t *timeout_entry) { /* FIXME decrease the frequency of this function being called; the expiration * check can be (should be) performed in the `connect` fuction as well */ h2o_socketpool_t *pool = H2O_STRUCT_FROM_MEMBER(h2o_socketpool_t, _interval_cb.entry, timeout_entry); if (pthread_mutex_trylock(&pool->_shared.mutex) == 0) { destroy_expired(pool); pthread_mutex_unlock(&pool->_shared.mutex); } h2o_timeout_link(pool->_interval_cb.loop, &pool->_interval_cb.timeout, &pool->_interval_cb.entry); }
static struct st_h2o_accept_data_t *create_accept_data(h2o_accept_ctx_t *ctx, h2o_socket_t *sock, struct timeval connected_at) { struct st_h2o_accept_data_t *data = h2o_mem_alloc(sizeof(*data)); data->ctx = ctx; data->sock = sock; data->timeout = (h2o_timeout_entry_t){}; data->timeout.cb = on_accept_timeout; h2o_timeout_link(ctx->ctx->loop, &ctx->ctx->handshake_timeout, &data->timeout); data->async_resumption_get_req = NULL; data->connected_at = connected_at; sock->data = data; return data; }