Skip to content

Commit

Permalink
lib-http: client: Perform output stream error handling in one place.
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanbosch authored and villesavolainen committed Mar 12, 2018
1 parent 1aa3d38 commit 38d87d0
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 45 deletions.
22 changes: 4 additions & 18 deletions src/lib-http/http-client-connection.c
Expand Up @@ -577,7 +577,6 @@ http_client_connection_continue_timeout(struct http_client_connection *conn)
struct http_client_request *const *wait_reqs;
struct http_client_request *req;
unsigned int wait_count;
const char *error;

i_assert(conn->pending_request == NULL);

Expand All @@ -592,18 +591,14 @@ http_client_connection_continue_timeout(struct http_client_connection *conn)
req = wait_reqs[wait_count-1];

req->payload_sync_continue = TRUE;
if (http_client_request_send_more(req, FALSE, &error) < 0) {
http_client_connection_lost(&conn,
t_strdup_printf("Failed to send request: %s", error));
}
(void)http_client_request_send_more(req, FALSE);
}

int http_client_connection_next_request(struct http_client_connection *conn)
{
struct http_client_peer *peer = conn->peer;
struct http_client_peer_shared *pshared = conn->ppool->peer;
struct http_client_request *req = NULL;
const char *error;
bool pipelined;
int ret;

Expand Down Expand Up @@ -636,11 +631,8 @@ int http_client_connection_next_request(struct http_client_connection *conn)
e_debug(conn->event, "Claimed request %s",
http_client_request_label(req));

if (http_client_request_send(req, pipelined, &error) < 0) {
http_client_connection_lost(&conn,
t_strdup_printf("Failed to send request: %s", error));
if (http_client_request_send(req, pipelined) < 0)
return -1;
}

if (req->connect_tunnel)
conn->tunneling = TRUE;
Expand Down Expand Up @@ -1028,10 +1020,7 @@ static void http_client_connection_input(struct connection *_conn)
return;
}

if (http_client_request_send_more(req, FALSE, &error) < 0) {
http_client_connection_lost(&conn,
t_strdup_printf("Failed to send request: %s", error));
}
(void)http_client_request_send_more(req, FALSE);
return;
} else if (response.status / 100 == 1) {
/* ignore other 1xx for now */
Expand Down Expand Up @@ -1201,7 +1190,6 @@ int http_client_connection_output(struct http_client_connection *conn)
struct http_client_request *const *reqs;
struct ostream *output = conn->conn.output;
unsigned int count;
const char *error;
int ret;

/* we've seen activity from the server; reset request timeout */
Expand Down Expand Up @@ -1237,10 +1225,8 @@ int http_client_connection_output(struct http_client_connection *conn)
}

