Merge branch 'mjog/986-namespace-assert' into 'mainline'
Disconnect from IMAP client sessions when logging out Closes #986 See merge request GNOME/geary!586
This commit is contained in:
commit
03f05c6448
9 changed files with 194 additions and 148 deletions
|
|
@ -45,7 +45,7 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
|||
*/
|
||||
public async FolderPath get_default_personal_namespace(Cancellable? cancellable)
|
||||
throws Error {
|
||||
ClientSession session = claim_session();
|
||||
ClientSession session = get_session();
|
||||
Gee.List<Namespace> personal = session.get_personal_namespaces();
|
||||
if (personal.is_empty) {
|
||||
throw new ImapError.INVALID("No personal namespace found");
|
||||
|
|
@ -69,7 +69,7 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
|||
public bool is_folder_path_valid(FolderPath? path) throws GLib.Error {
|
||||
bool is_valid = false;
|
||||
if (path != null) {
|
||||
ClientSession session = claim_session();
|
||||
ClientSession session = get_session();
|
||||
try {
|
||||
session.get_mailbox_for_path(path);
|
||||
is_valid = true;
|
||||
|
|
@ -94,7 +94,7 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
|||
Geary.Folder.SpecialUse? use,
|
||||
Cancellable? cancellable)
|
||||
throws Error {
|
||||
ClientSession session = claim_session();
|
||||
ClientSession session = get_session();
|
||||
MailboxSpecifier mailbox = session.get_mailbox_for_path(path);
|
||||
bool can_create_special = session.capabilities.has_capability(Capabilities.CREATE_SPECIAL_USE);
|
||||
CreateCommand cmd = (
|
||||
|
|
@ -125,7 +125,7 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
|||
public async Imap.Folder fetch_folder_async(FolderPath path,
|
||||
Cancellable? cancellable)
|
||||
throws Error {
|
||||
ClientSession session = claim_session();
|
||||
ClientSession session = get_session();
|
||||
Imap.Folder? folder = this.folders.get(path);
|
||||
if (folder == null) {
|
||||
Gee.List<MailboxInformation>? mailboxes = yield send_list_async(
|
||||
|
|
@ -169,7 +169,7 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
|||
fetch_child_folders_async(FolderPath parent,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
ClientSession session = claim_session();
|
||||
ClientSession session = get_session();
|
||||
Gee.List<Imap.Folder> children = new Gee.ArrayList<Imap.Folder>();
|
||||
Gee.List<MailboxInformation> mailboxes = yield send_list_async(
|
||||
session, parent, true, cancellable
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ public class Geary.Imap.ClientService : Geary.ClientService {
|
|||
if (!disconnect) {
|
||||
// If the session has a mailbox selected, close it before
|
||||
// adding it back to the pool
|
||||
ClientSession.ProtocolState proto = session.get_protocol_state();
|
||||
ClientSession.ProtocolState proto = session.protocol_state;
|
||||
if (proto == ClientSession.ProtocolState.SELECTED ||
|
||||
proto == ClientSession.ProtocolState.SELECTING) {
|
||||
// always close mailbox to return to authorized state
|
||||
|
|
@ -263,7 +263,7 @@ public class Geary.Imap.ClientService : Geary.ClientService {
|
|||
session.to_string(), imap_error.message);
|
||||
disconnect = true;
|
||||
}
|
||||
if (session.get_protocol_state() != AUTHORIZED) {
|
||||
if (session.protocol_state != AUTHORIZED) {
|
||||
// Closing it didn't leave it in the desired
|
||||
// state, so drop it
|
||||
disconnect = true;
|
||||
|
|
@ -393,7 +393,7 @@ public class Geary.Imap.ClientService : Geary.ClientService {
|
|||
/** Determines if a session is valid, disposing of it if not. */
|
||||
private async bool check_session(ClientSession target, bool claiming) {
|
||||
bool valid = false;
|
||||
switch (target.get_protocol_state()) {
|
||||
switch (target.protocol_state) {
|
||||
case ClientSession.ProtocolState.AUTHORIZED:
|
||||
case ClientSession.ProtocolState.CLOSING_MAILBOX:
|
||||
valid = true;
|
||||
|
|
@ -472,7 +472,7 @@ public class Geary.Imap.ClientService : Geary.ClientService {
|
|||
|
||||
// Only bother tracking disconnects and enabling keeping alive
|
||||
// now the session is properly established.
|
||||
new_session.disconnected.connect(on_disconnected);
|
||||
new_session.notify["disconnected"].connect(on_session_disconnected);
|
||||
new_session.enable_keepalives(selected_keepalive_sec,
|
||||
unselected_keepalive_sec,
|
||||
selected_with_idle_keepalive_sec);
|
||||
|
|
@ -509,7 +509,7 @@ public class Geary.Imap.ClientService : Geary.ClientService {
|
|||
}
|
||||
|
||||
private async void disconnect_session(ClientSession session) {
|
||||
if (session.get_protocol_state() != NOT_CONNECTED) {
|
||||
if (session.protocol_state != NOT_CONNECTED) {
|
||||
debug("Logging out session: %s", session.to_string());
|
||||
// No need to remove it after logging out, the
|
||||
// disconnected handler will do that for us.
|
||||
|
|
@ -548,21 +548,27 @@ public class Geary.Imap.ClientService : Geary.ClientService {
|
|||
}
|
||||
|
||||
if (removed) {
|
||||
session.disconnected.disconnect(on_disconnected);
|
||||
session.notify["disconnected"].connect(on_session_disconnected);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
private void on_disconnected(ClientSession session,
|
||||
ClientSession.DisconnectReason reason) {
|
||||
debug(
|
||||
"Session disconnected: %s: %s",
|
||||
session.to_string(), reason.to_string()
|
||||
);
|
||||
this.remove_session_async.begin(
|
||||
session,
|
||||
(obj, res) => { this.remove_session_async.end(res); }
|
||||
);
|
||||
private void on_session_disconnected(GLib.Object source,
|
||||
GLib.ParamSpec param) {
|
||||
var session = source as ClientSession;
|
||||
if (session != null &&
|
||||
session.protocol_state == NOT_CONNECTED &&
|
||||
session.disconnected != null) {
|
||||
debug(
|
||||
"Session disconnected: %s: %s",
|
||||
session.to_string(),
|
||||
session.disconnected.to_string()
|
||||
);
|
||||
this.remove_session_async.begin(
|
||||
session,
|
||||
(obj, res) => { this.remove_session_async.end(res); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
/** Determines if this folder accepts custom IMAP flags. */
|
||||
public Trillian accepts_user_flags { get; private set; default = Trillian.UNKNOWN; }
|
||||
|
||||
private MailboxSpecifier mailbox;
|
||||
|
||||
private Quirks quirks;
|
||||
|
||||
private Nonblocking.Mutex cmd_mutex = new Nonblocking.Mutex();
|
||||
|
|
@ -107,9 +109,9 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
session.search.connect(on_search);
|
||||
session.status_response_received.connect(on_status_response);
|
||||
|
||||
MailboxSpecifier mailbox = session.get_mailbox_for_path(folder.path);
|
||||
this.mailbox = session.get_mailbox_for_path(folder.path);
|
||||
StatusResponse? response = yield session.select_async(
|
||||
mailbox, cancellable
|
||||
this.mailbox, cancellable
|
||||
);
|
||||
throw_on_not_ok(response, "SELECT " + this.folder.path.to_string());
|
||||
|
||||
|
|
@ -125,7 +127,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
*/
|
||||
public async void enable_idle(Cancellable? cancellable)
|
||||
throws Error {
|
||||
ClientSession session = claim_session();
|
||||
ClientSession session = get_session();
|
||||
int token = yield this.cmd_mutex.claim_async(cancellable);
|
||||
Error? cmd_err = null;
|
||||
try {
|
||||
|
|
@ -301,7 +303,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
Gee.Set<Imap.UID>? search_results,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
ClientSession session = claim_session();
|
||||
ClientSession session = get_session();
|
||||
Gee.Map<Command, StatusResponse>? responses = null;
|
||||
int token = yield this.cmd_mutex.claim_async(cancellable);
|
||||
|
||||
|
|
@ -646,7 +648,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
public async void remove_email_async(Gee.List<MessageSet> msg_sets,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
ClientSession session = claim_session();
|
||||
ClientSession session = get_session();
|
||||
Gee.List<MessageFlag> flags = new Gee.ArrayList<MessageFlag>();
|
||||
flags.add(MessageFlag.DELETED);
|
||||
|
||||
|
|
@ -719,7 +721,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
FolderPath destination,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
ClientSession session = claim_session();
|
||||
ClientSession session = get_session();
|
||||
|
||||
MailboxSpecifier mailbox = session.get_mailbox_for_path(destination);
|
||||
CopyCommand cmd = new CopyCommand(msg_set, mailbox, cancellable);
|
||||
|
|
@ -1107,8 +1109,6 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
Geary.EmailFlags? flags,
|
||||
GLib.DateTime? date_received)
|
||||
throws GLib.Error {
|
||||
ClientSession session = claim_session();
|
||||
|
||||
MessageFlags? msg_flags = null;
|
||||
if (flags != null) {
|
||||
Imap.EmailFlags imap_flags = Imap.EmailFlags.from_api_email_flags(flags);
|
||||
|
|
@ -1121,9 +1121,8 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
if (date_received != null)
|
||||
internaldate = new InternalDate.from_date_time(date_received);
|
||||
|
||||
MailboxSpecifier mailbox = session.get_mailbox_for_path(this.folder.path);
|
||||
AppendCommand cmd = new AppendCommand(
|
||||
mailbox,
|
||||
this.mailbox,
|
||||
msg_flags,
|
||||
internaldate,
|
||||
message.get_rfc822_buffer(),
|
||||
|
|
@ -1161,6 +1160,26 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a valid IMAP client session for use by this object.
|
||||
*
|
||||
* In addition to the checks made by {@link
|
||||
* SessionObject.get_session}, this method also ensures that the
|
||||
* IMAP session is in the SELECTED state for the correct mailbox.
|
||||
*/
|
||||
protected override ClientSession get_session()
|
||||
throws ImapError {
|
||||
var session = base.get_session();
|
||||
if (session.protocol_state != SELECTED &&
|
||||
!this.mailbox.equal_to(session.selected_mailbox)) {
|
||||
throw new ImapError.NOT_CONNECTED(
|
||||
"IMAP object no longer SELECTED for %s",
|
||||
this.mailbox.to_string()
|
||||
);
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
// HACK: See https://bugzilla.gnome.org/show_bug.cgi?id=714902
|
||||
//
|
||||
// Detect when a server has returned a BAD response to FETCH
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ public abstract class Geary.Imap.SessionObject : BaseObject, Logging.Source {
|
|||
*/
|
||||
protected SessionObject(ClientSession session) {
|
||||
this.session = session;
|
||||
this.session.disconnected.connect(on_disconnected);
|
||||
this.session.notify["protocol-state"].connect(on_session_state_change);
|
||||
}
|
||||
|
||||
~SessionObject() {
|
||||
|
|
@ -63,7 +63,9 @@ public abstract class Geary.Imap.SessionObject : BaseObject, Logging.Source {
|
|||
this.session = null;
|
||||
|
||||
if (old_session != null) {
|
||||
old_session.disconnected.disconnect(on_disconnected);
|
||||
old_session.notify["protocol-state"].disconnect(
|
||||
on_session_state_change
|
||||
);
|
||||
}
|
||||
|
||||
return old_session;
|
||||
|
|
@ -83,25 +85,37 @@ public abstract class Geary.Imap.SessionObject : BaseObject, Logging.Source {
|
|||
}
|
||||
|
||||
/**
|
||||
* Obtains IMAP session the server for use by this object.
|
||||
* Returns a valid IMAP client session for use by this object.
|
||||
*
|
||||
* @throws ImapError.NOT_CONNECTED if the session with the server
|
||||
* server has been dropped via {@link close}, or because
|
||||
* the connection was lost.
|
||||
* @throws ImapError.NOT_CONNECTED if the client session has been
|
||||
* dropped via {@link close}, if the client session is logging out
|
||||
* or has been closed, or because the connection to the server was
|
||||
* lost.
|
||||
*/
|
||||
protected ClientSession claim_session()
|
||||
protected virtual ClientSession get_session()
|
||||
throws ImapError {
|
||||
if (this.session == null) {
|
||||
throw new ImapError.NOT_CONNECTED("IMAP object has no session");
|
||||
if (this.session == null ||
|
||||
this.session.protocol_state == NOT_CONNECTED) {
|
||||
throw new ImapError.NOT_CONNECTED(
|
||||
"IMAP object has no session or is not connected"
|
||||
);
|
||||
}
|
||||
return this.session;
|
||||
}
|
||||
|
||||
private void on_disconnected(ClientSession.DisconnectReason reason) {
|
||||
debug("Disconnected %s", reason.to_string());
|
||||
|
||||
close();
|
||||
disconnected(reason);
|
||||
private void on_session_state_change() {
|
||||
if (this.session != null &&
|
||||
this.session.protocol_state == NOT_CONNECTED) {
|
||||
// Disconnect reason will null when the session is being
|
||||
// logged out but the logout command has not yet been
|
||||
// completed.
|
||||
var reason = (
|
||||
this.session.disconnected ??
|
||||
ClientSession.DisconnectReason.LOCAL_CLOSE
|
||||
);
|
||||
close();
|
||||
disconnected(reason);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
*
|
||||
* See [[http://tools.ietf.org/html/rfc3501#section-3]]
|
||||
*
|
||||
* @see get_protocol_state
|
||||
* @see protocol_state
|
||||
*/
|
||||
public enum ProtocolState {
|
||||
NOT_CONNECTED,
|
||||
|
|
@ -230,6 +230,55 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
"Geary.Imap.ClientSession", State.NOT_CONNECTED, State.COUNT, Event.COUNT,
|
||||
state_to_string, event_to_string);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current IMAP protocol state for the session.
|
||||
*/
|
||||
public ProtocolState protocol_state {
|
||||
get {
|
||||
var state = ProtocolState.NOT_CONNECTED;
|
||||
switch (fsm.state) {
|
||||
case State.NOT_CONNECTED:
|
||||
case State.LOGOUT:
|
||||
case State.CLOSED:
|
||||
state = NOT_CONNECTED;
|
||||
break;
|
||||
|
||||
case State.NOAUTH:
|
||||
state = UNAUTHORIZED;
|
||||
break;
|
||||
|
||||
case State.AUTHORIZED:
|
||||
state = AUTHORIZED;
|
||||
break;
|
||||
|
||||
case State.SELECTED:
|
||||
state = SELECTED;
|
||||
break;
|
||||
|
||||
case State.CONNECTING:
|
||||
state = CONNECTING;
|
||||
break;
|
||||
|
||||
case State.AUTHORIZING:
|
||||
state = AUTHORIZING;
|
||||
break;
|
||||
|
||||
case State.SELECTING:
|
||||
state = SELECTING;
|
||||
break;
|
||||
|
||||
case State.CLOSING_MAILBOX:
|
||||
state = CLOSING_MAILBOX;
|
||||
break;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/** Specifies the reason the session was disconnected, if any. */
|
||||
public DisconnectReason? disconnected { get; private set; default = null; }
|
||||
|
||||
/**
|
||||
* Set of IMAP extensions reported as being supported by the server.
|
||||
*
|
||||
|
|
@ -330,9 +379,6 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
// Connection state changes
|
||||
//
|
||||
|
||||
/** Emitted when the session is disconnected for any reason. */
|
||||
public signal void disconnected(DisconnectReason reason);
|
||||
|
||||
/** Emitted when an IMAP command status response is received. */
|
||||
public signal void status_response_received(StatusResponse status_response);
|
||||
|
||||
|
|
@ -482,19 +528,25 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
new Geary.State.Mapping(State.CLOSED, Event.RECV_ERROR, Geary.State.nop),
|
||||
};
|
||||
|
||||
fsm = new Geary.State.Machine(machine_desc, mappings, on_ignored_transition);
|
||||
fsm.set_logging(false);
|
||||
this.fsm = new Geary.State.Machine(
|
||||
machine_desc,
|
||||
mappings,
|
||||
on_ignored_transition
|
||||
);
|
||||
this.fsm.notify["state"].connect(
|
||||
() => this.notify_property("protocol_state")
|
||||
);
|
||||
}
|
||||
|
||||
~ClientSession() {
|
||||
switch (fsm.get_state()) {
|
||||
switch (fsm.state) {
|
||||
case State.NOT_CONNECTED:
|
||||
case State.CLOSED:
|
||||
// no problem-o
|
||||
break;
|
||||
|
||||
default:
|
||||
warning("ClientSession ref dropped while still active");
|
||||
GLib.warning("ClientSession ref dropped while still active");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -599,6 +651,9 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
}
|
||||
if (ns == null) {
|
||||
// fall back to the default personal namespace
|
||||
if (this.personal_namespaces.is_empty) {
|
||||
throw new ImapError.UNAVAILABLE("No personal namespace");
|
||||
}
|
||||
ns = this.personal_namespaces[0];
|
||||
}
|
||||
|
||||
|
|
@ -634,43 +689,6 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
return delim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current {@link ProtocolState} of the {@link ClientSession} and, if selected,
|
||||
* the current mailbox.
|
||||
*/
|
||||
public ProtocolState get_protocol_state() {
|
||||
switch (fsm.get_state()) {
|
||||
case State.NOT_CONNECTED:
|
||||
case State.LOGOUT:
|
||||
case State.CLOSED:
|
||||
return ProtocolState.NOT_CONNECTED;
|
||||
|
||||
case State.NOAUTH:
|
||||
return ProtocolState.UNAUTHORIZED;
|
||||
|
||||
case State.AUTHORIZED:
|
||||
return ProtocolState.AUTHORIZED;
|
||||
|
||||
case State.SELECTED:
|
||||
return ProtocolState.SELECTED;
|
||||
|
||||
case State.CONNECTING:
|
||||
return ProtocolState.CONNECTING;
|
||||
|
||||
case State.AUTHORIZING:
|
||||
return ProtocolState.AUTHORIZING;
|
||||
|
||||
case State.SELECTING:
|
||||
return ProtocolState.SELECTING;
|
||||
|
||||
case State.CLOSING_MAILBOX:
|
||||
return ProtocolState.CLOSING_MAILBOX;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
// Some commands require waiting for a completion response in order to shift the state machine's
|
||||
// State; this allocates such a wait, returning false if another command is outstanding also
|
||||
// waiting for one to finish
|
||||
|
|
@ -779,7 +797,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
|
||||
private bool on_greeting_timeout() {
|
||||
// if still in CONNECTING state, the greeting never arrived
|
||||
if (fsm.get_state() == State.CONNECTING)
|
||||
if (fsm.state == State.CONNECTING)
|
||||
fsm.issue(Event.TIMEOUT);
|
||||
|
||||
return false;
|
||||
|
|
@ -1195,7 +1213,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
public void enable_idle()
|
||||
throws GLib.Error {
|
||||
if (this.is_idle_supported) {
|
||||
switch (get_protocol_state()) {
|
||||
switch (this.protocol_state) {
|
||||
case ProtocolState.AUTHORIZING:
|
||||
case ProtocolState.AUTHORIZED:
|
||||
case ProtocolState.SELECTED:
|
||||
|
|
@ -1216,7 +1234,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
unschedule_keepalive();
|
||||
|
||||
uint seconds;
|
||||
switch (get_protocol_state()) {
|
||||
switch (this.protocol_state) {
|
||||
case ProtocolState.NOT_CONNECTED:
|
||||
case ProtocolState.CONNECTING:
|
||||
return;
|
||||
|
|
@ -1553,10 +1571,11 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
MachineParams params = (MachineParams) object;
|
||||
|
||||
assert(params.cmd is LogoutCommand);
|
||||
if (!reserve_state_change_cmd(params, state, event))
|
||||
return state;
|
||||
if (reserve_state_change_cmd(params, state, event)) {
|
||||
state = State.LOGOUT;
|
||||
}
|
||||
|
||||
return State.LOGOUT;
|
||||
return state;
|
||||
}
|
||||
|
||||
private uint on_logging_out_recv_status(uint state,
|
||||
|
|
@ -1623,7 +1642,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
}
|
||||
|
||||
drop_connection();
|
||||
disconnected(DisconnectReason.LOCAL_CLOSE);
|
||||
this.disconnected = DisconnectReason.LOCAL_CLOSE;
|
||||
|
||||
if (disconnect_err != null)
|
||||
throw disconnect_err;
|
||||
|
|
@ -1642,12 +1661,12 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
return (this.selected_mailbox == null)
|
||||
? new Logging.State(
|
||||
this,
|
||||
this.fsm.get_state_string(fsm.get_state())
|
||||
this.fsm.get_state_string(fsm.state)
|
||||
)
|
||||
: new Logging.State(
|
||||
this,
|
||||
"%s:%s selected %s",
|
||||
this.fsm.get_state_string(fsm.get_state()),
|
||||
this.fsm.get_state_string(fsm.state),
|
||||
this.selected_mailbox.to_string(),
|
||||
this.selected_readonly ? "RO" : "RW"
|
||||
);
|
||||
|
|
@ -1659,6 +1678,8 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
}
|
||||
|
||||
private async void do_disconnect(DisconnectReason reason) {
|
||||
this.disconnected = reason;
|
||||
|
||||
try {
|
||||
yield this.cx.disconnect_async();
|
||||
} catch (GLib.Error err) {
|
||||
|
|
@ -1666,7 +1687,6 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
}
|
||||
|
||||
drop_connection();
|
||||
disconnected(reason);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source {
|
|||
|
||||
/** {@inheritDoc} */
|
||||
public Logging.State to_logging_state() {
|
||||
return new Logging.State(this, fsm.get_state_string(fsm.get_state()));
|
||||
return new Logging.State(this, fsm.get_state_string(fsm.state));
|
||||
}
|
||||
|
||||
/** Sets the connection's logging parent. */
|
||||
|
|
@ -429,7 +429,7 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source {
|
|||
}
|
||||
|
||||
private Mode get_mode() {
|
||||
switch (fsm.get_state()) {
|
||||
switch (fsm.state) {
|
||||
case State.LITERAL_DATA:
|
||||
return Mode.BLOCK;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,20 @@
|
|||
*/
|
||||
|
||||
public class Geary.State.Machine : BaseObject {
|
||||
|
||||
/** The state machine's current state. */
|
||||
public uint state { get; private set; }
|
||||
|
||||
/** Determines if the state machine crashes your app when mis-configured. */
|
||||
public bool abort_on_no_transition { get; set; default = true; }
|
||||
|
||||
/** Determines if transition logging is enabled. */
|
||||
public bool logging { get; private set; default = false; }
|
||||
|
||||
private Geary.State.MachineDescriptor descriptor;
|
||||
private uint state;
|
||||
private Mapping[,] transitions;
|
||||
private unowned Transition? default_transition;
|
||||
private bool locked = false;
|
||||
private bool abort_on_no_transition = true;
|
||||
private bool logging = false;
|
||||
private unowned PostTransition? post_transition = null;
|
||||
private void *post_user = null;
|
||||
private Object? post_object = null;
|
||||
|
|
@ -39,26 +46,6 @@ public class Geary.State.Machine : BaseObject {
|
|||
}
|
||||
}
|
||||
|
||||
public uint get_state() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public bool get_abort_on_no_transition() {
|
||||
return abort_on_no_transition;
|
||||
}
|
||||
|
||||
public void set_abort_on_no_transition(bool abort) {
|
||||
abort_on_no_transition = abort;
|
||||
}
|
||||
|
||||
public void set_logging(bool logging) {
|
||||
this.logging = logging;
|
||||
}
|
||||
|
||||
public bool is_logging() {
|
||||
return logging;
|
||||
}
|
||||
|
||||
public uint issue(uint event, void *user = null, Object? object = null, Error? err = null) {
|
||||
assert(event < descriptor.event_count);
|
||||
assert(state < descriptor.state_count);
|
||||
|
|
@ -70,7 +57,7 @@ public class Geary.State.Machine : BaseObject {
|
|||
string msg = "%s: No transition defined for %s@%s".printf(to_string(),
|
||||
descriptor.get_event_string(event), descriptor.get_state_string(state));
|
||||
|
||||
if (get_abort_on_no_transition())
|
||||
if (this.abort_on_no_transition)
|
||||
error(msg);
|
||||
else
|
||||
critical(msg);
|
||||
|
|
@ -96,7 +83,7 @@ public class Geary.State.Machine : BaseObject {
|
|||
}
|
||||
locked = false;
|
||||
|
||||
if (is_logging())
|
||||
if (this.logging)
|
||||
message("%s: %s", to_string(), get_transition_string(old_state, event, state));
|
||||
|
||||
// Perform post-transition if registered
|
||||
|
|
|
|||
|
|
@ -44,17 +44,17 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
|||
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.disconnect_async.begin(null, this.async_completion);
|
||||
test_article.disconnect_async.end(async_result());
|
||||
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
TestServer.Result result = this.server.wait_for_script(this.main_loop);
|
||||
assert_true(
|
||||
|
|
@ -148,13 +148,13 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
|||
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.login_async.begin(
|
||||
new Credentials(PASSWORD, "test", "password"),
|
||||
|
|
@ -162,11 +162,11 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
|||
this.async_completion
|
||||
);
|
||||
test_article.login_async.end(async_result());
|
||||
assert_true(test_article.get_protocol_state() == AUTHORIZED);
|
||||
assert_true(test_article.protocol_state == AUTHORIZED);
|
||||
|
||||
test_article.disconnect_async.begin(null, this.async_completion);
|
||||
test_article.disconnect_async.end(async_result());
|
||||
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
TestServer.Result result = this.server.wait_for_script(this.main_loop);
|
||||
assert_true(
|
||||
|
|
@ -185,17 +185,17 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
|||
this.server.add_script_line(DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.logout_async.begin(null, this.async_completion);
|
||||
test_article.logout_async.end(async_result());
|
||||
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
TestServer.Result result = this.server.wait_for_script(this.main_loop);
|
||||
assert_true(
|
||||
|
|
@ -216,13 +216,13 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
|||
this.server.add_script_line(DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.login_async.begin(
|
||||
new Credentials(PASSWORD, "test", "password"),
|
||||
|
|
@ -230,11 +230,11 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
|||
this.async_completion
|
||||
);
|
||||
test_article.login_async.end(async_result());
|
||||
assert_true(test_article.get_protocol_state() == AUTHORIZED);
|
||||
assert_true(test_article.protocol_state == AUTHORIZED);
|
||||
|
||||
test_article.logout_async.begin(null, this.async_completion);
|
||||
test_article.logout_async.end(async_result());
|
||||
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
TestServer.Result result = this.server.wait_for_script(this.main_loop);
|
||||
assert_true(
|
||||
|
|
@ -261,13 +261,13 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
|||
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.initiate_session_async.begin(
|
||||
new Credentials(PASSWORD, "test", "password"),
|
||||
|
|
@ -305,13 +305,13 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
|||
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.initiate_session_async.begin(
|
||||
new Credentials(PASSWORD, "test", "password"),
|
||||
|
|
@ -368,13 +368,13 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
|||
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.initiate_session_async.begin(
|
||||
new Credentials(PASSWORD, "test", "password"),
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class Integration.Imap.ClientSession : TestCase {
|
|||
}
|
||||
|
||||
public override void tear_down() throws GLib.Error {
|
||||
if (this.session.get_protocol_state() != NOT_CONNECTED) {
|
||||
if (this.session.protocol_state != NOT_CONNECTED) {
|
||||
this.session.disconnect_async.begin(null, this.async_completion);
|
||||
this.session.disconnect_async.end(async_result());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue