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; }
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); }
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); }
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); } }
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; }