Fixed bug in keepalive code. Cleaned up some exceptions.

Keepalive could cause a segfault if the server closed the connection.  This fixes that as well as updates some of the exception-throwing code to use more appropriate ImapErrors.
This commit is contained in:
Jim Nelson 2011-06-03 16:32:30 -07:00
parent 013f6b57e1
commit 5f6076e8cb
4 changed files with 34 additions and 13 deletions

View file

@ -56,7 +56,9 @@ public class Geary.Imap.ClientConnection {
// TODO: Close connection as gracefully as possible
}
// Generates a unique tag for the IMAP connection in the form of "<a-z><000-999>".
/**
* Generates a unique tag for the IMAP connection in the form of "<a-z><000-999>".
*/
public Tag generate_tag() {
// watch for odometer rollover
if (++tag_counter >= 1000) {
@ -71,9 +73,15 @@ public class Geary.Imap.ClientConnection {
return new Tag("%c%03d".printf(tag_prefix, tag_counter));
}
/**
* Returns silently if a connection is already established.
*/
public async void connect_async(Cancellable? cancellable = null) throws Error {
if (cx != null)
throw new IOError.EXISTS("Already connected to %s", to_string());
if (cx != null) {
debug("Already connected to %s", to_string());
return;
}
cx = yield socket_client.connect_to_host_async(host_specifier, default_port, cancellable);
ser = new Serializer(new BufferedOutputStream(cx.output_stream));
@ -159,7 +167,7 @@ public class Geary.Imap.ClientConnection {
private void check_for_connection() throws Error {
if (cx == null)
throw new IOError.CLOSED("Not connected to %s", to_string());
throw new ImapError.NOT_CONNECTED("Not connected to %s", to_string());
}
public string to_string() {

View file

@ -337,8 +337,11 @@ public class Geary.Imap.ClientSession {
fsm.set_logging(false);
}
public Tag? generate_tag() {
return (cx != null) ? cx.generate_tag() : null;
public Tag generate_tag() throws ImapError {
if (cx == null)
throw new ImapError.NOT_CONNECTED("Not connected to %s", to_string());
return cx.generate_tag();
}
public string? get_current_mailbox() {
@ -559,7 +562,15 @@ public class Geary.Imap.ClientSession {
}
private bool on_keepalive() {
send_command_async.begin(new NoopCommand(generate_tag()), null, on_keepalive_completed);
try {
send_command_async.begin(new NoopCommand(generate_tag()), null, on_keepalive_completed);
} catch (ImapError ierr) {
message("Unable to keepalive %s, halting attempts: %s", to_string(), ierr.message);
keepalive_id = 0;
return false;
}
return true;
}
@ -610,7 +621,7 @@ public class Geary.Imap.ClientSession {
if (cmd.has_name(LoginCommand.NAME) || cmd.has_name(LogoutCommand.NAME)
|| cmd.has_name(SelectCommand.NAME) || cmd.has_name(ExamineCommand.NAME)
|| cmd.has_name(CloseCommand.NAME)) {
throw new IOError.NOT_SUPPORTED("Use direct calls rather than commands");
throw new ImapError.NOT_SUPPORTED("Use direct calls rather than commands");
}
SendCommandParams params = new SendCommandParams(cmd, cancellable, send_command_async.callback);
@ -937,7 +948,7 @@ public class Geary.Imap.ClientSession {
assert(object != null);
AsyncParams params = (AsyncParams) object;
params.err = new IOError.CLOSED("Connection to %s closing or closed", to_string());
params.err = new ImapError.NOT_CONNECTED("Connection to %s closing or closed", to_string());
return state;
}
@ -973,7 +984,7 @@ public class Geary.Imap.ClientSession {
Cancellable? cancellable = null) {
if (cx == null) {
return new AsyncCommandResponse(null, user,
new IOError.CLOSED("Not connected to %s", server));
new ImapError.NOT_CONNECTED("Not connected to %s", server));
}
try {

View file

@ -10,6 +10,8 @@ public errordomain Geary.ImapError {
SERVER_ERROR,
NOT_CONNECTED,
COMMAND_FAILED,
UNAUTHENTICATED
UNAUTHENTICATED,
NOT_SUPPORTED,
NOT_SELECTED
}

View file

@ -27,7 +27,7 @@ public class Geary.Imap.Mailbox : Geary.SmartReference, Geary.Folder {
public async Gee.List<EmailHeader>? read(int low, int count, Cancellable? cancellable = null)
throws Error {
if (mailbox.is_closed())
throw new IOError.NOT_FOUND("Mailbox %s closed", mailbox.to_string());
throw new ImapError.NOT_SELECTED("Mailbox %s closed", mailbox.to_string());
CommandResponse resp = yield mailbox.session.send_command_async(
new FetchCommand(mailbox.session.generate_tag(), new MessageSet.range(low, count),
@ -53,7 +53,7 @@ public class Geary.Imap.Mailbox : Geary.SmartReference, Geary.Folder {
assert(header != null);
if (mailbox.is_closed())
throw new IOError.NOT_FOUND("Folder closed");
throw new ImapError.NOT_SELECTED("Folder closed");
CommandResponse resp = yield mailbox.session.send_command_async(
new FetchCommand(mailbox.session.generate_tag(), new MessageSet(hdr.msg_num),