if (!req->payload_sync || req->payload_sync_continue) {
if (http_client_request_send_more(req, pipelined, &error) < 0) {
http_client_connection_lost(&conn, error);
if (http_client_request_send_more(req, pipelined) < 0)
return -1;
}
if (!conn->output_locked) {
/* room for new requests */
if (http_client_connection_check_ready(conn) > 0)
Expand Down
4 changes: 2 additions & 2 deletions src/lib-http/http-client-private.h
Expand Up @@ -484,9 +484,9 @@ void http_client_request_get_peer_addr(const struct http_client_request *req,
enum http_response_payload_type
http_client_request_get_payload_type(struct http_client_request *req);
int http_client_request_send(struct http_client_request *req,
bool pipelined, const char **error_r);
bool pipelined);
int http_client_request_send_more(struct http_client_request *req,
bool pipelined, const char **error_r);
bool pipelined);
bool http_client_request_callback(struct http_client_request *req,
struct http_response *response);
void http_client_request_connect_callback(struct http_client_request *req,
Expand Down
43 changes: 18 additions & 25 deletions src/lib-http/http-client-request.c
Expand Up @@ -1054,12 +1054,13 @@ static void http_client_request_payload_input(struct http_client_request *req)
}

int http_client_request_send_more(struct http_client_request *req,
bool pipelined, const char **error_r)
bool pipelined)
{
struct http_client_connection *conn = req->conn;
struct http_client_context *cctx = conn->ppool->peer->cctx;
struct ostream *output = req->payload_output;
enum ostream_send_istream_result res;
const char *error;
uoff_t offset;

i_assert(req->payload_input != NULL);
Expand All @@ -1083,11 +1084,12 @@ int http_client_request_send_more(struct http_client_request *req,
/* finished sending */
if (!req->payload_chunked &&
req->payload_input->v_offset - req->payload_offset != req->payload_size) {
*error_r = t_strdup_printf("BUG: stream '%s' input size changed: "
error = t_strdup_printf("BUG: stream '%s' input size changed: "
"%"PRIuUOFF_T"-%"PRIuUOFF_T" != %"PRIuUOFF_T,
i_stream_get_name(req->payload_input),
req->payload_input->v_offset, req->payload_offset, req->payload_size);
i_error("%s", *error_r); //FIXME: remove?
i_error("%s", error); //FIXME: remove?
http_client_connection_lost(&conn, error);
return -1;
}

Expand Down Expand Up @@ -1123,28 +1125,28 @@ int http_client_request_send_more(struct http_client_request *req,
case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT:
/* we're in the middle of sending a request, so the connection
will also have to be aborted */
*error_r = t_strdup_printf("read(%s) failed: %s",
i_stream_get_name(req->payload_input),
i_stream_get_error(req->payload_input));
error = t_strdup_printf("read(%s) failed: %s",
i_stream_get_name(req->payload_input),
i_stream_get_error(req->payload_input));

/* the payload stream assigned to this request is broken,
fail this the request immediately */
http_client_request_error(&req,
HTTP_CLIENT_REQUEST_ERROR_BROKEN_PAYLOAD,
"Broken payload stream");

http_client_connection_lost(&conn, error);
return -1;
case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT:
/* failed to send request */
*error_r = t_strdup_printf("write(%s) failed: %s",
o_stream_get_name(output),
o_stream_get_error(output));
http_client_connection_handle_output_error(conn);
return -1;
}
i_unreached();
}

static int http_client_request_send_real(struct http_client_request *req,
bool pipelined, const char **error_r)
bool pipelined)
{
const struct http_client_settings *set = &req->client->set;
struct http_client_connection *conn = req->conn;
Expand Down Expand Up @@ -1263,17 +1265,14 @@ static int http_client_request_send_real(struct http_client_request *req,
io_wait_timer_get_usecs(req->conn->io_wait_timer);
o_stream_cork(output);
if (o_stream_sendv(output, iov, N_ELEMENTS(iov)) < 0) {
*error_r = t_strdup_printf("write(%s) failed: %s",
o_stream_get_name(output),
o_stream_get_error(output));
http_client_connection_handle_output_error(conn);
ret = -1;
} else {
e_debug(req->event, "Sent header");

if (req->payload_output != NULL) {
if (!req->payload_sync) {
if (http_client_request_send_more
(req, pipelined, error_r) < 0)
if (http_client_request_send_more(req, pipelined) < 0)
ret = -1;
} else {
e_debug(req->event, "Waiting for 100-continue");
Expand All @@ -1287,28 +1286,22 @@ static int http_client_request_send_real(struct http_client_request *req,
}
}
if (ret >= 0 && o_stream_uncork_flush(output) < 0) {
*error_r = t_strdup_printf("flush(%s) failed: %s",
o_stream_get_name(output),
o_stream_get_error(output));
http_client_connection_handle_output_error(conn);
ret = -1;
}

return ret;
}

int http_client_request_send(struct http_client_request *req,
bool pipelined, const char **error_r)
bool pipelined)
{
char *errstr = NULL;
int ret;

T_BEGIN {
ret = http_client_request_send_real(req, pipelined, error_r);
if (ret < 0)
errstr = i_strdup(*error_r);
ret = http_client_request_send_real(req, pipelined);
} T_END;
*error_r = t_strdup(errstr);
i_free(errstr);

return ret;
}

Expand Down

0 comments on commit 38d87d0

Please sign in to comment.