From: Timo Sirainen Date: Sun, 29 Oct 2017 22:16:35 +0000 (+0200) Subject: lib: iostream-pump - Specify what failed in completion callback parameter X-Git-Tag: 2.3.0.rc1~659 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=39435f00a35a276d329283179b3e7e0351482939;p=thirdparty%2Fdovecot%2Fcore.git lib: iostream-pump - Specify what failed in completion callback parameter This makes it easier for the caller to find out whether the failure was due to istream or ostream. --- diff --git a/src/lib-http/http-server-request.c b/src/lib-http/http-server-request.c index 6e6522fdc8..6cde504a54 100644 --- a/src/lib-http/http-server-request.c +++ b/src/lib-http/http-server-request.c @@ -670,7 +670,7 @@ payload_handler_pump_switch_ioloop( } static void -payload_handler_pump_callback(bool success, +payload_handler_pump_callback(enum iostream_pump_status status, struct http_server_payload_handler_pump *phandler) { struct http_server_payload_handler *handler = &phandler->handler; @@ -679,7 +679,8 @@ payload_handler_pump_callback(bool success, struct istream *input = iostream_pump_get_input(phandler->pump); struct ostream *output = iostream_pump_get_output(phandler->pump); - if (success) { + switch (status) { + case IOSTREAM_PUMP_STATUS_INPUT_EOF: if (!i_stream_read_eof(conn->incoming_payload)) { http_server_request_fail_close(req, 413, "Payload Too Large"); @@ -694,14 +695,16 @@ payload_handler_pump_callback(bool success, i_assert(req->callback_refcount > 0 || (req->response != NULL && req->response->submitted)); } - } else if (input->stream_errno != 0) { + break; + case IOSTREAM_PUMP_STATUS_INPUT_ERROR: http_server_request_client_error(req, "iostream_pump: read(%s) failed: %s", i_stream_get_name(input), i_stream_get_error(input)); http_server_request_fail_close(req, 400, "Bad Request"); - } else { + break; + case IOSTREAM_PUMP_STATUS_OUTPUT_ERROR: if (output->stream_errno != 0) { http_server_request_error(req, "iostream_pump: write(%s) failed: %s", @@ -710,6 +713,7 @@ payload_handler_pump_callback(bool success, } http_server_request_fail_close(req, 500, "Internal Server Error"); + break; } if (conn->payload_handler != NULL) diff --git a/src/lib/iostream-proxy.c b/src/lib/iostream-proxy.c index 1b05163891..ca74b0d5bc 100644 --- a/src/lib/iostream-proxy.c +++ b/src/lib/iostream-proxy.c @@ -20,14 +20,18 @@ struct iostream_proxy { }; static -void iostream_proxy_rtl_completion(bool success, struct iostream_proxy *proxy) +void iostream_proxy_rtl_completion(enum iostream_pump_status status, + struct iostream_proxy *proxy) { + bool success = (status == IOSTREAM_PUMP_STATUS_INPUT_EOF); proxy->callback(IOSTREAM_PROXY_SIDE_RIGHT, success, proxy->context); } static -void iostream_proxy_ltr_completion(bool success, struct iostream_proxy *proxy) +void iostream_proxy_ltr_completion(enum iostream_pump_status status, + struct iostream_proxy *proxy) { + bool success = (status == IOSTREAM_PUMP_STATUS_INPUT_EOF); proxy->callback(IOSTREAM_PROXY_SIDE_LEFT, success, proxy->context); } diff --git a/src/lib/iostream-pump.c b/src/lib/iostream-pump.c index ba1a5615cc..161db567ba 100644 --- a/src/lib/iostream-pump.c +++ b/src/lib/iostream-pump.c @@ -41,9 +41,12 @@ void iostream_pump_copy(struct iostream_pump *pump) switch(res) { case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT: + io_remove(&pump->io); + pump->callback(IOSTREAM_PUMP_STATUS_INPUT_ERROR, pump->context); + return; case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT: io_remove(&pump->io); - pump->callback(FALSE, pump->context); + pump->callback(IOSTREAM_PUMP_STATUS_OUTPUT_ERROR, pump->context); return; case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT: pump->waiting_output = TRUE; @@ -55,14 +58,14 @@ void iostream_pump_copy(struct iostream_pump *pump) /* flush it */ switch (o_stream_flush(pump->output)) { case -1: - pump->callback(FALSE, pump->context); + pump->callback(IOSTREAM_PUMP_STATUS_OUTPUT_ERROR, pump->context); break; case 0: pump->waiting_output = TRUE; pump->completed = TRUE; break; default: - pump->callback(TRUE, pump->context); + pump->callback(IOSTREAM_PUMP_STATUS_INPUT_EOF, pump->context); break; } return; @@ -79,12 +82,12 @@ int iostream_pump_flush(struct iostream_pump *pump) int ret; if ((ret = o_stream_flush(pump->output)) <= 0) { if (ret < 0) - pump->callback(FALSE, pump->context); + pump->callback(IOSTREAM_PUMP_STATUS_OUTPUT_ERROR, pump->context); return ret; } pump->waiting_output = FALSE; if (pump->completed) { - pump->callback(TRUE, pump->context); + pump->callback(IOSTREAM_PUMP_STATUS_INPUT_EOF, pump->context); return 1; } diff --git a/src/lib/iostream-pump.h b/src/lib/iostream-pump.h index 48d57c8ac0..385a1c0017 100644 --- a/src/lib/iostream-pump.h +++ b/src/lib/iostream-pump.h @@ -23,7 +23,20 @@ struct istream; struct ostream; struct iostream_pump; -typedef void iostream_pump_callback_t(bool success, void *context); +enum iostream_pump_status { + /* pump succeeded - EOF received from istream and all output was + written successfully to ostream. */ + IOSTREAM_PUMP_STATUS_INPUT_EOF, + /* pump failed - istream returned an error */ + IOSTREAM_PUMP_STATUS_INPUT_ERROR, + /* pump failed - ostream returned an error */ + IOSTREAM_PUMP_STATUS_OUTPUT_ERROR, +}; + +/* The callback is called once when the pump succeeds or fails due to + iostreams. (It's not called if pump is destroyed.) */ +typedef void iostream_pump_callback_t(enum iostream_pump_status status, + void *context); struct iostream_pump * iostream_pump_create(struct istream *input, struct ostream *output); @@ -41,7 +54,7 @@ void iostream_pump_set_completion_callback(struct iostream_pump *pump, iostream_pump_callback_t *callback, void *context); #define iostream_pump_set_completion_callback(pump, callback, context) \ iostream_pump_set_completion_callback(pump, (iostream_pump_callback_t *)callback, context + \ - CALLBACK_TYPECHECK(callback, void (*)(bool, typeof(context)))) + CALLBACK_TYPECHECK(callback, void (*)(enum iostream_pump_status, typeof(context)))) /* Returns TRUE if the pump is currently only writing to the ostream. The input listener has been removed either because the ostream buffer is full or diff --git a/src/lib/test-iostream-pump.c b/src/lib/test-iostream-pump.c index 8650c3dd24..303154dca4 100644 --- a/src/lib/test-iostream-pump.c +++ b/src/lib/test-iostream-pump.c @@ -18,10 +18,10 @@ static unsigned char data[] = "hello, world"; static -void completed(bool success, int *u0) +void completed(enum iostream_pump_status status, int *u0) { /* to somehow discern between error and success .. */ - (*u0) -= (success ? 1 : 2); + (*u0) -= (status == IOSTREAM_PUMP_STATUS_INPUT_EOF ? 1 : 2); io_loop_stop(current_ioloop); }