connection: keep-alive pings, act upon connection change (VPN)
This commit is contained in:
parent
a8ba4a3974
commit
f9436b63f1
|
@ -11,7 +11,8 @@ SOURCES
|
||||||
src/application.vala
|
src/application.vala
|
||||||
|
|
||||||
src/dbus/login1.vala
|
src/dbus/login1.vala
|
||||||
src/dbus/networkmanager.vala
|
src/dbus/network_manager.vala
|
||||||
|
src/dbus/network_manager_dbus_properties.vala
|
||||||
src/dbus/upower.vala
|
src/dbus/upower.vala
|
||||||
|
|
||||||
src/entity/account.vala
|
src/entity/account.vala
|
||||||
|
|
14
libdino/src/dbus/network_manager_dbus_properties.vala
Normal file
14
libdino/src/dbus/network_manager_dbus_properties.vala
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[DBus (name = "org.freedesktop.DBus.Properties")]
|
||||||
|
public interface NetworkManagerDBusProperties : GLib.Object {
|
||||||
|
public signal void properties_changed(string iface, HashTable<string, Variant> changed, string[] invalidated);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NetworkManagerDBusProperties? get_dbus_properties() {
|
||||||
|
NetworkManagerDBusProperties? dbus_properties = null;
|
||||||
|
try {
|
||||||
|
dbus_properties = Bus.get_proxy_sync(BusType.SYSTEM, "org.freedesktop.DBus.Properties", "/org/freedesktop/NetworkManager");
|
||||||
|
} catch (IOError e) {
|
||||||
|
stderr.printf("%s\n", e.message);
|
||||||
|
}
|
||||||
|
return dbus_properties;
|
||||||
|
}
|
|
@ -20,9 +20,11 @@ public class ConnectionManager {
|
||||||
private ArrayList<Account> connection_todo = new ArrayList<Account>(Account.equals_func);
|
private ArrayList<Account> connection_todo = new ArrayList<Account>(Account.equals_func);
|
||||||
private HashMap<Account, Connection> connections = new HashMap<Account, Connection>(Account.hash_func, Account.equals_func);
|
private HashMap<Account, Connection> connections = new HashMap<Account, Connection>(Account.hash_func, Account.equals_func);
|
||||||
private HashMap<Account, ConnectionError> connection_errors = new HashMap<Account, ConnectionError>(Account.hash_func, Account.equals_func);
|
private HashMap<Account, ConnectionError> connection_errors = new HashMap<Account, ConnectionError>(Account.hash_func, Account.equals_func);
|
||||||
|
private HashMap<Account, RecMutexWrap> connection_mutexes = new HashMap<Account, RecMutexWrap>(Account.hash_func, Account.equals_func);
|
||||||
|
|
||||||
private NetworkManager? network_manager;
|
private NetworkManager? network_manager;
|
||||||
private Login1Manager? login1;
|
private Login1Manager? login1;
|
||||||
|
private NetworkManagerDBusProperties? dbus_properties;
|
||||||
private ModuleManager module_manager;
|
private ModuleManager module_manager;
|
||||||
public string? log_options;
|
public string? log_options;
|
||||||
|
|
||||||
|
@ -48,12 +50,20 @@ public class ConnectionManager {
|
||||||
public Core.XmppStream stream { get; set; }
|
public Core.XmppStream stream { get; set; }
|
||||||
public ConnectionState connection_state { get; set; default = ConnectionState.DISCONNECTED; }
|
public ConnectionState connection_state { get; set; default = ConnectionState.DISCONNECTED; }
|
||||||
public DateTime established { get; set; }
|
public DateTime established { get; set; }
|
||||||
|
public DateTime last_activity { get; set; }
|
||||||
public class Connection(Core.XmppStream stream, DateTime established) {
|
public class Connection(Core.XmppStream stream, DateTime established) {
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
this.established = established;
|
this.established = established;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class RecMutexWrap {
|
||||||
|
public RecMutex mutex = new RecMutex();
|
||||||
|
public void lock() { mutex.lock(); }
|
||||||
|
public void unlock() { mutex.unlock(); }
|
||||||
|
public bool trylock() { return mutex.trylock(); }
|
||||||
|
}
|
||||||
|
|
||||||
public ConnectionManager(ModuleManager module_manager) {
|
public ConnectionManager(ModuleManager module_manager) {
|
||||||
this.module_manager = module_manager;
|
this.module_manager = module_manager;
|
||||||
network_manager = get_network_manager();
|
network_manager = get_network_manager();
|
||||||
|
@ -64,6 +74,25 @@ public class ConnectionManager {
|
||||||
if (login1 != null) {
|
if (login1 != null) {
|
||||||
login1.PrepareForSleep.connect(on_prepare_for_sleep);
|
login1.PrepareForSleep.connect(on_prepare_for_sleep);
|
||||||
}
|
}
|
||||||
|
dbus_properties = get_dbus_properties();
|
||||||
|
if (dbus_properties != null) {
|
||||||
|
dbus_properties.properties_changed.connect((s, sv, sa) => {
|
||||||
|
foreach (string key in sv.get_keys()) {
|
||||||
|
if (key == "PrimaryConnection") {
|
||||||
|
print("primary connection changed\n");
|
||||||
|
check_reconnects();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Timeout.add_seconds(60, () => {
|
||||||
|
foreach (Account account in connection_todo) {
|
||||||
|
if (connections[account].last_activity.compare(new DateTime.now_utc().add_minutes(-1)) < 0) {
|
||||||
|
check_reconnect(account);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Core.XmppStream? get_stream(Account account) {
|
public Core.XmppStream? get_stream(Account account) {
|
||||||
|
@ -92,6 +121,7 @@ public class ConnectionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Core.XmppStream? connect(Account account) {
|
public Core.XmppStream? connect(Account account) {
|
||||||
|
if (!connection_mutexes.contains(account)) connection_mutexes[account] = new RecMutexWrap();
|
||||||
if (!connection_todo.contains(account)) connection_todo.add(account);
|
if (!connection_todo.contains(account)) connection_todo.add(account);
|
||||||
if (!connections.has_key(account)) {
|
if (!connections.has_key(account)) {
|
||||||
return connect_(account);
|
return connect_(account);
|
||||||
|
@ -113,6 +143,8 @@ public class ConnectionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Core.XmppStream? connect_(Account account, string? resource = null) {
|
private Core.XmppStream? connect_(Account account, string? resource = null) {
|
||||||
|
if (!connection_mutexes[account].trylock()) return null;
|
||||||
|
|
||||||
if (connections.has_key(account)) connections[account].stream.remove_modules();
|
if (connections.has_key(account)) connections[account].stream.remove_modules();
|
||||||
connection_errors.unset(account);
|
connection_errors.unset(account);
|
||||||
if (resource == null) resource = account.resourcepart;
|
if (resource == null) resource = account.resourcepart;
|
||||||
|
@ -133,6 +165,9 @@ public class ConnectionManager {
|
||||||
set_connection_error(account, ConnectionError.Source.SASL, null);
|
set_connection_error(account, ConnectionError.Source.SASL, null);
|
||||||
change_connection_state(account, ConnectionState.DISCONNECTED);
|
change_connection_state(account, ConnectionState.DISCONNECTED);
|
||||||
});
|
});
|
||||||
|
stream.received_node.connect(() => {
|
||||||
|
connections[account].last_activity = new DateTime.now_utc();
|
||||||
|
});
|
||||||
new Thread<void*> (null, () => {
|
new Thread<void*> (null, () => {
|
||||||
try {
|
try {
|
||||||
stream.connect(account.domainpart);
|
stream.connect(account.domainpart);
|
||||||
|
@ -141,18 +176,20 @@ public class ConnectionManager {
|
||||||
change_connection_state(account, ConnectionState.DISCONNECTED);
|
change_connection_state(account, ConnectionState.DISCONNECTED);
|
||||||
if (!connection_todo.contains(account)) {
|
if (!connection_todo.contains(account)) {
|
||||||
connections.unset(account);
|
connections.unset(account);
|
||||||
} else {
|
return null;
|
||||||
StreamError.Flag? flag = stream.get_flag(StreamError.Flag.IDENTITY);
|
|
||||||
if (flag != null) {
|
|
||||||
set_connection_error(account, ConnectionError.Source.STREAM_ERROR, flag.error_type);
|
|
||||||
}
|
|
||||||
interpret_connection_error(account);
|
|
||||||
}
|
}
|
||||||
|
StreamError.Flag? flag = stream.get_flag(StreamError.Flag.IDENTITY);
|
||||||
|
if (flag != null) {
|
||||||
|
set_connection_error(account, ConnectionError.Source.STREAM_ERROR, flag.error_type);
|
||||||
|
}
|
||||||
|
interpret_connection_error(account);
|
||||||
}
|
}
|
||||||
|
connection_mutexes[account].unlock();
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
stream_opened(account, stream);
|
stream_opened(account, stream);
|
||||||
|
|
||||||
|
connection_mutexes[account].unlock();
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +219,7 @@ public class ConnectionManager {
|
||||||
}
|
}
|
||||||
print(@"recovering in $wait_sec\n");
|
print(@"recovering in $wait_sec\n");
|
||||||
Timeout.add_seconds(wait_sec, () => {
|
Timeout.add_seconds(wait_sec, () => {
|
||||||
connect_(account);
|
check_reconnect(account);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -194,6 +231,7 @@ public class ConnectionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void check_reconnect(Account account) {
|
private void check_reconnect(Account account) {
|
||||||
|
if (!connection_mutexes[account].trylock()) return;
|
||||||
bool acked = false;
|
bool acked = false;
|
||||||
|
|
||||||
Core.XmppStream stream = connections[account].stream;
|
Core.XmppStream stream = connections[account].stream;
|
||||||
|
@ -210,6 +248,8 @@ public class ConnectionManager {
|
||||||
try {
|
try {
|
||||||
connections[account].stream.disconnect();
|
connections[account].stream.disconnect();
|
||||||
} catch (Error e) { }
|
} catch (Error e) { }
|
||||||
|
connect_(account);
|
||||||
|
connection_mutexes[account].unlock();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue