dovecot-2.2: imap: URLFETCH error handling fixes.
dovecot at dovecot.org
dovecot at dovecot.org
Tue Oct 23 20:16:21 EEST 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/3e70eacf67a4
changeset: 15235:3e70eacf67a4
user: Timo Sirainen <tss at iki.fi>
date: Tue Oct 23 20:07:06 2012 +0300
description:
imap: URLFETCH error handling fixes.
diffstat:
src/imap/cmd-urlfetch.c | 60 ++++++++++++++++++------------
src/lib-imap-urlauth/imap-urlauth-fetch.c | 17 ++++----
src/lib-imap-urlauth/imap-urlauth-fetch.h | 3 +-
3 files changed, 46 insertions(+), 34 deletions(-)
diffs (191 lines):
diff -r acd76b5272e9 -r 3e70eacf67a4 src/imap/cmd-urlfetch.c
--- a/src/imap/cmd-urlfetch.c Tue Oct 23 12:59:41 2012 +0300
+++ b/src/imap/cmd-urlfetch.c Tue Oct 23 20:07:06 2012 +0300
@@ -16,6 +16,7 @@
struct cmd_urlfetch_context {
struct imap_urlauth_fetch *ufetch;
struct istream *input;
+ uoff_t size;
unsigned int failed:1;
unsigned int finished:1;
@@ -28,8 +29,7 @@
enum imap_urlauth_fetch_flags flags;
};
-static void cmd_urlfetch_finish
-(struct client_command_context *cmd)
+static void cmd_urlfetch_finish(struct client_command_context *cmd)
{
struct cmd_urlfetch_context *ctx =
(struct cmd_urlfetch_context *)cmd->context;
@@ -72,8 +72,6 @@
struct client *client = cmd->client;
struct cmd_urlfetch_context *ctx =
(struct cmd_urlfetch_context *)cmd->context;
- const unsigned char *data;
- size_t size;
int ret = 1;
/* are we in the middle of an urlfetch literal? */
@@ -88,25 +86,35 @@
}
/* transfer literal to client */
- o_stream_set_max_buffer_size(client->output, 4096);
- while (i_stream_read_data(ctx->input, &data, &size, 0) > 0) {
- if ((ret = o_stream_send(client->output, data, size)) < 0)
- break;
- i_stream_skip(ctx->input, ret);
- }
+ o_stream_set_max_buffer_size(client->output, 0);
+ ret = o_stream_send_istream(client->output, ctx->input);
o_stream_set_max_buffer_size(client->output, (size_t)-1);
- if (ret < 0 || ctx->input->stream_errno != 0) {
- /* fatal error */
+ if (ctx->input->v_offset == ctx->size) {
+ /* finished successfully */
+ i_stream_unref(&ctx->input);
+ return 1;
+ }
+ if (client->output->closed) {
+ /* client disconnected */
return -1;
}
+ if (ctx->input->stream_errno != 0) {
+ errno = ctx->input->stream_errno;
+ i_error("read(%s) failed: %m (URLFETCH)",
+ i_stream_get_name(ctx->input));
+ client_disconnect(client, "URLFETCH failed");
+ return -1;
+ }
+ if (!ctx->input->eof) {
+ o_stream_set_flush_pending(client->output, TRUE);
+ return 0;
+ }
- if (!ctx->input->eof)
- return 0;
-
- /* finished */
- i_stream_unref(&ctx->input);
- return 1;
+ i_error("URLFETCH got too little data: %"PRIuUOFF_T" vs %"PRIuUOFF_T,
+ ctx->input->v_offset, ctx->size);
+ client_disconnect(client, "FETCH failed");
+ return -1;
}
static bool cmd_urlfetch_continue(struct client_command_context *cmd)
@@ -208,12 +216,12 @@
if (reply->input != NULL) {
ctx->input = reply->input;
+ ctx->size = reply->size;
i_stream_ref(reply->input);
ret = cmd_urlfetch_transfer_literal(cmd);
if (ret < 0) {
ctx->failed = TRUE;
- cmd_urlfetch_finish(cmd);
return -1;
}
if (ret == 0) {
@@ -240,17 +248,20 @@
struct cmd_urlfetch_context *ctx = cmd->context;
int ret;
- if (cmd->cancel)
- return 1;
-
if (reply == NULL) {
/* fatal failure */
last = TRUE;
ctx->failed = TRUE;
} else if (reply->succeeded) {
/* URL fetch succeeded */
- if ((ret = cmd_urlfetch_url_sucess(cmd, reply)) <= 0)
- return ret;
+ ret = cmd_urlfetch_url_sucess(cmd, reply);
+ if (ret == 0)
+ return 0;
+ if (ret < 0) {
+ ctx->ufetch = NULL;
+ cmd_urlfetch_finish(cmd);
+ return -1;
+ }
} else {
/* URL fetch failed */
client_send_line(cmd->client,
@@ -262,6 +273,7 @@
}
if (last && cmd->state == CLIENT_COMMAND_STATE_WAIT_EXTERNAL) {
+ ctx->ufetch = NULL;
cmd_urlfetch_finish(cmd);
client_command_free(&cmd);
}
diff -r acd76b5272e9 -r 3e70eacf67a4 src/lib-imap-urlauth/imap-urlauth-fetch.c
--- a/src/lib-imap-urlauth/imap-urlauth-fetch.c Tue Oct 23 12:59:41 2012 +0300
+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.c Tue Oct 23 20:07:06 2012 +0300
@@ -58,23 +58,20 @@
if (ufetch->local_url != NULL)
imap_msgpart_url_free(&ufetch->local_url);
- if (ufetch->pending_reply.url != NULL)
- i_free(ufetch->pending_reply.url);
+ i_free_and_null(ufetch->pending_reply.url);
+ i_free_and_null(ufetch->pending_reply.bodypartstruct);
+ i_free_and_null(ufetch->pending_reply.error);
if (ufetch->pending_reply.input != NULL)
i_stream_unref(&ufetch->pending_reply.input);
- if (ufetch->pending_reply.bodypartstruct != NULL)
- i_free(ufetch->pending_reply.bodypartstruct);
- if (ufetch->pending_reply.error != NULL)
- i_free(ufetch->pending_reply.error);
url = ufetch->local_urls_head;
- while (url != NULL) {
+ for (; url != NULL; url = url_next) {
url_next = url->next;
i_free(url->url);
i_free(url);
ufetch->pending_requests--;
- url = url_next;
}
+ ufetch->local_urls_head = ufetch->local_urls_tail = NULL;
}
static void imap_urlauth_fetch_abort(struct imap_urlauth_fetch *ufetch)
@@ -131,7 +128,7 @@
reply.flags = url_flags;
reply.succeeded = FALSE;
reply.error = error;
-
+
T_BEGIN {
ret = ufetch->callback(&reply, ufetch->pending_requests == 0,
ufetch->context);
@@ -298,6 +295,8 @@
imap_urlauth_fetch_abort_local(ufetch);
ufetch->failed = TRUE;
}
+ if (ret != 0)
+ imap_urlauth_fetch_deinit(&ufetch);
return ret;
}
diff -r acd76b5272e9 -r 3e70eacf67a4 src/lib-imap-urlauth/imap-urlauth-fetch.h
--- a/src/lib-imap-urlauth/imap-urlauth-fetch.h Tue Oct 23 12:59:41 2012 +0300
+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.h Tue Oct 23 20:07:06 2012 +0300
@@ -33,7 +33,8 @@
for next reply, 0 if not all data was processed, and -1 for error. If a
callback returns 0, imap_urlauth_connection_continue() must be called once
new replies may be processed. If this is the last request to yield a reply,
- argument last is TRUE */
+ argument last is TRUE. The callback must not call
+ imap_urlauth_fetch_deinit(). */
typedef int
imap_urlauth_fetch_callback_t(struct imap_urlauth_fetch_reply *reply,
bool last, void *context);
More information about the dovecot-cvs
mailing list