}
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;
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");
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",
}
http_server_request_fail_close(req,
500, "Internal Server Error");
+ break;
}
if (conn->payload_handler != NULL)
};
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);
}
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;
/* 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;
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;
}
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);
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
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);
}