]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: iostream-pump - Specify what failed in completion callback parameter
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Sun, 29 Oct 2017 22:16:35 +0000 (00:16 +0200)
committerTimo Sirainen <tss@dovecot.fi>
Wed, 1 Nov 2017 00:23:31 +0000 (02:23 +0200)
This makes it easier for the caller to find out whether the failure was due
to istream or ostream.

src/lib-http/http-server-request.c
src/lib/iostream-proxy.c
src/lib/iostream-pump.c
src/lib/iostream-pump.h
src/lib/test-iostream-pump.c

index 6e6522fdc8079cb09ac0e555b0c24156a973e0d4..6cde504a54fef34c452bc5bb3136546f68d8745e 100644 (file)
@@ -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)
index 1b05163891cbfc4e8abbec62f2c83f6a2a3bc0fd..ca74b0d5bcdfeabf83a611116b5f5ffbf80131ad 100644 (file)
@@ -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);
 }
 
index ba1a5615cce9ed418ae1c9f1c0ae23d2850ab09e..161db567ba22d34d26d8243301d81bf5f5dccc45 100644 (file)
@@ -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;
        }
 
index 48d57c8ac04559b72d6ce4aac1f8a32fb542dccc..385a1c0017a8d39e4c01e1357d81ff7b42b81777 100644 (file)
@@ -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
index 8650c3dd24e59e0991d32f2c00e4b2def18c9542..303154dca40aacab84b3c0069c00af57f8aba6b7 100644 (file)
@@ -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);
 }