SRV records for XMPP over TLS
This commit is contained in:
parent
e3e6a426f4
commit
b29d52fdda
|
@ -73,17 +73,19 @@ public class Conversation : Object {
|
||||||
.value(db.conversation.jid_id, db.get_jid_id(counterpart))
|
.value(db.conversation.jid_id, db.get_jid_id(counterpart))
|
||||||
.value(db.conversation.type_, type_)
|
.value(db.conversation.type_, type_)
|
||||||
.value(db.conversation.encryption, encryption)
|
.value(db.conversation.encryption, encryption)
|
||||||
.value(db.conversation.read_up_to, read_up_to.id)
|
.value(db.conversation.active, active)
|
||||||
.value(db.conversation.active, active);
|
.value(db.conversation.notification, notify_setting)
|
||||||
|
.value(db.conversation.send_typing, send_typing)
|
||||||
|
.value(db.conversation.send_marker, send_marker);
|
||||||
|
if (read_up_to != null) {
|
||||||
|
insert.value(db.conversation.read_up_to, read_up_to.id);
|
||||||
|
}
|
||||||
if (counterpart.is_full()) {
|
if (counterpart.is_full()) {
|
||||||
insert.value(db.conversation.resource, counterpart.resourcepart);
|
insert.value(db.conversation.resource, counterpart.resourcepart);
|
||||||
}
|
}
|
||||||
if (last_active != null) {
|
if (last_active != null) {
|
||||||
insert.value(db.conversation.last_active, (long) last_active.to_unix());
|
insert.value(db.conversation.last_active, (long) last_active.to_unix());
|
||||||
}
|
}
|
||||||
insert.value(db.conversation.notification, notify_setting);
|
|
||||||
insert.value(db.conversation.send_typing, send_typing);
|
|
||||||
insert.value(db.conversation.send_marker, send_marker);
|
|
||||||
id = (int) insert.perform();
|
id = (int) insert.perform();
|
||||||
notify.connect(on_update);
|
notify.connect(on_update);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ public class ModuleManager {
|
||||||
lock(module_map) {
|
lock(module_map) {
|
||||||
module_map[account] = new ArrayList<Core.XmppStreamModule>();
|
module_map[account] = new ArrayList<Core.XmppStreamModule>();
|
||||||
module_map[account].add(new Tls.Module());
|
module_map[account].add(new Tls.Module());
|
||||||
|
module_map[account].add(new Xep.SrvRecordsTls.Module());
|
||||||
module_map[account].add(new Session.Module());
|
module_map[account].add(new Session.Module());
|
||||||
module_map[account].add(new Roster.Module());
|
module_map[account].add(new Roster.Module());
|
||||||
module_map[account].add(new Xep.ServiceDiscovery.Module.with_identity("client", "pc"));
|
module_map[account].add(new Xep.ServiceDiscovery.Module.with_identity("client", "pc"));
|
||||||
|
|
|
@ -145,7 +145,7 @@ public class NoAccountsPlaceholder : UnifiedWindowPlaceholder {
|
||||||
public class NoConversationsPlaceholder : UnifiedWindowPlaceholder {
|
public class NoConversationsPlaceholder : UnifiedWindowPlaceholder {
|
||||||
public NoConversationsPlaceholder() {
|
public NoConversationsPlaceholder() {
|
||||||
label.label = _("No conversation active");
|
label.label = _("No conversation active");
|
||||||
primary_button.label = _("Add Chat");
|
primary_button.label = _("Start Chat");
|
||||||
secondary_button.label = _("Join Conference");
|
secondary_button.label = _("Join Conference");
|
||||||
secondary_button.visible = true;
|
secondary_button.visible = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,9 +54,12 @@ public class ConversationTitlebarWidget : Button, Plugins.ConversationTitlebarWi
|
||||||
}
|
}
|
||||||
|
|
||||||
public void on_upload_available(Account account) {
|
public void on_upload_available(Account account) {
|
||||||
if (conversation.account.equals(account)) {
|
Idle.add(() => {
|
||||||
|
if (conversation != null && conversation.account.equals(account)) {
|
||||||
visible = true;
|
visible = true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public new void set_conversation(Conversation conversation) {
|
public new void set_conversation(Conversation conversation) {
|
||||||
|
|
|
@ -60,6 +60,7 @@ SOURCES
|
||||||
"src/module/xep/0203_delayed_delivery.vala"
|
"src/module/xep/0203_delayed_delivery.vala"
|
||||||
"src/module/xep/0280_message_carbons.vala"
|
"src/module/xep/0280_message_carbons.vala"
|
||||||
"src/module/xep/0333_chat_markers.vala"
|
"src/module/xep/0333_chat_markers.vala"
|
||||||
|
"src/module/xep/0368_srv_records_tls.vala"
|
||||||
"src/module/xep/pixbuf_storage.vala"
|
"src/module/xep/pixbuf_storage.vala"
|
||||||
PACKAGES
|
PACKAGES
|
||||||
${ENGINE_PACKAGES}
|
${ENGINE_PACKAGES}
|
||||||
|
|
|
@ -21,8 +21,9 @@ public class XmppStream {
|
||||||
private StanzaReader? reader;
|
private StanzaReader? reader;
|
||||||
private StanzaWriter? writer;
|
private StanzaWriter? writer;
|
||||||
|
|
||||||
private ArrayList<XmppStreamFlag> flags = new ArrayList<XmppStreamFlag>();
|
private Gee.List<XmppStreamFlag> flags = new ArrayList<XmppStreamFlag>();
|
||||||
private ArrayList<XmppStreamModule> modules = new ArrayList<XmppStreamModule>();
|
private Gee.List<XmppStreamModule> modules = new ArrayList<XmppStreamModule>();
|
||||||
|
private Gee.List<ConnectionProvider> connection_providers = new ArrayList<ConnectionProvider>();
|
||||||
private bool setup_needed = false;
|
private bool setup_needed = false;
|
||||||
private bool negotiation_complete = false;
|
private bool negotiation_complete = false;
|
||||||
|
|
||||||
|
@ -35,11 +36,24 @@ public class XmppStream {
|
||||||
public signal void received_nonza(XmppStream stream, StanzaNode node);
|
public signal void received_nonza(XmppStream stream, StanzaNode node);
|
||||||
public signal void stream_negotiated(XmppStream stream);
|
public signal void stream_negotiated(XmppStream stream);
|
||||||
|
|
||||||
|
public XmppStream() {
|
||||||
|
register_connection_provider(new StartTlsConnectionProvider());
|
||||||
|
}
|
||||||
|
|
||||||
public void connect(string? remote_name = null) throws IOStreamError {
|
public void connect(string? remote_name = null) throws IOStreamError {
|
||||||
if (remote_name != null) this.remote_name = (!)remote_name;
|
if (remote_name != null) this.remote_name = (!)remote_name;
|
||||||
SocketClient client = new SocketClient();
|
|
||||||
try {
|
try {
|
||||||
SocketConnection? stream = client.connect(new NetworkService("xmpp-client", "tcp", this.remote_name));
|
int min_priority = -1;
|
||||||
|
ConnectionProvider? best_provider = null;
|
||||||
|
foreach (ConnectionProvider connection_provider in connection_providers) {
|
||||||
|
int? priority = connection_provider.get_priority(remote_name);
|
||||||
|
if (priority != null && (priority < min_priority || min_priority == -1)) {
|
||||||
|
min_priority = priority;
|
||||||
|
best_provider = connection_provider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (best_provider == null) throw new IOStreamError.CONNECT("no suitable connection provider");
|
||||||
|
IOStream? stream = best_provider.connect(this);
|
||||||
if (stream == null) throw new IOStreamError.CONNECT("client.connect() returned null");
|
if (stream == null) throw new IOStreamError.CONNECT("client.connect() returned null");
|
||||||
reset_stream((!)stream);
|
reset_stream((!)stream);
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
|
@ -142,6 +156,10 @@ public class XmppStream {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void register_connection_provider(ConnectionProvider connection_provider) {
|
||||||
|
connection_providers.add(connection_provider);
|
||||||
|
}
|
||||||
|
|
||||||
private void setup() throws IOStreamError {
|
private void setup() throws IOStreamError {
|
||||||
StanzaNode outs = new StanzaNode.build("stream", "http://etherx.jabber.org/streams")
|
StanzaNode outs = new StanzaNode.build("stream", "http://etherx.jabber.org/streams")
|
||||||
.put_attribute("to", remote_name)
|
.put_attribute("to", remote_name)
|
||||||
|
@ -294,4 +312,34 @@ public abstract class XmppStreamNegotiationModule : XmppStreamModule {
|
||||||
public abstract bool negotiation_active(XmppStream stream);
|
public abstract bool negotiation_active(XmppStream stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract class ConnectionProvider {
|
||||||
|
public abstract int? get_priority(string remote_name);
|
||||||
|
public abstract IOStream? connect(XmppStream stream);
|
||||||
|
public abstract string get_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StartTlsConnectionProvider : ConnectionProvider {
|
||||||
|
private SrvTarget? srv_target;
|
||||||
|
|
||||||
|
public override int? get_priority(string remote_name) {
|
||||||
|
GLib.List<SrvTarget>? xmpp_target = null;
|
||||||
|
try {
|
||||||
|
Resolver resolver = Resolver.get_default();
|
||||||
|
xmpp_target = resolver.lookup_service("xmpp-client", "tcp", remote_name, null);
|
||||||
|
} catch (Error e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
xmpp_target.sort((a, b) => { return a.get_priority() - b.get_priority(); });
|
||||||
|
srv_target = xmpp_target.nth(0).data;
|
||||||
|
return xmpp_target.nth(0).data.get_priority();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IOStream? connect(XmppStream stream) {
|
||||||
|
SocketClient client = new SocketClient();
|
||||||
|
return client.connect_to_host(srv_target.get_hostname(), srv_target.get_port());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string get_id() { return "start_tls"; }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace Xmpp.Tls {
|
||||||
public class Flag : XmppStreamFlag {
|
public class Flag : XmppStreamFlag {
|
||||||
public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "tls");
|
public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "tls");
|
||||||
public TlsCertificate? peer_certificate;
|
public TlsCertificate? peer_certificate;
|
||||||
public bool finished = false;
|
public bool finished { get; set; default=false; }
|
||||||
|
|
||||||
public override string get_ns() { return NS_URI; }
|
public override string get_ns() { return NS_URI; }
|
||||||
public override string get_id() { return IDENTITY.id; }
|
public override string get_id() { return IDENTITY.id; }
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class Module : XmppStreamModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void require(XmppStream stream) {
|
public static void require(XmppStream stream) {
|
||||||
if (stream.get_module(IDENTITY) == null) stream.add_module(new ChatMarkers.Module());
|
if (stream.get_module(IDENTITY) == null) stream.add_module(new Module());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string get_ns() { return NS_URI; }
|
public override string get_ns() { return NS_URI; }
|
||||||
|
|
53
xmpp-vala/src/module/xep/0368_srv_records_tls.vala
Normal file
53
xmpp-vala/src/module/xep/0368_srv_records_tls.vala
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
using Gee;
|
||||||
|
|
||||||
|
using Xmpp.Core;
|
||||||
|
|
||||||
|
namespace Xmpp.Xep.SrvRecordsTls {
|
||||||
|
|
||||||
|
public class Module : XmppStreamNegotiationModule {
|
||||||
|
public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>("", "0363_srv_records_for_xmpp_over_tls");
|
||||||
|
|
||||||
|
public override void attach(XmppStream stream) {
|
||||||
|
stream.register_connection_provider(new TlsConnectionProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void detach(XmppStream stream) { }
|
||||||
|
|
||||||
|
public static void require(XmppStream stream) {
|
||||||
|
if (stream.get_module(IDENTITY) == null) stream.add_module(new Module());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool mandatory_outstanding(XmppStream stream) { return false; }
|
||||||
|
public override bool negotiation_active(XmppStream stream) { return false; }
|
||||||
|
public override string get_ns() { return IDENTITY.ns; }
|
||||||
|
public override string get_id() { return IDENTITY.id; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TlsConnectionProvider : ConnectionProvider {
|
||||||
|
private SrvTarget? srv_target;
|
||||||
|
|
||||||
|
public override int? get_priority(string remote_name) {
|
||||||
|
GLib.List<SrvTarget>? xmpp_target = null;
|
||||||
|
try {
|
||||||
|
Resolver resolver = Resolver.get_default();
|
||||||
|
xmpp_target = resolver.lookup_service("xmpps-client", "tcp", remote_name, null);
|
||||||
|
} catch (Error e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
xmpp_target.sort((a, b) => { return a.get_priority() - b.get_priority(); });
|
||||||
|
srv_target = xmpp_target.nth(0).data;
|
||||||
|
return xmpp_target.nth(0).data.get_priority();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IOStream? connect(XmppStream stream) {
|
||||||
|
SocketClient client = new SocketClient();
|
||||||
|
IOStream? io_stream = client.connect_to_host(srv_target.get_hostname(), srv_target.get_port());
|
||||||
|
io_stream = TlsClientConnection.new(io_stream, new NetworkAddress(srv_target.get_hostname(), srv_target.get_port()));
|
||||||
|
stream.add_flag(new Tls.Flag() { finished=true });
|
||||||
|
return io_stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string get_id() { return "start_tls"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue