Example #1
0
void http_server_request_submit_response(struct http_server_request *req)
{
	struct http_server_connection *conn = req->conn;

	i_assert(conn != NULL && req->response != NULL && req->response->submitted);

	http_server_request_ref(req);

	if (conn->payload_handler != NULL && conn->payload_handler->req == req)
		http_server_payload_handler_destroy(&conn->payload_handler);

	switch (req->state) {
	case HTTP_SERVER_REQUEST_STATE_NEW:
	case HTTP_SERVER_REQUEST_STATE_QUEUED:
	case HTTP_SERVER_REQUEST_STATE_PAYLOAD_IN:
	case HTTP_SERVER_REQUEST_STATE_PROCESSING:
		if (!http_server_request_is_complete(req)) {
			http_server_request_debug(req, "Not ready to respond");
			req->state = HTTP_SERVER_REQUEST_STATE_SUBMITTED_RESPONSE;
			break;
		}
		http_server_request_ready_to_respond(req);
		break;
	case HTTP_SERVER_REQUEST_STATE_READY_TO_RESPOND:
		http_server_connection_trigger_responses(req->conn);
		break;
	case HTTP_SERVER_REQUEST_STATE_ABORTED:
		break;
	default:
		i_unreached();
	}

	http_server_request_unref(&req);
}
Example #2
0
void http_server_request_continue_payload(struct http_server_request *req)
{
	i_assert(req->state <= HTTP_SERVER_REQUEST_STATE_QUEUED);
	req->payload_halted = FALSE;
	if (req->req.expect_100_continue && !req->sent_100_continue)
		http_server_connection_trigger_responses(req->conn);
}
Example #3
0
void http_server_request_ready_to_respond(struct http_server_request *req)
{
	http_server_request_debug(req, "Ready to respond");

	req->state = HTTP_SERVER_REQUEST_STATE_READY_TO_RESPOND;
	http_server_connection_trigger_responses(req->conn);
}
Example #4
0
void http_server_request_finished(struct http_server_request *req)
{
	struct http_server_connection *conn = req->conn;
	struct http_server_response *resp = req->response;
	http_server_tunnel_callback_t tunnel_callback = resp->tunnel_callback;
	void *tunnel_context = resp->tunnel_context;

	http_server_request_debug(req, "Finished");

	i_assert(req->state < HTTP_SERVER_REQUEST_STATE_FINISHED);
	req->state = HTTP_SERVER_REQUEST_STATE_FINISHED;

	http_server_connection_remove_request(conn, req);
	conn->stats.response_count++;

	if (tunnel_callback == NULL) {
		if (req->connection_close) {
			http_server_connection_close(&conn,
				t_strdup_printf("Server closed connection: %u %s",
					resp->status, resp->reason));
			http_server_request_destroy(&req);
			return;
		} else if (req->conn->input_broken) {
			http_server_connection_close(&conn,
				"Connection input is broken");
			http_server_request_destroy(&req);
			return;
		} else if (req->req.connection_close) {
			http_server_connection_close(&conn,
				"Client requested connection close");
			http_server_request_destroy(&req);
			return;
		}
	}

	http_server_request_destroy(&req);
	if (tunnel_callback != NULL) {
		http_server_connection_tunnel(&conn, tunnel_callback, tunnel_context);
		return;
	}
	
	http_server_connection_trigger_responses(conn);
}
Example #5
0
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;
}