static void finalostream_start_pull(h2o_ostream_t *_self, h2o_ostream_pull_cb cb) { struct st_h2o_http1_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1_conn_t, _ostr_final.super, _self); const char *connection = conn->req.http1_is_persistent ? "keep-alive" : "close"; size_t bufsz, headers_len; assert(conn->req._ostr_top == &conn->_ostr_final.super); assert(!conn->_ostr_final.sent_headers); conn->req.timestamps.response_start_at = *h2o_get_timestamp(conn->super.ctx, NULL, NULL); /* register the pull callback */ conn->_ostr_final.pull.cb = cb; /* setup the buffer */ bufsz = flatten_headers_estimate_size(&conn->req, conn->super.ctx->globalconf->server_name.len + strlen(connection)); if (bufsz < MAX_PULL_BUF_SZ) { if (MAX_PULL_BUF_SZ - bufsz < conn->req.res.content_length) { bufsz = MAX_PULL_BUF_SZ; } else { bufsz += conn->req.res.content_length; } } conn->_ostr_final.pull.buf = h2o_mem_alloc_pool(&conn->req.pool, bufsz); /* fill-in the header */ headers_len = flatten_headers(conn->_ostr_final.pull.buf, &conn->req, connection); conn->_ostr_final.sent_headers = 1; proceed_pull(conn, headers_len); }
void finalostream_send(h2o_ostream_t *_self, h2o_req_t *req, h2o_iovec_t *inbufs, size_t inbufcnt, int is_final) { struct st_h2o_http1_finalostream_t *self = (void *)_self; struct st_h2o_http1_conn_t *conn = (struct st_h2o_http1_conn_t *)req->conn; h2o_iovec_t *bufs = alloca(sizeof(h2o_iovec_t) * (inbufcnt + 1)); int bufcnt = 0; assert(self == &conn->_ostr_final); if (!self->sent_headers) { conn->req.timestamps.response_start_at = *h2o_get_timestamp(conn->super.ctx, NULL, NULL); /* build headers and send */ const char *connection = req->http1_is_persistent ? "keep-alive" : "close"; bufs[bufcnt].base = h2o_mem_alloc_pool( &req->pool, flatten_headers_estimate_size(req, conn->super.ctx->globalconf->server_name.len + strlen(connection))); bufs[bufcnt].len = flatten_headers(bufs[bufcnt].base, req, connection); ++bufcnt; self->sent_headers = 1; } memcpy(bufs + bufcnt, inbufs, sizeof(h2o_iovec_t) * inbufcnt); bufcnt += inbufcnt; if (bufcnt != 0) { h2o_socket_write(conn->sock, bufs, bufcnt, is_final ? on_send_complete : on_send_next_push); } else { on_send_complete(conn->sock, 0); } }
void h2o_http1_upgrade(h2o_http1_conn_t *conn, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_http1_upgrade_cb on_complete, void *user_data) { h2o_iovec_t *bufs = alloca(sizeof(h2o_iovec_t) * (inbufcnt + 1)); conn->upgrade.data = user_data; conn->upgrade.cb = on_complete; bufs[0].base = h2o_mem_alloc_pool( &conn->req.pool, flatten_headers_estimate_size(&conn->req, conn->super.ctx->globalconf->server_name.len + sizeof("upgrade") - 1)); bufs[0].len = flatten_headers(bufs[0].base, &conn->req, "upgrade"); memcpy(bufs + 1, inbufs, sizeof(h2o_iovec_t) * inbufcnt); h2o_socket_write(conn->sock, bufs, (int)(inbufcnt + 1), on_upgrade_complete); }
void h2o_http1_upgrade(h2o_req_t *req, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_http1_upgrade_cb on_complete, void *user_data) { struct st_h2o_http1_conn_t *conn = (void *)req->conn; assert(req->version <= 0x200); /* TODO find a better way to assert instanceof(req->conn) == struct st_h2o_http1_conn_t */ h2o_iovec_t *bufs = alloca(sizeof(h2o_iovec_t) * (inbufcnt + 1)); conn->upgrade.data = user_data; conn->upgrade.cb = on_complete; bufs[0].base = h2o_mem_alloc_pool(&conn->req.pool, flatten_headers_estimate_size(&conn->req, conn->super.ctx->globalconf->server_name.len + sizeof("upgrade") - 1)); bufs[0].len = flatten_headers(bufs[0].base, &conn->req, "upgrade"); memcpy(bufs + 1, inbufs, sizeof(h2o_iovec_t) * inbufcnt); h2o_socket_write(conn->sock, bufs, inbufcnt + 1, on_upgrade_complete); }