Pipelining disabled for "other" email services. Closes #4763
This commit is contained in:
parent
6e89c450dc
commit
e91eafce7a
7 changed files with 52 additions and 15 deletions
|
|
@ -186,6 +186,7 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
|
|||
account_info.imap_server_host = login.imap_host;
|
||||
account_info.imap_server_port = login.imap_port;
|
||||
account_info.imap_server_tls = login.imap_tls;
|
||||
account_info.imap_server_pipeline = (login.provider != Geary.ServiceProvider.OTHER);
|
||||
account_info.smtp_server_host = login.smtp_host;
|
||||
account_info.smtp_server_port = login.smtp_port;
|
||||
account_info.smtp_server_tls = login.smtp_tls;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ public class Geary.AccountInformation : Object {
|
|||
private const string IMAP_HOST = "imap_host";
|
||||
private const string IMAP_PORT = "imap_port";
|
||||
private const string IMAP_TLS = "imap_tls";
|
||||
private const string IMAP_PIPELINE = "imap_pipeline";
|
||||
private const string SMTP_HOST = "smtp_host";
|
||||
private const string SMTP_PORT = "smtp_port";
|
||||
private const string SMTP_TLS = "smtp_tls";
|
||||
|
|
@ -22,6 +23,7 @@ public class Geary.AccountInformation : Object {
|
|||
public string imap_server_host { get; set; default = ""; }
|
||||
public uint16 imap_server_port { get; set; default = Imap.ClientConnection.DEFAULT_PORT_TLS; }
|
||||
public bool imap_server_tls { get; set; default = true; }
|
||||
public bool imap_server_pipeline { get; set; default = true; }
|
||||
|
||||
public string smtp_server_host { get; set; default = ""; }
|
||||
public uint16 smtp_server_port { get; set; default = Smtp.ClientConnection.SECURE_SMTP_PORT; }
|
||||
|
|
@ -46,6 +48,7 @@ public class Geary.AccountInformation : Object {
|
|||
imap_server_port = get_uint16_value(key_file, GROUP, IMAP_PORT,
|
||||
Imap.ClientConnection.DEFAULT_PORT_TLS);
|
||||
imap_server_tls = get_bool_value(key_file, GROUP, IMAP_TLS, true);
|
||||
imap_server_pipeline = get_bool_value(key_file, GROUP, IMAP_PIPELINE, true);
|
||||
|
||||
smtp_server_host = get_string_value(key_file, GROUP, SMTP_HOST);
|
||||
smtp_server_port = get_uint16_value(key_file, GROUP, SMTP_PORT,
|
||||
|
|
@ -97,6 +100,7 @@ public class Geary.AccountInformation : Object {
|
|||
key_file.set_value(GROUP, IMAP_HOST, imap_server_host);
|
||||
key_file.set_integer(GROUP, IMAP_PORT, imap_server_port);
|
||||
key_file.set_boolean(GROUP, IMAP_TLS, imap_server_tls);
|
||||
key_file.set_boolean(GROUP, IMAP_PIPELINE, imap_server_pipeline);
|
||||
|
||||
key_file.set_value(GROUP, SMTP_HOST, smtp_server_host);
|
||||
key_file.set_integer(GROUP, SMTP_PORT, smtp_server_port);
|
||||
|
|
|
|||
|
|
@ -40,14 +40,14 @@ public class Geary.Engine {
|
|||
case ServiceProvider.GMAIL:
|
||||
return new GmailAccount(
|
||||
"Gmail account %s".printf(cred.to_string()), cred.user, account_info, user_data_dir,
|
||||
new Geary.Imap.Account(GmailAccount.IMAP_ENDPOINT, GmailAccount.SMTP_ENDPOINT, cred),
|
||||
new Geary.Sqlite.Account(cred, user_data_dir, resource_dir));
|
||||
new Geary.Imap.Account(GmailAccount.IMAP_ENDPOINT, GmailAccount.SMTP_ENDPOINT, cred,
|
||||
account_info), new Geary.Sqlite.Account(cred, user_data_dir, resource_dir));
|
||||
|
||||
case ServiceProvider.YAHOO:
|
||||
return new YahooAccount(
|
||||
"Yahoo account %s".printf(cred.to_string()), cred.user, account_info, user_data_dir,
|
||||
new Geary.Imap.Account(YahooAccount.IMAP_ENDPOINT, YahooAccount.SMTP_ENDPOINT, cred),
|
||||
new Geary.Sqlite.Account(cred, user_data_dir, resource_dir));
|
||||
new Geary.Imap.Account(YahooAccount.IMAP_ENDPOINT, YahooAccount.SMTP_ENDPOINT, cred,
|
||||
account_info), new Geary.Sqlite.Account(cred, user_data_dir, resource_dir));
|
||||
|
||||
case ServiceProvider.OTHER:
|
||||
Endpoint imap_endpoint = new Endpoint(account_info.imap_server_host,
|
||||
|
|
@ -60,7 +60,7 @@ public class Geary.Engine {
|
|||
|
||||
return new OtherAccount(
|
||||
"Other account %s".printf(cred.to_string()), cred.user, account_info, user_data_dir,
|
||||
new Geary.Imap.Account(imap_endpoint, smtp_endpoint, cred),
|
||||
new Geary.Imap.Account(imap_endpoint, smtp_endpoint, cred, account_info),
|
||||
new Geary.Sqlite.Account(cred, user_data_dir, resource_dir));
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -32,12 +32,13 @@ private class Geary.Imap.Account : Geary.AbstractAccount, Geary.RemoteAccount {
|
|||
private Geary.Smtp.ClientSession smtp;
|
||||
private Gee.HashMap<string, string?> delims = new Gee.HashMap<string, string?>();
|
||||
|
||||
public Account(Geary.Endpoint imap_endpoint, Geary.Endpoint smtp_endpoint, Geary.Credentials cred) {
|
||||
public Account(Geary.Endpoint imap_endpoint, Geary.Endpoint smtp_endpoint, Geary.Credentials cred,
|
||||
Geary.AccountInformation account_info) {
|
||||
base ("IMAP Account for %s".printf(cred.to_string()));
|
||||
|
||||
this.cred = cred;
|
||||
|
||||
session_mgr = new ClientSessionManager(imap_endpoint, cred);
|
||||
session_mgr = new ClientSessionManager(imap_endpoint, cred, account_info);
|
||||
session_mgr.login_failed.connect(on_login_failed);
|
||||
smtp = new Geary.Smtp.ClientSession(smtp_endpoint);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ public class Geary.Imap.ClientSessionManager {
|
|||
|
||||
private Endpoint endpoint;
|
||||
private Credentials credentials;
|
||||
private AccountInformation account_info;
|
||||
private Gee.HashSet<ClientSession> sessions = new Gee.HashSet<ClientSession>();
|
||||
private Geary.NonblockingMutex sessions_mutex = new Geary.NonblockingMutex();
|
||||
private Gee.HashSet<SelectedContext> examined_contexts = new Gee.HashSet<SelectedContext>();
|
||||
|
|
@ -19,9 +20,11 @@ public class Geary.Imap.ClientSessionManager {
|
|||
|
||||
public signal void login_failed();
|
||||
|
||||
public ClientSessionManager(Endpoint endpoint, Credentials credentials) {
|
||||
public ClientSessionManager(Endpoint endpoint, Credentials credentials,
|
||||
AccountInformation account_info) {
|
||||
this.endpoint = endpoint;
|
||||
this.credentials = credentials;
|
||||
this.account_info = account_info;
|
||||
|
||||
adjust_session_pool.begin();
|
||||
}
|
||||
|
|
@ -186,7 +189,7 @@ public class Geary.Imap.ClientSessionManager {
|
|||
|
||||
// This should only be called when sessions_mutex is locked.
|
||||
private async ClientSession create_new_authorized_session(Cancellable? cancellable) throws Error {
|
||||
ClientSession new_session = new ClientSession(endpoint);
|
||||
ClientSession new_session = new ClientSession(endpoint, account_info);
|
||||
|
||||
add_session(new_session);
|
||||
|
||||
|
|
|
|||
|
|
@ -167,6 +167,7 @@ public class Geary.Imap.ClientSession {
|
|||
state_to_string, event_to_string);
|
||||
|
||||
private Geary.Endpoint endpoint;
|
||||
private Geary.AccountInformation account_info;
|
||||
private Geary.State.Machine fsm;
|
||||
private ClientConnection? cx = null;
|
||||
private string? current_mailbox = null;
|
||||
|
|
@ -183,6 +184,8 @@ public class Geary.Imap.ClientSession {
|
|||
private int unselected_keepalive_secs = 0;
|
||||
private int selected_with_idle_keepalive_secs = 0;
|
||||
private bool allow_idle = true;
|
||||
private NonblockingMutex serialized_cmds_mutex = new NonblockingMutex();
|
||||
private int waiting_to_send = 0;
|
||||
|
||||
// state used only during connect and disconnect
|
||||
private bool awaiting_connect_response = false;
|
||||
|
|
@ -225,8 +228,9 @@ public class Geary.Imap.ClientSession {
|
|||
public virtual signal void unsolicited_flags(MailboxAttributes attrs) {
|
||||
}
|
||||
|
||||
public ClientSession(Geary.Endpoint endpoint) {
|
||||
public ClientSession(Geary.Endpoint endpoint, Geary.AccountInformation account_info) {
|
||||
this.endpoint = endpoint;
|
||||
this.account_info = account_info;
|
||||
|
||||
Geary.State.Mapping[] mappings = {
|
||||
new Geary.State.Mapping(State.DISCONNECTED, Event.CONNECT, on_connect),
|
||||
|
|
@ -1085,10 +1089,28 @@ public class Geary.Imap.ClientSession {
|
|||
new ImapError.NOT_CONNECTED("Not connected to %s", endpoint.to_string()));
|
||||
}
|
||||
|
||||
int claim_stub = NonblockingMutex.INVALID_TOKEN;
|
||||
if (!account_info.imap_server_pipeline) {
|
||||
try {
|
||||
debug("[%s] Waiting to send cmd %s: %d", to_string(), cmd.to_string(), ++waiting_to_send);
|
||||
claim_stub = yield serialized_cmds_mutex.claim_async(cancellable);
|
||||
debug("[%s] Ready, now waiting to send cmd %s: %d", to_string(), cmd.to_string(), --waiting_to_send);
|
||||
} catch (Error wait_err) {
|
||||
return new AsyncCommandResponse(null, user, wait_err);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
yield cx.send_async(cmd, cancellable);
|
||||
} catch (Error err) {
|
||||
return new AsyncCommandResponse(null, user, err);
|
||||
} catch (Error send_err) {
|
||||
try {
|
||||
if (!account_info.imap_server_pipeline && claim_stub != NonblockingMutex.INVALID_TOKEN)
|
||||
serialized_cmds_mutex.release(ref claim_stub);
|
||||
} catch (Error abort_err) {
|
||||
debug("Error attempting to abort from send operation: %s", abort_err.message);
|
||||
}
|
||||
|
||||
return new AsyncCommandResponse(null, user, send_err);
|
||||
}
|
||||
|
||||
// If the command didn't complete in the context of send_async(), wait for it
|
||||
|
|
@ -1103,6 +1125,14 @@ public class Geary.Imap.ClientSession {
|
|||
assert(cmd_response.is_sealed());
|
||||
assert(cmd_response.status_response.tag.equals(cmd.tag));
|
||||
|
||||
if (!account_info.imap_server_pipeline && claim_stub != NonblockingMutex.INVALID_TOKEN) {
|
||||
try {
|
||||
serialized_cmds_mutex.release(ref claim_stub);
|
||||
} catch (Error notify_err) {
|
||||
return new AsyncCommandResponse(null, user, notify_err);
|
||||
}
|
||||
}
|
||||
|
||||
return new AsyncCommandResponse(cmd_response, user, null);
|
||||
}
|
||||
|
||||
|
|
@ -1270,7 +1300,7 @@ public class Geary.Imap.ClientSession {
|
|||
}
|
||||
|
||||
public string to_string() {
|
||||
return "ClientSession:%s".printf(endpoint.to_string());
|
||||
return "ClientSession:%s".printf((cx == null) ? endpoint.to_string() : cx.to_string());
|
||||
}
|
||||
|
||||
public string to_full_string() {
|
||||
|
|
|
|||
|
|
@ -88,8 +88,6 @@ public abstract class Geary.NonblockingAbstractSemaphore {
|
|||
reset();
|
||||
}
|
||||
|
||||
// TODO: Allow the caller to pass their own cancellable in if they want to be able to cancel
|
||||
// this particular wait (and not all waiting threads of execution)
|
||||
public async void wait_async(Cancellable? cancellable = null) throws Error {
|
||||
for (;;) {
|
||||
check_user_cancelled(cancellable);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue