90 lines
3.9 KiB
Vala
90 lines
3.9 KiB
Vala
namespace Xmpp {
|
|
|
|
private class SrvTargetInfo {
|
|
public string host { get; set; }
|
|
public uint16 port { get; set; }
|
|
public string service { get; set; }
|
|
public uint16 priority { get; set; }
|
|
}
|
|
|
|
public class XmppStreamResult {
|
|
public TlsXmppStream? stream { get; set; }
|
|
public TlsCertificateFlags? tls_errors { get; set; }
|
|
public IOError? io_error { get; set; }
|
|
}
|
|
|
|
public async XmppStreamResult establish_stream(Jid bare_jid, Gee.List<XmppStreamModule> modules, string? log_options, owned TlsXmppStream.OnInvalidCert on_invalid_cert) {
|
|
Jid remote = bare_jid.domain_jid;
|
|
TlsXmppStream.OnInvalidCertWrapper on_invalid_cert_wrapper = new TlsXmppStream.OnInvalidCertWrapper(on_invalid_cert);
|
|
|
|
//Lookup xmpp-client and xmpps-client SRV records
|
|
GLib.List<SrvTargetInfo>? targets = new GLib.List<SrvTargetInfo>();
|
|
GLibFixes.Resolver resolver = GLibFixes.Resolver.get_default();
|
|
try {
|
|
GLib.List<SrvTarget> xmpp_services = yield resolver.lookup_service_async("xmpp-client", "tcp", remote.to_string(), null);
|
|
foreach (SrvTarget service in xmpp_services) {
|
|
targets.append(new SrvTargetInfo() { host=service.get_hostname(), port=service.get_port(), service="xmpp-client", priority=service.get_priority()});
|
|
}
|
|
} catch (Error e) {
|
|
debug("Got no xmpp-client DNS records for %s: %s", remote.to_string(), e.message);
|
|
}
|
|
try {
|
|
GLib.List<SrvTarget> xmpp_services = yield resolver.lookup_service_async("xmpps-client", "tcp", remote.to_string(), null);
|
|
foreach (SrvTarget service in xmpp_services) {
|
|
targets.append(new SrvTargetInfo() { host=service.get_hostname(), port=service.get_port(), service="xmpps-client", priority=service.get_priority()});
|
|
}
|
|
} catch (Error e) {
|
|
debug("Got no xmpps-client DNS records for %s: %s", remote.to_string(), e.message);
|
|
}
|
|
|
|
targets.sort((a, b) => {
|
|
return a.priority - b.priority;
|
|
});
|
|
|
|
// Add fallback connection
|
|
bool should_add_fallback = true;
|
|
foreach (SrvTargetInfo target in targets) {
|
|
if (target.service == "xmpp-client" && target.port == 5222 && target.host == remote.to_string()) {
|
|
should_add_fallback = false;
|
|
}
|
|
}
|
|
if (should_add_fallback) {
|
|
targets.append(new SrvTargetInfo() { host=remote.to_string(), port=5222, service="xmpp-client", priority=uint16.MAX});
|
|
}
|
|
|
|
// Try all connection options from lowest to highest priority
|
|
TlsXmppStream? stream = null;
|
|
TlsCertificateFlags? tls_errors = null;
|
|
IOError? io_error = null;
|
|
foreach (SrvTargetInfo target in targets) {
|
|
try {
|
|
if (target.service == "xmpp-client") {
|
|
stream = new StartTlsXmppStream(remote, target.host, target.port, on_invalid_cert_wrapper);
|
|
} else {
|
|
stream = new DirectTlsXmppStream(remote, target.host, target.port, on_invalid_cert_wrapper);
|
|
}
|
|
stream.log = new XmppLog(bare_jid.to_string(), log_options);
|
|
|
|
foreach (XmppStreamModule module in modules) {
|
|
stream.add_module(module);
|
|
}
|
|
|
|
yield stream.connect();
|
|
|
|
return new XmppStreamResult() { stream=stream };
|
|
} catch (IOError e) {
|
|
warning("Could not establish XMPP session with %s:%i: %s", target.host, target.port, e.message);
|
|
|
|
if (stream != null) {
|
|
if (stream.errors != null) {
|
|
tls_errors = stream.errors;
|
|
}
|
|
io_error = e;
|
|
stream.detach_modules();
|
|
}
|
|
}
|
|
}
|
|
|
|
return new XmppStreamResult() { io_error=io_error, tls_errors=tls_errors };
|
|
}
|
|
} |