static void http_server_istream_switch_ioloop(struct istream_private *stream) { struct http_server_istream *hsristream = (struct http_server_istream *)stream; if (hsristream->istream.istream.blocking) return; http_server_connection_switch_ioloop(hsristream->req->conn); }
void http_server_switch_ioloop(struct http_server *server) { struct connection *_conn = server->conn_list->connections; /* move connections */ /* FIXME: we wouldn't necessarily need to switch all of them immediately, only those that have requests now. but also connections that get new requests before ioloop is switched again.. */ for (; _conn != NULL; _conn = _conn->next) { struct http_server_connection *conn = (struct http_server_connection *)_conn; http_server_connection_switch_ioloop(conn); } }
static ssize_t http_server_istream_read(struct istream_private *stream) { struct http_server_istream *hsristream = (struct http_server_istream *)stream; struct http_server_request *req = hsristream->req; struct http_server *server; struct http_server_connection *conn; bool blocking = stream->istream.blocking; ssize_t ret; if (req == NULL) { /* request already gone (we shouldn't get here) */ stream->istream.stream_errno = EINVAL; return -1; } i_stream_seek(stream->parent, stream->parent_start_offset + stream->istream.v_offset); server = hsristream->req->server; conn = hsristream->req->conn; ret = i_stream_read_copy_from_parent(&stream->istream); if (ret == 0 && blocking) { struct ioloop *prev_ioloop = current_ioloop; struct io *io; http_server_connection_ref(conn); http_server_request_ref(req); i_assert(server->ioloop == NULL); server->ioloop = io_loop_create(); http_server_connection_switch_ioloop(conn); if (blocking && req->req.expect_100_continue && !req->sent_100_continue) http_server_connection_trigger_responses(conn); hsristream->read_status = 0; io = io_add_istream(&stream->istream, http_server_istream_read_any, hsristream); while (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED && hsristream->read_status == 0) { io_loop_run(server->ioloop); } io_remove(&io); io_loop_set_current(prev_ioloop); http_server_connection_switch_ioloop(conn); io_loop_set_current(server->ioloop); io_loop_destroy(&server->ioloop); ret = hsristream->read_status; if (!http_server_request_unref(&req)) hsristream->req = NULL; http_server_connection_unref(&conn); } return ret; }