Ejemplo n.º 1
0
void http_client_request_error(struct http_client_request **_req,
	unsigned int status, const char *error)
{
	struct http_client_request *req = *_req;

	i_assert(req->state < HTTP_REQUEST_STATE_FINISHED);
	req->state = HTTP_REQUEST_STATE_ABORTED;

	if (req->queue != NULL)
		http_client_queue_drop_request(req->queue, req);

	if (!req->submitted ||
		req->state == HTTP_REQUEST_STATE_GOT_RESPONSE) {
		/* we're still in http_client_request_submit() or in the callback
		   during a retry attempt. delay reporting the error, so the caller
		   doesn't have to handle immediate or nested callbacks. */
		i_assert(req->delayed_error == NULL);
		req->delayed_error = p_strdup(req->pool, error);
		req->delayed_error_status = status;
		http_client_delay_request_error(req->client, req);
	} else {
		if (http_client_request_send_error(req, status, error))
			http_client_request_destroy(&req);
	}
	*_req = NULL;
}
Ejemplo n.º 2
0
void http_client_request_error_delayed(struct http_client_request **_req)
{
	struct http_client_request *req = *_req;

	i_assert(req->delayed_error != NULL && req->delayed_error_status != 0);
	http_client_request_send_error(req, req->delayed_error_status,
				       req->delayed_error);
	http_client_request_unref(_req);
}
Ejemplo n.º 3
0
void http_client_request_error_delayed(struct http_client_request **_req)
{
	struct http_client_request *req = *_req;

	i_assert(req->state == HTTP_REQUEST_STATE_ABORTED);

	*_req = NULL;

	i_assert(req->delayed_error != NULL && req->delayed_error_status != 0);
	http_client_request_send_error(req, req->delayed_error_status,
				       req->delayed_error);
	if (req->queue != NULL)
		http_client_queue_drop_request(req->queue, req);
	http_client_request_destroy(&req);
}
Ejemplo n.º 4
0
void http_client_request_error(struct http_client_request *req,
	unsigned int status, const char *error)
{
	if (!req->submitted && req->state < HTTP_REQUEST_STATE_FINISHED) {
		/* we're still in http_client_request_submit(). delay
		   reporting the error, so the caller doesn't have to handle
		   immediate callbacks. */
		i_assert(req->delayed_error == NULL);
		req->delayed_error = p_strdup(req->pool, error);
		req->delayed_error_status = status;
		http_client_host_delay_request_error(req->host, req);
	} else {
		http_client_request_send_error(req, status, error);
		http_client_request_unref(&req);
	}
}
Ejemplo n.º 5
0
int http_client_request_send_more(struct http_client_request *req,
				  const char **error_r)
{
	struct http_client_connection *conn = req->conn;
	struct ostream *output = req->payload_output;
	off_t ret;
	int fd;

	i_assert(req->payload_input != NULL);
	i_assert(req->payload_output != NULL);

	if (conn->io_req_payload != NULL)
		io_remove(&conn->io_req_payload);

	/* chunked ostream needs to write to the parent stream's buffer */
	o_stream_set_max_buffer_size(output, IO_BLOCK_SIZE);
	ret = o_stream_send_istream(output, req->payload_input);
	o_stream_set_max_buffer_size(output, (size_t)-1);

	if (req->payload_input->stream_errno != 0) {
		/* the payload stream assigned to this request is broken,
		   fail this the request immediately */
		http_client_request_send_error(req,
			HTTP_CLIENT_REQUEST_ERROR_BROKEN_PAYLOAD,
			"Broken payload stream");

		/* we're in the middle of sending a request, so the connection
		   will also have to be aborted */
		errno = req->payload_input->stream_errno;
		*error_r = t_strdup_printf("read(%s) failed: %s",
					   i_stream_get_name(req->payload_input),
					   i_stream_get_error(req->payload_input));
		ret = -1;
	} else if (output->stream_errno != 0) {
		/* failed to send request */
		errno = output->stream_errno;
		*error_r = t_strdup_printf("write(%s) failed: %s",
					   o_stream_get_name(output),
					   o_stream_get_error(output));
		ret = -1;
	} else {
		i_assert(ret >= 0);
	}

	if (ret < 0 || i_stream_is_eof(req->payload_input)) {
		if (!req->payload_chunked &&
			req->payload_input->v_offset - req->payload_offset != req->payload_size) {
			*error_r = "stream input size changed [BUG]";
			i_error("stream input size changed"); //FIXME
			return -1;
		}

		if (req->payload_wait) {
			conn->output_locked = TRUE;
			if (req->client->ioloop != NULL)
				io_loop_stop(req->client->ioloop);
		} else {
			http_client_request_finish_payload_out(req);
		}
	} else if (i_stream_get_data_size(req->payload_input) > 0) {
		/* output is blocking */
		conn->output_locked = TRUE;
		o_stream_set_flush_pending(output, TRUE);
		http_client_request_debug(req, "Partially sent payload");
	} else {
		/* input is blocking */
		fd = i_stream_get_fd(req->payload_input);
		conn->output_locked = TRUE;	
		i_assert(fd >= 0);
		conn->io_req_payload = io_add
			(fd, IO_READ, http_client_request_payload_input, req);
	}
	return ret < 0 ? -1 : 0;
}