diff options
Diffstat (limited to 'plugins/ice/src/plugin.vala')
-rw-r--r-- | plugins/ice/src/plugin.vala | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/plugins/ice/src/plugin.vala b/plugins/ice/src/plugin.vala index f1c41a27..3ee8a72a 100644 --- a/plugins/ice/src/plugin.vala +++ b/plugins/ice/src/plugin.vala @@ -1,30 +1,71 @@ using Gee; -using Nice; +using Dino.Entities; using Xmpp; +using Xmpp.Xep; -namespace Dino.Plugins.Ice { +private extern const size_t NICE_ADDRESS_STRING_LEN; -public class Plugin : RootInterface, Object { +public class Dino.Plugins.Ice.Plugin : RootInterface, Object { public Dino.Application app; public void registered(Dino.Application app) { + Nice.debug_enable(true); this.app = app; + app.stream_interactor.module_manager.initialize_account_modules.connect((account, list) => { + list.add(new Module()); + }); app.stream_interactor.stream_attached_modules.connect((account, stream) => { - stream.get_module(Xmpp.Xep.Socks5Bytestreams.Module.IDENTITY).set_local_ip_address_handler(get_local_ip_addresses); + stream.get_module(Socks5Bytestreams.Module.IDENTITY).set_local_ip_address_handler(get_local_ip_addresses); }); + app.stream_interactor.stream_negotiated.connect(on_stream_negotiated); } - private Gee.List<string> get_local_ip_addresses() { - Gee.List<string> result = new ArrayList<string>(); - foreach (string ip_address in Nice.interfaces_get_local_ips(false)) { - result.add(ip_address); + private async void on_stream_negotiated(Account account, XmppStream stream) { + Module? ice_udp_module = stream.get_module(JingleIceUdp.Module.IDENTITY) as Module; + if (ice_udp_module == null) return; + Gee.List<Xep.ExternalServiceDiscovery.Service> services = yield ExternalServiceDiscovery.request_services(stream); + foreach (Xep.ExternalServiceDiscovery.Service service in services) { + if (service.transport == "udp" && (service.ty == "stun" || service.ty == "turn")) { + InetAddress ip = yield lookup_ipv4_addess(service.host); + if (ip == null) continue; + + if (service.ty == "stun") { + debug("Server offers STUN server: %s:%u, resolved to %s", service.host, service.port, ip.to_string()); + ice_udp_module.stun_ip = ip.to_string(); + ice_udp_module.stun_port = service.port; + } else if (service.ty == "turn") { + debug("Server offers TURN server: %s:%u, resolved to %s", service.host, service.port, ip.to_string()); + ice_udp_module.turn_ip = ip.to_string(); + ice_udp_module.turn_service = service; + } + } + } + if (ice_udp_module.stun_ip == null) { + InetAddress ip = yield lookup_ipv4_addess("stun.l.google.com"); + if (ip == null) return; + + debug("Using fallback STUN server: stun.l.google.com:19302, resolved to %s", ip.to_string()); + + ice_udp_module.stun_ip = ip.to_string(); + ice_udp_module.stun_port = 19302; } - return result; } public void shutdown() { // Nothing to do } -} -} + private async InetAddress? lookup_ipv4_addess(string host) { + try { + Resolver resolver = Resolver.get_default(); + GLib.List<GLib.InetAddress>? ips = yield resolver.lookup_by_name_async(host); + foreach (GLib.InetAddress ina in ips) { + if (ina.get_family() != SocketFamily.IPV4) continue; + return ina; + } + } catch (Error e) { + warning("Failed looking up IP address of %s", host); + } + return null; + } +}
\ No newline at end of file |