void http_client_request_destroy(struct http_client_request **_req) { struct http_client_request *req = *_req; struct http_client *client = req->client; *_req = NULL; http_client_request_debug(req, "Destroy (requests left=%d)", client->requests_count); if (req->state < HTTP_REQUEST_STATE_FINISHED) req->state = HTTP_REQUEST_STATE_ABORTED; req->callback = NULL; if (req->queue != NULL) http_client_queue_drop_request(req->queue, req); if (req->destroy_callback != NULL) { void (*callback)(void *) = req->destroy_callback; req->destroy_callback = NULL; callback(req->destroy_context); } http_client_request_remove(req); 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->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_abort(struct http_client_request **_req) { struct http_client_request *req = *_req; if (req->state >= HTTP_REQUEST_STATE_FINISHED) return; req->callback = NULL; req->state = HTTP_REQUEST_STATE_ABORTED; if (req->queue != NULL) http_client_queue_drop_request(req->queue, req); http_client_request_unref(_req); }
void http_client_request_finish(struct http_client_request **_req) { struct http_client_request *req = *_req; if (req->state >= HTTP_REQUEST_STATE_FINISHED) return; http_client_request_debug(req, "Finished"); req->callback = NULL; req->state = HTTP_REQUEST_STATE_FINISHED; if (req->payload_wait && req->client->ioloop != NULL) io_loop_stop(req->client->ioloop); http_client_request_unref(_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); } }
void http_client_request_finish(struct http_client_request *req) { if (req->state >= HTTP_REQUEST_STATE_FINISHED) return; i_assert(req->refcount > 0); http_client_request_debug(req, "Finished"); req->callback = NULL; req->state = HTTP_REQUEST_STATE_FINISHED; if (req->queue != NULL) http_client_queue_drop_request(req->queue, req); if (req->payload_wait && req->client->ioloop != NULL) io_loop_stop(req->client->ioloop); http_client_request_unref(&req); }
static int http_client_request_continue_payload(struct http_client_request **_req, const unsigned char *data, size_t size) { struct ioloop *prev_ioloop = current_ioloop; struct http_client_request *req = *_req; struct http_client_connection *conn = req->conn; struct http_client *client = req->client; int ret; i_assert(req->state == HTTP_REQUEST_STATE_NEW || req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT); i_assert(req->payload_input == NULL); if (conn != NULL) http_client_connection_ref(conn); http_client_request_ref(req); req->payload_wait = TRUE; if (data == NULL) { req->payload_input = NULL; if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT) http_client_request_finish_payload_out(req); } else { req->payload_input = i_stream_create_from_data(data, size); i_stream_set_name(req->payload_input, "<HTTP request payload>"); } req->payload_size = 0; req->payload_chunked = TRUE; if (req->state == HTTP_REQUEST_STATE_NEW) http_client_request_submit(req); /* Wait for payload data to be written */ i_assert(client->ioloop == NULL); client->ioloop = io_loop_create(); http_client_switch_ioloop(client); if (client->set.dns_client != NULL) dns_client_switch_ioloop(client->set.dns_client); while (req->state < HTTP_REQUEST_STATE_PAYLOAD_IN) { http_client_request_debug(req, "Waiting for request to finish"); if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT) o_stream_set_flush_pending(req->payload_output, TRUE); io_loop_run(client->ioloop); if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT && req->payload_input->eof) { i_stream_unref(&req->payload_input); req->payload_input = NULL; break; } } io_loop_set_current(prev_ioloop); http_client_switch_ioloop(client); if (client->set.dns_client != NULL) dns_client_switch_ioloop(client->set.dns_client); io_loop_set_current(client->ioloop); io_loop_destroy(&client->ioloop); switch (req->state) { case HTTP_REQUEST_STATE_PAYLOAD_IN: case HTTP_REQUEST_STATE_FINISHED: ret = 1; break; case HTTP_REQUEST_STATE_ABORTED: ret = -1; break; default: ret = 0; break; } req->payload_wait = FALSE; /* callback may have messed with our pointer, so unref using local variable */ if (!http_client_request_unref(&req)) *_req = NULL; if (conn != NULL) http_client_connection_unref(&conn); /* Return status */ return ret; }